diff --git a/public/0.3.2/index.html b/public/0.3.2/index.html
index 363fc0596b7a58f8b1fd8481df6bbbb7dae4496c..42f2b2fc2eed9aa395f5e86c830e25ee47c5dc81 100644
--- a/public/0.3.2/index.html
+++ b/public/0.3.2/index.html
@@ -157,5 +157,5 @@ Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https:/
 
 <!--
 MkDocs version : 1.2.2
-Build Date UTC : 2021-11-24 11:52:02.655024+00:00
+Build Date UTC : 2021-11-24 12:23:46.335676+00:00
 -->
diff --git a/public/0.3.2/search/search_index.json b/public/0.3.2/search/search_index.json
index cecb00920919e45c31a6c0cf106cb2f22c7c5b96..be4ec2a52a494e2f619b390dce16d2ea450170f1 100644
--- a/public/0.3.2/search/search_index.json
+++ b/public/0.3.2/search/search_index.json
@@ -1 +1 @@
-{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"RagConnect Documentation \uf0c1 RagConnect is a preprocessor to enable easy connection to/from models based on Reference Attribute Grammars and Relational Reference Attribute Grammars built with JastAdd .","title":"RagConnect Documentation"},{"location":"#ragconnect-documentation","text":"RagConnect is a preprocessor to enable easy connection to/from models based on Reference Attribute Grammars and Relational Reference Attribute Grammars built with JastAdd .","title":"RagConnect Documentation"},{"location":"adding/","text":"Adding RagConnect to your project \uf0c1 If you want to use RagConnect , either use the latest pre-build version or clone the repository and build it yourself . Use packaged version \uf0c1 Check the package overview page to find the latest version. To use it, three steps are needed. First add this GitLab as a repository in your build.gradle : repositories { maven { name \"gitlab-maven\" url \"https://git-st.inf.tu-dresden.de/api/v4/groups/jastadd/-/packages/maven\" } } Next, add RagConnect as a dependency: configurations { ragconnectClasspath } dependencies { ragconnectClasspath group: 'de.tudresden.inf.st', name: 'ragconnect', version: '0.2.3' } Finally, add a task to compile your specification: task ragConnect(type: JavaExec) { group = 'Build' main = 'org.jastadd.ragconnect.compiler.Compiler' classpath = configurations.ragconnectClasspath args([ '--verbose', '--o=src/gen/jastadd', 'src/main/jastadd/GoalModel.relast', 'src/main/jastadd/GoalModel.connect', '--rootNode=GoalModel' ]) } You might need to add another task for compiling relast specifications . Build from source \uf0c1 If you want to plan to extend RagConnect , the suggested way is to first build the jar from the RagConnect repository (if you only want to use it, consider using the packaged version ). git clone https://git-st.inf.tu-dresden.de/jastadd/ragconnect.git cd ragconnect ./gradlew jar ls ragconnect.base/build/libs/ This ragconnect-<version>.jar can then be copied to your project. Please note, that you can safely use ragconnect.jar as filename, because the version can always be printed using java -jar path/to/ragconnect.jar --version . cp ragconnect.base/build/libs/ragconnect-<version>.jar ../your-project/libs/ragconnect.jar cd ../your-project/ Finally, this jar has to be integrated into your build process. In case, Gradle is used, a task could look like the following (example taken from the ros2rag use case ). The path to the jar file may need to be changed according to your project structure. task ragConnect(type: JavaExec) { group = 'Build' main = '-jar' args([ '../libs/ragconnect.jar', '--verbose', '--o=src/gen/jastadd', 'src/main/jastadd/GoalModel.relast', 'src/main/jastadd/GoalModel.connect', '--rootNode=GoalModel' ]) } You might need to add another task for compiling relast specifications . Compiling RelAst specifications \uf0c1 The task to compile RagConnect specifications is typically accompanied by a task to invoke the RelAst compiler and the JastAdd gradle plugin . Currently, the parameter --useJastAddNames is required , and it may cause incompatibilities if not set. The additional arguments --listClass , --jastAddList and --resolverHelper to relast are not required. Please see the user manual of the RelAst compiler for more information. task relastToJastAdd(type: JavaExec) { group = 'Build' main = \"-jar\" args([\"../libs/relast.jar\", \"--grammarName=./src/gen/jastadd/model\", \"--useJastAddNames\", \"--listClass=java.util.ArrayList\", \"--jastAddList=JastAddList\", \"--resolverHelper\", \"--file\", \"src/gen/jastadd/GoalModel.relast\", \"src/gen/jastadd/RagConnect.relast\"]) } jastadd { ... } One also has to specify the dependencies to get correct ordering of tasks. generateAst.dependsOn relastToJastAdd relastToJastAdd.dependsOn ragConnect","title":"Adding RagConnect to your project"},{"location":"adding/#adding-ragconnect-to-your-project","text":"If you want to use RagConnect , either use the latest pre-build version or clone the repository and build it yourself .","title":"Adding RagConnect to your project"},{"location":"adding/#use-packaged-version","text":"Check the package overview page to find the latest version. To use it, three steps are needed. First add this GitLab as a repository in your build.gradle : repositories { maven { name \"gitlab-maven\" url \"https://git-st.inf.tu-dresden.de/api/v4/groups/jastadd/-/packages/maven\" } } Next, add RagConnect as a dependency: configurations { ragconnectClasspath } dependencies { ragconnectClasspath group: 'de.tudresden.inf.st', name: 'ragconnect', version: '0.2.3' } Finally, add a task to compile your specification: task ragConnect(type: JavaExec) { group = 'Build' main = 'org.jastadd.ragconnect.compiler.Compiler' classpath = configurations.ragconnectClasspath args([ '--verbose', '--o=src/gen/jastadd', 'src/main/jastadd/GoalModel.relast', 'src/main/jastadd/GoalModel.connect', '--rootNode=GoalModel' ]) } You might need to add another task for compiling relast specifications .","title":"Use packaged version"},{"location":"adding/#build-from-source","text":"If you want to plan to extend RagConnect , the suggested way is to first build the jar from the RagConnect repository (if you only want to use it, consider using the packaged version ). git clone https://git-st.inf.tu-dresden.de/jastadd/ragconnect.git cd ragconnect ./gradlew jar ls ragconnect.base/build/libs/ This ragconnect-<version>.jar can then be copied to your project. Please note, that you can safely use ragconnect.jar as filename, because the version can always be printed using java -jar path/to/ragconnect.jar --version . cp ragconnect.base/build/libs/ragconnect-<version>.jar ../your-project/libs/ragconnect.jar cd ../your-project/ Finally, this jar has to be integrated into your build process. In case, Gradle is used, a task could look like the following (example taken from the ros2rag use case ). The path to the jar file may need to be changed according to your project structure. task ragConnect(type: JavaExec) { group = 'Build' main = '-jar' args([ '../libs/ragconnect.jar', '--verbose', '--o=src/gen/jastadd', 'src/main/jastadd/GoalModel.relast', 'src/main/jastadd/GoalModel.connect', '--rootNode=GoalModel' ]) } You might need to add another task for compiling relast specifications .","title":"Build from source"},{"location":"adding/#compiling-relast-specifications","text":"The task to compile RagConnect specifications is typically accompanied by a task to invoke the RelAst compiler and the JastAdd gradle plugin . Currently, the parameter --useJastAddNames is required , and it may cause incompatibilities if not set. The additional arguments --listClass , --jastAddList and --resolverHelper to relast are not required. Please see the user manual of the RelAst compiler for more information. task relastToJastAdd(type: JavaExec) { group = 'Build' main = \"-jar\" args([\"../libs/relast.jar\", \"--grammarName=./src/gen/jastadd/model\", \"--useJastAddNames\", \"--listClass=java.util.ArrayList\", \"--jastAddList=JastAddList\", \"--resolverHelper\", \"--file\", \"src/gen/jastadd/GoalModel.relast\", \"src/gen/jastadd/RagConnect.relast\"]) } jastadd { ... } One also has to specify the dependencies to get correct ordering of tasks. generateAst.dependsOn relastToJastAdd relastToJastAdd.dependsOn ragConnect","title":"Compiling RelAst specifications"},{"location":"changelog/","text":"Changelog \uf0c1 0.3.2 \uf0c1 Allow connection endpoints for list nonterminals ( #21 ) Ensure correct connect and disconnect functionality ( #31 ) Enhance documentation ( #13 , #20 , #41 ) 0.3.1 \uf0c1 Full support for incremental dependency tracking Full support for subtree endpoint definitions ( #9 ) Internal: Use updated gradle plugin for tests ( #18 ) Bugfix #22 : Correct handling of malformed URIs passed when connecting an endpoint Bugfix #23 : Correct handling of OptComponents as endpoints Bugfix #27 : Correctly handle whitespaces in grammars 0.3.0 \uf0c1 Added API documentation to documentation Add methods to disconnect an endpoint Internal: PoC for incremental dependency tracking and subtree endpoint definitions ( #14 ) Bugfix #17 : Added missing support for boolean 0.2.2 \uf0c1 Allow normal tokens to be used in send definitions 0.2.1 \uf0c1 New communication protocol: REST Selection of protocol when connect methods are called, by scheme of given URI Development changes: Supported printing out YAML data used for mustache templates Moved string constants to MRagConnect structure 0.2.0 \uf0c1 Version submitted in paper \"A Connection from ROS to RAG-Based Models\" (2020) Supported communication protocols: MQTT","title":"Changelog"},{"location":"changelog/#changelog","text":"","title":"Changelog"},{"location":"changelog/#032","text":"Allow connection endpoints for list nonterminals ( #21 ) Ensure correct connect and disconnect functionality ( #31 ) Enhance documentation ( #13 , #20 , #41 )","title":"0.3.2"},{"location":"changelog/#031","text":"Full support for incremental dependency tracking Full support for subtree endpoint definitions ( #9 ) Internal: Use updated gradle plugin for tests ( #18 ) Bugfix #22 : Correct handling of malformed URIs passed when connecting an endpoint Bugfix #23 : Correct handling of OptComponents as endpoints Bugfix #27 : Correctly handle whitespaces in grammars","title":"0.3.1"},{"location":"changelog/#030","text":"Added API documentation to documentation Add methods to disconnect an endpoint Internal: PoC for incremental dependency tracking and subtree endpoint definitions ( #14 ) Bugfix #17 : Added missing support for boolean","title":"0.3.0"},{"location":"changelog/#022","text":"Allow normal tokens to be used in send definitions","title":"0.2.2"},{"location":"changelog/#021","text":"New communication protocol: REST Selection of protocol when connect methods are called, by scheme of given URI Development changes: Supported printing out YAML data used for mustache templates Moved string constants to MRagConnect structure","title":"0.2.1"},{"location":"changelog/#020","text":"Version submitted in paper \"A Connection from ROS to RAG-Based Models\" (2020) Supported communication protocols: MQTT","title":"0.2.0"},{"location":"compiler/","text":"Compiler options \uf0c1 The compiler is JastAdd-compliant, i.e., it accepts all flags available for JastAdd, though there is no process how to chain pre-processors yet . Additional options are as follows. Name Required (Default) Description --rootNode Yes Root node in the base grammar. --protocols No ( mqtt ) Protocols to enable, currently available: mqtt, rest . --printYaml No (false) Print out YAML instead of generating files. --verbose No (false) Print more messages while compiling. --logReads No (false) Enable logging for every received message. --logWrites No (false) Enable logging for every sent message. --logIncremental No (false) Enable logging for observer in incremental dependency tracking. --experimental-jastadd-329 No (false) Use trace events INC_FLUSH_START and INC_FLUSH_END ( JastAdd issue #329 ), see section about automatic dependency tracking . --incremental No (false) Enables incremental dependency tracking (if trace is also set appropriately). --trace[=flush] No (false) Enables incremental dependency tracking (if incremental is also set appropriately). --version No (false) Print version info and exit (reused JastAdd option) --o No ( . ) Output directory (reused JastAdd option) All files to be process have to be passed as arguments. Their type is decided by the file extension ( ast and relast for input grammars, connect and ragconnect for RagConnect definitions file). Additional software dependencies \uf0c1 Using RagConnect itself does not introduce dependencies. However, depending on the selected protocols and/or used features, additional dependencies are required when using the generated code. Communication protocol characteristics \uf0c1 MQTT \uf0c1 Protocol identifier: mqtt URI scheme: mqtt://<broker-host>[:port]/<topic> Default port: 1883 Type for mapping definitions: byte[] Required runtime dependencies: group: 'org.fusesource.mqtt-client', name: 'mqtt-client', version: '1.15' Additional remarks: First leading slash not included in topic. Mqtt is selected by default, so this dependency therefore is required \"by default\". Might work with other versions of org.fusesource.mqtt-client.mqtt.client as well. REST \uf0c1 Protocol identifier: rest URI scheme: rest://localhost[:port]/<path> Default port: 4567 Type for mapping definitions: String Required runtime dependencies: group: 'com.sparkjava', name: 'spark-core', version: '2.9.3' Additional remarks: Host is always localhost . Might work with newer versions of com.sparkjava.spark-core as well. For debugging, it is beneficial to include an implementation for SLF4J . Used features \uf0c1 Automatic dependency tracking \uf0c1 Condition: When passing --incremental and --trace=flush to RagConnect Required runtime dependencies: none Required options for RelAST compiler: none Required options for JastAdd: --incremental --trace=flush Remarks: Other (additional) values passed to those two options must be equal (e.g., --incremental=param passed to RagConnect must be also passed to JastAdd) Other values besides flush can be added to --trace Feature description (Safer) Automatic dependency tracking \uf0c1 Condition: When passing --experimental-jastadd-329 to RagConnect Required runtime dependencies: none Required options for RelAST compiler: none Required options for JastAdd: none Remarks: JastAdd version has to support INC_FLUSH_START and INC_FLUSH_END (i.e., has issue #329 resolved) Feature description Tree/List Endpoints \uf0c1 Condition: When using tree or list endpoints along with default mappings Required runtime dependencies: group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.12.1' group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.1' Required options for RelAST compiler: --serializer=jackson Required options for JastAdd: none Remarks: Feature description","title":"Compiler options"},{"location":"compiler/#compiler-options","text":"The compiler is JastAdd-compliant, i.e., it accepts all flags available for JastAdd, though there is no process how to chain pre-processors yet . Additional options are as follows. Name Required (Default) Description --rootNode Yes Root node in the base grammar. --protocols No ( mqtt ) Protocols to enable, currently available: mqtt, rest . --printYaml No (false) Print out YAML instead of generating files. --verbose No (false) Print more messages while compiling. --logReads No (false) Enable logging for every received message. --logWrites No (false) Enable logging for every sent message. --logIncremental No (false) Enable logging for observer in incremental dependency tracking. --experimental-jastadd-329 No (false) Use trace events INC_FLUSH_START and INC_FLUSH_END ( JastAdd issue #329 ), see section about automatic dependency tracking . --incremental No (false) Enables incremental dependency tracking (if trace is also set appropriately). --trace[=flush] No (false) Enables incremental dependency tracking (if incremental is also set appropriately). --version No (false) Print version info and exit (reused JastAdd option) --o No ( . ) Output directory (reused JastAdd option) All files to be process have to be passed as arguments. Their type is decided by the file extension ( ast and relast for input grammars, connect and ragconnect for RagConnect definitions file).","title":"Compiler options"},{"location":"compiler/#additional-software-dependencies","text":"Using RagConnect itself does not introduce dependencies. However, depending on the selected protocols and/or used features, additional dependencies are required when using the generated code.","title":"Additional software dependencies"},{"location":"compiler/#communication-protocol-characteristics","text":"","title":"Communication protocol characteristics"},{"location":"compiler/#mqtt","text":"Protocol identifier: mqtt URI scheme: mqtt://<broker-host>[:port]/<topic> Default port: 1883 Type for mapping definitions: byte[] Required runtime dependencies: group: 'org.fusesource.mqtt-client', name: 'mqtt-client', version: '1.15' Additional remarks: First leading slash not included in topic. Mqtt is selected by default, so this dependency therefore is required \"by default\". Might work with other versions of org.fusesource.mqtt-client.mqtt.client as well.","title":"MQTT"},{"location":"compiler/#rest","text":"Protocol identifier: rest URI scheme: rest://localhost[:port]/<path> Default port: 4567 Type for mapping definitions: String Required runtime dependencies: group: 'com.sparkjava', name: 'spark-core', version: '2.9.3' Additional remarks: Host is always localhost . Might work with newer versions of com.sparkjava.spark-core as well. For debugging, it is beneficial to include an implementation for SLF4J .","title":"REST"},{"location":"compiler/#used-features","text":"","title":"Used features"},{"location":"compiler/#automatic-dependency-tracking","text":"Condition: When passing --incremental and --trace=flush to RagConnect Required runtime dependencies: none Required options for RelAST compiler: none Required options for JastAdd: --incremental --trace=flush Remarks: Other (additional) values passed to those two options must be equal (e.g., --incremental=param passed to RagConnect must be also passed to JastAdd) Other values besides flush can be added to --trace Feature description","title":"Automatic dependency tracking"},{"location":"compiler/#safer-automatic-dependency-tracking","text":"Condition: When passing --experimental-jastadd-329 to RagConnect Required runtime dependencies: none Required options for RelAST compiler: none Required options for JastAdd: none Remarks: JastAdd version has to support INC_FLUSH_START and INC_FLUSH_END (i.e., has issue #329 resolved) Feature description","title":"(Safer) Automatic dependency tracking"},{"location":"compiler/#treelist-endpoints","text":"Condition: When using tree or list endpoints along with default mappings Required runtime dependencies: group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.12.1' group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.1' Required options for RelAST compiler: --serializer=jackson Required options for JastAdd: none Remarks: Feature description","title":"Tree/List Endpoints"},{"location":"extending/","text":"Extending RagConnect \uf0c1 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 : 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 . 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 ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/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 Furthermore, new test cases are appreciated, see below . Writing Tests \uf0c1 To add new tests, have a look at the module ragconnect.tests . It has three parts: 1) In src/test/01-input/* are the specifications that are going to be compiled (in principle using the steps described in the guide to add RagConnect ). 2) In src/test/java , the jUnit 5 test classes are implemented. They mostly correspond 1-to-1 to a directory of the first part. 3) In build.gradle the instructions how to compile the specifications using the gradle plugin PreprocessorPlugin ( org.jastadd.preprocessor:testing ). Specifications \uf0c1 Every specification must have at least a README.md to describe the purpose of the test, a grammar Test.relast , and a RagConnect specification Test.connect . Usually an aspect file Test.jadd is included. Test Classes \uf0c1 Based on jUnit 5, the test classes testing some behaviour. If sending and/or receiving functionality is used, consider extending AbstractMqttTest in order to avoid duplicate code. In case of extending this class, please order the methods according to their lifecycle, i.e.: - createModel - setupReceiverAndConnect - communicateSendInitialValue - communicateOnlyUpdatedValue - closeConnections Within AbstractMqttTest , an MqttHandler named publisher is available to publish content. Some convenience methods are provided in TestUtils , e.g., the DefaultMappings , and mqttUri to prepend \"mqtt://\" and the correct host for the mqtt broker ( localhost or a CI-specific host). All tests are required to run both locally, and within the CI. build.gradle \uf0c1 Use the PreprocessorPlugin , the build process can be written concisely in three parts per task: task compileTreeAllowedTokens(type: RagConnectTest) { ragconnect { outputDir = file('src/test/02-after-ragconnect/treeAllowedTokens') inputFiles = [file('src/test/01-input/treeAllowedTokens/Test.relast'), file('src/test/01-input/treeAllowedTokens/Test.connect'), file('src/test/01-input/treeAllowedTokens/TestDependencies.connect')] rootNode = 'Root' } relast { useJastAddNames = true grammarName = 'src/test/03-after-relast/treeAllowedTokens/treeAllowedTokens' serializer = 'jackson' } jastadd { jastAddList = 'JastAddList' packageName = 'treeAllowedTokens.ast' inputFiles = [file('src/test/01-input/treeAllowedTokens/Test.jadd')] } }","title":"Extending RagConnect"},{"location":"extending/#extending-ragconnect","text":"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 : 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 . 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 ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/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 Furthermore, new test cases are appreciated, see below .","title":"Extending RagConnect"},{"location":"extending/#writing-tests","text":"To add new tests, have a look at the module ragconnect.tests . It has three parts: 1) In src/test/01-input/* are the specifications that are going to be compiled (in principle using the steps described in the guide to add RagConnect ). 2) In src/test/java , the jUnit 5 test classes are implemented. They mostly correspond 1-to-1 to a directory of the first part. 3) In build.gradle the instructions how to compile the specifications using the gradle plugin PreprocessorPlugin ( org.jastadd.preprocessor:testing ).","title":"Writing Tests"},{"location":"extending/#specifications","text":"Every specification must have at least a README.md to describe the purpose of the test, a grammar Test.relast , and a RagConnect specification Test.connect . Usually an aspect file Test.jadd is included.","title":"Specifications"},{"location":"extending/#test-classes","text":"Based on jUnit 5, the test classes testing some behaviour. If sending and/or receiving functionality is used, consider extending AbstractMqttTest in order to avoid duplicate code. In case of extending this class, please order the methods according to their lifecycle, i.e.: - createModel - setupReceiverAndConnect - communicateSendInitialValue - communicateOnlyUpdatedValue - closeConnections Within AbstractMqttTest , an MqttHandler named publisher is available to publish content. Some convenience methods are provided in TestUtils , e.g., the DefaultMappings , and mqttUri to prepend \"mqtt://\" and the correct host for the mqtt broker ( localhost or a CI-specific host). All tests are required to run both locally, and within the CI.","title":"Test Classes"},{"location":"extending/#buildgradle","text":"Use the PreprocessorPlugin , the build process can be written concisely in three parts per task: task compileTreeAllowedTokens(type: RagConnectTest) { ragconnect { outputDir = file('src/test/02-after-ragconnect/treeAllowedTokens') inputFiles = [file('src/test/01-input/treeAllowedTokens/Test.relast'), file('src/test/01-input/treeAllowedTokens/Test.connect'), file('src/test/01-input/treeAllowedTokens/TestDependencies.connect')] rootNode = 'Root' } relast { useJastAddNames = true grammarName = 'src/test/03-after-relast/treeAllowedTokens/treeAllowedTokens' serializer = 'jackson' } jastadd { jastAddList = 'JastAddList' packageName = 'treeAllowedTokens.ast' inputFiles = [file('src/test/01-input/treeAllowedTokens/Test.jadd')] } }","title":"build.gradle"},{"location":"inner-workings/","text":"Inner workings of RagConnect \uf0c1 Please see API documentation for more details. RagConnect uses the 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 (currently its Java version ) 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 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.","title":"Inner workings"},{"location":"inner-workings/#inner-workings-of-ragconnect","text":"Please see API documentation for more details. RagConnect uses the 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 (currently its Java version ) 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 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.","title":"Inner workings of RagConnect"},{"location":"use_cases/","text":"Use cases with RagConnect \uf0c1 MPM4CPS Paper - Codename 'Ros2Rag' \uf0c1 In the publication \"Connecting conceptual models using Relational Reference Attribute Grammars\" , a use case involving a simulated robot arm and two different models connected to it was shown. One model was used to ensure a low speed of the robot when within a safety zone (purple boxes in the picture below), and the other model executes a workflow to control the robot. \ud83d\udcfd Recording of the simulated robot during the use case This paper was presented on October, 16h during the MPM4CPS workshop within the MODELS 2020 conference . For more information, see the presented slides or the a recording of the session . There is also a poster and a pre-recorded presentation of this poster. The repository with the used source code can be found at: https://git-st.inf.tu-dresden.de/ceti/ros/mpm4cps2020 The usage is dockerized, so starting the application only involves the commands listed below. As ROS takes some time to start up, it is best to use separate terminals for the three applications (ROS, Safety-Model, Goal-Model): # Preparation (only need once) ./prepare-docker-compose.sh docker-compose up -d mosquitto # Starts the MQTT broker # Terminal 1: ROS docker-compose up --build ros # Wait until you see no more new logging output # Terminal 2: Safety-Model docker-compose up rag_app # Terminal 3: Goal-Model docker-compose up rag_goal","title":"Use Cases"},{"location":"use_cases/#use-cases-with-ragconnect","text":"","title":"Use cases with RagConnect"},{"location":"use_cases/#mpm4cps-paper-codename-ros2rag","text":"In the publication \"Connecting conceptual models using Relational Reference Attribute Grammars\" , a use case involving a simulated robot arm and two different models connected to it was shown. One model was used to ensure a low speed of the robot when within a safety zone (purple boxes in the picture below), and the other model executes a workflow to control the robot. \ud83d\udcfd Recording of the simulated robot during the use case This paper was presented on October, 16h during the MPM4CPS workshop within the MODELS 2020 conference . For more information, see the presented slides or the a recording of the session . There is also a poster and a pre-recorded presentation of this poster. The repository with the used source code can be found at: https://git-st.inf.tu-dresden.de/ceti/ros/mpm4cps2020 The usage is dockerized, so starting the application only involves the commands listed below. As ROS takes some time to start up, it is best to use separate terminals for the three applications (ROS, Safety-Model, Goal-Model): # Preparation (only need once) ./prepare-docker-compose.sh docker-compose up -d mosquitto # Starts the MQTT broker # Terminal 1: ROS docker-compose up --build ros # Wait until you see no more new logging output # Terminal 2: Safety-Model docker-compose up rag_app # Terminal 3: Goal-Model docker-compose up rag_goal","title":"MPM4CPS Paper - Codename 'Ros2Rag'"},{"location":"using/","text":"Using RagConnect -- an example \uf0c1 The full example is available at https://git-st.inf.tu-dresden.de/jastadd/ragconnect-minimal . Preparation and Specification \uf0c1 The following examples are inspired by the real test case read1write2 The idea is to have two nonterminals, where input information is received on one of them, and - after transformation - is sent out by both. Let the following grammar be used: A ::= <Input:String> /<OutputOnA:String>/ B* ; B ::= /<OutputOnB:String>/ ; To declare receiving and sending tokens, a dedicated DSL is used: // endpoint definitions receive A.Input ; send A.OutputOnA ; send B.OutputOnB using Transformation ; // mapping definitions Transformation maps String s to String {: return s + \"postfix\"; :} This defines A.Input to receive updates, and the other two tokens to send their value, whenever it changes. Additionally, a transformation will be applied on B.OutputOnB before sending out its value. Such mapping definitions can be defined for receiving tokens as well. In this case, they are applied before the value is set. If no mapping definition is given, or if the required type (depending on the communication protocol, see later) does not match, a \"default mapping definition\" is used to avoid boilerplate code converting from or to primitive types. Furthermore, let the following attribute definitions be given: syn String A.getOutputOnA() = \"a\" + getInput(); syn String B.getOutputOnB() = \"b\" + input(); inh String B.input(); eq A.getB().input() = getInput(); In other words, OutputOnA depends on Input of the same node, and OutputOnB depends on Input of its parent node. Currently, those dependencies can be explicitly written down, or incremental evaluation can be used. Dependency tracking: Manually specified \uf0c1 This specification happens also in the DSL (dependencies have to be named to uniquely identify them): // dependency definitions A.OutputOnA canDependOn A.Input as dependencyA ; B.OutputOnB canDependOn A.Input as dependencyB ; Dependency tracking: Automatically derived \uf0c1 To automatically track dependencies, the two additional parameters --incremental and --trace=flush have to be provided to both RagConnect and (in the later stage) JastAdd. This will generate a different implementation of RagConnect relying on enabled incremental evaluation of JastAdd. The value for incremental has only been tested for incremental=param . The value for trace can include other values besides flush . An experimental, optimized version can be selected using --experimental-jastadd-329 reducing the risk of conflicts between concurrent attribute evaluations. However, this requires a version of JastAdd that resolved the issue 329 . Using generated code \uf0c1 After specifying everything, code will be generated if setup properly . Let's create an AST in some driver code: A a = new A(); // set some default value for input a.setInput(\"\"); B b1 = new B(); B b2 = new B(); a.addB(b1); a.addB(b2); If necessary, we have to set the dependencies as described earlier . // a.OutputOnA -> a.Input a.addDependencyA(a); // b1.OutputOnB -> a.Input b1.addDependencyB(a); // b2.OutputOnB -> a.Input b2.addDependencyB(a); Finally, we can actually connect the tokens. Depending on the enabled protocols, different URI schemes are allowed . In this example, we use the default protocol: MQTT. a.connectInput(\"mqtt://localhost/topic/for/input\"); a.connectOutputOnA(\"mqtt://localhost/a/out\", true); b1.connectOutputOnB(\"mqtt://localhost/b1/out\", true); b2.connectOutputOnB(\"mqtt://localhost/b2/out\", false); The first parameter of those connect-methods is always an URI-like String, to identify the protocol to use, the server operating the protocol, and a path to identify the concrete token. In case of MQTT, the server is the host running an MQTT broker, and the path is equal to the topic to publish or subscribe to. Please note, that the first leading slash ( / ) is removed for MQTT topics, e.g., for A.Input the topic is actually topic/for/input . For sending endpoints, there is a second boolean parameter to specify whether the current value shall be sent immediately after connecting. Remarks for using manual dependency tracking \uf0c1 When constructing the AST and connecting it, one should always set dependencies before connecting, especially if updates already arriving for receiving endpoints. Otherwise, updates might not be propagated after setting dependencies, if values are equal after applying transformations of mapping definitions. As an example, when using the following grammar and definitions for RagConnect ... A ::= <Input:int> /<Output:String>/ ; receive A.Input using Round ; send A.Output ; A.Output canDependOn A.Input as dependency1 ; Round maps float f to int {: return Math.round(f); :} ... connecting first could mean to store the first rounded value and not propagating this update, since no dependencies are set, and not propagating further updates leading to the same rounded value even after setting the dependencies. An advanced example \uf0c1 Non-terminal children can also be selected as endpoints (not only tokens). Normal Non-Terminal Children \uf0c1 Receiving normal non-terminal children and optionals means to replace them with a new node deserialized from the received message. Sending them involves serializing a node, and sending this representation in a message. Suppose, the following (shortened) grammar is used (inspired from the testcase tree ) Root ::= SenderRoot ReceiverRoot ; SenderRoot ::= <Input:int> /Alfa/ ; ReceiverRoot ::= Alfa ; Alfa ::= // some content ... Now, the complete node of type Alfa can be sent, and received again using the following connect specification: send tree SenderRoot.Alfa ; receive tree ReceiverRoot.Alfa ; Currently, receiving and sending trees requires the explicit demarcation from tokens using the keyword tree . To process non-terminals, default mappings are provided for every non-terminal type of the used grammar. They use the JSON serialization offered by the RelAST compiler, i.e., interpret the message as a String , deserialize the content reading the message as JSON, or vice versa. Additional dependencies are required to use this feature, as detailed in the compiler section . Receiving List Children \uf0c1 When receiving list children, there are a few more options to match the connection to given requirements. Suppose we use a similar grammar as above, i.e.: SenderRoot ::= /AlfaList:Alfa*/ /SingleAlfa:Alfa/; ReceiverRoot ::= Alfa* ; Several options are possible: list \uf0c1 A message for a list endpoint can be interpreted as a complete list (a sequence of nodes of type Alfa ) by using the list keyword instead of tree : receive list ReceiverRoot.Alfa ; list + with add \uf0c1 Upon receiving the message, the deserialized list can also be appended to the existing list instead of replace the latter. This can be achieved using the keyword with add in addition to the keyword list : receive list with add ReceiverRoot.Alfa ; tree (indexed) \uf0c1 A message for a list endpoint can also be interpreted as an element of this list. receive tree ReceiverRoot.Alfa ; Upon connection, the index of the deserialized element to set, has to be passed ( 1 in the example below). The list must have enough elements once a message is received. receiverRoot.connectAlfa(\"<some-url>\", 1); tree (wildcard) \uf0c1 Similar to the tree (indexed) case above, messages are interpreted as an element of the list, but the connection can also be made using a \"wildcard topic\" and without an index. Then, once a message is received from a new concrete topic, the deserialized element will be appended to the list and this topic is associated with the index of the newly added element. Any further message from that topic will replace the element at the associated index. In the short example below, MQTT is used to with a wildcard topic, as # matches every sub-topic. receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/#\"); // list is initially empty assertEquals(receiverRoot.getAlfaList(), list()); // after receiving \"1\" on new topic \"some/topic/one\" (index 0) assertEquals(receiverRoot.getAlfaList(), list(\"1\")); // after receiving \"other\" on new topic \"some/topic/two\" (index 1) assertEquals(receiverRoot.getAlfaList(), list(\"1\", \"other\")); // after receiving \"new\" on existing topic \"some/topic/one\" (index 0) assertEquals(receiverRoot.getAlfaList(), list(\"new\", \"other\")); tree (indexed/wildcard) + with add \uf0c1 Combining tree and with add results in a connection, where messages are interpreted as elements of the list, and new elements are appended to the existing list. In that case, wildcard and non-wildcard connections behave in the same way, as no index has to be passed, and the element is always append at the end. Reusing the example from above, the following observations can be made. receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/#\"); // or receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/one\"); receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/two\"); // list is initially empty assertEquals(receiverRoot.getAlfaList(), list()); // after receiving \"1\" on topic \"some/topic/one\" assertEquals(receiverRoot.getAlfaList(), list(\"1\")); // after receiving \"other\" on topic \"some/topic/two\" assertEquals(receiverRoot.getAlfaList(), list(\"1\", \"other\")); // after receiving \"new\" on topic \"some/topic/one\" assertEquals(receiverRoot.getAlfaList(), list(\"1\", \"other\", \"new\"));","title":"RagConnect by Example"},{"location":"using/#using-ragconnect-an-example","text":"The full example is available at https://git-st.inf.tu-dresden.de/jastadd/ragconnect-minimal .","title":"Using RagConnect -- an example"},{"location":"using/#preparation-and-specification","text":"The following examples are inspired by the real test case read1write2 The idea is to have two nonterminals, where input information is received on one of them, and - after transformation - is sent out by both. Let the following grammar be used: A ::= <Input:String> /<OutputOnA:String>/ B* ; B ::= /<OutputOnB:String>/ ; To declare receiving and sending tokens, a dedicated DSL is used: // endpoint definitions receive A.Input ; send A.OutputOnA ; send B.OutputOnB using Transformation ; // mapping definitions Transformation maps String s to String {: return s + \"postfix\"; :} This defines A.Input to receive updates, and the other two tokens to send their value, whenever it changes. Additionally, a transformation will be applied on B.OutputOnB before sending out its value. Such mapping definitions can be defined for receiving tokens as well. In this case, they are applied before the value is set. If no mapping definition is given, or if the required type (depending on the communication protocol, see later) does not match, a \"default mapping definition\" is used to avoid boilerplate code converting from or to primitive types. Furthermore, let the following attribute definitions be given: syn String A.getOutputOnA() = \"a\" + getInput(); syn String B.getOutputOnB() = \"b\" + input(); inh String B.input(); eq A.getB().input() = getInput(); In other words, OutputOnA depends on Input of the same node, and OutputOnB depends on Input of its parent node. Currently, those dependencies can be explicitly written down, or incremental evaluation can be used.","title":"Preparation and Specification"},{"location":"using/#dependency-tracking-manually-specified","text":"This specification happens also in the DSL (dependencies have to be named to uniquely identify them): // dependency definitions A.OutputOnA canDependOn A.Input as dependencyA ; B.OutputOnB canDependOn A.Input as dependencyB ;","title":"Dependency tracking: Manually specified"},{"location":"using/#dependency-tracking-automatically-derived","text":"To automatically track dependencies, the two additional parameters --incremental and --trace=flush have to be provided to both RagConnect and (in the later stage) JastAdd. This will generate a different implementation of RagConnect relying on enabled incremental evaluation of JastAdd. The value for incremental has only been tested for incremental=param . The value for trace can include other values besides flush . An experimental, optimized version can be selected using --experimental-jastadd-329 reducing the risk of conflicts between concurrent attribute evaluations. However, this requires a version of JastAdd that resolved the issue 329 .","title":"Dependency tracking: Automatically derived"},{"location":"using/#using-generated-code","text":"After specifying everything, code will be generated if setup properly . Let's create an AST in some driver code: A a = new A(); // set some default value for input a.setInput(\"\"); B b1 = new B(); B b2 = new B(); a.addB(b1); a.addB(b2); If necessary, we have to set the dependencies as described earlier . // a.OutputOnA -> a.Input a.addDependencyA(a); // b1.OutputOnB -> a.Input b1.addDependencyB(a); // b2.OutputOnB -> a.Input b2.addDependencyB(a); Finally, we can actually connect the tokens. Depending on the enabled protocols, different URI schemes are allowed . In this example, we use the default protocol: MQTT. a.connectInput(\"mqtt://localhost/topic/for/input\"); a.connectOutputOnA(\"mqtt://localhost/a/out\", true); b1.connectOutputOnB(\"mqtt://localhost/b1/out\", true); b2.connectOutputOnB(\"mqtt://localhost/b2/out\", false); The first parameter of those connect-methods is always an URI-like String, to identify the protocol to use, the server operating the protocol, and a path to identify the concrete token. In case of MQTT, the server is the host running an MQTT broker, and the path is equal to the topic to publish or subscribe to. Please note, that the first leading slash ( / ) is removed for MQTT topics, e.g., for A.Input the topic is actually topic/for/input . For sending endpoints, there is a second boolean parameter to specify whether the current value shall be sent immediately after connecting.","title":"Using generated code"},{"location":"using/#remarks-for-using-manual-dependency-tracking","text":"When constructing the AST and connecting it, one should always set dependencies before connecting, especially if updates already arriving for receiving endpoints. Otherwise, updates might not be propagated after setting dependencies, if values are equal after applying transformations of mapping definitions. As an example, when using the following grammar and definitions for RagConnect ... A ::= <Input:int> /<Output:String>/ ; receive A.Input using Round ; send A.Output ; A.Output canDependOn A.Input as dependency1 ; Round maps float f to int {: return Math.round(f); :} ... connecting first could mean to store the first rounded value and not propagating this update, since no dependencies are set, and not propagating further updates leading to the same rounded value even after setting the dependencies.","title":"Remarks for using manual dependency tracking"},{"location":"using/#an-advanced-example","text":"Non-terminal children can also be selected as endpoints (not only tokens).","title":"An advanced example"},{"location":"using/#normal-non-terminal-children","text":"Receiving normal non-terminal children and optionals means to replace them with a new node deserialized from the received message. Sending them involves serializing a node, and sending this representation in a message. Suppose, the following (shortened) grammar is used (inspired from the testcase tree ) Root ::= SenderRoot ReceiverRoot ; SenderRoot ::= <Input:int> /Alfa/ ; ReceiverRoot ::= Alfa ; Alfa ::= // some content ... Now, the complete node of type Alfa can be sent, and received again using the following connect specification: send tree SenderRoot.Alfa ; receive tree ReceiverRoot.Alfa ; Currently, receiving and sending trees requires the explicit demarcation from tokens using the keyword tree . To process non-terminals, default mappings are provided for every non-terminal type of the used grammar. They use the JSON serialization offered by the RelAST compiler, i.e., interpret the message as a String , deserialize the content reading the message as JSON, or vice versa. Additional dependencies are required to use this feature, as detailed in the compiler section .","title":"Normal Non-Terminal Children"},{"location":"using/#receiving-list-children","text":"When receiving list children, there are a few more options to match the connection to given requirements. Suppose we use a similar grammar as above, i.e.: SenderRoot ::= /AlfaList:Alfa*/ /SingleAlfa:Alfa/; ReceiverRoot ::= Alfa* ; Several options are possible:","title":"Receiving List Children"},{"location":"using/#list","text":"A message for a list endpoint can be interpreted as a complete list (a sequence of nodes of type Alfa ) by using the list keyword instead of tree : receive list ReceiverRoot.Alfa ;","title":"list"},{"location":"using/#list-with-add","text":"Upon receiving the message, the deserialized list can also be appended to the existing list instead of replace the latter. This can be achieved using the keyword with add in addition to the keyword list : receive list with add ReceiverRoot.Alfa ;","title":"list + with add"},{"location":"using/#tree-indexed","text":"A message for a list endpoint can also be interpreted as an element of this list. receive tree ReceiverRoot.Alfa ; Upon connection, the index of the deserialized element to set, has to be passed ( 1 in the example below). The list must have enough elements once a message is received. receiverRoot.connectAlfa(\"<some-url>\", 1);","title":"tree (indexed)"},{"location":"using/#tree-wildcard","text":"Similar to the tree (indexed) case above, messages are interpreted as an element of the list, but the connection can also be made using a \"wildcard topic\" and without an index. Then, once a message is received from a new concrete topic, the deserialized element will be appended to the list and this topic is associated with the index of the newly added element. Any further message from that topic will replace the element at the associated index. In the short example below, MQTT is used to with a wildcard topic, as # matches every sub-topic. receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/#\"); // list is initially empty assertEquals(receiverRoot.getAlfaList(), list()); // after receiving \"1\" on new topic \"some/topic/one\" (index 0) assertEquals(receiverRoot.getAlfaList(), list(\"1\")); // after receiving \"other\" on new topic \"some/topic/two\" (index 1) assertEquals(receiverRoot.getAlfaList(), list(\"1\", \"other\")); // after receiving \"new\" on existing topic \"some/topic/one\" (index 0) assertEquals(receiverRoot.getAlfaList(), list(\"new\", \"other\"));","title":"tree (wildcard)"},{"location":"using/#tree-indexedwildcard-with-add","text":"Combining tree and with add results in a connection, where messages are interpreted as elements of the list, and new elements are appended to the existing list. In that case, wildcard and non-wildcard connections behave in the same way, as no index has to be passed, and the element is always append at the end. Reusing the example from above, the following observations can be made. receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/#\"); // or receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/one\"); receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/two\"); // list is initially empty assertEquals(receiverRoot.getAlfaList(), list()); // after receiving \"1\" on topic \"some/topic/one\" assertEquals(receiverRoot.getAlfaList(), list(\"1\")); // after receiving \"other\" on topic \"some/topic/two\" assertEquals(receiverRoot.getAlfaList(), list(\"1\", \"other\")); // after receiving \"new\" on topic \"some/topic/one\" assertEquals(receiverRoot.getAlfaList(), list(\"1\", \"other\", \"new\"));","title":"tree (indexed/wildcard) + with add"}]}
\ No newline at end of file
+{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"RagConnect Documentation \uf0c1 RagConnect is a preprocessor to enable easy connection to/from models based on Reference Attribute Grammars and Relational Reference Attribute Grammars built with JastAdd .","title":"RagConnect Documentation"},{"location":"#ragconnect-documentation","text":"RagConnect is a preprocessor to enable easy connection to/from models based on Reference Attribute Grammars and Relational Reference Attribute Grammars built with JastAdd .","title":"RagConnect Documentation"},{"location":"adding/","text":"Adding RagConnect to your project \uf0c1 If you want to use RagConnect , either use the latest pre-build version or clone the repository and build it yourself . Use packaged version \uf0c1 Check the package overview page to find the latest version. To use it, three steps are needed. First add this GitLab as a repository in your build.gradle : repositories { maven { name \"gitlab-maven\" url \"https://git-st.inf.tu-dresden.de/api/v4/groups/jastadd/-/packages/maven\" } } Next, add RagConnect as a dependency: configurations { ragconnectClasspath } dependencies { ragconnectClasspath group: 'de.tudresden.inf.st', name: 'ragconnect', version: '0.2.3' } Finally, add a task to compile your specification: task ragConnect(type: JavaExec) { group = 'Build' main = 'org.jastadd.ragconnect.compiler.Compiler' classpath = configurations.ragconnectClasspath args([ '--verbose', '--o=src/gen/jastadd', 'src/main/jastadd/GoalModel.relast', 'src/main/jastadd/GoalModel.connect', '--rootNode=GoalModel' ]) } You might need to add another task for compiling relast specifications . Build from source \uf0c1 If you want to plan to extend RagConnect , the suggested way is to first build the jar from the RagConnect repository (if you only want to use it, consider using the packaged version ). git clone https://git-st.inf.tu-dresden.de/jastadd/ragconnect.git cd ragconnect ./gradlew jar ls ragconnect.base/build/libs/ This ragconnect-<version>.jar can then be copied to your project. Please note, that you can safely use ragconnect.jar as filename, because the version can always be printed using java -jar path/to/ragconnect.jar --version . cp ragconnect.base/build/libs/ragconnect-<version>.jar ../your-project/libs/ragconnect.jar cd ../your-project/ Finally, this jar has to be integrated into your build process. In case, Gradle is used, a task could look like the following (example taken from the ros2rag use case ). The path to the jar file may need to be changed according to your project structure. task ragConnect(type: JavaExec) { group = 'Build' main = '-jar' args([ '../libs/ragconnect.jar', '--verbose', '--o=src/gen/jastadd', 'src/main/jastadd/GoalModel.relast', 'src/main/jastadd/GoalModel.connect', '--rootNode=GoalModel' ]) } You might need to add another task for compiling relast specifications . Compiling RelAst specifications \uf0c1 The task to compile RagConnect specifications is typically accompanied by a task to invoke the RelAst compiler and the JastAdd gradle plugin . Currently, the parameter --useJastAddNames is required , and it may cause incompatibilities if not set. The additional arguments --listClass , --jastAddList and --resolverHelper to relast are not required. Please see the user manual of the RelAst compiler for more information. task relastToJastAdd(type: JavaExec) { group = 'Build' main = \"-jar\" args([\"../libs/relast.jar\", \"--grammarName=./src/gen/jastadd/model\", \"--useJastAddNames\", \"--listClass=java.util.ArrayList\", \"--jastAddList=JastAddList\", \"--resolverHelper\", \"--file\", \"src/gen/jastadd/GoalModel.relast\", \"src/gen/jastadd/RagConnect.relast\"]) } jastadd { ... } One also has to specify the dependencies to get correct ordering of tasks. generateAst.dependsOn relastToJastAdd relastToJastAdd.dependsOn ragConnect","title":"Adding RagConnect to your project"},{"location":"adding/#adding-ragconnect-to-your-project","text":"If you want to use RagConnect , either use the latest pre-build version or clone the repository and build it yourself .","title":"Adding RagConnect to your project"},{"location":"adding/#use-packaged-version","text":"Check the package overview page to find the latest version. To use it, three steps are needed. First add this GitLab as a repository in your build.gradle : repositories { maven { name \"gitlab-maven\" url \"https://git-st.inf.tu-dresden.de/api/v4/groups/jastadd/-/packages/maven\" } } Next, add RagConnect as a dependency: configurations { ragconnectClasspath } dependencies { ragconnectClasspath group: 'de.tudresden.inf.st', name: 'ragconnect', version: '0.2.3' } Finally, add a task to compile your specification: task ragConnect(type: JavaExec) { group = 'Build' main = 'org.jastadd.ragconnect.compiler.Compiler' classpath = configurations.ragconnectClasspath args([ '--verbose', '--o=src/gen/jastadd', 'src/main/jastadd/GoalModel.relast', 'src/main/jastadd/GoalModel.connect', '--rootNode=GoalModel' ]) } You might need to add another task for compiling relast specifications .","title":"Use packaged version"},{"location":"adding/#build-from-source","text":"If you want to plan to extend RagConnect , the suggested way is to first build the jar from the RagConnect repository (if you only want to use it, consider using the packaged version ). git clone https://git-st.inf.tu-dresden.de/jastadd/ragconnect.git cd ragconnect ./gradlew jar ls ragconnect.base/build/libs/ This ragconnect-<version>.jar can then be copied to your project. Please note, that you can safely use ragconnect.jar as filename, because the version can always be printed using java -jar path/to/ragconnect.jar --version . cp ragconnect.base/build/libs/ragconnect-<version>.jar ../your-project/libs/ragconnect.jar cd ../your-project/ Finally, this jar has to be integrated into your build process. In case, Gradle is used, a task could look like the following (example taken from the ros2rag use case ). The path to the jar file may need to be changed according to your project structure. task ragConnect(type: JavaExec) { group = 'Build' main = '-jar' args([ '../libs/ragconnect.jar', '--verbose', '--o=src/gen/jastadd', 'src/main/jastadd/GoalModel.relast', 'src/main/jastadd/GoalModel.connect', '--rootNode=GoalModel' ]) } You might need to add another task for compiling relast specifications .","title":"Build from source"},{"location":"adding/#compiling-relast-specifications","text":"The task to compile RagConnect specifications is typically accompanied by a task to invoke the RelAst compiler and the JastAdd gradle plugin . Currently, the parameter --useJastAddNames is required , and it may cause incompatibilities if not set. The additional arguments --listClass , --jastAddList and --resolverHelper to relast are not required. Please see the user manual of the RelAst compiler for more information. task relastToJastAdd(type: JavaExec) { group = 'Build' main = \"-jar\" args([\"../libs/relast.jar\", \"--grammarName=./src/gen/jastadd/model\", \"--useJastAddNames\", \"--listClass=java.util.ArrayList\", \"--jastAddList=JastAddList\", \"--resolverHelper\", \"--file\", \"src/gen/jastadd/GoalModel.relast\", \"src/gen/jastadd/RagConnect.relast\"]) } jastadd { ... } One also has to specify the dependencies to get correct ordering of tasks. generateAst.dependsOn relastToJastAdd relastToJastAdd.dependsOn ragConnect","title":"Compiling RelAst specifications"},{"location":"changelog/","text":"Changelog \uf0c1 0.3.2 \uf0c1 Allow connection endpoints for list nonterminals ( #21 ) Ensure correct connect and disconnect functionality ( #31 ) Enhance documentation ( #13 , #20 , #41 ) 0.3.1 \uf0c1 Full support for incremental dependency tracking Full support for subtree endpoint definitions ( #9 ) Internal: Use updated gradle plugin for tests ( #18 ) Bugfix #22 : Correct handling of malformed URIs passed when connecting an endpoint Bugfix #23 : Correct handling of OptComponents as endpoints Bugfix #27 : Correctly handle whitespaces in grammars 0.3.0 \uf0c1 Added API documentation to documentation Add methods to disconnect an endpoint Internal: PoC for incremental dependency tracking and subtree endpoint definitions ( #14 ) Bugfix #17 : Added missing support for boolean 0.2.2 \uf0c1 Allow normal tokens to be used in send definitions 0.2.1 \uf0c1 New communication protocol: REST Selection of protocol when connect methods are called, by scheme of given URI Development changes: Supported printing out YAML data used for mustache templates Moved string constants to MRagConnect structure 0.2.0 \uf0c1 Version submitted in paper \"A Connection from ROS to RAG-Based Models\" (2020) Supported communication protocols: MQTT","title":"Changelog"},{"location":"changelog/#changelog","text":"","title":"Changelog"},{"location":"changelog/#032","text":"Allow connection endpoints for list nonterminals ( #21 ) Ensure correct connect and disconnect functionality ( #31 ) Enhance documentation ( #13 , #20 , #41 )","title":"0.3.2"},{"location":"changelog/#031","text":"Full support for incremental dependency tracking Full support for subtree endpoint definitions ( #9 ) Internal: Use updated gradle plugin for tests ( #18 ) Bugfix #22 : Correct handling of malformed URIs passed when connecting an endpoint Bugfix #23 : Correct handling of OptComponents as endpoints Bugfix #27 : Correctly handle whitespaces in grammars","title":"0.3.1"},{"location":"changelog/#030","text":"Added API documentation to documentation Add methods to disconnect an endpoint Internal: PoC for incremental dependency tracking and subtree endpoint definitions ( #14 ) Bugfix #17 : Added missing support for boolean","title":"0.3.0"},{"location":"changelog/#022","text":"Allow normal tokens to be used in send definitions","title":"0.2.2"},{"location":"changelog/#021","text":"New communication protocol: REST Selection of protocol when connect methods are called, by scheme of given URI Development changes: Supported printing out YAML data used for mustache templates Moved string constants to MRagConnect structure","title":"0.2.1"},{"location":"changelog/#020","text":"Version submitted in paper \"A Connection from ROS to RAG-Based Models\" (2020) Supported communication protocols: MQTT","title":"0.2.0"},{"location":"compiler/","text":"Compiler options \uf0c1 The compiler is JastAdd-compliant, i.e., it accepts all flags available for JastAdd, though there is no process how to chain pre-processors yet . Additional options are as follows. Name Required (Default) Description --rootNode Yes Root node in the base grammar. --protocols No ( mqtt ) Protocols to enable, currently available: mqtt, rest . --printYaml No (false) Print out YAML instead of generating files. --verbose No (false) Print more messages while compiling. --logReads No (false) Enable logging for every received message. --logWrites No (false) Enable logging for every sent message. --logIncremental No (false) Enable logging for observer in incremental dependency tracking. --experimental-jastadd-329 No (false) Use trace events INC_FLUSH_START and INC_FLUSH_END ( JastAdd issue #329 ), see section about automatic dependency tracking . --incremental No (false) Enables incremental dependency tracking (if trace is also set appropriately). --trace[=flush] No (false) Enables incremental dependency tracking (if incremental is also set appropriately). --version No (false) Print version info and exit (reused JastAdd option) --o No ( . ) Output directory (reused JastAdd option) All files to be process have to be passed as arguments. Their type is decided by the file extension ( ast and relast for input grammars, connect and ragconnect for RagConnect definitions file). Additional software dependencies \uf0c1 Using RagConnect itself does not introduce dependencies. However, depending on the selected protocols and/or used features, additional dependencies are required when using the generated code. Communication protocol characteristics \uf0c1 MQTT \uf0c1 Protocol identifier: mqtt URI scheme: mqtt://<broker-host>[:port]/<topic> Default port: 1883 Type for mapping definitions: byte[] Required runtime dependencies: group: 'org.fusesource.mqtt-client', name: 'mqtt-client', version: '1.15' Additional remarks: First leading slash not included in topic. Mqtt is selected by default, so this dependency therefore is required \"by default\". Might work with other versions of org.fusesource.mqtt-client.mqtt.client as well. REST \uf0c1 Protocol identifier: rest URI scheme: rest://localhost[:port]/<path> Default port: 4567 Type for mapping definitions: String Required runtime dependencies: group: 'com.sparkjava', name: 'spark-core', version: '2.9.3' Additional remarks: Host is always localhost . Might work with newer versions of com.sparkjava.spark-core as well. For debugging, it is beneficial to include an implementation for SLF4J . Used features \uf0c1 Automatic dependency tracking \uf0c1 Condition: When passing --incremental and --trace=flush to RagConnect Required runtime dependencies: none Required options for RelAST compiler: none Required options for JastAdd: --incremental --trace=flush Remarks: Other (additional) values passed to those two options must be equal (e.g., --incremental=param passed to RagConnect must be also passed to JastAdd) Other values besides flush can be added to --trace Feature description (Safer) Automatic dependency tracking \uf0c1 Condition: When passing --experimental-jastadd-329 to RagConnect Required runtime dependencies: none Required options for RelAST compiler: none Required options for JastAdd: none Remarks: JastAdd version has to support INC_FLUSH_START and INC_FLUSH_END (i.e., has issue #329 resolved) Feature description Tree/List Endpoints \uf0c1 Condition: When using tree or list endpoints along with default mappings Required runtime dependencies: group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.12.1' group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.1' Required options for RelAST compiler: --serializer=jackson Required options for JastAdd: none Remarks: Feature description","title":"Compiler options"},{"location":"compiler/#compiler-options","text":"The compiler is JastAdd-compliant, i.e., it accepts all flags available for JastAdd, though there is no process how to chain pre-processors yet . Additional options are as follows. Name Required (Default) Description --rootNode Yes Root node in the base grammar. --protocols No ( mqtt ) Protocols to enable, currently available: mqtt, rest . --printYaml No (false) Print out YAML instead of generating files. --verbose No (false) Print more messages while compiling. --logReads No (false) Enable logging for every received message. --logWrites No (false) Enable logging for every sent message. --logIncremental No (false) Enable logging for observer in incremental dependency tracking. --experimental-jastadd-329 No (false) Use trace events INC_FLUSH_START and INC_FLUSH_END ( JastAdd issue #329 ), see section about automatic dependency tracking . --incremental No (false) Enables incremental dependency tracking (if trace is also set appropriately). --trace[=flush] No (false) Enables incremental dependency tracking (if incremental is also set appropriately). --version No (false) Print version info and exit (reused JastAdd option) --o No ( . ) Output directory (reused JastAdd option) All files to be process have to be passed as arguments. Their type is decided by the file extension ( ast and relast for input grammars, connect and ragconnect for RagConnect definitions file).","title":"Compiler options"},{"location":"compiler/#additional-software-dependencies","text":"Using RagConnect itself does not introduce dependencies. However, depending on the selected protocols and/or used features, additional dependencies are required when using the generated code.","title":"Additional software dependencies"},{"location":"compiler/#communication-protocol-characteristics","text":"","title":"Communication protocol characteristics"},{"location":"compiler/#mqtt","text":"Protocol identifier: mqtt URI scheme: mqtt://<broker-host>[:port]/<topic> Default port: 1883 Type for mapping definitions: byte[] Required runtime dependencies: group: 'org.fusesource.mqtt-client', name: 'mqtt-client', version: '1.15' Additional remarks: First leading slash not included in topic. Mqtt is selected by default, so this dependency therefore is required \"by default\". Might work with other versions of org.fusesource.mqtt-client.mqtt.client as well.","title":"MQTT"},{"location":"compiler/#rest","text":"Protocol identifier: rest URI scheme: rest://localhost[:port]/<path> Default port: 4567 Type for mapping definitions: String Required runtime dependencies: group: 'com.sparkjava', name: 'spark-core', version: '2.9.3' Additional remarks: Host is always localhost . Might work with newer versions of com.sparkjava.spark-core as well. For debugging, it is beneficial to include an implementation for SLF4J .","title":"REST"},{"location":"compiler/#used-features","text":"","title":"Used features"},{"location":"compiler/#automatic-dependency-tracking","text":"Condition: When passing --incremental and --trace=flush to RagConnect Required runtime dependencies: none Required options for RelAST compiler: none Required options for JastAdd: --incremental --trace=flush Remarks: Other (additional) values passed to those two options must be equal (e.g., --incremental=param passed to RagConnect must be also passed to JastAdd) Other values besides flush can be added to --trace Feature description","title":"Automatic dependency tracking"},{"location":"compiler/#safer-automatic-dependency-tracking","text":"Condition: When passing --experimental-jastadd-329 to RagConnect Required runtime dependencies: none Required options for RelAST compiler: none Required options for JastAdd: none Remarks: JastAdd version has to support INC_FLUSH_START and INC_FLUSH_END (i.e., has issue #329 resolved) Feature description","title":"(Safer) Automatic dependency tracking"},{"location":"compiler/#treelist-endpoints","text":"Condition: When using tree or list endpoints along with default mappings Required runtime dependencies: group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.12.1' group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.12.1' Required options for RelAST compiler: --serializer=jackson Required options for JastAdd: none Remarks: Feature description","title":"Tree/List Endpoints"},{"location":"extending/","text":"Extending RagConnect \uf0c1 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 : 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 . 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 ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/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 Furthermore, new test cases are appreciated, see below . Writing Tests \uf0c1 To add new tests, have a look at the module ragconnect.tests . It has three parts: 1) In src/test/01-input/* are the specifications that are going to be compiled (in principle using the steps described in the guide to add RagConnect ). 2) In src/test/java , the jUnit 5 test classes are implemented. They mostly correspond 1-to-1 to a directory of the first part. 3) In build.gradle the instructions how to compile the specifications using the gradle plugin PreprocessorPlugin ( org.jastadd.preprocessor:testing ). Specifications \uf0c1 Every specification must have at least a README.md to describe the purpose of the test, a grammar Test.relast , and a RagConnect specification Test.connect . Usually an aspect file Test.jadd is included. Test Classes \uf0c1 Based on jUnit 5, the test classes testing some behaviour. If sending and/or receiving functionality is used, consider extending AbstractMqttTest in order to avoid duplicate code. In case of extending this class, please order the methods according to their lifecycle, i.e.: - createModel - setupReceiverAndConnect - communicateSendInitialValue - communicateOnlyUpdatedValue - closeConnections Within AbstractMqttTest , an MqttHandler named publisher is available to publish content. Some convenience methods are provided in TestUtils , e.g., the DefaultMappings , and mqttUri to prepend \"mqtt://\" and the correct host for the mqtt broker ( localhost or a CI-specific host). All tests are required to run both locally, and within the CI. build.gradle \uf0c1 Use the PreprocessorPlugin , the build process can be written concisely in three parts per task: task compileTreeAllowedTokens(type: RagConnectTest) { ragconnect { outputDir = file('src/test/02-after-ragconnect/treeAllowedTokens') inputFiles = [file('src/test/01-input/treeAllowedTokens/Test.relast'), file('src/test/01-input/treeAllowedTokens/Test.connect'), file('src/test/01-input/treeAllowedTokens/TestDependencies.connect')] rootNode = 'Root' } relast { useJastAddNames = true grammarName = 'src/test/03-after-relast/treeAllowedTokens/treeAllowedTokens' serializer = 'jackson' } jastadd { jastAddList = 'JastAddList' packageName = 'treeAllowedTokens.ast' inputFiles = [file('src/test/01-input/treeAllowedTokens/Test.jadd')] } }","title":"Extending RagConnect"},{"location":"extending/#extending-ragconnect","text":"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 : 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 . 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 ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/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 Furthermore, new test cases are appreciated, see below .","title":"Extending RagConnect"},{"location":"extending/#writing-tests","text":"To add new tests, have a look at the module ragconnect.tests . It has three parts: 1) In src/test/01-input/* are the specifications that are going to be compiled (in principle using the steps described in the guide to add RagConnect ). 2) In src/test/java , the jUnit 5 test classes are implemented. They mostly correspond 1-to-1 to a directory of the first part. 3) In build.gradle the instructions how to compile the specifications using the gradle plugin PreprocessorPlugin ( org.jastadd.preprocessor:testing ).","title":"Writing Tests"},{"location":"extending/#specifications","text":"Every specification must have at least a README.md to describe the purpose of the test, a grammar Test.relast , and a RagConnect specification Test.connect . Usually an aspect file Test.jadd is included.","title":"Specifications"},{"location":"extending/#test-classes","text":"Based on jUnit 5, the test classes testing some behaviour. If sending and/or receiving functionality is used, consider extending AbstractMqttTest in order to avoid duplicate code. In case of extending this class, please order the methods according to their lifecycle, i.e.: - createModel - setupReceiverAndConnect - communicateSendInitialValue - communicateOnlyUpdatedValue - closeConnections Within AbstractMqttTest , an MqttHandler named publisher is available to publish content. Some convenience methods are provided in TestUtils , e.g., the DefaultMappings , and mqttUri to prepend \"mqtt://\" and the correct host for the mqtt broker ( localhost or a CI-specific host). All tests are required to run both locally, and within the CI.","title":"Test Classes"},{"location":"extending/#buildgradle","text":"Use the PreprocessorPlugin , the build process can be written concisely in three parts per task: task compileTreeAllowedTokens(type: RagConnectTest) { ragconnect { outputDir = file('src/test/02-after-ragconnect/treeAllowedTokens') inputFiles = [file('src/test/01-input/treeAllowedTokens/Test.relast'), file('src/test/01-input/treeAllowedTokens/Test.connect'), file('src/test/01-input/treeAllowedTokens/TestDependencies.connect')] rootNode = 'Root' } relast { useJastAddNames = true grammarName = 'src/test/03-after-relast/treeAllowedTokens/treeAllowedTokens' serializer = 'jackson' } jastadd { jastAddList = 'JastAddList' packageName = 'treeAllowedTokens.ast' inputFiles = [file('src/test/01-input/treeAllowedTokens/Test.jadd')] } }","title":"build.gradle"},{"location":"inner-workings/","text":"Inner workings of RagConnect \uf0c1 Please see API documentation for more details. RagConnect uses the 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 (currently its Java version ) 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 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.","title":"Inner workings"},{"location":"inner-workings/#inner-workings-of-ragconnect","text":"Please see API documentation for more details. RagConnect uses the 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 (currently its Java version ) 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 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.","title":"Inner workings of RagConnect"},{"location":"use_cases/","text":"Use cases with RagConnect \uf0c1 MPM4CPS Paper - Codename 'Ros2Rag' \uf0c1 In the publication \"Connecting conceptual models using Relational Reference Attribute Grammars\" , a use case involving a simulated robot arm and two different models connected to it was shown. One model was used to ensure a low speed of the robot when within a safety zone (purple boxes in the picture below), and the other model executes a workflow to control the robot. This paper was presented on October, 16h during the MPM4CPS workshop within the MODELS 2020 conference . For more information, see the presented slides , a recording of the session or the accompanied poster . The repository with the used source code can be found at: https://git-st.inf.tu-dresden.de/ceti/ros/mpm4cps2020 The usage is dockerized, so starting the application only involves the commands listed below. As ROS takes some time to start up, it is best to use separate terminals for the three applications (ROS, Safety-Model, Goal-Model): # Preparation (only need once) ./prepare-docker-compose.sh docker-compose up -d mosquitto # Starts the MQTT broker # Terminal 1: ROS docker-compose up --build ros # Wait until you see no more new logging output # Terminal 2: Safety-Model docker-compose up rag_app # Terminal 3: Goal-Model docker-compose up rag_goal","title":"Use Cases"},{"location":"use_cases/#use-cases-with-ragconnect","text":"","title":"Use cases with RagConnect"},{"location":"use_cases/#mpm4cps-paper-codename-ros2rag","text":"In the publication \"Connecting conceptual models using Relational Reference Attribute Grammars\" , a use case involving a simulated robot arm and two different models connected to it was shown. One model was used to ensure a low speed of the robot when within a safety zone (purple boxes in the picture below), and the other model executes a workflow to control the robot. This paper was presented on October, 16h during the MPM4CPS workshop within the MODELS 2020 conference . For more information, see the presented slides , a recording of the session or the accompanied poster . The repository with the used source code can be found at: https://git-st.inf.tu-dresden.de/ceti/ros/mpm4cps2020 The usage is dockerized, so starting the application only involves the commands listed below. As ROS takes some time to start up, it is best to use separate terminals for the three applications (ROS, Safety-Model, Goal-Model): # Preparation (only need once) ./prepare-docker-compose.sh docker-compose up -d mosquitto # Starts the MQTT broker # Terminal 1: ROS docker-compose up --build ros # Wait until you see no more new logging output # Terminal 2: Safety-Model docker-compose up rag_app # Terminal 3: Goal-Model docker-compose up rag_goal","title":"MPM4CPS Paper - Codename 'Ros2Rag'"},{"location":"using/","text":"Using RagConnect -- an example \uf0c1 The full example is available at https://git-st.inf.tu-dresden.de/jastadd/ragconnect-minimal . Preparation and Specification \uf0c1 The following examples are inspired by the real test case read1write2 The idea is to have two nonterminals, where input information is received on one of them, and - after transformation - is sent out by both. Let the following grammar be used: A ::= <Input:String> /<OutputOnA:String>/ B* ; B ::= /<OutputOnB:String>/ ; To declare receiving and sending tokens, a dedicated DSL is used: // endpoint definitions receive A.Input ; send A.OutputOnA ; send B.OutputOnB using Transformation ; // mapping definitions Transformation maps String s to String {: return s + \"postfix\"; :} This defines A.Input to receive updates, and the other two tokens to send their value, whenever it changes. Additionally, a transformation will be applied on B.OutputOnB before sending out its value. Such mapping definitions can be defined for receiving tokens as well. In this case, they are applied before the value is set. If no mapping definition is given, or if the required type (depending on the communication protocol, see later) does not match, a \"default mapping definition\" is used to avoid boilerplate code converting from or to primitive types. Furthermore, let the following attribute definitions be given: syn String A.getOutputOnA() = \"a\" + getInput(); syn String B.getOutputOnB() = \"b\" + input(); inh String B.input(); eq A.getB().input() = getInput(); In other words, OutputOnA depends on Input of the same node, and OutputOnB depends on Input of its parent node. Currently, those dependencies can be explicitly written down, or incremental evaluation can be used. Dependency tracking: Manually specified \uf0c1 This specification happens also in the DSL (dependencies have to be named to uniquely identify them): // dependency definitions A.OutputOnA canDependOn A.Input as dependencyA ; B.OutputOnB canDependOn A.Input as dependencyB ; Dependency tracking: Automatically derived \uf0c1 To automatically track dependencies, the two additional parameters --incremental and --trace=flush have to be provided to both RagConnect and (in the later stage) JastAdd. This will generate a different implementation of RagConnect relying on enabled incremental evaluation of JastAdd. The value for incremental has only been tested for incremental=param . The value for trace can include other values besides flush . An experimental, optimized version can be selected using --experimental-jastadd-329 reducing the risk of conflicts between concurrent attribute evaluations. However, this requires a version of JastAdd that resolved the issue 329 . Using generated code \uf0c1 After specifying everything, code will be generated if setup properly . Let's create an AST in some driver code: A a = new A(); // set some default value for input a.setInput(\"\"); B b1 = new B(); B b2 = new B(); a.addB(b1); a.addB(b2); If necessary, we have to set the dependencies as described earlier . // a.OutputOnA -> a.Input a.addDependencyA(a); // b1.OutputOnB -> a.Input b1.addDependencyB(a); // b2.OutputOnB -> a.Input b2.addDependencyB(a); Finally, we can actually connect the tokens. Depending on the enabled protocols, different URI schemes are allowed . In this example, we use the default protocol: MQTT. a.connectInput(\"mqtt://localhost/topic/for/input\"); a.connectOutputOnA(\"mqtt://localhost/a/out\", true); b1.connectOutputOnB(\"mqtt://localhost/b1/out\", true); b2.connectOutputOnB(\"mqtt://localhost/b2/out\", false); The first parameter of those connect-methods is always an URI-like String, to identify the protocol to use, the server operating the protocol, and a path to identify the concrete token. In case of MQTT, the server is the host running an MQTT broker, and the path is equal to the topic to publish or subscribe to. Please note, that the first leading slash ( / ) is removed for MQTT topics, e.g., for A.Input the topic is actually topic/for/input . For sending endpoints, there is a second boolean parameter to specify whether the current value shall be sent immediately after connecting. Remarks for using manual dependency tracking \uf0c1 When constructing the AST and connecting it, one should always set dependencies before connecting, especially if updates already arriving for receiving endpoints. Otherwise, updates might not be propagated after setting dependencies, if values are equal after applying transformations of mapping definitions. As an example, when using the following grammar and definitions for RagConnect ... A ::= <Input:int> /<Output:String>/ ; receive A.Input using Round ; send A.Output ; A.Output canDependOn A.Input as dependency1 ; Round maps float f to int {: return Math.round(f); :} ... connecting first could mean to store the first rounded value and not propagating this update, since no dependencies are set, and not propagating further updates leading to the same rounded value even after setting the dependencies. An advanced example \uf0c1 Non-terminal children can also be selected as endpoints (not only tokens). Normal Non-Terminal Children \uf0c1 Receiving normal non-terminal children and optionals means to replace them with a new node deserialized from the received message. Sending them involves serializing a node, and sending this representation in a message. Suppose, the following (shortened) grammar is used (inspired from the testcase tree ) Root ::= SenderRoot ReceiverRoot ; SenderRoot ::= <Input:int> /Alfa/ ; ReceiverRoot ::= Alfa ; Alfa ::= // some content ... Now, the complete node of type Alfa can be sent, and received again using the following connect specification: send tree SenderRoot.Alfa ; receive tree ReceiverRoot.Alfa ; Currently, receiving and sending trees requires the explicit demarcation from tokens using the keyword tree . To process non-terminals, default mappings are provided for every non-terminal type of the used grammar. They use the JSON serialization offered by the RelAST compiler, i.e., interpret the message as a String , deserialize the content reading the message as JSON, or vice versa. Additional dependencies are required to use this feature, as detailed in the compiler section . Receiving List Children \uf0c1 When receiving list children, there are a few more options to match the connection to given requirements. Suppose we use a similar grammar as above, i.e.: SenderRoot ::= /AlfaList:Alfa*/ /SingleAlfa:Alfa/; ReceiverRoot ::= Alfa* ; Several options are possible: list \uf0c1 A message for a list endpoint can be interpreted as a complete list (a sequence of nodes of type Alfa ) by using the list keyword instead of tree : receive list ReceiverRoot.Alfa ; list + with add \uf0c1 Upon receiving the message, the deserialized list can also be appended to the existing list instead of replace the latter. This can be achieved using the keyword with add in addition to the keyword list : receive list with add ReceiverRoot.Alfa ; tree (indexed) \uf0c1 A message for a list endpoint can also be interpreted as an element of this list. receive tree ReceiverRoot.Alfa ; Upon connection, the index of the deserialized element to set, has to be passed ( 1 in the example below). The list must have enough elements once a message is received. receiverRoot.connectAlfa(\"<some-url>\", 1); tree (wildcard) \uf0c1 Similar to the tree (indexed) case above, messages are interpreted as an element of the list, but the connection can also be made using a \"wildcard topic\" and without an index. Then, once a message is received from a new concrete topic, the deserialized element will be appended to the list and this topic is associated with the index of the newly added element. Any further message from that topic will replace the element at the associated index. In the short example below, MQTT is used to with a wildcard topic, as # matches every sub-topic. receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/#\"); // list is initially empty assertEquals(receiverRoot.getAlfaList(), list()); // after receiving \"1\" on new topic \"some/topic/one\" (index 0) assertEquals(receiverRoot.getAlfaList(), list(\"1\")); // after receiving \"other\" on new topic \"some/topic/two\" (index 1) assertEquals(receiverRoot.getAlfaList(), list(\"1\", \"other\")); // after receiving \"new\" on existing topic \"some/topic/one\" (index 0) assertEquals(receiverRoot.getAlfaList(), list(\"new\", \"other\")); tree (indexed/wildcard) + with add \uf0c1 Combining tree and with add results in a connection, where messages are interpreted as elements of the list, and new elements are appended to the existing list. In that case, wildcard and non-wildcard connections behave in the same way, as no index has to be passed, and the element is always append at the end. Reusing the example from above, the following observations can be made. receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/#\"); // or receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/one\"); receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/two\"); // list is initially empty assertEquals(receiverRoot.getAlfaList(), list()); // after receiving \"1\" on topic \"some/topic/one\" assertEquals(receiverRoot.getAlfaList(), list(\"1\")); // after receiving \"other\" on topic \"some/topic/two\" assertEquals(receiverRoot.getAlfaList(), list(\"1\", \"other\")); // after receiving \"new\" on topic \"some/topic/one\" assertEquals(receiverRoot.getAlfaList(), list(\"1\", \"other\", \"new\"));","title":"RagConnect by Example"},{"location":"using/#using-ragconnect-an-example","text":"The full example is available at https://git-st.inf.tu-dresden.de/jastadd/ragconnect-minimal .","title":"Using RagConnect -- an example"},{"location":"using/#preparation-and-specification","text":"The following examples are inspired by the real test case read1write2 The idea is to have two nonterminals, where input information is received on one of them, and - after transformation - is sent out by both. Let the following grammar be used: A ::= <Input:String> /<OutputOnA:String>/ B* ; B ::= /<OutputOnB:String>/ ; To declare receiving and sending tokens, a dedicated DSL is used: // endpoint definitions receive A.Input ; send A.OutputOnA ; send B.OutputOnB using Transformation ; // mapping definitions Transformation maps String s to String {: return s + \"postfix\"; :} This defines A.Input to receive updates, and the other two tokens to send their value, whenever it changes. Additionally, a transformation will be applied on B.OutputOnB before sending out its value. Such mapping definitions can be defined for receiving tokens as well. In this case, they are applied before the value is set. If no mapping definition is given, or if the required type (depending on the communication protocol, see later) does not match, a \"default mapping definition\" is used to avoid boilerplate code converting from or to primitive types. Furthermore, let the following attribute definitions be given: syn String A.getOutputOnA() = \"a\" + getInput(); syn String B.getOutputOnB() = \"b\" + input(); inh String B.input(); eq A.getB().input() = getInput(); In other words, OutputOnA depends on Input of the same node, and OutputOnB depends on Input of its parent node. Currently, those dependencies can be explicitly written down, or incremental evaluation can be used.","title":"Preparation and Specification"},{"location":"using/#dependency-tracking-manually-specified","text":"This specification happens also in the DSL (dependencies have to be named to uniquely identify them): // dependency definitions A.OutputOnA canDependOn A.Input as dependencyA ; B.OutputOnB canDependOn A.Input as dependencyB ;","title":"Dependency tracking: Manually specified"},{"location":"using/#dependency-tracking-automatically-derived","text":"To automatically track dependencies, the two additional parameters --incremental and --trace=flush have to be provided to both RagConnect and (in the later stage) JastAdd. This will generate a different implementation of RagConnect relying on enabled incremental evaluation of JastAdd. The value for incremental has only been tested for incremental=param . The value for trace can include other values besides flush . An experimental, optimized version can be selected using --experimental-jastadd-329 reducing the risk of conflicts between concurrent attribute evaluations. However, this requires a version of JastAdd that resolved the issue 329 .","title":"Dependency tracking: Automatically derived"},{"location":"using/#using-generated-code","text":"After specifying everything, code will be generated if setup properly . Let's create an AST in some driver code: A a = new A(); // set some default value for input a.setInput(\"\"); B b1 = new B(); B b2 = new B(); a.addB(b1); a.addB(b2); If necessary, we have to set the dependencies as described earlier . // a.OutputOnA -> a.Input a.addDependencyA(a); // b1.OutputOnB -> a.Input b1.addDependencyB(a); // b2.OutputOnB -> a.Input b2.addDependencyB(a); Finally, we can actually connect the tokens. Depending on the enabled protocols, different URI schemes are allowed . In this example, we use the default protocol: MQTT. a.connectInput(\"mqtt://localhost/topic/for/input\"); a.connectOutputOnA(\"mqtt://localhost/a/out\", true); b1.connectOutputOnB(\"mqtt://localhost/b1/out\", true); b2.connectOutputOnB(\"mqtt://localhost/b2/out\", false); The first parameter of those connect-methods is always an URI-like String, to identify the protocol to use, the server operating the protocol, and a path to identify the concrete token. In case of MQTT, the server is the host running an MQTT broker, and the path is equal to the topic to publish or subscribe to. Please note, that the first leading slash ( / ) is removed for MQTT topics, e.g., for A.Input the topic is actually topic/for/input . For sending endpoints, there is a second boolean parameter to specify whether the current value shall be sent immediately after connecting.","title":"Using generated code"},{"location":"using/#remarks-for-using-manual-dependency-tracking","text":"When constructing the AST and connecting it, one should always set dependencies before connecting, especially if updates already arriving for receiving endpoints. Otherwise, updates might not be propagated after setting dependencies, if values are equal after applying transformations of mapping definitions. As an example, when using the following grammar and definitions for RagConnect ... A ::= <Input:int> /<Output:String>/ ; receive A.Input using Round ; send A.Output ; A.Output canDependOn A.Input as dependency1 ; Round maps float f to int {: return Math.round(f); :} ... connecting first could mean to store the first rounded value and not propagating this update, since no dependencies are set, and not propagating further updates leading to the same rounded value even after setting the dependencies.","title":"Remarks for using manual dependency tracking"},{"location":"using/#an-advanced-example","text":"Non-terminal children can also be selected as endpoints (not only tokens).","title":"An advanced example"},{"location":"using/#normal-non-terminal-children","text":"Receiving normal non-terminal children and optionals means to replace them with a new node deserialized from the received message. Sending them involves serializing a node, and sending this representation in a message. Suppose, the following (shortened) grammar is used (inspired from the testcase tree ) Root ::= SenderRoot ReceiverRoot ; SenderRoot ::= <Input:int> /Alfa/ ; ReceiverRoot ::= Alfa ; Alfa ::= // some content ... Now, the complete node of type Alfa can be sent, and received again using the following connect specification: send tree SenderRoot.Alfa ; receive tree ReceiverRoot.Alfa ; Currently, receiving and sending trees requires the explicit demarcation from tokens using the keyword tree . To process non-terminals, default mappings are provided for every non-terminal type of the used grammar. They use the JSON serialization offered by the RelAST compiler, i.e., interpret the message as a String , deserialize the content reading the message as JSON, or vice versa. Additional dependencies are required to use this feature, as detailed in the compiler section .","title":"Normal Non-Terminal Children"},{"location":"using/#receiving-list-children","text":"When receiving list children, there are a few more options to match the connection to given requirements. Suppose we use a similar grammar as above, i.e.: SenderRoot ::= /AlfaList:Alfa*/ /SingleAlfa:Alfa/; ReceiverRoot ::= Alfa* ; Several options are possible:","title":"Receiving List Children"},{"location":"using/#list","text":"A message for a list endpoint can be interpreted as a complete list (a sequence of nodes of type Alfa ) by using the list keyword instead of tree : receive list ReceiverRoot.Alfa ;","title":"list"},{"location":"using/#list-with-add","text":"Upon receiving the message, the deserialized list can also be appended to the existing list instead of replace the latter. This can be achieved using the keyword with add in addition to the keyword list : receive list with add ReceiverRoot.Alfa ;","title":"list + with add"},{"location":"using/#tree-indexed","text":"A message for a list endpoint can also be interpreted as an element of this list. receive tree ReceiverRoot.Alfa ; Upon connection, the index of the deserialized element to set, has to be passed ( 1 in the example below). The list must have enough elements once a message is received. receiverRoot.connectAlfa(\"<some-url>\", 1);","title":"tree (indexed)"},{"location":"using/#tree-wildcard","text":"Similar to the tree (indexed) case above, messages are interpreted as an element of the list, but the connection can also be made using a \"wildcard topic\" and without an index. Then, once a message is received from a new concrete topic, the deserialized element will be appended to the list and this topic is associated with the index of the newly added element. Any further message from that topic will replace the element at the associated index. In the short example below, MQTT is used to with a wildcard topic, as # matches every sub-topic. receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/#\"); // list is initially empty assertEquals(receiverRoot.getAlfaList(), list()); // after receiving \"1\" on new topic \"some/topic/one\" (index 0) assertEquals(receiverRoot.getAlfaList(), list(\"1\")); // after receiving \"other\" on new topic \"some/topic/two\" (index 1) assertEquals(receiverRoot.getAlfaList(), list(\"1\", \"other\")); // after receiving \"new\" on existing topic \"some/topic/one\" (index 0) assertEquals(receiverRoot.getAlfaList(), list(\"new\", \"other\"));","title":"tree (wildcard)"},{"location":"using/#tree-indexedwildcard-with-add","text":"Combining tree and with add results in a connection, where messages are interpreted as elements of the list, and new elements are appended to the existing list. In that case, wildcard and non-wildcard connections behave in the same way, as no index has to be passed, and the element is always append at the end. Reusing the example from above, the following observations can be made. receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/#\"); // or receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/one\"); receiverRoot.connectAlfa(\"mqtt://<broker>/some/topic/two\"); // list is initially empty assertEquals(receiverRoot.getAlfaList(), list()); // after receiving \"1\" on topic \"some/topic/one\" assertEquals(receiverRoot.getAlfaList(), list(\"1\")); // after receiving \"other\" on topic \"some/topic/two\" assertEquals(receiverRoot.getAlfaList(), list(\"1\", \"other\")); // after receiving \"new\" on topic \"some/topic/one\" assertEquals(receiverRoot.getAlfaList(), list(\"1\", \"other\", \"new\"));","title":"tree (indexed/wildcard) + with add"}]}
\ No newline at end of file
diff --git a/public/0.3.2/sitemap.xml.gz b/public/0.3.2/sitemap.xml.gz
index 34a27ae0739d57673aa4e0aa44556b227a810dae..3c795d16297df88ec82e71fac5d47aea2b3e4f9e 100644
Binary files a/public/0.3.2/sitemap.xml.gz and b/public/0.3.2/sitemap.xml.gz differ
diff --git a/public/0.3.2/use_cases/index.html b/public/0.3.2/use_cases/index.html
index 6ad7c1ae928075a854af097b8c71d35c64dda891..ff2b2bf2058851e2163d4f4f2af35a936901e3a1 100644
--- a/public/0.3.2/use_cases/index.html
+++ b/public/0.3.2/use_cases/index.html
@@ -121,9 +121,7 @@
 <p>In the publication <a href="https://doi.org/10.1145/3417990.3421437"><em>"Connecting conceptual models using Relational Reference Attribute Grammars"</em></a>, a use case involving a simulated robot arm and two different models connected to it was shown.
 One model was used to ensure a low speed of the robot when within a safety zone (purple boxes in the picture below), and the other model executes a workflow to control the robot.</p>
 <p><img alt="Screenshot of Gazebo" src="../img/robo3d.png" /></p>
