Minden programozó életében egyszer elérkezik a pont, amikor valamilyen előre egyeztetett séma alapján forrás-álloményokat, azaz működő Java osztályokat kell generálnia. Jelenleg is számtalan eszközzel tudunk forrást generálni, gondoljunk csak az adatbázisból létrejövő entitásokra, vagy egy WSDL alapján generált osztály-struktúrára, sőt a legtöbb IDE alapértelmezetten segítséget nyújt ezen a területen, képes konstruktort, getter-setter metódusokat, stb készíteni pár kattintással. Ha saját magunknak szeretnénk készíteni egy forrás-generátort, természetesen arra is megvan a lehetőség. A JAXB-nek van egy al-projektje, a CodeModel, aminek segítségével megoldható a probléma, ha van elég kitartásunk megérteni a mikéntjét, ugyanis dokumentálva mondhatni egyáltalán nincs az eszköz. Rövid írásom célja, hogy ízelítőt adjon a CodeModel lehetőségeiből, ezért kézenfekvőnek tűnik, hogy ismerkedés gyanánt készítsünk egy olyan generátort, ami átadott paraméter-lista alapján összeállít egy DTO osztályt. Először is szükségünk lesz a jaxb-xjc csomagra, ugyanis ez tartalmazza a szükséges osztályokat. Magam részéről a DTO típusú osztály-generátort egy saját osztályba csomagoltam.
import com.sun.codemodel.JAnnotationUse;
import com.sun.codemodel.JClassAlreadyExistsException;
import com.sun.codemodel.JCodeModel;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JDocComment;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMod;
import java.io.Serializable;
import java.util.Map;
/**
* @author mhmxs
*/
public final class DTO {
private final String name;
private final Map<String, Class> parameters;
public DTO(String name, Map<String, Class> parameters) {
this.name = name;
this.parameters = parameters;
}
public JCodeModel generateSource() throws JClassAlreadyExistsException {
JCodeModel codeModel = new JCodeModel();
//define class header
JDefinedClass clazz = codeModel._class(name);
clazz._implements(Serializable.class);
JAnnotationUse annotation = clazz.annotate(SuppressWarnings.class);
annotation.param("value", "serial");
//Add Java-doc to class header
JDocComment jDocComment = clazz.javadoc();
jDocComment.add("Simple DTO class : " + name + "\n");
jDocComment.add("@author mhmxs");
//Create constructor
JMethod constr = clazz.constructor(JMod.PUBLIC);
//Generate getter and setter methods for all parameters
JMethod method;
for(String param : parameters.keySet()) {
//Add parameter to class declaration
clazz.field(JMod.PRIVATE, parameters.get(param), param);
//Add parameter to constructor
constr.param(parameters.get(param), param);
constr.body().directStatement("this." + param + " = " + param + ";");
String methodName = param.replaceFirst(String.valueOf(param.charAt(0)),
String.valueOf(param.charAt(0)).toUpperCase());
//Create getter method
method = clazz.method(JMod.PUBLIC, parameters.get(param), "get" + methodName);
method.body()._return(JExpr._this().ref(param));
//Create setter method
method = clazz.method(JMod.PUBLIC, Void.TYPE, "set" + methodName);
method.param(parameters.get(param), param);
method.body().directStatement("this." + param + " = " + param + ";");
}
return codeModel;
}
}Az osztály-t az alábbi módon tudjuk meghívni.Map<String, Class> parameters = new HashMap<String, Class>();
parameters.put("parameter", String.class);
parameters.put("parameter2", Integer.class);
DTO dto = new DTO("a.b.Clazz", parameters);
OutputStream out = new FileOutputStream(new File("/a/b/Clazz.java"));
dto.generateSource().build( new SingleStreamCodeWriter(out));
out.close();
Végül az eredmény.package a.b;
import java.io.Serializable;
/**
* Simple DTO class : a.b.Clazz
* @author mhmxs
*
*/
@SuppressWarnings("serial")
public class Clazz
implements Serializable
{
private String parameter;
private Integer parameter2;
public Clazz(String parameter, Integer parameter2) {
this.parameter = parameter;
this.parameter2 = parameter2;
}
public String getParameter() {
return this.parameter;
}
public void setParameter(String parameter) {
this.parameter = parameter;
}
public Integer getParameter2() {
return this.parameter2;
}
public void setParameter2(Integer parameter2) {
this.parameter2 = parameter2;
}
}