Skip to content

Commit 6b04998

Browse files
authored
Merge pull request #47 from LIonWeb-org/issue46-mm
Introducing M3 changes for recent changes
2 parents 0c12c05 + 24e7b23 commit 6b04998

File tree

11 files changed

+173
-37
lines changed

11 files changed

+173
-37
lines changed

core/src/main/java/org/lionweb/lioncore/java/metamodel/Concept.java

+1
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,5 @@ public Concept getConcept() {
151151
return allFeatures().stream().filter(f -> f instanceof Link).map(f -> (Link)f)
152152
.filter(c -> Objects.equals(c.getSimpleName(), linkName)).findFirst().orElse(null);
153153
}
154+
154155
}

core/src/main/java/org/lionweb/lioncore/java/metamodel/Feature.java

+36-15
Original file line numberDiff line numberDiff line change
@@ -18,31 +18,33 @@
1818
* @see <a href="https://www.jetbrains.com/help/mps/structure.html#conceptmembers">MPS equivalent <i>Concept members</i> in documentation</a>
1919
* @see org.jetbrains.mps.openapi.language.SConceptFeature MPS equivalent <i>SConceptFeature</i> in SModel
2020
*/
21-
public abstract class Feature<T extends M3Node> extends M3Node<T> implements NamespacedEntity {
22-
@Experimental
23-
private boolean derived;
21+
public abstract class Feature<T extends M3Node> extends M3Node<T> implements NamespacedEntity, HasKey<T> {
2422

2523
public Feature() {
26-
24+
setDerived(false);
2725
}
2826

2927
public Feature(@Nullable String simpleName, @Nonnull String id) {
3028
this(simpleName, null, id);
29+
setDerived(false);
3130
}
3231

3332
public Feature(@Nullable String simpleName, @Nullable FeaturesContainer container, @Nonnull String id) {
33+
setDerived(false);
3434
Objects.requireNonNull(id, "id should not be null");
3535
this.setID(id);
3636
// TODO verify that the container is also a NamespaceProvider
3737
// TODO enforce uniqueness of the name within the FeauturesContainer
3838
setSimpleName(simpleName);
39-
setContainer(container);
39+
setParent(container);
4040
}
41+
4142
public Feature(@Nullable String simpleName, @Nullable FeaturesContainer container) {
43+
setDerived(false);
4244
// TODO verify that the container is also a NamespaceProvider
4345
// TODO enforce uniqueness of the name within the FeauturesContainer
4446
setSimpleName(simpleName);
45-
setContainer(container);
47+
setParent(container);
4648
}
4749

4850
public boolean isOptional() {
@@ -60,12 +62,12 @@ public T setOptional(boolean optional) {
6062

6163
@Experimental
6264
public boolean isDerived() {
63-
return derived;
65+
return getPropertyValue("derived", Boolean.class);
6466
}
6567

6668
@Experimental
6769
public T setDerived(boolean derived) {
68-
this.derived = derived;
70+
setPropertyValue("derived", derived);
6971
return (T)this;
7072
}
7173

@@ -78,17 +80,36 @@ public void setSimpleName(@Nullable String simpleName) {
7880
this.setPropertyValue("simpleName", simpleName);
7981
}
8082

83+
/**
84+
* The container is always the parent. It is just casted for convenience.
85+
*/
8186
@Override
8287
public @Nullable NamespaceProvider getContainer() {
83-
return getReferenceSingleValue("container");
84-
}
85-
86-
public void setContainer(@Nullable FeaturesContainer container) {
87-
if (container == null) {
88-
this.setReferenceSingleValue("container", null);
88+
if (this.getParent() == null) {
89+
return null;
90+
}
91+
if (this.getParent() instanceof NamespaceProvider) {
92+
return (NamespaceProvider) this.getParent();
8993
} else {
90-
this.setReferenceSingleValue("container", new ReferenceValue(container, container.getSimpleName()));
94+
throw new IllegalStateException("The parent is not a NamespaceProvider");
9195
}
9296
}
9397

98+
@Override
99+
public String getKey() {
100+
return this.getPropertyValue("key", String.class);
101+
}
102+
103+
@Override
104+
public T setKey(String key) {
105+
setPropertyValue("key", key);
106+
return (T) this;
107+
}
108+
109+
protected Object getDerivedValue(Property property) {
110+
if (property.getKey().equals(this.getConcept().getPropertyByName("qualifiedName").getKey())) {
111+
return qualifiedName();
112+
}
113+
return null;
114+
}
94115
}

core/src/main/java/org/lionweb/lioncore/java/metamodel/FeaturesContainer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public FeaturesContainer(@Nullable Metamodel metamodel, @Nullable String simpleN
6060
public T addFeature(@Nonnull Feature feature) {
6161
Objects.requireNonNull(feature, "feature should not be null");
6262
this.addContainmentMultipleValue("features", feature);
63-
feature.setContainer(this);
63+
feature.setParent(this);
6464
return (T)this;
6565
}
6666

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package org.lionweb.lioncore.java.metamodel;
2+
3+
public interface HasKey<T> {
4+
String getKey();
5+
T setKey(String value);
6+
}

core/src/main/java/org/lionweb/lioncore/java/metamodel/Metamodel.java

+27-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
* @see org.eclipse.emf.ecore.EPackage Ecore equivalent <i>EPackage</i>
2222
* @see <a href="https://www.jetbrains.com/help/mps/structure.html">MPS equivalent <i>Language's structure aspect</i> in documentation</a>
2323
*/
24-
public class Metamodel extends M3Node<Metamodel> implements NamespaceProvider {
24+
public class Metamodel extends M3Node<Metamodel> implements NamespaceProvider, HasKey<Metamodel> {
2525
public Metamodel() {
2626
}
2727

@@ -35,6 +35,17 @@ public Metamodel setName(String name) {
3535
return this;
3636
}
3737

38+
public Metamodel setVersion(@Nullable String version) {
39+
setPropertyValue("version", version);
40+
return this;
41+
}
42+
43+
@Override
44+
public Metamodel setKey(String key) {
45+
setPropertyValue("key", key);
46+
return this;
47+
}
48+
3849
@Override
3950
public String namespaceQualifier() {
4051
return getName();
@@ -57,7 +68,7 @@ public Metamodel addDependency(@Nonnull Metamodel dependency) {
5768
public <T extends MetamodelElement> T addElement(@Nonnull T element) {
5869
Objects.requireNonNull(element, "element should not be null");
5970
this.addContainmentMultipleValue("elements", element);
60-
element.setMetamodel(this);
71+
element.setParent(this);
6172
return element;
6273
}
6374

@@ -88,6 +99,16 @@ public String getName() {
8899
return this.getPropertyValue("name", String.class);
89100
}
90101

102+
@Override
103+
public String getKey() {
104+
return this.getPropertyValue("key", String.class);
105+
}
106+
107+
@Nullable
108+
public String getVersion() {
109+
return this.getPropertyValue("version", String.class);
110+
}
111+
91112
public @Nullable MetamodelElement getElementByName(String name) {
92113
return getElements().stream().filter(element -> element.getSimpleName().equals(name)).findFirst()
93114
.orElse(null);
@@ -110,4 +131,8 @@ public Concept getConcept() {
110131
return LionCore.getMetamodel();
111132
}
112133

134+
@Override
135+
public String toString() {
136+
return "Metamodel(" + this.getName()+")";
137+
}
113138
}

core/src/main/java/org/lionweb/lioncore/java/metamodel/MetamodelElement.java

+36-12
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* @see <a href="http://127.0.0.1:63320/node?ref=r%3A00000000-0000-4000-0000-011c89590292%28jetbrains.mps.lang.structure.structure%29%2F1588368162880706270">MPS equivalent <i>IStructureElement</i> in local MPS</a>
1717
* @see org.jetbrains.mps.openapi.language.SElement MPS equivalent <i>SElement</i> in SModel
1818
*/
19-
public abstract class MetamodelElement<T extends M3Node> extends M3Node<T> implements NamespacedEntity {
19+
public abstract class MetamodelElement<T extends M3Node> extends M3Node<T> implements NamespacedEntity, HasKey<T> {
2020

2121
public MetamodelElement() {
2222

@@ -29,22 +29,22 @@ public MetamodelElement(@Nullable Metamodel metamodel, @Nullable String simpleNa
2929

3030
public MetamodelElement(@Nullable Metamodel metamodel, @Nullable String simpleName) {
3131
// TODO enforce uniqueness of the name within the Metamodel
32-
this.setMetamodel(metamodel);
32+
this.setParent(metamodel);
3333
this.setSimpleName(simpleName);
3434
}
3535

36-
// TODO consider making this a derived feature just casting the parent
36+
/**
37+
* This method returns the Metamodel containing this element. It is the parent, casted to Metamodel.
38+
* @return
39+
*/
3740
public @Nullable Metamodel getMetamodel() {
38-
return this.getReferenceSingleValue("metamodel");
39-
}
40-
41-
public T setMetamodel(@Nullable Metamodel metamodel) {
42-
if (metamodel == null) {
43-
this.setReferenceSingleValue("metamodel", null);
41+
if (getParent() == null) {
42+
return null;
43+
} else if (getParent() instanceof Metamodel) {
44+
return (Metamodel) getParent();
4445
} else {
45-
this.setReferenceSingleValue("metamodel", new ReferenceValue(metamodel, metamodel.getName()));
46+
throw new IllegalStateException("The parent of this MetamodelElement is not a Metamodel");
4647
}
47-
return (T)this;
4848
}
4949

5050
@Override
@@ -59,7 +59,31 @@ public T setSimpleName(String simpleName) {
5959

6060
@Override
6161
public @Nullable NamespaceProvider getContainer() {
62-
return this.getMetamodel();
62+
if (this.getParent() == null) {
63+
return null;
64+
}
65+
if (this.getParent() instanceof NamespaceProvider) {
66+
return (NamespaceProvider) this.getParent();
67+
} else {
68+
throw new IllegalStateException("The parent is not a NamespaceProvider");
69+
}
70+
}
71+
72+
@Override
73+
public String getKey() {
74+
return this.getPropertyValue("key", String.class);
6375
}
6476

77+
@Override
78+
public T setKey(String key) {
79+
setPropertyValue("key", key);
80+
return (T) this;
81+
}
82+
83+
protected Object getDerivedValue(Property property) {
84+
if (property.getKey().equals(this.getConcept().getPropertyByName("qualifiedName").getKey())) {
85+
return qualifiedName();
86+
}
87+
return null;
88+
}
6589
}

core/src/main/java/org/lionweb/lioncore/java/model/Node.java

+13
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import javax.annotation.Nonnull;
77
import javax.annotation.Nullable;
8+
import java.util.ArrayList;
89
import java.util.List;
910

1011
/**
@@ -101,4 +102,16 @@ default Object getPropertyValueByID(String propertyID) {
101102
Property property = this.getConcept().getPropertyByID(propertyID);
102103
return getPropertyValue(property);
103104
}
105+
106+
/**
107+
* Return a list containing this node and all its descendants.
108+
*/
109+
default @Nonnull List<Node> thisAndAllDescendants() {
110+
List<Node> nodes = new ArrayList<>();
111+
nodes.add(this);
112+
for (Node child: this.getChildren()) {
113+
nodes.addAll(child.thisAndAllDescendants());
114+
}
115+
return nodes;
116+
}
104117
}

core/src/main/java/org/lionweb/lioncore/java/model/impl/DynamicNode.java

+19-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,13 @@ public void setPropertyValue(@Nonnull Property property, Object value) {
4545
if (!getConcept().allProperties().contains(property)) {
4646
throw new IllegalArgumentException("Property " + property + " is not belonging to concept " + getConcept());
4747
}
48-
propertyValues.put(property.getID(), value);
48+
if (value == null || value == Boolean.FALSE) {
49+
// We remove values corresponding to default values, so that comparisons of instances of DynamicNode can be
50+
// simplified
51+
propertyValues.remove(property.getID());
52+
} else {
53+
propertyValues.put(property.getID(), value);
54+
}
4955
}
5056

5157
@Override
@@ -228,5 +234,17 @@ public boolean equals(Object o) {
228234
public int hashCode() {
229235
return Objects.hash(id, parent, concept, propertyValues, containmentValues, referenceValues);
230236
}
237+
238+
@Override
239+
public String toString() {
240+
return "DynamicNode{" +
241+
"id='" + id + '\'' +
242+
", parent=" + parent +
243+
", concept=" + concept +
244+
", propertyValues=" + propertyValues +
245+
", containmentValues=" + containmentValues +
246+
", referenceValues=" + referenceValues +
247+
'}';
248+
}
231249
}
232250

core/src/main/java/org/lionweb/lioncore/java/model/impl/M3Node.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ public T setID(String id) {
3838
return (T)this;
3939
}
4040

41-
public void setParent(Node parent) {
41+
public T setParent(Node parent) {
4242
this.parent = parent;
43+
return (T)this;
4344
}
4445

4546
@Override
@@ -80,8 +81,20 @@ public void addAnnotation(AnnotationInstance instance) {
8081
annotationInstances.add(instance);
8182
}
8283

84+
/**
85+
* Nodes which have derived properties can specify the values of such properties by implementing this method and
86+
* returning something different from null.
87+
*/
88+
protected @Nonnull Object getDerivedValue(Property property) {
89+
return null;
90+
}
91+
8392
@Override
8493
public Object getPropertyValue(Property property) {
94+
Object derivedValue = getDerivedValue(property);
95+
if (derivedValue != null) {
96+
return derivedValue;
97+
}
8598
if (!getConcept().allProperties().contains(property)) {
8699
throw new IllegalArgumentException("Property not belonging to this concept: " + property);
87100
}

0 commit comments

Comments
 (0)