Hello all,

Is anyone able to provide some guidence on this?

I have a class which contains(0..*) subclasses which then contains (0..*)

instances of itself i.e.

class c1 { val c2[*]#parent contains;}

class c2 { val c2[*] contains; ref c1#contains parent}

I need to transform this to a new model where c2 can not contain

instances. i.e. all instances in c2.contains need to be stored under

c1.contains.

The actual model is more detailed than this but this is the bit I'm stuck

on. I tried:

@lazy

rule NumberedParagraph

transform p1 : DocumentModel!ParagraphType

to p2:DocumentStructure!NumberedParagraph, t2 : DocumentStructure!Text{

guard : p1.numbering.isDefined() and p1.numbering <> ''

p2.numbering := p1.numbering;

t2.text := p1.text;

p2.text.add(t2);

for (z in p1.group){

p2.parent.children.add(z.getValue().equivalent());

}

}

But p2.parent does not exist yet. Anyone have any pointers to what I

should try next. Many thanks.

Darren]]>

Reply hidden below :)

Darren Clowes wrote:

> Hello all,

>

> Is anyone able to provide some guidence on this?

>

> I have a class which contains(0..*) subclasses which then contains

> (0..*) instances of itself i.e.

>

> class c1 { val c2[*]#parent contains;}

> class c2 { val c2[*] contains; ref c1#contains parent}

>

> I need to transform this to a new model where c2 can not contain

> instances. i.e. all instances in c2.contains need to be stored under

> c1.contains.

Ok, this seems a little odd to me. Consider the following model, which

instantiates the metamodel described above:

top, an instance of c1, contains:

foo, an instance of c2.

bar, an instance of c2, which contains:

baz an instance of c2.

The parent of foo is top (opposite of contains). The parent of bar is

top (opposite of contains). The parent of baz is null, as it is not

contained in an instance of c1 (but in an instance of c2).

Consequently, transforming model elements contained in instances of c2

will be tricky (though not impossible). A restructuring of the metamodel

fixes the null parent problem. Is it possible to restructure the

metamodel like so:

class c1 {

val c2[*]#parent contains;

}

class c2 extends c1 {

ref c1#contains parent;

}

>

> The actual model is more detailed than this but this is the bit I'm

> stuck on. I tried:

>

> @lazy

> rule NumberedParagraph

> transform p1 : DocumentModel!ParagraphType

> to p2:DocumentStructure!NumberedParagraph, t2 : DocumentStructure!Text{

> guard : p1.numbering.isDefined() and p1.numbering <> ''

> p2.numbering := p1.numbering;

> t2.text := p1.text;

> p2.text.add(t2);

> for (z in p1.group){

> p2.parent.children.add(z.getValue().equivalent());

> }

> }

If the above restructuring isn't possible, the following transformation

should work:

rule Container2Container

transform s : Source!c1

to t : Target!c1 {

-- transform other features, e.g:

-- t.name := s.name;

}

rule Content2Content

transform s : Source!c2

to t : Target!c2 {

t.parent := s.findParent().equivalent();

}

operation Source!c2 findParent() : Source!c1 {

if (self.parent.isUndefined()) {

return self.eContainer().findParent();

}

return self.parent;

}

The findParent operation is defined for instances of c2 in the source

metamodel. It uses recursion to locate the containing c1 element:

- if self.parent is non-null, the parent is simply returned (the base case)

- otherwise, we use the eContainer() method to determine the object that

contains this instance of c2, and recursively invoke findParent() (the

recursive case)

The use of eContainer() is _A Bad Thing_, it is specific to EMF

metamodels and can only be invoking on EObjects.

Finally, note the use of the built-in operation equivalent() in the body

of the Content2Content rule. equivalent() will convert from an instance

of the source model to an instance of the target model using the

transformation rules defined. In this case, equivalent() is used to

convert from an instance of Source!c1 to an instance of Target!c1. Hence

the need for the first rule.

Cheers,

Louis.]]>

Reply hidden below :)

Darren Clowes wrote:

> Hello all,

>

> Is anyone able to provide some guidence on this?

>

> I have a class which contains(0..*) subclasses which then contains

> (0..*) instances of itself i.e.

>

> class c1 { val c2[*]#parent contains;}

> class c2 { val c2[*] contains; ref c1#contains parent}

>

> I need to transform this to a new model where c2 can not contain

> instances. i.e. all instances in c2.contains need to be stored under

> c1.contains.

Ok, this seems a little odd to me. Consider the following model, which

instantiates the metamodel described above:

top, an instance of c1, contains:

foo, an instance of c2.

bar, an instance of c2, which contains:

baz an instance of c2.

The parent of foo is top (opposite of contains). The parent of bar is

top (opposite of contains). The parent of baz is null, as it is not

contained in an instance of c1 (but in an instance of c2).

Consequently, transforming model elements contained in instances of c2

will be tricky (though not impossible). A restructuring of the metamodel

fixes the null parent problem. Is it possible to restructure the

metamodel like so:

class c1 {

val c2[*]#parent contains;

}

class c2 extends c1 {

ref c1#contains parent;

}

>

> The actual model is more detailed than this but this is the bit I'm

> stuck on. I tried:

>

> @lazy

> rule NumberedParagraph

> transform p1 : DocumentModel!ParagraphType

> to p2:DocumentStructure!NumberedParagraph, t2 : DocumentStructure!Text{

> guard : p1.numbering.isDefined() and p1.numbering <> ''

> p2.numbering := p1.numbering;

> t2.text := p1.text;

> p2.text.add(t2);

> for (z in p1.group){

> p2.parent.children.add(z.getValue().equivalent());

> }

> }

If the above restructuring isn't possible, the following transformation

should work:

rule Container2Container

transform s : Source!c1

to t : Target!c1 {

-- transform other features, e.g:

-- t.name := s.name;

}

rule Content2Content

transform s : Source!c2

to t : Target!c2 {

t.parent := s.findParent().equivalent();

}

operation Source!c2 findParent() : Source!c1 {

if (self.parent.isUndefined()) {

return self.eContainer().findParent();

}

return self.parent;

}

The findParent operation is defined for instances of c2 in the source

metamodel. It uses recursion to locate the containing c1 element:

- if self.parent is non-null, the parent is simply returned (the base case)

- otherwise, we use the eContainer() method to determine the object that

contains this instance of c2, and recursively invoke findParent() (the

recursive case)

The use of eContainer() is _A Bad Thing_, it is specific to EMF

metamodels and can only be invoking on EObjects.

Finally, note the use of the built-in operation equivalent() in the body

of the Content2Content rule. equivalent() will convert from an instance

of the source model to an instance of the target model using the

transformation rules defined. In this case, equivalent() is used to

convert from an instance of Source!c1 to an instance of Target!c1. Hence

the need for the first rule.

Cheers,

Louis.]]>