sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1727091 - in /sis/branches/JDK8/core: sis-referencing/src/main/java/org/apache/sis/referencing/ sis-referencing/src/main/java/org/apache/sis/referencing/factory/ sis-referencing/src/test/java/org/apache/sis/referencing/ sis-referencing/src...
Date Wed, 27 Jan 2016 15:38:20 GMT
Author: desruisseaux
Date: Wed Jan 27 15:38:20 2016
New Revision: 1727091

URL: http://svn.apache.org/viewvc?rev=1727091&view=rev
Log:
Add tests.

Added:
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactoryTest.java
  (with props)
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.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/FilteredCodes.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/AuthorityFactoryMock.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/CommonAuthorityFactoryTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java
    sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/internal/util/DefinitionURITest.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java?rev=1727091&r1=1727090&r2=1727091&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
[UTF-8] Wed Jan 27 15:38:20 2016
@@ -556,7 +556,7 @@ check:  while (lower != 0 || upper != di
      * Otherwise, this method returns the {@link org.apache.sis.referencing.factory.MultiAuthoritiesFactory}
      * instance that manages all other factories.
      *
-     * <p>The {@code authority} argument can be {@code "EPSG"}, {@code "WMS"} or any
other authority found
+     * <p>The {@code authority} argument can be {@code "EPSG"}, {@code "OGC"} or any
other authority found
      * on the classpath. In the {@code "EPSG"} case, whether the full set of EPSG codes is
supported or not
      * depends on whether a {@linkplain org.apache.sis.referencing.factory.sql connection
to the database}
      * can be established. If no connection can be established, then this method returns
a small embedded
@@ -570,7 +570,7 @@ check:  while (lower != 0 || upper != di
      *     META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory
      * }
      *
-     * @param  authority The authority of the desired factory (typically {@code "EPSG"} or
{@code "WMS"}),
+     * @param  authority The authority of the desired factory (typically {@code "EPSG"} or
{@code "OGC"}),
      *         or {@code null} for the {@link org.apache.sis.referencing.factory.MultiAuthoritiesFactory}
      *         instance that manage all factories.
      * @return The system-wide authority factory used by SIS for the given authority.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java?rev=1727091&r1=1727090&r2=1727091&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/IdentifiedObjects.java
[UTF-8] Wed Jan 27 15:38:20 2016
@@ -496,7 +496,7 @@ public final class IdentifiedObjects ext
      *     Set<IdentifiedObject> found = finder.find(object);
      * }</div>
      *
-     * @param  authority The authority of the objects to search (typically {@code "EPSG"}
or {@code "WMS"}),
+     * @param  authority The authority of the objects to search (typically {@code "EPSG"}
or {@code "OGC"}),
      *         or {@code null} for searching among the objects created by all authorities.
      * @return A finder to use for looking up unidentified objects.
      * @throws FactoryException if the finder can not be created.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java?rev=1727091&r1=1727090&r2=1727091&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java
[UTF-8] Wed Jan 27 15:38:20 2016
@@ -47,6 +47,7 @@ import org.opengis.referencing.datum.Eng
 import org.apache.sis.internal.referencing.GeodeticObjectBuilder;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.internal.system.DefaultFactories;
+import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.measure.Units;
 import org.apache.sis.referencing.CommonCRS;
@@ -55,6 +56,7 @@ import org.apache.sis.referencing.cs.Coo
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.iso.DefaultNameSpace;
 import org.apache.sis.util.iso.SimpleInternationalString;
