• Keine Ergebnisse gefunden

4.5 Related Work and Discussion

5.1.1 State-Based Lenses & Focal

Asymmetric state-based lenses, the computational framework behind Focalis restricted to informational asymmetry, i.e., one of the two structures which are synchronized has to be an abstraction of the other. The setting is inspired by theview-update problem known in the database community, where a database view – the abstraction – has to be updated when the database changes and vice versa. Given a setCof concrete structures and a set Aof abstract structures, a lens comprises two functions:

get: C → A

put: A×C → C

The forward transformation get derives an abstract structure from a given concrete structure. The backward transformation put takes an updated abstract structure and the original concrete structure to yield an updated concrete structure. To allow initial creation of a concrete structure from an abstract one, sometimes an alternative non-incremental backward transformationcreate: A→Cis added, which uses default values for private parts of the concrete structure. It can be omitted if not needed in the given scenario, i.e., if a concrete structure is never created afresh from an abstract structure. A lens which supports the create case needs to be provided with adefault structure d∈C.

Fig. 5.1 visualizes the way the lens functions are used to derive an abstract view from a concrete source and how an updated source is constructed when the view changes.

5.1. Lenses: A Compositional Approach to Bidirectional Transformations 105

put get

create

A

A' C

C'

concrete source

abstract view

updated abstract

view updated

concrete source

lens

Figure 5.1: A lens synchronizes a concrete source and an abstract view (from Foster, 2009) Lenses specifywell-behaved bidirectional transformations, which means that every lens must obey the following lens laws (Foster et al., 2005):

get(put(a,c))=a (PutGet) get(create(a))=a (CreateGet)

put(get(c),c)=c (GetPut)

These laws formalize some behaviour one would generally expect from a bidirectional transformation: The updated (or initially created) concrete structure c fully reflects changes made in the abstract structure a (PutGet and CreateGet), and data in the concrete structure that is hidden by the abstraction is preserved (GetPut). In the community of bidirectional transformations, these laws are frequently subject of discus-sion. Some approaches add more laws or weaken some of those laws presented here.

General Lenses

The simplest lens is the id lens. It does not apply any actual synchronization logic, but only copies whatever it gets to the other side. Because the put function’s result is independent from the original concrete structure, which is simply discarded, id is a so-calledoblivious lens. The following listing shows the complete definition of theidlens; we use a post-colon notation for type annotation in lens definitions, similar to Scala or UML;

we omit (for now) type annotations of the lens functions’ parameters as they always refer to the abstract or concrete structure (but are sometimes subject to constraints):

id:lens {

get(c) =c put(a,c) =a create(a) =a }

106 Chapter 5. A Compositional Language for Bidirectional Model Transformation It is easy to show that with the idlens the lens laws hold. We only need to insert the definitions ofid’sput function andid’sget function into the PutGetlaw:

get(put(a,c))=a (PutGetlaw) get(a)=a (id.put inserted)

a=a (id.get inserted)

Now, the strength of lenses is their compositional notion: A set of atomic lenses – like id– whose well-behavedness has been manually proven, is provided together with a set of lens combinators for which it has been proven that the resulting composed lens is well-behaved if all of its sublenses are well-behaved. These lenses and combinators can then be used as a vocabulary for bidirectional transformations from which arbitrarily complex lenses can be composed without having to prove the lens laws again.

The most common combinator is the sequential composition comp which takes two lensesland k – its sublenses – as arguments and puts them in a sequence:

comp(l:lens,k:lens) :lens { get(c) =k.get(l.get(c))

put(a,c) =l.put(k.put(a,l.get(c)),c) create(a) =l.create(k.create(a)) }

The get function is straightforward: l’s get function is called and the result is used as input for k’s get function. The put direction is slightly more complicated: first, the original concrete input has to be abstracted by l’s get function to be a valid input for k’s put function. As can be seen, a combinator such as the sequential composition is a lens itself, differing from atomic lenses only because it is parameterized with sublenses.

