Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties [ISO-8859-1] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties [ISO-8859-1] Sat Feb 24 15:44:08 2018 @@ -25,29 +25,43 @@ # U+00A0 NO-BREAK SPACE before : # AmbiguousName_4 = Le nom \u00ab\u202f{3}\u202f\u00bb est ambigu\u00eb car il peut \u00eatre interpr\u00e9t\u00e9 aussi bien comme \u00ab\u202f{1}\u202f\u00bb ou \u00ab\u202f{2}\u202f\u00bb dans le contexte des donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb. +CanNotCreateFolderStore_1 = Ne peut pas cr\u00e9er des ressources bas\u00e9es sur le contenu du r\u00e9pertoire \u00ab\u202f{0}\u202f\u00bb. +CanNotGetCommonMetadata_2 = Ne peut pas obtenir les m\u00e9ta-donn\u00e9es communes aux fichiers \u00ab\u202f{0}\u202f\u00bb. La raison est\u2008: {1} CanNotReadCRS_WKT_1 = Ne peut pas lire le syst\u00e8me de r\u00e9f\u00e9rence spatial dans le \u00ab\u202fWell Known Text\u202f\u00bb (WKT) de \u00ab\u202f{0}\u202f\u00bb. CanNotReadDirectory_1 = Ne peut pas lire le r\u00e9pertoire \u00ab\u202f{0}\u202f\u00bb. CanNotReadFile_2 = Ne peut pas lire \u00ab\u202f{1}\u202f\u00bb comme un fichier au format {0}. CanNotReadFile_3 = Ne peut pas lire la ligne {2} de \u00ab\u202f{1}\u202f\u00bb comme une partie d\u2019un fichier au format {0}. CanNotReadFile_4 = Ne peut pas lire la ligne {2} (apr\u00e8s la colonne {3}) de \u00ab\u202f{1}\u202f\u00bb comme une partie d\u2019un fichier au format {0}. +CanNotRemoveResource_2 = Ne peut pas supprimer la ressource \u00ab\u202f{1}\u202f\u00bb de l\u2019agr\u00e9gat \u00ab\u202f{0}\u202f\u00bb. +CanNotStoreResourceType_2 = Ne peut pas enregistrer des ressources de type \u2018{1}\u2019 dans un entrep\u00f4t de donn\u00e9es \u00ab\u202f{0}\u202f\u00bb. ClosedReader_1 = Ce lecteur {0} est ferm\u00e9. ClosedWriter_1 = Cet encodeur {0} est ferm\u00e9. ConcurrentRead_1 = Une ou plusieurs op\u00e9rations de lecture sont en cours sur les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb. ConcurrentWrite_1 = Une op\u00e9ration d\u2019\u00e9criture est en cours sur les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb. +DataStoreCreate = Indique si l\u2019on autorise la cr\u00e9ation d\u2019une nouvelle source de donn\u00e9es si la source \u00e0 ouvrir n\u2019existe pas d\u00e9j\u00e0. DataStoreEncoding = Encodage des caract\u00e8res utilis\u00e9 par la source de donn\u00e9es. DataStoreLocale = Conventions d\u2019\u00e9criture des dates et des nombres. DataStoreLocation = Chemin (fichier ou URL) vers la source de donn\u00e9es. DataStoreTimeZone = Fuseau horaire des dates dans les donn\u00e9es. DirectoryContent_1 = Contenu du r\u00e9pertoire \u00ab\u202f{0}\u202f\u00bb. +DirectoryContentFormatName = Nom du format ou de la source de donn\u00e9es \u00e0 utiliser pour lire ou \u00e9crire le contenu du r\u00e9pertoire. ExcessiveStringSize_3 = La cha\u00eene de caract\u00e8res dans le fichier \u00ab\u202f{0}\u202f\u00bb est trop longue. La cha\u00eene fait {2} caract\u00e8res alors que la limite est {1}. FeatureAlreadyPresent_2 = Une entit\u00e9 nomm\u00e9e \u00ab\u202f{1}\u202f\u00bb est d\u00e9j\u00e0 pr\u00e9sente dans les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb. -FeatureNotFound_2 = L\u2019entit\u00e9 \u00ab\u202f{1}\u202f\u00bb n\u2019est pas \u00e9t\u00e9 trouv\u00e9e dans les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb. +FeatureNotFound_2 = L\u2019entit\u00e9 \u00ab\u202f{1}\u202f\u00bb n\u2019a pas \u00e9t\u00e9 trouv\u00e9e dans les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb. +FileAlreadyExists_2 = Un {1,choice,0#fichier|1#r\u00e9pertoire} existe d\u00e9j\u00e0 \u00e0 l\u2019emplacement \u00ab\u202f{0}\u202f\u00bb. +FileIsNotAResourceDirectory_1 = Le fichier \u00ab\u202f{0}\u202f\u00bb n\u2019est pas un r\u00e9pertoire de ressources. +FoliationRepresentation = Indique s\u2019il faut assembler les fragments de trajectoires (lignes dans un fichier CSV) dans une entit\u00e9 unique. IllegalFeatureType_2 = Le format {0} ne stocke pas de donn\u00e9es de type \u00ab\u202f{1}\u202f\u00bb. IllegalInputTypeForReader_2 = Le lecteur {0} n\u2019accepte pas des entr\u00e9s de type \u2018{1}\u2019. -IllegalOutputTypeForWriter_2 = Le l\u2019encodeur {0} n\u2019accepte pas des sorties de type \u2018{1}\u2019. +IllegalOutputTypeForWriter_2 = L\u2019encodeur {0} n\u2019accepte pas des sorties de type \u2018{1}\u2019. InconsistentNameComponents_2 = Les \u00e9l\u00e9ments qui composent le nom \u00ab\u202f{1}\u202f\u00bb ne sont pas coh\u00e9rents avec ceux du nom qui avait \u00e9t\u00e9 pr\u00e9c\u00e9demment li\u00e9 dans les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb. +MissingResourceIdentifier_1 = La ressource \u00ab\u202f{0}\u202f\u00bb n\u2019a pas d\u2019identifiant. MissingSchemeInURI_1 = Il manque le sch\u00e9ma dans l\u2019URI \u00ab\u202f{0}\u202f\u00bb. +NoSuchResourceDirectory_1 = Aucun r\u00e9pertoire de ressources n\u2019a \u00e9t\u00e9 trouv\u00e9 \u00e0 l\u2019emplacement \u00ab\u202f{0}\u202f\u00bb. +NoSuchResourceInAggregate_2 = La ressource \u00ab\u202f{1}\u202f\u00bb n\u2019est pas une partie de l\u2019agr\u00e9gat \u00ab\u202f{0}\u202f\u00bb. +NotAWritableFeatureSet_1 = La ressource \u00ab\u202f{0}\u202f\u00bb n\u2019est pas un ensemble d\u2019entit\u00e9s accessibles en \u00e9criture. ProcessingExecutedOn_1 = Traitement ex\u00e9cut\u00e9 sur {0}. +ResourceAlreadyExists_1 = Une ressource existe d\u00e9j\u00e0 \u00e0 l\u2019emplacement \u00ab\u202f{0}\u202f\u00bb. ResourceIdentifierCollision_2 = Plusieurs ressources utilisent l\u2019identifiant \u00ab\u202f{1}\u202f\u00bb dans les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb. ResourceNotFound_2 = Aucune ressource n\u2019a \u00e9t\u00e9 trouv\u00e9e pour l\u2019identifiant \u00ab\u202f{1}\u202f\u00bb dans les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb. ShallBeDeclaredBefore_2 = L\u2019\u00e9l\u00e9ment \u00ab\u202f{1}\u202f\u00bb doit \u00eatre d\u00e9clar\u00e9 avant \u00ab\u202f{0}\u202f\u00bb.
Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -17,14 +17,17 @@ package org.apache.sis.internal.storage; import java.net.URI; +import java.nio.charset.Charset; +import org.opengis.parameter.ParameterValueGroup; import org.opengis.parameter.ParameterDescriptor; import org.opengis.parameter.ParameterDescriptorGroup; -import org.opengis.parameter.ParameterValueGroup; +import org.opengis.parameter.ParameterNotFoundException; import org.apache.sis.parameter.ParameterBuilder; +import org.apache.sis.storage.StorageConnector; import org.apache.sis.storage.DataStore; import org.apache.sis.storage.DataStoreProvider; import org.apache.sis.storage.DataStoreException; -import org.apache.sis.storage.StorageConnector; +import org.apache.sis.storage.IllegalOpenParameterException; import org.apache.sis.internal.storage.io.IOUtilities; @@ -35,7 +38,7 @@ import org.apache.sis.internal.storage.i * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.8 * @module */ @@ -69,12 +72,12 @@ public abstract class URIDataStore exten /** * Creates parameter value group for the current location, if non-null. - * This convenience method is used for public {@code DataStore} implementations that can not extend - * {@code URIDataStore} directly, because this class is internal. + * This convenience method is used for {@link DataStore#getOpenParameters()} implementations in public + * {@code DataStore} that can not extend {@code URIDataStore} directly, because this class is internal. * - * @param provider - * @param location - * @return + * @param provider the provider of the data store for which to get open parameters. + * @param location file opened by the data store. + * @return parameters to be returned by {@link DataStore#getOpenParameters()}. * * @todo Verify if non-exported classes in JDK9 are hidden from Javadoc, like package-private classes. * If true, we could remove this hack and extend {@code URIDataStore} even in public classes. @@ -91,19 +94,35 @@ public abstract class URIDataStore exten * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.8 * @module */ public abstract static class Provider extends DataStoreProvider { /** - * Description of the location parameter. + * Description of the {@value #LOCATION} parameter. + */ + public static final ParameterDescriptor<URI> LOCATION_PARAM; + + /** + * Description of the optional {@value #CREATE} parameter, which may be present in writable data store. + * This parameter is not included in the descriptor created by {@link #build(ParameterBuilder)} default + * implementation. It is subclass responsibility to add it if desired, only if supported. + */ + public static final ParameterDescriptor<Boolean> CREATE_PARAM; + + /** + * Description of the optional parameter for character encoding used by the data store. + * This parameter is not included in the descriptor created by {@link #build(ParameterBuilder)} + * default implementation. It is subclass responsibility to add it if desired. */ - public static final ParameterDescriptor<URI> LOCATION_PARAM = new ParameterBuilder() - .setDescription(Resources.formatInternational(Resources.Keys.DataStoreLocation)) - .addName(LOCATION) - .setRequired(true) - .create(URI.class, null); + public static final ParameterDescriptor<Charset> ENCODING; + static { + final ParameterBuilder builder = new ParameterBuilder(); + ENCODING = builder.addName("encoding").setDescription(Resources.formatInternational(Resources.Keys.DataStoreEncoding)).create(Charset.class, null); + CREATE_PARAM = builder.addName( CREATE ).setDescription(Resources.formatInternational(Resources.Keys.DataStoreCreate )).create(Boolean.class, null); + LOCATION_PARAM = builder.addName( LOCATION ).setDescription(Resources.formatInternational(Resources.Keys.DataStoreLocation)).setRequired(true).create(URI.class, null); + } /** * The parameter descriptor to be returned by {@link #getOpenParameters()}. @@ -161,12 +180,39 @@ public abstract class URIDataStore exten public static ParameterDescriptorGroup descriptor(final String name) { return new ParameterBuilder().addName(name).createGroup(LOCATION_PARAM); } + + /** + * Creates a storage connector initialized to the location declared in given parameters. + * This convenience method does not set any other parameters. + * In particular, reading (or ignoring) the {@value #CREATE} parameter is left to callers, + * because not all implementations may create data stores with {@link java.nio.file.StandardOpenOption}. + * + * @param provider the provider for which to create a storage connector (for error messages). + * @param parameters the parameters to use for creating a storage connector. + * @return the storage connector initialized to the location specified in the parameters. + * @throws IllegalOpenParameterException if no {@value #LOCATION} parameter has been found. + */ + public static StorageConnector connector(final DataStoreProvider provider, final ParameterValueGroup parameters) + throws IllegalOpenParameterException + { + ParameterNotFoundException cause = null; + if (parameters != null) try { + final Object location = parameters.parameter(LOCATION).getValue(); + if (location != null) { + return new StorageConnector(location); + } + } catch (ParameterNotFoundException e) { + cause = e; + } + throw new IllegalOpenParameterException(Resources.format(Resources.Keys.UndefinedParameter_2, + provider.getShortName(), LOCATION), cause); + } } /** * Adds the filename (without extension) as the citation title if there is no title, or as the identifier otherwise. * This method should be invoked last, after {@code DataStore} implementation did its best effort for adding a title. - * The intend is actually to provide an identifier, but since the title is mandatory in ISO 19115 metadata, providing + * The intent is actually to provide an identifier, but since the title is mandatory in ISO 19115 metadata, providing * only an identifier without title would be invalid. * * @param builder where to add the title or identifier. Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/FeatureIterator.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/FeatureIterator.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/FeatureIterator.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/FeatureIterator.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -17,16 +17,16 @@ package org.apache.sis.internal.storage.csv; import java.util.Collection; +import java.util.Spliterator; +import java.util.function.Consumer; import java.util.concurrent.atomic.AtomicInteger; +import java.time.DateTimeException; import java.io.IOException; import org.apache.sis.util.ObjectConverter; import org.apache.sis.util.ObjectConverters; import org.apache.sis.util.collection.BackingStoreException; // Branch-dependent imports -import java.util.Spliterator; -import java.util.function.Consumer; -import java.time.DateTimeException; import org.opengis.feature.Feature; import org.opengis.feature.PropertyType; import org.opengis.feature.AttributeType; @@ -121,7 +121,7 @@ class FeatureIterator implements Spliter /* * If there is no time columns, then this column may be the trajectory (note that allowing * CSV files without time is obviously a departure from Moving Features specification. - * The intend is to have a CSV format applicable to other features than moving ones). + * The intent is to have a CSV format applicable to other features than moving ones). * Fall through in order to process trajectory. */ } Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/MovingFeatureIterator.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/MovingFeatureIterator.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/MovingFeatureIterator.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/MovingFeatureIterator.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -18,14 +18,14 @@ package org.apache.sis.internal.storage. import java.util.Map; import java.util.LinkedHashMap; +import java.util.function.Consumer; import java.util.logging.LogRecord; +import java.time.Instant; +import java.time.DateTimeException; import java.io.IOException; import org.apache.sis.internal.feature.MovingFeature; // Branch-dependent imports -import java.time.Instant; -import java.time.DateTimeException; -import java.util.function.Consumer; import org.opengis.feature.Attribute; import org.opengis.feature.Feature; Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -21,8 +21,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.Locale; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; import java.util.logging.Level; import java.util.logging.LogRecord; +import java.time.Instant; +import java.time.DateTimeException; import java.io.Reader; import java.io.BufferedReader; import java.io.LineNumberReader; @@ -40,6 +44,7 @@ import org.opengis.referencing.crs.Tempo import org.opengis.referencing.operation.TransformException; import org.apache.sis.feature.DefaultAttributeType; import org.apache.sis.feature.DefaultFeatureType; +import org.apache.sis.feature.FoliationRepresentation; import org.apache.sis.referencing.CRS; import org.apache.sis.referencing.CommonCRS; import org.apache.sis.internal.referencing.GeodeticObjectBuilder; @@ -55,6 +60,7 @@ import org.apache.sis.geometry.GeneralEn import org.apache.sis.geometry.ImmutableEnvelope; import org.apache.sis.metadata.iso.DefaultMetadata; import org.apache.sis.metadata.sql.MetadataStoreException; +import org.apache.sis.storage.DataOptionKey; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.DataStoreContentException; import org.apache.sis.storage.DataStoreReferencingException; @@ -69,10 +75,6 @@ import org.apache.sis.io.InvalidSeekExce import org.apache.sis.measure.Units; // Branch-dependent imports -import java.time.Instant; -import java.time.DateTimeException; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; import org.opengis.feature.Feature; import org.opengis.feature.FeatureType; import org.opengis.feature.PropertyType; @@ -84,7 +86,7 @@ import org.opengis.feature.AttributeType * See package javadoc for more information on the syntax. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.7 * @module */ @@ -227,12 +229,9 @@ final class Store extends URIDataStore i * * @param provider the factory that created this {@code DataStore} instance, or {@code null} if unspecified. * @param connector information about the storage (URL, stream, <i>etc</i>). - * @param immediate {@code true} for forcing the creation of a distinct {@code Feature} instance for each line. * @throws DataStoreException if an error occurred while opening the stream. */ - public Store(final StoreProvider provider, final StorageConnector connector, final boolean immediate) - throws DataStoreException - { + public Store(final StoreProvider provider, final StorageConnector connector) throws DataStoreException { super(provider, connector); final Reader r = connector.getStorageAs(Reader.class); connector.closeAllExcept(r); @@ -242,7 +241,7 @@ final class Store extends URIDataStore i } source = (r instanceof BufferedReader) ? (BufferedReader) r : new LineNumberReader(r); geometries = Geometries.implementation(connector.getOption(OptionKey.GEOMETRY_LIBRARY)); - dissociate = immediate; + dissociate = FoliationRepresentation.FRAGMENTED.equals(connector.getOption(DataOptionKey.FOLIATION_REPRESENTATION)); GeneralEnvelope envelope = null; FeatureType featureType = null; Foliation foliation = null; Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -16,14 +16,23 @@ */ package org.apache.sis.internal.storage.csv; +import org.opengis.parameter.ParameterValueGroup; +import org.opengis.parameter.ParameterDescriptor; +import org.opengis.parameter.ParameterDescriptorGroup; +import org.apache.sis.parameter.ParameterBuilder; +import org.apache.sis.parameter.Parameters; import org.apache.sis.storage.DataStore; import org.apache.sis.storage.DataStoreException; +import org.apache.sis.storage.DataOptionKey; import org.apache.sis.storage.ProbeResult; import org.apache.sis.storage.StorageConnector; +import org.apache.sis.feature.FoliationRepresentation; +import org.apache.sis.internal.storage.Resources; import org.apache.sis.internal.storage.Capability; -import org.apache.sis.internal.storage.Capabilities; +import org.apache.sis.internal.storage.StoreMetadata; import org.apache.sis.internal.storage.URIDataStore; import org.apache.sis.internal.storage.wkt.FirstKeywordPeek; +import org.apache.sis.util.ArgumentChecks; /** @@ -35,11 +44,13 @@ import org.apache.sis.internal.storage.w * the part of the caller. However the {@link Store} instances created by this factory are not thread-safe. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.8 * @module */ -@Capabilities(Capability.READ) +@StoreMetadata(formatName = StoreProvider.NAME, + fileSuffixes = "csv", + capabilities = Capability.READ) public final class StoreProvider extends URIDataStore.Provider { /** * The format names for static features and moving features. @@ -101,6 +112,19 @@ public final class StoreProvider extends } /** + * Description of the optional parameter for specifying whether the reader should assemble distinct CSV lines + * into a single {@code Feature} instance forming a foliation. This is ignored if the CSV file does not seem + * to contain moving features. + */ + private static final ParameterDescriptor<FoliationRepresentation> FOLIATION; + static { + final ParameterBuilder builder = new ParameterBuilder(); + FOLIATION = builder.addName("foliation") + .setDescription(Resources.formatInternational(Resources.Keys.FoliationRepresentation)) + .create(FoliationRepresentation.class, FoliationRepresentation.ASSEMBLED); + } + + /** * Creates a new provider. */ public StoreProvider() { @@ -138,6 +162,32 @@ public final class StoreProvider extends */ @Override public DataStore open(final StorageConnector connector) throws DataStoreException { - return new Store(this, connector, false); + return new Store(this, connector); + } + + /** + * Returns a CSV {@link Store} implementation from the given parameters. + * + * @return a data store implementation associated with this provider for the given parameters. + * @throws DataStoreException if an error occurred while creating the data store instance. + */ + @Override + public DataStore open(final ParameterValueGroup parameters) throws DataStoreException { + ArgumentChecks.ensureNonNull("parameter", parameters); + final StorageConnector connector = connector(this, parameters); + final Parameters pg = Parameters.castOrWrap(parameters); + connector.setOption(DataOptionKey.ENCODING, pg.getValue(ENCODING)); + connector.setOption(DataOptionKey.FOLIATION_REPRESENTATION, pg.getValue(FOLIATION)); + return new Store(this, connector); + } + + /** + * Invoked by {@link #getOpenParameters()} the first time that a parameter descriptor needs to be created. + * + * @return the parameters descriptor for CSV files. + */ + @Override + protected ParameterDescriptorGroup build(final ParameterBuilder builder) { + return builder.createGroup(LOCATION_PARAM, ENCODING, FOLIATION); } } Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/TimeEncoding.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/TimeEncoding.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/TimeEncoding.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/TimeEncoding.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -16,6 +16,7 @@ */ package org.apache.sis.internal.storage.csv; +import java.time.Instant; import javax.measure.Unit; import javax.measure.quantity.Time; import org.opengis.referencing.datum.TemporalDatum; @@ -24,9 +25,6 @@ import org.apache.sis.internal.util.Stan import org.apache.sis.referencing.CommonCRS; import org.apache.sis.measure.Units; -// Branch-dependent imports -import java.time.Instant; - /** * Specifies how time is encoded in the CSV file. Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/package-info.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/package-info.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/package-info.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/package-info.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -53,7 +53,7 @@ * </ul> * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.7 * @module */ Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/FolderStoreProvider.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/FolderStoreProvider.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/FolderStoreProvider.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/FolderStoreProvider.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -16,18 +16,21 @@ */ package org.apache.sis.internal.storage.folder; -import java.io.IOException; +import java.util.EnumSet; import java.util.Locale; import java.util.TimeZone; +import java.io.IOException; import java.nio.charset.Charset; -import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Files; +import java.nio.file.FileAlreadyExistsException; import java.nio.file.FileSystemNotFoundException; +import java.nio.file.NoSuchFileException; +import java.nio.file.StandardOpenOption; import org.opengis.util.InternationalString; import org.opengis.parameter.ParameterValueGroup; import org.opengis.parameter.ParameterDescriptor; import org.opengis.parameter.ParameterDescriptorGroup; -import org.opengis.parameter.ParameterNotFoundException; import org.apache.sis.parameter.ParameterBuilder; import org.apache.sis.parameter.Parameters; import org.apache.sis.storage.DataStore; @@ -35,12 +38,14 @@ 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.storage.IllegalOpenParameterException; import org.apache.sis.util.ArgumentChecks; import org.apache.sis.util.logging.Logging; import org.apache.sis.internal.system.Modules; import org.apache.sis.internal.storage.Resources; import org.apache.sis.internal.storage.URIDataStore; +import org.apache.sis.internal.storage.Capability; +import org.apache.sis.internal.storage.StoreMetadata; +import org.apache.sis.internal.storage.StoreUtilities; import org.apache.sis.setup.OptionKey; @@ -51,15 +56,16 @@ import org.apache.sis.setup.OptionKey; * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.8 * @module */ +@StoreMetadata(formatName=FolderStoreProvider.NAME, capabilities={Capability.READ, Capability.WRITE}) public final class FolderStoreProvider extends DataStoreProvider { /** * A short name or abbreviation for the data format. */ - private static final String NAME = "folder"; + static final String NAME = "folder"; /** * Description of the parameter for formating conventions of dates and numbers. @@ -77,6 +83,12 @@ public final class FolderStoreProvider e private static final ParameterDescriptor<Charset> ENCODING; /** + * Description of the parameter for name of format or {@code DataStoreProvider} + * to use for reading or writing the directory content. + */ + private static final ParameterDescriptor<String> FORMAT; + + /** * The group of parameter descriptors to be returned by {@link #getOpenParameters()}. */ static final ParameterDescriptorGroup PARAMETERS; @@ -84,17 +96,23 @@ public final class FolderStoreProvider e final ParameterDescriptor<Path> location; final ParameterBuilder builder = new ParameterBuilder(); final InternationalString remark = Resources.formatInternational(Resources.Keys.UsedOnlyIfNotEncoded); + ENCODING = annotate(builder, URIDataStore.Provider.ENCODING, remark); LOCALE = builder.addName("locale" ).setDescription(Resources.formatInternational(Resources.Keys.DataStoreLocale )).setRemarks(remark).create(Locale.class, null); TIMEZONE = builder.addName("timezone").setDescription(Resources.formatInternational(Resources.Keys.DataStoreTimeZone)).setRemarks(remark).create(TimeZone.class, null); - ENCODING = builder.addName("encoding").setDescription(Resources.formatInternational(Resources.Keys.DataStoreEncoding)).setRemarks(remark).create(Charset.class, null); - location = builder.addName( LOCATION ).setDescription(URIDataStore.Provider.LOCATION_PARAM.getDescription()) .setRequired(true) .create(Path.class, null); - PARAMETERS = builder.addName( NAME ).createGroup(location, LOCALE, TIMEZONE, ENCODING); + FORMAT = builder.addName("format" ).setDescription(Resources.formatInternational(Resources.Keys.DirectoryContentFormatName)).create(String.class, null); + location = new ParameterBuilder(URIDataStore.Provider.LOCATION_PARAM).create(Path.class, null); + PARAMETERS = builder.addName(NAME).createGroup(location, LOCALE, TIMEZONE, ENCODING, FORMAT, URIDataStore.Provider.CREATE_PARAM); + } + + /** + * Creates a parameter descriptor equals to the given one except for the remarks which are set to the given value. + */ + private static <T> ParameterDescriptor<T> annotate(ParameterBuilder builder, ParameterDescriptor<T> e, InternationalString remark) { + return builder.addName(e.getName()).setDescription(e.getDescription()).setRemarks(remark).create(e.getValueClass(), null); } /** * The unique instance of this provider. - * - * @see #open(Path) */ public static final FolderStoreProvider INSTANCE = new FolderStoreProvider(); @@ -149,6 +167,8 @@ public final class FolderStoreProvider e /** * Returns a data store implementation associated with this provider. + * The data store created by this method will try to auto-detect the format of every files in the directory. + * For exploring only the file of a known format, use {@link #open(ParameterValueGroup)} instead. * * @param connector information about the storage (URL, path, <i>etc</i>). * @return a data store implementation associated with this provider for the given storage. @@ -156,12 +176,89 @@ public final class FolderStoreProvider e */ @Override public DataStore open(final StorageConnector connector) throws DataStoreException { + return open(connector, null, EnumSet.noneOf(StandardOpenOption.class)); + } + + /** + * Shared implementation of public {@code open(…)} methods. + * Note that this method may modify the given {@code options} set for its own purpose. + * + * @param connector information about the storage (URL, path, <i>etc</i>). + * @param format format name for directory content, or {@code null} if unspecified. + * @param options whether to create a new directory, overwrite existing content, <i>etc</i>. + */ + private DataStore open(final StorageConnector connector, final String format, final EnumSet<StandardOpenOption> options) + throws DataStoreException + { + /* + * Determine now the provider to use for directory content. We do that for determining if the component + * has write capability. If not, then the WRITE, CREATE and related options will be ignored. If we can + * not determine whether the component store has write capabilities (i.e. if canWrite(…) returns null), + * assume that the answer is "yes". + */ + final DataStoreProvider componentProvider; + if (format != null) { + componentProvider = StoreUtilities.providerByFormatName(format.trim()); + if (Boolean.FALSE.equals(StoreUtilities.canWrite(componentProvider.getClass()))) { + options.clear(); // No write capability. + } + } else { + componentProvider = null; + options.clear(); // Can not write if we don't know the components format. + } + final Path path = connector.getStorageAs(Path.class); + final Store store; try { - return new Store(this, connector); + /* + * If the user asked to create a new directory, we need to perform this task before + * to create the Store (otherwise constructor will fail with NoSuchFileException). + * In the particular case of CREATE_NEW, we unconditionally attempt to create the + * directory in order to rely on the atomic check performed by Files.createDirectory(…). + */ + boolean isNew = false; + if (options.contains(StandardOpenOption.CREATE)) { + if (options.contains(StandardOpenOption.CREATE_NEW) || Files.notExists(path)) { + Files.createDirectory(path); // IOException if the directory already exists. + isNew = true; + } + } + if (isNew || (options.contains(StandardOpenOption.WRITE) && Files.isWritable(path))) { + store = new WritableStore(this, connector, path, componentProvider); // May throw NoSuchFileException. + } else { + store = new Store(this, connector, path, componentProvider); // May throw NoSuchFileException. + } + /* + * If there is a destructive operation to perform (TRUNCATE_EXISTING), do it last only + * after we have successfully created the data store. The check for directory existence + * is also done after creation to be sure to check the path used by the store. + */ + if (!Files.isDirectory(path)) { + throw new DataStoreException(Resources.format(Resources.Keys.FileIsNotAResourceDirectory_1, path)); + } + if (options.contains(StandardOpenOption.TRUNCATE_EXISTING)) { + WritableStore.deleteRecursively(path, false); + } } catch (IOException e) { - throw new DataStoreException(Resources.format(Resources.Keys.CanNotReadDirectory_1, - connector.getStorageName()), e); + /* + * In case of error, Java FileSystem implementation tries to throw a specific exception + * (NoSuchFileException or FileAlreadyExistsException), but this is not guaranteed. + */ + int isDirectory = 0; + final short errorKey; + if (e instanceof FileAlreadyExistsException) { + if (path != null && Files.isDirectory(path)) { + isDirectory = 1; + } + errorKey = Resources.Keys.FileAlreadyExists_2; + } else if (e instanceof NoSuchFileException) { + errorKey = Resources.Keys.NoSuchResourceDirectory_1; + } else { + errorKey = Resources.Keys.CanNotCreateFolderStore_1; + } + throw new DataStoreException(Resources.format(errorKey, + (path != null) ? path : connector.getStorageName(), isDirectory), e); } + return store; } /** @@ -173,32 +270,15 @@ public final class FolderStoreProvider e @Override public DataStore open(final ParameterValueGroup parameters) throws DataStoreException { ArgumentChecks.ensureNonNull("parameter", parameters); - ParameterNotFoundException cause = null; - try { - final Object location = parameters.parameter(LOCATION).getValue(); - if (location != null) { - final Parameters pg = Parameters.castOrWrap(parameters); - final StorageConnector connector = new StorageConnector(location); - connector.setOption(OptionKey.LOCALE, pg.getValue(LOCALE)); - connector.setOption(OptionKey.TIMEZONE, pg.getValue(TIMEZONE)); - connector.setOption(OptionKey.ENCODING, pg.getValue(ENCODING)); - return open(connector); - } - } catch (ParameterNotFoundException e) { - cause = e; + final StorageConnector connector = URIDataStore.Provider.connector(this, parameters); + final Parameters pg = Parameters.castOrWrap(parameters); + connector.setOption(OptionKey.LOCALE, pg.getValue(LOCALE)); + connector.setOption(OptionKey.TIMEZONE, pg.getValue(TIMEZONE)); + connector.setOption(OptionKey.ENCODING, pg.getValue(ENCODING)); + final EnumSet<StandardOpenOption> options = EnumSet.of(StandardOpenOption.WRITE); + if (Boolean.TRUE.equals(pg.getValue(URIDataStore.Provider.CREATE_PARAM))) { + options.add(StandardOpenOption.CREATE); } - throw new IllegalOpenParameterException(Resources.format(Resources.Keys.UndefinedParameter_2, - getShortName(), LOCATION), cause); - } - - /** - * Returns a folder data store for the given path. - * - * @param path the directory for which to create a data store. - * @return a data store for the given directory. - * @throws DataStoreException if an error occurred while creating the data store instance. - */ - public static DataStore open(final Path path) throws DataStoreException { - return INSTANCE.open(new StorageConnector(path)); + return open(connector, pg.getValue(FORMAT), options); } } Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/Store.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/Store.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/Store.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/Store.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -22,14 +22,15 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Locale; import java.util.TimeZone; +import java.util.logging.Level; +import java.util.concurrent.ConcurrentHashMap; import java.nio.charset.Charset; import java.nio.file.Path; import java.nio.file.Files; import java.nio.file.DirectoryStream; import java.nio.file.DirectoryIteratorException; import java.io.IOException; -import java.util.logging.Level; -import java.util.concurrent.ConcurrentHashMap; +import java.io.UncheckedIOException; import org.opengis.metadata.Metadata; import org.opengis.metadata.maintenance.ScopeCode; import org.opengis.parameter.ParameterValueGroup; @@ -45,11 +46,9 @@ import org.apache.sis.storage.Unsupporte import org.apache.sis.util.collection.BackingStoreException; import org.apache.sis.internal.util.UnmodifiableArrayList; import org.apache.sis.internal.storage.MetadataBuilder; +import org.apache.sis.internal.storage.StoreUtilities; import org.apache.sis.internal.storage.Resources; -// Branch-dependent imports -import java.io.UncheckedIOException; - /** * A folder store acts as an aggregate of multiple files in a single store. @@ -69,36 +68,36 @@ import java.io.UncheckedIOException; * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.8 * @module */ -final class Store extends DataStore implements Aggregate, DirectoryStream.Filter<Path> { +class Store extends DataStore implements Aggregate, DirectoryStream.Filter<Path> { /** * The {@link FolderStoreProvider#LOCATION} parameter value, or {@code null} if none. */ - private final Path location; + protected final Path location; /** * Formating conventions of dates and numbers, or {@code null} if unspecified. */ - private final Locale locale; + protected final Locale locale; /** * Timezone of dates in the data store, or {@code null} if unspecified. */ - private final TimeZone timezone; + protected final TimeZone timezone; /** * Character encoding used by the data store, or {@code null} if unspecified. */ - private final Charset encoding; + protected final Charset encoding; /** * All data stores (including sub-folders) found in the directory structure, including the root directory. * This is used for avoiding never-ending loop with symbolic links. */ - private final Map<Path,DataStore> children; + final Map<Path,DataStore> children; /** * Information about the data store as a whole, created when first needed. @@ -112,7 +111,14 @@ final class Store extends DataStore impl * * @see #components() */ - private transient Collection<Resource> components; + transient Collection<Resource> components; + + /** + * The provider to use for probing the directory content, opening files and creating new files. + * The provider is determined by the format name specified at construction time. + * This field is {@code null} if that format name is null. + */ + protected final DataStoreProvider componentProvider; /** * {@code true} if {@link #sharedRepository(Path)} has already been invoked for {@link #location} path. @@ -122,20 +128,30 @@ final class Store extends DataStore impl /** * Creates a new folder store from the given file, path or URI. + * The folder store will attempt to open only the files of the given format, if non-null. + * If a null format is specified, then the folder store will attempt to open any file + * found in the directory (this may produce confusing results). * * @param provider the factory that created this {@code DataStore} instance, or {@code null} if unspecified. * @param connector information about the storage (URL, stream, <i>etc</i>). - * @throws DataStoreException if an error occurred while opening the stream. - */ - @SuppressWarnings("ThisEscapedInObjectConstruction") // Okay because 'folders' does not escape. - Store(final DataStoreProvider provider, final StorageConnector connector) throws DataStoreException, IOException { + * @param path the value of {@code connector.getStorageAs(Path.class)}. + * @param format format to use for reading or writing the directory content, or {@code null}. + * @throws UnsupportedStorageException if the given format name is unknown. + * @throws DataStoreException if an error occurred while fetching the directory {@link Path}. + * @throws IOException if an error occurred while using the directory {@code Path}. + */ + @SuppressWarnings("ThisEscapedInObjectConstruction") // Okay because 'children' does not escape. + Store(final DataStoreProvider provider, final StorageConnector connector, final Path path, final DataStoreProvider format) + throws DataStoreException, IOException + { super(provider, connector); - location = connector.getStorageAs(Path.class); + location = path; locale = connector.getOption(OptionKey.LOCALE); timezone = connector.getOption(OptionKey.TIMEZONE); encoding = connector.getOption(OptionKey.ENCODING); children = new ConcurrentHashMap<>(); - children.put(location.toRealPath(), this); + children.put(path.toRealPath(), this); + componentProvider = format; } /** @@ -147,11 +163,12 @@ final class Store extends DataStore impl */ private Store(final Store parent, final StorageConnector connector) throws DataStoreException { super(parent, connector); - location = connector.getStorageAs(Path.class); - locale = connector.getOption(OptionKey.LOCALE); - timezone = connector.getOption(OptionKey.TIMEZONE); - encoding = connector.getOption(OptionKey.ENCODING); - children = parent.children; + location = connector.getStorageAs(Path.class); + locale = connector.getOption(OptionKey.LOCALE); + timezone = connector.getOption(OptionKey.TIMEZONE); + encoding = connector.getOption(OptionKey.ENCODING); + children = parent.children; + componentProvider = parent.componentProvider; } /** @@ -159,11 +176,13 @@ final class Store extends DataStore impl */ @Override public ParameterValueGroup getOpenParameters() { + final String format = StoreUtilities.getFormatName(componentProvider); final ParameterValueGroup pg = (provider != null ? provider.getOpenParameters() : FolderStoreProvider.PARAMETERS).createValue(); - pg.parameter(FolderStoreProvider.LOCATION).setValue(location); + pg.parameter(DataStoreProvider.LOCATION).setValue(location); if (locale != null) pg.parameter("locale" ).setValue(locale ); if (timezone != null) pg.parameter("timezone").setValue(timezone); if (encoding != null) pg.parameter("encoding").setValue(encoding); + if (format != null) pg.parameter("format" ).setValue(format); return pg; } @@ -204,8 +223,8 @@ final class Store extends DataStore impl @SuppressWarnings("ReturnOfCollectionOrArrayField") public synchronized Collection<Resource> components() throws DataStoreException { if (components == null) { + final List<DataStore> resources = new ArrayList<>(); try (DirectoryStream<Path> stream = Files.newDirectoryStream(location, this)) { - final List<DataStore> resources = new ArrayList<>(); for (final Path candidate : stream) { /* * The candidate path may be a symbolic link to a file that we have previously read. @@ -230,7 +249,16 @@ final class Store extends DataStore impl connector.setOption(OptionKey.TIMEZONE, timezone); connector.setOption(OptionKey.ENCODING, encoding); try { - next = DataStores.open(connector); + if (componentProvider == null) { + next = DataStores.open(connector); // May throw UnsupportedStorageException. + } else if (componentProvider.probeContent(connector).isSupported()) { + next = componentProvider.open(connector); // Open a file of specified format. + } else if (Files.isDirectory(candidate)) { + next = new Store(this, connector); // Open a sub-directory. + } else { + connector.closeAllExcept(null); // Not the format specified at construction time. + continue; + } } catch (UnsupportedStorageException ex) { if (!Files.isDirectory(candidate)) { connector.closeAllExcept(null); @@ -261,7 +289,6 @@ final class Store extends DataStore impl } resources.add(next); } - components = UnmodifiableArrayList.wrap(resources.toArray(new Resource[resources.size()])); } catch (DirectoryIteratorException | UncheckedIOException ex) { // The cause is an IOException (no other type allowed). throw new DataStoreException(canNotRead(), ex.getCause()); @@ -270,6 +297,7 @@ final class Store extends DataStore impl } catch (BackingStoreException ex) { throw ex.unwrapOrRethrow(DataStoreException.class); } + components = UnmodifiableArrayList.wrap(resources.toArray(new Resource[resources.size()])); } return components; // Safe because unmodifiable list. } @@ -296,12 +324,19 @@ final class Store extends DataStore impl } /** + * Returns the resource bundle to use for error message in exceptions. + */ + final Resources messages() { + return Resources.forLocale(getLocale()); + } + + /** * Returns a localized string for the given key and value. * * @param key one of the {@link Resources.Keys} constants ending with {@code _1} suffix. */ - private String message(final short key, final Object value) { - return Resources.forLocale(getLocale()).getString(key, value); + final String message(final short key, final Object value) { + return messages().getString(key, value); } /** Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/package-info.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/package-info.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/package-info.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/package-info.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -19,7 +19,7 @@ * {@link org.apache.sis.storage.DataStore} implementation for a folder containing an arbitrary amount of data files. * * @author Johann Sorel (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.8 * @module */ Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/InputStreamAdapter.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/InputStreamAdapter.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/InputStreamAdapter.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/InputStreamAdapter.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -18,10 +18,8 @@ package org.apache.sis.internal.storage. import java.io.InputStream; import java.io.IOException; -import javax.imageio.stream.ImageInputStream; - -// Branch-dependent imports import java.io.UncheckedIOException; +import javax.imageio.stream.ImageInputStream; /** Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/package-info.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/package-info.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/package-info.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/package-info.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -24,7 +24,7 @@ * may change in incompatible ways in any future version without notice. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.3 * @module */ Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -19,7 +19,6 @@ package org.apache.sis.internal.storage. import java.util.List; import java.util.Arrays; import java.util.ArrayList; -import java.util.logging.LogRecord; import java.io.Reader; import java.io.IOException; import java.text.ParsePosition; @@ -27,13 +26,13 @@ import java.text.ParseException; import org.opengis.metadata.Metadata; import org.opengis.referencing.ReferenceSystem; import org.apache.sis.internal.storage.Resources; -import org.apache.sis.internal.system.Loggers; import org.apache.sis.storage.StorageConnector; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.DataStoreContentException; import org.apache.sis.storage.UnsupportedStorageException; import org.apache.sis.internal.storage.MetadataBuilder; import org.apache.sis.internal.storage.URIDataStore; +import org.apache.sis.referencing.IdentifiedObjects; import org.apache.sis.setup.GeometryLibrary; import org.apache.sis.setup.OptionKey; import org.apache.sis.util.CharSequences; @@ -43,7 +42,7 @@ import org.apache.sis.util.CharSequences * A data store which creates data objects from a WKT definition. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.7 * @module */ @@ -144,19 +143,10 @@ final class Store extends URIDataStore { } /** - * Reports a warning. - */ - private void log(final LogRecord record) { - record.setSourceClassName(Store.class.getName()); - record.setSourceMethodName("getMetadata"); // Public facade for the parse() method. - record.setLoggerName(Loggers.WKT); - listeners.warning(record); - } - - /** * Returns the metadata associated to the parsed objects, or {@code null} if none. * The current implementation retains only instances of {@link ReferenceSystem} - * and ignore other objects. + * and ignore other objects. The identification information {@code Citation} is + * set to the CRS name and identifier, unless there is ambiguity. * * @return the metadata associated to the parsed object, or {@code null} if none. * @throws DataStoreException if an error occurred during the parsing process. @@ -166,13 +156,22 @@ final class Store extends URIDataStore { if (metadata == null) { parse(); final MetadataBuilder builder = new MetadataBuilder(); - builder.addTitle(getDisplayName()); + String name = null; + int count = 0; for (final Object object : objects) { if (object instanceof ReferenceSystem) { - builder.addReferenceSystem((ReferenceSystem) object); + final ReferenceSystem rs = (ReferenceSystem) object; + builder.addReferenceSystem(rs); + name = IdentifiedObjects.getName(rs, null); + count++; + builder.addIdentifier(IdentifiedObjects.getIdentifier(rs, null), MetadataBuilder.Scope.RESOURCE); } } - addTitleOrIdentifier(builder); + if (count == 1) { // Set the citation title only if non-ambiguous. + builder.addTitle(name); + } else { + addTitleOrIdentifier(builder); + } metadata = builder.build(true); } return metadata; Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -24,7 +24,7 @@ import org.apache.sis.storage.DataStoreE import org.apache.sis.storage.StorageConnector; import org.apache.sis.storage.ProbeResult; import org.apache.sis.internal.storage.Capability; -import org.apache.sis.internal.storage.Capabilities; +import org.apache.sis.internal.storage.StoreMetadata; import org.apache.sis.internal.storage.URIDataStore; import org.apache.sis.internal.metadata.WKTKeywords; import org.apache.sis.util.Version; @@ -34,11 +34,13 @@ import org.apache.sis.util.Version; * The provider of WKT {@link Store} instances. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.7 * @module */ -@Capabilities(Capability.READ) +@StoreMetadata(formatName = StoreProvider.NAME, + fileSuffixes = "prj", + capabilities = Capability.READ) public final class StoreProvider extends URIDataStore.Provider { /** * The format name. Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/StoreProvider.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/StoreProvider.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/StoreProvider.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/StoreProvider.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -20,7 +20,7 @@ import org.apache.sis.xml.Namespaces; import org.apache.sis.storage.DataStore; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.StorageConnector; -import org.apache.sis.internal.storage.Capabilities; +import org.apache.sis.internal.storage.StoreMetadata; import org.apache.sis.internal.storage.Capability; @@ -28,11 +28,13 @@ import org.apache.sis.internal.storage.C * The provider of {@link Store} instances. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.4 * @module */ -@Capabilities(Capability.READ) +@StoreMetadata(formatName = StoreProvider.NAME, + fileSuffixes = "xml", + capabilities = Capability.READ) public final class StoreProvider extends AbstractProvider { /** * The format name. Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/Aggregate.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/Aggregate.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/Aggregate.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/Aggregate.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -17,10 +17,6 @@ package org.apache.sis.storage; import java.util.Collection; -import org.opengis.metadata.Metadata; -import org.opengis.referencing.crs.CoordinateReferenceSystem; -import org.apache.sis.internal.storage.Resources; - /** * A collection of resources. An aggregate can have two or more components. @@ -58,7 +54,7 @@ import org.apache.sis.internal.storage.R * associated resources} with an {@link org.opengis.metadata.identification.AssociationType#IS_COMPOSED_OF} relation. * * @author Johann Sorel (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.8 * @module */ @@ -90,47 +86,4 @@ public interface Aggregate extends Resou * @throws DataStoreException if an error occurred while fetching the components. */ Collection<Resource> components() throws DataStoreException; - - /** - * Adds a new {@code Resource} in this {@code Aggregate}. - * The given {@link Resource} will be copied, and the <cite>effectively added</cite> resource returned. - * The effectively added resource may differ from the given resource in many aspects. - * The possible changes may include the followings but not only: - * <ul> - * <li>types and properties names</li> - * <li>{@link CoordinateReferenceSystem}</li> - * <li>{@link Metadata}</li> - * </ul> - * - * <div class="note"><b>Warning:</b> - * copying informations between stores may produce differences in many aspects. - * The range of changes depends both on the original {@link Resource} structure - * and the target {@code Resource} structure. If the differences are too large, - * then this {@code Aggregate} may throw an exception. - * </div> - * - * <p>The default implementation throws {@link ReadOnlyStorageException}.</p> - * - * @param resource the resource to copy in this {@code Aggregate}. - * @return the effectively added resource. May be {@code resource} itself if it has been added verbatim. - * @throws ReadOnlyStorageException if this instance does not support write operations. - * @throws DataStoreException if the given resource can not be stored in this {@code Aggregate} for another reason. - */ - default Resource add(Resource resource) throws ReadOnlyStorageException, DataStoreException { - throw new ReadOnlyStorageException(this, Resources.Keys.StoreIsReadOnly); - } - - /** - * Removes a {@code Resource} from this {@code Aggregate}. - * This operation is destructive: the {@link Resource} and it's related data will be removed. - * - * <p>The default implementation throws {@link ReadOnlyStorageException}.</p> - * - * @param resource child resource to remove, should not be null. - * @throws ReadOnlyStorageException if this instance does not support write operations. - * @throws DataStoreException if the given resource could not be removed for another reason. - */ - default void remove(Resource resource) throws ReadOnlyStorageException, DataStoreException { - throw new ReadOnlyStorageException(this, Resources.Keys.StoreIsReadOnly); - } } Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -47,7 +47,7 @@ import org.apache.sis.internal.util.Cita * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * * @see DataStores#open(Object) * Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreProvider.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -18,10 +18,9 @@ package org.apache.sis.storage; import org.opengis.parameter.ParameterValueGroup; import org.opengis.parameter.ParameterDescriptorGroup; -import org.opengis.parameter.ParameterNotFoundException; import org.opengis.metadata.distribution.Format; import org.apache.sis.internal.simple.SimpleFormat; -import org.apache.sis.internal.storage.Resources; +import org.apache.sis.internal.storage.URIDataStore; import org.apache.sis.metadata.iso.citation.DefaultCitation; import org.apache.sis.metadata.iso.distribution.DefaultFormat; import org.apache.sis.measure.Range; @@ -58,7 +57,7 @@ import org.apache.sis.util.Version; * * @author Martin Desruisseaux (Geomatys) * @author Johann Sorel (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.3 * @module */ @@ -70,16 +69,45 @@ public abstract class DataStoreProvider * * <p>Implementors are encouraged to define a parameter with this name * to ensure a common and consistent definition among providers. - * The parameter should be defined as mandatory and declared with a well-known Java class such as + * The parameter should be defined as mandatory and typed with a well-known Java class such as * {@link java.net.URI}, {@link java.nio.file.Path}, JDBC {@linkplain javax.sql.DataSource}, <i>etc</i>. * The type should have a compact textual representation, for serialization in XML or configuration files. * Consequently {@link java.io.InputStream} and {@link java.nio.channels.Channel} should be avoided.</p> * + * @see #CREATE * @see #getOpenParameters() */ public static final String LOCATION = "location"; /** + * Name of the parameter that specifies whether to allow creation of a new {@code DataStore} if none exist + * at the given location. A parameter named {@value} may be included in the group of parameters returned by + * {@link #getOpenParameters()} if the data store supports write operations. The parameter value is often a + * {@link Boolean} and the default value should be {@link Boolean#FALSE} or equivalent. + * + * <p>Implementors are encouraged to define an <em>optional</em> parameter with this name in complement to the + * {@value #LOCATION} parameter <em>only if</em> write operations are supported. If this parameter value is not + * set or is set to {@code false}, then the {@link #open(ParameterValueGroup)} method should fail if no file or + * database exists at the URL or path given by the {@value #LOCATION} parameter. Otherwise if this parameter is + * set to {@code true}, then the {@code open(…)} method may create files, a directory or a database at the given + * location.</p> + * + * <div class="note"><b>Relationship with standard file open options</b> + * <p>For data stores on file systems, a <code>{@value} = true</code> parameter value is equivalent to opening a file + * with {@link java.nio.file.StandardOpenOption#CREATE} and {@link java.nio.file.StandardOpenOption#APPEND APPEND}. + * The other file standard options like {@link java.nio.file.StandardOpenOption#CREATE_NEW CREATE_NEW} and + * {@link java.nio.file.StandardOpenOption#TRUNCATE_EXISTING TRUNCATE_EXISTING} should not be accessible through + * this {@value} parameter. The reason is that {@link ParameterValueGroup} may be used for storing parameters + * permanently (for example in a configuration file or in a database) for reopening the same {@link DataStore} + * many times. File options designed for being used only once like {@code CREATE_NEW} and {@code TRUNCATE_EXISTING} + * are incompatible with this usage.</p></div> + * + * @see #LOCATION + * @see #getOpenParameters() + */ + public static final String CREATE = "create"; + + /** * Creates a new provider. */ protected DataStoreProvider() { @@ -157,7 +185,8 @@ public abstract class DataStoreProvider * from a path or URL, together with additional information like character encoding. * * <p>Implementors are responsible for declaring all parameters and whether they are mandatory or optional. - * It is recommended to define at least a parameter named {@value #LOCATION}. + * It is recommended to define at least a parameter named {@value #LOCATION}, completed by {@value #CREATE} + * if the data store supports write operations. * That parameter will be recognized by the default {@code DataStoreProvider} methods and used whenever a * {@link StorageConnector} is required.</p> * @@ -175,6 +204,8 @@ public abstract class DataStoreProvider * * @return description of the parameters required or accepted for opening a {@link DataStore}. * + * @see #LOCATION + * @see #CREATE * @see #open(ParameterValueGroup) * @see DataStore#getOpenParameters() * @@ -281,24 +312,14 @@ public abstract class DataStoreProvider * @return a data store implementation associated with this provider for the given parameters. * @throws DataStoreException if an error occurred while creating the data store instance. * + * @see #LOCATION + * @see #CREATE * @see #getOpenParameters() * * @since 0.8 */ public DataStore open(final ParameterValueGroup parameters) throws DataStoreException { ArgumentChecks.ensureNonNull("parameter", parameters); - ParameterNotFoundException cause = null; - Object location; - try { - location = parameters.parameter(LOCATION).getValue(); - } catch (ParameterNotFoundException e) { - location = null; - cause = e; - } - if (location == null) { - throw new IllegalOpenParameterException(Resources.format(Resources.Keys.UndefinedParameter_2, - getShortName(), LOCATION), cause); - } - return open(new StorageConnector(location)); + return open(URIDataStore.Provider.connector(this, parameters)); } } Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreRegistry.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreRegistry.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreRegistry.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStoreRegistry.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -18,7 +18,7 @@ package org.apache.sis.storage; import java.util.List; import java.util.LinkedList; -import java.util.Collection; +import java.util.Set; import java.util.Iterator; import java.util.ServiceLoader; import org.apache.sis.internal.storage.Resources; @@ -41,7 +41,7 @@ import org.apache.sis.util.ArgumentCheck * on the part of the caller. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.4 * @module */ @@ -80,7 +80,7 @@ final class DataStoreRegistry { * * @since 0.8 */ - public Collection<DataStoreProvider> providers() { + public Set<DataStoreProvider> providers() { synchronized (loader) { final Iterator<DataStoreProvider> providers = loader.iterator(); return new LazySet<>(new Iterator<DataStoreProvider>() { Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStores.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStores.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStores.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStores.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -28,7 +28,8 @@ import org.apache.sis.internal.system.Sy * but can also be any other objects documented in the {@link StorageConnector} class. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @author Johann Sorel (Geomatys) + * @version 1.0 * @since 0.4 * @module */ @@ -79,7 +80,7 @@ public final class DataStores extends St } /** - * Returns the list of data store providers available at this method invocation time. + * Returns the set of data store providers available at this method invocation time. * 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/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSet.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSet.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSet.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSet.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -16,13 +16,9 @@ */ package org.apache.sis.storage; -import java.util.Iterator; -import org.apache.sis.internal.storage.Resources; +import java.util.stream.Stream; // Branch-dependent imports -import java.util.function.Predicate; -import java.util.function.UnaryOperator; -import java.util.stream.Stream; import org.opengis.feature.Feature; import org.opengis.feature.FeatureType; @@ -35,7 +31,7 @@ import org.opengis.feature.FeatureType; * are also allowed. * * @author Johann Sorel (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.8 * @module */ @@ -140,63 +136,4 @@ public interface FeatureSet extends Data * @throws DataStoreException if an error occurred while creating the stream. */ Stream<Feature> features(boolean parallel) throws DataStoreException; - - /** - * Inserts new features in this {@code FeatureSet}. - * Any feature already present in the {@link FeatureSet} will remain unmodified. - * - * <div class="note"><b>API note:</b> - * this method expects an {@link Iterator} rather then a {@link java.util.stream.Stream} for easing - * inter-operability with various API. Implementing a custom {@link Iterator} requires less effort - * than implementing a {@link Stream}. On the other side if the user has a {@link Stream}, - * obtaining an {@link Iterator} can be done by a call to {@link Stream#iterator()}.</div> - * - * <p>The default implementation throws {@link ReadOnlyStorageException}.</p> - * - * @param features features to insert in this {@code FeatureSet}. - * @throws ReadOnlyStorageException if this instance does not support write operations. - * @throws DataStoreException if another error occurred while storing new features. - */ - default void add(Iterator<? extends Feature> features) throws ReadOnlyStorageException, DataStoreException { - throw new ReadOnlyStorageException(this, Resources.Keys.StoreIsReadOnly); - } - - /** - * Removes all features from this {@code FeatureSet} which matches the given predicate. - * - * <p>The default implementation throws {@link ReadOnlyStorageException}.</p> - * - * @param filter a predicate which returns true for resources to be removed. - * @return {@code true} if any elements were removed. - * @throws ReadOnlyStorageException if this instance does not support write operations. - * @throws DataStoreException if another error occurred while removing features. - */ - default boolean removeIf(Predicate<? super Feature> filter) throws ReadOnlyStorageException, DataStoreException { - throw new ReadOnlyStorageException(this, Resources.Keys.StoreIsReadOnly); - } - - /** - * Updates all features from this {@code FeatureSet} which matches the given predicate. - * For each {@link Feature} instance matching the given {@link Predicate}, - * the <code>{@linkplain UnaryOperator#apply UnaryOperator.apply(Feature)}</code> method will be invoked. - * {@code UnaryOperator}s are free to modify the given {@code Feature} <i>in-place</i> or to return a - * different feature instance. Two behaviors are possible: - * <ul> - * <li>If the operator returns a non-null {@link Feature}, then the modified feature is stored - * in replacement of the previous feature (not necessarily at the same location).</li> - * <li>If the operator returns {@code null}, then the feature will be removed from the {@code FeatureSet}.</li> - * </ul> - * - * <p>The default implementation throws {@link ReadOnlyStorageException}.</p> - * - * @param filter a predicate which returns true for resources to be updated. - * @param updater operation called for each matching {@link Feature}. - * @throws ReadOnlyStorageException if this instance does not support write operations. - * @throws DataStoreException if another error occurred while replacing features. - */ - default void replaceIf(Predicate<? super Feature> filter, UnaryOperator<Feature> updater) - throws ReadOnlyStorageException, DataStoreException - { - throw new ReadOnlyStorageException(this, Resources.Keys.StoreIsReadOnly); - } } Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/ReadOnlyStorageException.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/ReadOnlyStorageException.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/ReadOnlyStorageException.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/ReadOnlyStorageException.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -16,17 +16,15 @@ */ package org.apache.sis.storage; -import org.apache.sis.util.Localized; - /** * Thrown when a {@code DataStore} can not perform a write operations. - * This exception may occur either because: - * - * <ul> - * <li>the data store does not support write operations, or</li> - * <li>write operations are supported but the channel is read-only.</li> - * </ul> + * If a data store does not support any write operation, then it should not implement + * {@link WritableAggregate} or {@link WritableFeatureSet} interface. + * But in some situations, a data store may implement a {@code Writable*} interface + * and nevertheless be unable to perform a write operation, for example because the + * underlying {@link java.nio.channels.Channel} is read-only or part of the file is + * locked by another process. * * @author Johann Sorel (Geomatys) * @version 0.8 @@ -74,15 +72,4 @@ public class ReadOnlyStorageException ex public ReadOnlyStorageException(final String message, final Throwable cause) { super(message, cause); } - - /** - * Creates a new exception which will format a localized message in the resource locale. - * - * @param originator the instance throwing this exception, or {@code null} if unknown. - * @param key one of {@link org.apache.sis.internal.storage.Resources.Keys} constants. - * @param parameters parameters to use for formatting the messages. - */ - ReadOnlyStorageException(final Resource originator, final short key, final Object... parameters) { - super((originator instanceof Localized) ? ((Localized) originator).getLocale() : null, key, parameters); - } } Modified: sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/package-info.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/package-info.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/package-info.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/main/java/org/apache/sis/storage/package-info.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -26,7 +26,7 @@ * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.3 * @module */ Modified: sis/branches/JDK9/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/csv/StoreTest.java URL: http://svn.apache.org/viewvc/sis/branches/JDK9/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/csv/StoreTest.java?rev=1825252&r1=1825251&r2=1825252&view=diff ============================================================================== --- sis/branches/JDK9/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/csv/StoreTest.java [UTF-8] (original) +++ sis/branches/JDK9/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/csv/StoreTest.java [UTF-8] Sat Feb 24 15:44:08 2018 @@ -18,12 +18,15 @@ package org.apache.sis.internal.storage. import java.util.Arrays; import java.util.Iterator; +import java.time.Instant; import java.io.StringReader; import org.opengis.metadata.Metadata; import org.opengis.metadata.extent.Extent; import org.opengis.metadata.extent.GeographicBoundingBox; +import org.apache.sis.feature.FoliationRepresentation; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.StorageConnector; +import org.apache.sis.storage.DataOptionKey; import org.apache.sis.test.TestCase; import org.junit.Test; import com.esri.core.geometry.Point2D; @@ -35,7 +38,6 @@ import static org.apache.sis.test.TestUt import static org.apache.sis.test.TestUtilities.getSingleton; // Branch-dependent imports -import java.time.Instant; import org.opengis.feature.Feature; import org.opengis.feature.FeatureType; import org.opengis.feature.PropertyType; @@ -46,7 +48,7 @@ import org.opengis.feature.AttributeType * Tests {@link Store}. * * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.7 * @module */ @@ -79,6 +81,15 @@ public final strictfp class StoreTest ex } /** + * Opens a CSV store on the test data for reading the lines as-is, without assembling them in a single trajectory. + */ + private static Store open() throws DataStoreException { + StorageConnector connector = new StorageConnector(testData()); + connector.setOption(DataOptionKey.FOLIATION_REPRESENTATION, FoliationRepresentation.FRAGMENTED); + return new Store(null, connector); + } + + /** * Tests {@link Store#getMetadata()}. * * @throws DataStoreException if an error occurred while parsing the data. @@ -86,7 +97,7 @@ public final strictfp class StoreTest ex @Test public void testGetMetadata() throws DataStoreException { final Metadata metadata; - try (Store store = new Store(null, new StorageConnector(testData()), true)) { + try (Store store = open()) { metadata = store.getMetadata(); } final Extent extent = getSingleton(getSingleton(metadata.getIdentificationInfo()).getExtents()); @@ -105,7 +116,7 @@ public final strictfp class StoreTest ex */ @Test public void testStaticFeatures() throws DataStoreException { - try (Store store = new Store(null, new StorageConnector(testData()), true)) { + try (Store store = open()) { verifyFeatureType(store.featureType, double[].class, 1); assertEquals("foliation", Foliation.TIME, store.foliation); final Iterator<Feature> it = store.features(false).iterator(); @@ -134,7 +145,7 @@ public final strictfp class StoreTest ex @Test public void testMovingFeatures() throws DataStoreException { isMovingFeature = true; - try (Store store = new Store(null, new StorageConnector(testData()), false)) { + try (Store store = new Store(null, new StorageConnector(testData()))) { verifyFeatureType(store.featureType, Polyline.class, Integer.MAX_VALUE); assertEquals("foliation", Foliation.TIME, store.foliation); final Iterator<Feature> it = store.features(false).iterator();
