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=1809404&r1=1809403&r2=1809404&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 Sep 23 11:47:20 2017
@@ -25,6 +25,7 @@
# 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.
+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}.
@@ -32,6 +33,11 @@ ClosedReader_1 = Ce l
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.
+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.
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.
@@ -44,6 +50,7 @@ ProcessingExecutedOn_1 = Trai
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.
+SharedDirectory_1 = Le r\u00e9pertoire \u00ab\u202f{0}\u202f\u00bb est utilis\u00e9 plus d\u2019une fois \u00e0 cause des liens symboliques.
StoreIsReadOnly = Les op\u00e9rations d\u2019\u00e9criture ne sont pas support\u00e9es.
StreamIsForwardOnly_1 = Ne peut pas reculer dans le flux de donn\u00e9es \u00ab\u202f{0}\u202f\u00bb.
StreamIsNotReadable_1 = Les donn\u00e9es de \u00ab\u202f{0}\u202f\u00bb ne sont pas accessibles en lecture.
@@ -52,3 +59,4 @@ StreamIsReadOnce_1 = Les
StreamIsWriteOnce_1 = Ne peut pas revenir sur les donn\u00e9es d\u00e9j\u00e0 \u00e9crites dans \u00ab\u202f{0}\u202f\u00bb.
UndefinedParameter_2 = Ne peut pas ouvrir une source de donn\u00e9es {0} sans le param\u00e8tre \u00ab\u202f{1}\u202f\u00bb.
UnknownFormatFor_1 = Le format de \u00ab\u202f{0}\u202f\u00bb n\u2019est pas reconnu.
+UsedOnlyIfNotEncoded = Utilis\u00e9 seulement si cette information n\u2019est pas encod\u00e9e avec les donn\u00e9es.
Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreTypeDetector.java
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreTypeDetector.java?rev=1809404&r1=1809403&r2=1809404&view=diff
==============================================================================
--- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreTypeDetector.java [UTF-8] (original)
+++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreTypeDetector.java [UTF-8] Sat Sep 23 11:47:20 2017
@@ -33,7 +33,7 @@ import org.apache.sis.storage.DataStoreE
* @since 0.4
* @module
*/
-public class StoreTypeDetector extends FileTypeDetector {
+public final class StoreTypeDetector extends FileTypeDetector {
/**
* Constructor for {@link java.util.ServiceLoader}.
*/
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=1809404&r1=1809403&r2=1809404&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 Sep 23 11:47:20 2017
@@ -25,6 +25,7 @@ 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.internal.storage.io.IOUtilities;
/**
@@ -98,7 +99,8 @@ public abstract class URIDataStore exten
/**
* Description of the location parameter.
*/
- protected static final ParameterDescriptor<URI> LOCATION_PARAM = new ParameterBuilder()
+ public static final ParameterDescriptor<URI> LOCATION_PARAM = new ParameterBuilder()
+ .setDescription(Resources.formatInternational(Resources.Keys.DataStoreLocation))
.addName(LOCATION)
.setRequired(true)
.create(URI.class, null);
@@ -120,7 +122,7 @@ public abstract class URIDataStore exten
* This method creates the descriptor only when first needed. Subclasses can override the
* {@link #build(ParameterBuilder)} method if they need to modify the descriptor to create.
*
- * @return description of the parameters required for opening a {@link DataStore}.
+ * @return description of the parameters required or accepted for opening a {@link DataStore}.
*/
@Override
public final ParameterDescriptorGroup getOpenParameters() {
@@ -160,4 +162,23 @@ public abstract class URIDataStore exten
return new ParameterBuilder().addName(name).createGroup(LOCATION_PARAM);
}
}
+
+ /**
+ * 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
+ * only an identifier without title would be invalid.
+ *
+ * @param builder where to add the title or identifier.
+ */
+ protected final void addTitleOrIdentifier(final MetadataBuilder builder) {
+ if (location != null) {
+ /*
+ * The getDisplayName() contract does not allow us to use it as an identifier. However current implementation
+ * in super.getDisplayName() returns the filename provided that the input was a URI, URL, File or Path. Since
+ * all those types are convertibles to URI, we can use (location != null) as a criterion.
+ */
+ builder.addTitleOrIdentifier(IOUtilities.filenameWithoutExtension(super.getDisplayName()), MetadataBuilder.Scope.ALL);
+ }
+ }
}
Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java?rev=1809404&r1=1809403&r2=1809404&view=diff
==============================================================================
--- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java [UTF-8] (original)
+++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/csv/Store.java [UTF-8] Sat Sep 23 11:47:20 2017
@@ -83,7 +83,7 @@ import org.apache.sis.feature.AbstractId
* @since 0.7
* @module
*/
-public final class Store extends URIDataStore implements FeatureSet {
+final class Store extends URIDataStore implements FeatureSet {
/**
* The character at the beginning of lines to ignore in the header.
* Note that this is not part of OGC Moving Feature Specification.
@@ -615,6 +615,7 @@ public final class Store extends URIData
listeners.warning(null, e);
}
builder.addFeatureType(featureType, null);
+ addTitleOrIdentifier(builder);
metadata = builder.build(true);
}
return metadata;
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=1809404&r1=1809390&r2=1809404&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 Sep 23 11:47:20 2017
@@ -43,6 +43,9 @@ import org.apache.sis.internal.storage.R
import org.apache.sis.internal.storage.URIDataStore;
import org.apache.sis.setup.OptionKey;
+// Branch-dependent imports
+import org.apache.sis.referencing.AbstractIdentifiedObject;
+
/**
* The provider of {@link Store} instances. This provider is intentionally <strong>not</strong> registered
@@ -87,7 +90,7 @@ public final class FolderStoreProvider e
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);
+ location = builder.addName( LOCATION ).setDescription(((AbstractIdentifiedObject) URIDataStore.Provider.LOCATION_PARAM).getDescription()).setRequired(true) .create(Path.class, null);
PARAMETERS = builder.addName( NAME ).createGroup(location, LOCALE, TIMEZONE, ENCODING);
}
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=1809404&r1=1809390&r2=1809404&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 Sep 23 11:47:20 2017
@@ -188,7 +188,7 @@ final class Store extends DataStore impl
if (metadata == null) {
final MetadataBuilder mb = new MetadataBuilder();
final String name = getDisplayName();
- mb.addResourceScope(ScopeCode.COLLECTION, Resources.formatInternational(Resources.Keys.DirectoryContent_1, name));
+ mb.addResourceScope(ScopeCode.valueOf("COLLECTION"), Resources.formatInternational(Resources.Keys.DirectoryContent_1, name));
mb.addLanguage(locale, MetadataBuilder.Scope.RESOURCE);
mb.addEncoding(encoding, MetadataBuilder.Scope.RESOURCE);
mb.addTitleOrIdentifier(name, MetadataBuilder.Scope.ALL);
Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelData.java
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelData.java?rev=1809404&r1=1809403&r2=1809404&view=diff
==============================================================================
--- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelData.java [UTF-8] (original)
+++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelData.java [UTF-8] Sat Sep 23 11:47:20 2017
@@ -49,7 +49,8 @@ public abstract class ChannelData implem
private static final int BIT_OFFSET_SIZE = 3;
/**
- * A file identifier used only for formatting error message.
+ * A short identifier (typically a filename without path) used for formatting error message.
+ * This is often the value given by {@link org.apache.sis.storage.StorageConnector#getStorageName()}.
*/
public final String filename;
@@ -114,7 +115,7 @@ public abstract class ChannelData implem
* Creates a new instance for the given channel and using the given buffer.
* The channel is not stored by this class - it shall be stored by the subclass.
*
- * @param filename a file identifier used only for formatting error message.
+ * @param filename a short identifier (typically a filename without path) used for formatting error message.
* @param channel the channel from where data are read or where to wrote.
* @param buffer the buffer where to store the data.
* @throws IOException if an error occurred while reading the channel.
Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java?rev=1809404&r1=1809403&r2=1809404&view=diff
==============================================================================
--- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java [UTF-8] (original)
+++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataInput.java [UTF-8] Sat Sep 23 11:47:20 2017
@@ -26,6 +26,7 @@ import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.FloatBuffer;
import java.nio.DoubleBuffer;
+import java.nio.charset.Charset;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SeekableByteChannel;
import org.apache.sis.internal.storage.Resources;
@@ -79,7 +80,7 @@ public class ChannelDataInput extends Ch
* If the buffer already contains some data, then the {@code filled} argument shall be {@code true}.
* Otherwise (e.g. if it is a newly created buffer), then {@code filled} shall be {@code false}.
*
- * @param filename a file identifier used only for formatting error message.
+ * @param filename a short identifier (typically a filename without path) used for formatting error message.
* @param channel the channel from where data are read.
* @param buffer the buffer where to copy the data.
* @param filled {@code true} if the buffer already contains data, or {@code false} if it needs
@@ -825,7 +826,7 @@ public class ChannelDataInput extends Ch
* @return the string decoded from the {@code length} next bytes.
* @throws IOException if an error occurred while reading the bytes, or if the given encoding is invalid.
*/
- public final String readString(final int length, final String encoding) throws IOException {
+ public final String readString(final int length, final Charset encoding) throws IOException {
if (buffer.hasArray() && length <= buffer.capacity()) {
ensureBufferContains(length);
final int position = buffer.position(); // Must be after 'ensureBufferContains(int)'.
Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java?rev=1809404&r1=1809403&r2=1809404&view=diff
==============================================================================
--- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java [UTF-8] (original)
+++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelFactory.java [UTF-8] Sat Sep 23 11:47:20 2017
@@ -21,6 +21,8 @@ import java.util.EnumSet;
import java.util.HashSet;
import java.util.Collections;
import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -43,8 +45,10 @@ import java.nio.channels.ReadableByteCha
import java.nio.channels.WritableByteChannel;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.logging.WarningListeners;
import org.apache.sis.internal.system.Modules;
import org.apache.sis.internal.storage.Resources;
+import org.apache.sis.storage.DataStore;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.ForwardOnlyStorageException;
@@ -53,13 +57,14 @@ import org.apache.sis.storage.ForwardOnl
* Opens a readable channel for a given input object (URL, input stream, <i>etc</i>).
* The {@link #prepare prepare(…)} method analyzes the given input {@link Object} and tries to return a factory instance
* capable to open at least one {@link ReadableByteChannel} for that input. For some kinds of input like {@link Path} or
- * {@link URL}, the {@link #reader(String)} method can be invoked an arbitrary amount of times for creating as many channels
- * as needed. But for other kinds of input like {@link InputStream}, only one channel can be returned. In such case,
- * only the first {@link #reader(String)} method invocation will succeed and all subsequent ones will throw an exception.
+ * {@link URL}, the {@link #reader reader(…)} method can be invoked an arbitrary amount of times for creating as many
+ * channels as needed. But for other kinds of input like {@link InputStream}, only one channel can be returned.
+ * In such case, only the first {@link #reader reader(…)} method invocation will succeed and all subsequent ones
+ * will throw an exception.
*
* <div class="section">Multi-threading</div>
* This class is not thread-safe, except for the static {@link #prepare prepare(…)} method.
- * Callers are responsible for synchronizing their call to any member methods ({@link #reader(String)}, <i>etc</i>).
+ * Callers are responsible for synchronizing their call to any member methods ({@link #reader reader(…)}, <i>etc</i>).
*
* @author Martin Desruisseaux (Geomatys)
* @author Johann Sorel (Geomatys)
@@ -211,7 +216,9 @@ public abstract class ChannelFactory {
* Unlikely to happen. But if it happens anyway, try to open the channel in a
* way less surprising for the user (closer to the object he has specified).
*/
- return new Fallback(file, e);
+ if (file.isFile()) {
+ return new Fallback(file, e);
+ }
}
}
}
@@ -223,24 +230,26 @@ public abstract class ChannelFactory {
if (storage instanceof URL) {
final URL file = (URL) storage;
return new ChannelFactory() {
- @Override public ReadableByteChannel reader(String filename) throws IOException {
+ @Override public ReadableByteChannel reader(String filename, WarningListeners<DataStore> listeners) throws IOException {
return Channels.newChannel(file.openStream());
}
- @Override public WritableByteChannel writer(String filename) throws IOException {
+ @Override public WritableByteChannel writer(String filename, WarningListeners<DataStore> listeners) throws IOException {
return Channels.newChannel(file.openConnection().getOutputStream());
}
};
}
if (storage instanceof Path) {
final Path path = (Path) storage;
- return new ChannelFactory() {
- @Override public ReadableByteChannel reader(String filename) throws IOException {
- return Files.newByteChannel(path, optionSet);
- }
- @Override public WritableByteChannel writer(String filename) throws IOException {
- return Files.newByteChannel(path, optionSet);
- }
- };
+ if (Files.isRegularFile(path)) {
+ return new ChannelFactory() {
+ @Override public ReadableByteChannel reader(String filename, WarningListeners<DataStore> listeners) throws IOException {
+ return Files.newByteChannel(path, optionSet);
+ }
+ @Override public WritableByteChannel writer(String filename, WarningListeners<DataStore> listeners) throws IOException {
+ return Files.newByteChannel(path, optionSet);
+ }
+ };
+ }
}
return null;
}
@@ -259,9 +268,9 @@ public abstract class ChannelFactory {
/**
* Returns {@code true} if this factory is capable to create another reader. This method returns {@code false}
- * if this factory is capable to create only one channel and {@link #reader(String)} has already been invoked.
+ * if this factory is capable to create only one channel and {@link #reader reader(…)} has already been invoked.
*
- * @return whether {@link #reader(String)} can be invoked.
+ * @return whether {@link #reader reader(…)} or {@link #writer writer(…)} can be invoked.
*/
public boolean canOpen() {
return true;
@@ -272,12 +281,15 @@ public abstract class ChannelFactory {
* it is caller's responsibility to wrap the stream in a {@link java.io.BufferedInputStream} if desired.
*
* @param filename data store name to report in case of failure.
+ * @param listeners set of registered {@code WarningListener}s for the data store, or {@code null} if none.
* @return the input stream.
* @throws DataStoreException if the channel is read-once.
* @throws IOException if the input stream or its underlying byte channel can not be created.
*/
- public InputStream inputStream(final String filename) throws DataStoreException, IOException {
- return Channels.newInputStream(reader(filename));
+ public InputStream inputStream(String filename, WarningListeners<DataStore> listeners)
+ throws DataStoreException, IOException
+ {
+ return Channels.newInputStream(reader(filename, listeners));
}
/**
@@ -285,12 +297,15 @@ public abstract class ChannelFactory {
* it is caller's responsibility to wrap the stream in a {@link java.io.BufferedOutputStream} if desired.
*
* @param filename data store name to report in case of failure.
+ * @param listeners set of registered {@code WarningListener}s for the data store, or {@code null} if none.
* @return the output stream.
* @throws DataStoreException if the channel is write-once.
* @throws IOException if the output stream or its underlying byte channel can not be created.
*/
- public OutputStream outputStream(final String filename) throws DataStoreException, IOException {
- return Channels.newOutputStream(writer(filename));
+ public OutputStream outputStream(String filename, WarningListeners<DataStore> listeners)
+ throws DataStoreException, IOException
+ {
+ return Channels.newOutputStream(writer(filename, listeners));
}
/**
@@ -299,11 +314,13 @@ public abstract class ChannelFactory {
* this method throws an exception.
*
* @param filename data store name to report in case of failure.
+ * @param listeners set of registered {@code WarningListener}s for the data store, or {@code null} if none.
* @return the channel for the given input.
* @throws DataStoreException if the channel is read-once.
* @throws IOException if an error occurred while opening the channel.
*/
- public abstract ReadableByteChannel reader(String filename) throws DataStoreException, IOException;
+ public abstract ReadableByteChannel reader(String filename, WarningListeners<DataStore> listeners)
+ throws DataStoreException, IOException;
/**
* Returns a byte channel from the output given to the {@link #prepare prepare(…)} method.
@@ -311,11 +328,13 @@ public abstract class ChannelFactory {
* this method throws an exception.
*
* @param filename data store name to report in case of failure.
+ * @param listeners set of registered {@code WarningListener}s for the data store, or {@code null} if none.
* @return the channel for the given output.
* @throws DataStoreException if the channel is write-once.
* @throws IOException if an error occurred while opening the channel.
*/
- public abstract WritableByteChannel writer(String filename) throws DataStoreException, IOException;
+ public abstract WritableByteChannel writer(String filename, WarningListeners<DataStore> listeners)
+ throws DataStoreException, IOException;
/**
* A factory that returns an existing channel <cite>as-is</cite>.
@@ -343,7 +362,7 @@ public abstract class ChannelFactory {
}
/**
- * Returns whether {@link #reader(String)} or {@link #writer(String)} can be invoked.
+ * Returns whether {@link #reader reader(…)} or {@link #writer writer(…)} can be invoked.
*/
@Override
public boolean canOpen() {
@@ -355,7 +374,9 @@ public abstract class ChannelFactory {
* throws an exception on all subsequent invocations.
*/
@Override
- public ReadableByteChannel reader(final String filename) throws DataStoreException, IOException {
+ public ReadableByteChannel reader(final String filename, final WarningListeners<DataStore> listeners)
+ throws DataStoreException, IOException
+ {
final Channel in = channel;
if (in instanceof ReadableByteChannel) {
channel = null;
@@ -375,7 +396,9 @@ public abstract class ChannelFactory {
* throws an exception on all subsequent invocations.
*/
@Override
- public WritableByteChannel writer(final String filename) throws DataStoreException, IOException {
+ public WritableByteChannel writer(final String filename, final WarningListeners<DataStore> listeners)
+ throws DataStoreException, IOException
+ {
final Channel out = channel;
if (out instanceof WritableByteChannel) {
channel = null;
@@ -425,7 +448,9 @@ public abstract class ChannelFactory {
* {@link File} to a {@link Path}. On all subsequent invocations, the file is opened silently.</p>
*/
@Override
- public FileInputStream inputStream(String filename) throws IOException {
+ public FileInputStream inputStream(final String filename, final WarningListeners<DataStore> listeners)
+ throws IOException
+ {
final FileInputStream in;
try {
in = new FileInputStream(file);
@@ -441,7 +466,7 @@ public abstract class ChannelFactory {
* But the exception was nevertheless unexpected, so log its stack trace in order
* to allow the developer to check if there is something wrong.
*/
- warning();
+ warning("inputStream", listeners);
return in;
}
@@ -453,7 +478,9 @@ public abstract class ChannelFactory {
* {@link File} to a {@link Path}. On all subsequent invocations, the file is opened silently.</p>
*/
@Override
- public FileOutputStream outputStream(String filename) throws IOException {
+ public FileOutputStream outputStream(final String filename, final WarningListeners<DataStore> listeners)
+ throws IOException
+ {
final FileOutputStream out;
try {
out = new FileOutputStream(file);
@@ -464,7 +491,7 @@ public abstract class ChannelFactory {
}
throw ioe;
}
- warning();
+ warning("outputStream", listeners);
return out;
}
@@ -473,10 +500,19 @@ public abstract class ChannelFactory {
* Since the exception was nevertheless unexpected, log its stack trace in order to allow the developer
* to check if there is something wrong.
*/
- private void warning() {
+ private void warning(final String method, final WarningListeners<DataStore> listeners) {
if (cause != null) {
- Logging.unexpectedException(Logging.getLogger(Modules.STORAGE), ChannelFactory.class, "prepare", cause);
+ final LogRecord record = new LogRecord(Level.WARNING, cause.toString());
+ record.setLoggerName(Modules.STORAGE);
+ record.setSourceMethodName(method);
+ record.setSourceClassName(ChannelFactory.class.getName());
+ record.setThrown(cause);
cause = null;
+ if (listeners != null) {
+ listeners.warning(record);
+ } else {
+ Logging.getLogger(Modules.STORAGE).log(record);
+ }
}
}
@@ -484,16 +520,16 @@ public abstract class ChannelFactory {
* Opens a new channel for the file given at construction time.
*/
@Override
- public ReadableByteChannel reader(String filename) throws IOException {
- return inputStream(filename).getChannel();
+ public ReadableByteChannel reader(String filename, WarningListeners<DataStore> listeners) throws IOException {
+ return inputStream(filename, listeners).getChannel();
}
/**
* Opens a new channel for the file given at construction time.
*/
@Override
- public WritableByteChannel writer(String filename) throws IOException {
- return outputStream(filename).getChannel();
+ public WritableByteChannel writer(String filename, WarningListeners<DataStore> listeners) throws IOException {
+ return outputStream(filename, listeners).getChannel();
}
}
Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java?rev=1809404&r1=1809403&r2=1809404&view=diff
==============================================================================
--- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java [UTF-8] (original)
+++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/IOUtilities.java [UTF-8] Sat Sep 23 11:47:20 2017
@@ -164,6 +164,29 @@ public final class IOUtilities extends S
}
/**
+ * Returns the given path without the directories and without the extension.
+ * For example if the given path is {@code "/Users/name/Map.png"}, then this
+ * method returns {@code "Map"}.
+ *
+ * @param path the path from which to get the filename without extension, or {@code null}.
+ * @return the filename without extension, or {@code null} if none.
+ */
+ public static String filenameWithoutExtension(String path) {
+ if (path != null) {
+ int s = path.lastIndexOf(File.separatorChar);
+ if (s < 0 && File.separatorChar != '/') {
+ s = path.lastIndexOf('/');
+ }
+ int e = path.lastIndexOf('.');
+ if (e <= ++s) {
+ e = path.length();
+ }
+ path = path.substring(s, e);
+ }
+ return path;
+ }
+
+ /**
* Encodes the characters that are not legal for the {@link URI#URI(String)} constructor.
* Note that in addition to unreserved characters ("{@code _-!.~'()*}"), the reserved
* characters ("{@code ?/[]@}") and the punctuation characters ("{@code ,;:$&+=}")
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=1809404&r1=1809403&r2=1809404&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 Sep 23 11:47:20 2017
@@ -189,6 +189,7 @@ final class Store extends URIDataStore {
builder.addReferenceSystem((ReferenceSystem) object);
}
}
+ addTitleOrIdentifier(builder);
metadata = builder.build(true);
}
return metadata;
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=1809404&r1=1809403&r2=1809404&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 Sep 23 11:47:20 2017
@@ -63,7 +63,7 @@ import org.opengis.referencing.crs.Coord
*/
public interface Aggregate extends Resource {
/**
- * Returns the children resources of this aggregate. The returned collection contains at least all
+ * Returns the children resources of this aggregate. The returned collection contains
* the resources listed by their name in the following {@linkplain #getMetadata() metadata} elements.
* The returned collection may contain more resources if the metadata are incomplete,
* and the resources do not need to be in the same order:
@@ -80,6 +80,11 @@ public interface Aggregate extends Resou
* {@link org.apache.sis.metadata.iso.identification.AbstractIdentification#getCitation() citation} /
* {@link org.apache.sis.metadata.iso.citation.DefaultCitation#getTitle() title}</blockquote>
*
+ * <div class="section">Lazy resource instantiation</div>
+ * If the collection instantiates components only when first needed, and if a checked exception occurs
+ * during invocation of a {@link Collection} or {@link java.util.Iterator} method, then the collection
+ * or the iterator should wrap the exception in a {@link org.apache.sis.util.collection.BackingStoreException}.
+ *
* @return all children resources that are components of this aggregate. Never {@code null}.
* @throws DataStoreException if an error occurred while fetching the components.
*/
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=1809404&r1=1809403&r2=1809404&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 Sep 23 11:47:20 2017
@@ -122,6 +122,32 @@ public abstract class DataStore implemen
}
/**
+ * Creates a new instance as a child of another data store instance.
+ * The new instance inherits the parent {@linkplain #getProvider() provider}.
+ * The parent and the child share the same listeners: adding or removing a listener to a parent
+ * adds or removes the same listeners to all children, and conversely.
+ *
+ * @param parent the parent data store, or {@code null} if none.
+ * @param connector information about the storage (URL, stream, reader instance, <i>etc</i>).
+ * @throws DataStoreException if an error occurred while creating the data store for the given storage.
+ *
+ * @since 0.8
+ */
+ protected DataStore(final DataStore parent, final StorageConnector connector) throws DataStoreException {
+ ArgumentChecks.ensureNonNull("connector", connector);
+ if (parent != null) {
+ provider = parent.provider;
+ locale = parent.locale;
+ listeners = parent.listeners;
+ } else {
+ provider = null;
+ locale = Locale.getDefault(Locale.Category.DISPLAY);
+ listeners = new WarningListeners<>(this);
+ }
+ name = connector.getStorageName();
+ }
+
+ /**
* Returns the factory that created this {@code DataStore} instance.
* The provider gives additional information on this {@code DataStore} such as a format description
* and a list of parameters that can be used for opening data stores of the same class.
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=1809404&r1=1809403&r2=1809404&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 Sep 23 11:47:20 2017
@@ -173,7 +173,7 @@ public abstract class DataStoreProvider
* <li>Parameters can more easily be serialized in XML or configuration files.</li>
* </ul></div>
*
- * @return description of the parameters required for opening a {@link DataStore}.
+ * @return description of the parameters required or accepted for opening a {@link DataStore}.
*
* @see #open(ParameterValueGroup)
* @see DataStore#getOpenParameters()
@@ -299,7 +299,6 @@ public abstract class DataStoreProvider
throw new IllegalOpenParameterException(Resources.format(Resources.Keys.UndefinedParameter_2,
getShortName(), LOCATION), cause);
}
- final StorageConnector connector = new StorageConnector(location);
- return open(connector);
+ return open(new StorageConnector(location));
}
}
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=1809404&r1=1809403&r2=1809404&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 Sep 23 11:47:20 2017
@@ -245,7 +245,9 @@ search: while (!deferred.isEmpty
}
}
if (open && selected == null) {
- throw new UnsupportedStorageException(null, Resources.Keys.UnknownFormatFor_1, connector.getStorageName());
+ @SuppressWarnings("null")
+ final String name = connector.getStorageName();
+ throw new UnsupportedStorageException(null, Resources.Keys.UnknownFormatFor_1, name);
}
return selected;
}
Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java?rev=1809404&r1=1809403&r2=1809404&view=diff
==============================================================================
--- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java [UTF-8] (original)
+++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/storage/StorageConnector.java [UTF-8] Sat Sep 23 11:47:20 2017
@@ -597,8 +597,10 @@ public class StorageConnector implements
}
/**
- * Returns a short name of the input/output object. The default implementation performs
- * the following choices based on the type of the {@linkplain #getStorage() storage} object:
+ * Returns a short name of the input/output object. For example if the storage is a file,
+ * this method returns the filename without the path (but including the file extension).
+ * The default implementation performs the following choices based on the type of the
+ * {@linkplain #getStorage() storage} object:
*
* <ul>
* <li>For {@link java.nio.file.Path}, {@link java.io.File}, {@link java.net.URI} or {@link java.net.URL}
@@ -921,7 +923,7 @@ public class StorageConnector implements
* (potentially an InputStream). We need to remember this chain in 'Coupled' objects.
*/
final String name = getStorageName();
- final ReadableByteChannel channel = factory.reader(name);
+ final ReadableByteChannel channel = factory.reader(name, null);
addView(ReadableByteChannel.class, channel, null, factory.isCoupled() ? CASCADE_ON_RESET : 0);
ByteBuffer buffer = getOption(OptionKey.BYTE_BUFFER); // User-supplied buffer.
if (buffer == null) {
@@ -1374,8 +1376,9 @@ public class StorageConnector implements
op.setValue(TableColumn.NAME, "options");
op.setValue(TableColumn.VALUE, options);
}
- if (views != null) {
- views.get(null).append(root.newChild(), views);
+ final Coupled c = getView(null);
+ if (c != null) {
+ c.append(root.newChild(), views);
}
return table.toString();
}
Modified: sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataInputTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataInputTest.java?rev=1809404&r1=1809403&r2=1809404&view=diff
==============================================================================
--- sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataInputTest.java [UTF-8] (original)
+++ sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/ChannelDataInputTest.java [UTF-8] Sat Sep 23 11:47:20 2017
@@ -21,6 +21,7 @@ import java.io.DataInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
import org.junit.Test;
import static org.junit.Assert.*;
@@ -134,7 +135,7 @@ public final strictfp class ChannelDataI
}
/**
- * Tests the {@link ChannelDataInput#readString(int, String)} method.
+ * Tests the {@link ChannelDataInput#readString(int, Charset)} method.
*
* @throws IOException should never happen since we read and write in memory only.
*/
@@ -146,7 +147,7 @@ public final strictfp class ChannelDataI
final ChannelDataInput input = new ChannelDataInput("testReadString",
new DripByteChannel(array, random, 1, 32),
ByteBuffer.allocate(array.length + 4), false);
- assertEquals(expected, input.readString(array.length, "UTF-8"));
+ assertEquals(expected, input.readString(array.length, StandardCharsets.UTF_8));
assertFalse(input.buffer.hasRemaining());
}
Modified: sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/IOUtilitiesTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/IOUtilitiesTest.java?rev=1809404&r1=1809403&r2=1809404&view=diff
==============================================================================
--- sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/IOUtilitiesTest.java [UTF-8] (original)
+++ sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/io/IOUtilitiesTest.java [UTF-8] Sat Sep 23 11:47:20 2017
@@ -35,7 +35,7 @@ import static org.junit.Assert.*;
*
* @author Martin Desruisseaux (Geomatys)
* @author Johann Sorel (Geomatys)
- * @version 0.4
+ * @version 0.8
* @since 0.3
* @module
*/
@@ -112,6 +112,17 @@ public final strictfp class IOUtilitiesT
}
/**
+ * Tests {@link IOUtilities#filenameWithoutExtension(String)}.
+ */
+ @Test
+ public void testFilenameWithoutExtension() {
+ assertEquals("Map", IOUtilities.filenameWithoutExtension("/Users/name/Map.png"));
+ assertEquals("Map", IOUtilities.filenameWithoutExtension("/Users/name/Map"));
+ assertEquals("Map", IOUtilities.filenameWithoutExtension("Map.png"));
+ assertEquals(".hidden", IOUtilities.filenameWithoutExtension("/Users/name/.hidden"));
+ }
+
+ /**
* Tests {@link IOUtilities#encodeURI(String)}.
*/
@Test
Modified: sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java?rev=1809404&r1=1809403&r2=1809404&view=diff
==============================================================================
--- sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java [UTF-8] (original)
+++ sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/test/suite/StorageTestSuite.java [UTF-8] Sat Sep 23 11:47:20 2017
@@ -48,6 +48,7 @@ import org.junit.BeforeClass;
org.apache.sis.internal.storage.wkt.StoreTest.class,
org.apache.sis.internal.storage.csv.StoreProviderTest.class,
org.apache.sis.internal.storage.csv.StoreTest.class,
+ org.apache.sis.internal.storage.folder.StoreTest.class,
org.apache.sis.storage.DataStoresTest.class
})
public final strictfp class StorageTestSuite extends TestSuite {
Modified: sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Store.java
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Store.java?rev=1809404&r1=1809403&r2=1809404&view=diff
==============================================================================
--- sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Store.java [UTF-8] (original)
+++ sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Store.java [UTF-8] Sat Sep 23 11:47:20 2017
@@ -29,7 +29,7 @@ import org.apache.sis.storage.DataStoreC
import org.apache.sis.storage.ConcurrentReadException;
import org.apache.sis.storage.IllegalNameException;
import org.apache.sis.internal.system.DefaultFactories;
-import org.apache.sis.internal.storage.AbstractDataSet;
+import org.apache.sis.internal.storage.AbstractResource;
import org.apache.sis.internal.storage.xml.stream.StaxDataStore;
import org.apache.sis.util.collection.BackingStoreException;
import org.apache.sis.util.ArgumentChecks;
@@ -177,7 +177,7 @@ public final class Store extends StaxDat
*/
@Override
public Envelope getEnvelope() throws DataStoreException {
- return AbstractDataSet.envelope(getMetadata());
+ return AbstractResource.envelope(getMetadata());
}
/**
Modified: sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java?rev=1809404&r1=1809403&r2=1809404&view=diff
==============================================================================
--- sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java [UTF-8] (original)
+++ sis/trunk/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/xml/stream/StaxDataStore.java [UTF-8] Sat Sep 23 11:47:20 2017
@@ -125,9 +125,9 @@ public abstract class StaxDataStore exte
* <p>We keep this reference as long as possible in order to use {@link #mark()} and {@link #reset()}
* instead than creating new streams for re-reading the data. If we can not reset the stream but can
* create a new one, then this field will become a reference to the new stream. This change should be
- * done only in last resort, when there is no way to reuse the existing stream. This is because the
- * streams created by {@link ChannelFactory#inputStream(String)} are not of the same kind than the
- * streams created by {@link StorageConnector}.</p>
+ * done only in last resort, when there is no way to reuse the existing stream. This is because the
+ * streams created by {@link ChannelFactory#inputStream(String, WarningListeners)} are not of the same
+ * kind than the streams created by {@link StorageConnector}.</p>
*
* @see #close()
*/
@@ -473,7 +473,7 @@ public abstract class StaxDataStore exte
if (channelFactory == null) {
throw new ForwardOnlyStorageException(getLocale(), name, StandardOpenOption.READ);
}
- inputOrFile = input = channelFactory.inputStream(name);
+ inputOrFile = input = channelFactory.inputStream(name, listeners);
type = InputType.STREAM;
if (stream == null) {
stream = input;
|