Reverse Relations

Hi,

Excuse for the bit complex text below, I don’t know how to say it more simple

I have a small problem with the way ReverseRelationships are connected to Party in the Demographic RM.
Maybe my problem is because of my misunderstanding.

The problem is not only conceptual, but it also causes problems in coding (programming) the kernel.

The problem is that ReverseRelationships are a Set of LocatableRef. This means that the PartyRelationship has to be stored before it can be added to a party ReverseRelationship list.
The PartyRelationship has to be stored because LocatableRef takes a ObjectVersionID as constructor-argument.

The conceptual problem is that the ReverseRelationship in this way is defined as a version of a specific PartyRelationship. If the PartyRelationship changes, for example in its details, than the new version is not anymore connected to the target-Party, or this connection needs extra code to restore

(replace the ObjectVersionID in the target-Party ReverseRelationship-set, maybe even create a new version of the PArty, because of a new version in another object, namely the PartyRelationship-object)

I don’t understand why that is, it seems a bad thing which causes extra complexity.
More logically would seem to me to connect the UID of to the list ReverseRelationships in the target Party, instead of the ObjectVersionID.

Maybe it is a matter of redefining the LocatableRef-definition to a kind of ObjectRef-class, and add a VersionedLocatableRef for versioning-purposes.

Hi Bert,

Hi,

Excuse for the bit complex text below, I don’t know how to say it more simple

I have a small problem with the way ReverseRelationships are connected to Party in the Demographic RM.
Maybe my problem is because of my misunderstanding.

The problem is not only conceptual, but it also causes problems in coding (programming) the kernel.

The problem is that ReverseRelationships are a Set of LocatableRef. This means that the PartyRelationship has to be stored before it can be added to a party ReverseRelationship list.
The PartyRelationship has to be stored because LocatableRef takes a ObjectVersionID as constructor-argument.

I presume this is in the Java implementation, since constructors are not defined in the openEHR specifications? Obviously using constructors is not the only possibility, setter routines could also be used. IN any case, creation of identifiers does not rely on persistence; it should be knowable beforehand, so I would expect the use of a constructor to be fine.

The conceptual problem is that the ReverseRelationship in this way is defined as a version of a specific PartyRelationship. If the PartyRelationship changes, for example in its details, than the new version is not anymore connected to the target-Party, or this connection needs extra code to restore

(replace the ObjectVersionID in the target-Party ReverseRelationship-set, maybe even create a new version of the PArty, because of a new version in another object, namely the PartyRelationship-object)

the reverse_relationships attribute of PARTY is intended to contain a set of reverse pointers to PARTY_RELATIONSHIPs for which the PARTY is a ‘target’. The first thing to note is that the attribute is optional, and you can ignore it if you want. If you use it, it should always contain the current list of PARTY_RELATIONSHIPs for which the PARTY is a ‘target’. If any such relationship is changed, then the relevant PARTYs would have to be updated.

The problem you point out is that if the change in the PARTY_RELATIONSHIP (taking it from version 3 to 4, let’s say) doesn’t affect a given PARTY, which is a target of version 3 of the PARTY_RELATIONSHIP, then you are still forced to update the PARTY so that it its reverse_relationships now has the v4 id for the updated PARTY_RELATIONSHIP rather than the v3 id. One way to fix this would be if we were to enable a ‘latest’ version id that always automatically pointed to the latest version of something. This is defined for openEHR EHR URIs, but not for the type OBJECT_VERSION_ID, used in LOCATABLE_REF.

I think a better solution is that PARTY simply does not contain reverse relationships, because it is essentially solving a database indexing problem, which could be better solved by maintaining index objects and/or native indexes, depending on how the demographic model persistence is implemented.

I don’t understand why that is, it seems a bad thing which causes extra complexity.
More logically would seem to me to connect the UID of to the list ReverseRelationships in the target Party, instead of the ObjectVersionID.

that would probably risk the reverse_relationships attribute getting out of data quickly and containing wrong information, unless the implementation meticulously checked whether the validity was always maintained or not.

I would be interested to know what other experience there is with this attribute; my suspicion is that it should be deprecated.

  • thomas

I agree with Thomas, the reverse relationships should be derived from the forward relationships. The RM doesn’t necessarily need to be reflected in the persistence model.

