Package org.apache.sis.metadata
Class MetadataVisitor<R>
java.lang.Object
org.apache.sis.metadata.MetadataVisitor<R>
- Type Parameters:
R
- the type of result of walking in the metadata.
- Direct Known Subclasses:
HashCode
,MetadataCopier
,Pruner
,StateChanger
A visitor of metadata properties with a safety against infinite recursivity.
The visitor may compute a result, for example a hash code value or a boolean
testing whether the metadata is empty. Each
MetadataVisitor
instance
is used by one thread; this class does not need to be thread-safe.- Since:
- 1.0
- Version:
- 1.0
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescription(package private) static enum
Filter the properties to visit. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate boolean
Value of theSemaphores.NULL_COLLECTION
flag when we started the walk.private int
Count of nested calls towalk(MetadataStandard, Class, Object, boolean)
method.private String[]
The name of the property being visited as the last element of the queue.(package private) static final Object
Sentinel value that may be returned byvisit(Class, Object)
for notifying the walker to stop.A guard against infinite recursivity inwalk(MetadataStandard, Class, Object, boolean)
. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescription(package private) ThreadLocal
<? extends MetadataVisitor<?>> creator()
The thread-local variable that created thisMetadataVisitor
instance.Returns the path to the currently visited property.(package private) MetadataVisitor.Filter
preVisit
(PropertyAccessor accessor) Invoked when a new metadata is about to be visited.(package private) R
result()
Returns the result of visiting all elements in a metadata instance.(package private) final void
setCurrentProperty
(String name) Sets the name of the method being visited.(package private) abstract Object
Invoked when a new metadata property is being visited.(package private) final R
walk
(MetadataStandard standard, Class<?> type, Object metadata, boolean mandatory) Invokesvisit(Class, Object)
for all elements of the given metadata if that metadata has not already been visited.
-
Field Details
-
SKIP_SIBLINGS
Sentinel value that may be returned byvisit(Class, Object)
for notifying the walker to stop. This value causeswalk(…)
to stop its iteration, but does not stop iteration by the parent ifwalk(…)
has been invoked recursively. Theresult()
method shall return a valid result even if the iteration has been terminated. -
visited
A guard against infinite recursivity inwalk(MetadataStandard, Class, Object, boolean)
. Keys are visited metadata instances and values are computed value. The value may be null if the computation is in progress.The problem
Cyclic associations can exist in ISO 19115 metadata. For example,Instrument
has a reference to the platform it is mounted on, and thePlatform
has a list of instruments mounted on it. Consequently, walking down the metadata tree can cause infinite recursivity, unless we keep trace of previously visited metadata objects in order to avoid visiting them again. We use anIdentityHashMap
for that purpose, since the recursivity problem exists only when revisiting the exact same instance. Furthermore,HashMap
would not suit since it invokesequals(Object)
andhashCode()
, which are among the methods that we want to avoid invoking twice. -
propertyPath
The name of the property being visited as the last element of the queue. Ifvisit
method is invoked recursively, then the properties before the last one are the parent properties. The number of valid elements isnestedCount
. -
nestedCount
private int nestedCountCount of nested calls towalk(MetadataStandard, Class, Object, boolean)
method. When this count reach zero, the visitor should be removed from the thread local variable.- See Also:
-
allowNull
private boolean allowNullValue of theSemaphores.NULL_COLLECTION
flag when we started the walk. TheNULL_COLLECTION
flag prevents creation of new empty collections by getter methods (a consequence of lazy instantiation). The intent is to avoid creation of unnecessary objects for all unused properties. Users should not see behavioral difference, except if they override some getters with an implementation invoking other getters. However in such cases, users would have been exposed to null values at XML marshalling time anyway.
-
-
Constructor Details
-
MetadataVisitor
MetadataVisitor()Creates a new visitor.
-
-
Method Details
-
creator
ThreadLocal<? extends MetadataVisitor<?>> creator()The thread-local variable that created thisMetadataVisitor
instance. This is usually a static finalVISITORS
constant defined in the subclass. May benull
if this visitor does not use thread-local instances.If this method returns a non-null value, then
ThreadLocal.remove()
will be invoked afterMetadataVisitor
finished to walk through a metadata and all its children. -
setCurrentProperty
Sets the name of the method being visited. This is invoked byPropertyAccessor.walk
methods only. -
getCurrentPropertyPath
Returns the path to the currently visited property. Each element in the list is the UML identifier of a property. Element at index 0 is the name of the property of the root metadata object being visited. Element at index 1 is the name of a property which is a children of above property, etc.The returned list is valid only during
visit(Class, Object)
method execution. The content of this list become undetermined after thevisit
method returned.- Returns:
- the path to the currently visited property.
-
walk
Invokesvisit(Class, Object)
for all elements of the given metadata if that metadata has not already been visited. The computation result is returned (may be the result of a previous computation).This method is typically invoked recursively while we iterate down the metadata tree. It maintains a map of visited nodes for preventing the same node to be visited twice.
- Parameters:
standard
- the metadata standard implemented by the object to visit.type
- the standard interface implemented by the metadata object, ornull
if unknown.metadata
- the metadata to visit.mandatory
-true
for throwing an exception for unsupported metadata type, orfalse
for ignoring.- Returns:
- the value of
result()
after all elements of the given metadata have been visited. If the given metadata instance has already been visited, then this is the previously computed value. If the computation is in progress (e.g. a cyclic graph), then this method returnsnull
.
-
preVisit
Invoked when a new metadata is about to be visited. After this method has been invoked,visit(Class, Object)
will be invoked for each property in the metadata object.- Parameters:
accessor
- information about the standard interface and implementation of the metadata being visited.- Returns:
- most common values are
NON_EMPTY
for visiting all non-empty properties (the default), orWRITABLE
for visiting only writable properties.
-
visit
Invoked when a new metadata property is being visited. The current property value is given in argument. The return value is interpreted as below:SKIP_SIBLINGS
: do not iterate over other properties of current metadata, but continue iteration over properties of the parent metadata.value
: continue with next sibling property without setting any value.null
: clear the property value, then continue with next sibling property. If the property type is a collection, then "null" value is interpreted as an instruction to clear the collection.- Any other value: set the property value to the given value, then continue with next sibling property.
- Parameters:
type
- the type of elements. Note that this is not necessarily the type of givenvalue
argument if the latter is a collection.value
- value of the metadata property being visited.- Returns:
- the new property value to set, or
SKIP_SIBLINGS
. - Throws:
Exception
- if the visit operation failed.
-
result
R result()Returns the result of visiting all elements in a metadata instance. This method is invoked zero or one time per metadata instance. The invocation time depends on the value returned bypreVisit(PropertyAccessor)
:- If
MetadataVisitor.Filter.NONE
, then this method is never invoked for the current metadata instance. - If
MetadataVisitor.Filter.NON_EMPTY
orMetadataVisitor.Filter.WRITABLE
, then this method is invoked after all properties have been visited or aftervisit(Class, Object)
returnedSKIP_SIBLINGS
. - If
MetadataVisitor.Filter.WRITABLE_RESULT
, then this method is invoked before metadata properties are visited. In such case, this method should return an initially empty instance.
null
. - If
-