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;
}
|