|
|
Re: Traversing from child to parent in derived relation [message #879030 is a reply to message #878969] |
Wed, 30 May 2012 11:43 |
ModelGeek Mising name Messages: 550 Registered: June 2011 |
Senior Member |
|
|
Hi,
here comes an example
there are 3 classes ClassA, ClassB, ClassC. ClassA is directly connected ith ClassB and ClassC but ClassC and ClassB are connected through derived relation.
import ecore : 'http://www.eclipse.org/emf/2002/Ecore#/';
package temp : EAAT = '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 composes }
{
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 };
}
}
now if you take a dynamic instance of ClassA and add one instance of both ClassB and ClassC as child. Now you can use OCL Console and use ClassB's object as context.
Now self.classC statement will return you instance of ClassC but if you make ClassC's object as context in OCL Console and evaluate self.classB then it will not return anything. (Used Eclipse Juno). Even in UI you chould classB's object is holding ClassC's object in property classC but ClassC's object does not have ClassB's Object.
Even i have tried by removing "composes" in ClassB's derived property but same problem
property classC#classB : ClassC[*] { ordered derived}
[Updated on: Wed, 30 May 2012 11:48] Report message to a moderator
|
|
|
|
|
|
|
|
Re: Traversing from child to parent in derived relation [message #879142 is a reply to message #879117] |
Wed, 30 May 2012 15:41 |
ModelGeek Mising name Messages: 550 Registered: June 2011 |
Senior Member |
|
|
Actually i have a derived boolean attribute and its derived statement tries to traverse through number of relations to find a specific object and it might need to traverse using derived relation(from child to parent) and that is where it is unable to do that. In case of parent to child(derived realtion) is works fine.
The example you have written is not for derived relation.
In my earlier example, i want to traverse from ClassC(child) to ClassB(parent).
Derived Relation = Derived Property
property classC#classB : ClassC[*] { ordered derived }
{
derivation: classA.classC->asOrderedSet();
}
Hope i have explained it better this time.
thanks alot for support.
Cheers
[Updated on: Wed, 30 May 2012 15:42] Report message to a moderator
|
|
|
|
|
|
|
|
|
Re: Traversing from child to parent in derived relation [message #879475 is a reply to message #879436] |
Thu, 31 May 2012 09:37 |
Ed Willink Messages: 7669 Registered: July 2009 |
Senior Member |
|
|
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.05352 seconds