diff --git a/pages/docs/dsl.md b/pages/docs/dsl.md index 19125a893a07aa3dda53a34ddd7f46537675bbb8..e8b6b2bb11c67168bafd33efa48b505248ea9b37 100644 --- a/pages/docs/dsl.md +++ b/pages/docs/dsl.md @@ -13,7 +13,7 @@ The kind of the element determines, whether an endpoint for it can be receiving, To declare a new endpoints, use the following syntax: ``` -("send"|"receive") ["indexed"] ["with add"] <Non-Terminal>[.<Target>["()"]] ["using" <Mapping-Name> (, <Mapping-Name>)*] ";" +("send"|"receive") ["indexed"] ["with add"] <Non-Terminal>[.<Target>["(<AttributeType>)"]] ["using" <Mapping-Name> (, <Mapping-Name>)*] ";" ``` A breakdown of the parts of that syntax: @@ -28,10 +28,12 @@ A breakdown of the parts of that syntax: - The second optional keyword `with add` can also be used only for receiving endpoints targeting a list children. As described above, it can be combined with `indexed`. If used on its own, the incoming data is interpreted as a complete list and its elements will be appended to the current list. -- The `<Non-Terminal>[.<Target>["()"]]` notation describes the actual affected node. +- The `<Non-Terminal>[.<Target>["(<AttributeType>)"]]` notation describes the actual affected node. - If the target is omitted, all nodes of that non-terminal type can be connected, irrespective of their context. This is a context-free endpoint definition. - The target can be any child on the right-hand side of a production rule, a role of a relation, or an attribute. - The brackets `()` after the target must be used in case of an attribute, and only then. + The brackets `(<AttributeType>)` after the target must be used in case of an attribute, and only then. + Here, the return type of the attribute has to be specified, as aspect files are not parsed by RagConnect. + Hence, RagConnect can not and will not verify the existence of the attribute, and the possible non-existence of an attribute will be found by the Java compiler. - Optionally, an endpoint can use one or more [mappings](#mappings). They will be applied before sending, or after receiving a message. Mappings will always be applied in the order they are listed after `using`. diff --git a/ragconnect.base/src/main/jastadd/Analysis.jrag b/ragconnect.base/src/main/jastadd/Analysis.jrag index b5fb2ce222e7f43334ac1dbe93548319e69e45a9..d4e166a34a2b62150d76dfa0decf3c0a827bb649 100644 --- a/ragconnect.base/src/main/jastadd/Analysis.jrag +++ b/ragconnect.base/src/main/jastadd/Analysis.jrag @@ -76,15 +76,17 @@ aspect Analysis { } } - // TODO rename entityIsNormalAttribute to actual meaning - syn boolean EndpointTarget.entityIsNormalAttribute(); - eq AttributeEndpointTarget.entityIsNormalAttribute() = true; - eq TokenEndpointTarget.entityIsNormalAttribute() = !getToken().getNTA(); - eq TypeEndpointTarget.entityIsNormalAttribute() = !getType().getNTA(); - eq ContextFreeTypeEndpointTarget.entityIsNormalAttribute() = false; + syn boolean EndpointTarget.hasAttributeResetMethod(); + eq AttributeEndpointTarget.hasAttributeResetMethod() = false; + eq TokenEndpointTarget.hasAttributeResetMethod() = getToken().getNTA(); + eq TypeEndpointTarget.hasAttributeResetMethod() = getType().getNTA(); + eq ContextFreeTypeEndpointTarget.hasAttributeResetMethod() = false; // --- needProxyToken --- - syn boolean TokenComponent.needProxyToken() = !getDependencySourceDefinitionList().isEmpty() || getTokenEndpointTargetList().stream().map(EndpointTarget::containingEndpointDefinition).anyMatch(EndpointDefinition::shouldSendValue); + syn boolean TokenComponent.needProxyToken() = !getDependencySourceDefinitionList().isEmpty() || + getTokenEndpointTargetList().stream() + .map(EndpointTarget::containingEndpointDefinition) + .anyMatch(EndpointDefinition::shouldNotResetValue); // --- effectiveUsedAt --- coll Set<EndpointDefinition> MappingDefinition.effectiveUsedAt() diff --git a/ragconnect.base/src/main/jastadd/Intermediate.jadd b/ragconnect.base/src/main/jastadd/Intermediate.jadd index e26b797e9c30c6a53d565485835c333fe15828e1..47f3aa473e0959ece3a24b684b98b59893c58413 100644 --- a/ragconnect.base/src/main/jastadd/Intermediate.jadd +++ b/ragconnect.base/src/main/jastadd/Intermediate.jadd @@ -168,7 +168,6 @@ aspect MustacheMappingApplicationAndDefinition { syn String MEndpointDefinition.preemptiveReturn(); syn String MEndpointDefinition.firstInputVarName(); - // TODO check MAttributeSendDefinition eq MAttributeSendDefinition.firstInputVarName() = getterMethodCall(); eq MAttributeSendDefinition.preemptiveExpectedValue() = lastValueGetterCall(); eq MAttributeSendDefinition.preemptiveReturn() = "return false;"; @@ -438,7 +437,7 @@ aspect MustacheSendDefinition { syn String EndpointDefinition.senderName() = getEndpointTarget().senderName(); - syn boolean EndpointDefinition.shouldSendValue() = getSend() && getEndpointTarget().entityIsNormalAttribute(); + syn boolean EndpointDefinition.shouldNotResetValue() = getSend() && !getEndpointTarget().hasAttributeResetMethod(); syn String EndpointDefinition.tokenResetMethodName() = getterMethodName() + "_reset"; @@ -468,13 +467,11 @@ aspect MustacheSendDefinition { syn String EndpointTarget.senderName() = ragconnect().internalRagConnectPrefix() + "_sender_" + entityName(); eq ContextFreeTypeEndpointTarget.senderName() = null; - // TOOO both updateMethodName and writeMethodName could be defined for MEndpointDefinition using getEndpointDefinition().enitityName() syn String MEndpointDefinition.updateMethodName(); syn String MEndpointDefinition.writeMethodName(); - // TODO check MAttributeSendDefinition. maybe name-clash possible if there is an attribute with same name as a child - eq MAttributeSendDefinition.updateMethodName() = ragconnect().internalRagConnectPrefix() + "_update_" + getEndpointDefinition().entityName(); - eq MAttributeSendDefinition.writeMethodName() = ragconnect().internalRagConnectPrefix() + "_writeLastValue_" + getEndpointDefinition().entityName(); + eq MAttributeSendDefinition.updateMethodName() = ragconnect().internalRagConnectPrefix() + "_update_attr_" + getEndpointDefinition().entityName(); + eq MAttributeSendDefinition.writeMethodName() = ragconnect().internalRagConnectPrefix() + "_writeLastValue_attr_" + getEndpointDefinition().entityName(); eq MTokenReceiveDefinition.updateMethodName() = null; eq MTokenReceiveDefinition.writeMethodName() = null; @@ -509,7 +506,7 @@ aspect MustacheTokenComponent { syn EndpointDefinition TokenComponent.normalTokenSendDef() { for (EndpointTarget target : getTokenEndpointTargetList()) { - if (target.isTokenEndpointTarget() && target.containingEndpointDefinition().shouldSendValue()) { + if (target.isTokenEndpointTarget() && target.containingEndpointDefinition().shouldNotResetValue()) { return target.containingEndpointDefinition(); } } diff --git a/ragconnect.base/src/main/jastadd/IntermediateToYAML.jrag b/ragconnect.base/src/main/jastadd/IntermediateToYAML.jrag index fb198ce9cfe34db3234cc5a7feff5ddfb210dc91..49c2693696a02de14852e252f3aadd3a722dfb95 100644 --- a/ragconnect.base/src/main/jastadd/IntermediateToYAML.jrag +++ b/ragconnect.base/src/main/jastadd/IntermediateToYAML.jrag @@ -103,7 +103,7 @@ aspect IntermediateToYAML { result.put("lastValueGetterCall" , lastValueGetterCall()); result.put("lastValueSetter" , lastValueSetter()); result.put("senderName" , senderName()); - result.put("shouldSendValue" , shouldSendValue()); + result.put("shouldNotResetValue" , shouldNotResetValue()); result.put("tokenResetMethodName" , tokenResetMethodName()); result.put("updateMethodName" , updateMethodName()); result.put("writeMethodName" , writeMethodName()); diff --git a/ragconnect.base/src/main/jastadd/Mappings.jrag b/ragconnect.base/src/main/jastadd/Mappings.jrag index fb7c296cdd1c888488bda1a3ce3cb6399044de2e..aa070695a83e31f819d62308b094679b27125a8e 100644 --- a/ragconnect.base/src/main/jastadd/Mappings.jrag +++ b/ragconnect.base/src/main/jastadd/Mappings.jrag @@ -191,14 +191,6 @@ aspect Mappings { // --- suitableReceiveDefaultMapping --- syn DefaultMappingDefinition EndpointDefinition.suitableReceiveDefaultMapping() { - // TODO might be expanded to AttributeEndpointTarget - 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": @@ -226,8 +218,7 @@ aspect Mappings { default: try { TypeDecl typeDecl = program().resolveTypeDecl(targetTypeName()); - // TODO: also support list-types, if list is first type - return ragconnect().defaultBytesToTreeMapping(typeDecl.getName()); + return getEndpointTarget().isTypeEndpointTarget() && typeIsList() && !getIndexBasedListAccess() ? ragconnect().defaultBytesToListTreeMapping(typeDecl.getName()) : ragconnect().defaultBytesToTreeMapping(typeDecl.getName()); } catch (Exception ignore) { } System.err.println("Could not find suitable default mapping for " + targetTypeName() + " on " + this); @@ -237,10 +228,6 @@ aspect Mappings { // --- suitableSendDefaultMapping --- syn DefaultMappingDefinition EndpointDefinition.suitableSendDefaultMapping() { - // TODO might be expanded to AttributeEndpointTarget - if (getEndpointTarget().isTypeEndpointTarget() && typeIsList() && !getIndexBasedListAccess()) { - return ragconnect().defaultListTreeToBytesMapping(); - } switch (targetTypeName()) { case "boolean": case "Boolean": @@ -266,6 +253,9 @@ aspect Mappings { case "String": return ragconnect().defaultStringToBytesMapping(); default: + if (getEndpointTarget().isTypeEndpointTarget() && typeIsList() && !getIndexBasedListAccess()) { + return ragconnect().defaultListTreeToBytesMapping(); + } try { TypeDecl typeDecl = program().resolveTypeDecl(targetTypeName()); return ragconnect().defaultTreeToBytesMapping(typeDecl.getName()); diff --git a/ragconnect.base/src/main/jastadd/Navigation.jrag b/ragconnect.base/src/main/jastadd/Navigation.jrag index cb89e315da9c8bff07e1dfb15db07e552aabbd28..dac193142b1382f01b61e696a0f9d5b02dd8b038 100644 --- a/ragconnect.base/src/main/jastadd/Navigation.jrag +++ b/ragconnect.base/src/main/jastadd/Navigation.jrag @@ -1,6 +1,5 @@ aspect NewStuff { - // TODO regenerate for AttributeEndpointTarget /** Tests if EndpointTarget is a TokenEndpointTarget. * @return 'true' if this is a TokenEndpointTarget, otherwise 'false' */ diff --git a/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag b/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag index 3de934126aa88278d14488ee61638841170c1f16..04e8cadc459653830e5f29e2d189b1aa2c6c0ad5 100644 --- a/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag +++ b/ragconnect.base/src/main/jastadd/parser/ParserRewrites.jrag @@ -50,7 +50,7 @@ aspect ParserRewrites { eq UntypedEndpointTarget.parentTypeName() = "<untyped.parentTypeName>"; eq UntypedEndpointTarget.entityName() = "<untyped.entityName>"; eq UntypedEndpointTarget.isAlreadyDefined() = false; - eq UntypedEndpointTarget.entityIsNormalAttribute() = false; + eq UntypedEndpointTarget.hasAttributeResetMethod() = false; eq UntypedEndpointTarget.targetTypeName() = "<untyped.targetTypeName>"; eq UntypedEndpointTarget.isTypeEndpointTarget() = false; } diff --git a/ragconnect.base/src/main/resources/sendDefinition.mustache b/ragconnect.base/src/main/resources/sendDefinition.mustache index 28050973478b56cfa74b39430b16cf347c74d612..18d48cafc978318d3e06b32af8e9f315e75c31a4 100644 --- a/ragconnect.base/src/main/resources/sendDefinition.mustache +++ b/ragconnect.base/src/main/resources/sendDefinition.mustache @@ -97,9 +97,9 @@ public boolean {{parentTypeName}}.{{disconnectMethodName}}(String {{connectParam } protected boolean {{parentTypeName}}.{{updateMethodName}}({{#IndexBasedListAccess}}int index{{/IndexBasedListAccess}}) { - {{^shouldSendValue}} + {{^shouldNotResetValue}} {{tokenResetMethodName}}(); - {{/shouldSendValue}} + {{/shouldNotResetValue}} {{> mappingApplication}} {{lastValueSetter}}({{#IndexBasedListAccess}}index, {{/IndexBasedListAccess}}{{lastResult}}); // normally we would return true here. unless no connect method was called so far to initialize {{senderName}} yet diff --git a/ragconnect.tests/src/test/01-input/errors/Standard.connect b/ragconnect.tests/src/test/01-input/errors/Standard.connect index 6224df4184a2f7cc21d913934785cd022b14f5b0..fb2c7cb2400d1b8ca44903a9aeb3bb0bfcf28537 100644 --- a/ragconnect.tests/src/test/01-input/errors/Standard.connect +++ b/ragconnect.tests/src/test/01-input/errors/Standard.connect @@ -60,6 +60,15 @@ D.SourceDoubledValue canDependOn D.TargetDoubledValue as DoubledValue ; D.SourceDoubledValue canDependOn D.TargetDoubledValue as DoubledValue ; send D.TargetDoubledValue; +// non-existence of attributes is not checked by RagConnect +send A.nonExistingAttribute(int); + +// Already defined endpoints for attributes will be reported, however +send A.nonExistingAttribute(int); + +// mappings are not checked, here string would not match +send A.anotherIntAttribute(int) using StringToString; + // --- mapping definitions --- ListToList maps java.util.List<String> list to java.util.List<String> {: return list; diff --git a/ragconnect.tests/src/test/01-input/errors/Standard.expected b/ragconnect.tests/src/test/01-input/errors/Standard.expected index 9b3d23ac98118e0857ffb9964e1a04d592b1dea1..1f2b02da133cc26bc9660b466112cb73421ab529 100644 --- a/ragconnect.tests/src/test/01-input/errors/Standard.expected +++ b/ragconnect.tests/src/test/01-input/errors/Standard.expected @@ -11,3 +11,5 @@ Standard.connect Line 43, column 1: Endpoint definition already defined for C.Do Standard.connect Line 44, column 1: Endpoint definition already defined for C.DoubledValue Standard.connect Line 55, column 1: The name of a dependency definition must not be equal to a list-node on the source Standard.connect Line 60, column 1: Dependency definition already defined for D with name DoubledValue +Standard.connect Line 64, column 1: Endpoint definition already defined for A.nonExistingAttribute +Standard.connect Line 67, column 1: Endpoint definition already defined for A.nonExistingAttribute diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ForwardingTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ForwardingTest.java index e73f76981cd82034e2fd36d21225b539e8d00e74..570c4d04742d78501f2a206aa4149d1d79d3b9f5 100644 --- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ForwardingTest.java +++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ForwardingTest.java @@ -51,7 +51,7 @@ public class ForwardingTest extends AbstractMqttTest { @Override protected void createModel() { model = new Root(); - model.trace().setReceiver(TestUtils::logEvent); +// model.trace().setReceiver(TestUtils::logEvent); senderRoot = new SenderRoot(); model.setSenderRoot(senderRoot);