Skip to content
Snippets Groups Projects
Select Git revision
  • main protected
  • dev default protected
  • feature/ros-java-integration
3 results

Generation.jadd

Blame
  • Generation.jadd 14.56 KiB
    aspect GenerationUtils {
      public static final String ASTNode.aspectIndent = "  ";
    
      public String ASTNode.ind(int n) {
        StringBuilder s = new StringBuilder();
        for (int i = 0; i < n; i++) {
          s.append(aspectIndent);
        }
        return s.toString();
      }
    
      // --- prettyPrint ---
      syn String MappingDefinitionType.prettyPrint();
      eq JavaMappingDefinitionType.prettyPrint() = getType().getName();
      eq JavaArrayMappingDefinitionType.prettyPrint() = getType().getName() + "[]";
    
      syn String JavaTypeUse.prettyPrint() {
        StringBuilder sb = new StringBuilder();
        generateAbstractGrammar(sb);
        return sb.toString();
      }
    }
    
    /* Open questions
    - Should all string constants be defined on the normal AST, or on the special mustache AST?
    Design considerations
    - InnerMappingDefinition needed for iteration attribute (first, last) - not easily possible with list-relation
    */
    
    aspect AttributesForMustache {
      // --- MRagConnect ---
      eq MRagConnect.getChild().mqttHandlerAttribute() = mqttHandlerAttribute();
      eq MRagConnect.getChild().restHandlerAttribute() = restHandlerAttribute();
      eq MRagConnect.getChild().mqttHandlerField() = mqttHandlerField();
      eq MRagConnect.getRootTypeComponent(int i).isFirst() = i == 0;
    
      syn String MRagConnect.closeMethod() = "ragconnectCloseConnections";
    //  syn boolean MRagConnect.usesMqtt() = getRagConnect().usesMqtt();
      syn String MRagConnect.mqttHandlerAttribute() = "_mqttHandler";
      syn String MRagConnect.mqttHandlerField() = "_mqttHandler";
    //  syn String MRagConnect.mqttSetHostMethod() = "MqttSetHost";
      syn String MRagConnect.mqttSetupWaitUntilReadyMethod() = "ragconnectSetupMqttWaitUntilReady";
    
    //  syn boolean MRagConnect.usesRest() = getRagConnect().usesRest();
      syn String MRagConnect.restHandlerAttribute() = "_restHandler";
      syn String MRagConnect.restHandlerField() = "_restHandler";
    //  syn String MRagConnect.restSetPortMethod() = "RestSetPort";
    
      // --- MEndpointDefinition ---
      syn String MEndpointDefinition.preemptiveExpectedValue();
      syn String MEndpointDefinition.preemptiveReturn();
      syn TokenEndpointDefinition MEndpointDefinition.endpointDef();
      syn String MEndpointDefinition.firstInputVarName();
    //  syn String MEndpointDefinition.newConnectionMethod();
    
      eq MEndpointDefinition.getInnerMappingDefinition(int i).isLast() = i == getNumInnerMappingDefinition() - 1;
      eq MEndpointDefinition.getInnerMappingDefinition().resultVarPrefix() = resultVarPrefix();
      eq MEndpointDefinition.getInnerMappingDefinition(int i).inputVarName() = i == 0 ? firstInputVarName() : resultVarPrefix() + getInnerMappingDefinition(i - 1).methodName();
    
      inh String MEndpointDefinition.mqttHandlerAttribute();
      inh String MEndpointDefinition.restHandlerAttribute();
    
      syn String MEndpointDefinition.connectParameterName() = "uriString";
    //    switch (endpointDef().protocol()) {
    //      case "mqtt": return "topic";
    //      case "rest": return "path";
    //      default: return null;
    //    }
    //  }
    //  syn String MEndpointDefinition.handlerAttribute() {
    //    switch (endpointDef().protocol()) {
    //      case "mqtt": return mqttHandlerAttribute();
    //      case "rest": return restHandlerAttribute();
    //      default: return null;
    //    }
    //  }
      syn String MEndpointDefinition.connectMethod() = "connect" + tokenName();
      syn TokenComponent MEndpointDefinition.token() = endpointDef().getToken();
      syn boolean MEndpointDefinition.alwaysApply() = endpointDef().getAlwaysApply();
      syn String MEndpointDefinition.resultVarPrefix() = "result";  // we do not need "_" here, because methodName begins with one
      syn String MEndpointDefinition.parentTypeName() = token().containingTypeDecl().getName();
      syn String MEndpointDefinition.tokenName() = token().getName();
      syn MInnerMappingDefinition MEndpointDefinition.lastDefinition() = getInnerMappingDefinition(getNumInnerMappingDefinition() - 1);
      syn String MEndpointDefinition.lastDefinitionToType() = lastDefinition().toType();
      syn String MEndpointDefinition.lastDefinitionName() = lastDefinition().methodName();
      syn String MEndpointDefinition.lastResult() = resultVarPrefix() + lastDefinitionName();
      syn String MEndpointDefinition.condition() {
        if (lastDefinition().mappingDef().getToType().isArray()) {
          return "java.util.Arrays.equals(" + preemptiveExpectedValue() + ", " + lastResult() + ")";
        }
        if (token().isPrimitiveType() && lastDefinition().mappingDef().getToType().isPrimitiveType()) {
          return preemptiveExpectedValue() + " == " + lastResult();
        }
        if (lastDefinition().mappingDef().isDefaultMappingDefinition()) {
          return preemptiveExpectedValue() + " != null && " + preemptiveExpectedValue() + ".equals(" + lastResult() + ")";
        }
        return preemptiveExpectedValue() + " != null ? " + preemptiveExpectedValue() + ".equals(" + lastResult() + ") : " + lastResult() + " == null";
      }
    
      // --- MInnerMappingDefinition ---
      inh boolean MInnerMappingDefinition.isLast();
      inh String MInnerMappingDefinition.resultVarPrefix();
      inh String MInnerMappingDefinition.inputVarName();
      syn String MInnerMappingDefinition.toType() = mappingDef().getToType().prettyPrint();
      syn String MInnerMappingDefinition.methodName() = getMMappingDefinition().methodName();
      syn MappingDefinition MInnerMappingDefinition.mappingDef() = getMMappingDefinition().getMappingDefinition();
    
      // --- MReceiveDefinition ---
      eq MReceiveDefinition.preemptiveExpectedValue() = "get" + tokenName() + "()";
      eq MReceiveDefinition.preemptiveReturn() = "return;";
      eq MReceiveDefinition.endpointDef() = getReceiveTokenEndpointDefinition();
      eq MReceiveDefinition.firstInputVarName() = "message";
    
    //  syn String MReceiveDefinition.newConnectionMethod() {
    //    switch (endpointDef().protocol()) {
    //      case "mqtt": return "newConnection";
    //      case "rest": return "newPUTConnection";
    //      default: return null;
    //    }
    //  }
    
      // --- MSendDefinition ---
      eq MSendDefinition.preemptiveExpectedValue() = lastValue();
      eq MSendDefinition.preemptiveReturn() = "return false;";
    //    switch (endpointDef().protocol()) {
    //      case "mqtt": return "return false;";
    //      case "rest": return "throw e;";  // e is Exception variable
    //      default: return null;
    //    }
    //  }
      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.isPush() = getSendTokenEndpointDefinition().isPush();
    //  syn String MSendDefinition.newConnectionMethod() {
    //    switch (endpointDef().protocol()) {
    //      case "mqtt": return null;
    //      case "rest": return "newGETConnection";
    //      default: return null;
    //    }
    //  }
    
      // --- MMappingDefinition ---
      syn String MMappingDefinition.toType() = getMappingDefinition().getToType().prettyPrint();
      syn String MMappingDefinition.methodName() = "_apply_" + getMappingDefinition().getID();
      syn String MMappingDefinition.fromType() = getMappingDefinition().getFromType().prettyPrint();
      syn String MMappingDefinition.fromVariableName() = getMappingDefinition().getFromVariableName();
      syn String MMappingDefinition.content() = getMappingDefinition().getContent();
    
      // --- MDependencyDefinition ---
      syn String MDependencyDefinition.targetParentTypeName() = getDependencyDefinition().getTarget().containingTypeDecl().getName();
      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() {
        return getDependencyDefinition().targetEndpointDefinition().toMustache();
      }
    
      // --- MTypeComponent ---
      syn String MTypeComponent.name() = getTypeComponent().getName();
      inh String MTypeComponent.mqttHandlerAttribute();
      inh String MTypeComponent.mqttHandlerField();
      inh boolean MTypeComponent.isFirst();
    
      // --- MTokenComponent ---
      syn String MTokenComponent.parentTypeName() = getTokenComponent().containingTypeDecl().getName();
      syn String MTokenComponent.name() = getTokenComponent().getName();
      syn String MTokenComponent.javaType() = getTokenComponent().effectiveJavaTypeUse().prettyPrint();
      syn String MTokenComponent.internalName() = getTokenComponent().getDependencySourceDefinitionList().isEmpty() ? externalName() : "_internal_" + name();
      syn String MTokenComponent.externalName() = name();
    
      // --- toMustache ---
      syn lazy MRagConnect RagConnect.toMustache() {
        MRagConnect result = new MRagConnect();
        result.setRagConnect(this);
        for (EndpointDefinition def : getEndpointDefinitionList()) {
          if (def.isSendTokenEndpointDefinition()) {
            SendTokenEndpointDefinition sendDef = def.asSendTokenEndpointDefinition();
            result.addSendDefinition(sendDef.toMustache());
          } else {
            result.addReceiveDefinition(def.asReceiveTokenEndpointDefinition().toMustache());
          }
        }
        for (MappingDefinition def : allMappingDefinitions()) {
          result.addMappingDefinition(def.toMustache());
        }
        for (DependencyDefinition def : getDependencyDefinitionList()) {
          result.addDependencyDefinition(def.toMustache());
        }
        for (TokenComponent token : getProgram().allTokenComponents()) {
          if (!token.getDependencySourceDefinitionList().isEmpty()) {
            result.addTokenComponent(token.toMustache());
          }
        }
        for (Component child : rootNode.getComponentList()) {
          if (child.isTypeComponent()) {
            result.addRootTypeComponent(child.asTypeComponent().toMustache());
          }
        }
        return result;
      }
    
    //MInnerMappingDefinition.MappingDefinition -> MappingDefinition;
      protected void MEndpointDefinition.addInnerMappings() {
        for (MappingDefinition def : endpointDef().effectiveMappings()) {
          MInnerMappingDefinition inner = new MInnerMappingDefinition();
          inner.setMMappingDefinition(def.toMustache());
          addInnerMappingDefinition(inner);
        }
      }
      syn lazy MReceiveDefinition ReceiveTokenEndpointDefinition.toMustache() {
        MReceiveDefinition result = new MReceiveDefinition();
        result.setReceiveTokenEndpointDefinition(this);
        result.addInnerMappings();
        return result;
      }
      syn lazy MSendDefinition SendTokenEndpointDefinition.toMustache() {
        MSendDefinition result = new MSendDefinition();
        result.setSendTokenEndpointDefinition(this);
        result.addInnerMappings();
        return result;
      }
      syn lazy MMappingDefinition MappingDefinition.toMustache() {
        MMappingDefinition result = new MMappingDefinition();
        result.setMappingDefinition(this);
        return result;
      }
      syn lazy MDependencyDefinition DependencyDefinition.toMustache() {
        MDependencyDefinition result = new MDependencyDefinition();
        result.setDependencyDefinition(this);
        return result;
      }
      syn lazy MTypeComponent TypeComponent.toMustache() {
        MTypeComponent result = new MTypeComponent();
        result.setTypeComponent(this);
        return result;
      }
      syn lazy MTokenComponent TokenComponent.toMustache() {
        MTokenComponent result = new MTokenComponent();
        result.setTokenComponent(this);
        for (DependencyDefinition def : getDependencySourceDefinitionList()) {
          result.addDependencyDefinition(def.toMustache());
        }
        return result;
      }
    }
    
    aspect AspectGeneration {
    
    //  syn boolean SendTokenEndpointDefinition.isPush();
    //  eq SendToMqttDefinition.isPush() = true;
    //  eq SendToRestDefinition.isPush() = false;
    
      // --- rootNodeName ---
      syn String ASTNode.rootNodeName() = rootNode.getName();
    
      public String RagConnect.generateAspect(String rootNodeName) {
        rootNode = getProgram().resolveTypeDecl(rootNodeName);
        return toMustache().generateAspect();
      }
    
      public String MRagConnect.generateAspect() {
        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 RelationGeneration {
      syn java.util.List<Relation> RagConnect.additionalRelations() {
        java.util.List<Relation> result = new java.util.ArrayList<>();
        for (DependencyDefinition dd : getDependencyDefinitionList()) {
          result.add(dd.getRelationToCreate());
        }
        return result;
      }
    
      syn nta Relation DependencyDefinition.getRelationToCreate() {
        String internalRelationPrefix = toMustache().internalRelationPrefix();
        BidirectionalRelation result = new BidirectionalRelation();
        NavigableRole left = new ListRole(internalRelationPrefix + "Source");
        left.setType(getTarget().containingTypeDecl());
        NavigableRole right = new ListRole(internalRelationPrefix + "Target");
        right.setType(getSource().containingTypeDecl());
        result.setLeft(left);
        result.setRight(right);
        result.addComment(new WhitespaceComment("\n"));
        return result;
      }
    }
    
    aspect GrammarExtension {
      refine BackendAbstractGrammar public void TokenComponent.generateAbstractGrammar(StringBuilder b) {
        if (getNTA()) {
          b.append("/");
        }
        b.append("<");
        if (!getName().equals("")) {
          b.append(toMustache().internalName()).append(":");
        }
        effectiveJavaTypeUse().generateAbstractGrammar(b);
        b.append(">");
        if (getNTA()) {
          b.append("/");
        }
      }
    }