sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1514792 - in /sis/branches/JDK7: core/sis-utility/src/main/java/org/apache/sis/util/ core/sis-utility/src/test/java/org/apache/sis/util/ storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ storage/sis-netcdf/src/main/java...
Date Fri, 16 Aug 2013 17:06:54 GMT
Author: desruisseaux
Date: Fri Aug 16 17:06:53 2013
New Revision: 1514792

URL: http://svn.apache.org/r1514792
Log:
NetCDF provider can now provide MIME type and file version number.

Modified:
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/Version.java
    sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/VersionTest.java
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
    sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
    sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreProviderTest.java
    sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/ProbeResult.java

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/Version.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/Version.java?rev=1514792&r1=1514791&r2=1514792&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/Version.java [UTF-8]
(original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/Version.java [UTF-8]
Fri Aug 16 17:06:53 2013
@@ -18,6 +18,7 @@ package org.apache.sis.util;
 
 import java.io.Serializable;
 import java.util.StringTokenizer;
+import org.apache.sis.util.resources.Errors;
 
 
 /**
@@ -31,9 +32,9 @@ import java.util.StringTokenizer;
  * <p>This class provides methods for performing comparisons of {@code Version} objects
where major,
  * minor and revision parts are compared as numbers when possible, or as strings otherwise.</p>
  *
- * @author  Martin Desruisseaux (IRD)
+ * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3 (derived from geotk-2.4)
- * @version 0.3
+ * @version 0.4
  * @module
  */
 @Immutable
@@ -44,15 +45,26 @@ public class Version implements CharSequ
     private static final long serialVersionUID = 8402041502662929792L;
 
     /**
+     * The separator characters between {@linkplain #getMajor() major}, {@linkplain #getMinor()
minor}
+     * and {@linkplain #getRevision() revision} components. Any character in this string
fits.
+     */
+    private static final String SEPARATORS = ".-";
+
+    /**
      * The version of this Apache SIS distribution.
      */
     public static final Version SIS = new Version("0.4-SNAPSHOT");
 
     /**
-     * The separator characters between {@linkplain #getMajor() major}, {@linkplain #getMinor()
minor}
-     * and {@linkplain #getRevision() revision} components. Any character in this string
fits.
+     * A few commonly used version numbers. This list is based on SIS needs, e.g. in {@code
DataStore}
+     * implementations. New constants are likely to be added in any future SIS versions.
+     *
+     * @see #valueOf(int[])
      */
-    private static final String SEPARATORS = ".-";
+    private static final Version[] CONSTANTS = {
+        new Version("1"),
+        new Version("2")
+    };
 
     /**
      * The version in string form, with leading and trailing spaces removed.
@@ -81,7 +93,56 @@ public class Version implements CharSequ
      */
     public Version(final String version) {
         ArgumentChecks.ensureNonNull("version", version);
-        this.version = CharSequences.trimWhitespaces(version);
+        this.version = version;
+    }
+
+    /**
+     * Returns an instance for the given integer values.
+     * The {@code components} array must contain at least 1 element, where:
+     *
+     * <ul>
+     *   <li>The first element is the {@linkplain #getMajor() major} number.</li>
+     *   <li>The second element (if any) is the {@linkplain #getMinor() minor} number.</li>
+     *   <li>The third element (if any) is the {@linkplain #getRevision() revision}
number.</li>
+     *   <li>Other elements (if any) will be appended to the {@link #toString() string
value}.</li>
+     * </ul>
+     *
+     * @param  components The major number, optionally followed by minor, revision or other
numbers.
+     * @return A new or existing instance of {@code Version} for the given numbers.
+     *
+     * @since 0.4
+     */
+    public static Version valueOf(final int... components) {
+        if (components.length == 0) {
+            throw new IllegalArgumentException(Errors.format(Errors.Keys.EmptyArgument_1,
"components"));
+        }
+        final Version version;
+        final int major = components[0];
+        if (components.length == 1) {
+            if (major >= 1 && major <= CONSTANTS.length) {
+                return CONSTANTS[major-1];
+            } else {
+                version = new Version(Integer.toString(major));
+            }
+        } else {
+            final StringBuilder buffer = new StringBuilder().append(major);
+            for (int i=1; i<components.length; i++) {
+                buffer.append('.').append(components[i]);
+            }
+            version = new Version(buffer.toString());
+        }
+        /*
+         * Pre-compute the 'parsed' array since we already have the integer values. It will
avoid the need to
+         * create the 'this.components' array and to parse the String values if a 'getFoo()'
method is invoked.
+         * Note that the cost is typically only the 'parsed' array creation, not Integer
objects creation, since
+         * version numbers are usually small enough for allowing 'Integer.valueOf(int)' to
cache them.
+         */
+        final Integer[] parsed = new Integer[components.length];
+        for (int i=0; i<components.length; i++) {
+            parsed[i] = components[i];
+        }
+        version.parsed = parsed;
+        return version;
     }
 
     /**

Modified: sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/VersionTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/VersionTest.java?rev=1514792&r1=1514791&r2=1514792&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/VersionTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/test/java/org/apache/sis/util/VersionTest.java
[UTF-8] Fri Aug 16 17:06:53 2013
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.util;
 
+import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
@@ -25,9 +26,9 @@ import static org.apache.sis.test.Assert
 /**
  * Tests the {@link Version} class, especially the {@code compareTo} method.
  *
- * @author  Martin Desruisseaux (IRD)
+ * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3 (derived from geotk-2.4)
- * @version 0.3
+ * @version 0.4
  * @module
  */
 public final strictfp class VersionTest extends TestCase {
@@ -54,6 +55,7 @@ public final strictfp class VersionTest 
      * Tests a alpha-numeric version.
      */
     @Test
+    @DependsOnMethod("testNumeric")
     public void testAlphaNumeric() {
         final Version version = new Version("1.6.b2");
         assertEquals("1.6.b2", version.toString());
@@ -69,6 +71,48 @@ public final strictfp class VersionTest 
     }
 
     /**
+     * Tests the {@link Version#valueOf(int[])} method.
+     */
+    @Test
+    public void testValueOf() {
+        Version version = Version.valueOf(1);
+        assertEquals("1", version.toString());
+        assertEquals( 1,  version.getMajor());
+        assertNull  (     version.getMinor());
+        assertNull  (     version.getRevision());
+
+        version = Version.valueOf(10);
+        assertEquals("10", version.toString());
+        assertEquals( 10,  version.getMajor());
+        assertNull  (      version.getMinor());
+        assertNull  (      version.getRevision());
+
+        version = Version.valueOf(0, 4);
+        assertEquals("0.4", version.toString());
+        assertEquals( 0,    version.getMajor());
+        assertEquals(   4,  version.getMinor());
+        assertNull  (       version.getRevision());
+
+        version = Version.valueOf(6, 11, 2);
+        assertEquals("6.11.2", version.toString());
+        assertEquals( 6,       version.getMajor());
+        assertEquals(   11,    version.getMinor());
+        assertEquals(      2,  version.getRevision());
+    }
+
+    /**
+     * Tests the cached values of {@link Version#valueOf(int[])}.
+     */
+    @Test
+    @DependsOnMethod("testValueOf")
+    public void testCachedValueOf() {
+        for (int major=1; major<=2; major++) {
+            final Version version = Version.valueOf(major);
+            assertSame(version.toString(), version, Version.valueOf(major));
+        }
+    }
+
+    /**
      * Tests serialization.
      */
     @Test

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java?rev=1514792&r1=1514791&r2=1514792&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/ChannelDecoder.java
[UTF-8] Fri Aug 16 17:06:53 2013
@@ -76,6 +76,11 @@ public final class ChannelDecoder extend
     public static final int MAGIC_NUMBER = ('C' << 24) | ('D' << 16) | ('F' <<
 8);
 
     /**
+     * The maximal version number supported by this implementation.
+     */
+    public static final int MAX_VERSION = 2;
+
+    /**
      * The encoding of dimension, variable and attribute names. This is fixed to {@value}
by the
      * NetCDF specification. Note however that the encoding of attribute values may be different.
      *
@@ -211,6 +216,7 @@ public final class ChannelDecoder extend
             case 1:  is64bits = false; break;
             case 2:  is64bits = true;  break;
             default: throw new DataStoreException(errors().getString(Errors.Keys.UnsupportedVersion_1,
version));
+            // If more cases are added, remember to increment the MAX_VERSION constant.
         }
         numrecs = input.readInt();
         /*

Modified: sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java?rev=1514792&r1=1514791&r2=1514792&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
[UTF-8] Fri Aug 16 17:06:53 2013
@@ -35,6 +35,7 @@ import org.apache.sis.storage.DataStoreE
 import org.apache.sis.storage.ProbeResult;
 import org.apache.sis.util.logging.WarningListeners;
 import org.apache.sis.util.ThreadSafe;
+import org.apache.sis.util.Version;
 
 
 /**
@@ -54,6 +55,11 @@ import org.apache.sis.util.ThreadSafe;
 @ThreadSafe
 public class NetcdfStoreProvider extends DataStoreProvider {
     /**
+     * The MIME type for NetCDF files.
+     */
+    static final String MIME_TYPE = "application/x-netcdf";
+
+    /**
      * The name of the {@link ucar.nc2.NetcdfFile} class, which is {@value}.
      */
     private static final String UCAR_CLASSNAME = "ucar.nc2.NetcdfFile";
@@ -113,6 +119,9 @@ public class NetcdfStoreProvider extends
      */
     @Override
     public ProbeResult probeContent(StorageConnector storage) throws DataStoreException {
+        int     version     = 0;
+        boolean hasVersion  = false;
+        boolean isSupported = false;
         final ByteBuffer buffer = storage.getStorageAs(ByteBuffer.class);
         if (buffer != null) {
             if (buffer.remaining() < Integer.SIZE / Byte.SIZE) {
@@ -120,39 +129,56 @@ public class NetcdfStoreProvider extends
             }
             final int header = buffer.getInt(buffer.position());
             if ((header & 0xFFFFFF00) == ChannelDecoder.MAGIC_NUMBER) {
-                return ProbeResult.SUPPORTED;
+                hasVersion  = true;
+                version     = header & 0xFF;
+                isSupported = (version >= 1 && version <= ChannelDecoder.MAX_VERSION);
             }
         }
         /*
          * If we failed to check using the embedded decoder, tries using the UCAR library.
+         * The UCAR library is an optional dependency. If that library is present and the
+         * input is a String, then the following code may trigs a large amount of classes
+         * loading.
          */
-        final String path = storage.getStorageAs(String.class);
-        if (path != null) {
-            ensureInitialized();
-            final Method method = canOpenFromPath;
-            if (method != null) try {
-                return ((Boolean) method.invoke(null, path)) ? ProbeResult.SUPPORTED : ProbeResult.UNSUPPORTED_STORAGE;
-            } catch (IllegalAccessException e) {
-                throw new AssertionError(e); // Should never happen, since the method is
public.
-            } catch (InvocationTargetException e) {
-                final Throwable cause = e.getCause();
-                if (cause instanceof DataStoreException) throw (DataStoreException) cause;
-                if (cause instanceof RuntimeException)   throw (RuntimeException)   cause;
-                if (cause instanceof Error)              throw (Error)              cause;
-                throw new DataStoreException(e); // The cause may be IOException.
+        if (!isSupported) {
+            final String path = storage.getStorageAs(String.class);
+            if (path != null) {
+                ensureInitialized();
+                final Method method = canOpenFromPath;
+                if (method != null) try {
+                    isSupported = (Boolean) method.invoke(null, path);
+                } catch (IllegalAccessException e) {
+                    // Should never happen, since the method is public.
+                    throw (Error) new IncompatibleClassChangeError("canOpen").initCause(e);
+                } catch (InvocationTargetException e) {
+                    final Throwable cause = e.getCause();
+                    if (cause instanceof DataStoreException) throw (DataStoreException) cause;
+                    if (cause instanceof RuntimeException)   throw (RuntimeException)   cause;
+                    if (cause instanceof Error)              throw (Error)              cause;
+                    throw new DataStoreException(e); // The cause may be IOException.
+                }
+            } else {
+                /*
+                 * Check if the given input is itself an instance of the UCAR oject.
+                 * We check classnames instead of netcdfFileClass.isInstance(storage)
+                 * in order to avoid loading the UCAR library if not needed.
+                 */
+                for (Class<?> type = storage.getStorage().getClass(); type != null;
type = type.getSuperclass()) {
+                    if (UCAR_CLASSNAME.equals(type.getName())) {
+                        isSupported = true;
+                        break;
+                    }
+                }
             }
         }
         /*
-         * Check if the given input is itself an instance of the UCAR oject.
-         * We check classnames instead of netcdfFileClass.isInstance(storage)
-         * in order to avoid loading the UCAR library if not needed.
+         * At this point, the readability status has been determined. The file version number
+         * is unknown if we are able to open the file only through the UCAR library.
          */
-        for (Class<?> type = storage.getStorage().getClass(); type != null; type =
type.getSuperclass()) {
-            if (UCAR_CLASSNAME.equals(type.getName())) {
-                return ProbeResult.SUPPORTED;
-            }
+        if (hasVersion) {
+            return new ProbeResult(isSupported, MIME_TYPE, Version.valueOf(version));
         }
-        return ProbeResult.UNSUPPORTED_STORAGE;
+        return isSupported ? new ProbeResult(true, MIME_TYPE, null) : ProbeResult.UNSUPPORTED_STORAGE;
     }
 
     /**

Modified: sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreProviderTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreProviderTest.java?rev=1514792&r1=1514791&r2=1514792&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreProviderTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-netcdf/src/test/java/org/apache/sis/storage/netcdf/NetcdfStoreProviderTest.java
[UTF-8] Fri Aug 16 17:06:53 2013
@@ -27,6 +27,7 @@ import org.apache.sis.internal.netcdf.im
 import org.apache.sis.storage.ProbeResult;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.util.Version;
 import org.apache.sis.test.DependsOn;
 import org.junit.Test;
 
@@ -38,7 +39,7 @@ import static org.opengis.test.Assert.*;
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.3
- * @version 0.3
+ * @version 0.4
  * @module
  */
 @DependsOn({
@@ -55,7 +56,10 @@ public final strictfp class NetcdfStoreP
     public void testProbeContentFromStream() throws DataStoreException {
         final StorageConnector c = new StorageConnector(IOTestCase.class.getResourceAsStream(NCEP));
         final NetcdfStoreProvider provider = new NetcdfStoreProvider();
-        assertEquals(ProbeResult.SUPPORTED, provider.probeContent(c));
+        final ProbeResult probe = provider.probeContent(c);
+        assertTrue  ("isSupported", probe.isSupported());
+        assertEquals("getMimeType", NetcdfStoreProvider.MIME_TYPE, probe.getMimeType());
+        assertEquals("getVersion",  new Version("1"), probe.getVersion());
         c.closeAllExcept(null);
     }
 
@@ -70,7 +74,10 @@ public final strictfp class NetcdfStoreP
         final NetcdfFile file = open(NCEP);
         final StorageConnector c = new StorageConnector(file);
         final NetcdfStoreProvider provider = new NetcdfStoreProvider();
-        assertEquals(ProbeResult.SUPPORTED, provider.probeContent(c));
+        final ProbeResult probe = provider.probeContent(c);
+        assertTrue  ("isSupported", probe.isSupported());
+        assertEquals("getMimeType", NetcdfStoreProvider.MIME_TYPE, probe.getMimeType());
+        assertNull  ("getVersion",  probe.getVersion());
         file.close();
     }
 

Modified: sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/ProbeResult.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/ProbeResult.java?rev=1514792&r1=1514791&r2=1514792&view=diff
==============================================================================
--- sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/ProbeResult.java
[UTF-8] (original)
+++ sis/branches/JDK7/storage/sis-storage/src/main/java/org/apache/sis/storage/ProbeResult.java
[UTF-8] Fri Aug 16 17:06:53 2013
@@ -43,9 +43,9 @@ import java.util.Objects;
  *
  * {@section Special values}
  * In addition to the supported/unsupported information, {@code ProbeResult} defines two
constants having
- * a special meaning: {@link #INSUFFICIENT_BYTES} and {@link #UNDETERMINED} indicate that
the provider does
+ * a special meaning: {@link #INSUFFICIENT_BYTES} and {@link #UNDETERMINED}, which indicate
that the provider does
  * not have enough information for telling whether the storage can be opened.
- * SIS will try to use such provider last, if no better suited provider is found.
+ * In such cases, SIS will revisit those providers only if no better suited provider is found.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
@@ -141,14 +141,14 @@ public class ProbeResult implements Seri
     private final boolean isSupported;
 
     /**
-     * The storage MIME type, or {@code null} if unknown or irrelevant.
+     * The storage MIME type, or {@code null} if unknown or not applicable.
      *
      * @see #getMimeType()
      */
     private final String mimeType;
 
     /**
-     * The version of file format or database schema used by the storage, or {@code null}
if unknown or irrelevant.
+     * The version of file format or database schema used by the storage, or {@code null}
if unknown or not applicable.
      *
      * @see #getVersion()
      */
@@ -158,9 +158,9 @@ public class ProbeResult implements Seri
      * Creates a new {@code ProbeResult} with the given support status, MIME type and version
number.
      *
      * @param isSupported {@code true} if the storage is supported by the {@link DataStoreProvider}.
-     * @param mimeType    The storage MIME type, or {@code null} if unknown or irrelevant.
+     * @param mimeType    The storage MIME type, or {@code null} if unknown or not applicable.
      * @param version     The version of file format or database schema used by the storage,
-     *                    or {@code null} if unknown or irrelevant.
+     *                    or {@code null} if unknown or not applicable.
      */
     public ProbeResult(final boolean isSupported, final String mimeType, final Version version)
{
         this.isSupported = isSupported;
@@ -180,7 +180,7 @@ public class ProbeResult implements Seri
     }
 
     /**
-     * Returns the MIME type of the storage file format, or {@code null} if unknown or irrelevant.
+     * Returns the MIME type of the storage file format, or {@code null} if unknown or not
applicable.
      * The {@link DataStoreProvider} may (at implementation choice) inspect the storage content
for
      * determining a more accurate MIME type.
      *
@@ -203,7 +203,7 @@ public class ProbeResult implements Seri
      * Consequently, a XML data store provider may need to read the root element of a XML
document in order
      * to determine the document MIME type.}
      *
-     * @return The storage MIME type, or {@code null} if unknown or irrelevant.
+     * @return The storage MIME type, or {@code null} if unknown or not applicable.
      */
     public String getMimeType() {
         return mimeType;
@@ -211,10 +211,10 @@ public class ProbeResult implements Seri
 
     /**
      * Returns the version of file format or database schema used by the storage,
-     * or {@code null} if unknown or irrelevant.
+     * or {@code null} if unknown or not applicable.
      *
      * @return The version of file format or database schema used by the storage,
-     *         or {@code null} if unknown or irrelevant.
+     *         or {@code null} if unknown or not applicable.
      */
     public Version getVersion() {
         return version;



Mime
View raw message