Intersult Coder ist ein Werkzeug zur Analyse und zum Generieren von Java-Code. Das Projekt wird von Abraxas verwendet, um die Konvertierung von XML nach Java und umgekehrt durchzuführen. Ziel des Projekts ist die einfache Nutzbarkeit durch Convention over Configuration.
Da der Reflector die reflektierten Klassen in internen Listen ansammelt, kann es nützlich sein den Reflector nach Gebrauch dem Garbage-Collector zu übergeben. Für diesen Fall kann ein Reflector durch new Reflector() einfach erzeugt werden. Für alle anderen Fälle kann die Default-Instanz Reflector.INSTANCE verwendet werden.
Darüber hinaus liefert der Reflector einige nützliche Informationen über eine Klasse, die über die Java-Reflection nicht zugreifbar sind. Dazu gehören die Namen von Methoden-Parametern und Kommentare von Klassen und Methoden. Dies wird zum Beispiel vom SOAP-Service Abraxas benutzt, um die Service-Aufrufe zu erzeugen.
JavaClass stringClass = Reflector.INSTANCE.reflect(String.class); System.out.println(stringClass.getTypeNameSimple(true)); System.out.println(stringClass.getClassDefinition());
Erklärung: Der Reflector erzeugt aus der String.class-Klasse eine JavaClass, die erweiterte Methoden enthält, wie zum Beispiel getTypeName und getTypeNameSimple. Die Methode getClassDefinition liefert die Definition, wie sie in der Java-Datei steht, für String:
public final class String implements Serializable, Comparable<T>, CharSequence
Folgende Klassen sind bereits enthalten:
WILDCARD, OBJECT, STRING, VOID, ATOMIC_VOID, SHORT, ATOMIC_SHORT, INTEGER, ATOMIC_INTEGER, LONG, ATOMIC_LONG, BOOLEAN, ATOMIC_BOOLEAN, BYTE, ATOMIC_BYTE, DOUBLE, ATOMIC_DOUBLE, FLOAT, ATOMIC_FLOAT, BIG_DECIMAL, CLASS, DATE, URI, URL, QNAME, LIST, SERIALIZABLE, BASE64
Dazu kommen Annotation-Klassen:
OVERRIDE, REQUIRED, DEFAULT, NAME, KEY
Für die Implementierung eigener Maven-Plugins oder anderer Art von Code-Generierung kann die Klasse com.intersult.code.Generator direkt verwendet werden. Die Verwendung ist dabei sehr einfach:
JavaClass javaClass = new JavaClass("com.intersult.test", "Test"); javaClass.generatePath(); Generator.generateClass(Reflector.INSTANCE, javaClass);
Erklärung: Es wird eine neue Klasse com.intersult.test.Test erzeugt. Die Methode generatePath erzeugt den Package-Pfad, der nicht in jedem Fall erwünscht sein kann. Der Generator schreibt dann mit generateClass die Klasse in Dateien. Der Java-Standard ist dabei so definiert, dass Unterklassen (Sub-Classes) in getrennte Dateien geschrieben werden mit dem Namensmuster <Hauptklasse>$<Unterklasse>.
Optional kann eine Liste übergeben werden, in der die generierten Dateien eingetragen werden:
List<File> files = new ArrayList<File>(); Generator.generateClass(Reflector.INSTANCE, javaClass, list);
JavaMethod equals = javaClass.addMethod("equals"); equals.setReturnType(Reflector.INSTANCE.ATOMIC_BOOLEAN); equals.addAnnotation(Reflector.INSTANCE.OVERRIDE.newInstance()); JavaVariable object = new JavaVariable(Reflector.INSTANCE.OBJECT); equals.getParameters().add(object); equals.getCode().add("if (" + object.getVariableName() + " == null || !(" + object.getVariableName() + " instanceof " + javaClass.getTypeNameSimple(false) + "))"); equals.getCode().add("\treturn false;"); equals.getCode().add("if (this == " + object.getVariableName() + ")"); equals.getCode().add("\treturn true;"); JavaVariable field = javaClass.getFields().get("field"); equals.getCode().add("return " + field.getGetter() + "().equals(((" + javaClass.getTypeName(false) + ")" + object.getVariableName() + ")." + field.getGetter() + "());");
Accessor accessor = javaClass.addAccessor(Reflector.INSTANCE.STRING, "name");
Eine JavaClass kann allerdings auch aus dem Code erzeugt werden, also über den Konstruktor new JavaClass("<package>", "<name>"). In diesem Fall kann eine Instance durch die Methode newInstance() der Klasse JavaClass erzeugt werden. Es handelt sich natürlich um keine echte Java-Instanz, sondern um ein Objekt vom Typ com.intersult.code.Instance.