package TaiGameCore.dev;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import TaiGameCore.GameDataBase;
import TaiGameCore.TaiDAWG;
import TaiGameCore.GameDataBase.StringBase.ExtendsData;
import TaiGameCore.GameDataBase.StringBase.MakeGetters;
import TaiGameCore.GameDataBase.StringBase.ScopePreValidate;
import TaiGameCore.GameDataBase.StringBase.ValidationException;
/**
* Fills in the appropriate automatic serialization / deserialization of a given gamedatabase
*/
public class GameDataBase$AutoWriter {
public static void main(String[] args) throws Throwable{
Scanner in = new Scanner(System.in);
while(in.hasNextLine()){
try {
main(in.nextLine());
} catch (Throwable e){
e.printStackTrace();
}
}
}
public static void main(String className) throws ClassNotFoundException{
String[] parts = className.split("/");
Class got = GameDataBase$AutoWriter.class.getClassLoader().loadClass(parts[0]);
for(int k = 1; k < parts.length; k++){
got = getInArray(got.getDeclaredClasses(),parts[k]);
}
//System.out.println(got);
ArrayList<Field> fields = new ArrayList();
for(Field q : got.getDeclaredFields()){
fields.add(q);
}
if (GameDataBase.StringBase.class.isAssignableFrom(got)){
handleExtendedTemplates(got,fields);
//We have a string parsable class. Write its parser.
System.out.println("public ArrayList<Exception> parseFromStrings(TaiDAWG<TaiScriptStatementAndContext> data, Validator ... valid) {");
System.out.println("\tArrayList<Exception> toRet = new ArrayList();");
System.out.println("\tWordByRef<TaiScriptStatementAndContext> word;");
ArrayList<String> scriptables = new ArrayList();
String scopeAndValidate = null;
try {
GameDataBase.StringBase.ScopePreValidate a = (ScopePreValidate) got.getAnnotation(GameDataBase.StringBase.ScopePreValidate.class);
if (a!=null){
scopeAndValidate = a.method();
}
} catch (NullPointerException e){
//None.
}
for(Field k : fields){
boolean isCritical = false;
try {
GameDataBase.StringBase.CriticalScriptField a = k.getAnnotation(GameDataBase.StringBase.CriticalScriptField.class);
if (a!=null){
isCritical = true;
}
} catch (NullPointerException e){
//None.
}
boolean isScriptable = false;
try {
GameDataBase.StringBase.FromScript a = k.getAnnotation(GameDataBase.StringBase.FromScript.class);
if (a!=null){
isScriptable = true;
scriptables.add(k.getName());
}
} catch (NullPointerException e){
//None.
}
int valid = -1;
try {
GameDataBase.StringBase.HasValidator a = k.getAnnotation(GameDataBase.StringBase.HasValidator.class);
if (a!=null){
valid = a.num();
}
} catch (NullPointerException e){
//None.
}
boolean skipScopeAndValidate = false;
try {
GameDataBase.StringBase.IsUnscoped a = k.getAnnotation(GameDataBase.StringBase.IsUnscoped.class);
if (a!=null){
skipScopeAndValidate = true;
}
} catch (NullPointerException e){
//None.
}
if (isScriptable){
System.out.println("\tword = data.get(\""+k.getName()+"\");");
System.out.println("\tif (word!=null){String val = word.getContentData().rawString;");
System.out.println("try {");
{//Validating exceptions! If it does not validate, don't write it.
System.out.println("if (false){throw new ValidationException(null, null);}//Workaround for unreachable catch block");
if (scopeAndValidate!=null && !skipScopeAndValidate){
System.out.println("val = "+scopeAndValidate+"(word.getContentData(),"+k.getType().getSimpleName()+".class,\""+k.getName()+"\");");
}
if (valid!=-1){
System.out.println("\tvalid["+valid+"].validate(\""+k.getName()+"\",val);");
}
if (k.getType().equals(String.class)){
System.out.println("\t"+k.getName()+"= val;");
} else if (k.getType().equals(Integer.TYPE)){
System.out.println("\t"+k.getName()+"= new Integer(val.trim());");
} else if (k.getType().equals(int[].class)){
System.out.println("\tString[] spli = val.split(\",\");");
System.out.println("\t"+k.getName()+"= new int[spli.length];");
System.out.println("\tfor(int k = 0; k < spli.length; k++){");
System.out.println("\t\t"+k.getName()+"[k]=new Integer(spli[k].trim());");
System.out.println("\t}");
} else if (k.getType().equals(double[].class)){
System.out.println("\tString[] spli = val.split(\",\");");
System.out.println("\t"+k.getName()+"= new double[spli.length];");
System.out.println("\tfor(int k = 0; k < spli.length; k++){");
System.out.println("\t\t"+k.getName()+"[k]=new Double(spli[k].trim());");
System.out.println("\t}");
} else if (k.getType().equals(float[].class)){
System.out.println("\tString[] spli = val.split(\",\");");
System.out.println("\t"+k.getName()+"= new float[spli.length];");
System.out.println("\tfor(int k = 0; k < spli.length; k++){");
System.out.println("\t\t"+k.getName()+"[k]=new Float(spli[k].trim());");
System.out.println("\t}");
} else if (k.getType().equals(Double.TYPE)){
System.out.println("\t"+k.getName()+"= new Double(val.trim());");
} else if (k.getType().equals(Float.TYPE)){
System.out.println("\t"+k.getName()+"= new Float(val.trim());");
} else {
System.out.println("Unknown type : "+k.getName());
}
//Validate error? add exception, don't store value.
System.out.println("} catch (ValidationException e){");
System.out.println("toRet.add(e);}");
}
System.out.println("\t}");
if (isCritical){
System.out.println("\t else {");
System.out.println("\t\ttoRet.add(new FieldRequiredException(\""+k.getName()+" required.\"));");
System.out.println("\t}");
}
}
}
//Do we have any unrecognized fields?
System.out.println("StringTreeIterator<WordByRef<TaiScriptStatementAndContext>> iterator = data.iterator();");
System.out.println("while(iterator.hasNext()){");
System.out.println(" String key = iterator.next();");
System.out.print("if (");
for(int p = 0; p < scriptables.size(); p++){
String k = scriptables.get(p);
System.out.print("!key.equals(\""+k+"\")");
if (p+1<scriptables.size()){
System.out.print("&&");
}
}
System.out.println("){");
System.out.println("\t\ttoRet.add(new ValidationException(\"Unrecognized var: \"+key+\".\",key));");
System.out.println("}");
System.out.println(" iterator.tryNext();");
System.out.println("}");
System.out.println("\treturn toRet;");
System.out.println("}");
}
System.out.println("public void autoWrittenDeSerializeCode(){");
for(Field k : fields){
printDeserializerForField(k);
}
System.out.println("}");
System.out.flush();
//OK, now the serialization code:
System.out.println("public void autoWrittenSerializeCode(){");
for(Field k : fields){
printSerializerForField(k);
}
System.out.println("}");
}
/**
* Adds to outFields any serializable fields added by the extended class.
*/
private static void handleExtendedTemplates(Class got, List<Field> outFields) {
try {
GameDataBase.StringBase.ExtendsData ex = (ExtendsData) got.getAnnotation(GameDataBase.StringBase.ExtendsData.class);
if (ex!=null){
for(Class q : ex.parents()){
System.out.println("//Template "+q.toString());
for(Field e : q.getDeclaredFields()){
outFields.add(e);
for(Annotation a : e.getAnnotations()){
Class<? extends Annotation> aType = a.annotationType();
System.out.print("@"+aType.getSimpleName()+"(");
for (Method aT : aType.getDeclaredMethods()){
Object valObj = aT.invoke(a, null);
String valStr = null;
if (valObj.getClass()==String.class){
valStr = "\""+valObj+"\"";
} else {
valStr = ""+valObj;
}
System.out.print(aT.getName()+" = "+valStr);
}
System.out.println(")");
}
System.out.print("public "+e.getType().getSimpleName()+" "+e.getName()+";");
System.out.println();
}
try {
GameDataBase.StringBase.MakeGetters m = (MakeGetters) q.getAnnotation(GameDataBase.StringBase.MakeGetters.class);
if (m!=null){
//Make the getters.
for(Field e : q.getDeclaredFields()){
String name = e.getName();
System.out.print("public "+e.getType().getSimpleName()+" get");
System.out.print(Character.toUpperCase(name.charAt(0)));
if (name.length()>1){
System.out.print(name.substring(1));
}
System.out.println("() {");
System.out.println("\treturn "+name+";");
System.out.println("}");
}
}
} catch (NullPointerException e){
}
}
}
} catch (NullPointerException e){
//None.
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void printDeserializerForField(Field k) {
if (Modifier.isStatic(k.getModifiers())){
return;
}
String annotatedDefault = null;
try {
GameDataBase.DefaultValue a = k.getAnnotation(GameDataBase.DefaultValue.class);
if (a!=null){
annotatedDefault = a.value();
if(annotatedDefault.length()==0){
annotatedDefault = null;
}
}
} catch (NullPointerException e){
//None.
}
if (annotatedDefault==null){
annotatedDefault = "";
}
System.out.print("\t");
if (GameDataBase.class.isAssignableFrom(k.getType())){
String stringTempForm = k.getName()+"_strTmp";
System.out.print("String "+stringTempForm);
System.out.print("= ((StringEntry)readField(\""+k.getName()+"\", ");
System.out.print("new StringEntry(\"\"))).getString();");
System.out.println();
System.out.println("\tif ("+stringTempForm+".length()>0){"); //We actually have a value.
System.out.println("\t\t"+k.getName()+" = new "+k.getType().getSimpleName()+"("+stringTempForm+");");
System.out.println("\t}");
if (annotatedDefault.length()>0){
System.out.println("\t else {");
System.out.println("\t\t"+k.getName()+" = new "+k.getType().getSimpleName()+"(\""+annotatedDefault+"\");");
System.out.println("\t }");
}
} else if (k.getType().isArray() && GameDataBase.class.isAssignableFrom(k.getType().getComponentType())){
String stringTempForm = k.getName()+"_strTmp";
System.out.print("String "+stringTempForm + " = ");
System.out.print("((StringEntry)readField(\""+k.getName()+"\", ");
String defaultStr = annotatedDefault!=null?annotatedDefault:"";
System.out.print("new StringEntry(\""+defaultStr+"\"))).getString();");
System.out.println();
System.out.println("\tif ("+stringTempForm+".length()>0){"); //We actually have a value.
System.out.println("\t\tString[] parts123456 = "+stringTempForm+".split(\",\");");
System.out.println("\t\t"+k.getName()+" = new "+k.getType().getComponentType().getSimpleName()+"[parts123456.length];");
System.out.println("\t\tfor(int qqq = 0; qqq < parts123456.length; qqq++){");
System.out.println("\t\t\t"+k.getName()+"[qqq]=new "+k.getType().getComponentType().getSimpleName()+"(parts123456[qqq]);");
System.out.println("\t}}");
} else if (TaiDAWG.class.isAssignableFrom(k.getType())){
String StringEntryName = "got"+System.nanoTime();
System.out.println("\tStringEntry "+StringEntryName+" = (StringEntry)readField(\""+k.getName()+"\", null);");
System.out.println("\t"+k.getName()+" = new TaiDAWG();");
System.out.println("\t\tif ("+StringEntryName+"!=null){");
System.out.println("\t\t\ttry{");
System.out.println("\t\t\tByteArrayInputStream bais = new ByteArrayInputStream(decodeString("+StringEntryName+".getString()));");
System.out.println("\t\t\tObjectInputStream ois = new ObjectInputStream(bais);");
System.out.println("\t\t\t"+k.getName()+".readInTree(ois,null);");
System.out.println("\t\t} catch (Throwable e){ System.err.println(\"Error in Deserialization of TAIDAWG\"); }");
System.out.println("\t}");
} else if (k.getType().equals(String.class)){
System.out.print(k.getName()+" = ");
System.out.print("((StringEntry)readField(\""+k.getName()+"\", ");
String defaultStr = annotatedDefault!=null?annotatedDefault:"[default]";
System.out.print("new StringEntry(\""+defaultStr+"\"))).getString();");
System.out.println();
} else if (k.getType().equals(Boolean.TYPE)){
System.out.print(k.getName()+" = ");
System.out.print("((IntEntry)readField(\""+k.getName()+"\", ");
String defaultStr = annotatedDefault!=null?annotatedDefault:"0";
System.out.print("new IntEntry("+defaultStr+"))).getInt()==1;");
System.out.println();
} else if (k.getType().equals(Integer.TYPE)){
System.out.print(k.getName()+" = ");
System.out.print("((IntEntry)readField(\""+k.getName()+"\", ");
String defaultStr = annotatedDefault!=null?annotatedDefault:"0";
System.out.print("new IntEntry("+defaultStr+"))).getInt();");
System.out.println();
} else if (k.getType().equals(Double.TYPE)){
System.out.print(k.getName()+" = ");
System.out.print("((DoubleEntry)readField(\""+k.getName()+"\", ");
String defaultStr = annotatedDefault!=null?annotatedDefault:"0";
System.out.print("new DoubleEntry("+defaultStr+"))).getDouble();");
System.out.println();
} else if (k.getType().equals(Float.TYPE)){
System.out.print(k.getName()+" = (float)");
System.out.print("((DoubleEntry)readField(\""+k.getName()+"\", ");
String defaultStr = annotatedDefault!=null?annotatedDefault:"0";
System.out.print("new DoubleEntry("+defaultStr+"))).getDouble();");
System.out.println();
} else if (k.getType().equals(int[].class)){
System.out.print(k.getName()+" = ");
System.out.print("((IntArrayEntry)readField(\""+k.getName()+"\", ");
String defaultStr = annotatedDefault!=null?annotatedDefault:"";
System.out.print("new IntArrayEntry(new int[]{"+defaultStr+"}))).getIntArray();");
System.out.println();
} else if (k.getType().equals(byte[].class)){
System.out.print(k.getName()+" = ");
System.out.print("((ByteArrayEntry)readField(\""+k.getName()+"\", ");
String defaultStr = annotatedDefault!=null?annotatedDefault:"";
System.out.print("new ByteArrayEntry(new byte[]{"+defaultStr+"}))).getByteArray();");
System.out.println();
} else if (k.getType().equals(double[].class)){
System.out.print(k.getName()+" = ");
System.out.print("((DoubleArrayEntry)readField(\""+k.getName()+"\", ");
String defaultStr = annotatedDefault!=null?annotatedDefault:"";
System.out.print("new DoubleArrayEntry(new double[]{"+defaultStr+"}))).getDoubleArray();");
System.out.println();
} else if (k.getType().equals(float[].class)){
System.out.print(k.getName()+" = ");
System.out.print("((FloatArrayEntry)readField(\""+k.getName()+"\", ");
String defaultStr = annotatedDefault!=null?annotatedDefault:"";
System.out.print("new FloatArrayEntry(new float[]{"+defaultStr+"}))).getFloatArray();");
System.out.println();
} else {
System.out.println("customDeserialize"+k.getName()+"();");
//throw new RuntimeException("Invalid entrytype: "+k);
}
}
private static void printSerializerForField(Field k) {
if (Modifier.isStatic(k.getModifiers())){
return;
}
System.out.print("\t");
if (GameDataBase.class.isAssignableFrom(k.getType())){
System.out.print("writeField(\""+k.getName()+"\", ");
System.out.print("new StringEntry("+k.getName()+"!=null?"+k.getName()+".hashToString():\"\"));");
System.out.println();
} else if (k.getType().isArray() && GameDataBase.class.isAssignableFrom(k.getType().getComponentType())){
System.out.print("writeField(\""+k.getName()+"\", ");
System.out.print("new StringEntry("+k.getName()+"!=null?hashAllToString("+k.getName()+"):\"\"));");
System.out.println();
} else if (TaiDAWG.class.isAssignableFrom(k.getType())){
System.out.println("\tif ("+k.getName()+"!=null){");
System.out.println("\t\ttry {");
System.out.println("\t\t\tByteArrayOutputStream baos = new ByteArrayOutputStream();");
System.out.println("\t\t\tObjectOutputStream oow = new ObjectOutputStream(baos);");
System.out.println("\t\t\t"+k.getName()+".writeOutTree(oow);");
System.out.println("\t\t\toow.close();");
System.out.println("\t\t\tbaos.flush();");
System.out.println("\t\t\tString encodeString = encodeString(baos.toByteArray());");
System.out.println("\t\t\twriteField(\""+k.getName()+"\", new StringEntry(encodeString));");
System.out.println("\t\t} catch (Throwable e){;");
System.out.println("\t\t\tSystem.err.println(\"Error in taiDAWG serializations\");");
System.out.println("\t\t}");
System.out.println("\t}");
} else if (k.getType().equals(String.class)){
System.out.print("writeField(\""+k.getName()+"\", ");
System.out.print("new StringEntry("+k.getName()+"));");
System.out.println();
} else if (k.getType().equals(Integer.TYPE)){
System.out.print("writeField(\""+k.getName()+"\", ");
System.out.print("new IntEntry("+k.getName()+"));");
System.out.println();
} else if (k.getType().equals(Boolean.TYPE)){
System.out.print("writeField(\""+k.getName()+"\", ");
System.out.print("new IntEntry("+k.getName()+"?1:0));");
System.out.println();
} else if (k.getType().equals(Double.TYPE) || k.getType().equals(Float.TYPE)){
System.out.print("writeField(\""+k.getName()+"\", ");
System.out.print("new DoubleEntry("+k.getName()+"));");
System.out.println();
} else if (k.getType().equals(int[].class)){
System.out.print("writeField(\""+k.getName()+"\", ");
System.out.print("new IntArrayEntry("+k.getName()+"));");
System.out.println();
} else if (k.getType().equals(byte[].class)){
System.out.print("writeField(\""+k.getName()+"\", ");
System.out.print("new ByteArrayEntry("+k.getName()+"));");
System.out.println();
} else if (k.getType().equals(double[].class)){
System.out.print("writeField(\""+k.getName()+"\", ");
System.out.print("new DoubleArrayEntry("+k.getName()+"));");
System.out.println();
} else if (k.getType().equals(float[].class)){
System.out.print("writeField(\""+k.getName()+"\", ");
System.out.print("new FloatArrayEntry("+k.getName()+"));");
System.out.println();
} else {
System.out.println("customSerialize"+k.getName()+"();");
//throw new RuntimeException("Invalid entrytype: "+k);
}
}
private static Class getInArray(Class[] declaredClasses, String string) {
for(Class stuff : declaredClasses){
if (stuff.getSimpleName().equals(string)){
return stuff;
}
}
return null;
}
}