diff --git a/libs/buildSrc.jar b/libs/buildSrc.jar deleted file mode 100644 index b0ca2cbc4fc7f12022592944d7446a429d855add..0000000000000000000000000000000000000000 Binary files a/libs/buildSrc.jar and /dev/null differ diff --git a/ragconnect.base/src/main/jastadd/Configuration.jadd b/ragconnect.base/src/main/jastadd/Configuration.jadd index 8d3b16c3f99014408c6aefa5655201d222c3d892..4116807c5b921b74bd645a992c849d841b43bcf2 100644 --- a/ragconnect.base/src/main/jastadd/Configuration.jadd +++ b/ragconnect.base/src/main/jastadd/Configuration.jadd @@ -4,4 +4,5 @@ aspect Configuration { public static TypeDecl ASTNode.rootNode; public static boolean ASTNode.usesMqtt; public static boolean ASTNode.usesRest; + public static boolean ASTNode.incrementalOptionActive; } diff --git a/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java b/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java index d2894e6c6475b3929f063fa7742a4bb11002c00d..b14ed91e9b6ba31824e7ffb72995c781e9689015 100644 --- a/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java +++ b/ragconnect.base/src/main/java/org/jastadd/ragconnect/compiler/Compiler.java @@ -78,7 +78,6 @@ public class Compiler extends AbstractCompiler { printMessage("Writing output files"); final List<String> handlers = new ArrayList<>(); - handlers.add("RagConnectObserver.jadd"); if (ASTNode.usesMqtt) { handlers.add("MqttHandler.jadd"); } @@ -224,6 +223,8 @@ public class Compiler extends AbstractCompiler { ragConnect.additionalRelations().forEach(ragConnectGrammarPart::addDeclaration); ASTNode.loggingEnabledForReads = optionLogReads.value(); ASTNode.loggingEnabledForWrites = optionLogWrites.value(); + // reuse "--incremental" option of JastAdd + ASTNode.incrementalOptionActive = getConfiguration().incremental() && getConfiguration().traceFlush(); ASTNode.usesMqtt = optionProtocols.hasValue(OPTION_PROTOCOL_MQTT); ASTNode.usesRest = optionProtocols.hasValue(OPTION_PROTOCOL_REST); return ragConnect; diff --git a/ragconnect.base/src/main/resources/MqttHandler.jadd b/ragconnect.base/src/main/resources/MqttHandler.jadd index 6b0ea71960b7d465ea1ddd63b62c6b19caaffe70..987c0c451317098cdeabd7b2d7009a2e8ceda301 100644 --- a/ragconnect.base/src/main/resources/MqttHandler.jadd +++ b/ragconnect.base/src/main/resources/MqttHandler.jadd @@ -252,7 +252,7 @@ public class MqttHandler { } // register callback logger.debug("new connection for {}", topic); - if (callbacks.get(topic) == null) { + if (callbacks.get(topic) == null || callbacks.get(topic).isEmpty()) { callbacks.put(topic, new java.util.ArrayList<>()); // subscribe at broker diff --git a/ragconnect.base/src/main/resources/RagConnectObserver.jadd b/ragconnect.base/src/main/resources/RagConnectObserver.jadd index 3658f7b6211802ec795b0b608770256c83b0f97c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/ragconnect.base/src/main/resources/RagConnectObserver.jadd +++ b/ragconnect.base/src/main/resources/RagConnectObserver.jadd @@ -1,54 +0,0 @@ -aspect RagConnectObserver { - class RagConnectObserver implements ASTState.Trace.Receiver { - ASTState.Trace.Receiver oldReceiver; - class RagConnectObserverEntry { - ASTNode node; - String attributeString; - Runnable attributeCall; - RagConnectObserverEntry(ASTNode node, String attributeString, Runnable attributeCall) { - this.node = node; - this.attributeString = attributeString; - this.attributeCall = attributeCall; - } - } - java.util.List<RagConnectObserverEntry> observedNodes = new java.util.ArrayList<>(); - RagConnectObserver(ASTNode node) { - // set the receiver. potentially dangerous because overriding existing receiver! - oldReceiver = node.trace().getReceiver(); - node.trace().setReceiver(this); - } - void add(ASTNode node, String attributeString, Runnable attributeCall) { - System.out.println("** observer add " + node + " on " + attributeString); - observedNodes.add(new RagConnectObserverEntry(node, attributeString, attributeCall)); - } - void remove(ASTNode node, String attributeString, Runnable attributeCall) { - observedNodes.remove(new RagConnectObserverEntry(node, attributeString, attributeCall)); - } - @Override - public void accept(ASTState.Trace.Event event, ASTNode node, String attribute, Object params, Object value) { - oldReceiver.accept(event, node, attribute, params, value); - // ignore all events but INC_FLUSH_ATTR - if (event != ASTState.Trace.Event.INC_FLUSH_ATTR) { - return; - } - System.out.println("** observer check INC_FLUSH_ATTR event"); - // iterate through list, if matching pair. could maybe be more efficient. - for (RagConnectObserverEntry entry : observedNodes) { - if (entry.node.equals(node) && entry.attributeString.equals(attribute)) { - // hit. call the attribute/nta-token - System.out.println("** observer hit " + entry.node + " on " + entry.attributeString); - entry.attributeCall.run(); - } - } - } - } - - private static RagConnectObserver ASTNode._ragConnectObserverInstance; - RagConnectObserver ASTNode._ragConnectObserver() { - if (_ragConnectObserverInstance == null) { - // does not matter, which node is used to create the observer as ASTState/tracing is also static - _ragConnectObserverInstance = new RagConnectObserver(this); - } - return _ragConnectObserverInstance; - } -} diff --git a/ragconnect.base/src/main/resources/ragconnect.mustache b/ragconnect.base/src/main/resources/ragconnect.mustache index 49d1721cbf0cf0131fe2248fe4e736906448bccf..d82f43093071a7bd4fb5ad05d341b5fc13f4e1cf 100644 --- a/ragconnect.base/src/main/resources/ragconnect.mustache +++ b/ragconnect.base/src/main/resources/ragconnect.mustache @@ -21,3 +21,62 @@ aspect ROS2RAG { {{> tokenComponent}} {{/TokenComponents}} } + +{{#incrementalOptionActive}} +aspect RagConnectObserver { + class RagConnectObserver implements ASTState.Trace.Receiver { + ASTState.Trace.Receiver oldReceiver; + class RagConnectObserverEntry { + final ConnectToken connectToken; + final ASTNode node; + final String attributeString; + final Runnable attributeCall; + RagConnectObserverEntry(ConnectToken connectToken, ASTNode node, String attributeString, Runnable attributeCall) { + this.connectToken = connectToken; + this.node = node; + this.attributeString = attributeString; + this.attributeCall = attributeCall; + } + } + java.util.List<RagConnectObserverEntry> observedNodes = new java.util.ArrayList<>(); + RagConnectObserver(ASTNode node) { + // set the receiver. potentially dangerous because overriding existing receiver! + oldReceiver = node.trace().getReceiver(); + node.trace().setReceiver(this); + } + void add(ConnectToken connectToken, ASTNode node, String attributeString, Runnable attributeCall) { + System.out.println("** observer add " + node + " on " + attributeString); + observedNodes.add(new RagConnectObserverEntry(connectToken, node, attributeString, attributeCall)); + } + void remove(ConnectToken connectToken) { + observedNodes.removeIf(entry -> entry.connectToken.equals(connectToken)); + } + @Override + public void accept(ASTState.Trace.Event event, ASTNode node, String attribute, Object params, Object value) { + oldReceiver.accept(event, node, attribute, params, value); + // ignore all events but INC_FLUSH_ATTR + if (event != ASTState.Trace.Event.INC_FLUSH_ATTR) { + return; + } + System.out.println("** observer check INC_FLUSH_ATTR event"); + // iterate through list, if matching pair. could maybe be more efficient. + for (RagConnectObserverEntry entry : observedNodes) { + if (entry.node.equals(node) && entry.attributeString.equals(attribute)) { + // hit. call the attribute/nta-token + System.out.println("** observer hit " + entry.node + " on " + entry.attributeString); + entry.attributeCall.run(); + } + } + } + } + + private static RagConnectObserver ASTNode._ragConnectObserverInstance; + RagConnectObserver ASTNode._ragConnectObserver() { + if (_ragConnectObserverInstance == null) { + // does not matter, which node is used to create the observer as ASTState/tracing is also static + _ragConnectObserverInstance = new RagConnectObserver(this); + } + return _ragConnectObserverInstance; + } +} +{{/incrementalOptionActive}} diff --git a/ragconnect.base/src/main/resources/sendDefinition.mustache b/ragconnect.base/src/main/resources/sendDefinition.mustache index 44db8f73db8c4c1484acbb4adc11a4f7f9251275..bee941ff75a105431db457c64ff24b769439a179 100644 --- a/ragconnect.base/src/main/resources/sendDefinition.mustache +++ b/ragconnect.base/src/main/resources/sendDefinition.mustache @@ -3,6 +3,12 @@ private byte[] {{parentTypeName}}.{{lastValue}} = null; public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterName}}, boolean writeCurrentValue) throws java.io.IOException { {{>handleUri}} + ConnectToken connectToken; + if (connectTokens.computeIfAbsent(this, astNode -> new java.util.HashMap<java.net.URI, ConnectToken>()) + .get(uri) != null) { + System.err.println("Already connected for " + uri + " on " + this + "!"); + return true; + } switch (scheme) { {{#usesMqtt}} case "mqtt": @@ -18,35 +24,45 @@ public boolean {{parentTypeName}}.{{connectMethod}}(String {{connectParameterNam if (writeCurrentValue) { {{writeMethod}}(); } + connectToken = new ConnectToken(uri); break; {{/usesMqtt}} {{#usesRest}} case "rest": - ConnectToken connectToken = {{restHandlerAttribute}}().newGETConnection(uri, () -> { + connectToken = {{restHandlerAttribute}}().newGETConnection(uri, () -> { {{updateMethod}}(); return new String({{lastValue}}); }); if (connectToken == null) { return false; } - connectTokens.computeIfAbsent(this, astNode -> new java.util.HashMap<java.net.URI, ConnectToken>()) - .put(uri, connectToken); break; {{/usesRest}} default: System.err.println("Unknown protocol '" + scheme + "'."); return false; } - _ragConnectObserver().add(this, "{{parentTypeName}}.get{{tokenName}}()", () -> { + connectTokens.computeIfAbsent(this, astNode -> new java.util.HashMap<java.net.URI, ConnectToken>()) + .put(uri, connectToken); + {{#incrementalOptionActive}} + _ragConnectObserver().add(connectToken, this, "{{parentTypeName}}.get{{tokenName}}()", () -> { if (this.{{updateMethod}}()) { this.{{writeMethod}}(); } }); + {{/incrementalOptionActive}} return true; } public boolean {{parentTypeName}}.{{disconnectMethod}}(String {{connectParameterName}}) throws java.io.IOException { {{>handleUri}} + ConnectToken connectToken = connectTokens.get(this).remove(uri); + if (connectToken == null) { + System.err.println("Disconnect without connect for " + uri + " on " + this + "!"); + } + {{#incrementalOptionActive}} + _ragConnectObserver().remove(connectToken); + {{/incrementalOptionActive}} switch (scheme) { {{#usesMqtt}} case "mqtt": @@ -56,7 +72,7 @@ public boolean {{parentTypeName}}.{{disconnectMethod}}(String {{connectParameter {{/usesMqtt}} {{#usesRest}} case "rest": - {{restHandlerAttribute}}().disconnect(connectTokens.get(this).get(uri)); + {{restHandlerAttribute}}().disconnect(connectToken); break; {{/usesRest}} default: diff --git a/ragconnect.tests/build.gradle b/ragconnect.tests/build.gradle index 9af1e5bb9de9878a66fc14564f2a0e504ab77abe..0788d6600618ef2adb3f1f524737278208bf6960 100644 --- a/ragconnect.tests/build.gradle +++ b/ragconnect.tests/build.gradle @@ -1,8 +1,14 @@ buildscript { - repositories.mavenCentral() + repositories { + mavenCentral() + maven { + name "gitlab-maven" + url "https://git-st.inf.tu-dresden.de/api/v4/groups/jastadd/-/packages/maven" + } + } dependencies { classpath 'org.jastadd:jastaddgradle:1.13.3' - classpath fileTree(include: ['buildSrc.jar'], dir: '../libs') + classpath 'org.jastadd.relast:relast-test:0.2.4' } } @@ -24,7 +30,6 @@ group = 'de.tudresden.inf.st' repositories { mavenCentral() - jcenter() } dependencies { @@ -82,7 +87,9 @@ sourceSets.test.java.srcDir genSrc idea.module.generatedSourceDirs += genSrc clean { - delete 'src/test/02-after-ragconnect/*/', 'src/test/03-after-relast/*/', 'src/test/java-gen/*/' + delete fileTree(dir: 'src/test/02-after-ragconnect/', exclude: '.gitignore') + delete fileTree(dir: 'src/test/03-after-relast/', exclude: '.gitignore') + delete fileTree(dir: 'src/test/java-gen/', exclude: '.gitignore') } // --- Test: Example --- @@ -332,6 +339,7 @@ task compileTutorialTest(type: RelastTest) { moreInputFiles 'src/test/01-input/tutorial/Test.jadd', 'src/test/02-after-ragconnect/tutorial/MqttHandler.jadd', 'src/test/02-after-ragconnect/tutorial/RagConnect.jadd' +// extraJastAddOptions "--tracing=cache,flush" } compileTestJava.dependsOn compileTutorialTest