Issue 11097: Dynamic typing with allInstances() (ocl2-rtf) Source: No Magic, Inc. (Mr. Tomas Juknevicius, tomas.juknevicius(at)nomagic.com) Nature: Uncategorized Issue Severity: Summary: I have an issue with OclAny::allInstances() method, as described in the 11.2.5 section of the OCL2 spec (06-05-01.pdf). If I understand correctly, OCL is a statically typed language (e.g. as stated in the beginning of 8.2 section or 8.3 section OclExpression paragraph). Every expression has a type and this type can be statically determined by analyzing the expression and its context. Most of the concepts in the OCL spec follows this rule, however I have an issue with the allInstances() method, defined on OclAny. Specifically, the "Returns all instances of self. Type T is equal to self." statement is problematic. When allInstances is used on the literal type specifier, there is no problem. E.g. context classFoo inv: somepackage::classBar.allInstances()->size() < self.limit Here, return type of the expression "somepackage::classBar.allInstances()" can be determined by static analysis ("at compile time") - it is Set(classBar). However when allInstances is invoked on variable, calculated by some expression, and all the staticallity of OCL crumbles and the hell breaks loose :D. And there are no restrictions, on what objects allInstances() can be invoked, the only rules are that the object to be classifier and the instance set be finite. E.g. (singleton rule - all the classes must have at most 1 instance) context Class inv: self.allInstances()->size() <= 1 Now, what is the type of the self.allInstances() expression? Well, it depends on what is the self object - and self object is supplied at run time. If we evaluate this constraint on classFoo, we see that type of "self.allInstances()" must be Set(classFoo), if we evaluate this constraint on classBar, type of expression must be Set(classBar). Hence the type of expression can not be determined at "compile time", it must be determined at "run time". E.g. we have 2 classes classFoo and classBar; classFoo has a field someField, classBar doesn't. context whatever inv: let s:Set(Classifier) = Set{classFoo, classBar} in s->allInstances()->any(true)->any(true).someField = someValue Now what is the type of s->allInstances()->any(true)->any(true) expression? We have: expression |expression type |expression value --------------------------------------------------------------------------------- s |Set(Classifier) |Set{classFoo, classBar} s->allInstances() |Set(Set(???)) |Set{ Set_of_instances_of_classFoo, Set_of_instances_of_classBar} s->allInstances()->any(true) |Set(???) |either Set_of_instances_of_classFoo or Set_of_instances_of_classBar s->allInstances()->any(true)->any(true) |???? |either instance of classFoo or instance of classBar Now the question arises: can we access someField property? Here we must have a runtime introspection check in the OCL evaluation code - if s->allInstances()->any(true)->any(true) returned instance of classFoo, we can access the field, if instance of classBar - we must runtime-fail here. Please advise. Is this a problem of the spec or I am wrong somewhere? Granted, we are making jumps 2 levels down in metamodel hierarchy here (first from metamodel to model elements-classes, then from classes to instances of those classes), but there is nothing in the spec, what precludes this. Resolution: Revised Text: Actions taken: June 11, 2007: received issue October 16, 2009: closed issue Discussion: The description of allInstances() is already clear that it may only be applied to classifiers of finite extent, such as user-defined Classes. In particular, it does not apply to DataTypes, which by definition have unbounded extents, and this includes collection types such as Set(Classifier). Thus, much of the submitter’s argument is faulty. Disposition: Closed, no change End of Annotations:===== te: Mon, 11 Jun 2007 16:07:08 +0300 From: Tomas Juknevicius X-Mailer: Mozilla 4.78 [en] (Windows NT 5.0; U) X-Accept-Language: en To: issues@omg.org, ocl2-rtf@omg.org Subject: Dynamic typing with allInstances() Hello, I have an issue with OclAny::allInstances() method, as described in the 11.2.5 section of the OCL2 spec (06-05-01.pdf). If I understand correctly, OCL is a statically typed language (e.g. as stated in the beginning of 8.2 section or 8.3 section OclExpression paragraph). Every expression has a type and this type can be statically determined by analyzing the expression and its context. Most of the concepts in the OCL spec follows this rule, however I have an issue with the allInstances() method, defined on OclAny. Specifically, the "Returns all instances of self. Type T is equal to self." statement is problematic. When allInstances is used on the literal type specifier, there is no problem. E.g. context classFoo inv: somepackage::classBar.allInstances()->size() < self.limit Here, return type of the expression "somepackage::classBar.allInstances()" can be determined by static analysis ("at compile time") - it is Set(classBar). However when allInstances is invoked on variable, calculated by some expression, and all the staticallity of OCL crumbles and the hell breaks loose :D. And there are no restrictions, on what objects allInstances() can be invoked, the only rules are that the object to be classifier and the instance set be finite. E.g. (singleton rule - all the classes must have at most 1 instance) context Class inv: self.allInstances()->size() <= 1 Now, what is the type of the self.allInstances() expression? Well, it depends on what is the self object - and self object is supplied at run time. If we evaluate this constraint on classFoo, we see that type of "self.allInstances()" must be Set(classFoo), if we evaluate this constraint on classBar, type of expression must be Set(classBar). Hence the type of expression can not be determined at "compile time", it must be determined at "run time". E.g. we have 2 classes classFoo and classBar; classFoo has a field someField, classBar doesn't. context whatever inv: let s:Set(Classifier) = Set{classFoo, classBar} in s->allInstances()->any(true)->any(true).someField = someValue Now what is the type of s->allInstances()->any(true)->any(true) expression? We have: expression |expression type |expression value --------------------------------------------------------------------------------- s |Set(Classifier) |Set{classFoo, classBar} s->allInstances() |Set(Set(???)) |Set{ Set_of_instances_of_classFoo, Set_of_instances_of_classBar} s->allInstances()->any(true) |Set(???) |either Set_of_instances_of_classFoo or Set_of_instances_of_classBar s->allInstances()->any(true)->any(true) |???? |either instance of classFoo or instance of classBar Now the question arises: can we access someField property? Here we must have a runtime introspection check in the OCL evaluation code - if s->allInstances()->any(true)->any(true) returned instance of classFoo, we can access the field, if instance of classBar - we must runtime-fail here. Please advise. Is this a problem of the spec or I am wrong somewhere? Granted, we are making jumps 2 levels down in metamodel hierarchy here (first from metamodel to model elements-classes, then from classes to instances of those classes), but there is nothing in the spec, what precludes this. -- Tomas Juknevicius System Analyst No Magic Lithuanian Development Center Savanoriu 363-IVa., LT-49425, Kaunas Phone: +370-37-324032; Fax: +370-37-320670 e-mail: Tomas_dot_Juknevicius_at_nomagic_dot_com WWW: http://www.nomagic.com Subject: Feedback on issues from 8663 to 12485 Date: Thu, 9 Oct 2008 16:04:37 +0200 X-MS-Has-Attach: X-MS-TNEF-Correlator: Thread-Topic: Feedback on issues from 8663 to 12485 thread-index: AckqF/bHnUBqNPt8Ry6DkAvW50hUEQ== From: To: X-OriginalArrivalTime: 09 Oct 2008 14:04:41.0376 (UTC) FILETIME=[F9688200:01C92A17] Hi all, Continuing with my feedback on the proposed resolutions, here is my feedback for the rest of the issues from Christian document (from 8663 to 12485) >>> Issue 8663: Section: 11.9.1 exists Agree (No change, misunderstanding) >>> Issue 8664: Section: 11.9.1 reject Agree (No change, misunderstanding) >>> Issue 8787: The spec does not describes the syntax of integer, real or string literals Agree (Adding some text in 9.3 Concrete Syntax section). >>> Issue 8790: OclAny cannot be an instance of Classifier Agree (Closed, Already resolved) >>> Issue 8818: Reusing TypedElement for UnspecifiedValueExp Agree (Closed, Already resolved) >>> Issue 10787: OCL Collections applied to Properties Agree (No change) >>> Issue 8917: allInstances Agree (Adjusting the description text of allInstances) >>> Issue 8937: Notation for accessing class operations is inconsistent Agree (clarifying allInstance is not static) >>> Issue 9171: Introduction and oclType() Strongly agree. But the exact wording of teh resolution will depend on resolution of issue 6532 Notice that EssentialOcl merges the reflection MOF capability. However its true that getMetaClass() is not applicable to the values of DataTypes since it returns a Class. >>> Issue 9405: Wrong subtyping of PropertyCallExp and NavigationCallExp Agree (clarifying why the subtyping is not wrong) >>> Issue 9796: Section: 7.3.4 Agree (Fixing usage of @pre) >>> Issue 9913: Section: 8.3.5 Agree (Adding the missing definitions in concrete syntax part). In fact the FTF, for timing reasons didn't touch the concrete syntax section which become somehow de-synchrnized with the rest. >>> Issue 10430: Section 7.6.3 Agree (Clarifying number of iterators in forAll). >>> Issue 10432: Section "IteratorExpCS" Agree (No change) >>> Issue 10433: 11.2.3 Agree. Good point. OclVoid cannot conform to OclInvalid. >>> Issue 10434: 11.2.4 (OclInvalid) - similar criticism as 11.2.3 Agree (same as previous). >>> Issue 10436: 11.2.5 Agree (description reformulation). Indeed replacement of OclType by Classifier depends on issue 6532. >>> Issue 10436: 11.2.5 (02) Agree (Re-typing to a supertype does not mean ability to access an overridden property). However still the question whether we allow access to an overriden property is pending. (available in various languages). This may be useful when defining the overriden version of an Operation. But for sure this should not use the oclAsType operator. Replacement of OclType by Classifier depends on issue 6532. >>> Issue 10825: ownership of association ends does not matter for traversal in OCL I think this issue is controversial. We should take care not to define behaviors that cannot be easily implemented. Also this may have an impact on reflection. Does it means that when we use the reflective MOF interface to look for attributes of a class we obtain also not owned Attributes? Any opinion, reacion here? >>> Issue 10921: TypeType This depends on resolution of issue 6532. >>> Issue 10946: Collection element type serialization Agree. Non uniqueness of collection types is important since it gives more freedom on where to place its definition. However, it is important to clarify that it is not mandatory to use the "generatedType" association to store the generated types. Depending on the context of usage, these generated types can also be created within a Package (using ownedType association). >>> Issue 11097: Dynamic typing with allInstances() I don't think I agree with all the text. I prefer the actual definition notation: allInstances() : Set( T ) Instead of allInstances() : Set( self ) Which is syntactically very hazardous. Now, making the allInstances be an operation of Classifier (the M1 instance representing the UML Classifier metatype) will be, for sure, consistent with the proposed resolution of 6532. So I think this depends on issue 6532. More specifically, I believe this kind of change should be part of resolution of 6532 and not be the resolution of this issue. The resolution for issue 11097 should then probably be: Closed, no change. >>> Issue: 11098: Section: 7.4.7, 7.4.9, 9.3.2 Agree (adding implies and let in operator priority definition). >>> Issue 12378: Section 8.2 InvalidType Agree. Terminology clarification. >>> Issue 12419: CollectionType and CollectionKind I believe the resolution is not complete. The example provided by the submitter of the issue shows that the CollectionType cannot be an abstract metaclass since the definition of a OCL constraint really requires instatiating CollectionTypes (Collection(Type) in the provided example). In fact a Collection is "abstract" from a runtime point of view, but not "abstract" from an OCL constraint definition point of view. But in practice this means that the M2 metaclass ColelctionType cannot be abstract. >>> Issue 12449: no explanations about how to manipulate optional and multivalued attributes Agree (Misunderstanding) >>> Issue 12450: The Tuple constructor is problematic Agree (Misunderstanding) >>> Issue 12484: Section 8.2.1 Type Conformance on page 37 Agree (already discussed) >>> Issue 12485: Section 8.2 page 35 InvalidType Agree (duplicated) Mariano Belaunde Senior Researcher in Modelling Techniques Orange Labs 8 Avenue Pierre Marzin 22300 Lannion France tel +33 2 96 05 30 85 Subject: RE: Feedback on issues from 8663 to 12485 Date: Fri, 10 Oct 2008 15:23:57 +0200 X-MS-Has-Attach: X-MS-TNEF-Correlator: Thread-Topic: Feedback on issues from 8663 to 12485 thread-index: AckqK5JTWdKUuCO/Tl6woKz525KspwABGLzg From: To: , X-OriginalArrivalTime: 10 Oct 2008 13:24:06.0364 (UTC) FILETIME=[7870E9C0:01C92ADB] Hi Christian and all, Some responses below... >>> Issue 9913: Section: 8.3.5 >>> Should we completely overhaul this section, perhaps also using a more modern notation? I think this is an issue for OCL 2.2 RTF. For OCL 2.1 we will not have enough time to provide a good response how to re-synchrnize the Concrete Syntax section. By the way the same is for section 10 (Semantics described with UML). >>> Issue 9171: Introduction and oclType() >>> Should we repeat these operations on the CollectionType metaclass? >>> Personally, I don't see that reflection on collection values would be useful in practice, >>> but what do others think? I think it sounds strange to have an operator to access meta type information that works for almost all objects but not for collection values. I believe we should consider having also this operation for collections. By the way, two comments here: maybe oclMetaType() would be a better name name oclType()?? This depends whether at M1-level accessing the type means always accessing an instance representing the meta type. Also is there any relationship between the type of an object returned by an OCL expression and this oclType() operation? Some clarification is needed here. The second comment: To be entirely consistent with UML2 and MOF2, I believe we should also avoid having this very specific type "OclAny" and instead use the reflective "Object" meta-type (which works for all kinds of objects, including collections). Looking at the operations defined for AnyType we can see that there are only two operations that are not applicable to collections: oclIsNew and allInstances. However these two operations are not valid also for primitives types. So at the end I see no justification for having this special type - that is unknown in UML and MOF - except to play the role of the more general Object. In UML context, however we may have the problem that the MOF reflexion capability is not merged by default... So a possible global solution could be: let's simply change the definition of OclAny so that it represents _really_ any object (without excluding the collection values). In the context of EssentialOcl, OclAny is a pure renaming of MOF::Object. This solution would have the advantage not to change the terminology and limit the editorial impact of the resolution. Any opinion on this idea? Should we then treat the problem of OclAny in OCL 2.1 consistently with OclType (as part of UML/MOF re-alignment in resolution of issue 6532), or defer the problem to OCL 2.2? >>> Issue 12419: CollectionType and CollectionKind I>>> 'm afraid I didn't quite follow your response. Are we agreed that CollectionType being non-abstract >>> and Collection(T) abstract, as they are currently defined, is correct? Or are you suggesting that >>> Collection(T) should also not be abstract? I'm not sure what you are proposing to add to or amend >>> in the resolution text. Yes, we all agree that CollectionType should be non-abstract and Collection is abstract. However in the OCL2 actual specification, the CollectionType metaclass is abstract and this is an error. Some change is needed in the text describing the CollectionType metaclass (Section 8.2) and in the figure 8.1 (removing italics). >>> Issue 10825: ownership of association ends does not matter for traversal in OCL >>> Navigation of association-owned ends is identified as an optional compliance point in Table 2.1, >>> which I think is reasonable as this does have implementation dependencies. OK, but in that case there should be a note to remain that implementation of this feature is an optional compliance point. >>> Issue 10946: Collection element type serialization >>> I gather that the QVT language, for example, does specify a package to own these types? Yes. Theses types types are owned by the qvt module which is a kind of package. >>> Issue 11097: Dynamic typing with allInstances() >>> However, this raises the question of how to represent T in the model. >>> I can imagine a UML representation, but not so easily an EMOF one. >>> Am I opening a can of worms? For OCL this is currently an unresolved issue (deferred to OCL 2.2??) . If we want just to represent the signature of the parameterized operations in the Ocl StdLib then a simple new metaclass TemplateParameterType is sufficient. This approach is taken currently in QVT. Now, if we are more ambitious and we want to let users define their own parameterized operations then the complete UML template support will be needed. Best Regards, Mariano -------------------------------------------------------------------------------- De : Christian W. Damus [mailto:cdamus@zeligsoft.com] Envoyé : jeudi 9 octobre 2008 18:22 À : ocl2-rtf@omg.org Objet : Re: Feedback on issues from 8663 to 12485 Hi, Mariano, Thanks again for taking the time for careful review of these proposals. I have a few more responses, in-line. cW On 9-Oct-08, at 10:04 AM, wrote: Hi all, Continuing with my feedback on the proposed resolutions, here is my feedback for the rest of the issues from Christian document (from 8663 to 12485) >>> Issue 8663: Section: 11.9.1 exists Agree (No change, misunderstanding) >>> Issue 8664: Section: 11.9.1 reject Agree (No change, misunderstanding) >>> Issue 8787: The spec does not describes the syntax of integer, real or string literals Agree (Adding some text in 9.3 Concrete Syntax section). >>> Issue 8790: OclAny cannot be an instance of Classifier Agree (Closed, Already resolved) >>> Issue 8818: Reusing TypedElement for UnspecifiedValueExp Agree (Closed, Already resolved) >>> Issue 10787: OCL Collections applied to Properties Agree (No change) >>> Issue 8917: allInstances Agree (Adjusting the description text of allInstances) >>> Issue 8937: Notation for accessing class operations is inconsistent Agree (clarifying allInstance is not static) >>> Issue 9171: Introduction and oclType() Strongly agree. But the exact wording of teh resolution will depend on resolution of issue 6532 Notice that EssentialOcl merges the reflection MOF capability. However its true that getMetaClass() is not applicable to the values of DataTypes since it returns a Class. Good point! I had not considered that. There is also a corollary: the oclIsKindOf() and other operations are defined by OclAny (as would the proposed oclType() operation). This makes them available on data types, except for the OCL collections, which explicitly do not not specialize OclAny. Should we repeat these operations on the CollectionType metaclass? Personally, I don't see that reflection on collection values would be useful in practice, but what do others think? >>> Issue 9405: Wrong subtyping of PropertyCallExp and NavigationCallExp Agree (clarifying why the subtyping is not wrong) >>> Issue 9796: Section: 7.3.4 Agree (Fixing usage of @pre) >>> Issue 9913: Section: 8.3.5 Agree (Adding the missing definitions in concrete syntax part). In fact the FTF, for timing reasons didn't touch the concrete syntax section which become somehow de-synchrnized with the rest. That raises a good question. Should we completely overhaul this section, perhaps also using a more modern notation? Or, should we excise it from this document altogether and let it be specified using a standard notation in a separate document as suggested in Issue 12562? Would anybody have the time for such an effort? I, personally, am rather weak in the practice of formal grammar definition. >>> Issue 10430: Section 7.6.3 Agree (Clarifying number of iterators in forAll). >>> Issue 10432: Section "IteratorExpCS" Agree (No change) >>> Issue 10433: 11.2.3 Agree. Good point. OclVoid cannot conform to OclInvalid. >>> Issue 10434: 11.2.4 (OclInvalid) - similar criticism as 11.2.3 Agree (same as previous). >>> Issue 10436: 11.2.5 Agree (description reformulation). Indeed replacement of OclType by Classifier depends on issue 6532. >>> Issue 10436: 11.2.5 (02) Agree (Re-typing to a supertype does not mean ability to access an overridden property). However still the question whether we allow access to an overriden property is pending. (available in various languages). This may be useful when defining the overriden version of an Operation. But for sure this should not use the oclAsType operator. Replacement of OclType by Classifier depends on issue 6532. Agreed. >>> Issue 10825: ownership of association ends does not matter for traversal in OCL I think this issue is controversial. We should take care not to define behaviors that cannot be easily implemented. Also this may have an impact on reflection. Does it means that when Navigation of association-owned ends is identified as an optional compliance point in Table 2.1, which I think is reasonable as this does have implementation dependencies. we use the reflective MOF interface to look for attributes of a class we obtain also not owned Attributes? Any opinion, reacion here? I don't think that OCL should attempt to change MOF's reflection capability. In any case, the question doesn't arise in EMOF because EMOF doesn't have associations. It would only be a concern in CompleteOcl (UML), but in the UML, the association-owned ends are not features of the corresponding end classifier. I think that the "... is considered as a property of ..." wording in the proposal is too strong and suggests a contradiction with UML semantics. I may have misunderstood your question. Are you, instead, suggesting that an OCL implementation should use MOF reflection in looking up attributes? >>> Issue 10921: TypeType This depends on resolution of issue 6532. Agreed. >>> Issue 10946: Collection element type serialization Agree. Non uniqueness of collection types is important since it gives more freedom on where to place its definition. However, it is important to clarify that it is not mandatory to use the "generatedType" association to store the generated types. Depending on the context of usage, these generated types can also be created within a Package (using ownedType association). Agreed, good point. I gather that the QVT language, for example, does specify a package to own these types? >>> Issue 11097: Dynamic typing with allInstances() I don't think I agree with all the text. I prefer the actual definition notation: allInstances() : Set( T ) Instead of allInstances() : Set( self ) Which is syntactically very hazardous. Yes, I agree that T is clearer and more consistent with other usage in the document. However, this raises the question of how to represent T in the model. OCL currently uses the names T and T2 as type parameters in various places, but the language does not seem to have caught up to the fact that UML 2.x classifiers and operations are templateable elements, and that some of the types that it needs to deal with are actually owned parametered elements. In particular, how does the OCL Standard Library represent T and T2? I can imagine a UML representation, but not so easily an EMOF one. Am I opening a can of worms? It is an important question, though, for the MOF serializations of the metamodel and standard library that I think we need to publish. Now, making the allInstances be an operation of Classifier (the M1 instance representing the UML Classifier metatype) will be, for sure, consistent with the proposed resolution of 6532. So I think this depends on issue 6532. Agreed. More specifically, I believe this kind of change should be part of resolution of 6532 and not be the resolution of this issue. The resolution for issue 11097 should then probably be: Closed, no change. Agreed, good idea. >>> Issue: 11098: Section: 7.4.7, 7.4.9, 9.3.2 Agree (adding implies and let in operator priority definition). >>> Issue 12378: Section 8.2 InvalidType Agree. Terminology clarification. >>> Issue 12419: CollectionType and CollectionKind I believe the resolution is not complete. The example provided by the submitter of the issue shows that the CollectionType cannot be an abstract metaclass since the definition of a OCL constraint really requires instatiating CollectionTypes (Collection(Type) in the provided example). In fact a Collection is "abstract" from a runtime point of view, but not "abstract" from an OCL constraint definition point of view. But in practice this means that the M2 metaclass ColelctionType cannot be abstract. I'm afraid I didn't quite follow your response. Are we agreed that CollectionType being non-abstract and Collection(T) abstract, as they are currently defined, is correct? Or are you suggesting that Collection(T) should also not be abstract? I'm not sure what you are proposing to add to or amend in the resolution text. >>> Issue 12449: no explanations about how to manipulate optional and multivalued attributes Agree (Misunderstanding) >>> Issue 12450: The Tuple constructor is problematic Agree (Misunderstanding) >>> Issue 12484: Section 8.2.1 Type Conformance on page 37 Agree (already discussed) >>> Issue 12485: Section 8.2 page 35 InvalidType Agree (duplicated) Mariano Belaunde Senior Researcher in Modelling Techniques Orange Labs 8 Avenue Pierre Marzin 22300 Lannion France tel +33 2 96 05 30 85 mariano.belaunde@orange-ftgroup.com -- Christian W. Damus Senior Software Developer, Zeligsoft Inc. Component Lead, Eclipse MDT OCL and EMF-QTV E-mail: cdamus@zeligsoft.com mariano.belaunde@orange-ftgroup.com