sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1720181 - in /sis/branches/JDK8/core: sis-referencing/src/main/java/org/apache/sis/internal/referencing/ sis-referencing/src/main/java/org/apache/sis/referencing/ sis-referencing/src/main/java/org/apache/sis/referencing/factory/ sis-refere...
Date Tue, 15 Dec 2015 15:30:11 GMT
Author: desruisseaux
Date: Tue Dec 15 15:30:10 2015
New Revision: 1720181

URL: http://svn.apache.org/viewvc?rev=1720181&view=rev
Log:
Moved DeprecatedName and DeprecatedCode in internal package so we can reuse them in EPSGFactory.
Opportunistic trivial reformatting of "//" comments (inserting more space between code and
comment).

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DeprecatedCode.java
      - copied, changed from r1720180, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/DeprecatedCode.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DeprecatedName.java
      - copied, changed from r1720180, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/DeprecatedName.java
Removed:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/DeprecatedCode.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/DeprecatedName.java
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultNameSpace.java

Copied: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DeprecatedCode.java
(from r1720180, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/DeprecatedCode.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DeprecatedCode.java?p2=sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DeprecatedCode.java&p1=sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/DeprecatedCode.java&r1=1720180&r2=1720181&rev=1720181&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/DeprecatedCode.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DeprecatedCode.java
[UTF-8] Tue Dec 15 15:30:10 2015
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.referencing;
+package org.apache.sis.internal.referencing;
 
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.citation.Citation;
@@ -27,17 +27,17 @@ import org.apache.sis.util.Deprecable;
  * This is used mostly for deprecated EPSG codes.
  *
  * <div class="note"><b>Implementation note:</b>
- * this class opportunistically recycle the {@linkplain #getDescription() description} property
into a
+ * this class opportunistically recycles the {@linkplain #getDescription() description} property
into a
  * {@linkplain #getRemarks() remarks} property. This is a lazy way to inherit {@link #equals(Object)}
- * and {@link #hashCode()} implementation without adding code in this class for taking in
account a
+ * and {@link #hashCode()} implementations without adding code in this class for taking in
account a
  * new field.</div>
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.6
- * @version 0.6
+ * @version 0.7
  * @module
  */
-final class DeprecatedCode extends ImmutableIdentifier implements Deprecable {
+public final class DeprecatedCode extends ImmutableIdentifier implements Deprecable {
     /**
      * For cross-version compatibility.
      */
@@ -45,8 +45,14 @@ final class DeprecatedCode extends Immut
 
     /**
      * Creates a deprecated identifier.
+     *
+     * @param authority  Organization or party responsible for definition and maintenance
of the code space or code.
+     * @param codeSpace  Name or identifier of the person or organization responsible for
namespace.
+     * @param code       Identifier code or name, optionally from a controlled list or pattern
defined by a code space.
+     * @param version    The version of the associated code space or code as specified by
the code authority, or {@code null} if none.
+     * @param remarks    Comments on or information about why this identifier is deprecated,
or {@code null} if none.
      */
-    DeprecatedCode(final Citation authority, final String codeSpace,
+    public DeprecatedCode(final Citation authority, final String codeSpace,
             final String code, final String version, final InternationalString remarks)
     {
         super(authority, codeSpace, code, version, remarks);

Copied: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DeprecatedName.java
(from r1720180, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/DeprecatedName.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DeprecatedName.java?p2=sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DeprecatedName.java&p1=sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/DeprecatedName.java&r1=1720180&r2=1720181&rev=1720181&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/DeprecatedName.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/DeprecatedName.java
[UTF-8] Tue Dec 15 15:30:10 2015
@@ -14,8 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.referencing;
+package org.apache.sis.internal.referencing;
 
+import org.apache.sis.referencing.NamedIdentifier;
 import org.opengis.util.InternationalString;
 import org.opengis.metadata.citation.Citation;
 import org.apache.sis.util.Deprecable;
@@ -25,34 +26,36 @@ import org.apache.sis.util.Deprecable;
  * A deprecated name.
  * This is used mostly for names which were used in legacy versions of the EPSG database.
  *
+ * <div class="note"><b>Implementation note:</b>
+ * this class opportunistically recycles the {@linkplain #getDescription() description} property
into a
+ * {@linkplain #getRemarks() remarks} property. This is a lazy way to inherit {@link #equals(Object)}
+ * and {@link #hashCode()} implementations without adding code in this class for taking in
account a
+ * new field.</div>
+ *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.6
- * @version 0.6
+ * @version 0.7
  * @module
  */
-final class DeprecatedName extends NamedIdentifier implements Deprecable {
+public final class DeprecatedName extends NamedIdentifier implements Deprecable {
     /**
      * For cross-version compatibility.
      */
     private static final long serialVersionUID = 1792369861343798471L;
 
     /**
-     * Information about the replacement for this name.
-     *
-     * @see #getRemarks()
-     */
-    private final InternationalString remarks;
-
-    /**
      * Creates a new deprecated EPSG name.
      *
-     * @param supersededBy The name that replace this one.
+     * @param authority  Organization or party responsible for definition and maintenance
of the name.
+     * @param codeSpace  Name or identifier of the person or organization responsible for
namespace.
+     * @param code       Name, optionally from a controlled list or pattern defined by a
namespace.
+     * @param version    The version of the associated namespace or name as specified by
the code authority, or {@code null} if none.
+     * @param remarks    Comments on or information about why this name is deprecated, or
{@code null} if none.
      */
-    DeprecatedName(final Citation authority, final String codeSpace, final CharSequence code,
final String version,
-            final InternationalString remarks)
+    public DeprecatedName(final Citation authority, final String codeSpace,
+            final CharSequence code, final String version, final InternationalString remarks)
     {
-        super(authority, codeSpace, code, version, null);
-        this.remarks = remarks;
+        super(authority, codeSpace, code, version, remarks);
     }
 
     /**
@@ -74,6 +77,17 @@ final class DeprecatedName extends Named
      */
     @Override
     public InternationalString getRemarks() {
-        return remarks;
+        return super.getDescription();
+    }
+
+    /**
+     * Returns {@code null}, since we used the description for the superseded information.
+     * See <cite>"Implementation note"</cite> in class javadoc.
+     *
+     * @return {@code null}.
+     */
+    @Override
+    public InternationalString getDescription() {
+        return null;
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java?rev=1720181&r1=1720180&r2=1720181&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/Builder.java
[UTF-8] Tue Dec 15 15:30:10 2015
@@ -33,6 +33,8 @@ import org.opengis.referencing.Identifie
 import org.apache.sis.metadata.iso.ImmutableIdentifier;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.util.Citations;
+import org.apache.sis.internal.referencing.DeprecatedCode;
+import org.apache.sis.internal.referencing.DeprecatedName;
 import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.Deprecable;
 import org.apache.sis.util.resources.Errors;

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java?rev=1720181&r1=1720180&r2=1720181&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/NamedIdentifier.java
[UTF-8] Tue Dec 15 15:30:10 2015
@@ -88,7 +88,7 @@ import java.util.Objects;
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.6
+ * @version 0.7
  * @module
  */
 public class NamedIdentifier extends ImmutableIdentifier implements GenericName {
@@ -142,7 +142,59 @@ public class NamedIdentifier extends Imm
 
     /**
      * Constructs an identifier from the given properties. The content of the properties
map is used as
-     * described in the {@linkplain ImmutableIdentifier#ImmutableIdentifier(Map) super-class
constructor}.
+     * described in the {@linkplain ImmutableIdentifier#ImmutableIdentifier(Map) super-class
constructor},
+     * with the addition of an optional {@code "name"} property.
+     *
+     * <table class="sis">
+     *   <caption>Recognized properties</caption>
+     *   <tr>
+     *     <th>Property name</th>
+     *     <th>Value type</th>
+     *     <th>Returned by</th>
+     *   </tr>
+     *   <tr>
+     *     <td>{@code "name"}</td>
+     *     <td>{@link GenericName}</td>
+     *     <td>(none)</td>
+     *   </tr>
+     *   <tr>
+     *     <th colspan="3" class="hsep">Defined in parent class (reminder)</th>
+     *   </tr>
+     *   <tr>
+     *     <td>{@value org.opengis.metadata.Identifier#CODE_KEY}</td>
+     *     <td>{@link String}</td>
+     *     <td>{@link #getCode()}</td>
+     *   </tr>
+     *   <tr>
+     *     <td>{@value org.opengis.metadata.Identifier#CODESPACE_KEY}</td>
+     *     <td>{@link String}</td>
+     *     <td>{@link #getCodeSpace()}</td>
+     *   </tr>
+     *   <tr>
+     *     <td>{@value org.opengis.metadata.Identifier#AUTHORITY_KEY}</td>
+     *     <td>{@link String} or {@link Citation}</td>
+     *     <td>{@link #getAuthority()}</td>
+     *   </tr>
+     *   <tr>
+     *     <td>{@value org.opengis.metadata.Identifier#VERSION_KEY}</td>
+     *     <td>{@link String}</td>
+     *     <td>{@link #getVersion()}</td>
+     *   </tr>
+     *   <tr>
+     *     <td>{@value org.opengis.metadata.Identifier#DESCRIPTION_KEY}</td>
+     *     <td>{@link String} or {@link InternationalString}</td>
+     *     <td>{@link #getDescription()}</td>
+     *   </tr>
+     *   <tr>
+     *     <td>{@value org.apache.sis.referencing.AbstractIdentifiedObject#LOCALE_KEY}</td>
+     *     <td>{@link Locale}</td>
+     *     <td>(none)</td>
+     *   </tr>
+     * </table>
+     *
+     * The {@value org.opengis.metadata.Identifier#CODE_KEY} property is mandatory and all
other properties
+     * are optional. If a {@code "name"} property is provided, then calls to name-related
methods like
+     * {@link #tip()}, {@link #head()} and {@link #scope()} will delegate to the given name.
      *
      * @param  properties The properties to be given to this identifier.
      * @throws InvalidParameterValueException if a property has an invalid value.
@@ -150,6 +202,8 @@ public class NamedIdentifier extends Imm
      */
     public NamedIdentifier(final Map<String,?> properties) throws IllegalArgumentException
{
         super(properties);
+        name = (GenericName) properties.get("name");
+        isNameSupplied = (name != null);
     }
 
     /**
@@ -171,7 +225,7 @@ public class NamedIdentifier extends Imm
         super(authority, Citations.getCodeSpace(authority), toString(code));
         if (code instanceof InternationalString) {
             name = createName(authority, super.getCodeSpace(), code);
-            isNameSupplied = true; // Because 'code' is an international string.
+            isNameSupplied = true;      // Because 'code' is an international string.
         }
     }
 
@@ -204,7 +258,7 @@ public class NamedIdentifier extends Imm
         super(authority, codeSpace, toString(code), version, description);
         if (code instanceof InternationalString) {
             name = createName(authority, codeSpace, code);
-            isNameSupplied = true; // Because 'code' is an international string.
+            isNameSupplied = true;      // Because 'code' is an international string.
         }
     }
 
@@ -232,7 +286,7 @@ public class NamedIdentifier extends Imm
     /**
      * Returns the generic name of this identifier.
      * The name will be constructed automatically the first time it will be needed.
-     * The name's scope is inferred from the shortest alternative title (if any).
+     * The name's head is inferred from the shortest alternative title (if any).
      * This heuristic rule is compatible to the ISO 19115 remark saying that the
      * {@linkplain Citation#getAlternateTitles() alternate titles} often contains abbreviation
      * (for example "DCW" as an alternative title for "Digital Chart of the World").
@@ -260,7 +314,7 @@ public class NamedIdentifier extends Imm
      */
     private static GenericName createName(final Citation authority, String codeSpace, final
CharSequence code) {
         if (codeSpace == null) {
-            codeSpace = Citations.getCodeSpace(authority);   // Whitespaces trimed by Citations.
+            codeSpace = Citations.getCodeSpace(authority);          // Whitespaces trimed
by Citations.
         }
         final NameFactory factory = DefaultFactories.forBuildin(NameFactory.class);
         if (codeSpace != null) {
@@ -410,7 +464,7 @@ public class NamedIdentifier extends Imm
         }
         if (super.equals(object)) {
             if (!isNameSupplied) {
-                return true; // No need to compare names if they are computed from the same
values.
+                return true;            // No need to compare names if they are computed
from the same values.
             }
             final NamedIdentifier that = (NamedIdentifier) object;
             return Objects.equals(this.getName(), that.getName());

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java?rev=1720181&r1=1720180&r2=1720181&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
[UTF-8] Tue Dec 15 15:30:10 2015
@@ -221,7 +221,7 @@ public abstract class ConcurrentAuthorit
      * by strong references. Note that those default values may change in any future SIS
versions based
      * on experience gained.
      *
-     * @param nameFactory The factory to use for parsing authority code as {@link org.opengis.util.GenericName}
instances.
+     * @param nameFactory The factory to use for parsing authority codes as {@link org.opengis.util.GenericName}
instances.
      */
     protected ConcurrentAuthorityFactory(final NameFactory nameFactory) {
         this(nameFactory, 100, 8);

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java?rev=1720181&r1=1720180&r2=1720181&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/GeodeticAuthorityFactory.java
[UTF-8] Tue Dec 15 15:30:10 2015
@@ -74,7 +74,7 @@ public abstract class GeodeticAuthorityF
     /**
      * Creates a new authority factory for geodetic objects.
      *
-     * @param nameFactory The factory to use for parsing authority code as {@link GenericName}
instances.
+     * @param nameFactory The factory to use for parsing authority codes as {@link GenericName}
instances.
      */
     protected GeodeticAuthorityFactory(final NameFactory nameFactory) {
         ArgumentChecks.ensureNonNull("nameFactory", nameFactory);

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java?rev=1720181&r1=1720180&r2=1720181&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGFactory.java
[UTF-8] Tue Dec 15 15:30:10 2015
@@ -18,10 +18,11 @@ package org.apache.sis.referencing.facto
 
 import java.util.Set;
 import java.util.Map;
+import java.util.List;
 import java.util.HashSet;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
-import java.util.IdentityHashMap;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Calendar;
 import java.util.Date;
@@ -45,6 +46,7 @@ import javax.measure.converter.Conversio
 
 import org.opengis.util.NameSpace;
 import org.opengis.util.NameFactory;
+import org.opengis.util.GenericName;
 import org.opengis.util.InternationalString;
 import org.opengis.util.FactoryException;
 import org.opengis.util.NoSuchIdentifierException;
@@ -58,11 +60,13 @@ import org.opengis.metadata.citation.Cit
 import org.opengis.metadata.citation.OnLineFunction;
 import org.opengis.metadata.quality.PositionalAccuracy;
 import org.opengis.referencing.NoSuchAuthorityCodeException;
+import org.apache.sis.internal.referencing.DeprecatedCode;
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.internal.util.Constants;
-import org.apache.sis.metadata.iso.DefaultIdentifier;
+import org.apache.sis.metadata.iso.ImmutableIdentifier;
 import org.apache.sis.metadata.iso.citation.DefaultCitation;
 import org.apache.sis.metadata.iso.citation.DefaultOnlineResource;
+import org.apache.sis.referencing.NamedIdentifier;
 import org.apache.sis.referencing.datum.BursaWolfParameters;
 import org.apache.sis.referencing.factory.FactoryDataException;
 import org.apache.sis.referencing.factory.GeodeticAuthorityFactory;
@@ -122,6 +126,15 @@ import org.apache.sis.measure.Units;
 public abstract class EPSGFactory extends GeodeticAuthorityFactory implements CRSAuthorityFactory,
         CSAuthorityFactory, DatumAuthorityFactory, CoordinateOperationAuthorityFactory, Disposable
 {
+    /**
+     * The prefix in table names. The SQL scripts are provided by EPSG with this prefix in
front of all table names.
+     * SIS rather uses a modified version of those SQL scripts which creates the tables in
an "EPSG" database schema.
+     * But we still need to check for existence of this prefix in case someone used the original
SQL scripts.
+     */
+    private static final String TABLE_PREFIX = "epsg_";
+
+
+
     //////////////////////////////////////////////////////////////////////////////////////////////
     //////                                                                              
  ///////
     //////   HARD CODED VALUES (other than SQL statements) RELATIVE TO THE EPSG DATABASE
  ///////
@@ -278,6 +291,13 @@ public abstract class EPSGFactory extend
     private Citation authority;
 
     /**
+     * The namespace of EPSG names and codes. This namespace is needed by all {@code createFoo(String)}
methods.
+     * The {@code EPSGFactory} constructor relies on the {@link #nameFactory} caching mechanism
for giving us
+     * the same {@code NameSpace} instance than the one used by previous {@code EPSGFactory}
instances, if any.
+     */
+    private final NameSpace namespace;
+
+    /**
      * Last object type returned by {@link #createObject(String)}, or -1 if none.
      * This type is an index in the {@link #TABLES_INFO} array and is strictly for {@link
#createObject} internal use.
      */
@@ -307,17 +327,13 @@ public abstract class EPSGFactory extend
     /**
      * A pool of prepared statements. Keys are {@link String} objects related to their originating
method
      * (for example "Ellipsoid" for {@link #createEllipsoid(String)}).
-     *
-     * <div class="note"><b>Note:</b>
-     * it is okay to use {@link IdentityHashMap} instead of {@link HashMap} because the keys
will always be
-     * the exact same object, namely the hard-coded argument given to calls to {@link #prepareStatement}
in
-     * this class.</div>
      */
-    private final Map<String,PreparedStatement> statements = new IdentityHashMap<>();
+    private final Map<String,PreparedStatement> statements = new HashMap<>();
 
     /**
      * The set of authority codes for different types. This map is used by the {@link #getAuthorityCodes(Class)}
-     * method as a cache for returning the set created in a previous call.
+     * method as a cache for returning the set created in a previous call. We do not want
this map to exist for
+     * a long time anyway.
      *
      * <p>Note that this {@code EPSGFactory} instance can not be disposed as long as
this map is not empty, since
      * {@link AuthorityCodes} caches some SQL statements and consequently require the {@linkplain
#connection} to
@@ -368,7 +384,7 @@ public abstract class EPSGFactory extend
      *
      * @see #createProperties(String, String, String, String, boolean)
      */
-    private final Map<Integer,NameSpace> scopes = new HashMap<>();
+    private final Map<String,NameSpace> scopes = new HashMap<>();
 
     /**
      * The properties to be given the objects to construct.
@@ -399,12 +415,14 @@ public abstract class EPSGFactory extend
      * Creates a factory using the given connection. The connection will be {@linkplain Connection#close()
closed}
      * when this factory will be {@linkplain #dispose() disposed}.
      *
-     * @param connection The connection to the underlying EPSG database.
+     * @param connection   The connection to the underlying EPSG database.
+     * @param nameFactory  The factory to use for creating authority codes as {@link GenericName}
instances.
      */
     public EPSGFactory(final Connection connection, final NameFactory nameFactory) {
         super(nameFactory);
-        this.connection = connection;
         ArgumentChecks.ensureNonNull("connection", connection);
+        this.connection = connection;
+        this.namespace  = nameFactory.createNameSpace(nameFactory.createLocalName(null, Constants.EPSG),
null);
     }
 
     /**
@@ -428,7 +446,7 @@ public abstract class EPSGFactory extend
     public synchronized Citation getAuthority() {
         if (authority == null) {
             final DefaultCitation c = new DefaultCitation("EPSG Geodetic Parameter Dataset");
-            c.setIdentifiers(Collections.singleton(new DefaultIdentifier(Constants.EPSG)));
+            c.setIdentifiers(Collections.singleton(new ImmutableIdentifier(null, null, Constants.EPSG)));
             try {
                 /*
                  * Get the most recent version number from the history table. We get the
date in local timezone
@@ -776,6 +794,184 @@ addURIs:        for (int i=0; ; i++) {
         return stmt.executeQuery();
     }
 
+    /**
+     * Converts a code from an arbitrary name to the numerical identifier (the primary key).
+     * If the supplied code is already a numerical value, then it is returned unchanged.
+     * If the code is not found in the name column, it is returned unchanged as well
+     * so that the caller will produce an appropriate "Code not found" error message.
+     * If the code is found more than once, then an exception is thrown.
+     *
+     * <p>Note that this method includes a call to {@link #trimAuthority(String)},
+     * so there is no need to call it before or after this method.</p>
+     *
+     * @param  type        The type of object to create.
+     * @param  code        The code to check.
+     * @param  table       The table where the code should appears.
+     * @param  codeColumn  The column name for the code.
+     * @param  nameColumn  The column name for the name.
+     * @return The numerical identifier (i.e. the table primary key value).
+     * @throws SQLException if an error occurred while reading the database.
+     */
+    private String toPrimaryKey(final Class<?> type, final String code, final String
table,
+            final String codeColumn, final String nameColumn) throws SQLException, FactoryException
+    {
+        assert Thread.holdsLock(this);
+        String identifier = trimAuthority(code);
+        if (!isPrimaryKey(identifier)) {
+            /*
+             * The given string is not a numerical code. Search the value in the database.
+             * If a prepared statement is already available, reuse it providing that it was
+             * created for the current table. Otherwise we will create a new statement.
+             */
+            final String KEY = "NumericalIdentifier";
+            PreparedStatement statement = statements.get(KEY);
+            if (statement != null) {
+                if (!table.equals(lastTableForName)) {
+                    statements.remove(KEY);
+                    statement.close();
+                    statement        = null;
+                    lastTableForName = null;
+                }
+            }
+            if (statement == null) {
+                final String query = "SELECT " + codeColumn + " FROM " + table +
+                                     " WHERE " + nameColumn + " = ?";
+                statement = connection.prepareStatement(adaptSQL(query));
+                statements.put(KEY, statement);
+            }
+            // Do not use executeQuery(statement, primaryKey) because "identifier" is a name
here.
+            statement.setString(1, identifier);
+            identifier = null;
+            try (ResultSet result = statement.executeQuery()) {
+                while (result.next()) {
+                    identifier = ensureSingleton(result.getString(1), identifier, code);
+                }
+            }
+            if (identifier == null) {
+                throw noSuchAuthorityCode(type, code);
+            }
+        }
+        return identifier;
+    }
+
+    /**
+     * Makes sure that an object constructed from the database is not incoherent.
+     * If the code supplied to a {@code createFoo(String)} method exists in the database,
+     * then we should find only one record. However we will do a paranoiac check and verify
if there is
+     * more records, using a {@code while (results.next())} loop instead of {@code if (results.next())}.
+     * This method is invoked in the loop for making sure that, if there is more than one
record
+     * (which should never happen), at least they have identical content.
+     *
+     * @param  newValue  The newly constructed object.
+     * @param  oldValue  The object previously constructed, or {@code null} if none.
+     * @param  code The EPSG code (for formatting error message).
+     * @throws FactoryDataException if a duplication has been detected.
+     */
+    private static <T> T ensureSingleton(final T newValue, final T oldValue, final
String code) throws FactoryDataException {
+        if (oldValue == null) {
+            return newValue;
+        }
+        if (oldValue.equals(newValue)) {
+            return oldValue;
+        }
+        throw new FactoryDataException(Errors.format(Errors.Keys.DuplicatedIdentifier_1,
code));
+    }
+
+    /**
+     * Returns the name and aliases for the {@link IdentifiedObject} to construct.
+     *
+     * @param  table       The table on which a query has been executed.
+     * @param  name        The name for the {@link IndentifiedObject} to construct.
+     * @param  code        The EPSG code of the object to construct.
+     * @param  remarks     Remarks, or {@code null} if none.
+     * @param  deprecated  {@code true} if the object to create is deprecated.
+     * @return The name together with a set of properties.
+     */
+    @SuppressWarnings("ReturnOfCollectionOrArrayField")
+    private Map<String,Object> createProperties(final String table, final String name,
String code,
+            String remarks, final boolean deprecated) throws SQLException, FactoryException
+    {
+        properties.clear();
+        GenericName gn = null;
+        final Citation authority = getAuthority();
+        final InternationalString edition = authority.getEdition();
+        final String version = (edition != null) ? edition.toString() : null;
+        if (name != null) {
+            properties.put("name", gn = nameFactory.createLocalName(namespace, name.trim()));
+            properties.put(NamedIdentifier.AUTHORITY_KEY, authority);
+            properties.put(NamedIdentifier.CODE_KEY,      name.trim());
+            properties.put(NamedIdentifier.VERSION_KEY,   version);
+            final NamedIdentifier id = new NamedIdentifier(properties);
+            properties.clear();
+            properties.put(IdentifiedObject.NAME_KEY, id);
+        }
+        if (code != null) {
+            code = code.trim();
+            final ImmutableIdentifier identifier;
+            if (deprecated) {
+                identifier = new DeprecatedCode(authority, Constants.EPSG, code, version,
null);
+            } else {
+                identifier = new ImmutableIdentifier(authority, Constants.EPSG, code, version,
+                                    (gn != null) ? gn.toInternationalString() : null);
+            }
+            properties.put(IdentifiedObject.IDENTIFIERS_KEY, identifier);
+        }
+        if (remarks != null && !(remarks = remarks.trim()).isEmpty()) {
+            properties.put(IdentifiedObject.REMARKS_KEY, remarks);
+        }
+        /*
+         * Search for aliases.
+         */
+        List<GenericName> alias = null;
+        final PreparedStatement stmt;
+        stmt = prepareStatement(
+                "[Alias]", "SELECT NAMING_SYSTEM_NAME, ALIAS, OBJECT_TABLE_NAME" +
+                " FROM [Alias] INNER JOIN [Naming System]" +
+                  " ON [Alias].NAMING_SYSTEM_CODE =" +
+                " [Naming System].NAMING_SYSTEM_CODE" +
+                " WHERE OBJECT_CODE = ?");
+        try (ResultSet result = executeQuery(stmt, code)) {
+            while (result.next()) {
+                String owner = result.getString(3);
+                if (owner != null) {
+                    /*
+                     * We have found an alias for a object having the ID we are looking for,
but we need to check if
+                     * it is really from the same table since a few different tables have
objects with the same ID.
+                     */
+                    if (owner.startsWith(TABLE_PREFIX)) {
+                        owner = owner.substring(TABLE_PREFIX.length());
+                    }
+                    if (!CharSequences.isAcronymForWords(owner, table)) {
+                        continue;
+                    }
+                }
+                final String scope = result.getString(1);
+                final String local = getString(result, 2, code);
+                final GenericName generic;
+                if (scope == null) {
+                    generic = nameFactory.createLocalName(null, local);
+                } else {
+                    NameSpace cached = scopes.get(scope);
+                    if (cached == null) {
+                        cached = nameFactory.createNameSpace(
+                                 nameFactory.createLocalName(null, scope),
+                                 Collections.singletonMap("separator", ":"));
+                        scopes.put(scope, cached);
+                    }
+                    generic = nameFactory.createLocalName(cached, local);
+                }
+                if (alias == null) {
+                    alias = new ArrayList<>();
+                }
+                alias.add(generic);
+            }
+        }
+        if (alias != null) {
+            properties.put(IdentifiedObject.ALIAS_KEY, alias.toArray(new GenericName[alias.size()]));
+        }
+        return properties;
+    }
+
     final boolean isProjection(final int code) throws NoSuchIdentifierException, SQLException
{
         return false;
     }
@@ -801,6 +997,40 @@ addURIs:        for (int i=0; ; i++) {
     }
 
     /**
+     * Returns {@code true} if the specified code may be a primary key in some table.
+     * This method does not need to check any entry in the database.
+     * It should just check from the syntax if the code looks like a valid EPSG identifier.
+     *
+     * <p>When this method returns {@code false}, {@code createFoo(String)} methods
+     * may look for the code in the name column instead than the primary key column.
+     * This allows to accept the <cite>"WGS 84 / World Mercator"</cite> string
(for example)
+     * in addition to the {@code "3395"} primary key. Both string values should fetch the
same object.</p>
+     *
+     * <p>If this method returns {@code true}, then this factory does not search for
matching names.
+     * In such case, an appropriate exception will be thrown in {@code createFoo(String)}
methods
+     * if the code is not found in the primary key column.</p>
+     *
+     * <div class="section">Default implementation</div>
+     * The default implementation returns {@code true} if all non-space characters
+     * are {@linkplain Character#isDigit(int) digits}.
+     *
+     * @param  code  The code the inspect.
+     * @return {@code true} if the code is probably a primary key.
+     * @throws FactoryException if an unexpected error occurred while inspecting the code.
+     */
+    protected boolean isPrimaryKey(final String code) throws FactoryException {
+        final int length = code.length();
+        for (int i=0; i<length;) {
+            final int c = code.codePointAt(i);
+            if (!Character.isDigit(c) && !Character.isSpaceChar(c)) {
+                return false;
+            }
+            i += Character.charCount(c);
+        }
+        return true;
+    }
+
+    /**
      * Logs a warning about an unexpected but non-fatal exception.
      *
      * @param method    The source method.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultNameSpace.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultNameSpace.java?rev=1720181&r1=1720180&r2=1720181&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultNameSpace.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultNameSpace.java
[UTF-8] Tue Dec 15 15:30:10 2015
@@ -209,9 +209,7 @@ public class DefaultNameSpace implements
      *          parsed names} of any name in that namespace.
      * @return A namespace having the given name, or {@code null} if name was null.
      */
-    static DefaultNameSpace forName(final GenericName name,
-            final String headSeparator, final String separator)
-    {
+    static DefaultNameSpace forName(final GenericName name, final String headSeparator, final
String separator) {
         if (name == null) {
             return null;
         }
@@ -251,7 +249,7 @@ public class DefaultNameSpace implements
      */
     @Override
     public boolean isGlobal() {
-        return false; // To be overridden by GlobalNameSpace.
+        return false;               // To be overridden by GlobalNameSpace.
     }
 
     /**
@@ -388,7 +386,7 @@ public class DefaultNameSpace implements
         if (name == null) {
             name = key;
         }
-        final WeakValueHashMap<String,Object> childs = this.childs; // Paranoiac protection
against accidental changes.
+        final WeakValueHashMap<String,Object> childs = this.childs;     // Paranoiac
protection against accidental changes.
         DefaultNameSpace child;
         synchronized (childs) {
             final Object existing = childs.get(key);
@@ -396,7 +394,7 @@ public class DefaultNameSpace implements
                 child = (DefaultNameSpace) existing;
                 if (!child.separator    .equals(separator) ||
                     !child.headSeparator.equals(headSeparator) ||
-                    !child.name         .equals(name)) // Same test than equalsIgnoreParent.
+                    !child.name         .equals(name))                  // Same test than
equalsIgnoreParent.
                 {
                     child = new DefaultNameSpace(this, name, headSeparator, separator);
                     /*
@@ -408,7 +406,7 @@ public class DefaultNameSpace implements
             } else {
                 child = new DefaultNameSpace(this, name, headSeparator, separator);
                 if (childs.put(key, child) != existing) {
-                    throw new AssertionError(); // Paranoiac check.
+                    throw new AssertionError();                         // Paranoiac check.
                 }
             }
         }
@@ -429,7 +427,7 @@ public class DefaultNameSpace implements
     final DefaultLocalName local(final CharSequence name, final DefaultLocalName candidate)
{
         ensureNonNull("name", name);
         final String key = name.toString();
-        final WeakValueHashMap<String,Object> childs = this.childs; // Paranoiac protection
against accidental changes.
+        final WeakValueHashMap<String,Object> childs = this.childs;     // Paranoiac
protection against accidental changes.
         DefaultLocalName child;
         synchronized (childs) {
             final Object existing = childs.get(key);
@@ -448,7 +446,7 @@ public class DefaultNameSpace implements
             // Cache only if the slot is not already occupied by a NameSpace.
             if (!(existing instanceof DefaultNameSpace)) {
                 if (childs.put(key, child) != existing) {
-                    throw new AssertionError(); // Paranoiac check.
+                    throw new AssertionError();                         // Paranoiac check.
                 }
             }
         }
@@ -510,7 +508,7 @@ public class DefaultNameSpace implements
     private boolean equalsIgnoreParent(final DefaultNameSpace that) {
         return Objects.equals(this.headSeparator, that.headSeparator) &&
                Objects.equals(this.separator,     that.separator) &&
-               Objects.equals(this.name,          that.name); // Most expensive test last.
+               Objects.equals(this.name,          that.name);               // Most expensive
test last.
     }
 
     /**
@@ -546,7 +544,7 @@ public class DefaultNameSpace implements
             } else {
                 init();
                 if (pool.put(key, this) != existing) {
-                    throw new AssertionError(); // Paranoiac check.
+                    throw new AssertionError();             // Paranoiac check.
                 }
                 return this;
             }




Mime
View raw message