<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <title-group>
        <article-title>Solving the TTC Families to Persons Case with FunnyQT</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Tassilo Horn tsdh@gnu.org</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>The GNU Project</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>Tassilo Horn. A Functional, Comprehensive and Extensible Multi-Platform Querying and Transformation Approach. PhD thesis, University Koblenz-Landau, Germany</institution>
          ,
          <addr-line>2016</addr-line>
        </aff>
      </contrib-group>
      <pub-date>
        <year>2008</year>
      </pub-date>
      <abstract>
        <p>This paper describes the FunnyQT solution to the bidirectional Families to Persons transformation case of TTC 2017. The solution is simple and concise and passes all batch transformations and some incremental tests. Solution Description This section explains the FunnyQT solution. First, Section 2.1 explains the actual transformation solving the case. Then, Section 2.2 explains how the solution is integrated into the benchmarx framework.</p>
      </abstract>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>-</title>
      <p>Introduction
This paper describes the FunnyQT1 [Hor16, Hor15] solution of the Families to Persons case [ABW17] of TTC
2017. With only 52 lines of declarative code, the solution is able to pass all batch transformation tests and
some incremental tests. The solution project is available on Github2 and it is integrated into the benchmarx 3
framework.</p>
      <p>FunnyQT is a model querying and transformation library for the functional Lisp dialect Clojure4. Queries
and transformations are Clojure functions using the features provided by the FunnyQT API.</p>
      <p>Clojure provides strong metaprogramming capabilities that are used by FunnyQT in order to define several
embedded domain-specific languages (embedded DSL [Fow10]) for different querying and transformation tasks.</p>
      <p>FunnyQT is designed to be extensible. By default, it supports EMF [SBPM08] and JGraLab5 TGraph models.
Support for other modeling frameworks can be added without having to touch FunnyQT’s internals.</p>
      <p>The FunnyQT API is structured into several namespaces, each namespace providing constructs supporting
concrete querying and transformation use-cases, e.g., model management, functional querying, polymorphic
functions, relational querying, pattern matching, in-place transformations, out-place transformations, bidirectional
transformations, and some more. For solving the Families to Persons case, its bidirectional transformation and
relational model querying DSLs have been used.
2.1</p>
      <p>As a first step, relational querying APIs for the two metamodels are generated.</p>
      <p>This makes the relations for the families metamodel available with the namespace alias f and those of the
persons metamodel with alias p. Relations are generated for every metamodel element. For example, there is a
Copyright c by the paper’s authors. Copying permitted for private and academic purposes.</p>
      <p>In: A. Garcia-Dominguez, G. Hinkel and F. Krikava (eds.): Proceedings of the 10th Transformation Tool Contest, Marburg, Germany,
21-07-2017, published at http://ceur-ws.org
relation (f/Family f family) which succeeds for every family in the given family model f. There is a relation
(f/name f el n) which succeeds if el is a member or family of the family model f whose name is n. And there
are reference relations like (f/-&gt;sons f parent child) which succeed if child is a son of parent.</p>
      <p>Before the transformation itself, we define a helper relation which defines the possible kinds of relationships
between a family and a family member depending on if we prefer to create parents over creating children (parameter
pref-parent). This is a higher-order relation in that the two remaining parameters are a parent relation prel
(either f/-&gt;father or f/-&gt;mother) and a child relation (either f/-&gt;daughters or f/-&gt;sons).
3 (defn relationshipo [pref-parent f family member prel crel]
4 (ccl/conda
5 [(bx/target-directiono :right) ;; (1)
6 (ccl/conde
7 [(prel f family member)]
8 [(crel f family member)])]
9 [(bx/existing-elemento? member)] ;; (2)
10 [(ccl/== pref-parent false) ;; (3)
11 (crel f family member)]
12 [(bx/unseto? f family prel member) ;; (4)
13 (prel f family member)]
14 [(crel f family member)])) ;; (5)</p>
      <p>ccl/conda is like a short-cutting logical disjunction. The n-th clause is only tried if all preceeding clauses fail.
The first clause succeeds when we are transforming into the direction of the right model, i.e., the person register.
In this case, member may be in a parental role of family (prel), or it might be in a child role (crel). We don’t
really care but want to ensure that all members of the given family are reachable, thus we use a non-short-cutting
ccl/conde which gives both clauses a chance to succeed.</p>
      <p>All other clauses deal with transforming a person model to a family model, i.e., the backward transformation.
