Skip to content
Snippets Groups Projects
Commit 21f989ad authored by Johannes Mey's avatar Johannes Mey
Browse files

implement json pointer (built-in) and manual pointer treatment with two...

implement json pointer (built-in) and manual pointer treatment with two examples (json pointer and relative json pointer)
parent 2568fb4c
No related branches found
No related tags found
1 merge request!5Json pointer
Pipeline #4688 passed
Showing
with 1145 additions and 41 deletions
...@@ -246,6 +246,36 @@ task compileSerializerDefaultNamesTest(type: RelastTest) { ...@@ -246,6 +246,36 @@ task compileSerializerDefaultNamesTest(type: RelastTest) {
moreInputFiles 'src/test/jastadd/Utils.jadd' moreInputFiles 'src/test/jastadd/Utils.jadd'
} }
task compileSerializerPointerTest(type: RelastTest) {
verbose = true
resolverHelper = true
relastFiles 'src/test/jastadd/serializer-pointer/Serializer.relast'
grammarName = 'src/test/jastadd/serializer-pointer/Serializer'
serializer = 'jackson-json-pointer'
packageName = 'pointer.serializer.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd'
}
task compileSerializerManualTest(type: RelastTest) {
verbose = true
resolverHelper = true
relastFiles 'src/test/jastadd/serializer-manual/Serializer.relast'
grammarName = 'src/test/jastadd/serializer-manual/Serializer'
serializer = 'jackson-manual-references'
packageName = 'manual.serializer.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd', 'src/test/jastadd/serializer-manual/JsonPointer.jrag'
}
task compileSerializerManualRelativeTest(type: RelastTest) {
verbose = true
resolverHelper = true
relastFiles 'src/test/jastadd/serializer-manual-relative/Serializer.relast'
grammarName = 'src/test/jastadd/serializer-manual-relative/Serializer'
serializer = 'jackson-manual-references'
packageName = 'manual.relative.serializer.ast'
moreInputFiles 'src/test/jastadd/Utils.jadd', 'src/test/jastadd/serializer-manual-relative/JsonPointer.jrag'
}
test { test {
outputs.upToDateWhen { false } outputs.upToDateWhen { false }
useJUnitPlatform() useJUnitPlatform()
......
...@@ -5,6 +5,8 @@ aspect BackendAbstractGrammar { ...@@ -5,6 +5,8 @@ aspect BackendAbstractGrammar {
public static boolean ASTNode.resolverHelper = false; public static boolean ASTNode.resolverHelper = false;
public static boolean ASTNode.serializer = false; public static boolean ASTNode.serializer = false;
public static boolean ASTNode.jsonPointer = false;
public static boolean ASTNode.manualReferences = false;
public static boolean ASTNode.useJastAddNames = false; public static boolean ASTNode.useJastAddNames = false;
public String Program.generateAbstractGrammar() { public String Program.generateAbstractGrammar() {
...@@ -823,13 +825,73 @@ aspect NameResolutionHelper { ...@@ -823,13 +825,73 @@ aspect NameResolutionHelper {
r.generateContextDependentNameResolution(sb); r.generateContextDependentNameResolution(sb);
} }
if (resolverHelper) { if (resolverHelper || ASTNode.jsonPointer || ASTNode.manualReferences) {
for (TypeDecl decl : getTypeDeclList()) { for (TypeDecl decl : getTypeDeclList()) {
decl.generateContextIndependentNameResolution(sb); decl.generateContextIndependentNameResolution(sb);
sb.append("\n"); sb.append("\n");
} }
} }
sb.append("}\n\n"); sb.append("}\n\n");
if (ASTNode.manualReferences) {
sb.append("aspect RefCreatorStubs {\n\n");
for (Relation r: getRelations()) {
r.generateContextDependentRefCreation(sb);
}
generateGenericRefCreation(sb);
sb.append("\n");
for (TypeDecl decl : getTypeDeclList()) {
decl.generateContextIndependentRefCreation(sb);
sb.append("\n");
}
sb.append("}\n\n");
}
}
public void Program.generateGenericRefCreation(StringBuilder sb) {
sb.append(ind(1) + "// generic reference creation\n");
sb.append(ind(1) + "syn String ASTNode.createReference();\n");
sb.append(ind(1) + "eq ASTNode.createReference() {\n");
sb.append(ind(2) + "throw new RuntimeException(\"Generic reference creation not implemented.\");\n");
sb.append(ind(1) + "}\n");
}
public void Relation.generateContextDependentRefCreation(StringBuilder sb) {
sb.append(ind(1) + "// " + prettyPrint() + "\n");
getDirection().generateContextDependentRefCreation(sb);
sb.append("\n");
}
public abstract void Direction.generateContextDependentRefCreation(StringBuilder sb);
public void RightDirection.generateContextDependentRefCreation(StringBuilder sb) {
relation().getLeft().generateContextDependentRefCreation(sb);
}
public void LeftDirection.generateContextDependentRefCreation(StringBuilder sb) {
relation().getRight().generateContextDependentRefCreation(sb);
}
public void Bidirectional.generateContextDependentRefCreation(StringBuilder sb) {
relation().getLeft().generateContextDependentRefCreation(sb);
relation().getRight().generateContextDependentRefCreation(sb);
}
public void RelationComponent.generateContextDependentRefCreation(StringBuilder sb) {
sb.append(ind(1) + "// context-dependent reference creation\n");
sb.append(ind(1) + "syn String " + toTypeDecl() + ".createRefTo" + nameCapitalized() + "(" + ofTypeDecl() + " target) {\n");
sb.append(ind(2) + "// default to context-independent reference creation\n");
sb.append(ind(2) + "return target.createReference();\n");
sb.append(ind(1) + "}\n");
}
public void TypeDecl.generateContextIndependentRefCreation(StringBuilder sb) {
sb.append(ind(1) + "// context-independent reference creation\n");
sb.append(ind(1) + "eq " + getID() + ".createReference() {\n");
sb.append(ind(2) + "// default to generic reference creation\n");
sb.append(ind(2) + "return super.createReference();\n");
sb.append(ind(1) + "}\n");
} }
public void Program.generateRewriteToSuperTypeStub(StringBuilder sb) { public void Program.generateRewriteToSuperTypeStub(StringBuilder sb) {
...@@ -894,8 +956,12 @@ aspect NameResolutionHelper { ...@@ -894,8 +956,12 @@ aspect NameResolutionHelper {
sb.append(ind(1) + "// context-independent name resolution\n"); sb.append(ind(1) + "// context-independent name resolution\n");
sb.append(ind(1) + "uncache ASTNode.globallyResolve" + getID() + "ByToken(String id);\n"); sb.append(ind(1) + "uncache ASTNode.globallyResolve" + getID() + "ByToken(String id);\n");
sb.append(ind(1) + "syn " + getID() + " ASTNode.globallyResolve" + getID() + "ByToken(String id) {\n"); sb.append(ind(1) + "syn " + getID() + " ASTNode.globallyResolve" + getID() + "ByToken(String id) {\n");
if (serializer) { if (serializer && !manualReferences) {
if (jsonPointer) {
sb.append(ind(2) + "return (" + getID() + ") resolveJsonPointer(id);\n");
} else {
sb.append(ind(2) + "return (" + getID() + ") globallyResolveASTNodeByUID(id);\n"); sb.append(ind(2) + "return (" + getID() + ") globallyResolveASTNodeByUID(id);\n");
}
} else { } else {
sb.append(ind(2) + "// perform context independent name resolution here using the id\n"); sb.append(ind(2) + "// perform context independent name resolution here using the id\n");
sb.append(ind(2) + "throw new RuntimeException(\"Context-independent name resolution for " + getID() + " not implemented.\");\n"); sb.append(ind(2) + "throw new RuntimeException(\"Context-independent name resolution for " + getID() + " not implemented.\");\n");
...@@ -1002,11 +1068,18 @@ aspect Serializer { ...@@ -1002,11 +1068,18 @@ aspect Serializer {
protected static String ASTNode.jsonTypeKey = "type"; protected static String ASTNode.jsonTypeKey = "type";
protected static String ASTNode.jsonNodeType = "com.fasterxml.jackson.databind.JsonNode"; protected static String ASTNode.jsonNodeType = "com.fasterxml.jackson.databind.JsonNode";
protected static String ASTNode.jsonNodeTypeAccessor = ".get(\"" + jsonTypeKey + "\").asText()"; protected static String ASTNode.jsonNodeTypeAccessor = ".get(\"" + jsonTypeKey + "\").asText()";
public String Program.generateSerializer() { public String Program.generateJacksonSerializer() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
generateFromJson(sb); generateFromJson(sb);
generateToJson(sb); generateToJson(sb);
if (jsonPointer) {
writeJsonPointer(sb);
} else if (manualReferences) {
// TODO
} else {
writeUID(sb); writeUID(sb);
}
return sb.toString(); return sb.toString();
} }
...@@ -1083,9 +1156,11 @@ aspect Serializer { ...@@ -1083,9 +1156,11 @@ aspect Serializer {
sb.append(ind(3) + "} else {\n"); sb.append(ind(3) + "} else {\n");
sb.append(ind(4) + "g.writeObjectFieldStart(fieldName);\n"); sb.append(ind(4) + "g.writeObjectFieldStart(fieldName);\n");
sb.append(ind(3) + "}\n"); sb.append(ind(3) + "}\n");
if (!jsonPointer && !manualReferences) {
sb.append(ind(3) + "g.writeStringField(\"" + jsonTypeKey + "\", \"" + getID() + "\");\n"); sb.append(ind(3) + "g.writeStringField(\"" + jsonTypeKey + "\", \"" + getID() + "\");\n");
sb.append(ind(3) + "if (unique$Id() == null) throw new SerializationException(\"The unique identifier of " + getID() + " is missing.\");\n"); sb.append(ind(3) + "if (unique$Id() == null) throw new SerializationException(\"The unique identifier of " + getID() + " is missing.\");\n");
sb.append(ind(3) + "g.writeStringField(\"id\", unique$Id());\n"); sb.append(ind(3) + "g.writeStringField(\"id\", unique$Id());\n");
}
if (componentsTransitive().size() > 0) { if (componentsTransitive().size() > 0) {
sb.append(ind(3) + "g.writeObjectFieldStart(\"children\");\n"); sb.append(ind(3) + "g.writeObjectFieldStart(\"children\");\n");
for (Component child : componentsTransitive()) { for (Component child : componentsTransitive()) {
...@@ -1196,19 +1271,43 @@ aspect Serializer { ...@@ -1196,19 +1271,43 @@ aspect Serializer {
public void OneRelationComponent.serialize(StringBuilder sb, int indent) { public void OneRelationComponent.serialize(StringBuilder sb, int indent) {
if (useJastAddNames){ if (useJastAddNames){
if (jsonPointer) {
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().jsonPointer());\n");
} else if (manualReferences) {
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", createRefTo" + getID() + "(" + getID() + "()));\n");
} else {
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().unique$Id());\n"); sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().unique$Id());\n");
}
} else {
if (jsonPointer) {
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", " + getID() + "().jsonPointer());\n");
} else if (manualReferences) {
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", createRefTo" + getID() + "(" + getID() + "()));\n");
} else { } else {
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", " + getID() + "().unique$Id());\n"); sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", " + getID() + "().unique$Id());\n");
} }
} }
}
public void OptionalRelationComponent.serialize(StringBuilder sb, int indent) { public void OptionalRelationComponent.serialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "if (has" + nameCapitalized() + "()) {\n"); sb.append(ind(indent) + "if (has" + nameCapitalized() + "()) {\n");
if (useJastAddNames){ if (useJastAddNames){
if (jsonPointer) {
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().jsonPointer());\n");
} else if (manualReferences) {
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().createReference());\n");
} else {
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().unique$Id());\n"); sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().unique$Id());\n");
}
} else {
if (jsonPointer) {
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", " + getID() + "().jsonPointer());\n");
} else if (manualReferences) {
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", " + "createRefTo" + getID() + "(" + getID() + "()));\n");
} else { } else {
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", " + getID() + "().unique$Id());\n"); sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", " + getID() + "().unique$Id());\n");
} }
}
sb.append(ind(indent) + "}\n"); sb.append(ind(indent) + "}\n");
} }
...@@ -1219,7 +1318,14 @@ aspect Serializer { ...@@ -1219,7 +1318,14 @@ aspect Serializer {
} else { } else {
sb.append(ind(indent) + "for (" + ofTypeDecl().getID() + " child : " + getID() + "()) {\n"); sb.append(ind(indent) + "for (" + ofTypeDecl().getID() + " child : " + getID() + "()) {\n");
} }
if (jsonPointer) {
sb.append(ind(indent + 1) + "g.writeString(child.jsonPointer());\n");
} else if (manualReferences) {
sb.append(ind(indent + 1) + "g.writeString(createRefTo" + getID() + "(child));\n");
}else {
sb.append(ind(indent + 1) + "g.writeString(child.unique$Id());\n"); sb.append(ind(indent + 1) + "g.writeString(child.unique$Id());\n");
}
sb.append(ind(indent) + "}\n"); sb.append(ind(indent) + "}\n");
sb.append(ind(indent) + "g.writeEndArray();\n"); sb.append(ind(indent) + "g.writeEndArray();\n");
} }
...@@ -1256,10 +1362,12 @@ aspect Serializer { ...@@ -1256,10 +1362,12 @@ aspect Serializer {
sb.append(ind(2) + "element = new " + getID() + "();\n"); sb.append(ind(2) + "element = new " + getID() + "();\n");
} }
if (!jsonPointer && !manualReferences) {
// deserialize id // deserialize id
sb.append(ind(2) + "if (node.has(\"id\")) {\n"); sb.append(ind(2) + "if (node.has(\"id\")) {\n");
sb.append(ind(3) + "element.unique$Id = node.get(\"id\").asText();\n"); sb.append(ind(3) + "element.unique$Id = node.get(\"id\").asText();\n");
sb.append(ind(2) + "}\n"); sb.append(ind(2) + "}\n");
}
// deserialize containment children // deserialize containment children
if (componentsTransitive().size() > 0) { if (componentsTransitive().size() > 0) {
...@@ -1361,6 +1469,140 @@ aspect Serializer { ...@@ -1361,6 +1469,140 @@ aspect Serializer {
} }
} }
public void Component.writeJsonPointer(StringBuilder sb) {
// do nothing for other components
}
public void NormalComponent.writeJsonPointer(StringBuilder sb) {
sb.append(ind(1) + "eq " + enclosingTypeDecl().getID() + (useJastAddNames?".get":".") + getID() + "().jsonPointerInh() {\n");
sb.append(ind(2) + "return this.jsonPointer() + \"/children/" + getID() + "\";\n");
sb.append(ind(1) + "}\n");
}
public void ListComponent.writeJsonPointer(StringBuilder sb) {
sb.append(ind(1) + "eq " + enclosingTypeDecl().getID() + (useJastAddNames?".get":".") + getID() + "(int index).jsonPointerInh() {\n");
sb.append(ind(2) + "return this.jsonPointer() + \"/children/" + getID() + "/\" + index;\n");
sb.append(ind(1) + "}\n");
}
public void OptComponent.writeJsonPointer(StringBuilder sb) {
sb.append(ind(1) + "eq " + enclosingTypeDecl().getID() + (useJastAddNames?".get":".") + getID() + "().jsonPointerInh() {\n");
sb.append(ind(2) + "return this.jsonPointer() + \"/children/" + getID() + "\";\n");
sb.append(ind(1) + "}\n");
}
public void NTAComponent.writeJsonPointer(StringBuilder sb) {
sb.append(ind(1) + "eq " + enclosingTypeDecl().getID() + (useJastAddNames?".get":".") + getID() + "().jsonPointerInh() {\n");
sb.append(ind(2) + "return this.jsonPointer() + \"/children/" + getID() + "\";\n");
sb.append(ind(1) + "}\n");
}
public void NTAListComponent.writeJsonPointer(StringBuilder sb) {
sb.append(ind(1) + "eq " + enclosingTypeDecl().getID() + (useJastAddNames?".get":".") + getID() + "(int index).jsonPointerInh() {\n");
sb.append(ind(2) + "return this.jsonPointer() + \"/children/" + getID() + "/\" + index;\n");
sb.append(ind(1) + "}\n");
}
public void NTAOptComponent.writeJsonPointer(StringBuilder sb) {
sb.append(ind(1) + "eq " + enclosingTypeDecl().getID() + (useJastAddNames?".get":".") + getID() + "().jsonPointerInh() {\n");
sb.append(ind(2) + "return this.jsonPointer() + \"/children/" + getID() + "\";\n");
sb.append(ind(1) + "}\n");
}
public void Component.resolveJsonPointer(StringBuilder sb) {
// do nothing for other components
}
public void NormalComponent.resolveJsonPointer(StringBuilder sb) {
sb.append(ind(4) + "case \"" + getID() + "\":\n");
sb.append(ind(5) + "return get" + getID() + "().resolveJsonPointer(pointer, index + 2);\n");
}
public void ListComponent.resolveJsonPointer(StringBuilder sb) {
sb.append(ind(4) + "case \"" + getID() + "\":\n");
sb.append(ind(5) + "return get" + getID() + "(Integer.valueOf(pointer[index + 2])).resolveJsonPointer(pointer, index + 3);\n");
}
public void OptComponent.resolveJsonPointer(StringBuilder sb) {
sb.append(ind(4) + "case \"" + getID() + "\":\n");
sb.append(ind(5) + "return get" + getID() + "().resolveJsonPointer(pointer, index + 2);\n");
}
public void NTAComponent.resolveJsonPointer(StringBuilder sb) {
sb.append(ind(4) + "case \"" + getID() + "\":\n");
sb.append(ind(5) + "return get" + getID() + "().resolveJsonPointer(pointer, index + 2);\n");
}
public void NTAListComponent.resolveJsonPointer(StringBuilder sb) {
sb.append(ind(4) + "case \"" + getID() + "\":\n");
sb.append(ind(5) + "return get" + getID() + "(Integer.valueOf(pointer[index + 2])).resolveJsonPointer(pointer, index + 3);\n");
}
public void NTAOptComponent.resolveJsonPointer(StringBuilder sb) {
sb.append(ind(4) + "case \"" + getID() + "\":\n");
sb.append(ind(5) + "return get" + getID() + "().resolveJsonPointer(pointer, index + 2);\n");
}
public void TypeDecl.resolveJsonPointer(StringBuilder sb) {
sb.append(ind(1) + "eq " + getID() + ".resolveJsonPointer(String[] pointer, int index) {\n");
sb.append(ind(2) + "if (pointer.length == 0 || pointer.length == index) {\n");
sb.append(ind(3) + "return this;\n");
sb.append(ind(2) + "} else if (pointer.length == index + 1) {\n");
sb.append(ind(3) + "throw new RuntimeException(\"there is only one child called \" + pointer[index]);\n");
sb.append(ind(2) + "} else {\n");
sb.append(ind(3) + "switch (pointer[index + 1]) {\n");
for (Component c: getComponentList()) {
c.resolveJsonPointer(sb);
}
sb.append(ind(4) + "default:\n");
sb.append(ind(5) + "return super.resolveJsonPointer(pointer, index);\n");
sb.append(ind(3) + "}\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
}
public void Program.writeJsonPointer(StringBuilder sb) {
sb.append("aspect JsonPointer {\n");
sb.append(ind(1) + "syn String ASTNode.jsonPointer() {\n");
sb.append(ind(2) + "if (getParent() == null) {\n");
sb.append(ind(3) + "return \"\";\n");
sb.append(ind(2) + "} else {\n");
sb.append(ind(3) + "return jsonPointerInh();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "inh String ASTNode.jsonPointerInh();\n");
// define json pointer for each component
for (TypeDecl td: getTypeDeclList()) {
for (Component c: td.getComponentList()) {
c.writeJsonPointer(sb);
}
}
sb.append(ind(1) + "syn ASTNode ASTNode.resolveJsonPointer(String pointer) = root().resolveJsonPointer(pointer.split(\"/\"), 1);\n");
sb.append(ind(1) + "ASTNode ASTNode.root() {\n");
sb.append(ind(2) + "if (getParent() == null) return this;\n");
sb.append(ind(2) + "else return getParent().root();\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "syn ASTNode ASTNode.resolveJsonPointer(String[] pointer, int index) {\n");
sb.append(ind(2) + "if (index < pointer.length) {\n");
sb.append(ind(3) + "throw new RuntimeException(\"found wrong child \" + pointer[index + 1] + \" in class \" + this.getClass().getSimpleName());\n");
sb.append(ind(2) + "} else {\n");
sb.append(ind(3) + "throw new RuntimeException(\"Cannot resolve JSON pointer for class \" + this.getClass().getSimpleName());\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
// resolve JSON pointers in each nonterminal
for (TypeDecl td: getTypeDeclList()) {
td.resolveJsonPointer(sb);
}
sb.append("}\n");
}
public void Program.writeUID(StringBuilder sb) { public void Program.writeUID(StringBuilder sb) {
sb.append("aspect UID {\n"); sb.append("aspect UID {\n");
sb.append(ind(1) + "class UIDProvider {\n"); sb.append(ind(1) + "class UIDProvider {\n");
......
...@@ -89,8 +89,17 @@ public class Compiler { ...@@ -89,8 +89,17 @@ public class Compiler {
ASTNode.serializer = true; ASTNode.serializer = true;
switch (optionSerializer.getValue()) { switch (optionSerializer.getValue()) {
case "jackson": case "jackson":
writeToFile(grammarName + "Serializer.jadd", p.generateSerializer()); writeToFile(grammarName + "Serializer.jadd", p.generateJacksonSerializer());
break; break;
case "jackson-json-pointer":
ASTNode.jsonPointer = true;
writeToFile(grammarName + "Serializer.jadd", p.generateJacksonSerializer());
break;
case "jackson-manual-references":
ASTNode.manualReferences = true;
writeToFile(grammarName + "Serializer.jadd", p.generateJacksonSerializer());
break;
} }
} }
...@@ -151,7 +160,7 @@ public class Compiler { ...@@ -151,7 +160,7 @@ public class Compiler {
optionResolverHelper = addOption(new FlagOption("resolverHelper", "create a subtype for each type containing a string that can be used to resolve the type later")); optionResolverHelper = addOption(new FlagOption("resolverHelper", "create a subtype for each type containing a string that can be used to resolve the type later"));
optionJastAddList = addOption(new StringOption("jastAddList", "set the name of the List type in JastAdd (has to match the option '--List' or its default List)")); optionJastAddList = addOption(new StringOption("jastAddList", "set the name of the List type in JastAdd (has to match the option '--List' or its default List)"));
optionUseJastaddNames = addOption(new FlagOption("useJastAddNames", "generate names in the form of addX, removeX and setX. If omitted, the default, original naming scheme resulting in addToX, removeFromX and setX will be used.")); optionUseJastaddNames = addOption(new FlagOption("useJastAddNames", "generate names in the form of addX, removeX and setX. If omitted, the default, original naming scheme resulting in addToX, removeFromX and setX will be used."));
optionSerializer = addOption(new EnumOption("serializer", "generate a (de-)serializer", Arrays.asList("jackson"), "jackson")); optionSerializer = addOption(new EnumOption("serializer", "generate a (de-)serializer", Arrays.asList("jackson", "jackson-json-pointer", "jackson-manual-references"), "jackson"));
optionQuiet = addOption(new FlagOption("quiet", "do not output anything on stdout")); optionQuiet = addOption(new FlagOption("quiet", "do not output anything on stdout"));
} }
......
aspect MyRewrites { aspect MyRewrites {
// context-independent name resolution // context-independent name resolution
refine RefResolverStubs eq ASTNode.globallyResolveNamedElementByToken(String id) { refine RefResolverStubs eq ASTNode.globallyResolveNamedElementByToken(String id) = root().findNamedElement(id);
System.out.println("resolving " + id + " to " + root().findNamedElement(id)); refine RefResolverStubs eq ASTNode.globallyResolveAByToken(String id) = root().findA(id);
return root().findNamedElement(id); refine RefResolverStubs eq ASTNode.globallyResolveBByToken(String id) = root().findB(id);
}
// context-independent name resolution
refine RefResolverStubs eq ASTNode.globallyResolveAByToken(String id) {
System.out.println("resolving " + id + " to " + root().findNamedElement(id));
return root().findA(id);
}
// context-independent name resolution
refine RefResolverStubs eq ASTNode.globallyResolveBByToken(String id) {
System.out.println("resolving " + id + " to " + root().findNamedElement(id));
return root().findB(id);
}
} }
aspect Utils { aspect Utils {
inh Root ASTNode.root(); inh Root ASTNode.root();
eq Root.getA(int i).root() = this; eq Root.getChild().root() = this;
eq Root.getB(int i).root() = this;
syn NamedElement Root.findNamedElement(String name) { syn NamedElement Root.findNamedElement(String name) {
for (A a : getAList()) { for (A a : getAList()) {
......
aspect Utils { aspect Utils {
inh Root ASTNode.root(); inh Root ASTNode.root();
eq Root.getA(int i).root() = this; eq Root.getChild().root() = this;
eq Root.getB(int i).root() = this;
syn NamedElement Root.findNamedElement(String name) { syn NamedElement Root.findNamedElement(String name) {
for (A a : getAList()) { for (A a : getAList()) {
......
aspect JsonPointer {
refine RefCreatorStubs eq A.createRefToDi1(B target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToDi2(B target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToDi3(B target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToBi1(B target) = createReferenceTo(target);
refine RefCreatorStubs eq B.createRefToBi1(A target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToBi2(B target) = createReferenceTo(target);
refine RefCreatorStubs eq B.createRefToBi2(A target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToBi3(B target) = createReferenceTo(target);
refine RefCreatorStubs eq B.createRefToBi3(A target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToBi5(B target) = createReferenceTo(target);
refine RefCreatorStubs eq B.createRefToBi5(A target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToBi6(B target) = createReferenceTo(target);
refine RefCreatorStubs eq B.createRefToBi6(A target) = createReferenceTo(target);
refine RefCreatorStubs eq A.createRefToBi9(B target) = createReferenceTo(target);
refine RefCreatorStubs eq B.createRefToBi9(A target) = createReferenceTo(target);
refine RefCreatorStubs eq Root.createRefToD(D target) = createReferenceTo(target);
refine RefCreatorStubs eq D.createRefToRoot(Root target) = createReferenceTo(target);
syn String ASTNode.createReferenceTo(ASTNode target) {
// find common subtree
java.util.List<ASTNode> myParents = parents();
java.util.List<ASTNode> targetParents = target.parents();
int minSize = Math.min(myParents.size(), targetParents.size());
if (minSize > 0) {
int commonDepth = 0;
while (commonDepth < minSize && myParents.get(commonDepth) == targetParents.get(commonDepth)) {
commonDepth ++;
}
int stepsUp = 0;
for (int i = commonDepth; i < myParents.size(); i++) {
stepsUp += (myParents.get(i).inList()) ? 3 : 2;
}
return stepsUp + "#" + target.jsonPointerFrom(myParents.get(commonDepth-1));
} else {
return (myParents.size() == 0) ? target.jsonPointerFrom(this) : myParents.size() + "#";
}
}
syn boolean ASTNode.inList() = (getParent() == null) ? false : inListInh();
inh boolean ASTNode.inListInh();
eq Root.getA().inListInh() = true;
eq Root.getB().inListInh() = true;
eq Root.getC().inListInh() = false;
eq C.getD1().inListInh() = false;
eq C.getD2().inListInh() = false;
eq C.getD3().inListInh() = true;
syn ASTNode ASTNode.goUp(int steps) = steps > 0 ? goUpInh(steps) : this;
inh ASTNode ASTNode.goUpInh(int steps);
eq Root.getA().goUpInh(int steps) = goUp(steps-3);
eq Root.getB().goUpInh(int steps) = goUp(steps-3);
eq Root.getC().goUpInh(int steps) = goUp(steps-2);
eq C.getD1().goUpInh(int steps) = goUp(steps-2);
eq C.getD2().goUpInh(int steps) = goUp(steps-2);
eq C.getD3().goUpInh(int steps) = goUp(steps-3);
/**
* return the parent from root to the current node
*/
syn java.util.List<ASTNode> ASTNode.parents() {
java.util.List<ASTNode> result = new java.util.ArrayList<>();
if (getParent() != null) {
result.addAll(getParent().parents());
if (!(this instanceof List) && !(this instanceof Opt)) result.add(this);
} else {
// add the root
result.add(this);
}
return result;
}
syn String ASTNode.jsonPointerFrom(ASTNode p) = (getParent() == null || this == p) ? "" : jsonPointerInh(p);
inh String ASTNode.jsonPointerInh(ASTNode p);
eq Root.A(int index).jsonPointerInh(ASTNode p) = this.jsonPointerFrom(p) + "/children/A/" + index;
eq Root.B(int index).jsonPointerInh(ASTNode p) = this.jsonPointerFrom(p) + "/children/B/" + index;
eq Root.C().jsonPointerInh(ASTNode p) = this.jsonPointerFrom(p) + "/children/C";
eq C.D1().jsonPointerInh(ASTNode p) = this.jsonPointerFrom(p) + "/children/D1";
eq C.D2().jsonPointerInh(ASTNode p) = this.jsonPointerFrom(p) + "/children/D2";
eq C.D3(int index).jsonPointerInh(ASTNode p) = this.jsonPointerFrom(p) + "/children/D3/" + index;
// context-independent name resolution
refine RefResolverStubs eq ASTNode.globallyResolveRootByToken(String id) = (Root) resolveJsonPointer(id);
refine RefResolverStubs eq ASTNode.globallyResolveAByToken(String id) = (A) resolveJsonPointer(id);
refine RefResolverStubs eq ASTNode.globallyResolveBByToken(String id) = (B) resolveJsonPointer(id);
refine RefResolverStubs eq ASTNode.globallyResolveCByToken(String id) = (C) resolveJsonPointer(id);
refine RefResolverStubs eq ASTNode.globallyResolveDByToken(String id) = (D) resolveJsonPointer(id);
refine RefResolverStubs eq ASTNode.globallyResolveNamedElementByToken(String id) = (NamedElement) resolveJsonPointer(id);
syn ASTNode ASTNode.resolveJsonPointer(String pointer) {
if (pointer.isEmpty() || pointer.startsWith("/")) {
return root().resolveJsonPointer(pointer.split("/"),1);
} else {
// a lot of assumptions here...
int depth = Integer.valueOf(pointer.split("#")[0]);
ASTNode result = goUp(depth);
return result.resolveJsonPointer(pointer.split("/"),1);
}
}
ASTNode ASTNode.root() {
if (getParent() == null) return this;
else return getParent().root();
}
syn ASTNode ASTNode.resolveJsonPointer(String[] pointer, int index) {
if (index < pointer.length) {
throw new RuntimeException("found wrong child " + pointer[index + 1] + " in class " + this.getClass().getSimpleName());
} else {
throw new RuntimeException("Cannot resolve JSON pointer for class " + this.getClass().getSimpleName());
}
}
eq Root.resolveJsonPointer(String[] pointer, int index) {
if (pointer.length == 0 || pointer.length == index) {
return this;
} else if (pointer.length == index + 1) {
throw new RuntimeException("there is only one child called " + pointer[index]);
} else {
switch (pointer[index + 1]) {
case "A":
return getA(Integer.valueOf(pointer[index + 2])).resolveJsonPointer(pointer, index + 3);
case "B":
return getB(Integer.valueOf(pointer[index + 2])).resolveJsonPointer(pointer, index + 3);
case "C":
return getC().resolveJsonPointer(pointer, index + 2);
default:
return super.resolveJsonPointer(pointer, index);
}
}
}
eq A.resolveJsonPointer(String[] pointer, int index) {
if (pointer.length == 0 || pointer.length == index) {
return this;
} else if (pointer.length == index + 1) {
throw new RuntimeException("there is only one child called " + pointer[index]);
} else {
switch (pointer[index + 1]) {
default:
return super.resolveJsonPointer(pointer, index);
}
}
}
eq B.resolveJsonPointer(String[] pointer, int index) {
if (pointer.length == 0 || pointer.length == index) {
return this;
} else if (pointer.length == index + 1) {
throw new RuntimeException("there is only one child called " + pointer[index]);
} else {
switch (pointer[index + 1]) {
default:
return super.resolveJsonPointer(pointer, index);
}
}
}
eq C.resolveJsonPointer(String[] pointer, int index) {
if (pointer.length == 0 || pointer.length == index) {
return this;
} else if (pointer.length == index + 1) {
throw new RuntimeException("there is only one child called " + pointer[index]);
} else {
switch (pointer[index + 1]) {
case "D1":
return getD1().resolveJsonPointer(pointer, index + 2);
case "D2":
return getD2().resolveJsonPointer(pointer, index + 2);
case "D3":
return getD3(Integer.valueOf(pointer[index + 2])).resolveJsonPointer(pointer, index + 3);
default:
return super.resolveJsonPointer(pointer, index);
}
}
}
eq D.resolveJsonPointer(String[] pointer, int index) {
if (pointer.length == 0 || pointer.length == index) {
return this;
} else if (pointer.length == index + 1) {
throw new RuntimeException("there is only one child called " + pointer[index]);
} else {
switch (pointer[index + 1]) {
default:
return super.resolveJsonPointer(pointer, index);
}
}
}
eq NamedElement.resolveJsonPointer(String[] pointer, int index) {
if (pointer.length == 0 || pointer.length == index) {
return this;
} else if (pointer.length == index + 1) {
throw new RuntimeException("there is only one child called " + pointer[index]);
} else {
switch (pointer[index + 1]) {
default:
return super.resolveJsonPointer(pointer, index);
}
}
}
}
Root ::= A* B* C;
A:NamedElement;
B:NamedElement;
C:NamedElement ::= D1:D [D2:D] D3:D*;
D:NamedElement;
abstract NamedElement ::= <Name>;
rel A.Di1 -> B;
rel A.Di2? -> B;
rel A.Di3* -> B;
rel A.Bi1 <-> B.Bi1;
rel A.Bi2 <-> B.Bi2?;
rel A.Bi3 <-> B.Bi3*;
rel A.Bi5? <-> B.Bi5?;
rel A.Bi6? <-> B.Bi6*;
rel A.Bi9* <-> B.Bi9*;
rel Root.D <-> D.Root?;
aspect JsonPointer {
refine RefCreatorStubs eq ASTNode.createReference() = jsonPointer();
syn String ASTNode.jsonPointer() {
if (getParent() == null) {
return "";
} else {
return jsonPointerInh();
}
}
inh String ASTNode.jsonPointerInh();
eq Root.A(int index).jsonPointerInh() {
return this.jsonPointer() + "/children/A/" + index;
}
eq Root.B(int index).jsonPointerInh() {
return this.jsonPointer() + "/children/B/" + index;
}
eq Root.C().jsonPointerInh() {
return this.jsonPointer() + "/children/C";
}
eq C.D1().jsonPointerInh() {
return this.jsonPointer() + "/children/D1";
}
eq C.D2().jsonPointerInh() {
return this.jsonPointer() + "/children/D2";
}
eq C.D3(int index).jsonPointerInh() {
return this.jsonPointer() + "/children/D3/" + index;
}
// context-independent name resolution
refine RefResolverStubs eq ASTNode.globallyResolveRootByToken(String id) {
return (Root) resolveJsonPointer(id);
}
// context-independent name resolution
refine RefResolverStubs eq ASTNode.globallyResolveAByToken(String id) {
return (A) resolveJsonPointer(id);
}
// context-independent name resolution
refine RefResolverStubs eq ASTNode.globallyResolveBByToken(String id) {
return (B) resolveJsonPointer(id);
}
// context-independent name resolution
refine RefResolverStubs eq ASTNode.globallyResolveCByToken(String id) {
return (C) resolveJsonPointer(id);
}
// context-independent name resolution
refine RefResolverStubs eq ASTNode.globallyResolveDByToken(String id) {
return (D) resolveJsonPointer(id);
}
// context-independent name resolution
refine RefResolverStubs eq ASTNode.globallyResolveNamedElementByToken(String id) {
return (NamedElement) resolveJsonPointer(id);
}
syn ASTNode ASTNode.resolveJsonPointer(String pointer) = root().resolveJsonPointer(pointer.split("/"), 1);
ASTNode ASTNode.root() {
if (getParent() == null) return this;
else return getParent().root();
}
syn ASTNode ASTNode.resolveJsonPointer(String[] pointer, int index) {
if (index < pointer.length) {
throw new RuntimeException("found wrong child " + pointer[index + 1] + " in class " + this.getClass().getSimpleName());
} else {
throw new RuntimeException("Cannot resolve JSON pointer for class " + this.getClass().getSimpleName());
}
}
eq Root.resolveJsonPointer(String[] pointer, int index) {
if (pointer.length == 0 || pointer.length == index) {
return this;
} else if (pointer.length == index + 1) {
throw new RuntimeException("there is only one child called " + pointer[index]);
} else {
switch (pointer[index + 1]) {
case "A":
return getA(Integer.valueOf(pointer[index + 2])).resolveJsonPointer(pointer, index + 3);
case "B":
return getB(Integer.valueOf(pointer[index + 2])).resolveJsonPointer(pointer, index + 3);
case "C":
return getC().resolveJsonPointer(pointer, index + 2);
default:
return super.resolveJsonPointer(pointer, index);
}
}
}
eq A.resolveJsonPointer(String[] pointer, int index) {
if (pointer.length == 0 || pointer.length == index) {
return this;
} else if (pointer.length == index + 1) {
throw new RuntimeException("there is only one child called " + pointer[index]);
} else {
switch (pointer[index + 1]) {
default:
return super.resolveJsonPointer(pointer, index);
}
}
}
eq B.resolveJsonPointer(String[] pointer, int index) {
if (pointer.length == 0 || pointer.length == index) {
return this;
} else if (pointer.length == index + 1) {
throw new RuntimeException("there is only one child called " + pointer[index]);
} else {
switch (pointer[index + 1]) {
default:
return super.resolveJsonPointer(pointer, index);
}
}
}
eq C.resolveJsonPointer(String[] pointer, int index) {
if (pointer.length == 0 || pointer.length == index) {
return this;
} else if (pointer.length == index + 1) {
throw new RuntimeException("there is only one child called " + pointer[index]);
} else {
switch (pointer[index + 1]) {
case "D1":
return getD1().resolveJsonPointer(pointer, index + 2);
case "D2":
return getD2().resolveJsonPointer(pointer, index + 2);
case "D3":
return getD3(Integer.valueOf(pointer[index + 2])).resolveJsonPointer(pointer, index + 3);
default:
return super.resolveJsonPointer(pointer, index);
}
}
}
eq D.resolveJsonPointer(String[] pointer, int index) {
if (pointer.length == 0 || pointer.length == index) {
return this;
} else if (pointer.length == index + 1) {
throw new RuntimeException("there is only one child called " + pointer[index]);
} else {
switch (pointer[index + 1]) {
default:
return super.resolveJsonPointer(pointer, index);
}
}
}
eq NamedElement.resolveJsonPointer(String[] pointer, int index) {
if (pointer.length == 0 || pointer.length == index) {
return this;
} else if (pointer.length == index + 1) {
throw new RuntimeException("there is only one child called " + pointer[index]);
} else {
switch (pointer[index + 1]) {
default:
return super.resolveJsonPointer(pointer, index);
}
}
}
}
Root ::= A* B* C;
A:NamedElement;
B:NamedElement;
C:NamedElement ::= D1:D [D2:D] D3:D*;
D:NamedElement;
abstract NamedElement ::= <Name>;
rel A.Di1 -> B;
rel A.Di2? -> B;
rel A.Di3* -> B;
rel A.Bi1 <-> B.Bi1;
rel A.Bi2 <-> B.Bi2?;
rel A.Bi3 <-> B.Bi3*;
rel A.Bi5? <-> B.Bi5?;
rel A.Bi6? <-> B.Bi6*;
rel A.Bi9* <-> B.Bi9*;
rel Root.D <-> D.Root?;
Root ::= A* B* C;
A:NamedElement;
B:NamedElement;
C:NamedElement ::= D1:D [D2:D] D3:D*;
D:NamedElement;
abstract NamedElement ::= <Name>;
rel A.Di1 -> B;
rel A.Di2? -> B;
rel A.Di3* -> B;
rel A.Bi1 <-> B.Bi1;
rel A.Bi2 <-> B.Bi2?;
rel A.Bi3 <-> B.Bi3*;
rel A.Bi5? <-> B.Bi5?;
rel A.Bi6? <-> B.Bi6*;
rel A.Bi9* <-> B.Bi9*;
rel Root.D <-> D.Root?;
package org.jastadd.relast.tests;
import org.junit.jupiter.api.Test;
import manual.serializer.ast.*;
import java.io.File;
import java.io.IOException;
import static org.assertj.core.api.Assertions.assertThat;
class SerializerManual {
@Test
void testDi1() throws SerializationException, DeserializationException, IOException {
Root r = new Root();
A a1 = new A("a1");
A a2 = new A("a2");
A a3 = new A("a3");
B b1 = new B("b1");
B b2 = new B("b2");
B b3 = new B("b3");
C c = new C();
c.setName("c");
// non-terminals
D d1 = new D("d1");
c.setD1(d1);
c.setD2(new D("d2"));
c.addD3(new D("D3-1"));
c.addD3(new D("D3-2"));
c.addD3(new D("D3-3"));
r.setC(c);
// non-containment relations
r.addA(a1);
r.addA(a2);
r.addA(a3);
r.addB(b1);
r.addB(b2);
r.addB(b3);
// Di1
a1.setDi1(b2);
a2.setDi1(b1);
a3.setDi1(b3);
// Di2
a1.setDi2(b2);
a3.setDi2(b1);
// Di3
a1.addToDi3(b1);
a1.addToDi3(b2);
a1.addToDi3(b3);
a2.addToDi3(b2);
// Bi1
a1.setBi1(b3);
a2.setBi1(b2);
a3.setBi1(b1);
// Bi2
a1.setBi2(b1);
a2.setBi2(b2);
a3.setBi2(b3);
// Bi3
a1.setBi3(b2);
a2.setBi3(b2);
a3.setBi3(b2);
// Bi5
a1.setBi5(b1);
a2.setBi5(b3);
// Bi6
a2.setBi6(b3);
a3.setBi6(b3);
// Bi9
a1.addToBi9(b1);
a1.addToBi9(b3);
a2.addToBi9(b3);
// D
r.setD(d1);
File f1a = File.createTempFile("original", ".json");
System.out.println(f1a.getAbsoluteFile());
r.serialize(f1a);
com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory();
com.fasterxml.jackson.core.JsonGenerator generator = factory.createGenerator(System.out, com.fasterxml.jackson.core.JsonEncoding.UTF8);
generator.setPrettyPrinter(new com.fasterxml.jackson.core.util.DefaultPrettyPrinter());
r.serialize(generator);
generator.close();
Root copy = Root.deserialize(f1a);
File f1b = File.createTempFile("copy", ".json");
copy.serialize(f1b);
assertThat(f1b).hasSameContentAs(f1a);
// remove a2
a1.setDi1(b3);
a1.setDi2(b3);
a1.removeFromDi3(b2);
a1.removeFromDi3(b2);
a1.setBi3(b1);
a3.setBi3(b1);
b3.clearBi5();
b3.removeFromBi6(a2);
b3.removeFromBi9(a2);
r.getAList().removeChild(r.getAList().getIndexOfChild(a2));
r.getBList().removeChild(r.getBList().getIndexOfChild(b2));
File f2a = File.createTempFile("original", ".json");
System.out.println(f2a.getAbsoluteFile());
r.serialize(f2a);
copy = Root.deserialize(f2a);
File f2b = File.createTempFile("copy", ".json");
copy.serialize(f2b);
assertThat(f2b).hasSameContentAs(f2a);
}
}
package org.jastadd.relast.tests;
import manual.relative.serializer.ast.*;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
import static org.assertj.core.api.Assertions.assertThat;
class SerializerManualRelative {
@Test
void testDi1() throws SerializationException, DeserializationException, IOException {
Root r = new Root();
A a1 = new A("a1");
A a2 = new A("a2");
A a3 = new A("a3");
B b1 = new B("b1");
B b2 = new B("b2");
B b3 = new B("b3");
C c = new C();
c.setName("c");
// non-terminals
D d1 = new D("d1");
c.setD1(d1);
c.setD2(new D("d2"));
c.addD3(new D("D3-1"));
c.addD3(new D("D3-2"));
c.addD3(new D("D3-3"));
r.setC(c);
// non-containment relations
r.addA(a1);
r.addA(a2);
r.addA(a3);
r.addB(b1);
r.addB(b2);
r.addB(b3);
// Di1
a1.setDi1(b2);
a2.setDi1(b1);
a3.setDi1(b3);
// Di2
a1.setDi2(b2);
a3.setDi2(b1);
// Di3
a1.addToDi3(b1);
a1.addToDi3(b2);
a1.addToDi3(b3);
a2.addToDi3(b2);
// Bi1
a1.setBi1(b3);
a2.setBi1(b2);
a3.setBi1(b1);
// Bi2
a1.setBi2(b1);
a2.setBi2(b2);
a3.setBi2(b3);
// Bi3
a1.setBi3(b2);
a2.setBi3(b2);
a3.setBi3(b2);
// Bi5
a1.setBi5(b1);
a2.setBi5(b3);
// Bi6
a2.setBi6(b3);
a3.setBi6(b3);
// Bi9
a1.addToBi9(b1);
a1.addToBi9(b3);
a2.addToBi9(b3);
// D
r.setD(d1);
File f1a = File.createTempFile("original", ".json");
System.out.println(f1a.getAbsoluteFile());
r.serialize(f1a);
com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory();
com.fasterxml.jackson.core.JsonGenerator generator = factory.createGenerator(System.out, com.fasterxml.jackson.core.JsonEncoding.UTF8);
generator.setPrettyPrinter(new com.fasterxml.jackson.core.util.DefaultPrettyPrinter());
r.serialize(generator);
generator.close();
Root copy = Root.deserialize(f1a);
File f1b = File.createTempFile("copy", ".json");
copy.serialize(f1b);
assertThat(f1b).hasSameContentAs(f1a);
// remove a2
a1.setDi1(b3);
a1.setDi2(b3);
a1.removeFromDi3(b2);
a1.removeFromDi3(b2);
a1.setBi3(b1);
a3.setBi3(b1);
b3.clearBi5();
b3.removeFromBi6(a2);
b3.removeFromBi9(a2);
r.getAList().removeChild(r.getAList().getIndexOfChild(a2));
r.getBList().removeChild(r.getBList().getIndexOfChild(b2));
File f2a = File.createTempFile("original", ".json");
System.out.println(f2a.getAbsoluteFile());
r.serialize(f2a);
copy = Root.deserialize(f2a);
File f2b = File.createTempFile("copy", ".json");
copy.serialize(f2b);
assertThat(f2b).hasSameContentAs(f2a);
}
}
package org.jastadd.relast.tests;
import org.junit.jupiter.api.Test;
import pointer.serializer.ast.*;
import java.io.File;
import java.io.IOException;
import java.time.Instant;
import java.time.Period;
import static org.assertj.core.api.Assertions.assertThat;
class SerializerPointer {
@Test
void testDi1() throws SerializationException, DeserializationException, IOException {
Root r = new Root();
A a1 = new A("a1");
A a2 = new A("a2");
A a3 = new A("a3");
B b1 = new B("b1");
B b2 = new B("b2");
B b3 = new B("b3");
C c = new C();
c.setName("c");
// non-terminals
D d1 = new D("d1");
c.setD1(d1);
c.setD2(new D("d2"));
c.addD3(new D("D3-1"));
c.addD3(new D("D3-2"));
c.addD3(new D("D3-3"));
r.setC(c);
// non-containment relations
r.addA(a1);
r.addA(a2);
r.addA(a3);
r.addB(b1);
r.addB(b2);
r.addB(b3);
// Di1
a1.setDi1(b2);
a2.setDi1(b1);
a3.setDi1(b3);
// Di2
a1.setDi2(b2);
a3.setDi2(b1);
// Di3
a1.addToDi3(b1);
a1.addToDi3(b2);
a1.addToDi3(b3);
a2.addToDi3(b2);
// Bi1
a1.setBi1(b3);
a2.setBi1(b2);
a3.setBi1(b1);
// Bi2
a1.setBi2(b1);
a2.setBi2(b2);
a3.setBi2(b3);
// Bi3
a1.setBi3(b2);
a2.setBi3(b2);
a3.setBi3(b2);
// Bi5
a1.setBi5(b1);
a2.setBi5(b3);
// Bi6
a2.setBi6(b3);
a3.setBi6(b3);
// Bi9
a1.addToBi9(b1);
a1.addToBi9(b3);
a2.addToBi9(b3);
// D
r.setD(d1);
File f1a = File.createTempFile("original", ".json");
System.out.println(f1a.getAbsoluteFile());
r.serialize(f1a);
com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory();
com.fasterxml.jackson.core.JsonGenerator generator = factory.createGenerator(System.out, com.fasterxml.jackson.core.JsonEncoding.UTF8);
generator.setPrettyPrinter(new com.fasterxml.jackson.core.util.DefaultPrettyPrinter());
r.serialize(generator);
generator.close();
Root copy = Root.deserialize(f1a);
File f1b = File.createTempFile("copy", ".json");
copy.serialize(f1b);
assertThat(f1b).hasSameContentAs(f1a);
// remove a2
a1.setDi1(b3);
a1.setDi2(b3);
a1.removeFromDi3(b2);
a1.removeFromDi3(b2);
a1.setBi3(b1);
a3.setBi3(b1);
b3.clearBi5();
b3.removeFromBi6(a2);
b3.removeFromBi9(a2);
r.getAList().removeChild(r.getAList().getIndexOfChild(a2));
r.getBList().removeChild(r.getBList().getIndexOfChild(b2));
File f2a = File.createTempFile("original", ".json");
System.out.println(f2a.getAbsoluteFile());
r.serialize(f2a);
copy = Root.deserialize(f2a);
File f2b = File.createTempFile("copy", ".json");
copy.serialize(f2b);
assertThat(f2b).hasSameContentAs(f2a);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment