Commit e3e8ea60 authored by Johannes Mey's avatar Johannes Mey
Browse files

Merge branch '19-poc-use-mustache-as-template-engine' into 'master'

Resolve "PoC: Use mustache as template engine"

Closes #19

See merge request jastadd/ros2rag!2
parents 2e3c1b05 972f9aea
Pipeline #7203 passed with stages
in 5 minutes and 50 seconds
...@@ -40,7 +40,6 @@ subprojects { ...@@ -40,7 +40,6 @@ subprojects {
dependencies { dependencies {
implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.11.2' implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.11.2'
implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.2' implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.11.2'
testImplementation group: 'junit', name: 'junit', version: '4.12'
testImplementation group: 'org.hamcrest', name: 'hamcrest-junit', version: '2.0.0.0' testImplementation group: 'org.hamcrest', name: 'hamcrest-junit', version: '2.0.0.0'
} }
......
...@@ -17,10 +17,9 @@ buildscript { ...@@ -17,10 +17,9 @@ buildscript {
} }
dependencies { dependencies {
implementation 'com.fasterxml.jackson.core:jackson-core:2.9.8' implementation group: 'com.github.spullara.mustache.java', name: 'compiler', version: '0.9.6'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8' implementation group: 'org.apache.logging.log4j', name: 'log4j-jul', version: '2.11.2'
// api 'org.jastadd:jastadd:2.3.4' runtime group: 'org.jastadd', name: 'jastadd', version: '2.3.4'
runtime 'org.jastadd:jastadd:2.3.4'
api group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11' api group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
} }
...@@ -62,6 +61,7 @@ task relast(type: JavaExec) { ...@@ -62,6 +61,7 @@ task relast(type: JavaExec) {
"../libs/relast.jar", "../libs/relast.jar",
"../relast.preprocessor/src/main/jastadd/RelAst.relast", "../relast.preprocessor/src/main/jastadd/RelAst.relast",
"./src/main/jastadd/Ros2Rag.relast", "./src/main/jastadd/Ros2Rag.relast",
"./src/main/jastadd/MustacheNodes.relast",
"--listClass=java.util.ArrayList", "--listClass=java.util.ArrayList",
"--jastAddList=JastAddList", "--jastAddList=JastAddList",
"--useJastAddNames", "--useJastAddNames",
...@@ -72,11 +72,12 @@ task relast(type: JavaExec) { ...@@ -72,11 +72,12 @@ task relast(type: JavaExec) {
inputs.files file("../libs/relast.jar"), inputs.files file("../libs/relast.jar"),
file("../relast.preprocessor/src/main/jastadd/RelAST.relast"), file("../relast.preprocessor/src/main/jastadd/RelAST.relast"),
file("src/main/jastadd/Ros2Rag.relast") file("./src/main/jastadd/Ros2Rag.relast")
file("./src/main/jastadd/MustacheNodes.relast")
outputs.files file("./src/gen/jastadd/Ros2Rag.ast"), outputs.files file("./src/gen/jastadd/Ros2Rag.ast"),
file("src/gen/jastadd/Ros2Rag.jadd"), file("./src/gen/jastadd/Ros2Rag.jadd"),
file("src/gen/jastadd/Ros2RagRefResolver.jadd"), file("./src/gen/jastadd/Ros2RagRefResolver.jadd"),
file('src/gen/jastadd/Ros2RagResolverStubs.jrag') file('./src/gen/jastadd/Ros2RagResolverStubs.jrag')
} }
jastadd { jastadd {
......
//TypeComponentMustache ;
//rel TypeComponentMustache.TypeComponent -> TypeComponent ;
MRos2Rag ::= ReadDefinition:MReadDefinition* WriteDefinition:MWriteDefinition* MappingDefinition:MMappingDefinition* DependencyDefinition:MDependencyDefinition* RootTypeComponent:MTypeComponent* TokenComponent:MTokenComponent*;
abstract MUpdateDefinition ::= InnerMappingDefinition:MInnerMappingDefinition*;
MReadDefinition : MUpdateDefinition;
MWriteDefinition : MUpdateDefinition;
MMappingDefinition;
MInnerMappingDefinition;
MDependencyDefinition;
MTypeComponent;
MTokenComponent;
rel MRos2Rag.Ros2Rag -> Ros2Rag;
rel MInnerMappingDefinition.MappingDefinition -> MappingDefinition;
rel MReadDefinition.ReadFromMqttDefinition -> ReadFromMqttDefinition;
rel MWriteDefinition.WriteToMqttDefinition -> WriteToMqttDefinition;
rel MMappingDefinition.MappingDefinition -> MappingDefinition;
rel MDependencyDefinition.DependencyDefinition -> DependencyDefinition;
rel MTypeComponent.TypeComponent -> TypeComponent;
rel MTokenComponent.TokenComponent -> TokenComponent;
rel MTokenComponent.DependencyDefinition* -> MDependencyDefinition;
...@@ -2,10 +2,12 @@ aspect Navigation { ...@@ -2,10 +2,12 @@ aspect Navigation {
// --- program --- // --- program ---
eq Ros2Rag.getChild().program() = getProgram(); eq Ros2Rag.getChild().program() = getProgram();
eq MRos2Rag.getChild().program() = getRos2Rag().program();
// --- ros2rag // --- ros2rag ---
inh Ros2Rag ASTNode.ros2rag(); inh Ros2Rag ASTNode.ros2rag();
eq Ros2Rag.getChild().ros2rag() = this; eq Ros2Rag.getChild().ros2rag() = this;
eq MRos2Rag.getChild().ros2rag() = getRos2Rag();
// --- containedFile (first equation should be in preprocessor) --- // --- containedFile (first equation should be in preprocessor) ---
eq Program.getChild().containedFile() = null; eq Program.getChild().containedFile() = null;
...@@ -32,6 +34,7 @@ aspect Navigation { ...@@ -32,6 +34,7 @@ aspect Navigation {
eq GrammarFile.getChild().containedFileName() = getFileName(); eq GrammarFile.getChild().containedFileName() = getFileName();
eq Ros2Rag.getChild().containedFileName() = getFileName(); eq Ros2Rag.getChild().containedFileName() = getFileName();
eq Program.getChild().containedFileName() = null; eq Program.getChild().containedFileName() = null;
eq MRos2Rag.getChild().containedFileName() = null;
// --- isTokenUpdateDefinition --- // --- isTokenUpdateDefinition ---
syn boolean UpdateDefinition.isTokenUpdateDefinition() = false; syn boolean UpdateDefinition.isTokenUpdateDefinition() = false;
...@@ -49,6 +52,10 @@ aspect Navigation { ...@@ -49,6 +52,10 @@ aspect Navigation {
syn WriteToMqttDefinition UpdateDefinition.asWriteToMqttDefinition() = null; syn WriteToMqttDefinition UpdateDefinition.asWriteToMqttDefinition() = null;
eq WriteToMqttDefinition.asWriteToMqttDefinition() = this; eq WriteToMqttDefinition.asWriteToMqttDefinition() = this;
// --- asReadFromMqttDefinition ---
syn ReadFromMqttDefinition UpdateDefinition.asReadFromMqttDefinition() = null;
eq ReadFromMqttDefinition.asReadFromMqttDefinition() = this;
// --- targetUpdateDefinition --- // --- targetUpdateDefinition ---
syn WriteToMqttDefinition DependencyDefinition.targetUpdateDefinition() { syn WriteToMqttDefinition DependencyDefinition.targetUpdateDefinition() {
// resolve definition in here, as we do not need resolveMethod in any other place (yet) // resolve definition in here, as we do not need resolveMethod in any other place (yet)
......
...@@ -10,7 +10,6 @@ rel TokenUpdateDefinition.Token -> TokenComponent; ...@@ -10,7 +10,6 @@ rel TokenUpdateDefinition.Token -> TokenComponent;
ReadFromMqttDefinition : TokenUpdateDefinition; ReadFromMqttDefinition : TokenUpdateDefinition;
WriteToMqttDefinition : TokenUpdateDefinition; WriteToMqttDefinition : TokenUpdateDefinition;
// example: RobotArm._AppropriateSpeed canDependOn Joint.CurrentPosition as dependency1
DependencyDefinition ::= <ID>; DependencyDefinition ::= <ID>;
rel DependencyDefinition.Source <-> TokenComponent.DependencySourceDefinition*; rel DependencyDefinition.Source <-> TokenComponent.DependencySourceDefinition*;
rel DependencyDefinition.Target -> TokenComponent; rel DependencyDefinition.Target -> TokenComponent;
......
aspect Configuration { aspect Configuration {
public static boolean ASTNode.loggingEnabledForReads = false; public static boolean ASTNode.loggingEnabledForReads = false;
public static boolean ASTNode.loggingEnabledForWrites = false; public static boolean ASTNode.loggingEnabledForWrites = false;
public static TypeDecl ASTNode.rootNode;
} }
package org.jastadd.ros2rag.compiler;
import java.io.IOException;
import java.io.Writer;
/**
* Writer appending to a StringBuilder.
*
* @author rschoene - Initial contribution
*/
public class AppendableWriter extends Writer {
private final StringBuilder sb;
public AppendableWriter(StringBuilder sb) {
this.sb = sb;
}
@Override
public void write(char[] chars, int off, int len) throws IOException {
sb.append(chars, off, len);
}
@Override
public void write(String str) throws IOException {
sb.append(str);
}
@Override
public void flush() {
}
@Override
public void close() {
}
}
...@@ -37,6 +37,8 @@ public class Compiler { ...@@ -37,6 +37,8 @@ public class Compiler {
} }
public void run(String[] args) throws CommandLineException, CompilerException { public void run(String[] args) throws CommandLineException, CompilerException {
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
System.setProperty("mustache.debug", "true");
options = new ArrayList<>(); options = new ArrayList<>();
addOptions(); addOptions();
commandLine = new CommandLine(options); commandLine = new CommandLine(options);
......
public void {{targetParentTypeName}}.{{dependencyMethod}}({{sourceParentTypeName}} source) {
add{{internalRelationPrefix}}Source(source);
}
{{lastDefinitionToType}} {{resultVarPrefix}}{{lastDefinitionName}};
try {
{{#InnerMappingDefinitions}}
{{^last}}{{ToType}} {{/last}}{{resultVarPrefix}}{{methodName}} = {{methodName}}({{inputVarName}});{{!inputVarName has to be computed beforehand}}
{{/InnerMappingDefinitions}}
} catch (Exception e) {
e.printStackTrace();
{{preemptiveReturn}}
}
{{^alwaysApply}}
if ({{{condition}}}) {
{{preemptiveReturn}}
}
{{/alwaysApply}}
protected static {{toType}} ASTNode.{{methodName}}({{fromType}} {{fromVariableName}}) throws Exception {
{{{content}}}{{!maybe print line by line to get better indentation}}
}
aspect MQTT {
private MqttUpdater {{rootNodeName}}.{{mqttUpdaterField}} = new MqttUpdater();
public void {{rootNodeName}}.{{mqttSetHostMethod}}(String host) throws java.io.IOException {
{{mqttUpdaterField}}.setHost(host);
}
public void {{rootNodeName}}.{{mqttSetHostMethod}}(String host, int port) throws java.io.IOException {
{{mqttUpdaterField}}.setHost(host, port);
}
public boolean {{rootNodeName}}.{{mqttWaitUntilReadyMethod}}(long time, java.util.concurrent.TimeUnit unit) {
return {{mqttUpdaterField}}.waitUntilReady(time, unit);
}
public void {{rootNodeName}}.{{mqttCloseMethod}}() {
{{mqttUpdaterField}}.close();
}
inh MqttUpdater ASTNode.{{mqttUpdaterAttribute}}();
{{#getRootTypeComponents}}
eq {{rootNodeName}}.get{{name}}().{{mqttUpdaterAttribute}}() = {{mqttUpdaterField}};
{{/getRootTypeComponents}}
}
public void {{parentTypeName}}.{{connectMethod}}(String topic) {
{{mqttUpdaterAttribute}}().newConnection(topic, message -> {
{{> mappingApplication}}
{{#loggingEnabledForReads}}
System.out.println("[Read] " + topic + " -> {{tokenName}} = " + {{lastResult}});{{!lastResult has to be a new attribute}}
{{/loggingEnabledForReads}}
set{{tokenName}}({{lastResult}});
});
}
{{> mqtt}}
aspect ROS2RAG {
{{#ReadDefinitions}}
{{> readDefinition}}
{{/ReadDefinitions}}
{{#WriteDefinitions}}
{{> writeDefinition}}
{{/WriteDefinitions}}
{{#MappingDefinitions}}
{{> mappingDefinition}}
{{/MappingDefinitions}}
{{#DependencyDefinitions}}
{{> dependencyDefinition}}
{{/DependencyDefinitions}}
{{#TokenComponents}}
{{> tokenComponent}}
{{/TokenComponents}}
}
public {{parentTypeName}} {{parentTypeName}}.set{{name}}({{javaType}} value) {
set{{internalName}}(value);
{{#DependencyDefinitions}}
for ({{targetParentTypeName}} target : get{{internalRelationPrefix}}TargetList()) {
{{#targetUpdateDefinition}}
if (target.{{updateMethod}}()) {
target.{{writeMethod}}();
}
{{/targetUpdateDefinition}}
}
{{/DependencyDefinitions}}
return this;
}
public {{javaType}} {{parentTypeName}}.get{{name}}() {
return get{{internalName}}();
}
private String {{parentTypeName}}.{{writeTopic}} = null;
private byte[] {{parentTypeName}}.{{lastValue}} = null;
public void {{parentTypeName}}.{{connectMethod}}(String topic, boolean writeCurrentValue) {
{{writeTopic}} = topic;
{{updateMethod}}();
if (writeCurrentValue) {
{{writeMethod}}();
}
}
protected boolean {{parentTypeName}}.{{updateMethod}}() {
{{tokenResetMethod}}();
{{> mappingApplication}}
{{lastValue}} = {{lastResult}};
return true;
}
protected void {{parentTypeName}}.{{writeMethod}}() {
{{#loggingEnabledForWrites}}
System.out.println("[Write] {{tokenName}} = " + get{{tokenName}}() + " -> " + {{writeTopic}});
{{/loggingEnabledForWrites}}
{{mqttUpdaterAttribute}}().publish({{writeTopic}}, {{lastValue}});
}
...@@ -25,8 +25,8 @@ dependencies { ...@@ -25,8 +25,8 @@ dependencies {
implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: "${jackson_version}" implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: "${jackson_version}"
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: "${jackson_version}" implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: "${jackson_version}"
implementation group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11' implementation group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
compile 'com.google.protobuf:protobuf-java:3.0.0' implementation group: 'com.google.protobuf', name: 'protobuf-java', version: '3.0.0'
compile group: 'org.fusesource.mqtt-client', name: 'mqtt-client', version: '1.15' implementation group: 'org.fusesource.mqtt-client', name: 'mqtt-client', version: '1.15'
protobuf files("$projectDir/../ros2rag.example/src/main/proto") protobuf files("$projectDir/../ros2rag.example/src/main/proto")
} }
......
...@@ -4,9 +4,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; ...@@ -4,9 +4,10 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import config.Dataconfig.DataConfig; import config.Dataconfig.DataConfig;
import config.Robotconfig.RobotConfig; import config.Robotconfig.RobotConfig;
import de.tudresden.inf.st.ros2rag.starter.Util;
import de.tudresden.inf.st.ros2rag.starter.ast.MqttUpdater; import de.tudresden.inf.st.ros2rag.starter.ast.MqttUpdater;
import de.tudresden.inf.st.ros2rag.starter.data.DataConfiguration; import de.tudresden.inf.st.ros2rag.starter.data.DataConfiguration;
import de.tudresden.inf.st.ros2rag.starter.data.DataJoint; import de.tudresden.inf.st.ros2rag.starter.data.DataConfiguration.ActualConfiguration;
import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
...@@ -16,6 +17,7 @@ import java.io.File; ...@@ -16,6 +17,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class Main { public class Main {
...@@ -27,23 +29,24 @@ public class Main { ...@@ -27,23 +29,24 @@ public class Main {
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
File configFile = new File(args[0]); File configFile = new File(args[0]);
System.out.println("Using config file: " + configFile.getAbsolutePath()); System.out.println("Using config file: " + configFile.getAbsolutePath());
DataConfiguration config = mapper.readValue(configFile, DataConfiguration.class); ActualConfiguration config = mapper.readValue(configFile, DataConfiguration.class).panda_mqtt_connector;
main.run(config); main.run(config);
} }
private void run(DataConfiguration config) throws IOException, InterruptedException { private void run(ActualConfiguration config) throws IOException, InterruptedException {
final CountDownLatch finish = new CountDownLatch(1); final CountDownLatch finish = new CountDownLatch(1);
int topicMaxLength = 0; AtomicInteger topicMaxLength = new AtomicInteger();
MqttUpdater receiver = new MqttUpdater("receiver stub"); MqttUpdater receiver = new MqttUpdater("receiver stub");
receiver.setHost(config.mqttHost); Util.setMqttHost(receiver, config);
receiver.waitUntilReady(2, TimeUnit.SECONDS); receiver.waitUntilReady(2, TimeUnit.SECONDS);
receiver.newConnection(config.robotConfigTopic, this::printRobotConfig); receiver.newConnection(config.topics.robotConfig, this::printRobotConfig);
receiver.newConnection(config.dataConfigTopic, this::printDataConfig); receiver.newConnection(config.topics.dataConfig, this::printDataConfig);
for (DataJoint joint : config.joints) {
receiver.newConnection(joint.topic, this::printPandaLinkState); Util.iterateLinks((isEndEffector, topic, name) -> {
topicMaxLength = Math.max(topicMaxLength, joint.topic.length()); receiver.newConnection(topic, this::printPandaLinkState);
} topicMaxLength.set(Math.max(topicMaxLength.get(), topic.length()));
}, config);
this.topicPattern = "%" + topicMaxLength + "s"; this.topicPattern = "%" + topicMaxLength + "s";
receiver.newConnection("components", bytes -> { receiver.newConnection("components", bytes -> {
...@@ -59,11 +62,7 @@ public class Main { ...@@ -59,11 +62,7 @@ public class Main {
}); });
Runtime.getRuntime().addShutdownHook(new Thread(receiver::close)); Runtime.getRuntime().addShutdownHook(new Thread(receiver::close));
if (config.exitAfterSeconds > 0) { finish.await();
finish.await(config.exitAfterSeconds, TimeUnit.SECONDS);
} else {
finish.await();
}
receiver.close(); receiver.close();
} }
......
...@@ -25,8 +25,8 @@ dependencies { ...@@ -25,8 +25,8 @@ dependencies {
implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: "${jackson_version}" implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-xml', version: "${jackson_version}"
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: "${jackson_version}" implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: "${jackson_version}"
implementation group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11' implementation group: 'net.sf.beaver', name: 'beaver-rt', version: '0.9.11'
compile 'com.google.protobuf:protobuf-java:3.0.0' implementation group: 'com.google.protobuf', name: 'protobuf-java', version: '3.0.0'
compile group: 'org.fusesource.mqtt-client', name: 'mqtt-client', version: '1.15' implementation group: 'org.fusesource.mqtt-client', name: 'mqtt-client', version: '1.15'
protobuf files("$projectDir/../ros2rag.example/src/main/proto") protobuf files("$projectDir/../ros2rag.example/src/main/proto")
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment