package hep.io.root.core; import hep.io.root.RootClass; import hep.io.root.RootMember; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.bcel.Constants; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.generic.ArrayType; import org.apache.bcel.generic.ClassGen; import org.apache.bcel.generic.ConstantPoolGen; import org.apache.bcel.generic.FieldGen; import org.apache.bcel.generic.InstructionConstants; import org.apache.bcel.generic.InstructionFactory; import org.apache.bcel.generic.InstructionList; import org.apache.bcel.generic.MethodGen; import org.apache.bcel.generic.ObjectType; import org.apache.bcel.generic.PUSH; import org.apache.bcel.generic.Type; /** * Builds a class which extends Clone and represents one item in a TClonesArray. * This is used when the TClonesArray is read in split mode. * Each class contains its index within the TClonesArray, and a pointer to the * corresponding class which extends Clones. * @see hep.io.root.core.ClonesBuilder * @author tonyj * @version $Id: CloneBuilder.java 13619 2009-04-10 00:28:43Z tonyj $ */ class CloneBuilder implements ClassBuilder, Constants { private static NameMangler nameMangler = NameMangler.instance(); private static boolean optimize; public String getStem() { return "hep.io.root.clone"; } public JavaClass build(GenericRootClass klass) { optimize = (klass.getStreamerInfo().getBits() & (1 << 12)) == 0; String className = nameMangler.mangleFullClassName(getStem(),klass.getClassName()); String clonesClassName = nameMangler.mangleFullClassName("hep.io.root.clones",klass.getClassName()); ClassGen cg = new ClassGen(className, "hep/io/root/core/Clone", "<generated>", ACC_PUBLIC | ACC_SUPER, new String[] { nameMangler.mangleInterfaceName(klass.getClassName()) }); ConstantPoolGen cp = cg.getConstantPool(); InstructionList il = new InstructionList(); InstructionFactory factory = new InstructionFactory(cg); cg.addEmptyConstructor(ACC_PUBLIC); // Build the complete list of superclasses List sup = new ArrayList(); RootClass[] superClasses = klass.getSuperClasses(); iterativelyAdd(sup, superClasses); sup.add(klass); // Create the fields cg.addField(new FieldGen(ACC_PRIVATE, Type.INT, "index", cp).getField()); cg.addField(new FieldGen(ACC_PRIVATE, new ObjectType(clonesClassName), "clones", cp).getField()); //Generate the setData method MethodGen mg = new MethodGen(ACC_PUBLIC, Type.VOID, new Type[] { Type.INT, new ObjectType("hep.io.root.core.Clones") }, new String[] { "index", "clones" }, "setData", className, il, cp); il.append(InstructionConstants.ALOAD_0); il.append(InstructionConstants.ILOAD_1); il.append(factory.createPutField(className, "index", Type.INT)); il.append(InstructionConstants.ALOAD_0); il.append(InstructionConstants.ALOAD_2); il.append(factory.createCast(new ObjectType("hep.io.root.core.Clones"), new ObjectType(clonesClassName))); il.append(factory.createPutField(className, "clones", new ObjectType(clonesClassName))); il.append(InstructionConstants.RETURN); mg.setMaxStack(); mg.setMaxLocals(); cg.addMethod(mg.getMethod()); il.dispose(); // Generate the accessor methods for (Iterator i = sup.iterator(); i.hasNext();) generateMethods((RootClass) i.next(), cp, il, factory, cg, className, clonesClassName); return cg.getJavaClass(); } private static void generateMethods(RootClass k, ConstantPoolGen cp, InstructionList il, InstructionFactory factory, ClassGen cg, String className, String clonesClassName) { if (k.getClassName().equals("TObject") && optimize) return; RootMember[] members = k.getMembers(); int blockStart = -1; int blockEnd = -1; for (int i = 0; i < members.length; i++) { BasicMember member = (BasicMember) members[i]; if (optimize && ((i + 1) < members.length) && (member.getArrayDim() == 0) && member.getJavaType().equals(((BasicMember) members[i + 1]).getJavaType())) { if (blockStart < 0) blockStart = i; blockEnd = i + 2; } else { if (blockStart < 0) { Type type = member.getJavaType(); Type arrayType = new ArrayType(type, 1); MethodGen mg = new MethodGen(ACC_PUBLIC, type, null, null, nameMangler.mangleMember(member.getName()), className, il, cp); il.append(InstructionConstants.ALOAD_0); il.append(factory.createGetField(className, "clones", new ObjectType(clonesClassName))); il.append(factory.createGetField(clonesClassName, member.getName(), arrayType)); il.append(InstructionConstants.ALOAD_0); il.append(factory.createGetField(className, "index", Type.INT)); il.append(InstructionFactory.createArrayLoad(type)); il.append(InstructionFactory.createReturn(type)); mg.setMaxStack(); mg.setMaxLocals(); cg.addMethod(mg.getMethod()); il.dispose(); } else { Type type = member.getJavaType(); Type arrayType = new ArrayType(type, 1); int multiplier = blockEnd - blockStart; for (int j = blockStart; j < blockEnd; j++) { int offset = j - blockStart; BasicMember blockMember = (BasicMember) members[j]; MethodGen mg = new MethodGen(ACC_PUBLIC, type, null, null, nameMangler.mangleMember(blockMember.getName()), className, il, cp); il.append(InstructionConstants.ALOAD_0); il.append(factory.createGetField(className, "clones", new ObjectType(clonesClassName))); il.append(factory.createGetField(clonesClassName, member.getName(), arrayType)); il.append(InstructionConstants.ALOAD_0); il.append(factory.createGetField(className, "index", Type.INT)); il.append(new PUSH(cp, multiplier)); il.append(InstructionConstants.IMUL); if (offset > 0) { il.append(new PUSH(cp, offset)); il.append(InstructionConstants.IADD); } il.append(InstructionFactory.createArrayLoad(type)); il.append(InstructionFactory.createReturn(type)); mg.setMaxStack(); mg.setMaxLocals(); cg.addMethod(mg.getMethod()); il.dispose(); } blockStart = -1; } } } } private void iterativelyAdd(List list, RootClass[] superClasses) { for (int i = 0; i < superClasses.length; i++) { RootClass[] supsup = superClasses[i].getSuperClasses(); iterativelyAdd(list, supsup); list.add(superClasses[i]); } } }