Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • dev
  • feature/ros-java-integration
  • main
3 results

Target

Select target project
  • jastadd/ragconnect
1 result
Select Git revision
  • dev
  • feature/ros-java-integration
  • main
3 results
Show changes
Commits on Source (6)
Showing
with 400 additions and 116 deletions
......@@ -21,7 +21,7 @@ build:
- ./gradlew --console=plain --no-daemon assemble jar
artifacts:
paths:
- "/builds/jastadd/ragconnect/ragconnect.base/build/libs/ragconnect-*.jar"
- "ragconnect.base/build/libs/ragconnect-*.jar"
expire_in: 1 week
test:
......@@ -32,9 +32,14 @@ test:
alias: "mqtt"
script:
- ./gradlew --console=plain --no-daemon allTests
- ls -lh
- ls -lh ragconnect.tests
- ls -lh ragconnect.tests/build/test-results/
- ls -lh ragconnect.tests/build/test-results/allTests
artifacts:
when: always
reports:
junit: "/builds/jastadd/ragconnect/ragconnect.tests/build/test-results/test/TEST-*.xml"
junit: "ragconnect.tests/build/test-results/**/TEST-*.xml"
expire_in: 1 week
publish:
......
[submodule "relast-preprocessor"]
path = relast-preprocessor
url = ../relast-preprocessor.git
branch = jastadd-fix-inc-param-debug
[submodule "ragconnect.base/src/main/jastadd/mustache"]
path = ragconnect.base/src/main/jastadd/mustache
url = ../mustache
File deleted
File added
......@@ -12,6 +12,19 @@ aspect Analysis {
return result;
}
// --- lookupTypeEndpointDefinition ---
inh java.util.List<TypeEndpointDefinition> TypeEndpointDefinition.lookupTypeEndpointDefinitions(TypeComponent type);
eq RagConnect.getEndpointDefinition().lookupTypeEndpointDefinitions(TypeComponent type) = lookupTypeEndpointDefinitions(type);
syn java.util.List<TypeEndpointDefinition> RagConnect.lookupTypeEndpointDefinitions(TypeComponent type) {
java.util.List<TypeEndpointDefinition> result = new java.util.ArrayList<>();
for (EndpointDefinition def : getEndpointDefinitionList()) {
if (def.isTypeEndpointDefinition() && def.asTypeEndpointDefinition().getType().equals(type)) {
result.add(def.asTypeEndpointDefinition());
}
}
return result;
}
// --- lookupDependencyDefinition ---
inh DependencyDefinition DependencyDefinition.lookupDependencyDefinition(TypeDecl source, String id);
eq RagConnect.getDependencyDefinition().lookupDependencyDefinition(TypeDecl source, String id) {
......@@ -31,10 +44,12 @@ aspect Analysis {
}
syn boolean DependencyDefinition.isAlreadyDefined() = lookupDependencyDefinition(getSource().containingTypeDecl(), getID()) != this;
// --- matchesType ---
syn boolean TokenEndpointDefinition.matchesType(TokenEndpointDefinition other);
eq ReceiveTokenEndpointDefinition.matchesType(TokenEndpointDefinition other) = other.isReceiveTokenEndpointDefinition();
eq SendTokenEndpointDefinition.matchesType(TokenEndpointDefinition other) = other.isSendTokenEndpointDefinition();
// --- assignableTo ---
syn boolean MappingDefinitionType.assignableTo(JavaTypeUse target);
eq JavaMappingDefinitionType.assignableTo(JavaTypeUse target) = getType().assignableTo(target);
eq JavaArrayMappingDefinitionType.assignableTo(JavaTypeUse target) {
......@@ -65,6 +80,7 @@ aspect Analysis {
// --- shouldSendValue ---
syn boolean TokenEndpointDefinition.shouldSendValue() = isSendTokenEndpointDefinition() && !getToken().getNTA();
syn boolean TypeEndpointDefinition.shouldSendValue() = isSendTypeEndpointDefinition() && !getType().getNTA();
// --- needProxyToken ---
syn boolean TokenComponent.needProxyToken() = !getDependencySourceDefinitionList().isEmpty() || getTokenEndpointDefinitionList().stream().anyMatch(TokenEndpointDefinition::shouldSendValue);
......
......@@ -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;
}
......@@ -32,6 +32,10 @@ aspect Errors {
when isAlreadyDefined()
to RagConnect.errors();
SendTypeEndpointDefinition contributes error("At least one mapping needs to be used")
when effectiveMappings().isEmpty()
to RagConnect.errors();
DependencyDefinition contributes error("Dependency definition already defined for " + getSource().containingTypeDecl().getName() + " with name " + getID())
when isAlreadyDefined()
to RagConnect.errors();
......
......@@ -11,4 +11,20 @@ aspect NameResolution {
return null;
}
refine RefResolverStubs eq ASTNode.globallyResolveTypeComponentByToken(String id) {
// return a TypeComponent. id is of the form 'parent_type_name + "." + child_type_name'
int dotIndex = id.indexOf(".");
String parentTypeName = id.substring(0, dotIndex);
String childTypeName = id.substring(dotIndex + 1);
TypeDecl type = program().resolveTypeDecl(parentTypeName);
// iterate over components and find the matching typeComponent
for (Component comp : type.getComponentList()) {
if (comp.isTypeComponent() && comp.getName().equals(childTypeName)) {
return comp.asTypeComponent();
}
}
System.err.println("Could not resolve TypeComponent '" + id + "'.");
return null;
}
}
......@@ -27,13 +27,13 @@ aspect Navigation {
syn TokenEndpointDefinition EndpointDefinition.asTokenEndpointDefinition() = null;
eq TokenEndpointDefinition.asTokenEndpointDefinition() = this;
// --- isSendTokenEndpointDefinition ---
syn boolean EndpointDefinition.isSendTokenEndpointDefinition() = false;
eq SendTokenEndpointDefinition.isSendTokenEndpointDefinition() = true;
// --- isTypeEndpointDefinition ---
syn boolean EndpointDefinition.isTypeEndpointDefinition() = false;
eq TypeEndpointDefinition.isTypeEndpointDefinition() = true;
// --- asSendTokenEndpointDefinition ---
syn SendTokenEndpointDefinition EndpointDefinition.asSendTokenEndpointDefinition() = null;
eq SendTokenEndpointDefinition.asSendTokenEndpointDefinition() = this;
// --- asTypeEndpointDefinition ---
syn TypeEndpointDefinition EndpointDefinition.asTypeEndpointDefinition() = null;
eq TypeEndpointDefinition.asTypeEndpointDefinition() = this;
// --- isReceiveTokenEndpointDefinition ---
syn boolean EndpointDefinition.isReceiveTokenEndpointDefinition() = false;
......@@ -43,6 +43,30 @@ aspect Navigation {
syn ReceiveTokenEndpointDefinition EndpointDefinition.asReceiveTokenEndpointDefinition() = null;
eq ReceiveTokenEndpointDefinition.asReceiveTokenEndpointDefinition() = this;
// --- isSendTokenEndpointDefinition ---
syn boolean EndpointDefinition.isSendTokenEndpointDefinition() = false;
eq SendTokenEndpointDefinition.isSendTokenEndpointDefinition() = true;
// --- asSendTokenEndpointDefinition ---
syn SendTokenEndpointDefinition EndpointDefinition.asSendTokenEndpointDefinition() = null;
eq SendTokenEndpointDefinition.asSendTokenEndpointDefinition() = this;
// --- isReceiveTypeEndpointDefinition ---
syn boolean EndpointDefinition.isReceiveTypeEndpointDefinition() = false;
eq ReceiveTypeEndpointDefinition.isReceiveTypeEndpointDefinition() = true;
// --- asReceiveTypeEndpointDefinition ---
syn ReceiveTypeEndpointDefinition EndpointDefinition.asReceiveTypeEndpointDefinition() = null;
eq ReceiveTypeEndpointDefinition.asReceiveTypeEndpointDefinition() = this;
// --- isSendTypeEndpointDefinition ---
syn boolean EndpointDefinition.isSendTypeEndpointDefinition() = false;
eq SendTypeEndpointDefinition.isSendTypeEndpointDefinition() = true;
// --- asSendTypeEndpointDefinition ---
syn SendTypeEndpointDefinition EndpointDefinition.asSendTypeEndpointDefinition() = null;
eq SendTypeEndpointDefinition.asSendTypeEndpointDefinition() = this;
// --- targetEndpointDefinition ---
syn SendTokenEndpointDefinition DependencyDefinition.targetEndpointDefinition() {
// resolve definition in here, as we do not need resolveMethod in any other place (yet)
......
......@@ -10,6 +10,12 @@ rel TokenEndpointDefinition.Token <-> TokenComponent.TokenEndpointDefinition*;
ReceiveTokenEndpointDefinition : TokenEndpointDefinition;
SendTokenEndpointDefinition : TokenEndpointDefinition;
abstract TypeEndpointDefinition : EndpointDefinition;
rel TypeEndpointDefinition.Type <-> TypeComponent.TypeEndpointDefinition*;
ReceiveTypeEndpointDefinition : TypeEndpointDefinition;
SendTypeEndpointDefinition : TypeEndpointDefinition;
DependencyDefinition ::= <ID>;
rel DependencyDefinition.Source <-> TokenComponent.DependencySourceDefinition*;
rel DependencyDefinition.Target -> TokenComponent;
......
......@@ -18,29 +18,42 @@ aspect AttributesForMustache {
// --- MEndpointDefinition ---
syn String MEndpointDefinition.preemptiveExpectedValue();
syn String MEndpointDefinition.preemptiveReturn();
syn TokenEndpointDefinition MEndpointDefinition.endpointDef();
syn EndpointDefinition MEndpointDefinition.endpointDef();
syn String MEndpointDefinition.firstInputVarName();
syn String MEndpointDefinition.parentTypeName();
syn String MEndpointDefinition.entityName();
eq MEndpointDefinition.getInnerMappingDefinition(int i).isLast() = i == getNumInnerMappingDefinition() - 1;
eq MEndpointDefinition.getInnerMappingDefinition(int i).inputVarName() = i == 0 ? firstInputVarName() : getInnerMappingDefinition(i - 1).outputVarName();
syn String MEndpointDefinition.connectParameterName() = "uriString";
syn String MEndpointDefinition.connectMethod() = "connect" + tokenName();
syn String MEndpointDefinition.connectMethod() = "connect" + entityName();
syn String MEndpointDefinition.disconnectMethod() {
// if both (send and receive) are defined for the token, ensure methods with different names
String extra = endpointDef().lookupTokenEndpointDefinitions(token()).size() > 1 ? uniqueSuffix() : "";
return "disconnect" + extra + tokenName();
String extra;
if (endpointDef().isTokenEndpointDefinition()) {
extra = endpointDef().asTokenEndpointDefinition().lookupTokenEndpointDefinitions(token()).size() > 1 ? uniqueSuffix() : "";
} else if (endpointDef().isTypeEndpointDefinition()) {
extra = endpointDef().asTypeEndpointDefinition().lookupTypeEndpointDefinitions(type()).size() > 1 ? uniqueSuffix() : "";
} else {
extra = "";
}
return "disconnect" + extra + entityName();
}
//
syn String MEndpointDefinition.uniqueSuffix();
eq MSendDefinition.uniqueSuffix() = "Send";
eq MReceiveDefinition.uniqueSuffix() = "Receive";
eq MTokenSendDefinition.uniqueSuffix() = "Send";
eq MTokenReceiveDefinition.uniqueSuffix() = "Receive";
eq MTypeSendDefinition.uniqueSuffix() = "Send";
eq MTypeReceiveDefinition.uniqueSuffix() = "Receive";
syn TokenComponent MEndpointDefinition.token() = endpointDef().getToken();
// TODO potentially dangerous because asXEndpointDefinition can return null
syn TokenComponent MEndpointDefinition.token() = endpointDef().asTokenEndpointDefinition().getToken();
syn TypeComponent MEndpointDefinition.type() = endpointDef().asTypeEndpointDefinition().getType();
syn boolean MEndpointDefinition.alwaysApply() = endpointDef().getAlwaysApply();
syn String MEndpointDefinition.parentTypeName() = token().containingTypeDecl().getName();
syn String MEndpointDefinition.tokenName() = token().getName();
syn String MEndpointDefinition.typeName() = type().getName();
syn MInnerMappingDefinition MEndpointDefinition.lastDefinition() = getInnerMappingDefinition(getNumInnerMappingDefinition() - 1);
syn String MEndpointDefinition.lastDefinitionToType() = lastDefinition().toType();
syn String MEndpointDefinition.lastResult() = lastDefinition().outputVarName();
......@@ -51,12 +64,20 @@ aspect AttributesForMustache {
if (token().isPrimitiveType() && lastDefinition().mappingDef().getToType().isPrimitiveType()) {
return preemptiveExpectedValue() + " == " + lastResult();
}
if (lastDefinition().mappingDef().isDefaultMappingDefinition()) {
if (lastDefinition().mappingDef().getToType().isPrimitiveType() || lastDefinition().mappingDef().isDefaultMappingDefinition()) {
return preemptiveExpectedValue() + " != null && " + preemptiveExpectedValue() + ".equals(" + lastResult() + ")";
}
return preemptiveExpectedValue() + " != null ? " + preemptiveExpectedValue() + ".equals(" + lastResult() + ") : " + lastResult() + " == null";
}
// --- MTokenEndpointDefinition ---
eq MTokenEndpointDefinition.parentTypeName() = token().containingTypeDecl().getName();
eq MTokenEndpointDefinition.entityName() = tokenName();
// --- MTypeEndpointDefinition ---
eq MTypeEndpointDefinition.parentTypeName() = type().containingTypeDecl().getName();
eq MTypeEndpointDefinition.entityName() = typeName();
// --- MInnerMappingDefinition ---
inh boolean MInnerMappingDefinition.isLast();
inh String MInnerMappingDefinition.inputVarName();
......@@ -65,24 +86,43 @@ aspect AttributesForMustache {
syn MappingDefinition MInnerMappingDefinition.mappingDef() = getMMappingDefinition().getMappingDefinition();
syn String MInnerMappingDefinition.outputVarName() = "result" + methodName(); // we do not need "_" in between here, because methodName begins with one
// --- MReceiveDefinition ---
eq MReceiveDefinition.preemptiveExpectedValue() = "get" + tokenName() + "()";
eq MReceiveDefinition.preemptiveReturn() = "return;";
eq MReceiveDefinition.endpointDef() = getReceiveTokenEndpointDefinition();
eq MReceiveDefinition.firstInputVarName() = "message";
// --- MSendDefinition ---
eq MSendDefinition.preemptiveExpectedValue() = lastValue();
eq MSendDefinition.preemptiveReturn() = "return false;";
eq MSendDefinition.endpointDef() = getSendTokenEndpointDefinition();
eq MSendDefinition.firstInputVarName() = "get" + tokenName() + "()";
syn String MSendDefinition.sender() = "_sender_" + tokenName();
syn String MSendDefinition.lastValue() = "_lastValue" + tokenName();
syn String MSendDefinition.updateMethod() = "_update_" + tokenName();
syn String MSendDefinition.writeMethod() = "_writeLastValue_" + tokenName();
syn String MSendDefinition.tokenResetMethod() = "get" + tokenName() + "_reset";
syn boolean MSendDefinition.shouldSendValue() = endpointDef().shouldSendValue();
// --- MTokenReceiveDefinition ---
eq MTokenReceiveDefinition.preemptiveExpectedValue() = "get" + tokenName() + "()";
eq MTokenReceiveDefinition.preemptiveReturn() = "return;";
eq MTokenReceiveDefinition.endpointDef() = getReceiveTokenEndpointDefinition();
eq MTokenReceiveDefinition.firstInputVarName() = "message";
// --- MTokenSendDefinition ---
eq MTokenSendDefinition.preemptiveExpectedValue() = lastValue();
eq MTokenSendDefinition.preemptiveReturn() = "return false;";
eq MTokenSendDefinition.endpointDef() = getSendTokenEndpointDefinition();
eq MTokenSendDefinition.firstInputVarName() = "get" + tokenName() + "()";
syn String MTokenSendDefinition.sender() = "_sender_" + tokenName();
syn String MTokenSendDefinition.lastValue() = "_lastValue" + tokenName();
syn String MTokenSendDefinition.updateMethod() = "_update_" + tokenName();
syn String MTokenSendDefinition.writeMethod() = "_writeLastValue_" + tokenName();
syn String MTokenSendDefinition.tokenResetMethod() = "get" + tokenName() + "_reset";
syn boolean MTokenSendDefinition.shouldSendValue() = endpointDef().asTokenEndpointDefinition().shouldSendValue();
// MTypeReceiveDefinition
eq MTypeReceiveDefinition.preemptiveExpectedValue() = null;
eq MTypeReceiveDefinition.preemptiveReturn() = null;
eq MTypeReceiveDefinition.endpointDef() = getReceiveTypeEndpointDefinition();
eq MTypeReceiveDefinition.firstInputVarName() = null;
// MTypeSendDefinition
eq MTypeSendDefinition.preemptiveExpectedValue() = null;
eq MTypeSendDefinition.preemptiveReturn() = null;
eq MTypeSendDefinition.endpointDef() = getSendTypeEndpointDefinition();
eq MTypeSendDefinition.firstInputVarName() = null;
syn String MTypeSendDefinition.sender() = "_sender_" + typeName();
syn String MTypeSendDefinition.lastValue() = "_lastValue" + typeName();
syn String MTypeSendDefinition.updateMethod() = "_update_" + typeName();
syn String MTypeSendDefinition.writeMethod() = "_writeLastValue_" + typeName();
syn String MTypeSendDefinition.tokenResetMethod() = "get" + typeName() + "_reset";
syn boolean MTypeSendDefinition.shouldSendValue() = endpointDef().asTypeEndpointDefinition().shouldSendValue();
// --- MMappingDefinition ---
syn String MMappingDefinition.toType() = getMappingDefinition().getToType().prettyPrint();
......@@ -96,7 +136,7 @@ aspect AttributesForMustache {
syn String MDependencyDefinition.dependencyMethod() = "add" + capitalize(getDependencyDefinition().getID());
syn String MDependencyDefinition.sourceParentTypeName() = getDependencyDefinition().getSource().containingTypeDecl().getName();
syn String MDependencyDefinition.internalRelationPrefix() = "_internal_" + getDependencyDefinition().getID();
syn nta MSendDefinition MDependencyDefinition.targetEndpointDefinition() {
syn nta MTokenSendDefinition MDependencyDefinition.targetEndpointDefinition() {
return getDependencyDefinition().targetEndpointDefinition().toMustache();
}
......@@ -110,7 +150,7 @@ aspect AttributesForMustache {
syn String MTokenComponent.javaType() = getTokenComponent().effectiveJavaTypeUse().prettyPrint();
syn String MTokenComponent.internalName() = getTokenComponent().needProxyToken() ? "_internal_" + name() : externalName();
syn String MTokenComponent.externalName() = name();
syn MSendDefinition MTokenComponent.normalTokenSendDef() {
syn MTokenSendDefinition MTokenComponent.normalTokenSendDef() {
for (TokenEndpointDefinition endpointDef : getTokenComponent().getTokenEndpointDefinitionList()) {
if (endpointDef.shouldSendValue()) {
return endpointDef.asSendTokenEndpointDefinition().toMustache();
......@@ -124,11 +164,16 @@ aspect AttributesForMustache {
MRagConnect result = new MRagConnect();
result.setRagConnect(this);
for (EndpointDefinition def : getEndpointDefinitionList()) {
if (def.isSendTokenEndpointDefinition()) {
SendTokenEndpointDefinition sendDef = def.asSendTokenEndpointDefinition();
result.addSendDefinition(sendDef.toMustache());
if (def.isReceiveTokenEndpointDefinition()) {
result.addTokenReceiveDefinition(def.asReceiveTokenEndpointDefinition().toMustache());
} else if (def.isSendTokenEndpointDefinition()) {
result.addTokenSendDefinition(def.asSendTokenEndpointDefinition().toMustache());
} else if (def.isReceiveTypeEndpointDefinition()) {
result.addTypeReceiveDefinition(def.asReceiveTypeEndpointDefinition().toMustache());
} else if (def.isSendTypeEndpointDefinition()) {
result.addTypeSendDefinition(def.asSendTypeEndpointDefinition().toMustache());
} else {
result.addReceiveDefinition(def.asReceiveTokenEndpointDefinition().toMustache());
throw new RuntimeException("Unknown endpoint definition: " + def);
}
}
for (MappingDefinition def : allMappingDefinitions()) {
......@@ -163,20 +208,34 @@ aspect AttributesForMustache {
}
}
syn lazy MReceiveDefinition ReceiveTokenEndpointDefinition.toMustache() {
MReceiveDefinition result = new MReceiveDefinition();
syn lazy MTokenReceiveDefinition ReceiveTokenEndpointDefinition.toMustache() {
MTokenReceiveDefinition result = new MTokenReceiveDefinition();
result.setReceiveTokenEndpointDefinition(this);
result.addInnerMappings();
return result;
}
syn lazy MSendDefinition SendTokenEndpointDefinition.toMustache() {
MSendDefinition result = new MSendDefinition();
syn lazy MTokenSendDefinition SendTokenEndpointDefinition.toMustache() {
MTokenSendDefinition result = new MTokenSendDefinition();
result.setSendTokenEndpointDefinition(this);
result.addInnerMappings();
return result;
}
syn lazy MTypeReceiveDefinition ReceiveTypeEndpointDefinition.toMustache() {
MTypeReceiveDefinition result = new MTypeReceiveDefinition();
result.setReceiveTypeEndpointDefinition(this);
result.addInnerMappings();
return result;
}
syn lazy MTypeSendDefinition SendTypeEndpointDefinition.toMustache() {
MTypeSendDefinition result = new MTypeSendDefinition();
result.setSendTypeEndpointDefinition(this);
result.addInnerMappings();
return result;
}
syn lazy MMappingDefinition MappingDefinition.toMustache() {
MMappingDefinition result = new MMappingDefinition();
result.setMappingDefinition(this);
......
......@@ -79,44 +79,32 @@ aspect DefaultMappings {
aspect Mappings {
// --- effectiveMappings ---
syn java.util.List<MappingDefinition> EndpointDefinition.effectiveMappings();
eq ReceiveTokenEndpointDefinition.effectiveMappings() {
// if there is a first mapping, check if it is suitable.
// or if no mappings are specified.
// then prepend the suitable default mapping
syn java.util.List<MappingDefinition> EndpointDefinition.effectiveMappings() {
java.util.List<MappingDefinition> result;
if (getMappingList().isEmpty() || !hasSuitableEdgeMapping()) {
result = new java.util.ArrayList();
result.add(suitableDefaultMapping());
result.addAll(getMappingList());
if (isReceiveTokenEndpointDefinition() || isReceiveTypeEndpointDefinition()) {
// if no mappings are specified, or if first mapping is not suitable.
// then prepend the suitable default mapping
if (getMappingList().isEmpty() || !getMappingList().get(0).getFromType().isByteArray()) {
result = new java.util.ArrayList();
result.add(suitableReceiveDefaultMapping());
result.addAll(getMappingList());
} else {
result = getMappingList();
}
} else if (isSendTokenEndpointDefinition() || isSendTypeEndpointDefinition()) {
// if no mappings are specified, or if last mapping is not suitable
// then append the suitable default mapping
if (getMappingList().isEmpty() || !getMappingList().get(getMappingList().size() - 1).getToType().isByteArray()) {
result = new java.util.ArrayList(getMappingList());
result.add(suitableSendDefaultMapping());
} else {
result = getMappingList();
}
} else {
result = getMappingList();
throw new RuntimeException("Unknown endpoint definition: " + this);
}
return result;
}
eq SendTokenEndpointDefinition.effectiveMappings() {
// if there is a mapping, check if it is suitable.
// or if no mappings are specified.
// then append the suitable default mapping
java.util.List<MappingDefinition> result;
if (getMappingList().isEmpty() || !hasSuitableEdgeMapping()) {
result = new java.util.ArrayList(getMappingList());
result.add(suitableDefaultMapping());
} else {
result = getMappingList();
}
return result;
}
// --- hasSuitableEdgeMapping ---
syn boolean TokenEndpointDefinition.hasSuitableEdgeMapping();
eq ReceiveTokenEndpointDefinition.hasSuitableEdgeMapping() = isSuitableEdgeMapping(getMappingList().get(0));
eq SendTokenEndpointDefinition.hasSuitableEdgeMapping() = isSuitableEdgeMapping(getMappingList().get(getMappingList().size() - 1));
// --- isSuitableEdgeMapping(def) ---
syn boolean TokenEndpointDefinition.isSuitableEdgeMapping(MappingDefinition def);
eq ReceiveTokenEndpointDefinition.isSuitableEdgeMapping(MappingDefinition def) = def.getFromType().isByteArray();
eq SendTokenEndpointDefinition.isSuitableEdgeMapping(MappingDefinition def) = def.getToType().isByteArray();
// --- isPrimitiveType ---
syn boolean TokenComponent.isPrimitiveType() = effectiveJavaTypeUse().isPrimitiveType();
......@@ -140,13 +128,9 @@ aspect Mappings {
syn boolean MappingDefinitionType.isArray() = false;
eq JavaArrayMappingDefinitionType.isArray() = true;
// --- suitableDefaultMapping ---
syn DefaultMappingDefinition EndpointDefinition.suitableDefaultMapping();
eq ReceiveTokenEndpointDefinition.suitableDefaultMapping() {
String typeName = getMappingList().isEmpty() ?
getToken().effectiveJavaTypeUse().getName() :
getMappingList().get(0).getFromType().prettyPrint();
switch(typeName) {
// --- suitableReceiveDefaultMapping ---
syn DefaultMappingDefinition EndpointDefinition.suitableReceiveDefaultMapping() {
switch (targetTypeName()) {
case "int":
case "Integer": return ragconnect().defaultBytesToIntMapping();
case "short":
......@@ -163,11 +147,9 @@ aspect Mappings {
default: return null;
}
}
eq SendTokenEndpointDefinition.suitableDefaultMapping() {
String typeName = getMappingList().isEmpty() ?
getToken().effectiveJavaTypeUse().getName() :
getMappingList().get(getMappingList().size() - 1).getFromType().prettyPrint();
switch(typeName) {
// --- suitableSendDefaultMapping ---
syn DefaultMappingDefinition EndpointDefinition.suitableSendDefaultMapping() {
switch (targetTypeName()) {
case "int":
case "Integer": return ragconnect().defaultIntToBytesMapping();
case "short":
......@@ -184,6 +166,26 @@ aspect Mappings {
default: return null;
}
}
// --- targetTypeName ---
syn String EndpointDefinition.targetTypeName();
eq ReceiveTokenEndpointDefinition.targetTypeName() {
return getMappingList().isEmpty() ?
getToken().effectiveJavaTypeUse().getName() :
getMappingList().get(0).getFromType().prettyPrint();
}
eq ReceiveTypeEndpointDefinition.targetTypeName() {
return getMappingList().get(0).getFromType().prettyPrint();
}
eq SendTokenEndpointDefinition.targetTypeName() {
return getMappingList().isEmpty() ?
getToken().effectiveJavaTypeUse().getName() :
getMappingList().get(getMappingList().size() - 1).getToType().prettyPrint();
}
eq SendTypeEndpointDefinition.targetTypeName() {
return getMappingList().get(getMappingList().size() - 1).getToType().prettyPrint();
}
// eq ReceiveFromRestDefinition.suitableDefaultMapping() {
// String typeName = getMappingList().isEmpty() ?
// getToken().getJavaTypeUse().getName() :
......
MRagConnect ::= ReceiveDefinition:MReceiveDefinition* SendDefinition:MSendDefinition* MappingDefinition:MMappingDefinition* DependencyDefinition:MDependencyDefinition* RootTypeComponent:MTypeComponent* TokenComponent:MTokenComponent* Handler:MHandler*;
MRagConnect ::= TokenReceiveDefinition:MTokenReceiveDefinition* TokenSendDefinition:MTokenSendDefinition* TypeReceiveDefinition:MTypeReceiveDefinition* TypeSendDefinition:MTypeSendDefinition* MappingDefinition:MMappingDefinition* DependencyDefinition:MDependencyDefinition* RootTypeComponent:MTypeComponent* TokenComponent:MTokenComponent* Handler:MHandler*;
abstract MEndpointDefinition ::= InnerMappingDefinition:MInnerMappingDefinition*;
MReceiveDefinition : MEndpointDefinition;
MSendDefinition : MEndpointDefinition;
abstract MTokenEndpointDefinition : MEndpointDefinition;
MTokenReceiveDefinition : MTokenEndpointDefinition;
MTokenSendDefinition : MTokenEndpointDefinition;
abstract MTypeEndpointDefinition : MEndpointDefinition;
MTypeReceiveDefinition : MTypeEndpointDefinition;
MTypeSendDefinition : MTypeEndpointDefinition;
MMappingDefinition;
MInnerMappingDefinition;
MDependencyDefinition;
......@@ -11,8 +17,10 @@ MHandler ::= <ClassName> <Construction> <AttributeName> <FieldName> <InUse:boole
rel MRagConnect.RagConnect -> RagConnect;
rel MInnerMappingDefinition.MMappingDefinition -> MMappingDefinition;
rel MReceiveDefinition.ReceiveTokenEndpointDefinition -> ReceiveTokenEndpointDefinition;
rel MSendDefinition.SendTokenEndpointDefinition -> SendTokenEndpointDefinition;
rel MTokenReceiveDefinition.ReceiveTokenEndpointDefinition -> ReceiveTokenEndpointDefinition;
rel MTokenSendDefinition.SendTokenEndpointDefinition -> SendTokenEndpointDefinition;
rel MTypeReceiveDefinition.ReceiveTypeEndpointDefinition -> ReceiveTypeEndpointDefinition;
rel MTypeSendDefinition.SendTypeEndpointDefinition -> SendTypeEndpointDefinition;
rel MMappingDefinition.MappingDefinition -> MappingDefinition;
rel MDependencyDefinition.DependencyDefinition -> DependencyDefinition;
rel MTypeComponent.TypeComponent -> TypeComponent;
......
......@@ -25,19 +25,33 @@ aspect MustacheNodesToYAML {
root.put("restHandlerField", restHandlerField());
root.put("restHandlerAttribute", restHandlerAttribute());
// ReceiveDefinitions
// TokenReceiveDefinitions
ListElement receiveDefinitions = new ListElement();
for (MReceiveDefinition def : getReceiveDefinitionList()) {
for (MTokenReceiveDefinition def : getTokenReceiveDefinitionList()) {
receiveDefinitions.addElement(def.toYAML());
}
root.put("ReceiveDefinitions", receiveDefinitions);
root.put("TokenReceiveDefinitions", receiveDefinitions);
// SendDefinitions
// TokenSendDefinitions
ListElement sendDefinitions = new ListElement();
for (MSendDefinition def : getSendDefinitionList()) {
for (MTokenSendDefinition def : getTokenSendDefinitionList()) {
sendDefinitions.addElement(def.toYAML());
}
root.put("SendDefinitions", sendDefinitions);
root.put("TokenSendDefinitions", sendDefinitions);
// TypeReceiveDefinitions
ListElement typeReceiveDefinitions = new ListElement();
for (MTypeReceiveDefinition def : getTypeReceiveDefinitionList()) {
typeReceiveDefinitions.addElement(def.toYAML());
}
root.put("TypeReceiveDefinitions", typeReceiveDefinitions);
// TypeSendDefinitions
ListElement typeSendDefinitions = new ListElement();
for (MTypeSendDefinition def : getTypeSendDefinitionList()) {
typeSendDefinitions.addElement(def.toYAML());
}
root.put("TypeSendDefinitions", typeSendDefinitions);
// MappingDefinitions
ListElement mappingDefinitions = new ListElement();
......@@ -88,13 +102,30 @@ aspect MustacheNodesToYAML {
return result;
}
syn MappingElement MReceiveDefinition.toYAML() {
syn MappingElement MTokenReceiveDefinition.toYAML() {
MappingElement result = super.toYAML();
result.put("loggingEnabledForReads", loggingEnabledForReads);
return result;
}
syn MappingElement MTokenSendDefinition.toYAML() {
MappingElement result = super.toYAML();
result.put("sender", sender());
result.put("lastValue", lastValue());
result.put("loggingEnabledForWrites", loggingEnabledForWrites);
result.put("updateMethod", updateMethod());
result.put("writeMethod", writeMethod());
result.put("tokenResetMethod", tokenResetMethod());
return result;
}
syn MappingElement MTypeReceiveDefinition.toYAML() {
MappingElement result = super.toYAML();
result.put("loggingEnabledForReads", loggingEnabledForReads);
return result;
}
syn MappingElement MSendDefinition.toYAML() {
syn MappingElement MTypeSendDefinition.toYAML() {
MappingElement result = super.toYAML();
result.put("sender", sender());
result.put("lastValue", lastValue());
......
......@@ -33,12 +33,18 @@ EndpointDefinition endpoint_definition
EndpointDefinition endpoint_definition_type
= RECEIVE token_ref {: return new ReceiveTokenEndpointDefinition().setToken(token_ref); :}
| SEND token_ref {: return new SendTokenEndpointDefinition().setToken(token_ref); :}
| RECEIVE TREE type_ref {: return new ReceiveTypeEndpointDefinition().setType(type_ref); :}
| SEND TREE type_ref {: return new SendTypeEndpointDefinition().setType(type_ref); :}
;
TokenComponent token_ref
= ID.type_name DOT ID.token_name {: return TokenComponent.createRef(type_name + "." + token_name); :}
;
TypeComponent type_ref
= ID.parent_type_name DOT ID.child_type_name {: return TypeComponent.createRef(parent_type_name + "." + child_type_name); :}
;
ArrayList string_list
= ID
| string_list COMMA ID
......
......@@ -5,3 +5,4 @@
"maps" { return sym(Terminals.MAPS); }
"to" { return sym(Terminals.TO); }
"as" { return sym(Terminals.AS); }
"tree" { return sym(Terminals.TREE); }
......@@ -223,6 +223,9 @@ 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();
printMessage("ASTNode.incrementalOptionActive = " + ASTNode.incrementalOptionActive);
ASTNode.usesMqtt = optionProtocols.hasValue(OPTION_PROTOCOL_MQTT);
ASTNode.usesRest = optionProtocols.hasValue(OPTION_PROTOCOL_REST);
return ragConnect;
......
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
aspect MqttHandler {
......@@ -160,9 +161,9 @@ public class MqttHandler {
org.fusesource.mqtt.client.Callback<org.fusesource.mqtt.client.Callback<Void>> ack) {
// this method is called, whenever a MQTT message is received
String topicString = topic.toString();
java.util.List<java.util.function.Consumer<byte[]>> callbackList = callbacks.get(topicString);
java.util.List<java.util.function.Consumer<byte[]>> callbackList = new java.util.ArrayList<>(callbacks.get(topicString));
if (callbackList == null || callbackList.isEmpty()) {
logger.debug("Got a message, but no callback to call. Forgot to subscribe?");
logger.debug("Got a message at {}, but no callback to call. Forgot to subscribe?", topic);
} else {
byte[] message = body.toByteArray();
for (java.util.function.Consumer<byte[]> callback : callbackList) {
......@@ -247,7 +248,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
......
{{#usesMqtt}}{{> mqtt}}{{/usesMqtt}}
{{> handler}}
aspect ROS2RAG {
{{#ReceiveDefinitions}}
aspect RagConnect {
{{#TokenReceiveDefinitions}}
{{> receiveDefinition}}
{{/ReceiveDefinitions}}
{{/TokenReceiveDefinitions}}
{{#SendDefinitions}}
{{#TokenSendDefinitions}}
{{> sendDefinition}}
{{/SendDefinitions}}
{{/TokenSendDefinitions}}
{{#TypeReceiveDefinitions}}
{{> receiveDefinition}}
{{/TypeReceiveDefinitions}}
{{#TypeSendDefinitions}}
{{> sendDefinition}}
{{/TypeSendDefinitions}}
{{#MappingDefinitions}}
{{> mappingDefinition}}
......@@ -20,4 +28,75 @@ aspect ROS2RAG {
{{#TokenComponents}}
{{> tokenComponent}}
{{/TokenComponents}}
public void {{rootNodeName}}.ragconnectCheckIncremental() {
{{#incrementalOptionActive}}
// check if --tracing is active
trace().getReceiver();
// check if tracing of INC_FLUSH_ATTR is possible, i.e., if --tracing=flush
ASTState.Trace.Event checkTracing = ASTState.Trace.Event.INC_FLUSH_ATTR;
// check if --rewrite is active
mayHaveRewrite();
// check if --incremental is active
Object checkIncremental = inc_throwAway_visited;
{{/incrementalOptionActive}}
}
}
{{#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}}
......@@ -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,30 +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;
}
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":
......@@ -51,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:
......