@@ -283,6 +285,19 @@ public class CommonAuthorityFactory exte
     }
 
     /**
+     * Rewrites the given code in a canonical format.
+     * If the code can not be reformatted, then this method returns {@code null}.
+     */
+    static String reformat(final String code) {
+        try {
+            return format(Integer.parseInt(code.substring(skipNamespace(code) & ~LEGACY_MASK)));
+        } catch (NoSuchAuthorityCodeException | NumberFormatException e) {
+            Logging.recoverableException(Logging.getLogger(Loggers.CRS_FACTORY), CommonAuthorityFactory.class,
"reformat", e);
+            return null;
+        }
+    }
+
+    /**
      * Returns the index where the code begins, ignoring spaces and the {@code "OGC"}, {@code
"CRS"}, {@code "AUTO"},
      * {@code "AUTO1"} or {@code "AUTO2"} namespaces if present. If a namespace is found
and is a legacy one, then
      * this {@link #LEGACY_MASK} bit will be set.
@@ -351,8 +366,7 @@ public class CommonAuthorityFactory exte
     @Override
     public Set<String> getAuthorityCodes(final Class<? extends IdentifiedObject>
type) throws FactoryException {
         ArgumentChecks.ensureNonNull("type", type);
-        final boolean all = type.isAssignableFrom(SingleCRS.class);
-        if (!all && !SingleCRS.class.isAssignableFrom(type)) {
+        if (!type.isAssignableFrom(SingleCRS.class) && !SingleCRS.class.isAssignableFrom(type))
{
             return Collections.emptySet();
         }
         synchronized (codes) {
@@ -367,15 +381,22 @@ public class CommonAuthorityFactory exte
                 }
             }
         }
-        return all ? Collections.unmodifiableSet(codes.keySet()) : new FilteredCodes(codes,
type).keySet();
+        return new FilteredCodes(codes, type).keySet();
+    }
+
+    /**
+     * Formats the given code with a {@code "CRS:"} or {@code "AUTO2:"} prefix.
+     */
+    private static String format(final int code) {
+        return ((code >= FIRST_PROJECTION_CODE) ? AUTO2 : Constants.CRS) + DefaultNameSpace.DEFAULT_SEPARATOR
+ code;
     }
 
     /**
      * Adds an element in the {@link #codes} map, witch check against duplicated values.
      */
     private void add(final int code, final Class<? extends SingleCRS> type) throws
FactoryException {
-        final String namespace = (code >= FIRST_PROJECTION_CODE) ? AUTO2 : Constants.CRS;
-        if (codes.put(namespace + DefaultNameSpace.DEFAULT_SEPARATOR + code, type) != null)
{
+        assert (code >= FIRST_PROJECTION_CODE) == (ProjectedCRS.class.isAssignableFrom(type))
: code;
+        if (codes.put(format(code), type) != null) {
             throw new FactoryException();    // Should never happen, but we are paranoiac.
         }
     }

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=1727091&r1=1727090&r2=1727091&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] Wed Jan 27 15:38:20 2016
@@ -215,13 +215,15 @@ public abstract class ConcurrentAuthorit
     /**
      * {@code true} if the call to {@link #closeExpired()} is scheduled for future execution
in the background
      * cleaner thread. A value of {@code true} implies that this factory contains at least
one active data access.
-     * However the reciprocal is not true: this field may be set to {@code false} while a
worker factory is currently
-     * in use because this field is set to {@code true} only when a worker factory is {@linkplain
#release() released}.
+     * However the reciprocal is not true: this field may be set to {@code false} while a
DAO is currently in use
+     * because this field is set to {@code true} only when a worker factory is {@linkplain
#release released}.
      *
      * <p>Note that we can not use {@code !availableDAOs.isEmpty()} as a replacement
of {@code isCleanScheduled}
      * because the queue is empty if all Data Access Objects are currently in use.</p>
      *
      * <p>Every access to this field must be performed in a block synchronized on {@link
#availableDAOs}.</p>
+     *
+     * @see #isCleanScheduled()
      */
     private boolean isCleanScheduled;
 
@@ -307,6 +309,8 @@ public abstract class ConcurrentAuthorit
     /**
      * Returns the number of Data Access Objects available for reuse. This count does not
include the
      * Data Access Objects that are currently in use. This method is used only for testing
purpose.
+     *
+     * @see #isCleanScheduled()
      */
     @Debug
     final int countAvailableDataAccess() {
@@ -471,6 +475,23 @@ public abstract class ConcurrentAuthorit
         }
     }
 
