sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1701585 - /sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java
Date Mon, 07 Sep 2015 09:39:44 GMT
Author: desruisseaux
Date: Mon Sep  7 09:39:44 2015
New Revision: 1701585

URL: http://svn.apache.org/r1701585
Log:
Fix a hole in support of <gml:OperationParameter>: take in account that identifiers
and aliases are collections when merging two descriptors.

Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java?rev=1701585&r1=1701584&r2=1701585&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/jaxb/referencing/CC_GeneralOperationParameter.java
[UTF-8] Mon Sep  7 09:39:44 2015
@@ -21,7 +21,12 @@ import java.util.Map;
 import java.util.Set;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.lang.reflect.Array;
 import javax.xml.bind.annotation.XmlElementRef;
+import org.opengis.util.GenericName;
+import org.opengis.metadata.Identifier;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.parameter.GeneralParameterDescriptor;
@@ -31,6 +36,7 @@ import org.apache.sis.parameter.DefaultP
 import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
 import org.apache.sis.parameter.DefaultParameterValueGroup;
 import org.apache.sis.parameter.Parameters;
+import org.apache.sis.referencing.NamedIdentifier;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.CorruptedObjectException;
@@ -72,11 +78,8 @@ public final class CC_GeneralOperationPa
      * <ul>
      *   <li>We ignore the name because the comparisons shall be performed by the caller
