Skip to content
Snippets Groups Projects

Resolve "Feature: Add context-free connect"

Merged René Schöne requested to merge 34-feature-add-context-free-connect into dev
13 files
+ 123
144
Compare changes
  • Side-by-side
  • Inline
Files
13
  • 8dd7a3fa
    working on concise grammar · 8dd7a3fa
    René Schöne authored
    - resolve todos, mainly renaming
    - fix negative test cases
    - run negative test cases also in CI
    - move generateAspect into Compiler.java
/*
Design considerations
- [OLD] InnerMappingDefinition needed for iteration attribute (first, last) - not possible with list-relation
- [NEW in 1.0.0] no complete intermediate structure, but instead single nodes where applicable
- InnerMappingDefinition needed for iteration attribute (first, last) - not possible with list-relation
- no complete intermediate structure, but instead single nodes where applicable/needed
*/
aspect NewStuff {
aspect AttributesForMustache {
syn List<TypeComponent> RagConnect.rootTypeComponents() {
List<TypeComponent> result = new ArrayList<>();
for (Component child : rootNode.getComponentList()) {
@@ -15,13 +15,10 @@ aspect NewStuff {
}
syn boolean RagConnect.hasRootTypeComponents() = !rootTypeComponents().isEmpty();
// inh boolean TypeComponent.isFirst();
// eq RagConnect.getRootTypeComponentList(int i).isFirst() = i == 0;
syn String RagConnect.closeMethod() = "ragconnectCloseConnections";
syn String RagConnect.closeMethodName() = "ragconnectCloseConnections";
syn String RagConnect.mqttHandlerAttribute() = "_mqttHandler";
syn String RagConnect.mqttHandlerField() = "_mqttHandler";
syn String RagConnect.mqttSetupWaitUntilReadyMethod() = "ragconnectSetupMqttWaitUntilReady";
syn String RagConnect.mqttSetupWaitUntilReadyMethodName() = "ragconnectSetupMqttWaitUntilReady";
syn String RagConnect.restHandlerAttribute() = "_restHandler";
syn String RagConnect.restHandlerField() = "_restHandler";
@@ -47,20 +44,20 @@ aspect NewStuff {
syn String EndpointDefinition.preemptiveExpectedValue() = toMustache().preemptiveExpectedValue();
syn String EndpointDefinition.preemptiveReturn() = toMustache().preemptiveReturn();
syn String EndpointDefinition.firstInputVarName() = toMustache().firstInputVarName();
syn String EndpointDefinition.updateMethod() = toMustache().updateMethod();
syn String EndpointDefinition.writeMethod() = toMustache().writeMethod();
syn String EndpointDefinition.updateMethodName() = toMustache().updateMethodName();
syn String EndpointDefinition.writeMethodName() = toMustache().writeMethodName();
syn String EndpointDefinition.parentTypeName() = getEndpointTarget().parentTypeName();
syn String EndpointDefinition.entityName() = getEndpointTarget().entityName();
syn String EndpointDefinition.getterMethod() = getEndpointTarget().getterMethod();
syn String EndpointDefinition.getterMethodName() = getEndpointTarget().getterMethodName();
syn String EndpointDefinition.uniqueSuffix() = getSend() ? "Send" : "Receive";
syn String EndpointDefinition.connectParameterName() = "uriString";
syn String EndpointDefinition.connectMethod() = "connect" + entityName();
syn String EndpointDefinition.internalConnectMethod() = "_internal_" + connectMethod();
syn String EndpointDefinition.connectMethodName() = "connect" + entityName();
syn String EndpointDefinition.internalConnectMethodName() = "_internal_" + connectMethodName();
syn String EndpointDefinition.disconnectMethod() {
syn String EndpointDefinition.disconnectMethodName() {
// if both (send and receive) are defined for an endpoint, ensure methods with different names
String extra;
if (getEndpointTarget().isTokenEndpointTarget()) {
@@ -72,7 +69,7 @@ aspect NewStuff {
}
return "disconnect" + extra + entityName();
}
// TODO [OLD] potentially dangerous because asXEndpointDefinition can return null
// token and type are potentially dangerous because asXEndpointTarget can return null
syn TokenComponent EndpointDefinition.token() = getEndpointTarget().asTokenEndpointTarget().getToken();
syn TypeComponent EndpointDefinition.type() = getEndpointTarget().asTypeEndpointTarget().getType();
syn String EndpointDefinition.tokenName() = token().getName();
@@ -85,7 +82,7 @@ aspect NewStuff {
syn MInnerMappingDefinition MEndpointDefinition.lastDefinition() = getInnerMappingDefinition(getNumInnerMappingDefinition() - 1);
syn String EndpointDefinition.lastDefinitionToType() = lastDefinition().toType();
syn String EndpointDefinition.lastResult() = lastDefinition().outputVarName();
// TODO check, whether this works
inh boolean MInnerMappingDefinition.isLast();
eq MEndpointDefinition.getInnerMappingDefinition(int i).isLast() = i == getNumInnerMappingDefinition() - 1;
eq MEndpointDefinition.getInnerMappingDefinition(int i).inputVarName() = i == 0 ? firstInputVarName() : getInnerMappingDefinition(i - 1).outputVarName();
@@ -112,45 +109,42 @@ aspect NewStuff {
return preemptiveExpectedValue() + " != null ? " + preemptiveExpectedValue() + ".equals(" + lastResult() + ") : " + lastResult() + " == null";
}
// TODO rename sender to senderName
syn String EndpointDefinition.sender() = getEndpointTarget().senderName(); // only needed for send endpoints
syn String EndpointDefinition.senderName() = getEndpointTarget().senderName(); // only needed for send endpoints
syn String EndpointTarget.senderName();
eq TokenEndpointTarget.senderName() = "_sender_" + getToken().getName();
eq TypeEndpointTarget.senderName() = "_sender_" + getType().getName();
syn String EndpointDefinition.lastValue() = sender() + ".lastValue"; // only needed for send endpoints
syn String EndpointDefinition.lastValue() = senderName() + ".lastValue"; // only needed for send endpoints
syn String MEndpointDefinition.lastValue() = getEndpointDefinition().lastValue();
// TODO rename getterMethod to getterMethodName
syn String EndpointTarget.getterMethod();
syn String EndpointTarget.getterMethodName();
syn String EndpointTarget.parentTypeName();
syn String EndpointTarget.entityName();
eq TokenEndpointTarget.getterMethod() = "get" + getToken().getName();
eq TokenEndpointTarget.getterMethodName() = "get" + getToken().getName();
eq TokenEndpointTarget.parentTypeName() = getToken().containingTypeDecl().getName();
eq TokenEndpointTarget.entityName() = getToken().getName();
eq TypeEndpointTarget.getterMethod() = "get" + getType().getName() + (typeIsList() ? "List" : "");
eq TypeEndpointTarget.getterMethodName() = "get" + getType().getName() + (typeIsList() ? "List" : "");
eq TypeEndpointTarget.parentTypeName() = getType().containingTypeDecl().getName();
eq TypeEndpointTarget.entityName() = getType().getName() + (typeIsList() && !containingEndpointDefinition().getIndexBasedListAccess() ? "List" : "");
// only for token + send
// TODO rename tokenResetMethod to tokenResetMethodName
syn String EndpointDefinition.tokenResetMethod() = getterMethod() + "_reset";
syn String EndpointDefinition.tokenResetMethodName() = getterMethodName() + "_reset";
// only for type + receive
syn String EndpointDefinition.resolveInListMethodName() = "_ragconnect_resolve" + entityName() + "InList";
// --- MMappingDefinition ---
// --- MappingDefinition ---
syn String MappingDefinition.toType() = getToType().prettyPrint();
syn String MappingDefinition.methodName() = "_apply_" + getID();
syn String MappingDefinition.fromType() = getFromType().prettyPrint();
syn boolean MappingDefinition.isUsed() = !effectiveUsedAt().isEmpty();
// --- MDependencyDefinition ---
// --- DependencyDefinition ---
syn String DependencyDefinition.targetParentTypeName() = getTarget().containingTypeDecl().getName();
syn String DependencyDefinition.dependencyMethod() = "add" + capitalize(getID());
syn String DependencyDefinition.dependencyMethodName() = "add" + capitalize(getID());
syn String DependencyDefinition.sourceParentTypeName() = getSource().containingTypeDecl().getName();
syn String DependencyDefinition.internalRelationPrefix() = "_internal_" + getID();
// --- MTokenComponent ---
// --- TokenComponent ---
syn String TokenComponent.parentTypeName() = containingTypeDecl().getName();
syn String TokenComponent.javaType() = effectiveJavaTypeUse().prettyPrint();
syn String TokenComponent.internalName() = needProxyToken() ? "_internal_" + getName() : externalName();
@@ -203,9 +197,8 @@ aspect NewStuff {
syn JastAddList<MInnerMappingDefinition> EndpointDefinition.innerMappingDefinitions() = toMustache().getInnerMappingDefinitionList();
syn boolean EndpointDefinition.hasTypeEndpointTarget() = getEndpointTarget().isTypeEndpointTarget();
}
aspect OldStuff { // copied unchanged, but should work
// === OldStuff (copied unchanged, but should work) ===
// --- EndpointDefinition ---
syn String EndpointDefinition.idTokenName() = "InternalRagconnectTopicInList";
@@ -215,9 +208,9 @@ aspect OldStuff { // copied unchanged, but should work
syn String MEndpointDefinition.firstInputVarName();
syn String MEndpointDefinition.parentTypeName() = getEndpointDefinition().parentTypeName();
syn String MEndpointDefinition.entityName() = getEndpointDefinition().entityName();
syn String MEndpointDefinition.updateMethod();
syn String MEndpointDefinition.writeMethod();
syn String MEndpointDefinition.getterMethod() = getEndpointDefinition().getterMethod();
syn String MEndpointDefinition.updateMethodName();
syn String MEndpointDefinition.writeMethodName();
syn String MEndpointDefinition.getterMethodName() = getEndpointDefinition().getterMethodName();
// --- MInnerMappingDefinition ---
inh String MInnerMappingDefinition.inputVarName();
@@ -226,72 +219,37 @@ aspect OldStuff { // copied unchanged, but should work
syn String MInnerMappingDefinition.outputVarName() = "result" + methodName(); // we do not need "_" in between here, because methodName begins with one
// --- MTokenReceiveDefinition ---
eq MTokenReceiveDefinition.preemptiveExpectedValue() = getterMethod() + "()";
eq MTokenReceiveDefinition.preemptiveExpectedValue() = getterMethodName() + "()";
eq MTokenReceiveDefinition.preemptiveReturn() = "return;";
eq MTokenReceiveDefinition.firstInputVarName() = "message";
eq MTokenReceiveDefinition.updateMethod() = null;
eq MTokenReceiveDefinition.writeMethod() = null;
eq MTokenReceiveDefinition.updateMethodName() = null;
eq MTokenReceiveDefinition.writeMethodName() = null;
// --- MTokenSendDefinition ---
eq MTokenSendDefinition.preemptiveExpectedValue() = lastValue();
eq MTokenSendDefinition.preemptiveReturn() = "return false;";
eq MTokenSendDefinition.firstInputVarName() = getterMethod() + "()";
eq MTokenSendDefinition.updateMethod() = "_update_" + tokenName();
eq MTokenSendDefinition.writeMethod() = "_writeLastValue_" + tokenName();
eq MTokenSendDefinition.firstInputVarName() = getterMethodName() + "()";
eq MTokenSendDefinition.updateMethodName() = "_update_" + tokenName();
eq MTokenSendDefinition.writeMethodName() = "_writeLastValue_" + tokenName();
// MTypeReceiveDefinition
eq MTypeReceiveDefinition.preemptiveExpectedValue() = getterMethod() + "()";
eq MTypeReceiveDefinition.preemptiveExpectedValue() = getterMethodName() + "()";
eq MTypeReceiveDefinition.preemptiveReturn() = "return;";
eq MTypeReceiveDefinition.firstInputVarName() = "message";
eq MTypeReceiveDefinition.updateMethod() = null;
eq MTypeReceiveDefinition.writeMethod() = null;
eq MTypeReceiveDefinition.updateMethodName() = null;
eq MTypeReceiveDefinition.writeMethodName() = null;
// MTypeSendDefinition
eq MTypeSendDefinition.preemptiveExpectedValue() = lastValue();
eq MTypeSendDefinition.preemptiveReturn() = "return false;";
eq MTypeSendDefinition.firstInputVarName() = getterMethod() + "()";
eq MTypeSendDefinition.updateMethod() = "_update_" + typeName();
eq MTypeSendDefinition.writeMethod() = "_writeLastValue_" + typeName();
eq MTypeSendDefinition.firstInputVarName() = getterMethodName() + "()";
eq MTypeSendDefinition.updateMethodName() = "_update_" + typeName();
eq MTypeSendDefinition.writeMethodName() = "_writeLastValue_" + typeName();
}
aspect AspectGeneration {
// --- rootNodeName ---
syn String ASTNode.rootNodeName() = rootNode.getName();
public String RagConnect.generateAspect(String rootNodeName) {
rootNode = getProgram().resolveTypeDecl(rootNodeName);
return generateAspect();
}
public String RagConnect.generateAspect() {
// TODO move this to Compiler.java
// Handler ::= <ClassName> <Construction> <AttributeName> <FieldName> <InUse:boolean>;
this.addHandler(new Handler("MqttServerHandler", "new MqttServerHandler(\"RagConnectMQTT\")",
mqttHandlerAttribute(), mqttHandlerField(), usesMqtt));
this.addHandler(new Handler("RestServerHandler", "new RestServerHandler(\"RagConnectREST\")",
restHandlerAttribute(), restHandlerField(), usesRest));
StringBuilder sb = new StringBuilder();
com.github.mustachejava.reflect.ReflectionObjectHandler roh = new com.github.mustachejava.reflect.ReflectionObjectHandler() {
@Override
public com.github.mustachejava.Binding createBinding(String name, final com.github.mustachejava.TemplateContext tc, com.github.mustachejava.Code code) {
return new com.github.mustachejava.reflect.GuardedBinding(this, name, tc, code) {
@Override
protected synchronized com.github.mustachejava.util.Wrapper getWrapper(String name, java.util.List<Object> scopes) {
com.github.mustachejava.util.Wrapper wrapper = super.getWrapper(name, scopes);
if (wrapper instanceof com.github.mustachejava.reflect.MissingWrapper) {
throw new com.github.mustachejava.MustacheException(name + " not found in " + tc);
}
return wrapper;
}
};
}
};
com.github.mustachejava.DefaultMustacheFactory mf = new com.github.mustachejava.DefaultMustacheFactory();
mf.setObjectHandler(roh);
com.github.mustachejava.Mustache m = mf.compile("ragconnect.mustache");
m.execute(new java.io.PrintWriter(new org.jastadd.ragconnect.compiler.AppendableWriter(sb)), this);
return sb.toString();
}
}
aspect GrammarGeneration {
Loading