package org.jruby.anno;
import java.util.List;
import java.util.Map;
import org.jruby.Ruby;
import org.jruby.RubyModule;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.internal.runtime.methods.JavaMethod;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.MethodFactory;
import org.jruby.runtime.MethodIndex;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
public abstract class TypePopulator {
public static void populateMethod(JavaMethod javaMethod, int arity, String simpleName, boolean isStatic, boolean notImplemented) {
javaMethod.setIsBuiltin(true);
javaMethod.setArity(Arity.createArity(arity));
javaMethod.setJavaName(simpleName);
javaMethod.setSingleton(isStatic);
javaMethod.setNotImplemented(notImplemented);
}
public static void populateMethod(JavaMethod javaMethod, int arity, String simpleName, boolean isStatic, boolean notImplemented,
Class nativeTarget, String nativeName, Class nativeReturn, Class[] nativeArguments) {
javaMethod.setIsBuiltin(true);
javaMethod.setArity(Arity.createArity(arity));
javaMethod.setJavaName(simpleName);
javaMethod.setSingleton(isStatic);
javaMethod.setNotImplemented(notImplemented);
javaMethod.setNativeCall(nativeTarget, nativeName, nativeReturn, nativeArguments, isStatic, false);
}
public static DynamicMethod populateModuleMethod(RubyModule cls, DynamicMethod javaMethod) {
DynamicMethod moduleMethod = javaMethod.dup();
moduleMethod.setImplementationClass(cls.getSingletonClass());
moduleMethod.setVisibility(Visibility.PUBLIC);
return moduleMethod;
}
public abstract void populate(RubyModule clsmod, Class clazz);
public static final TypePopulator DEFAULT = new DefaultTypePopulator();
public static class DefaultTypePopulator extends TypePopulator {
public void populate(RubyModule clsmod, Class clazz) {
ReflectiveTypePopulator populator = new ReflectiveTypePopulator(clazz);
populator.populate(clsmod, clazz);
}
}
public static final class ReflectiveTypePopulator extends TypePopulator {
private final Class clazz;
private final RubyModule.MethodClumper clumper;
public ReflectiveTypePopulator(Class clazz) {
this.clazz = clazz;
this.clumper = new RubyModule.MethodClumper();
clumper.clump(clazz);
}
public void populate(final RubyModule target, final Class clazz) {
assert clazz == this.clazz : "populator for " + this.clazz + " used for " + clazz;
AnnotationHelper.populateMethodIndex(clumper.readGroups, MethodIndex::addMethodReadFieldsPacked);
AnnotationHelper.populateMethodIndex(clumper.writeGroups, MethodIndex::addMethodWriteFieldsPacked);
final Ruby runtime = target.getRuntime();
final MethodFactory methodFactory = MethodFactory.createFactory(runtime.getJRubyClassLoader());
for (Map.Entry<String, List<JavaMethodDescriptor>> entry : clumper.getStaticAnnotatedMethods().entrySet()) {
final String name = entry.getKey();
final List<JavaMethodDescriptor> methods = entry.getValue();
target.defineAnnotatedMethod(name, methods, methodFactory);
addBoundMethodsUnlessOmitted(runtime, name, methods);
}
for (Map.Entry<String, List<JavaMethodDescriptor>> entry : clumper.getAnnotatedMethods().entrySet()) {
final String name = entry.getKey();
final List<JavaMethodDescriptor> methods = entry.getValue();
target.defineAnnotatedMethod(name, methods, methodFactory);
addBoundMethodsUnlessOmitted(runtime, name, methods);
}
}
private static void addBoundMethodsUnlessOmitted(final Ruby runtime, final String name, final List<JavaMethodDescriptor> methods) {
final int size = methods.size();
if ( size == 1 ) {
final JavaMethodDescriptor desc = methods.get(0);
if (!desc.anno.omit()) runtime.addBoundMethod(desc.declaringClassName, desc.name, name);
return;
}
for ( int i=0; i<size; i++ ) {
final JavaMethodDescriptor desc = methods.get(i);
if (!desc.anno.omit()) runtime.addBoundMethod(desc.declaringClassName, desc.name, name);
}
}
}
protected static final Class[] ARG0 = new Class[] {};
protected static final Class[] ARG1 = new Class[] { IRubyObject.class };
protected static final Class[] ARG2 = new Class[] { IRubyObject.class, IRubyObject.class };
protected static final Class[] ARG3 = new Class[] { IRubyObject.class, IRubyObject.class, IRubyObject.class };
protected static final Class[] ARG4 = new Class[] { IRubyObject.class, IRubyObject.class, IRubyObject.class, IRubyObject.class };
protected static final Class[] ARG0_ARY = new Class[] { IRubyObject[].class };
protected static final Class[] ARG1_ARY = new Class[] { IRubyObject.class, IRubyObject[].class };
protected static final Class[] CONTEXT_ARG0 = new Class[] { ThreadContext.class };
protected static final Class[] CONTEXT_ARG1 = new Class[] { ThreadContext.class, IRubyObject.class };
protected static final Class[] CONTEXT_ARG2 = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject.class };
protected static final Class[] CONTEXT_ARG3 = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject.class, IRubyObject.class };
protected static final Class[] CONTEXT_ARG4 = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, IRubyObject.class };
protected static final Class[] CONTEXT_ARG0_ARY = new Class[] { ThreadContext.class, IRubyObject[].class };
protected static final Class[] CONTEXT_ARG1_ARY = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject[].class };
protected static final Class[] ARG0_BLOCK = new Class[] { Block.class };
protected static final Class[] ARG1_BLOCK = new Class[] { IRubyObject.class, Block.class };
protected static final Class[] ARG2_BLOCK = new Class[] { IRubyObject.class, IRubyObject.class, Block.class };
protected static final Class[] ARG3_BLOCK = new Class[] { IRubyObject.class, IRubyObject.class, IRubyObject.class, Block.class };
protected static final Class[] ARG4_BLOCK = new Class[] { IRubyObject.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, Block.class };
protected static final Class[] ARG0_ARY_BLOCK = new Class[] { IRubyObject[].class, Block.class };
protected static final Class[] ARG1_ARY_BLOCK = new Class[] { IRubyObject.class, IRubyObject[].class, Block.class };
protected static final Class[] CONTEXT_ARG0_BLOCK = new Class[] { ThreadContext.class, Block.class };
protected static final Class[] CONTEXT_ARG1_BLOCK = new Class[] { ThreadContext.class, IRubyObject.class, Block.class };
protected static final Class[] CONTEXT_ARG2_BLOCK = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject.class, Block.class };
protected static final Class[] CONTEXT_ARG3_BLOCK = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, Block.class };
protected static final Class[] CONTEXT_ARG4_BLOCK = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, IRubyObject.class, Block.class };
protected static final Class[] CONTEXT_ARG0_ARY_BLOCK = new Class[] { ThreadContext.class, IRubyObject[].class, Block.class };
protected static final Class[] CONTEXT_ARG1_ARY_BLOCK = new Class[] { ThreadContext.class, IRubyObject.class, IRubyObject[].class, Block.class };
}