Home » Modeling » OCL » exclusion among attributes of different types
exclusion among attributes of different types [message #71676] |
Fri, 10 July 2009 06:45 |
John T.E. Timm Messages: 161 Registered: July 2009 |
Senior Member |
|
|
I have the following model:
Class1
a : A
b : B
c : C
A
B
C
I am looking to write an OCL invariant that checks whether exactly one of
{Class1.a, Class1.b, Class1.c} is defined at any given time. So far, I
have come up with these 3 alternatives:
Option 1:
(not self.a.oclIsUndefined() and self.b.oclIsUndefined and
self.c.oclIsUndefined)
or
(not self.b.oclIsUndefined() and self.a.oclIsUndefined() and
self.c.oclIsUndefined)
or
(not self.c.oclIsUndefined) and self.a.oclIsUndefined() and
self.b.oclIsUndefined)
Option 2:
(not self.a.oclIsUndefined() implies self.b.oclIsUndefined() and
self.c.oclIsUndefined())
and
(not self.b.oclIsUndefined() implies self.a.oclIsUndefined() and
self.c.oclIsUndefined())
and
(not self.c.oclIsUndefined() implies self.a.oclIsUndefined() and
self.b.oclIsUndefined())
Option 3:
-- As A, B, and C do not have an explicit common super type in the model
-- I cast them to EObject
Bag{self.a.oclAsType(ecore::EObject), self.b.oclAsType(ecore::EObject),
self.c.oclAsType(ecore::EObject)}->select(not oclIsUndefined())->size() = 1
In my specific application, I need to check more than just 3 attributes
and I am looking for the most succinct way possible (without resorting to
using Java). Are there any better alternatives? Is something like Option 3
bad practice?
Thanks,
JT
|
|
|
Re: exclusion among attributes of different types [message #71694 is a reply to message #71676] |
Fri, 10 July 2009 19:05 |
Eclipse User |
|
|
|
Originally posted by: Alexander.Igdalov.borland.com
Hi John,
Option 3 looks good, however, you can make it more concise.
1. by omitting type cast to EObject since oclIsUndefined() operation is
defined on OclAny. NB: OclAny is a common supertype for all objects
(except Collections in OCL 2.0 - however, this exception is dropped in
the next version of the OCL standard). Thus, the type of
'Bag{self.a, self.b, self.c}' is 'Bag(OclAny)'.
2. by using one() iterator to check that there is exactly one element
in the source collection for which some condition is true.
IOW, I mean:
Bag{self.a, self.b, self.c}->one(not oclIsUndefined())
HTH,
Alex.
John T.E. Timm wrote:
> I have the following model:
>
> Class1
> a : A
> b : B
> c : C
> A
> B
> C
>
> I am looking to write an OCL invariant that checks whether exactly one
> of {Class1.a, Class1.b, Class1.c} is defined at any given time. So far,
> I have come up with these 3 alternatives:
>
> Option 1:
> (not self.a.oclIsUndefined() and self.b.oclIsUndefined and
> self.c.oclIsUndefined)
> or
> (not self.b.oclIsUndefined() and self.a.oclIsUndefined() and
> self.c.oclIsUndefined)
> or
> (not self.c.oclIsUndefined) and self.a.oclIsUndefined() and
> self.b.oclIsUndefined)
>
> Option 2:
> (not self.a.oclIsUndefined() implies self.b.oclIsUndefined() and
> self.c.oclIsUndefined())
> and
> (not self.b.oclIsUndefined() implies self.a.oclIsUndefined() and
> self.c.oclIsUndefined())
> and
> (not self.c.oclIsUndefined() implies self.a.oclIsUndefined() and
> self.b.oclIsUndefined())
>
> Option 3:
> -- As A, B, and C do not have an explicit common super type in the model
> -- I cast them to EObject
> Bag{self.a.oclAsType(ecore::EObject), self.b.oclAsType(ecore::EObject),
> self.c.oclAsType(ecore::EObject)}->select(not oclIsUndefined())->size() = 1
>
> In my specific application, I need to check more than just 3 attributes
> and I am looking for the most succinct way possible (without resorting
> to using Java). Are there any better alternatives? Is something like
> Option 3 bad practice?
>
> Thanks,
>
> JT
>
>
|
|
|
Re: exclusion among attributes of different types [message #71713 is a reply to message #71694] |
Sat, 11 July 2009 05:51 |
John T.E. Timm Messages: 161 Registered: July 2009 |
Senior Member |
|
|
Alex:
Thanks for the suggestions. Unfortunately, RSM 7.5.2 (which is running
org.eclipse.ocl 1.2.3) is giving me this error:
Parsing Error: Type Mismatch, No common supertype {A}, {B}
with this constraint:
Bag{self.a, self.b, self.c}->one(not oclIsUndefined())
Any ideas?
Thanks,
JT
Alexander Igdalov wrote:
> Hi John,
> Option 3 looks good, however, you can make it more concise.
> 1. by omitting type cast to EObject since oclIsUndefined() operation is
> defined on OclAny. NB: OclAny is a common supertype for all objects
> (except Collections in OCL 2.0 - however, this exception is dropped in
> the next version of the OCL standard). Thus, the type of
> 'Bag{self.a, self.b, self.c}' is 'Bag(OclAny)'.
> 2. by using one() iterator to check that there is exactly one element
> in the source collection for which some condition is true.
> IOW, I mean:
> Bag{self.a, self.b, self.c}->one(not oclIsUndefined())
> HTH,
> Alex.
> John T.E. Timm wrote:
>> I have the following model:
>>
>> Class1
>> a : A
>> b : B
>> c : C
>> A
>> B
>> C
>>
>> I am looking to write an OCL invariant that checks whether exactly one
>> of {Class1.a, Class1.b, Class1.c} is defined at any given time. So far,
>> I have come up with these 3 alternatives:
>>
>> Option 1:
>> (not self.a.oclIsUndefined() and self.b.oclIsUndefined and
>> self.c.oclIsUndefined)
>> or
>> (not self.b.oclIsUndefined() and self.a.oclIsUndefined() and
>> self.c.oclIsUndefined)
>> or
>> (not self.c.oclIsUndefined) and self.a.oclIsUndefined() and
>> self.b.oclIsUndefined)
>>
>> Option 2:
>> (not self.a.oclIsUndefined() implies self.b.oclIsUndefined() and
>> self.c.oclIsUndefined())
>> and
>> (not self.b.oclIsUndefined() implies self.a.oclIsUndefined() and
>> self.c.oclIsUndefined())
>> and
>> (not self.c.oclIsUndefined() implies self.a.oclIsUndefined() and
>> self.b.oclIsUndefined())
>>
>> Option 3:
>> -- As A, B, and C do not have an explicit common super type in the model
>> -- I cast them to EObject
>> Bag{self.a.oclAsType(ecore::EObject), self.b.oclAsType(ecore::EObject),
>> self.c.oclAsType(ecore::EObject)}->select(not oclIsUndefined())->size() = 1
>>
>> In my specific application, I need to check more than just 3 attributes
>> and I am looking for the most succinct way possible (without resorting
>> to using Java). Are there any better alternatives? Is something like
>> Option 3 bad practice?
>>
>> Thanks,
>>
>> JT
>>
>>
|
|
| | |
Re: exclusion among attributes of different types [message #71769 is a reply to message #71713] |
Sat, 11 July 2009 10:54 |
Eclipse User |
|
|
|
Originally posted by: Alexander.Igdalov.borland.com
John,
What about this workaround then:
Bag{self.a.oclIsUndefined(), self.b.oclIsUndefined(),
self.c.oclIsUndefined()}->one(false)
HTH,
Alex.
John T.E. Timm wrote:
> Alex:
>
> Thanks for the suggestions. Unfortunately, RSM 7.5.2 (which is running
> org.eclipse.ocl 1.2.3) is giving me this error:
>
> Parsing Error: Type Mismatch, No common supertype {A}, {B}
>
> with this constraint:
>
> Bag{self.a, self.b, self.c}->one(not oclIsUndefined())
>
> Any ideas?
>
> Thanks,
>
> JT
>
> Alexander Igdalov wrote:
>
>> Hi John,
>
>> Option 3 looks good, however, you can make it more concise.
>
>> 1. by omitting type cast to EObject since oclIsUndefined() operation
>> is defined on OclAny. NB: OclAny is a common supertype for all objects
>> (except Collections in OCL 2.0 - however, this exception is dropped in
>> the next version of the OCL standard). Thus, the type of
>> 'Bag{self.a, self.b, self.c}' is 'Bag(OclAny)'.
>> 2. by using one() iterator to check that there is exactly one element
>> in the source collection for which some condition is true.
>
>> IOW, I mean:
>
>> Bag{self.a, self.b, self.c}->one(not oclIsUndefined())
>
>> HTH,
>> Alex.
>
>> John T.E. Timm wrote:
>>> I have the following model:
>>>
>>> Class1
>>> a : A
>>> b : B
>>> c : C
>>> A
>>> B
>>> C
>>>
>>> I am looking to write an OCL invariant that checks whether exactly
>>> one of {Class1.a, Class1.b, Class1.c} is defined at any given time.
>>> So far, I have come up with these 3 alternatives:
>>>
>>> Option 1:
>>> (not self.a.oclIsUndefined() and self.b.oclIsUndefined and
>>> self.c.oclIsUndefined)
>>> or
>>> (not self.b.oclIsUndefined() and self.a.oclIsUndefined() and
>>> self.c.oclIsUndefined)
>>> or
>>> (not self.c.oclIsUndefined) and self.a.oclIsUndefined() and
>>> self.b.oclIsUndefined)
>>>
>>> Option 2:
>>> (not self.a.oclIsUndefined() implies self.b.oclIsUndefined() and
>>> self.c.oclIsUndefined())
>>> and
>>> (not self.b.oclIsUndefined() implies self.a.oclIsUndefined() and
>>> self.c.oclIsUndefined())
>>> and
>>> (not self.c.oclIsUndefined() implies self.a.oclIsUndefined() and
>>> self.b.oclIsUndefined())
>>>
>>> Option 3:
>>> -- As A, B, and C do not have an explicit common super type in the model
>>> -- I cast them to EObject
>>> Bag{self.a.oclAsType(ecore::EObject),
>>> self.b.oclAsType(ecore::EObject),
>>> self.c.oclAsType(ecore::EObject)}->select(not
>>> oclIsUndefined())->size() = 1
>>>
>>> In my specific application, I need to check more than just 3
>>> attributes and I am looking for the most succinct way possible
>>> (without resorting to using Java). Are there any better alternatives?
>>> Is something like Option 3 bad practice?
>>>
>>> Thanks,
>>>
>>> JT
>>>
>>>
>
>
|
|
| |
Re: exclusion among attributes of different types [message #71806 is a reply to message #71788] |
Sun, 12 July 2009 03:57 |
John T.E. Timm Messages: 161 Registered: July 2009 |
Senior Member |
|
|
Ed:
As per my original post, I suggested:
Bag{self.a.oclAsType(ecore::EObject), self.b.oclAsType(ecore::EObject),
self.c.oclAsType(ecore::EObject)->select(not oclIsUndefined())->size() = 1
as one possibility for exclusion among attributes of different types. I
understand the portability issues, but was having problems trying to use
OclAny as the common super type which is what Alex recommended in the
following solution:
Bag{self.a, self.b, self.c)->one(not oclIsUndefined())
This option, which appears to be the best solution, yields the following
error:
Parsing Error: Type Mismatch, No common supertype {A}, {B}
Which is due to this bug (in OCL 1.2.3):
https://bugs.eclipse.org/bugs/show_bug.cgi?id=260403
Therefore, as a *workaround* for the bug (not for the EObject based
option), Alex suggested this:
Bag{self.a.oclIsUndefined(), self.b.oclIsUndefined(),
self.c.oclIsUndefined())->one(false)
Which will work well for me until I can upgrade to OCL 1.3.
Thanks,
JT
Ed Willink wrote:
> Alexander Igdalov wrote:
>> John,
>>
>> What about this workaround then:
>>
>> Bag{self.a.oclIsUndefined(), self.b.oclIsUndefined(),
>> self.c.oclIsUndefined()}->one(false)
>>
>> HTH,
>> Alex.
> Hardly a workaround; a much better solution.
> Anything involving EObject has major portability issues
> and anything involving ecore:: has issues in mapping the
> name ecore to an appropriate meta-model.
> Regards
> Ed Willink
|
|
|
Re: exclusion among attributes of different types [message #71861 is a reply to message #71769] |
Wed, 15 July 2009 00:15 |
John T.E. Timm Messages: 161 Registered: July 2009 |
Senior Member |
|
|
Alex:
I tried:
Bag{self.a.oclIsUndefined(), self.b.oclIsUndefined(),
self.c.oclIsUndefined()}->one(false)
and was unable to get it working. So I tried this:
Bag{false, true, true}->one(false)
which also did not work. Then, when I changed it to this:
Bag{false, true, true}->one(x|x=false)
it seemed to work. So apparently, OCL 1.2.3 does not like true or false by
itself in the ->one(expr). Have you experienced such behavior?
Thanks,
JT
Alexander Igdalov wrote:
> John,
> What about this workaround then:
> Bag{self.a.oclIsUndefined(), self.b.oclIsUndefined(),
> self.c.oclIsUndefined()}->one(false)
> HTH,
> Alex.
> John T.E. Timm wrote:
>> Alex:
>>
>> Thanks for the suggestions. Unfortunately, RSM 7.5.2 (which is running
>> org.eclipse.ocl 1.2.3) is giving me this error:
>>
>> Parsing Error: Type Mismatch, No common supertype {A}, {B}
>>
>> with this constraint:
>>
>> Bag{self.a, self.b, self.c}->one(not oclIsUndefined())
>>
>> Any ideas?
>>
>> Thanks,
>>
>> JT
>>
>> Alexander Igdalov wrote:
>>
>>> Hi John,
>>
>>> Option 3 looks good, however, you can make it more concise.
>>
>>> 1. by omitting type cast to EObject since oclIsUndefined() operation
>>> is defined on OclAny. NB: OclAny is a common supertype for all objects
>>> (except Collections in OCL 2.0 - however, this exception is dropped in
>>> the next version of the OCL standard). Thus, the type of
>>> 'Bag{self.a, self.b, self.c}' is 'Bag(OclAny)'.
>>> 2. by using one() iterator to check that there is exactly one element
>>> in the source collection for which some condition is true.
>>
>>> IOW, I mean:
>>
>>> Bag{self.a, self.b, self.c}->one(not oclIsUndefined())
>>
>>> HTH,
>>> Alex.
>>
>>> John T.E. Timm wrote:
>>>> I have the following model:
>>>>
>>>> Class1
>>>> a : A
>>>> b : B
>>>> c : C
>>>> A
>>>> B
>>>> C
>>>>
>>>> I am looking to write an OCL invariant that checks whether exactly
>>>> one of {Class1.a, Class1.b, Class1.c} is defined at any given time.
>>>> So far, I have come up with these 3 alternatives:
>>>>
>>>> Option 1:
>>>> (not self.a.oclIsUndefined() and self.b.oclIsUndefined and
>>>> self.c.oclIsUndefined)
>>>> or
>>>> (not self.b.oclIsUndefined() and self.a.oclIsUndefined() and
>>>> self.c.oclIsUndefined)
>>>> or
>>>> (not self.c.oclIsUndefined) and self.a.oclIsUndefined() and
>>>> self.b.oclIsUndefined)
>>>>
>>>> Option 2:
>>>> (not self.a.oclIsUndefined() implies self.b.oclIsUndefined() and
>>>> self.c.oclIsUndefined())
>>>> and
>>>> (not self.b.oclIsUndefined() implies self.a.oclIsUndefined() and
>>>> self.c.oclIsUndefined())
>>>> and
>>>> (not self.c.oclIsUndefined() implies self.a.oclIsUndefined() and
>>>> self.b.oclIsUndefined())
>>>>
>>>> Option 3:
>>>> -- As A, B, and C do not have an explicit common super type in the model
>>>> -- I cast them to EObject
>>>> Bag{self.a.oclAsType(ecore::EObject),
>>>> self.b.oclAsType(ecore::EObject),
>>>> self.c.oclAsType(ecore::EObject)}->select(not
>>>> oclIsUndefined())->size() = 1
>>>>
>>>> In my specific application, I need to check more than just 3
>>>> attributes and I am looking for the most succinct way possible
>>>> (without resorting to using Java). Are there any better alternatives?
>>>> Is something like Option 3 bad practice?
>>>>
>>>> Thanks,
>>>>
>>>> JT
>>>>
>>>>
>>
>>
|
|
| |
Re: exclusion among attributes of different types [message #71900 is a reply to message #71881] |
Wed, 15 July 2009 07:22 |
John T.E. Timm Messages: 161 Registered: July 2009 |
Senior Member |
|
|
Ed:
Thanks for the clarification on using ->one(expr). If this example:
Bag{false, true, true}->one(false)
is too simple to evaluate as desired without my elaboration x | x = false.
Then why does this expression:
Bag{self.a.oclIsUndefined(), self.b.oclIsUndefined(),
self.c.oclIsUndefined()}->one(false)
produce identical results to the example above when one and only one
attribute is set? Whereas this expression:
Bag{self.a.oclIsUndefined(), self.b.oclIsUndefined(),
self.c.oclIsUndefined()}->one(x | x = false)
produces the desired results when one and only one attribute is set. Does
this expression suffer from the ills as the "too simple" example? The
syntax given in the OCL 2.0 spec states that in:
source->one(iterator | body)
iterator *may* have at most one iterator variable. I would assume that the
language would be *must* if the iterator variable was always required.
However, given the above results, it would appear that no "shorthand"
notation exists such that source->one(false) has equivalent semantics to
source->one(x | x = false). Is my understanding correct?
Thanks,
JT
Ed Willink wrote:
> John T.E. Timm wrote:
>> So I tried this:
>>
>> Bag{false, true, true}->one(false)
>>
>> which also did not work. Then, when I changed it to this:
>>
>> Bag{false, true, true}->one(x|x=false)
>>
>> it seemed to work. So apparently, OCL 1.2.3 does not like true or false
>> by itself in the ->one(expr). Have you experienced such behavior?
> This is correct behaviour.
> "one
> Results in true if there is exactly one element in the source collection
> for which body is true."
> So the too simple example has three elements for each of which the body
> is false (regardless of the element value).
> Your elaboration introduces the required data dependence.
> Regards
> Ed Willink
|
|
|
Re: exclusion among attributes of different types [message #71976 is a reply to message #71900] |
Wed, 15 July 2009 09:34 |
Ed Willink Messages: 7671 Registered: July 2009 |
Senior Member |
|
|
Hi John
At first reading I thought you had found a bug, but with more careful
reading I think you have just repeated the misunderstanding.
Any expression of the form
Bag{x, y, ...}->one(false)
with any number of elements should return false.
Bag{x}->one(true)
should return true.
The body is evaluated in the iteration context, not with the iteration
value, so the evaluation is data value independent.
You must use the iterator value for the evaluation to use it.
Your examples are shorthand for
...->one(x | false)
not
...->one(x | x = false)
Regards
Ed Willink
John T.E. Timm wrote:
> Ed:
>
> Thanks for the clarification on using ->one(expr). If this example:
>
> Bag{false, true, true}->one(false)
>
> is too simple to evaluate as desired without my elaboration x | x =
> false. Then why does this expression:
>
> Bag{self.a.oclIsUndefined(), self.b.oclIsUndefined(),
> self.c.oclIsUndefined()}->one(false)
>
> produce identical results to the example above when one and only one
> attribute is set? Whereas this expression:
>
> Bag{self.a.oclIsUndefined(), self.b.oclIsUndefined(),
> self.c.oclIsUndefined()}->one(x | x = false)
>
> produces the desired results when one and only one attribute is set.
> Does this expression suffer from the ills as the "too simple" example?
> The syntax given in the OCL 2.0 spec states that in:
>
> source->one(iterator | body)
>
> iterator *may* have at most one iterator variable. I would assume that
> the language would be *must* if the iterator variable was always
> required. However, given the above results, it would appear that no
> "shorthand" notation exists such that source->one(false) has equivalent
> semantics to source->one(x | x = false). Is my understanding correct?
>
> Thanks,
>
> JT
>
> Ed Willink wrote:
>
>> John T.E. Timm wrote:
>>> So I tried this:
>>>
>>> Bag{false, true, true}->one(false)
>>>
>>> which also did not work. Then, when I changed it to this:
>>>
>>> Bag{false, true, true}->one(x|x=false)
>>>
>>> it seemed to work. So apparently, OCL 1.2.3 does not like true or
>>> false by itself in the ->one(expr). Have you experienced such behavior?
>
>> This is correct behaviour.
>
>> "one
>
>> Results in true if there is exactly one element in the source
>> collection for which body is true."
>
>> So the too simple example has three elements for each of which the
>> body is false (regardless of the element value).
>
>> Your elaboration introduces the required data dependence.
>
>> Regards
>
>> Ed Willink
>
>
|
|
|
Re: exclusion among attributes of different types [message #71995 is a reply to message #71976] |
Wed, 15 July 2009 10:26 |
Eclipse User |
|
|
|
Originally posted by: Alexander.Igdalov.borland.com
Hi Ed,
I totally agree with you. Sorry for having confused you, John.
Your assumption that
Bag{x, y, ...}->one(false)
is equivalent to
Bag{x, y, ...}->one(i | i = false)
would be correct if 'false' were not a literal but a property of the
collection element type.
Note, that the case below looks similar but is actually different:
Bag{x, y, ...}->one(oclIsUndefined())
It is equal to 'Bag{x, y, ...}->one(i | i.oclIsUndefined())' because of
the implicit source resolution of oclIsUndefined().
Cheers,
Alex.
Ed Willink wrote:
> Hi John
>
> At first reading I thought you had found a bug, but with more careful
> reading I think you have just repeated the misunderstanding.
>
> Any expression of the form
>
> Bag{x, y, ...}->one(false)
>
> with any number of elements should return false.
>
> Bag{x}->one(true)
>
> should return true.
>
> The body is evaluated in the iteration context, not with the iteration
> value, so the evaluation is data value independent.
>
> You must use the iterator value for the evaluation to use it.
>
> Your examples are shorthand for
>
> ...->one(x | false)
>
> not
>
> ...->one(x | x = false)
>
> Regards
>
> Ed Willink
>
>
> John T.E. Timm wrote:
>> Ed:
>>
>> Thanks for the clarification on using ->one(expr). If this example:
>>
>> Bag{false, true, true}->one(false)
>>
>> is too simple to evaluate as desired without my elaboration x | x =
>> false. Then why does this expression:
>>
>> Bag{self.a.oclIsUndefined(), self.b.oclIsUndefined(),
>> self.c.oclIsUndefined()}->one(false)
>>
>> produce identical results to the example above when one and only one
>> attribute is set? Whereas this expression:
>>
>> Bag{self.a.oclIsUndefined(), self.b.oclIsUndefined(),
>> self.c.oclIsUndefined()}->one(x | x = false)
>>
>> produces the desired results when one and only one attribute is set.
>> Does this expression suffer from the ills as the "too simple" example?
>> The syntax given in the OCL 2.0 spec states that in:
>>
>> source->one(iterator | body)
>>
>> iterator *may* have at most one iterator variable. I would assume that
>> the language would be *must* if the iterator variable was always
>> required. However, given the above results, it would appear that no
>> "shorthand" notation exists such that source->one(false) has
>> equivalent semantics to source->one(x | x = false). Is my
>> understanding correct?
>>
>> Thanks,
>>
>> JT
>>
>> Ed Willink wrote:
>>
>>> John T.E. Timm wrote:
>>>> So I tried this:
>>>>
>>>> Bag{false, true, true}->one(false)
>>>>
>>>> which also did not work. Then, when I changed it to this:
>>>>
>>>> Bag{false, true, true}->one(x|x=false)
>>>>
>>>> it seemed to work. So apparently, OCL 1.2.3 does not like true or
>>>> false by itself in the ->one(expr). Have you experienced such behavior?
>>
>>> This is correct behaviour.
>>
>>> "one
>>
>>> Results in true if there is exactly one element in the source
>>> collection for which body is true."
>>
>>> So the too simple example has three elements for each of which the
>>> body is false (regardless of the element value).
>>
>>> Your elaboration introduces the required data dependence.
>>
>>> Regards
>>
>>> Ed Willink
>>
>>
|
|
|
Goto Forum:
Current Time: Fri Sep 27 00:31:15 GMT 2024
Powered by FUDForum. Page generated in 0.04732 seconds
|