+    /**
+     * {@code true} if the call to {@link #closeExpired()} is scheduled for future execution
in the background
+     * cleaner thread. A value of {@code true} implies that this factory contains at least
one active data access.
+     * However the reciprocal is not true: this field may be set to {@code false} while a
DAO is currently in use
+     * because this field is set to {@code true} only when a worker factory is {@linkplain
#release released}.
+     *
+     * <p>This method is used only for testing purpose.</p>
+     *
+     * @see #countAvailableDataAccess()
+     */
+    @Debug
+    final boolean isCleanScheduled() {
+        synchronized (availableDAOs) {
+            return isCleanScheduled;
+        }
+    }
+
     /**
      * Confirms that the given factories can be closed. If any factory is still in use,
      * it will be removed from that {@cod factories} list and re-injected in the {@link #availableDAOs}
queue.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/FilteredCodes.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/FilteredCodes.java?rev=1727091&r1=1727090&r2=1727091&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/FilteredCodes.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/FilteredCodes.java
[UTF-8] Wed Jan 27 15:38:20 2016
@@ -88,10 +88,17 @@ final class FilteredCodes extends Abstra
     }
 
     /**
-     * Ignored, except that it must be non-null.
+     * Returns a non-null value if the given code is included in the set.
      */
     @Override
     public Boolean get(final Object key) {
-        return Boolean.TRUE;
+        Class<?> t = codes.get(key);
+        if (t == null && key instanceof String) {
+            t = codes.get(CommonAuthorityFactory.reformat((String) key));
+            if (t == null) {
+                return null;
+            }
+        }
+        return type.isAssignableFrom(t) ? Boolean.TRUE : null;
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java?rev=1727091&r1=1727090&r2=1727091&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/MultiAuthoritiesFactory.java
[UTF-8] Wed Jan 27 15:38:20 2016
@@ -759,7 +759,7 @@ public class MultiAuthoritiesFactory ext
             int end = CharSequences.skipTrailingWhitespaces(code, 0, afterAuthority);
             int start = CharSequences.skipLeadingWhitespaces(code, 0, end);
             if (start >= end) {
-                throw new NoSuchAuthorityFactoryException(Errors.format(Errors.Keys.MissingAuthority_1,
code), null);
+                throw new NoSuchAuthorityCodeException(Errors.format(Errors.Keys.MissingAuthority_1,
code), null, code);
             }
             authority = code.substring(start, end);
             /*

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java?rev=1727091&r1=1727090&r2=1727091&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/AuthorityFactoriesTest.java
[UTF-8] Wed Jan 27 15:38:20 2016
@@ -16,13 +16,25 @@
  */
 package org.apache.sis.referencing;
 
+import java.util.Collection;
+import org.opengis.util.FactoryException;
+import org.opengis.referencing.NoSuchAuthorityCodeException;
+import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.crs.CRSAuthorityFactory;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.GeographicCRS;
-import org.opengis.util.FactoryException;
+import org.apache.sis.util.ComparisonMode;
+import org.apache.sis.util.logging.Logging;
 import org.apache.sis.internal.system.Loggers;
+import org.apache.sis.internal.util.Constants;
+import org.apache.sis.referencing.crs.HardCodedCRS;
+import org.apache.sis.referencing.factory.IdentifiedObjectFinder;
+import org.apache.sis.referencing.factory.NoSuchAuthorityFactoryException;
+
+// Test imports
+import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.LoggingWatcher;
 import org.apache.sis.test.TestCase;
-import org.apache.sis.util.logging.Logging;
 import org.junit.Rule;
 import org.junit.Test;
 
@@ -116,4 +128,113 @@ public final strictfp class AuthorityFac
         assertEquals(0, listener.maximumLogCount);
         assertSame(crs, factory.createGeographicCRS("urn:ogc:def:crs:EPSG::4326"));
     }
