package pt.ist.fenixframework.pstm.dml;
import java.io.PrintWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.Iterator;
import java.util.List;
import dml.*;
import dml.runtime.Relation;
public class FenixValueTypeSerializationGenerator extends FenixCodeGenerator {
protected static final String SERIALIZATION_METHOD_PREFIX = "serialize$";
protected static final String DESERIALIZATION_METHOD_PREFIX = "deSerialize$";
protected PrintWriter out;
public FenixValueTypeSerializationGenerator(CompilerArgs compArgs, DomainModel domainModel) {
super(compArgs, domainModel);
}
@Override
public void generateCode() {
// create the FenixValueTypeSerializationGenerator before starting the "standard" generation.
String packageName = "pt.ist.fenixframework";
String vtGenClassname = "ValueTypeSerializationGenerator";
File file = new File(getBaseDirectoryFor(packageName), vtGenClassname + ".java");
try {
file.getParentFile().mkdirs();
this.out = new PrintWriter(new FileWriter(file), true);
} catch (java.io.IOException ioe) {
throw new Error("Can't open file" + file);
}
generateFilePreamble(packageName, this.out);
newline(out);
printWords(out, "public", "class", "ValueTypeSerializationGenerator");
newBlock(out);
generateValueTypeSerializations();
closeBlock(out);
}
protected void generateValueTypeSerializations() {
for (ValueType vt : getDomainModel().getAllValueTypes()) {
if (!(vt.isBuiltin() || vt.isEnum())) {
println(out, "");
print(out, "// VT: " + vt.getDomainName());
generateValueTypeSerializableForm(vt);
generateValueTypeSerialization(vt);
generateValueTypeDeSerialization(vt);
}
}
}
protected void generateValueTypeSerializableForm(ValueType vt) {
newline(out);
print(out, "public static class " + makeSerializationValueTypeName(vt) + " implements java.io.Serializable");
newBlock(out);
onNewline(out);
println(out, "private static final long serialVersionUID = 1L;");
generateSlots(vt);
generateConstructor(vt);
closeBlock(out);
}
protected void generateSlots(ValueType vt) {
List<ExternalizationElement> extElems = vt.getExternalizationElements();
for (ExternalizationElement extElem : extElems) {
ValueType extElemVt = extElem.getType();
if (extElemVt.isBuiltin() || extElemVt.isEnum()) {
generateSlotDeclaration(out, extElemVt.getFullname(), makeSlotName(extElem));
} else {
generateSlotDeclaration(out, makeSerializationValueTypeName(extElemVt),
extElem.getMethodName().replace('.', '_'));
}
}
}
protected void generateConstructor(ValueType vt) {
onNewline(out);
printMethod(out, "private", "", makeSerializationValueTypeName(vt), makeArg(vt.getFullname(), "obj"));
startMethodBody(out);
List<ExternalizationElement> extElems = vt.getExternalizationElements();
for (ExternalizationElement extElem : extElems) {
ValueType extElemVt = extElem.getType();
printWords(out, "this." + makeSlotName(extElem), "=",
applyExternalizationIfRequired(applyExternalizerTo(extElem, "obj"), extElemVt));
println(out, ";");
}
endMethodBody(out);
}
protected String applyExternalizerTo(ExternalizationElement extElem, String expr) {
String extMethodName = extElem.getMethodName();
// parametric types require cast, so we alwys cast
String cast = "(" + extElem.getType().getFullname() + ")";
return (extMethodName.contains("."))
? cast + extMethodName + "(" + expr + ")"
: cast + expr + "." + extMethodName + "()";
}
protected String applyExternalizationIfRequired(String expr, ValueType vt) {
if (!(vt.isBuiltin() || vt.isEnum())) {
return SERIALIZATION_METHOD_PREFIX + makeSafeValueTypeName(vt) + "(" + expr + ")";
} else {
return expr;
}
}
protected String makeSerializationValueTypeName(ValueType vt) {
return "Serialized$" + makeSafeValueTypeName(vt);
}
protected String makeSafeValueTypeName(ValueType vt) {
return vt.getDomainName().replace('.', '$');
}
protected String makeSlotName(ExternalizationElement extElem) {
return extElem.getMethodName().replace('.', '_');
}
protected void generateCheckNullable(ValueType vt) {
if (FenixDomainModel.isNullableType(vt)) {
print(out, "(obj == null) ? null : ");
}
}
protected void generateValueTypeSerialization(ValueType vt) {
onNewline(out);
printMethod(out, "public static", makeSerializationValueTypeName(vt),
SERIALIZATION_METHOD_PREFIX + makeSafeValueTypeName(vt),
makeArg(vt.getFullname(), "obj"));
startMethodBody(out);
print(out, "return ");
generateCheckNullable(vt);
print(out, "new " + makeSerializationValueTypeName(vt) + "(obj);");
endMethodBody(out);
}
protected void generateValueTypeDeSerialization(ValueType vt) {
onNewline(out);
printMethod(out, "public static", vt.getFullname(),
DESERIALIZATION_METHOD_PREFIX + makeSafeValueTypeName(vt),
makeArg(makeSerializationValueTypeName(vt) , "obj"));
startMethodBody(out);
String internalizationMethodName = vt.getInternalizationMethodName();
if (internalizationMethodName == null) { // class constructor
internalizationMethodName = "new " + vt.getFullname();
} else if (!internalizationMethodName.contains(".")) { // static method in the same class
internalizationMethodName = vt.getFullname() + "." + internalizationMethodName;
}
print(out, "return ");
generateCheckNullable(vt);
print(out, "(" + vt.getFullname() + ")");
print(out, internalizationMethodName + "(");
boolean firstArg = true;
List<ExternalizationElement> extElems = vt.getExternalizationElements();
for (ExternalizationElement extElem : extElems) {
if (firstArg) {
firstArg = false;
} else {
print(out, ", ");
}
ValueType extElemVt = extElem.getType();
if (extElemVt.isBuiltin() || extElemVt.isEnum()) {
print(out, "obj." + makeSlotName(extElem));
} else {
print(out, DESERIALIZATION_METHOD_PREFIX + makeSafeValueTypeName(extElemVt) + "(obj." +
extElem.getMethodName().replace('.', '_') + ")");
}
}
print(out, ");");
endMethodBody(out);
}
}