sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1731924 - in /sis/branches/JDK8: application/sis-console/src/main/java/org/apache/sis/console/ storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/ storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/ st...
Date Tue, 23 Feb 2016 18:40:34 GMT
Author: desruisseaux
Date: Tue Feb 23 18:40:33 2016
New Revision: 1731924

URL: http://svn.apache.org/viewvc?rev=1731924&view=rev
Log:
Add capability to parse WKT from the command-line.

Added:
    sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/
    sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java
      - copied, changed from r1731653, sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/XMLStore.java
    sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java
      - copied, changed from r1731653, sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/XMLStoreProvider.java
    sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/package-info.java
      - copied, changed from r1731653, sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/package-info.java
    sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/wkt/
    sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/wkt/StoreProviderTest.java
      - copied, changed from r1731653, sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreProviderTest.java
    sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/wkt/StoreTest.java
      - copied, changed from r1731653, sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreTest.java
Modified:
    sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/Command.java
    sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataSC.java
    sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/SubCommand.java
    sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/XMLStore.java
    sis/branches/JDK8/storage/sis-storage/src/main/resources/META-INF/services/org.apache.sis.storage.DataStoreProvider
    sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java

Modified: sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/Command.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/Command.java?rev=1731924&r1=1731923&r2=1731924&view=diff
==============================================================================
--- sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/Command.java
[UTF-8] (original)
+++ sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/Command.java
[UTF-8] Tue Feb 23 18:40:33 2016
@@ -38,6 +38,7 @@ import org.apache.sis.util.logging.Monol
  * <tr><td>{@code about}    </td><td>Show information about Apache
SIS and system configuration.</td></tr>
  * <tr><td>{@code mime-type}</td><td>Show MIME type for the given
file.</td></tr>
  * <tr><td>{@code metadata} </td><td>Show metadata information for
the given file.</td></tr>
+ * <tr><td>{@code crs}      </td><td>Show Coordinate Reference System
information for the given file or code.</td></tr>
  * </table></blockquote>
  *
  * Each command can accepts an arbitrary amount of the following options:
@@ -60,11 +61,11 @@ import org.apache.sis.util.logging.Monol
  *
  * <div class="section">SIS installation on remote machines</div>
  * Some sub-commands can operate on SIS installation on remote machines, provided that remote
