Do you think this should be corrected on the flattener? (I don’t know if this is a bug or this is the expected behaviour and the reference to the slots and ontologies are resolved in some other way).
Other question: is this a bug?
I’ve codedd a simple slot finder and reference loader to test archetype flattening, and it seems the slots I found had no parent (i.e. the reference to the attribute containing the slot is null in the slot):
I don’t have any idea what the current Java flattener does, but we will need to get any/all ADL 1.5 flatteners in sync. I believe the ADL Workbench has the definitive algorithm at the moment, but there may be still details to change.
Anyway, in the near term, I intend to publish the algorithm in a friendly way (the code is of course available in the ref_impl_eiffel SVN, but it’s in Eiffel, so we need a language neutral form). I’ve been cleaning it up a bit, so it should end up being pretty comprehensible… well, for what it is… the full flattening semantics are not trivial.
If I get this out in the next couple of weeks, it would be good if anyone/everyone can have a look, try to find bugs, errors, clean simplifications etc, and also see if the java code can implement it.
When we get to that point we need to develop a bunch of test archetypes for flattening, including with regression. One way to do this is to manually build ‘correct’ flat archetypes that the compiler should always be able to match by generation. Another way is to implement a second algorithm, which I will also publish, which is the ‘flat archetype differencing algorithm’, which can reconstitute the child differential from a generated flat. if the latter is done properly then it should always be the case that this latter generated diff form is identical to the original authored diff. While this doesn’t theoretically guarantee the correctness of the flattening operation (since both flattening and diffing could be wrong, but in the same way), we can assume it does for practical purposes.
Obviously I don’t guarantee that either of these algorithms as I have defined them is perfect, but they appear to work properly on all cases I have tested, so i think they are a good starting point.
Hi Thomas, it would be great to have the algorithms specified, I can help with Java/Groovy implementation and testing.
I also need some of this functionality for ADL 1.4, but just to resolve slots, not specialization with semantic codes resolution.
We need both 1.4 & 1.5 to put the “test base” together and generate some initial artifacts (I’m working on this right now, I started trying things on 1.4).
AFAIK, seeing the code, the java ref flattener flattens only XML templates, maybe Rong can enlight us on that.
The current flattener in Java project only handles templates in OET
format (not ADL 1.5). So, for instance it doesn't deal with
differential forms of archetypes.
And Yes, Thomas! It would definitely be a great step to publish the
algorithms and to build up a set of standard test archetypes.
groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: nodeID for class: org.openehr.am.archetype.constraintmodel.CComplexObject
It seems that some properties are still read-only, like CComplexObject.nodeID. What I tried to do is what Thomas suggested: put the archetypeId in the nodeID of the resolved slots on the flat archetype.
About the null parent attribute on ArchetypeSlot, I do an ugly workaround passing the parent object to every method of my archetype slot finder walk through.
We have relaxed the immutability of AOM objects. The attribute nodeID
is deprecated, so you should use setNodeId() and getNodeId() instead.
I just recall that in the Swedish project, we didn't have any
Instruction/Activities templates so it could be the case that this use
case is not covered by the OET flattener. Feel free to improve it and
accompany the new functionality with a testcase.
Not sure about the null parent issue in ArchetypeSlot, can you provide
more details on it?
Hi Pablo,
I am aware of null parent in the aom objects. The thing is before the
aom objects are immutable and during ADL parsing all the objects are
built from bottom up so there is no possibility to set parent when
building the child. Now immutability is not enforced anymore in aom
but I still question the virtue of have such cyclic references in the
objects.
There are other ways of retrieving the parent, e.g. path based
approach. so if the use case isn't sufficient strong, I am bit
reluctant to implement it. please let me know how you think.
Regards,
Rong
Maybe a second pass top-down can set the parent on each node on the parser code.
The problem of the path approach is that if a CObject has no nodeID, then it’s path is equal to the CAttribute path.
When I do an archetype.node(pathToAttribute) that contains a child with no nodeID, I get the CObject instead of the CAttribute.
(BTW: I don’t know if this is the expected behaviour)
Related to this, I saw that on ACTION archetypes, there are sibling ISM_TRANSITION nodes that doesn’t have a nodeID, violating a rule on the specs, but it’s getting parsed without problems.
Maybe a second pass top-down can set the parent on each node on the parser
code.
Yes, that's definitely possible. I will give it a try to see if this
really affects others.
The problem of the path approach is that if a CObject has no nodeID, then
it's path is equal to the CAttribute path.
When I do an archetype.node(pathToAttribute) that contains a child with no
nodeID, I get the CObject instead of the CAttribute.
(BTW: I don't know if this is the expected behaviour)
Related to this, I saw that on ACTION archetypes, there are sibling
ISM_TRANSITION nodes that doesn't have a nodeID, violating a rule on the
specs, but it's getting parsed without problems.
Right. This should be picked up by archetype-validator after parsing I believe.
this is probably completely obvious, but just in case… Obviously I don’t know the Java code, but the Eiffel and .Net code I think does the same thing: when a node object (e.g. a C_OBJECT of some kind) is created and attached to its parent (a C_ATTRIBUTE, except for the root object), the normal pattern is (in pseudo-code): in CAttribute: addChild (CObject anObjNode) { children.append (anObjNode); anObjNode.setParent (this); } in CObject: setParent (CAttribute anAttrNode) { parent := anAttrNode; } this setParent routine should only be visible to CAttribute There is the same pattern in the other sense, to enable CAttribute to set a parent CComplexObject. - thomas
When flattening archetypes, when resolving slots, I use nodeID with this format: archetypeID::atNNNN.
That’s to avoid collisions between node ids in the root archetype and node ids of archetypes referenced by slots.
When I parse the flat archetype I get an error, it seems there is a constraint on nodeID format.
BTW: the flattened ADL was generated by the ADLSerializer.
I changed “::” to “_” but I get another exception: (I don’t know if this exception has something to do with the nodeID format or with an ISM_TRANSITION having a nodeID)
this is probably completely obvious, but just in case...
Obviously I don't know the Java code, but the Eiffel and .Net code I think
does the same thing: when a node object (e.g. a C_OBJECT of some kind) is
created and attached to its parent (a C_ATTRIBUTE, except for the root
object), the normal pattern is (in pseudo-code):
I was revisiting the specs
I’m working with ADL 1.4, trying to implement a suggestion from Thomas: to flat archetype slots preserving the original node ids.
To do so, I need to use the archetype id and the node id to avoid node conflicts, e.g.