The second clause deals with the case where member is an already existing element, i.e., not created by the current
execution of the transformation. Here, we assume that this member is already properly assigned to a family, so
we simply succeed without doing anything.</p>
      <p>In the third clause, if we do not prefer assigning to parental roles, then the child relation crel must succeed
between the family and the member. The child relations can always succeed because a family can have an arbitrary
number of daughters and sons. Thus, in the remaining clauses we have to deal only with the case where assigning
to parental roles is preferred.</p>
      <p>In the fourth clause, if the family’s parental role is still unset or already assigned to member, then the parental
relation must succeed between the family and the member.</p>
      <p>Lastly, if no clause has succeeded until now, then the child relation has to succeed. As said, this goal6 can
always succeed.</p>
      <p>In the following, the actual transformation definition is explained. It is defined using the deftransformation
macro provided by FunnyQT.
15 (bx/deftransformation families2persons [f p prefer-parent prefer-ex-family]
16 :delete-unmatched-target-elements true
17 :id-init-fn bx/number-all-source-model-elements</p>
      <p>The name of the transformation is families2persons and it declares four parameters. The parameter f is
the family model (the left model), p is the persons model (the right model), prefer-parent is a Boolean flag
determining if we prefer creating parents to creating children, and prefer-ex-family is a Boolean flag, too,
determining if we prefer re-using existing families over creating new families for new family members.</p>
      <p>By default, bidirectional FunnyQT transformations will never delete elements from the current target model,
i.e., the model being created or modified by the synchronization. The reason for that behavior is that it allows to
run the transformation in one direction first and then in the other direction in order to perform a full
synchronization where missing elements are created in each of the two models. Thus, after running a transformation, e.g., in
the direction of the right model, it is only ensured that for each element (considered by the transformation’s rules)
in the left model, there is a corresponding counterpart in the right model. However, the right model might still
contain elements which have no counterpart in the left model. With option :delete-unmatched-target-elements
set to true, this behavior is changed. Elements in the current target model which are not required by the current
source model and the transformation relations are deleted.</p>
      <p>6The application of a relation is called a goal.</p>
      <p>The next option, :id-init-fn, has the following purpose. In this transformation case, family members and
persons do not have some kind of unique identity. For example, it is allowed to have two members named Jim with
the same name in the very same family Smith. However, FunnyQT BX transformations have forall-there-exists
semantics where it would suffice to create just one person in the right model with the name set to “Smith, Jim”.
But the case description mandates that we create one person for every member and vice versa, no matter if they
can be distinguished based on their attribute values. For such scenarios, FunnyQT’s bidirectional transformation
DSL provides a concept of synthetic ID attributes. The value of :id-init-fn has to be a function which returns
a map from elements to their synthetic IDs. The built-in function bx/number-all-source-model-elements returns
a map where every element in the source model gets assigned a unique integer number. These synthetic IDs are
then used in a transformation relation which is discussed further below.</p>
      <p>The first transformation relation, family-register2person-register, transforms between family and person
registers.</p>
      <p>(^:top family-register2person-register
:left [(f/FamilyRegister f ?family-register)]
:right [(p/PersonRegister p ?person-register)]
:where [(member2female :?family-register ?family-register :?person-register ?person-register)
(member2male :?family-register ?family-register :?person-register ?person-register)])</p>
      <p>It is defined as a top-level rule meaning that it will be executed as the entry point of the transformation. Its
:left and :right clauses describe that for every ?family-register there has to be a ?person-register and vice
versa. We assume that there is always just one register in each model.</p>
      <p>The :where clause defines that after this relation has been enforced (or checked in checkonly mode), then the
two transformation relations member2female and member2male have to be enforced (or tested) between the current
?family-register and ?person-register7.</p>
      <p>The next transformation relation, member2person, describes how family members of a family contained in a
family register in the left model correspond to persons contained in a person register in the right model. As it can
be seen, there is no goal describing how the ?family and the ?member are connected in the :left clause and in the
:right clause we are dealing with just a ?person of type Person which is an abstract class. As such, this relation
is not sufficient for the complete synchronization between members in the different roles of a family to females
and males. Instead, it only captures the aspects that are common in the cases where mothers and daughters are
synchronized with females and fathers and sons are synchronized with males. Therefore, this relation is declared
abstract.</p>
      <p>(^:abstract member2person
:left [(f/-&gt;families f ?family-register ?family)
(f/Family f ?family)
(f/name f ?family ?last-name)
(f/FamilyMember f ?member)
(f/name f ?member ?first-name)
(id ?member ?id)
(ccl/conda
[(ccl/== prefer-ex-family true)]
[(bx/existing-elemento? ?member)
(id ?family ?last-name)]
[(id ?family ?id)])]
:right [(p/-&gt;persons p ?person-register ?person)
(p/Person p ?person)
(p/name p ?person ?full-name)
(id ?person ?id)]
:when [(rel/stro ?last-name ", " ?first-name ?full-name)])</p>
      <p>So what are these common aspects? Well, a ?member of a ?family (where we have not determined the role, yet)
contained in the ?family-register passed in as parameter from family-register2person-register corresponds
to a ?person (where we have not determined the gender, yet) contained in the ?person-register passed in as the
other parameter from family-register2person-register. The :when clause defines that the concatenation of the
?family’s ?last-name, the string ", " and the ?member’s ?first-name gives the ?full-name of the ?person.</p>
      <p>What has not been described so far are the id goals in lines 29, and 34 and the ccl/conda goal starting in
line 30. The first two define that the ?member and the corresponding ?person must have the same synthetic ID.
Remember the :id-init-fn in line 17 which assigned a unique number to every element in the respective source
7Transformation relations are called with keyword parameters. The two calls in the :where clause state that the current
?family-register will be bound to the logic variable with the same name in the called relation and the same is true for the
?person-register.
model of the transformation. With these synthetic IDs, the transformation is able to create one person for every
member and vice versa even in the case where two elements are equal based on their attribute values.</p>
      <p>Lastly, the ccl/conda goal starting in line 30 of the :left clause handles the preference of re-using existing
families, i.e., assigning new members to existing families, over creating new families for new members. By default,
FunnyQT would always try to re-use an existing family. Thus, if the prefer-ex-family parameter is true, nothing
needs to be done. Likewise, if ?member is an existing element for which we assume she is already assigned to some
family, we can also just stick to the default behavior but define the ID of the ?family to be its name (although
it is probably not unique). If the first two ccl/conda clauses fail, i.e., prefer-ex-family is false and ?member is
a new member which is just going to be created by the enforcement of this relation, then we define that the ID
of the ?family must equal to the IDs of the ?member and ?person. Thus, in this case and only in this case, new
members force the creation of a new family even when there is already a family with the right name.</p>
      <p>The last two transformation relations extend the member2person relation for synchronizing between members
in the role of a family mother or daughter and female persons and between family fathers or sons and male
persons.
(member2female
:extends [(member2person)]
:left [(relationshipo prefer-parent f ?family ?member f/-&gt;mother f/-&gt;daughters)]
:right [(p/Female p ?person)])
(member2male
:extends [(member2person)]
:left [(relationshipo prefer-parent f ?family ?member f/-&gt;father f/-&gt;sons)]
:right [(p/Male p ?person)]))</p>
      <p>In the :left clauses we use the relationshipo helper relation described in the beginning of this section which
