Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.java [UTF-8] Sat Feb 24 15:36:52 2018 @@ -67,7 +67,12 @@ public final class Resources extends Ind public static final short AmbiguousName_4 = 15; /** - * Can not get metadata common to “{0}” files. Reason: {1} + * Can not create resources based on the content of “{0}” directory. + */ + public static final short CanNotCreateFolderStore_1 = 43; + + /** + * Can not get metadata common to “{0}” files. The reason is: {1} */ public static final short CanNotGetCommonMetadata_2 = 39; @@ -97,6 +102,16 @@ public final class Resources extends Ind public static final short CanNotReadFile_4 = 3; /** + * Can not remove resource “{1}” from aggregate “{0}”. + */ + public static final short CanNotRemoveResource_2 = 49; + + /** + * Can not save resources of type ‘{1}’ in a “{0}” store. + */ + public static final short CanNotStoreResourceType_2 = 41; + + /** * This {0} reader is closed. */ public static final short ClosedReader_1 = 4; @@ -117,6 +132,11 @@ public final class Resources extends Ind public static final short ConcurrentWrite_1 = 20; /** + * Whether to allow new data store creation if the source to open does not already exist. + */ + public static final short DataStoreCreate = 51; + + /** * Character encoding used by the data store. */ public static final short DataStoreEncoding = 29; @@ -137,6 +157,11 @@ public final class Resources extends Ind public static final short DataStoreTimeZone = 32; /** + * Name of the format to use for reading or writing the directory content. + */ + public static final short DirectoryContentFormatName = 40; + + /** * Content of “{0}” directory. */ public static final short DirectoryContent_1 = 35; @@ -158,6 +183,16 @@ public final class Resources extends Ind public static final short FeatureNotFound_2 = 17; /** + * A {1,choice,0#file|1#directory} already exists at “{0}”. + */ + public static final short FileAlreadyExists_2 = 45; + + /** + * The “{0}” file is not a directory of resources. + */ + public static final short FileIsNotAResourceDirectory_1 = 44; + + /** * Whether to assemble trajectory fragments (lines in CSV file) in a single feature instance. */ public static final short FoliationRepresentation = 38; @@ -184,16 +219,41 @@ public final class Resources extends Ind public static final short InconsistentNameComponents_2 = 10; /** + * Resource “{0}” does not have an identifier. + */ + public static final short MissingResourceIdentifier_1 = 42; + + /** * Missing scheme in “{0}” URI. */ public static final short MissingSchemeInURI_1 = 11; /** + * No directory of resources found at “{0}”. + */ + public static final short NoSuchResourceDirectory_1 = 46; + + /** + * Resource “{1}” is not part of aggregate “{0}”. + */ + public static final short NoSuchResourceInAggregate_2 = 50; + + /** + * Resource “{0}” is not a writable feature set. + */ + public static final short NotAWritableFeatureSet_1 = 47; + + /** * Processing executed on {0}. */ public static final short ProcessingExecutedOn_1 = 12; /** + * A resource already exists at “{0}”. + */ + public static final short ResourceAlreadyExists_1 = 48; + + /** * More than one resource have the “{1}” identifier in the “{0}” data store. */ public static final short ResourceIdentifierCollision_2 = 23;
Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties [ISO-8859-1] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources.properties [ISO-8859-1] Sat Feb 24 15:36:52 2018 @@ -16,35 +16,47 @@ # # -# Resources in this file are for "sis-netcdf" usage only and should not be used by any other module. +# Resources in this file are for "sis-storage" 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. # AmbiguousName_4 = Name \u201c{3}\u201d is ambiguous because it can be understood as either \u201c{1}\u201d or \u201c{2}\u201d in the context of \u201c{0}\u201d data. -CanNotGetCommonMetadata_2 = Can not get metadata common to \u201c{0}\u201d files. Reason: {1} +CanNotCreateFolderStore_1 = Can not create resources based on the content of \u201c{0}\u201d directory. +CanNotGetCommonMetadata_2 = Can not get metadata common to \u201c{0}\u201d files. The reason is: {1} CanNotReadCRS_WKT_1 = Can not read the Coordinate Reference System (CRS) Well Known Text (WKT) in \u201c{0}\u201d. CanNotReadDirectory_1 = Can not read \u201c{0}\u201d directory. CanNotReadFile_2 = Can not read \u201c{1}\u201d as a file in the {0} format. CanNotReadFile_3 = Can not read line {2} of \u201c{1}\u201d as part of a file in the {0} format. CanNotReadFile_4 = Can not read line {2} (after column {3}) of \u201c{1}\u201d as part of a file in the {0} format. +CanNotRemoveResource_2 = Can not remove resource \u201c{1}\u201d from aggregate \u201c{0}\u201d. +CanNotStoreResourceType_2 = Can not save resources of type \u2018{1}\u2019 in a \u201c{0}\u201d store. ClosedReader_1 = This {0} reader is closed. ClosedWriter_1 = This {0} writer is closed. ConcurrentRead_1 = One or more read operations are in progress in the \u201c{0}\u201d data store. ConcurrentWrite_1 = A write operation is in progress in the \u201c{0}\u201d data store. +DataStoreCreate = Whether to allow new data store creation if the source to open does not already exist. DataStoreEncoding = Character encoding used by the data store. DataStoreLocale = Formating conventions of dates and numbers. DataStoreLocation = Data store location as a file or URL. DataStoreTimeZone = Timezone of dates in the data store. DirectoryContent_1 = Content of \u201c{0}\u201d directory. +DirectoryContentFormatName = Name of the format to use for reading or writing the directory content. FeatureAlreadyPresent_2 = A feature named \u201c{1}\u201d is already present in the \u201c{0}\u201d data store. FeatureNotFound_2 = Feature \u201c{1}\u201d has not been found in the \u201c{0}\u201d data store. +FileAlreadyExists_2 = A {1,choice,0#file|1#directory} already exists at \u201c{0}\u201d. +FileIsNotAResourceDirectory_1 = The \u201c{0}\u201d file is not a directory of resources. FoliationRepresentation = Whether to assemble trajectory fragments (lines in CSV file) in a single feature instance. ExcessiveStringSize_3 = Character string in the \u201c{0}\u201d file is too long. The string has {2} characters while the limit is {1}. IllegalFeatureType_2 = The {0} data store does not accept features of type \u201c{1}\u201d. IllegalInputTypeForReader_2 = The {0} reader does not accept inputs of type \u2018{1}\u2019. IllegalOutputTypeForWriter_2 = The {0} writer does not accept outputs of type \u2018{1}\u2019. InconsistentNameComponents_2 = Components of the \u201c{1}\u201d name are inconsistent with those of the name previously binded in \u201c{0}\u201d data store. +MissingResourceIdentifier_1 = Resource \u201c{0}\u201d does not have an identifier. MissingSchemeInURI_1 = Missing scheme in \u201c{0}\u201d URI. +NoSuchResourceDirectory_1 = No directory of resources found at \u201c{0}\u201d. +NoSuchResourceInAggregate_2 = Resource \u201c{1}\u201d is not part of aggregate \u201c{0}\u201d. +NotAWritableFeatureSet_1 = Resource \u201c{0}\u201d is not a writable feature set. ProcessingExecutedOn_1 = Processing executed on {0}. +ResourceAlreadyExists_1 = A resource already exists at \u201c{0}\u201d. ResourceIdentifierCollision_2 = More than one resource have the \u201c{1}\u201d identifier in the \u201c{0}\u201d data store. ResourceNotFound_2 = No resource found for the \u201c{1}\u201d identifier in the \u201c{0}\u201d data store. ShallBeDeclaredBefore_2 = The \u201c{1}\u201d element must be declared before \u201c{0}\u201d. Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties [ISO-8859-1] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/Resources_fr.properties [ISO-8859-1] Sat Feb 24 15:36:52 2018 @@ -25,31 +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. -CanNotGetCommonMetadata_2 = Ne peut pas obtenir les m\u00e9ta-donn\u00e9es communes aux fichiers \u00ab\u202f{0}\u202f\u00bb. Raison\u2008: {1} +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\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. Copied: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java (from r1825247, sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java) URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java?p2=sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java&p1=sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java&r1=1825247&r2=1825249&rev=1825249&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java [UTF-8] Sat Feb 24 15:36:52 2018 @@ -38,7 +38,7 @@ import org.apache.sis.util.CharSequences import org.apache.sis.util.Classes; // Branch-dependent imports -import org.opengis.feature.Feature; +import org.apache.sis.feature.AbstractFeature; /** @@ -292,7 +292,7 @@ public final class StoreUtilities extend */ public static void copy(final FeatureSet source, final WritableFeatureSet target) throws DataStoreException { target.updateType(source.getType()); - try (Stream<Feature> stream = source.features(false)) { + try (Stream<AbstractFeature> stream = source.features(false)) { target.add(stream.iterator()); } } Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java [UTF-8] Sat Feb 24 15:36:52 2018 @@ -94,17 +94,24 @@ 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. @@ -113,6 +120,7 @@ public abstract class URIDataStore exten 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); } @@ -176,6 +184,8 @@ public abstract class URIDataStore exten /** * 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. @@ -186,7 +196,7 @@ public abstract class URIDataStore exten throws IllegalOpenParameterException { ParameterNotFoundException cause = null; - try { + if (parameters != null) try { final Object location = parameters.parameter(LOCATION).getValue(); if (location != null) { return new StorageConnector(location); @@ -202,7 +212,7 @@ public abstract class URIDataStore exten /** * 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/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/FeatureIterator.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/FeatureIterator.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/FeatureIterator.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/FeatureIterator.java [UTF-8] Sat Feb 24 15:36:52 2018 @@ -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/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/StoreProvider.java [UTF-8] Sat Feb 24 15:36:52 2018 @@ -29,7 +29,7 @@ import org.apache.sis.storage.StorageCon 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; @@ -48,7 +48,9 @@ import org.apache.sis.util.ArgumentCheck * @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. Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/FolderStoreProvider.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/FolderStoreProvider.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/FolderStoreProvider.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/FolderStoreProvider.java [UTF-8] Sat Feb 24 15:36:52 2018 @@ -16,13 +16,17 @@ */ 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; @@ -39,6 +43,9 @@ import org.apache.sis.util.logging.Loggi 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; // Branch-dependent imports @@ -52,15 +59,16 @@ import org.apache.sis.parameter.DefaultP * * @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. @@ -78,6 +86,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; @@ -88,8 +102,9 @@ public final class FolderStoreProvider e 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); + 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); + PARAMETERS = builder.addName(NAME).createGroup(location, LOCALE, TIMEZONE, ENCODING, FORMAT, URIDataStore.Provider.CREATE_PARAM); } /** @@ -101,8 +116,6 @@ public final class FolderStoreProvider e /** * The unique instance of this provider. - * - * @see #open(Path) */ public static final FolderStoreProvider INSTANCE = new FolderStoreProvider(); @@ -157,6 +170,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. @@ -164,12 +179,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; } /** @@ -186,17 +278,10 @@ public final class FolderStoreProvider e connector.setOption(OptionKey.LOCALE, pg.getValue(LOCALE)); connector.setOption(OptionKey.TIMEZONE, pg.getValue(TIMEZONE)); connector.setOption(OptionKey.ENCODING, pg.getValue(ENCODING)); - return open(connector); - } - - /** - * 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)); + final EnumSet<StandardOpenOption> options = EnumSet.of(StandardOpenOption.WRITE); + if (Boolean.TRUE.equals(pg.getValue(URIDataStore.Provider.CREATE_PARAM))) { + options.add(StandardOpenOption.CREATE); + } + return open(connector, pg.getValue(FORMAT), options); } } Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/Store.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/Store.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/Store.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/Store.java [UTF-8] Sat Feb 24 15:36:52 2018 @@ -22,6 +22,8 @@ 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; @@ -29,8 +31,6 @@ import java.nio.file.DirectoryStream; import java.nio.file.DirectoryIteratorException; import java.io.IOException; import java.io.UncheckedIOException; -import java.util.logging.Level; -import java.util.concurrent.ConcurrentHashMap; import org.opengis.metadata.Metadata; import org.opengis.metadata.maintenance.ScopeCode; import org.opengis.parameter.ParameterValueGroup; @@ -46,6 +46,7 @@ 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; @@ -67,36 +68,36 @@ import org.apache.sis.internal.storage.R * * @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. @@ -110,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. @@ -120,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; } /** @@ -145,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; } /** @@ -157,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; } @@ -202,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. @@ -228,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); @@ -259,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()); @@ -268,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. } @@ -294,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/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/package-info.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/package-info.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/package-info.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/folder/package-info.java [UTF-8] Sat Feb 24 15:36:52 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/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/Store.java [UTF-8] Sat Feb 24 15:36:52 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/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/wkt/StoreProvider.java [UTF-8] Sat Feb 24 15:36:52 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/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/StoreProvider.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/StoreProvider.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/StoreProvider.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/xml/StoreProvider.java [UTF-8] Sat Feb 24 15:36:52 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/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/Aggregate.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/Aggregate.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/Aggregate.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/Aggregate.java [UTF-8] Sat Feb 24 15:36:52 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 {@code 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/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java [UTF-8] Sat Feb 24 15:36:52 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/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=1825249&r1=1825248&r2=1825249&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] Sat Feb 24 15:36:52 2018 @@ -57,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 */ @@ -69,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() { @@ -156,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> * @@ -174,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() * @@ -280,6 +312,8 @@ 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 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=1825249&r1=1825248&r2=1825249&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] Sat Feb 24 15:36:52 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/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=1825249&r1=1825248&r2=1825249&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] Sat Feb 24 15:36:52 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/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSet.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSet.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSet.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/FeatureSet.java [UTF-8] Sat Feb 24 15:36:52 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.apache.sis.feature.AbstractFeature; import org.apache.sis.feature.DefaultFeatureType; @@ -35,7 +31,7 @@ import org.apache.sis.feature.DefaultFea * 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<AbstractFeature> 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 AbstractFeature> 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 AbstractFeature> 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 {@code 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 {@code 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 {@code 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 AbstractFeature> filter, UnaryOperator<AbstractFeature> updater) - throws ReadOnlyStorageException, DataStoreException - { - throw new ReadOnlyStorageException(this, Resources.Keys.StoreIsReadOnly); - } } Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/ReadOnlyStorageException.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/ReadOnlyStorageException.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/ReadOnlyStorageException.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/ReadOnlyStorageException.java [UTF-8] Sat Feb 24 15:36:52 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); - } } Copied: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/WritableFeatureSet.java (from r1825247, sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/WritableFeatureSet.java) URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/WritableFeatureSet.java?p2=sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/WritableFeatureSet.java&p1=sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/WritableFeatureSet.java&r1=1825247&r2=1825249&rev=1825249&view=diff ============================================================================== --- sis/branches/JDK8/storage/sis-storage/src/main/java/org/apache/sis/storage/WritableFeatureSet.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/WritableFeatureSet.java [UTF-8] Sat Feb 24 15:36:52 2018 @@ -22,8 +22,8 @@ import java.util.function.Predicate; import java.util.function.UnaryOperator; // Branch-dependent imports -import org.opengis.feature.Feature; -import org.opengis.feature.FeatureType; +import org.apache.sis.feature.AbstractFeature; +import org.apache.sis.feature.DefaultFeatureType; /** @@ -49,7 +49,7 @@ public interface WritableFeatureSet exte * @throws IllegalFeatureTypeException if the given type is not compatible with the types supported by the store. * @throws DataStoreException if another error occurred while changing the feature type. */ - void updateType(FeatureType newType) throws IllegalFeatureTypeException, DataStoreException; + void updateType(DefaultFeatureType newType) throws IllegalFeatureTypeException, DataStoreException; /** * Inserts new features in this {@code FeatureSet}. @@ -64,7 +64,7 @@ public interface WritableFeatureSet exte * @param features features to insert in this {@code FeatureSet}. * @throws DataStoreException if another error occurred while storing new features. */ - void add(Iterator<? extends Feature> features) throws DataStoreException; + void add(Iterator<? extends AbstractFeature> features) throws DataStoreException; /** * Removes all features from this {@code FeatureSet} which matches the given predicate. @@ -73,24 +73,24 @@ public interface WritableFeatureSet exte * @return {@code true} if any elements were removed. * @throws DataStoreException if another error occurred while removing features. */ - boolean removeIf(Predicate<? super Feature> filter) throws DataStoreException; + boolean removeIf(Predicate<? super AbstractFeature> filter) throws DataStoreException; /** * Updates all features from this {@code FeatureSet} which matches the given predicate. - * For each {@link Feature} instance matching the given {@link Predicate}, + * For each {@code 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 + * <li>If the operator returns a non-null {@code 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> * * @param filter a predicate which returns true for resources to be updated. - * @param updater operation called for each matching {@link Feature}. + * @param updater operation called for each matching {@code Feature}. * @throws DataStoreException if another error occurred while replacing features. */ - void replaceIf(Predicate<? super Feature> filter, UnaryOperator<Feature> updater) + void replaceIf(Predicate<? super AbstractFeature> filter, UnaryOperator<AbstractFeature> updater) throws DataStoreException; } Modified: sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/folder/StoreTest.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/folder/StoreTest.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/folder/StoreTest.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/folder/StoreTest.java [UTF-8] Sat Feb 24 15:36:52 2018 @@ -24,6 +24,7 @@ import java.nio.file.Paths; import java.util.Arrays; import java.util.HashSet; import java.util.Set; +import org.opengis.parameter.ParameterValueGroup; import org.opengis.metadata.identification.Identification; import org.apache.sis.metadata.iso.citation.Citations; import org.apache.sis.storage.Aggregate; @@ -42,7 +43,7 @@ import static org.junit.Assume.assumeTru * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.8 * @module */ @@ -68,9 +69,32 @@ public final strictfp class StoreTest ex */ @Test public void testComponents() throws URISyntaxException, DataStoreException, IOException { + final Set<String> identifiers = new HashSet<>(Arrays.asList("EPSG:4326", "Sample 1", "Sample 2", "Sample 3", "data4")); + final Path path = testDirectory(); + try (Store store = new Store(null, new StorageConnector(path), path, null)) { + assertEquals("Wrong number of data stores.", 4, store.components().size()); + verifyContent(store, identifiers); + } + if (!identifiers.isEmpty()) { + fail("Missing resources: " + identifiers); + } + } + + /** + * Verifies that specifying a format effectively restricts the number of resources to be found. + * + * @throws URISyntaxException if the URL to test data can not be converted to a path of the file system. + * @throws DataStoreException if an error occurred while reading the resources. + * @throws IOException if an I/O error occurs. + */ + @Test + public void testSearchProviderParameter() throws URISyntaxException, DataStoreException, IOException { final Set<String> identifiers = new HashSet<>(Arrays.asList("Sample 1", "Sample 2", "Sample 3", "data4")); - try (Store store = new Store(null, new StorageConnector(testDirectory()))) { - assertEquals("Expected three data stores.", 3, store.components().size()); + final ParameterValueGroup params = FolderStoreProvider.PARAMETERS.createValue(); + params.parameter("location").setValue(testDirectory()); + params.parameter("format").setValue("XML"); + try (Store store = (Store) FolderStoreProvider.INSTANCE.open(params)) { + assertEquals("Expected one less data store.", 3, store.components().size()); verifyContent(store, identifiers); } if (!identifiers.isEmpty()) { Modified: sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/storage/StorageConnectorTest.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/storage/StorageConnectorTest.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/storage/StorageConnectorTest.java [UTF-8] (original) +++ sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/storage/StorageConnectorTest.java [UTF-8] Sat Feb 24 15:36:52 2018 @@ -191,7 +191,7 @@ public final strictfp class StorageConne final byte[] sample = new byte[32]; data.readFully(sample); /* - * Request again the InputStream and read the same amount of bytes than above. The intend of this test + * Request again the InputStream and read the same amount of bytes than above. The intent of this test * is to verify that StorageConnector has reseted the InputStream position before to return it. * Note that this test requires InputStream implementations supporting mark/reset operations * (which is the case when the resource is an ordinary file, not an entry inside a JAR file), Modified: sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/GroupAsPolylineOperation.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/GroupAsPolylineOperation.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/GroupAsPolylineOperation.java [UTF-8] (original) +++ sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/GroupAsPolylineOperation.java [UTF-8] Sat Feb 24 15:36:52 2018 @@ -137,7 +137,7 @@ final class GroupAsPolylineOperation ext * The attribute resulting from execution if the {@link GroupAsPolylineOperation}. * The value is computed when first requested, then cached for this {@code Result} instance only. * Note that the cache is not used when {@code apply(Feature, ParameterValueGroup)} is invoked, - * causing a new value to be computed again. The intend is to behave as if the operation has been + * causing a new value to be computed again. The intent is to behave as if the operation has been * executed at {@code apply(…)} invocation time, even if we deferred the actual execution. * * @param <G> the root geometry class (implementation-dependent). Modified: sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Link.java URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Link.java?rev=1825249&r1=1825248&r2=1825249&view=diff ============================================================================== --- sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Link.java [UTF-8] (original) +++ sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Link.java [UTF-8] Sat Feb 24 15:36:52 2018 @@ -99,7 +99,7 @@ public final class Link implements Onlin /** * Invoked by JAXB after unmarshalling. If the {@linkplain #uri} is not set but the {@link #text} looks - * like a URI, uses that text. The intend is to handle link that should have been defined like below: + * like a URI, uses that text. The intent is to handle link that should have been defined like below: * * {@preformat xml * <link href="http://some.site.org"> 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=1825249&r1=1825248&r2=1825249&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] Sat Feb 24 15:36:52 2018 @@ -22,7 +22,7 @@ import org.apache.sis.storage.DataStore; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.StorageConnector; 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.xml.stream.StaxDataStoreProvider; import org.apache.sis.measure.Range; import org.apache.sis.util.Version; @@ -34,11 +34,13 @@ import org.apache.sis.util.Version; * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.0 * @since 0.8 * @module */ -@Capabilities({Capability.READ, Capability.WRITE}) +@StoreMetadata(formatName = "GPX", + fileSuffixes = "xml", + capabilities = {Capability.READ, Capability.WRITE}) public final class StoreProvider extends StaxDataStoreProvider { /** * The "1.0" version.
