sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1813747 [2/13] - in /sis/branches/JDK9: ./ application/ application/sis-console/ application/sis-console/src/main/artifact/ application/sis-console/src/main/artifact/lib/ application/sis-console/src/main/artifact/lib/darwin/ application/si...
Date Mon, 30 Oct 2017 10:25:10 GMT
Modified: sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -530,7 +530,7 @@ public class DefaultFeatureType extends
          */
         if (feature instanceof DefaultFeatureType) {
             final DefaultFeatureType dt = (DefaultFeatureType) feature;
-            return dt.isResolved = resolve(feature, dt.properties, previous, dt.isResolved);
+            return dt.isResolved = resolve(dt, dt.properties, previous, dt.isResolved);
         } else {
             return resolve(feature, feature.getProperties(false), previous, feature.isSimple());
         }
@@ -559,7 +559,7 @@ public class DefaultFeatureType extends
             for (final PropertyType property : toUpdate) {
                 if (property instanceof FeatureAssociationRole) {
                     if (property instanceof DefaultAssociationRole) {
-                        if (!((DefaultAssociationRole) property).resolve(this)) {
+                        if (!((DefaultAssociationRole) property).resolve(this, properties)) {
                             resolved = false;
                             continue;
                         }

Modified: sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -43,6 +43,7 @@ import org.apache.sis.util.logging.Loggi
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.resources.Vocabulary;
 import org.apache.sis.internal.util.CollectionsExt;
+import org.apache.sis.internal.feature.Geometries;
 import org.apache.sis.internal.system.Modules;
 import org.apache.sis.referencing.IdentifiedObjects;
 import org.apache.sis.math.MathFunctions;
@@ -98,6 +99,11 @@ public class FeatureFormat extends Tabul
     private static final long serialVersionUID = -5792086817264884947L;
 
     /**
+     * The separator to use in comma-separated lists.
+     */
+    private static final String SEPARATOR = ", ";
+
+    /**
      * An instance created when first needed and potentially shared.
      */
     private static final AtomicReference<FeatureFormat> INSTANCE = new AtomicReference<>();
@@ -350,7 +356,7 @@ public class FeatureFormat extends Tabul
             String separator = " ⇾ ";                                       // UML symbol for inheritance.
             for (final FeatureType parent : featureType.getSuperTypes()) {
                 toAppendTo.append(separator).append(toString(parent.getName()));
-                separator = ", ";
+                separator = SEPARATOR;
             }
         }
         toAppendTo.append(getLineSeparator());
@@ -463,19 +469,37 @@ public class FeatureFormat extends Tabul
                 if (!isFirstColumn) nextColumn(table);
                 isFirstColumn = false;
                 switch (column) {
+                    /*
+                     * Human-readable name of the property. May contains any characters (spaces, ideographs, etc).
+                     * In many cases, this information is not provided and the whole column is skipped.
+                     */
                     case DESIGNATION: {
                         final InternationalString d = propertyType.getDesignation();
                         if (d != null) table.append(d.toString(displayLocale));
                         break;
                     }
+                    /*
+                     * Machine-readable name of the property (identifier). This information is mandatory.
+                     * This name is usually shorter than the designation and should contain only valid
+                     * Unicode identifier characters (e.g. no spaces).
+                     */
                     case NAME: {
                         table.append(toString(propertyType.getName()));
                         break;
                     }
+                    /*
+                     * The base class or interface for all values in properties of the same type.
+                     * This is typically String, Number, Integer, Geometry or URL.
+                     */
                     case TYPE: {
                         table.append(valueType);
                         break;
                     }
+                    /*
+                     * Minimum and maximum number of occurrences allowed for this property.
+                     * If we are formatting a Feature instead than a FeatureType, then the
+                     * actual number of values is also formatted. Example: 42 ∈ [0 … ∞]
+                     */
                     case CARDINALITY: {
                         table.setCellAlignment(TableAppender.ALIGN_RIGHT);
                         if (cardinality >= 0) {
@@ -501,6 +525,12 @@ public class FeatureFormat extends Tabul
                         }
                         break;
                     }
+                    /*
+                     * If formatting a FeatureType, the default value. If formatting a Feature, the actual value.
+                     * A java.text.Format instance dedicated to the value class is used if possible. In addition
+                     * to types for which a java.text.Format may be available, we also have to check for other
+                     * special cases. If there is more than one value, they are formatted as a coma-separated list.
+                     */
                     case VALUE: {
                         table.setCellAlignment(TableAppender.ALIGN_LEFT);
                         final Format format = getFormat(valueClass);                            // Null if valueClass is null.
@@ -555,28 +585,62 @@ public class FeatureFormat extends Tabul
                                 length = formatValue(value, table.append(separator), length);
                                 buffer.setLength(0);
                                 if (length < 0) break;      // Value is too long, abandon remaining iterations.
-                                separator = ", ";
-                                length += 2;
+                                separator = SEPARATOR;
+                                length += SEPARATOR.length();
                             }
                         }
                         break;
                     }
+                    /*
+                     * Characteristics are optional information attached to some values. For example if a property
+                     * value is a temperature measurement, a characteritic of that value may be the unit of measure.
+                     * Characteristics are handled as "attributes of attributes".
+                     */
                     case CHARACTERISTICS: {
                         if (propertyType instanceof AttributeType<?>) {
+                            int length = 0;
                             String separator = "";
-                            for (final AttributeType<?> attribute : ((AttributeType<?>) propertyType).characteristics().values()) {
-                                table.append(separator).append(toString(attribute.getName()));
-                                Object c = attribute.getDefaultValue();
+format:                     for (final AttributeType<?> ct : ((AttributeType<?>) propertyType).characteristics().values()) {
+                                /*
+                                 * Format the characteristic name. We will append the value(s) later.
+                                 * We keep trace of the text length in order to stop formatting if the
+                                 * text become too long.
+                                 */
+                                final GenericName cn = ct.getName();
+                                final String cs = toString(cn);
+                                table.append(separator).append(cs);
+                                length += separator.length() + cs.length();
+                                Collection<?> cv = CollectionsExt.singletonOrEmpty(ct.getDefaultValue());
                                 if (feature != null) {
-                                    final Property p = feature.getProperty(propertyType.getName().toString());
-                                    if (p instanceof Attribute<?>) {            // Should always be true, but we are paranoiac.
-                                        c = ((Attribute<?>) p).characteristics().get(attribute.getName().toString());
+                                    /*
+                                     * Usually, the property 'cp' below is null because all features use the same
+                                     * characteristic value (for example the same unit of measurement),  which is
+                                     * given by the default value 'cv'.  Nevertheless we have to check if current
+                                     * feature overrides this characteristic.
+                                     */
+                                    final Property cp = feature.getProperty(propertyType.getName().toString());
+                                    if (cp instanceof Attribute<?>) {            // Should always be true, but we are paranoiac.
+                                        Attribute<?> ca = ((Attribute<?>) cp).characteristics().get(cn.toString());
+                                        if (ca != null) cv = ca.getValues();
                                     }
                                 }
-                                if (c != null) {
-                                    formatValue(c, table.append(" = "), 0);
+                                /*
+                                 * Now format the value, separated from the name with " = ". Example: unit = m/s
+                                 * If the value accepts multi-occurrences, we will format the value between {…}.
+                                 * We use {…} because we may have more than one characteristic in the same cell,
+                                 * so we need a way to distinguish multi-values from multi-characteristics.
+                                 */
+                                final boolean multi = ct.getMaximumOccurs() > 1;
+                                String sep = multi ? " = {" : " = ";
+                                for (Object c : cv) {
+                                    length = formatValue(c, table.append(sep), length += sep.length());
+                                    if (length < 0) break format;   // Value is too long, abandon remaining iterations.
+                                    sep = SEPARATOR;
+                                }
+                                separator = SEPARATOR;
+                                if (multi && sep == SEPARATOR) {
+                                    table.append('}');
                                 }
-                                separator = ", ";
                             }
                         }
                         break;
@@ -635,7 +699,7 @@ public class FeatureFormat extends Tabul
      *         the length exceed the maximal length (in which case the caller should break iteration).
      */
     private int formatValue(final Object value, final TableAppender table, final int length) {
-        final String text;
+        String text;
         if (value instanceof InternationalString) {
             text = ((InternationalString) value).toString(displayLocale);
         } else if (value instanceof GenericName) {
@@ -644,7 +708,7 @@ public class FeatureFormat extends Tabul
             text = toString(((IdentifiedType) value).getName());
         } else if (value instanceof IdentifiedObject) {
             text = IdentifiedObjects.getIdentifierOrName((IdentifiedObject) value);
-        } else {
+        } else if ((text = Geometries.toString(value)) == null) {
             text = value.toString();
         }
         final int remaining = MAXIMAL_VALUE_LENGTH - length;

Modified: sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/NamedFeatureType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/NamedFeatureType.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/NamedFeatureType.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/NamedFeatureType.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -53,9 +53,9 @@ final class NamedFeatureType implements
 
     /**
      * The feature type to use instead of the {@code NamedFeatureType}. Initially null, then set to the "real"
-     * feature type after {@link DefaultAssociationRole#resolve(DefaultFeatureType)} has been able to create it.
-     * This information is stored in case the same {@code NamedFeatureType} instance has been used in more than
-     * one {@link DefaultFeatureType}.
+     * feature type after {@link DefaultAssociationRole#resolve(DefaultFeatureType, Collection)} has been able
+     * to create it. This information is stored in case the same {@code NamedFeatureType} instance has been used
+     * in more than one {@link DefaultFeatureType}.
      */
     volatile FeatureType resolved;
 

Modified: sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -202,6 +202,10 @@ public class FeatureTypeBuilder extends
 
     /**
      * Creates a new builder instance using the given feature type as a template.
+     * This constructor initializes the list of {@linkplain #properties() properties}, the
+     * {@linkplain #getSuperTypes() super types} and {@link #isAbstract() isAbstract} flag
+     * to values inferred from the given template. The properties list will contain properties
+     * declared explicitely in the given template, not including properties inherited from super types.
      *
      * @param template  an existing feature type to use as a template, or {@code null} if none.
      *
@@ -263,6 +267,7 @@ public class FeatureTypeBuilder extends
     /**
      * Sets all properties of this builder to the values of the given feature type.
      * This builder is {@linkplain #clear() cleared} before the properties of the given type are copied.
+     * The copy is performed as documented in the {@linkplain #FeatureTypeBuilder(FeatureType) constructor}.
      *
      * @param  template  an existing feature type to use as a template, or {@code null} if none.
      * @return {@code this} for allowing method calls chaining.
@@ -407,9 +412,10 @@ public class FeatureTypeBuilder extends
 
     /**
      * Sets the parent types (or super-type) from which to inherit properties.
-     * If this method is not invoked, then the default value is to have no parent.
+     * If this method is not invoked, then the default value is no parent.
      *
      * @param  parents  the parent types from which to inherit properties, or an empty array if none.
+     *                  Null elements are ignored.
      * @return {@code this} for allowing method calls chaining.
      */
     public FeatureTypeBuilder setSuperTypes(final FeatureType... parents) {
@@ -418,6 +424,11 @@ public class FeatureTypeBuilder extends
         if (!superTypes.equals(asList)) {
             superTypes.clear();
             superTypes.addAll(asList);
+            for (int i=superTypes.size(); --i >= 0;) {
+                if (superTypes.get(i) == null) {
+                    superTypes.remove(i);
+                }
+            }
             clearCache();
         }
         return this;
@@ -595,10 +606,12 @@ public class FeatureTypeBuilder extends
 
     /**
      * Returns a view of all attributes and associations added to the {@code FeatureType} to build.
+     * This list contains only properties declared explicitely to this builder;
+     * it does not include properties inherited from {@linkplain #getSuperTypes() super-types}.
      * The returned list is <cite>live</cite>: changes in this builder are reflected in that list and conversely.
      * However the returned list allows only {@linkplain List#remove(Object) remove} operations;
      * new attributes or associations can be added only by calls to one of the {@code addAttribute(…)}
-     * or {@code addAssociation(…)} methods.
+     * or {@code addAssociation(…)} methods. Removal operations never affect the super-types.
      *
      * @return a live list over the properties declared to this builder.
      *

Modified: sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/ESRI.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/ESRI.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/ESRI.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/ESRI.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -23,9 +23,12 @@ import com.esri.core.geometry.MultiPath;
 import com.esri.core.geometry.Polyline;
 import com.esri.core.geometry.Polygon;
 import com.esri.core.geometry.Point;
+import com.esri.core.geometry.WktImportFlags;
+import com.esri.core.geometry.OperatorImportFromWkt;
 import org.apache.sis.geometry.GeneralEnvelope;
 import org.apache.sis.setup.GeometryLibrary;
 import org.apache.sis.math.Vector;
+import org.apache.sis.util.Classes;
 
 
 /**
@@ -48,6 +51,14 @@ final class ESRI extends Geometries<Geom
     }
 
     /**
+     * If the given object is a JTS geometry, returns a short string representation the class name.
+     */
+    @Override
+    final String tryGetLabel(Object geometry) {
+        return (geometry instanceof Geometry) ? Classes.getShortClassName(geometry) : null;
+    }
+
+    /**
      * If the given object is an ESRI geometry and its envelope is non-empty, returns
      * that envelope as an Apache SIS implementation. Otherwise returns {@code null}.
      *
@@ -169,4 +180,12 @@ final class ESRI extends Geometries<Geom
         }
         return path;
     }
+
+    /**
+     * Parses the given WKT.
+     */
+    @Override
+    public Object parseWKT(final String wkt) {
+        return OperatorImportFromWkt.local().execute(WktImportFlags.wktImportDefaults, Geometry.Type.Unknown, wkt, null);
+    }
 }

Modified: sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Geometries.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -93,7 +93,7 @@ public abstract class Geometries<G> {
         this.pointClass    = pointClass;
         this.polylineClass = polylineClass;
         this.polygonClass  = polygonClass;
-        fallback = implementation;
+        this.fallback      = implementation;
     }
 
     /**
@@ -178,7 +178,7 @@ public abstract class Geometries<G> {
     abstract GeneralEnvelope tryGetEnvelope(Object geometry);
 
     /**
-     * If the given object is one of the recognized type and its envelope is non-empty,
+     * If the given object is one of the recognized types and its envelope is non-empty,
      * returns that envelope as an Apache SIS implementation. Otherwise returns {@code null}.
      *
      * @param  geometry  the geometry from which to get the envelope, or {@code null}.
@@ -194,6 +194,35 @@ public abstract class Geometries<G> {
     }
 
     /**
+     * If the given geometry is the type supported by this {@code Geometries} instance,
+     * returns a short string representation the class name. Otherwise returns {@code null}.
+     */
+    abstract String tryGetLabel(Object geometry);
+
+    /**
+     * If the given object is one of the recognized types, returns a short string representation
+     * (typically the class name and the bounds). Otherwise returns {@code null}.
+     *
+     * @param  geometry  the geometry from which to get a string representation, or {@code null}.
+     * @return a short string representation of the given geometry, or {@code null} if the given
+     *         object is not a recognized geometry.
+     */
+    public static String toString(final Object geometry) {
+        for (Geometries<?> g = implementation; g != null; g = g.fallback) {
+            String s = g.tryGetLabel(geometry);
+            if (s != null) {
+                GeneralEnvelope env = g.tryGetEnvelope(geometry);
+                if (env != null) {
+                    final String bbox = env.toString();
+                    s += bbox.substring(bbox.indexOf('('));
+                }
+                return s;
+            }
+        }
+        return null;
+    }
+
+    /**
      * Creates a two-dimensional point from the given coordinate. If the CRS is geographic, then the
      * (x,y) values should be (longitude, latitude) for compliance with usage in ESRI and JTS libraries.
      *
@@ -255,6 +284,14 @@ public abstract class Geometries<G> {
     }
 
     /**
+     * Parses the given WKT.
+     *
+     * @param  wkt  the WKT to parse.
+     * @return the geometry object for the given WKT.
+     */
+    public abstract Object parseWKT(String wkt);
+
+    /**
      * Returns an error message for an unsupported geometry object.
      *
      * @param  dimension  number of dimensions (2 or 3) requested for the geometry object.

Modified: sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/JTS.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -21,6 +21,7 @@ import java.lang.reflect.Method;
 import java.lang.reflect.InvocationTargetException;
 import org.apache.sis.geometry.GeneralEnvelope;
 import org.apache.sis.math.Vector;
+import org.apache.sis.util.Classes;
 
 
 /**
@@ -62,6 +63,14 @@ final class JTS extends Geometries<Objec
     }
 
     /**
+     * If the given object is a JTS geometry, returns a short string representation the class name.
+     */
+    @Override
+    final String tryGetLabel(Object geometry) {
+        return (rootClass.isInstance(geometry)) ? Classes.getShortClassName(geometry) : null;
+    }
+
+    /**
      * If the given object is a JTS geometry and its envelope is non-empty, returns
      * that envelope as an Apache SIS implementation. Otherwise returns {@code null}.
      *
@@ -137,4 +146,12 @@ final class JTS extends Geometries<Objec
     final Object tryMergePolylines(final Object first, final Iterator<?> polylines) {
         throw unsupported(2);   // TODO - see class javadoc
     }
+
+    /**
+     * Parses the given WKT.
+     */
+    @Override
+    public Object parseWKT(final String wkt) {
+        throw unsupported(2);
+    }
 }

Modified: sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Java2D.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Java2D.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Java2D.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-feature/src/main/java/org/apache/sis/internal/feature/Java2D.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -26,6 +26,7 @@ import org.apache.sis.geometry.GeneralEn
 import org.apache.sis.setup.GeometryLibrary;
 import org.apache.sis.internal.referencing.j2d.ShapeUtilities;
 import org.apache.sis.math.Vector;
+import org.apache.sis.util.Classes;
 
 
 /**
@@ -48,6 +49,21 @@ final class Java2D extends Geometries<Sh
     }
 
     /**
+     * If the given geometry is a Java2D geometry, returns a short string representation the class name,
+     * ignoring the primitive type specialization. For example if the class is {@code Rectangle2D.Float},
+     * then this method returns {@code "Rectangle2D"}.
+     */
+    @Override
+    final String tryGetLabel(Object geometry) {
+        if (geometry instanceof Shape) {
+            Class<?> c = geometry.getClass();
+            Class<?> e = c.getEnclosingClass();
+            return Classes.getShortName(e != null ? e : c);
+        }
+        return null;
+    }
+
+    /**
      * If the given object is a Java2D geometry and its envelope is non-empty, returns
      * that envelope as an Apache SIS implementation. Otherwise returns {@code null}.
      *
@@ -197,4 +213,12 @@ final class Java2D extends Geometries<Sh
         }
         return ShapeUtilities.toPrimitive(path);
     }
+
+    /**
+     * Parses the given WKT.
+     */
+    @Override
+    public Object parseWKT(final String wkt) {
+        throw unsupported(2);
+    }
 }

Modified: sis/branches/JDK9/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureFormatTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureFormatTest.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureFormatTest.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureFormatTest.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -157,16 +157,16 @@ public final strictfp class FeatureForma
         final FeatureFormat format = create();
         final String text = format.format(feature);
         assertMultilinesEquals("World metropolis\n" +
-                "┌──────────────┬─────────────────────┬─────────────┬──────────────┬─────────────────┐\n" +
-                "│ Name         │ Type                │ Cardinality │ Value        │ Characteristics │\n" +
-                "├──────────────┼─────────────────────┼─────────────┼──────────────┼─────────────────┤\n" +
-                "│ city         │ String              │ 1 ∈ [1 … 1] │ Tokyo        │                 │\n" +
-                "│ population   │ Integer             │ 1 ∈ [1 … 1] │ 13,185,502   │                 │\n" +
-                "│ region       │ InternationalString │ 0 ∉ [1 … 1] │              │                 │\n" +
-                "│ isGlobal     │ Boolean             │ 0 ∉ [1 … 1] │              │                 │\n" +
-                "│ universities │ String              │ 2 ∈ [0 … ∞] │ Waseda, Keio │                 │\n" +
-                "│ temperature  │ Float               │ 1 ∈ [1 … 1] │ NaN          │ accuracy, units │\n" +
-                "└──────────────┴─────────────────────┴─────────────┴──────────────┴─────────────────┘\n", text);
+                "┌──────────────┬─────────────────────┬─────────────┬──────────────┬────────────────────────────┐\n" +
+                "│ Name         │ Type                │ Cardinality │ Value        │ Characteristics            │\n" +
+                "├──────────────┼─────────────────────┼─────────────┼──────────────┼────────────────────────────┤\n" +
+                "│ city         │ String              │ 1 ∈ [1 … 1] │ Tokyo        │                            │\n" +
+                "│ population   │ Integer             │ 1 ∈ [1 … 1] │ 13,185,502   │                            │\n" +
+                "│ region       │ InternationalString │ 0 ∉ [1 … 1] │              │                            │\n" +
+                "│ isGlobal     │ Boolean             │ 0 ∉ [1 … 1] │              │                            │\n" +
+                "│ universities │ String              │ 2 ∈ [0 … ∞] │ Waseda, Keio │                            │\n" +
+                "│ temperature  │ Float               │ 1 ∈ [1 … 1] │ NaN          │ accuracy = 0.1, units = °C │\n" +
+                "└──────────────┴─────────────────────┴─────────────┴──────────────┴────────────────────────────┘\n", text);
     }
 
     /**

Modified: sis/branches/JDK9/core/sis-feature/src/test/java/org/apache/sis/feature/builder/FeatureTypeBuilderTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-feature/src/test/java/org/apache/sis/feature/builder/FeatureTypeBuilderTest.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-feature/src/test/java/org/apache/sis/feature/builder/FeatureTypeBuilderTest.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-feature/src/test/java/org/apache/sis/feature/builder/FeatureTypeBuilderTest.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -20,8 +20,8 @@ import java.util.Iterator;
 import java.util.Collections;
 import com.esri.core.geometry.Geometry;
 import com.esri.core.geometry.Point;
-import org.apache.sis.feature.AbstractOperation;
 import org.opengis.geometry.Envelope;
+import org.apache.sis.feature.AbstractOperation;
 import org.apache.sis.internal.feature.AttributeConvention;
 import org.apache.sis.feature.DefaultFeatureTypeTest;
 import org.apache.sis.feature.FeatureOperations;
@@ -47,6 +47,7 @@ import org.opengis.feature.Operation;
  *
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
+ * @author  Michael Hausegger
  * @version 0.8
  * @since   0.8
  * @module
@@ -54,9 +55,56 @@ import org.opengis.feature.Operation;
 @DependsOn(AttributeTypeBuilderTest.class)
 public final strictfp class FeatureTypeBuilderTest extends TestCase {
     /**
+     * Verifies that {@link FeatureTypeBuilder#setSuperTypes(FeatureType...)} ignores null parents.
+     * This method tests only the builder state without creating feature type.
+     */
+    @Test
+    public void testNullParents() {
+        final FeatureTypeBuilder builder = new FeatureTypeBuilder(null);
+        assertSame(builder, builder.setSuperTypes(new FeatureType[6]));
+        assertEquals(0, builder.getSuperTypes().length);
+    }
+
+    /**
+     * Verifies {@link FeatureTypeBuilder#setAbstract(boolean)}.
+     * This method tests only the builder state without creating feature type.
+     */
+    @Test
+    public void testSetAbstract() {
+        final FeatureTypeBuilder builder = new FeatureTypeBuilder(null);
+        assertFalse("isAbstract", builder.isAbstract());
+        assertSame (builder, builder.setAbstract(true));
+        assertTrue ("isAbstract", builder.isAbstract());
+    }
+
+    /**
+     * Verifies {@link FeatureTypeBuilder#setDeprecated(boolean)}.
+     * This method tests only the builder state without creating feature type.
+     */
+    @Test
+    public void testSetDeprecated() {
+        FeatureTypeBuilder builder = new FeatureTypeBuilder();
+        assertFalse("isDeprecated", builder.isDeprecated());
+        builder.setDeprecated(true);
+        assertTrue("isDeprecated", builder.isDeprecated());
+    }
+
+    /**
+     * Verifies {@link FeatureTypeBuilder#setNameSpace(CharSequence)}.
+     */
+    @Test
+    public void testSetNameSpace() {
+        final FeatureTypeBuilder builder = new FeatureTypeBuilder();
+        assertNull("nameSpace", builder.getNameSpace());
+        assertSame(builder, builder.setNameSpace("myNameSpace"));
+        assertEquals("nameSpace", "myNameSpace", builder.getNameSpace());
+    }
+
+    /**
      * Tests with the minimum number of parameters (no property and no super type).
      */
     @Test
+    @DependsOnMethod({"testSetAbstract", "testSetDeprecated", "testSetNameSpace"})
     public void testInitialization() {
         final FeatureTypeBuilder builder = new FeatureTypeBuilder();
         try {

Modified: sis/branches/JDK9/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -54,6 +54,7 @@ import org.junit.BeforeClass;
     org.apache.sis.internal.feature.AttributeConventionTest.class,
     org.apache.sis.feature.builder.CharacteristicTypeBuilderTest.class,
     org.apache.sis.feature.builder.AttributeTypeBuilderTest.class,
+    org.apache.sis.feature.builder.AssociationRoleBuilderTest.class,
     org.apache.sis.feature.builder.FeatureTypeBuilderTest.class
 })
 public final strictfp class FeatureTestSuite extends TestSuite {

Modified: sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/direct/GO_ScopedName.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/direct/GO_ScopedName.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/direct/GO_ScopedName.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/metadata/direct/GO_ScopedName.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -19,7 +19,7 @@ package org.apache.sis.internal.jaxb.met
 import javax.xml.bind.annotation.adapters.XmlAdapter;
 import org.opengis.util.ScopedName;
 import org.opengis.util.GenericName;
-import org.apache.sis.internal.jaxb.gml.CodeType;
+import org.apache.sis.internal.jaxb.gco.NameValue;
 
 
 /**
@@ -34,7 +34,7 @@ import org.apache.sis.internal.jaxb.gml.
  * @since 0.5
  * @module
  */
-public final class GO_ScopedName extends XmlAdapter<CodeType.ScopedName, ScopedName> {
+public final class GO_ScopedName extends XmlAdapter<NameValue.Scoped, ScopedName> {
     /**
      * Converts a GeoAPI interface to the SIS implementation for XML marshalling.
      *
@@ -42,9 +42,9 @@ public final class GO_ScopedName extends
      * @return the adapter for the given value, here the SIS implementation.
      */
     @Override
-    public CodeType.ScopedName marshal(final ScopedName name) {
+    public NameValue.Scoped marshal(final ScopedName name) {
         if (name != null) {
-            final CodeType.ScopedName code = new CodeType.ScopedName();
+            final NameValue.Scoped code = new NameValue.Scoped();
             code.setName(name);
             return code;
         }
@@ -58,7 +58,7 @@ public final class GO_ScopedName extends
      * @return the value to marshal (which is the same).
      */
     @Override
-    public ScopedName unmarshal(final CodeType.ScopedName code) {
+    public ScopedName unmarshal(final NameValue.Scoped code) {
         if (code != null) {
             final GenericName parsed = code.getName();
             if (parsed instanceof ScopedName) {

Modified: sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/AxisDirections.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -429,22 +429,22 @@ public final class AxisDirections extend
      * Returns the angular unit of the specified coordinate system.
      * The preference will be given to the longitude axis, if found.
      *
-     * @param  cs    the coordinate system from which to get the angular unit, or {@code null}.
-     * @param  unit  the default unit to return if no angular unit is found.
+     * @param  cs        the coordinate system from which to get the angular unit, or {@code null}.
+     * @param  fallback  the default unit to return if no angular unit is found.
      * @return the angular unit, of {@code unit} if no angular unit was found.
      *
      * @see org.apache.sis.internal.referencing.ReferencingUtilities#getUnit(CoordinateSystem)
      *
      * @since 0.6
      */
-    public static Unit<Angle> getAngularUnit(final CoordinateSystem cs, Unit<Angle> unit) {
+    public static Unit<Angle> getAngularUnit(final CoordinateSystem cs, Unit<Angle> fallback) {
         if (cs != null) {
             for (int i = cs.getDimension(); --i>=0;) {
                 final CoordinateSystemAxis axis = cs.getAxis(i);
                 if (axis != null) {                                                     // Paranoiac check.
                     final Unit<?> candidate = axis.getUnit();
                     if (Units.isAngular(candidate)) {
-                        unit = candidate.asType(Angle.class);
+                        fallback = candidate.asType(Angle.class);
                         if (AxisDirection.EAST.equals(absolute(axis.getDirection()))) {
                             break;                                                      // Found the longitude axis.
                         }
@@ -452,7 +452,7 @@ public final class AxisDirections extend
                 }
             }
         }
-        return unit;
+        return fallback;
     }
 
     /**

Modified: sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/NameMeaning.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/NameMeaning.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/NameMeaning.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/NameMeaning.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -29,19 +29,20 @@ import org.opengis.referencing.operation
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.citation.Citation;
 import org.apache.sis.util.Static;
+import org.apache.sis.internal.util.Utilities;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.internal.util.DefinitionURI;
 import org.apache.sis.metadata.iso.citation.Citations;
 
 
 /**
- * The meaning of some part of URN in the {@code "ogc"} namespace.
+ * The meaning of some parts of URN in the {@code "ogc"} namespace.
  * The meaning are defined by <cite>OGC Naming Authority</cite> (OGCNA) or other OGC sources.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.7
+ * @version 0.8
  *
- * @see org.apache.sis.internal.util.DefinitionURI
+ * @see DefinitionURI
  * @see <a href="http://www.opengeospatial.org/ogcna">http://www.opengeospatial.org/ogcna</a>
  * @see <a href="http://portal.opengeospatial.org/files/?artifact_id=24045">Definition identifier URNs in OGC namespace</a>
  *
@@ -71,7 +72,7 @@ public final class NameMeaning extends S
 
     /**
      * The object types for instances of {@link #CLASSES}.
-     * See {@link org.apache.sis.internal.util.DefinitionURI} javadoc for a list of object types in URN.
+     * See {@link DefinitionURI} javadoc for a list of object types in URN.
      *
      * <p>Types not yet listed (waiting to see if there is a use for them):</p>
      *
@@ -142,8 +143,10 @@ public final class NameMeaning extends S
 
     /**
      * Formats the given identifier using the {@code "ogc:urn:def:"} syntax with possible heuristic changes to
-     * the given values. This method delegates to {@link DefinitionURI#format(String, String, String, String)}
-     * after "fixing" the given values using some heuristic knowledge about the meaning of URN.
+     * the given values. The identifier code space, version and code are appended omitting any characters that
+     * are not valid for a Unicode identifier. If some information are missing in the given identifier, then
+     * this method returns {@code null}. This method tries to "fix" the given values using some heuristic
+     * knowledge about the meaning of URN.
      *
      * @param  type       the object type.
      * @param  authority  the authority as one of the values documented in {@link DefinitionURI} javadoc.
@@ -151,49 +154,67 @@ public final class NameMeaning extends S
      * @param  code       the code.
      * @return an identifier using the URN syntax, or {@code null} if a mandatory information is missing.
      *
-     * @see DefinitionURI#format(String, String, String, String)
-     *
      * @since 0.7
      */
     public static String toURN(final Class<?> type, final String authority, String version, String code) {
-        if (type != null && authority != null && code != null) {
-            final String key = authority.toUpperCase(Locale.US);
-            String codeSpace = AUTHORITIES.get(key);
-            if (codeSpace == null) {
-                /*
-                 * If the given authority is not one of the authorities that we expected for the OGC namespace,
-                 * verify if we can related it to one of the specifications enumerated in the Citations class.
-                 * For example if the user gave us "OGP" as the authority, we will replace that by "IOGP" (the
-                 * new name for that organization).
-                 */
-                final Citation c = Citations.fromName(key);
-                codeSpace = org.apache.sis.internal.util.Citations.getCodeSpace(c);
-                if (AUTHORITIES.get(codeSpace) == null) {
-                    return null;            // Not an authority that we recognize for the OGC namespace.
-                }
-                version = getVersion(c);    // Unconditionally overwrite the user-specified version.
+        if (type == null || authority == null || code == null) {
+            return null;
+        }
+        final String key = authority.toUpperCase(Locale.US);
+        String codeSpace = AUTHORITIES.get(key);
+        if (codeSpace == null) {
+            /*
+             * If the given authority is not one of the authorities that we expected for the OGC namespace,
+             * verify if we can related it to one of the specifications enumerated in the Citations class.
+             * For example if the user gave us "OGP" as the authority, we will replace that by "IOGP" (the
+             * new name for that organization).
+             */
+            final Citation c = Citations.fromName(key);
+            codeSpace = Citations.getCodeSpace(c);
+            if (AUTHORITIES.get(codeSpace) == null) {
+                return null;            // Not an authority that we recognize for the OGC namespace.
+            }
+            version = getVersion(c);    // Unconditionally overwrite the user-specified version.
+            /*
+             * If the above lines resulted in a change of codespace, we may need to concatenate the authority
+             * with the code for preserving information. The main use case is WMS codes like "CRS:84":
+             *
+             *   1) Citations.fromName("CRS") gave us Citations.WMS (version 1.3) as the authority.
+             *   2) getCodeSpace(Citations.WMS) gave us "OGC", which is indeed the codespace used in URN.
+             *   3) OGC Naming Authority – Procedures (OGC-09-046r2) said that "CRS:84" should be formatted
+             *      as "urn:ogc:def:crs:OGC:1.3:CRS84". We already got the "OGC" and "1.3" parts with above
+             *      steps, the last part is to replace "84" by "CRS84".
+             */
+            if (!authority.equals(codeSpace) && !code.startsWith(authority)) {
+                code = authority + code;    // Intentionally no ':' separator.
+            }
+        }
+        final StringBuilder buffer = new StringBuilder(DefinitionURI.PREFIX);
+loop:   for (int p=0; ; p++) {
+            final String part;
+            switch (p) {
+                case 0:  part = toObjectType(type); break;
+                case 1:  part = codeSpace;          break;
+                case 2:  part = version;            break;
+                case 3:  part = code;               break;
+                default: break loop;
+            }
+            if (!Utilities.appendUnicodeIdentifier(buffer.append(DefinitionURI.SEPARATOR), '\u0000', part, ".-", false)) {
                 /*
-                 * If the above lines resulted in a chance of codespace, we may need to concatenate the authority
-                 * with the code for preserving information. The main use case is WMS codes like "CRS:84":
-                 *
-                 *   1) Citations.fromName("CRS") gave us Citations.WMS (version 1.3) as the authority.
-                 *   2) getCodeSpace(Citations.WMS) gave us "OGC", which is indeed the codespace used in URN.
-                 *   3) OGC Naming Authority – Procedures (OGC-09-046r2) said that "CRS:84" should be formatted
-                 *      as "urn:ogc:def:crs:OGC:1.3:CRS84". We already got the "OGC" and "1.3" parts with above
-                 *      steps, the last part is to replace "84" by "CRS84".
+                 * Only the version (p = 2) is optional. All other fields are mandatory.
+                 * If no character has been added for a mandatory field, we can not build a URN.
                  */
-                if (!authority.equals(codeSpace) && !code.startsWith(authority)) {
-                    code = authority + code;    // Intentionally no ':' separator.
+                if (p != 2) {
+                    return null;
                 }
             }
-            return DefinitionURI.format(toObjectType(type), codeSpace, version, code);
         }
-        return null;
+        return buffer.toString();
     }
 
     /**
      * Returns the "object type" part of an OGC URN for the given class, or {@code null} if unknown.
-     * See {@link org.apache.sis.internal.util.DefinitionURI} javadoc for a list of object types in URN.
+     * See {@link DefinitionURI} javadoc for a list of object types in URN.
      *
      * @param  type  the class for which to get the URN type.
      * @return the URN type, or {@code null} if unknown.

Modified: sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/ReferencingServices.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -31,17 +31,14 @@ import org.opengis.referencing.crs.CRSFa
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.SingleCRS;
 import org.opengis.referencing.crs.DerivedCRS;
-import org.opengis.referencing.crs.GeodeticCRS;
 import org.opengis.referencing.crs.VerticalCRS;
 import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.cs.CSFactory;
 import org.opengis.referencing.cs.CartesianCS;
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.cs.CoordinateSystemAxis;
-import org.opengis.referencing.cs.EllipsoidalCS;
 import org.opengis.referencing.datum.DatumFactory;
 import org.opengis.referencing.datum.PrimeMeridian;
-import org.opengis.referencing.datum.VerticalDatum;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
 import org.opengis.referencing.operation.CoordinateOperationFactory;
@@ -58,7 +55,6 @@ import org.apache.sis.internal.system.De
 import org.apache.sis.internal.system.OptionalDependency;
 import org.apache.sis.internal.system.Modules;
 import org.apache.sis.io.wkt.FormattableObject;
-import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.Deprecable;
 
 
@@ -438,85 +434,6 @@ public class ReferencingServices extends
     }
 
     /**
-     * Creates a compound CRS, but we special processing for (two-dimensional Geographic + ellipsoidal heights) tupples.
-     * If any such tupple is found, a three-dimensional geographic CRS is created instead than the compound CRS.
-     *
-     * @param  crsFactory  the factory to use for creating compound or three-dimensional geographic CRS.
-     * @param  csFactory   the factory to use for creating three-dimensional ellipsoidal CS, if needed.
-     * @param  properties  name and other properties to give to the new object.
-     * @param  components  ordered array of {@code CoordinateReferenceSystem} objects.
-     * @return the coordinate reference system for the given properties.
-     * @throws FactoryException if the object creation failed.
-     *
-     * @since 0.7
-     */
-    public final CoordinateReferenceSystem createCompoundCRS(final CRSFactory crsFactory, final CSFactory csFactory,
-            final Map<String,?> properties, CoordinateReferenceSystem... components) throws FactoryException
-    {
-        for (int i=0; i<components.length; i++) {
-            final CoordinateReferenceSystem vertical = components[i];
-            if (vertical instanceof VerticalCRS) {
-                final VerticalDatum datum = ((VerticalCRS) vertical).getDatum();
-                if (datum != null && datum.getVerticalDatumType() == VerticalDatumTypes.ELLIPSOIDAL) {
-                    int axisPosition = 0;
-                    EllipsoidalCS cs = null;
-                    CoordinateReferenceSystem crs = null;
-                    if (i == 0 || (cs = getCsIfGeographic2D(crs = components[i - 1])) == null) {
-                        /*
-                         * GeographicCRS are normally before VerticalCRS. But Apache SIS is tolerant to the
-                         * opposite order (note however that such ordering is illegal according ISO 19162).
-                         */
-                        if (i+1 >= components.length || (cs = getCsIfGeographic2D(crs = components[i + 1])) == null) {
-                            continue;
-                        }
-                        axisPosition = 1;
-                    }
-                    /*
-                     * At this point we have the horizontal and vertical components. The horizontal component
-                     * begins at 'axisPosition', which is almost always zero. Create the three-dimensional CRS.
-                     * If the result is the CRS to be returned directly by this method (components.length == 2),
-                     * use the properties given in argument. Otherwise we need to use other properties; current
-                     * implementation recycles the properties of the existing two-dimensional CRS.
-                     */
-                    final CoordinateSystemAxis[] axes = new CoordinateSystemAxis[3];
-                    axes[axisPosition++   ] = cs.getAxis(0);
-                    axes[axisPosition++   ] = cs.getAxis(1);
-                    axes[axisPosition %= 3] = vertical.getCoordinateSystem().getAxis(0);
-                    cs = csFactory.createEllipsoidalCS(getProperties(cs), axes[0], axes[1], axes[2]);
-                    crs = crsFactory.createGeographicCRS((components.length == 2) ? properties : getProperties(crs),
-                            ((GeodeticCRS) crs).getDatum(), cs);
-                    /*
-                     * Remove the VerticalCRS and store the three-dimensional GeographicCRS in place of the previous
-                     * two-dimensional GeographicCRS. Then let the loop continues in case there is other CRS to merge
-                     * (should never happen, but we are paranoiac).
-                     */
-                    components = ArraysExt.remove(components, i, 1);
-                    if (axisPosition != 0) i--;             // GeographicCRS before VerticalCRS (usual case).
-                    components[i] = crs;
-                }
-            }
-        }
-        switch (components.length) {
-            case 0:  return null;
-            case 1:  return components[0];
-            default: return crsFactory.createCompoundCRS(properties, components);
-        }
-    }
-
-    /**
-     * Returns the coordinate system if the given CRS is a two-dimensional geographic CRS, or {@code null} otherwise.
-     */
-    private static EllipsoidalCS getCsIfGeographic2D(final CoordinateReferenceSystem crs) {
-        if (crs instanceof GeodeticCRS) {
-            final CoordinateSystem cs = crs.getCoordinateSystem();
-            if (cs instanceof EllipsoidalCS && cs.getDimension() == 2) {
-                return (EllipsoidalCS) cs;
-            }
-        }
-        return null;
-    }
-
-    /**
      * Creates a format for {@link DirectPosition} instances.
      *
      * @param  locale    the locale for the new {@code Format}, or {@code null} for {@code Locale.ROOT}.
@@ -588,6 +505,8 @@ public class ReferencingServices extends
      * If the given properties are empty and the {@code mtFactory} is the system default, then this method
      * returns the system default {@code CoordinateOperationFactory} instead of creating a new one.
      *
+     * <p>It is okay to set all parameters to {@code null} in order to get the system default factory.</p>
+     *
      * @param  properties  the default properties.
      * @param  mtFactory   the math transform factory to use.
      * @param  crsFactory  the factory to use if the operation factory needs to create CRS for intermediate steps.
@@ -616,11 +535,12 @@ public class ReferencingServices extends
      * Returns the properties of the given object.
      *
      * @param  object  the object from which to get the properties.
+     * @param  keepId  {@code true} for preserving the identifiers, {@code false} for discarding them.
      * @return the properties of the given object.
      *
      * @since 0.6
      */
-    public Map<String,?> getProperties(final IdentifiedObject object) {
+    public Map<String,?> getProperties(final IdentifiedObject object, final boolean keepId) {
         return Collections.singletonMap(IdentifiedObject.NAME_KEY, object.getName());
     }
 

Modified: sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Initializer.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -22,6 +22,7 @@ import java.net.URLClassLoader;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.io.IOException;
 import java.util.concurrent.Callable;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
@@ -41,6 +42,7 @@ import javax.naming.event.EventContext;
 import javax.naming.event.NamingEvent;
 import javax.naming.event.NamingExceptionEvent;
 import javax.naming.event.ObjectChangeListener;
+import org.apache.sis.setup.InstallationResources;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.system.DataDirectory;
 import org.apache.sis.internal.system.Shutdown;
@@ -58,6 +60,15 @@ import org.apache.sis.util.logging.Loggi
  *   META-INF/services/org.apache.sis.internal.metadata.sql.Initializer
  * }
  *
+ * {@code Initializer} implementations should define the following methods:
+ *
+ * <ul>
+ *   <li>{@link #createSchema(Connection)} — invoked when a new database is created.</li>
+ *   <li>{@link #dataSourceChanged()} — invoked when the data source changed.</li>
+ * </ul>
+ *
+ * All other methods are related to getting the {@code DataSource} instance, through JNDI or otherwise.
+ *
  * @author  Martin Desruisseaux (Geomatys)
  * @version 0.8
  * @since   0.7
@@ -67,8 +78,11 @@ public abstract class Initializer {
     /**
      * Name of the database to open in the {@code $SIS_DATA/Databases} directory or the directory given by
      * the {@code derby.system.home} property.
+     *
+     * <div class="note"><b>Note:</b>
+     * this field is public for the needs of {@code non-free:sis-embedded-data} module.</div>
      */
-    private static final String DATABASE = "SpatialMetadata";
+    public static final String DATABASE = "SpatialMetadata";
 
     /**
      * The property name for the home of Derby databases.
@@ -81,6 +95,11 @@ public abstract class Initializer {
     public static final String JNDI = "jdbc/" + DATABASE;
 
     /**
+     * A pseudo-authority name used by {@link InstallationResources} for the embedded data resources.
+     */
+    public static final String EMBEDDED = "Embedded";
+
+    /**
      * The class loader for JavaDB (i.e. the Derby database distributed with the JDK), created when first needed.
      * This field is never reset to {@code null} even if the classpath changed because this class loader is for
      * a JAR file the JDK installation directory, and we presume that the JDK installation do not change.
@@ -100,6 +119,7 @@ public abstract class Initializer {
     /**
      * {@code true} if {@link #connected(DatabaseMetaData)} has been invoked at least once.
      * This is reset to {@code false} if the {@link #source} is changed.
+     * We use this information for logging purpose.
      */
     private static boolean connected;
 
@@ -239,6 +259,10 @@ public abstract class Initializer {
                     Listener.register((EventContext) env);
                 }
                 return source;
+                /*
+                 * No Derby shutdown hook for DataSource fetched fron JNDI.
+                 * We presume that shutdowns are handled by the container.
+                 */
             } catch (NameNotFoundException e) {
                 final LogRecord record = Messages.getResources(null).getLogRecord(
                         Level.CONFIG, Messages.Keys.JNDINotSpecified_1, JNDI);
@@ -248,38 +272,60 @@ public abstract class Initializer {
             /*
              * At this point we determined that there is no JNDI context or no object binded to "jdbc/SpatialMetadata".
              * As a fallback, try to open the Derby database located in $SIS_DATA/Databases/SpatialMetadata directory.
+             * Only if the SIS_DATA environment variable is not set, verify first if the 'sis-embedded-data' module is
+             * on the classpath. Note that if SIS_DATA is defined and valid, it has precedence.
              */
-            final boolean create;
-            final String home = AccessController.doPrivileged((PrivilegedAction<String>) () -> System.getProperty(DERBY_HOME_KEY));
-            final Path dir = DataDirectory.DATABASES.getDirectory();
-            if (dir != null) {
-                Path path = dir.resolve(DATABASE);
-                if (home != null) try {
-                    /*
-                     * If a "derby.system.home" property is set, we may be able to get a shorter path by making it
-                     * relative to Derby home. The intend is to have a nicer URL like "jdbc:derby:SpatialMetadata"
-                     * instead than "jdbc:derby:/a/long/path/to/SIS/Data/Databases/SpatialMetadata". In addition
-                     * to making loggings and EPSGDataAccess.getAuthority() output nicer, it also reduces the risk
-                     * of encoding issues if the path contains spaces or non-ASCII characters.
-                     */
-                    path = Paths.get(home).relativize(path);
-                } catch (IllegalArgumentException | SecurityException e) {
-                    // The path can not be relativized. This is okay.
-                    Logging.recoverableException(Logging.getLogger(Loggers.SQL), Initializer.class, "getDataSource", e);
+            boolean create = false;
+            final boolean isEnvClear = DataDirectory.isEnvClear();
+            if (!isEnvClear || (source = embedded()) == null) {
+                final String home = AccessController.doPrivileged((PrivilegedAction<String>) () -> System.getProperty(DERBY_HOME_KEY));
+                final Path dir = DataDirectory.DATABASES.getDirectory();
+                final String dbURL;
+                if (dir != null) {
+                    Path path = dir.resolve(DATABASE);
+                    if (home != null) try {
+                        /*
+                         * If a "derby.system.home" property is set, we may be able to get a shorter path by making it
+                         * relative to Derby home. The intend is to have a nicer URL like "jdbc:derby:SpatialMetadata"
+                         * instead than "jdbc:derby:/a/long/path/to/SIS/Data/Databases/SpatialMetadata". In addition
+                         * to making loggings and EPSGDataAccess.getAuthority() output nicer, it also reduces the risk
+                         * of encoding issues if the path contains spaces or non-ASCII characters.
+                         */
+                        path = Paths.get(home).relativize(path);
+                    } catch (IllegalArgumentException | SecurityException e) {
+                        // The path can not be relativized. This is okay.
+                        Logging.recoverableException(Logging.getLogger(Loggers.SQL), Initializer.class, "getDataSource", e);
+                    }
+                    path   = path.normalize();
+                    create = !Files.exists(path);
+                    dbURL  = path.toString().replace(path.getFileSystem().getSeparator(), "/");
+                } else if (home != null) {
+                    final Path path = Paths.get(home);
+                    create = !Files.exists(path.resolve(DATABASE)) && Files.isDirectory(path);
+                    dbURL  = DATABASE;
+                } else {
+                    create = true;
+                    dbURL  = null;
                 }
                 /*
-                 * Create the Derby data source using the context class loader if possible,
-                 * or otherwise a URL class loader to the JavaDB distributed with the JDK.
+                 * If we need to create the database, verify if an embedded database is available instead.
+                 * We perform this check only if we have not already checked for embedded database at the
+                 * beginning of this block.
                  */
-                path   = path.normalize();
-                create = !Files.exists(path);
-                source = forJavaDB(path.toString().replace(path.getFileSystem().getSeparator(), "/"));
-            } else if (home != null) {
-                final Path path = Paths.get(home);
-                create = !Files.exists(path.resolve(DATABASE)) && Files.isDirectory(path);
-                source = forJavaDB(DATABASE);
-            } else {
-                return null;
+                if (create & !isEnvClear) {
+                    source = embedded();
+                    create = (source == null);
+                }
+                if (source == null) {
+                    if (dbURL == null) {
+                        return null;
+                    }
+                    /*
+                     * Create the Derby data source using the context class loader if possible,
+                     * or otherwise a URL class loader to the JavaDB distributed with the JDK.
+                     */
+                    source = forJavaDB(dbURL);
+                }
             }
             /*
              * Register the shutdown hook before to attempt any operation on the database in order to close
@@ -321,6 +367,34 @@ public abstract class Initializer {
     }
 
     /**
+     * If the {@code non-free:sis-embedded-data} module is present on the classpath,
+     * returns the data source for embedded Derby database. Otherwise returns {@code null}.
+     *
+     * @see <a href="https://issues.apache.org/jira/browse/SIS-337">SIS-337</a>
+     *
+     * @since 0.8
+     */
+    private static DataSource embedded() {
+        for (InstallationResources res : DefaultFactories.createServiceLoader(InstallationResources.class)) {
+            if (res.getAuthorities().contains(EMBEDDED)) try {
+                final String[] names = res.getResourceNames(EMBEDDED);
+                for (int i=0; i<names.length; i++) {
+                    if (DATABASE.equals(names[i])) {
+                        final Object ds = res.getResource(EMBEDDED, i);
+                        if (ds instanceof DataSource) {
+                            return (DataSource) ds;
+                        }
+                    }
+                }
+            } catch (IOException e) {
+                Logging.unexpectedException(Logging.getLogger(Loggers.SQL), Initializer.class, "getDataSource", e);
+                // Continue - the system will fallback on the hard-coded subset of EPSG definitions.
+            }
+        }
+        return null;
+    }
+
+    /**
      * Prepares a log record saying that a connection to the spatial metadata database has been created.
      * This method can be invoked after {@link DataSource#getConnection()}. When invoked for the first time,
      * the record level is set to {@link Level#CONFIG}. On next calls, the level become {@link Level#FINE}.
@@ -449,10 +523,13 @@ public abstract class Initializer {
     /**
      * Returns {@code true} if the given exception is the one that we expect in successful shutdown of a Derby database.
      *
+     * <div class="note"><b>Note:</b>
+     * this method is public for the needs of {@code non-free:sis-embedded-data} module.</div>
+     *
      * @param  e  the exception thrown by Derby.
      * @return {@code true} if the exception indicates a successful shutdown.
      */
-    static boolean isSuccessfulShutdown(final SQLException e) {
+    public static boolean isSuccessfulShutdown(final SQLException e) {
         final String state = e.getSQLState();
         return "08006".equals(state) ||     // Database 'SpatialMetadata' shutdown.
                "XJ004".equals(state);       // Database 'SpatialMetadata' not found (may happen if we failed to open it in the first place).

Modified: sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Convention.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Convention.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Convention.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Convention.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -28,7 +28,7 @@ import org.apache.sis.metadata.iso.citat
  * (also known as “WKT 2”), or whether to use the format previously defined in OGC 01-009 (referenced as “WKT 1”).
  *
  * <div class="section">WKT 1 variants</div>
- * The WKT 2 format should be parsed and formatted consistently by all softwares.
+ * The WKT 2 format should be parsed and formatted consistently by all software products.
  * But the WKT 1 format has been interpreted differently by various implementors.
  * Apache SIS can adapt itself to different WKT variants, sometime automatically. But some aspects can not be guessed.
  * One noticeable source of confusion is the unit of measurement of {@code PRIMEM[…]} and {@code PARAMETER[…]} elements:
@@ -37,8 +37,8 @@ import org.apache.sis.metadata.iso.citat
  *   <li>The unit of the Prime Meridian shall be the angular unit of the enclosing Geographic CRS
  *       according the OGC 01-009 (<cite>Coordinate transformation services</cite>) specification.</li>
  *   <li>An older specification — <cite>Simple Features</cite> — was unclear on this matter and has been
- *       interpreted by many softwares as fixing the unit to decimal degrees.</li>
- *   <li>Some softwares support only (<var>longitude</var>, <var>latitude</var>) axis order
+ *       interpreted by many software products as fixing the unit to decimal degrees.</li>
+ *   <li>Some software products support only (<var>longitude</var>, <var>latitude</var>) axis order
  *       and ignore completely all {@code AXIS[…]} elements in the WKT.</li>
  * </ul>
  *
@@ -172,7 +172,7 @@ public enum Convention {
      * <p>Note that {@code AXIS[…]} elements still need to be well formed even when parsing a text with this convention.
      * Malformed axis elements will continue to cause a {@link java.text.ParseException} despite their content being ignored.</p>
      *
-     * <p>This convention may be useful for compatibility with some other softwares that do not handle axis order correctly.
+     * <p>This convention may be useful for compatibility with some other software products that do not handle axis order correctly.
      * But except when imposed by such compatibility reasons, this convention should be avoided as much as possible.</p>
      *
      * @since 0.6

Modified: sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -70,6 +70,7 @@ import org.apache.sis.internal.metadata.
 import org.apache.sis.internal.metadata.VerticalDatumTypes;
 import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.internal.metadata.TransformationAccuracy;
+import org.apache.sis.internal.metadata.EllipsoidalHeightCombiner;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.util.CharSequences;
@@ -1928,7 +1929,7 @@ class GeodeticObjectParser extends MathT
                 if (VerticalDatumType.OTHER_SURFACE.equals(datum.getVerticalDatumType())) {
                     final VerticalDatumType type = VerticalDatumTypes.guess(datum.getName().getCode(), datum.getAlias(), cs.getAxis(0));
                     if (!VerticalDatumType.OTHER_SURFACE.equals(type)) {
-                        datum = datumFactory.createVerticalDatum(referencing.getProperties(datum), type);
+                        datum = datumFactory.createVerticalDatum(referencing.getProperties(datum, true), type);
                     }
                 }
                 verticalCRS = crsFactory.createVerticalCRS(properties, datum, (VerticalCS) cs);
@@ -2179,8 +2180,9 @@ class GeodeticObjectParser extends MathT
             components.add(crs);
         }
         try {
-            return referencing.createCompoundCRS(crsFactory, csFactory, parseMetadataAndClose(element, name, null),
-                    components.toArray(new CoordinateReferenceSystem[components.size()]));
+            return new EllipsoidalHeightCombiner(crsFactory, csFactory, opFactory).createCompoundCRS(
+                            parseMetadataAndClose(element, name, null),
+                            components.toArray(new CoordinateReferenceSystem[components.size()]));
         } catch (FactoryException exception) {
             throw element.parseFailed(exception);
         }

Modified: sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Symbols.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Symbols.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Symbols.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Symbols.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -605,7 +605,7 @@ public class Symbols implements Localize
      * of confusion when processing geographic data. Some applications just ignore any declared axis order
      * in favor of their own hard-coded (<var>longitude</var>, <var>latitude</var>) axis order.
      * Consequently, the presence of {@code AXIS[…]} elements in a WKT is an indication that the encoded
-     * object may not be understood as intended by some external softwares.
+     * object may not be understood as intended by some external software products.
      *
      * @param  wkt  the WKT to inspect.
      * @return {@code true} if the given WKT contains at least one instance of the {@code AXIS[…]} element.

Modified: sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/package-info.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/package-info.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/package-info.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -39,7 +39,7 @@
  *   <li>Apply syntactic coloring on terminal supporting <cite>ANSI escape codes</cite>
  *       (a.k.a. ECMA-48, ISO/IEC 6429 and X3.64).</li>
  *   <li>Alter the parsing in a way compatible with non-standard (but commonly used) WKT.
- *       For example some others softwares ignore the {@code AXIS[…]} elements at parsing time.</li>
+ *       For example some others software products ignore the {@code AXIS[…]} elements at parsing time.</li>
  *   <li>Report warnings that occurred during parsing or formatting.</li>
  * </ul>
  *
@@ -56,9 +56,9 @@
  * The WKT 1 format has been interpreted differently by various implementors.
  * One noticeable difference is the unit of measurement of prime meridians and projection parameters.
  * The WKT 2 format aims to solve the inter-operability problem caused by such mismatches,
- * but not all softwares support this new format. Consequently importing or exporting data from/to a software with
- * the WKT syntax require knowledge of the WKT variant used by that software. This variant can be specified by the
- * {@link org.apache.sis.io.wkt.Convention} enumeration.
+ * but not all software products support this new format. Consequently importing or exporting data from/to a software
+ * with the WKT syntax require knowledge of the WKT variant used by that software. This variant can be specified by
+ * the {@link org.apache.sis.io.wkt.Convention} enumeration.
  *
  * <div class="section">Geometry WKT</div>
  * The {@link org.apache.sis.geometry.GeneralEnvelope} and {@link org.apache.sis.geometry.GeneralDirectPosition} classes

Modified: sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/DefaultIdentifier.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -23,7 +23,7 @@ import org.opengis.metadata.Identifier;
 import org.opengis.metadata.citation.Citation;
 import org.opengis.util.InternationalString;
 import org.apache.sis.metadata.TitleProperty;
-import org.apache.sis.internal.util.Citations;
+import org.apache.sis.metadata.iso.citation.Citations;
 
 
 /**

Modified: sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/ImmutableIdentifier.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -314,7 +314,7 @@ public class ImmutableIdentifier extends
          */
         value = properties.get(CODESPACE_KEY);
         if (value == null) {
-            codeSpace = org.apache.sis.internal.util.Citations.getCodeSpace(authority);
+            codeSpace = Citations.getCodeSpace(authority);
         } else if (value instanceof String) {
             codeSpace = trimWhitespaces((String) value);
         } else {

Modified: sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/Citations.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/Citations.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/Citations.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/Citations.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -251,7 +251,7 @@ public final class Citations extends Sta
      * <ul>
      *   <li><a href="http://www.opengeospatial.org/standards/ct">Coordinate Transformation Service</a></li>
      *   <li><a href="http://www.opengeospatial.org/standards/wms">Web Map Service</a></li>
-     *   <li>Definition identifier URNs in OGC namespace</li>
+     *   <li><a href="http://portal.opengeospatial.org/files/?artifact_id=24045">Definition identifier URNs in OGC namespace</a></li>
      * </ul>
      *
      * We do not commit to a particular OGC specification in order to keep the flexibility to change the
@@ -308,14 +308,14 @@ public final class Citations extends Sta
      * <a href="http://www.unidata.ucar.edu/software/netcdf-java">NetCDF</a> specification.
      * The {@linkplain IdentifierSpace#getName() name} of this identifier space is fixed to {@code "NetCDF"}.
      * This citation is used as the authority for some map projection method and parameter names
-     * as used in NetCDF files.
+     * as used in netCDF files.
      *
      * <div class="note"><b>Example</b>
-     * the Mercator projection can be defined in a NetCDF file with the following parameters:
+     * the Mercator projection can be defined in a netCDF file with the following parameters:
      *
      * <table class="sis">
-     * <caption>Example of identifiers in NetCDF name space</caption>
-     * <tr><th>Name in NetCDF namespace</th>                           <th>Name in default namespace (EPSG)</th></tr>
+     * <caption>Example of identifiers in netCDF name space</caption>
+     * <tr><th>Name in netCDF namespace</th>                           <th>Name in default namespace (EPSG)</th></tr>
      * <tr><td>{@code "NetCDF:semi_major_axis"}</td>                   <td></td></tr>
      * <tr><td>{@code "NetCDF:semi_minor_axis"}</td>                   <td></td></tr>
      * <tr><td>{@code "NetCDF:latitude_of_projection_origin"}</td>     <td>Latitude of natural origin</td></tr>
@@ -689,7 +689,29 @@ public final class Citations extends Sta
      *
      * @since 0.6
      */
+    @SuppressWarnings("deprecation")
     public static String getUnicodeIdentifier(final Citation citation) {
         return org.apache.sis.internal.util.Citations.getUnicodeIdentifier(citation);
     }
+
+    /**
+     * Infers a code space from the given citation, or returns {@code null} if none.
+     * This method is very close to {@link #getUnicodeIdentifier(Citation)}, except that it looks for
+     * {@link IdentifierSpace#getName()} before to scan the identifiers and titles. The result should
+     * be the same in most cases, except some cases like the {@link org.apache.sis.metadata.iso.citation.Citations}
+     * constant for {@code "Proj.4"} in which case this method returns {@code "Proj4"} instead of {@code null}.
+     *
+     * @param  citation  the citation for which to infer the code space, or {@code null}.
+     * @return a non-empty code space for the given citation without leading or trailing whitespaces,
+     *         or {@code null} if the given citation is null or does not have any Unicode identifier or title.
+     *
+     * @since 0.8
+     */
+    public static String getCodeSpace(final Citation citation) {
+        if (citation instanceof IdentifierSpace<?>) {
+            return ((IdentifierSpace<?>) citation).getName();
+        } else {
+            return getUnicodeIdentifier(citation);
+        }
+    }
 }

Modified: sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultResponsibleParty.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultResponsibleParty.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultResponsibleParty.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultResponsibleParty.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -127,7 +127,7 @@ public class DefaultResponsibleParty ext
 
     /**
      * Returns the name or the position of the first individual. If no individual is found in the list of parties,
-     * then this method will search in the list of organization members. The later structure is used by our NetCDF
+     * then this method will search in the list of organization members. The later structure is used by our netCDF
      * reader.
      *
      * @param  position {@code true} for returning the position name instead than individual name.

Modified: sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultBoundingPolygon.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultBoundingPolygon.java?rev=1813747&r1=1813746&r2=1813747&view=diff
==============================================================================
--- sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultBoundingPolygon.java [UTF-8] (original)
+++ sis/branches/JDK9/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/extent/DefaultBoundingPolygon.java [UTF-8] Mon Oct 30 10:25:08 2017
@@ -47,7 +47,7 @@ import org.opengis.metadata.extent.Bound
  * @author  Touraïvane (IRD)
  * @author  Cédric Briançon (Geomatys)
  * @author  Guilhem Legal (Geomatys)
- * @version 0.3
+ * @version 0.8
  * @since   0.3
  * @module
  */
@@ -77,6 +77,7 @@ public class DefaultBoundingPolygon exte
      * @param polygon  the sets of points defining the bounding polygon.
      */
     public DefaultBoundingPolygon(final Geometry polygon) {
+        super(true);
         polygons = singleton(polygon, Geometry.class);
     }
 



Mime
View raw message