org.eclipse.ocl.examples.impactanalyzer.instanceScope
Class AbstractNavigationStep

java.lang.Object
  extended by org.eclipse.ocl.examples.impactanalyzer.instanceScope.AbstractNavigationStep
All Implemented Interfaces:
NavigationStep, SemanticComparable
Direct Known Subclasses:
AbsoluteNavigationStep, AllInstancesNavigationStep, AssociationNavigationStep, CompositeNavigationStep, IdentityNavigationStep, IndirectingStep, OppositePropertyNavigationStep, PredicateCheckNavigationStep, RefImmediateCompositeNavigationStep

public abstract class AbstractNavigationStep
extends java.lang.Object
implements NavigationStep

Abstract implementation of the NavigationStep interface. Provides fields for source and target type and performs the necessary type checks in navigate(Set, TracebackCache, Notification). Furthermore, does the unfolding of the from argument to navigate(Set, TracebackCache, Notification) and dispatches for individual objects to the navigate(AnnotatedEObject, TracebackCache, Notification) operation to be implemented by all subclasses. Furthermore, generaly bookkeeping facilities are implemented here, such as counting cache misses, managing an ID and maintaining for which OCLExpressions this is the corresponding navigation step (see debugInfo).

This class implements the observer pattern specified by the NavigationStep interface for setting the source and target type and for defining this step as always empty.

A default Object.hashCode() and Object.equals(java.lang.Object) implementation is provided based on the behavior of this step. Navigation steps are only allowed to call themselves equal to another step if for all from objects their navigate(AnnotatedEObject, TracebackCache, Notification) operation returns equal results for an equal model state and the same original change notification.

Subclasses have to make sure that any modification to equals/hashCode-related parts of the object's state are announced by firing HashCodeChangeListener.beforeHashCodeChange(NavigationStep, int) before and HashCodeChangeListener.afterHashCodeChange(NavigationStep, int) after the change. This class manages this for those state changes affecting this class's implementation of equals/hashCode.

Author:
Axel Uhl

Constructor Summary
AbstractNavigationStep(org.eclipse.emf.ecore.EClass sourceType, org.eclipse.emf.ecore.EClass targetType, OCLExpression debugInfo)
           
 
Method Summary
 void addAlwaysEmptyChangeListener(AlwaysEmptyChangeListener listener)
          Whenever the result of NavigationStep.isAlwaysEmpty() changes, registered listeners will be informed by calling their ChangeListener#alwaysEmptyChanged(NavigationStep) method with this step as parameter.
 void addEnteringScopes(java.util.Set<Variable> enteringScope)
          Sets the set of variables that come into scope when this navigation step is navigated.
 void addExpressionForWhichThisIsNavigationStep(OCLExpression oclExpression)
          Adds oclExpression as an expression for which this is the computed navigation step.
 void addHashCodeChangeListener(HashCodeChangeListener listener)
           
 void addLeavingScopes(java.util.Set<Variable> leavingScopes)
          Adds variables to the set of variables leaving scope when navigating this step.
 void addSourceTypeChangeListener(SourceTypeChangeListener listener)
          Whenever the result of NavigationStep.getSourceType() changes, registered listeners will be informed by calling their SourceTypeChangeListener.sourceTypeChanged(NavigationStep) method with this step as parameter.
 void addTargetTypeChangeListener(TargetTypeChangeListener listener)
          Whenever the result of NavigationStep.getTargetType() changes, registered listeners will be informed by calling their TargetTypeChangeListener.targetTypeChanged(NavigationStep) method with this step as parameter.
protected  AnnotatedEObject annotateEObject(AnnotatedEObject fromObject, org.eclipse.emf.ecore.EObject next)
           
 java.lang.String contentToString(java.util.Map<NavigationStep,java.lang.Integer> visited, int indent)
           
 int distinctSize()
           
protected  int distinctSize(java.util.Set<SemanticIdentity> visited)
           
protected  boolean doesSourceTypeMatch(AnnotatedEObject fromObject)
           
protected  void fireAfterHashCodeChange(int token)
           
protected  void fireBeforeHashCodeChange(int token)
           
 java.util.Set<OCLExpression> getDebugInfo()
          Optionally, a navigation step may tell for which OCL expression it was mainly created.
 java.util.Set<Variable> getEnteringScopes()
          Returns the variables that come into scope when this navigation step is navigated.
 int getId()
           
 java.util.Set<Variable> getLeavingScopes()
          Returns the variables that fall out of scope when navigating this step.
 int getNavigateCounter()
           
 int getResultObjectsCounter()
           
 SemanticIdentity getSemanticIdentity()
           
 org.eclipse.emf.ecore.EClass getSourceType()
           
 org.eclipse.emf.ecore.EClass getTargetType()
           
