public abstract class AbstractNavigationStep extends java.lang.Object implements NavigationStep
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 OCLExpression
s 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.
Constructor and Description |
---|
AbstractNavigationStep(org.eclipse.emf.ecore.EClass sourceType,
org.eclipse.emf.ecore.EClass targetType,
OCLExpression debugInfo) |
Modifier and Type | Method and Description |
---|---|
void |
addAlwaysEmptyChangeListener(AlwaysEmptyChangeListener listener)
Whenever the result of
NavigationStep.isAlwaysEmpty() changes, registered listeners will be informed by calling their
AlwaysEmptyChangeListener.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) |
public AbstractNavigationStep(org.eclipse.emf.ecore.EClass sourceType, org.eclipse.emf.ecore.EClass targetType, OCLExpression debugInfo)
protected static int newTokenForFiringHashCodeChangeEvent()
public org.eclipse.emf.ecore.EClass getTargetType()
getTargetType
in interface NavigationStep
public org.eclipse.emf.ecore.EClass getSourceType()
getSourceType
in interface NavigationStep
public void addAlwaysEmptyChangeListener(AlwaysEmptyChangeListener listener)
NavigationStep
NavigationStep.isAlwaysEmpty()
changes, registered listeners will be informed by calling their
AlwaysEmptyChangeListener.alwaysEmptyChanged(NavigationStep)
method with this step as parameter.addAlwaysEmptyChangeListener
in interface NavigationStep
public void addSourceTypeChangeListener(SourceTypeChangeListener listener)
NavigationStep
NavigationStep.getSourceType()
changes, registered listeners will be informed by calling their
SourceTypeChangeListener.sourceTypeChanged(NavigationStep)
method with this step as parameter.addSourceTypeChangeListener
in interface NavigationStep
public void addTargetTypeChangeListener(TargetTypeChangeListener listener)
NavigationStep
NavigationStep.getTargetType()
changes, registered listeners will be informed by calling their
TargetTypeChangeListener.targetTypeChanged(NavigationStep)
method with this step as parameter.addTargetTypeChangeListener
in interface NavigationStep
public void addHashCodeChangeListener(HashCodeChangeListener listener)
addHashCodeChangeListener
in interface NavigationStep
protected void fireAfterHashCodeChange(int token)
protected void fireBeforeHashCodeChange(int token)
public void addExpressionForWhichThisIsNavigationStep(OCLExpression oclExpression)
NavigationStep
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()
.addExpressionForWhichThisIsNavigationStep
in interface NavigationStep
public int getNavigateCounter()
public int getResultObjectsCounter()
public java.util.Set<OCLExpression> getDebugInfo()
NavigationStep
getDebugInfo
in interface NavigationStep
protected AnnotatedEObject annotateEObject(AnnotatedEObject fromObject, org.eclipse.emf.ecore.EObject next)
protected void incrementNavigateCounter(java.util.Set<AnnotatedEObject> from)
public java.util.Set<AnnotatedEObject> navigate(java.util.Set<AnnotatedEObject> from, TracebackCache cache, org.eclipse.emf.common.notify.Notification changeEvent)
navigate
in interface NavigationStep
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.protected boolean doesSourceTypeMatch(AnnotatedEObject fromObject)
public boolean isAbsolute()
isAbsolute
in interface NavigationStep
public boolean isAlwaysEmpty()
isAlwaysEmpty
in interface NavigationStep
protected void setAlwaysEmpty()
protected abstract java.util.Set<AnnotatedEObject> navigate(AnnotatedEObject fromObject, TracebackCache cache, org.eclipse.emf.common.notify.Notification changeEvent)
public java.lang.String toString()
toString
in class java.lang.Object
protected java.lang.String toString(java.util.Map<NavigationStep,java.lang.Integer> visited, int indent)
public java.lang.String contentToString(java.util.Map<NavigationStep,java.lang.Integer> visited, int indent)
protected static boolean haveIntersectingSubclassTree(org.eclipse.emf.ecore.EClass a, org.eclipse.emf.ecore.EClass b)
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 nullpublic int size()
size
in interface NavigationStep
protected int size(java.util.Set<NavigationStep> visited)
public int distinctSize()
distinctSize
in interface NavigationStep
protected int distinctSize(java.util.Set<SemanticIdentity> visited)
public int getId()
public SemanticIdentity getSemanticIdentity()
getSemanticIdentity
in interface SemanticComparable
public java.util.Set<Variable> getLeavingScopes()
NavigationStep
Variable
s. 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.getLeavingScopes
in interface NavigationStep
null
, but possibly empty set of expressions that form scopes that are left when this
step is navigated.public void addLeavingScopes(java.util.Set<Variable> leavingScopes)
NavigationStep
Variable
s. 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.addLeavingScopes
in interface NavigationStep
leavingScopes
- the set of Variable
s that fall out of scope by navigating this step.public java.util.Set<Variable> getEnteringScopes()
NavigationStep
Variable
.getEnteringScopes
in interface NavigationStep
null
, but possibly empty set of expressions that form scopes that are entered when this
step is navigated.public void addEnteringScopes(java.util.Set<Variable> enteringScope)
NavigationStep
Set>Variable
>
.addEnteringScopes
in interface NavigationStep
enteringScope
- the set of Variable
s representing the variables getting into scope by navigating this step.