access has been enabled
- * at the Java Virtual Machine startup time. See {@link org.apache.sis.console} package javadoc
for more information.
+ * at the Java Virtual Machine startup time. See {@linkplain org.apache.sis.console package
javadoc} for more information.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.6
+ * @version 0.7
  * @module
  */
 public final class Command {

Modified: sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataSC.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataSC.java?rev=1731924&r1=1731923&r2=1731924&view=diff
==============================================================================
--- sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataSC.java
[UTF-8] (original)
+++ sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/MetadataSC.java
[UTF-8] Tue Feb 23 18:40:33 2016
@@ -46,7 +46,7 @@ import org.apache.sis.xml.XML;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.4
+ * @version 0.7
  * @module
  */
 final class MetadataSC extends SubCommand {
@@ -83,6 +83,7 @@ final class MetadataSC extends SubComman
      * @throws IOException Should never happen, since we are appending to a print writer.
      */
     @Override
+    @SuppressWarnings("UseOfSystemOutOrSystemErr")
     public int run() throws InvalidOptionException, DataStoreException, JAXBException, IOException
{
         /*
          * Output format can be either "text" (the default) or "xml".
@@ -112,24 +113,31 @@ final class MetadataSC extends SubComman
         }
         /*
          * Read metadata from the data storage.
-         * If we are executing the "crs" sub-command, extract the first CRS.
          */
-        if (hasUnexpectedFileCount(1, 1)) {
-            return Command.INVALID_ARGUMENT_EXIT_CODE;
-        }
-        final Metadata metadata;
-        try (DataStore store = DataStores.open(files.get(0))) {
-            metadata = store.getMetadata();
+        Object metadata;
+        if (useStandardInput()) {
+            try (DataStore store = DataStores.open(System.in)) {
+                metadata = store.getMetadata();
+            }
+        } else {
+            if (hasUnexpectedFileCount(1, 1)) {
+                return Command.INVALID_ARGUMENT_EXIT_CODE;
+            }
+            try (DataStore store = DataStores.open(files.get(0))) {
+                metadata = store.getMetadata();
+            }
         }
         if (metadata == null) {
             return 0;
         }
-        Object object = metadata;
-        if (isCRS) {
+        /*
+         * If we are executing the "crs" sub-command, extract the first CRS.
+         */
+        if (isCRS && (metadata instanceof Metadata)) {
             boolean found = false;
-            for (final ReferenceSystem rs : metadata.getReferenceSystemInfo()) {
+            for (final ReferenceSystem rs : ((Metadata) metadata).getReferenceSystemInfo())
{
                 if (rs instanceof CoordinateReferenceSystem) {
-                    object = (CoordinateReferenceSystem) rs;
+                    metadata = rs;
                     found = true;
                     break;
                 }
@@ -158,7 +166,7 @@ final class MetadataSC extends SubComman
                 if (colors) {
                     f.setColors(Colors.DEFAULT);
                 }
-                f.format(object, out);
+                f.format(metadata, out);
                 out.println();
                 break;
             }
@@ -169,11 +177,11 @@ final class MetadataSC extends SubComman
                 marshaller.setProperty(XML.LOCALE,   locale);
                 marshaller.setProperty(XML.TIMEZONE, timezone);
                 if (isConsole()) {
-                    marshaller.marshal(object, out);
+                    marshaller.marshal(metadata, out);
                 } else {
                     out.flush();
                     marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding.name());
-                    marshaller.marshal(object, System.out); // Use OutputStream instead than
Writer.
+                    marshaller.marshal(metadata, System.out);   // Intentionally use OutputStream
instead than Writer.
                     System.out.flush();
                 }
                 break;
@@ -190,7 +198,7 @@ final class MetadataSC extends SubComman
      * {@code Writer} and let the marshaller apply the encoding itself.
      */
     private boolean isConsole() {
-        if (outputBuffer != null) return true; // Special case for JUnit tests only.
+        if (outputBuffer != null) return true;                      // Special case for JUnit
tests only.
         final Console console = System.console();
         return (console != null) && console.writer() == out;
     }

Modified: sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/SubCommand.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/SubCommand.java?rev=1731924&r1=1731923&r2=1731924&view=diff
==============================================================================
--- sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/SubCommand.java
[UTF-8] (original)
+++ sis/branches/JDK8/application/sis-console/src/main/java/org/apache/sis/console/SubCommand.java
[UTF-8] Tue Feb 23 18:40:33 2016
@@ -38,7 +38,7 @@ import org.apache.sis.internal.util.X364
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.7
  * @module
  */
 abstract class SubCommand {
@@ -281,6 +281,13 @@ abstract class SubCommand {
     }
 
     /**
+     * Returns {@code true} if the command should use the standard input.
+     */
+    final boolean useStandardInput() {
+        return files.isEmpty() && System.console() == null;
+    }
+
+    /**
      * Prints the <cite>"Can not open …"</cite> error message followed by the
message in the given exception.
      *
      * @param fileIndex Index in the {@link #files} list of the file that can not be opened.

Copied: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java
(from r1731653, sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/XMLStore.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java?p2=sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java&p1=sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/XMLStore.java&r1=1731653&r2=1731924&rev=1731924&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/XMLStore.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java
[UTF-8] Tue Feb 23 18:40:33 2016
@@ -14,168 +14,103 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.storage.xml;
+package org.apache.sis.internal.storage.wkt;
 
-import java.util.Map;
-import java.util.Collections;
-import java.util.logging.LogRecord;
-import java.io.Closeable;
+import java.util.Arrays;
 import java.io.Reader;
-import java.io.InputStream;
 import java.io.IOException;
-import javax.xml.bind.JAXBException;
-import javax.xml.transform.stream.StreamSource;
 import org.opengis.metadata.Metadata;
 import org.opengis.referencing.ReferenceSystem;
-import org.apache.sis.xml.XML;
+import org.opengis.util.FactoryException;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.metadata.iso.DefaultMetadata;
-import org.apache.sis.util.logging.WarningListener;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.referencing.CRS;
 
 import static java.util.Collections.singleton;
 
 
 /**
- * A data store which creates data objects from a XML file.
- * This {@code DataStore} implementation is basically a facade for the {@link XML#unmarshal(Source,
Map)} method.
- * The current implementation recognizes the following objects:
- *
- * <ul>
- *   <li>{@link Metadata}, typically built from the {@code <gmd:MD_Metadata>}
XML element.</li>
- *   <li>{@link ReferenceSystem}, accessible by {@link Metadata#getReferenceSystemInfo()}.</li>
- * </ul>
- *
- * The above list may be extended in any future SIS version.
+ * A data store which creates data objects from a WKT definition.
+ * This {@code DataStore} implementation is basically a facade for the {@link CRS#fromWKT(String)}
method.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @since   0.4
- * @version 0.4
+ * @since   0.7
+ * @version 0.7
  * @module
  */
-public class XMLStore extends DataStore {
+final class Store extends DataStore {
     /**
      * The file name.
      */
     private final String name;
 
     /**
-     * The input stream or reader, set by the constructor and cleared when no longer needed.
+     * The reader, set by the constructor and cleared when no longer needed.
      */
-    private StreamSource source;
+    private Reader source;
 
     /**
-     * The unmarshalled object, initialized only when first needed.
-     * May still {@code null} if the unmarshalling failed.
+     * The parsed object, initialized only when first needed.
+     * May still {@code null} if the parsing failed.
      */
     private Object object;
 
     /**
-     * The metadata object, determined when first needed.
+     * The metadata object, created when first needed.
      */
     private Metadata metadata;
 
     /**
-     * Creates a new XML store from the given file, URL or stream.
+     * Creates a new WKT store from the given file, URL or stream.
      *
      * @param  connector Information about the storage (URL, stream, <i>etc</i>).
      * @throws DataStoreException If an error occurred while opening the stream.
      */
-    public XMLStore(final StorageConnector connector) throws DataStoreException {
+    public Store(final StorageConnector connector) throws DataStoreException {
         name = connector.getStorageName();
-        final InputStream in = connector.getStorageAs(InputStream.class);
-        if (in != null) {
-            source = new StreamSource(in);
-        } else {
-            final Reader reader = connector.getStorageAs(Reader.class);
-            if (reader != null) {
-                source = new StreamSource(reader);
-            }
-        }
-        final Closeable c = input(source);
-        connector.closeAllExcept(c);
-        if (c == null) {
+        source = connector.getStorageAs(Reader.class);
+        connector.closeAllExcept(source);
+        if (source == null) {
             throw new DataStoreException(Errors.format(Errors.Keys.CanNotOpen_1, name));
         }
     }
 
     /**
-     * Returns the input stream or reader set in the given source, or {@code null} if none.
-     */
-    private static Closeable input(final StreamSource source) {
-        Closeable in = null;
-        if (source != null) {
-            in = source.getInputStream();
-            if (in == null) {
-                in = source.getReader();
-            }
-        }
-        return in;
-    }
-
-    /**
-     * Returns the properties to give to the (un)marshaller.
-     */
-    private Map<String,?> properties() {
-        if (listeners.hasListeners()) {
-            return Collections.singletonMap(XML.WARNING_LISTENER, new WarningListener<Object>()
{
-                /** Returns the type of objects that emit warnings of interest for this listener.
*/
-                @Override public Class<Object> getSourceClass() {
-                    return Object.class;
-                }
-
-                /** Reports the occurrence of a non-fatal error during XML unmarshalling.
*/
-                @Override public void warningOccured(final Object source, final LogRecord
warning) {
-                    listeners.warning(warning);
-                }
-            });
-        }
-        return null;
-    }
-
-    /**
-     * Unmarshal the object, if not already done. Note that {@link #object} may still be
null
+     * Parses the object, if not already done. Note that {@link #object} may still be null
      * if an exception has been thrown at this invocation time or in previous invocation.
      *
-     * @throws DataStoreException If an error occurred during the unmarshalling process.
-     */
-    private void unmarshal() throws DataStoreException {
-        final StreamSource s = source;
-        final Closeable in = input(s);
-        source = null; // Cleared first in case of error.
-        if (in != null) try {
-            try {
-                object = XML.unmarshal(s, properties());
-            } finally {
-                in.close();
-            }
-        } catch (JAXBException | IOException e) {
-            throw new DataStoreException(Errors.format(Errors.Keys.CanNotRead_1, name), e);
-        }
-    }
-
-    /**
-     * Returns the metadata associated to the unmarshalled object, or {@code null} if none.
-     * The current implementation performs the following choice:
-     *
-     * <ul>
-     *   <li>If the unmarshalled object implements the {@link Metadata} interface,
then it is returned directly.</li>
-     * </ul>
-     *
-     * Other cases may be added in any future SIS version.
-     *
-     * @return The metadata associated to the unmarshalled object, or {@code null} if none.
-     * @throws DataStoreException If an error occurred during the unmarshalling process.
+     * @return The metadata associated to the parsed object, or {@code null} if none.
+     * @throws DataStoreException If an error occurred during the parsing process.
      */
     @Override
     public Metadata getMetadata() throws DataStoreException {
-        unmarshal();
         if (metadata == null) {
-            if (object instanceof Metadata) {
-                metadata = (Metadata) object;
-            } else if (object instanceof ReferenceSystem) {
+            final Reader in = source;
+            source = null;                      // Cleared first in case of error.
+            if (in != null) try {
+                char[] buffer = new char[StoreProvider.READ_AHEAD_LIMIT];
+                int length = 0;
+                try {
+                    int n;
+                    while ((n = in.read(buffer, length, buffer.length - length)) >= 0)
{
+                        if ((length += n) >= buffer.length) {
+                            if (n >= Integer.MAX_VALUE / 1024) {     // Arbitrary size
limit.
+                                throw new DataStoreException(Errors.format(Errors.Keys.ExcessiveStringSize));
+                            }
+                            buffer = Arrays.copyOf(buffer, n << 1);
+                        }
+                    }
+                } finally {
+                    in.close();
+                }
+                object = CRS.fromWKT(String.valueOf(buffer, 0, length));
+            } catch (IOException | FactoryException e) {
+                throw new DataStoreException(Errors.format(Errors.Keys.CanNotRead_1, name),
e);
+            }
+            if (object instanceof ReferenceSystem) {
                 final DefaultMetadata d = new DefaultMetadata();
                 d.setReferenceSystemInfo(singleton((ReferenceSystem) object));
                 metadata = d;
@@ -191,11 +126,11 @@ public class XMLStore extends DataStore
      */
     @Override
     public void close() throws DataStoreException {
+        final Reader s = source;
+        source = null;                  // Cleared first in case of failure.
         object = null;
-        final Closeable in = input(source);
-        source = null; // Cleared first in case of failure.
-        if (in != null) try {
-            in.close();
+        if (s != null) try {
+            s.close();
         } catch (IOException e) {
             throw new DataStoreException(e);
         }

Copied: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java
(from r1731653, sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/XMLStoreProvider.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java?p2=sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java&p1=sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/XMLStoreProvider.java&r1=1731653&r2=1731924&rev=1731924&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/XMLStoreProvider.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java
[UTF-8] Tue Feb 23 18:40:33 2016
@@ -14,8 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.storage.xml;
+package org.apache.sis.internal.storage.wkt;
 
+import java.util.HashSet;
+import java.util.Set;
 import java.io.Reader;
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -24,110 +26,180 @@ import org.apache.sis.storage.DataStoreP
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.ProbeResult;
+import org.apache.sis.internal.metadata.WKTKeywords;
 
 
 /**
- * The provider of {@link XMLStore} instances.
+ * The provider of WKT {@link Store} instances.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @since   0.4
- * @version 0.4
+ * @since   0.7
+ * @version 0.7
  * @module
  */
-public class XMLStoreProvider extends DataStoreProvider {
+public class StoreProvider extends DataStoreProvider {
     /**
-     * The {@value} MIME type, used only of {@link #probeContent(StorageConnector)} can not
determine
-     * a more accurate type.
+     * The read-ahead limit when reading the WKT from a {@link Reader}.
      */
-    public static final String MIME_TYPE = "application/xml";
+    static final int READ_AHEAD_LIMIT = 2048;
 
     /**
-     * The read-ahead limit when reading the XML document from a {@link Reader}.
+     * Length of the shortest WKT keyword.
      */
-    private static final int READ_AHEAD_LIMIT = 2048;
+    static final int MIN_LENGTH = 6;
 
     /**
-     * The expected XML header. According XML specification, this declaration is required
to appear
-     * at the document beginning (no space allowed before the declaration).
+     * Length of the longest WKT keyword.
      */
-    private static final byte[] HEADER = {'<','?','x','m','l',' '};
+    static final int MAX_LENGTH = 14;
+
+    /**
+     * The set of WKT keywords.
+     */
+    private static final Set<String> KEYWORDS = keywords();
+    static Set<String> keywords() {
+        final Set<String> s = new HashSet<>(22);
+        s.add(WKTKeywords.GeodeticCRS);
+        s.add(WKTKeywords.GeodCRS);
+        s.add(WKTKeywords.GeogCS);
+        s.add(WKTKeywords.GeocCS);
+        s.add(WKTKeywords.VerticalCRS);
+        s.add(WKTKeywords.VertCRS);
+        s.add(WKTKeywords.Vert_CS);
+        s.add(WKTKeywords.TimeCRS);
+        s.add(WKTKeywords.ImageCRS);
+        s.add(WKTKeywords.EngineeringCRS);
+        s.add(WKTKeywords.EngCRS);
+        s.add(WKTKeywords.Local_CS);
+        s.add(WKTKeywords.CompoundCRS);
+        s.add(WKTKeywords.Compd_CS);
+        s.add(WKTKeywords.ProjectedCRS);
+        s.add(WKTKeywords.ProjCRS);
+        s.add(WKTKeywords.ProjCS);
+        s.add(WKTKeywords.Fitted_CS);
+        return s;
+    }
 
     /**
      * Creates a new provider.
      */
-    public XMLStoreProvider() {
+    public StoreProvider() {
+    }
+
+    /**
+     * Returns the next character which is not a white space, or -1 if the end of stream
is reached.
+     * Exactly one of {@code buffer} and {@code reader} shall be non-null.
+     */
+    private static int nextAfterSpaces(final ByteBuffer buffer, final Reader reader) throws
IOException {
+        if (buffer != null) {
+            while (buffer.hasRemaining()) {
+                final char c = (char) buffer.get();
+                if (!Character.isWhitespace(c)) {
+                    return c;
+                }
+            }
+            return -1;
+        }
+        int c;
+        while ((c = reader.read()) >= 0) {
+            if (!Character.isWhitespace(c)) break;
+        }
+        return c;
+    }
+
+    /**
+     * Returns {@code true} if the given character is valid for a WKT keyword.
+     */
+    private static boolean isValidChar(final int c) {
+        return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
|| (c == '_');
     }
 
     /**
-     * Returns {@link ProbeResult#SUPPORTED} if the given storage appears to be supported
by {@link XMLStore}.
+     * Returns {@link ProbeResult#SUPPORTED} if the given storage appears to be supported
by WKT {@link Store}.
      * Returning {@code SUPPORTED} from this method does not guarantee that reading or writing
will succeed,
      * only that there appears to be a reasonable chance of success based on a brief inspection
of the storage
      * header.
      *
-     * @return {@link ProbeResult#SUPPORTED} if the given storage seems to be readable as
a XML file.
+     * @return {@link ProbeResult#SUPPORTED} if the given storage seems to be readable as
a WKT file.
      * @throws DataStoreException if an I/O or SQL error occurred.
      */
     @Override
+    @SuppressWarnings("null")
     public ProbeResult probeContent(final StorageConnector storage) throws DataStoreException
{
-        /*
-         * Usual case. This include InputStream, DataInput, File, Path, URL, URI.
-         */
-        final ByteBuffer buffer = storage.getStorageAs(ByteBuffer.class);
-        if (buffer != null) {
-            if (buffer.remaining() < HEADER.length) {
-                return ProbeResult.INSUFFICIENT_BYTES;
-            }
-            // Quick check for "<?xml " header.
-            for (int i=0; i<HEADER.length; i++) {
-                if (buffer.get(i) != HEADER[i]) {
+        char[] keyword = null;
+        int pos = 0;
+        try {
+            final ByteBuffer buffer = storage.getStorageAs(ByteBuffer.class);
+            final Reader reader;
+            if (buffer != null) {
+                buffer.mark();
+                reader = null;
+            } else {
+                // User gave us explicitely a Reader (e.g. a StringReader wrapping a String
instance).
+                reader = storage.getStorageAs(Reader.class);
+                if (reader == null) {
                     return ProbeResult.UNSUPPORTED_STORAGE;
                 }
+                reader.mark(READ_AHEAD_LIMIT);
             }
-            // Now check for a more accurate MIME type.
-            buffer.position(HEADER.length);
-            final ProbeResult result = new MimeTypeDetector() {
-                @Override int read() {
-                    if (buffer.hasRemaining()) {
-                        return buffer.get();
+            /*
+             * Ignore leading spaces if any, then get a keyword no longer than LENGTH.
+             * That keyword shall be followed by [ or (, ignoring whitespaces.
+             */
+            int c = nextAfterSpaces(buffer, reader);
+            if (isValidChar(c)) {
+                keyword = new char[MAX_LENGTH];
+                do {
+                    if (pos >= MAX_LENGTH) {
+                        keyword = null;             // Keyword too long.
+                        break;
                     }
-                    insufficientBytes = (buffer.limit() != buffer.capacity());
-                    return -1;
+                    keyword[pos++] = (char) c;
+                    c = (buffer == null) ? reader.read() : buffer.hasRemaining() ? (char)
buffer.get() : -1;
+                } while (isValidChar(c));
+                if (Character.isWhitespace(c)) {
+                    c = nextAfterSpaces(buffer, reader);
+                }
+                if (c != '[' && c != '(') {
+                    keyword = null;
                 }
-            }.probeContent();
-            buffer.position(0);
-            return result;
+            }
+            if (buffer != null) {
+                buffer.reset();
+            } else {
+                reader.reset();
+            }
+            if (c < 0) {
+                return ProbeResult.INSUFFICIENT_BYTES;
+            }
+        } catch (IOException e) {
+            throw new DataStoreException(e);
         }
         /*
-         * We should enter in this block only if the user gave us explicitely a Reader.
-         * A common case is a StringReader wrapping a String object.
+         * At this point we got the first keyword. Change the case to match the one used
in the KEYWORDS map,
+         * then verify if the keyword that we found is one of the known WKT keywords.
          */
-        final Reader reader = storage.getStorageAs(Reader.class);
-        if (reader != null) try {
-            // Quick check for "<?xml " header.
-            reader.mark(HEADER.length + READ_AHEAD_LIMIT);
-            for (int i=0; i<HEADER.length; i++) {
-                if (reader.read() != HEADER[i]) {
-                    reader.reset();
-                    return ProbeResult.UNSUPPORTED_STORAGE;
-                }
+        final int length = pos;
+        if (pos >= MIN_LENGTH) {
+            keyword[       0] &= ~0x20;         // Make upper-case (valid only for characters
in the a-z range).
+            keyword[--pos] &= ~0x20;
+            if ((keyword[--pos] &= ~0x20) == 'R') {
+                keyword[--pos] &= ~0x20;     // Make "CRS" suffix in upper case (otherwise,
was "CS" suffix)
             }
-            // Now check for a more accurate MIME type.
-            final ProbeResult result = new MimeTypeDetector() {
-                private int remaining = READ_AHEAD_LIMIT;
-                @Override int read() throws IOException {
-                    return (--remaining >= 0) ? reader.read() : -1;
+            while (--pos != 0) {
+                if (keyword[pos] != '_') {
+                    keyword[pos] |= 0x20;    // Make lower-case.
                 }
-            }.probeContent();
-            reader.reset();
-            return result;
-        } catch (IOException e) {
-            throw new DataStoreException(e);
+            }
+            if (KEYWORDS.contains(String.valueOf(keyword, 0, length))) {
+                return ProbeResult.SUPPORTED;
+            }
         }
         return ProbeResult.UNSUPPORTED_STORAGE;
     }
 
     /**
-     * Returns a {@link XMLStore} implementation associated with this provider.
+     * Returns a {@link Store} implementation associated with this provider.
      *
      * @param  storage Information about the storage (URL, stream, <i>etc</i>).
      * @return A data store implementation associated with this provider for the given storage.
@@ -135,6 +207,6 @@ public class XMLStoreProvider extends Da
      */
     @Override
     public DataStore open(final StorageConnector storage) throws DataStoreException {
-        return new XMLStore(storage);
+        return new Store(storage);
     }
 }

Copied: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/package-info.java
(from r1731653, sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/package-info.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/package-info.java?p2=sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/package-info.java&p1=sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/package-info.java&r1=1731653&r2=1731924&rev=1731924&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/package-info.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/package-info.java
[UTF-8] Tue Feb 23 18:40:33 2016
@@ -16,13 +16,11 @@
  */
 
 /**
- * {@link org.apache.sis.storage.DataStore} implementation for XML files.
- * The kind of objects recognized by this package is listed in the
- * {@link org.apache.sis.internal.storage.xml.XMLStore} class.
+ * {@link org.apache.sis.storage.DataStore} implementation for Well Known Text.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @since   0.4
- * @version 0.4
+ * @since   0.7
+ * @version 0.7
  * @module
  */
-package org.apache.sis.internal.storage.xml;
+package org.apache.sis.internal.storage.wkt;

Modified: sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/XMLStore.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/XMLStore.java?rev=1731924&r1=1731923&r2=1731924&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/XMLStore.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/XMLStore.java
[UTF-8] Tue Feb 23 18:40:33 2016
@@ -55,7 +55,7 @@ import static java.util.Collections.sing
  * @version 0.4
  * @module
  */
-public class XMLStore extends DataStore {
+final class XMLStore extends DataStore {
     /**
      * The file name.
      */
@@ -171,8 +171,8 @@ public class XMLStore extends DataStore
      */
     @Override
     public Metadata getMetadata() throws DataStoreException {
-        unmarshal();
         if (metadata == null) {
+            unmarshal();
             if (object instanceof Metadata) {
                 metadata = (Metadata) object;
             } else if (object instanceof ReferenceSystem) {

Modified: sis/branches/JDK8/storage/sis-storage/src/main/resources/META-INF/services/org.apache.sis.storage.DataStoreProvider
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/main/resources/META-INF/services/org.apache.sis.storage.DataStoreProvider?rev=1731924&r1=1731923&r2=1731924&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/main/resources/META-INF/services/org.apache.sis.storage.DataStoreProvider
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/main/resources/META-INF/services/org.apache.sis.storage.DataStoreProvider
[UTF-8] Tue Feb 23 18:40:33 2016
@@ -1 +1,2 @@
 org.apache.sis.internal.storage.xml.XMLStoreProvider
+org.apache.sis.internal.storage.wkt.StoreProvider

Copied: sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/wkt/StoreProviderTest.java
(from r1731653, sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreProviderTest.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/wkt/StoreProviderTest.java?p2=sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/wkt/StoreProviderTest.java&p1=sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreProviderTest.java&r1=1731653&r2=1731924&rev=1731924&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreProviderTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/wkt/StoreProviderTest.java
[UTF-8] Tue Feb 23 18:40:33 2016
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.storage.xml;
+package org.apache.sis.internal.storage.wkt;
 
 import java.io.StringReader;
 import org.apache.sis.storage.StorageConnector;
@@ -27,26 +27,58 @@ import static org.junit.Assert.*;
 
 
 /**
- * Tests {@link XMLStoreProvider}.
+ * Tests the WKT {@link StoreProvider}.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @since   0.4
- * @version 0.4
+ * @since   0.7
+ * @version 0.7
  * @module
  */
-public final strictfp class XMLStoreProviderTest extends TestCase {
+public final strictfp class StoreProviderTest extends TestCase {
     /**
-     * Tests {@link XMLStoreProvider#probeContent(StorageConnector)} method from a {@link
Reader} object.
+     * Verifies validity of {@code StoreProvider.MIN_LENGTH} and {@code StoreProvider.MAX_LENGTH}
constants
+     * by comparing them with the content of {@code StoreProvider.KEYWORDS} map.
+     */
+    @Test
+    public void testKeywordsMap() {
+        int min = Integer.MAX_VALUE;
+        int max = Integer.MIN_VALUE;
+        for (final String keyword : StoreProvider.keywords()) {
+            final int length = keyword.length();
+            if (length < min) min = length;
+            if (length > max) max = length;
+        }
+        assertEquals("MIN_LENGTH", min, StoreProvider.MIN_LENGTH);
+        assertEquals("MAX_LENGTH", max, StoreProvider.MAX_LENGTH);
+    }
+
+    /**
+     * Tests {@link StoreProvider#probeContent(StorageConnector)} method from a {@link Reader}
object.
      *
      * @throws DataStoreException Should never happen.
      */
     @Test
     public void testProbeContentFromReader() throws DataStoreException {
-        final XMLStoreProvider p = new XMLStoreProvider();
-        final StorageConnector c = new StorageConnector(new StringReader(XMLStoreTest.XML));
-        final ProbeResult      r = p.probeContent(c);
+        final StoreProvider p = new StoreProvider();
+        testProbeContentFromReader(true,  p, StoreTest.WKT);
+        testProbeContentFromReader(true,  p, "GeodeticCRS[…]");
+        testProbeContentFromReader(true,  p, "GeodeticCRS(…)");
+        testProbeContentFromReader(true,  p, "Vert_CS[…]");
+        testProbeContentFromReader(false, p, "DummyCS[…]");
+        testProbeContentFromReader(true,  p, "   GeodeticCRS  […]");
+        testProbeContentFromReader(false, p, "   DummyCS  […]");
+        testProbeContentFromReader(false, p, "Geodetic");
+    }
+
+    /**
+     * Implementation of {@link #testProbeContentFromReader()}.
+     */
+    private static void testProbeContentFromReader(final boolean supported,
+            final StoreProvider p, final String wkt) throws DataStoreException
+    {
+        final StorageConnector c = new StorageConnector(new StringReader(wkt));
+        final ProbeResult r = p.probeContent(c);
         c.closeAllExcept(null);
-        assertTrue  ("isSupported()", r.isSupported());
-        assertEquals("getMimeType()", "application/vnd.iso.19139+xml", r.getMimeType());
+        assertEquals("isSupported()", supported, r.isSupported());
     }
 }

Copied: sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/wkt/StoreTest.java
(from r1731653, sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreTest.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/wkt/StoreTest.java?p2=sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/wkt/StoreTest.java&p1=sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreTest.java&r1=1731653&r2=1731924&rev=1731924&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/xml/XMLStoreTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/wkt/StoreTest.java
[UTF-8] Tue Feb 23 18:40:33 2016
@@ -14,98 +14,57 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.storage.xml;
+package org.apache.sis.internal.storage.wkt;
 
-import java.util.Locale;
 import java.io.StringReader;
 import org.opengis.metadata.Metadata;
-import org.opengis.metadata.citation.*;
-import org.apache.sis.xml.Namespaces;
+import org.opengis.referencing.crs.GeographicCRS;
+import org.opengis.referencing.cs.AxisDirection;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.test.TestUtilities;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
 import static org.opengis.test.Assert.*;
-import static org.apache.sis.test.TestUtilities.getSingleton;
-
-// Branch-dependent imports
-import java.nio.charset.StandardCharsets;
 
 
 /**
- * Tests {@link XMLStore}.
+ * Tests the WKT {@link Store}.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @since   0.4
- * @version 0.5
+ * @since   0.7
+ * @version 0.7
  * @module
  */
-public final strictfp class XMLStoreTest extends TestCase {
+public final strictfp class StoreTest extends TestCase {
     /**
-     * The metadata to unmarshal.
+     * The WKT to parse.
      */
-    public static final String XML =
-            "<?xml version=\"1.0\" standalone=\"yes\"?>\n" +
-            "<gmd:MD_Metadata\n" +
-            "  xmlns:gmd = \"" + Namespaces.GMD + "\"\n"  +
-            "  xmlns:gco = \"" + Namespaces.GCO + "\"\n"  +
-            "  xmlns:xsi = \"" + Namespaces.XSI + "\"\n>" +
-            "  <gmd:language>\n" +
-            "    <gmd:LanguageCode codeListValue=\"eng\">English</gmd:LanguageCode>\n"
+
-            "  </gmd:language>\n" +
-            "  <gmd:characterSet>\n" +
-            "    <gmd:MD_CharacterSetCode codeListValue=\"utf8\">UTF-8</gmd:MD_CharacterSetCode>\n"
+
-            "  </gmd:characterSet>\n" +
-            "  <gmd:contact>\n" +
-            "    <gmd:CI_ResponsibleParty>\n" +
-            "      <gmd:organisationName>\n" +
-            "        <gco:CharacterString>Apache SIS</gco:CharacterString>\n"
+
-            "      </gmd:organisationName>\n" +
-            "      <gmd:contactInfo>\n" +
-            "        <gmd:CI_Contact>\n" +
-            "          <gmd:onlineResource>\n" +
-            "            <gmd:CI_OnlineResource>\n" +
-            "              <gmd:linkage>\n" +
-            "                <gmd:URL>http://sis.apache.org</gmd:URL>\n" +
-            "              </gmd:linkage>\n" +
-            "              <gmd:function>\n" +
-            "                <gmd:CI_OnLineFunctionCode codeListValue=\"information\"
codeSpace=\"fra\">Information</gmd:CI_OnLineFunctionCode>\n" +
-            "              </gmd:function>\n" +
-            "            </gmd:CI_OnlineResource>\n" +
-            "          </gmd:onlineResource>\n" +
-            "        </gmd:CI_Contact>\n" +
-            "      </gmd:contactInfo>\n" +
-            "      <gmd:role>\n" +
-            "        <gmd:CI_RoleCode codeListValue=\"principalInvestigator\">Principal
investigator</gmd:CI_RoleCode>\n" +
-            "      </gmd:role>\n" +
-            "    </gmd:CI_ResponsibleParty>\n" +
-            "  </gmd:contact>\n" +
-            "</gmd:MD_Metadata>\n";
+    public static final String WKT =
+            "GEOGCS[“NTF (Paris)”,\n" +
+            "  DATUM[“Nouvelle Triangulation Française (Paris)”,\n" +
+            "    SPHEROID[“Clarke 1880 (IGN)”, 6378249.2, 293.4660212936269]],\n" +
+            "    PRIMEM[“Paris”, 2.5969213, AUTHORITY[“EPSG”, “8903”]],\n" +
+            "  UNIT[“grade”, 0.015707963267948967],\n" +
+            "  AXIS[“Latitude”, NORTH],\n" +
+            "  AXIS[“Longitude”, EAST]]";
 
     /**
-     * Tests {@link XMLStore#getMetadata()}.
+     * Tests {@link Store#getMetadata()}.
      *
      * @throws DataStoreException If an error occurred while reading the metadata.
      */
     @Test
     public void testMetadata() throws DataStoreException {
         final Metadata metadata;
-        try (XMLStore store = new XMLStore(new StorageConnector(new StringReader(XML))))
{
+        try (Store store = new Store(new StorageConnector(new StringReader(WKT)))) {
             metadata = store.getMetadata();
             assertSame("Expected cached value.", metadata, store.getMetadata());
         }
-        final Responsibility resp     = getSingleton(metadata.getContacts());
-        final Party          party    = getSingleton(resp.getParties());
-        final Contact        contact  = getSingleton(party.getContactInfo());
-        final OnlineResource resource = getSingleton(contact.getOnlineResources());
-
-        assertInstanceOf("party", Organisation.class, party);
-        assertEquals(Locale.ENGLISH,              getSingleton(metadata.getLanguages()));
-        assertEquals(StandardCharsets.UTF_8,      getSingleton(metadata.getCharacterSets()));
-        assertEquals(Role.PRINCIPAL_INVESTIGATOR, resp.getRole());
-        assertEquals("Apache SIS",                String.valueOf(party.getName()));
-        assertEquals("http://sis.apache.org",     String.valueOf(resource.getLinkage()));
-        assertEquals(OnLineFunction.INFORMATION,  resource.getFunction());
+        final GeographicCRS crs = (GeographicCRS) TestUtilities.getSingleton(metadata.getReferenceSystemInfo());
+        assertEquals("NTF (Paris)", crs.getName().getCode());
+        assertEquals("Nouvelle Triangulation Française (Paris)", crs.getDatum().getName().getCode());
+        assertAxisDirectionsEqual("EllipsoidalCS", crs.getCoordinateSystem(), AxisDirection.NORTH,
AxisDirection.EAST);
     }
 }

Modified: sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java?rev=1731924&r1=1731923&r2=1731924&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
[UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
[UTF-8] Tue Feb 23 18:40:33 2016
@@ -26,7 +26,7 @@ import org.junit.BeforeClass;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.5
+ * @version 0.7
  * @module
  */
 @Suite.SuiteClasses({
@@ -40,6 +40,8 @@ import org.junit.BeforeClass;
     org.apache.sis.internal.storage.xml.MimeTypeDetectorTest.class,
     org.apache.sis.internal.storage.xml.XMLStoreProviderTest.class,
     org.apache.sis.internal.storage.xml.XMLStoreTest.class,
+    org.apache.sis.internal.storage.wkt.StoreProviderTest.class,
+    org.apache.sis.internal.storage.wkt.StoreTest.class,
     org.apache.sis.storage.DataStoresTest.class,
     org.apache.sis.index.GeoHashCoderTest.class
 })




Mime
View raw message