/*It only start from parent generate the child.
* It should build from the AST and symbol table
* Should have a standard interface class for general compatible with JAVA
* The main model java represent the package
* All the model import the default interface
* abstract class means table can combine class into one
* static means must be stand as itself
* THE SYNTAX NEED TO BE REVISITED AFTER THE EXPERIMENT.
* For the interested it maybe need the field name suffix
* Enum should be generated as types in table.
* MethodToJAVATypeMap is good concept and should extend used
* For example: add zero and non-zero. And less (((())))
* Get the Result Set by different criteria
*/
package samples;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup;
public class GaeJavaGen {
private static ArrayList<Class<?>> classes;
private final static String stgPath = "src/main/resources/";
private final static String outPutPath = "src/main/java/gaegen/";
private final static String target = "CompositeModel$menu";
private final static String pkgname = "samples";
private static String suffix;
private static String groupFile;
public static void main(String[] args) throws IOException,
SecurityException, NoSuchFieldException, ClassNotFoundException {
// LOAD all classes
ClassLoader classLoader = Thread.currentThread()
.getContextClassLoader();
File pkg = new File(classLoader.getResources(pkgname).nextElement()
.getFile());
classes = new ArrayList<Class<?>>();
File[] files = pkg.listFiles();
for (File file : files) {
if (file.getName().endsWith(".class")) {
classes.add(Class.forName(pkgname
+ '.'
+ file.getName().substring(0,
file.getName().length() - 6)));
}
}
LinkedList<member> members = new LinkedList<member>();
Class<?> c = Class.forName(pkgname + "." + target);
buildMembers(c, members, c);
genSQL(c, members);
genJAVA(c, members);
// System.out.println(output.toString());
}
public static void genSQL(Class<?> c, LinkedList<member> members) throws SecurityException,
NoSuchFieldException, IOException {
suffix = ".sql";
groupFile = stgPath + "Sql.stg";
FileReader fr = new FileReader(groupFile);
StringTemplateGroup templates = new StringTemplateGroup(fr);
fr.close();
templates.registerRenderer(Class.class, new TypeRenderer());
PrintWriter outfile = new PrintWriter(new File(outPutPath
+ c.getSimpleName() + suffix));
for (member m : members) {
StringTemplate classST = templates.getInstanceOf("output");
classST.setAttribute("class", m.cls);
classST.setAttribute("fields", m.fields);
classST.setAttribute("arrayFields", m.arrayFields);
classST.setAttribute("methodFields", m.methodFields);
outfile.print(classST);
}
outfile.flush();
}
protected static void buildMembers(Class<?> currentClass,
LinkedList<member> memberList, Class<?> parentClass)
throws SecurityException, NoSuchFieldException {
List<column> fields = new ArrayList<column>();
List<column> arrayFields = new ArrayList<column>();
List<column> methodFields = new ArrayList<column>();
for (member m : memberList) {
if (m.cls.simpleName.equals(currentClass.getSimpleName())) {
return;
}
}
memberList.add(new member(new table(currentClass.getSimpleName(),
currentClass.isInterface(),
currentClass.getInterfaces().length == 0), fields, arrayFields,
methodFields, arrayToList(currentClass.getInterfaces())));
List<Class<?>> parentList = getParent(currentClass);
if (currentClass.isInterface()) {
methodFields.addAll(arrayToList(currentClass.getMethods()));
return;
} else if (methodFields.isEmpty()) {
methodFields.addAll(arrayToList(currentClass.getMethods()));
}
if (!currentClass.equals(parentClass)) {
fields.add(new column(parentClass.getSimpleName() + "_ID", "int",
parentClass, classes));
fields.add(new column(parentClass.getSimpleName() + "_EntityType", "String",
parentClass, classes));
}
for (Field f : currentClass.getFields()) {
if (f.getType().isArray()) {
arrayFields.add(new column(f.getName(), f.getType()
.getSimpleName(), f.getType(), classes));
List<Class<?>> arrayParentList = getParent(f.getType()
.getComponentType());
Class<?> parent = getParent(arrayParentList, parentList);
if (parent == null) {
buildMembers(f.getType().getComponentType(), memberList,
f.getDeclaringClass());
} else {
for (Class<?> c : classes) {
List<Field> parentFields = new ArrayList<Field>(
Arrays.asList(currentClass.getFields()));
boolean sw = true;
if (currentClass != c && getParent(c).contains(parent)) {
if (!c.isInterface()) {
buildMembers(parent, memberList, parent);
List<Field> currentFields = new ArrayList<Field>(
Arrays.asList(c.getFields()));
currentFields.removeAll(parentFields);
if (Modifier.isStatic(c.getModifiers())) {
buildMembers(c, memberList, currentClass);
} else {
for (Field columnInParent : currentFields) {
fields.add(new column(columnInParent
.getName(), columnInParent
.getType().getSimpleName(),
columnInParent.getType(),
classes));
}
}
if (sw) {
fields.add(new column(currentClass
.getSimpleName() + "_ID", "int",
currentClass, classes));
sw = false;
}
} else {
buildMembers(c, memberList, parent);
}
}
}
}
} else {
for (Class<?> c : classes) {
if (currentClass != c
&& !(getParent(getParent(c), parentList) == null)
&& !In(currentClass, c)) {
buildMembers(c, memberList, c);
}
}
List<Class<?>> currentList = getParent(f.getType());
int i = currentList.size();
currentList.removeAll(parentList);
if (i == currentList.size()) {
fields.add(new column(f.getName(), f.getType()
.getSimpleName(), f.getType(), classes));
}
}
}
}
private static boolean In(Class<?> currentclass, Class<?> c) {
for (Field f : currentclass.getFields()) {
if (f.getType().isArray()) {
if (!(getParent(getParent(c), getParent(f.getType()
.getComponentType())) == null)) {
return true;
}
} else {
if (!(getParent(getParent(c), getParent(f.getType())) == null)) {
return true;
}
}
}
return false;
}
public static void genJAVA(Class<?> c, LinkedList<member> members) throws SecurityException,
NoSuchFieldException, IOException {
suffix = ".java";
groupFile = stgPath + "JavaModel.stg";
FileReader fr = new FileReader(groupFile);
StringTemplateGroup templates = new StringTemplateGroup(fr);
fr.close();
templates.registerRenderer(Class.class, new TypeRenderer());
for (member m : members) {
PrintWriter outfile = new PrintWriter(new File(outPutPath
+ m.cls.simpleName + suffix));
StringTemplate classST = templates.getInstanceOf("output");
classST.setAttribute("class", m.cls);
classST.setAttribute("fields", m.fields);
classST.setAttribute("arrayFields", m.arrayFields);
classST.setAttribute("methodFields", m.methodFields);
classST.setAttribute("interfaceImps", m.interfaceImps);
outfile.print(classST);
outfile.flush();
outfile.close();
}
groupFile = stgPath + "Java.stg";
fr = new FileReader(groupFile);
templates = new StringTemplateGroup(fr);
fr.close();
for (member m : members) {
if (!m.cls.isInterface) {
PrintWriter outfile = new PrintWriter(new File(outPutPath
+ m.cls.simpleName + "IO" + suffix));
StringTemplate classST = templates.getInstanceOf("output");
classST.setAttribute("class", m.cls);
classST.setAttribute("fields", m.fields);
classST.setAttribute("arrayFields", m.arrayFields);
classST.setAttribute("methodFields", m.methodFields);
outfile.print(classST);
outfile.flush();
outfile.close();
}
}
}
private static Class<?> getParent(List<Class<?>> currentList,
List<Class<?>> parentList) {
for (Class<?> s1 : parentList) {
for (Class<?> s2 : currentList) {
if (s1.equals(s2)) {
return s2;
}
}
}
return null;
}
public static List<Class<?>> getParent(Class<?> c) {
List<Class<?>> r = new LinkedList<Class<?>>();
r.add(c);
Class<?>[] nxtParent = c.getInterfaces();
while (nxtParent.length > 0) {
r.add(nxtParent[0]);
nxtParent = nxtParent[0].getInterfaces();
}
return r;
}
private static List<column> arrayToList(Class<?>[] list) {
List<column> interfaceImps = new ArrayList<column>();
for (Class<?> c : list) {
interfaceImps.add(new column(c.getSimpleName(), "intferace", c,
classes));
}
return interfaceImps;
}
private static List<column> arrayToList(Method[] list) {
List<column> interfaceImps = new ArrayList<column>();
for (Method c : list) {
if (c.getDeclaringClass().getPackage().getName().equals(pkgname))
interfaceImps.add(new column(c.getName(), c.getReturnType()
.getSimpleName(), c.getReturnType(), classes));
}
return interfaceImps;
}
}
class member {
table cls;
List<column> fields;
List<column> arrayFields;
List<column> methodFields;
List<column> interfaceImps;
member(table c, List<column> f, List<column> af, List<column> n,
List<column> i) {
this.cls = c;
this.fields = f;
this.arrayFields = af;
this.methodFields = n;
this.interfaceImps = i;
}
@Override
public String toString() {
return cls.simpleName;
}
}
class table {
public String simpleName;
public boolean isInterface;
public boolean isImp;
table(String name, boolean b, boolean c) {
this.simpleName = name;
this.isInterface = b;
this.isImp = c;
}
}
class column {
public String name;
public String type;
public String componentType;
public List<column> childClasses;
column(String name, String type, Class<?> c, List<Class<?>> classes) {
this.name = name;
this.type = type;
this.componentType = getComType(c);
this.childClasses = getChildren(c, classes);
}
private List<column> getChildren(Class<?> parent, List<Class<?>> classes) {
List<column> children = new ArrayList<column>();
if (classes != null) {
for (Class<?> c : classes) {
if (!c.isInterface()
&& isChild(c.getInterfaces(),
parent.isArray() ? parent.getComponentType()
: parent)) {
children.add(new column(c.getSimpleName(), null, null, null));
}
}
}
if (children.isEmpty() && parent != null) {
children.add(new column((parent.isArray() ? parent
.getComponentType() : parent).getSimpleName(), null, null,
null));
}
return children;
}
private boolean isChild(Class<?>[] interfaces, Class<?> parent) {
for (Class<?> c : interfaces) {
if (GaeJavaGen.getParent(c).contains(parent)) {
return true;
}
}
return false;
}
private static String getComType(Class<?> c) {
if (c != null && c.isArray()) {
return c.getComponentType().getSimpleName();
}
return null;
}
}