Mod-it library provides an API to ease creations of EMF Models in XTend.
Using for tests
EMod-it instance frees developers of tedious EMF factory syntax making model description close to JSon file.
It also suppresses the constraint of sequencing code by providing a registry and resolving references during an assembling phase.
It is provided with reverse engine EReversIt which generates Xtend classes from existing models.
Using such syntax helps to:
-
Speed up the creation of tests
-
Improve the readability of the tests
-
Improve maintainability when the tested metamodel changes
-
Ease the creation of inter-connected models
It has been created and used in industrial project to ease the creation input for JUnit tests on the metamodel and business rules.
Using as integrated DSL.
Going further is it possible to reference dynamic model from EMF api.
For example, Eclipse Sirius or E4 descriptors can be generated and loaded at runtime avoiding static XML.
Moreover, Sirius expressions can be replaced by Xtend lambda avoiding AQL syntax or declaration of Java static classes.
Installation
Install the feature Mod-it Feature (…) from the following update site:
Origin of the project
Usage
How to start
Create a Mod-it factory
extension factory = EModIt.using(YourPackage.eINSTANCE)
Keyword extension provides new fonctions to Class of EObject
Examples
All the examples use the following metamodel: 
How to create an element
// Single element creation
val pool = A.create [
name = "AName"
].assemble
How to add children
val model = A.create [
name = "AName";
// Single valued containment feature
childNodeA = Node.create [
name = "SingleChildName"
]
// Adds one child
childrenNodeA += Node.create [
name = "ANodeName0"
]
// Adds several children at once
childrenNodeA += #[
Node.create [
name = "ANodeName1"
],
Node.create [
name = "ANodeName2"
]
]
].assemble
How to reference between elements
val model = B.create [
name = "AName"
// Adds one child with reference
childrenNodeA += Node.createAs("id0") [
name = "ANodeName0"
]
// Adds several children at once with references
childrenNodeA += #[
Node.createAs("id1") [
name = "ANodeName1"
],
Node.createAs("id2") [
name = "ANodeName2"
]
]
// Adds several children at once with references
childrenNodeB += #[
Node.createAs("id3") [
name = "ANodeName3"
],
Node.createAs("id4") [
name = "ANodeName4"
]
]
].assemble
// Accessing node
assertEquals("ANodeName0", model.access(Node, "id0").name)
assertEquals("ANodeName1", model.access(Node, "id1").name)
assertEquals("ANodeName2", model.access(Node, "id2").name)
assertEquals(2, model.root.childrenNodeB.size)
assertEquals("ANodeName3", model.access(Node, "id3").name)
assertEquals("ANodeName4", model.access(Node, "id4").name)
You can even register an id provider against the Factory description.
It will compute an id for each element (at create time) using your rules.
For example:
extension EModit factory = EModit.using(BoemTestPackage.eINSTANCE)[
idProvider = [
if (it instanceof NamedElement) name
null
]
]
//...
val model = B.create [
name = "AName"
// Adds one child with reference
childrenNodeA += Node.create [
name = "ANodeName0"
]
// Adds several children at once with references
childrenNodeA += #[
Node.create [
name = "ANodeName1"
],
Node.create [
name = "ANodeName2"
]
]
// Adds several children at once with references
childrenNodeB += #[
Node.create [
name = "ANodeName3"
],
Node.create [
name = "ANodeName4"
]
]
].assemble
// Accessing node
assertEquals("ANodeName0", model.access(Node, "ANodeName0").name)
assertEquals("ANodeName1", model.access(Node, "ANodeName1").name)
assertEquals("ANodeName2", model.access(Node, "ANodeName2").name)
assertEquals(2, model.root.childrenNodeB.size)
assertEquals("ANodeName3", model.access(Node, "ANodeName3").name)
assertEquals("ANodeName4", model.access(Node, "ANodeName4").name)
You can also use a shorter syntax to access your elements
val model = A.create [
name = "AName"
childrenNodeA += Node.createAs("id1") [
name = "ANode"
]
].assemble
val target = model.access(Node, "id1");
val target2 = ("id1" => model) as Node
assertTrue(target2 == target)
val target3 = model.access("id1")
assertTrue(target3 == target)
assertTrue(target == "id1" => model)
How to create references
val it = A.create [
name = "AName"
autoContainementA += B.createAs("id0") [
referenceNodeA = Node.createRef("id1")
]
childrenNodeA += Node.createAs("id1") [
name = "ANode"
]
].assemble
or with a shorter syntax
val it = A.create [
name = "AName"
autoContainementA += B.createAs("id0") [
referenceNodeA = Node.ref("id1")
]
childrenNodeA += Node.createAs("id1") [
name = "ANode"
]
].assemble
How to update an element
// In real code, declare pool as extension
val pool = A.create [
autoContainementA += B.createAs("B") [
autoContainementA += C.createAs("D")
]
].assemble
assertEquals(null, pool.root.name)
assertEquals(null, pool.access(NamedElement, "B").name)
assertEquals(null, pool.access(A, "C").name)
pool.update [
name = "NameA"
autoContainementA.get(0).with [
name = "NameB"
autoContainementA.get(0).with [
name = "NameD"
]
]
]
assertEquals("NameA", pool.root.name)
assertEquals("NameB", pool.access(B, "B").name)
assertEquals("NameC", pool.access(C, "C").name)
pool.access(B, "B").name = "NameB2"
pool.access(C, "C").name = "NameB2"
assertEquals("NameB2", pool.access(B, "B").name)
assertEquals("NameC2", pool.access(C, "C").name)