=Paper=
{{Paper
|id=Vol-3089/ttc20_paper_Boronat
|storemode=property
|title=EMF-Syncer solution to TTC’20 round-trip migration case
|pdfUrl=https://ceur-ws.org/Vol-3089/ttc20_paper2_Boronat.pdf
|volume=Vol-3089
|authors=Artur Boronat
|dblpUrl=https://dblp.org/rec/conf/ttc/Boronat21
}}
==EMF-Syncer solution to TTC’20 round-trip migration case==
EMF-Syncer solution to TTC’20 round-trip migration case
Artur Boronat1
1
School of Computing and Mathematical Sciences, University of Leicester, University Rd, LE1 7RH, Leicester, United Kingdom
Abstract
In this paper, we present a solution to the TTC’20 offline case Round-trip migration of object-oriented data model instances [1].
This case involves the application of maintenance tasks to web APIs that are associated with domain models so that updates
are backward compatible. The solution presented in this article features the EMF-Syncer [2], a synchronization tool for
bridging MDE-agnostic programs and MDE-aware programs, which may have some similarities in their object-oriented data
models at run time. EMF-Syncer provides a generic synchronization strategy that exploits such similarities automatically
and is, therefore, a suitable candidate for solving the proposed problems, since each problem relies on a small change and
there is a large overlap between two versions of the same data model. In the paper, we used the case benchmark framework
to justify that our solution exhibits a good balance between specification conciseness and performance.
Keywords
Model syncing, model-driven engineering, round-trip engineering
1. Introduction assumes that MDE-agnostic programs are implemented
in a JVM language and that MDE-aware programs repre-
The Round-trip migration of object-oriented data model sent their data model using EMF-generated code.
instances case [1] for the TTC’20 exposes an evolution Given a source data model (represented in a package
problem in the context of web API development, where of classes in the MDE-agnostic program), a target data
different APIs work on top of a common data model. To model (represented as an Ecore model in an EMF-based
accommodate new or changing requirements in the sys- program), and a collection of objects representing the
tem, API designers need to ensure backward-compatible source program state, EMF-Syncer translates the MDE-
changes in the underlying data model. Assuming an agile agnostic objects as an EMF model instance in the target
software development environment where data models EMF-based program, synchronizing the state of both pro-
may evolve rapidly, the case proposes the use of round- grams at run time. EMF-Syncer automatically infers
trip migration services, relying on Model-Driven Engi- structural similarities between object-oriented data mod-
neering (MDE) technology, for enabling the co-existence els by mapping object structural features by name, when
of different versions of the data model at run time. In found, translating both attribute and reference values.
particular, the Eclipse Modeling Framework (EMF) [3] is This translation can be performed using a push-based
used to encode data models with the EMF meta-modeling model, where the entire source program state is migrated,
language, namely Ecore, so that tools built atop EMF can or using a pull-based model, where only those feature
be used to implement data migration services. values accessed in the target program are migrated. Once
The solution presented in this article features the EMF- synchronization is established, changes that have been
Syncer [2], a synchronization tool for bridging MDE- applied to target EMF model instances can be incremen-
agnostic programs and MDE-aware programs, which tally back-propagated to the source MDE-agnostic coun-
may have some similarities in their object-oriented data terpart. Incrementality of back-migration entails that
models1 , at run time. EMF-Syncer provides a generic only changes in target model instances are propagated
synchronization strategy that exploits such similarities back and merged within the source instance.
automatically and is, therefore, a suitable candidate for The aforementioned generic mapping strategy that is
solving the proposed problems, since each problem relies built in EMF-Syncer can be customized in order to allow
on a small change and there is a large overlap between for more complex data transformations between the data
two versions of the same data model. The EMF-Syncer models involved. A domain-specific mapping strategy is
TTC’20: Transformation Tool Contest, Part of the Software declared with a mapping specification that maps a source
Technologies: Applications and Foundations (STAF) federated feature type to a target feature type, possibly including
conferences, Eds. A. Boronat, A. García-Domínguez, G. Hinkel, and F. feature value transformations, either from source to tar-
Křikava, 17 July 2020, Bergen, Norway (online). get, or from target to source, or both. Two main custom
" artur.boronat@leicester.ac.uk (A. Boronat)
mapping strategies can be declared:
~ https://arturboronat.github.io/ (A. Boronat)
0000-0003-2024-1736 (A. Boronat) • Renaming of feature types: such renamings may
© 2021 Copyright for this paper by its authors. Use permitted under Creative
CEUR
Workshop
http://ceur-ws.org
ISSN 1613-0073
Commons License Attribution 4.0 International (CC BY 4.0).
CEUR Workshop Proceedings (CEUR-WS.org) affect the name of the class, where the feature
is declared, and the name of the feature. This
Proceedings
1
We refer to these data models as domain models in [2].
mapping strategy allows for transformations that constructor. All of the solutions use the push-based
modify the data model either syntactically, when model in syncForward, which is specified by indicating
either a class or a feature is renamed in the tar- syncer.syncingStrategy = SyncingStrategy.EAGER,
get model, or structurally, when a feature type is forcing the migration of the entire source instance.
moved to an unrelated object type. In this case, In the method migrate, the statement
feature values are transformed using the generic syncer.syncForward(person_v1) migrates
synchronization strategy. the source Person instance obtaining the target
• Transformation of feature values, with or without instance with the age feature, which is not initial-
renaming of feature types: feature value trans- ized until the statement person_v2.age = -1 is
formations are expressed using Xtend lambda ex- evaluated. In the method migrateBack, the state-
pressions defined for a contextual object type, ment syncer.syncBack(person_v2) migrates the
from the source data model, and result in a sin- instance back to the source Java program.
gle target feature value. This mapping strategy The method modify is used to implement changes to
allows for semantic transformations, where the target model instances that need to be propagated back.
feature value can be computed using navigation This logic is hardcoded in test cases in the benchmark
expressions from the contextual type. A feature framework. EMF-Syncer needs to track which changes
value transformation is applied in a single direc- are performed in the target model instance in order to
tion, either from source to target or from target enable incremental back migration. Therefore, this logic
to source. A programmer can opt to provide fea- has been moved from test cases to task classes.
ture value transformations in both directions (as 1 class Task_1_M1_M2_M1 extends AbstractTask {
in Task_2 in §2.2), only in one (as in Task_3 in 2
3
val Syncer syncer
§2.3), or none at all. The last case corresponds to 4 new (EPackage model1, EPackage model2) {
a simple renaming of feature types as explained 5
6
super(model1, model2);
syncer = new Syncer(#[’scenario1_v1’], model2)
above. 7 syncer.syncingStrategy = SyncingStrategy.EAGER
8 }
For the TTC 2020 case, we are relying on the obser- 9
10 override migrate(EObject instance) {
vation that an EMF-based program can be regarded as a 11 val person_v1 = instance as scenario1_v1.Person
plain Java program. Hence, the given Java program will 12 val person_v2 = syncer.syncForward(person_v1) as scenario1_v2
.Person
refer to the source data model and the EMF-based pro- 13 person_v2.age = -1
gram will refer to the target data model. In the following 14
15 }
return person_v2;
sections, we discuss the solution to the case in §2, and 16
the evaluation of the solution in §3 using the evaluation 17
18
override migrateBack(EObject instance) {
val person_v2 = instance as scenario1_v2.Person
criteria proposed in the case, wrapping up with some 19 return syncer.syncBack(person_v2) as scenario1_v1.Person
conclusions in §4. 20
21
}
22 override modify(EObject instance) { }
23 }
2. Solution
The solutions to the different tasks of the It is important to note that the bidirectional transfor-
case are explained below and are available at mation between both data models is completely inferred
https://github.com/emf-syncer/ttc20-roundtrip. The by the EMF-Syncer automatically in this task. In the
solution has been implemented using the language back migration, as the age feature does not exist in the
Xtend [4]. source program, it is not propagated.
The solution to the symmetric problem
Task1_M2_M1_M2 is achieved by inverting the di-
2.1. Task 1: create/delete field
rection in which the EMF-Syncer is applied to the data
In this task, a new feature age is added to the class models, as seen in the listing below. In this case, the data
Person in the modified data model 𝑀2 and when a model M2 is regarded as the Java program and the data
Person instance is migrated, its feature value is set to model M1 as the EMF program. In this case, the value
-1. When the instance is migrated back, this information of the age feature of a Person class is preserved on
is lost. the back migration because this feature does not exist
The solution Task1_M1_M2_M1, shown in the listing in M1 and, therefore, no changes can be applied to the
below, illustrates the pattern used in all of the solutions. feature age. In the following subsections, solutions to
The EMF-Syncer is used by instantiating the class symmetric problems are achieved by flipping, as for this
EMFSyncer between a source Java package name list task, the direction in which the EMF-Syncer is applied
#[’scenario1_v1’] and a target Ecore model in the and are not included in the paper.
1 class Task_1_M2_M1_M2 extends AbstractTask { 17 Integer.valueOf(Calendar.getInstance().get(Calendar.YEAR) -
2 val EMFSyncer syncer person_v2.ybirth) as Object
3 18 ]
4 new (EPackage model1, EPackage model2) { 19 )
5 super(model1, model2); 20
6 syncer = new Syncer(#[’scenario1_v2’], model1) 21 new (EPackage model1, EPackage model2) {
7 syncer.syncingStrategy = SyncingStrategy.EAGER 22 super(model1, model2);
8 } 23 syncer = new EMFSyncer(#[’scenario2_v1’], model2,
9 newArrayList(mapping))
10 override migrate(EObject instance) { 24 syncer.syncingStrategy = SyncingStrategy.EAGER
11 val person_v2 = instance as scenario1_v2.Person 25 }
12 return syncer.syncForward(person_v2) as scenario1_v1.Person 26
13 } 27 override migrate(EObject instance) {
14 28 val person_v1 = instance as Person
15 override migrateBack(EObject instance) { 29 return syncer.syncForward(person_v1) as scenario2_v2.Person
16 val person_v1 = instance as scenario1_v1.Person 30 }
17 return syncer.syncBack(person_v1) as scenario1_v2.Person 31
18 } 32 override migrateBack(EObject instance) {
19 33 val person_v2 = instance as scenario2_v2.Person
20 override modify(EObject instance) { } 34 return syncer.syncBack(person_v2) as Person
21 } 35 }
36
37 override modify(EObject instance) { }
38 }
2.2. Task 2: rename field
In this task, the feature age of the class Person is re-
2.3. Task 3: declare field
named to ybirth, and its semantics is changed by repre-
senting the age and the year of birth, respectively. This optional/mandatory
renaming involves domain-specific semantics that is not In this task, the multiplicity of a feature type is modified
present in the Ecore model, requiring a mapping spec- so that the feature is mandatory in one data model and
ification so that the EMF-Syncer can perform the data optional in the modified version. This task exposes a
transformation correctly. difference between a MDE-agnostic program, where it
A mapping specification consists of a collection of is not possible to know whether a feature is optional in
mappings between feature types by name, ’Person’, plain Java, and a MDE-aware one, where this informa-
’age’, /* <–> */ ’Person’, ’ybirth’, and by tion is encoded in the Ecore model. As the EMF-Syncer
adding optional feature value transformations as lambda treats the source program as a plain Java program, it disre-
expressions. For example, in the solution, the lambda gards the information contained in the Ecore model, and
expression the logic to transform null values in to empty Strings
1 val person_v1 = it as scenario2_v1.Person needs to be provided in a custom mapping. The ex-
2 Integer.valueOf(Calendar.getInstance().get(Calendar.YEAR) -
person_v1.age) as Object
pression person_v2.name ?: "" returns an empty
String when the name of the Person instance is null,
which is checked using the Elvis operator ?:. The rest
of the data transformation is fully inferred by the EMF-
gets a Person instance from the source data model and
Syncer .
returns the ybirth value. When the EMF-Syncer ap-
plies the transformation syncForward, the feature value 1 class Task_3_M1_M2_M1 extends AbstractTask {
2 val EMFSyncer syncer
for Person::ybirth will be obtained by applying this 3
expression. The rest of the solution follows the same 4 // custom mapping strategy: M1 <--> M2
5 val public static mapping = new EMFSyncerMapping(
structure as the solution explained in §2.1. 6 ’Person’, ’name’, /* <--> */ ’Person’, ’name’,
7 null,
1 class Task_2_M1_M2_M1 extends AbstractTask { 8 // target to source feature value transformation
2 val EMFSyncer syncer 9 [
3 10 val person_v2 = it as scenario3_v2.Person
4 // custom mapping strategy: M1 <--> M2 11 person_v2.name ?: ""
5 val public static mapping = new EMFSyncerMapping( 12 ]
6 ’Person’, ’age’, /* <--> */ ’Person’, ’ybirth’, 13 )
7 // source to target feature value transformation 14
8 [ 15 new (EPackage model1, EPackage model2) {
9 val person_v1 = it as scenario2_v1.Person 16 super(model1, model2);
10 Integer.valueOf(Calendar.getInstance().get(Calendar.YEAR) - 17 syncer = new EMFSyncer(#[’scenario3_v1’], model2,
person_v1.age) as Object 18 newArrayList(mapping))
11 ], 19 syncer.syncingStrategy = SyncingStrategy.EAGER
12 20 }
13 21
14 // target to source feature value transformation 22 override migrate(EObject instance) {
15 [ 23 val person_v1 = instance as scenario3_v1.Person
16 val person_v2 = it as scenario2_v2.Person 24 return syncer.syncForward(person_v1) as Person
25 } framework has been adapted in order to work with code
26
27 override migrateBack(EObject instance) {
generated from Ecore models via EMF, which is required
28 val person_v2 = instance as Person by EMF-Syncer . The main properties (namely, name,
29
30 }
syncer.syncBack(person_v2) as scenario3_v1.Person
nsPrefix and nsUri) of the EPackage in each Ecore
31 model were updated in order to generate disjoint names-
32
33
override modify(EObject instance) {
val person_v2 = instance as Person
paces. In test cases, loading resources for each Ecore
34 syncer.track[ person_v2.name = null ] model was modified in order to use the corresponding
35
36 }
return person_v2
generated factory for each model instance. Model in-
37 } stances, used as input/output data, were modified to re-
fer to the corresponding nsUri. In some cases, the test
case also performs a change in the target instance, as in
This solution also contains an example of how to track Task_3, that needs to be propagated back to the source
changes performed in the target instance, in the modify instance. Such modifications have been encoded in the
method, that need to be migrated back. This change is task itself, in the method modify, as the EMF-Syncer
encoded in the corresponding test case in the original needs to track those changes. Such changes refer to im-
test framework. plementation details and do not alter the correctness
properties checked2 by the test suite.
2.4. Task 4: multiple edits Solutions for all of the tasks have been implemented
and all of them pass the correctness check.
This task combines Task_1 and Task_2 with the aim
of analysing reuse mechanisms that can be employed.
3.2. Comprehensibility
The solution below reuses the transformation logic of
Task_1, as it is handled by the EMF-Syncer automati- Task solutions have been implemented using Xtend.
cally, and it reuses the mapping specification of Task_2, However, the EMF-Syncer can be used from Java pro-
which is defined as a static field. The rest of the solution is grams as well. Given that the transformation in most
as in §2.1, after renaming the corresponding namespaces. of the solutions is inferred automatically and that so-
1 class Task_4_M1_M2_M1 extends AbstractTask { lutions use generated code, instead of using the EMF
2 val EMFSyncer syncer reflection API for accessing/mutating values, we argue
3
4 new (EPackage model1, EPackage model2) { that solutions are likely to be more comprehensible than
5 super(model1, model2); the reference ones.
6 syncer = new EMFSyncer(#[’scenario4_v1’], model2,
7 newArrayList(Task_2_M1_M2_M1.mapping)) When custom mappings are required, e.g. in Task_2
8 syncer.syncingStrategy = SyncingStrategy.EAGER and in Task_4, these are defined by instantiating the
9 }
10 class EMFSyncerMapping, where feature value transfor-
11 override migrate(EObject instance) { mations are defined as Xtend lambda expressions. Such
12 val container_v1 = instance as scenario4_v1.Container
13 return syncer.syncForward(container_v1) as scenario4_v2. mapping expressions could have been defined similarly
Container in Java as well.
14 }
15
16 override migrateBack(EObject instance) {
17 val container_v2 = instance as scenario4_v2.Container 3.3. Bidirectionality
18 syncer.syncBack(container_v2) as scenario4_v1.Container
19 } In the solution for most of the tasks, the EMF-Syncer
20
21 override modify(EObject instance) { }
infers both transformations to be applied, syncForward
22 } and syncBack, automatically. In such cases, the pro-
grammer does not need to provide a transformation spec-
ification and a bidirectional data transformation is being
used internally so that Java instances can be migrated
to an EMF program, and back again, at run time. A cus-
3. Evaluation tom mapping specification containing only feature type
renamings is fully bidirectional. Feature value transfor-
In this section, we provide an evaluation of the solution
mation expressions are unidirectional though.
according to the evaluation criteria proposed in [1].
Therefore, the EMF-Syncer provides support for bidi-
rectional transformations by default for all of the solu-
3.1. Expressiveness tions and accommodates special cases with unidirectional
Two test cases are provided for checking the correct-
ness of each task. A test case provides the input for a 2
The test case task_3_M1_M2_M1_b had to be updated in or-
round-trip migration and the expected output. The test der to check that the name was migrated back correctly.
Expressiveness Comprehensibility Bidirectionality Re-usability
Task 1: "Create/Delete Field"
Task_1_M1_M2_M1 2 (2) 2 (2) 1 (1) n.a.
Task_1_M2_M1_M2 2 (2) 2 (2) 1 (1) n.a.
Task 2: "Create/Delete Field"
Task_2_M1_M2_M1 2 (2) 2 (2) 1 (1) n.a.
Task_2_M2_M1_M2 2 (2) 2 (2) 1 (1) n.a.
Task 3: "Create/Delete Field"
Task_3_M1_M2_M1 2 (2) 2 (2) 1 (1) n.a.
Task_3_M2_M1_M2 2 (2) 2 (2) 1 (1) n.a.
Task 4: "Create/Delete Field"
Task_4_M1_M2_M1 2 (2) 2 (2) 1 (1) 4 (4)
Task_4_M2_M1_M2 2 (2) 2 (2) 1 (1) 4 (4)
∑︀ ∑︀ ∑︀ ∑︀
: 16 (16) : 16 (16) : 8 (8) : 8 (8)
Table 1
Summary of evaluation results.
feature value transformations, which correspond to a 35000
fraction of the data migration to be performed. 30000
25000
20000
3.4. Re-usability
15000
Re-usability is internalized in the EMF-Syncer by infer- 10000
ring transformations automatically. That is, when a user 5000
does not need to provide a mapping specification, the 0
transformation logic in the EMF-Syncer is reused for
10000
90000
170000
250000
330000
410000
490000
570000
650000
730000
810000
890000
970000
1050000
1130000
1210000
1290000
1370000
1450000
1530000
1610000
1690000
1770000
1850000
1930000
any data model change. For example, reuse of the logic
transformation in Task_1 falls under this category. reference (ms) EMFSyncer (ms)
On the other hand, as EMF-Syncer is a JVM library, a
programmer can rely on reuse mechanisms provided by
the JVM language of choice. For example, reuse of the Figure 1: Performance results (ms.) along iterations
transformation logic in Task_2 falls under this category.
The mapping specification defined for Task_2 is reused
by calling a static field and by using a common interface 4. Conclusions
for the class Person, which has been implemented using
inheritance in Task_4. Following from the justification of the evaluation criteria
in the section above, the results are summarized in Ta-
3.5. Performance ble 1, where the score 𝑋 out of 𝑌 is expressed as 𝑋(𝑌 ).
Overall, this solution shows that the EMF-Syncer helps
We have run the performance tests both for the refer- in achieving a competitive trade-off between data migra-
ence solution and for the EMF-Syncer solution on a tion specification and performance. On the one hand, the
MacBookPro11,5 Core i7 2.5 GHz, with four cores and automatic inference of data transformations between dif-
16 GB of RAM. The runtime results (in ms.) obtained ferent object-oriented data models reduces the need for
are displayed in Fig. 1. The EMF-Syncer solution ex- specifying data transformations. When these have to be
hibits a linear growth with respect to the number of specified, a programmer can rely on their programming
iterations, as instructed in the case benchmark. However, skills, using a JVM programming language, for reusing
the EMF-Syncer solution is more efficient than the refer- transformation logic. On the other hand, EMF-Syncer
ence one thanks to its support for incremental migration can be used as an efficient data migration service at run
of changes. While the reference solution takes about 31 s. time. For example, the EMF-Syncer solution is faster
for 2 million iterations, the EMF-Syncer solution takes than the reference solution developed in raw Java. EMF-
about 9 s, with an improvement factor of 70%. The in- Syncer can be used for building more scalable solutions,
cremental propagation relies on a traceability model that involving very large models, by using the pull-based
caches relevant data at run time. An analysis of memory model for propagating changes in syncForward only
consumption is left for future work as it was not part of when they are required in the target program.
the case benchmark.
References
[1] L. Beurer-Kellner, J. von Pilgrim, T. Kehrer, Round-
Trip Migration of Object-Oriented Data Model In-
stances, in: Proceedings of the 13th Transformation
Tool Contest, a part of the Software Technologies:
Applications and Foundations (STAF 2018) federa-
tion of conferences, CEUR Workshop Proceedings,
CEUR-WS.org, 2020.
[2] A. Boronat, Code-first model-driven engineering:
On the agile adoption of mde tooling, in: Proceedings
of the 34th IEEE/ACM International Conference on
Automated Software Engineering (ASE 2019), San
Diego, CA, November 11-15, ACM, 2019.
[3] D. Steinberg, F. Budinsky, M. Paternostro, E. Merks,
EMF: Eclipse Modeling Framework 2.0, 2nd ed.,
Addison-Wesley Professional, 2009.
[4] T. E. Foundation, Xtend (official web page), 2018.
http://www.eclipse.org/xtend/.