package japicmp.util; import com.google.common.base.Optional; import javassist.ClassPool; import javassist.CtClass; import javassist.Modifier; import javassist.bytecode.AnnotationsAttribute; import javassist.bytecode.ClassFile; import javassist.bytecode.ConstPool; import javassist.bytecode.annotation.Annotation; import java.util.ArrayList; import java.util.List; public class CtClassBuilder { public static final String DEFAULT_CLASS_NAME = "japicmp.Test"; private String name = DEFAULT_CLASS_NAME; private int modifier = Modifier.PUBLIC; private List<String> annotations = new ArrayList<>(); private Optional<CtClass> superclass = Optional.absent(); private List<CtClass> interfaces = new ArrayList<>(); public CtClassBuilder name(String name) { this.name = name; return this; } public CtClassBuilder syntheticModifier() { this.modifier = this.modifier | ModifierHelper.ACC_SYNTHETIC; return this; } public CtClassBuilder withAnnotation(String annotation) { this.annotations.add(annotation); return this; } public CtClassBuilder abstractModifier() { this.modifier = this.modifier | Modifier.ABSTRACT; return this; } public CtClassBuilder finalModifier() { this.modifier = this.modifier | Modifier.FINAL; return this; } public CtClassBuilder privateModifier() { this.modifier = this.modifier & ~Modifier.PUBLIC; this.modifier = this.modifier & ~Modifier.PROTECTED; this.modifier |= Modifier.PRIVATE; return this; } public CtClassBuilder enumModifier() { this.modifier = this.modifier | Modifier.ENUM; return this; } public CtClassBuilder withSuperclass(CtClass superclass) { this.superclass = Optional.of(superclass); return this; } public CtClass addToClassPool(ClassPool classPool) { CtClass ctClass; if (this.superclass.isPresent()) { ctClass = classPool.makeClass(this.name, this.superclass.get()); } else { ctClass = classPool.makeClass(this.name); } ctClass.setModifiers(this.modifier); for (String annotation : annotations) { ClassFile classFile = ctClass.getClassFile(); ConstPool constPool = classFile.getConstPool(); AnnotationsAttribute attr = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag); Annotation annot = new Annotation(annotation, constPool); attr.setAnnotation(annot); ctClass.getClassFile2().addAttribute(attr); } for (CtClass interfaceCtClass : interfaces) { ctClass.addInterface(interfaceCtClass); } return ctClass; } public static CtClassBuilder create() { return new CtClassBuilder(); } public CtClassBuilder implementsInterface(CtClass ctClass) { interfaces.add(ctClass); return this; } }