Modified: sis/trunk/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java URL: http://svn.apache.org/viewvc/sis/trunk/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java [UTF-8] (original) +++ sis/trunk/profiles/sis-french-profile/src/main/java/org/apache/sis/internal/profile/fra/ProfileTypes.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -26,7 +26,7 @@ import org.apache.sis.internal.jaxb.Type * * @author Martin Desruisseaux (Geomatys) * @since 0.4 - * @version 0.4 + * @version 0.8 * @module */ public final class ProfileTypes extends TypeRegistration { @@ -34,7 +34,7 @@ public final class ProfileTypes extends * Adds to the given collection the metadata types that should be given to the initial JAXB context. */ @Override - public void getTypes(final Collection<Class<?>> addTo) { + protected void getTypes(final Collection<Class<?>> addTo) { addTo.add(DataIdentification.class); addTo.add(DirectReferenceSystem.class); addTo.add(IndirectReferenceSystem.class);
Modified: sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.java [UTF-8] (original) +++ sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -59,6 +59,11 @@ public final class Resources extends Ind } /** + * Can not use UCAR library for NetCDF format. Fallback on Apache SIS implementation. + */ + public static final short CanNotUseUCAR = 4; + + /** * Dimension “{2}” declared by attribute “{1}” is not found in the “{0}” file. */ public static final short DimensionNotFound_3 = 1; Modified: sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.properties URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.properties?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.properties [ISO-8859-1] (original) +++ sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources.properties [ISO-8859-1] Fri Feb 3 08:01:02 2017 @@ -19,6 +19,7 @@ # Resources in this file are for "sis-netcdf" usage only and should not be used by any other module. # For resources shared by all modules in the Apache SIS project, see "org.apache.sis.util.resources" package. # +CanNotUseUCAR = Can not use UCAR library for NetCDF format. Fallback on Apache SIS implementation. DimensionNotFound_3 = Dimension \u201c{2}\u201d declared by attribute \u201c{1}\u201d is not found in the \u201c{0}\u201d file. UnexpectedDimensionForVariable_4 = Variable \u201c{1}\u201d in file \u201c{0}\u201d has a dimension \u201c{3}\u201d while we expected \u201c{2}\u201d. VariableNotFound_2 = Variable \u201c{1}\u201d is not found in the \u201c{0}\u201d file. Modified: sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources_fr.properties URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources_fr.properties?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources_fr.properties [ISO-8859-1] (original) +++ sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Resources_fr.properties [ISO-8859-1] Fri Feb 3 08:01:02 2017 @@ -24,6 +24,7 @@ # U+202F NARROW NO-BREAK SPACE before ; ! and ? # U+00A0 NO-BREAK SPACE before : # +CanNotUseUCAR = Ne peut pas utiliser la biblioth\u00e8que de l\u2019UCAR pour le format NetCDF. L\u2019impl\u00e9mentation de Apache SIS sera utilis\u00e9e \u00e0 la place. DimensionNotFound_3 = La dimension \u00ab\u202f{2}\u202f\u00bb d\u00e9clar\u00e9e par l\u2019attribut \u00ab\u202f{1}\u202f\u00bb n\u2019a pas \u00e9t\u00e9 trouv\u00e9e dans le fichier \u00ab\u202f{0}\u202f\u00bb. UnexpectedDimensionForVariable_4 = La variable \u00ab\u202f{1}\u202f\u00bb dans le fichier \u00ab\u202f{0}\u202f\u00bb a une dimension \u00ab\u202f{3}\u202f\u00bb alors qu\u2019on attendait \u00ab\u202f{2}\u202f\u00bb. VariableNotFound_2 = La variable \u00ab\u202f{1}\u202f\u00bb n\u2019a pas \u00e9t\u00e9 trouv\u00e9e dans le fichier \u00ab\u202f{0}\u202f\u00bb. Modified: sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java [UTF-8] (original) +++ sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -16,6 +16,8 @@ */ package org.apache.sis.storage.netcdf; +import java.util.logging.Level; +import java.util.logging.LogRecord; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; @@ -25,6 +27,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.UndeclaredThrowableException; import org.apache.sis.internal.netcdf.Decoder; +import org.apache.sis.internal.netcdf.Resources; import org.apache.sis.internal.netcdf.impl.ChannelDecoder; import org.apache.sis.internal.netcdf.ucar.DecoderWrapper; import org.apache.sis.internal.storage.io.ChannelDataInput; @@ -136,7 +139,7 @@ public class NetcdfStoreProvider extends * @throws DataStoreException if an I/O error occurred. */ @Override - public ProbeResult probeContent(StorageConnector connector) throws DataStoreException { + public ProbeResult probeContent(final StorageConnector connector) throws DataStoreException { int version = 0; boolean hasVersion = false; boolean isSupported = false; @@ -164,7 +167,7 @@ public class NetcdfStoreProvider extends if (!isSupported) { final String path = connector.getStorageAs(String.class); if (path != null) { - ensureInitialized(); + ensureInitialized(false); final Method method = canOpenFromPath; if (method != null) try { isSupported = (Boolean) method.invoke(null, path); @@ -275,7 +278,7 @@ public class NetcdfStoreProvider extends private static Decoder createByReflection(final WarningListeners<?> listeners, final Object input, final boolean isUCAR) throws IOException, DataStoreException { - ensureInitialized(); + ensureInitialized(true); /* * Get the appropriate constructor for the isUCAR argument. This constructor will be null * if the above code failed to load the UCAR library. Otherwise, instantiate the wrapper. @@ -300,17 +303,23 @@ public class NetcdfStoreProvider extends if (cause instanceof DataStoreException) throw (DataStoreException) cause; if (cause instanceof RuntimeException) throw (RuntimeException) cause; if (cause instanceof Error) throw (Error) cause; - throw new UndeclaredThrowableException(cause); // Should never happen actually. + throw new UndeclaredThrowableException(cause); // Should never happen actually. } catch (ReflectiveOperationException e) { - throw new AssertionError(e); // Should never happen (shall be verified by the JUnit tests). + throw new AssertionError(e); // Should never happen (shall be verified by the JUnit tests). } } /** * Gets the {@link java.lang.Class} that represent the {@link ucar.nc2.NetcdfFile type}. + * + * @param open {@code true} if this method is invoked (indirectly) from the {@link #open(StorageConnector)} + * method, or {@code false} if invoked from the {@link #probeContent(StorageConnector)} method. + * This is used only for logging message. */ - private static void ensureInitialized() { + private static void ensureInitialized(final boolean open) { if (netcdfFileClass == null) { + Level severity = null; // Logging level to use in case of failure. + Throwable cause = null; // Cause of the failure (may stay null). synchronized (NetcdfStoreProvider.class) { /* * No double-check because it is not a big deal if the constructors are fetched twice. @@ -318,29 +327,50 @@ public class NetcdfStoreProvider extends */ try { netcdfFileClass = Class.forName(UCAR_CLASSNAME); + canOpenFromPath = netcdfFileClass.getMethod("canOpen", String.class); + if (canOpenFromPath.getReturnType() == Boolean.TYPE) { + /* + * At this point we found the class and method from UCAR API. Now get the Apache SIS wrapper + * using reflection for avoiding "hard" dependency from this provider to the UCAR library. + */ + final Class<? extends Decoder> wrapper = + Class.forName("org.apache.sis.internal.netcdf.ucar.DecoderWrapper").asSubclass(Decoder.class); + final Class<?>[] parameterTypes = new Class<?>[] {WarningListeners.class, netcdfFileClass}; + createFromUCAR = wrapper.getConstructor(parameterTypes); + parameterTypes[1] = String.class; + createFromPath = wrapper.getConstructor(parameterTypes); + return; // Success + } } catch (ClassNotFoundException e) { - netcdfFileClass = Void.TYPE; - return; - } - try { /* - * UCAR API. + * Happen if the UCAR library is not on the classpath. Log at the configuration level without + * reporting the exception (for avoiding scaring logs) because this is a typical use case. */ - canOpenFromPath = netcdfFileClass.getMethod("canOpen", String.class); - assert canOpenFromPath.getReturnType() == Boolean.TYPE; + severity = Level.CONFIG; + } catch (NoClassDefFoundError | ReflectiveOperationException e) { /* - * SIS Wrapper API. + * NoClassDefFoundError may happen if the UCAR class has been found but one of its dependencies + * is missing (for example SLF4J). Log at the warning level because the user probably wanted to + * use the UCAR library. + * + * ReflectiveOperationException should never happen because API compatibility shall be verified + * by the JUnit tests. If it happen anyway (for example because the user puts on his classpath + * a different version of the NetCDF library than the one we tested), report a warning. */ - final Class<? extends Decoder> wrapper = - Class.forName("org.apache.sis.internal.netcdf.ucar.DecoderWrapper").asSubclass(Decoder.class); - final Class<?>[] parameterTypes = new Class<?>[] {WarningListeners.class, netcdfFileClass}; - createFromUCAR = wrapper.getConstructor(parameterTypes); - parameterTypes[1] = String.class; - createFromPath = wrapper.getConstructor(parameterTypes); - } catch (ReflectiveOperationException e) { - throw new AssertionError(e); // Should never happen (shall be verified by the JUnit tests). + severity = Level.WARNING; + cause = e; } + /* + * At this point we failed to use the UCAR library. Remember that failure while we are still in the + * synchronized block, then log a message outside the synchronized block. + */ + reset(); + netcdfFileClass = Void.TYPE; } + final LogRecord record = Resources.forLocale(null).getLogRecord(severity, Resources.Keys.CanNotUseUCAR); + record.setThrown(cause); + record.setLoggerName(Modules.NETCDF); + Logging.log(NetcdfStoreProvider.class, open ? "open" : "probeContent", record); } } Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/FeatureStore.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/FeatureStore.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/FeatureStore.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/FeatureStore.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -84,6 +84,8 @@ public abstract class FeatureStore exten * * @return a stream over all features in the data store. * @throws DataStoreException if an error occurred while creating the feature stream. + * + * @todo a future version of this method will take some kind of {@code Query} or {@code Filter} argument. */ - public abstract Stream<AbstractFeature> getFeatures() throws DataStoreException; + public abstract Stream<AbstractFeature> features() throws DataStoreException; } Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -497,8 +497,10 @@ public final class Store extends Feature } catch (TransformException e) { throw new DataStoreReferencingException(getLocale(), "CSV", getDisplayName(), source).initCause(e); } catch (UnsupportedOperationException e) { - // Failed to set the temporal components if the sis-temporal module was - // not on the classpath, but the other dimensions still have been set. + /* + * Failed to set the temporal components if the sis-temporal module was + * not on the classpath, but the other dimensions still have been set. + */ listeners.warning(null, e); } builder.add(featureType, null); @@ -540,12 +542,12 @@ public final class Store extends Feature * @todo Needs to reset the position when doing another pass on the features. */ @Override - public Stream<AbstractFeature> getFeatures() { + public Stream<AbstractFeature> features() { return StreamSupport.stream(new Iter(), false); } /** - * Implementation of the iterator returned by {@link #getFeatures()}. + * Implementation of the iterator returned by {@link #features()}. */ private final class Iter implements Spliterator<AbstractFeature> { /** @@ -699,11 +701,17 @@ public final class Store extends Feature } /** - * Guarantees that we will not return null element. + * Returns the characteristics of the iteration over feature instances. + * The iteration is assumed {@link #ORDERED} in the declaration order in the CSV file. + * The iteration is {@link #NONNULL} (i.e. {@link #tryAdvance(Consumer)} is not allowed + * to return null value) and {@link #IMMUTABLE} (i.e. we do not support modification of + * the CSV file while an iteration is in progress). + * + * @return characteristics of iteration over the features in the CSV file. */ @Override public int characteristics() { - return NONNULL; + return ORDERED | NONNULL | IMMUTABLE; } } Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -20,6 +20,8 @@ import org.opengis.metadata.distribution import org.apache.sis.internal.simple.SimpleFormat; import org.apache.sis.metadata.iso.citation.DefaultCitation; import org.apache.sis.metadata.iso.distribution.DefaultFormat; +import org.apache.sis.measure.Range; +import org.apache.sis.util.Version; /** @@ -117,6 +119,17 @@ public abstract class DataStoreProvider } /** + * Returns the range of versions supported by the data store, or {@code null} if unspecified. + * + * @return the range of supported versions, or {@code null} if unspecified. + * + * @since 0.8 + */ + public Range<Version> getSupportedVersions() { + return null; + } + + /** * Indicates if the given storage appears to be supported by the {@code DataStore}s created by this provider. * The most typical return values are: * Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreRegistry.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreRegistry.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreRegistry.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreRegistry.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -212,18 +212,18 @@ final class DataStoreRegistry { */ if (deferred != null) { search: while (!deferred.isEmpty() && connector.prefetch()) { - for (final Iterator<ProbeProviderPair> it=deferred.iterator(); it.hasNext();) { + for (final Iterator<ProbeProviderPair> it = deferred.iterator(); it.hasNext();) { final ProbeProviderPair p = it.next(); - p.probe = provider.probeContent(connector); + p.probe = p.provider.probeContent(connector); if (p.probe.isSupported()) { selected = p; break search; } if (!ProbeResult.INSUFFICIENT_BYTES.equals(p.probe)) { if (ProbeResult.UNDETERMINED.equals(p.probe)) { - selected = p; // To be used only if we don't find a better match. + selected = p; // To be used only if we don't find a better match. } - it.remove(); // UNSUPPORTED_* or UNDETERMINED: do not try again those providers. + it.remove(); // UNSUPPORTED_* or UNDETERMINED: do not try again those providers. } } } @@ -237,7 +237,7 @@ search: while (!deferred.isEmpty */ if (open && selected != null) { selected.store = selected.provider.open(connector); - connector = null; // For preventing it to be closed. + connector = null; // For preventing it to be closed. } } finally { if (connector != null && connector != storage) { Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStores.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStores.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStores.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStores.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -80,7 +80,7 @@ public final class DataStores extends St /** * Returns the list of data store providers available at this method invocation time. - * More providers may be added later if new modules are added on the classpath. + * More providers may be added later in a running JVM if new modules are added on the classpath. * * @return descriptions of available data stores. * Modified: sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/csv/StoreTest.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/csv/StoreTest.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/csv/StoreTest.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/csv/StoreTest.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -91,7 +91,7 @@ public final strictfp class StoreTest ex } /** - * Verifies the feature type, then tests {@link Store#getFeatures()}. + * Verifies the feature type, then tests {@link Store#features()}. * * @throws DataStoreException if an error occurred while parsing the data. */ @@ -100,7 +100,7 @@ public final strictfp class StoreTest ex try (Store store = new Store(null, new StorageConnector(testData()))) { verifyFeatureType(store.featureType); assertEquals("foliation", Foliation.TIME, store.foliation); - final Iterator<AbstractFeature> it = store.getFeatures().iterator(); + final Iterator<AbstractFeature> it = store.features().iterator(); assertPropertyEquals(it.next(), "a", "12:33:51", "12:36:11", new double[] {11, 2, 12, 3}, "walking", 1); assertPropertyEquals(it.next(), "b", "12:33:51", "12:36:51", new double[] {10, 2, 11, 3}, "walking", 2); assertPropertyEquals(it.next(), "a", "12:36:11", "12:36:51", new double[] {12, 3, 10, 3}, "walking", 2); Modified: sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Metadata.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Metadata.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Metadata.java [UTF-8] (original) +++ sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Metadata.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -38,6 +38,7 @@ import org.opengis.metadata.identificati import org.opengis.metadata.identification.Identification; import org.opengis.metadata.content.ContentInformation; import org.opengis.metadata.distribution.Format; +import org.opengis.referencing.ReferenceSystem; import org.opengis.util.InternationalString; import org.apache.sis.io.TableAppender; @@ -46,6 +47,7 @@ import org.apache.sis.internal.util.Unmo import org.apache.sis.metadata.iso.citation.DefaultCitationDate; import org.apache.sis.metadata.iso.identification.DefaultKeywords; import org.apache.sis.metadata.iso.extent.Extents; +import org.apache.sis.referencing.CommonCRS; import org.apache.sis.util.iso.SimpleInternationalString; import org.apache.sis.util.iso.Types; @@ -354,6 +356,17 @@ public final class Metadata extends Simp } /** + * Description of the spatial and temporal reference systems used in the dataset. + * This is fixed to WGS 84 in GPX files. We use (latitude, longitude) axis order. + * + * @return WGS 84 (EPSG:4326). + */ + @Override + public Collection<ReferenceSystem> getReferenceSystemInfo() { + return Collections.<ReferenceSystem>singletonList(CommonCRS.WGS84.geographic()); + } + + /** * ISO 19115 metadata property determined by the {@link #time} field. * This is part of the information returned by {@link #getCitation()}. * Modified: sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Reader.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Reader.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Reader.java [UTF-8] (original) +++ sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Reader.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -168,16 +168,16 @@ final class Reader extends StaxStreamRea Version version = null; if (ver != null) { version = new Version(ver); - if (version.compareTo(Store.V1_0, 2) < 0 || - version.compareTo(Store.V1_1, 2) > 0) + if (version.compareTo(StoreProvider.V1_0, 2) < 0 || + version.compareTo(StoreProvider.V1_1, 2) > 0) { throw new DataStoreContentException(errors().getString( Errors.Keys.UnsupportedFormatVersion_2, owner.getFormatName(), version)); } } else if (namespace != null) { switch (namespace) { - case Tags.NAMESPACE_V10: version = Store.V1_0; break; - case Tags.NAMESPACE_V11: version = Store.V1_1; break; + case Tags.NAMESPACE_V10: version = StoreProvider.V1_0; break; + case Tags.NAMESPACE_V11: version = StoreProvider.V1_1; break; } } /* Modified: sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Store.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Store.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Store.java [UTF-8] (original) +++ sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Store.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -51,16 +51,6 @@ import org.apache.sis.feature.DefaultFea */ public final class Store extends StaxDataStore { /** - * The "1.0" version. - */ - static final Version V1_0 = new Version("1.0"); - - /** - * The "1.1" version. - */ - static final Version V1_1 = new Version("1.1"); - - /** * Version of the GPX file, or {@code null} if unknown. */ Version version; @@ -150,9 +140,9 @@ public final class Store extends StaxDat @Override public synchronized Metadata getMetadata() throws DataStoreException { if (metadata == null) try { - reader = new Reader(this); - version = reader.initialize(true); - metadata = reader.getMetadata(); + reader = new Reader(this); + version = reader.initialize(true); + metadata = reader.getMetadata(); } catch (DataStoreException e) { throw e; } catch (URISyntaxException | RuntimeException e) { @@ -179,11 +169,11 @@ public final class Store extends StaxDat /** * Returns the stream of features. * - * @return a stream over all features in the CSV file. + * @return a stream over all features in the XML file. * @throws DataStoreException if an error occurred while creating the feature stream. */ @Override - public synchronized Stream<AbstractFeature> getFeatures() throws DataStoreException { + public synchronized Stream<AbstractFeature> features() throws DataStoreException { Reader r = reader; reader = null; if (r == null) try { Modified: sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/StoreProvider.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/StoreProvider.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/StoreProvider.java [UTF-8] (original) +++ sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/StoreProvider.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -24,6 +24,8 @@ import org.apache.sis.storage.StorageCon import org.apache.sis.internal.storage.Capability; import org.apache.sis.internal.storage.Capabilities; import org.apache.sis.internal.storage.xml.stream.StaxDataStoreProvider; +import org.apache.sis.measure.Range; +import org.apache.sis.util.Version; /** @@ -39,6 +41,21 @@ import org.apache.sis.internal.storage.x @Capabilities({Capability.READ, Capability.WRITE}) public final class StoreProvider extends StaxDataStoreProvider { /** + * The "1.0" version. + */ + static final Version V1_0 = Version.valueOf(1,0); + + /** + * The "1.1" version. + */ + static final Version V1_1 = Version.valueOf(1,1); + + /** + * The range of versions returned by {@link #getSupportedVersions()}. + */ + private static final Range<Version> VERSIONS = new Range<>(Version.class, V1_0, true, V1_1, true); + + /** * Creates a new GPX store provider. */ public StoreProvider() { @@ -48,6 +65,16 @@ public final class StoreProvider extends } /** + * Returns the range of versions supported by the GPX data store. + * + * @return the range of supported versions. + */ + @Override + public Range<Version> getSupportedVersions() { + return VERSIONS; + } + + /** * Returns a GPX {@link Store} implementation associated with this provider. * * @param connector information about the storage (URL, stream, <i>etc</i>). Modified: sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Writer.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Writer.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Writer.java [UTF-8] (original) +++ sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Writer.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -67,7 +67,7 @@ final class Writer extends StaxStreamWri super(owner); this.metadata = metadata; final Version ver = owner.version; - if (ver != null && ver.compareTo(Store.V1_0, 2) <= 0) { + if (ver != null && ver.compareTo(StoreProvider.V1_0, 2) <= 0) { version = 0; } else { version = 1; @@ -86,8 +86,8 @@ final class Writer extends StaxStreamWri final Version ver; switch (version) { default: - case 1: ver = Store.V1_1; namespace = Tags.NAMESPACE_V11; break; - case 0: ver = Store.V1_0; namespace = Tags.NAMESPACE_V10; break; + case 1: ver = StoreProvider.V1_1; namespace = Tags.NAMESPACE_V11; break; + case 0: ver = StoreProvider.V1_0; namespace = Tags.NAMESPACE_V10; break; } super.writeStartDocument(); writer.setDefaultNamespace(namespace); Modified: sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java [UTF-8] (original) +++ sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -43,12 +43,16 @@ import org.apache.sis.internal.storage.i import org.apache.sis.internal.storage.io.IOUtilities; import org.apache.sis.internal.storage.io.Markable; import org.apache.sis.internal.util.AbstractMap; +import org.apache.sis.internal.util.Constants; +import org.apache.sis.internal.util.Utilities; +import org.apache.sis.io.wkt.WKTFormat; import org.apache.sis.storage.ConcurrentReadException; import org.apache.sis.storage.ConcurrentWriteException; import org.apache.sis.storage.DataStoreClosedException; import org.apache.sis.storage.ForwardOnlyStorageException; import org.apache.sis.storage.UnsupportedStorageException; import org.apache.sis.util.logging.WarningListener; +import org.apache.sis.util.Debug; /** @@ -171,6 +175,12 @@ public abstract class StaxDataStore exte private final ChannelFactory channelFactory; /** + * The number of spaces to use in indentations, or -1 if the XML output should not be formatted. + * This is ignored at reading time. + */ + private final byte indentation; + + /** * Whether the {@linkplain #stream} is currently in use by a {@link StaxStreamIO}. Value can be * one of {@link #START}, {@link #READING}, {@link #WRITING} or {@link #FINISHED} constants. */ @@ -191,10 +201,14 @@ public abstract class StaxDataStore exte */ protected StaxDataStore(final StaxDataStoreProvider provider, final StorageConnector connector) throws DataStoreException { super(provider, connector); + final Integer indent; storage = connector.getStorage(); locale = connector.getOption(OptionKey.LOCALE); timezone = connector.getOption(OptionKey.TIMEZONE); encoding = connector.getOption(OptionKey.ENCODING); + indent = connector.getOption(OptionKey.INDENTATION); + indentation = (indent == null) ? Constants.DEFAULT_INDENTATION + : (byte) Math.max(WKTFormat.SINGLE_LINE, Math.min(120, indent)); configuration = new Config(); storageToWriter = OutputType.forType(storage.getClass()); storageToReader = InputType.forType(storage.getClass()); @@ -341,6 +355,15 @@ public abstract class StaxDataStore exte public final Class<Object> getSourceClass() { return Object.class; } + + /** + * Do not format all properties for avoiding a never-ending loop. + */ + @Debug + @Override + public String toString() { + return Utilities.toString(getClass(), "locale", locale, "timezone", timezone); + } } /** @@ -544,7 +567,10 @@ public abstract class StaxDataStore exte mark(); } } - final XMLStreamWriter writer = type.create(this, outputOrFile); + XMLStreamWriter writer = type.create(this, outputOrFile); + if (indentation >= 0) { + writer = new FormattedWriter(writer, indentation); + } target.stream = output; state = WRITING; return writer; Modified: sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxStreamWriter.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxStreamWriter.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxStreamWriter.java [UTF-8] (original) +++ sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxStreamWriter.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -145,7 +145,7 @@ public abstract class StaxStreamWriter e public void writeStartDocument() throws Exception { final Charset encoding = owner.encoding; if (encoding != null) { - writer.writeStartDocument(encoding.name()); + writer.writeStartDocument(encoding.name(), null); } else { writer.writeStartDocument(); } @@ -294,6 +294,11 @@ public abstract class StaxStreamWriter e if (m == null) { m = getMarshallerPool().acquireMarshaller(); m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); + m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.FALSE); // Formatting will be done by FormattedWriter. + final Charset encoding = owner.encoding; + if (encoding != null) { + m.setProperty(Marshaller.JAXB_ENCODING, encoding.name()); + } for (final Map.Entry<String,?> entry : ((Map<String,?>) owner.configuration).entrySet()) { m.setProperty(entry.getKey(), entry.getValue()); } @@ -308,7 +313,7 @@ public abstract class StaxStreamWriter e } marshaller = null; m.marshal(new JAXBElement<>(qn, type, object), out); - marshaller = m; // Allow reuse or recycling only on success. + marshaller = m; // Allow reuse or recycling only on success. } /** Modified: sis/trunk/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/storage/gpx/ReaderTest.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/storage/gpx/ReaderTest.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/storage/gpx/ReaderTest.java [UTF-8] (original) +++ sis/trunk/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/storage/gpx/ReaderTest.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -139,7 +139,7 @@ public final strictfp class ReaderTest e verifyMetadata(md, 1); assertNull(md.author.link); assertNull(md.copyright); - assertEquals("version", Store.V1_0, reader.getVersion()); + assertEquals("version", StoreProvider.V1_0, reader.getVersion()); } } @@ -157,7 +157,7 @@ public final strictfp class ReaderTest e assertEquals("Apache", md.copyright.author); assertEquals(2004, md.copyright.year.intValue()); assertStringEquals("http://www.apache.org/licenses/LICENSE-2.0", md.copyright.license); - assertEquals("version", Store.V1_1, reader.getVersion()); + assertEquals("version", StoreProvider.V1_1, reader.getVersion()); } } @@ -222,8 +222,8 @@ public final strictfp class ReaderTest e public void testWayPoint100() throws DataStoreException { try (final Store reader = create("1.0/waypoint.xml")) { verifyAlmostEmptyMetadata((Metadata) reader.getMetadata()); - assertEquals("version", Store.V1_0, reader.getVersion()); - try (final Stream<AbstractFeature> features = reader.getFeatures()) { + assertEquals("version", StoreProvider.V1_0, reader.getVersion()); + try (final Stream<AbstractFeature> features = reader.features()) { final Iterator<AbstractFeature> it = features.iterator(); verifyPoint(it.next(), 0, false); verifyPoint(it.next(), 1, false); @@ -243,8 +243,8 @@ public final strictfp class ReaderTest e public void testWayPoint110() throws DataStoreException { try (final Store reader = create("1.1/waypoint.xml")) { verifyAlmostEmptyMetadata((Metadata) reader.getMetadata()); - assertEquals("version", Store.V1_1, reader.getVersion()); - try (final Stream<AbstractFeature> features = reader.getFeatures()) { + assertEquals("version", StoreProvider.V1_1, reader.getVersion()); + try (final Stream<AbstractFeature> features = reader.features()) { final Iterator<AbstractFeature> it = features.iterator(); verifyPoint(it.next(), 0, true); verifyPoint(it.next(), 1, true); @@ -264,8 +264,8 @@ public final strictfp class ReaderTest e public void testRoute100() throws DataStoreException { try (final Store reader = create("1.0/route.xml")) { verifyAlmostEmptyMetadata((Metadata) reader.getMetadata()); - assertEquals("version", Store.V1_0, reader.getVersion()); - try (final Stream<AbstractFeature> features = reader.getFeatures()) { + assertEquals("version", StoreProvider.V1_0, reader.getVersion()); + try (final Stream<AbstractFeature> features = reader.features()) { final Iterator<AbstractFeature> it = features.iterator(); verifyRoute(it.next(), false, 1); verifyEmpty(it.next(), "rtept"); @@ -284,7 +284,7 @@ public final strictfp class ReaderTest e public void testRoute110() throws DataStoreException { try (final Store reader = create("1.1/route.xml")) { verifyAlmostEmptyMetadata((Metadata) reader.getMetadata()); - assertEquals("version", Store.V1_1, reader.getVersion()); + assertEquals("version", StoreProvider.V1_1, reader.getVersion()); verifyRoute110(reader); } } @@ -294,7 +294,7 @@ public final strictfp class ReaderTest e * This verification is shared by {@link #testRoute110()} and {@link #testSequentialReads()}. */ static void verifyRoute110(final Store reader) throws DataStoreException { - try (final Stream<AbstractFeature> features = reader.getFeatures()) { + try (final Stream<AbstractFeature> features = reader.features()) { final Iterator<AbstractFeature> it = features.iterator(); verifyRoute(it.next(), true, 3); verifyEmpty(it.next(), "rtept"); @@ -371,8 +371,8 @@ public final strictfp class ReaderTest e public void testTrack100() throws DataStoreException { try (final Store reader = create("1.0/track.xml")) { verifyAlmostEmptyMetadata((Metadata) reader.getMetadata()); - assertEquals("version", Store.V1_0, reader.getVersion()); - try (final Stream<AbstractFeature> features = reader.getFeatures()) { + assertEquals("version", StoreProvider.V1_0, reader.getVersion()); + try (final Stream<AbstractFeature> features = reader.features()) { final Iterator<AbstractFeature> it = features.iterator(); verifyTrack(it.next(), false, 1); verifyEmpty(it.next(), "trkseg"); @@ -391,8 +391,8 @@ public final strictfp class ReaderTest e public void testTrack110() throws DataStoreException { try (final Store reader = create("1.1/track.xml")) { verifyAlmostEmptyMetadata((Metadata) reader.getMetadata()); - assertEquals("version", Store.V1_1, reader.getVersion()); - try (final Stream<AbstractFeature> features = reader.getFeatures()) { + assertEquals("version", StoreProvider.V1_1, reader.getVersion()); + try (final Stream<AbstractFeature> features = reader.features()) { final Iterator<AbstractFeature> it = features.iterator(); verifyTrack(it.next(), true, 3); verifyEmpty(it.next(), "trkseg"); @@ -583,8 +583,8 @@ public final strictfp class ReaderTest e verifyRoute110(reader); /* * Ask for metadata only after a first read, for testing the way the store manages readers. - * The new 'getFeatures()' call should reuse the reader created by 'getMetadata()' - this - * can be verified by stepping in the code with a debugger. + * The new 'features()' call should reuse the reader created by 'getMetadata()' - this can + * be verified by stepping in the code with a debugger. */ md = (Metadata) reader.getMetadata(); verifyRoute110(reader); @@ -607,13 +607,13 @@ public final strictfp class ReaderTest e @DependsOnMethod("testSequentialReads") public void testConcurrentReads() throws DataStoreException { try (final Store reader = createFromURL()) { - final Stream<AbstractFeature> f1 = reader.getFeatures(); + final Stream<AbstractFeature> f1 = reader.features(); final Iterator<AbstractFeature> i1 = f1.iterator(); verifyRoute(i1.next(), true, 3); - final Stream<AbstractFeature> f2 = reader.getFeatures(); + final Stream<AbstractFeature> f2 = reader.features(); final Iterator<AbstractFeature> i2 = f2.iterator(); verifyEmpty(i1.next(), "rtept"); - final Stream<AbstractFeature> f3 = reader.getFeatures(); + final Stream<AbstractFeature> f3 = reader.features(); final Iterator<AbstractFeature> i3 = f3.iterator(); verifyRoute(i2.next(), true, 3); verifyRoute(i3.next(), true, 3); Modified: sis/trunk/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/storage/gpx/WriterTest.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/storage/gpx/WriterTest.java?rev=1781503&r1=1781502&r2=1781503&view=diff ============================================================================== --- sis/trunk/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/storage/gpx/WriterTest.java [UTF-8] (original) +++ sis/trunk/storage/sis-xmlstore/src/test/java/org/apache/sis/internal/storage/gpx/WriterTest.java [UTF-8] Fri Feb 3 08:01:02 2017 @@ -113,7 +113,7 @@ public final strictfp class WriterTest e */ @Test public void testMetadata100() throws Exception { - testMetadata(Store.V1_0, "1.0/metadata.xml"); + testMetadata(StoreProvider.V1_0, "1.0/metadata.xml"); } /** @@ -124,7 +124,7 @@ public final strictfp class WriterTest e */ @Test public void testMetadata110() throws Exception { - testMetadata(Store.V1_1, "1.1/metadata.xml"); + testMetadata(StoreProvider.V1_1, "1.1/metadata.xml"); } /** @@ -153,7 +153,7 @@ public final strictfp class WriterTest e @Test @DependsOnMethod("testMetadata100") public void testWayPoints100() throws Exception { - testFeatures(Store.V1_0, Type.WAY_POINT, "1.0/waypoint.xml"); + testFeatures(StoreProvider.V1_0, Type.WAY_POINT, "1.0/waypoint.xml"); } /** @@ -165,7 +165,7 @@ public final strictfp class WriterTest e @Test @DependsOnMethod("testMetadata110") public void testWayPoints110() throws Exception { - testFeatures(Store.V1_1, Type.WAY_POINT, "1.1/waypoint.xml"); + testFeatures(StoreProvider.V1_1, Type.WAY_POINT, "1.1/waypoint.xml"); } /** @@ -177,7 +177,7 @@ public final strictfp class WriterTest e @Test @DependsOnMethod("testWayPoints100") public void testRoutes100() throws Exception { - testFeatures(Store.V1_0, Type.ROUTE, "1.0/route.xml"); + testFeatures(StoreProvider.V1_0, Type.ROUTE, "1.0/route.xml"); } /** @@ -189,7 +189,7 @@ public final strictfp class WriterTest e @Test @DependsOnMethod("testWayPoints110") public void testRoutes110() throws Exception { - testFeatures(Store.V1_1, Type.ROUTE, "1.1/route.xml"); + testFeatures(StoreProvider.V1_1, Type.ROUTE, "1.1/route.xml"); } /** @@ -201,7 +201,7 @@ public final strictfp class WriterTest e @Test @DependsOnMethod("testRoutes100") public void testTracks100() throws Exception { - testFeatures(Store.V1_0, Type.TRACK, "1.0/track.xml"); + testFeatures(StoreProvider.V1_0, Type.TRACK, "1.0/track.xml"); } /** @@ -213,7 +213,7 @@ public final strictfp class WriterTest e @Test @DependsOnMethod("testRoutes110") public void testTracks110() throws Exception { - testFeatures(Store.V1_1, Type.TRACK, "1.1/track.xml"); + testFeatures(StoreProvider.V1_1, Type.TRACK, "1.1/track.xml"); } /** @@ -373,7 +373,7 @@ public final strictfp class WriterTest e * but the main purpose of following code is to advance in the stream. */ ReaderTest.verifyMetadata((Metadata) store.getMetadata(), 3); - assertEquals("version", Store.V1_1, store.getVersion()); + assertEquals("version", StoreProvider.V1_1, store.getVersion()); /* * Replace the metadata content by route content. The data store should rewind * to the begining of the file and replace the input stream by an output stream.
