∗ **BoolBinaryOp** corresponds to the several common binary operators returning a boolean value, such as:
⇔, →, and, or, =, 6=, ≤, ≥, <, >.

- **SetExpression** defines the main constructs available to deal with sets within expressions:
- **SetValue** corresponds to a set of value occurrences, such as {1, 2, 3}. To tackle various contents as set elements (e.g. {1, x + 1}), it is composed of a list of elements conformed to **Expression**.

- **SetFunction** corresponds to the call of known functions over sets, such as the cardinality function.

- **SetOperator** is specialized only in **SetBinaryOp**
since no unary operator is commonly used on sets. For instance, intersection, union and difference are available.

- **AlgebraicExpression** defines the numerical expressions:
- **AlgValue** is abstract and represents the three main concepts of values in numerical expressions:
IntValue for integer values, **RealValue** for real number values and **IntervalValue** for interval values such as [−1, 1].

- **AlgFunction** corresponds to the call of a well-known function over numbers, such as trigonometric functions.

- **AlgOperator** refers to the common operators used in algebraic expressions: **AlgUnaryOp**(−, +) and AlgBinaryOp (+, −, ∗, / and ˆ).

Our pivot metamodel has been defined to fit with most modeling needs in CP, but also to fit with the metamodel of CP languages. Thus, some simplifications have been done to ease transformations such as the **VarOccurrence** concept which directly inherits from **Expression**. Indeed, variable occurrences can be typed in expressions (i.e. boolean, set or algebraic), but we define only one to avoid redundancies.

## Pivot Model Refactoring

Model transformations are implemented as rewriting operations over pivot models.

For sake of clarity, we will present a few operations using an imperative pseudo-code style, while specific transformation languages are used in practice. The main interest given by the concept hierarchy is to provide navigation mechanisms through models. For instance, it is immediate to iterate over the set of variables of a constraint, since this information is gathered in the corresponding abstract constraint concept (see e.g. Algorithm 2). It is therefore possible to manipulate models globally, which is very powerful. Object flattening This refactoring step replaces object instances, namely variables whose type is a class, by all elements defined in the class definition (variable, constants, constraints and other statements). In order to prevent name conflicts, named elements are prefixed with the name of object instances.

This refactoring transformation can be expressed in terms of a brief pseudo-code algorithm as shown in Algorithm 1.

Algorithm 1 Transforming and removing object variables and class definitions objectRemoval(m : **Model**) : **Model**
1: let res : **Model**
2: **for all** o in m.elements do 3: if is var(o) and is **class**(o.type) **then**
4: res.insert(**flatten**(o,o.type.features))
5: else if not is class(o) **then**
6: res.elements.insert(o)
7: **end if**

## 8: End For 9: Return Res

flatten(o : **Variable**, features : Set of **ModelFeature**) : Set of **ModelFeature**
1: let res : Set of **ModelFeature** = ∅
2: **for all** f in features do 3: if is var(f) and not is **class**(f.type) **then**
4: let v : **Variable**
5: v ← duplicate(f)
6: v.name = o.name + ' ' + v.name 7: res.insert(v) 8: **else**
9: ...

10: **end if**
11: **end for**

## 12: Return Res

The **ObjectRemoval** function processes a source model by iterating on all its elements (line 2). If object instances are detected (line 3), then the function **flatten** is called and its result is added to the output model elements (line 4). Instances not being a **Class** definition are duplicated in the output model (line 5,6), while **Class** definitions are removed. In the **flatten** function every feature given as parameter is cloned and added to the resulting set of ModelFeature. In the case of a variable (and also constants), its name is concatenated to the object variable name
(line 6). Figure 6 depicts the result of the transformation on the social golfers example previously presented.

class SocialGolfers { **Week weekSched[w];**.. .} class Week { **Group groupSched[g];**. . .}
class Group { **Name set players;**. . .}
⇒ Name set weekSched groupSched **players[g*w];**
Figure 6: Applying the object flattening transformation on the social golfers example using s-COMMA syntax.

Arrays of objects and expressions refactoring are not presented here to keep the algorithm simple. As mentioned at the end of Section 3, in the case of object arrays, we must transfer their size to their attributes and a loop statement has to be introduced to iterate on their **Statement** instances.

Within expressions, instances of **VarOccurrence** may just be updated with the declaration of the new flat variables.