Generation.jadd 14.7 KB
Newer Older
René Schöne's avatar
René Schöne committed
1
2
3
4
5
6
7
8
9
10
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();
  }
René Schöne's avatar
René Schöne committed
11
12
13
14
15
16
17
18
19
20
21

  // --- 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();
  }
René Schöne's avatar
René Schöne committed
22
23
}

René Schöne's avatar
René Schöne committed
24
25
/* Open questions
- Should all string constants be defined on the normal AST, or on the special mustache AST?
26
27
Design considerations
- InnerMappingDefinition needed for iteration attribute (first, last) - not easily possible with list-relation
René Schöne's avatar
René Schöne committed
28
29
30
*/

aspect AttributesForMustache {
31
32
  // --- MRagConnect ---
  eq MRagConnect.getChild().mqttHandlerAttribute() = mqttHandlerAttribute();
33
  eq MRagConnect.getChild().restHandlerAttribute() = restHandlerAttribute();
34
35
  eq MRagConnect.getChild().mqttHandlerField() = mqttHandlerField();
  eq MRagConnect.getRootTypeComponent(int i).isFirst() = i == 0;
René Schöne's avatar
René Schöne committed
36

René Schöne's avatar
René Schöne committed
37
  syn boolean MRagConnect.usesMqtt() = getRagConnect().usesMqtt();
38
39
40
41
42
  syn String MRagConnect.mqttHandlerAttribute() = "_mqttHandler";
  syn String MRagConnect.mqttHandlerField() = "_mqttHandler";
  syn String MRagConnect.mqttSetHostMethod() = "MqttSetHost";
  syn String MRagConnect.mqttWaitUntilReadyMethod() = "MqttWaitUntilReady";
  syn String MRagConnect.mqttCloseMethod() = "MqttCloseConnections";
René Schöne's avatar
René Schöne committed
43

René Schöne's avatar
René Schöne committed
44
  syn boolean MRagConnect.usesRest() = getRagConnect().usesRest();
45
46
47
48
  syn String MRagConnect.restHandlerAttribute() = "_restHandler";
  syn String MRagConnect.restHandlerField() = "_restHandler";
  syn String MRagConnect.restSetPortMethod() = "RestSetPort";
  syn String MRagConnect.restCloseMethod() = "RestCloseConnections";
René Schöne's avatar
René Schöne committed
49

50
51
52
53
54
  // --- MEndpointDefinition ---
  syn String MEndpointDefinition.preemptiveExpectedValue();
  syn String MEndpointDefinition.preemptiveReturn();
  syn TokenEndpointDefinition MEndpointDefinition.endpointDef();
  syn String MEndpointDefinition.firstInputVarName();
55
  syn String MEndpointDefinition.newConnectionMethod();
56
57
58

  eq MEndpointDefinition.getInnerMappingDefinition(int i).isLast() = i == getNumInnerMappingDefinition() - 1;
  eq MEndpointDefinition.getInnerMappingDefinition().resultVarPrefix() = resultVarPrefix();
59
  eq MEndpointDefinition.getInnerMappingDefinition(int i).inputVarName() = i == 0 ? firstInputVarName() : resultVarPrefix() + getInnerMappingDefinition(i - 1).methodName();
60
61

  inh String MEndpointDefinition.mqttHandlerAttribute();
62
  inh String MEndpointDefinition.restHandlerAttribute();
63

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  syn String MEndpointDefinition.connectParameterName() {
    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() + (ragconnect().lookupTokenEndpointDefinitions(token()).size() > 1 ? "Via" + capitalize(endpointDef().protocol()) : "");
79
80
81
82
83
84
  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);
85
  syn String MEndpointDefinition.lastDefinitionToType() = lastDefinition().toType();
86
87
88
  syn String MEndpointDefinition.lastDefinitionName() = lastDefinition().methodName();
  syn String MEndpointDefinition.lastResult() = resultVarPrefix() + lastDefinitionName();
  syn String MEndpointDefinition.condition() {
89
    if (lastDefinition().mappingDef().getToType().isArray()) {
90
      return "java.util.Arrays.equals(" + preemptiveExpectedValue() + ", " + lastResult() + ")";
René Schöne's avatar
René Schöne committed
91
    }
92
    if (token().isPrimitiveType() && lastDefinition().mappingDef().getToType().isPrimitiveType()) {
93
      return preemptiveExpectedValue() + " == " + lastResult();
René Schöne's avatar
René Schöne committed
94
    }
95
    if (lastDefinition().mappingDef().isDefaultMappingDefinition()) {
96
      return preemptiveExpectedValue() + " != null && " + preemptiveExpectedValue() + ".equals(" + lastResult() + ")";
René Schöne's avatar
René Schöne committed
97
    }
98
    return preemptiveExpectedValue() + " != null ? " + preemptiveExpectedValue() + ".equals(" + lastResult() + ") : " + lastResult() + " == null";
René Schöne's avatar
René Schöne committed
99
100
101
102
103
104
  }

  // --- MInnerMappingDefinition ---
  inh boolean MInnerMappingDefinition.isLast();
  inh String MInnerMappingDefinition.resultVarPrefix();
  inh String MInnerMappingDefinition.inputVarName();
105
106
107
  syn String MInnerMappingDefinition.toType() = mappingDef().getToType().prettyPrint();
  syn String MInnerMappingDefinition.methodName() = getMMappingDefinition().methodName();
  syn MappingDefinition MInnerMappingDefinition.mappingDef() = getMMappingDefinition().getMappingDefinition();
René Schöne's avatar
René Schöne committed
108

109
110
111
  // --- MReceiveDefinition ---
  eq MReceiveDefinition.preemptiveExpectedValue() = "get" + tokenName() + "()";
  eq MReceiveDefinition.preemptiveReturn() = "return;";
René Schöne's avatar
René Schöne committed
112
  eq MReceiveDefinition.endpointDef() = getReceiveTokenEndpointDefinition();
113
114
  eq MReceiveDefinition.firstInputVarName() = "message";

115
116
117
118
119
120
121
  syn String MReceiveDefinition.newConnectionMethod() {
    switch (endpointDef().protocol()) {
      case "mqtt": return "newConnection";
      case "rest": return "newPUTConnection";
      default: return null;
    }
  }
René Schöne's avatar
René Schöne committed
122

123
124
  // --- MSendDefinition ---
  eq MSendDefinition.preemptiveExpectedValue() = lastValue();
125
126
127
128
129
130
131
  eq MSendDefinition.preemptiveReturn() {
    switch (endpointDef().protocol()) {
      case "mqtt": return "return false;";
      case "rest": return "throw e;";  // e is Exception variable
      default: return null;
    }
  }
René Schöne's avatar
René Schöne committed
132
  eq MSendDefinition.endpointDef() = getSendTokenEndpointDefinition();
133
134
  eq MSendDefinition.firstInputVarName() = "get" + tokenName() + "()";

135
136
137
138
139
  syn String MSendDefinition.sendTopic() = "_topic_" + 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";
René Schöne's avatar
René Schöne committed
140
  syn boolean MSendDefinition.isPush() = getSendTokenEndpointDefinition().isPush();
141
142
143
144
145
146
147
  syn String MSendDefinition.newConnectionMethod() {
    switch (endpointDef().protocol()) {
      case "mqtt": return null;
      case "rest": return "newGETConnection";
      default: return null;
    }
  }
René Schöne's avatar
René Schöne committed
148
149
150

  // --- MMappingDefinition ---
  syn String MMappingDefinition.toType() = getMappingDefinition().getToType().prettyPrint();
151
  syn String MMappingDefinition.methodName() = "_apply_" + getMappingDefinition().getID();
René Schöne's avatar
René Schöne committed
152
153
154
155
156
157
  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();
158
  syn String MDependencyDefinition.dependencyMethod() = "add" + capitalize(getDependencyDefinition().getID());
René Schöne's avatar
René Schöne committed
159
  syn String MDependencyDefinition.sourceParentTypeName() = getDependencyDefinition().getSource().containingTypeDecl().getName();
160
  syn String MDependencyDefinition.internalRelationPrefix() = "_internal_" + getDependencyDefinition().getID();
René Schöne's avatar
René Schöne committed
161
  syn nta MSendDefinition MDependencyDefinition.targetEndpointDefinition() {
162
    return getDependencyDefinition().targetEndpointDefinition().toMustache();
René Schöne's avatar
René Schöne committed
163
164
165
166
  }

  // --- MTypeComponent ---
  syn String MTypeComponent.name() = getTypeComponent().getName();
167
168
  inh String MTypeComponent.mqttHandlerAttribute();
  inh String MTypeComponent.mqttHandlerField();
169
  inh boolean MTypeComponent.isFirst();
170
171
172
173

  // --- MTokenComponent ---
  syn String MTokenComponent.parentTypeName() = getTokenComponent().containingTypeDecl().getName();
  syn String MTokenComponent.name() = getTokenComponent().getName();
René Schöne's avatar
René Schöne committed
174
  syn String MTokenComponent.javaType() = getTokenComponent().effectiveJavaTypeUse().prettyPrint();
175
176
  syn String MTokenComponent.internalName() = getTokenComponent().getDependencySourceDefinitionList().isEmpty() ? externalName() : "_internal_" + name();
  syn String MTokenComponent.externalName() = name();
René Schöne's avatar
René Schöne committed
177

178
  // --- toMustache ---
179
180
181
  syn lazy MRagConnect RagConnect.toMustache() {
    MRagConnect result = new MRagConnect();
    result.setRagConnect(this);
182
    for (EndpointDefinition def : getEndpointDefinitionList()) {
René Schöne's avatar
René Schöne committed
183
      if (def.isSendTokenEndpointDefinition()) {
René Schöne's avatar
René Schöne committed
184
185
186
187
188
189
        SendTokenEndpointDefinition sendDef = def.asSendTokenEndpointDefinition();
        if (sendDef.isPush()) {
          result.addPushSendDefinition(sendDef.toMustache());
        } else {
          result.addPullSendDefinition(sendDef.toMustache());
        }
René Schöne's avatar
René Schöne committed
190
      } else {
René Schöne's avatar
René Schöne committed
191
        result.addReceiveDefinition(def.asReceiveTokenEndpointDefinition().toMustache());
René Schöne's avatar
René Schöne committed
192
193
194
      }
    }
    for (MappingDefinition def : allMappingDefinitions()) {
195
      result.addMappingDefinition(def.toMustache());
René Schöne's avatar
René Schöne committed
196
197
    }
    for (DependencyDefinition def : getDependencyDefinitionList()) {
198
      result.addDependencyDefinition(def.toMustache());
René Schöne's avatar
René Schöne committed
199
200
    }
    for (TokenComponent token : getProgram().allTokenComponents()) {
René Schöne's avatar
René Schöne committed
201
202
203
      if (!token.getDependencySourceDefinitionList().isEmpty()) {
        result.addTokenComponent(token.toMustache());
      }
204
205
206
    }
    for (Component child : rootNode.getComponentList()) {
      if (child.isTypeComponent()) {
René Schöne's avatar
René Schöne committed
207
        result.addRootTypeComponent(child.asTypeComponent().toMustache());
208
      }
René Schöne's avatar
René Schöne committed
209
210
211
    }
    return result;
  }
212

René Schöne's avatar
René Schöne committed
213
//MInnerMappingDefinition.MappingDefinition -> MappingDefinition;
214
215
  protected void MEndpointDefinition.addInnerMappings() {
    for (MappingDefinition def : endpointDef().effectiveMappings()) {
216
      MInnerMappingDefinition inner = new MInnerMappingDefinition();
217
      inner.setMMappingDefinition(def.toMustache());
218
      addInnerMappingDefinition(inner);
René Schöne's avatar
René Schöne committed
219
220
    }
  }
René Schöne's avatar
René Schöne committed
221
  syn lazy MReceiveDefinition ReceiveTokenEndpointDefinition.toMustache() {
222
    MReceiveDefinition result = new MReceiveDefinition();
René Schöne's avatar
René Schöne committed
223
224
225
226
    result.setReceiveTokenEndpointDefinition(this);
    result.addInnerMappings();
    return result;
  }
René Schöne's avatar
René Schöne committed
227
  syn lazy MSendDefinition SendTokenEndpointDefinition.toMustache() {
228
    MSendDefinition result = new MSendDefinition();
René Schöne's avatar
René Schöne committed
229
    result.setSendTokenEndpointDefinition(this);
René Schöne's avatar
René Schöne committed
230
231
232
    result.addInnerMappings();
    return result;
  }
233
  syn lazy MMappingDefinition MappingDefinition.toMustache() {
René Schöne's avatar
René Schöne committed
234
235
236
237
    MMappingDefinition result = new MMappingDefinition();
    result.setMappingDefinition(this);
    return result;
  }
238
  syn lazy MDependencyDefinition DependencyDefinition.toMustache() {
René Schöne's avatar
René Schöne committed
239
240
241
242
    MDependencyDefinition result = new MDependencyDefinition();
    result.setDependencyDefinition(this);
    return result;
  }
243
  syn lazy MTypeComponent TypeComponent.toMustache() {
René Schöne's avatar
René Schöne committed
244
245
    MTypeComponent result = new MTypeComponent();
    result.setTypeComponent(this);
246
247
248
249
250
    return result;
  }
  syn lazy MTokenComponent TokenComponent.toMustache() {
    MTokenComponent result = new MTokenComponent();
    result.setTokenComponent(this);
René Schöne's avatar
René Schöne committed
251
    for (DependencyDefinition def : getDependencySourceDefinitionList()) {
252
      result.addDependencyDefinition(def.toMustache());
René Schöne's avatar
René Schöne committed
253
254
255
256
257
    }
    return result;
  }
}

