Skip to content
Snippets Groups Projects
Commit b71daace authored by René Schöne's avatar René Schöne
Browse files

Resolve "Refactorings/Clean-Up"

- add cloc and two use cases to pages
- move some aspects into separate template files
- add a method to reset the evaluation counter
- rename forwardingNTA to forwarding
- begin with default mappings using templates 
- also indirectly work on #55 to include marshalling methods only when needed
- move TestUtils to a separate package
parent da232e01
No related branches found
No related tags found
3 merge requests!39Version 1.1.0,!35Version 1.0.0,!33Resolve "Refactorings/Clean-Up"
Showing
with 707 additions and 503 deletions
pages/docs/img/ros2rag-process.png

23.4 KiB

......@@ -2,17 +2,17 @@
Please see [API documentation](ragdoc/index.html) for more details.
![ros2rag-process](img/ros2rag-process.png)
![ragconnect-process](img/ragconnect-process.png)
`RagConnect` uses the [relast-preprocessor](https://git-st.inf.tu-dresden.de/jastadd/relast-preprocessor) to parse `.relast` grammar files.
This results in an ASTNode of type `Program`.
It further uses a dedicated parser for `.connect` files containing endpoint-, mapping-, and dependency-definitions.
It further uses a dedicated parser for `.connect` files containing port-, mapping-, and dependency-definitions.
This results in an ASTNode of type `RagConnect`.
The goal is to generate an aspect file containing setters and getters of tokens referred to by endpoint-definitions
The goal is to generate an aspect file containing setters and getters of tokens referred to by port-definitions
We use [mustache](https://mustache.github.io/) (currently its [Java version](https://github.com/spullara/mustache.java)) making use of partials to separate concerns.
The `.mustache` files are located in `ragconnect.base/src/main/resources`.
The generation process uses intermediates NTAs (whose types are defined in `Intermediate.relast`) to ease the definition of two main generation "problems".
Those problems are differentiation on both kinds of an endpoint (send/receive and type/token/list), and attributes depending on position in n-ary relations.
Those problems are differentiation on both kinds of a port (send/receive and type/token/list), and attributes depending on position in n-ary relations.
There are aspect files for `Navigation` (mainly isX/asX attributes), `Analysis` (static analysis attributes), `Printing`, `Mappings` (default mappings).
One of the main aspects is `Intermediate` containing all attributes consumed by `mustache` and other attributes the former depend on.
......@@ -26,7 +26,7 @@ In the following, details for special implementation topics are discussed.
## Forwarding
When a nonterminal is used in a send endpoints, it needs an implicit forwarding attribute to work, because only _computed elements_ can be sent.
When a nonterminal is used in a send ports, it needs an implicit forwarding attribute to work, because only _computed elements_ can be sent.
Since the nonterminal itself should be sent, the generated attribute simply returns this nonterminal.
However, changing any token within the whole subtree or changing the structure of the subtree must trigger a new message, upon computation of the forwarding attribute, all tokens are "touched" (their getter is called).
......@@ -46,16 +46,27 @@ To help with finding errors/bugs when tests fail, there are several things to fi
- Use `Assumptions.assumeTrue(false);` to abort unneeded test cases early.
- When editing RagConnect itself and force recreating source for the affected test, e.g., `compileForwardingIncremental.outputs.upToDateWhen { false }`
- _Remember to undo all changes, once the bug is fixed._
- **Activate logs**. Add the following to the `ragconnect` specification of the compile-task of the affected test:
```
- **Activate logs**. Activate logging in the `ragconnect` specification of the compile-task of the affected test:
- _Remember to remove those lines, once the bug is fixed._
```groovy
task compile(type: RagConnectTest) {
ragconnect {
// ... other parameters ...
logReads = true
logWrites = true
logIncremental = true
}
// ... other tools ...
}
```
_Remember to remove those lines, once the bug is fixed._
- **Trace incremental events**. Add the following right after create the root node (named `model` here):
- **Trace incremental events**. Add a receiver right after creation of the root node (named `model` here)
- This will output every event fired by the incremental evaluation engine.
- _Remember to remove this line, once the bug is fixed._
```java
model.trace().setReceiver(TestUtils::logEvent);
```
This will output every event fired by the incremental evaluation engine. _Remember to remove this line, once the bug is fixed._
- **Add log statements**. As there will be quite some log output, add some identifying log statement (i.e., using `logger.fatal("---")`) right before the suspicious statement to inspect only the relevant log message after that.
# Use cases with `RagConnect`
## MPM4CPS Paper - Codename 'Ros2Rag'
## MPM4CPS Paper (2020) - Codename 'Ros2Rag'
In the publication [*"Connecting conceptual models using Relational Reference Attribute Grammars"*](https://doi.org/10.1145/3417990.3421437), a use case involving a simulated robot arm and two different models connected to it was shown.
One model was used to ensure a low speed of the robot when within a safety zone (purple boxes in the picture below), and the other model executes a workflow to control the robot.
![Screenshot of Gazebo](img/robo3d.png)
![Screenshot of Gazebo](img/2020_mpm4cps/robo3d.png)
This paper was presented on October, 16h during the [MPM4CPS workshop](https://msdl.uantwerpen.be/conferences/MPM4CPS/2020/) within the [MODELS 2020 conference](https://conf.researchr.org/home/models-2020). For more information, see the [presented slides](img/mpm4cps-slides.pdf), [a recording of the session](https://youtu.be/Hgc1qFfmr44?t=1220) or the accompanied [poster](img/poster.pdf).
This paper was presented on October, 16th 2020 during the [MPM4CPS workshop](https://msdl.uantwerpen.be/conferences/MPM4CPS/2020/) within the [MODELS 2020 conference](https://conf.researchr.org/home/models-2020). For more information, see the [presented slides](img/2020_mpm4cps/slides.pdf), [a recording of the session](https://youtu.be/Hgc1qFfmr44?t=1220) or the accompanied [poster](img/2020_mpm4cps/poster.pdf).
The repository with the used source code can be found at: <https://git-st.inf.tu-dresden.de/ceti/ros/mpm4cps2020>
The usage is dockerized, so starting the application only involves the commands listed below.
......@@ -28,3 +28,22 @@ docker-compose up rag_app
# Terminal 3: Goal-Model
docker-compose up rag_goal
```
## ACSOS Paper (2022) - Codename 'Motion Grammar Demo'
In the paper [*"Specifying Reactive Robotic Applications
With Reference Attribute Motion Grammars"*](http://mg.relational-rags.eu), motion grammars (an older approach by [Dantham and Stilman](https://doi.org/10.1109/TRO.2013.2239553)) were implemented using Relational RAGs.
This paper will be presented on September, 21st 2022 during the [Posters and Demos session](https://2022.acsos.org/track/acsos-2022-posters-and-demos) of the [ACSOS 2022 conference](https://2022.acsos.org/).
For more information, see <http://mg.relational-rags.eu/>.
## MODELS Paper (2022) - Codename 'Ros3Rag'
In the paper [*"Incremental Causal Connection for Self-Adaptive Systems Based on Relational Reference Attribute Grammars"*](https://doi.org/10.1145/3550355.3552460), a [previous use case](#mpm4cps-paper-codename-ros2rag) was extended to Collaborative, Teaching-Based Robotic Cells.
![Screenshot](img/2022_models/photo.jpg)
This paper will be presented in the technical track of the [MODELS 2022 conference](https://conf.researchr.org/home/models-2022) (Oct 23 - Oct 29).
There is an [artifact hosted at Zenodo](https://doi.org/10.5281/zenodo.7009758) containing all source code and the executable case study.
Furthermore, the presentation slides and a poster will be available soon.
The repository with the used source code can be found at: <https://git-st.inf.tu-dresden.de/ceti/ros/models2022>
......@@ -17,7 +17,7 @@ B ::= <OutputOnB:String> ;
To declare receiving and sending tokens, a dedicated DSL is used:
```java
// endpoint definitions
// port definitions
receive A.Input ;
send A.OutputOnA ;
send B.OutputOnB using Transformation ;
......@@ -101,11 +101,11 @@ The first parameter of those connect-methods is always a URI-like String, to ide
In case of MQTT, the server is the host running an MQTT broker, and the path is equal to the topic to publish or subscribe to.
Please note, that the first leading slash (`/`) is removed for MQTT topics, e.g., for `A.Input` the topic is actually `topic/for/input`.
For sending endpoints, there is a second boolean parameter to specify whether the current value shall be sent immediately after connecting.
For sending ports, there is a second boolean parameter to specify whether the current value shall be sent immediately after connecting.
## Remarks for using manual dependency tracking
When constructing the AST and connecting it, one should always set dependencies before connecting, especially if updates already arriving for receiving endpoints.
When constructing the AST and connecting it, one should always set dependencies before connecting, especially if updates already arriving for receiving ports.
Otherwise, updates might not be propagated after setting dependencies, if values are equal after applying transformations of mapping definitions.
As an example, when using the following grammar and definitions for RagConnect ...
......@@ -129,7 +129,7 @@ Round maps float f to int {:
# An advanced example
Non-terminal children can also be selected as endpoints (not only tokens).
Non-terminal children can also be selected as ports (not only tokens).
## Normal Non-Terminal Children
......@@ -156,7 +156,7 @@ receive ReceiverRoot.A ;
To process non-terminals, default mappings are provided for every non-terminal type of the used grammar.
They use the JSON serialization offered by the RelAST compiler, i.e., interpret the message as a `String`, deserialize the content reading the message as JSON, or vice versa.
Additional dependencies are required to use this feature, as detailed in [the compiler section](compiler.md#treelist-endpoints).
Additional dependencies are required to use this feature, as detailed in [the compiler section](compiler.md#treelist-ports).
## Receiving List Children
......@@ -173,7 +173,7 @@ Several options are possible (please also refer to the specification of the [con
### (empty)
A message for a list endpoint can be interpreted as a complete list (a sequence of nodes of type `A`) by not specifying any special keyword:
A message for a list port can be interpreted as a complete list (a sequence of nodes of type `A`) by not specifying any special keyword:
```
receive ReceiverRoot.A ;
......@@ -190,7 +190,7 @@ receive with add ReceiverRoot.Alfa ;
### indexed
A message for a list endpoint can also be interpreted as an element of this list.
A message for a list port can also be interpreted as an element of this list.
```
receive tree ReceiverRoot.A ;
......@@ -245,10 +245,10 @@ assertEquals(receiverRoot.getAList(), list("1", "other"));
assertEquals(receiverRoot.getAList(), list("1", "other", "new"));
```
## Using attributes as endpoint targets
## Using attributes as port targets
As described in the [DSL specification](dsl.md), attributes can be used as endpoint targets.
They can only be used in send endpoints, and the return type of the attribute must be specified in the connect specification (because aspect files are not handled completely yet).
As described in the [DSL specification](dsl.md), attributes can be used as port targets.
They can only be used in send ports, and the return type of the attribute must be specified in the connect specification (because aspect files are not handled completely yet).
Currently, synthesized, inherited, collection, and circular attributes are supported.
Nonterminal attributes are best used with the "legacy" notation `/Context:Type/` within the grammar.
......
......@@ -9,6 +9,7 @@ nav:
- "RagConnect Specification Language": dsl.md
- "Compiler options": compiler.md
- "Inner workings": inner-workings.md
- "Evaluation Metrics: Lines of Code": cloc.md
- "Extending RagConnect": extending.md
- "Changelog": changelog.md
- "API documentation": ragdoc/index.html
......
......@@ -31,7 +31,7 @@ configurations {
}
dependencies {
relast group: 'org.jastadd', name: 'relast', version: "0.3.0-137"
relast group: 'org.jastadd', name: 'relast', version: "${relast_version}"
implementation group: 'org.jastadd', name: 'relast-preprocessor', version: "${preprocessor_version}"
implementation group: 'com.github.spullara.mustache.java', name: 'compiler', version: "${mustache_java_version}"
jastadd2 group: 'org.jastadd', name: 'jastadd2', version: '2.3.5-dresden'
......
aspect Analysis {
// --- isAlreadyDefined ---
syn boolean EndpointDefinition.isAlreadyDefined() = getEndpointTarget().isAlreadyDefined();
syn boolean EndpointTarget.isAlreadyDefined();
eq AttributeEndpointTarget.isAlreadyDefined() {
syn boolean PortDefinition.isAlreadyDefined() = getPortTarget().isAlreadyDefined();
syn boolean PortTarget.isAlreadyDefined();
eq AttributePortTarget.isAlreadyDefined() {
// define lookup here, as not used elsewhere
int numberOfSameDefs = 0;
for (EndpointTarget target : ragconnect().givenEndpointTargetList()) {
if (target.isAttributeEndpointTarget()) {
AttributeEndpointTarget other = target.asAttributeEndpointTarget();
for (PortTarget target : ragconnect().givenPortTargetList()) {
if (target.isAttributePortTarget()) {
AttributePortTarget other = target.asAttributePortTarget();
if (other.getParentTypeDecl().equals(this.getParentTypeDecl()) && other.getName().equals(this.getName())) {
numberOfSameDefs += 1;
}
......@@ -15,12 +15,12 @@ aspect Analysis {
}
return numberOfSameDefs > 1;
}
eq RelationEndpointTarget.isAlreadyDefined() {
eq RelationPortTarget.isAlreadyDefined() {
// define lookup here, as not used elsewhere
int numberOfSameDefs = 0;
for (EndpointTarget target : ragconnect().givenEndpointTargetList()) {
if (target.isRelationEndpointTarget()) {
RelationEndpointTarget other = target.asRelationEndpointTarget();
for (PortTarget target : ragconnect().givenPortTargetList()) {
if (target.isRelationPortTarget()) {
RelationPortTarget other = target.asRelationPortTarget();
if (other.getRole().equals(this.getRole())) {
numberOfSameDefs += 1;
}
......@@ -28,25 +28,25 @@ aspect Analysis {
}
return numberOfSameDefs > 1;
}
eq TokenEndpointTarget.isAlreadyDefined() {
return lookupTokenEndpointDefinitions(getToken()).stream()
.filter(containingEndpointDefinition()::matchesType)
eq TokenPortTarget.isAlreadyDefined() {
return lookupTokenPortDefinitions(getToken()).stream()
.filter(containingPortDefinition()::matchesType)
.count() > 1;
}
eq TypeEndpointTarget.isAlreadyDefined() {
return lookupGivenTypeEndpointDefinitions(getType()).stream()
.filter(containingEndpointDefinition()::matchesType)
eq TypePortTarget.isAlreadyDefined() {
return lookupGivenTypePortDefinitions(getType()).stream()
.filter(containingPortDefinition()::matchesType)
.count() > 1;
}
eq ContextFreeTypeEndpointTarget.isAlreadyDefined() {
return lookupContextFreeTypeEndpointDefinitions(getTypeDecl()).stream()
.filter(containingEndpointDefinition()::matchesType)
eq ContextFreeTypePortTarget.isAlreadyDefined() {
return lookupContextFreeTypePortDefinitions(getTypeDecl()).stream()
.filter(containingPortDefinition()::matchesType)
.count() > 1;
}
syn boolean DependencyDefinition.isAlreadyDefined() = lookupDependencyDefinition(getSource().containingTypeDecl(), getID()) != this;
// --- matchesType ---
syn boolean EndpointDefinition.matchesType(EndpointDefinition other) = this.getSend() == other.getSend();
syn boolean PortDefinition.matchesType(PortDefinition other) = this.getSend() == other.getSend();
// --- assignableTo ---
syn boolean MappingDefinitionType.assignableTo(JavaTypeUse target);
......@@ -90,24 +90,24 @@ aspect Analysis {
}
}
syn boolean EndpointTarget.hasAttributeResetMethod();
eq AttributeEndpointTarget.hasAttributeResetMethod() = false;
eq RelationEndpointTarget.hasAttributeResetMethod() = false;
eq TokenEndpointTarget.hasAttributeResetMethod() = getToken().getNTA();
eq TypeEndpointTarget.hasAttributeResetMethod() = getType().getNTA();
eq ContextFreeTypeEndpointTarget.hasAttributeResetMethod() = false;
syn boolean PortTarget.hasAttributeResetMethod();
eq AttributePortTarget.hasAttributeResetMethod() = false;
eq RelationPortTarget.hasAttributeResetMethod() = false;
eq TokenPortTarget.hasAttributeResetMethod() = getToken().getNTA();
eq TypePortTarget.hasAttributeResetMethod() = getType().getNTA();
eq ContextFreeTypePortTarget.hasAttributeResetMethod() = false;
// --- needProxyToken ---
syn boolean TokenComponent.needProxyToken() = !getDependencySourceDefinitionList().isEmpty() ||
getTokenEndpointTargetList().stream()
.map(EndpointTarget::containingEndpointDefinition)
.anyMatch(EndpointDefinition::shouldNotResetValue);
getTokenPortTargetList().stream()
.map(PortTarget::containingPortDefinition)
.anyMatch(PortDefinition::shouldNotResetValue);
// --- effectiveUsedAt ---
coll Set<EndpointDefinition> MappingDefinition.effectiveUsedAt()
[new java.util.HashSet<EndpointDefinition>()]
coll Set<PortDefinition> MappingDefinition.effectiveUsedAt()
[new java.util.HashSet<PortDefinition>()]
root RagConnect;
EndpointDefinition contributes this
PortDefinition contributes this
to MappingDefinition.effectiveUsedAt()
for each effectiveMappings();
......
......@@ -3,45 +3,45 @@ aspect Errors {
[new TreeSet<CompilerMessage>()]
root RagConnect;
EndpointDefinition contributes error("Endpoint definition already defined for " + parentTypeName() + "." + entityName())
PortDefinition contributes error("Port definition already defined for " + parentTypeName() + "." + entityName())
when isAlreadyDefined()
to RagConnect.errors();
EndpointDefinition contributes error("Receiving target token must not be an NTA token!")
when !getSend() && getEndpointTarget().isTokenEndpointTarget() && token().getNTA()
PortDefinition contributes error("Receiving target token must not be an NTA token!")
when !getSend() && getPortTarget().isTokenPortTarget() && token().getNTA()
to RagConnect.errors();
EndpointDefinition contributes error("Indexed based list access may only be used for type endpoint targets!")
when getIndexBasedListAccess() && !getEndpointTarget().isTypeEndpointTarget()
PortDefinition contributes error("Indexed based list access may only be used for type port targets!")
when getIndexBasedListAccess() && !getPortTarget().isTypePortTarget()
to RagConnect.errors();
// if first mapping is null, then suitableDefaultMapping() == null
EndpointDefinition contributes error("No suitable default mapping found for type " +
PortDefinition contributes error("No suitable default mapping found for type " +
((getMappingList().isEmpty())
? token().effectiveJavaTypeUse().prettyPrint()
: getMappingList().get(0).getFromType().prettyPrint()))
when !getSend() && getEndpointTarget().isTokenEndpointTarget() && effectiveMappings().get(0) == null
when !getSend() && getPortTarget().isTokenPortTarget() && effectiveMappings().get(0) == null
to RagConnect.errors();
EndpointDefinition contributes error("to-type of last mapping (" +
PortDefinition contributes error("to-type of last mapping (" +
effectiveMappings().get(effectiveMappings().size() - 1).getToType().prettyPrint() +
") not assignable to type of the token (" + token().effectiveJavaTypeUse().prettyPrint() + ")!")
when !getSend() && getEndpointTarget().isTokenEndpointTarget() &&
when !getSend() && getPortTarget().isTokenPortTarget() &&
!effectiveMappings().get(effectiveMappings().size() - 1).getToType().assignableTo(
token().effectiveJavaTypeUse())
to RagConnect.errors();
UntypedEndpointTarget contributes error("Could not resolve endpoint target " + getTypeName() + "." + getChildName())
UntypedPortTarget contributes error("Could not resolve port target " + getTypeName() + "." + getChildName())
to RagConnect.errors();
ContextFreeTypeEndpointTarget contributes error("Context-Free endpoint not allowed for root node " +
ContextFreeTypePortTarget contributes error("Context-Free port not allowed for root node " +
getTypeDecl().getName() + "!")
when getTypeDecl().occurencesInProductionRules().isEmpty()
to RagConnect.errors();
EndpointDefinition contributes error("Clash with implied, indexed endpoint definition of context-free endpoint in line " +
clashingContextFreeEndpointDefinition().getStartLine() + "!")
when clashingContextFreeEndpointDefinition() != null && clashingContextFreeEndpointDefinition().matchesType(this)
PortDefinition contributes error("Clash with implied, indexed port definition of context-free port in line " +
clashingContextFreePortDefinition().getStartLine() + "!")
when clashingContextFreePortDefinition() != null && clashingContextFreePortDefinition().matchesType(this)
to RagConnect.errors();
DependencyDefinition contributes error("Dependency definition already defined for " + getSource().containingTypeDecl().getName() + " with name " + getID())
......@@ -63,14 +63,14 @@ aspect ErrorHelpers {
return false;
}
syn EndpointDefinition EndpointDefinition.clashingContextFreeEndpointDefinition() {
syn PortDefinition PortDefinition.clashingContextFreePortDefinition() {
if (getSend() || !typeIsList() || getIndexBasedListAccess()) {
return null;
}
List<EndpointDefinition> contextFreeEndpointsWithSameType = lookupContextFreeTypeEndpointDefinitions(
getEndpointTarget().asTypeEndpointTarget().getType().getTypeDecl());
if (!contextFreeEndpointsWithSameType.isEmpty()) {
return contextFreeEndpointsWithSameType.get(0);
List<PortDefinition> contextFreePortsWithSameType = lookupContextFreeTypePortDefinitions(
getPortTarget().asTypePortTarget().getType().getTypeDecl());
if (!contextFreePortsWithSameType.isEmpty()) {
return contextFreePortsWithSameType.get(0);
}
return null;
}
......
This diff is collapsed.
abstract MEndpointDefinition ::= InnerMappingDefinition:MInnerMappingDefinition*;
rel MEndpointDefinition.EndpointDefinition -> EndpointDefinition;
abstract MPortDefinition ::= InnerMappingDefinition:MInnerMappingDefinition*;
rel MPortDefinition.PortDefinition -> PortDefinition;
MAttributeSendDefinition : MEndpointDefinition;
MRelationSendDefinition : MEndpointDefinition;
abstract MTokenEndpointDefinition : MEndpointDefinition;
MTokenReceiveDefinition : MTokenEndpointDefinition;
MTokenSendDefinition : MTokenEndpointDefinition;
abstract MTypeEndpointDefinition : MEndpointDefinition;
MTypeReceiveDefinition : MTypeEndpointDefinition;
MTypeSendDefinition : MTypeEndpointDefinition;
abstract MContextFreeTypeEndpointDefinition : MEndpointDefinition;
MContextFreeTypeReceiveDefinition : MContextFreeTypeEndpointDefinition;
MContextFreeTypeSendDefinition : MContextFreeTypeEndpointDefinition;
MAttributeSendDefinition : MPortDefinition;
MRelationSendDefinition : MPortDefinition;
abstract MTokenPortDefinition : MPortDefinition;
MTokenReceiveDefinition : MTokenPortDefinition;
MTokenSendDefinition : MTokenPortDefinition;
abstract MTypePortDefinition : MPortDefinition;
MTypeReceiveDefinition : MTypePortDefinition;
MTypeSendDefinition : MTypePortDefinition;
abstract MContextFreeTypePortDefinition : MPortDefinition;
MContextFreeTypeReceiveDefinition : MContextFreeTypePortDefinition;
MContextFreeTypeSendDefinition : MContextFreeTypePortDefinition;
MInnerMappingDefinition;
rel MInnerMappingDefinition.MappingDefinition -> MappingDefinition;
......
......@@ -27,12 +27,12 @@ aspect IntermediateToYAML {
// listAspect
root.put("configJastAddList" , configJastAddList());
root.put("hasTreeListEndpoints" , hasTreeListEndpoints());
ListElement typesForReceivingListEndpointsElement = new ListElement();
for (TypeDecl typeDecl : typesForReceivingListEndpoints()) {
typesForReceivingListEndpointsElement.addElement(typeDecl.toYAML());
root.put("hasTreeListPorts" , hasTreeListPorts());
ListElement typesForReceivingListPortsElement = new ListElement();
for (TypeDecl typeDecl : typesForReceivingListPorts()) {
typesForReceivingListPortsElement.addElement(typeDecl.toYAML());
}
root.put("typesForReceivingListEndpoints" , typesForReceivingListEndpointsElement);
root.put("typesForReceivingListPorts" , typesForReceivingListPortsElement);
// ragconnect
ListElement dependencyDefinitionsElement = new ListElement();
......@@ -40,11 +40,11 @@ aspect IntermediateToYAML {
dependencyDefinitionsElement.addElement(def.toYAML());
}
root.put("allDependencyDefinitionList" , dependencyDefinitionsElement);
ListElement endpointDefinitionsElement = new ListElement();
for (EndpointDefinition def : allEndpointDefinitionList()) {
endpointDefinitionsElement.addElement(def.toYAML());
ListElement portDefinitionsElement = new ListElement();
for (PortDefinition def : allPortDefinitionList()) {
portDefinitionsElement.addElement(def.toYAML());
}
root.put("allEndpointDefinitionList" , endpointDefinitionsElement);
root.put("allPortDefinitionList" , portDefinitionsElement);
ListElement mappingDefinitionsElement = new ListElement();
for (MappingDefinition def : allMappingDefinitions()) {
mappingDefinitionsElement.addElement(def.toYAML());
......@@ -70,7 +70,7 @@ aspect IntermediateToYAML {
return doc;
}
syn MappingElement EndpointDefinition.toYAML() {
syn MappingElement PortDefinition.toYAML() {
MappingElement result = new MappingElement();
// grammar children
result.put("AlwaysApply" , getAlwaysApply());
......@@ -108,16 +108,16 @@ aspect IntermediateToYAML {
result.put("updateMethodName" , updateMethodName());
result.put("writeMethodName" , writeMethodName());
} else {
result.put("hasTypeEndpointTarget" , hasTypeEndpointTarget());
result.put("hasTypePortTarget" , hasTypePortTarget());
result.put("idTokenName" , idTokenName());
result.put("internalConnectMethodName" , internalConnectMethodName());
result.put("resolveInListMethodName" , resolveInListMethodName());
result.put("typeIsList" , getEndpointTarget().typeIsList());
result.put("typeIsList" , getPortTarget().typeIsList());
}
return result;
}
void UntypedEndpointTarget.addToYAML(MappingElement result) {
void UntypedPortTarget.addToYAML(MappingElement result) {
// empty
}
......@@ -147,6 +147,17 @@ aspect IntermediateToYAML {
return result;
}
syn Element TemplateDefaultMappingDefinition.toYAML() {
MappingElement result = new MappingElement();
// ragconnect / mapping
result.put("isUsed" , isUsed());
result.put("isSerializeListMapping" , isSerializeListMapping());
result.put("isSerializeJavaUtilListMapping" , isSerializeJavaUtilListMapping());
result.put("isDeserializeListMapping" , isDeserializeListMapping());
return result;
}
syn Element DependencyDefinition.toYAML() {
MappingElement result = new MappingElement();
// dependencyDefinition
......@@ -156,7 +167,7 @@ aspect IntermediateToYAML {
result.put("targetParentTypeName" , targetParentTypeName());
// tokenComponent
result.put("targetEndpointDefinition" , targetEndpointDefinition().toYAML());
result.put("targetPortDefinition" , targetPortDefinition().toYAML());
return result;
}
......
......@@ -27,6 +27,16 @@ aspect DefaultMappings {
result.setContent(content);
return result;
}
private TemplateDefaultMappingDefinition RagConnect.initTemplateMappingDefinition(
TemplateDefaultMappingDefinition prototype, String id, String type, boolean fromBytes) {
MappingDefinitionType givenType = new JavaMappingDefinitionType().setType(new SimpleJavaTypeUse(type));
MappingDefinitionType bytesType = new JavaArrayMappingDefinitionType().setType(new SimpleJavaTypeUse("byte"));
prototype.setID(id);
prototype.setFromType(fromBytes ? bytesType : givenType);
prototype.setToType(fromBytes ? givenType : bytesType);
return prototype;
}
private DefaultMappingDefinition RagConnect.baseDefaultMappingDefinition(String fromTypeName, String toTypeName, String content) {
return createDefaultMappingDefinition("_Default", fromTypeName, toTypeName, content);
......@@ -81,7 +91,7 @@ aspect DefaultMappings {
"com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();\n" +
"com.fasterxml.jackson.core.JsonFactory factory = new com.fasterxml.jackson.core.JsonFactory();\n" +
"com.fasterxml.jackson.core.JsonParser parser = factory.createParser(content);\n" +
configJastAddList() + "<" + typeName + ">" + " result = " + typeName + ".deserializeList((com.fasterxml.jackson.databind.node.ArrayNode)mapper.readTree(parser));\n" +
configJastAddList() + "<" + typeName + ">" + " result = " + typeName + ".deserializeListOf" + typeName + "((com.fasterxml.jackson.databind.node.ArrayNode)mapper.readTree(parser));\n" +
"parser.close();\n" +
"return result;"
);
......@@ -155,9 +165,18 @@ aspect DefaultMappings {
"char", "String", "return String.valueOf(input);");
}
aspect TemplateDefaultMappingDefinitions {
syn nta TemplateDefaultMappingDefinition RagConnect.serializeListMapping() = initTemplateMappingDefinition(
new SerializeListMapping(), "SerializeListMapping", "JastAddList", false);
syn nta TemplateDefaultMappingDefinition RagConnect.serializeJavaUtilListMapping() = initTemplateMappingDefinition(
new SerializeJavaUtilListMapping(), "SerializeJavaUtilListMapping", "java.util.List", false);
syn nta TemplateDefaultMappingDefinition RagConnect.deserializeListMapping(String name) = initTemplateMappingDefinition(
new DeserializeListMapping().setName(name), "DeserializeListMapping", "JastAddList", true);
}
aspect Mappings {
// --- effectiveMappings ---
syn java.util.List<MappingDefinition> EndpointDefinition.effectiveMappings() {
syn java.util.List<MappingDefinition> PortDefinition.effectiveMappings() {
java.util.List<MappingDefinition> result;
if (!getSend()) {
// if no mappings are specified, or if first mapping is not suitable.
......@@ -183,10 +202,10 @@ aspect Mappings {
}
// --- isPrimitiveType ---
syn boolean EndpointDefinition.isPrimitiveType() = getEndpointTarget().isPrimitiveType();
syn boolean EndpointTarget.isPrimitiveType() = false;
eq TokenEndpointTarget.isPrimitiveType() = getToken().isPrimitiveType();
eq AttributeEndpointTarget.isPrimitiveType() = new SimpleJavaTypeUse(getTypeName()).isPrimitiveType();
syn boolean PortDefinition.isPrimitiveType() = getPortTarget().isPrimitiveType();
syn boolean PortTarget.isPrimitiveType() = false;
eq TokenPortTarget.isPrimitiveType() = getToken().isPrimitiveType();
eq AttributePortTarget.isPrimitiveType() = new SimpleJavaTypeUse(getTypeName()).isPrimitiveType();
syn boolean TokenComponent.isPrimitiveType() = effectiveJavaTypeUse().isPrimitiveType();
syn boolean JavaTypeUse.isPrimitiveType() = false;
eq SimpleJavaTypeUse.isPrimitiveType() {
......@@ -212,7 +231,7 @@ aspect Mappings {
eq JavaArrayMappingDefinitionType.isArray() = true;
// --- suitableReceiveDefaultMapping ---
syn DefaultMappingDefinition EndpointDefinition.suitableReceiveDefaultMapping() {
syn DefaultMappingDefinition PortDefinition.suitableReceiveDefaultMapping() {
switch (targetTypeName()) {
case "boolean":
case "Boolean":
......@@ -240,7 +259,7 @@ aspect Mappings {
default:
try {
TypeDecl typeDecl = program().resolveTypeDecl(targetTypeName());
return getEndpointTarget().isTypeEndpointTarget() && typeIsList() && !getIndexBasedListAccess() ? ragconnect().defaultBytesToListMapping(typeDecl.getName()) : ragconnect().defaultBytesToTreeMapping(typeDecl.getName());
return getPortTarget().isTypePortTarget() && typeIsList() && !getIndexBasedListAccess() ? ragconnect().defaultBytesToListMapping(typeDecl.getName()) : ragconnect().defaultBytesToTreeMapping(typeDecl.getName());
} catch (Exception ignore) {
}
System.err.println("Could not find suitable default receive mapping for " + targetTypeName() + " on " + this);
......@@ -249,7 +268,7 @@ aspect Mappings {
}
// --- suitableSendDefaultMapping ---
syn DefaultMappingDefinition EndpointDefinition.suitableSendDefaultMapping() {
syn DefaultMappingDefinition PortDefinition.suitableSendDefaultMapping() {
switch (targetTypeName()) {
case "boolean":
case "Boolean":
......@@ -275,10 +294,10 @@ aspect Mappings {
case "String":
return ragconnect().defaultStringToBytesMapping();
default:
if (getEndpointTarget().isTypeEndpointTarget() && typeIsList() && !getIndexBasedListAccess()) {
if (getPortTarget().isTypePortTarget() && typeIsList() && !getIndexBasedListAccess()) {
return ragconnect().defaultListToBytesMapping();
}
if (getEndpointTarget().isRelationEndpointTarget() && typeIsList() && !getIndexBasedListAccess()) {
if (getPortTarget().isRelationPortTarget() && typeIsList() && !getIndexBasedListAccess()) {
return ragconnect().defaultJavaUtilListToBytesMapping();
}
try {
......@@ -293,9 +312,9 @@ aspect Mappings {
}
// --- targetTypeName ---
syn String EndpointDefinition.targetTypeName() {
syn String PortDefinition.targetTypeName() {
if (getMappingList().isEmpty()) {
return getEndpointTarget().targetTypeName();
return getPortTarget().targetTypeName();
} else {
if (getSend()) {
return getMappingList().get(getMappingList().size() - 1).getToType().prettyPrint();
......@@ -304,12 +323,12 @@ aspect Mappings {
}
}
}
syn String EndpointTarget.targetTypeName();
eq AttributeEndpointTarget.targetTypeName() = getTypeName();
eq RelationEndpointTarget.targetTypeName() = getRole().oppositeRole().targetTypeName();
eq TokenEndpointTarget.targetTypeName() = getToken().effectiveJavaTypeUse().getName();
eq TypeEndpointTarget.targetTypeName() = getType().getTypeDecl().getName();
eq ContextFreeTypeEndpointTarget.targetTypeName() = getTypeDecl().getName();
syn String PortTarget.targetTypeName();
eq AttributePortTarget.targetTypeName() = getTypeName();
eq RelationPortTarget.targetTypeName() = getRole().oppositeRole().targetTypeName();
eq TokenPortTarget.targetTypeName() = getToken().effectiveJavaTypeUse().getName();
eq TypePortTarget.targetTypeName() = getType().getTypeDecl().getName();
eq ContextFreeTypePortTarget.targetTypeName() = getTypeDecl().getName();
syn String Role.targetTypeName() = getType().getName();
eq ListRole.targetTypeName() = "java.util.List<" + getType().getName() + ">";
......@@ -390,9 +409,12 @@ aspect Mappings {
result.add(defaultBytesToTreeMapping(typeDecl.getName()));
result.add(defaultTreeToBytesMapping(typeDecl.getName()));
result.add(defaultBytesToListMapping(typeDecl.getName()));
result.add(deserializeListMapping(typeDecl.getName()));
}
result.add(defaultListToBytesMapping());
result.add(defaultJavaUtilListToBytesMapping());
result.add(serializeListMapping());
result.add(serializeJavaUtilListMapping());
// // string conversion
// result.add(defaultStringToBooleanMapping());
// result.add(defaultStringToIntMapping());
......
aspect RagConnectNameResolution {
// --- lookupTokenEndpointDefinition ---
inh java.util.List<EndpointDefinition> EndpointDefinition.lookupTokenEndpointDefinitions(TokenComponent token);
inh java.util.List<EndpointDefinition> EndpointTarget.lookupTokenEndpointDefinitions(TokenComponent token);
eq RagConnect.getConnectSpecificationFile().lookupTokenEndpointDefinitions(TokenComponent token) = lookupTokenEndpointDefinitions(token);
syn java.util.List<EndpointDefinition> RagConnect.lookupTokenEndpointDefinitions(TokenComponent token) {
java.util.List<EndpointDefinition> result = new java.util.ArrayList<>();
for (EndpointTarget target : givenEndpointTargetList()) {
if (target.isTokenEndpointTarget() && target.asTokenEndpointTarget().getToken().equals(token)) {
result.add(target.containingEndpointDefinition());
// --- lookupTokenPortDefinition ---
inh java.util.List<PortDefinition> PortDefinition.lookupTokenPortDefinitions(TokenComponent token);
inh java.util.List<PortDefinition> PortTarget.lookupTokenPortDefinitions(TokenComponent token);
eq RagConnect.getConnectSpecificationFile().lookupTokenPortDefinitions(TokenComponent token) = lookupTokenPortDefinitions(token);
syn java.util.List<PortDefinition> RagConnect.lookupTokenPortDefinitions(TokenComponent token) {
java.util.List<PortDefinition> result = new java.util.ArrayList<>();
for (PortTarget target : givenPortTargetList()) {
if (target.isTokenPortTarget() && target.asTokenPortTarget().getToken().equals(token)) {
result.add(target.containingPortDefinition());
}
}
return result;
}
// --- lookupGivenTypeEndpointDefinition ---
inh java.util.List<EndpointDefinition> EndpointDefinition.lookupGivenTypeEndpointDefinitions(TypeComponent type);
inh java.util.List<EndpointDefinition> EndpointTarget.lookupGivenTypeEndpointDefinitions(TypeComponent type);
eq RagConnect.getConnectSpecificationFile().lookupGivenTypeEndpointDefinitions(TypeComponent type) = lookupTypeEndpointDefinitions(type, true);
// --- lookupGivenTypePortDefinition ---
inh java.util.List<PortDefinition> PortDefinition.lookupGivenTypePortDefinitions(TypeComponent type);
inh java.util.List<PortDefinition> PortTarget.lookupGivenTypePortDefinitions(TypeComponent type);
eq RagConnect.getConnectSpecificationFile().lookupGivenTypePortDefinitions(TypeComponent type) = lookupTypePortDefinitions(type, true);
// --- lookupAllTypeEndpointDefinition ---
inh java.util.List<EndpointDefinition> EndpointDefinition.lookupAllTypeEndpointDefinitions(TypeComponent type);
inh java.util.List<EndpointDefinition> EndpointTarget.lookupAllTypeEndpointDefinitions(TypeComponent type);
eq RagConnect.getConnectSpecificationFile().lookupAllTypeEndpointDefinitions(TypeComponent type) = lookupTypeEndpointDefinitions(type, false);
// --- lookupAllTypePortDefinition ---
inh java.util.List<PortDefinition> PortDefinition.lookupAllTypePortDefinitions(TypeComponent type);
inh java.util.List<PortDefinition> PortTarget.lookupAllTypePortDefinitions(TypeComponent type);
eq RagConnect.getConnectSpecificationFile().lookupAllTypePortDefinitions(TypeComponent type) = lookupTypePortDefinitions(type, false);
syn java.util.List<EndpointDefinition> RagConnect.lookupTypeEndpointDefinitions(TypeComponent type, boolean onlyGiven) {
java.util.List<EndpointDefinition> result = new java.util.ArrayList<>();
for (EndpointDefinition def : onlyGiven ? givenEndpointDefinitionList() : allEndpointDefinitionList()) {
EndpointTarget target = def.getEndpointTarget();
if (target.isTypeEndpointTarget() && target.asTypeEndpointTarget().getType().equals(type)) {
syn java.util.List<PortDefinition> RagConnect.lookupTypePortDefinitions(TypeComponent type, boolean onlyGiven) {
java.util.List<PortDefinition> result = new java.util.ArrayList<>();
for (PortDefinition def : onlyGiven ? givenPortDefinitionList() : allPortDefinitionList()) {
PortTarget target = def.getPortTarget();
if (target.isTypePortTarget() && target.asTypePortTarget().getType().equals(type)) {
result.add(def);
}
}
return result;
}
// --- lookupContextFreeTypeEndpointDefinition ---
inh java.util.List<EndpointDefinition> EndpointDefinition.lookupContextFreeTypeEndpointDefinitions(TypeDecl typeDecl);
inh java.util.List<EndpointDefinition> EndpointTarget.lookupContextFreeTypeEndpointDefinitions(TypeDecl typeDecl);
eq RagConnect.getConnectSpecificationFile().lookupContextFreeTypeEndpointDefinitions(TypeDecl typeDecl) = lookupContextFreeTypeEndpointDefinitions(typeDecl);
syn java.util.List<EndpointDefinition> RagConnect.lookupContextFreeTypeEndpointDefinitions(TypeDecl typeDecl) {
java.util.List<EndpointDefinition> result = new java.util.ArrayList<>();
for (EndpointTarget target : givenEndpointTargetList()) {
if (target.isContextFreeTypeEndpointTarget() && target.asContextFreeTypeEndpointTarget().getTypeDecl().equals(typeDecl)) {
result.add(target.containingEndpointDefinition());
// --- lookupContextFreeTypePortDefinition ---
inh java.util.List<PortDefinition> PortDefinition.lookupContextFreeTypePortDefinitions(TypeDecl typeDecl);
inh java.util.List<PortDefinition> PortTarget.lookupContextFreeTypePortDefinitions(TypeDecl typeDecl);
eq RagConnect.getConnectSpecificationFile().lookupContextFreeTypePortDefinitions(TypeDecl typeDecl) = lookupContextFreeTypePortDefinitions(typeDecl);
syn java.util.List<PortDefinition> RagConnect.lookupContextFreeTypePortDefinitions(TypeDecl typeDecl) {
java.util.List<PortDefinition> result = new java.util.ArrayList<>();
for (PortTarget target : givenPortTargetList()) {
if (target.isContextFreeTypePortTarget() && target.asContextFreeTypePortTarget().getTypeDecl().equals(typeDecl)) {
result.add(target.containingPortDefinition());
}
}
return result;
......@@ -59,15 +59,15 @@ aspect RagConnectNameResolution {
return null;
}
// rel EndpointDefinition.Mapping* -> MappingDefinition
refine RefResolverStubs eq EndpointDefinition.resolveMappingByToken(String id, int position) {
// rel PortDefinition.Mapping* -> MappingDefinition
refine RefResolverStubs eq PortDefinition.resolveMappingByToken(String id, int position) {
MappingDefinition result = tryResolveMappingByToken(id);
if (result == null) {
System.err.println("Could not resolve MappingDefinition '" + id + "'.");
}
return result;
}
syn MappingDefinition EndpointDefinition.tryResolveMappingByToken(String id) {
syn MappingDefinition PortDefinition.tryResolveMappingByToken(String id) {
for (MappingDefinition mappingDefinition : ragconnect().givenMappingDefinitionList()) {
if (mappingDefinition.getID().equals(id)) {
return mappingDefinition;
......
aspect GeneratedNavigation {
/** Tests if EndpointTarget is a TokenEndpointTarget.
* @return 'true' if this is a TokenEndpointTarget, otherwise 'false'
/** Tests if PortTarget is a TokenPortTarget.
* @return 'true' if this is a TokenPortTarget, otherwise 'false'
*/
syn boolean EndpointTarget.isTokenEndpointTarget() = false;
eq TokenEndpointTarget.isTokenEndpointTarget() = true;
syn boolean PortTarget.isTokenPortTarget() = false;
eq TokenPortTarget.isTokenPortTarget() = true;
/** Tests if EndpointTarget is a TypeEndpointTarget.
* @return 'true' if this is a TypeEndpointTarget, otherwise 'false'
/** Tests if PortTarget is a TypePortTarget.
* @return 'true' if this is a TypePortTarget, otherwise 'false'
*/
syn boolean EndpointTarget.isTypeEndpointTarget() = false;
eq TypeEndpointTarget.isTypeEndpointTarget() = true;
syn boolean PortTarget.isTypePortTarget() = false;
eq TypePortTarget.isTypePortTarget() = true;
/** Tests if EndpointTarget is a ContextFreeTypeEndpointTarget.
* @return 'true' if this is a ContextFreeTypeEndpointTarget, otherwise 'false'
/** Tests if PortTarget is a ContextFreeTypePortTarget.
* @return 'true' if this is a ContextFreeTypePortTarget, otherwise 'false'
*/
syn boolean EndpointTarget.isContextFreeTypeEndpointTarget() = false;
eq ContextFreeTypeEndpointTarget.isContextFreeTypeEndpointTarget() = true;
syn boolean PortTarget.isContextFreeTypePortTarget() = false;
eq ContextFreeTypePortTarget.isContextFreeTypePortTarget() = true;
/** Tests if EndpointTarget is a UntypedEndpointTarget.
* @return 'true' if this is a UntypedEndpointTarget, otherwise 'false'
/** Tests if PortTarget is a UntypedPortTarget.
* @return 'true' if this is a UntypedPortTarget, otherwise 'false'
*/
syn boolean EndpointTarget.isUntypedEndpointTarget() = false;
eq UntypedEndpointTarget.isUntypedEndpointTarget() = true;
syn boolean PortTarget.isUntypedPortTarget() = false;
eq UntypedPortTarget.isUntypedPortTarget() = true;
/** Tests if EndpointTarget is a AttributeEndpointTarget.
* @return 'true' if this is a AttributeEndpointTarget, otherwise 'false'
/** Tests if PortTarget is a AttributePortTarget.
* @return 'true' if this is a AttributePortTarget, otherwise 'false'
*/
syn boolean EndpointTarget.isAttributeEndpointTarget() = false;
eq AttributeEndpointTarget.isAttributeEndpointTarget() = true;
syn boolean PortTarget.isAttributePortTarget() = false;
eq AttributePortTarget.isAttributePortTarget() = true;
/** Tests if EndpointTarget is a RelationEndpointTarget.
* @return 'true' if this is a RelationEndpointTarget, otherwise 'false'
/** Tests if PortTarget is a RelationPortTarget.
* @return 'true' if this is a RelationPortTarget, otherwise 'false'
*/
syn boolean EndpointTarget.isRelationEndpointTarget() = false;
eq RelationEndpointTarget.isRelationEndpointTarget() = true;
syn boolean PortTarget.isRelationPortTarget() = false;
eq RelationPortTarget.isRelationPortTarget() = true;
/** casts a EndpointTarget into a TokenEndpointTarget if possible.
* @return 'this' cast to a TokenEndpointTarget or 'null'
/** Tests if TemplateDefaultMappingDefinition is a SerializeListMapping.
* @return 'true' if this is a SerializeListMapping, otherwise 'false'
*/
syn TokenEndpointTarget EndpointTarget.asTokenEndpointTarget();
eq EndpointTarget.asTokenEndpointTarget() = null;
eq TokenEndpointTarget.asTokenEndpointTarget() = this;
syn boolean TemplateDefaultMappingDefinition.isSerializeListMapping() = false;
eq SerializeListMapping.isSerializeListMapping() = true;
/** casts a EndpointTarget into a TypeEndpointTarget if possible.
* @return 'this' cast to a TypeEndpointTarget or 'null'
/** Tests if TemplateDefaultMappingDefinition is a SerializeJavaUtilListMapping.
* @return 'true' if this is a SerializeJavaUtilListMapping, otherwise 'false'
*/
syn TypeEndpointTarget EndpointTarget.asTypeEndpointTarget();
eq EndpointTarget.asTypeEndpointTarget() = null;
eq TypeEndpointTarget.asTypeEndpointTarget() = this;
syn boolean TemplateDefaultMappingDefinition.isSerializeJavaUtilListMapping() = false;
eq SerializeJavaUtilListMapping.isSerializeJavaUtilListMapping() = true;
/** casts a EndpointTarget into a ContextFreeTypeEndpointTarget if possible.
* @return 'this' cast to a ContextFreeTypeEndpointTarget or 'null'
/** Tests if TemplateDefaultMappingDefinition is a DeserializeListMapping.
* @return 'true' if this is a DeserializeListMapping, otherwise 'false'
*/
syn ContextFreeTypeEndpointTarget EndpointTarget.asContextFreeTypeEndpointTarget();
eq EndpointTarget.asContextFreeTypeEndpointTarget() = null;
eq ContextFreeTypeEndpointTarget.asContextFreeTypeEndpointTarget() = this;
syn boolean TemplateDefaultMappingDefinition.isDeserializeListMapping() = false;
eq DeserializeListMapping.isDeserializeListMapping() = true;
/** casts a EndpointTarget into a UntypedEndpointTarget if possible.
* @return 'this' cast to a UntypedEndpointTarget or 'null'
/** casts a PortTarget into a TokenPortTarget if possible.
* @return 'this' cast to a TokenPortTarget or 'null'
*/
syn UntypedEndpointTarget EndpointTarget.asUntypedEndpointTarget();
eq EndpointTarget.asUntypedEndpointTarget() = null;
eq UntypedEndpointTarget.asUntypedEndpointTarget() = this;
syn TokenPortTarget PortTarget.asTokenPortTarget();
eq PortTarget.asTokenPortTarget() = null;
eq TokenPortTarget.asTokenPortTarget() = this;
/** casts a EndpointTarget into a AttributeEndpointTarget if possible.
* @return 'this' cast to a AttributeEndpointTarget or 'null'
/** casts a PortTarget into a TypePortTarget if possible.
* @return 'this' cast to a TypePortTarget or 'null'
*/
syn AttributeEndpointTarget EndpointTarget.asAttributeEndpointTarget();
eq EndpointTarget.asAttributeEndpointTarget() = null;
eq AttributeEndpointTarget.asAttributeEndpointTarget() = this;
syn TypePortTarget PortTarget.asTypePortTarget();
eq PortTarget.asTypePortTarget() = null;
eq TypePortTarget.asTypePortTarget() = this;
/** casts a EndpointTarget into a RelationEndpointTarget if possible.
* @return 'this' cast to a RelationEndpointTarget or 'null'
/** casts a PortTarget into a ContextFreeTypePortTarget if possible.
* @return 'this' cast to a ContextFreeTypePortTarget or 'null'
*/
syn RelationEndpointTarget EndpointTarget.asRelationEndpointTarget();
eq EndpointTarget.asRelationEndpointTarget() = null;
eq RelationEndpointTarget.asRelationEndpointTarget() = this;
syn ContextFreeTypePortTarget PortTarget.asContextFreeTypePortTarget();
eq PortTarget.asContextFreeTypePortTarget() = null;
eq ContextFreeTypePortTarget.asContextFreeTypePortTarget() = this;
/** casts a PortTarget into a UntypedPortTarget if possible.
* @return 'this' cast to a UntypedPortTarget or 'null'
*/
syn UntypedPortTarget PortTarget.asUntypedPortTarget();
eq PortTarget.asUntypedPortTarget() = null;
eq UntypedPortTarget.asUntypedPortTarget() = this;
/** casts a PortTarget into a AttributePortTarget if possible.
* @return 'this' cast to a AttributePortTarget or 'null'
*/
syn AttributePortTarget PortTarget.asAttributePortTarget();
eq PortTarget.asAttributePortTarget() = null;
eq AttributePortTarget.asAttributePortTarget() = this;
/** casts a PortTarget into a RelationPortTarget if possible.
* @return 'this' cast to a RelationPortTarget or 'null'
*/
syn RelationPortTarget PortTarget.asRelationPortTarget();
eq PortTarget.asRelationPortTarget() = null;
eq RelationPortTarget.asRelationPortTarget() = this;
}
aspect RagConnectNavigation {
// adapted from generated navigation, was defined only for DefaultMappingDefinition
/** Tests if MappingDefinition is a TemplateDefaultMappingDefinition.
* @return 'true' if this is a TemplateDefaultMappingDefinition, otherwise 'false'
*/
syn boolean MappingDefinition.isTemplateDefaultMappingDefinition() = false;
eq TemplateDefaultMappingDefinition.isTemplateDefaultMappingDefinition() = true;
// --- program ---
eq RagConnect.getChild().program() = getProgram();
......@@ -94,9 +119,9 @@ aspect RagConnectNavigation {
eq Program.getChild().containedConnectSpecification() = null;
eq ConnectSpecification.getChild().containedConnectSpecification() = this;
// --- containingEndpointDefinition ---
inh EndpointDefinition EndpointTarget.containingEndpointDefinition();
eq EndpointDefinition.getEndpointTarget().containingEndpointDefinition() = this;
// --- containingPortDefinition ---
inh PortDefinition PortTarget.containingPortDefinition();
eq PortDefinition.getPortTarget().containingPortDefinition() = this;
// --- containedFile
eq RagConnect.getChild().containedFile() = null;
......@@ -115,11 +140,11 @@ aspect RagConnectNavigation {
inh boolean DependencyDefinition.isFirstInList();
eq ConnectSpecification.getDependencyDefinition(int index).isFirstInList() = index == 0;
//--- givenEndpointTargetList ---
syn List<EndpointTarget> RagConnect.givenEndpointTargetList() {
List<EndpointTarget> result = new ArrayList<>();
//--- givenPortTargetList ---
syn List<PortTarget> RagConnect.givenPortTargetList() {
List<PortTarget> result = new ArrayList<>();
for (ConnectSpecification spec : getConnectSpecificationFileList()) {
spec.getEndpointDefinitionList().forEach(endpointDef -> result.add(endpointDef.getEndpointTarget()));
spec.getPortDefinitionList().forEach(portDef -> result.add(portDef.getPortTarget()));
}
return result;
}
......
RagConnect ::= ConnectSpecificationFile* Program Handler* Configuration;
abstract ConnectSpecification ::= EndpointDefinition* DependencyDefinition* MappingDefinition*;
abstract ConnectSpecification ::= PortDefinition* DependencyDefinition* MappingDefinition*;
ConnectSpecificationFile : ConnectSpecification ::= <FileName>;
EndpointDefinition ::= <AlwaysApply:boolean> <IndexBasedListAccess:boolean> <WithAdd:boolean> <Send:boolean> EndpointTarget;
rel EndpointDefinition.Mapping* <-> MappingDefinition.UsedAt*;
PortDefinition ::= <AlwaysApply:boolean> <IndexBasedListAccess:boolean> <WithAdd:boolean> <Send:boolean> PortTarget;
rel PortDefinition.Mapping* <-> MappingDefinition.UsedAt*;
abstract EndpointTarget;
TokenEndpointTarget : EndpointTarget;
rel TokenEndpointTarget.Token <-> TokenComponent.TokenEndpointTarget*;
TypeEndpointTarget : EndpointTarget;
rel TypeEndpointTarget.Type <-> TypeComponent.TypeEndpointTarget*;
ContextFreeTypeEndpointTarget : EndpointTarget;
rel ContextFreeTypeEndpointTarget.TypeDecl <-> TypeDecl.ContextFreeTypeEndpointTarget*;
AttributeEndpointTarget : EndpointTarget ::= <Name> <TypeName> ;
rel AttributeEndpointTarget.ParentTypeDecl <-> TypeDecl.AttributeEndpointTarget*;
RelationEndpointTarget : EndpointTarget ;
rel RelationEndpointTarget.Role <-> NavigableRole.RelationEndpointTarget* ;
UntypedEndpointTarget : EndpointTarget ::= <TypeName> <ChildName> <IsAttribute:boolean>; // only used by parser
abstract PortTarget;
TokenPortTarget : PortTarget;
rel TokenPortTarget.Token <-> TokenComponent.TokenPortTarget*;
TypePortTarget : PortTarget;
rel TypePortTarget.Type <-> TypeComponent.TypePortTarget*;
ContextFreeTypePortTarget : PortTarget;
rel ContextFreeTypePortTarget.TypeDecl <-> TypeDecl.ContextFreeTypePortTarget*;
AttributePortTarget : PortTarget ::= <Name> <TypeName> ;
rel AttributePortTarget.ParentTypeDecl <-> TypeDecl.AttributePortTarget*;
RelationPortTarget : PortTarget ;
rel RelationPortTarget.Role <-> NavigableRole.RelationPortTarget* ;
UntypedPortTarget : PortTarget ::= <TypeName> <ChildName> <IsAttribute:boolean>; // only used by parser
DependencyDefinition ::= <ID>;
rel DependencyDefinition.Source <-> TokenComponent.DependencySourceDefinition*;
......@@ -28,6 +28,10 @@ abstract MappingDefinitionType ::= ;
JavaMappingDefinitionType : MappingDefinitionType ::= Type:JavaTypeUse;
JavaArrayMappingDefinitionType : MappingDefinitionType ::= Type:JavaTypeUse;
DefaultMappingDefinition : MappingDefinition;
abstract TemplateDefaultMappingDefinition : DefaultMappingDefinition ;
SerializeListMapping : TemplateDefaultMappingDefinition ;
SerializeJavaUtilListMapping : TemplateDefaultMappingDefinition ;
DeserializeListMapping : TemplateDefaultMappingDefinition ::= <Name> ;
Handler ::= <ClassName> <UniqueName> <InUse:boolean>;
......
......@@ -11,7 +11,7 @@ aspect Warnings {
when this.isFirstInList() // print warning only once for first dependency definition
to RagConnect.warnings();
EndpointDefinition contributes warning("No dependency definitions are given, and incremental evaluation is disabled. No messages will be sent for this!")
PortDefinition contributes warning("No dependency definitions are given, and incremental evaluation is disabled. No messages will be sent for this!")
when getSend() && ragconnect().allDependencyDefinitionList().isEmpty() && !ragconnect().configIncrementalOptionActive()
to RagConnect.warnings();
......
aspect ParserRewrites {
rewrite UntypedEndpointTarget {
rewrite UntypedPortTarget {
when (getChildName() != null && tryGloballyResolveTypeComponentByToken(combinedName()) != null)
to TypeEndpointTarget {
TypeEndpointTarget result = new TypeEndpointTarget();
to TypePortTarget {
TypePortTarget result = new TypePortTarget();
result.copyOtherValuesFrom(this);
result.setType(TypeComponent.createRef(this.combinedName()));
return result;
}
when (getChildName() != null && tryGloballyResolveTokenComponentByToken(combinedName()) != null)
to TokenEndpointTarget {
TokenEndpointTarget result = new TokenEndpointTarget();
to TokenPortTarget {
TokenPortTarget result = new TokenPortTarget();
result.copyOtherValuesFrom(this);
result.setToken(TokenComponent.createRef(this.combinedName()));
return result;
}
when (getChildName() != null && tryGloballyResolveNavigableRoleByToken(combinedName()) != null)
to RelationEndpointTarget {
RelationEndpointTarget result = new RelationEndpointTarget();
to RelationPortTarget {
RelationPortTarget result = new RelationPortTarget();
result.copyOtherValuesFrom(this);
result.setRole(NavigableRole.createRef(this.combinedName()));
return result;
}
when (getChildName() == "")
to ContextFreeTypeEndpointTarget {
ContextFreeTypeEndpointTarget result = new ContextFreeTypeEndpointTarget();
to ContextFreeTypePortTarget {
ContextFreeTypePortTarget result = new ContextFreeTypePortTarget();
result.copyOtherValuesFrom(this);
result.setTypeDecl(TypeDecl.createRef(getTypeName()));
return result;
}
when (getIsAttribute())
to AttributeEndpointTarget {
AttributeEndpointTarget result = new AttributeEndpointTarget();
to AttributePortTarget {
AttributePortTarget result = new AttributePortTarget();
String[] tokens = this.getChildName().split(":");
String attributeName = tokens[0];
String attributeTypeName = tokens[1];
......@@ -46,19 +46,19 @@ aspect ParserRewrites {
}
}
syn String UntypedEndpointTarget.combinedName() = getTypeName() + "." + getChildName();
syn String UntypedPortTarget.combinedName() = getTypeName() + "." + getChildName();
protected void EndpointTarget.copyOtherValuesFrom(EndpointTarget source) {
protected void PortTarget.copyOtherValuesFrom(PortTarget source) {
this.setStart(source.getStartLine(), source.getStartColumn());
this.setEnd(source.getEndLine(), source.getEndColumn());
}
eq UntypedEndpointTarget.senderName() = "<untyped.senderName>";
eq UntypedEndpointTarget.getterMethodName() = "<untyped.getterMethodName>";
eq UntypedEndpointTarget.parentTypeName() = "<untyped.parentTypeName>";
eq UntypedEndpointTarget.entityName() = "<untyped.entityName>";
eq UntypedEndpointTarget.isAlreadyDefined() = false;
eq UntypedEndpointTarget.hasAttributeResetMethod() = false;
eq UntypedEndpointTarget.targetTypeName() = "<untyped.targetTypeName>";
eq UntypedEndpointTarget.isTypeEndpointTarget() = false;
eq UntypedPortTarget.senderName() = "<untyped.senderName>";
eq UntypedPortTarget.getterMethodName() = "<untyped.getterMethodName>";
eq UntypedPortTarget.parentTypeName() = "<untyped.parentTypeName>";
eq UntypedPortTarget.entityName() = "<untyped.entityName>";
eq UntypedPortTarget.isAlreadyDefined() = false;
eq UntypedPortTarget.hasAttributeResetMethod() = false;
eq UntypedPortTarget.targetTypeName() = "<untyped.targetTypeName>";
eq UntypedPortTarget.isTypePortTarget() = false;
}
ConnectSpecificationFile connect_specification_file
= endpoint_definition.d connect_specification_file.r
= port_definition.d connect_specification_file.r
{:
r.getEndpointDefinitionList().insertChild(d, 0); return r;
r.getPortDefinitionList().insertChild(d, 0); return r;
:}
| dependency_definition.d connect_specification_file.r
{:
......@@ -22,50 +22,50 @@ ConnectSpecificationFile connect_specification_file
private Iterable<String> makeMappingDefs(ArrayList<?> raw_mapping_defs) {
return () -> raw_mapping_defs.stream().map(raw -> ((Symbol) raw).value.toString()).iterator();
}
// private TokenEndpointDefinition enableAlwaysApply(TokenEndpointDefinition def) {
// private TokenPortDefinition enableAlwaysApply(TokenPortDefinition def) {
// def.setAlwaysApply(true);
// return def;
// }
private EndpointDefinition createEndpointDefinition(
EndpointTarget endpointTarget, boolean send,
private PortDefinition createPortDefinition(
PortTarget portTarget, boolean send,
boolean indexBasedListAccess, boolean withAdd) {
EndpointDefinition result = new EndpointDefinition();
PortDefinition result = new PortDefinition();
result.setSend(send);
result.setIndexBasedListAccess(indexBasedListAccess);
result.setWithAdd(withAdd);
result.setEndpointTarget(endpointTarget);
result.setPortTarget(portTarget);
return result;
}
:} ;
EndpointDefinition endpoint_definition
= endpoint_definition_type.endpointDef SCOL
PortDefinition port_definition
= port_definition_type.portDef SCOL
{:
return endpointDef;
return portDef;
:}
| endpoint_definition_type.endpointDef USING string_list.mapping_defs SCOL
| port_definition_type.portDef USING string_list.mapping_defs SCOL
{:
for (String mapping_def : makeMappingDefs(mapping_defs)) {
endpointDef.addMapping(MappingDefinition.createRef(mapping_def));
portDef.addMapping(MappingDefinition.createRef(mapping_def));
}
return endpointDef;
return portDef;
:}
;
EndpointDefinition endpoint_definition_type
= SEND endpoint_target.t {: return createEndpointDefinition(t, true, false, false); :}
| SEND INDEXED endpoint_target.t {: return createEndpointDefinition(t, true, true, false); :}
| RECEIVE endpoint_target.t {: return createEndpointDefinition(t, false, false, false); :}
| RECEIVE INDEXED endpoint_target.t {: return createEndpointDefinition(t, false, true, false); :}
| RECEIVE WITH ADD endpoint_target.t {: return createEndpointDefinition(t, false, false, true ); :}
| RECEIVE INDEXED WITH ADD endpoint_target.t {: return createEndpointDefinition(t, false, true, true ); :}
PortDefinition port_definition_type
= SEND port_target.t {: return createPortDefinition(t, true, false, false); :}
| SEND INDEXED port_target.t {: return createPortDefinition(t, true, true, false); :}
| RECEIVE port_target.t {: return createPortDefinition(t, false, false, false); :}
| RECEIVE INDEXED port_target.t {: return createPortDefinition(t, false, true, false); :}
| RECEIVE WITH ADD port_target.t {: return createPortDefinition(t, false, false, true ); :}
| RECEIVE INDEXED WITH ADD port_target.t {: return createPortDefinition(t, false, true, true ); :}
;
EndpointTarget endpoint_target
= ID.type_name DOT ID.child_name {: return new UntypedEndpointTarget(type_name, child_name, false); :}
PortTarget port_target
= ID.type_name DOT ID.child_name {: return new UntypedPortTarget(type_name, child_name, false); :}
| ID.type_name DOT ID.child_name BRACKET_LEFT java_type_use.attribute_type_name BRACKET_RIGHT
{: return new UntypedEndpointTarget(type_name, child_name + ":" + attribute_type_name.prettyPrint(), true); :}
| ID.type_name {: return new UntypedEndpointTarget(type_name, "", false); :}
{: return new UntypedPortTarget(type_name, child_name + ":" + attribute_type_name.prettyPrint(), true); :}
| ID.type_name {: return new UntypedPortTarget(type_name, "", false); :}
;
ArrayList string_list
......
......@@ -364,6 +364,8 @@ public class Compiler extends AbstractCompiler {
com.github.mustachejava.DefaultMustacheFactory mf = new com.github.mustachejava.DefaultMustacheFactory();
mf.setObjectHandler(roh);
com.github.mustachejava.Mustache m = mf.compile("ragconnect.mustache");
// String yaml = ragConnect.toYAML().prettyPrint();
// Object context = new org.yaml.snakeyaml.Yaml().load(new StringReader(yaml));
m.execute(new java.io.PrintWriter(new org.jastadd.ragconnect.compiler.AppendableWriter(sb)), ragConnect);
return sb.toString();
}
......
aspect EvaluationCounter {
public String ASTNode.{{evaluationCounterSummaryMethodName}}() {
{{#configEvaluationCounter}}
return {{evaluationCounterVariable}}.summary();
{{/configEvaluationCounter}}
{{^configEvaluationCounter}}
String message = "Option --evaluationCounter was not set. No Summary available";
{{logWarn}}(message);
return message;
{{/configEvaluationCounter}}
}
{{#configEvaluationCounter}}
static EvaluationCounter ASTNode.{{evaluationCounterVariable}} = new EvaluationCounter();
public void {{rootNodeName}}.ragconnectResetEvaluationCounter() {
{{#configEvaluationCounter}}
{{evaluationCounterVariable}}.reset();
{{/configEvaluationCounter}}
{{^configEvaluationCounter}}
{{logWarn}}("Option --evaluationCounter was not set. Nothing to reset!");
{{/configEvaluationCounter}}
}
public class EvaluationCounter {
private java.util.Map<String, java.util.Map<String, {{evaluationCounterInnerClass}}>> counters = new java.util.HashMap<>();
private final java.util.function.Function<? super String, ? extends java.util.Map<String, {{evaluationCounterInnerClass}}>> parentAbsent = key -> {
return new java.util.HashMap<>();
};
private final java.util.function.Function<? super String, ? extends {{evaluationCounterInnerClass}}> entityAbsent = key -> {
return new {{evaluationCounterInnerClass}}();
};
public void incrementReceive(String parentTypeName, String entityName) {
getCounter(parentTypeName, entityName).receive += 1;
}
public void incrementSend(String parentTypeName, String entityName) {
getCounter(parentTypeName, entityName).send += 1;
}
public void incrementCall(String parentTypeName, String entityName) {
getCounter(parentTypeName, entityName).call += 1;
}
public void incrementFirstNull(String parentTypeName, String entityName) {
getCounter(parentTypeName, entityName).firstNull += 1;
}
public void incrementSkip(String parentTypeName, String entityName) {
getCounter(parentTypeName, entityName).skip += 1;
}
public void incrementException(String parentTypeName, String entityName) {
getCounter(parentTypeName, entityName).exception += 1;
}
public void incrementReject(String parentTypeName, String entityName) {
getCounter(parentTypeName, entityName).reject += 1;
}
public String summary() {
StringBuilder sb = new StringBuilder();
// header
sb.append("parentTypeName,entityName,receive,send,call,firstNull,skip,exception,reject").append("\n");
// values
java.util.Set<String> sortedParentTypes = new java.util.TreeSet<>(counters.keySet());
for (String parentType : sortedParentTypes) {
java.util.Set<String> sortedEntityNames = new java.util.TreeSet<>(counters.get(parentType).keySet());
for (String entityName : sortedEntityNames) {
{{evaluationCounterInnerClass}} count = getCounter(parentType, entityName);
java.util.StringJoiner sj = new java.util.StringJoiner(",", "", "\n");
sj.add(parentType)
.add(entityName)
.add(Integer.toString(count.receive))
.add(Integer.toString(count.send))
.add(Integer.toString(count.call))
.add(Integer.toString(count.firstNull))
.add(Integer.toString(count.skip))
.add(Integer.toString(count.exception))
.add(Integer.toString(count.reject))
;
sb.append(sj);
}
}
return sb.toString();
}
private {{evaluationCounterInnerClass}} getCounter(String parentTypeName, String entityName) {
return counters.computeIfAbsent(parentTypeName, parentAbsent).computeIfAbsent(entityName, entityAbsent);
}
public void reset() {
counters = new java.util.HashMap<>();
}
}
class {{evaluationCounterInnerClass}} {
int receive = 0;
int send = 0;
int call = 0;
int firstNull = 0;
int skip = 0;
int exception = 0;
int reject = 0;
}
{{/configEvaluationCounter}}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment