How to force Acceleo to iterate over a collection in the same order on every template execution?

StackOverflow https://stackoverflow.com/questions/20366831

Pergunta

I'm using an EMF model based on Modisco KDM metamodel. At some point of my Acceleo template I need to iterate over a collection, e.g.:

[for (e: AbstractCodeElement | action.codeElement) separator(', ')][e.generateCode() /]

The action.codeElement is a collection and modisco's kdm.ecore metamodel defines it as non-ordered.

Every time I run my generator, the output is generated on a different order. Cleary the serialized model xmi enforces a specific order, and every model editor (emf default editor, modisco editor) I open the model shows the same order always (matching the order the elements were serialized to the xmi file).

Since I cannot change the kdm.ecore metamodel to make the set ordered, would there be a workaround to get Acceleo to always iterate on the same order?

Thanks in advance

Foi útil?

Solução

I'm afraid you can't. Try and cast it to a sequence:

action.codeElement->asSequence()

but I don't think anything guarantees that the sequence you get will always be sorted in the same order.

If the metamodel is made that way, there should be a reason, so either you can contact the metamodel authors to check this reason, or you should sort the result of action.codeElement with some stable criterion:

action.codeElement->sortedBy( some OCL expression)

Outras dicas

I don't know of a clean way. I solved the problem by altering the name attribute of a child element so that it was sortable alphabetically in the way I wanted.

I wanted Slots in the same order every time, so I changed the name of each of their "value" child.

The names looked like: "01_id", "02_username", "03_city", ... "10_instructions", "11_contact". I didn't have to change what the "value" elements held, just their name, which I wasn't using for anything anyways. Hope this helps.

[for (s : Slot | instanceSpecification.slot->select(definingFeature.name = 'column')->sortedBy(value->asSequence()->first().name)]
    ... do work here ...
[/for]
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top