sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1707580 [2/2] - in /sis/trunk: ./ core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/ core/sis...
Date Thu, 08 Oct 2015 16:24:20 GMT
Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/Context.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/Context.java?rev=1707580&r1=1707579&r2=1707580&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/Context.java [UTF-8]
(original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/Context.java [UTF-8]
Thu Oct  8 16:24:19 2015
@@ -17,8 +17,12 @@
 package org.apache.sis.internal.jaxb;
 
 import java.util.Map;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
 import java.util.Locale;
 import java.util.TimeZone;
+import java.util.LinkedList;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.logging.LogRecord;
@@ -32,21 +36,25 @@ import org.apache.sis.util.resources.Ind
 import org.apache.sis.internal.jaxb.gco.PropertyType;
 import org.apache.sis.internal.system.Semaphores;
 import org.apache.sis.internal.system.Loggers;
+import org.apache.sis.xml.IdentifierSpace;
 import org.apache.sis.xml.MarshalContext;
 import org.apache.sis.xml.ValueConverter;
 import org.apache.sis.xml.ReferenceResolver;
 
+// Branch-dependent imports.
+import org.apache.sis.internal.jdk8.JDK8;
+
 
 /**
  * Thread-local status of a marshalling or unmarshalling processes.
  * All non-static methods in this class except {@link #finish()} are implementation of public
API.
  * All static methods are internal API. Those methods expect a {@code Context} instance as
their first argument.
- * They should be though as if they were normal member methods, except that they accept {@code
null} instance
+ * They can be though as if they were normal member methods, except that they accept {@code
null} instance
  * if no (un)marshalling is in progress.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.6
+ * @version 0.7
  * @module
  */
 public final class Context extends MarshalContext {
@@ -98,8 +106,6 @@ public final class Context extends Marsh
 
     /**
      * The logger to use for warnings that are specific to XML.
-     *
-     * @see org.apache.sis.metadata.iso.ISOMetadata#LOGGER
      */
     public static final Logger LOGGER = Logging.getLogger(Loggers.XML);
 
@@ -109,9 +115,9 @@ public final class Context extends Marsh
     private int bitMasks;
 
     /**
-     * The locale to use for marshalling, or {@code null} if no locale were explicitly specified.
+     * The locale to use for marshalling, or an empty queue if no locale were explicitly
specified.
      */
-    private Locale locale;
+    private final Deque<Locale> locales;
 
     /**
      * The timezone, or {@code null} if unspecified.
@@ -142,6 +148,24 @@ public final class Context extends Marsh
     private final ValueConverter converter;
 
     /**
+     * The objects associated to XML identifiers. At marhalling time, this is used for avoiding
duplicated identifiers
+     * in the same XML document. At unmarshalling time, this is used for getting a previous
object from its identifier.
+     *
+     * @since 0.7
+     */
+    private final Map<String,Object> identifiers;
+
+    /**
+     * The identifiers used for marshalled objects. This is the converse of {@link #identifiers},
used in order to
+     * identify which {@code gml:id} to use for the given object. The {@code gml:id} to use
are not necessarily the
+     * same than the one associated to {@link IdentifierSpace#ID} if the identifier was already
used for another
+     * object in the same XML document.
+     *
+     * @since 0.7
+     */
+    private final Map<Object,String> identifiedObjects;
+
+    /**
      * The object to inform about warnings, or {@code null} if none.
      */
     private final WarningListener<?> warningListener;
@@ -160,7 +184,7 @@ public final class Context extends Marsh
 
     /**
      * The context which was previously used. This form a linked list allowing to push properties
-     * (e.g. {@link #push(Locale)}) and pull back the context to its previous state once
finished.
+     * and pull back the context to its previous state once finished.
      */
     private final Context previous;
 
@@ -193,50 +217,25 @@ public final class Context extends Marsh
                    final ReferenceResolver  resolver, final ValueConverter converter,
                    final WarningListener<?> warningListener)
     {
-        this.bitMasks        = bitMasks;
-        this.locale          = locale;
-        this.timezone        = timezone;
-        this.schemas         = schemas; // No clone, because this class is internal.
-        this.versionGML      = versionGML;
-        this.resolver        = resolver;
-        this.converter       = converter;
-        this.warningListener = warningListener;
+        this.bitMasks          = bitMasks;
+        this.locales           = new LinkedList<Locale>();
+        this.timezone          = timezone;
+        this.schemas           = schemas; // No clone, because this class is internal.
+        this.versionGML        = versionGML;
+        this.resolver          = resolver;
+        this.converter         = converter;
+        this.warningListener   = warningListener;
+        this.identifiers       = new HashMap<String,Object>();
+        this.identifiedObjects = new IdentityHashMap<Object,String>();
         if ((bitMasks & MARSHALLING) != 0) {
             if (!Semaphores.queryAndSet(Semaphores.NULL_COLLECTION)) {
                 this.bitMasks |= CLEAR_SEMAPHORE;
             }
         }
-        previous = current();
-        CURRENT.set(this);
-    }
-
-    /**
-     * Inherits all configuration from the previous context, if any.
-     *
-     * @param previous The context from which to inherit the configuration, or {@code null}.
-     *
-     * @see #push(Locale)
-     */
-    @SuppressWarnings("ThisEscapedInObjectConstruction")
-    private Context(final Context previous) {
-        if (previous != null) {
-            bitMasks        = previous.bitMasks;
-            locale          = previous.locale;
-            timezone        = previous.timezone;
-            schemas         = previous.schemas;
-            versionGML      = previous.versionGML;
-            resolver        = previous.resolver;
-            converter       = previous.converter;
-            warningListener = previous.warningListener;
-        } else {
-            timezone        = null;
-            schemas         = null;
-            versionGML      = null;
-            resolver        = null;
-            converter       = null;
-            warningListener = null;
+        if (locale != null) {
+            locales.add(locale);
         }
-        this.previous = previous;
+        previous = CURRENT.get();
         CURRENT.set(this);
     }
 
@@ -247,7 +246,7 @@ public final class Context extends Marsh
      */
     @Override
     public final Locale getLocale() {
-        return locale;
+        return locales.peekLast();
     }
 
     /**
@@ -275,12 +274,18 @@ public final class Context extends Marsh
         return null;
     }
 
-    /*
-     * ---- END OF PUBLIC API --------------------------------------------------------------
-     *
-     * Following are internal API. They are provided as static methods with a Context
-     * argument rather than normal member methods in order to accept null context.
-     */
+
+
+
+    ////////////////////////////////////////////////////////////////////////////////////////
+    ////////                                                                        ////////
+    ////////    END OF PUBLIC (non-internal) API.                                   ////////
+    ////////                                                                        ////////
+    ////////    Following are internal API. They are provided as static methods     ////////
+    ////////    with a Context argument rather than normal member methods           ////////
+    ////////    in order to accept null context.                                    ////////
+    ////////                                                                        ////////
+    ////////////////////////////////////////////////////////////////////////////////////////
 
     /**
      * Returns the context of the XML (un)marshalling currently progressing in the current
thread,
@@ -293,6 +298,45 @@ public final class Context extends Marsh
     }
 
     /**
+     * Sets the locale to the given value. The old locales are remembered and will
+     * be restored by the next call to {@link #pull()}. This method can be invoked
+     * when marshalling object that need to marshall their children in a different
+     * locale, like below:
+     *
+     * {@preformat java
+     *     private void beforeMarshal(Marshaller marshaller) {
+     *         Context.push(language);
+     *     }
+     *
+     *     private void afterMarshal(Marshaller marshaller) {
+     *         Context.pull();
+     *     }
+     * }
+     *
+     * @param locale The locale to set, or {@code null}.
+     */
+    public static void push(Locale locale) {
+        final Context current = current();
+        if (current != null) {
+            if (locale == null) {
+                locale = current.getLocale();
+            }
+            current.locales.addLast(locale);
+        }
+    }
+
+    /**
+     * Restores the locale which was used prior the call to {@link #push(Locale)}.
+     * It is not necessary to invoke this method in a {@code finally} block.
+     */
+    public static void pull() {
+        final Context current = current();
+        if (current != null) {
+            current.locales.removeLast();
+        }
+    }
+
+    /**
      * Returns {@code true} if the given flag is set.
      *
      * @param  context The current context, or {@code null} if none.
@@ -305,6 +349,30 @@ public final class Context extends Marsh
     }
 
     /**
+     * Returns {@code true} if the GML version is equals or newer than the specified version.
+     * If no GML version were specified, then this method returns {@code true}, i.e. newest
+     * version is assumed.
+     *
+     * <div class="note"><b>API note:</b>
+     * This method is static for the convenience of performing the check for null context.</div>
+     *
+     * @param  context The current context, or {@code null} if none.
+     * @param  version The version to compare to.
+     * @return {@code true} if the GML version is equals or newer than the specified version.
+     *
+     * @see #getVersion(String)
+     */
+    public static boolean isGMLVersion(final Context context, final Version version) {
+        if (context != null) {
+            final Version versionGML = context.versionGML;
+            if (versionGML != null) {
+                return versionGML.compareTo(version) >= 0;
+            }
+        }
+        return true;
+    }
+
+    /**
      * Returns the base URL of ISO 19139 (or other standards) schemas.
      * The valid values are documented in the {@link org.apache.sis.xml.XML#SCHEMAS} property.
      * If the returned value is not empty, then this method guarantees it ends with {@code
'/'}.
@@ -389,24 +457,55 @@ public final class Context extends Marsh
     }
 
     /**
-     * Returns {@code true} if the GML version is equals or newer than the specified version.
-     * If no GML version were specified, then this method returns {@code true}, i.e. newest
-     * version is assumed.
+     * If a {@code gml:id} value has already been used for the given object in the current
XML document,
+     * returns that identifier. Otherwise returns {@code null}.
      *
-     * <div class="note"><b>API note:</b>
-     * This method is static for the convenience of performing the check for null context.</div>
+     * @param  context The current context, or {@code null} if none.
+     * @param  object  The object for which to get the {@code gml:id}.
+     * @return The identifier used in the current XML document for the given object, or {@code
null} if none.
+     *
+     * @since 0.7
+     */
+    public static String getObjectID(final Context context, final Object object) {
+        return (context != null) ? context.identifiedObjects.get(object) : null;
+    }
+
+    /**
+     * Returns the object for the given {@code gml:id}, or {@code null} if none.
+     * This association is valid only for the current XML document.
      *
      * @param  context The current context, or {@code null} if none.
-     * @param  version The version to compare to.
-     * @return {@code true} if the GML version is equals or newer than the specified version.
+     * @param  id      The identifier for which to get the object.
+     * @return The object associated to the given identifier, or {@code null} if none.
      *
-     * @see #getVersion(String)
+     * @since 0.7
      */
-    public static boolean isGMLVersion(final Context context, final Version version) {
+    public static Object getObjectForID(final Context context, final String id) {
+        return (context != null) ? context.identifiers.get(id) : null;
+    }
+
+    /**
+     * Returns {@code true} if the given identifier is available, or {@code false} if it
is used by another object.
+     * If this method returns {@code true}, then the given identifier is associated to the
given object for future
+     * invocation of {@code Context} method.  If this method returns {@code false}, then
the caller is responsible
+     * for computing an other identifier candidate.
+     *
+     * @param  context The current context, or {@code null} if none.
+     * @param  object  The object for which to assign the {@code gml:id}.
+     * @param  id      The identifier to assign to the given object.
+     * @return {@code true} if the given identifier can be used.
+     *
+     * @since 0.7
+     */
+    public static boolean setObjectForID(final Context context, final Object object, final
String id) {
         if (context != null) {
-            final Version versionGML = context.versionGML;
-            if (versionGML != null) {
-                return versionGML.compareTo(version) >= 0;
+            final Object existing = JDK8.putIfAbsent(context.identifiers, id, object);
+            if (existing == null) {
+                if (context.identifiedObjects.put(object, id) != null) {
+                    throw new AssertionError(id);   // Caller forgot to invoke getExistingID(context,
object).
+                }
+            } else if (existing != object) {
+                return false;
             }
         }
         return true;
@@ -544,44 +643,6 @@ public final class Context extends Marsh
     }
 
     /**
-     * Sets the locale to the given value. The old locales are remembered and will
-     * be restored by the next call to {@link #pull()}. This method can be invoked
-     * when marshalling object that need to marshall their children in a different
-     * locale, like below:
-     *
-     * {@preformat java
-     *     private void beforeMarshal(Marshaller marshaller) {
-     *         Context.push(language);
-     *     }
-     *
-     *     private void afterMarshal(Marshaller marshaller) {
-     *         Context.pull();
-     *     }
-     * }
-     *
-     * @param locale The locale to set, or {@code null}.
-     */
-    public static void push(final Locale locale) {
-        final Context context = new Context(current());
-        if (locale != null) {
-            context.locale = locale;
-        }
-    }
-
-    /**
-     * Restores the locale (or any other setting) which was used prior the call
-     * to {@link #push(Locale)}. It is not necessary to invoke this method in a
-     * {@code finally} block if the parent {@code Context} is itself
-     * disposed in a {@code finally} block.
-     */
-    public static void pull() {
-        final Context current = current();
-        if (current != null) {
-            current.finish();
-        }
-    }
-
-    /**
      * Invoked in a {@code finally} block when a unmarshalling process is finished.
      */
     public final void finish() {

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/PropertyType.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/PropertyType.java?rev=1707580&r1=1707579&r2=1707580&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/PropertyType.java
[UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gco/PropertyType.java
[UTF-8] Thu Oct  8 16:24:19 2015
@@ -106,7 +106,7 @@ import org.apache.sis.util.iso.SimpleInt
  * @author  Cédric Briançon (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.4
+ * @version 0.7
  * @module
  *
  * @see XmlAdapter
@@ -131,9 +131,8 @@ public abstract class PropertyType<Value
      * Either {@code null}, an {@link ObjectReference} or a {@link String}.
      *
      * <ul>
-     *   <li>{@link ObjectReference} defines the {@code idref}, {@code uuidref}, {@code
xlink:href},
-     *       {@code xlink:role}, {@code xlink:arcrole}, {@code xlink:title}, {@code xlink:show}
and
-     *       {@code xlink:actuate} attributes.</li>
+     *   <li>{@link ObjectReference} defines the {@code uuidref}, {@code xlink:href},
{@code xlink:role},
+     *       {@code xlink:arcrole}, {@code xlink:title}, {@code xlink:show} and {@code xlink:actuate}
attributes.</li>
      *   <li>{@link String} defines the {@code nilReason} attribute.</li>
      * </ul>
      *
@@ -174,7 +173,6 @@ public abstract class PropertyType<Value
      * @param value The interface to wrap.
      */
     protected PropertyType(final BoundType value) {
-        metadata = value;
         /*
          * Do not invoke NilReason.forObject(metadata) in order to avoid unnecessary synchronization.
          * Subclasses will use the PropertyType(BoundType, boolean) constructor instead when
a check
@@ -184,9 +182,28 @@ public abstract class PropertyType<Value
             final NilReason reason = ((NilObject) value).getNilReason();
             if (reason != null) {
                 reference = reason.toString();
-                metadata  = null;
+                return;
             }
         }
+        /*
+         * Verifies if the object to marshall can be replaced by a xlink or uuidref.
+         * First, check if we can use a xlink:href="#foo" reference to a gml:id="foo".
+         * Only if no gml:id was found, check for user-defined xlink or uuidref.
+         */
+        @SuppressWarnings("OverridableMethodCallDuringObjectConstruction")
+        final Class<BoundType>  type     = getBoundType();
+        final Context           context  = Context.current();
+        final ReferenceResolver resolver = Context.resolver(context);
+        final String id = Context.getObjectID(context, value);
+        if (id != null && resolver.canSubstituteByReference(context, type, value,
id)) try {
+            final XLink link = new XLink();
+            link.setHRef(new URI(null, null, id));
+            reference = new ObjectReference(null, link);
+            return;
+        } catch (URISyntaxException e) {
+            Context.warningOccured(context, getClass(), "<init>", e, true);
+        }
+        metadata = value;   // Non-null only after we verified that not a NilObject or xlink:href="#foo".
         if (value instanceof IdentifiedObject) {
             /*
              * Get the identifiers as full UUID or XLink objects. We do not use the more
permissive methods
@@ -209,13 +226,9 @@ public abstract class PropertyType<Value
              * org.apache.sis.internal.jaxb.ModifiableIdentifierMap.put(Citation, String).
              */
             final IdentifierMap map = ((IdentifiedObject) value).getIdentifierMap();
-            XLink  link = map.getSpecialized(IdentifierSpace.XLINK);
-            UUID   uuid = map.getSpecialized(IdentifierSpace.UUID);
+            XLink link = map.getSpecialized(IdentifierSpace.XLINK);
+            UUID  uuid = map.getSpecialized(IdentifierSpace.UUID);
             if (uuid != null || link != null) {
-                @SuppressWarnings("OverridableMethodCallDuringObjectConstruction")
-                final Class<BoundType>  type     = getBoundType();
-                final Context           context  = Context.current();
-                final ReferenceResolver resolver = Context.resolver(context);
                 /*
                  * Check if the user gives us the permission to use reference to those identifiers.
                  * If not, forget them in order to avoid marshalling the identifiers twice
(see the
@@ -350,8 +363,8 @@ public abstract class PropertyType<Value
 
     /**
      * A URN to an external resources, or to an other part of a XML document, or an identifier.
-     * The {@code idref} attribute allows an XML element to refer to another XML element
that
-     * has a corresponding {@code id} attribute.
+     * The {@code xlink:href} attribute allows an XML element to refer to another XML element
+     * that has a corresponding {@code id} attribute.
      *
      * @return the current value, or {@code null} if none.
      * @category xlink

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gml/GMLAdapter.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gml/GMLAdapter.java?rev=1707580&r1=1707579&r2=1707580&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gml/GMLAdapter.java
[UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/gml/GMLAdapter.java
[UTF-8] Thu Oct  8 16:24:19 2015
@@ -59,7 +59,7 @@ public abstract class GMLAdapter {
      * </ul>
      *
      * @see <a href="https://www.seegrid.csiro.au/wiki/bin/view/AppSchemas/GmlIdentifiers">GML
identifiers</a>
-     * @see org.apache.sis.internal.jaxb.gco.ObjectReference#getUUIDREF()
+     * @see org.apache.sis.internal.jaxb.gco.PropertyType#getUUIDREF()
      */
     @XmlID
     @XmlAttribute(namespace = Namespaces.GML, required = true)
@@ -94,7 +94,7 @@ public abstract class GMLAdapter {
     }
 
     /**
-     * Assign the {@link #id} value (if non-null) to the given object. This method
+     * Assigns the {@link #id} value (if non-null) to the given object. This method
      * is typically invoked at unmarshalling time in order to assign the ID of this
      * temporary wrapper to the "real" GeoAPI implementation instance.
      *

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/package-info.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/package-info.java?rev=1707580&r1=1707579&r2=1707580&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/package-info.java
[UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/jaxb/package-info.java
[UTF-8] Thu Oct  8 16:24:19 2015
@@ -34,7 +34,7 @@
  *
  * @author  Cédric Briançon (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.7
  * @module
  */
 package org.apache.sis.internal.jaxb;

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java?rev=1707580&r1=1707579&r2=1707580&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java
[UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java
[UTF-8] Thu Oct  8 16:24:19 2015
@@ -64,7 +64,10 @@ public final class CollectionsExt extend
 
     /**
      * Returns the first element of the given iterable, or {@code null} if none.
-     * This method is null-safe. Note that the first element may be null.
+     * This method does not emit warning if more than one element is found.
+     * Consequently, this method should be used only when multi-occurrence is not ambiguous.
+     *
+     * <p>This method is null-safe. Note however that the first element may be null.</p>
      *
      * @param  <T> The type of elements contained in the iterable.
      * @param  collection The iterable from which to get the first element, or {@code null}.

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/RecordDefinition.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/RecordDefinition.java?rev=1707580&r1=1707579&r2=1707580&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/RecordDefinition.java
[UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/RecordDefinition.java
[UTF-8] Thu Oct  8 16:24:19 2015
@@ -187,6 +187,7 @@ abstract class RecordDefinition { // Int
     /**
      * Read-only access to the map of member indices.
      */
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
     final Map<MemberName,Integer> memberIndices() {
         return memberIndices;
     }
@@ -195,7 +196,8 @@ abstract class RecordDefinition { // Int
      * Returns the number of elements in records.
      */
     final int size() {
-        return members.length;
+        // 'members' should not be null, but let be safe.
+        return (members != null) ? members.length : 0;
     }
 
     /**
@@ -241,7 +243,7 @@ abstract class RecordDefinition { // Int
     final String toString(final String head, final Object values) {
         final StringBuilder buffer = new StringBuilder(250);
         final String lineSeparator = JDK7.lineSeparator();
-        final String[] names = new String[members.length];
+        final String[] names = new String[size()];
         int width = 0;
         buffer.append(head).append("[“").append(getRecordType().getTypeName()).append("”]
{").append(lineSeparator);
         for (int i=0; i<names.length; i++) {

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/logging/package-info.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/logging/package-info.java?rev=1707580&r1=1707579&r2=1707580&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/logging/package-info.java
[UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/logging/package-info.java
[UTF-8] Thu Oct  8 16:24:19 2015
@@ -43,12 +43,6 @@
  *   <li>Any other JAR registering a {@link org.apache.sis.util.logging.LoggerFactory}
implementation.</li>
  * </ul>
  *
- * <div class="section">Apache SIS logger constants</div>
- * Some static final {@code Logger} constant defined in Apache SIS are:
- * <ul>
- *   <li>{@link org.apache.sis.metadata.iso.ISOMetadata#LOGGER} for the {@code org.apache.sis.metadata.iso.*}
packages</li>
- * </ul>
- *
  * <div class="section">Note for SIS developers</div>
  * All SIS code should fetch their logger through a call to our custom
  * {@link org.apache.sis.util.logging.Logging#getLogger(String)} method instead than

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/ReferenceResolver.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/ReferenceResolver.java?rev=1707580&r1=1707579&r2=1707580&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/ReferenceResolver.java [UTF-8]
(original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/ReferenceResolver.java [UTF-8]
Thu Oct  8 16:24:19 2015
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.xml;
 
+import java.net.URI;
 import java.util.UUID;
 import java.lang.reflect.Proxy;
 import org.opengis.metadata.Identifier;
@@ -23,6 +24,7 @@ import org.apache.sis.util.Emptiable;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.LenientComparable;
 import org.apache.sis.internal.jaxb.gmx.Anchor;
+import org.apache.sis.internal.jaxb.Context;
 
 import static org.apache.sis.util.ArgumentChecks.*;
 
@@ -33,13 +35,13 @@ import static org.apache.sis.util.Argume
  * to an existing instance instead than writing the full object definition.
  * At unmarshalling time, this class replaces (if possible) a reference by the full object
definition.
  *
- * <p>Subclasses can override the methods defined in this class in order to search
in their
- * own catalog. See the {@link XML#RESOLVER} javadoc for an example of registering a custom
- * {@code ReferenceResolver} to a unmarshaller.</p>
+ * <p>Subclasses can override the methods defined in this class in order to search
in their own catalog.
+ * See the {@link XML#RESOLVER} javadoc for an example of registering a custom {@code ReferenceResolver}
+ * to a unmarshaller.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.4
+ * @version 0.7
  * @module
  */
 public class ReferenceResolver {
@@ -72,8 +74,7 @@ public class ReferenceResolver {
      *
      * @param  <T>     The compile-time type of the {@code type} argument.
      * @param  context Context (GML version, locale, <i>etc.</i>) of the (un)marshalling
process.
-     * @param  type    The type of object to be unmarshalled as an <strong>interface</strong>.
-     *                 This is usually a <a href="http://www.geoapi.org">GeoAPI</a>
interface.
+     * @param  type    The type of object to be unmarshalled, often as a GeoAPI interface.
      * @param  identifiers An arbitrary amount of identifiers. For each identifier, the
      *         {@linkplain Identifier#getAuthority() authority} is typically (but not
      *         necessarily) one of the constants defined in {@link IdentifierSpace}.
@@ -90,13 +91,12 @@ public class ReferenceResolver {
     }
 
     /**
-     * Returns an object of the given type for the given {@code uuid} attribute, or {@code
null}
-     * if none. The default implementation returns {@code null} in all cases.
+     * Returns an object of the given type for the given {@code uuid} attribute, or {@code
null} if none.
+     * The default implementation returns {@code null} in all cases.
      *
      * @param  <T>     The compile-time type of the {@code type} argument.
      * @param  context Context (GML version, locale, <i>etc.</i>) of the (un)marshalling
process.
-     * @param  type    The type of object to be unmarshalled as an <strong>interface</strong>.
-     *                 This is usually a <a href="http://www.geoapi.org">GeoAPI</a>
interface.
+     * @param  type    The type of object to be unmarshalled, often as a GeoAPI interface.
      * @param  uuid The {@code uuid} attributes.
      * @return An object of the given type for the given {@code uuid} attribute, or {@code
null} if none.
      */
@@ -108,26 +108,77 @@ public class ReferenceResolver {
     }
 
     /**
-     * Returns an object of the given type for the given {@code xlink} attribute, or {@code
null}
-     * if none. The default implementation returns {@code null} in all cases.
+     * Returns an object of the given type for the given {@code xlink} attribute, or {@code
null} if none.
+     * The default implementation performs the following lookups:
+     *
+     * <ul>
+     *   <li>If the {@link XLink#getHRef() xlink:href} attribute is an {@linkplain
URI#getFragment() URI fragment}
+     *       of the form {@code "#foo"} and if an object of class {@code type} with the {@code
gml:id="foo"} attribute
+     *       has previously been seen in the same XML document, then that object is returned.</li>
+     *   <li>Otherwise returns {@code null}.</li>
+     * </ul>
      *
      * @param  <T>     The compile-time type of the {@code type} argument.
      * @param  context Context (GML version, locale, <i>etc.</i>) of the (un)marshalling
process.
-     * @param  type    The type of object to be unmarshalled, often as an interface.
+     * @param  type    The type of object to be unmarshalled, often as a GeoAPI interface.
      * @param  link    The {@code xlink} attributes.
      * @return An object of the given type for the given {@code xlink} attribute, or {@code
null} if none.
      */
     public <T> T resolve(final MarshalContext context, final Class<T> type, final
XLink link) {
         ensureNonNull("type",  type);
         ensureNonNull("xlink", link);
+        final URI href = link.getHRef();
+        if (href != null && href.toString().startsWith("#")) {
+            final Object object = Context.getObjectForID(Context.current(), href.getFragment());
+            if (type.isInstance(object)) {
+                return type.cast(object);
+            }
+        }
         return null;
     }
 
     /**
-     * Returns {@code true} if the marshaller can use a reference to the given metadata
-     * instead than writing the full element. This method is invoked when a metadata to
-     * be marshalled has a UUID identifier. Because those metadata may be defined externally,
-     * SIS can not know if the metadata shall be fully marshalled or not.
+     * Returns {@code true} if the marshaller can use a {@code xlink:href="#id"} reference
to the given object
+     * instead than writing the full XML element. This method is invoked by the marshaller
when:
+     *
+     * <ul>
+     *   <li>The given object has already been marshalled in the same XML document.</li>
+     *   <li>The marshalled object had a {@code gml:id} attribute
+     *     <ul>
+     *       <li>either specified explicitely by
+     *         <code>{@linkplain IdentifierMap#put IdentifierMap.put}({@linkplain IdentifierSpace#ID},
id)</code></li>
+     *       <li>or inferred automatically by the marshalled object
+     *         (e.g. {@link org.apache.sis.referencing.AbstractIdentifiedObject}).</li>
+     *     </ul>
+     *   </li>
+     * </ul>
+     *
+     * Note that if this method returns {@code true}, then the use of {@code xlink:href="#id"}
will have
+     * precedence over {@linkplain #canSubstituteByReference(MarshalContext, Class, Object,
UUID) UUID}
+     * and {@linkplain #canSubstituteByReference(MarshalContext, Class, Object, XLink) XLink
alternatives}.
+     *
+     * <p>The default implementation unconditionally returns {@code true}.
+     * Subclasses can override this method if they want to filter which objects to declare
by reference.</p>
+     *
+     * @param  <T>     The compile-time type of the {@code type} argument.
+     * @param  context Context (GML version, locale, <i>etc.</i>) of the (un)marshalling
process.
+     * @param  type    The type of object to be unmarshalled, often as a GeoAPI interface.
+     * @param  object  The object to be marshalled.
+     * @param  id      The {@code gml:id} value of the object to be marshalled.
+     * @return {@code true} if the marshaller can use the {@code xlink:href="#id"} attribute
+     *         instead than marshalling the given object.
+     *
+     * @since 0.7
+     */
+    public <T> boolean canSubstituteByReference(final MarshalContext context, final
Class<T> type, final T object, final String id) {
+        return true;
+    }
+
+    /**
+     * Returns {@code true} if the marshaller can use a reference to the given object
+     * instead than writing the full XML element. This method is invoked when an object to
+     * be marshalled has a UUID identifier. Because those object may be defined externally,
+     * SIS can not know if the object shall be fully marshalled or not.
      * Such information needs to be provided by the application.
      *
      * <p>The default implementation returns {@code true} in the following cases:</p>
@@ -140,11 +191,11 @@ public class ReferenceResolver {
      *
      * @param  <T>     The compile-time type of the {@code type} argument.
      * @param  context Context (GML version, locale, <i>etc.</i>) of the (un)marshalling
process.
-     * @param  type    The type of object to be unmarshalled, often as an interface.
+     * @param  type    The type of object to be unmarshalled, often as a GeoAPI interface.
      * @param  object  The object to be marshalled.
      * @param  uuid    The unique identifier of the object to be marshalled.
      * @return {@code true} if the marshaller can use the {@code uuidref} attribute
-     *         instead than marshalling the given metadata.
+     *         instead than marshalling the given object.
      */
     public <T> boolean canSubstituteByReference(final MarshalContext context, final
Class<T> type, final T object, final UUID uuid) {
         return (object instanceof NilObject) || (object instanceof Emptiable && ((Emptiable)
object).isEmpty());
@@ -152,9 +203,9 @@ public class ReferenceResolver {
 
     /**
      * Returns {@code true} if the marshaller can use a {@code xlink:href} reference to the
given
-     * metadata instead than writing the full element. This method is invoked when a metadata
to be
-     * marshalled has a {@link XLink} identifier. Because those metadata may be defined externally,
-     * SIS can not know if the metadata shall be fully marshalled or not.
+     * object instead than writing the full XML element. This method is invoked when an object
to be
+     * marshalled has a {@link XLink} identifier. Because those object may be defined externally,
+     * SIS can not know if the object shall be fully marshalled or not.
      * Such information needs to be provided by the application.
      *
      * <p>The default implementation returns {@code true} in the following cases:</p>
@@ -167,12 +218,11 @@ public class ReferenceResolver {
      *
      * @param  <T>     The compile-time type of the {@code type} argument.
      * @param  context Context (GML version, locale, <i>etc.</i>) of the (un)marshalling
process.
-     * @param  type    The type of object to be marshalled as an <strong>interface</strong>.
-     *                 This is usually a <a href="http://www.geoapi.org">GeoAPI</a>
interface.
+     * @param  type    The type of object to be unmarshalled, often as a GeoAPI interface.
      * @param  object  The object to be marshalled.
      * @param  link    The reference of the object to be marshalled.
      * @return {@code true} if the marshaller can use the {@code xlink:href} attribute
-     *         instead than marshalling the given metadata.
+     *         instead than marshalling the given object.
      */
     public <T> boolean canSubstituteByReference(final MarshalContext context, final
Class<T> type, final T object, final XLink link) {
         return (object instanceof NilObject) || (object instanceof Emptiable && ((Emptiable)
object).isEmpty());

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/XLink.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/XLink.java?rev=1707580&r1=1707579&r2=1707580&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/XLink.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/XLink.java [UTF-8] Thu Oct
 8 16:24:19 2015
@@ -416,12 +416,7 @@ public class XLink implements Serializab
     }
 
     /**
-     * Returns a URN to an external resources, or to an other part of a XML document, or
an
-     * identifier.
-     *
-     * <div class="note"><b>Note:</b>
-     * This serves a role similar to {@code idref}. The {@code idref} attribute allows an
XML element
-     * to refer to another XML element that has a corresponding {@code id} attribute.</div>
+     * Returns a URN to an external resources, or to an other part of a XML document, or
an identifier.
      *
      * @return A URN to a resources, or {@code null} if none.
      *

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/XML.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/XML.java?rev=1707580&r1=1707579&r2=1707580&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/XML.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/XML.java [UTF-8] Thu Oct 
8 16:24:19 2015
@@ -171,16 +171,21 @@ public final class XML extends Static {
     public static final String GML_VERSION = "org.apache.sis.gml.version";
 
     /**
-     * Allows client code to replace {@code xlink} or {@code uuidref} attributes by the actual
-     * object to use. The value for this property shall be an instance of {@link ReferenceResolver}.
+     * Allows client code to replace {@code xlink} or {@code uuidref} attributes by the actual
objects to use.
+     * The value for this property shall be an instance of {@link ReferenceResolver}.
      *
      * <p>If a property in a XML document is defined only by {@code xlink} or {@code
uuidref} attributes,
-     * without any concrete definition, then the default behavior is to create an empty element
which
-     * contain only the values of the above-cited attributes. This is usually not the right
behavior,
-     * since we should use the reference ({@code href} or {@code uuidref} attributes) for
fetching
-     * the appropriate object. However doing so require some application knowledge, for example
a
-     * catalog where to perform the search, which is left to users. Users can define their
search
-     * algorithm by subclassing {@link ReferenceResolver} and configure a unmarshaller as
below:</p>
+     * without any concrete definition, then the default behavior is as below:</p>
+     *
+     * <ul>
+     *   <li>If the reference is of the form {@code xlink:href="#foo"} and an object
with the {@code gml:id="foo"}
+     *       attribute was previously found in the same XML document, then that object will
be used.</li>
+     *   <li>Otherwise an empty element containing only the values of the above-cited
attributes is created.</li>
+     * </ul>
+     *
+     * Applications can sometime do better by using some domain-specific knowledge, for example
by searching in a
+     * database. Users can define their search algorithm by subclassing {@link ReferenceResolver}
and configuring
+     * a unmarshaller as below:
      *
      * {@preformat java
      *     ReferenceResolver  myResolver = ...;

Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/package-info.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/package-info.java?rev=1707580&r1=1707579&r2=1707580&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/package-info.java [UTF-8]
(original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/xml/package-info.java [UTF-8]
Thu Oct  8 16:24:19 2015
@@ -59,7 +59,7 @@
  * @author  Guilhem Legal (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.4
+ * @version 0.7
  * @module
  */
 package org.apache.sis.xml;

Modified: sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gco/StringAdapterTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gco/StringAdapterTest.java?rev=1707580&r1=1707579&r2=1707580&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gco/StringAdapterTest.java
[UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/jaxb/gco/StringAdapterTest.java
[UTF-8] Thu Oct  8 16:24:19 2015
@@ -32,7 +32,7 @@ import static org.junit.Assert.*;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.7
  * @module
  */
 public final strictfp class StringAdapterTest extends TestCase {
@@ -48,7 +48,7 @@ public final strictfp class StringAdapte
 
     /**
      * Tests {@link StringAdapter#toString(CharSequence)} for an {@link InternationalString}
-     * having loalization in different languages.
+     * having localizations in different languages.
      */
     @Test
     @DependsOnMethod("testToUnlocalizedString")
@@ -57,25 +57,16 @@ public final strictfp class StringAdapte
         i18n.add(Locale.ENGLISH,  "A word");
         i18n.add(Locale.FRENCH,   "Un mot");
         i18n.add(Locale.JAPANESE, "言葉");
-        Context.push(Locale.JAPANESE);
+        final Context context = new Context(0, Locale.ENGLISH, null, null, null, null, null,
null);
         try {
-            assertEquals("言葉", StringAdapter.toString(i18n));
-            Context.push(Locale.FRENCH);
-            try {
-                assertEquals("Un mot", StringAdapter.toString(i18n));
-                Context.push(Locale.ENGLISH);
-                try {
-                    assertEquals("A word", StringAdapter.toString(i18n));
-                } finally {
-                    Context.pull();
-                }
-                assertEquals("Un mot", StringAdapter.toString(i18n));
-            } finally {
-                Context.pull();
-            }
-            assertEquals("言葉", StringAdapter.toString(i18n));
+            Context.push(Locale.JAPANESE);  assertEquals("言葉",    StringAdapter.toString(i18n));
+            Context.push(Locale.FRENCH);    assertEquals("Un mot", StringAdapter.toString(i18n));
+            Context.push(Locale.ENGLISH);   assertEquals("A word", StringAdapter.toString(i18n));
+            Context.pull();                 assertEquals("Un mot", StringAdapter.toString(i18n));
+            Context.pull();                 assertEquals("言葉",    StringAdapter.toString(i18n));
+            Context.pull();                 assertEquals("A word", StringAdapter.toString(i18n));
         } finally {
-            Context.pull();
+            context.finish();
         }
     }
 }




Mime
View raw message