A lens created from two lenses usingcomp, is a well-behaved lens – that is, the lens laws hold – as long as the two sublenses are well-behaved (Foster et al., 2007).

Focal: A Lens Library for Tree Transformations

Focal is a lens library based on state-based lenses, that provides a set of atomic lenses and lens combinators for tree transformations. Lenses provided by Focal work on edge-labeled trees where a tree t is defined as an unordered, potentially empty set of labels which refer to a tree (denoted by 7→). Fig. 5.2 shows an example of a contact list tree where names refer to a phone number and a URL, encoded as an edge-labeled tree in a horizontal notation.

Figure 5.2: An example of an edge-labeled tree

5.1. Lenses: A Compositional Approach to Bidirectional Transformations 107 As can be seen, all data is encoded as labels (i.e., strings), and leafs are encoded as labels that refer to an empty set of labels (denoted by {}). Now, additionally to general lenses like id and comp, which are also part of Focal, tree-specific lenses are provided.

An example of a lens which performs a simple structural tree modification ishoist. It is defined as follows:

hoist(n:label) :lens {

get(c) =t if c={n7→t} put(a,c) ={n7→a}

create(a) ={n7→a} }

Thehoistlens is parameterized with an edge-labeln. A concrete treec given tohoist’s get function must have exactly one root edge which must have the specified label n and leads to c’s single child tree t. This is the concrete-side constraint of the hoist lens.

Function get then yields this child tree t. Thus, hoist’s forward transformation removes c’s single root edge and thereby flattens the tree by one level. Correspondingly, the two backward transformationsput and create restore the specified root edge by adding it to the potentially modified abstract treea.

A tree-specific lens-combinator which is frequently used in Focal to compose more complex tree-specific lenses is fork. It splits the given tree by dividing the set of labels into two sets depending on whether a label satisfies a conditionp(which is a parameter of fork) and then applies one of two lenses (which are the other parameters) for each subtree.

Afterwards, the two resulting trees are combined. In the following definition, we denote tree combination – i.e., concatenating the child lists of two trees – by a triple-colon ‘:::’.

fork(p:condition, l:lens, r:lens) :lens {

get(c) =l.get({x∈c| p(x)}) :::r.get({x∈c| ¬p(x)})

put(a,c) =l.put({x∈a | p(x)},{y∈c| p(y)}) :::r.put({x∈a |¬p(x)},{y∈c|¬p(y)}) create(a) =l.create({x∈c| p(x)}) :::r.create({x∈c| ¬p(x)})

}

The fork lens combinator is one way of realizingparallel lens composition: in contrast to the comp lens combinator, which puts two lenses in sequence,fork puts two lenses in parallel. Using fork, other tree-specific lenses can be constructed. For instance, a filter lens can be created by applying const({}), a lens which realizes a constant replacement with an empty tree, to the one subset and the idlens to the other subset. This way, the subset which does not satisfy the condition is filtered away, whereas the other subset stays untouched:

filter(p:condition) :lens= f ork(p, id, const({}))

The introducing example in Foster et al. (2005) is a synchronization between the contact list tree shown above and a phone book tree which only contains names which refer to a phone number (Fig. 5.3). The lens which implements this synchronization therefore, in the forward direction, filters away the URLs and flattens the tree by one level. This lens can be described by parameterizing a focus lens to extract the phone number and composing it with amap lens combinator to apply it to all entries of a list:

108 Chapter 5. A Compositional Language for Bidirectional Model Transformation

phoneBookSync:lens=map(f ocus("Phone",{"URL"7→"http://default.com”}) The focus lens again is composed: focus(n,d) can be expanded tocomp(filter(n,{d}), hoist(n)) wheren is an edge-label andd is an appropriate default structure for thecreate function – in the example, a default URL.

Figure 5.3: A concrete tree and a derived abstract tree being kept in sync by a lens Focaldemonstrates that with a comparably small set of atomic lenses and combinators a rich lens library can be constructed. Based onFocal, Bohannon et al. (2008) presented a comprehensive lens library for bidirectional string transformation called Boomerang.