chooses the right female or male role based on the preference parameter prefer-parent and the current state of
the family, i.e., by checking if the respective parental role is still unset. In the two :right clauses, we only need
to specify that the Person ?person is actually a Female or Male.</p>
      <p>These 33 lines of transformation specification plus the 12 lines for the relationshipo helper, and two lines
for the generation of the metamodel-specific relational querying APIs form the complete functional parts of the
solution. The only thing omitted from the paper are the namespace declarations8 consisting of 5 lines of code.
2.2</p>
      <p>Gluing the Solution with the Framework
Typically, open-source Clojure libraries and programs are distributed as JAR files that contain the source files
rather than byte-compiled class files. This solution does almost the same except that the JAR contains the
solution source code, FunnyQT itself (also as sources) and every dependency of FunnyQT (like Clojure) except
for EMF which the benchmarx project already provides.</p>
      <p>Calling Clojure functions from Java is really easy and FunnyQT transformations are no exception because they
are plain Clojure functions, too. The BXTool implementation FunnyQTFamiliesToPerson extends the BXToolForEMF
class. Essentially, it has just a static member T which is set to the transformation.
public class FunnyQTFamiliesToPerson extends BXToolForEMF&lt;FamilyRegister, PersonRegister, Decisions&gt; {
private final static Keyword LEFT = (Keyword) Clojure.read(":left");
private final static Keyword RIGHT = (Keyword) Clojure.read(":right");
private final static IFn T; // &lt;-- The FunnyQT Transformation
static {
final String transformationNamespace = "ttc17-families2persons-bx.core";
// Clojure’s require is similar to Java’s import. However, it also loads the required
// namespace from a source code file and immediately compiles it.
final IFn require = Clojure.var("clojure.core", "require");
require.invoke(Clojure.read(transformationNamespace));</p>
      <p>T = Clojure.var(transformationNamespace, "families2persons");</p>
      <p>All Clojure functions implement the IFn interface and can be called using invoke(). And exactly this is done
to call the transformation.</p>
      <p>private void transform(Keyword direction) {</p>
      <p>T.invoke(srcModel, trgModel, direction,
configurator.decide(Decisions.PREFER_CREATING_PARENT_TO_CHILD),
configurator.decide(Decisions.PREFER_EXISTING_FAMILY_TO_NEW));
}
}
This corresponds to a direct Clojure call (families2persons src trg dir prefer-parent prefer-ex-family).
8The Clojure equivalent of Java’s package statement and imports.
In this section, the test results of the FunnyQT solution are presented and classified as requested by the case
description [ABW17]. Since the bidirectional transformation DSL of FunnyQT is state-based and not incremental
at all (and by design), many of the incremental tests are mostly out of scope. However, in its core use case,
non-incremental bidirectional transformations, the solution passes all tests.</p>
      <p>BatchForward.* All tests result in an expected pass.</p>
      <p>BatchBwdEandP.* All tests result in an expected pass.</p>
      <p>BatchBwdEnotP.* All tests result in an expected pass.</p>
      <p>BatchBwdNotEandP.* All tests result in an expected pass.</p>
      <p>BatchBwdNotEnotP.* All tests result in an expected pass.</p>
      <p>IncrementalForward.* The solution expectedly passes the tests testStability, testHippocraticness, and
testIncrementalInserts. All remaining tests fail expectedly because those tests require incremental
abilities. For example, in some tests the birthdates are set manually in the persons model. The re-execution of
the transformation causes deletion and re-creation of those persons, however then they get assigned default
birthdates and not the manually edited ones as the transformation does not consider this attribute at all.
IncrementalBackward.* The solution expectedly passes the tests testStability,
testIncrementalInsertsFixedConfig, testIncrementalOperational, and testHippocraticness. The test
testIncrementalInsertsDynamicConfig fails unexpectedly. When we neither prefer existing families nor
assigning to parental roles, the transformation still adds the new Seymore to an existing family in a parental
role. All other tests are expected fails due to the fact that they require incremental capabilities.</p>
      <p>In summary, the correctness is satisfying. There is only one test which fails unexpectedly. All other fails are
expected and can hardly be solved by a non-incremental approach.</p>
      <p>A very weak point of the solution is its performance. It is at least an order of magnitude slower than the
other solutions already integrated in the benchmarx project (BiGUL, eMoflon, BXtend, MediniQVT). Where
their runtimes are in the tenth of seconds or below, the FunnyQT solution takes seconds. With models in the
size of thousands of elements, you might have to wait a bit for the transformation to finish. One reason is that
the FunnyQT BX implementation is state-based and thus needs to recompute the correspondences between all
elements in the source and target models on every invocation instead of just propagating small deltas like
incremental approaches do. Furthermore, FunnyQT’s bidirectional transformation DSL is built upon the relational
programming library core.logic9 which is not tuned for performance but for simplicity and extensibility of its
implementation and FunnyQT probably does not use it in the best possible way.</p>
      <p>Other good points of the solution are its conciseness and simplicity. With only 52 lines of code, it is by far
the most concise solution currently integrated in the benchmarx project. And it is quite simple to understand.
The only complexities it has arose from the different alternatives depending on external parameters.
[Fow10]
[Hor15]
[Hor16]</p>
      <p>Martin Fowler. Domain-Specific Languages. Addison-Wesley Professional, 2010.</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          <string-name>
            <given-names>Tassilo</given-names>
            <surname>Horn</surname>
          </string-name>
          .
          <article-title>Graph Pattern Matching as an Embedded Clojure DSL</article-title>
          .
          <source>In International Conference on Graph Transformation - 8th International Conference, ICGT</source>
          <year>2015</year>
          , L'Aquila, Italy,
          <year>July 2015</year>
          ,
          <year>2015</year>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>