Commit 4a507826 authored by Johannes Mey's avatar Johannes Mey
Browse files

serializer and deserializer (reference resolving not working)

parent bf521752
*.jarsrc/test/java/org/jastadd/relast/tests/Resolver2.java
*.jar
.idea/
.gradle/
build
......@@ -8,6 +8,8 @@ out/
*.class
src/test/jastadd/relations/Relations.ast
src/test/jastadd/relations/Relations.jadd
src/test/jastadd/relations/Relations2.ast
src/test/jastadd/relations/Relations2.jadd
src/test/jastadd/lowerbounds/LowerBounds.ast
src/test/jastadd/lowerbounds/LowerBounds.jadd
src/test/jastadd/multiple/Multiple.ast
......@@ -15,8 +17,14 @@ src/test/jastadd/multiple/Multiple.jadd
src/test/jastadd/resolver/Resolver.ast
src/test/jastadd/resolver/Resolver.jadd
src/test/jastadd/resolver/ResolverRefResolver.jadd
src/test/jastadd/resolver/ResolverResolverStubs.jrag
src/test/jastadd/resolver2/Resolver.ast
src/test/jastadd/resolver2/Resolver.jadd
src/test/jastadd/resolver2/ResolverRefResolver.jadd
src/test/jastadd/resolver2/ResolverResolverStubs.jrag
src/test/jastadd/listnames/ListNames.ast
src/test/jastadd/listnames/ListNames.jadd
\ No newline at end of file
src/test/jastadd/listnames/ListNames.jadd
src/test/jastadd/serializer/Serializer.ast
src/test/jastadd/serializer/Serializer.jadd
src/test/jastadd/serializer/SerializerSerializer.jadd
src/test/jastadd/serializer/SerializerRefResolver.jadd
......@@ -21,6 +21,8 @@ buildscript {
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.4.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.4.0'
compile 'com.fasterxml.jackson.core:jackson-core:2.9.8'
compile 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
runtime 'org.jastadd:jastadd:2.3.2'
compile group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.10.0'
......@@ -49,6 +51,7 @@ jar {
jastadd {
configureModuleBuild()
modules {
//noinspection GroovyAssignabilityCheck
module("RelAst") {
java {
......@@ -110,6 +113,7 @@ task preprocessRelationTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/relations/Relations.relast', '--file', '--grammarName=src/test/jastadd/relations/Relations'
}
......@@ -121,6 +125,7 @@ task doublePreprocessRelationTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/relations/Relations.ast', '--file', '--grammarName=src/test/jastadd/relations/Relations2'
}
......@@ -132,7 +137,11 @@ task compileRelationTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.JastAdd'
args '--o=src/test/java-gen/', '--package=relations.ast', 'src/test/jastadd/relations/Relations.ast', 'src/test/jastadd/relations/Relations.jadd', 'src/test/jastadd/Utils.jadd'
//noinspection GroovyAssignabilityCheck
args '--o=src/test/java-gen/', '--package=relations.ast',
'src/test/jastadd/relations/Relations.ast',
'src/test/jastadd/relations/Relations.jadd',
'src/test/jastadd/Utils.jadd'
}
task preprocessLowerBoundsTest(type: JavaExec, group: 'verification') {
......@@ -143,6 +152,7 @@ task preprocessLowerBoundsTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/lowerbounds/LowerBounds.relast', '--file', '--grammarName=src/test/jastadd/lowerbounds/LowerBounds'
}
......@@ -154,7 +164,11 @@ task compileLowerBoundsTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.JastAdd'
args '--o=src/test/java-gen/', '--package=lowerbounds.ast', 'src/test/jastadd/lowerbounds/LowerBounds.ast', 'src/test/jastadd/lowerbounds/LowerBounds.jadd', 'src/test/jastadd/Utils.jadd'
//noinspection GroovyAssignabilityCheck
args '--o=src/test/java-gen/', '--package=lowerbounds.ast',
'src/test/jastadd/lowerbounds/LowerBounds.ast',
'src/test/jastadd/lowerbounds/LowerBounds.jadd',
'src/test/jastadd/Utils.jadd'
}
task preprocessMultipleTest(type: JavaExec, group: 'verification') {
......@@ -165,6 +179,7 @@ task preprocessMultipleTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/multiple/Part1.relast', 'src/test/jastadd/multiple/Part2.relast', 'src/test/jastadd/multiple/Part3.relast', '--file', '--grammarName=src/test/jastadd/multiple/Multiple'
}
......@@ -176,17 +191,22 @@ task compileMultipleTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.JastAdd'
args '--o=src/test/java-gen/', '--package=multiple.ast', 'src/test/jastadd/multiple/Multiple.ast', 'src/test/jastadd/multiple/Multiple.jadd', 'src/test/jastadd/Utils.jadd'
//noinspection GroovyAssignabilityCheck
args '--o=src/test/java-gen/', '--package=multiple.ast',
'src/test/jastadd/multiple/Multiple.ast',
'src/test/jastadd/multiple/Multiple.jadd',
'src/test/jastadd/Utils.jadd'
}
task preprocessResolverTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/jastadd/resolver/Resolver.ast', 'src/test/jastadd/resolver/Resolver.jadd', 'src/test/jastadd/resolver/ResolverRefResolver.jadd'
delete 'src/test/jastadd/resolver/Resolver.ast', 'src/test/jastadd/resolver/Resolver.jadd', 'src/test/jastadd/resolver/ResolverRefResolver.jadd', 'src/test/jastadd/resolver/ResolverResolverStubs.jrag'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/resolver/Resolver.relast', '--file', '--grammarName=src/test/jastadd/resolver/Resolver', '--resolverHelper'
}
......@@ -198,7 +218,15 @@ task compileResolverTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.JastAdd'
args '--o=src/test/java-gen/', '--package=resolver.ast', 'src/test/jastadd/resolver/Resolver.ast', 'src/test/jastadd/resolver/Resolver.jadd', 'src/test/jastadd/resolver/ResolverUtils.jadd', 'src/test/jastadd/resolver/ResolverRefResolver.jadd', 'src/test/jastadd/resolver/MyRefResolver.jadd', 'src/test/jastadd/Utils.jadd'
//noinspection GroovyAssignabilityCheck
args '--o=src/test/java-gen/', '--package=resolver.ast',
'src/test/jastadd/resolver/Resolver.ast',
'src/test/jastadd/resolver/Resolver.jadd',
'src/test/jastadd/resolver/ResolverUtils.jadd',
'src/test/jastadd/resolver/ResolverRefResolver.jadd',
'src/test/jastadd/resolver/ResolverResolverStubs.jrag',
'src/test/jastadd/resolver/MyRefResolver.jadd',
'src/test/jastadd/Utils.jadd'
}
......@@ -210,6 +238,7 @@ task preprocessResolver2Test(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/resolver2/Resolver.relast', '--file', '--grammarName=src/test/jastadd/resolver2/Resolver', '--resolverHelper'
}
......@@ -221,7 +250,15 @@ task compileResolver2Test(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.JastAdd'
args '--o=src/test/java-gen/', '--package=resolver2.ast', 'src/test/jastadd/resolver2/Resolver.ast', 'src/test/jastadd/resolver2/Resolver.jadd', 'src/test/jastadd/resolver2/ResolverUtils.jadd', 'src/test/jastadd/resolver2/ResolverRefResolver.jadd', 'src/test/jastadd/resolver2/MyRefResolver.jadd', 'src/test/jastadd/Utils.jadd'
//noinspection GroovyAssignabilityCheck
args '--o=src/test/java-gen/', '--package=resolver2.ast',
'src/test/jastadd/resolver2/Resolver.ast',
'src/test/jastadd/resolver2/Resolver.jadd',
'src/test/jastadd/resolver2/ResolverUtils.jadd',
'src/test/jastadd/resolver2/ResolverRefResolver.jadd',
'src/test/jastadd/resolver2/ResolverResolverStubs.jrag',
'src/test/jastadd/resolver2/MyRefResolver.jadd',
'src/test/jastadd/Utils.jadd'
}
task preprocessListNamesTest(type: JavaExec, group: 'verification') {
......@@ -232,6 +269,7 @@ task preprocessListNamesTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/listnames/ListNames.relast', '--file', '--grammarName=src/test/jastadd/listnames/ListNames', '--jastAddList=ListyMcListface'
}
......@@ -243,9 +281,44 @@ task compileListNamesTest(type: JavaExec, group: 'verification') {
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.JastAdd'
args '--o=src/test/java-gen/', '--package=listnames.ast', 'src/test/jastadd/listnames/ListNames.ast', 'src/test/jastadd/listnames/ListNames.jadd', 'src/test/jastadd/Utils.jadd', '--List=ListyMcListface'
//noinspection GroovyAssignabilityCheck
args '--o=src/test/java-gen/', '--package=listnames.ast', '--List=ListyMcListface',
'src/test/jastadd/listnames/ListNames.ast',
'src/test/jastadd/listnames/ListNames.jadd',
'src/test/jastadd/Utils.jadd'
}
task preprocessSerializerTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/jastadd/serializer/Serializer.ast',
'src/test/jastadd/serializer/Serializer.jadd',
'src/test/jastadd/serializer/SerializerRefResolver.jadd',
'src/test/jastadd/serializer/SerializerSerializer.jadd'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.relast.compiler.Compiler'
//noinspection GroovyAssignabilityCheck
args 'src/test/jastadd/serializer/Serializer.relast', '--file', '--grammarName=src/test/jastadd/serializer/Serializer', '--serializer=jackson'
}
task compileSerializerTest(type: JavaExec, group: 'verification') {
doFirst {
delete 'src/test/java-gen/serializer'
}
classpath = sourceSets.main.runtimeClasspath
main = 'org.jastadd.JastAdd'
//noinspection GroovyAssignabilityCheck
args '--o=src/test/java-gen/', '--package=serializer.ast',
'src/test/jastadd/serializer/Serializer.ast',
'src/test/jastadd/serializer/Serializer.jadd',
'src/test/jastadd/serializer/SerializerRefResolver.jadd',
'src/test/jastadd/serializer/SerializerSerializer.jadd',
'src/test/jastadd/Utils.jadd'
}
test {
outputs.upToDateWhen { false }
......@@ -270,4 +343,7 @@ test.dependsOn compileResolver2Test
compileResolver2Test.dependsOn preprocessResolver2Test
test.dependsOn compileListNamesTest
compileListNamesTest.dependsOn preprocessListNamesTest
\ No newline at end of file
compileListNamesTest.dependsOn preprocessListNamesTest
test.dependsOn compileSerializerTest
compileSerializerTest.dependsOn preprocessSerializerTest
\ No newline at end of file
......@@ -3,7 +3,8 @@ aspect BackendAbstractGrammar {
public static String ASTNode.listClass = "ArrayList";
public static String ASTNode.jastAddListType = "List";
public static boolean ASTNode.resolverHelper = false;
public static boolean ASTNode.resolverHelper = false;
public static boolean ASTNode.serializer = false;
public String Program.generateAbstractGrammar() {
StringBuilder sb = new StringBuilder();
......@@ -694,7 +695,13 @@ aspect NameResolutionHelper {
return sb.toString();
}
public void Program.generateRewriteToSuperTypeStub(StringBuilder sb) {
public String Program.generateResolverStubs() {
StringBuilder sb = new StringBuilder();
generateResolverStubs(sb);
return sb.toString();
}
public void Program.generateResolverStubs(StringBuilder sb) {
sb.append("aspect RefResolverStubs {\n\n");
for (Relation r: getRelations()) {
......@@ -708,6 +715,9 @@ aspect NameResolutionHelper {
}
}
sb.append("}\n\n");
}
public void Program.generateRewriteToSuperTypeStub(StringBuilder sb) {
sb.append("aspect ReferenceCreation {\n\n");
......@@ -871,6 +881,391 @@ aspect NameResolutionHelper {
}
}
aspect Serializer {
protected static String ASTNode.jsonTypeKey = "type";
protected static String ASTNode.jsonNodeType = "com.fasterxml.jackson.databind.JsonNode";
protected static String ASTNode.jsonNodeTypeAccessor = ".get(\"" + jsonTypeKey + "\").asText()";
public String Program.generateSerializer() {
StringBuilder sb = new StringBuilder();
generateFromJson(sb);
generateToJson(sb);
writeUID(sb);
return sb.toString();
}
public void Program.generateFromJson(StringBuilder sb) {
sb.append("aspect JsonToModel {\n");
sb.append(ind(1) + "public class DeserializationException extends Exception {\n");
sb.append(ind(2) + "public DeserializationException(String message) {\n");
sb.append(ind(3) + "super(message);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "public DeserializationException(String message, Exception cause) {\n");
sb.append(ind(3) + "super(message, cause);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "public void ASTNode.serialize(com.fasterxml.jackson.core.JsonGenerator g) throws SerializationException {\n");
sb.append(ind(2) + "serialize(g, null);\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "public void ASTNode.serialize(com.fasterxml.jackson.core.JsonGenerator g, String field) throws SerializationException {\n");
sb.append(ind(2) + "throw new SerializationException(\"unable to serialize class \" + this.getClass().getSimpleName());\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "public void ASTNode.serialize(java.io.File file) throws SerializationException {\n");
sb.append(ind(2) + "try {\n");
sb.append(ind(3) + "com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory();\n");
sb.append(ind(3) + "com.fasterxml.jackson.core.JsonGenerator generator = factory.createGenerator(file, com.fasterxml.jackson.core.JsonEncoding.UTF8);\n");
sb.append(ind(3) + "generator.setPrettyPrinter(new com.fasterxml.jackson.core.util.DefaultPrettyPrinter());\n");
sb.append(ind(3) + "serialize(generator);\n");
sb.append(ind(3) + "generator.close();\n");
sb.append(ind(2) + "} catch (java.io.IOException e) {\n");
sb.append(ind(3) + "throw new SerializationException(\"Unable to serialize file \" + file.getAbsolutePath(), e);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
for (TypeDecl decl : getTypeDeclList()) {
if (!decl.isUnresolved()) {
decl.deserialize(sb);
}
}
sb.append("}\n");
}
public void Program.generateToJson(StringBuilder sb) {
sb.append("aspect ModelToJson {\n");
sb.append(ind(1) + "public class SerializationException extends Exception {\n");
sb.append(ind(2) + "public SerializationException(String message) {\n");
sb.append(ind(3) + "super(message);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(2) + "public SerializationException(String message, Exception cause) {\n");
sb.append(ind(3) + "super(message, cause);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
for (TypeDecl decl : getTypeDeclList()) {
if (!decl.isUnresolved()) {
decl.serialize(sb);
}
}
sb.append("}\n");
}
public void TypeDecl.serialize(StringBuilder sb) {
sb.append(ind(1) + "public void " + getID() + ".serialize(com.fasterxml.jackson.core.JsonGenerator g, String fieldName) throws SerializationException {\n");
sb.append(ind(2) + "try {\n");
sb.append(ind(3) + "if (fieldName == null) {\n");
sb.append(ind(4) + "g.writeStartObject();\n");
sb.append(ind(3) + "} else {\n");
sb.append(ind(4) + "g.writeObjectFieldStart(fieldName);\n");
sb.append(ind(3) + "}\n");
sb.append(ind(3) + "g.writeStringField(\"" + jsonTypeKey + "\", \"" + getID() + "\");\n");
sb.append(ind(3) + "g.writeStringField(\"id\", __uid());\n");
if (componentsTransitive().size() > 0) {
sb.append(ind(3) + "g.writeObjectFieldStart(\"children\");\n");
for (Component child : componentsTransitive()) {
child.serialize(sb, 3);
}
sb.append(ind(3) + "g.writeEndObject(); // children\n");
}
if (relationComponents().size() > 0) {
sb.append(ind(3) + "g.writeObjectFieldStart(\"relations\");\n");
for (RelationComponent relation : relationComponents()) {
relation.serialize(sb, 3);
}
sb.append(ind(3) + "g.writeEndObject(); // relations\n");
}
sb.append(ind(3) + "g.writeEndObject();\n");
sb.append(ind(2) + "} catch (java.io.IOException e) {\n");
sb.append(ind(3) + "throw new SerializationException(\"unable to serialize " + getID() + "\", e);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
}
public abstract void Component.serialize(StringBuilder sb, int indent);
public void NormalComponent.serialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "get" + getID() + "().serialize(g, \"" + getID() + "\");\n");
}
public void OptComponent.serialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "if (has" + getID() + "()) {\n");
sb.append(ind(indent + 1) + "get" + getID() + "().serialize(g, \"" + getID() + "\");\n");
sb.append(ind(indent) + "}\n");
}
public void TokenComponent.serialize(StringBuilder sb, int indent) {
String type = getTypeUse().getID();
switch (type) {
case "float":
case "Float":
case "double":
case "Double":
case "int":
case "Integer":
case "short":
case "Short":
case "long":
case "Long":
case "byte":
case "Byte":
sb.append(ind(indent) + "g.writeNumberField(\"" + getID() + "\", get" + getID() + "());\n");
break;
case "boolean":
case "Boolean":
sb.append(ind(indent) + "g.writeBooleanField(\"" + getID() + "\", get" + getID() + "());\n");
break;
case "char":
case "Character":
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", Character.toString(get"+ getID() + "()));\n");
break;
case "String":
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "());\n");
break;
case "java.time.Instant":
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "()).toString());\n");
break;
case "java.time.Period":
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "()).toString());\n");
break;
default:
// assume that the type is an enum. there is no way of checking this here
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "()).name());\n");
// sb.append("throw new DeserializationException(\"Unable to deserialize child node of type \"" + getTypeUse() + "\"\")")
}
}
public void NTAComponent.serialize(StringBuilder sb, int indent) {
// do not serialize NTA
}
public void ListComponent.serialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "if (getNum" + getID() + "() > 0) {\n");
sb.append(ind(indent + 1) + "g.writeArrayFieldStart(\"" + getID() + "\");\n");
sb.append(ind(indent + 1) + "for (" + getTypeUse().decl().getID() + " child : get" + getID() + "List()) {\n");
sb.append(ind(indent + 2) + "child.serialize(g);\n");
sb.append(ind(indent + 1) + "}\n");
sb.append(ind(indent + 1) + "g.writeEndArray();\n");
sb.append(ind(indent) + "}\n");
}
public void OneRelationComponent.serialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().__uid());\n");
}
public void OptionalRelationComponent.serialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "if (has" + getID() + "()) {\n");
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().__uid());\n");
sb.append(ind(indent) + "}\n");
}
public void ManyRelationComponent.serialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "g.writeArrayFieldStart(\"" + getID() + "\");\n");
sb.append(ind(indent) + "for (" + ofTypeDecl().getID() + " child : get" + getID() + "List()) {\n");
sb.append(ind(indent + 1) + "g.writeString(child.__uid());\n");
sb.append(ind(indent) + "}\n");
sb.append(ind(indent) + "g.writeEndArray();\n");
}
public void TypeDecl.deserialize(StringBuilder sb) {
sb.append(ind(1) + "public static " + getID() + " " + getID() + ".deserialize(java.io.File file) throws DeserializationException {\n");
sb.append(ind(2) + "try {\n");
sb.append(ind(3) + "com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();\n");
sb.append(ind(3) + "com.fasterxml.jackson.core.JsonFactory factory = mapper.getFactory();\n");
sb.append(ind(3) + "com.fasterxml.jackson.core.JsonParser parser = factory.createParser(file);\n");
sb.append(ind(3) + "return deserialize((com.fasterxml.jackson.databind.JsonNode)mapper.readTree(parser));\n");
sb.append(ind(2) + "} catch (java.io.IOException e) {\n");
sb.append(ind(3) + "throw new DeserializationException(\"unable to deserialize \" + file.getAbsolutePath(), e);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "public static " + getID() + " " + getID() + ".deserialize(" + jsonNodeType + " node) throws DeserializationException {\n");
sb.append(ind(2) + getID() + " element;\n");
if (getAbstract()) {
// switch case between all implementations of the abstract class
sb.append(ind(2) + "switch (node" + jsonNodeTypeAccessor + ") {\n");
for (TypeDecl subType : subTypeDecls()) {
sb.append(ind(3) + "case \"" + subType.getID() + "\":\n");
sb.append(ind(4) + "element = " + subType.getID() + ".deserialize(node);\n");
sb.append(ind(4) + "break;\n");
}
sb.append(ind(3) + "default:\n");
sb.append(ind(4) + "throw new DeserializationException(\"Unable to deserialize child of unexpected type \" + node" + jsonNodeTypeAccessor + " + \"(" + getID() + " expected)\");\n");
sb.append(ind(2) + "}\n");
} else {
sb.append(ind(2) + "element = new " + getID() + "();\n");
}
// deserialize id
sb.append(ind(2) + "if (node.has(\"id\")) {\n");
sb.append(ind(3) + "element.__uid = node.get(\"id\").asText();\n");
sb.append(ind(2) + "}\n");
// deserialize containment children
if (componentsTransitive().size() > 0) {
sb.append(ind(2) + "if (node.has(\"children\")) {\n");
sb.append(ind(3) + jsonNodeType + " children = node.get(\"children\");\n");
for (Component component : componentsTransitive()) {
sb.append(ind(3) + "if (children.has(\"" + component.getID() + "\")) {\n");
component.deserialize(sb, 4);
sb.append(ind(3) + "}\n");
}
sb.append(ind(2) + "}\n");
}
// deserialize non-containment children
Set<RelationComponent> relationComponents = relationComponents();
if (relationComponents.size() > 0) {
sb.append(ind(2) + "if (node.has(\"relations\")) {\n");
sb.append(ind(3) + jsonNodeType + " relations = node.get(\"relations\");\n");
for (RelationComponent component : relationComponents) {
sb.append(ind(3) + "if (relations.has(\"" + component.getID() + "\")) {\n");
component.deserialize(sb, 4);
sb.append(ind(3) + "}\n");
}
sb.append(ind(2) + "}\n");
}
sb.append(ind(2) + "return element;\n");
sb.append(ind(1) + "}\n");
}
public abstract void Component.deserialize(StringBuilder sb, int indent);
public void NormalComponent.deserialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "element.set" + getID() + "(" + getTypeUse().decl().getID() + ".deserialize(children.get(\"" + getID() + "\")));\n");
sb.append(ind(indent - 1) + "} else {\n");
sb.append(ind(indent) + "throw new DeserializationException(\"deserializer of missing mandatory child " + getID() + "\");\n");
}
public void OptComponent.deserialize(StringBuilder sb, int indent) {
sb.append(ind(indent + 1) + "element.set" + getID() + "(" + getTypeUse().decl().getID() + ".deserialize(children.get(\"" + getID() + "\")));\n");
}
public void TokenComponent.deserialize(StringBuilder sb, int indent) {
String type = getTypeUse().getID();
switch (type) {
case "float":
case "Float":
sb.append(ind(indent) + "element.set" + getID() + "(Float.valueOf(children.get(\"" + getID() + "\").asText()));\n");
break;
case "double":
case "Double":
sb.append(ind(indent) + "element.set" + getID() + "(children.get(\"" + getID() + "\").asDouble());\n");
break;
case "int":
case "Integer":
sb.append(ind(indent) + "element.set" + getID() + "(children.get(\"" + getID() + "\").asInt());\n");
break;
case "short":
case "Short":
sb.append(ind(indent) + "element.set" + getID() + "(Short.valueOf(children.get(\"" + getID() + "\").asText()));\n");
break;
case "long":
case "Long":
sb.append(ind(indent) + "element.set" + getID() + "(children.get(\"" + getID() + "\").asLong());\n");
break;
case "byte":
case "Byte":
sb.append(ind(indent) + "element.set" + getID() + "(Byte.valueOf(children.get(\"" + getID() + "\").asText()));\n");
break;
case "boolean":
case "Boolean":
sb.append(ind(indent) + "element.set" + getID() + "(children.get(\"" + getID() + "\").asBoolean());\n");
break;
case "char":
case "Character":
sb.append(ind(indent) + "String chars = children.get(\"" + getID() + "\").asText();\n");
sb.append(ind(indent) + "if (chars.length() == 1) {\n");
sb.append(ind(indent + 2) + "element.set" + getID() + "(chars.charAt(0))\n");
sb.append(ind(indent) + "} else {\n");
sb.append(ind(indent + 2) + "throw new DeserializationException(\"unable to deserialize char '\" + chars + \"'\");\n");
sb.append(ind(indent) + "}\n");
break;
case "String":
sb.append(ind(indent) + "element.set" + getID() + "(children.get(\"" + getID() + "\").asText());\n");
break;
case "java.time.Instant":
sb.append(ind(indent) + "element.set" + getID() + "(java.time.Instant.parse(children.get(\"" + getID() + "\").asText()));\n");
break;
case "java.time.Period":
sb.append(ind(indent) + "element.set" + getID() + "(java.time.Period.parse(children.get(\"" + getID() + "\").asText()));\n");
break;
default:
// assume that the type is an enum. there is no way of checking this here
sb.append(ind(indent) + "element.set" + getID() + "Enum.valueOf(" + type + ".getClass(), children.get(\"" + getID() + "\".asText())));\n");
// sb.append("throw new DeserializationException(\"Unable to deserialize child node of type \"" + getTypeUse() + "\"\")")
}
}
public void Program.writeUID(StringBuilder sb) {
sb.append("aspect UID {\n");
sb.append(ind(1) + "class UIDProvider {\n");
sb.append(ind(2) + "private static long nextUID = 0;\n");
sb.append(ind(2) + "public static String getUID() {\n");
sb.append(ind(3) + "return String.valueOf(nextUID++);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
sb.append("\n");
sb.append(ind(1) + "protected String ASTNode.__uid = null;\n");
sb.append("\n");
sb.append(ind(1) + "protected String ASTNode.__uid() {\n");
sb.append(ind(2) + "String customUID = serializationID();\n");
sb.append(ind(2) + "if (customUID == null) {\n");
sb.append(ind(3) + "if (__uid == null) {\n");
sb.append(ind(4) + "__uid = UIDProvider.getUID();\n");
sb.append(ind(3) + "}\n");
sb.append(ind(3) + "return __uid;\n");
sb.append(ind(2) + "} else {\n");
sb.append(ind(3) + "return customUID;\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
sb.append("\n");
sb.append(ind(1) + "protected String ASTNode.serializationID() {\n");
sb.append(ind(2) + "return null;\n");
sb.append(ind(1) + "}\n");
sb.append("}\n");
}
public void NTAComponent.deserialize(StringBuilder sb, int indent) {
// do not serialize NTA
}
public void ListComponent.deserialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "for (" + jsonNodeType + " child : children.get(\"" + getID() + "\")) {\n");
sb.append(ind(indent + 1) + "element.add" + getID() + "(" + getTypeUse().decl().getID() + ".deserialize(child));\n");
sb.append(ind(indent) + "}\n");
}
public void OneRelationComponent.deserialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "element.set" + getID() + "(" + ofTypeDecl().getID() + ".createRefDirection(relations.get(\"" + getID() + "\").asText()));\n");
sb.append(ind(indent - 1) + "} else {\n");
sb.append(ind(indent) + "throw new DeserializationException(\"deserializer of missing mandatory relation child " + getID() + "\");\n");
}
public void OptionalRelationComponent.deserialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "element.set" + getID() + "(" + ofTypeDecl().getID() + ".createRefDirection(relations.get(\"" + getID() + "\").asText()));\n");