René Schöne's avatar
René Schöne committed
258
aspect AspectGeneration {
René Schöne's avatar
René Schöne committed
259
260
261
262
263

  syn boolean SendTokenEndpointDefinition.isPush();
  eq SendToMqttDefinition.isPush() = true;
  eq SendToRestDefinition.isPush() = false;

René Schöne's avatar
René Schöne committed
264
265
  // --- rootNodeName ---
  syn String ASTNode.rootNodeName() = rootNode.getName();
René Schöne's avatar
René Schöne committed
266

267
  public String RagConnect.generateAspect(String rootNodeName) {
René Schöne's avatar
René Schöne committed
268
    rootNode = getProgram().resolveTypeDecl(rootNodeName);
René Schöne's avatar
René Schöne committed
269
270
271
    return toMustache().generateAspect();
  }

272
  public String MRagConnect.generateAspect() {
René Schöne's avatar
René Schöne committed
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
    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);
291
292
    com.github.mustachejava.Mustache m = mf.compile("ragconnect.mustache");
    m.execute(new java.io.PrintWriter(new org.jastadd.ragconnect.compiler.AppendableWriter(sb)), this);
293
    return sb.toString();
René Schöne's avatar
René Schöne committed
294
295
  }
}
296
297

aspect RelationGeneration {
298
  syn java.util.List<Relation> RagConnect.additionalRelations() {
299
300
301
302
303
304
305
306
    java.util.List<Relation> result = new java.util.ArrayList<>();
    for (DependencyDefinition dd : getDependencyDefinitionList()) {
      result.add(dd.getRelationToCreate());
    }
    return result;
  }

  syn nta Relation DependencyDefinition.getRelationToCreate() {
307
    String internalRelationPrefix = toMustache().internalRelationPrefix();
308
    BidirectionalRelation result = new BidirectionalRelation();
309
    NavigableRole left = new ListRole(internalRelationPrefix + "Source");
310
    left.setType(getTarget().containingTypeDecl());
311
    NavigableRole right = new ListRole(internalRelationPrefix + "Target");
312
313
314
    right.setType(getSource().containingTypeDecl());
    result.setLeft(left);
    result.setRight(right);
315
    result.addComment(new WhitespaceComment("\n"));
316
317
318
319
320
321
322
323
324
325
326
    return result;
  }
}

aspect GrammarExtension {
  refine BackendAbstractGrammar public void TokenComponent.generateAbstractGrammar(StringBuilder b) {
    if (getNTA()) {
      b.append("/");
    }
    b.append("<");
    if (!getName().equals("")) {
327
      b.append(toMustache().internalName()).append(":");
328
    }
René Schöne's avatar
René Schöne committed
329
    effectiveJavaTypeUse().generateAbstractGrammar(b);
330
331
332
333
334
335
    b.append(">");
    if (getNTA()) {
      b.append("/");
    }
  }
}