Skip to content
Snippets Groups Projects

Json pointer

Merged Johannes Mey requested to merge json-pointer into master
15 files
+ 1206
43
Compare changes
  • Side-by-side
  • Inline
Files
15
+ 259
17
@@ -5,6 +5,8 @@ aspect BackendAbstractGrammar {
public static boolean ASTNode.resolverHelper = 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 String Program.generateAbstractGrammar() {
@@ -823,13 +825,73 @@ aspect NameResolutionHelper {
r.generateContextDependentNameResolution(sb);
}
if (resolverHelper) {
if (resolverHelper || ASTNode.jsonPointer || ASTNode.manualReferences) {
for (TypeDecl decl : getTypeDeclList()) {
decl.generateContextIndependentNameResolution(sb);
sb.append("\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 " + getTypeUse().decl() + ".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) {
@@ -894,8 +956,12 @@ aspect NameResolutionHelper {
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) + "syn " + getID() + " ASTNode.globallyResolve" + getID() + "ByToken(String id) {\n");
if (serializer) {
sb.append(ind(2) + "return (" + getID() + ") globallyResolveASTNodeByUID(id);\n");
if (serializer && !manualReferences) {
if (jsonPointer) {
sb.append(ind(2) + "return (" + getID() + ") resolveJsonPointer(id);\n");
} else {
sb.append(ind(2) + "return (" + getID() + ") globallyResolveASTNodeByUID(id);\n");
}
} else {
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");
@@ -1002,11 +1068,18 @@ 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() {
public String Program.generateJacksonSerializer() {
StringBuilder sb = new StringBuilder();
generateFromJson(sb);
generateToJson(sb);
writeUID(sb);
if (jsonPointer) {
writeJsonPointer(sb);
} else if (manualReferences) {
// TODO
} else {
writeUID(sb);
}
return sb.toString();
}
@@ -1083,9 +1156,11 @@ aspect Serializer {
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) + "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");
if (!jsonPointer && !manualReferences) {
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) + "g.writeStringField(\"id\", unique$Id());\n");
}
if (componentsTransitive().size() > 0) {
sb.append(ind(3) + "g.writeObjectFieldStart(\"children\");\n");
for (Component child : componentsTransitive()) {
@@ -1196,18 +1271,42 @@ aspect Serializer {
public void OneRelationComponent.serialize(StringBuilder sb, int indent) {
if (useJastAddNames){
sb.append(ind(indent) + "g.writeStringField(\""+getID()+"\", get" + getID() + "().unique$Id());\n");
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");
}
} else {
sb.append(ind(indent) + "g.writeStringField(\""+getID()+"\", " + getID() + "().unique$Id());\n");
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 {
sb.append(ind(indent) + "g.writeStringField(\"" + getID() + "\", " + getID() + "().unique$Id());\n");
}
}
}
public void OptionalRelationComponent.serialize(StringBuilder sb, int indent) {
sb.append(ind(indent) + "if (has" + nameCapitalized() + "()) {\n");
if (useJastAddNames){
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", get" + getID() + "().unique$Id());\n");
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");
}
} else {
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", " + getID() + "().unique$Id());\n");
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 {
sb.append(ind(indent + 1) + "g.writeStringField(\"" + getID() + "\", " + getID() + "().unique$Id());\n");
}
}
sb.append(ind(indent) + "}\n");
}
@@ -1219,7 +1318,14 @@ aspect Serializer {
} else {
sb.append(ind(indent) + "for (" + ofTypeDecl().getID() + " child : " + getID() + "()) {\n");
}
sb.append(ind(indent + 1) + "g.writeString(child.unique$Id());\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) + "}\n");
sb.append(ind(indent) + "g.writeEndArray();\n");
}
@@ -1256,10 +1362,12 @@ aspect Serializer {
sb.append(ind(2) + "element = new " + getID() + "();\n");
}
// deserialize id
sb.append(ind(2) + "if (node.has(\"id\")) {\n");
sb.append(ind(3) + "element.unique$Id = node.get(\"id\").asText();\n");
sb.append(ind(2) + "}\n");
if (!jsonPointer && !manualReferences) {
// deserialize id
sb.append(ind(2) + "if (node.has(\"id\")) {\n");
sb.append(ind(3) + "element.unique$Id = node.get(\"id\").asText();\n");
sb.append(ind(2) + "}\n");
}
// deserialize containment children
if (componentsTransitive().size() > 0) {
@@ -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) {
sb.append("aspect UID {\n");
sb.append(ind(1) + "class UIDProvider {\n");
Loading