diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 332575587e4abd3f9be73902219966d25549b287..8ab105a892f39a38343b71583a1747e06ea07ffb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -38,6 +38,7 @@ test: needs: - build script: + - ./gradlew --console=plain --no-daemon test - ./gradlew --console=plain --no-daemon allTests artifacts: when: always diff --git a/pages/docs/extending.md b/pages/docs/extending.md index 61cabca224b7834f08cca7d96f3913c7cb9feb37..14fa8c8dbb525900f26c0ccbf9f7b45ac17544e5 100644 --- a/pages/docs/extending.md +++ b/pages/docs/extending.md @@ -1,32 +1,24 @@ # Extending `RagConnect` -To add a new communication protocol, the following locations have to be changed (replace `ABC` and `abc` with the name of the protocol): +To add a new communication protocol, the following locations have to be changed (replace `ABC` and `abc` with the name of the protocol). -Within `ragconnect.base/src/main/resources`: +### Within `ragconnect.base/src/main/resources` {% raw %} -- Add a new handler `ABCHandler`, if appropriate, similar to the existing handlers - - If further methods are needed for handler initialization, add a new template `abc.mustache` containing those procedures. Add `{{#usesABC}}{{> abc}}{{/usesABC}}` at the top of `ragconnect.mustache` to use this template -- In `receiveDefinition.mustache` and `sendDefinition.mustache`: add a new case in the switch statement defining the logic to happen for both definitions. If the new protocol is close to a PUSH semantic, follow `mqtt`. If it is closer to PULL semantic, follow `rest`. +- Add a new handler `ABCHandler.jadd`, similar to the existing handlers. +- In `handler.mustache`, add further methods if needed for handler usage in the application code (similar to `{{rootNodeName}}.{{SetupWaitUntilReadyMethodName}}` for `mqtt`) +- In `receiveDefinition.mustache` and `sendDefinition.mustache`: add a new case in the switch statements defining the logic to happen upon connect and disconnect for both definitions. If the new protocol is close to a PUSH semantic, follow `mqtt`. If it is closer to PULL semantic, follow `rest`. {% endraw %} -Within `ragconnect.base/src/main/jastadd`: +### Within `ragconnect.base/src/main/jastadd` -- In `backend/Configuration`: - - Add a new static boolean flag `usesABC` to indicate whether the protocol is used -- In `backend/Generation`: - - Add new attributes for type `MRagConnect` for handler attribute and handler field, if needed - - Add attributes for newly introduced references in changed mustache templates, if any - - Add a newly constructed handler within the definition of `RagConnect.toMustache` with the needed fields (class name, construction snippet, handler attribute, handler field, the boolean flag you just added to Configuration) -- In `backend/MustacheNodesToYAML`: - - Add key-value-pair for `usesABC` (and handler, if any) - - Add key-value-pairs for newly introduced referemces in changed mustache templates, if any +In `Handlers.jrag`: Add a new attribute `RagConnect.abcHandler()` returning the resolved handler -In `ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java`: +### Within `ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler` +In `Compiler.java`: - Add a new choice for `--protocols` similar to the existing ones -- Set the flag `usesABC` if the choice is given. -- Add code to add the handler to the list `handlers` if the choice is given, i.e., if `ASTNode.usesABC` +- Add a newly constructed handler in `setConfiguration` with the needed fields (definition file name within `resources` directory, commonly `ABCHandler.jadd`; class name of the handler; unique name for the protocol; whether the handler is used, i.e., if it was given in `--protocols`) Furthermore, new test cases are appreciated, see [below](#writing-tests). @@ -58,7 +50,7 @@ All tests are required to run both locally, and within the CI. ### build.gradle -Use the [PreprocessorPlugin][preprocessor-plugin], the build process can be written concisely in three parts per task: +Using the [PreprocessorPlugin][preprocessor-plugin], the build process can be written concisely in three parts per task: ```groovy task compileTreeAllowedTokens(type: RagConnectTest) { diff --git a/pages/docs/inner-workings.md b/pages/docs/inner-workings.md index 6d8b41e13847f2ae337f08c65068cbef6085e065..a36a62654511e88a4063a52d356f69fc9125a27f 100644 --- a/pages/docs/inner-workings.md +++ b/pages/docs/inner-workings.md @@ -4,12 +4,18 @@ Please see [API documentation](ragdoc/index.html) for more details.  -`RagConnect` uses the [relast-preprocessor](https://git-st.inf.tu-dresden.de/jastadd/relast-preprocessor) to parse `.relast` grammar files. This results in an ASTNode of type `Program`. -It further uses a dedicated parser for `.connect` files containing endpoint-, mapping-, and dependency-definitions. This results in an ASTNode of type `RagConnect`. +`RagConnect` uses the [relast-preprocessor](https://git-st.inf.tu-dresden.de/jastadd/relast-preprocessor) to parse `.relast` grammar files. +This results in an ASTNode of type `Program`. +It further uses a dedicated parser for `.connect` files containing endpoint-, mapping-, and dependency-definitions. +This results in an ASTNode of type `RagConnect`. The goal is to generate an aspect file containing setters and getters of tokens referred to by endpoint-definitions -We use [mustache](https://mustache.github.io/) (currently its [Java version](https://github.com/spullara/mustache.java)) making use of partials resulting in a set of `.mustache` files located in `ragconnect.base/src/main/resources`. -The generation process uses an intermediate NTA of type `MRagConnect` defined in `MustacheNodes.relast` to separate this generation concern from the content of the DSL +We use [mustache](https://mustache.github.io/) (currently its [Java version](https://github.com/spullara/mustache.java)) making use of partials to separate concerns. +The `.mustache` files are located in `ragconnect.base/src/main/resources`. +The generation process uses intermediates NTAs (whose types are defined in `Intermediate.relast`) to ease the definition of two main generation "problems". +Those problems are differentiation on both kinds of an endpoint (send/receive and type/token/list), and attributes depending on position in n-ary relations. -There are aspect files for `Navigation` (mainly isX/asX attributes), `Analysis` (lookup attributes), `Printing`, `backend/Mappings` (default mappings) -One of the main aspects is `backend/Generation` containing attributes to construct the `MRagConnect` NTA and all necessary attributes used within the mustache templates -The other main aspect (which is currently not really used) is `backend/MustacheNodesToYAML.jrag` containing the transformation from a `MRagConnect` subtree to a `Document` subtree defined by `YAML.relast`. This is used to generate a YAML file containing the data used by mustache. It can be used by the default mustache implementation together with the templates. +There are aspect files for `Navigation` (mainly isX/asX attributes), `Analysis` (static analysis attributes), `Printing`, `Mappings` (default mappings). +One of the main aspects is `Intermediate` containing all attributes consumed by `mustache` and other attributes the former depend on. +The other main aspect (which is currently not really used) is `IntermediateToYAML` containing the transformation from a `RagConnect` subtree to a `Document` subtree defined by `Mustache.relast` (located in `relast-preprocessor` submodule). +This is used to generate a YAML file containing the data used by mustache. +It can be used by the default mustache implementation together with the templates. diff --git a/ragconnect.base/build.gradle b/ragconnect.base/build.gradle index c1ee98d52184b358a411a17a359f75a4fa601e8e..f039c8bc129e8f2ca58ed389c1cc5bf5cd8e92e9 100644 --- a/ragconnect.base/build.gradle +++ b/ragconnect.base/build.gradle @@ -24,6 +24,9 @@ repositories { mavenCentral() jcenter() } +tasks.compileJava { + options.release.set(11) +} dependencies { implementation project(':relast-preprocessor') @@ -33,6 +36,12 @@ dependencies { api group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11' } +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(11)) + } +} + def versionFile = 'src/main/resources/ragConnectVersion.properties' def props = new Properties() @@ -77,7 +86,7 @@ jar { File preprocessorGrammar = file('../relast-preprocessor/src/main/jastadd/RelAst.relast') File ragConnectGrammar = file('./src/main/jastadd/RagConnect.relast') -File intermediateGrammar = file('./src/main/jastadd/intermediate/MustacheNodes.relast') +File intermediateGrammar = file('./src/main/jastadd/Intermediate.relast') File mustacheGrammar = file('../relast-preprocessor/src/main/jastadd/mustache/Mustache.relast') task relast(type: JavaExec) { group = 'Build' diff --git a/ragconnect.base/src/main/jastadd/Analysis.jrag b/ragconnect.base/src/main/jastadd/Analysis.jrag index ac891b0e819b1e57e135afced64495a76396db5e..66e6a5a81aff0823c07e4ec3079551c0740b4963 100644 --- a/ragconnect.base/src/main/jastadd/Analysis.jrag +++ b/ragconnect.base/src/main/jastadd/Analysis.jrag @@ -1,59 +1,29 @@ aspect Analysis { - // --- lookupTokenEndpointDefinition --- - inh java.util.List<TokenEndpointDefinition> TokenEndpointDefinition.lookupTokenEndpointDefinitions(TokenComponent token); - eq RagConnect.getConnectSpecificationFile().lookupTokenEndpointDefinitions(TokenComponent token) = lookupTokenEndpointDefinitions(token); - syn java.util.List<TokenEndpointDefinition> RagConnect.lookupTokenEndpointDefinitions(TokenComponent token) { - java.util.List<TokenEndpointDefinition> result = new java.util.ArrayList<>(); - for (EndpointDefinition def : allEndpointDefinitionList()) { - if (def.isTokenEndpointDefinition() && def.asTokenEndpointDefinition().getToken().equals(token)) { - result.add(def.asTokenEndpointDefinition()); - } - } - return result; - } - - // --- lookupTypeEndpointDefinition --- - inh java.util.List<TypeEndpointDefinition> TypeEndpointDefinition.lookupTypeEndpointDefinitions(TypeComponent type); - eq RagConnect.getConnectSpecificationFile().lookupTypeEndpointDefinitions(TypeComponent type) = lookupTypeEndpointDefinitions(type); - syn java.util.List<TypeEndpointDefinition> RagConnect.lookupTypeEndpointDefinitions(TypeComponent type) { - java.util.List<TypeEndpointDefinition> result = new java.util.ArrayList<>(); - for (EndpointDefinition def : allEndpointDefinitionList()) { - if (def.isTypeEndpointDefinition() && def.asTypeEndpointDefinition().getType().equals(type)) { - result.add(def.asTypeEndpointDefinition()); - } - } - return result; - } - - // --- lookupDependencyDefinition --- - inh DependencyDefinition DependencyDefinition.lookupDependencyDefinition(TypeDecl source, String id); - eq RagConnect.getConnectSpecificationFile().lookupDependencyDefinition(TypeDecl source, String id) { - for (DependencyDefinition def : allDependencyDefinitionList()) { - if (def.getID().equals(id) && def.getSource().containingTypeDecl().equals(source)) { - return def; - } - } - return null; - } - // --- isAlreadyDefined --- - syn boolean TokenEndpointDefinition.isAlreadyDefined() { + syn boolean EndpointDefinition.isAlreadyDefined() = getEndpointTarget().isAlreadyDefined(); + syn boolean EndpointTarget.isAlreadyDefined(); + eq TokenEndpointTarget.isAlreadyDefined() { return lookupTokenEndpointDefinitions(getToken()).stream() - .filter(this::matchesType) - .count() > 1; + .filter(containingEndpointDefinition()::matchesType) + .count() > 1; + } + eq TypeEndpointTarget.isAlreadyDefined() { + return lookupTypeEndpointDefinitions(getType()).stream() + .filter(containingEndpointDefinition()::matchesType) + .count() > 1; } syn boolean DependencyDefinition.isAlreadyDefined() = lookupDependencyDefinition(getSource().containingTypeDecl(), getID()) != this; // --- matchesType --- - syn boolean TokenEndpointDefinition.matchesType(TokenEndpointDefinition other); - eq ReceiveTokenEndpointDefinition.matchesType(TokenEndpointDefinition other) = other.isReceiveTokenEndpointDefinition(); - eq SendTokenEndpointDefinition.matchesType(TokenEndpointDefinition other) = other.isSendTokenEndpointDefinition(); + syn boolean EndpointDefinition.matchesType(EndpointDefinition other) = this.getSend() == other.getSend(); // --- assignableTo --- syn boolean MappingDefinitionType.assignableTo(JavaTypeUse target); eq JavaMappingDefinitionType.assignableTo(JavaTypeUse target) = getType().assignableTo(target); eq JavaArrayMappingDefinitionType.assignableTo(JavaTypeUse target) { - if (!target.getName().endsWith("[]")) { return false; } + if (!target.getName().endsWith("[]")) { + return false; + } return getType().assignableTo(new SimpleJavaTypeUse(target.getName().replace("[]", ""))); } syn boolean JavaTypeUse.assignableTo(JavaTypeUse target) { @@ -61,31 +31,39 @@ aspect Analysis { return target.primitivePrettyPrint().equals(this.primitivePrettyPrint()); } syn String JavaTypeUse.primitivePrettyPrint() { - switch(getName()) { + switch (getName()) { case "boolean": - case "Boolean": return "boolean"; + case "Boolean": + return "boolean"; case "int": - case "Integer": return "int"; + case "Integer": + return "int"; case "short": - case "Short": return "short"; + case "Short": + return "short"; case "long": - case "Long": return "long"; + case "Long": + return "long"; case "float": - case "Float": return "float"; + case "Float": + return "float"; case "double": - case "Double": return "double"; + case "Double": + return "double"; case "char": - case "Character": return "char"; - default: return getName(); + case "Character": + return "char"; + default: + return getName(); } } - // --- shouldSendValue --- - syn boolean TokenEndpointDefinition.shouldSendValue() = isSendTokenEndpointDefinition() && !getToken().getNTA(); - syn boolean TypeEndpointDefinition.shouldSendValue() = isSendTypeEndpointDefinition() && !getType().getNTA(); + syn boolean EndpointTarget.entityIsNormalAttribute(); + eq TokenEndpointTarget.entityIsNormalAttribute() = !getToken().getNTA(); + eq TypeEndpointTarget.entityIsNormalAttribute() = !getType().getNTA(); // --- needProxyToken --- - syn boolean TokenComponent.needProxyToken() = !getDependencySourceDefinitionList().isEmpty() || getTokenEndpointDefinitionList().stream().anyMatch(TokenEndpointDefinition::shouldSendValue); + syn boolean TokenComponent.needProxyToken() = !getDependencySourceDefinitionList().isEmpty() || getTokenEndpointTargetList().stream().map(EndpointTarget::containingEndpointDefinition).anyMatch(EndpointDefinition::shouldSendValue); // --- effectiveUsedAt --- coll Set<EndpointDefinition> MappingDefinition.effectiveUsedAt() @@ -95,10 +73,4 @@ aspect Analysis { to MappingDefinition.effectiveUsedAt() for each effectiveMappings(); - // --- typeIsList --- - syn boolean EndpointDefinition.typeIsList() = false; - eq TypeEndpointDefinition.typeIsList() { - return getType().isListComponent(); - } - } diff --git a/ragconnect.base/src/main/jastadd/Configuration.jadd b/ragconnect.base/src/main/jastadd/Configuration.jadd index 8fd0e64b14bbd9a05c7cbf9b7de59ed0cd216d78..9a4645b515e3d690ae4c4b2cdecaac26da516a88 100644 --- a/ragconnect.base/src/main/jastadd/Configuration.jadd +++ b/ragconnect.base/src/main/jastadd/Configuration.jadd @@ -1,11 +1,3 @@ -aspect Configuration { - public static boolean ASTNode.loggingEnabledForReads = false; - public static boolean ASTNode.loggingEnabledForWrites = false; - public static boolean ASTNode.loggingEnabledForIncremental = false; - public static TypeDecl ASTNode.rootNode; - public static String ASTNode.JastAddList = "List"; - public static boolean ASTNode.usesMqtt; - public static boolean ASTNode.usesRest; - public static boolean ASTNode.incrementalOptionActive; - public static boolean ASTNode.experimentalJastAdd329; +aspect ConfigurationShortcuts { + syn TypeDecl RagConnect.rootNode() = getConfiguration().getRootNode(); } diff --git a/ragconnect.base/src/main/jastadd/Errors.jrag b/ragconnect.base/src/main/jastadd/Errors.jrag index 770e506cc5c0145a0ba9979d57a1086a399ed39e..61f966507a1d793ad711bb0e3dde085ee0b46ed6 100644 --- a/ragconnect.base/src/main/jastadd/Errors.jrag +++ b/ragconnect.base/src/main/jastadd/Errors.jrag @@ -3,38 +3,37 @@ aspect Errors { [new TreeSet<ErrorMessage>()] root RagConnect; - ReceiveTokenEndpointDefinition contributes error("Receive definition already defined for " + getToken().getName()) - when isAlreadyDefined() - to RagConnect.errors(); + EndpointDefinition contributes error("Endpoint definition already defined for " + parentTypeName() + "." + entityName()) + when isAlreadyDefined() + to RagConnect.errors(); - ReceiveTokenEndpointDefinition contributes error("Receiving target token must not be an NTA token!") - when getToken().getNTA() - to RagConnect.errors(); + EndpointDefinition contributes error("Receiving target token must not be an NTA token!") + when !getSend() && getEndpointTarget().isTokenEndpointTarget() && token().getNTA() + to RagConnect.errors(); - // if first mapping is null, then suitableDefaultMapping() == null - ReceiveTokenEndpointDefinition contributes error("No suitable default mapping found for type " + + // if first mapping is null, then suitableDefaultMapping() == null + EndpointDefinition contributes error("No suitable default mapping found for type " + ((getMappingList().isEmpty()) - ? getToken().effectiveJavaTypeUse().prettyPrint() - : getMappingList().get(0).getFromType().prettyPrint())) - when effectiveMappings().get(0) == null - to RagConnect.errors(); - - ReceiveTokenEndpointDefinition contributes error("to-type of last mapping (" + effectiveMappings().get(effectiveMappings().size() - 1).getToType().prettyPrint() + ") not assignable to type of the Token (" + getToken().effectiveJavaTypeUse().prettyPrint() + ")!") - when !effectiveMappings().get(effectiveMappings().size() - 1).getToType().assignableTo( - getToken().effectiveJavaTypeUse()) - to RagConnect.errors(); - - SendTokenEndpointDefinition contributes error("Send definition already defined for " + getToken().getName()) - when isAlreadyDefined() - to RagConnect.errors(); - - DependencyDefinition contributes error("Dependency definition already defined for " + getSource().containingTypeDecl().getName() + " with name " + getID()) - when isAlreadyDefined() - to RagConnect.errors(); - - DependencyDefinition contributes error("The name of a dependency definition must not be equal to a list-node on the source") - when isAlreadyDefinedAsList() - to RagConnect.errors(); + ? token().effectiveJavaTypeUse().prettyPrint() + : getMappingList().get(0).getFromType().prettyPrint())) + when !getSend() && getEndpointTarget().isTokenEndpointTarget() && effectiveMappings().get(0) == null + to RagConnect.errors(); + + EndpointDefinition contributes error("to-type of last mapping (" + + effectiveMappings().get(effectiveMappings().size() - 1).getToType().prettyPrint() + + ") not assignable to type of the token (" + token().effectiveJavaTypeUse().prettyPrint() + ")!") + when !getSend() && getEndpointTarget().isTokenEndpointTarget() && + !effectiveMappings().get(effectiveMappings().size() - 1).getToType().assignableTo( + token().effectiveJavaTypeUse()) + to RagConnect.errors(); + + DependencyDefinition contributes error("Dependency definition already defined for " + getSource().containingTypeDecl().getName() + " with name " + getID()) + when isAlreadyDefined() + to RagConnect.errors(); + + DependencyDefinition contributes error("The name of a dependency definition must not be equal to a list-node on the source") + when isAlreadyDefinedAsList() + to RagConnect.errors(); } aspect ErrorHelpers { @@ -46,7 +45,6 @@ aspect ErrorHelpers { } return false; } - syn String TokenComponent.parentTypeDeclAndName() = containingTypeDecl().getName() + "." + getName(); } aspect ErrorMessage { @@ -68,12 +66,15 @@ aspect ErrorMessage { public ASTNode getNode() { return node; } + public int getLine() { return line; } + public int getCol() { return col; } + public String getMessage() { return message; } @@ -94,7 +95,7 @@ aspect ErrorMessage { return n; } - n = col-err.col; + n = col - err.col; if (n != 0) { return n; } diff --git a/ragconnect.base/src/main/jastadd/Handlers.jrag b/ragconnect.base/src/main/jastadd/Handlers.jrag new file mode 100644 index 0000000000000000000000000000000000000000..57c7ccda67ae38524dc46de4f1db192cc345cb91 --- /dev/null +++ b/ragconnect.base/src/main/jastadd/Handlers.jrag @@ -0,0 +1,14 @@ +aspect RagConnectHandlers { + syn Handler RagConnect.mqttHandler() = resolveHandlerByName("mqtt"); + syn Handler RagConnect.restHandler() = resolveHandlerByName("rest"); + + private Handler RagConnect.resolveHandlerByName(String uniqueName) { + for (Handler handler : getHandlerList()) { + if (uniqueName.equals(handler.getUniqueName())) { + return handler; + } + } + System.err.println("Could not find handler with name '" + uniqueName + "'"); + return null; + } +} diff --git a/ragconnect.base/src/main/jastadd/Intermediate.jadd b/ragconnect.base/src/main/jastadd/Intermediate.jadd new file mode 100644 index 0000000000000000000000000000000000000000..3729453a4123d34514ad3475b439139bd7ef7136 --- /dev/null +++ b/ragconnect.base/src/main/jastadd/Intermediate.jadd @@ -0,0 +1,449 @@ +/* +Design considerations +- InnerMappingDefinition needed for iteration attribute (first, last) - not possible with list-relation +- no complete intermediate structure, but instead single nodes where applicable/needed +*/ +aspect SharedMustache { + // === RagConnect === + syn boolean RagConnect.configIncrementalOptionActive() = getConfiguration().getIncrementalOptionActive(); + + syn boolean RagConnect.configLoggingEnabledForIncremental() = getConfiguration().getLoggingEnabledForIncremental(); + + syn boolean RagConnect.configExperimentalJastAdd329() = getConfiguration().getExperimentalJastAdd329(); + + syn String RagConnect.rootNodeName() = getConfiguration().getRootNode().getName(); + + // === EndpointDefinition === + syn String EndpointDefinition.lastResult() = lastDefinition().outputVarName(); +} + +aspect MustacheDependencyDefinition { + // === DependencyDefinition === + syn String DependencyDefinition.dependencyMethodName() = "add" + capitalize(getID()); + + syn String DependencyDefinition.internalRelationPrefix() = "_internal_" + getID(); + + syn String DependencyDefinition.sourceParentTypeName() = getSource().containingTypeDecl().getName(); + + syn String DependencyDefinition.targetParentTypeName() = getTarget().containingTypeDecl().getName(); +} + +aspect MustacheHandler { + // === RagConnect === + syn String RagConnect.closeMethodName() = "ragconnectCloseConnections"; + + syn boolean RagConnect.hasRootTypeComponents() = !rootTypeComponents().isEmpty(); + + syn List<TypeComponent> RagConnect.rootTypeComponents() { + List<TypeComponent> result = new ArrayList<>(); + for (Component child : rootNode().getComponentList()) { + if (child.isTypeComponent()) { + result.add(child.asTypeComponent()); + } + } + return result; + } + + // === Handler === + syn String Handler.attributeName() = "_" + getUniqueName() + "Handler"; + + syn String Handler.constructionSnippet() = "new " + getClassName() + "(\"Handler for " + ragconnect().rootNodeName() + ".\" + this.hashCode())"; + + syn String Handler.fieldName() = "_" + getUniqueName() + "Handler"; + + syn String Handler.setupWaitUntilReadyMethodName() = "ragconnectSetup" + capitalize(getUniqueName()) + "WaitUntilReady"; +} + +aspect MustacheHandleUri { /* empty */ } + +aspect MustacheListAspect { + // === RagConnect === + syn String RagConnect.configJastAddList() = getConfiguration().getJastAddList(); + + syn boolean RagConnect.hasTreeListEndpoints() { + for (EndpointDefinition endpointDef : allEndpointDefinitionList()) { + if (endpointDef.typeIsList()) { + return true; + } + } + return false; + } + + syn Set<TypeDecl> RagConnect.typesForReceivingListEndpoints() { + Set<TypeDecl> result = new HashSet<>(); + for (EndpointDefinition endpointDef : allEndpointDefinitionList()) { + if (endpointDef.typeIsList() && !endpointDef.getSend()) { + result.add(endpointDef.type().getTypeDecl()); + } + } + return result; + } +} + +aspect MustacheMappingApplicationAndDefinition { + // === EndpointDefinition === + syn String EndpointDefinition.condition() { + // TODO [OLD] probably, this has to be structured in a better way + if (lastDefinition().getMappingDefinition().getToType().isArray()) { + return "java.util.Arrays.equals(" + preemptiveExpectedValue() + ", " + lastResult() + ")"; + } + if (getEndpointTarget().isTokenEndpointTarget() && token().isPrimitiveType() && lastDefinition().getMappingDefinition().getToType().isPrimitiveType()) { + return preemptiveExpectedValue() + " == " + lastResult(); + } + if (!getSend() && getEndpointTarget().isTypeEndpointTarget() && getWithAdd()) { + // only check if received list is not null + return lastResult() + " == null"; + } + if (getEndpointTarget().isTypeEndpointTarget() && type().isOptComponent()) { + // use "hasX()" instead of "getX() != null" for optionals + return "has" + typeName() + "()" + " && " + preemptiveExpectedValue() + ".equals(" + lastResult() + ")"; + } + if (lastDefinition().getMappingDefinition().getToType().isPrimitiveType() || lastDefinition().getMappingDefinition().isDefaultMappingDefinition()) { + return preemptiveExpectedValue() + " != null && " + preemptiveExpectedValue() + ".equals(" + lastResult() + ")"; + } + return preemptiveExpectedValue() + " != null ? " + preemptiveExpectedValue() + ".equals(" + lastResult() + ") : " + lastResult() + " == null"; + } + + syn JastAddList<MInnerMappingDefinition> EndpointDefinition.innerMappingDefinitions() = toMustache().getInnerMappingDefinitionList(); + + syn String EndpointDefinition.lastDefinitionToType() = lastDefinition().toType(); + + syn String EndpointDefinition.preemptiveReturn() = toMustache().preemptiveReturn(); + + // === (MInner)MappingDefinition === + syn String MappingDefinition.fromType() = getFromType().prettyPrint(); + + inh boolean MInnerMappingDefinition.isLast(); + eq MEndpointDefinition.getInnerMappingDefinition(int i).isLast() { + return i == getNumInnerMappingDefinition() - 1; + } + + inh String MInnerMappingDefinition.inputVarName(); + eq MEndpointDefinition.getInnerMappingDefinition(int i).inputVarName() { + return i == 0 + ? firstInputVarName() + : getInnerMappingDefinition(i - 1).outputVarName(); + } + + syn String MInnerMappingDefinition.methodName() = getMappingDefinition().methodName(); + syn String MappingDefinition.methodName() = "_apply_" + getID(); + + syn String MInnerMappingDefinition.outputVarName() = "result" + methodName(); // we do not need "_" in between here, because methodName begins with one + + syn String MInnerMappingDefinition.toType() = getMappingDefinition().toType(); + syn String MappingDefinition.toType() = getToType().prettyPrint(); + + // === attributes needed for computing above ones === + syn String EndpointDefinition.preemptiveExpectedValue() = toMustache().preemptiveExpectedValue(); + syn String EndpointDefinition.firstInputVarName() = toMustache().firstInputVarName(); + + syn String MEndpointDefinition.preemptiveExpectedValue(); + syn String MEndpointDefinition.preemptiveReturn(); + syn String MEndpointDefinition.firstInputVarName(); + + eq MTokenReceiveDefinition.firstInputVarName() = "message"; + eq MTokenReceiveDefinition.preemptiveExpectedValue() = getterMethodName() + "()"; + eq MTokenReceiveDefinition.preemptiveReturn() = "return;"; + + eq MTokenSendDefinition.firstInputVarName() = getterMethodName() + "()"; + eq MTokenSendDefinition.preemptiveExpectedValue() = lastValue(); + eq MTokenSendDefinition.preemptiveReturn() = "return false;"; + + eq MTypeReceiveDefinition.firstInputVarName() = "message"; + eq MTypeReceiveDefinition.preemptiveExpectedValue() = getterMethodName() + "()"; + eq MTypeReceiveDefinition.preemptiveReturn() = "return;"; + + eq MTypeSendDefinition.firstInputVarName() = getterMethodName() + "()"; + eq MTypeSendDefinition.preemptiveExpectedValue() = lastValue(); + eq MTypeSendDefinition.preemptiveReturn() = "return false;"; + + syn String MEndpointDefinition.parentTypeName() = getEndpointDefinition().parentTypeName(); + + syn String MEndpointDefinition.getterMethodName() = getEndpointDefinition().getterMethodName(); +} + +aspect MustacheRagConnect { + // === RagConnect === + syn List<DependencyDefinition> RagConnect.allDependencyDefinitionList() { + List<DependencyDefinition> result = new ArrayList<>(); + for (ConnectSpecification spec : getConnectSpecificationFileList()) { + spec.getDependencyDefinitionList().forEach(result::add); + } + return result; + } + + syn List<EndpointDefinition> RagConnect.allEndpointDefinitionList() { + List<EndpointDefinition> result = new ArrayList<>(); + for (ConnectSpecification spec : getConnectSpecificationFileList()) { + spec.getEndpointDefinitionList().forEach(result::add); + } + return result; + } + + // > allMappingDefinitions in Mappings.jrag + + syn List<TokenComponent> RagConnect.tokenComponentsThatNeedProxy() { + List<TokenComponent> result = new ArrayList<>(); + for (TokenComponent token : getProgram().allTokenComponents()) { + if (token.needProxyToken()) { + result.add(token); + } + } + return result; + } + + // === MappingDefinition === + syn boolean MappingDefinition.isUsed() = !effectiveUsedAt().isEmpty(); +} + +aspect MustacheReceiveAndSendAndHandleUri { + // === EndpointDefinition === + syn String EndpointDefinition.connectMethodName() = "connect" + entityName(); + + syn String EndpointDefinition.connectParameterName() = "uriString"; + + syn String EndpointDefinition.disconnectMethodName() { + // if both (send and receive) are defined for an endpoint, ensure methods with different names + String extra; + if (getEndpointTarget().isTokenEndpointTarget()) { + extra = lookupTokenEndpointDefinitions(token()).size() > 1 ? uniqueSuffix() : ""; + } else if (getEndpointTarget().isTypeEndpointTarget()) { + extra = lookupTypeEndpointDefinitions(type()).size() > 1 ? uniqueSuffix() : ""; + } else { + extra = ""; + } + return "disconnect" + extra + entityName(); + } + + syn String EndpointDefinition.entityName() = getEndpointTarget().entityName(); + + syn String EndpointDefinition.getterMethodName() = getEndpointTarget().getterMethodName(); + + syn String EndpointDefinition.parentTypeName() = getEndpointTarget().parentTypeName(); + + // === attributes needed for computing above ones === + syn String EndpointTarget.getterMethodName(); + syn String EndpointTarget.parentTypeName(); + syn String EndpointTarget.entityName(); + + eq TokenEndpointTarget.getterMethodName() = "get" + getToken().getName(); + eq TokenEndpointTarget.parentTypeName() = getToken().containingTypeDecl().getName(); + eq TokenEndpointTarget.entityName() = getToken().getName(); + + eq TypeEndpointTarget.getterMethodName() = "get" + getType().getName() + (typeIsList() ? "List" : ""); + eq TypeEndpointTarget.parentTypeName() = getType().containingTypeDecl().getName(); + eq TypeEndpointTarget.entityName() = getType().getName() + (typeIsList() && !containingEndpointDefinition().getIndexBasedListAccess() ? "List" : ""); + +} + +aspect MustacheReceiveDefinition { + // === RagConnect === + syn boolean RagConnect.configLoggingEnabledForReads() = getConfiguration().getLoggingEnabledForReads(); + + // === EndpointDefinition === + syn boolean EndpointDefinition.hasTypeEndpointTarget() = getEndpointTarget().isTypeEndpointTarget(); + + syn String EndpointDefinition.idTokenName() = "InternalRagconnectTopicInList"; + + syn String EndpointDefinition.internalConnectMethodName() = "_internal_" + connectMethodName(); + + syn String EndpointDefinition.resolveInListMethodName() = "_ragconnect_resolve" + entityName() + "InList"; + + syn boolean EndpointDefinition.typeIsList() = getEndpointTarget().typeIsList(); + + // === attributes needed for computing above ones === + syn boolean EndpointTarget.typeIsList() = false; + eq TypeEndpointTarget.typeIsList() { + return getType().isListComponent(); + } + + syn String EndpointDefinition.uniqueSuffix() = getSend() ? "Send" : "Receive"; +} + +aspect MustacheSendDefinition { + // === RagConnect === + syn boolean RagConnect.configLoggingEnabledForWrites() = getConfiguration().getLoggingEnabledForWrites(); + + // === EndpointDefinition === + syn String EndpointDefinition.lastValue() = senderName() + ".lastValue"; + + syn String EndpointDefinition.senderName() = getEndpointTarget().senderName(); + + syn boolean EndpointDefinition.shouldSendValue() = getSend() && getEndpointTarget().entityIsNormalAttribute(); + + syn String EndpointDefinition.tokenResetMethodName() = getterMethodName() + "_reset"; + + syn String EndpointDefinition.updateMethodName() = toMustache().updateMethodName(); + + syn String EndpointDefinition.writeMethodName() = toMustache().writeMethodName(); + + // === attributes needed for computing above ones === + syn String EndpointTarget.senderName(); + eq TokenEndpointTarget.senderName() = "_sender_" + getToken().getName(); + eq TypeEndpointTarget.senderName() = "_sender_" + getType().getName(); + + syn String MEndpointDefinition.updateMethodName(); + syn String MEndpointDefinition.writeMethodName(); + + // MTokenReceiveDefinition + eq MTokenReceiveDefinition.updateMethodName() = null; + eq MTokenReceiveDefinition.writeMethodName() = null; + + // MTokenSendDefinition + eq MTokenSendDefinition.updateMethodName() = "_update_" + tokenName(); + eq MTokenSendDefinition.writeMethodName() = "_writeLastValue_" + tokenName(); + + // MTypeReceiveDefinition + eq MTypeReceiveDefinition.updateMethodName() = null; + eq MTypeReceiveDefinition.writeMethodName() = null; + + // MTypeSendDefinition + eq MTypeSendDefinition.updateMethodName() = "_update_" + typeName(); + eq MTypeSendDefinition.writeMethodName() = "_writeLastValue_" + typeName(); + + syn String EndpointDefinition.tokenName() = token().getName(); + syn String MEndpointDefinition.tokenName() = getEndpointDefinition().tokenName(); + + syn String EndpointDefinition.typeName() = type().getName(); + syn String MEndpointDefinition.typeName() = getEndpointDefinition().typeName(); +} + +aspect MustacheTokenComponent { + // === TokenComponent === + syn String TokenComponent.internalName() = needProxyToken() ? "_internal_" + getName() : getName(); + + syn String TokenComponent.javaType() = effectiveJavaTypeUse().prettyPrint(); + + syn EndpointDefinition TokenComponent.normalTokenSendDef() { + for (EndpointTarget target : getTokenEndpointTargetList()) { + if (target.isTokenEndpointTarget() && target.containingEndpointDefinition().shouldSendValue()) { + return target.containingEndpointDefinition(); + } + } + return null; + } + + syn String TokenComponent.parentTypeName() = containingTypeDecl().getName(); + + // > see MustacheDependencyDefinition for internalRelationPrefix, targetParentTypeName + + // === DependencyDefinition === + syn EndpointDefinition DependencyDefinition.targetEndpointDefinition() { + // resolve definition in here, as we do not need resolveMethod in any other place (yet) + for (EndpointDefinition endpointDefinition : ragconnect().allEndpointDefinitionList()) { + if (!endpointDefinition.getSend()) { + continue; + } + EndpointTarget endpointTarget = endpointDefinition.getEndpointTarget(); + if (endpointTarget.isTokenEndpointTarget() && + endpointTarget.asTokenEndpointTarget().getToken().equals(this.getTarget())) { + return endpointDefinition; + } + if (endpointTarget.isTypeEndpointTarget() && + endpointTarget.asTypeEndpointTarget().getType().equals(this.getTarget())) { + return endpointDefinition; + } + } + return null; + } + + // > see MustacheSend for updateMethodName, writeMethodName +} + +aspect AttributesForMustache { + syn String MEndpointDefinition.lastValue() = getEndpointDefinition().lastValue(); + + // token and type are potentially dangerous because asXEndpointTarget can return null + syn TokenComponent EndpointDefinition.token() = getEndpointTarget().asTokenEndpointTarget().getToken(); + syn TypeComponent EndpointDefinition.type() = getEndpointTarget().asTypeEndpointTarget().getType(); + + syn MInnerMappingDefinition EndpointDefinition.lastDefinition() = toMustache().lastDefinition(); + syn MInnerMappingDefinition MEndpointDefinition.lastDefinition() = getInnerMappingDefinition(getNumInnerMappingDefinition() - 1); + + syn nta MEndpointDefinition EndpointDefinition.toMustache() { + final MEndpointDefinition result; + if (getEndpointTarget().isTokenEndpointTarget()) { + if (getSend()) { + result = new MTokenSendDefinition(); + } else { + result = new MTokenReceiveDefinition(); + } + } else if (getEndpointTarget().isTypeEndpointTarget()) { + if (getSend()) { + result = new MTypeSendDefinition(); + } else { + result = new MTypeReceiveDefinition(); + } + } else { + throw new RuntimeException("Unknown endpoint target type: " + getEndpointTarget()); + } + result.setEndpointDefinition(this); + for (MappingDefinition def : effectiveMappings()) { + MInnerMappingDefinition inner = new MInnerMappingDefinition(); + inner.setMappingDefinition(def); + result.addInnerMappingDefinition(inner); + } + return result; + } +} + +aspect GrammarGeneration { + syn java.util.List<Relation> RagConnect.additionalRelations() { + java.util.List<Relation> result = new java.util.ArrayList<>(); + for (DependencyDefinition dd : allDependencyDefinitionList()) { + result.add(dd.getRelationToCreate()); + } + return result; + } + + syn nta Relation DependencyDefinition.getRelationToCreate() { + BidirectionalRelation result = new BidirectionalRelation(); + NavigableRole left = new ListRole(internalRelationPrefix() + "Source"); + left.setType(getTarget().containingTypeDecl()); + NavigableRole right = new ListRole(internalRelationPrefix() + "Target"); + right.setType(getSource().containingTypeDecl()); + result.setLeft(left); + result.setRight(right); + result.addComment(new WhitespaceComment("\n")); + return result; + } + + syn java.util.Map<TypeDecl, TokenComponent> RagConnect.additionalTokens() { + java.util.Map<TypeDecl, TokenComponent> result = new java.util.HashMap<>(); + for (EndpointDefinition def : allEndpointDefinitionList()) { + if (def.getTokenToCreate() != null) { + result.put(def.type().getTypeDecl(), def.getTokenToCreate()); + } + } + return result; + } + + syn TokenComponent EndpointDefinition.getTokenToCreate() { + if (typeIsList() && getIndexBasedListAccess()) { + TokenComponent result = new TokenComponent(); + result.setName(idTokenName()); + result.setNTA(false); + result.setJavaTypeUse(new SimpleJavaTypeUse("String")); + return result; + } else { + return null; + } + } +} + +aspect GrammarExtension { + refine BackendAbstractGrammar public void TokenComponent.generateAbstractGrammar(StringBuilder b) { + if (getNTA()) { + b.append("/"); + } + b.append("<"); + if (!getName().equals("")) { + b.append(internalName()).append(":"); + } + effectiveJavaTypeUse().generateAbstractGrammar(b); + b.append(">"); + if (getNTA()) { + b.append("/"); + } + } +} diff --git a/ragconnect.base/src/main/jastadd/Intermediate.relast b/ragconnect.base/src/main/jastadd/Intermediate.relast new file mode 100644 index 0000000000000000000000000000000000000000..d7afd2ea942558f6999c8fa64c91bfdc480d659c --- /dev/null +++ b/ragconnect.base/src/main/jastadd/Intermediate.relast @@ -0,0 +1,12 @@ +abstract MEndpointDefinition ::= InnerMappingDefinition:MInnerMappingDefinition*; +rel MEndpointDefinition.EndpointDefinition -> EndpointDefinition; + +abstract MTokenEndpointDefinition : MEndpointDefinition; +MTokenReceiveDefinition : MTokenEndpointDefinition; +MTokenSendDefinition : MTokenEndpointDefinition; +abstract MTypeEndpointDefinition : MEndpointDefinition; +MTypeReceiveDefinition : MTypeEndpointDefinition; +MTypeSendDefinition : MTypeEndpointDefinition; + +MInnerMappingDefinition; +rel MInnerMappingDefinition.MappingDefinition -> MappingDefinition; diff --git a/ragconnect.base/src/main/jastadd/IntermediateToYAML.jrag b/ragconnect.base/src/main/jastadd/IntermediateToYAML.jrag new file mode 100644 index 0000000000000000000000000000000000000000..67ccf2738e32f3f91f2fbac3eec8349d348228d6 --- /dev/null +++ b/ragconnect.base/src/main/jastadd/IntermediateToYAML.jrag @@ -0,0 +1,206 @@ +aspect IntermediateToYAML { + syn Document RagConnect.toYAML() { + Document doc = new Document(); + MappingElement root = new MappingElement(); + // grammar children + ListElement handlersElement = new ListElement(); + for (Handler handler : getHandlerList()) { + handlersElement.add(handler.toYAML()); + } + root.put("Handlers" , handlersElement); + + // shared + root.put("configIncrementalOptionActive" , configIncrementalOptionActive()); + root.put("configLoggingEnabledForIncremental" , configLoggingEnabledForIncremental()); + root.put("configExperimentalJastAdd329" , configExperimentalJastAdd329()); + root.put("rootNodeName" , rootNodeName()); + + // handler + root.put("closeMethodName" , closeMethodName()); + root.put("hasRootTypeComponents" , hasRootTypeComponents()); + ListElement rootTypeComponentsElement = new ListElement(); + for (TypeComponent comp : rootTypeComponents()) { + rootTypeComponentsElement.addElement(comp.toYAML()); + } + root.put("rootTypeComponents" , rootTypeComponentsElement); + + // listAspect + root.put("configJastAddList" , configJastAddList()); + root.put("hasTreeListEndpoints" , hasTreeListEndpoints()); + ListElement typesForReceivingListEndpointsElement = new ListElement(); + for (TypeDecl typeDecl : typesForReceivingListEndpoints()) { + typesForReceivingListEndpointsElement.addElement(typeDecl.toYAML()); + } + root.put("typesForReceivingListEndpoints" , typesForReceivingListEndpointsElement); + + // ragconnect + ListElement dependencyDefinitionsElement = new ListElement(); + for (DependencyDefinition def : allDependencyDefinitionList()) { + dependencyDefinitionsElement.addElement(def.toYAML()); + } + root.put("allDependencyDefinitionList" , dependencyDefinitionsElement); + ListElement endpointDefinitionsElement = new ListElement(); + for (EndpointDefinition def : allEndpointDefinitionList()) { + endpointDefinitionsElement.addElement(def.toYAML()); + } + root.put("allEndpointDefinitionList" , endpointDefinitionsElement); + ListElement mappingDefinitionsElement = new ListElement(); + for (MappingDefinition def : allMappingDefinitions()) { + mappingDefinitionsElement.addElement(def.toYAML()); + } + root.put("allMappingDefinitions" , mappingDefinitionsElement); + ListElement tokenComponentsElement = new ListElement(); + for (TokenComponent comp : tokenComponentsThatNeedProxy()) { + tokenComponentsElement.addElement(comp.toYAML()); + } + root.put("tokenComponentsThatNeedProxy" , tokenComponentsElement); + + // receive + root.put("configLoggingEnabledForReads" , configLoggingEnabledForReads()); + + // send + root.put("configLoggingEnabledForWrites" , configLoggingEnabledForWrites()); + + // from Handlers.jrag + root.put("mqttHandler" , mqttHandler().toYAML()); + root.put("restHandler" , restHandler().toYAML()); + + doc.setRootElement(root); + return doc; + } + + syn MappingElement EndpointDefinition.toYAML() { + MappingElement result = new MappingElement(); + // grammar children + result.put("AlwaysApply" , getAlwaysApply()); + result.put("IndexBasedListAccess" , getIndexBasedListAccess()); + result.put("WithAdd" , getWithAdd()); + result.put("Send" , getSend()); + + // shared + result.put("lastResult" , lastResult()); + + // mapping + result.put("condition" , sanitizeValueForYAML(condition())); + ListElement innerMappingDefinitions = new ListElement(); + for (MInnerMappingDefinition def : innerMappingDefinitions()) { + innerMappingDefinitions.addElement(def.toYAML()); + } + result.put("innerMappingDefinitions" , innerMappingDefinitions); + result.put("lastDefinitionToType" , lastDefinitionToType()); + result.put("preemptiveReturn" , preemptiveReturn()); + + // receive + send + result.put("connectMethodName" , connectMethodName()); + result.put("connectParameterName" , connectParameterName()); + result.put("disconnectMethodName" , disconnectMethodName()); + result.put("entityName" , entityName()); + result.put("getterMethodName" , getterMethodName()); + result.put("parentTypeName" , parentTypeName()); + + if (getSend()) { + result.put("lastValue" , lastValue()); + result.put("senderName" , senderName()); + result.put("shouldSendValue" , shouldSendValue()); + result.put("tokenResetMethodName" , tokenResetMethodName()); + result.put("updateMethodName" , updateMethodName()); + result.put("writeMethodName" , writeMethodName()); + } else { + result.put("hasTypeEndpointTarget" , hasTypeEndpointTarget()); + result.put("idTokenName" , idTokenName()); + result.put("internalConnectMethodName" , internalConnectMethodName()); + result.put("resolveInListMethodName" , resolveInListMethodName()); + result.put("typeIsList" , getEndpointTarget().typeIsList()); + } + return result; + } + + void UntypedEndpointTarget.addToYAML(MappingElement result) { + // empty + } + + syn Element MInnerMappingDefinition.toYAML() { + MappingElement result = new MappingElement(); + result.put("last" , isLast()); + result.put("inputVarName" , inputVarName()); + result.put("methodName" , methodName()); + result.put("outputVarName" , outputVarName()); + result.put("toType" , toType()); + return result; + } + + syn Element MappingDefinition.toYAML() { + MappingElement result = new MappingElement(); + // grammar children + result.put("FromVariableName" , getFromVariableName()); + result.put("Content" , sanitizeValueForYAML(getContent())); + + // mapping + result.put("fromType" , fromType()); + result.put("methodName" , methodName()); + result.put("toType" , toType()); + + // ragconnect + result.put("isUsed" , isUsed()); + return result; + } + + syn Element DependencyDefinition.toYAML() { + MappingElement result = new MappingElement(); + // dependencyDefinition + result.put("dependencyMethodName" , dependencyMethodName()); + result.put("internalRelationPrefix" , internalRelationPrefix()); + result.put("sourceParentTypeName" , sourceParentTypeName()); + result.put("targetParentTypeName" , targetParentTypeName()); + + // tokenComponent + result.put("targetEndpointDefinition" , targetEndpointDefinition().toYAML()); + return result; + } + + syn Element TokenComponent.toYAML() { + MappingElement result = new MappingElement(); + result.put("Name" , getName()); + ListElement dependencySourceDefinitions = new ListElement(); + for (DependencyDefinition def : getDependencySourceDefinitionList()) { + dependencySourceDefinitions.add(def.toYAML()); + } + result.put("DependencySourceDefinitions" , dependencySourceDefinitions); + + result.put("javaType" , javaType()); + result.put("normalTokenSendDef" , normalTokenSendDef().toYAML()); + result.put("parentTypeName" , parentTypeName()); + return result; + } + + syn MappingElement Handler.toYAML() { + MappingElement result = new MappingElement(); + result.put("ClassName" , getClassName()); + result.put("InUse" , getInUse()); + + result.put("attributeName" , attributeName()); + result.put("constructionSnippet" , constructionSnippet()); + result.put("fieldName" , fieldName()); + result.put("setupWaitUntilReadyMethodName" , setupWaitUntilReadyMethodName()); + return result; + } + + syn MappingElement TypeComponent.toYAML() { + return new MappingElement().put("Name", getName()); + } + + syn MappingElement TypeDecl.toYAML() { + return new MappingElement().put("Name", getName()); + } + + protected StringElement ASTNode.sanitizeValueForYAML(String value) { + return StringElement.of(value.replace("\"" , "\\\"").replace("\n" , "\\n")); + } +} + +aspect Navigation { + eq Document.getChild().program() = null; + eq Document.getChild().ragconnect() = null; + eq Document.getChild().containedFile() = null; + eq Document.containedFileName() = getFileName(); +} diff --git a/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag b/ragconnect.base/src/main/jastadd/Mappings.jrag similarity index 62% rename from ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag rename to ragconnect.base/src/main/jastadd/Mappings.jrag index 9d122978ee65307972063cb33e111e951b979569..093f4cc1d4f1cb0eecf1ffe7914c20e6fa715b27 100644 --- a/ragconnect.base/src/main/jastadd/intermediate/Mappings.jrag +++ b/ragconnect.base/src/main/jastadd/Mappings.jrag @@ -47,50 +47,50 @@ aspect DefaultMappings { syn nta DefaultMappingDefinition RagConnect.defaultBytesToTreeMapping(String typeName) { return treeDefaultMappingDefinition("byte[]", typeName, - "String content = new String(input);\n" + - "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" + - typeName + " result = " + typeName + ".deserialize((com.fasterxml.jackson.databind.JsonNode)mapper.readTree(parser));\n" + - "parser.close();\n" + - "return result;" + "String content = new String(input);\n" + + "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" + + typeName + " result = " + typeName + ".deserialize((com.fasterxml.jackson.databind.JsonNode)mapper.readTree(parser));\n" + + "parser.close();\n" + + "return result;" ); } syn nta DefaultMappingDefinition RagConnect.defaultTreeToBytesMapping(String typeName) { return treeDefaultMappingDefinition(typeName, "byte[]", - "java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();\n" + - "com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory();\n" + - "com.fasterxml.jackson.core.JsonGenerator generator = factory.createGenerator(outputStream, com.fasterxml.jackson.core.JsonEncoding.UTF8);\n"+ - "input.serialize(generator);\n" + - "generator.flush();\n" + - "return outputStream.toString().getBytes();" + "java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();\n" + + "com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory();\n" + + "com.fasterxml.jackson.core.JsonGenerator generator = factory.createGenerator(outputStream, com.fasterxml.jackson.core.JsonEncoding.UTF8);\n" + + "input.serialize(generator);\n" + + "generator.flush();\n" + + "return outputStream.toString().getBytes();" ); } syn nta DefaultMappingDefinition RagConnect.defaultBytesToListTreeMapping(String typeName) { - return treeDefaultMappingDefinition("byte[]", JastAddList + "<" + typeName + ">", - "String content = new String(input);\n" + - "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" + - JastAddList + "<" + typeName + ">" + " result = " + typeName + ".deserializeList((com.fasterxml.jackson.databind.node.ArrayNode)mapper.readTree(parser));\n" + - "parser.close();\n" + - "return result;" + return treeDefaultMappingDefinition("byte[]", configJastAddList() + "<" + typeName + ">", + "String content = new String(input);\n" + + "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" + + "parser.close();\n" + + "return result;" ); } syn nta DefaultMappingDefinition RagConnect.defaultListTreeToBytesMapping() { - return treeDefaultMappingDefinition(JastAddList, "byte[]", - "java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();\n" + - "com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory();\n" + - "com.fasterxml.jackson.core.JsonGenerator generator = factory.createGenerator(outputStream, com.fasterxml.jackson.core.JsonEncoding.UTF8);\n"+ - "input.serialize(generator);\n" + - "generator.flush();\n" + - "return outputStream.toString().getBytes();" + return treeDefaultMappingDefinition(configJastAddList(), "byte[]", + "java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();\n" + + "com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory();\n" + + "com.fasterxml.jackson.core.JsonGenerator generator = factory.createGenerator(outputStream, com.fasterxml.jackson.core.JsonEncoding.UTF8);\n" + + "input.serialize(generator);\n" + + "generator.flush();\n" + + "return outputStream.toString().getBytes();" ); } syn nta DefaultMappingDefinition RagConnect.defaultBooleanToBytesMapping() = baseDefaultMappingDefinition( - "boolean", "byte[]", "return java.nio.ByteBuffer.allocate(1).put((byte) (input ? 1 : 0)).array();"); + "boolean", "byte[]", "return java.nio.ByteBuffer.allocate(1).put((byte) (input ? 1 : 0)).array();"); syn nta DefaultMappingDefinition RagConnect.defaultIntToBytesMapping() = baseDefaultMappingDefinition( "int", "byte[]", "return java.nio.ByteBuffer.allocate(Integer.BYTES).putInt(input).array();"); syn nta DefaultMappingDefinition RagConnect.defaultShortToBytesMapping() = baseDefaultMappingDefinition( @@ -141,7 +141,7 @@ aspect Mappings { // --- effectiveMappings --- syn java.util.List<MappingDefinition> EndpointDefinition.effectiveMappings() { java.util.List<MappingDefinition> result; - if (isReceiveTokenEndpointDefinition() || isReceiveTypeEndpointDefinition()) { + if (!getSend()) { // if no mappings are specified, or if first mapping is not suitable. // then prepend the suitable default mapping if (getMappingList().isEmpty() || !getMappingList().get(0).getFromType().isByteArray()) { @@ -151,7 +151,7 @@ aspect Mappings { } else { result = getMappingList(); } - } else if (isSendTokenEndpointDefinition() || isSendTypeEndpointDefinition()) { + } else { // if no mappings are specified, or if last mapping is not suitable // then append the suitable default mapping if (getMappingList().isEmpty() || !getMappingList().get(getMappingList().size() - 1).getToType().isByteArray()) { @@ -160,8 +160,6 @@ aspect Mappings { } else { result = getMappingList(); } - } else { - throw new RuntimeException("Unknown endpoint definition: " + this); } return result; } @@ -170,7 +168,7 @@ aspect Mappings { syn boolean TokenComponent.isPrimitiveType() = effectiveJavaTypeUse().isPrimitiveType(); syn boolean JavaTypeUse.isPrimitiveType() = false; eq SimpleJavaTypeUse.isPrimitiveType() { - switch(getName()) { + switch (getName()) { case "boolean": case "int": case "short": @@ -178,8 +176,10 @@ aspect Mappings { case "float": case "double": case "char": - case "byte": return true; - default: return false; + case "byte": + return true; + default: + return false; } } syn boolean MappingDefinitionType.isPrimitiveType() = false; @@ -191,153 +191,164 @@ aspect Mappings { // --- suitableReceiveDefaultMapping --- syn DefaultMappingDefinition EndpointDefinition.suitableReceiveDefaultMapping() { + if (getEndpointTarget().isTypeEndpointTarget()) { + try { + TypeDecl typeDecl = program().resolveTypeDecl(targetTypeName()); + return typeIsList() && !getIndexBasedListAccess() ? ragconnect().defaultBytesToListTreeMapping(typeDecl.getName()) : ragconnect().defaultBytesToTreeMapping(typeDecl.getName()); + } catch (Exception ignore) { + } + } switch (targetTypeName()) { case "boolean": - case "Boolean": return ragconnect().defaultBytesToBooleanMapping(); + case "Boolean": + return ragconnect().defaultBytesToBooleanMapping(); case "int": - case "Integer": return ragconnect().defaultBytesToIntMapping(); + case "Integer": + return ragconnect().defaultBytesToIntMapping(); case "short": - case "Short": return ragconnect().defaultBytesToShortMapping(); + case "Short": + return ragconnect().defaultBytesToShortMapping(); case "long": - case "Long": return ragconnect().defaultBytesToLongMapping(); + case "Long": + return ragconnect().defaultBytesToLongMapping(); case "float": - case "Float": return ragconnect().defaultBytesToFloatMapping(); + case "Float": + return ragconnect().defaultBytesToFloatMapping(); case "double": - case "Double": return ragconnect().defaultBytesToDoubleMapping(); + case "Double": + return ragconnect().defaultBytesToDoubleMapping(); case "char": - case "Character": return ragconnect().defaultBytesToCharMapping(); - case "String": return ragconnect().defaultBytesToStringMapping(); + case "Character": + return ragconnect().defaultBytesToCharMapping(); + case "String": + return ragconnect().defaultBytesToStringMapping(); default: try { TypeDecl typeDecl = program().resolveTypeDecl(targetTypeName()); // TODO: also support list-types, if list is first type return ragconnect().defaultBytesToTreeMapping(typeDecl.getName()); - } catch (Exception ignore) {} + } catch (Exception ignore) { + } System.err.println("Could not find suitable default mapping for " + targetTypeName() + " on " + this); return null; } } - eq TypeEndpointDefinition.suitableReceiveDefaultMapping() { - try { - TypeDecl typeDecl = program().resolveTypeDecl(targetTypeName()); - return typeIsList() && !getIndexBasedListAccess() ? ragconnect().defaultBytesToListTreeMapping(typeDecl.getName()) : ragconnect().defaultBytesToTreeMapping(typeDecl.getName()); - } catch (Exception ignore) {} - return super.suitableReceiveDefaultMapping(); - } // --- suitableSendDefaultMapping --- syn DefaultMappingDefinition EndpointDefinition.suitableSendDefaultMapping() { + if (getEndpointTarget().isTypeEndpointTarget()) { + try { + TypeDecl typeDecl = program().resolveTypeDecl(targetTypeName()); + return typeIsList() && !getIndexBasedListAccess() ? ragconnect().defaultListTreeToBytesMapping() : ragconnect().defaultTreeToBytesMapping(typeDecl.getName()); + } catch (Exception ignore) { + } + } switch (targetTypeName()) { case "boolean": - case "Boolean": return ragconnect().defaultBooleanToBytesMapping(); + case "Boolean": + return ragconnect().defaultBooleanToBytesMapping(); case "int": - case "Integer": return ragconnect().defaultIntToBytesMapping(); + case "Integer": + return ragconnect().defaultIntToBytesMapping(); case "short": - case "Short": return ragconnect().defaultShortToBytesMapping(); + case "Short": + return ragconnect().defaultShortToBytesMapping(); case "long": - case "Long": return ragconnect().defaultLongToBytesMapping(); + case "Long": + return ragconnect().defaultLongToBytesMapping(); case "float": - case "Float": return ragconnect().defaultFloatToBytesMapping(); + case "Float": + return ragconnect().defaultFloatToBytesMapping(); case "double": - case "Double": return ragconnect().defaultDoubleToBytesMapping(); + case "Double": + return ragconnect().defaultDoubleToBytesMapping(); case "char": - case "Character": return ragconnect().defaultCharToBytesMapping(); - case "String": return ragconnect().defaultStringToBytesMapping(); + case "Character": + return ragconnect().defaultCharToBytesMapping(); + case "String": + return ragconnect().defaultStringToBytesMapping(); default: try { TypeDecl typeDecl = program().resolveTypeDecl(targetTypeName()); // TODO: also support list-types, if list is last type return ragconnect().defaultTreeToBytesMapping(typeDecl.getName()); - } catch (Exception ignore) {} + } catch (Exception ignore) { + } System.err.println("Could not find suitable default mapping for " + targetTypeName() + " on " + this); return null; } } - eq TypeEndpointDefinition.suitableSendDefaultMapping() { - try { - TypeDecl typeDecl = program().resolveTypeDecl(targetTypeName()); - return typeIsList() && !getIndexBasedListAccess() ? ragconnect().defaultListTreeToBytesMapping() : ragconnect().defaultTreeToBytesMapping(typeDecl.getName()); - } catch (Exception ignore) {} - return super.suitableSendDefaultMapping(); - } // --- targetTypeName --- - syn String EndpointDefinition.targetTypeName(); - eq ReceiveTokenEndpointDefinition.targetTypeName() { - return getMappingList().isEmpty() ? - getToken().effectiveJavaTypeUse().getName() : - getMappingList().get(0).getFromType().prettyPrint(); - } - eq ReceiveTypeEndpointDefinition.targetTypeName() { - return getMappingList().isEmpty() ? - getType().getTypeDecl().getName() : - getMappingList().get(0).getFromType().prettyPrint(); - } - eq SendTokenEndpointDefinition.targetTypeName() { - return getMappingList().isEmpty() ? - getToken().effectiveJavaTypeUse().getName() : - getMappingList().get(getMappingList().size() - 1).getToType().prettyPrint(); - } - eq SendTypeEndpointDefinition.targetTypeName() { - return getMappingList().isEmpty() ? - getType().getTypeDecl().getName() : - getMappingList().get(getMappingList().size() - 1).getToType().prettyPrint(); + syn String EndpointDefinition.targetTypeName() { + if (getMappingList().isEmpty()) { + return getEndpointTarget().targetTypeName(); + } else { + if (getSend()) { + return getMappingList().get(getMappingList().size() - 1).getToType().prettyPrint(); + } else { + return getMappingList().get(0).getFromType().prettyPrint(); + } + } } + syn String EndpointTarget.targetTypeName(); + eq TokenEndpointTarget.targetTypeName() = getToken().effectiveJavaTypeUse().getName(); + eq TypeEndpointTarget.targetTypeName() = getType().getTypeDecl().getName(); -// eq ReceiveFromRestDefinition.suitableDefaultMapping() { -// String typeName = getMappingList().isEmpty() ? -// getToken().getJavaTypeUse().getName() : -// getMappingList().get(0).getFromType().prettyPrint(); -// switch(typeName) { -// case "int": -// case "Integer": return ragconnect().defaultStringToIntMapping(); -// case "short": -// case "Short": return ragconnect().defaultStringToShortMapping(); -// case "long": -// case "Long": return ragconnect().defaultStringToLongMapping(); -// case "float": -// case "Float": return ragconnect().defaultStringToFloatMapping(); -// case "double": -// case "Double": return ragconnect().defaultStringToDoubleMapping(); -// case "char": -// case "Character": return ragconnect().defaultStringToCharMapping(); -// default: return null; -// } -// } -// eq SendToRestDefinition.suitableDefaultMapping() { -// String typeName = getMappingList().isEmpty() ? -// getToken().getJavaTypeUse().getName() : -// getMappingList().get(getMappingList().size() - 1).getFromType().prettyPrint(); -// switch(typeName) { -// case "int": -// case "Integer": return ragconnect().defaultIntToStringMapping(); -// case "short": -// case "Short": return ragconnect().defaultShortToStringMapping(); -// case "long": -// case "Long": return ragconnect().defaultLongToStringMapping(); -// case "float": -// case "Float": return ragconnect().defaultFloatToStringMapping(); -// case "double": -// case "Double": return ragconnect().defaultDoubleToStringMapping(); -// case "char": -// case "Character": return ragconnect().defaultCharToStringMapping(); -// default: return null; -// } -// } + // eq ReceiveFromRestDefinition.suitableDefaultMapping() { + // String typeName = getMappingList().isEmpty() ? + // getToken().getJavaTypeUse().getName() : + // getMappingList().get(0).getFromType().prettyPrint(); + // switch(typeName) { + // case "int": + // case "Integer": return ragconnect().defaultStringToIntMapping(); + // case "short": + // case "Short": return ragconnect().defaultStringToShortMapping(); + // case "long": + // case "Long": return ragconnect().defaultStringToLongMapping(); + // case "float": + // case "Float": return ragconnect().defaultStringToFloatMapping(); + // case "double": + // case "Double": return ragconnect().defaultStringToDoubleMapping(); + // case "char": + // case "Character": return ragconnect().defaultStringToCharMapping(); + // default: return null; + // } + // } + // eq SendToRestDefinition.suitableDefaultMapping() { + // String typeName = getMappingList().isEmpty() ? + // getToken().getJavaTypeUse().getName() : + // getMappingList().get(getMappingList().size() - 1).getFromType().prettyPrint(); + // switch(typeName) { + // case "int": + // case "Integer": return ragconnect().defaultIntToStringMapping(); + // case "short": + // case "Short": return ragconnect().defaultShortToStringMapping(); + // case "long": + // case "Long": return ragconnect().defaultLongToStringMapping(); + // case "float": + // case "Float": return ragconnect().defaultFloatToStringMapping(); + // case "double": + // case "Double": return ragconnect().defaultDoubleToStringMapping(); + // case "char": + // case "Character": return ragconnect().defaultCharToStringMapping(); + // default: return null; + // } + // } // --- isByteArray --- syn boolean MappingDefinitionType.isByteArray() = false; eq JavaArrayMappingDefinitionType.isByteArray() = getType().getName().equals("byte"); -// // --- isString --- -// syn boolean MappingDefinitionType.isString() = false; -// eq JavaMappingDefinitionType.isString() = getType().getName().equals("String"); + // // --- isString --- + // syn boolean MappingDefinitionType.isString() = false; + // eq JavaMappingDefinitionType.isString() = getType().getName().equals("String"); // --- allMappingDefinitions --- syn java.util.List<MappingDefinition> RagConnect.allMappingDefinitions() { java.util.List<MappingDefinition> result = new java.util.ArrayList<>(); // user-defined mappings - allMappingDefinitionList().iterator().forEachRemaining(result::add); + givenMappingDefinitionList().iterator().forEachRemaining(result::add); // byte[] <-> primitive conversion result.add(defaultBytesToBooleanMapping()); result.add(defaultBytesToIntMapping()); diff --git a/ragconnect.base/src/main/jastadd/NameResolution.jrag b/ragconnect.base/src/main/jastadd/NameResolution.jrag index 80525b590d886af4db3c0dd1916a73d356df2244..9b37ee7f93ea9f31414f61a3a70b01a1ba5ca489 100644 --- a/ragconnect.base/src/main/jastadd/NameResolution.jrag +++ b/ragconnect.base/src/main/jastadd/NameResolution.jrag @@ -1,4 +1,42 @@ aspect RagConnectNameResolution { + // --- lookupTokenEndpointDefinition --- + inh java.util.List<EndpointDefinition> EndpointDefinition.lookupTokenEndpointDefinitions(TokenComponent token); + inh java.util.List<EndpointDefinition> EndpointTarget.lookupTokenEndpointDefinitions(TokenComponent token); + eq RagConnect.getConnectSpecificationFile().lookupTokenEndpointDefinitions(TokenComponent token) = lookupTokenEndpointDefinitions(token); + syn java.util.List<EndpointDefinition> RagConnect.lookupTokenEndpointDefinitions(TokenComponent token) { + java.util.List<EndpointDefinition> result = new java.util.ArrayList<>(); + for (EndpointTarget target : allEndpointTargetList()) { + if (target.isTokenEndpointTarget() && target.asTokenEndpointTarget().getToken().equals(token)) { + result.add(target.containingEndpointDefinition()); + } + } + return result; + } + + // --- lookupTypeEndpointDefinition --- + inh java.util.List<EndpointDefinition> EndpointDefinition.lookupTypeEndpointDefinitions(TypeComponent type); + inh java.util.List<EndpointDefinition> EndpointTarget.lookupTypeEndpointDefinitions(TypeComponent type); + eq RagConnect.getConnectSpecificationFile().lookupTypeEndpointDefinitions(TypeComponent type) = lookupTypeEndpointDefinitions(type); + syn java.util.List<EndpointDefinition> RagConnect.lookupTypeEndpointDefinitions(TypeComponent type) { + java.util.List<EndpointDefinition> result = new java.util.ArrayList<>(); + for (EndpointTarget target : allEndpointTargetList()) { + if (target.isTypeEndpointTarget() && target.asTypeEndpointTarget().getType().equals(type)) { + result.add(target.containingEndpointDefinition()); + } + } + return result; + } + + // --- lookupDependencyDefinition --- + inh DependencyDefinition DependencyDefinition.lookupDependencyDefinition(TypeDecl source, String id); + eq RagConnect.getConnectSpecificationFile().lookupDependencyDefinition(TypeDecl source, String id) { + for (DependencyDefinition def : allDependencyDefinitionList()) { + if (def.getID().equals(id) && def.getSource().containingTypeDecl().equals(source)) { + return def; + } + } + return null; + } // rel EndpointDefinition.Mapping* -> MappingDefinition refine RefResolverStubs eq EndpointDefinition.resolveMappingByToken(String id, int position) { @@ -9,7 +47,7 @@ aspect RagConnectNameResolution { return result; } syn MappingDefinition EndpointDefinition.tryResolveMappingByToken(String id) { - for (MappingDefinition mappingDefinition : ragconnect().allMappingDefinitionList()) { + for (MappingDefinition mappingDefinition : ragconnect().givenMappingDefinitionList()) { if (mappingDefinition.getID().equals(id)) { return mappingDefinition; } @@ -64,7 +102,7 @@ aspect RagConnectNameResolution { } // rel ___ -> TokenComponent (from relast-preprocessor) - // refine here to have an attribute without writing on stderr if not found + // refine from relast PP here to have an attribute that does not write on stderr if no TokenComponent was found refine NameResolution eq ASTNode.globallyResolveTokenComponentByToken(String id) { TokenComponent result = tryGloballyResolveTokenComponentByToken(id); if (result == null) { diff --git a/ragconnect.base/src/main/jastadd/Navigation.jrag b/ragconnect.base/src/main/jastadd/Navigation.jrag index 437f65196c2dc3b8c4f5a112a23e80608084a063..7419f3d880b592e28ae4a45b7a9451849b855368 100644 --- a/ragconnect.base/src/main/jastadd/Navigation.jrag +++ b/ragconnect.base/src/main/jastadd/Navigation.jrag @@ -1,25 +1,66 @@ +aspect NewStuff { + + /** Tests if EndpointTarget is a TokenEndpointTarget. + * @return 'true' if this is a TokenEndpointTarget, otherwise 'false' + */ + syn boolean EndpointTarget.isTokenEndpointTarget() = false; + eq TokenEndpointTarget.isTokenEndpointTarget() = true; + + /** Tests if EndpointTarget is a TypeEndpointTarget. + * @return 'true' if this is a TypeEndpointTarget, otherwise 'false' + */ + syn boolean EndpointTarget.isTypeEndpointTarget() = false; + eq TypeEndpointTarget.isTypeEndpointTarget() = true; + + /** Tests if EndpointTarget is a UntypedEndpointTarget. + * @return 'true' if this is a UntypedEndpointTarget, otherwise 'false' + */ + syn boolean EndpointTarget.isUntypedEndpointTarget() = false; + eq UntypedEndpointTarget.isUntypedEndpointTarget() = true; + + /** casts a EndpointTarget into a TokenEndpointTarget if possible. + * @return 'this' cast to a TokenEndpointTarget or 'null' + */ + syn TokenEndpointTarget EndpointTarget.asTokenEndpointTarget(); + eq EndpointTarget.asTokenEndpointTarget() = null; + eq TokenEndpointTarget.asTokenEndpointTarget() = this; + + /** casts a EndpointTarget into a TypeEndpointTarget if possible. + * @return 'this' cast to a TypeEndpointTarget or 'null' + */ + syn TypeEndpointTarget EndpointTarget.asTypeEndpointTarget(); + eq EndpointTarget.asTypeEndpointTarget() = null; + eq TypeEndpointTarget.asTypeEndpointTarget() = this; + + /** casts a EndpointTarget into a UntypedEndpointTarget if possible. + * @return 'this' cast to a UntypedEndpointTarget or 'null' + */ + syn UntypedEndpointTarget EndpointTarget.asUntypedEndpointTarget(); + eq EndpointTarget.asUntypedEndpointTarget() = null; + eq UntypedEndpointTarget.asUntypedEndpointTarget() = this; +} aspect RagConnectNavigation { // --- program --- eq RagConnect.getChild().program() = getProgram(); - eq MRagConnect.getChild().program() = getRagConnect().program(); // --- ragconnect --- inh RagConnect ASTNode.ragconnect(); eq RagConnect.getChild().ragconnect() = this; - eq MRagConnect.getChild().ragconnect() = getRagConnect(); // --- containedConnectSpecification --- inh ConnectSpecification ASTNode.containedConnectSpecification(); eq RagConnect.getChild().containedConnectSpecification() = null; - eq MRagConnect.getChild().containedConnectSpecification() = null; eq Document.getChild().containedConnectSpecification() = null; eq Program.getChild().containedConnectSpecification() = null; eq ConnectSpecification.getChild().containedConnectSpecification() = this; + // --- containingEndpointDefinition --- + inh EndpointDefinition EndpointTarget.containingEndpointDefinition(); + eq EndpointDefinition.getEndpointTarget().containingEndpointDefinition() = this; + // --- containedFile eq RagConnect.getChild().containedFile() = null; - eq MRagConnect.getChild().containedFile() = null; // --- containedFileName --- eq ConnectSpecificationFile.containedFileName() = getFileName(); @@ -31,97 +72,26 @@ aspect RagConnectNavigation { // return containedFile().getFileName(); } - //--- allEndpointDefinitionList --- - syn List<EndpointDefinition> RagConnect.allEndpointDefinitionList() { - List<EndpointDefinition> result = new ArrayList<>(); - for (var spec : getConnectSpecificationFileList()) { - spec.getEndpointDefinitionList().forEach(result::add); - } - return result; - } - //--- allDependencyDefinitionList --- - syn List<DependencyDefinition> RagConnect.allDependencyDefinitionList() { - List<DependencyDefinition> result = new ArrayList<>(); - for (var spec : getConnectSpecificationFileList()) { - spec.getDependencyDefinitionList().forEach(result::add); + //--- allEndpointTargetList --- + syn List<EndpointTarget> RagConnect.allEndpointTargetList() { + List<EndpointTarget> result = new ArrayList<>(); + for (ConnectSpecification spec : getConnectSpecificationFileList()) { + spec.getEndpointDefinitionList().forEach(endpointDef -> result.add(endpointDef.getEndpointTarget())); } return result; } - //--- allMappingDefinitionList --- - syn List<MappingDefinition> RagConnect.allMappingDefinitionList() { + + //--- givenMappingDefinitionList --- + syn List<MappingDefinition> RagConnect.givenMappingDefinitionList() { List<MappingDefinition> result = new ArrayList<>(); - for (var spec : getConnectSpecificationFileList()) { + for (ConnectSpecification spec : getConnectSpecificationFileList()) { spec.getMappingDefinitionList().forEach(result::add); } return result; } - // --- isTokenEndpointDefinition --- - syn boolean EndpointDefinition.isTokenEndpointDefinition() = false; - eq TokenEndpointDefinition.isTokenEndpointDefinition() = true; - - // --- asTokenEndpointDefinition --- - syn TokenEndpointDefinition EndpointDefinition.asTokenEndpointDefinition() = null; - eq TokenEndpointDefinition.asTokenEndpointDefinition() = this; - - // --- isTypeEndpointDefinition --- - syn boolean EndpointDefinition.isTypeEndpointDefinition() = false; - eq TypeEndpointDefinition.isTypeEndpointDefinition() = true; - - // --- asTypeEndpointDefinition --- - syn TypeEndpointDefinition EndpointDefinition.asTypeEndpointDefinition() = null; - eq TypeEndpointDefinition.asTypeEndpointDefinition() = this; - - // --- isReceiveTokenEndpointDefinition --- - syn boolean EndpointDefinition.isReceiveTokenEndpointDefinition() = false; - eq ReceiveTokenEndpointDefinition.isReceiveTokenEndpointDefinition() = true; - - // --- asReceiveTokenEndpointDefinition --- - syn ReceiveTokenEndpointDefinition EndpointDefinition.asReceiveTokenEndpointDefinition() = null; - eq ReceiveTokenEndpointDefinition.asReceiveTokenEndpointDefinition() = this; - - // --- isSendTokenEndpointDefinition --- - syn boolean EndpointDefinition.isSendTokenEndpointDefinition() = false; - eq SendTokenEndpointDefinition.isSendTokenEndpointDefinition() = true; - - // --- asSendTokenEndpointDefinition --- - syn SendTokenEndpointDefinition EndpointDefinition.asSendTokenEndpointDefinition() = null; - eq SendTokenEndpointDefinition.asSendTokenEndpointDefinition() = this; - - // --- isReceiveTypeEndpointDefinition --- - syn boolean EndpointDefinition.isReceiveTypeEndpointDefinition() = false; - eq ReceiveTypeEndpointDefinition.isReceiveTypeEndpointDefinition() = true; - - // --- asReceiveTypeEndpointDefinition --- - syn ReceiveTypeEndpointDefinition EndpointDefinition.asReceiveTypeEndpointDefinition() = null; - eq ReceiveTypeEndpointDefinition.asReceiveTypeEndpointDefinition() = this; - - // --- isSendTypeEndpointDefinition --- - syn boolean EndpointDefinition.isSendTypeEndpointDefinition() = false; - eq SendTypeEndpointDefinition.isSendTypeEndpointDefinition() = true; - - // --- asSendTypeEndpointDefinition --- - syn SendTypeEndpointDefinition EndpointDefinition.asSendTypeEndpointDefinition() = null; - eq SendTypeEndpointDefinition.asSendTypeEndpointDefinition() = this; - - // --- targetEndpointDefinition --- - syn EndpointDefinition DependencyDefinition.targetEndpointDefinition() { - // resolve definition in here, as we do not need resolveMethod in any other place (yet) - for (EndpointDefinition endpointDefinition : ragconnect().allEndpointDefinitionList()) { - if (endpointDefinition.isSendTokenEndpointDefinition() && - endpointDefinition.asSendTokenEndpointDefinition().getToken().equals(this.getTarget())) { - return endpointDefinition; - } - if (endpointDefinition.isSendTypeEndpointDefinition() && - endpointDefinition.asSendTypeEndpointDefinition().getType().equals(this.getTarget())) { - return endpointDefinition; - } - } - return null; - } - // --- effectiveJavaTypeUse (should be in preprocessor) --- syn lazy JavaTypeUse TokenComponent.effectiveJavaTypeUse() = hasJavaTypeUse() ? getJavaTypeUse() : new SimpleJavaTypeUse("String"); @@ -129,13 +99,6 @@ aspect RagConnectNavigation { syn boolean MappingDefinition.isDefaultMappingDefinition() = false; eq DefaultMappingDefinition.isDefaultMappingDefinition() = true; - // --- mragconnect --- - inh MRagConnect MHandler.mragconnect(); - eq MRagConnect.getHandler().mragconnect() = this; - - // --- rootTypeComponents --- - syn JastAddList<MTypeComponent> MHandler.rootTypeComponents() = mragconnect().getRootTypeComponents(); - // --- isListComponent --- (defined in PP, but only on TypeComponent) syn boolean Component.isListComponent() = false; } diff --git a/ragconnect.base/src/main/jastadd/RagConnect.relast b/ragconnect.base/src/main/jastadd/RagConnect.relast index 4301c70e77435e46fb131b093e9009577109d680..30e6d5ad6a034f9b35de570414e8d4e904751ca2 100644 --- a/ragconnect.base/src/main/jastadd/RagConnect.relast +++ b/ragconnect.base/src/main/jastadd/RagConnect.relast @@ -1,35 +1,39 @@ -RagConnect ::= ConnectSpecificationFile* Program ; +RagConnect ::= ConnectSpecificationFile* Program Handler* Configuration; -abstract ConnectSpecification ::= EndpointDefinition* DependencyDefinition* MappingDefinition* ; -ConnectSpecificationFile : ConnectSpecification ::= <FileName> ; - -abstract EndpointDefinition ::= <AlwaysApply:boolean> ; +abstract ConnectSpecification ::= EndpointDefinition* DependencyDefinition* MappingDefinition*; +ConnectSpecificationFile : ConnectSpecification ::= <FileName>; +EndpointDefinition ::= <AlwaysApply:boolean> <IndexBasedListAccess:boolean> <WithAdd:boolean> <Send:boolean> EndpointTarget; rel EndpointDefinition.Mapping* <-> MappingDefinition.UsedAt*; -abstract TokenEndpointDefinition : EndpointDefinition; -rel TokenEndpointDefinition.Token <-> TokenComponent.TokenEndpointDefinition*; - -ReceiveTokenEndpointDefinition : TokenEndpointDefinition; -SendTokenEndpointDefinition : TokenEndpointDefinition; - -abstract TypeEndpointDefinition : EndpointDefinition ::= <IndexBasedListAccess:boolean> ; -rel TypeEndpointDefinition.Type <-> TypeComponent.TypeEndpointDefinition*; - -ReceiveTypeEndpointDefinition : TypeEndpointDefinition ::= <WithAdd:boolean>; -SendTypeEndpointDefinition : TypeEndpointDefinition; +abstract EndpointTarget; +TokenEndpointTarget : EndpointTarget; +rel TokenEndpointTarget.Token <-> TokenComponent.TokenEndpointTarget*; +TypeEndpointTarget : EndpointTarget; +rel TypeEndpointTarget.Type <-> TypeComponent.TypeEndpointTarget*; +UntypedEndpointTarget : EndpointTarget ::= <TokenOrType>; // only used by parser +// to be integrated: +//AttributeEndpointTarget : EndpointTarget ::= <Name> ; +//RelationEndpointTarget : EndpointTarget ; +//rel RelationEndpointTarget.Role <-> Role.RelationEndpointTarget* ; DependencyDefinition ::= <ID>; rel DependencyDefinition.Source <-> TokenComponent.DependencySourceDefinition*; rel DependencyDefinition.Target -> Component; -MappingDefinition ::= <ID> FromType:MappingDefinitionType <FromVariableName> ToType:MappingDefinitionType <Content> ; +MappingDefinition ::= <ID> FromType:MappingDefinitionType <FromVariableName> ToType:MappingDefinitionType <Content>; abstract MappingDefinitionType ::= ; -JavaMappingDefinitionType : MappingDefinitionType ::= Type:JavaTypeUse ; -JavaArrayMappingDefinitionType : MappingDefinitionType ::= Type:JavaTypeUse ; -DefaultMappingDefinition : MappingDefinition ; - -// only used by parser -abstract UntypedEndpointDefinition : EndpointDefinition ::= <TokenOrType> <Indexed:boolean> <WithAdd:boolean> ; -ReceiveUntypedEndpointDefinition : UntypedEndpointDefinition; -SendUntypedEndpointDefinition : UntypedEndpointDefinition; +JavaMappingDefinitionType : MappingDefinitionType ::= Type:JavaTypeUse; +JavaArrayMappingDefinitionType : MappingDefinitionType ::= Type:JavaTypeUse; +DefaultMappingDefinition : MappingDefinition; + +Handler ::= <DefinitionFileName> <ClassName> <UniqueName> <InUse:boolean>; + +Configuration ::= +<LoggingEnabledForReads:boolean> +<LoggingEnabledForWrites:boolean> +<LoggingEnabledForIncremental:boolean> +<JastAddList:String> +<IncrementalOptionActive:boolean> +<ExperimentalJastAdd329:boolean>; +rel Configuration.RootNode -> TypeDecl ; diff --git a/ragconnect.base/src/main/jastadd/Util.jadd b/ragconnect.base/src/main/jastadd/Util.jadd index 3b59b13c53a8d0e1ca2a05feba43294797a4577e..81b820c0b4610e17f82aa31f97c44c97405443e0 100644 --- a/ragconnect.base/src/main/jastadd/Util.jadd +++ b/ragconnect.base/src/main/jastadd/Util.jadd @@ -2,4 +2,6 @@ aspect Util { static String ASTNode.capitalize(String s) { return Character.toUpperCase(s.charAt(0)) + s.substring(1); } + protected T JastAddList.firstChild() { return getChild(0); } + protected T JastAddList.lastChild() { return getChild(getNumChild() - 1); } } diff --git a/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd b/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd deleted file mode 100644 index f4045d7aab8c587970e9645f3cb13e36cb617db4..0000000000000000000000000000000000000000 --- a/ragconnect.base/src/main/jastadd/intermediate/Generation.jadd +++ /dev/null @@ -1,428 +0,0 @@ -/* -Design considerations -- InnerMappingDefinition needed for iteration attribute (first, last) - not easily possible with list-relation -*/ - -aspect AttributesForMustache { - // --- EndpointDefinition --- - syn String EndpointDefinition.idTokenName() = "InternalRagconnectTopicInList"; - - // --- MRagConnect --- - eq MRagConnect.getRootTypeComponent(int i).isFirst() = i == 0; - - syn String MRagConnect.closeMethod() = "ragconnectCloseConnections"; - syn String MRagConnect.mqttHandlerAttribute() = "_mqttHandler"; - syn String MRagConnect.mqttHandlerField() = "_mqttHandler"; - syn String MRagConnect.mqttSetupWaitUntilReadyMethod() = "ragconnectSetupMqttWaitUntilReady"; - - syn String MRagConnect.restHandlerAttribute() = "_restHandler"; - syn String MRagConnect.restHandlerField() = "_restHandler"; - - syn boolean MRagConnect.hasTreeListEndpoints() = !sendingTreeListEndpoints().isEmpty() || !receivingTreeListEndpoints().isEmpty(); - syn List<MTypeEndpointDefinition> MRagConnect.sendingTreeListEndpoints() { - List<MTypeEndpointDefinition> result = new ArrayList<>(); - for (var mEndpointDef : getTypeSendDefinitionList()) { - if (mEndpointDef.typeIsList()) { - result.add(mEndpointDef); - } - } - return result; - } - syn List<MTypeEndpointDefinition> MRagConnect.receivingTreeListEndpoints() { - List<MTypeEndpointDefinition> result = new ArrayList<>(); - for (var mEndpointDef : getTypeReceiveDefinitionList()) { - if (mEndpointDef.typeIsList()) { - result.add(mEndpointDef); - } - } - return result; - } - syn List<TypeDecl> MRagConnect.typesForReceivingListEndpoints() { - return receivingTreeListEndpoints().stream() - .map(mEndpointDef -> mEndpointDef.type().getTypeDecl()) - .distinct() - .collect(java.util.stream.Collectors.toList()); - } - - // --- MEndpointDefinition --- - syn String MEndpointDefinition.preemptiveExpectedValue(); - syn String MEndpointDefinition.preemptiveReturn(); - syn EndpointDefinition MEndpointDefinition.endpointDef(); - syn String MEndpointDefinition.firstInputVarName(); - syn String MEndpointDefinition.parentTypeName(); - syn String MEndpointDefinition.entityName(); - syn String MEndpointDefinition.updateMethod(); - syn String MEndpointDefinition.writeMethod(); - syn String MEndpointDefinition.getterMethod(); - - eq MEndpointDefinition.getInnerMappingDefinition(int i).isLast() = i == getNumInnerMappingDefinition() - 1; - eq MEndpointDefinition.getInnerMappingDefinition(int i).inputVarName() = i == 0 ? firstInputVarName() : getInnerMappingDefinition(i - 1).outputVarName(); - - syn String MEndpointDefinition.connectParameterName() = "uriString"; - syn String MEndpointDefinition.connectMethod() = "connect" + entityName(); - syn String MEndpointDefinition.internalConnectMethod() = "_internal_" + connectMethod(); - syn boolean MEndpointDefinition.isTypeEndpointDefinition() = endpointDef().isTypeEndpointDefinition(); - - syn String MEndpointDefinition.disconnectMethod() { - // if both (send and receive) are defined for an endpoint, ensure methods with different names - String extra; - if (endpointDef().isTokenEndpointDefinition()) { - extra = endpointDef().asTokenEndpointDefinition().lookupTokenEndpointDefinitions(token()).size() > 1 ? uniqueSuffix() : ""; - } else if (endpointDef().isTypeEndpointDefinition()) { - extra = endpointDef().asTypeEndpointDefinition().lookupTypeEndpointDefinitions(type()).size() > 1 ? uniqueSuffix() : ""; - } else { - extra = ""; - } - return "disconnect" + extra + entityName(); - } - - syn String MEndpointDefinition.uniqueSuffix(); - eq MTokenSendDefinition.uniqueSuffix() = "Send"; - eq MTokenReceiveDefinition.uniqueSuffix() = "Receive"; - eq MTypeSendDefinition.uniqueSuffix() = "Send"; - eq MTypeReceiveDefinition.uniqueSuffix() = "Receive"; - - // TODO potentially dangerous because asXEndpointDefinition can return null - syn TokenComponent MEndpointDefinition.token() = endpointDef().asTokenEndpointDefinition().getToken(); - syn TypeComponent MEndpointDefinition.type() = endpointDef().asTypeEndpointDefinition().getType(); - syn boolean MEndpointDefinition.alwaysApply() = endpointDef().getAlwaysApply(); - syn boolean MEndpointDefinition.typeIsList() = endpointDef().typeIsList(); - syn String MEndpointDefinition.tokenName() = token().getName(); - syn String MEndpointDefinition.typeName() = type().getName(); - syn String MEndpointDefinition.typeDeclName() = type().getTypeDecl().getName(); - syn MInnerMappingDefinition MEndpointDefinition.lastDefinition() = getInnerMappingDefinition(getNumInnerMappingDefinition() - 1); - syn String MEndpointDefinition.lastDefinitionToType() = lastDefinition().toType(); - syn String MEndpointDefinition.lastResult() = lastDefinition().outputVarName(); - syn String MEndpointDefinition.condition() { - // TODO probably, this has to be structured in a better way - if (lastDefinition().mappingDef().getToType().isArray()) { - return "java.util.Arrays.equals(" + preemptiveExpectedValue() + ", " + lastResult() + ")"; - } - if (endpointDef().isTokenEndpointDefinition() && token().isPrimitiveType() && lastDefinition().mappingDef().getToType().isPrimitiveType()) { - return preemptiveExpectedValue() + " == " + lastResult(); - } - if (endpointDef().isReceiveTypeEndpointDefinition() && endpointDef().asReceiveTypeEndpointDefinition().getWithAdd()) { - // only check if received list is not null - return lastResult() + " == null"; - } - if (endpointDef().isTypeEndpointDefinition() && type().isOptComponent()) { - // use "hasX()" instead of "getX() != null" for optionals - return "has" + typeName() + "()" + " && " + preemptiveExpectedValue() + ".equals(" + lastResult() + ")"; - } - if (lastDefinition().mappingDef().getToType().isPrimitiveType() || lastDefinition().mappingDef().isDefaultMappingDefinition()) { - return preemptiveExpectedValue() + " != null && " + preemptiveExpectedValue() + ".equals(" + lastResult() + ")"; - } - return preemptiveExpectedValue() + " != null ? " + preemptiveExpectedValue() + ".equals(" + lastResult() + ") : " + lastResult() + " == null"; - } - syn String MEndpointDefinition.sender() = null; // only for M*SendDefinitions - syn String MEndpointDefinition.lastValue() = sender() + ".lastValue"; // only for M*SendDefinitions - - // --- MTokenEndpointDefinition --- - eq MTokenEndpointDefinition.getterMethod() = "get" + tokenName(); - eq MTokenEndpointDefinition.parentTypeName() = token().containingTypeDecl().getName(); - eq MTokenEndpointDefinition.entityName() = tokenName(); - - // --- MTypeEndpointDefinition --- - syn boolean MTypeEndpointDefinition.isWithAdd() = endpointDef().isReceiveTypeEndpointDefinition() ? endpointDef().asReceiveTypeEndpointDefinition().getWithAdd() : false; - syn boolean MTypeEndpointDefinition.isIndexBasedListAccess() = endpointDef().asTypeEndpointDefinition().getIndexBasedListAccess(); - eq MTypeEndpointDefinition.getterMethod() = "get" + typeName() + (typeIsList() ? "List" : ""); - eq MTypeEndpointDefinition.parentTypeName() = type().containingTypeDecl().getName(); - eq MTypeEndpointDefinition.entityName() = typeName() + (typeIsList() && !isIndexBasedListAccess() ? "List" : ""); - - // --- MInnerMappingDefinition --- - inh boolean MInnerMappingDefinition.isLast(); - inh String MInnerMappingDefinition.inputVarName(); - syn String MInnerMappingDefinition.toType() = mappingDef().getToType().prettyPrint(); - syn String MInnerMappingDefinition.methodName() = getMMappingDefinition().methodName(); - syn MappingDefinition MInnerMappingDefinition.mappingDef() = getMMappingDefinition().getMappingDefinition(); - syn String MInnerMappingDefinition.outputVarName() = "result" + methodName(); // we do not need "_" in between here, because methodName begins with one - - // --- MTokenReceiveDefinition --- - eq MTokenReceiveDefinition.preemptiveExpectedValue() = getterMethod() + "()"; - eq MTokenReceiveDefinition.preemptiveReturn() = "return;"; - eq MTokenReceiveDefinition.endpointDef() = getReceiveTokenEndpointDefinition(); - eq MTokenReceiveDefinition.firstInputVarName() = "message"; - eq MTokenReceiveDefinition.updateMethod() = null; - eq MTokenReceiveDefinition.writeMethod() = null; - - // --- MTokenSendDefinition --- - eq MTokenSendDefinition.preemptiveExpectedValue() = lastValue(); - eq MTokenSendDefinition.preemptiveReturn() = "return false;"; - eq MTokenSendDefinition.endpointDef() = getSendTokenEndpointDefinition(); - eq MTokenSendDefinition.firstInputVarName() = getterMethod() + "()"; - eq MTokenSendDefinition.updateMethod() = "_update_" + tokenName(); - eq MTokenSendDefinition.writeMethod() = "_writeLastValue_" + tokenName(); - - eq MTokenSendDefinition.sender() = "_sender_" + tokenName(); - syn String MTokenSendDefinition.tokenResetMethod() = getterMethod() + "_reset"; - syn boolean MTokenSendDefinition.shouldSendValue() = endpointDef().asTokenEndpointDefinition().shouldSendValue(); - - // MTypeReceiveDefinition - eq MTypeReceiveDefinition.preemptiveExpectedValue() = getterMethod() + "()"; - eq MTypeReceiveDefinition.preemptiveReturn() = "return;"; - eq MTypeReceiveDefinition.endpointDef() = getReceiveTypeEndpointDefinition(); - eq MTypeReceiveDefinition.firstInputVarName() = "message"; - eq MTypeReceiveDefinition.updateMethod() = null; - eq MTypeReceiveDefinition.writeMethod() = null; - - syn String MTypeReceiveDefinition.resolveInListMethodName() = "_ragconnect_resolve" + entityName() + "InList"; - syn String MTypeReceiveDefinition.idTokenName() = endpointDef().idTokenName(); - - // MTypeSendDefinition - eq MTypeSendDefinition.preemptiveExpectedValue() = lastValue(); - eq MTypeSendDefinition.preemptiveReturn() = "return false;"; - eq MTypeSendDefinition.endpointDef() = getSendTypeEndpointDefinition(); - eq MTypeSendDefinition.firstInputVarName() = getterMethod() + "()"; - eq MTypeSendDefinition.updateMethod() = "_update_" + typeName(); - eq MTypeSendDefinition.writeMethod() = "_writeLastValue_" + typeName(); - - eq MTypeSendDefinition.sender() = "_sender_" + typeName(); - syn String MTypeSendDefinition.tokenResetMethod() = getterMethod() + "_reset"; - syn boolean MTypeSendDefinition.shouldSendValue() = endpointDef().asTypeEndpointDefinition().shouldSendValue(); - - // --- MMappingDefinition --- - syn String MMappingDefinition.toType() = getMappingDefinition().getToType().prettyPrint(); - syn String MMappingDefinition.methodName() = "_apply_" + getMappingDefinition().getID(); - syn String MMappingDefinition.fromType() = getMappingDefinition().getFromType().prettyPrint(); - syn String MMappingDefinition.fromVariableName() = getMappingDefinition().getFromVariableName(); - syn String MMappingDefinition.content() = getMappingDefinition().getContent(); - syn boolean MMappingDefinition.isUsed() = !getMappingDefinition().effectiveUsedAt().isEmpty(); - - // --- MDependencyDefinition --- - syn String MDependencyDefinition.targetParentTypeName() = getDependencyDefinition().getTarget().containingTypeDecl().getName(); - syn String MDependencyDefinition.dependencyMethod() = "add" + capitalize(getDependencyDefinition().getID()); - syn String MDependencyDefinition.sourceParentTypeName() = getDependencyDefinition().getSource().containingTypeDecl().getName(); - syn String MDependencyDefinition.internalRelationPrefix() = "_internal_" + getDependencyDefinition().getID(); - syn nta MEndpointDefinition MDependencyDefinition.targetEndpointDefinition() { - return getDependencyDefinition().targetEndpointDefinition().toMustache(); - } - - // --- MTypeComponent --- - syn String MTypeComponent.name() = getTypeComponent().getName(); - inh boolean MTypeComponent.isFirst(); - - // --- MTokenComponent --- - syn String MTokenComponent.parentTypeName() = getTokenComponent().containingTypeDecl().getName(); - syn String MTokenComponent.name() = getTokenComponent().getName(); - syn String MTokenComponent.javaType() = getTokenComponent().effectiveJavaTypeUse().prettyPrint(); - syn String MTokenComponent.internalName() = getTokenComponent().needProxyToken() ? "_internal_" + name() : externalName(); - syn String MTokenComponent.externalName() = name(); - syn MTokenSendDefinition MTokenComponent.normalTokenSendDef() { - for (TokenEndpointDefinition endpointDef : getTokenComponent().getTokenEndpointDefinitionList()) { - if (endpointDef.shouldSendValue()) { - return endpointDef.asSendTokenEndpointDefinition().toMustache(); - } - } - return null; - } - - // --- toMustache --- - syn lazy MRagConnect RagConnect.toMustache() { - MRagConnect result = new MRagConnect(); - result.setRagConnect(this); - for (EndpointDefinition def : allEndpointDefinitionList()) { - if (def.isReceiveTokenEndpointDefinition()) { - result.addTokenReceiveDefinition(def.asReceiveTokenEndpointDefinition().toMustache()); - } else if (def.isSendTokenEndpointDefinition()) { - result.addTokenSendDefinition(def.asSendTokenEndpointDefinition().toMustache()); - } else if (def.isReceiveTypeEndpointDefinition()) { - result.addTypeReceiveDefinition(def.asReceiveTypeEndpointDefinition().toMustache()); - } else if (def.isSendTypeEndpointDefinition()) { - result.addTypeSendDefinition(def.asSendTypeEndpointDefinition().toMustache()); - } else { - throw new RuntimeException("Unknown endpoint definition: " + def); - } - } - for (MappingDefinition def : allMappingDefinitions()) { - result.addMappingDefinition(def.toMustache()); - } - for (DependencyDefinition def : allDependencyDefinitionList()) { - result.addDependencyDefinition(def.toMustache()); - } - for (TokenComponent token : getProgram().allTokenComponents()) { - if (token.needProxyToken()) { - result.addTokenComponent(token.toMustache()); - } - } - for (Component child : rootNode.getComponentList()) { - if (child.isTypeComponent()) { - result.addRootTypeComponent(child.asTypeComponent().toMustache()); - } - } - // MHandler ::= <ClassName> <Construction> <AttributeName> <FieldName> <InUse:boolean>; - result.addHandler(new MHandler("MqttServerHandler", "new MqttServerHandler(\"RagConnectMQTT\")", - result.mqttHandlerAttribute(), result.mqttHandlerField(), usesMqtt)); - result.addHandler(new MHandler("RestServerHandler", "new RestServerHandler(\"RagConnectREST\")", - result.restHandlerAttribute(), result.restHandlerField(), usesRest)); - return result; - } - - protected void MEndpointDefinition.addInnerMappings() { - for (MappingDefinition def : endpointDef().effectiveMappings()) { - MInnerMappingDefinition inner = new MInnerMappingDefinition(); - inner.setMMappingDefinition(def.toMustache()); - addInnerMappingDefinition(inner); - } - } - - public abstract MEndpointDefinition EndpointDefinition.toMustache(); - syn lazy MTokenReceiveDefinition ReceiveTokenEndpointDefinition.toMustache() { - MTokenReceiveDefinition result = new MTokenReceiveDefinition(); - result.setReceiveTokenEndpointDefinition(this); - result.addInnerMappings(); - return result; - } - - syn lazy MTokenSendDefinition SendTokenEndpointDefinition.toMustache() { - MTokenSendDefinition result = new MTokenSendDefinition(); - result.setSendTokenEndpointDefinition(this); - result.addInnerMappings(); - return result; - } - - syn lazy MTypeReceiveDefinition ReceiveTypeEndpointDefinition.toMustache() { - MTypeReceiveDefinition result = new MTypeReceiveDefinition(); - result.setReceiveTypeEndpointDefinition(this); - result.addInnerMappings(); - return result; - } - - syn lazy MTypeSendDefinition SendTypeEndpointDefinition.toMustache() { - MTypeSendDefinition result = new MTypeSendDefinition(); - result.setSendTypeEndpointDefinition(this); - result.addInnerMappings(); - return result; - } - - syn lazy MMappingDefinition MappingDefinition.toMustache() { - MMappingDefinition result = new MMappingDefinition(); - result.setMappingDefinition(this); - return result; - } - - syn lazy MDependencyDefinition DependencyDefinition.toMustache() { - MDependencyDefinition result = new MDependencyDefinition(); - result.setDependencyDefinition(this); - return result; - } - - syn lazy MTypeComponent TypeComponent.toMustache() { - MTypeComponent result = new MTypeComponent(); - result.setTypeComponent(this); - return result; - } - - syn lazy MTokenComponent TokenComponent.toMustache() { - MTokenComponent result = new MTokenComponent(); - result.setTokenComponent(this); - for (DependencyDefinition def : getDependencySourceDefinitionList()) { - result.addDependencyDefinition(def.toMustache()); - } - return result; - } -} - -aspect AspectGeneration { - // --- rootNodeName --- - syn String ASTNode.rootNodeName() = rootNode.getName(); - - public String RagConnect.generateAspect(String rootNodeName) { - rootNode = getProgram().resolveTypeDecl(rootNodeName); - return toMustache().generateAspect(); - } - - public String MRagConnect.generateAspect() { - StringBuilder sb = new StringBuilder(); - com.github.mustachejava.reflect.ReflectionObjectHandler roh = new com.github.mustachejava.reflect.ReflectionObjectHandler() { - @Override - public com.github.mustachejava.Binding createBinding(String name, final com.github.mustachejava.TemplateContext tc, com.github.mustachejava.Code code) { - return new com.github.mustachejava.reflect.GuardedBinding(this, name, tc, code) { - @Override - protected synchronized com.github.mustachejava.util.Wrapper getWrapper(String name, java.util.List<Object> scopes) { - com.github.mustachejava.util.Wrapper wrapper = super.getWrapper(name, scopes); - if (wrapper instanceof com.github.mustachejava.reflect.MissingWrapper) { - throw new com.github.mustachejava.MustacheException(name + " not found in " + tc); - } - return wrapper; - } - }; - } - }; - com.github.mustachejava.DefaultMustacheFactory mf = new com.github.mustachejava.DefaultMustacheFactory(); - mf.setObjectHandler(roh); - com.github.mustachejava.Mustache m = mf.compile("ragconnect.mustache"); - m.execute(new java.io.PrintWriter(new org.jastadd.ragconnect.compiler.AppendableWriter(sb)), this); - return sb.toString(); - } -} - -aspect GrammarGeneration { - syn java.util.List<Relation> RagConnect.additionalRelations() { - java.util.List<Relation> result = new java.util.ArrayList<>(); - for (DependencyDefinition dd : allDependencyDefinitionList()) { - result.add(dd.getRelationToCreate()); - } - return result; - } - - syn nta Relation DependencyDefinition.getRelationToCreate() { - String internalRelationPrefix = toMustache().internalRelationPrefix(); - BidirectionalRelation result = new BidirectionalRelation(); - NavigableRole left = new ListRole(internalRelationPrefix + "Source"); - left.setType(getTarget().containingTypeDecl()); - NavigableRole right = new ListRole(internalRelationPrefix + "Target"); - right.setType(getSource().containingTypeDecl()); - result.setLeft(left); - result.setRight(right); - result.addComment(new WhitespaceComment("\n")); - return result; - } - -// coll java.util.Map<TypeDecl, TokenComponent> RagConnect.additionalTokens() [new java.util.HashMap<>()] with put root RagConnect; - -// TypeEndpointDefinition contributes getTokenToCreate() -// when typeIsList() && !getUseList() -// to RagConnect.additionalTokens() -//// for ragconnect() -// ; - - syn java.util.Map<TypeDecl, TokenComponent> RagConnect.additionalTokens() { - java.util.Map<TypeDecl, TokenComponent> result = new java.util.HashMap<>(); - for (EndpointDefinition def : allEndpointDefinitionList()) { - if (def.isTypeEndpointDefinition() && def.getTokenToCreate() != null) { - result.put(def.asTypeEndpointDefinition().getType().getTypeDecl(), def.getTokenToCreate()); - } - } - return result; - } - - syn TokenComponent EndpointDefinition.getTokenToCreate() = null; - eq TypeEndpointDefinition.getTokenToCreate() { - if (typeIsList() && getIndexBasedListAccess()) { - TokenComponent result = new TokenComponent(); - result.setName(idTokenName()); - result.setNTA(false); - result.setJavaTypeUse(new SimpleJavaTypeUse("String")); - return result; - } else { - return null; - } - } -} - -aspect GrammarExtension { - refine BackendAbstractGrammar public void TokenComponent.generateAbstractGrammar(StringBuilder b) { - if (getNTA()) { - b.append("/"); - } - b.append("<"); - if (!getName().equals("")) { - b.append(toMustache().internalName()).append(":"); - } - effectiveJavaTypeUse().generateAbstractGrammar(b); - b.append(">"); - if (getNTA()) { - b.append("/"); - } - } -} diff --git a/ragconnect.base/src/main/jastadd/intermediate/MustacheNodes.relast b/ragconnect.base/src/main/jastadd/intermediate/MustacheNodes.relast deleted file mode 100644 index 8255cfe5ad9e67e00e53e95b4ddc110a480dce28..0000000000000000000000000000000000000000 --- a/ragconnect.base/src/main/jastadd/intermediate/MustacheNodes.relast +++ /dev/null @@ -1,28 +0,0 @@ -MRagConnect ::= TokenReceiveDefinition:MTokenReceiveDefinition* TokenSendDefinition:MTokenSendDefinition* TypeReceiveDefinition:MTypeReceiveDefinition* TypeSendDefinition:MTypeSendDefinition* MappingDefinition:MMappingDefinition* DependencyDefinition:MDependencyDefinition* RootTypeComponent:MTypeComponent* TokenComponent:MTokenComponent* Handler:MHandler*; - -abstract MEndpointDefinition ::= InnerMappingDefinition:MInnerMappingDefinition*; -abstract MTokenEndpointDefinition : MEndpointDefinition; -MTokenReceiveDefinition : MTokenEndpointDefinition; -MTokenSendDefinition : MTokenEndpointDefinition; -abstract MTypeEndpointDefinition : MEndpointDefinition; -MTypeReceiveDefinition : MTypeEndpointDefinition; -MTypeSendDefinition : MTypeEndpointDefinition; - -MMappingDefinition; -MInnerMappingDefinition; -MDependencyDefinition; -MTypeComponent; -MTokenComponent; -MHandler ::= <ClassName> <Construction> <AttributeName> <FieldName> <InUse:boolean>; - -rel MRagConnect.RagConnect -> RagConnect; -rel MInnerMappingDefinition.MMappingDefinition -> MMappingDefinition; -rel MTokenReceiveDefinition.ReceiveTokenEndpointDefinition -> ReceiveTokenEndpointDefinition; -rel MTokenSendDefinition.SendTokenEndpointDefinition -> SendTokenEndpointDefinition; -rel MTypeReceiveDefinition.ReceiveTypeEndpointDefinition -> ReceiveTypeEndpointDefinition; -rel MTypeSendDefinition.SendTypeEndpointDefinition -> SendTypeEndpointDefinition; -rel MMappingDefinition.MappingDefinition -> MappingDefinition; -rel MDependencyDefinition.DependencyDefinition -> DependencyDefinition; -rel MTypeComponent.TypeComponent -> TypeComponent; -rel MTokenComponent.TokenComponent -> TokenComponent; -rel MTokenComponent.DependencyDefinition* -> MDependencyDefinition; diff --git a/ragconnect.base/src/main/jastadd/intermediate2mustache/MustacheNodesToYAML.jrag b/ragconnect.base/src/main/jastadd/intermediate2mustache/MustacheNodesToYAML.jrag deleted file mode 100644 index 04b9cf89c248c39740677c88835b56c5325493bf..0000000000000000000000000000000000000000 --- a/ragconnect.base/src/main/jastadd/intermediate2mustache/MustacheNodesToYAML.jrag +++ /dev/null @@ -1,212 +0,0 @@ -aspect MustacheNodesToYAML { - syn Document MRagConnect.toYAML() { - Document doc = new Document(); - MappingElement root = new MappingElement(); - root.put("rootNodeName", rootNodeName()); - root.put("closeMethod", closeMethod()); - root.put("usesMqtt", usesMqtt); - root.put("usesRest", usesRest); - // mqtt - root.put("mqttHandlerField", mqttHandlerField()); - root.put("mqttHandlerAttribute", mqttHandlerAttribute()); - root.put("mqttSetupWaitUntilReadyMethod", mqttSetupWaitUntilReadyMethod()); - - // rootTypeComponents - ListElement rootTypeComponents = new ListElement(); - for (MTypeComponent comp : getRootTypeComponentList()) { - MappingElement inner = new MappingElement(); - inner.put("first", comp.isFirst()); - inner.put("name", comp.name()); - rootTypeComponents.addElement(inner); - } - root.put("RootTypeComponents", rootTypeComponents); - - // rest - root.put("restHandlerField", restHandlerField()); - root.put("restHandlerAttribute", restHandlerAttribute()); - - // TokenReceiveDefinitions - ListElement receiveDefinitions = new ListElement(); - for (MTokenReceiveDefinition def : getTokenReceiveDefinitionList()) { - receiveDefinitions.addElement(def.toYAML()); - } - root.put("TokenReceiveDefinitions", receiveDefinitions); - - // TokenSendDefinitions - ListElement sendDefinitions = new ListElement(); - for (MTokenSendDefinition def : getTokenSendDefinitionList()) { - sendDefinitions.addElement(def.toYAML()); - } - root.put("TokenSendDefinitions", sendDefinitions); - - // TypeReceiveDefinitions - ListElement typeReceiveDefinitions = new ListElement(); - for (MTypeReceiveDefinition def : getTypeReceiveDefinitionList()) { - typeReceiveDefinitions.addElement(def.toYAML()); - } - root.put("TypeReceiveDefinitions", typeReceiveDefinitions); - - // TypeSendDefinitions - ListElement typeSendDefinitions = new ListElement(); - for (MTypeSendDefinition def : getTypeSendDefinitionList()) { - typeSendDefinitions.addElement(def.toYAML()); - } - root.put("TypeSendDefinitions", typeSendDefinitions); - - // MappingDefinitions - ListElement mappingDefinitions = new ListElement(); - for (MMappingDefinition def : getMappingDefinitionList()) { - mappingDefinitions.addElement(def.toYAML()); - } - root.put("MappingDefinitions", mappingDefinitions); - - // DependencyDefinitions - ListElement dependencyDefinitions = new ListElement(); - for (MDependencyDefinition def : getDependencyDefinitionList()) { - dependencyDefinitions.addElement(def.toYAML()); - } - root.put("DependencyDefinitions", dependencyDefinitions); - - // TokenComponents - ListElement tokenComponents = new ListElement(); - for (MTokenComponent comp : getTokenComponentList()) { - tokenComponents.addElement(comp.toYAML()); - } - root.put("TokenComponents", tokenComponents); - - // Handlers - ListElement handlers = new ListElement(); - for (MHandler handler : getHandlerList()) { - handlers.add(handler.toYAML() - .put("rootTokenComponents", rootTypeComponents.treeCopy()) ); - } - root.put("Handlers", handlers); - - doc.setRootElement(root); - return doc; - } - - syn MappingElement MEndpointDefinition.toYAML() { - MappingElement result = new MappingElement(); - result.put("parentTypeName", parentTypeName()); - result.put("connectMethod", connectMethod()); - result.put("connectParameterName", connectParameterName()); - result.put("lastDefinitionToType", lastDefinitionToType()); - result.put("preemptiveReturn", preemptiveReturn()); - result.put("alwaysApply", alwaysApply()); - result.put("condition", - condition().replace("\"", "\\\"").replace("\n", "\\n")); - result.put("lastResult", lastResult()); - result.put("tokenName", tokenName()); - result.put("InnerMappingDefinitions", innerMappingDefinitionsAsListElement()); - return result; - } - - syn MappingElement MTokenReceiveDefinition.toYAML() { - MappingElement result = super.toYAML(); - result.put("loggingEnabledForReads", loggingEnabledForReads); - return result; - } - - syn MappingElement MTokenSendDefinition.toYAML() { - MappingElement result = super.toYAML(); - result.put("sender", sender()); - result.put("lastValue", lastValue()); - result.put("loggingEnabledForWrites", loggingEnabledForWrites); - result.put("updateMethod", updateMethod()); - result.put("writeMethod", writeMethod()); - result.put("tokenResetMethod", tokenResetMethod()); - return result; - } - - syn MappingElement MTypeReceiveDefinition.toYAML() { - MappingElement result = super.toYAML(); - result.put("typeIsList", typeIsList()); - result.put("loggingEnabledForReads", loggingEnabledForReads); - return result; - } - - syn MappingElement MTypeSendDefinition.toYAML() { - MappingElement result = super.toYAML(); - result.put("typeIsList", typeIsList()); - result.put("sender", sender()); - result.put("lastValue", lastValue()); - result.put("loggingEnabledForWrites", loggingEnabledForWrites); - result.put("updateMethod", updateMethod()); - result.put("writeMethod", writeMethod()); - result.put("tokenResetMethod", tokenResetMethod()); - return result; - } - - syn Element MMappingDefinition.toYAML() { - MappingElement result = new MappingElement(); - result.put("toType", toType()); - result.put("methodName", methodName()); - result.put("fromType", fromType()); - result.put("fromVariableName", fromVariableName()); - result.put("content", - content().replace("\"", "\\\"").replace("\n", "\\n")); - return result; - } - - syn Element MDependencyDefinition.toYAML() { - MappingElement result = new MappingElement(); - result.put("targetParentTypeName", targetParentTypeName()); - result.put("dependencyMethod", dependencyMethod()); - result.put("sourceParentTypeName", sourceParentTypeName()); - result.put("internalRelationPrefix", internalRelationPrefix()); - return result; - } - - syn Element MTokenComponent.toYAML() { - MappingElement result = new MappingElement(); - result.put("parentTypeName", parentTypeName()); - result.put("name", name()); - result.put("javaType", javaType()); - result.put("internalName", internalName()); - ListElement dependencyDefinitions = new ListElement(); - for (MDependencyDefinition def : getDependencyDefinitionList()) { - MappingElement inner = new MappingElement(); - inner.put("targetParentTypeName", def.targetParentTypeName()); - inner.put("internalRelationPrefix", def.internalRelationPrefix()); - MappingElement targetEndpointDefinition = new MappingElement(); - targetEndpointDefinition.put("updateMethod", def.targetEndpointDefinition().updateMethod()); - targetEndpointDefinition.put("writeMethod", def.targetEndpointDefinition().writeMethod()); - inner.put("targetEndpointDefinition", targetEndpointDefinition); - dependencyDefinitions.addElement(inner); - } - result.put("DependencyDefinitions", dependencyDefinitions); - return result; - } - - ListElement MEndpointDefinition.innerMappingDefinitionsAsListElement() { - ListElement innerMappingDefinitions = new ListElement(); - for (MInnerMappingDefinition def : getInnerMappingDefinitionList()) { - MappingElement inner = new MappingElement(); - inner.put("toType", def.toType()); - inner.put("methodName", def.methodName()); - inner.put("inputVarName", def.inputVarName()); - inner.put("outputVarName", def.outputVarName()); - inner.put("last", def.isLast()); - innerMappingDefinitions.addElement(inner); - } - return innerMappingDefinitions; - } - - syn MappingElement MHandler.toYAML() { - MappingElement result = new MappingElement(); - result.put("ClassName", getClassName()); - result.put("Construction", getConstruction()); - result.put("AttributeName", getAttributeName()); - result.put("FieldName", getFieldName()); - result.put("InUse", getInUse()); - return result; - } -} - -aspect Navigation { - eq Document.getChild().program() = null; - eq Document.getChild().ragconnect() = null; - eq Document.getChild().containedFile() = null; - eq Document.containedFileName() = getFileName(); -} diff --git a/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag b/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag index faaf35ad579259148d06fc7d2f8975f740f2730b..bbf0c11b7ba08c1f7c172cf8fd31420e7fd74561 100644 --- a/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag +++ b/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag @@ -1,68 +1,24 @@ aspect ParserRewrites { - rewrite SendUntypedEndpointDefinition { + rewrite UntypedEndpointTarget { when (tryGloballyResolveTypeComponentByToken(getTokenOrType()) != null) - to SendTypeEndpointDefinition { - SendTypeEndpointDefinition result = new SendTypeEndpointDefinition(); - result.applyFrom(this); - result.setIndexBasedListAccess(this.getIndexed()); + to TypeEndpointTarget { + TypeEndpointTarget result = new TypeEndpointTarget(); + result.setType(TypeComponent.createRef(this.getTokenOrType())); return result; } - } - - rewrite ReceiveUntypedEndpointDefinition { - when (tryGloballyResolveTypeComponentByToken(getTokenOrType()) != null) - to ReceiveTypeEndpointDefinition { - ReceiveTypeEndpointDefinition result = new ReceiveTypeEndpointDefinition(); - result.applyFrom(this); - result.setWithAdd(this.getWithAdd()); - result.setIndexBasedListAccess(this.getIndexed()); - return result; - } - } - - rewrite SendUntypedEndpointDefinition { - when (tryGloballyResolveTokenComponentByToken(getTokenOrType()) != null) - to SendTokenEndpointDefinition { - SendTokenEndpointDefinition result = new SendTokenEndpointDefinition(); - result.applyFrom(this); - return result; - } - } - - rewrite ReceiveUntypedEndpointDefinition { when (tryGloballyResolveTokenComponentByToken(getTokenOrType()) != null) - to ReceiveTokenEndpointDefinition { - ReceiveTokenEndpointDefinition result = new ReceiveTokenEndpointDefinition(); - result.applyFrom(this); + to TokenEndpointTarget { + TokenEndpointTarget result = new TokenEndpointTarget(); + result.setToken(TokenComponent.createRef(this.getTokenOrType())); return result; } } - protected void TypeEndpointDefinition.applyFrom(UntypedEndpointDefinition def) { - this.setAlwaysApply(def.getAlwaysApply()); - this.setType(TypeComponent.createRef(def.getTokenOrType())); - this.moveMappingsFrom(def); - } - - protected void TokenEndpointDefinition.applyFrom(UntypedEndpointDefinition def) { - this.setAlwaysApply(def.getAlwaysApply()); - this.setToken(TokenComponent.createRef(def.getTokenOrType())); - this.moveMappingsFrom(def); - } - - protected void EndpointDefinition.moveMappingsFrom(UntypedEndpointDefinition def) { - // can safely iterate over list as we get an unmodifyable list - for (MappingDefinition mapping : def.getMappingList().toArray(new MappingDefinition[0])) { - def.removeMapping(mapping); - this.addMapping(mapping); - } - } - - private void UntypedEndpointDefinition.clearMappings() { - } - - eq UntypedEndpointDefinition.targetTypeName() = "<unknown>"; - syn MEndpointDefinition UntypedEndpointDefinition.toMustache() { - throw new RuntimeException("UntypedEndpoint can not be transformed using toMustache!"); - } + eq UntypedEndpointTarget.senderName() = "<untyped.senderName>"; + eq UntypedEndpointTarget.getterMethodName() = "<untyped.getterMethodName>"; + eq UntypedEndpointTarget.parentTypeName() = "<untyped.parentTypeName>"; + eq UntypedEndpointTarget.entityName() = "<untyped.entityName>"; + eq UntypedEndpointTarget.isAlreadyDefined() = false; + eq UntypedEndpointTarget.entityIsNormalAttribute() = false; + eq UntypedEndpointTarget.targetTypeName() = "<untyped.targetTypeName>"; } diff --git a/ragconnect.base/src/main/jastadd/parser/RagConnect.parser b/ragconnect.base/src/main/jastadd/parser/RagConnect.parser index 1088ba51ac2de82cc2baaa7b618b0b05d84da4cb..5ddef630253006a13e64ea84cd4df30dc4b6aa2b 100644 --- a/ragconnect.base/src/main/jastadd/parser/RagConnect.parser +++ b/ragconnect.base/src/main/jastadd/parser/RagConnect.parser @@ -22,10 +22,20 @@ ConnectSpecificationFile connect_specification_file private Iterable<String> makeMappingDefs(ArrayList<?> raw_mapping_defs) { return () -> raw_mapping_defs.stream().map(raw -> ((Symbol) raw).value.toString()).iterator(); } - private TokenEndpointDefinition enableAlwaysApply(TokenEndpointDefinition def) { - def.setAlwaysApply(true); - return def; - } +// private TokenEndpointDefinition enableAlwaysApply(TokenEndpointDefinition def) { +// def.setAlwaysApply(true); +// return def; +// } + private EndpointDefinition createEndpointDefinition( + String type_name, String child_name, boolean send, + boolean indexBasedListAccess, boolean withAdd) { + EndpointDefinition result = new EndpointDefinition(); + result.setSend(send); + result.setIndexBasedListAccess(indexBasedListAccess); + result.setWithAdd(withAdd); + result.setEndpointTarget(new UntypedEndpointTarget(type_name + "." + child_name)); + return result; + } :} ; EndpointDefinition endpoint_definition @@ -45,44 +55,27 @@ EndpointDefinition endpoint_definition EndpointDefinition endpoint_definition_type = SEND ID.type_name DOT ID.child_name {: - SendUntypedEndpointDefinition result = new SendUntypedEndpointDefinition(); - result.setTokenOrType(type_name + "." + child_name); - return result; - :} - | SEND INDEXED ID.type_name DOT ID.child_name - {: - SendUntypedEndpointDefinition result = new SendUntypedEndpointDefinition(); - result.setTokenOrType(type_name + "." + child_name); - result.setIndexed(true); - return result; + return createEndpointDefinition(type_name, child_name, true, false, false); :} +// | SEND INDEXED ID.type_name DOT ID.child_name +// {: +// return createEndpointDefinition(type_name, child_name, true, true, false); +// :} | RECEIVE ID.type_name DOT ID.child_name {: - ReceiveUntypedEndpointDefinition result = new ReceiveUntypedEndpointDefinition(); - result.setTokenOrType(type_name + "." + child_name); - return result; + return createEndpointDefinition(type_name, child_name, false, false, false); :} | RECEIVE INDEXED ID.type_name DOT ID.child_name {: - ReceiveUntypedEndpointDefinition result = new ReceiveUntypedEndpointDefinition(); - result.setTokenOrType(type_name + "." + child_name); - result.setIndexed(true); - return result; + return createEndpointDefinition(type_name, child_name, false, true, false); :} | RECEIVE WITH ADD ID.type_name DOT ID.child_name {: - ReceiveUntypedEndpointDefinition result = new ReceiveUntypedEndpointDefinition(); - result.setTokenOrType(type_name + "." + child_name); - result.setWithAdd(true); - return result; + return createEndpointDefinition(type_name, child_name, false, false, true); :} | RECEIVE INDEXED WITH ADD ID.type_name DOT ID.child_name {: - ReceiveUntypedEndpointDefinition result = new ReceiveUntypedEndpointDefinition(); - result.setTokenOrType(type_name + "." + child_name); - result.setIndexed(true); - result.setWithAdd(true); - return result; + return createEndpointDefinition(type_name, child_name, false, true, true); :} ; diff --git a/ragconnect.base/src/main/jastadd/scanner/Keywords.flex b/ragconnect.base/src/main/jastadd/scanner/Keywords.flex index 11f73da45e957a008b32fbddc050bb619f58f100..8a1eaec1e8d95c0d8786f9f44168d1f060b27cfa 100644 --- a/ragconnect.base/src/main/jastadd/scanner/Keywords.flex +++ b/ragconnect.base/src/main/jastadd/scanner/Keywords.flex @@ -5,8 +5,6 @@ "maps" { return sym(Terminals.MAPS); } "to" { return sym(Terminals.TO); } "as" { return sym(Terminals.AS); } -//"tree" { return sym(Terminals.TREE); } -//"list" { return sym(Terminals.LIST); } "with" { return sym(Terminals.WITH); } "indexed" { return sym(Terminals.INDEXED); } "add" { return sym(Terminals.ADD); } diff --git a/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java b/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java index 915d9f92d49cf3a847f05d0b23393bce1832fc1a..b94e0ddf2f97b18721084ae1c26c4687b53b3a3e 100644 --- a/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java +++ b/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java @@ -20,7 +20,7 @@ import java.util.logging.Logger; public class Compiler extends AbstractCompiler { -// private ValueOption optionOutputDir; + // private ValueOption optionOutputDir; private ValueOption optionRootNode; private ValueOption optionProtocols; private BooleanOption optionPrintYaml; @@ -68,6 +68,7 @@ public class Compiler extends AbstractCompiler { } RagConnect ragConnect = parseProgram(getConfiguration().getFiles()); + setConfiguration(ragConnect); if (!ragConnect.errors().isEmpty()) { StringBuilder sb = new StringBuilder("Errors:\n"); @@ -79,23 +80,19 @@ public class Compiler extends AbstractCompiler { } if (optionPrintYaml.value()) { - ASTNode.rootNode = ragConnect.getProgram().resolveTypeDecl(optionRootNode.value()); - String yamlContent = ragConnect.toMustache().toYAML().prettyPrint(); - System.out.println(yamlContent); + String yamlContent = ragConnect.toYAML().prettyPrint(); + LOGGER.fine(yamlContent); writeToFile(getConfiguration().outputDir().toPath().resolve("RagConnect.yml"), yamlContent); return 0; } LOGGER.fine("Writing output files"); - final List<String> handlers = new ArrayList<>(); - if (ASTNode.usesMqtt) { - handlers.add("MqttHandler.jadd"); - } - if (ASTNode.usesRest) { - handlers.add("RestHandler.jadd"); - } // copy handlers into outputDir - for (String handlerFileName : handlers) { + for (Handler handler : ragConnect.getHandlerList()) { + if (!handler.getInUse()) { + continue; + } + String handlerFileName = handler.getDefinitionFileName(); try { InputStream inputStream = Compiler.class.getClassLoader().getResourceAsStream(handlerFileName); if (inputStream == null) { @@ -112,7 +109,8 @@ public class Compiler extends AbstractCompiler { Path outputFile = getConfiguration().outputDir().toPath().resolve(grammarFile.getFileName()); writeToFile(outputFile, grammarFile.generateAbstractGrammar()); } - writeToFile(getConfiguration().outputDir().toPath().resolve("RagConnect.jadd"), ragConnect.generateAspect(optionRootNode.value())); + writeToFile(getConfiguration().outputDir().toPath().resolve("RagConnect.jadd"), + generateAspect(ragConnect)); return 0; } @@ -128,14 +126,14 @@ public class Compiler extends AbstractCompiler { /** * Reads the version string. - * + * <p> * The version string is read from the property file * src/main/resources/Version.properties. This * file should be generated during the build process. If it is missing * then there is some problem in the build script. * - * @author Jesper Öqvist <jesper.oqvist@cs.lth.se> * @return the read version string, or <code>version ?</code> + * @author Jesper Öqvist <jesper.oqvist@cs.lth.se> */ private String readVersion() { try { @@ -158,26 +156,26 @@ public class Compiler extends AbstractCompiler { super.initOptions(); optionRootNode = addOption( new ValueOption("rootNode", "root node in the base grammar.") - .acceptAnyValue() - .needsValue(true)); + .acceptAnyValue() + .needsValue(true)); optionProtocols = addOption( new ValueOption("protocols", "Protocols to enable") - .acceptMultipleValues(true) - .addDefaultValue(OPTION_PROTOCOL_MQTT, "Enable MQTT") - .addAcceptedValue(OPTION_PROTOCOL_REST, "Enable REST") + .acceptMultipleValues(true) + .addDefaultValue(OPTION_PROTOCOL_MQTT, "Enable MQTT") + .addAcceptedValue(OPTION_PROTOCOL_REST, "Enable REST") ); optionPrintYaml = addOption( - new BooleanOption("printYaml", "Print out YAML instead of generating files") - .defaultValue(false)); + new BooleanOption("printYaml", "Print out YAML instead of generating files and exit.") + .defaultValue(false)); optionVerbose = addOption( new BooleanOption("verbose", "Print more messages while compiling.") - .defaultValue(false)); + .defaultValue(false)); optionLogReads = addOption( new BooleanOption("logReads", "Enable logging for every read.") - .defaultValue(false)); + .defaultValue(false)); optionLogWrites = addOption( new BooleanOption("logWrites", "Enable logging for every write.") - .defaultValue(false)); + .defaultValue(false)); optionLogIncremental = addOption( new BooleanOption("logIncremental", "Enable logging for observer in incremental dependency tracking.") .defaultValue(false)); @@ -233,20 +231,7 @@ public class Compiler extends AbstractCompiler { ragConnect.additionalRelations().forEach(ragConnectGrammarPart::addDeclaration); ragConnect.additionalTokens().forEach(TypeDecl::addComponent); - ASTNode.loggingEnabledForReads = optionLogReads.value(); - ASTNode.loggingEnabledForWrites = optionLogWrites.value(); - ASTNode.loggingEnabledForIncremental = optionLogIncremental.value(); - ASTNode.experimentalJastAdd329 = optionExperimentalJastAdd329.value(); - - // reuse "--incremental" option of JastAdd - ASTNode.incrementalOptionActive = getConfiguration().incremental() && getConfiguration().traceFlush(); - LOGGER.fine(() -> "ASTNode.incrementalOptionActive = " + ASTNode.incrementalOptionActive); - // reuse "--List" option of JastAdd - ASTNode.JastAddList = getConfiguration().listType(); - - ASTNode.usesMqtt = optionProtocols.hasValue(OPTION_PROTOCOL_MQTT); - ASTNode.usesRest = optionProtocols.hasValue(OPTION_PROTOCOL_REST); return ragConnect; } @@ -279,6 +264,7 @@ public class Compiler extends AbstractCompiler { /** * Extracts the basename of the given file, with file extension + * * @param filename the given filename * @return the basename */ @@ -286,9 +272,49 @@ public class Compiler extends AbstractCompiler { return new File(filename).getName(); } -// protected void printUsage() { -// System.out.println("Usage: java -jar ragconnect.jar [--option1] [--option2=value] ... <filename1> <filename2> ... "); -// System.out.println("Options:"); -// System.out.print(commandLine.printOptionHelp()); -// } + private void setConfiguration(RagConnect ragConnect) { + ragConnect.setConfiguration(new Configuration()); + ragConnect.getConfiguration().setLoggingEnabledForReads(optionLogReads.value()); + ragConnect.getConfiguration().setLoggingEnabledForWrites(optionLogWrites.value()); + ragConnect.getConfiguration().setLoggingEnabledForIncremental(optionLogIncremental.value()); + ragConnect.getConfiguration().setExperimentalJastAdd329(optionExperimentalJastAdd329.value()); + + // reuse "--incremental" and "--trace=flush" options of JastAdd + boolean incrementalOptionActive = this.getConfiguration().incremental() && this.getConfiguration().traceFlush(); + ragConnect.getConfiguration().setIncrementalOptionActive(incrementalOptionActive); + LOGGER.fine(() -> "ragConnect.getConfiguration().IncrementalOptionActive = " + incrementalOptionActive); + + // reuse "--List" option of JastAdd + ragConnect.getConfiguration().setJastAddList(this.getConfiguration().listType()); + + ragConnect.getConfiguration().setRootNode(ragConnect.getProgram().resolveTypeDecl(optionRootNode.value())); + + // Handler ::= <ClassName> <UniqueName> <InUse:boolean>; + ragConnect.addHandler(new Handler("MqttHandler.jadd", "MqttServerHandler", "mqtt", optionProtocols.hasValue(OPTION_PROTOCOL_MQTT))); + ragConnect.addHandler(new Handler("RestHandler.jadd", "RestServerHandler", "rest", optionProtocols.hasValue(OPTION_PROTOCOL_REST))); + } + + public String generateAspect(RagConnect ragConnect) { + StringBuilder sb = new StringBuilder(); + com.github.mustachejava.reflect.ReflectionObjectHandler roh = new com.github.mustachejava.reflect.ReflectionObjectHandler() { + @Override + public com.github.mustachejava.Binding createBinding(String name, final com.github.mustachejava.TemplateContext tc, com.github.mustachejava.Code code) { + return new com.github.mustachejava.reflect.GuardedBinding(this, name, tc, code) { + @Override + protected synchronized com.github.mustachejava.util.Wrapper getWrapper(String name, java.util.List<Object> scopes) { + com.github.mustachejava.util.Wrapper wrapper = super.getWrapper(name, scopes); + if (wrapper instanceof com.github.mustachejava.reflect.MissingWrapper) { + throw new com.github.mustachejava.MustacheException(name + " not found in " + tc); + } + return wrapper; + } + }; + } + }; + com.github.mustachejava.DefaultMustacheFactory mf = new com.github.mustachejava.DefaultMustacheFactory(); + mf.setObjectHandler(roh); + com.github.mustachejava.Mustache m = mf.compile("ragconnect.mustache"); + m.execute(new java.io.PrintWriter(new org.jastadd.ragconnect.compiler.AppendableWriter(sb)), ragConnect); + return sb.toString(); + } } diff --git a/ragconnect.base/src/main/resources/ListAspect.mustache b/ragconnect.base/src/main/resources/ListAspect.mustache index 764b5441862c96a010f6d07f86e2c1aad2dec81c..31eaf5ac82a5854956077403e92124c9b6160353 100644 --- a/ragconnect.base/src/main/resources/ListAspect.mustache +++ b/ragconnect.base/src/main/resources/ListAspect.mustache @@ -1,5 +1,5 @@ {{#hasTreeListEndpoints}} -public void {{JastAddList}}.serialize(com.fasterxml.jackson.core.JsonGenerator g) throws SerializationException { +public void {{configJastAddList}}.serialize(com.fasterxml.jackson.core.JsonGenerator g) throws SerializationException { try { g.writeStartArray(); for (T child : this) { @@ -7,13 +7,13 @@ public void {{JastAddList}}.serialize(com.fasterxml.jackson.core.JsonGenerator g } g.writeEndArray(); } catch (java.io.IOException e) { - throw new SerializationException("unable to serialize {{JastAddList}}", e); + throw new SerializationException("unable to serialize {{configJastAddList}}", e); } } {{#typesForReceivingListEndpoints}} -public static {{JastAddList}}<{{Name}}> {{Name}}.deserializeList(com.fasterxml.jackson.databind.node.ArrayNode node) throws DeserializationException { - {{JastAddList}}<{{Name}}> result = new {{JastAddList}}<>(); +public static {{configJastAddList}}<{{Name}}> {{Name}}.deserializeList(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)); diff --git a/ragconnect.base/src/main/resources/MqttHandler.jadd b/ragconnect.base/src/main/resources/MqttHandler.jadd index d859d38d819c17df941d4b0179fbeec28df6f83f..0651d5fa84940f16ea6ff2ba1c674b477e509fe8 100644 --- a/ragconnect.base/src/main/resources/MqttHandler.jadd +++ b/ragconnect.base/src/main/resources/MqttHandler.jadd @@ -316,11 +316,8 @@ public class MqttHandler { needSubscribe = pairToAddTo.callbacks.isEmpty(); pairToAddTo.callbacks.add(callback); } else { // normal topic - java.util.List<java.util.function.BiConsumer<String, byte[]>> callbacksForTopic = normalCallbacks.get(topic); - if (callbacksForTopic == null) { - callbacksForTopic = new java.util.ArrayList<>(); - normalCallbacks.put(topic, callbacksForTopic); - } + java.util.List<java.util.function.BiConsumer<String, byte[]>> callbacksForTopic = normalCallbacks. + computeIfAbsent(topic, t -> new java.util.ArrayList<>()); needSubscribe = callbacksForTopic.isEmpty(); callbacksForTopic.add(callback); } @@ -346,7 +343,10 @@ public class MqttHandler { }); }); try { - operationFinished.await(2, java.util.concurrent.TimeUnit.SECONDS); + boolean finishedInTime = operationFinished.await(2, java.util.concurrent.TimeUnit.SECONDS); + if (!finishedInTime) { + return false; + } return success.get(); } catch (InterruptedException e) { return false; @@ -428,7 +428,10 @@ public class MqttHandler { }); }); try { - operationFinished.await(2, java.util.concurrent.TimeUnit.SECONDS); + boolean finishedInTime = operationFinished.await(2, java.util.concurrent.TimeUnit.SECONDS); + if (!finishedInTime) { + return false; + } } catch (InterruptedException e) { logger.catching(e); success.set(false); diff --git a/ragconnect.base/src/main/resources/dependencyDefinition.mustache b/ragconnect.base/src/main/resources/dependencyDefinition.mustache index 0ab8d55242816a7d3ada0491c8c7db6dcd70ee42..891935029b5c5345df4dd7546705af347a422a5e 100644 --- a/ragconnect.base/src/main/resources/dependencyDefinition.mustache +++ b/ragconnect.base/src/main/resources/dependencyDefinition.mustache @@ -1,3 +1,3 @@ -public void {{targetParentTypeName}}.{{dependencyMethod}}({{sourceParentTypeName}} source) { +public void {{targetParentTypeName}}.{{dependencyMethodName}}({{sourceParentTypeName}} source) { add{{internalRelationPrefix}}Source(source); } diff --git a/ragconnect.base/src/main/resources/handler.mustache b/ragconnect.base/src/main/resources/handler.mustache index fe8d9459a0d1b977f7416da85ba3fb1c4d3e6b8f..37923f4419371cea7bbafe2eab9ad7cb745fe425 100644 --- a/ragconnect.base/src/main/resources/handler.mustache +++ b/ragconnect.base/src/main/resources/handler.mustache @@ -1,19 +1,28 @@ aspect RagConnectHandler { {{#Handlers}} {{#InUse}} - private {{ClassName}} {{rootNodeName}}.{{FieldName}} = {{{Construction}}}; + private {{ClassName}} {{rootNodeName}}.{{fieldName}} = {{{constructionSnippet}}}; + {{#hasRootTypeComponents}}inh {{ClassName}} ASTNode.{{attributeName}}();{{/hasRootTypeComponents}} {{#rootTypeComponents}} - {{#first}}inh {{ClassName}} ASTNode.{{AttributeName}}();{{/first}} - eq {{rootNodeName}}.get{{name}}().{{AttributeName}}() = {{FieldName}}; + eq {{rootNodeName}}.get{{Name}}().{{attributeName}}() = {{fieldName}}; {{/rootTypeComponents}} - syn {{ClassName}} {{rootNodeName}}.{{AttributeName}}() = {{FieldName}}; + syn {{ClassName}} {{rootNodeName}}.{{attributeName}}() = {{fieldName}}; {{/InUse}} {{/Handlers}} - public void {{rootNodeName}}.{{closeMethod}}() { + public void {{rootNodeName}}.{{closeMethodName}}() { {{#Handlers}} - {{#InUse}}{{FieldName}}.close();{{/InUse}} + {{#InUse}}{{fieldName}}.close();{{/InUse}} {{/Handlers}} } + +{{#mqttHandler}} + {{#InUse}} + public void {{rootNodeName}}.{{setupWaitUntilReadyMethodName}}(long time, java.util.concurrent.TimeUnit unit) { + {{fieldName}}.setupWaitUntilReady(time, unit); + } + {{/InUse}} +{{/mqttHandler}} + class RagConnectToken { static java.util.concurrent.atomic.AtomicLong counter = new java.util.concurrent.atomic.AtomicLong(0); final long id; diff --git a/ragconnect.base/src/main/resources/mappingApplication.mustache b/ragconnect.base/src/main/resources/mappingApplication.mustache index bc59e0b318dcd430b5f21fd0a67d157b35a4bb7c..836e8d438397db9fc8e862c828e5b57eeb34d2f1 100644 --- a/ragconnect.base/src/main/resources/mappingApplication.mustache +++ b/ragconnect.base/src/main/resources/mappingApplication.mustache @@ -1,8 +1,8 @@ {{{lastDefinitionToType}}} {{lastResult}}; try { - {{#InnerMappingDefinitions}} + {{#innerMappingDefinitions}} {{^last}}{{{toType}}} {{/last}}{{outputVarName}} = {{methodName}}({{inputVarName}}); - {{/InnerMappingDefinitions}} + {{/innerMappingDefinitions}} } catch (RagConnectRejectMappingException e) { // do not print message in case of rejection {{preemptiveReturn}} @@ -10,8 +10,8 @@ try { e.printStackTrace(); {{preemptiveReturn}} } -{{^alwaysApply}} +{{^AlwaysApply}} if ({{{condition}}}) { {{preemptiveReturn}} } -{{/alwaysApply}} +{{/AlwaysApply}} diff --git a/ragconnect.base/src/main/resources/mappingDefinition.mustache b/ragconnect.base/src/main/resources/mappingDefinition.mustache index 09f161f37c3742850b09969d4eb85c7798d2d346..5be93e4bdc91ca2eaa54f364eb8e5f7c069da2a5 100644 --- a/ragconnect.base/src/main/resources/mappingDefinition.mustache +++ b/ragconnect.base/src/main/resources/mappingDefinition.mustache @@ -1,3 +1,3 @@ -protected static {{{toType}}} ASTNode.{{methodName}}({{{fromType}}} {{fromVariableName}}) throws Exception { - {{{content}}} +protected static {{{toType}}} ASTNode.{{methodName}}({{{fromType}}} {{FromVariableName}}) throws Exception { + {{{Content}}} } diff --git a/ragconnect.base/src/main/resources/mqtt.mustache b/ragconnect.base/src/main/resources/mqtt.mustache deleted file mode 100644 index f12cb8982443f01dd6195e2c86a0ae55f1485811..0000000000000000000000000000000000000000 --- a/ragconnect.base/src/main/resources/mqtt.mustache +++ /dev/null @@ -1,5 +0,0 @@ -aspect MQTT { - public void {{rootNodeName}}.{{mqttSetupWaitUntilReadyMethod}}(long time, java.util.concurrent.TimeUnit unit) { - {{mqttHandlerField}}.setupWaitUntilReady(time, unit); - } -} diff --git a/ragconnect.base/src/main/resources/ragconnect.mustache b/ragconnect.base/src/main/resources/ragconnect.mustache index dd509aa53b34e56f425777c16f5f9f3d34c2fc7a..c3b50710f38fd247aca8ca11456c23279a0bee8c 100644 --- a/ragconnect.base/src/main/resources/ragconnect.mustache +++ b/ragconnect.base/src/main/resources/ragconnect.mustache @@ -1,45 +1,37 @@ -{{#usesMqtt}}{{> mqtt}}{{/usesMqtt}} {{> handler}} aspect RagConnect { - {{#TokenReceiveDefinitions}} - {{> receiveDefinition}} - {{/TokenReceiveDefinitions}} - - {{#TokenSendDefinitions}} - {{> sendDefinition}} - {{/TokenSendDefinitions}} - - {{#TypeReceiveDefinitions}} - {{> receiveDefinition}} - {{/TypeReceiveDefinitions}} - - {{#TypeSendDefinitions}} - {{> sendDefinition}} - {{/TypeSendDefinitions}} + {{#allEndpointDefinitionList}} + {{#Send}} + {{> sendDefinition}} + {{/Send}} + {{^Send}} + {{> receiveDefinition}} + {{/Send}} + {{/allEndpointDefinitionList}} class RagConnectRejectMappingException extends RuntimeException {} private static void ASTNode.reject() { throw new RagConnectRejectMappingException(); } - {{#MappingDefinitions}} + {{#allMappingDefinitions}} {{#isUsed}} {{> mappingDefinition}} {{/isUsed}} - {{/MappingDefinitions}} + {{/allMappingDefinitions}} - {{#DependencyDefinitions}} + {{#allDependencyDefinitionList}} {{> dependencyDefinition}} - {{/DependencyDefinitions}} + {{/allDependencyDefinitionList}} - {{#TokenComponents}} + {{#tokenComponentsThatNeedProxy}} {{> tokenComponent}} - {{/TokenComponents}} + {{/tokenComponentsThatNeedProxy}} {{> ListAspect}} public void {{rootNodeName}}.ragconnectCheckIncremental() { - {{#incrementalOptionActive}} + {{#configIncrementalOptionActive}} // check if --tracing is active trace().getReceiver(); // check if tracing of INC_FLUSH_ATTR is possible, i.e., if --tracing=flush @@ -48,11 +40,11 @@ aspect RagConnect { mayHaveRewrite(); // check if --incremental is active Object checkIncremental = inc_throwAway_visited; - {{/incrementalOptionActive}} + {{/configIncrementalOptionActive}} } } -{{#incrementalOptionActive}} +{{#configIncrementalOptionActive}} aspect RagConnectObserver { class RagConnectObserver implements ASTState.Trace.Receiver { @@ -71,7 +63,7 @@ aspect RagConnectObserver { } } -{{#experimentalJastAdd329}} +{{#configExperimentalJastAdd329}} class RagConnectObserverStartEntry { final ASTNode node; final String attributeString; @@ -82,16 +74,16 @@ aspect RagConnectObserver { this.flushIncToken = flushIncToken; } } -{{/experimentalJastAdd329}} +{{/configExperimentalJastAdd329}} ASTState.Trace.Receiver oldReceiver; java.util.List<RagConnectObserverEntry> observedNodes = new java.util.ArrayList<>(); -{{#experimentalJastAdd329}} +{{#configExperimentalJastAdd329}} java.util.Set<RagConnectObserverEntry> entryQueue = new java.util.HashSet<>(); RagConnectObserverStartEntry startEntry = null; -{{/experimentalJastAdd329}} +{{/configExperimentalJastAdd329}} RagConnectObserver(ASTNode node) { // set the receiver. potentially dangerous because overriding existing receiver! @@ -100,9 +92,9 @@ aspect RagConnectObserver { } void add(RagConnectToken connectToken, ASTNode node, String attributeString, Runnable attributeCall) { - {{#loggingEnabledForIncremental}} + {{#configLoggingEnabledForIncremental}} System.out.println("** observer add: " + node + " on " + attributeString); - {{/loggingEnabledForIncremental}} + {{/configLoggingEnabledForIncremental}} observedNodes.add(new RagConnectObserverEntry(connectToken, node, attributeString, attributeCall)); } void remove(RagConnectToken connectToken) { @@ -111,12 +103,12 @@ aspect RagConnectObserver { @Override public void accept(ASTState.Trace.Event event, ASTNode node, String attribute, Object params, Object value) { oldReceiver.accept(event, node, attribute, params, value); -{{#experimentalJastAdd329}} +{{#configExperimentalJastAdd329}} // react to INC_FLUSH_START and remember entry if (event == ASTState.Trace.Event.INC_FLUSH_START && startEntry == null) { - {{#loggingEnabledForIncremental}} + {{#configLoggingEnabledForIncremental}} System.out.println("** observer start: " + node + " on " + attribute); - {{/loggingEnabledForIncremental}} + {{/configLoggingEnabledForIncremental}} startEntry = new RagConnectObserverStartEntry(node, attribute, value); return; } @@ -130,37 +122,37 @@ aspect RagConnectObserver { RagConnectObserverEntry[] entriesToProcess = entryQueue.toArray(new RagConnectObserverEntry[entryQueue.size()]); entryQueue.clear(); startEntry = null; - {{#loggingEnabledForIncremental}} + {{#configLoggingEnabledForIncremental}} System.out.println("** observer process (" + entriesToProcess.length + "): " + node + " on " + attribute); - {{/loggingEnabledForIncremental}} + {{/configLoggingEnabledForIncremental}} for (RagConnectObserverEntry entry : entriesToProcess) { entry.attributeCall.run(); } return; } -{{/experimentalJastAdd329}} +{{/configExperimentalJastAdd329}} // ignore all other events but INC_FLUSH_ATTR if (event != ASTState.Trace.Event.INC_FLUSH_ATTR) { return; } - {{#loggingEnabledForIncremental}} + {{#configLoggingEnabledForIncremental}} System.out.println("** observer check INC_FLUSH_ATTR event: " + node + " on " + attribute); - {{/loggingEnabledForIncremental}} + {{/configLoggingEnabledForIncremental}} // iterate through list, if matching pair. could maybe be more efficient. for (RagConnectObserverEntry entry : observedNodes) { if (entry.node.equals(node) && entry.attributeString.equals(attribute)) { // hit. call the attribute/nta-token - {{#loggingEnabledForIncremental}} + {{#configLoggingEnabledForIncremental}} System.out.println("** observer hit: " + entry.node + " on " + entry.attributeString); - {{/loggingEnabledForIncremental}} -{{#experimentalJastAdd329}} + {{/configLoggingEnabledForIncremental}} +{{#configExperimentalJastAdd329}} entryQueue.add(entry); -{{/experimentalJastAdd329}} -{{^experimentalJastAdd329}} +{{/configExperimentalJastAdd329}} +{{^configExperimentalJastAdd329}} entry.attributeCall.run(); -{{/experimentalJastAdd329}} +{{/configExperimentalJastAdd329}} } } } @@ -175,4 +167,4 @@ aspect RagConnectObserver { return _ragConnectObserverInstance; } } -{{/incrementalOptionActive}} +{{/configIncrementalOptionActive}} diff --git a/ragconnect.base/src/main/resources/receiveDefinition.mustache b/ragconnect.base/src/main/resources/receiveDefinition.mustache index 2fd0ea21f1dc6072941b99d6bfa6238f1c0f4f90..25dd2a484abd288091f4a501f6fe8e06a90c1f95 100644 --- a/ragconnect.base/src/main/resources/receiveDefinition.mustache +++ b/ragconnect.base/src/main/resources/receiveDefinition.mustache @@ -13,67 +13,67 @@ private int {{parentTypeName}}.{{resolveInListMethodName}}(String topic) { /** * Connects the receive endpoint {{entityName}}. -{{#typeIsList}}{{#isWithAdd}} +{{#typeIsList}}{{#WithAdd}} * New values are appended to the end of the list. -{{/isWithAdd}}{{/typeIsList}} +{{/WithAdd}}{{/typeIsList}} * @param {{connectParameterName}} string describing protocol and path as an URI -{{#typeIsList}}{{#IndexBasedListAccess}}{{^isWithAdd}} +{{#typeIsList}}{{#IndexBasedListAccess}}{{^WithAdd}} * @param index index of node in list to connect (the list is expected to have enough elements) -{{/isWithAdd}}{{/IndexBasedListAccess}}{{/typeIsList}} +{{/WithAdd}}{{/IndexBasedListAccess}}{{/typeIsList}} * @return true if connect was successful, false otherwise * @throws java.io.IOException if connect failed */ -public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterName}}{{#typeIsList}}{{#IndexBasedListAccess}}{{^isWithAdd}}, int index{{/isWithAdd}}{{/IndexBasedListAccess}}{{/typeIsList}}) throws java.io.IOException { +public boolean {{parentTypeName}}.{{connectMethodName}}(String {{connectParameterName}}{{#typeIsList}}{{#IndexBasedListAccess}}{{^WithAdd}}, int index{{/WithAdd}}{{/IndexBasedListAccess}}{{/typeIsList}}) throws java.io.IOException { java.util.function.BiConsumer<String, byte[]> consumer = (topic, message) -> { {{> mappingApplication}} -{{#loggingEnabledForReads}} +{{#configLoggingEnabledForReads}} System.out.println("[Receive] " + {{connectParameterName}} + " -> {{entityName}} = " + {{lastResult}}); -{{/loggingEnabledForReads}} -{{#isTypeEndpointDefinition}} +{{/configLoggingEnabledForReads}} +{{#hasTypeEndpointTarget}} {{lastResult}}.treeResolveAll(); {{#typeIsList}} {{^IndexBasedListAccess}} - {{#isWithAdd}} - {{getterMethod}}().addAll({{lastResult}}); - {{/isWithAdd}} - {{^isWithAdd}} + {{#WithAdd}} + {{getterMethodName}}().addAll({{lastResult}}); + {{/WithAdd}} + {{^WithAdd}} set{{entityName}}({{lastResult}}); - {{/isWithAdd}} + {{/WithAdd}} {{/IndexBasedListAccess}} {{#IndexBasedListAccess}} {{lastResult}}.set{{idTokenName}}(topic); - {{#isWithAdd}} - {{getterMethod}}().add({{lastResult}}); - {{/isWithAdd}} - {{^isWithAdd}} + {{#WithAdd}} + {{getterMethodName}}().add({{lastResult}}); + {{/WithAdd}} + {{^WithAdd}} set{{entityName}}({{lastResult}}, index); - {{/isWithAdd}} + {{/WithAdd}} {{/IndexBasedListAccess}} {{/typeIsList}} {{^typeIsList}} set{{entityName}}({{lastResult}}); {{/typeIsList}} -{{/isTypeEndpointDefinition}} -{{^isTypeEndpointDefinition}} +{{/hasTypeEndpointTarget}} +{{^hasTypeEndpointTarget}} set{{entityName}}({{lastResult}}); -{{/isTypeEndpointDefinition}} +{{/hasTypeEndpointTarget}} }; - return {{internalConnectMethod}}({{connectParameterName}}, consumer); + return {{internalConnectMethodName}}({{connectParameterName}}, consumer); } -{{#typeIsList}}{{#IndexBasedListAccess}}{{^isWithAdd}} +{{#typeIsList}}{{#IndexBasedListAccess}}{{^WithAdd}} /** * Connects the receive endpoint {{entityName}} using a "wildcard" URI (if supported by the chosen protocol). * @param {{connectParameterName}} string describing protocol and path as an URI * @return true if connect was successful, false otherwise * @throws java.io.IOException if connect failed */ -public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterName}}) throws java.io.IOException { +public boolean {{parentTypeName}}.{{connectMethodName}}(String {{connectParameterName}}) throws java.io.IOException { java.util.function.BiConsumer<String, byte[]> consumer = (topic, message) -> { {{> mappingApplication}} -{{#loggingEnabledForReads}} +{{#configLoggingEnabledForReads}} System.out.println("[Receive] " + {{connectParameterName}} + " (" + topic + ") -> {{entityName}} = " + {{lastResult}}); -{{/loggingEnabledForReads}} +{{/configLoggingEnabledForReads}} {{lastResult}}.set{{idTokenName}}(topic); int resolvedIndex = {{resolveInListMethodName}}(topic); if (resolvedIndex == -1) { @@ -82,29 +82,33 @@ public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterNam set{{entityName}}({{lastResult}}, resolvedIndex); } }; - return {{internalConnectMethod}}({{connectParameterName}}, consumer); + return {{internalConnectMethodName}}({{connectParameterName}}, consumer); } -{{/isWithAdd}}{{/IndexBasedListAccess}}{{/typeIsList}} +{{/WithAdd}}{{/IndexBasedListAccess}}{{/typeIsList}} -private boolean {{parentTypeName}}.{{internalConnectMethod}}(String {{connectParameterName}}, +private boolean {{parentTypeName}}.{{internalConnectMethodName}}(String {{connectParameterName}}, java.util.function.BiConsumer<String, byte[]> consumer) throws java.io.IOException { {{>handleUri}} RagConnectToken connectToken = new RagConnectToken(uri, "{{entityName}}"); boolean success; switch (scheme) { - {{#usesMqtt}} + {{#mqttHandler}} + {{#InUse}} case "mqtt": - success = {{mqttHandlerAttribute}}().newConnection(connectToken, consumer); + success = {{attributeName}}().newConnection(connectToken, consumer); break; - {{/usesMqtt}} - {{#usesRest}} + {{/InUse}} + {{/mqttHandler}} + {{#restHandler}} + {{#InUse}} case "rest": - success = {{restHandlerAttribute}}().newPUTConnection(connectToken, input -> { + success = {{attributeName}}().newPUTConnection(connectToken, input -> { // TODO wildcard-topic not supported yet consumer.accept("", input.getBytes()); }); break; - {{/usesRest}} + {{/InUse}} + {{/restHandler}} default: System.err.println("Unknown protocol '" + scheme + "'."); success = false; @@ -115,7 +119,7 @@ private boolean {{parentTypeName}}.{{internalConnectMethod}}(String {{connectPar return success; } -public boolean {{parentTypeName}}.{{disconnectMethod}}(String {{connectParameterName}}) throws java.io.IOException { +public boolean {{parentTypeName}}.{{disconnectMethodName}}(String {{connectParameterName}}) throws java.io.IOException { {{>handleUri}} java.util.List<RagConnectToken> connectTokens = connectTokenMap.removeAll(this, true, uri, "{{entityName}}"); if (connectTokens.isEmpty()) { @@ -124,14 +128,18 @@ public boolean {{parentTypeName}}.{{disconnectMethod}}(String {{connectParameter } RagConnectDisconnectHandlerMethod disconnectingMethod; switch (scheme) { - {{#usesMqtt}} - case "mqtt": disconnectingMethod = {{mqttHandlerAttribute}}()::disconnect; + {{#mqttHandler}} + {{#InUse}} + case "mqtt": disconnectingMethod = {{attributeName}}()::disconnect; break; - {{/usesMqtt}} - {{#usesRest}} - case "rest": disconnectingMethod = {{restHandlerAttribute}}()::disconnect; + {{/InUse}} + {{/mqttHandler}} + {{#restHandler}} + {{#InUse}} + case "rest": disconnectingMethod = {{attributeName}}()::disconnect; break; - {{/usesRest}} + {{/InUse}} + {{/restHandler}} default: System.err.println("Unknown protocol '" + scheme + "' in '" + {{connectParameterName}} + "' for disconnecting {{parentTypeName}}.{{entityName}}"); return false; diff --git a/ragconnect.base/src/main/resources/sendDefinition.mustache b/ragconnect.base/src/main/resources/sendDefinition.mustache index 5cee6a483cda29519905918a505337db7779fce6..3c29e922faf0bc1de3838468886cbc905d97b2dc 100644 --- a/ragconnect.base/src/main/resources/sendDefinition.mustache +++ b/ragconnect.base/src/main/resources/sendDefinition.mustache @@ -1,74 +1,82 @@ -private RagConnectPublisher {{parentTypeName}}.{{sender}} = new RagConnectPublisher(); +private RagConnectPublisher {{parentTypeName}}.{{senderName}} = new RagConnectPublisher(); -public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterName}}, boolean writeCurrentValue) throws java.io.IOException { +public boolean {{parentTypeName}}.{{connectMethodName}}(String {{connectParameterName}}, boolean writeCurrentValue) throws java.io.IOException { {{>handleUri}} RagConnectToken connectToken = new RagConnectToken(uri, "{{entityName}}"); boolean success; switch (scheme) { - {{#usesMqtt}} + {{#mqttHandler}} + {{#InUse}} case "mqtt": - final MqttHandler handler = {{mqttHandlerAttribute}}().resolveHandler(uri); - final String topic = {{mqttHandlerAttribute}}().extractTopic(uri); - {{sender}}.add(() -> { - {{#loggingEnabledForWrites}} - System.out.println("[Send] {{entityName}} = " + {{getterMethod}}() + " -> " + {{connectParameterName}}); - {{/loggingEnabledForWrites}} + final MqttHandler handler = {{attributeName}}().resolveHandler(uri); + final String topic = {{attributeName}}().extractTopic(uri); + {{senderName}}.add(() -> { + {{#configLoggingEnabledForWrites}} + System.out.println("[Send] {{entityName}} = " + {{getterMethodName}}() + " -> " + {{connectParameterName}}); + {{/configLoggingEnabledForWrites}} handler.publish(topic, {{lastValue}}); }, connectToken); - {{updateMethod}}(); + {{updateMethodName}}(); if (writeCurrentValue) { - {{writeMethod}}(); + {{writeMethodName}}(); } success = true; break; - {{/usesMqtt}} - {{#usesRest}} + {{/InUse}} + {{/mqttHandler}} + {{#restHandler}} + {{#InUse}} case "rest": - success = {{restHandlerAttribute}}().newGETConnection(connectToken, () -> { - {{updateMethod}}(); + success = {{attributeName}}().newGETConnection(connectToken, () -> { + {{updateMethodName}}(); return new String({{lastValue}}); }); break; - {{/usesRest}} + {{/InUse}} + {{/restHandler}} default: System.err.println("Unknown protocol '" + scheme + "'."); success = false; } if (success) { connectTokenMap.add(this, false, connectToken); - {{#incrementalOptionActive}} - _ragConnectObserver().add(connectToken, this, "{{getterMethod}}", () -> { - if (this.{{updateMethod}}()) { - this.{{writeMethod}}(); + {{#configIncrementalOptionActive}} + _ragConnectObserver().add(connectToken, this, "{{getterMethodName}}", () -> { + if (this.{{updateMethodName}}()) { + this.{{writeMethodName}}(); } }); - {{/incrementalOptionActive}} + {{/configIncrementalOptionActive}} } return success; } -public boolean {{parentTypeName}}.{{disconnectMethod}}(String {{connectParameterName}}) throws java.io.IOException { +public boolean {{parentTypeName}}.{{disconnectMethodName}}(String {{connectParameterName}}) throws java.io.IOException { {{>handleUri}} java.util.List<RagConnectToken> connectTokens = connectTokenMap.removeAll(this, false, uri, "{{entityName}}"); if (connectTokens.isEmpty()) { System.err.println("Disconnect called without connection for sending " + this + ".{{entityName}} to '" + {{connectParameterName}} + "'!"); return false; } - {{#incrementalOptionActive}} + {{#configIncrementalOptionActive}} connectTokens.forEach(token -> _ragConnectObserver().remove(token)); - {{/incrementalOptionActive}} + {{/configIncrementalOptionActive}} RagConnectDisconnectHandlerMethod disconnectingMethod; switch (scheme) { - {{#usesMqtt}} + {{#mqttHandler}} + {{#InUse}} case "mqtt": - disconnectingMethod = {{sender}}::remove; + disconnectingMethod = {{senderName}}::remove; break; - {{/usesMqtt}} - {{#usesRest}} + {{/InUse}} + {{/mqttHandler}} + {{#restHandler}} + {{#InUse}} case "rest": - disconnectingMethod = {{restHandlerAttribute}}()::disconnect; + disconnectingMethod = {{attributeName}}()::disconnect; break; - {{/usesRest}} + {{/InUse}} + {{/restHandler}} default: System.err.println("Unknown protocol '" + scheme + "' in '" + {{connectParameterName}} + "' for disconnecting {{parentTypeName}}.{{entityName}}"); return false; @@ -80,16 +88,16 @@ public boolean {{parentTypeName}}.{{disconnectMethod}}(String {{connectParameter return success; } -protected boolean {{parentTypeName}}.{{updateMethod}}() { +protected boolean {{parentTypeName}}.{{updateMethodName}}() { {{^shouldSendValue}} - {{tokenResetMethod}}(); + {{tokenResetMethodName}}(); {{/shouldSendValue}} {{> mappingApplication}} {{lastValue}} = {{lastResult}}; - // normally we would return true here. unless no connect method was called so far to initialize {{sender}} yet - return {{sender}} != null; + // normally we would return true here. unless no connect method was called so far to initialize {{senderName}} yet + return {{senderName}} != null; } -protected void {{parentTypeName}}.{{writeMethod}}() { - {{sender}}.run(); +protected void {{parentTypeName}}.{{writeMethodName}}() { + {{senderName}}.run(); } diff --git a/ragconnect.base/src/main/resources/tokenComponent.mustache b/ragconnect.base/src/main/resources/tokenComponent.mustache index 169f5f64fff01ef2c34abeea34266b5a82deaf3a..3b0ae62080f39f17a329a34caeb410da66365f5d 100644 --- a/ragconnect.base/src/main/resources/tokenComponent.mustache +++ b/ragconnect.base/src/main/resources/tokenComponent.mustache @@ -1,22 +1,22 @@ -public {{parentTypeName}} {{parentTypeName}}.set{{name}}({{javaType}} value) { +public {{parentTypeName}} {{parentTypeName}}.set{{Name}}({{javaType}} value) { set{{internalName}}(value); - {{#DependencyDefinitions}} + {{#DependencySourceDefinitions}} for ({{targetParentTypeName}} target : get{{internalRelationPrefix}}TargetList()) { {{#targetEndpointDefinition}} - if (target.{{updateMethod}}()) { - target.{{writeMethod}}(); + if (target.{{updateMethodName}}()) { + target.{{writeMethodName}}(); } {{/targetEndpointDefinition}} } - {{/DependencyDefinitions}} + {{/DependencySourceDefinitions}} {{#normalTokenSendDef}} - if ({{updateMethod}}()) { - {{writeMethod}}(); + if ({{updateMethodName}}()) { + {{writeMethodName}}(); } {{/normalTokenSendDef}} return this; } -public {{javaType}} {{parentTypeName}}.get{{name}}() { +public {{javaType}} {{parentTypeName}}.get{{Name}}() { return get{{internalName}}(); } diff --git a/ragconnect.tests/build.gradle b/ragconnect.tests/build.gradle index ee6da58c40c1bb690258d3958ac53a6ec44ac362..cfeb6ae4680eca67212c256e3e39debc514609c7 100644 --- a/ragconnect.tests/build.gradle +++ b/ragconnect.tests/build.gradle @@ -9,7 +9,7 @@ buildscript { } dependencies { classpath 'org.jastadd:jastaddgradle:1.13.3' - classpath 'org.jastadd.preprocessor:testing:0.2.10' + classpath 'org.jastadd.preprocessor:testing:0.2.11' } } @@ -32,11 +32,14 @@ group = 'de.tudresden.inf.st' repositories { mavenCentral() } +tasks.compileTestJava { + options.release.set(11) +} dependencies { implementation project(':ragconnect.base') - runtimeOnly group: 'org.jastadd', name: 'jastadd', version: '2.3.5' + runtimeOnly group: 'org.jastadd', name: 'jastadd', version: '2.3.5-dresden' // runtimeOnly fileTree(include: ['jastadd2.jar'], dir: '../libs') testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.4.0' @@ -61,6 +64,12 @@ dependencies { api group: 'com.google.protobuf', name: 'protobuf-java', version: '3.0.0' } +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(11)) + } +} + //task helper { // doLast { // println(defaultOnlyRead.inputs.files.files) @@ -278,7 +287,6 @@ task compileIncremental(type: RagConnectTest) { inputFiles = [file('src/test/01-input/incremental/Test.relast'), file('src/test/01-input/incremental/Test.connect')] rootNode = 'A' - logWrites = true } relast { useJastAddNames = true @@ -303,9 +311,6 @@ task compileMapping(type: RagConnectTest) { inputFiles = [file('src/test/01-input/mapping/Test.relast'), file('src/test/01-input/mapping/Test.connect')] rootNode = 'A' - logReads = true - logWrites = true - verbose = true } relast { useJastAddNames = true @@ -532,6 +537,7 @@ task compileSingleListVariantIncremental(type: RagConnectTest, dependsOn: ':ragc inputFiles = [file('src/test/01-input/singleListVariant/Test.relast'), file('src/test/01-input/singleListVariant/Test.connect')] rootNode = 'Root' + extraOptions = ['--experimental-jastadd-329'] } relast { useJastAddNames = true diff --git a/ragconnect.tests/src/test/01-input/errors/Part.expected b/ragconnect.tests/src/test/01-input/errors/Part.expected index 70ea4a4baeaffb5b35df672c03e90821eb3cec82..86bb6dd0d9cc23865031bdcf89ba71c441f85a7f 100644 --- a/ragconnect.tests/src/test/01-input/errors/Part.expected +++ b/ragconnect.tests/src/test/01-input/errors/Part.expected @@ -1,11 +1,11 @@ -Part1.connect Line 3, column 1: Receive definition already defined for DoubledValue -Part1.connect Line 4, column 1: Receive definition already defined for DoubledValue +Part1.connect Line 3, column 1: Endpoint definition already defined for B.DoubledValue +Part1.connect Line 4, column 1: Endpoint definition already defined for B.DoubledValue Part1.connect Line 10, column 1: Receiving target token must not be an NTA token! Part1.connect Line 13, column 1: No suitable default mapping found for type java.util.List -Part1.connect Line 13, column 1: to-type of last mapping (java.util.List) not assignable to type of the Token (String)! -Part1.connect Line 16, column 1: to-type of last mapping (List) not assignable to type of the Token (String)! -Part1.connect Line 19, column 1: to-type of last mapping (int) not assignable to type of the Token (String)! -Part2.connect Line 5, column 1: Send definition already defined for DoubledValue -Part2.connect Line 6, column 1: Send definition already defined for DoubledValue +Part1.connect Line 13, column 1: to-type of last mapping (java.util.List) not assignable to type of the token (String)! +Part1.connect Line 16, column 1: to-type of last mapping (List) not assignable to type of the token (String)! +Part1.connect Line 19, column 1: to-type of last mapping (int) not assignable to type of the token (String)! +Part2.connect Line 5, column 1: Endpoint definition already defined for C.DoubledValue +Part2.connect Line 6, column 1: Endpoint definition already defined for C.DoubledValue Part2.connect Line 17, column 1: The name of a dependency definition must not be equal to a list-node on the source Part2.connect Line 22, column 1: Dependency definition already defined for D with name DoubledValue diff --git a/ragconnect.tests/src/test/01-input/errors/Standard.expected b/ragconnect.tests/src/test/01-input/errors/Standard.expected index 3ee660570525834a63c41f26820966a7504f7789..2e14612cc9fc4d7ffae435745e8b8593a22258d5 100644 --- a/ragconnect.tests/src/test/01-input/errors/Standard.expected +++ b/ragconnect.tests/src/test/01-input/errors/Standard.expected @@ -1,11 +1,11 @@ -Standard.connect Line 3, column 1: Receive definition already defined for DoubledValue -Standard.connect Line 4, column 1: Receive definition already defined for DoubledValue +Standard.connect Line 3, column 1: Endpoint definition already defined for B.DoubledValue +Standard.connect Line 4, column 1: Endpoint definition already defined for B.DoubledValue Standard.connect Line 10, column 1: Receiving target token must not be an NTA token! Standard.connect Line 13, column 1: No suitable default mapping found for type java.util.List -Standard.connect Line 13, column 1: to-type of last mapping (java.util.List) not assignable to type of the Token (String)! -Standard.connect Line 16, column 1: to-type of last mapping (List) not assignable to type of the Token (String)! -Standard.connect Line 19, column 1: to-type of last mapping (int) not assignable to type of the Token (String)! -Standard.connect Line 39, column 1: Send definition already defined for DoubledValue -Standard.connect Line 40, column 1: Send definition already defined for DoubledValue +Standard.connect Line 13, column 1: to-type of last mapping (java.util.List) not assignable to type of the token (String)! +Standard.connect Line 16, column 1: to-type of last mapping (List) not assignable to type of the token (String)! +Standard.connect Line 19, column 1: to-type of last mapping (int) not assignable to type of the token (String)! +Standard.connect Line 39, column 1: Endpoint definition already defined for C.DoubledValue +Standard.connect Line 40, column 1: Endpoint definition already defined for C.DoubledValue Standard.connect Line 51, column 1: The name of a dependency definition must not be equal to a list-node on the source Standard.connect Line 56, column 1: Dependency definition already defined for D with name DoubledValue diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/singleListVariant/SingleListVariantIncrementalVariantTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/singleListVariant/SingleListVariantIncrementalVariantTest.java index 174bea2923e2977c93a058dc1408113276e47382..0bd6bcf7218b32f4737716380a5239d178ecdbce 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/singleListVariant/SingleListVariantIncrementalVariantTest.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/singleListVariant/SingleListVariantIncrementalVariantTest.java @@ -1,6 +1,7 @@ package org.jastadd.ragconnect.tests.singleListVariant; import org.jastadd.ragconnect.tests.TestUtils; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Tag; import singleListVariantInc.ast.*; @@ -16,6 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; * @author rschoene - Initial contribution */ @Tag("Incremental") +@Disabled("Fails indeterministically") public class SingleListVariantIncrementalVariantTest extends AbstractSingleListVariantTest { private Root model;