From 0fe7e9282d44ae5ab12e64c636585ea3ad0c3c5f Mon Sep 17 00:00:00 2001 From: rschoene <rene.schoene@tu-dresden.de> Date: Mon, 5 Sep 2022 13:27:35 +0200 Subject: [PATCH] begin with default mappings using templates - also indirectly work on #55 to include marshalling methods only when needed --- .../src/main/jastadd/Intermediate.jadd | 4 ++ .../src/main/jastadd/IntermediateToYAML.jrag | 11 +++++ .../src/main/jastadd/Mappings.jrag | 24 ++++++++++- .../src/main/jastadd/Navigation.jrag | 25 +++++++++++ .../src/main/jastadd/RagConnect.relast | 4 ++ .../main/resources/mappingDefinition.mustache | 43 +++++++++++++++++++ .../src/main/resources/ragconnect.mustache | 4 +- 7 files changed, 111 insertions(+), 4 deletions(-) diff --git a/ragconnect.base/src/main/jastadd/Intermediate.jadd b/ragconnect.base/src/main/jastadd/Intermediate.jadd index 1a24fa9..036159f 100644 --- a/ragconnect.base/src/main/jastadd/Intermediate.jadd +++ b/ragconnect.base/src/main/jastadd/Intermediate.jadd @@ -333,6 +333,10 @@ aspect MustacheRagConnect { // === MappingDefinition === syn boolean MappingDefinition.isUsed() = !effectiveUsedAt().isEmpty(); + eq SerializeListMapping.isUsed() = ragconnect().defaultListToBytesMapping().isUsed(); + eq SerializeJavaUtilListMapping.isUsed() = ragconnect().defaultJavaUtilListToBytesMapping().isUsed(); + eq DeserializeListMapping.isUsed() = program().typeDecls().stream().anyMatch( + typeDecl -> ragconnect().defaultBytesToListMapping(typeDecl.getName()).isUsed()); // === attributes needed for computing above ones === syn List<EndpointDefinition> RagConnect.givenEndpointDefinitionList() { diff --git a/ragconnect.base/src/main/jastadd/IntermediateToYAML.jrag b/ragconnect.base/src/main/jastadd/IntermediateToYAML.jrag index 49c2693..23f32d9 100644 --- a/ragconnect.base/src/main/jastadd/IntermediateToYAML.jrag +++ b/ragconnect.base/src/main/jastadd/IntermediateToYAML.jrag @@ -147,6 +147,17 @@ aspect IntermediateToYAML { return result; } + syn Element TemplateDefaultMappingDefinition.toYAML() { + MappingElement result = new MappingElement(); + + // ragconnect / mapping + result.put("isUsed" , isUsed()); + result.put("isSerializeListMapping" , isSerializeListMapping()); + result.put("isSerializeJavaUtilListMapping" , isSerializeJavaUtilListMapping()); + result.put("isDeserializeListMapping" , isDeserializeListMapping()); + return result; + } + syn Element DependencyDefinition.toYAML() { MappingElement result = new MappingElement(); // dependencyDefinition diff --git a/ragconnect.base/src/main/jastadd/Mappings.jrag b/ragconnect.base/src/main/jastadd/Mappings.jrag index e92fc4f..133fae2 100644 --- a/ragconnect.base/src/main/jastadd/Mappings.jrag +++ b/ragconnect.base/src/main/jastadd/Mappings.jrag @@ -27,6 +27,16 @@ aspect DefaultMappings { result.setContent(content); return result; } + private TemplateDefaultMappingDefinition RagConnect.initTemplateMappingDefinition( + TemplateDefaultMappingDefinition prototype, String id, String type, boolean fromBytes) { + MappingDefinitionType givenType = new JavaMappingDefinitionType().setType(new SimpleJavaTypeUse(type)); + MappingDefinitionType bytesType = new JavaArrayMappingDefinitionType().setType(new SimpleJavaTypeUse("byte")); + + prototype.setID(id); + prototype.setFromType(fromBytes ? bytesType : givenType); + prototype.setToType(fromBytes ? givenType : bytesType); + return prototype; + } private DefaultMappingDefinition RagConnect.baseDefaultMappingDefinition(String fromTypeName, String toTypeName, String content) { return createDefaultMappingDefinition("_Default", fromTypeName, toTypeName, content); @@ -81,7 +91,7 @@ aspect DefaultMappings { "com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();\n" + "com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory();\n" + "com.fasterxml.jackson.core.JsonParser parser = factory.createParser(content);\n" + - configJastAddList() + "<" + typeName + ">" + " result = " + typeName + ".deserializeList((com.fasterxml.jackson.databind.node.ArrayNode)mapper.readTree(parser));\n" + + configJastAddList() + "<" + typeName + ">" + " result = " + typeName + ".deserializeListOf" + typeName + "((com.fasterxml.jackson.databind.node.ArrayNode)mapper.readTree(parser));\n" + "parser.close();\n" + "return result;" ); @@ -155,6 +165,15 @@ aspect DefaultMappings { "char", "String", "return String.valueOf(input);"); } +aspect TemplateDefaultMappingDefinitions { + syn nta TemplateDefaultMappingDefinition RagConnect.serializeListMapping() = initTemplateMappingDefinition( + new SerializeListMapping(), "SerializeListMapping", "JastAddList", false); + syn nta TemplateDefaultMappingDefinition RagConnect.serializeJavaUtilListMapping() = initTemplateMappingDefinition( + new SerializeListMapping(), "SerializeJavaUtilListMapping", "java.util.List", false); + syn nta TemplateDefaultMappingDefinition RagConnect.deserializeListMapping(String name) = initTemplateMappingDefinition( + new DeserializeListMapping().setName(name), "DeserializeListMapping", "JastAddList", true); +} + aspect Mappings { // --- effectiveMappings --- syn java.util.List<MappingDefinition> EndpointDefinition.effectiveMappings() { @@ -390,9 +409,12 @@ aspect Mappings { result.add(defaultBytesToTreeMapping(typeDecl.getName())); result.add(defaultTreeToBytesMapping(typeDecl.getName())); result.add(defaultBytesToListMapping(typeDecl.getName())); + result.add(deserializeListMapping(typeDecl.getName())); } result.add(defaultListToBytesMapping()); result.add(defaultJavaUtilListToBytesMapping()); + result.add(serializeListMapping()); + result.add(serializeJavaUtilListMapping()); // // string conversion // result.add(defaultStringToBooleanMapping()); // result.add(defaultStringToIntMapping()); diff --git a/ragconnect.base/src/main/jastadd/Navigation.jrag b/ragconnect.base/src/main/jastadd/Navigation.jrag index 5288a9f..02f6f23 100644 --- a/ragconnect.base/src/main/jastadd/Navigation.jrag +++ b/ragconnect.base/src/main/jastadd/Navigation.jrag @@ -36,6 +36,24 @@ aspect GeneratedNavigation { syn boolean EndpointTarget.isRelationEndpointTarget() = false; eq RelationEndpointTarget.isRelationEndpointTarget() = true; + /** Tests if TemplateDefaultMappingDefinition is a SerializeListMapping. + * @return 'true' if this is a SerializeListMapping, otherwise 'false' + */ + syn boolean TemplateDefaultMappingDefinition.isSerializeListMapping() = false; + eq SerializeListMapping.isSerializeListMapping() = true; + + /** Tests if TemplateDefaultMappingDefinition is a SerializeJavaUtilListMapping. + * @return 'true' if this is a SerializeJavaUtilListMapping, otherwise 'false' + */ + syn boolean TemplateDefaultMappingDefinition.isSerializeJavaUtilListMapping() = false; + eq SerializeJavaUtilListMapping.isSerializeJavaUtilListMapping() = true; + + /** Tests if TemplateDefaultMappingDefinition is a DeserializeListMapping. + * @return 'true' if this is a DeserializeListMapping, otherwise 'false' + */ + syn boolean TemplateDefaultMappingDefinition.isDeserializeListMapping() = false; + eq DeserializeListMapping.isDeserializeListMapping() = true; + /** casts a EndpointTarget into a TokenEndpointTarget if possible. * @return 'this' cast to a TokenEndpointTarget or 'null' */ @@ -80,6 +98,13 @@ aspect GeneratedNavigation { } aspect RagConnectNavigation { + // adapted from generated navigation, was defined only for DefaultMappingDefinition + /** Tests if MappingDefinition is a TemplateDefaultMappingDefinition. + * @return 'true' if this is a TemplateDefaultMappingDefinition, otherwise 'false' + */ + syn boolean MappingDefinition.isTemplateDefaultMappingDefinition() = false; + eq TemplateDefaultMappingDefinition.isTemplateDefaultMappingDefinition() = true; + // --- program --- eq RagConnect.getChild().program() = getProgram(); diff --git a/ragconnect.base/src/main/jastadd/RagConnect.relast b/ragconnect.base/src/main/jastadd/RagConnect.relast index df50e3d..ef96abf 100644 --- a/ragconnect.base/src/main/jastadd/RagConnect.relast +++ b/ragconnect.base/src/main/jastadd/RagConnect.relast @@ -28,6 +28,10 @@ abstract MappingDefinitionType ::= ; JavaMappingDefinitionType : MappingDefinitionType ::= Type:JavaTypeUse; JavaArrayMappingDefinitionType : MappingDefinitionType ::= Type:JavaTypeUse; DefaultMappingDefinition : MappingDefinition; +abstract TemplateDefaultMappingDefinition : DefaultMappingDefinition ; +SerializeListMapping : TemplateDefaultMappingDefinition ; +SerializeJavaUtilListMapping : TemplateDefaultMappingDefinition ; +DeserializeListMapping : TemplateDefaultMappingDefinition ::= <Name> ; Handler ::= <ClassName> <UniqueName> <InUse:boolean>; diff --git a/ragconnect.base/src/main/resources/mappingDefinition.mustache b/ragconnect.base/src/main/resources/mappingDefinition.mustache index b6a035e..392f444 100644 --- a/ragconnect.base/src/main/resources/mappingDefinition.mustache +++ b/ragconnect.base/src/main/resources/mappingDefinition.mustache @@ -1,3 +1,46 @@ +{{#isUsed}} + {{#isTemplateDefaultMappingDefinition}} + {{#isSerializeListMapping}} +public void {{configJastAddList}}.serialize(com.fasterxml.jackson.core.JsonGenerator g) throws SerializationException { + try { + g.writeStartArray(); + for (T child : this) { + child.serialize(g); + } + g.writeEndArray(); + } catch (java.io.IOException e) { + throw new SerializationException("unable to serialize {{configJastAddList}}", e); + } +} + {{/isSerializeListMapping}} + {{#SerializeJavaUtilListMapping}} +protected static <T extends ASTNode> void ASTNode.serializeJavaUtilList( + java.util.List<T> input, com.fasterxml.jackson.core.JsonGenerator g) throws SerializationException { + try { + g.writeStartArray(); + for (T child : input) { + child.serialize(g); + } + g.writeEndArray(); + } catch (java.io.IOException e) { + throw new SerializationException("unable to serialize list", e); + } +} + {{/SerializeJavaUtilListMapping}} + {{#DeserializeListMapping}} +public static {{configJastAddList}}<{{Name}}> {{Name}}.deserializeListOf{{Name}}(com.fasterxml.jackson.databind.node.ArrayNode node) throws DeserializationException { + {{configJastAddList}}<{{Name}}> result = new {{configJastAddList}}<>(); + for (java.util.Iterator<com.fasterxml.jackson.databind.JsonNode> it = node.elements(); it.hasNext();) { + com.fasterxml.jackson.databind.JsonNode element = it.next(); + result.add(deserialize(element)); + } + return result; +} + {{/DeserializeListMapping}} + {{/isTemplateDefaultMappingDefinition}} + {{^TemplateDefaultMappingDefinition}} protected {{{toType}}} ASTNode.{{methodName}}({{{fromType}}} {{FromVariableName}}) throws Exception { {{{Content}}} } + {{/TemplateDefaultMappingDefinition}} +{{/isUsed}} diff --git a/ragconnect.base/src/main/resources/ragconnect.mustache b/ragconnect.base/src/main/resources/ragconnect.mustache index c428021..738ecbe 100644 --- a/ragconnect.base/src/main/resources/ragconnect.mustache +++ b/ragconnect.base/src/main/resources/ragconnect.mustache @@ -15,9 +15,7 @@ aspect RagConnect { } {{#allMappingDefinitions}} - {{#isUsed}} {{> mappingDefinition}} - {{/isUsed}} {{/allMappingDefinitions}} {{#allDependencyDefinitionList}} @@ -65,7 +63,7 @@ aspect RagConnect { return this; } - {{> ListAspect}} +{{!{{> ListAspect}} static void ASTNode.{{logConsoleOut}}(String message, Object... args) { System.out.println(String.format(message, args)); -- GitLab