with
      *       {@link IdentifiedObjects#isHeuristicMatchForName} or something equivalent.</li>
-     *   <li>We ignore aliases and identifiers for now for avoiding the additional
complexity
-     *       of dealing with collections, and because the Apache SIS pre-defined descriptors
-     *       will be more complete in a majority of case.
-     *
-     *       <b>TODO - </b> this may be revised in any future SIS version.</li>
+     *   <li>We ignore aliases and identifiers because they are collections, which
require
+     *       handling in a special way.</li>
      * </ul>
      */
     private static final String[] IGNORE_DURING_MERGE = {
@@ -207,7 +210,9 @@ public final class CC_GeneralOperationPa
         final Map<String,?> actual   = IdentifiedObjects.getProperties(provided, IGNORE_DURING_MERGE);
         final boolean canSubstitute  = complete.getMinimumOccurs() == minimumOccurs
                                     && complete.getMaximumOccurs() == maximumOccurs
-                                    && expected.entrySet().containsAll(actual.entrySet());
+                                    && expected.entrySet().containsAll(actual.entrySet())
+                                    && containsAll(complete.getAlias(), provided.getAlias())
+                                    && containsAll(complete.getIdentifiers(), provided.getIdentifiers());
         if (canSubstitute && !isGroup) {
             /*
              * The pre-defined or ParameterValue descriptor contains at least all the information
found
@@ -224,13 +229,15 @@ public final class CC_GeneralOperationPa
          */
         final Map<String,Object> merged = new HashMap<>(expected);
         merged.putAll(actual);  // May overwrite pre-defined properties.
+        mergeArrays(GeneralParameterDescriptor.ALIAS_KEY,       GenericName.class, provided.getAlias(),
      merged, complete.getName());
+        mergeArrays(GeneralParameterDescriptor.IDENTIFIERS_KEY, Identifier.class,  provided.getIdentifiers(),
merged, null);
         if (isGroup) {
             final List<GeneralParameterDescriptor> descriptors = ((ParameterDescriptorGroup)
provided).descriptors();
             return merge(DefaultParameterValueGroup.class, merged, merged, minimumOccurs,
maximumOccurs,
                     descriptors.toArray(new GeneralParameterDescriptor[descriptors.size()]),
                     (ParameterDescriptorGroup) complete, canSubstitute);
         } else {
-            return merge(merged, (ParameterDescriptor<?>) provided, (ParameterDescriptor<?>)
complete);
+            return create(merged, (ParameterDescriptor<?>) provided, (ParameterDescriptor<?>)
complete);
         }
     }
 
@@ -322,12 +329,13 @@ public final class CC_GeneralOperationPa
      * Creates a new descriptor with the same properties than the {@code provided} one, but
completed with
      * information not found in GML. Those extra information are given by the {@code complete}
descriptor.
      *
-     * <p>It is the caller's responsibility to construct the {@code properties} map
as a merge
-     * of the properties of the two given descriptors.</p>
-     */
-    private static <T> ParameterDescriptor<T> merge(final Map<String,?>
         merged,
-                                                    final ParameterDescriptor<?> provided,
-                                                    final ParameterDescriptor<T> complete)
+     * <p>It is the caller's responsibility to construct the {@code merged} properties
as a merge of the properties
+     * of the two given descriptors. This can be done with the help of {@link #mergeArrays(String,
Class, Collection,
+     * Map, Identifier)} among others.</p>
+     */
+    private static <T> ParameterDescriptor<T> create(final Map<String,?>
         merged,
+                                                     final ParameterDescriptor<?> provided,
+                                                     final ParameterDescriptor<T> complete)
     {
         final Class<T> valueClass = complete.getValueClass();
         return new DefaultParameterDescriptor<>(merged,
@@ -340,4 +348,79 @@ public final class CC_GeneralOperationPa
                 CollectionsExt.toArray(complete.getValidValues(), valueClass),
                 complete.getDefaultValue());
     }
+
+    /**
+     * Returns {@code true} if the {@code complete} collection contains all elements in the
{@code provided}
+     * collection, where each element have been converted to the canonical {@link NamedIdentifier}
implementation
+     * for comparison purpose.
+     *
+     * @param  <T>      The type of elements in the collection.
+     * @param  complete The collection which is expected to contains all elements.
+     * @param  provided The collection which may be a subset of {@code complete}.
+     * @return {@code true} if {@code complete} contains all {@code provided} elements.
+     */
+    private static <T> boolean containsAll(final Collection<T> complete, final
Collection<T> provided) {
+        if (!provided.isEmpty()) {
+            final int size = complete.size();
+            if (size == 0) {
+                return false;
+            }
+            final Set<NamedIdentifier> c = new HashSet<>(Containers.hashMapCapacity(size));
+            for (final T e : complete) {
+                c.add(toNamedIdentifier(e));
+            }
+            for (final T e : provided) {
+                if (!c.contains(toNamedIdentifier(e))) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Merges the property of type {@code Collection} identified by the given key.
+     * This is used when we can not just substitute one collection by the other.
+     *
+     * @param <T>           The type of elements in the array or collection.
+     * @param key           The key where to fetch or store the array in the {@code merged}
map.
+     * @param componentType The type of elements in the array or collection.
+     * @param provided      The elements unmarshalled from the XML document.
+     * @param merged        The map used for completing missing information.
+     */
+    @SuppressWarnings("unchecked")
+    private static <T> void mergeArrays(final String key, final Class<T> componentType,
+            Collection<T> provided, final Map<String,Object> merged, final Identifier
remove)
+    {
+        if (!provided.isEmpty()) {
+            T[] complete = (T[]) merged.get(key);
+            if (complete != null) {
+                final Map<NamedIdentifier,T> c = new LinkedHashMap<>();
+                for (final T e : provided) c.put(toNamedIdentifier(e), e);
+                for (final T e : complete) c.put(toNamedIdentifier(e), e);
+                c.remove(toNamedIdentifier(remove));
+                provided = c.values();
+            }
+            complete = provided.toArray((T[]) Array.newInstance(componentType, provided.size()));
+            merged.put(key, complete);
+        }
+    }
+
+    /**
+     * Given an {@link Identifier} or {@link GenericName} instance, returns that instance
as a {@link NamedIdentifier}
+     * implementation. The intend is to allow {@code Object.equals(Object)} and hash code
to correctly recognize two
+     * name or identifier as equal even if they are of different implementations.
+     *
+     * <p>Note that {@link NamedIdentifier} is the type of unmarshalled names, aliases
and identifiers.
+     * So this method should not create any new object in a majority of cases.</p>
+     */
+    private static NamedIdentifier toNamedIdentifier(final Object name) {
+        if (name == null || name.getClass() == NamedIdentifier.class) {
+            return (NamedIdentifier) name;
+        } else if (name instanceof Identifier) {
+            return new NamedIdentifier((Identifier) name);
+        } else {
+            return new NamedIdentifier((GenericName) name);
+        }
+    }
 }



Mime
View raw message