package iitb.con.net.codegenerator;
import iitb.con.core.Attribute;
import iitb.con.core.DataType;
import iitb.con.core.Entity;
import iitb.con.core.Relation;
import iitb.con.core.Type;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
public class CodeGenerator {
static Logger log = Logger.getLogger("ada.wadk.types.CodeGenerator");
private final String templateFile = "ClassTemplate.txt";
private byte index;
private static CodeGenerator instance = null;
private CodeGenerator(){}
public static CodeGenerator getInstance() {
if(instance == null)
instance = new CodeGenerator();
return instance;
}
public boolean generateCode(String path, Entity entity) {
index = ENTITY;
return generateTypeCode(path, entity);
}
public boolean generateCode(String path, Relation relation, String leftEntityName,
String rightEntityName) {
index = RELATION;
StringBuilder relSetters = new StringBuilder(RELATION_SETTERS);
replaceAll(relSetters,L_INSTANCE_NAME, leftEntityName);
replaceAll(relSetters,R_INSTANCE_NAME, rightEntityName);
RELATION_SETTERS_STRING = relSetters.toString();
StringBuilder rPackageString = new StringBuilder(IMPORT_RESULT);
rPackageString.append(IMPORT_TYPE + leftEntityName +";\n");
if(!leftEntityName.equals(rightEntityName))
rPackageString.append(IMPORT_TYPE + rightEntityName +";\n");
R_PACKAGE_STRING = rPackageString.toString();
return generateTypeCode(path, relation);
}
private boolean generateTypeCode(String path, Type type) {
String tempStr = new String(readFileAsString(this.getClass(),templateFile));
tempStr = tempStr.replace(CLASS_NAME, type.name);
tempStr = tempStr.replace(SUPER_TYPE,INSTANCE[index]);
tempStr = tempStr.replace(PACKAGE_NAME,PACKAGE_PATH[index]);
tempStr = tempStr.replace(IMPORT_PACKAGE, generatePackageStrings(type.getAllAttributes()));
tempStr = tempStr.replace(MEMBER_VARIABLES, generateAttributes(type.getAllAttributes()));
tempStr = tempStr.replace(MEMBER_FUNCTIONS, generateMethods(type));
String fullPath = path + CODE_PATH[index];
File filePath = new File(fullPath);
boolean dirExists = true;
if(!filePath.exists()) dirExists = filePath.mkdirs();
if(dirExists) {
writeToFile(fullPath + type.name + EXTENSION,tempStr);
compile(path,fullPath + type.name + EXTENSION);
return true;
}
else {
log.info("Code generation path: " + fullPath);
log.severe("Error in file creation and code is not generated");
}
return false;
}
private String readFileAsString(String fullPathFilename) {
try{
StringBuilder buffer = new StringBuilder();
BufferedReader reader = new BufferedReader(new FileReader(fullPathFilename));
char[] chars = new char[1024];
while((reader.read(chars)) > -1){
buffer.append(String.valueOf(chars));
}
reader.close();
return buffer.toString();
}catch (IOException ioException) {
log.info("Application Location: " + new File(".").getAbsolutePath());
log.log(Level.SEVERE,"The template file for class generation NOT found" +
"in the location: " + fullPathFilename , ioException);
return null;
}
}
private String readFileAsString(Class clazz, String filename) {
try{
StringBuilder contents = new StringBuilder();
BufferedReader reader = new BufferedReader(
new InputStreamReader(getStream(clazz, filename)));
String line;
while ((line = reader.readLine()) != null) {
contents.append(line + "\n");
}
reader.close();
return contents.toString();
}catch (IOException ioException) {
log.log(Level.SEVERE,"The template file for class generation NOT found" +
"in the location: " + clazz.toString() + "/" + filename , ioException);
return null;
}
}
private InputStream getStream(Class clazz, String filename) {
InputStream is = null;
if (clazz != null) {
is = clazz.getResourceAsStream(filename);
} else {
try {
is = new FileInputStream(filename);
} catch (FileNotFoundException e) {
return null;
}
}
if (is == null) {
return null;
} else {
return new BufferedInputStream(is);
}
}
private void writeToFile(String fullPathFilename, String contents) {
try{
BufferedWriter writer = new BufferedWriter(new FileWriter(fullPathFilename));
writer.write(contents);
writer.flush();
writer.close();
}catch (IOException ioException) {
log.log(Level.SEVERE,"Error in writing the auto code generation file", ioException);
}
}
private void compile(String classpath, String fullPathFileName) {
com.sun.tools.javac.Main javac = new com.sun.tools.javac.Main();
String[] options = new String[] { fullPathFileName };
javac.compile(options);
}
private String generateAttributes(List<Attribute> attributeList) {
StringBuilder attributeCode = new StringBuilder("");
for(Attribute attribute : attributeList) {
String strTemp = new String("\t public ");
attributeCode.append(strTemp);
String dataType = DataType.getDataTypeString(attribute.dataType);
if(attribute.repeating) {
attributeCode.append("List<" + dataType + "> "
+ attribute.name + " = new ArrayList<" + dataType + ">();\n");
}else {
if(attribute.defaultValue != null) {
attributeCode.append(dataType + " " + attribute.name + " = " +
DataType.getDataValue(attribute.dataType, attribute.defaultValue) + ";\n");
}else {
attributeCode.append(dataType + " " + attribute.name + ";\n");
}
}
}
return attributeCode.toString();
}
private String generateMethods(Type type) {
List<Attribute> attributeList = type.getAllAttributes();
boolean flag = false;
StringBuilder strCode = new StringBuilder("");
if(attributeList.size() > 0)
{
StringBuilder strTemp = new StringBuilder("");
strCode.append(setterTemplate);
if(index == RELATION) strCode.append(superSetterCall);
for(Attribute attribute : attributeList) {
String dataType = DataType.getDataTypeString(attribute.dataType);
if(flag)
strTemp.append("else ");
else
strTemp.append("\n\t\t");
if(attribute.repeating)
strTemp.append(SETTER_IF_R);
else
strTemp.append(SETTER_IF);
replaceAll(strTemp,DATA_TYPE, dataType);
replaceAll(strTemp,ATTR_NAME,attribute.name);
strCode.append(strTemp);
flag= true;
strTemp.setLength(0); }
strCode.append("else { \n \t\t}");
strCode.append("\n\t}");
strTemp.setLength(0);
flag = false;
strCode.append(getterTemplate);
if(index == RELATION) strCode.append(superGetterCall);
for(Attribute attribute : attributeList) {
if(flag)
strTemp.append("else ");
else
strTemp.append("\n\t\t");
strTemp.append(GETTER_IF);
replaceAll(strTemp,ATTR_NAME,attribute.name);
strCode.append(strTemp);
flag= true;
strTemp.setLength(0); }
strCode.append("else { \n \t\t\treturn null;\n \t\t}");
strCode.append("\n\t}"); }
if(index == RELATION) {
strCode.append(RELATION_SETTERS_STRING);
}
return strCode.toString();
}
private String generatePackageStrings(List<Attribute> attributeList) {
StringBuilder strPackages = new StringBuilder(INSTANCE_PKG_STRING[index]);
if(index == RELATION)
strPackages.append(R_PACKAGE_STRING);
for(Attribute attr: attributeList) {
if(attr.repeating) {
strPackages.append(PACKAGE_STRING);
return strPackages.toString();
}
}
return strPackages.toString();
}
private void replaceAll(StringBuilder source, String target, String replacement) {
int index = source.indexOf(target);
while(index > 0) {
source.replace(index, index + target.length(), replacement);
index = source.indexOf(target);
}
}
private static final String setterTemplate = "\tpublic void " +
"setAttributeValue(String name, Object value) {";
private static final String getterTemplate = "\n\tpublic Object getAttributeValue(String name) {";
private static final String superSetterCall = "\n\t\tsuper.setAttributeValue(name,value);";
private static final String superGetterCall = "\n\t\tObject obj = super.getAttributeValue(name);" +
"\n\t\tif(obj != null) return obj;";
private static final String SETTER_IF ="if(name.equals(\"$Attr_Name$\")) {" +
"\n\t\t\tthis.$Attr_Name$ = ($DT$) value;" +
"\n\t\t}";
private static final String SETTER_IF_R ="if(name.equals(\"$Attr_Name$\")) {" +
"\n\t\t\tthis.$Attr_Name$ = (List<$DT$>) value;" +
"\n\t\t}";
private static final String GETTER_IF ="if(name.equals(\"$Attr_Name$\")) {" +
"\n\t\t\treturn this.$Attr_Name$;" +
"\n\t\t}";
private static final byte RELATION = 1;
private static final byte ENTITY = 0;
private static final String ATTR_NAME = "$Attr_Name$";
private static final String DATA_TYPE = "$DT$";
private static final String PACKAGE_NAME = "$PACKAGE_NAME$";
private static final String CLASS_NAME = "$CLASS_NAME$";
private static final String SUPER_TYPE = "$SUPER_TYPE$";
private static final String IMPORT_PACKAGE = "$IMPORT_PACKAGE$";
private static final String MEMBER_VARIABLES = "$MEMBER_VARIABLES$";
private static final String MEMBER_FUNCTIONS = "$MEMBER_FUNCTIONS$";
private static final String EXTENSION = ".java";
private static final String L_INSTANCE_NAME = "$L_INSTANCE_NAME$";
private static final String R_INSTANCE_NAME = "$R_INSTANCE_NAME$";
private static final String[] PACKAGE_PATH = {"types.entities","types.relations"};
private static final String[] INSTANCE = {"EntityInstance","RelationInstance"};
private static final String[] INSTANCE_PKG_STRING =
{"import iitb.con.core.EntityInstance;\n","import iitb.con.core.RelationInstance;\n"};
private static final String PACKAGE_STRING = "import java.util.ArrayList; \nimport java.util.List;";
private static final String[] CODE_PATH =
{"/types/entities/","/types/relations/"};
private static final String IMPORT_TYPE = "import types.entities.";
private static final String IMPORT_RESULT = "import iitb.con.util.Result;\n";
private String R_PACKAGE_STRING = "";
private String RELATION_SETTERS_STRING = "";
private static String RELATION_SETTERS = "\tpublic Result setLeftInstance($L_INSTANCE_NAME$ instance) {\n" +
"\t\treturn super.setLeftInstance(instance);\n" +
"\t}\n\n" +
"\tpublic Result setRightInstance($R_INSTANCE_NAME$ instance) {\n" +
"\t\treturn super.setRightInstance(instance);\n" +
"\t}\n\n";
}