Class MetadataCopier

java.lang.Object
org.apache.sis.metadata.MetadataVisitor<Object>
org.apache.sis.metadata.MetadataCopier

public class MetadataCopier extends MetadataVisitor<Object>
Performs deep copies of given metadata instances. This class performs copies, not clones, since the copied metadata may not be instances of the same class than the original metadata. This class performs the following steps:
  • Get the implementation class of the given metadata instance.
  • Create a new instance of the implementation class using the public no-argument constructor.
  • Invoke all non-deprecated setter methods on the new instance with the corresponding value from the given metadata.
  • If any of the values copied in above step is itself a metadata, recursively performs deep copy on those metadata instances too.
This copier may be used for converting metadata tree of unknown implementations (for example the result of a call to MetadataSource.lookup(Class, String)) into instances of AbstractMetadata. The copier may also be used if a modifiable metadata is desired after the original metadata has been made final.

Default implementation copies all copiable children, regardless their state. Static factory methods allow to construct some variants, for example skipping the copy of unmodifiable metadata instances since they can be safely shared.

This class supports cyclic graphs in the metadata tree. It may return the given metadata object directly if the implementation class does not provide any setter method.

This class is not thread-safe. In multi-threads environment, each thread should use its own MetadataCopier instance.

Since:
0.8
Version:
1.2
  • Field Details

    • standard

      private final MetadataStandard standard
      The default metadata standard to use for object that are not AbstractMetadata instances, or null if none.
    • target

      private Object target
      The current metadata instance where to copy the property values.
  • Constructor Details

    • MetadataCopier

      public MetadataCopier(MetadataStandard standard)
      Creates a new metadata copier.
      Parameters:
      standard - the default metadata standard to use for object that are not AbstractMetadata instances, or null if none.
  • Method Details

    • getStandard

      private MetadataStandard getStandard(Object metadata)
      Returns the metadata standard to use for the given metadata object, or null if unknown.
    • forModifiable

      public static MetadataCopier forModifiable(MetadataStandard standard)
      Creates a new metadata copier which avoid copying unmodifiable metadata. More specifically, any ModifiableMetadata instance in final state will be kept as-is; those final metadata will not be copied since they can be safely shared.
      Parameters:
      standard - the default metadata standard to use for object that are not AbstractMetadata instances, or null if none.
      Returns:
      a metadata copier which skip the copy of unmodifiable metadata.
      Since:
      1.0
    • copy

      public Object copy(Object metadata)
      Performs a potentially deep copy of a metadata object of unknown type. The return value does not need to be of the same class than the argument.
      Parameters:
      metadata - the metadata object to copy, or null.
      Returns:
      a copy of the given metadata object, or null if the given argument is null.
      Throws:
      UnsupportedOperationException - if there is no implementation class for a metadata to copy, or an implementation class does not provide a public default constructor.
    • copy

      public <T> T copy(Class<T> type, T metadata)
      Performs a potentially deep copy of the given metadata object. This method is preferred to copy(Object) when the type is known. The specified type should be an interface, not an implementation (for example Metadata, not DefaultMetadata).
      Type Parameters:
      T - compile-time value of the type argument.
      Parameters:
      type - the interface of the metadata object to copy.
      metadata - the metadata object to copy, or null.
      Returns:
      a copy of the given metadata object, or null if the given argument is null.
      Throws:
      IllegalArgumentException - if type is an implementation class instead of interface.
      UnsupportedOperationException - if there is no implementation class for a metadata to copy, or an implementation class does not provide a public default constructor.
    • copyRecursively

      protected Object copyRecursively(Class<?> type, Object metadata)
      Performs the actual copy operation on a single metadata instance. This method is invoked by all public copy(…) method with the root metadata object in argument, then is invoked recursively for all properties in that metadata object. If a metadata property is a collection, then this method is invoked for each element in the collection.

      Subclasses can override this method if they need some control on the copy process.

      Parameters:
      type - the interface of the metadata object to copy, or null if unspecified.
      metadata - the metadata object to copy, or null.
      Returns:
      a copy of the given metadata object, or null if the given argument is null.
      Throws:
      UnsupportedOperationException - if there is no implementation class for a metadata to copy, or an implementation class does not provide a public default constructor.
    • preVisit

      final MetadataVisitor.Filter preVisit(PropertyAccessor accessor)
      Invoked before the properties of a metadata instance are visited. This method creates a new instance, to be returned by result(), and returns MetadataVisitor.Filter.WRITABLE_RESULT for notifying the caller that write operations need to be performed on that result object.
      Overrides:
      preVisit in class MetadataVisitor<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), or WRITABLE for visiting only writable properties.
    • result

      final Object result()
      Returns the metadata instance resulting from the copy. This method is invoked before metadata properties are visited. The returned value is a new, initially empty, metadata instance created by preVisit(PropertyAccessor).
      Overrides:
      result in class MetadataVisitor<Object>
    • visit

      final Object visit(Class<?> type, Object metadata)
      Verifies if the given metadata value is a map or a collection before to invoke copyRecursively(Class, Object) for metadata elements. This method is invoked by PropertyAccessor.walkWritable(MetadataVisitor, Object, Object).
      Specified by:
      visit in class MetadataVisitor<Object>
      Parameters:
      type - the type of elements. Note that this is not necessarily the type of given value argument if the latter is a collection.
      metadata - value of the metadata property being visited.
      Returns:
      the new property value to set, or MetadataVisitor.SKIP_SIBLINGS.
    • getCurrentPropertyPath

      protected List<String> getCurrentPropertyPath()
      Returns the path to the currently copied 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 copied. 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 copyRecursively(Class, Object) method execution. The content of this list become undetermined after the copyRecursively method returned.

      Overrides:
      getCurrentPropertyPath in class MetadataVisitor<Object>
      Returns:
      the path to the currently copied property.
      Since:
      1.0