+
+    /**
+     * Tests the {@code createCoordinateReferenceSystem(…)} method with various code.
+     *
+     * @throws FactoryException if a CRS creation failed.
+     */
+    @Test
+    @DependsOnMethod("testCRS84")
+    public void testCreateCRS() throws FactoryException {
+        final CRSAuthorityFactory factory = AuthorityFactories.ALL;
+        final CRSAuthorityFactory wms = AuthorityFactories.ALL.getAuthorityFactory(CRSAuthorityFactory.class,
Constants.OGC, null);
+        CoordinateReferenceSystem actual, expected;
+
+        actual   = factory.createCoordinateReferenceSystem("CRS:84");
+        expected = wms.createCoordinateReferenceSystem("84");
+        assertSame(expected, actual);
+        assertSame(expected, factory.createObject("CRS:84"));
+
+        actual   = factory .createCoordinateReferenceSystem("AUTO:42001,0,0");
+        expected = wms.createCoordinateReferenceSystem("42001,0,0");
+        assertSame(expected, actual);
+        assertSame(expected, factory.createObject("AUTO:42001,0,0"));
+
+        actual   = factory.createCoordinateReferenceSystem("CRS:27");
+        expected = wms.createCoordinateReferenceSystem("27");
+        assertSame(expected, actual);
+        assertSame(expected, factory.createObject("CRS:27"));
+
+        try {
+            factory.createCoordinateReferenceSystem("84");
+            fail("Should not work without authority.");
+        } catch (NoSuchAuthorityCodeException exception) {
+            // This is the expected exception.
+            assertEquals("84", exception.getAuthorityCode());
+        }
+
+        try {
+            factory.createCoordinateReferenceSystem("FOO:84");
+            fail("Should not work with unknown authority.");
+        } catch (NoSuchAuthorityFactoryException exception) {
+            // This is the expected exception.
+            assertEquals("FOO", exception.getAuthority());
+        }
+    }
+
+    /**
+     * Tests creation of CRS from codes in the {@code "http://www.opengis.net/gml/srs/"}
name space.
+     *
+     * @throws FactoryException if a CRS creation failed.
+     */
+    @Test
+    public void testHttp() throws FactoryException {
+        final CRSAuthorityFactory factory = AuthorityFactories.ALL;
+        final CRSAuthorityFactory wms = AuthorityFactories.ALL.getAuthorityFactory(CRSAuthorityFactory.class,
Constants.OGC, null);
+        CoordinateReferenceSystem actual, expected;
+
+        actual   = factory.createCoordinateReferenceSystem("http://www.opengis.net/gml/srs/CRS#84");
+        expected = wms.createCoordinateReferenceSystem("84");
+        assertSame(expected, actual);
+
+        actual = factory.createCoordinateReferenceSystem("HTTP://WWW.OPENGIS.NET/GML/SRS/crs#84");
+        assertSame(expected, actual);
+
+        actual = factory.createCoordinateReferenceSystem("http://www.opengis.net/gml/srs/CRS.xml#84");
+        assertSame(expected, actual);
+
+        try {
+            factory.createCoordinateReferenceSystem("http://www.dummy.net/gml/srs/CRS#84");
+            fail("Should not accept http://www.dummy.net");
+        } catch (NoSuchAuthorityCodeException e) {
+            assertNotNull(e.getMessage());
+        }
+
+        try {
+            factory.createCoordinateReferenceSystem("http://www.opengis.net/gml/dummy/CRS#84");
+            fail("Should not accept “dummy” as an authority");
+        } catch (NoSuchAuthorityCodeException e) {
+            assertNotNull(e.getMessage());
+        }
+    }
+
+    /**
+     * Tests the {@code getAuthorityCodes(…)} method.
+     *
+     * @throws FactoryException if an error occurred while fetching the codes.
+     */
+    @Test
+    public void testGetAuthorityCodes() throws FactoryException {
+        final CRSAuthorityFactory factory = AuthorityFactories.ALL;
+        final Collection<String> codes = factory.getAuthorityCodes(CoordinateReferenceSystem.class);
+        assertFalse(codes.isEmpty());
+        assertTrue(codes.contains("CRS:84"));
+        assertTrue(codes.contains("AUTO:42001") || codes.contains("AUTO2:42001"));
+    }
+
+    /**
+     * Tests the {@code IdentifiedObjectFinder.find(…)} method.
+     *
+     * @throws FactoryException if the operation failed creation failed.
+     */
+    @Test
+    public void testFind() throws FactoryException {
+        final CRSAuthorityFactory factory = AuthorityFactories.ALL;
+        final IdentifiedObjectFinder finder = AuthorityFactories.ALL.newIdentifiedObjectFinder();
+        final IdentifiedObject find = finder.findSingleton(HardCodedCRS.WGS84);
+        assertNotNull("With scan allowed, should find the CRS.", find);
+        assertTrue(HardCodedCRS.WGS84.equals(find, ComparisonMode.DEBUG));
+        assertSame(factory.createCoordinateReferenceSystem("CRS:84"), find);
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/AuthorityFactoryMock.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/AuthorityFactoryMock.java?rev=1727091&r1=1727090&r2=1727091&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/AuthorityFactoryMock.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/AuthorityFactoryMock.java
[UTF-8] Wed Jan 27 15:38:20 2016
@@ -52,8 +52,8 @@ import static org.junit.Assert.*;
  * @version 0.7
  * @module
  */
-public final strictfp class AuthorityFactoryMock extends GeodeticAuthorityFactory
-        implements CRSAuthorityFactory, CSAuthorityFactory, DatumAuthorityFactory, CoordinateOperationAuthorityFactory
+public final strictfp class AuthorityFactoryMock extends GeodeticAuthorityFactory implements
CRSAuthorityFactory,
+        CSAuthorityFactory, DatumAuthorityFactory, CoordinateOperationAuthorityFactory, AutoCloseable
 {
     /**
      * The authority.
@@ -61,6 +61,12 @@ public final strictfp class AuthorityFac
     private final Citation authority;
 
     /**
+     * {@code true} if this factory has been closed by
+     * an explicit call to the {@link #close()} method.
+     */
+    private boolean closed;
+
+    /**
      * Creates a new factory for the given authority.
      *
      * @param authority The title of the authority to declare.
@@ -100,6 +106,7 @@ public final strictfp class AuthorityFac
      */
     @Override
     public Set<String> getAuthorityCodes(Class<? extends IdentifiedObject> type)
{
+        assertFalse("This factory has been closed.", isClosed());
         final Set<String> codes = new LinkedHashSet<>();
         if (type.isAssignableFrom(GeocentricCRS.class)) add(codes, 4979);
         if (type.isAssignableFrom(GeographicCRS.class)) add(codes, 84, 4326);
@@ -117,6 +124,7 @@ public final strictfp class AuthorityFac
      */
     @Override
     public IdentifiedObject createObject(final String code) throws NoSuchAuthorityCodeException
{
+        assertFalse("This factory has been closed.", isClosed());
         final int n;
         try {
             n = Integer.parseInt(trimNamespace(code));
@@ -151,6 +159,7 @@ public final strictfp class AuthorityFac
      */
     @Override
     public Unit<?> createUnit(final String code) throws NoSuchAuthorityCodeException
{
+        assertFalse("This factory has been closed.", isClosed());
         final int n;
         try {
             n = Integer.parseInt(trimNamespace(code));
@@ -172,6 +181,7 @@ public final strictfp class AuthorityFac
      */
     @Override
     public Extent createExtent(final String code) throws NoSuchAuthorityCodeException {
+        assertFalse("This factory has been closed.", isClosed());
         final int n;
         try {
             n = Integer.parseInt(trimNamespace(code));
@@ -183,4 +193,20 @@ public final strictfp class AuthorityFac
             default: throw new NoSuchAuthorityCodeException(code, authority.getTitle().toString(),
code);
         }
     }
+
+    /**
+     * Returns {@code true} if this factory has been closed
+     * by an explicit call to the {@link #close()} method.
+     */
+    final synchronized boolean isClosed() {
+        return closed;
+    }
+
+    /**
+     * Flags this factory as closed.
+     */
+    @Override
+    public synchronized void close() {
+        closed = true;
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/CommonAuthorityFactoryTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/CommonAuthorityFactoryTest.java?rev=1727091&r1=1727090&r2=1727091&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/CommonAuthorityFactoryTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/CommonAuthorityFactoryTest.java
[UTF-8] Wed Jan 27 15:38:20 2016
@@ -17,6 +17,7 @@
 package org.apache.sis.referencing.factory;
 
 import java.util.Arrays;
+import java.util.Set;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.NoninvertibleTransformException;
 import javax.measure.unit.SI;
@@ -91,6 +92,16 @@ public final strictfp class CommonAuthor
                 factory.getAuthorityCodes(VerticalCRS.class));
         assertSetEquals(Arrays.asList("CRS:1"),
                 factory.getAuthorityCodes(EngineeringCRS.class));
+
+        final Set<String> codes = factory.getAuthorityCodes(GeographicCRS.class);
+        assertFalse("CRS:1",      codes.contains("CRS:1"));
+        assertTrue ("CRS:27",     codes.contains("CRS:27"));
+        assertTrue ("CRS:83",     codes.contains("CRS:83"));
+        assertTrue ("CRS:84",     codes.contains("CRS:84"));
+        assertFalse("CRS:88",     codes.contains("CRS:88"));
+        assertTrue ("0084",       codes.contains("0084"));
+        assertFalse("0088",       codes.contains("0088"));
+        assertTrue ("OGC:CRS084", codes.contains("OGC:CRS084"));
     }
 
     /**

Added: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactoryTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactoryTest.java?rev=1727091&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactoryTest.java
(added)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactoryTest.java
[UTF-8] Wed Jan 27 15:38:20 2016
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.referencing.factory;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.TimeUnit;
+import org.opengis.util.FactoryException;
+import org.apache.sis.util.logging.Logging;
+import org.apache.sis.test.DependsOn;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+import static org.junit.Assume.assumeTrue;
+
+
+/**
+ * Tests {@link ConcurrentAuthorityFactory}.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.7
+ * @version 0.7
+ * @module
+ */
+@DependsOn(AuthorityFactoryProxyTest.class)
+public final strictfp class ConcurrentAuthorityFactoryTest extends TestCase {
+    /**
+     * The timeout used for this test.
+     */
+    private static final long TIMEOUT = ConcurrentAuthorityFactory.TIMEOUT_RESOLUTION * 4;
+
+    /**
+     * A concurrent factory which creates new instances of {@link AuthorityFactoryMock}.
+     */
+    private static final strictfp class Mock extends ConcurrentAuthorityFactory<AuthorityFactoryMock>
{
+        /** All factories created by this mock, including any factories having been disposed.
*/
+        private final Queue<AuthorityFactoryMock> allDAOs = new ConcurrentLinkedQueue<>();
+
+        /** Creates a new concurrent authority factory. */
+        Mock() {
+            super(AuthorityFactoryMock.class);
+            setTimeout(TIMEOUT, TimeUnit.NANOSECONDS);
+        }
+
+        /** Invoked when a new factory needs to be created. */
+        @Override protected AuthorityFactoryMock newDataAccess() {
+            assertFalse("Should be invoked outside synchronized block.", Thread.holdsLock(this));
+            final AuthorityFactoryMock factory = new AuthorityFactoryMock("Mock", null);
+            assertTrue(allDAOs.add(factory));
+            return factory;
+        }
+
+        /** Returns a copy of the factories queue. */
+        final synchronized List<AuthorityFactoryMock> createdDAOs() {
+            return new ArrayList<>(allDAOs);
+        }
+    }
+
+
+    /**
+     * Tests the disposal of Data Access Objects (DAO) after the timeout.
+     *
+     * @throws FactoryException should never happen.
+     * @throws InterruptedException if the test has been interrupted.
+     */
+    @Test
+    public void testTimeout() throws FactoryException, InterruptedException {
+        final Mock factory = new Mock();
+        /*
+         * Ask for one element, wait for the timeout and check that the DAO is disposed.
+         */
+        long workTime = System.nanoTime();
+        assertTrue  ("Should have initially no DAO.", factory.createdDAOs().isEmpty());
+        assertEquals("Should have initially no DAO.", 0, factory.countAvailableDataAccess());
+        assertNotNull(factory.createObject("84"));
+
+        List<AuthorityFactoryMock> createdDAOs = factory.createdDAOs();
+        assertEquals("Expected a new DAO.",         1, createdDAOs.size());
+        assertEquals("Expected one valid DAO.",     1, factory.countAvailableDataAccess());
+        assertFalse ("Should not be disposed yet.", createdDAOs.get(0).isClosed());
+
+        sleepWithoutExceedingTimeout(workTime, 2 * ConcurrentAuthorityFactory.TIMEOUT_RESOLUTION);
+        assertEquals("Expected no new DAO.",        createdDAOs, factory.createdDAOs());
+        assertEquals("Expected one valid DAO.",     1, factory.countAvailableDataAccess());
+        assertFalse ("Should not be disposed yet.", createdDAOs.get(0).isClosed());
+
+        sleepUntilAfterTimeout(3 * ConcurrentAuthorityFactory.TIMEOUT_RESOLUTION, factory);
+        assertEquals("Expected no new DAO.",       createdDAOs, factory.createdDAOs());
+        assertEquals("Worker should be disposed.", 0, factory.countAvailableDataAccess());
+        assertTrue  ("Worker should be disposed.", createdDAOs.get(0).isClosed());
+        /*
+         * Ask again for the same object and check that no new DAO
+         * were created because the value was taken from the cache.
+         */
+        assertNotNull(factory.createObject("84"));
+        assertEquals("Expected no new DAO.",      createdDAOs, factory.createdDAOs());
+        assertEquals("Worker should be disposed.", 0, factory.countAvailableDataAccess());
+        /*
+         * Ask for one element and check that a new DAO is created.
+         */
+        workTime = System.nanoTime();
+        assertNotNull(factory.createObject("4326"));
+        createdDAOs = factory.createdDAOs();
+        assertEquals("Expected a new DAO.",         2, createdDAOs.size());
+        assertEquals("Expected one valid DAO.",     1, factory.countAvailableDataAccess());
+        assertFalse ("Should not be disposed yet.", createdDAOs.get(1).isClosed());
+
+        sleepWithoutExceedingTimeout(workTime, 2 * ConcurrentAuthorityFactory.TIMEOUT_RESOLUTION);
+        assertEquals("Expected no new DAO.",        createdDAOs, factory.createdDAOs());
+        assertEquals("Expected one valid DAO.",     1, factory.countAvailableDataAccess());
+        assertFalse ("Should not be disposed yet.", createdDAOs.get(1).isClosed());
+        /*
+         * Ask again for a new element before the timeout is elapsed and check
+         * that the disposal of the Data Access Objects has been reported.
+         */
+        workTime = System.nanoTime();
+        assertNotNull(factory.createObject("4979"));
+        sleepWithoutExceedingTimeout(workTime, ConcurrentAuthorityFactory.TIMEOUT_RESOLUTION);
+        assertNotNull(factory.createObject("5714"));
+        sleepWithoutExceedingTimeout(workTime, 2 * ConcurrentAuthorityFactory.TIMEOUT_RESOLUTION);
+        assertEquals("Expected one valid DAO.",     1, factory.countAvailableDataAccess());
+        assertFalse ("Should not be disposed yet.", createdDAOs.get(1).isClosed());
+        assertEquals("Expected no new DAO.",        createdDAOs, factory.createdDAOs());
+
+        sleepUntilAfterTimeout(3 * ConcurrentAuthorityFactory.TIMEOUT_RESOLUTION, factory);
+        assertEquals("Expected no new DAO.",        createdDAOs, factory.createdDAOs());
+        assertEquals("Worker should be disposed.",  0, factory.countAvailableDataAccess());
+        assertTrue  ("Worker should be disposed.",  createdDAOs.get(1).isClosed());     
       // TODO: sometime not yet disposed.
+        assertTrue  ("Worker should be disposed.",  createdDAOs.get(0).isClosed());
+    }
+
+    /**
+     * Sleeps and ensures that the sleep time did not exceeded the timeout. The sleep time
could be greater if the test
+     * machine is under heavy load (for example a Jenkins server), in which case we will
cancel the test without failure.
+     */
+    private static void sleepWithoutExceedingTimeout(final long previousTime, final long
waitTime) throws InterruptedException {
+        Thread.sleep(TimeUnit.NANOSECONDS.toMillis(waitTime));
+        assumeTrue(System.nanoTime() - previousTime < TIMEOUT);
+    }
+
+    /**
+     * Sleeps a time long enough so that we exceed the timeout time. After this method call,
the
+     * DAOs should be disposed. However if they are not, then we will wait a little bit more.
+     *
+     * <p>The workers should be disposed right after the sleep time. However the workers
disposal is performed
+     * by a shared (SIS-library wide) daemon thread. Because the later is invoked in a background
thread,
+     * it is subject to the hazard of thread scheduling.</p>
+     */
+    private static void sleepUntilAfterTimeout(final long waitTime, final ConcurrentAuthorityFactory<?>
factory)
+            throws InterruptedException
+    {
+        Thread.sleep(TimeUnit.NANOSECONDS.toMillis(waitTime));
+        int n = 3;
+        while (factory.isCleanScheduled()) {
+            Logging.getLogger("org.geotoolkit.referencing.factory")
+                    .warning("Execution of ConcurrentAuthorityFactory.disposeExpired() has
been delayed.");
+            Thread.sleep(TIMEOUT);
+            System.gc();
+            if (--n == 0) {
+                break;
+            }
+        }
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactoryTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/ConcurrentAuthorityFactoryTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1727091&r1=1727090&r2=1727091&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
[UTF-8] Wed Jan 27 15:38:20 2016
@@ -197,6 +197,7 @@ import org.junit.BeforeClass;
     org.apache.sis.referencing.CommonCRSTest.class,
     org.apache.sis.referencing.factory.CommonAuthorityFactoryTest.class,
     org.apache.sis.referencing.factory.AuthorityFactoryProxyTest.class,
+    org.apache.sis.referencing.factory.ConcurrentAuthorityFactoryTest.class,
     org.apache.sis.referencing.factory.IdentifiedObjectFinderTest.class,
     org.apache.sis.referencing.factory.MultiAuthoritiesFactoryTest.class,
     org.apache.sis.referencing.factory.sql.EPSGFactoryTest.class,

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java?rev=1727091&r1=1727090&r2=1727091&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/internal/util/DefinitionURI.java
[UTF-8] Wed Jan 27 15:38:20 2016
@@ -460,6 +460,7 @@ public final class DefinitionURI {
      * @param url       The URL to parse.
      * @param result    If non-null, store the type, authority and code in that object.
      */
+    @SuppressWarnings("fallthrough")
     private static String codeForGML(final String type, String authority, final String url,
int lower,
             final DefinitionURI result)
     {
@@ -484,17 +485,24 @@ public final class DefinitionURI {
                 }
                 lower += authority.length();
                 int upper = url.length();
-                if (lower < upper && url.charAt(lower) == '.') {
-                    // Ignore the extension (typically ".xml", but we accept anything).
-                    if ((lower = url.indexOf('#', lower+1)) >= 0) {
-                        final String code = trimWhitespaces(url, lower+1, upper).toString();
-                        if (result != null) {
-                            result.isGML     = true;
-                            result.type      = entry.getKey();
-                            result.authority = authority;
-                            result.code      = code;
+                if (lower < upper) {
+                    switch (url.charAt(lower)) {
+                        case '.': {
+                            // Ignore the extension (typically ".xml", but we accept anything).
+                            lower = url.indexOf('#', lower + 1);
+                            if (lower < 0) continue;
+                            // Fall through
+                        }
+                        case '#': {
+                            final String code = trimWhitespaces(url, lower+1, upper).toString();
+                            if (result != null) {
+                                result.isGML     = true;
+                                result.type      = entry.getKey();
+                                result.authority = authority;
+                                result.code      = code;
+                            }
+                            return code;
                         }
-                        return code;
                     }
                 }
             }

Modified: sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/internal/util/DefinitionURITest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/internal/util/DefinitionURITest.java?rev=1727091&r1=1727090&r2=1727091&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/internal/util/DefinitionURITest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/test/java/org/apache/sis/internal/util/DefinitionURITest.java
[UTF-8] Wed Jan 27 15:38:20 2016
@@ -134,6 +134,13 @@ public final strictfp class DefinitionUR
         assertEquals ("code",      "4326", parsed.code);
         assertNull   ("parameters",        parsed.parameters);
         assertEquals ("toString()", "http://www.opengis.net/gml/srs/epsg.xml#4326", parsed.toString());
+
+        final DefinitionURI withoutExtension = DefinitionURI.parse("http://www.opengis.net/gml/srs/epsg#4326");
+        assertNotNull("Should parse even if the .xml extension is missig.", withoutExtension);
+        assertEquals(parsed.toString(), withoutExtension.toString());
+
+        assertNull("Should not parse if no '#' character.",
+                DefinitionURI.parse("http://www.opengis.net/gml/srs/epsg?4326"));
     }
 
     /**




Mime
View raw message