sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1784619 - in /sis/branches/JDK8/core: sis-metadata/src/main/java/org/apache/sis/metadata/ sis-metadata/src/test/java/org/apache/sis/metadata/ sis-utility/src/main/java/org/apache/sis/internal/util/ sis-utility/src/main/java/org/apache/sis/...
Date Mon, 27 Feb 2017 18:40:02 GMT
Author: desruisseaux
Date: Mon Feb 27 18:40:01 2017
New Revision: 1784619

URL: http://svn.apache.org/viewvc?rev=1784619&view=rev
Log:
Begin implementation of a metadata "deep copy" operation.

Added:
    sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/Freezer.java
      - copied, changed from r1784618, sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/Cloner.java
Removed:
    sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/Cloner.java
Modified:
    sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java
    sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
    sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
    sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/StandardImplementation.java
    sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Cloner.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties

Copied: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/Freezer.java
(from r1784618, sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/Cloner.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/Freezer.java?p2=sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/Freezer.java&p1=sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/Cloner.java&r1=1784618&r2=1784619&rev=1784619&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/Cloner.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/Freezer.java
[UTF-8] Mon Feb 27 18:40:01 2017
@@ -31,19 +31,19 @@ import org.apache.sis.metadata.iso.ident
 
 /**
  * Returns unmodifiable view of metadata elements of arbitrary type.
- * Despite the {@code Cloner} class name, this class actually tries
- * to avoid creating new clones as much as possible.
+ * Despite the {@code Cloner} parent class name, this class actually
+ * tries to avoid creating new clones as much as possible.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.7
+ * @version 0.8
  * @module
  */
-final class Cloner extends org.apache.sis.internal.util.Cloner {
+final class Freezer extends org.apache.sis.internal.util.Cloner {
     /**
-     * Creates a new {@code Cloner} instance.
+     * Creates a new {@code Freezer} instance.
      */
-    Cloner() {
+    Freezer() {
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java?rev=1784619&r1=1784618&r2=1784619&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java
[UTF-8] Mon Feb 27 18:40:01 2017
@@ -19,6 +19,7 @@ package org.apache.sis.metadata;
 import java.util.Set;
 import java.util.Map;
 import java.util.LinkedHashSet;
+import java.util.IdentityHashMap;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.concurrent.ConcurrentMap;
@@ -35,6 +36,8 @@ import org.apache.sis.util.Classes;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.collection.TreeTable;
 import org.apache.sis.util.collection.CheckedContainer;
+import org.apache.sis.util.collection.BackingStoreException;
+import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.system.Modules;
 import org.apache.sis.internal.system.Semaphores;
 import org.apache.sis.internal.system.SystemListener;
@@ -588,7 +591,7 @@ public class MetadataStandard implements
 
     /**
      * Returns the implementation class for the given interface, or {@code null} if none.
-     * The default implementation returns {@code null} if every cases. Subclasses shall
+     * The default implementation returns {@code null} in every cases. Subclasses shall
      * override this method in order to map GeoAPI interfaces to their implementation.
      *
      * @param  <T>   the compile-time {@code type}.
@@ -1042,6 +1045,48 @@ public class MetadataStandard implements
     }
 
     /**
+     * Returns a deep copy of the given metadata object. This method performs a <em>copy</em>,
not a clone,
+     * since the copied metadata may not be of the same class than the original metadata.
+     * This method performs the following step:
+     *
+     * <ul>
+     *   <li>Get the {@linkplain #getImplementation implementation class} of the given
metadata instance.</li>
+     *   <li>Create a new instance of the implementation class using the public no-argument
constructor.</li>
+     *   <li>Invoke all non-deprecated setter methods on the new instance with the
corresponding value from
+     *       the given metadata.</li>
+     *   <li>If any of the values copied in above step is itself a metadata, recursively
performs deep copy
+     *       on those metadata instances too.</li>
+     * </ul>
+     *
+     * This method supports cyclic graphs. This method may return the given {@code metadata}
object directly
+     * if the {@linkplain #getImplementation implementation class} does not provide any setter
method.
+     *
+     * @param  metadata  the metadata object to copy, or {@code null}.
+     * @return A copy of the given metadata object, or {@code null} if the given argument
is {@code null}.
+     * @throws ClassCastException if the metadata object does not implement a metadata interface
of the expected package.
+     * @throws UnsupportedOperationException if there is no implementation class for at least
one metadata to copy,
+     *         or an implementation class does not provide a public default constructor.
+     *
+     * @since 0.8
+     */
+    Object deepCopy(final Object metadata) throws ClassCastException {
+        if (metadata != null) {
+            final PropertyAccessor accessor = getAccessor(new CacheKey(metadata.getClass()),
true);
+            final Map<Object,Object> copies = new IdentityHashMap<>();
+            try {
+                return accessor.deepCopy(metadata, copies);
+            } catch (ReflectiveOperationException e) {
+                throw new UnsupportedOperationException(Errors.format(Errors.Keys.CanNotCopy_1,
accessor.type));
+            } catch (RuntimeException e) {
+                throw e;
+            } catch (Exception e) {  // Other non-checked exception may be throw by default
metadata constructor.
+                throw new BackingStoreException(e);
+            }
+        }
+        return metadata;
+    }
+
+    /**
      * Returns a string representation of this metadata standard.
      * This is for debugging purpose only and may change in any future version.
      */

Modified: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java?rev=1784619&r1=1784618&r2=1784619&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
[UTF-8] Mon Feb 27 18:40:01 2017
@@ -83,7 +83,7 @@ import static org.apache.sis.util.collec
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.5
+ * @version 0.8
  * @module
  */
 @XmlTransient
@@ -167,8 +167,13 @@ public abstract class ModifiableMetadata
      * @return an unmodifiable copy of this metadata.
      */
     public AbstractMetadata unmodifiable() {
-        // Reminder: 'unmodifiable' is reset to null by checkWritePermission().
-        if (unmodifiable == null) {
+        /*
+         * The 'unmodifiable' field is reset to null by checkWritePermission().
+         * However this is not sufficient since the setter method of some child
+         * could have been invoked without invoking any setter method on 'this'.
+         * So we also need to perform an equality check.
+         */
+        if (unmodifiable == null || (unmodifiable != this && unmodifiable != FREEZING
&& !equals(unmodifiable))) {
             final ModifiableMetadata candidate;
             try {
                 /*
@@ -387,7 +392,7 @@ public abstract class ModifiableMetadata
             if (unmodifiable == FREEZING) {
                 /*
                  * freeze() method is under progress. The source collection is already
-                 * an unmodifiable instance created by Cloner.clone(Object).
+                 * an unmodifiable instance created by Freezer.clone(Object).
                  */
                 assert collectionType(elementType).isInstance(source);
                 return (Collection<E>) source;

Modified: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java?rev=1784619&r1=1784618&r2=1784619&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
[UTF-8] Mon Feb 27 18:40:01 2017
@@ -81,7 +81,7 @@ import static org.apache.sis.util.collec
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.5
+ * @version 0.8
  * @module
  */
 class PropertyAccessor {
@@ -1161,7 +1161,7 @@ class PropertyAccessor {
         assert implementation.isInstance(metadata) : metadata;
         if (setters != null) try {
             final Object[] arguments = new Object[1];
-            final Cloner cloner = new Cloner();
+            final Freezer freezer = new Freezer();
             for (int i=0; i<allCount; i++) {
                 final Method setter = setters[i];
                 if (setter != null) {
@@ -1180,7 +1180,7 @@ class PropertyAccessor {
                     }
                     final Method getter = getters[i];
                     final Object source = get(getter, metadata);
-                    final Object target = cloner.clone(source);
+                    final Object target = freezer.clone(source);
                     if (source != target) {
                         arguments[0] = target;
                         set(setter, metadata, arguments);
@@ -1201,6 +1201,41 @@ class PropertyAccessor {
     }
 
     /**
+     * Returns a deep copy of the given metadata object.
+     *
+     * @param  metadata   the metadata object to copy.
+     * @param  copies     a map of metadata objects already copied.
+     * @return a copy of the given metadata object, or {@code metadata} itself if there is
+     *         no known implementation class or that implementation has no setter method.
+     * @throws Exception if an error occurred while creating the copy. This include any
+     *         checked checked exception that the no-argument constructor may throw.
+     */
+    final Object deepCopy(final Object metadata, final Map<Object,Object> copies) throws
Exception {
+        if (setters == null) {
+            return metadata;
+        }
+        Object copy = copies.get(metadata);
+        if (copy == null) {
+            copy = implementation.newInstance();
+            copies.put(metadata, copy);                     // Need to be first in case of
cyclic graphs.
+            final Object[] arguments = new Object[1];
+            for (int i=0; i<allCount; i++) {
+                final Method setter = setters[i];
+                if (setter != null && !setter.isAnnotationPresent(Deprecated.class))
{
+                    final Method getter = getters[i];
+                    Object value = get(getter, metadata);
+                    if (value != null) {
+                        // TODO: perform deep copy here.
+                        arguments[0] = value;
+                        set(setter, copy, arguments);
+                    }
+                }
+            }
+        }
+        return copy;
+    }
+
+    /**
      * Computes a hash code for the specified metadata. The hash code is defined as the sum
      * of hash code values of all non-empty properties, plus the hash code of the interface.
      * This is a similar contract than {@link java.util.Set#hashCode()} (except for the interface)

Modified: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/StandardImplementation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/StandardImplementation.java?rev=1784619&r1=1784618&r2=1784619&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/StandardImplementation.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/metadata/StandardImplementation.java
[UTF-8] Mon Feb 27 18:40:01 2017
@@ -66,7 +66,7 @@ final class StandardImplementation exten
      * But maybe the most interesting property is that it allocates less objects since {@code
IdentityHashMap}
      * implementation doesn't need the chain of objects created by {@code HashMap}.</div>
      */
-    private final transient Map<Class<?>,Class<?>> implementations; //
written by reflection on deserialization.
+    private final transient Map<Class<?>,Class<?>> implementations;   
 // written by reflection on deserialization.
 
     /**
      * Creates a new instance working on implementation of interfaces defined in the
@@ -161,7 +161,7 @@ final class StandardImplementation exten
                         Logging.recoverableException(Logging.getLogger(Modules.METADATA),
                                 MetadataStandard.class, "getImplementation", e);
                     }
-                    implementations.put(type, Void.TYPE); // Marker for "class not found".
+                    implementations.put(type, Void.TYPE);                       // Marker
for "class not found".
                 }
             }
         }

Modified: sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java?rev=1784619&r1=1784618&r2=1784619&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataStandardTest.java
[UTF-8] Mon Feb 27 18:40:01 2017
@@ -356,6 +356,21 @@ public final strictfp class MetadataStan
     }
 
     /**
+     * Tests {@link MetadataStandard#deepCopy(Object)}.
+     */
+    @Test
+    @DependsOnMethod("testEquals")
+    public void testDeepCopy() {
+        standard = MetadataStandard.ISO_19115;
+        final DefaultCitation original = HardCodedCitations.EPSG;
+        final DefaultCitation copy = (DefaultCitation) standard.deepCopy(original);
+        assertNotSame(original, copy);
+//      assertNotSame(getSingleton(original.getCitedResponsibleParties()),
+//                    getSingleton(copy.getCitedResponsibleParties()));
+        assertEquals(original, copy);
+    }
+
+    /**
      * Tests serialization of pre-defined constants.
      */
     @Test

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Cloner.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Cloner.java?rev=1784619&r1=1784618&r2=1784619&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Cloner.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/Cloner.java
[UTF-8] Mon Feb 27 18:40:01 2017
@@ -91,7 +91,7 @@ public class Cloner {
         try {
             if (valueType != type) {
                 method = valueType.getMethod("clone", (Class<?>[]) null);
-                type = valueType; // Set only if the above line succeed.
+                type = valueType;                                           // Set only if
the above line succeed.
                 /*
                  * If the class implementing the 'clone()' method is not public, we may not
be able to access that
                  * method even if it is public. Try to make the method accessible. If we
fail for security reason,

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1784619&r1=1784618&r2=1784619&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
[UTF-8] Mon Feb 27 18:40:01 2017
@@ -106,6 +106,11 @@ public final class Errors extends Indexe
         public static final short CanNotConvertValue_2 = 8;
 
         /**
+         * Can not copy “{0}”.
+         */
+        public static final short CanNotCopy_1 = 169;
+
+        /**
          * Can not open “{0}”.
          */
         public static final short CanNotOpen_1 = 9;

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1784619&r1=1784618&r2=1784619&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
[ISO-8859-1] Mon Feb 27 18:40:01 2017
@@ -32,6 +32,7 @@ CanNotConnectTo_1                 = Can
 CanNotConvertFromType_2           = Can not convert from type \u2018{0}\u2019 to type \u2018{1}\u2019.
 CanNotConvertValue_2              = Can not convert value \u201c{0}\u201d to type \u2018{1}\u2019.
 CanNotCompute_1                   = Can not compute \u201c{0}\u201d.
+CanNotCopy_1                      = Can not copy \u201c{0}\u201d.
 CanNotOpen_1                      = Can not open \u201c{0}\u201d.
 CanNotParseFile_2                 = Can not parse \u201c{1}\u201d as a file in the {0} format.
 CanNotRead_1                      = Can not read \u201c{0}\u201d.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1784619&r1=1784618&r2=1784619&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
[ISO-8859-1] Mon Feb 27 18:40:01 2017
@@ -29,6 +29,7 @@ CanNotConnectTo_1                 = Ne p
 CanNotConvertFromType_2           = Ne peut pas convertir du type \u2018{0}\u2019 vers le
type \u2018{1}\u2019.
 CanNotConvertValue_2              = La valeur \u00ab\u202f{0}\u202f\u00bb ne peut pas \u00eatre
convertie vers le type \u2018{1}\u2019.
 CanNotCompute_1                   = Ne peut pas calculer \u00ab\u202f{0}\u202f\u00bb.
+CanNotCopy_1                      = Ne peut pas copier \u00ab\u202f{0}\u202f\u00bb.
 CanNotOpen_1                      = Ne peut pas ouvrir \u00ab\u202f{0}\u202f\u00bb.
 CanNotParseFile_2                 = Ne peut pas lire \u00ab\u202f{1}\u202f\u00bb comme un
fichier au format {0}.
 CanNotRead_1                      = Ne peut pas lire \u00ab\u202f{0}\u202f\u00bb.



Mime
View raw message