-<p><a href="../img/moving-robot.mp4">📽 Recording of the simulated robot during the use case</a></p>
-<p>This paper was presented on October, 16h during the <a href="https://msdl.uantwerpen.be/conferences/MPM4CPS/2020/">MPM4CPS workshop</a> within the <a href="https://conf.researchr.org/home/models-2020">MODELS 2020 conference</a>. For more information, see the <a href="../img/mpm4cps-slides.pdf">presented slides</a> or the <a href="https://youtu.be/Hgc1qFfmr44?t=1220">a recording of the session</a>.</p>
-<p>There is also a <a href="../img/poster.pdf">poster</a> and a <a href="../img/poster-presentation.mp4">pre-recorded presentation</a> of this poster.</p>
+<p>This paper was presented on October, 16h during the <a href="https://msdl.uantwerpen.be/conferences/MPM4CPS/2020/">MPM4CPS workshop</a> within the <a href="https://conf.researchr.org/home/models-2020">MODELS 2020 conference</a>. For more information, see the <a href="../img/mpm4cps-slides.pdf">presented slides</a>, <a href="https://youtu.be/Hgc1qFfmr44?t=1220">a recording of the session</a> or the accompanied <a href="../img/poster.pdf">poster</a>.</p>
 <p>The repository with the used source code can be found at: <a href="https://git-st.inf.tu-dresden.de/ceti/ros/mpm4cps2020">https://git-st.inf.tu-dresden.de/ceti/ros/mpm4cps2020</a>
 The usage is dockerized, so starting the application only involves the commands listed below.
 As ROS takes some time to start up, it is best to use separate terminals for the three applications (ROS, Safety-Model, Goal-Model):</p>
@@ -149,7 +147,7 @@ docker-compose up rag_goal
 <hr>
 Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
 
-<small><br><i>Last updated <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-datetime">February 4, 2021 13:10:23</span></i></small>
+<small><br><i>Last updated <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-datetime">November 24, 2021 12:05:01</span></i></small>
 
 </p>