This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new 8e76ba4 Modify the policy about default implementation in AbstractResource: construct metadata from getIdentifier() and getEnvelope() instead than providing a default implementation of those methods based on metadata. A side effect of this work is to provide an implementation of JoinFeatureSet.getEnvelope() based on newly added Envelopes.union(Envelope...) ùethod.
8e76ba4 is described below
commit 8e76ba427e64e892f7be45580a77f4fa8d5362df
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Mon Nov 19 00:22:12 2018 +0100
Modify the policy about default implementation in AbstractResource: construct metadata from getIdentifier() and getEnvelope() instead than providing a default implementation of those methods based on metadata. A side effect of this work is to provide an implementation of JoinFeatureSet.getEnvelope() based on newly added Envelopes.union(Envelope...) ùethod.
---
.../org/apache/sis/geometry/EnvelopeReducer.java | 160 +++++++++++++++++++++
.../java/org/apache/sis/geometry/Envelopes.java | 40 ++++++
.../org/apache/sis/geometry/GeneralEnvelope.java | 2 +
.../apache/sis/internal/referencing/Resources.java | 5 +
.../sis/internal/referencing/Resources.properties | 1 +
.../internal/referencing/Resources_fr.properties | 1 +
.../main/java/org/apache/sis/referencing/CRS.java | 3 +-
.../apache/sis/geometry/EnvelopeReducerTest.java | 95 ++++++++++++
.../sis/test/suite/ReferencingTestSuite.java | 1 +
.../sis/storage/geotiff/ImageFileDirectory.java | 5 +-
.../sis/internal/netcdf/impl/FeaturesInfo.java | 9 --
.../sis/internal/netcdf/ucar/FeaturesWrapper.java | 6 -
.../sis/internal/storage/AbstractFeatureSet.java | 43 ++----
.../sis/internal/storage/AbstractGridResource.java | 71 +++++++++
.../sis/internal/storage/AbstractResource.java | 120 ++++------------
.../sis/internal/storage/JoinFeatureSet.java | 52 ++++---
.../sis/internal/storage/MemoryFeatureSet.java | 11 --
.../sis/internal/storage/StoreUtilities.java | 37 ++++-
.../sis/internal/storage/query/FeatureSubset.java | 9 --
.../main/java/org/apache/sis/storage/DataSet.java | 5 +-
.../java/org/apache/sis/storage/DataStore.java | 31 +++-
.../org/apache/sis/internal/storage/gpx/Store.java | 4 +-
22 files changed, 527 insertions(+), 184 deletions(-)
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/geometry/EnvelopeReducer.java b/core/sis-referencing/src/main/java/org/apache/sis/geometry/EnvelopeReducer.java
new file mode 100644
index 0000000..e4b4752
--- /dev/null
+++ b/core/sis-referencing/src/main/java/org/apache/sis/geometry/EnvelopeReducer.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.geometry;
+
+import org.apache.sis.internal.referencing.Resources;
+import org.opengis.geometry.Envelope;
+import org.opengis.metadata.extent.GeographicBoundingBox;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.TransformException;
+import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.util.Utilities;
+
+
+/**
+ * Applies union or intersection operations on a sequence of envelopes.
+ * This utility class infers the a common coordinate reference system
+ * for performing the reduce operation.
+ *
+ * @author Martin Desruisseaux (IRD, Geomatys)
+ * @version 1.0
+ *
+ * @see Envelopes#union(Envelope...)
+ * @see Envelopes#intersect(Envelope...)
+ *
+ * @since 1.0
+ * @module
+ */
+class EnvelopeReducer {
+ /**
+ * A reducer performing the {@linkplain GeneralEnvelope#add(Envelope) union} operation.
+ *
+ * @see Envelopes#union(Envelope...)
+ */
+ static final EnvelopeReducer UNION = new EnvelopeReducer();
+
+ /**
+ * A reducer performing the {@linkplain GeneralEnvelope#intersect(Envelope) intersection} operation.
+ *
+ * @see Envelopes#intersect(Envelope...)
+ */
+ static final EnvelopeReducer INTERSECT = new EnvelopeReducer() {
+ @Override void reduce(GeneralEnvelope result, Envelope other) {
+ result.intersect(other);
+ }
+
+ @Override void reduce(DefaultGeographicBoundingBox result, GeographicBoundingBox other) {
+ result.intersect(other);
+ }
+ };
+
+ /**
+ * Creates a new reducer. We should have a singleton instance for each type of reduce operation.
+ */
+ EnvelopeReducer() {
+ }
+
+ /**
+ * Applies the reduce operation on the given {@code result} envelope.
+ * The result is modified in-place.
+ */
+ void reduce(GeneralEnvelope result, Envelope other) {
+ result.add(other);
+ }
+
+ /**
+ * Applies the reduce operation on the given {@code result} bounding box.
+ * The result is modified in-place.
+ */
+ void reduce(DefaultGeographicBoundingBox result, GeographicBoundingBox other) {
+ result.add(other);
+ }
+
+ /**
+ * Reduces all given envelopes, transforming them to a common CRS if necessary.
+ * If all envelopes use the same CRS (ignoring metadata) or if the CRS of all envelopes is {@code null},
+ * then the reduce operation is performed without transforming any envelope. Otherwise all envelopes are
+ * transformed to a {@linkplain CRS#suggestCommonTarget common CRS} before reduction.
+ * The CRS of the returned envelope may different than the CRS of all given envelopes.
+ *
+ * @param envelopes the envelopes for which to perform the reduce operation. Null elements are ignored.
+ * @return result of reduce operation, or {@code null} if the given array does not contain non-null elements.
+ * @throws TransformException if this method can not determine a common CRS, or if a transformation failed.
+ */
+ final GeneralEnvelope reduce(final Envelope[] envelopes) throws TransformException {
+ /*
+ * First, compute the unions or intersections of all envelopes having a common CRS
+ * without performing any reprojection. In the common case where all envelopes use
+ * the same CRS, this will result in an array having only one non-null element.
+ */
+ final GeneralEnvelope[] reduced = new GeneralEnvelope[envelopes.length];
+ int count = 0;
+merge: for (final Envelope envelope : envelopes) {
+ if (envelope != null) {
+ final CoordinateReferenceSystem crs = envelope.getCoordinateReferenceSystem();
+ for (int i=0; i<count; i++) {
+ final GeneralEnvelope previous = reduced[i];
+ if (Utilities.equalsIgnoreMetadata(crs, previous.getCoordinateReferenceSystem())) {
+ reduce(previous, envelope);
+ continue merge;
+ }
+ }
+ reduced[count++] = new GeneralEnvelope(envelope);
+ }
+ }
+ switch (count) {
+ case 0: return null;
+ case 1: return reduced[0];
+ }
+ /*
+ * Compute the geographic bounding box of all remaining elements to reduce.
+ * This will be used for choosing a common CRS.
+ */
+ CoordinateReferenceSystem[] crs = new CoordinateReferenceSystem[count];
+ DefaultGeographicBoundingBox more = new DefaultGeographicBoundingBox();
+ DefaultGeographicBoundingBox bbox = null;
+ for (int i=0; i<count; i++) {
+ final GeneralEnvelope e = reduced[i];
+ crs[i] = e.getCoordinateReferenceSystem();
+ more.setBounds(e);
+ if (i == 0) {
+ bbox = more;
+ more = new DefaultGeographicBoundingBox();
+ } else {
+ reduce(bbox, more);
+ }
+ }
+ /*
+ * Now transform all remaining envelopes, so we can perform final reduction.
+ */
+ final CoordinateReferenceSystem target = CRS.suggestCommonTarget(bbox, crs);
+ if (target == null) {
+ throw new TransformException(Resources.format(Resources.Keys.CanNotFindCommonCRS));
+ }
+ GeneralEnvelope result = null;
+ for (int i=0; i<count; i++) {
+ final Envelope other = Envelopes.transform(reduced[i], target);
+ if (result == null) {
+ result = GeneralEnvelope.castOrCopy(other);
+ } else {
+ reduce(result, other);
+ }
+ }
+ return result;
+ }
+}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/geometry/Envelopes.java b/core/sis-referencing/src/main/java/org/apache/sis/geometry/Envelopes.java
index 0bea159..243d58a 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/geometry/Envelopes.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/geometry/Envelopes.java
@@ -156,6 +156,46 @@ public final class Envelopes extends Static {
}
/**
+ * Computes the union of all given envelopes, transforming them to a common CRS if necessary.
+ * If all envelopes use the same CRS ({@link ComparisonMode#IGNORE_METADATA ignoring metadata})
+ * or if the CRS of all envelopes is {@code null}, then the {@linkplain GeneralEnvelope#add(Envelope)
+ * union is computed} without transforming any envelope. Otherwise all envelopes are transformed to a
+ * {@linkplain CRS#suggestCommonTarget common CRS} before union is computed.
+ * The CRS of the returned envelope may different than the CRS of all given envelopes.
+ *
+ * @param envelopes the envelopes for which to compute union. Null elements are ignored.
+ * @return union of given envelopes, or {@code null} if the given array does not contain non-null elements.
+ * @throws TransformException if this method can not determine a common CRS, or if a transformation failed.
+ *
+ * @see GeneralEnvelope#add(Envelope)
+ *
+ * @since 1.0
+ */
+ public static GeneralEnvelope union(final Envelope... envelopes) throws TransformException {
+ return EnvelopeReducer.UNION.reduce(envelopes);
+ }
+
+ /**
+ * Computes the intersection of all given envelopes, transforming them to a common CRS if necessary.
+ * If all envelopes use the same CRS ({@link ComparisonMode#IGNORE_METADATA ignoring metadata})
+ * or if the CRS of all envelopes is {@code null}, then the {@linkplain GeneralEnvelope#intersect(Envelope)
+ * intersection is computed} without transforming any envelope. Otherwise all envelopes are transformed to a
+ * {@linkplain CRS#suggestCommonTarget common CRS} before intersection is computed.
+ * The CRS of the returned envelope may different than the CRS of all given envelopes.
+ *
+ * @param envelopes the envelopes for which to compute intersection. Null elements are ignored.
+ * @return intersection of given envelopes, or {@code null} if the given array does not contain non-null elements.
+ * @throws TransformException if this method can not determine a common CRS, or if a transformation failed.
+ *
+ * @see GeneralEnvelope#intersect(Envelope)
+ *
+ * @since 1.0
+ */
+ public static GeneralEnvelope intersect(final Envelope... envelopes) throws TransformException {
+ return EnvelopeReducer.INTERSECT.reduce(envelopes);
+ }
+
+ /**
* Invoked when a recoverable exception occurred. Those exceptions must be minor enough
* that they can be silently ignored in most cases.
*/
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralEnvelope.java b/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralEnvelope.java
index cf2f0fb..195fc27 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralEnvelope.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/geometry/GeneralEnvelope.java
@@ -601,6 +601,7 @@ public class GeneralEnvelope extends ArrayEnvelope implements Cloneable, Seriali
* @throws MismatchedDimensionException if the given envelope does not have the expected number of dimensions.
* @throws AssertionError if assertions are enabled and the envelopes have mismatched CRS.
*
+ * @see Envelopes#union(Envelope...)
* @see org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox#add(GeographicBoundingBox)
*/
public void add(final Envelope envelope) throws MismatchedDimensionException {
@@ -726,6 +727,7 @@ public class GeneralEnvelope extends ArrayEnvelope implements Cloneable, Seriali
* @throws MismatchedDimensionException if the given envelope does not have the expected number of dimensions.
* @throws AssertionError if assertions are enabled and the envelopes have mismatched CRS.
*
+ * @see Envelopes#intersect(Envelope...)
* @see org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox#intersect(GeographicBoundingBox)
*/
public void intersect(final Envelope envelope) throws MismatchedDimensionException {
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
index 3f22dcb..4688fda 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
@@ -88,6 +88,11 @@ public final class Resources extends IndexedResourceBundle {
public static final short CanNotCreateObjectAsInstanceOf_2 = 4;
/**
+ * Can not find a coordinate reference system common to all given envelopes.
+ */
+ public static final short CanNotFindCommonCRS = 82;
+
+ /**
* Can not infer a grid size from the given values in {0} range.
*/
public static final short CanNotInferGridSizeFromValues_1 = 75;
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
index 0fb2c64..c11c140 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
@@ -46,6 +46,7 @@ CanNotCombineUriAsType_1 = Can not create objects of type \u2018{0}\u20
CanNotComputeDerivative = Can not compute the coordinate operation derivative.
CanNotConcatenateTransforms_2 = Can not concatenate transforms \u201c{0}\u201d and \u201c{1}\u201d.
CanNotCreateObjectAsInstanceOf_2 = Can not create an object of type \u201c{1}\u201d as an instance of class \u2018{0}\u2019.
+CanNotFindCommonCRS = Can not find a coordinate reference system common to all given envelopes.
CanNotInferGridSizeFromValues_1 = Can not infer a grid size from the given values in {0} range.
CanNotInstantiateGeodeticObject_1 = Can not instantiate geodetic object for \u201c{0}\u201d.
CanNotMapAxisToDirection_1 = Can not map an axis from the specified coordinate system to the \u201c{0}\u201d direction.
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
index 41cf4df..6f829a7 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
@@ -51,6 +51,7 @@ CanNotCombineUriAsType_1 = Ne peut pas cr\u00e9er d\u2019objets de type
CanNotComputeDerivative = La d\u00e9riv\u00e9 de l\u2019op\u00e9ration sur les coordonn\u00e9es ne peut pas \u00eatre calcul\u00e9e.
CanNotConcatenateTransforms_2 = Les transformations \u00ab\u202f{0}\u202f\u00bb et \u00ab\u202f{1}\u202f\u00bb ne peuvent pas \u00eatre combin\u00e9es.
CanNotCreateObjectAsInstanceOf_2 = Ne peut pas cr\u00e9er un objet du type \u00ab\u202f{1}\u202f\u00bb comme une instance de la classe \u2018{0}\u2019.
+CanNotFindCommonCRS = Ne peut pas trouver un syst\u00e8me de r\u00e9f\u00e9rence des coordonn\u00e9es commun pour toutes les enveloppes donn\u00e9es.
CanNotInferGridSizeFromValues_1 = Ne peut pas inf\u00e9rer une taille de grille \u00e0 partir des valeurs donn\u00e9es dans la plage {0}.
CanNotInstantiateGeodeticObject_1 = Ne peut pas cr\u00e9er l\u2019objet g\u00e9od\u00e9tique pour \u00ab\u202f{0}\u202f\u00bb.
CanNotMapAxisToDirection_1 = Aucun axe du syst\u00e8me de coordonn\u00e9es sp\u00e9cifi\u00e9 n\u2019a pu \u00eatre associ\u00e9 \u00e0 la direction \u00ab\u202f{0}\u202f\u00bb.
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
index 30dd2f1..abce0c2 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
@@ -442,8 +442,9 @@ public final class CRS extends Static {
* for choosing a common CRS which is less likely to fail.</div>
*
* @param regionOfInterest the geographic area for which the coordinate operations will be applied,
- * or {@code null} if unknown.
+ * or {@code null} if unknown. Will be intersected with CRS domains of validity.
* @param sourceCRS the coordinate reference systems for which a common target CRS is desired.
+ * May contain {@code null} elements, in which case this method returns {@code null}.
* @return a CRS that may be used as a common target for all the given source CRS in the given region of interest,
* or {@code null} if this method did not find a common target CRS. The returned CRS may be different than
* all given CRS.
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/geometry/EnvelopeReducerTest.java b/core/sis-referencing/src/test/java/org/apache/sis/geometry/EnvelopeReducerTest.java
new file mode 100644
index 0000000..f32fd09
--- /dev/null
+++ b/core/sis-referencing/src/test/java/org/apache/sis/geometry/EnvelopeReducerTest.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.geometry;
+
+import org.opengis.referencing.operation.TransformException;
+import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.test.DependsOn;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.apache.sis.test.ReferencingAssert.*;
+
+
+/**
+ * Tests the {@link EnvelopeReducer} class.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since 1.0
+ * @module
+ */
+@DependsOn(EnvelopesTest.class)
+public final strictfp class EnvelopeReducerTest extends TestCase {
+ /**
+ * The envelopes on which to perform an operation.
+ */
+ private final GeneralEnvelope[] sources;
+
+ /**
+ * Creates an envelope for the given coordinate values.
+ */
+ private static GeneralEnvelope createFromExtremums(boolean latlon, double xmin, double ymin, double xmax, double ymax) {
+ final CommonCRS crs = CommonCRS.WGS84;
+ final GeneralEnvelope env;
+ if (latlon) {
+ env = new GeneralEnvelope(crs.geographic());
+ env.setRange(1, xmin, xmax);
+ env.setRange(0, ymin, ymax);
+ } else {
+ env = new GeneralEnvelope(crs.normalizedGeographic());
+ env.setRange(0, xmin, xmax);
+ env.setRange(1, ymin, ymax);
+ }
+ return env;
+ }
+
+ /**
+ * Creates a new test case.
+ */
+ public EnvelopeReducerTest() {
+ sources = new GeneralEnvelope[] {
+ createFromExtremums(true, 50, -5, 60, 15),
+ createFromExtremums(false, 44, 3, 52, 16),
+ createFromExtremums(true, 48, -2, 54, 12)
+ };
+ }
+
+ /**
+ * Test {@link Envelopes#union(Envelope...)} method.
+ *
+ * @throws TransformException if an error occurred while transforming an envelope.
+ */
+ @Test
+ public void testUnion() throws TransformException {
+ final GeneralEnvelope expected = createFromExtremums(true, 44, -5, 60, 16);
+ final GeneralEnvelope actual = Envelopes.union(sources);
+ assertEnvelopeEquals(expected, actual, STRICT);
+ }
+
+ /**
+ * Test {@link Envelopes#intersect(Envelope...)} method.
+ *
+ * @throws TransformException if an error occurred while transforming an envelope.
+ */
+ @Test
+ public void testIntersect() throws TransformException {
+ final GeneralEnvelope expected = createFromExtremums(true, 50, 3, 52, 12);
+ final GeneralEnvelope actual = Envelopes.intersect(sources);
+ assertEnvelopeEquals(expected, actual, STRICT);
+ }
+}
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java b/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
index 3a6f889..d1465d5 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
@@ -250,6 +250,7 @@ import org.junit.BeforeClass;
org.apache.sis.geometry.CurveExtremumTest.class,
org.apache.sis.geometry.Shapes2DTest.class, // Simpler than EnvelopesTest.
org.apache.sis.geometry.EnvelopesTest.class,
+ org.apache.sis.geometry.EnvelopeReducerTest.class,
org.apache.sis.internal.referencing.ServicesForMetadataTest.class,
org.apache.sis.internal.metadata.EllipsoidalHeightCombinerTest.class,
org.apache.sis.geometry.CoordinateFormatTest.class,
diff --git a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java
index 16e57b2..4cc3df0 100644
--- a/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java
+++ b/storage/sis-geotiff/src/main/java/org/apache/sis/storage/geotiff/ImageFileDirectory.java
@@ -30,12 +30,11 @@ import org.opengis.metadata.citation.DateType;
import org.opengis.util.FactoryException;
import org.opengis.util.GenericName;
import org.apache.sis.internal.geotiff.Resources;
-import org.apache.sis.internal.storage.AbstractResource;
import org.apache.sis.internal.storage.MetadataBuilder;
+import org.apache.sis.internal.storage.AbstractGridResource;
import org.apache.sis.internal.storage.io.ChannelDataInput;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.DataStoreContentException;
-import org.apache.sis.storage.GridCoverageResource;
import org.apache.sis.coverage.grid.GridGeometry;
import org.apache.sis.coverage.grid.GridExtent;
import org.apache.sis.math.Vector;
@@ -57,7 +56,7 @@ import org.apache.sis.measure.Units;
* @since 0.8
* @module
*/
-final class ImageFileDirectory extends AbstractResource implements GridCoverageResource {
+final class ImageFileDirectory extends AbstractGridResource {
/**
* Possible value for the {@link #tileTagFamily} field. That field tells whether image tiling
* was specified using the {@code Tile*} family of TIFF tags or the {@code Strip*} family.
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java
index 764afe6..dbc84e1 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/impl/FeaturesInfo.java
@@ -28,7 +28,6 @@ import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import java.util.function.Consumer;
import java.io.IOException;
-import org.opengis.util.GenericName;
import org.apache.sis.math.Vector;
import org.apache.sis.internal.netcdf.DataType;
import org.apache.sis.internal.netcdf.DiscreteSampling;
@@ -153,14 +152,6 @@ final class FeaturesInfo extends DiscreteSampling {
}
/**
- * Returns an identifier for the collection of features in the netCDF file.
- */
- @Override
- public GenericName getIdentifier() {
- return type.getName();
- }
-
- /**
* Returns {@code true} if the given attribute value is one of the {@code cf_role} attribute values
* supported by this implementation.
*/
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/FeaturesWrapper.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/FeaturesWrapper.java
index 226c977..4072b5c 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/FeaturesWrapper.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/ucar/FeaturesWrapper.java
@@ -17,7 +17,6 @@
package org.apache.sis.internal.netcdf.ucar;
import java.util.stream.Stream;
-import org.opengis.util.GenericName;
import org.apache.sis.storage.DataStore;
import org.apache.sis.setup.GeometryLibrary;
import org.apache.sis.internal.netcdf.DiscreteSampling;
@@ -56,11 +55,6 @@ final class FeaturesWrapper extends DiscreteSampling {
}
@Override
- public GenericName getIdentifier() {
- throw new UnsupportedOperationException(); // TODO
- }
-
- @Override
public FeatureType getType() {
throw new UnsupportedOperationException(); // TODO
}
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractFeatureSet.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractFeatureSet.java
index 8cd92d9..e386c4e 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractFeatureSet.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractFeatureSet.java
@@ -22,11 +22,7 @@ import org.apache.sis.storage.FeatureSet;
import org.apache.sis.storage.Query;
import org.apache.sis.storage.UnsupportedQueryException;
import org.apache.sis.internal.storage.query.SimpleQuery;
-import org.apache.sis.metadata.iso.DefaultMetadata;
-import org.apache.sis.metadata.iso.citation.DefaultCitation;
-import org.apache.sis.metadata.iso.identification.DefaultDataIdentification;
import org.apache.sis.util.logging.WarningListeners;
-import org.opengis.metadata.Metadata;
import org.opengis.util.GenericName;
// Branch-dependent imports
@@ -44,13 +40,6 @@ import org.opengis.feature.FeatureType;
*/
public abstract class AbstractFeatureSet extends AbstractResource implements FeatureSet {
/**
- * A description of this set of features, or {@code null} if not yet computed.
- * Those metadata are created by {@link #getMetadata()} when first needed.
- * Subclasses can set a value to this field directly.
- */
- protected Metadata metadata;
-
- /**
* Creates a new resource.
*
* @param listeners the set of registered warning listeners for the data store, or {@code null} if none.
@@ -70,32 +59,20 @@ public abstract class AbstractFeatureSet extends AbstractResource implements Fea
}
/**
- * Returns a description of this set of features.
- * Current implementation sets only the resource name; this may change in any future Apache SIS version.
+ * Returns the feature type name as the identifier for this resource.
+ *
+ * @return the resource identifier inferred from metadata, or {@code null} if none or ambiguous.
+ * @throws DataStoreException if an error occurred while fetching the identifier.
*
- * <div class="note"><b>Note:</b>
- * we currently do not set the geographic extent from the envelope because default {@link #getEnvelope()}
- * implementation itself invokes {@code getMetadata()}. Consequently requesting the envelope from this
- * method could create a never-ending loop.</div>
+ * @see DataStore#getIdentifier()
*/
@Override
- public synchronized Metadata getMetadata() throws DataStoreException {
- if (metadata == null) {
- final DefaultMetadata metadata = new DefaultMetadata();
- final FeatureType type = getType();
- if (type != null) {
- final GenericName name = type.getName();
- if (name != null) { // Paranoiac check (should never be null).
- final DefaultCitation citation = new DefaultCitation(name.toInternationalString());
- final DefaultDataIdentification identification = new DefaultDataIdentification();
- identification.setCitation(citation);
- }
- }
- // No geographic extent - see above javadoc.
- metadata.transition(DefaultMetadata.State.FINAL);
- this.metadata = metadata;
+ public GenericName getIdentifier() throws DataStoreException {
+ final FeatureType type = getType();
+ if (type != null) {
+ return type.getName();
}
- return metadata;
+ return null;
}
/**
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractGridResource.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractGridResource.java
new file mode 100644
index 0000000..9d967bb
--- /dev/null
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractGridResource.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.storage;
+
+import org.apache.sis.storage.DataStore;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.GridCoverageResource;
+import org.apache.sis.coverage.grid.GridGeometry;
+import org.apache.sis.storage.Resource;
+import org.apache.sis.util.logging.WarningListeners;
+import org.opengis.geometry.Envelope;
+
+
+/**
+ * Base class for implementations of {@link GridCoverageResource}.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.0
+ * @since 0.8
+ * @module
+ */
+public abstract class AbstractGridResource extends AbstractResource implements GridCoverageResource {
+ /**
+ * Creates a new resource.
+ *
+ * @param listeners the set of registered warning listeners for the data store, or {@code null} if none.
+ */
+ protected AbstractGridResource(final WarningListeners<DataStore> listeners) {
+ super(listeners);
+ }
+
+ /**
+ * Creates a new resource with the same warning listeners than the given resource,
+ * or {@code null} if the listeners are unknown.
+ *
+ * @param resource the resources from which to get the listeners, or {@code null} if none.
+ */
+ protected AbstractGridResource(final Resource resource) {
+ super(resource);
+ }
+
+ /**
+ * Returns the grid geometry envelope, or {@code null} if unknown.
+ * This implementation fetches the envelope from the grid geometry instead than from metadata.
+ *
+ * @return the grid geometry envelope, or {@code null}.
+ * @throws DataStoreException if an error occurred while computing the grid geometry.
+ */
+ @Override
+ public Envelope getEnvelope() throws DataStoreException {
+ final GridGeometry gg = getGridGeometry();
+ if (gg != null && gg.isDefined(GridGeometry.ENVELOPE)) {
+ return gg.getEnvelope();
+ }
+ return null;
+ }
+}
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java
index 511d86a..69f973f 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/AbstractResource.java
@@ -18,16 +18,8 @@ package org.apache.sis.internal.storage;
import java.util.Locale;
import org.opengis.util.GenericName;
-import org.opengis.geometry.Envelope;
import org.opengis.metadata.Metadata;
-import org.opengis.metadata.Identifier;
-import org.opengis.metadata.citation.Citation;
-import org.opengis.metadata.extent.Extent;
-import org.opengis.metadata.extent.GeographicBoundingBox;
-import org.opengis.metadata.extent.GeographicExtent;
-import org.opengis.metadata.identification.Identification;
-import org.apache.sis.referencing.NamedIdentifier;
-import org.apache.sis.geometry.GeneralEnvelope;
+import org.opengis.geometry.Envelope;
import org.apache.sis.util.Localized;
import org.apache.sis.util.logging.WarningListeners;
import org.apache.sis.storage.Resource;
@@ -35,6 +27,9 @@ import org.apache.sis.storage.DataStore;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.event.ChangeEvent;
import org.apache.sis.storage.event.ChangeListener;
+import org.apache.sis.metadata.iso.DefaultMetadata;
+import org.apache.sis.metadata.iso.citation.DefaultCitation;
+import org.apache.sis.metadata.iso.identification.DefaultDataIdentification;
/**
@@ -50,6 +45,16 @@ import org.apache.sis.storage.event.ChangeListener;
*/
public abstract class AbstractResource implements Resource, Localized {
/**
+ * A description of this resource as an unmodifiable metadata, or {@code null} if not yet computed.
+ * If non-null, this metadata shall contain at least the resource {@linkplain #getIdentifier() identifier}.
+ *
+ * <p>Those metadata are created by {@link #getMetadata()} when first needed.
+ * Subclasses can set a value to this field directly if they wish to bypass the
+ * default metadata creation process.</p>
+ */
+ protected Metadata metadata;
+
+ /**
* The set of registered warning listeners for the data store, or {@code null} if none.
*/
protected final WarningListeners<DataStore> listeners;
@@ -97,98 +102,35 @@ public abstract class AbstractResource implements Resource, Localized {
}
/**
- * Returns an identifier for this resource. The default implementation returns the first identifier
- * of {@code Metadata/identificationInfo/citation}, provided that exactly one such citation is found.
- * If more than one citation is found, then this method returns {@code null} since the identification
- * is considered ambiguous. This is the same default implementation than {@link DataStore#getIdentifier()}.
- *
- * @return the resource identifier inferred from metadata, or {@code null} if none or ambiguous.
- * @throws DataStoreException if an error occurred while fetching the identifier.
- *
- * @see DataStore#getIdentifier()
- */
- @Override
- public GenericName getIdentifier() throws DataStoreException {
- return identifier(getMetadata());
- }
-
- /**
- * Implementation of {@link #getIdentifier()}, provided as a separated method for implementations
- * that do not extend {@code AbstractResource}.
- *
- * @param metadata the metadata from which to infer the identifier, or {@code null}.
- * @return the resource identifier inferred from metadata, or {@code null} if none or ambiguous.
- *
- * @see StoreUtilities#getAnyIdentifier(Metadata, boolean)
- */
- public static GenericName identifier(final Metadata metadata) {
- if (metadata != null) {
- Citation citation = null;
- for (final Identification id : metadata.getIdentificationInfo()) {
- final Citation c = id.getCitation();
- if (c != null) {
- if (citation != null && citation != c) return null; // Ambiguity.
- citation = c;
- }
- }
- if (citation != null) {
- Identifier first = null;
- for (final Identifier c : citation.getIdentifiers()) {
- if (c instanceof GenericName) {
- return (GenericName) c;
- } else if (first == null) {
- first = c;
- }
- }
- if (first != null) {
- return new NamedIdentifier(first);
- }
- }
- }
- return null;
- }
-
- /**
* Returns the spatio-temporal envelope of this resource.
- * The default implementation computes the union of all {@link GeographicBoundingBox} in the resource metadata,
- * assuming the {@linkplain org.apache.sis.referencing.CommonCRS#defaultGeographic() default geographic CRS}
- * (usually WGS 84).
+ * The default implementation returns {@code null}.
*
* @return the spatio-temporal resource extent, or {@code null} if none.
- * @throws DataStoreException if an error occurred while reading or computing the envelope.
*
- * @see org.apache.sis.storage.DataSet#getEnvelope()
+ * @throws DataStoreException if an error occurred while reading or computing the envelope.
*/
public Envelope getEnvelope() throws DataStoreException {
- return envelope(getMetadata());
+ return null;
}
/**
- * Implementation of {@link #getEnvelope()}, provided as a separated method for
- * {@link org.apache.sis.storage.DataSet} implementations that do not extend {@code AbstractResource}.
- *
- * @param metadata the metadata from which to compute the envelope, or {@code null}.
- * @return the spatio-temporal resource extent, or {@code null} if none.
+ * Returns a description of this set of features.
+ * Current implementation sets only the resource name; this may change in any future Apache SIS version.
*/
- public static Envelope envelope(final Metadata metadata) {
- GeneralEnvelope bounds = null;
- if (metadata != null) {
- for (final Identification identification : metadata.getIdentificationInfo()) {
- for (final Extent extent : identification.getExtents()) {
- for (final GeographicExtent ge : extent.getGeographicElements()) {
- if (ge instanceof GeographicBoundingBox) {
- final GeneralEnvelope env = new GeneralEnvelope((GeographicBoundingBox) ge);
- if (bounds == null) {
- bounds = env;
- } else {
- bounds.add(env);
- }
- }
- }
- }
+ @Override
+ public synchronized Metadata getMetadata() throws DataStoreException {
+ if (metadata == null) {
+ final DefaultMetadata metadata = new DefaultMetadata();
+ final GenericName name = getIdentifier();
+ if (name != null) { // Paranoiac check (should never be null).
+ final DefaultCitation citation = new DefaultCitation(name.toInternationalString());
+ final DefaultDataIdentification identification = new DefaultDataIdentification();
+ identification.setCitation(citation);
}
+ metadata.transition(DefaultMetadata.State.FINAL);
+ this.metadata = metadata;
}
- return bounds;
+ return metadata;
}
/**
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/JoinFeatureSet.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/JoinFeatureSet.java
index f7e6e7f..27e22a4 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/JoinFeatureSet.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/JoinFeatureSet.java
@@ -17,6 +17,8 @@
package org.apache.sis.internal.storage;
import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Spliterator;
import java.util.function.Consumer;
@@ -24,14 +26,17 @@ import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.opengis.util.GenericName;
import org.opengis.geometry.Envelope;
+import org.opengis.referencing.operation.TransformException;
+import org.apache.sis.geometry.Envelopes;
import org.apache.sis.feature.FeatureOperations;
import org.apache.sis.feature.DefaultFeatureType;
import org.apache.sis.feature.DefaultAssociationRole;
import org.apache.sis.internal.feature.AttributeConvention;
import org.apache.sis.internal.storage.query.SimpleQuery;
import org.apache.sis.storage.DataStore;
-import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.FeatureSet;
+import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.DataStoreReferencingException;
import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.collection.BackingStoreException;
import org.apache.sis.util.collection.Containers;
@@ -255,16 +260,6 @@ public class JoinFeatureSet extends AbstractFeatureSet {
}
/**
- * Returns the name of the join operation resulting feature type.
- *
- * @return resulting feature type name.
- */
- @Override
- public GenericName getIdentifier() {
- return type.getName();
- }
-
- /**
* Creates a minimal {@code properties} map for feature type or property type constructors.
* This minimalist map contain only the mandatory entry, which is the name.
*/
@@ -294,15 +289,38 @@ public class JoinFeatureSet extends AbstractFeatureSet {
}
/**
- * Returns {@code null} since computing an envelope would be costly for this set.
+ * Returns the union of the envelope on both sides, or {@code null} if none.
+ * The coordinate reference system is the CRS of the "main" side.
*
- * @return always {@code null} in default implementation.
- *
- * @todo Revisit the method contract by allowing the envelope to be only an estimation, potentially larger.
+ * @return union of envelopes of both sides, or {@code null}.
+ * @throws DataStoreException if an error occurred while computing the envelope.
*/
@Override
- public Envelope getEnvelope() {
- return null;
+ public Envelope getEnvelope() throws DataStoreException {
+ final List<Envelope> envelopes = new ArrayList<>();
+ getEnvelopes(envelopes);
+ try {
+ return Envelopes.union(envelopes.toArray(new Envelope[envelopes.size()]));
+ } catch (TransformException e) {
+ throw new DataStoreReferencingException(e);
+ }
+ }
+
+ /**
+ * Adds the envelopes of the two joined feature set in the given list. If some of the feature sets
+ * are themselves joined feature sets, then this method traverses them recursively. We compute the
+ * union of all envelopes at once after we got all envelopes.
+ */
+ private void getEnvelopes(final List<Envelope> addTo) throws DataStoreException {
+ boolean side = swapSides;
+ do {
+ final FeatureSet f = side ? right : left;
+ if (f instanceof JoinFeatureSet) {
+ ((JoinFeatureSet) f).getEnvelopes(addTo);
+ } else {
+ addTo.add(f.getEnvelope());
+ }
+ } while ((side = !side) != swapSides);
}
/**
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryFeatureSet.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryFeatureSet.java
index 6757d43..32a911d 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryFeatureSet.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/MemoryFeatureSet.java
@@ -18,7 +18,6 @@ package org.apache.sis.internal.storage;
import java.util.Collection;
import java.util.stream.Stream;
-import org.opengis.util.GenericName;
import org.opengis.metadata.Metadata;
import org.apache.sis.storage.DataStore;
import org.apache.sis.util.ArgumentChecks;
@@ -73,16 +72,6 @@ public final class MemoryFeatureSet extends AbstractFeatureSet {
}
/**
- * Returns the name of the feature type.
- *
- * @return feature type name.
- */
- @Override
- public GenericName getIdentifier() {
- return type.getName();
- }
-
- /**
* Returns the type common to all feature instances in this set.
*
* @return a description of properties that are common to all features in this dataset.
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java
index 2b08ef4..2557a06 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/StoreUtilities.java
@@ -21,7 +21,11 @@ import java.util.stream.Stream;
import java.nio.file.OpenOption;
import java.nio.file.StandardOpenOption;
import org.opengis.util.GenericName;
+import org.opengis.geometry.Envelope;
import org.opengis.metadata.Metadata;
+import org.opengis.metadata.extent.Extent;
+import org.opengis.metadata.extent.GeographicExtent;
+import org.opengis.metadata.extent.GeographicBoundingBox;
import org.opengis.metadata.identification.Identification;
import org.opengis.metadata.identification.DataIdentification;
import org.apache.sis.util.Static;
@@ -33,6 +37,7 @@ import org.apache.sis.storage.DataStoreProvider;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.WritableFeatureSet;
import org.apache.sis.storage.UnsupportedStorageException;
+import org.apache.sis.geometry.GeneralEnvelope;
import org.apache.sis.internal.util.Citations;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.CharSequences;
@@ -92,7 +97,7 @@ public final class StoreUtilities extends Static {
* @param unicode whether to restrict to valid Unicode identifiers.
* @return a data identifier, or {@code null} if none.
*
- * @see AbstractResource#identifier(Metadata)
+ * @see DataStore#getIdentifier()
* @see Citations#removeIgnorableCharacters(String)
*/
private static String getAnyIdentifier(final Metadata metadata, final boolean unicode) {
@@ -141,6 +146,36 @@ public final class StoreUtilities extends Static {
}
/**
+ * Returns the spatio-temporal envelope of the given metadata.
+ * This method computes the union of all {@link GeographicBoundingBox} in the metadata, assuming the
+ * {@linkplain org.apache.sis.referencing.CommonCRS#defaultGeographic() default geographic CRS}
+ * (usually WGS 84).
+ *
+ * @param metadata the metadata from which to compute the envelope, or {@code null}.
+ * @return the spatio-temporal extent, or {@code null} if none.
+ */
+ public static Envelope getEnvelope(final Metadata metadata) {
+ GeneralEnvelope bounds = null;
+ if (metadata != null) {
+ for (final Identification identification : metadata.getIdentificationInfo()) {
+ for (final Extent extent : identification.getExtents()) {
+ for (final GeographicExtent ge : extent.getGeographicElements()) {
+ if (ge instanceof GeographicBoundingBox) {
+ final GeneralEnvelope env = new GeneralEnvelope((GeographicBoundingBox) ge);
+ if (bounds == null) {
+ bounds = env;
+ } else {
+ bounds.add(env);
+ }
+ }
+ }
+ }
+ }
+ }
+ return bounds;
+ }
+
+ /**
* Returns the most specific interface implemented by the given class.
* For indicative purpose only, as this method has arbitrary behavior if more than one leaf is found.
*
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/FeatureSubset.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/FeatureSubset.java
index cc65820..9fe1f5f 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/FeatureSubset.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/query/FeatureSubset.java
@@ -19,7 +19,6 @@ package org.apache.sis.internal.storage.query;
import java.util.List;
import java.util.stream.Stream;
import org.opengis.util.GenericName;
-import org.opengis.geometry.Envelope;
import org.apache.sis.internal.feature.FeatureUtilities;
import org.apache.sis.internal.storage.AbstractFeatureSet;
import org.apache.sis.storage.DataStoreException;
@@ -80,14 +79,6 @@ final class FeatureSubset extends AbstractFeatureSet {
}
/**
- * Returns {@code null} since computing the envelope would be costly.
- */
- @Override
- public Envelope getEnvelope() {
- return null;
- }
-
- /**
* Returns a description of properties that are common to all features in this dataset.
*/
@Override
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/DataSet.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/DataSet.java
index b633835..d9ef1fa 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/storage/DataSet.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/DataSet.java
@@ -49,7 +49,7 @@ import org.opengis.geometry.Envelope;
public interface DataSet extends Resource {
/**
* Returns the spatio-temporal extent of this resource in its most natural coordinate reference system.
- * The following relationship to {@linkplain #getMetadata()} should hold:
+ * The following relationship to {@linkplain #getMetadata()} should hold (departures may exist):
*
* <ul>
* <li>The envelope should be contained in the union of all geographic, vertical or temporal extents
@@ -67,6 +67,9 @@ public interface DataSet extends Resource {
* If this resource uses many different CRS with none of them covering all data, then the envelope should use a
* global system (typically a {@linkplain org.apache.sis.referencing.crs.DefaultGeocentricCRS geographic CRS}).
*
+ * <p>The returned envelope is not necessarily the smallest bounding box encompassing all data.
+ * If the smallest envelope is too costly to compute, this method may conservatively return a larger envelope.</p>
+ *
* @return the spatio-temporal resource extent. Should not be {@code null} (but may happen if too costly to compute).
* @throws DataStoreException if an error occurred while reading or computing the envelope.
*/
diff --git a/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java b/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java
index 510ea56..0889df2 100644
--- a/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java
+++ b/storage/sis-storage/src/main/java/org/apache/sis/storage/DataStore.java
@@ -23,14 +23,17 @@ import java.util.NoSuchElementException;
import org.opengis.util.ScopedName;
import org.opengis.util.GenericName;
import org.opengis.metadata.Metadata;
+import org.opengis.metadata.Identifier;
+import org.opengis.metadata.citation.Citation;
+import org.opengis.metadata.identification.Identification;
import org.opengis.parameter.ParameterValueGroup;
import org.apache.sis.util.Localized;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.logging.WarningListener;
import org.apache.sis.util.logging.WarningListeners;
-import org.apache.sis.internal.storage.AbstractResource;
import org.apache.sis.internal.storage.StoreUtilities;
import org.apache.sis.internal.storage.Resources;
+import org.apache.sis.referencing.NamedIdentifier;
/**
@@ -292,7 +295,31 @@ public abstract class DataStore implements Resource, Localized, AutoCloseable {
*/
@Override
public GenericName getIdentifier() throws DataStoreException {
- return AbstractResource.identifier(getMetadata());
+ final Metadata metadata = getMetadata();
+ if (metadata != null) {
+ Citation citation = null;
+ for (final Identification id : metadata.getIdentificationInfo()) {
+ final Citation c = id.getCitation();
+ if (c != null) {
+ if (citation != null && citation != c) return null; // Ambiguity.
+ citation = c;
+ }
+ }
+ if (citation != null) {
+ Identifier first = null;
+ for (final Identifier c : citation.getIdentifiers()) {
+ if (c instanceof GenericName) {
+ return (GenericName) c;
+ } else if (first == null) {
+ first = c;
+ }
+ }
+ if (first != null) {
+ return new NamedIdentifier(first);
+ }
+ }
+ }
+ return null;
}
/**
diff --git a/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Store.java b/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Store.java
index 7c8db04..4f0602f 100644
--- a/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Store.java
+++ b/storage/sis-xmlstore/src/main/java/org/apache/sis/internal/storage/gpx/Store.java
@@ -32,7 +32,7 @@ import org.apache.sis.storage.DataStoreContentException;
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.AbstractResource;
+import org.apache.sis.internal.storage.StoreUtilities;
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 StaxDataStore implements FeatureSet {
*/
@Override
public Envelope getEnvelope() throws DataStoreException {
- return AbstractResource.envelope(getMetadata());
+ return StoreUtilities.getEnvelope(getMetadata());
}
/**
|