package pt.ist.fenixframework.pstm.dml;
import java.io.PrintWriter;
import java.util.Iterator;
import dml.*;
import dml.runtime.Relation;
import pt.ist.fenixframework.pstm.repository.DbUtil;
public class FenixCodeGeneratorOneBoxPerObject extends FenixCodeGenerator {
private static final String DO_STATE_SUPER = "pt.ist.fenixframework.pstm.OneBoxDomainObject.DO_State ";
private static final String ONE_BOX_DOMAIN_OBJECT_CLASS = "pt.ist.fenixframework.pstm.OneBoxDomainObject";
protected DomainClass currentClass;
// used by the value-type generator
protected FenixValueTypeSerializationGenerator valueTypeGenerator;
public FenixCodeGeneratorOneBoxPerObject(CompilerArgs compArgs, DomainModel domainModel) {
super(compArgs, domainModel);
this.valueTypeGenerator = new FenixValueTypeSerializationGenerator(compArgs, domainModel);
}
@Override
protected String getDomainClassRoot() {
return ONE_BOX_DOMAIN_OBJECT_CLASS;
}
@Override
protected void generateBaseClassBody(DomainClass domClass, PrintWriter out) {
// this is a hack to help redefine the getSlotExpression method
// the proper way of doing this would be to change the
// protocol used in dml.CodeGenerator to distinguish between
// slots corresponding to roles from others
// but this allows us to test this code without having to
// change the DML code
currentClass = domClass;
super.generateBaseClassBody(domClass, out);
generateMethodGetRelationFor(domClass, out);
generateMakeNewStateMethod(out);
generateCreateAllListsMethod(domClass, out);
generateDOStateInnerClass(domClass, out);
}
protected void generateMethodGetRelationFor(DomainClass domClass, PrintWriter out) {
printMethod(out, "protected", Relation.class.getName(), "get$$relationFor", makeArg("String", "attrName"));
startMethodBody(out);
for (Role role : domClass.getRoleSlotsList()) {
if ((role.getName() != null) && (role.getMultiplicityUpper() != 1)) {
print(out, "if (attrName.equals(\"");
print(out, role.getName());
print(out, "\")) return ");
print(out, getRelationSlotNameFor(role));
println(out, ";");
}
}
println(out, "return super.get$$relationFor(attrName);");
endMethodBody(out);
}
@Override
protected void generateSlots(Iterator slotsIter, PrintWriter out) {
// do nothing
}
@Override
protected void generateInitSlot(Slot slot, PrintWriter out) {
// do nothing
}
@Override
protected void generateRoleSlot(Role role, PrintWriter out) {
// don't generate slots for roles anymore
// but generate an accessor for collections instead
if (role.getMultiplicityUpper() != 1) {
generateRelationListGetter(role, out);
}
}
protected void generateRelationListGetter(Role role, PrintWriter out) {
onNewline(out);
printMethod(out, "private", getRelationAwareTypeFor(role), makeRelationListGetterName(role.getName()));
startMethodBody(out);
printWords(out, "return", "get$$relationList(\"");
print(out, role.getName());
print(out, "\", ");
print(out, getRelationSlotNameFor(role));
println(out, ");");
endMethodBody(out);
}
@Override
protected void generateInitRoleSlot(Role role, PrintWriter out) {
// don't init anymore
}
@Override
protected String getRoleOneBaseType() {
return RoleOne.class.getName();
}
@Override
protected void generateGetSlotExpression(String slotName, PrintWriter out) {
print(out, getSlotExpression(slotName));
}
@Override
protected String getSlotExpression(String slotName) {
Role role = currentClass.findRoleSlot(slotName);
if ((role != null) && (role.getMultiplicityUpper() != 1)) {
return makeRelationListGetterName(slotName) + "()";
} else {
return "((DO_State)this.get$obj$state(false))." + slotName;
}
}
protected String makeRelationListGetterName(String roleName) {
return "get$rl$" + roleName;
}
@Override
protected void generateSetterBody(String setterName, String slotName, String typeName, PrintWriter out) {
print(out, "((DO_State)this.get$obj$state(true)).");
print(out, slotName);
print(out, " = ");
print(out, slotName);
print(out, ";");
}
protected void generateDOStateInnerClass(DomainClass domClass, PrintWriter out) {
onNewline(out);
print(out, "protected static class DO_State extends ");
String superclassName = getEntityFullName(domClass.getSuperclass());
printWords(out, (superclassName == null) ? getDomainClassRoot() : superclassName);
print(out, ".DO_State");
newBlock(out);
onNewline(out);
// all the slots
for (Slot slot : domClass.getSlotsList()) {
generateSlotDeclaration(out, slot.getTypeName(), slot.getName());
}
for (Role role : domClass.getRoleSlotsList()) {
if ((role.getName() != null) && (role.getMultiplicityUpper() == 1)) {
generateSlotDeclaration(out, getTypeFullName(role.getType()), role.getName());
}
}
// the copyTo method
printMethod(out, "protected", "void", "copyTo", makeArg(DO_STATE_SUPER, "newState"));
startMethodBody(out);
println(out, "super.copyTo(newState);");
println(out, "DO_State newCasted = (DO_State)newState;");
for (Slot slot : domClass.getSlotsList()) {
printWords(out, "newCasted." + slot.getName(), "=", "this." + slot.getName());
println(out, ";");
}
for (Role role : domClass.getRoleSlotsList()) {
if ((role.getName() != null) && (role.getMultiplicityUpper() == 1)) {
printWords(out, "newCasted." + role.getName(), "=", "this." + role.getName());
println(out, ";");
}
}
endMethodBody(out);
generateSerializationCode(domClass, out);
closeBlock(out);
}
/* Override the main generation method to create an additional generation instance. It will
* generate the class for value-type serialization.
*/
@Override
public void generateCode() {
this.valueTypeGenerator.generateCode();
super.generateCode();
}
protected void generateSerializationCode(DomainClass domClass, PrintWriter out) {
newline(out);
println(out, "// serialization code");
generateWriteReplace(out);
newline(out);
print(out, "protected static class SerializedForm extends ");
String superclassName = getEntityFullName(domClass.getSuperclass());
printWords(out, (superclassName == null) ? getDomainClassRoot() : superclassName);
print(out, ".DO_State.SerializedForm");
newBlock(out);
onNewline(out);
println(out, "private static final long serialVersionUID = 1L;");
// all the slots to serialize
newline(out);
for (Slot slot : domClass.getSlotsList()) {
ValueType vt = slot.getSlotType();
if (vt.isBuiltin() || vt.isEnum()) { // declare the same type
generateSlotDeclaration(out, slot.getTypeName(), slot.getName());
} else {
generateSlotDeclaration(out, this.valueTypeGenerator.makeSerializationValueTypeName(vt), slot.getName());
}
}
for (Role role : domClass.getRoleSlotsList()) {
if ((role.getName() != null) && (role.getMultiplicityUpper() == 1)) {
generateSlotDeclaration(out, getTypeFullName(role.getType()), role.getName());
}
}
generateSerializedFormConstructor(domClass, out);
generateSerializedFormReadResolve(domClass, out);
generateSerializedFormFillInState(domClass, out);
closeBlock(out);
}
protected void generateWriteReplace(PrintWriter out) {
printMethod(out, "protected", "Object", "writeReplace");
print(out, " throws java.io.ObjectStreamException");
startMethodBody(out);
print(out, "return new SerializedForm(this);");
endMethodBody(out);
}
protected void generateSerializedFormConstructor(DomainClass domClass, PrintWriter out) {
newline(out);
printMethod(out, "protected", "", "SerializedForm", makeArg("DO_State", "obj"));
startMethodBody(out);
print(out, "super(obj);");
onNewline(out);
// copy values to all the slots
for (Slot slot : domClass.getSlotsList()) {
generateSlotSerializedForm(slot, out);
}
for (Role role : domClass.getRoleSlotsList()) {
if ((role.getName() != null) && (role.getMultiplicityUpper() == 1)) {
printWords(out, "this." + role.getName(), "=", "obj." + role.getName());
println(out, ";");
}
}
endMethodBody(out);
}
protected void generateSlotSerializedForm(Slot slot, PrintWriter out) {
// value types have to be externalized. others are simply copied
ValueType vt = slot.getSlotType();
printWords(out, "this." + slot.getName(), "=");
if (vt.isBuiltin() || vt.isEnum()) {
printWords(out, "obj." + slot.getName());
} else {
printWords(out, "pt.ist.fenixframework.ValueTypeSerializationGenerator."
+ this.valueTypeGenerator.SERIALIZATION_METHOD_PREFIX
+ this.valueTypeGenerator.makeSafeValueTypeName(vt));
print(out, "(obj." + slot.getName() + ")");
}
println(out, ";");
}
protected void generateSerializedFormReadResolve(DomainClass domClass, PrintWriter out) {
newline(out);
printMethod(out, "", "Object", "readResolve");
print(out, " throws java.io.ObjectStreamException");
startMethodBody(out);
println(out, "DO_State newState = new DO_State();");
println(out, "fillInState(newState);");
print(out, "return newState;");
endMethodBody(out);
}
protected void generateSerializedFormFillInState(DomainClass domClass, PrintWriter out) {
newline(out);
printMethod(out, "protected", "void", "fillInState", makeArg("pt.ist.fenixframework.pstm.OneBoxDomainObject.DO_State", "obj"));
startMethodBody(out);
println(out, "super.fillInState(obj);");
println(out, "DO_State state = (DO_State)obj;");
// value types have to be internalized. others are simply copied
for (Slot slot : domClass.getSlotsList()) {
ValueType vt = slot.getSlotType();
printWords(out, "state." + slot.getName(), "=");
if (vt.isBuiltin() || vt.isEnum()) {
printWords(out, "this." + slot.getName());
} else {
printWords(out, "pt.ist.fenixframework.ValueTypeSerializationGenerator."
+ this.valueTypeGenerator.DESERIALIZATION_METHOD_PREFIX
+ this.valueTypeGenerator.makeSafeValueTypeName(vt));
print(out, "(this." + slot.getName() + ")");
}
println(out, ";");
}
for (Role role : domClass.getRoleSlotsList()) {
if ((role.getName() != null) && (role.getMultiplicityUpper() == 1)) {
printWords(out, "state." + role.getName(), "=", "this." + role.getName());
println(out, ";");
}
}
endMethodBody(out);
}
protected void generateMakeNewStateMethod(PrintWriter out) {
printMethod(out, "protected", DO_STATE_SUPER, "make$newState");
startMethodBody(out);
println(out, "return new DO_State();");
endMethodBody(out);
}
protected void generateCreateAllListsMethod(DomainClass domClass, PrintWriter out) {
printMethod(out, "protected", "void", "create$allLists");
startMethodBody(out);
println(out, "super.create$allLists();");
for (Role role : domClass.getRoleSlotsList()) {
if ((role.getName() != null) && (role.getMultiplicityUpper() != 1)) {
print(out, "get$$relationList(\"");
print(out, role.getName());
print(out, "\", ");
print(out, getRelationSlotNameFor(role));
println(out, ");");
}
}
endMethodBody(out);
}
@Override
protected void generateDatabaseReader(DomainClass domClass, PrintWriter out) {
newline(out);
printMethod(out, "protected", "void", "readStateFromResultSet", makeArg("java.sql.ResultSet", "rs"), makeArg(
DO_STATE_SUPER, "state"));
print(out, " throws java.sql.SQLException");
startMethodBody(out);
if (domClass.hasSuperclass()) {
println(out, "super.readStateFromResultSet(rs, state);");
}
println(out, "DO_State castedState = (DO_State)state;");
for (Slot slot : domClass.getSlotsList()) {
generateOneSlotRsReader(out, slot.getName(), slot.getSlotType());
}
for (Role role : domClass.getRoleSlotsList()) {
if ((role.getName() != null) && (role.getMultiplicityUpper() == 1)) {
generateOneRoleSlotRsReader(out, role.getName());
}
}
endMethodBody(out);
}
@Override
protected void generateOneSlotRsReader(PrintWriter out, String name, ValueType type) {
onNewline(out);
print(out, "set$");
print(out, name);
print(out, "(");
printRsReaderExpressions(out, type, DbUtil.convertToDBStyle(name), 0);
print(out, ", state);");
}
@Override
protected void generateOneRoleSlotRsReader(PrintWriter out, String name) {
onNewline(out);
print(out, "castedState.");
print(out, name);
print(out, " = ");
print(out, RESULT_SET_READER_CLASS);
print(out, ".readDomainObject(rs, \"OID_");
print(out, DbUtil.convertToDBStyle(name));
print(out, "\");");
}
@Override
protected void generateInternalizationSetter(String name, ValueType type, PrintWriter out) {
newline(out);
print(out, "private final void set$");
print(out, name);
print(out, "(");
ValueType vt = getExternalizationType(type);
print(out, vt.getFullname());
print(out, " arg0, ");
print(out, DO_STATE_SUPER);
print(out, " obj$state)");
startMethodBody(out);
print(out, "((DO_State)obj$state).");
print(out, name);
print(out, " = (");
print(out, type.getFullname());
print(out, ")(");
if (FenixDomainModel.isNullableType(vt)) {
print(out, "(arg0 == null) ? null : ");
}
print(out, getRsReaderExpression(type));
print(out, ");");
endMethodBody(out);
}
protected String getObjStateExpression(String baseType, String prefix, String name, boolean forWriting) {
return String.format("((%s.DO_State)%s.get$obj$state(%b)).%s", baseType, prefix, forWriting, name);
}
protected String getReadExpression(String baseType, String prefix, String name) {
return getObjStateExpression(baseType, prefix, name, false);
}
protected String getLValueExpression(String baseType, String prefix, String name) {
return getObjStateExpression(baseType, prefix, name, true);
}
@Override
protected String getRoleArgs(Role role) {
return "";
}
@Override
protected void generateRoleClassGetter(Role role, Role otherRole, PrintWriter out) {
String rType = getTypeFullName(role.getType());
String oType = getTypeFullName(otherRole.getType());
if (role.getMultiplicityUpper() == 1) {
printMethod(out, "public", rType, "getValue", makeArg(oType, "o1"));
startMethodBody(out);
print(out, "return ");
print(out, getReadExpression(otherRole.getType().getBaseName(), "o1", role.getName()));
print(out, ";");
endMethodBody(out);
printMethod(out, "public", "void", "setValue", makeArg(oType, "o1"), makeArg(rType, "o2"));
startMethodBody(out);
print(out, getLValueExpression(otherRole.getType().getBaseName(), "o1", role.getName()));
print(out, " = o2;");
endMethodBody(out);
} else {
printMethod(out, "public", makeGenericType("dml.runtime.RelationBaseSet", rType), "getSet", makeArg(oType, "o1"));
startMethodBody(out);
print(out, "return ((");
print(out, otherRole.getType().getBaseName());
print(out, ")o1).");
print(out, makeRelationListGetterName(role.getName()) + "()");
print(out, ";");
endMethodBody(out);
}
}
}