Traversing from child to parent in derived relation [message #878946] |
Wed, 30 May 2012 04:54  |
Eclipse User |
|
|
|
Hi,
I have observed that it is not possible to traverse from child to parent in derived realtion even though opposites are mentioned on both sides.
Example :
parent.child works fine
child.parent does not work
Any reason for that?
Cheers,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Re: Traversing from child to parent in derived relation [message #879475 is a reply to message #879436] |
Thu, 31 May 2012 05:37   |
Eclipse User |
|
|
|
Hi
Great. I finally grasp the problem. You've given me another stupid case
for my Complete OCL tutorial.
Opposite properties are a facility defined by the UML specification and
realised by EMOF and Ecore. The Ecore realisation uses an
EReference.eOpposite. A double opposite navigation should be an identity
navigation and the built-in realisation using non-derived behaviour does
this. When you specify a derived algorithm, you take control.
You are using an algorithmic definition of the forward property. OCL is
side effect free, so there is some scope for analyzing the forward
algorithm to deduce its inverse. However asOrderedSet() is not
monotonic, it is difficult (probably impossible) to determine how many
candidates were present when a unique one was selected for the Set. So
automated support for OCL defined opposites is going to need non-trivial
symbolic analysis/global model search, which isn't going to be available
any time soon.
So if you define a derived property, with an opposite, it is your
responsibility to provide a derived opposite property too.
Therefore in
property classC#classB : ClassC[*] { ordered derived volatile }
{
derivation: classA.classC->asOrderedSet();
}
....
property classB#classC : ClassB[?] { ordered volatile };
you have two errors:
a) already mentioned; you should use "transient" too
b) The missing opposite OCL derivation should be diagnosed.
The solution to your problem is to define two derived algorithms.
property classC#classB : ClassC[*] { ordered derived transient volatile }
{
derivation: classA.classC->asOrderedSet();
}
....
property classB#classC : ClassB[?] { ordered derived transient volatile };
{
derivation: some-inverse-algorithm;
}
and possibly an invariant for class B
invariant ConsistentOpposite: let doubleOpposites : Set(ClassC) =
classC.classB->asSet() in doubleOpposites->forAll(b | b = self);
If you open your Ecore file with the Sample Ecore Editor, and use Load
Complete OCL Resource to load the attached Complete OCL document, and
Validate, you will get diagnosis of many of the unwise things that can
be attempted with OCL derivation.
This assumes you are using a recent Juno build:
M6 for Load Complete OCL Resource
RC2 for DND of Complete OCL Document
RC3 for Load Complete OCL Resource into OCLinEcore and Papyrus editors
Regards
Ed Willink
On 31/05/2012 09:11, ModelGeek Mising name wrote:
> import ecore : 'http://www.eclipse.org/emf/2002/Ecore#/';
>
> package temp : Test =
> 'http://www.eclipse.org/mdt/ocl/oclinecore/tutorial'
> {
> class ClassA
> {
> attribute ID : ecore::ELongObject { ordered };
> attribute name : String { ordered };
> property classB#classA : ClassB[*] { composes };
> property classC#classA : ClassC[*] { volatile composes };
> }
> class ClassB
> {
> attribute ID : ecore::ELongObject { ordered };
> attribute name : String { ordered };
> property classA#classB : ClassA[?] { ordered };
> property classC#classB : ClassC[*] { ordered derived volatile }
> {
> derivation: classA.classC->asOrderedSet();
> }
> }
> class ClassC
> {
> attribute ID : ecore::ELongObject { ordered };
> attribute name : String { ordered };
> property classA#classC : ClassA[?] { ordered };
> property classB#classC : ClassB[?] { ordered volatile };
> }
> }
/**
* <copyright>
*
* Copyright (c) 2012 E.D.Willink and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* E.D.Willink - Initial API and implementation
*
* </copyright>
*
* This file provides additional validation constraints for use of OCL embedded in Ecore.
*/
import ecore : 'http://www.eclipse.org/emf/2002/Ecore#/'
package ecore
context EModelElement
/**
* Declare a helper operation to map an ok/warning verdict to ok/error.
*/
def: asError(verdict : Boolean) : Boolean = if verdict then true else null endif
/**
* Extra validation for EReference and EAttribute.
*/
context EStructuralFeature
/**
* Declare a helper property to determine whether an EStructuralFeature has an OCL derivation.
*/
def: hasDerivation : Boolean = eAnnotations->select(source.startsWith('http://www.eclipse.org/emf/2002/Ecore/OCL'))->notEmpty()
/**
* If a feature has an OCL derivation, it should be transient; otherwise it is not executed.
*/
inv DerivationIsTransient: hasDerivation implies transient
/**
* If a feature has an OCL derivation, it must be volatile; otherwise the cached value suppresses execution.
*/
inv DerivationIsVolatile: asError(hasDerivation implies volatile)
/**
* If a feature has an OCL derivation, it should not also have a default value.
*/
inv DerivationIsUninitialized: hasDerivation implies defaultValue.oclIsUndefined()
/**
* Extra validation for just EReference.
*/
context EReference
/**
* If a feature has an OCL derivation, it should not compete with built-in containment.
*/
inv DerivationIsNotComposed: asError(hasDerivation implies not containment)
/**
* If a feature has an OCL derivation, it should be not waste time resolving proxies.
*/
inv DerivationDoesNotResolveProxies: hasDerivation implies not resolveProxies
/**
* If a feature has an OCL derivation and an opposite, the opposite should also have an OCL derivation
*/
inv DerivationWithOppositeHasOppositeDerivation: hasDerivation and eOpposite <> null implies eOpposite.hasDerivation
endpackage
|
|
|
|
Powered by
FUDForum. Page generated in 0.04875 seconds