-
Notifications
You must be signed in to change notification settings - Fork 1
2018_m2m
In this laboratory, model transformation will be presented, specially one of this type: event-driven transformation, through an example. This transformation will create (and then incrementally update while active) a relational database schema from any entity relation diagram.
First, we have to install some plug-ins, if these are not installed already.
Install EMF SDK 2.13 and Sirius 5.1 or newer. Help → Install New Software... → In the new window paste the link below to Work with, select those plug-ins which selected in the pictures and Finish
http://download.eclipse.org/releases/oxygen
Same steps with Viatra 1.7.
http://download.eclipse.org/viatra/updates/release/1.7.0
Clone this repository with and check out 1.0 tag.
From this repository we will use the projects below:
- hu.bme.mit.mdsd.erdiagram
- hu.bme.mit.mdsd.erdiagram.design
- hu.bme.mit.mdsd.m2m2c
- hu.bme.mit.mdsd.m2m2c.ui
- hu.bme.mit.mdsd.rdb
- hu.bme.mit.mdsd.rdb.design
- hu.bme.mit.mdsd.trace
After import there will be a lot of errors in the workspace, but the following steps will resolve them.
First of all, you have to generate the model code from each genmodel (they are located in the model folder in each project), which are in the following projects:
- hu.bme.mit.mdsd.erdiagram
- hu.bme.mit.mdsd.rdb
- hu.bme.mit.mdsd.trace
To generate model code, open a .genmodel file, right click on the root element, and click Generate All. Order is mater, trace model have to be the last one because it use the other two models.
After you’ve done that, clean all projects.
That’s it, you are all set now, the workspace should be errorless.
Model transformation can be done in many different ways, the most simple one is to write many for loops traversing the source model to create the target model. However, it is more maintainable to use graph transformation rules for such a task.
Note that we will mainly use Xtend.
Open ErdToRdbLiveTransformation.xtend file in hu.bme.mit.mdsd.m2m2c package of hu.bme.mit.mdsd.m2m2c project. Tip: use ctrl + shift + t shortcut.
At this point the transformation use only one rule. This is the entityRule_C. Note that C means create, D means delete and U means update.
private def createTransformation() {
// Initialize event-driven transformation
val fixedPriorityResolver = new InvertedDisappearancePriorityConflictResolver
fixedPriorityResolver.setPriority(entityRule_C.rule.ruleSpecification, 1)
transformation = EventDrivenTransformation.forEngine(engine).setConflictResolver(fixedPriorityResolver)
.addRule(entityRule_C.rule)
.setSchedulerFactory(Schedulers.getQueryEngineSchedulerFactory(engine)
).build
}
InvertedDisappearancePriorityConflictResolver add priority to the rule (smaller number first). After that it can be added to the transformation.
Let's see what looks inside this rule. Open AbstractRule.xtend, because EntityRule_C.xtend inherited from this. There is 3 Classes which must be mentioned.
-
IModelManipulations
- This interface provides to manipulate the models easily wrapped in command. -
EventDrivenTransformationRuleFactory
- helper class for creatingEventDrivenTransformationRule
s. -
RdbPackage
- provides EReferences, EClasses and EAttributes from RDB domain model.
We will use EMF-IncQuery from Java in the model transformation, thus it is important to understand how to use it beforehand.
For each query four Java classes are generated into the src-gen folder
-
[PatternName]QuerySpecification.java
- Represents a pattern, containing its name, parameters, body, annotations, etc. -
[PatternName]Match.java
- Represents a match of a pattern (parameters) on an instance model, containing references to the EObjects. -
[PatternName]Matcher.java
- Basically a query specification initialized on a concrete instance model. The match set can obtained from it. -
[PatternName]Processor.java
- Abstract class for defining an action on match. -
[FileName].java
- IncQuery also generates a class for every .eiq file containing the QuerySpecifications in a list.
Open EntityRule_C.xtend.
rule = createRule.name("EntityRule")
// left hand side - queries a single entity
.precondition(Entity_CMatcher.querySpecification)
.action(CRUDActivationStateEnum.CREATED) [
println('''EntityRule CREATED («entity.name»)''')
// create table
val table = traceRoot.rdbRoot.createChild(rdbPackage.relationalDataBase_Tables, rdbPackage.table) as Table
table.set(rdbPackage.namedElement_Name, entity.name)
val key = table.createChild(rdbPackage.table_Columns, rdbPackage.key) as Key
key.set(rdbPackage.namedElement_Name, entity.name + "_ID")
createTrace(traceRoot, entity, table)
].build
.precondition(Entity_CMatcher.querySpecification)
line set precondition
of the rule to query specification of matcher of Entity_C pattern and the next line
set action which trigger the rule. This is Created action which means if an pattern
like Entity_C pattern appears, then this rule will be triggered. In this course we
will use Deleted and Updated too. Deleted means the rule will be triggered
if an pattern like in the precondition disappears. Updated means the rule will be
triggered if an pattern like in the precondition changes.
Important note: Every rule must have an Created action (it cloud be empty inside) rule to Updated or Deleted action can happen.
Let see Entity_C pattern, ctrl + click in Entity_CMatcher. It contains a Negative Application Condition (NAC), with 3. parameter is Entity, let see that.
traceOfElement pattern looks like this:
Entity_C rule will match all entities which do not match in traceOfElement.
So now we know EntityRule_C will trigger if Entity appear which is not traced with an RDB element. It could be happen 2 cases:
- A new Entity created.
- An already exists Entity not traced any more.
Go back to EntityRule_C and see the action. It creates an table in rdbRoot with IModelManipulations extension (createChild), sets its name, creates a key in table and sets the key's name too, at the end its. At the end it calls createTrace method.
Try out what we have now. Start an runtime-eclipse with this plug-ins. Import hu.bme.mit.mdsd.erdiagram.examplediagrams project from the repository. May the project is not a modeling project, so convert to it, right click on the project → Configure → Convert to Modeling Project. Unfold My.erdiagram and ER diagram inside it and open new EntityRelationDiagram.
Right click on ER diagram → Prepare to EDT. This command creates an rdb model and an trace model with just one-one root elements in those. (F5 may be needed)
Create an representation to the RDB element inside the rdb model. Open both representations at the same type. And finally start the EDT, right click on the ER diagram → Start EDT.
After arrange the results should look like this:
Note: If you create an Entity it will appear as Table in the rdb model with empty name, because when the entity created it does not have name. But if you delete the table it will regenerated with right name.
Create an xtend file in hu.bme.mit.mdsd.m2m2c.rules package, named it to EntityRule_UD and copy the next snippet into it.
class EntityRule_UD extends AbstractRule{
new(ViatraQueryEngine engine, IModelManipulations manipulation, TraceRoot traceRoot) {
super(engine, manipulation, traceRoot)
rule = createRule.name("EntityRule")
// left hand side - queries a single entity
.precondition(Entity_UDMatcher.querySpecification)
.action(CRUDActivationStateEnum.CREATED) [
println('''EntityRule CREATED [empty RHS] («entity.name»)''')
].action(CRUDActivationStateEnum.UPDATED) [
println('''EntityRule UPDATED («entity.name»)''')
if(!entity.name.equals(table.name)){
table.set(rdbPackage.namedElement_Name, entity.name)
}
val key = table.columns.filter(Key).head
if(!key.name.equals(entity.name + "_ID")){
key.set(rdbPackage.namedElement_Name, entity.name + "_ID")
}
].action(CRUDActivationStateEnum.DELETED)[
println('''EntityRule DELETED («entity.name»)''')
deleteTrace(trace)
].build
}
}
The snippet refers to Entity_UDMatcher so create Entity_UD pattern in traceQueries.vql file.
pattern entity_UD(entity : Entity, trace: Trace, table: Table){
find traceOfElement(_, trace, entity, table);
}
Go to ErdToRdbLiveTransformation and add entityRule_UD to the transformation as like entityRule_C:
- Add to fields the entityRule_C
- Initialize entityRule_C
- Set priority of the rule to 1
- Add the rule to the transformation
- Xtend language elements (including templating) - https://eclipse.org/xtend/documentation/203_xtend_expressions.html
- IncQuery (VIATRA Query) API usage - https://wiki.eclipse.org/VIATRA/Query/UserDocumentation/API
- VIATRA-MT API
- https://wiki.eclipse.org/VIATRA/Transformation/Transformation_API
- http://static.incquerylabs.com/projects/viatra/viatra-docs/ViatraDocs.html#_batch_transformations
- There is a m2m2c-end branch to get the final code: https://github.com/FTSRG/mdsd-examples
- 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)