-
Notifications
You must be signed in to change notification settings - Fork 1
2014_incquery
-
Import the project from
start.zip
. -
Generate the model, the edit and the editor from the
genmodel
file in themodel
folder of thehu.bme.mit.mdsd.erdiagram
project. -
Run as Eclipse Application.
-
Import the
ERDiagramExample
to the runtime Eclipse and check the instance model. -
Create a new IncQuery project and name it to
hu.bme.mit.mdsd.erdiagram.queries
. -
Create a new query definition in a package named
hu.bme.mit.mdsd.erdiagram
and a file namedqueries.eiq
. In the wizard create an empty query. Fill the first query:package hu.bme.mit.mdsd.erdiagram import "hu.bme.mit.mdsd.erdiagram" pattern entityWithName(entity, name) { Entity.Name(entity,name); }
-
Load the query and the instance model to the Query Explorer.
-
Structure your source code to 4 blocks like this:
//------------------------------- // Support //------------------------------- //------------------------------- // Visualize //------------------------------- //------------------------------- // Validate //------------------------------- //------------------------------- // Derived //-------------------------------
Every pattern goes to one of those categories. The
entityWithName
goes to Support. -
Create a query to the Validate that checks if the name of a
NamedElement
is only an empty string:pattern emptyNamedElement(element: NamedElement) { NamedElement.Name(element, ""); }
-
Create a query to the Validate that checks if two entity has the same name:
pattern sameNamedEntities(entity1, entity2, commonName) { Entity.Name(entity1, commonName); Entity.Name(entity2, commonName); entity1!=entity2; }
-
Create a query to the Validate that checks if the name starts with a noncapital letter:
pattern entityStartsWithSmallCase(entity) { Entity.Name(entity,name); check ( !name.matches("^[A-Z].+") ); }
-
Create a query to the Derived that gets the other endign of a relation ending:
pattern other(ending:RelationEnding, other) { Relation.leftEnding(relation, ending); Relation.rightEnding(relation, other); } or { Relation.rightEnding(relation, ending); Relation.leftEnding(relation, other); }
-
Create a query to the Visualize that summarizes this three validation condition:
pattern badEntity(entity, name) { find sameNamedEntities(entity, _other, name); } or { Entity.Name(entity, name); find emptyNamedElement(entity); } or { Entity.Name(entity, name); find entityStartsWithSmallCase(entity); }
-
Create a query to the Visualize that matches to the well-named entities:
pattern goodEntity(entity, name) { Entity.Name(entity, name); neg find badEntity(entity,_); }
-
Create a query to the Visualize that gets the attributes:
pattern attribute(entity, attribute) { Entity.attributes(entity,attribute); }
-
Create a query to the Visualize that gets the attributes:
pattern attribute(entity, attribute) { Entity.attributes(entity,attribute); }
-
Create a query to the Visualize that gets relations:
pattern relation(entity1, entity2) { Relation.leftEnding.target(relation, entity1); Relation.rightEnding.target(relation,entity2); }
-
Create a query to the Visualize that matches on the attributes and check the properties:
pattern attributeWithName(attribute, name, type, key){ Attribute.Name(attribute,name); Attribute.type.Name(attribute,type); Attribute.isKey(attribute,true); key=="[k]"; } or { Attribute.Name(attribute,name); Attribute.type.Name(attribute,type); Attribute.isKey(attribute,false); key==""; }
-
Use the visualize block to create a view. Annote the patterns:
@Item(item = entity, label = "$name$") pattern goodEntity(entity, name) @Item(item = entity, label = "$name$") @Format(color = "#ff0000") pattern badEntity(entity, name) @Item(item = attribute, label = "$key$$name$: $type$") @Format(color = "#00ffff") pattern attributeWithName(attribute, name, type, key) @Edge(source = entity, target = attribute) pattern attribute(entity, attribute) @Edge(source = entity1, target = entity2) pattern relation(entity1, entity2)
-
Watch the result in the Viewers sandbox.
-
For the sake of simplicity switch off the Query Explorer for the previous patterns with the following annotation:
@QueryExplorer(display = false)
-
Create Support patterns for the inheritance:
//@QueryExplorer(display = false) pattern superEnitities(entity, superEntity) { Entity.isA(entity, superEntity); } //@QueryExplorer(display = false) pattern allSuperEntities(entity, superEntity) { find superEnitities+(entity, superEntity); }
-
Create a pattern that detects a circle in the type hierarchy:
pattern circleInTypeHierarchy(entity) { find allSuperEntities(entity, entity); }
-
Create a pattern that detects a (transitive) diamond in the type type hierarchy:
pattern diamondInTypeHierarchy(entity1, entity2, entity3, entity4) { find allSuperEntities(entity1,entity2); find allSuperEntities(entity1,entity3); entity2 != entity3; find allSuperEntities(entity2,entity4); find allSuperEntities(entity3,entity4); }
-
Every diamond has matched at least two times. This should be prevented if we make the pattern assimetric by defining somehow that
entity2 < entity3
. Let us define an ordering relation between the entities:pattern order(a, b) { Entity.Name(a, name1); Entity.Name(b, name2); check( name1.compareTo(name2) < 0 ); }
And change the diamond code:
pattern diamondInTypeHierarchy(entity1, entity2, entity3, entity4) { find allSuperEntities(entity1,entity2); find allSuperEntities(entity1,entity3); //entity2 != entity3; find order(entity2, entity3); find allSuperEntities(entity2,entity4); find allSuperEntities(entity3,entity4); }
-
By the way, calculate the infimum of the order:
pattern FirstInOrder(first: Entity) { neg find order(_, first); }
-
Extend the patterns to get the inherited relations and attributes too:
pattern attribute(entity, attribute) { Entity.attributes(entity,attribute); } or { find allSuperEntities(entity, superEntity); find attribute(superEntity, attribute); }
and
pattern relation(entity1, entity2) { Relation.leftEnding.target(relation, entity1); Relation.rightEnding.target(relation, entity2); } or { find allSuperEntities(entity1, superEntity); find relation(superEntity, entity2); }
-
Print out how many attributes a well-formed entity has:
@Item(item = entity, label = "$name$ ($attributes$)") pattern goodEntity(entity, name, attributes) { Entity.Name(entity, name); neg find badEntity(entity,_); attributes == count find attribute(entity,_); }
-
At first we need to import the query project to the host Eclipse. To do this copy the path of the project from the properties menu.
-
Close the project in the runtime Eclipse to avoid conflicts.
-
Go to the host Eclipse and import the query project.
-
Annotate some pattern with
@Constraint
, like:@Constraint(message = "The name is not unique!", location=entity1, severity = "error") pattern sameNamedEntities(entity1, entity2, commonName) @Constraint(message = "The name is empty!", location=element, severity = "error") pattern emptyNamedElement(element: NamedElement)
-
Start the runtime Eclipse, open the instance model and right click on the resource and choose EMF-IncQuery validation | Initialize EMF-IncQuery validators on Editor.
-
If you make a mistake an error will rise.
-
Create a new EReference named
otherEnding
in theRelationEnding
to itself. Set the following properties:- Changeable = false
- Derived = true
- Transient = true
- Volatile = false
-
Annote the pattern pattern
other
:@QueryBasedFeature pattern other(ending:RelationEnding, other)
-
Start the runtime Eclipse and try the feature in the instance model.
- Eclipse basics
- EMF (incl. advanced topics)
- VIATRA Query
- Sirius
- Xtext+Xtend
- M2M
- Eclipse basics
- EMF (incl. advanced topics)
- VIATRA Query
- Sirius
- Xtext
- M2M
(Gradually replaced with updated content)
- Eclipse basics
- EGit
- EMF (incl. advanced topics)
- VIATRA Query
- Sirius
- Xtext
- M2M (VIATRA)
- Eclipse basics
- EGit
- EMF (incl. advanced topics)
- VIATRA Query
- Sirius
- Xtext
- M2M (VIATRA)