protected static boolean haveIntersectingSubclassTree(org.eclipse.emf.ecore.EClass a, org.eclipse.emf.ecore.EClass b)
          For a or b being null (a yet unresolved IndirectingStep, probablu), we unfortunately don't know yet if there will be a non-empty subtype tree intersection.
protected  void incrementNavigateCounter(java.util.Set<AnnotatedEObject> from)
          The incrementing of the navigate counter gets its own protected method because subclasses must be able to suppress incrementing under special circumstances (e.g.
 boolean isAbsolute()
          By default, navigation steps depend on the object set to which they are applied.
 boolean isAlwaysEmpty()
          By default it is expected that steps return non-empty sets in some cases.
protected abstract  java.util.Set<AnnotatedEObject> navigate(AnnotatedEObject fromObject, TracebackCache cache, org.eclipse.emf.common.notify.Notification changeEvent)
           
 java.util.Set<AnnotatedEObject> navigate(java.util.Set<AnnotatedEObject> from, TracebackCache cache, org.eclipse.emf.common.notify.Notification changeEvent)
          Breaks down the navigation from the from set to the individual elements in from and manages the type checks.
protected static int newTokenForFiringHashCodeChangeEvent()
           
protected  void setAlwaysEmpty()
           
 int size()
          The default size in particular for atomic navigation steps is 1.
protected  int size(java.util.Set<NavigationStep> visited)
          The default size in particular for atomic navigation steps is 1.
 java.lang.String toString()
           
protected  java.lang.String toString(java.util.Map<NavigationStep,java.lang.Integer> visited, int indent)
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

AbstractNavigationStep

public AbstractNavigationStep(org.eclipse.emf.ecore.EClass sourceType,
                              org.eclipse.emf.ecore.EClass targetType,
                              OCLExpression debugInfo)
Method Detail

newTokenForFiringHashCodeChangeEvent

protected static int newTokenForFiringHashCodeChangeEvent()

getTargetType

public org.eclipse.emf.ecore.EClass getTargetType()
Specified by:
getTargetType in interface NavigationStep

getSourceType

public org.eclipse.emf.ecore.EClass getSourceType()
Specified by:
getSourceType in interface NavigationStep

addAlwaysEmptyChangeListener

public void addAlwaysEmptyChangeListener(AlwaysEmptyChangeListener listener)
Description copied from interface: NavigationStep
Whenever the result of NavigationStep.isAlwaysEmpty() changes, registered listeners will be informed by calling their ChangeListener#alwaysEmptyChanged(NavigationStep) method with this step as parameter.

Specified by:
addAlwaysEmptyChangeListener in interface NavigationStep

addSourceTypeChangeListener

public void addSourceTypeChangeListener(SourceTypeChangeListener listener)
Description copied from interface: NavigationStep
Whenever the result of NavigationStep.getSourceType() changes, registered listeners will be informed by calling their SourceTypeChangeListener.sourceTypeChanged(NavigationStep) method with this step as parameter.

Specified by:
addSourceTypeChangeListener in interface NavigationStep

addTargetTypeChangeListener

public void addTargetTypeChangeListener(TargetTypeChangeListener listener)
Description copied from interface: NavigationStep
Whenever the result of NavigationStep.getTargetType() changes, registered listeners will be informed by calling their TargetTypeChangeListener.targetTypeChanged(NavigationStep) method with this step as parameter.

Specified by:
addTargetTypeChangeListener in interface NavigationStep

addHashCodeChangeListener

public void addHashCodeChangeListener(HashCodeChangeListener listener)
Specified by:
addHashCodeChangeListener in interface NavigationStep

fireAfterHashCodeChange

protected void fireAfterHashCodeChange(int token)

fireBeforeHashCodeChange

protected void fireBeforeHashCodeChange(int token)

addExpressionForWhichThisIsNavigationStep

public void addExpressionForWhichThisIsNavigationStep(OCLExpression oclExpression)
Description copied from interface: NavigationStep
Adds oclExpression as an expression for which this is the computed navigation step. Multiple expressions may share the same navigation step. An expression added here will be returned in the set resulting from NavigationStep.getDebugInfo().

Specified by:
addExpressionForWhichThisIsNavigationStep in interface NavigationStep

getNavigateCounter

public int getNavigateCounter()

getResultObjectsCounter

public int getResultObjectsCounter()

getDebugInfo

public java.util.Set<OCLExpression> getDebugInfo()
Description copied from interface: NavigationStep
Optionally, a navigation step may tell for which OCL expression it was mainly created. This can aid the impact analysis debugging process. May return null.

Specified by:
getDebugInfo in interface NavigationStep
Returns:

annotateEObject

protected AnnotatedEObject annotateEObject(AnnotatedEObject fromObject,
                                           org.eclipse.emf.ecore.EObject next)

incrementNavigateCounter

protected void incrementNavigateCounter(java.util.Set<AnnotatedEObject> from)
The incrementing of the navigate counter gets its own protected method because subclasses must be able to suppress incrementing under special circumstances (e.g. suppress count of additional recursive round trip in IndirectingStep)


navigate

public java.util.Set<AnnotatedEObject> navigate(java.util.Set<AnnotatedEObject> from,
                                                TracebackCache cache,
                                                org.eclipse.emf.common.notify.Notification changeEvent)
Breaks down the navigation from the from set to the individual elements in from and manages the type checks.

Specified by:
navigate in interface NavigationStep
Parameters:
cache - keys are lists of which the first element (index 0) is the NavigationStep, the second element (index 1) the from-object (of type AnnotatedEObject) for which to look up any previously computed results.

doesSourceTypeMatch

protected boolean doesSourceTypeMatch(AnnotatedEObject fromObject)

isAbsolute

public boolean isAbsolute()
By default, navigation steps depend on the object set to which they are applied.

Specified by:
isAbsolute in interface NavigationStep
Returns:
always false

isAlwaysEmpty

public boolean isAlwaysEmpty()
By default it is expected that steps return non-empty sets in some cases.

Specified by:
isAlwaysEmpty in interface NavigationStep
Returns:
always false

setAlwaysEmpty

protected void setAlwaysEmpty()

navigate

protected abstract java.util.Set<AnnotatedEObject> navigate(AnnotatedEObject fromObject,
                                                            TracebackCache cache,
                                                            org.eclipse.emf.common.notify.Notification changeEvent)

toString

public java.lang.String toString()
Overrides:
toString in class java.lang.Object

toString

protected java.lang.String toString(java.util.Map<NavigationStep,java.lang.Integer> visited,
                                    int indent)

contentToString

public java.lang.String contentToString(java.util.Map<NavigationStep,java.lang.Integer> visited,
                                        int indent)

haveIntersectingSubclassTree

protected static boolean haveIntersectingSubclassTree(org.eclipse.emf.ecore.EClass a,
                                                      org.eclipse.emf.ecore.EClass b)
For a or b being null (a yet unresolved IndirectingStep, probablu), we unfortunately don't know yet if there will be a non-empty subtype tree intersection. Therefore, this method returns true if either of a or b is null


size

public int size()
The default size in particular for atomic navigation steps is 1.

Specified by:
size in interface NavigationStep

size

protected int size(java.util.Set<NavigationStep> visited)
The default size in particular for atomic navigation steps is 1.


distinctSize

public int distinctSize()
Specified by:
distinctSize in interface NavigationStep

distinctSize

protected int distinctSize(java.util.Set<SemanticIdentity> visited)

getId

public int getId()

getSemanticIdentity

public SemanticIdentity getSemanticIdentity()
Specified by:
getSemanticIdentity in interface SemanticComparable

getLeavingScopes

public java.util.Set<Variable> getLeavingScopes()
Description copied from interface: NavigationStep
Returns the variables that fall out of scope when navigating this step. Scopes are given in form of Variables. Note that variables leaving scope can immediately come into scope again, thus occurring in the results of NavigationStep.getLeavingScopes() as well as NavigationStep.getEnteringScopes(). It just means that the variable shows up in a new dynamic scope.

Specified by:
getLeavingScopes in interface NavigationStep
Returns:
always non-null, but possibly empty set of expressions that form scopes that are left when this step is navigated.

addLeavingScopes

public void addLeavingScopes(java.util.Set<Variable> leavingScopes)
Description copied from interface: NavigationStep
Adds variables to the set of variables leaving scope when navigating this step. Scopes are given in form of Variables. Note that variables leaving scope can immediately come into scope again, thus occurring in the results of NavigationStep.getLeavingScopes() as well as NavigationStep.getEnteringScopes(). It just means that the variable shows up in a new dynamic scope.

Specified by:
addLeavingScopes in interface NavigationStep
Parameters:
leavingScopes - the set of Variables that fall out of scope by navigating this step.

getEnteringScopes

public java.util.Set<Variable> getEnteringScopes()
Description copied from interface: NavigationStep
Returns the variables that come into scope when this navigation step is navigated. It is given as an Variable.

Specified by:
getEnteringScopes in interface NavigationStep
Returns:
always non-null, but possibly empty set of expressions that form scopes that are entered when this step is navigated.

addEnteringScopes

public void addEnteringScopes(java.util.Set<Variable> enteringScope)
Description copied from interface: NavigationStep
Sets the set of variables that come into scope when this navigation step is navigated. It is given as an Set>|Variable>.

Specified by:
addEnteringScopes in interface NavigationStep
Parameters:
enteringScope - the set of Variables representing the variables getting into scope by navigating this step.