Having said that, we do have a fundamental issue regarding OBJECT_REF with regard to using VERSIONED_OBJECT uid or VERSION uid, in some cases it is desirable to use the former because you want the relationship to exits even if the referenced object is revised, whilst in other case this may not be safe practice. I think this issue deserves some discussion and a Wiki page for the outcome.

Heath

Thanks, Thomas, for your reply.

The problem is that ReverseRelationships are a Set of LocatableRef. This means that the PartyRelationship has to be stored before it can be added to a party ReverseRelationship list.
The PartyRelationship has to be stored because LocatableRef takes a ObjectVersionID as constructor-argument.

I presume this is in the Java implementation, since constructors are not defined in the openEHR specifications? Obviously using constructors is not the only possibility, setter routines could also be used. IN any case, creation of identifiers does not rely on persistence; it should be knowable beforehand, so I would expect the use of a constructor to be fine.

It is true this is in a java-implementation.

But the way to assign a ObjectVersionID to a version-able object in my code is to persist it, after which my code does some checks, also on versions, and then returns the ObjectVersionID.
This can be re-coded, I could predict the ObjectVersionID, reserve it (protect it against other threads trying to do the same simultaneously), and first create the LocatableRef, then set it in the target-Party which needs the ReverseRelation and if no exceptions occur then persist the PartyRelationship.

As you can see, this will be very complex code.

The way I solved the problem now does also not deserve a prize in a beauty contest (dutch saying).
I describe it to illustrate which problems this situation causes to me.

I, first, persist the PartyRelationship, then try to assign it to the source and target, and if that fails, for example because the archetype of the source-Party does not allow that (or any) PartyRelationship to be assigned, than I need to remove the persisted PartyRelationship. Because my persistence-code does not have any removal (from persistence)-code, I have to assign the orphaned and persisted PartyRelationship as “deleted”, which is not a nice solution, but does not put a (relatively) heavy load on my kernel-functionality.

I think a better solution is that PARTY simply does not contain reverse relationships, because it is essentially solving a database indexing problem, which could be better solved by maintaining index objects and/or native indexes, depending on how the demographic model persistence is implemented.

This is a good idea, there shouldn’t be any optimization attributes in the RM-specifications. It is always possible to retrieve ReverseRelationships at the moment of getting a Party from the persistence-layer.

Thanks, this is the best solution, it really helps me further.

I don’t understand why that is, it seems a bad thing which causes extra complexity.
More logically would seem to me to connect the UID of to the list ReverseRelationships in the target Party, instead of the ObjectVersionID.

that would probably risk the reverse_relationships attribute getting out of data quickly and containing wrong information, unless the implementation meticulously checked whether the validity was always maintained or not.

I don’t understand, my code always retrieves the latest version of a persisted object, when queried by UID. The version-functionality is not yet used in an API. But the storage is already prepared to use it in the future, so, there is code, and are tables and indexes already in use (data are stored), for when that API will come, (which will be within a year or so)

that’s probably the best way to implement the ‘latest’ version idea. We should describe that use..

  • thomas

Op 29-04-11 03:03, Heath Frankel schreef:

I agree with Thomas, the reverse relationships should be derived from the forward relationships. The RM doesn’t necessarily need to be reflected in the persistence model.

Thanks Heath, this is indeed a pitfall, trying to reflect the RM. I sometimes fall into it too.

Having said that, we do have a fundamental issue regarding OBJECT_REF with regard to using VERSIONED_OBJECT uid or VERSION uid, in some cases it is desirable to use the former because you want the relationship to exits even if the referenced object is revised, whilst in other case this may not be safe practice. I think this issue deserves some discussion and a Wiki page for the outcome.

A PartyRelationship can change in its details without change to the source and target-attribute. For example, the meaning of the Relation can change, a wife can become an ex-wife. Still the same target and source.

As the specs are now: When this happens the target-party will need a new version because one of its attributes have changed (because the LocatableRef changed), and the PartyRelationship needs a new version, because its details changed.

I think it is desirable that in a case like this, only the PartyRelationship need a new version, not the target-party, and if I am right, it is sufficient to use a PartyRef as ReverseRelation instead of a LocatableRef

This idea is extra confirmed because it does not seem logically to write a new version of a PartyRelationship in case the source of the target change, because, in that case, the relation doesn’t exist any more, I cannot imagine a situation in which there would be a reason to prolong the lifetime (write a new version) of a PartyRelationship when the relation finish to exist.

But, I am not sure.

Bert