As it says in the topic: exactly which combination of inheritance and generics this field is supposed to help describe? I read the spec and even Archie code base, but I cannot understand what it is supposed to model.
As far as I can see, this field is never set to anything in Archie. I used a breakpoint and debugged the call to .getClasDefinitions() which I thought would access the setter if the condition modelled by this field every occured in the RM, but the setter was never called.
Reading the spec, it says:
āIf set, is the corresponding generic parameter definition in an ancestor class.ā
My reading of this is we have a type parameter T in SOME_GENERIC_TYPE which has a ācorrespondingā type parameter in some ancestor, except I cannot imagine the scenario in which T is somehow associated to a type parameter of another type in the inheritance hierarchy. I just could not think of how that association may come to be, let alone how it would be expressed in terms of declaration of types. In pseudo sytnax, we can have:
but in all these cases T is a type variable of SOME_GENERIC_TYPE and whatever association it may hold ā¦ I could not think about.
If weāre looking at
SOME_TYPE extends PARENT_TYPE<T> then SOME_TYPE may inherit a field with type T but this is not the scenario that is defined by the spec as far as I can see.
Search for BmmParameterTypein Archie. It is first used when converting from ODIN (archie/bmm/src/main/java/org/openehr/bmm/v2/persistence/PBmmGenericParameter.javacreateBmmGenericParameter()).
The spec (āIf set, is the corresponding generic parameter definition in an ancestor class.ā) might be misleading. Especially the part referring to the āancestor classā.
BMM_PARAMETER_TYPE is a type of parameters of a generic type (T). The actual type of T is via its property BmmParameterType.conformsToType which is of type BmmEffectiveType āconnectingā generic parameters to the BMM type system.
Maybe it should be named BMM_GENERIC_PARAMETER since it doesnāt directly specify type (it can even have a name only, without type ā meaning ANY type).
@borut.jures thanks, but Iām not sure I managed to express myself. I agree with what you say about the BMM_PARAMETER_TYPE, but my question is about the specific field of that type. I can see what BMM_PARAMETER_TYPE does, I want to understand what that specific field indicates.
Iām referrring to this location in the spec: BMM_PARAMETER_TYPE Class and specifically to inheritance_precursor attribute. Thatās it. Thatās my question. What is it for exactly?
I missed the mention of inheritancePrecursor in the title
I can confirm that Iām not setting its value in my BMM parser either (just like Archie).
Iām using it in only one place ā if conformsToType would be null, then inheritancePrecursor would be used.
However after researching it further, I remembered that when generating code, I have to handle cases where conformsToType of a generic parameter T isnāt specified for a BMM type. Since languages like Java/Kotlin/C# require a type, the generator searches for the type of T in āthe corresponding generic parameter definition in an ancestor classā ā just like the quoted description from the specs says.
What I do in the generators, should probably be done when parsing BMM files. If this was the case, I would set inheritancePrecursor to the found type of T in the ancestor class.
The example you provided would use T in the PARENT_TYPE (instead of G):
Maybe my memory of parametric polymorphism in JAVA/C# etc are a bit rusty but I donāt think you can declare a type in these mainstream languages so that T in the below declaration are interpreted as the same type parameter for both the child and parent types. I.e. the compiler(s) would interpret these type parameters in the scope of declaring child and parent types. Update: I just reread the declaration and I think Iām wrong: T would be defined as a type parameter during declaration and its scope would include PARENT_TYPEās declaration
Yesterday I watched @thomas.beale add a new abstract type in the middle of class hieararchy and my comment was: āit looks nice in the UML diagram, but it gets tricky when converting the types to classes in programming languagesā
One major obstacle for most languages is when a type of a property is changed in a descendant class. I managed to solve this for 4 programming languages, but Iām always anxious what the next version of BMM files will bring
Iām also eager to learn the intended way of using the inheritance_precursor attribute.
Using slightly more comprehensible class names, imagine FAST_SORTED_LIST<T> extends SORTED_LIST<T>. The inheritance_precursor of 'T' in an instance of BMM_GENERIC_CLASS is the BMM_PARAMETER_TYPE object representing is the 'T' in the BMM_GENERIC_CLASS instance representing SORTED_LIST<T>. This is replicated for all generic paramaters for which there are precursors in the inheritance hierarchy, e.g. '<K,V>' params of Map types.
Itās useful for each generic parameter in a descendant generic class to know its inheritance precursor, because that may have a type constraint, i.e. to know that the first 'T' below has to conform to ORDERED.
We could do without the stored inheritance_precursor, and compute it each time. Itās in the spec to support implementations that compute it on first read of the classes - itās surprisingly tricky to get right, since the numbers of generic parameters can vary from child to parent etc. To compute it on the fly means doing all this work every time. No-one would notice of course, so it could indeed be purely computed rather than stored in the in-memory model.
In this case, there is no relation between the 'T' mentioned in SOME_GENERIC_TYPE and the G, because PARENT_TYPE has closed the G generic parameter, e.g. FAST_SORTED_PACKET_LIST extends FAST_SORTED_LIST<PACKET>. Here the G parameter has been āclosedā, i.e. substituted, in PARENT_TYPE, which is not itself generic.
Either you forgot to type something after ārepresentingā or this is as far as my English gets me. Sorry, could not follow that. Update: re-read this and almost understood but then it did not make sense: should not the precursor be in the FAST_SORTED_LIST 's bmm representation? Based on you also saying:
Inheritance precursor emerges in the context of ā¦ inheritance My expected way of seeing this attribute populated in the child classās bmm representation is explained below:
This is more useful for me, thanks. I think the pseudo syntax is not helping in its current form. If we brake it down: class SORTED_LIST<T extends ORDERED>{....
followed by: class FAST_SORTED_LIST<T> extends SORTED_LIST<T> {...
then this gives us the case the inheritancePrecursor attribute is useful for. That is, the subtype extends the supertype with its type parameter. However, since the definition of the supertype already has a constraint defined on its type parameter (T extends ORDERED) the type parameter of subtype (FAST_SORTED_LIST) has to respect that constraint, otherwise it would conflict with its supertypeās contract/definition.
This fact would then be indicated via inhertiancePrecursor attribute of parameter T for FAST_SORTED_LIST (via the BmmGenericType instanceās type parameter )
Assuming I got it, the next question is do we have this anywhere in the RM ? Specifically in BMM speak, in any BmmDefinedType ? As I said, I did not see this field materialise to a non-null value in Archie, though I may not have been able to trigger the correct execution path.
Poor formatting on my part - I adjusted my original reply, hopefully it reads more clearly now.
It does - thatās the point. Donāt forget, BMMās purpose is to do exactly this kind of type policing. So in this case, the in-memory representation of a model needs to get its hands on generic parameter pre-cursors to inspect for type constraints - just as the Java or C# compiler has to do.
You did
Pretty much everything in the BMM was created because we needed it. This particular case would be needed for generic types like DV_INTERVAL<V> (see here) and others (I think in Task Planning from memory). In the soon-to-be-published S2 RM, we have a lot more generics, and the situation this construct solves occurs more often.
Aside: when we were building the openEHR RM back in the early 2000s, and OOPLs were still shaking out (you could still read articles back then that mentioned SmallTalk and Eiffel, as well as C++ and the newcomer Java), I guessed that all languages would evolve to support multiple inheritance, since C++ and Eiffel already had it, but hardly any would handle generic types properly (only Eiffel did at the time). Completely wrong guess, as any Java programmer knows - multiple inheritance never went mainstream, but we now have not just generic types but generic methods.
So supporting generic type semantics in a meta-model like BMM is in my view essential to enable models to be written that will conveniently translate to languages like Java, C#, Kotlin, etc.
That was the first type I checked, but unless Iām being extra thick, nothing inherits DV_INTERVAL in the RM.
Going back to my updated comments above: is inheritancePrecursor supposed to be instantiated/expressed in DV_INTERVALās Bmm representation (BmmGenericClass) or its subtypesā Bmm represantations. (though I cannot see any subtypes)
Sorry, as usual, Iām expecting people to understand whatās on my mind without me explaining it. My question was related to something else I tried to articulate above: when the object oriented BMM representation of DV_INTERVAL is build by Archie, Iād expect the BmmGenericClass representing it to have a type parameter object (BmmTypeParameter), which it does, and I also expect that object to have the inheritancePrecursor set. In other words, I expect inheritancePrecursor attribute to be available in the type parameter object of the subtype (DV_INTERVAL) in this subtype-supertype relationship. Iāll double check, but I think Archie is not populating it, so thatās why I was a bit confused.
As I said, Iāll double check and post the screenshots from the debugger.
By the way, once you use generics and inheritance in the object model, thereās no way to avoid this kind of detail in the meta representation. So Iām not disagreeing with the way the way the meta model is designed. You know I had my fair share of assumption about where programming languages and software development would go Iām just trying to figure out the why and how of BMM a bit better these days.
Got it - Iāll have a look myself later today when I get a minute, Iāve recently been working on that bit of Archie. It may be that it doesnāt do that properly, although they have been very careful in their work, so maybe itās just done another way
A quick inspection shows that BmmParameterType.setInheritancePrecursor() is never called. It should be called from BmmGenericClass.addGenericParameter(), but is not.
My Eiffel implementation, from which the BMM part of Archie is derived has more code.
I suspect that part of BMM in Archie might have been written before I added the extra code in Archie (inspecting dates in Github would reveal things). Generally @pieterbos seems to have either used what I did, or else invented a better replacement. In this case, I canāt see any replacement.
So unless it is secretly being done somewhere else that we canāt see, we might consider writing a PR to fix that. Iāll have a really good look soon and test if it is working or not with DV_INTERVAL<T>, and if not, add the extra logic.
The BMM implementation was done by Claude Nanjo, and integrated into Archie by me in collaboration with him. This implementation was missing a couple of things. I implemented the parts that were absolutely essential for use in openEHR. Then later we refactored it, replacing the custom ODIN parser code with the generic Archie one and unraveling quite a lot of spaghetti into a more clear control flow. Thomas also did work on more refactoring, and some more unimplemented bits were implemented as part of this process. But some parts of the BMM functionality in Archie remain unimplemented, likely including this.