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
commit a7ca5df1780f533c9ef6a60fbb6626371daa7232 Author: Martin Desruisseaux <[email protected]> AuthorDate: Fri Oct 24 18:42:38 2025 +0200 Move `MemoryFeatureSet` and `MemoryGridCoverage` to public API, after improvement in their API for consistency with each other. --- .../MultiResolutionCoverageLoaderTest.java | 2 +- .../org/apache/sis/storage/landsat/BandGroup.java | 7 +- .../apache/sis/storage/landsat/LandsatStore.java | 2 +- .../sis/storage/landsat/MetadataReaderTest.java | 2 +- .../apache/sis/storage/netcdf/base/TestCase.java | 2 +- .../org/apache/sis/storage/AbstractResource.java | 32 +++----- .../sis/storage/{base => }/MemoryFeatureSet.java | 64 ++++++++++++---- ...source.java => MemoryGridCoverageResource.java} | 87 +++++++++++----------- .../main/org/apache/sis/storage/Resource.java | 22 ++++-- .../storage/aggregate/AggregatedFeatureSet.java | 12 --- .../sis/storage/aggregate/AggregatedResource.java | 10 +++ .../aggregate/BandAggregateGridResource.java | 36 ++++----- .../storage/aggregate/ConcatenatedFeatureSet.java | 2 +- .../aggregate/ConcatenatedGridCoverage.java | 6 +- .../aggregate/ConcatenatedGridResource.java | 12 +-- .../sis/storage/aggregate/CoverageAggregator.java | 16 +++- .../apache/sis/storage/base/PseudoResource.java | 72 ++++++++++++++++++ .../apache/sis/storage/base/TiledGridResource.java | 14 ---- .../storage/image/WritableSingleImageStore.java | 4 +- .../main/org/apache/sis/storage/package-info.java | 8 +- .../org/apache/sis/storage/CoverageSubsetTest.java | 4 +- .../test/org/apache/sis/storage/DataStoreMock.java | 2 +- .../org/apache/sis/storage/FeatureQueryTest.java | 1 - .../org/apache/sis/storage/GridResourceMock.java | 12 +-- ...st.java => MemoryGridCoverageResourceTest.java} | 21 +++--- .../aggregate/BandAggregateGridResourceTest.java | 11 +-- .../aggregate/ConcatenatedFeatureSetTest.java | 2 +- .../sis/storage/aggregate/CoverageMosaicTest.java | 5 +- .../sis/storage/aggregate/JoinFeatureSetTest.java | 2 +- .../sis/storage/aggregate/OpaqueGridResource.java | 6 +- .../test/org/apache/sis/map/SEPortrayerTest.java | 17 +---- .../sis/map/service/GraphicsPortrayerTest.java | 2 +- .../coveragejson/CoverageJsonStoreTest.java | 4 +- .../org/apache/sis/gui/dataset/RootResource.java | 16 ---- 34 files changed, 295 insertions(+), 222 deletions(-) diff --git a/endorsed/src/org.apache.sis.portrayal/test/org/apache/sis/map/coverage/MultiResolutionCoverageLoaderTest.java b/endorsed/src/org.apache.sis.portrayal/test/org/apache/sis/map/coverage/MultiResolutionCoverageLoaderTest.java index a29b181882..2cfa93f0a4 100644 --- a/endorsed/src/org.apache.sis.portrayal/test/org/apache/sis/map/coverage/MultiResolutionCoverageLoaderTest.java +++ b/endorsed/src/org.apache.sis.portrayal/test/org/apache/sis/map/coverage/MultiResolutionCoverageLoaderTest.java @@ -101,7 +101,7 @@ public final class MultiResolutionCoverageLoaderTest extends TestCase { private static final class DummyResource extends AbstractGridCoverageResource { /** Creates a dummy resource. */ DummyResource() { - super(null, false); + super(null); } /** Returns the preferred resolutions in units of CRS axes. */ diff --git a/endorsed/src/org.apache.sis.storage.earthobservation/main/org/apache/sis/storage/landsat/BandGroup.java b/endorsed/src/org.apache.sis.storage.earthobservation/main/org/apache/sis/storage/landsat/BandGroup.java index 3e56317e93..9596970d84 100644 --- a/endorsed/src/org.apache.sis.storage.earthobservation/main/org/apache/sis/storage/landsat/BandGroup.java +++ b/endorsed/src/org.apache.sis.storage.earthobservation/main/org/apache/sis/storage/landsat/BandGroup.java @@ -31,7 +31,6 @@ import org.apache.sis.storage.Aggregate; import org.apache.sis.storage.AbstractResource; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.DataStore; -import org.apache.sis.storage.event.StoreListeners; import org.apache.sis.storage.base.StoreResource; import org.apache.sis.storage.base.MetadataBuilder; import org.apache.sis.util.ArraysExt; @@ -69,10 +68,10 @@ final class BandGroup extends AbstractResource implements Aggregate, StoreResour * Creates a new aggregate for the specified group. * This constructor will copy only the resources for that group from the given array. */ - private BandGroup(final StoreListeners parent, final BandGroupName group, + private BandGroup(final Resource parent, final BandGroupName group, final Band[] resources, final int count) { - super(parent, false); + super(parent); this.group = group; int n = 0; Band[] components = new Band[resources.length]; @@ -88,7 +87,7 @@ final class BandGroup extends AbstractResource implements Aggregate, StoreResour /** * Creates aggregates for the given bands. */ - static BandGroup[] group(final StoreListeners parent, final Band[] resources, final int count) { + static BandGroup[] group(final Resource parent, final Band[] resources, final int count) { final BandGroupName[] groups = BandGroupName.values(); final BandGroup[] aggregates = new BandGroup[groups.length]; int n = 0; diff --git a/endorsed/src/org.apache.sis.storage.earthobservation/main/org/apache/sis/storage/landsat/LandsatStore.java b/endorsed/src/org.apache.sis.storage.earthobservation/main/org/apache/sis/storage/landsat/LandsatStore.java index edd45d2353..aa82c8cea5 100644 --- a/endorsed/src/org.apache.sis.storage.earthobservation/main/org/apache/sis/storage/landsat/LandsatStore.java +++ b/endorsed/src/org.apache.sis.storage.earthobservation/main/org/apache/sis/storage/landsat/LandsatStore.java @@ -251,7 +251,7 @@ public class LandsatStore extends DataStore implements Aggregate { } catch (FactoryException e) { throw new DataStoreReferencingException(e.getMessage(), e); } - final BandGroup[] bands = BandGroup.group(listeners, resources, count); + final BandGroup[] bands = BandGroup.group(this, resources, count); for (final BandGroup c : bands) { c.identifier = factory.createLocalName(scope, c.group.name()); } diff --git a/endorsed/src/org.apache.sis.storage.earthobservation/test/org/apache/sis/storage/landsat/MetadataReaderTest.java b/endorsed/src/org.apache.sis.storage.earthobservation/test/org/apache/sis/storage/landsat/MetadataReaderTest.java index 31099f6d44..bc1b7c8544 100644 --- a/endorsed/src/org.apache.sis.storage.earthobservation/test/org/apache/sis/storage/landsat/MetadataReaderTest.java +++ b/endorsed/src/org.apache.sis.storage.earthobservation/test/org/apache/sis/storage/landsat/MetadataReaderTest.java @@ -246,7 +246,7 @@ public final class MetadataReaderTest extends TestCase { final class DummyResource extends AbstractResource { /** Creates a dummy resource without parent. */ DummyResource() { - super(null, false); + super(null); } /** Makes listeners accessible to this package. */ diff --git a/endorsed/src/org.apache.sis.storage.netcdf/test/org/apache/sis/storage/netcdf/base/TestCase.java b/endorsed/src/org.apache.sis.storage.netcdf/test/org/apache/sis/storage/netcdf/base/TestCase.java index c34b3efeeb..cf34b35b18 100644 --- a/endorsed/src/org.apache.sis.storage.netcdf/test/org/apache/sis/storage/netcdf/base/TestCase.java +++ b/endorsed/src/org.apache.sis.storage.netcdf/test/org/apache/sis/storage/netcdf/base/TestCase.java @@ -138,7 +138,7 @@ public abstract class TestCase extends org.apache.sis.test.TestCase { final class DummyResource extends AbstractResource { /** Creates a dummy resource without parent. */ DummyResource() { - super(null, false); + super(null); } /** Makes listeners accessible to this package. */ diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/AbstractResource.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/AbstractResource.java index 49c9497819..d64b18401f 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/AbstractResource.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/AbstractResource.java @@ -18,7 +18,6 @@ package org.apache.sis.storage; import java.util.Locale; import java.util.Optional; -import org.opengis.util.GenericName; import org.opengis.metadata.Metadata; import org.opengis.geometry.Envelope; import org.opengis.referencing.operation.TransformException; @@ -31,6 +30,7 @@ import org.apache.sis.storage.event.StoreEvent; import org.apache.sis.storage.event.StoreListener; import org.apache.sis.storage.event.StoreListeners; import org.apache.sis.storage.internal.Resources; +import org.apache.sis.storage.base.PseudoResource; import org.apache.sis.storage.base.MetadataBuilder; import org.apache.sis.util.resources.Errors; import org.apache.sis.util.logging.Logging; @@ -43,7 +43,7 @@ import org.apache.sis.xml.NilReason; * Subclasses should override the following methods: * * <ul> - * <li>{@link #getIdentifier()} (strongly recommended)</li> + * <li>{@link #getIdentifier()} (recommended)</li> * <li>{@link #getEnvelope()} (recommended)</li> * <li>{@link #createMetadata()} (optional)</li> * <li>{@link #getSynchronizationLock()} (optional)</li> @@ -54,7 +54,7 @@ import org.apache.sis.xml.NilReason; * Synchronization, when needed, uses {@link #getSynchronizationLock()}. * * @author Martin Desruisseaux (Geomatys) - * @version 1.4 + * @version 1.6 * @since 1.2 */ public abstract class AbstractResource implements Resource { @@ -85,7 +85,14 @@ public abstract class AbstractResource implements Resource { @SuppressWarnings("this-escape") protected AbstractResource(final Resource parent) { StoreListeners parentListeners = null; - if (parent instanceof AbstractResource) { + if (parent instanceof PseudoResource) { // Internal hack, may change in any future version. + final var r = (PseudoResource) parent; + parentListeners = r.listeners; + if (parentListeners != null && r.childrenAreHidden) { + listeners = parentListeners; + return; + } + } else if (parent instanceof AbstractResource) { parentListeners = ((AbstractResource) parent).listeners; } else if (parent instanceof DataStore) { parentListeners = ((DataStore) parent).listeners; @@ -119,23 +126,6 @@ public abstract class AbstractResource implements Resource { } } - /** - * Returns the resource persistent identifier if available. - * The default implementation returns an empty value. - * Subclasses are strongly encouraged to override if they can provide a value. - * - * <h4>Relationship with metadata</h4> - * The default implementation of {@link #createMetadata()} uses this identifier for initializing - * the {@code metadata/identificationInfo/citation/title} property. - * - * @return a persistent identifier unique within the data store. - * @throws DataStoreException if an error occurred while fetching the identifier. - */ - @Override - public Optional<GenericName> getIdentifier() throws DataStoreException { - return Optional.empty(); - } - /** * Returns the spatiotemporal envelope of this resource. This information is part of API only in some kinds * of resource such as {@link FeatureSet}. But the method is provided in this base class for convenience. diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MemoryFeatureSet.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/MemoryFeatureSet.java similarity index 58% rename from endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MemoryFeatureSet.java rename to endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/MemoryFeatureSet.java index 8b25894a1b..a2d8297510 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MemoryFeatureSet.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/MemoryFeatureSet.java @@ -14,14 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.sis.storage.base; +package org.apache.sis.storage; import java.util.Objects; import java.util.Collection; import java.util.OptionalLong; import java.util.stream.Stream; -import org.apache.sis.storage.Resource; -import org.apache.sis.storage.AbstractFeatureSet; // Specific to the geoapi-3.1 and geoapi-4.0 branches: import org.opengis.feature.Feature; @@ -29,36 +27,48 @@ import org.opengis.feature.FeatureType; /** - * Set of features stored in memory. Features are specified at construction time. - * Metadata can be specified by overriding {@link #createMetadata()}. + * Set of feature instances stored in memory. + * Features are specified at construction time. + * Metadata can be specified by overriding the {@link #createMetadata()} method. + * + * <h2>When to use</h2> + * This class is useful for small sets of features, or for testing purposes, + * or when the features are in memory anyway (for example, a computation result). + * It should generally not be used for large data sets read from files or databases. * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) + * + * @since 1.6 */ public class MemoryFeatureSet extends AbstractFeatureSet { /** - * The type specified at construction time and returned by {@link #getType()}. + * The type specified at construction time. + * + * @see #getType() */ - private final FeatureType type; + protected final FeatureType type; /** * The features specified at construction time, potentially as a modifiable collection. * For all features in this collection, {@link Feature#getType()} shall be {@link #type}. + * + * @see #features(boolean) */ - private final Collection<Feature> features; + protected final Collection<Feature> features; /** * Creates a new set of features stored in memory. It is caller responsibility to ensure that * <code>{@linkplain Feature#getType()} == type</code> for all elements in the given collection - * (this is not verified). + * (this is not verified by this constructor). * - * @param parent the parent resource, or {@code null} if none. - * @param type the type of all features in the given collection. - * @param features collection of stored features. This collection will not be copied. + * @param parent the parent resource, or {@code null} if none. + * @param type the type of all features in the given collection. + * @param features collection of stored features. This collection will not be copied. */ public MemoryFeatureSet(final Resource parent, final FeatureType type, final Collection<Feature> features) { super(parent); - this.type = Objects.requireNonNull(type); + this.type = Objects.requireNonNull(type); this.features = Objects.requireNonNull(features); } @@ -92,4 +102,32 @@ public class MemoryFeatureSet extends AbstractFeatureSet { public Stream<Feature> features(final boolean parallel) { return parallel ? features.parallelStream() : features.stream(); } + + /** + * Tests whether this memory feature set is wrapping the same feature instances as the given object. + * This method checks also that the listeners are equal. + * + * @param obj the object to compare. + * @return whether the two objects are memory resources wrapping the same features. + */ + @Override + public boolean equals(final Object obj) { + if (obj != null && obj.getClass() == getClass()) { + final var other = (MemoryFeatureSet) obj; + return type.equals(other.type) && + features.equals(other.features) && + listeners.equals(other.listeners); + } + return false; + } + + /** + * Returns a hash code value for consistency with {@code equals(Object)}. + * + * @return a hash code value. + */ + @Override + public int hashCode() { + return type.hashCode() + 31 * features.hashCode() + 37 * listeners.hashCode(); + } } diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MemoryGridResource.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/MemoryGridCoverageResource.java similarity index 79% rename from endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MemoryGridResource.java rename to endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/MemoryGridCoverageResource.java index dc4e70c0f2..3d0ed813a4 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MemoryGridResource.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/MemoryGridCoverageResource.java @@ -14,14 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.sis.storage.base; +package org.apache.sis.storage; import java.util.List; import java.util.Arrays; import java.util.Objects; -import java.util.Optional; import java.awt.image.RenderedImage; -import org.opengis.util.GenericName; import org.apache.sis.coverage.SampleDimension; import org.apache.sis.coverage.grid.GridCoverage; import org.apache.sis.coverage.grid.GridCoverageBuilder; @@ -30,36 +28,41 @@ import org.apache.sis.coverage.grid.GridExtent; import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.coverage.grid.GridRoundingMode; import org.apache.sis.coverage.grid.PixelInCell; -import org.apache.sis.storage.AbstractGridCoverageResource; -import org.apache.sis.storage.RasterLoadingStrategy; -import org.apache.sis.storage.event.StoreListeners; -import static org.apache.sis.storage.base.TiledGridCoverage.BIDIMENSIONAL; /** - * A {@link org.apache.sis.storage.GridCoverageResource} in memory. + * A Grid Coverage Resource stored in memory. * This resource wraps an arbitrary {@link GridCoverage} specified at construction time. - * Metadata can be specified by overriding {@link #createMetadata()}. + * Metadata can be specified by overriding the {@link #createMetadata()} method. + * + * <h2>When to use</h2> + * This class is useful for small grid coverages, or for testing purposes, + * or when the coverage is in memory anyway (for example, a computation result). + * It should generally not be used for large coverages read from files or databases. * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) + * + * @since 1.6 */ -public class MemoryGridResource extends AbstractGridCoverageResource { +public class MemoryGridCoverageResource extends AbstractGridCoverageResource { /** - * The grid coverage specified at construction time. + * A constant for identifying code that relying on having 2 dimensions. */ - public final GridCoverage coverage; + private static final int BIDIMENSIONAL = 2; /** - * The grid coverage processor to use for selecting bands. - * It may be configured with a colorizer for determining the color models. + * The grid coverage specified at construction time. + * + * @see #getGridCoverage() */ - private final GridCoverageProcessor processor; + protected final GridCoverage coverage; /** - * The resource identifier, or {@code null} if none. + * The grid coverage processor to use for selecting bands. + * It may be configured with a colorizer for determining the color models. */ - private final GenericName identifer; + protected final GridCoverageProcessor processor; /** * Whether to defer the calls to {@link GridCoverage#render(GridExtent)}. @@ -71,26 +74,28 @@ public class MemoryGridResource extends AbstractGridCoverageResource { /** * Creates a new coverage stored in memory. * - * @param parent listeners of the parent resource, or {@code null} if none. - * @param identifier resource identifier, or {@code null} if none. - * @param coverage stored coverage retained as-is (not copied). Cannot be null. - * @param processor the grid coverage processor for selecting bands, or {@code null} for default. + * @param parent the parent resource, or {@code null} if none. + * @param coverage stored coverage retained as-is (not copied). Cannot be null. + * @param processor the grid coverage processor for selecting bands, or {@code null} for default. */ - public MemoryGridResource(final StoreListeners parent, final GenericName identifier, - final GridCoverage coverage, final GridCoverageProcessor processor) - { - super(parent, false); - this.identifer = identifier; + public MemoryGridCoverageResource(final Resource parent, final GridCoverage coverage, final GridCoverageProcessor processor) { + super(parent); this.coverage = Objects.requireNonNull(coverage); this.processor = (processor != null) ? processor : new GridCoverageProcessor(); } /** - * Returns the resource identifier specified at construction time, if any. + * Returns the grid coverage wrapped by this resource. + * The grid coverage returned by this method shall be the same or equivalent + * to the coverage that would be returned by a call to {@code read(null)}, + * and should not be expansive to get. + * + * @return the grid coverage wrapped by this resource. + * + * @see #read(GridGeometry, int...) */ - @Override - public Optional<GenericName> getIdentifier() { - return Optional.ofNullable(identifer); + public GridCoverage getGridCoverage() { + return coverage; } /** @@ -132,10 +137,10 @@ public class MemoryGridResource extends AbstractGridCoverageResource { } /** - * Returns a subset of the wrapped grid coverage. If a non-null grid geometry is specified, then - * this method tries to return a grid coverage matching the given grid geometry on a best-effort basis. - * In the current implementation, this is either a {@link org.apache.sis.coverage.grid.GridCoverage2D} - * or the original grid coverage. + * Returns a subset of the wrapped grid coverage. If a null grid geometry and a null or empty range is specified, + * then this method shall return the same grid coverage as {@link #getGridCoverage()} or an equivalent coverage. + * If a non-null grid geometry is specified, then this method tries to return a grid coverage matching the given + * grid geometry on a best-effort basis. It may be the whole coverage. * * @param domain desired grid extent and resolution, or {@code null} for the whole domain. * @param ranges 0-based indices of sample dimensions to read, or {@code null} or an empty sequence for reading them all. @@ -228,8 +233,8 @@ public class MemoryGridResource extends AbstractGridCoverageResource { } /** - * Tests whether this memory grid resource is wrapping the same coverage than the given object. - * This method requires also the listeners and processor to be the equal. + * Tests whether this memory grid coverage resource is wrapping the same coverage as the given object. + * This method checks also that the listeners and the grid coverage processor are equal. * * @param obj the object to compare. * @return whether the two objects are memory resources wrapping the same coverage. @@ -237,9 +242,8 @@ public class MemoryGridResource extends AbstractGridCoverageResource { @Override public boolean equals(final Object obj) { if (obj != null && obj.getClass() == getClass()) { - final var other = (MemoryGridResource) obj; - return Objects.equals(identifer, other.identifer) && - coverage.equals(other.coverage) && + final var other = (MemoryGridCoverageResource) obj; + return coverage.equals(other.coverage) && processor.equals(other.processor) && listeners.equals(other.listeners); } @@ -253,10 +257,7 @@ public class MemoryGridResource extends AbstractGridCoverageResource { */ @Override public int hashCode() { - return coverage.hashCode() - + 17 * Objects.hashCode(identifer) - + 31 * processor.hashCode() - + 37 * listeners.hashCode(); + return coverage.hashCode() + 31 * processor.hashCode() + 37 * listeners.hashCode(); } /** diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/Resource.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/Resource.java index 61022718dc..34f16f3acc 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/Resource.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/Resource.java @@ -54,7 +54,7 @@ import org.apache.sis.storage.event.StoreListener; * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 1.5 + * @version 1.6 * * @see Aggregate#components() * @@ -84,7 +84,9 @@ public interface Resource { * * @since 1.0 */ - Optional<GenericName> getIdentifier() throws DataStoreException; + default Optional<GenericName> getIdentifier() throws DataStoreException { + return Optional.empty(); + } /** * Returns information about this resource. @@ -140,7 +142,7 @@ public interface Resource { * If the caller wants to modify some metadata elements, it may be necessary to perform a * {@linkplain org.apache.sis.metadata.iso.DefaultMetadata#deepCopy(Metadata) deep copy} first. * - * @return information about this resource. Should not be {@code null}. + * @return information about this resource. Should not be {@code null}, but this is not strictly forbidden. * @throws DataStoreException if an error occurred while reading the metadata. * * @see DataStore#getMetadata() @@ -364,11 +366,16 @@ public interface Resource { * This side-effect is applied on the assumption that the registered listener will handle * warnings in its own way, for example by showing warnings in a widget. * + * <h4>Default implementation</h4> + * The default implementation does nothing. + * This is okay for resources that do not emit any event. + * * @param <T> compile-time value of the {@code eventType} argument. * @param listener listener to notify about events. * @param eventType type of {@link StoreEvent}s to listen (cannot be {@code null}). */ - <T extends StoreEvent> void addListener(Class<T> eventType, StoreListener<? super T> listener); + default <T extends StoreEvent> void addListener(Class<T> eventType, StoreListener<? super T> listener) { + } /** * Unregisters a listener previously added to this resource for the given type of events. @@ -386,9 +393,14 @@ public interface Resource { * and if, after this method invocation, there are no remaining listeners for warning events, * then this {@code Resource} will send future warnings to the loggers. * + * <h4>Default implementation</h4> + * The default implementation does nothing. + * This is okay for resources that do not emit any event. + * * @param <T> compile-time value of the {@code eventType} argument. * @param listener listener to stop notifying about events. * @param eventType type of {@link StoreEvent}s which were listened (cannot be {@code null}). */ - <T extends StoreEvent> void removeListener(Class<T> eventType, StoreListener<? super T> listener); + default <T extends StoreEvent> void removeListener(Class<T> eventType, StoreListener<? super T> listener) { + } } diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/AggregatedFeatureSet.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/AggregatedFeatureSet.java index 63b180e995..6a7e1f17b2 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/AggregatedFeatureSet.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/AggregatedFeatureSet.java @@ -30,7 +30,6 @@ import org.apache.sis.storage.Resource; import org.apache.sis.storage.FeatureSet; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.AbstractFeatureSet; -import org.apache.sis.storage.event.StoreListeners; import org.apache.sis.storage.base.MetadataBuilder; // Specific to the geoapi-3.1 and geoapi-4.0 branches: @@ -70,17 +69,6 @@ abstract class AggregatedFeatureSet extends AbstractFeatureSet { super(parent); } - /** - * Creates a new aggregated feature set. - * - * @param parent listeners of the parent resource, or {@code null} if none. - * This is usually the listeners of the {@link org.apache.sis.storage.DataStore} - * that created this resource. - */ - protected AggregatedFeatureSet(final StoreListeners parent) { - super(parent, false); - } - /** * Returns all feature set used by this aggregation. This method is invoked for implementation of * {@link #getEnvelope()} and {@link #createMetadata(MetadataBuilder)}. diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/AggregatedResource.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/AggregatedResource.java index 4930ea9f4f..b037d547a7 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/AggregatedResource.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/AggregatedResource.java @@ -28,6 +28,7 @@ import org.apache.sis.storage.AbstractResource; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.event.StoreListeners; import org.apache.sis.storage.base.MetadataBuilder; +import org.apache.sis.storage.base.PseudoResource; import org.apache.sis.geometry.Envelopes; import org.apache.sis.geometry.ImmutableEnvelope; import org.apache.sis.util.internal.shared.Strings; @@ -73,6 +74,15 @@ abstract class AggregatedResource extends AbstractResource { */ private boolean envelopeIsEvaluated; + /** + * Creates a new concatenated resource as the child of the given resource. + * + * @param parent the parent resource, or {@code null} if none. + */ + AggregatedResource(final PseudoResource parent) { + super(parent); + } + /** * Creates a new concatenated resource. * diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/BandAggregateGridResource.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/BandAggregateGridResource.java index ad3fd98827..40d122fdf3 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/BandAggregateGridResource.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/BandAggregateGridResource.java @@ -30,9 +30,9 @@ import org.apache.sis.storage.GridCoverageResource; import org.apache.sis.storage.AbstractGridCoverageResource; import org.apache.sis.storage.RasterLoadingStrategy; import org.apache.sis.storage.DataStoreException; +import org.apache.sis.storage.MemoryGridCoverageResource; import org.apache.sis.storage.base.MetadataBuilder; -import org.apache.sis.storage.base.MemoryGridResource; -import org.apache.sis.storage.event.StoreListeners; +import org.apache.sis.storage.base.PseudoResource; import org.apache.sis.util.ArgumentChecks; import org.apache.sis.util.ArraysExt; import org.apache.sis.util.internal.shared.UnmodifiableArrayList; @@ -109,18 +109,18 @@ final class BandAggregateGridResource extends AggregatedResource implements Grid * The {@linkplain #getSampleDimensions() list of sample dimensions} of the aggregated resource * will be the concatenation of the lists of all sources, or a subset of this concatenation. * - * @param parentListeners listeners of the parent resource, or {@code null} if none. - * @param aggregate sources to aggregate together with the bands to select for each source. - * @param processor the processor to use for creating grid coverages. + * @param parent the parent resource, or {@code null} if none. + * @param aggregate sources to aggregate together with the bands to select for each source. + * @param processor the processor to use for creating grid coverages. * @throws BackingStoreException if an error occurred while fetching the grid geometry or sample dimensions from a resource. * @throws IllegalGridGeometryException if a grid geometry is not compatible with the others. * @throws IllegalArgumentException if some band indices are duplicated or outside their range of validity. */ - private BandAggregateGridResource(final StoreListeners parentListeners, + private BandAggregateGridResource(final PseudoResource parent, final BandAggregateArgument<GridCoverageResource> aggregate, final GridCoverageProcessor processor) { - super(null, parentListeners, false); + super(parent); this.sources = aggregate.sources(); this.gridGeometry = aggregate.domain(BandAggregateGridResource::domain); this.sampleDimensions = List.copyOf(aggregate.ranges()); @@ -149,16 +149,16 @@ final class BandAggregateGridResource extends AggregatedResource implements Grid * The intersection of the domain of all resources shall be non-empty, * and all resources shall use the same data type in their rendered image. * - * @param parentListeners listeners of the parent resource, or {@code null} if none. - * @param sources resources whose bands shall be aggregated, in order. At least one resource must be provided. - * @param bandsPerSource sample dimensions for each source. May be {@code null} or may contain {@code null} elements. - * @param processor the processor to use for creating grid coverages. + * @param parent the parent resource, or {@code null} if none. + * @param sources resources whose bands shall be aggregated, in order. At least one resource must be provided. + * @param bandsPerSource sample dimensions for each source. May be {@code null} or may contain {@code null} elements. + * @param processor the processor to use for creating grid coverages. * @return the band aggregated grid resource. * @throws DataStoreException if an error occurred while fetching the grid geometry or sample dimensions from a resource. * @throws IllegalGridGeometryException if a grid geometry is not compatible with the others. * @throws IllegalArgumentException if some band indices are duplicated or outside their range of validity. */ - static GridCoverageResource create(final StoreListeners parentListeners, + static GridCoverageResource create(final PseudoResource parent, GridCoverageResource[] sources, int[][] bandsPerSource, final GridCoverageProcessor processor) throws DataStoreException { @@ -168,14 +168,14 @@ final class BandAggregateGridResource extends AggregatedResource implements Grid for (int i=0; i<sources.length; i++) { final GridCoverageResource source = sources[i]; ArgumentChecks.ensureNonNullElement("sources", i, source); - if (source instanceof MemoryGridResource) { + if (source instanceof MemoryGridCoverageResource) { if (count == 0) { sources = sources.clone(); // Clone when first needed. bandsPerSource = (bandsPerSource != null) ? bandsPerSource.clone() : new int[sources.length][]; } final int[] bands = bandsPerSource[i]; final int numBands = (bands != null) ? bands.length : source.getSampleDimensions().size(); - coverages[count] = ((MemoryGridResource) source).coverage; + coverages[count] = ((MemoryGridCoverageResource) source).getGridCoverage(); coverageBands[count] = bands; bandsPerSource[i] = ArraysExt.range(firstBand, firstBand + numBands); sources[i] = null; // To be replaced by the aggregated coverage. @@ -184,13 +184,13 @@ final class BandAggregateGridResource extends AggregatedResource implements Grid } } /* - * If at least one `MemoryGridResource` has been found, apply the aggregation directly - * on the grid coverage, then build a single `MemoryGridResource` with the result. + * If at least one `MemoryGridCoverageResource` has been found, apply the aggregation directly + * on the grid coverage, then build a single `MemoryGridCoverageResource` with the result. */ if (count != 0) { coverages = ArraysExt.resize(coverages, count); coverageBands = ArraysExt.resize(coverageBands, count); - var aggregate = new MemoryGridResource(parentListeners, null, processor.aggregateRanges(coverages, coverageBands), processor); + var aggregate = new MemoryGridCoverageResource(parent, processor.aggregateRanges(coverages, coverageBands), processor); for (int i=0; i<sources.length; i++) { if (sources[i] == null) { sources[i] = aggregate; @@ -209,7 +209,7 @@ final class BandAggregateGridResource extends AggregatedResource implements Grid if (aggregate.isIdentity()) { return aggregate.sources()[0]; } - return new BandAggregateGridResource(parentListeners, aggregate, processor); + return new BandAggregateGridResource(parent, aggregate, processor); } catch (BackingStoreException e) { throw e.unwrapOrRethrow(DataStoreException.class); } diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedFeatureSet.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedFeatureSet.java index dbafaf4e76..78a9582e76 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedFeatureSet.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedFeatureSet.java @@ -76,7 +76,7 @@ public class ConcatenatedFeatureSet extends AggregatedFeatureSet { * but different sources. This is used for creating {@linkplain #subset(Query) subsets}. */ private ConcatenatedFeatureSet(final FeatureSet[] sources, final ConcatenatedFeatureSet original) { - super(original.listeners); + super(original); this.sources = UnmodifiableArrayList.wrap(sources); commonType = original.commonType; } diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridCoverage.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridCoverage.java index 9649c38087..743bbf6863 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridCoverage.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridCoverage.java @@ -28,9 +28,9 @@ import org.apache.sis.coverage.grid.GridExtent; import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.coverage.grid.GridCoverage; import org.apache.sis.coverage.grid.DisjointExtentException; +import org.apache.sis.storage.MemoryGridCoverageResource; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.internal.Resources; -import org.apache.sis.storage.base.MemoryGridResource; import org.apache.sis.util.collection.Cache; import org.apache.sis.util.logging.Logging; import org.apache.sis.util.internal.shared.Numerics; @@ -135,8 +135,8 @@ final class ConcatenatedGridCoverage extends GridCoverage { if (opposite == null) { List<SampleDimension> sampleDimensions = null; for (final GridSlice slice : locator.slices) { - if (slice.resource instanceof MemoryGridResource) { - GridCoverage coverage = ((MemoryGridResource) slice.resource).coverage; + if (slice.resource instanceof MemoryGridCoverageResource) { + GridCoverage coverage = ((MemoryGridCoverageResource) slice.resource).getGridCoverage(); coverage = coverage.forConvertedValues(converted); sampleDimensions = coverage.getSampleDimensions(); break; diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridResource.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridResource.java index 760d194e16..b7e01be507 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridResource.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/ConcatenatedGridResource.java @@ -34,9 +34,9 @@ import org.apache.sis.storage.Resource; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.DataStoreReferencingException; import org.apache.sis.storage.GridCoverageResource; +import org.apache.sis.storage.MemoryGridCoverageResource; import org.apache.sis.storage.RasterLoadingStrategy; import org.apache.sis.storage.event.StoreListeners; -import org.apache.sis.storage.base.MemoryGridResource; import org.apache.sis.storage.base.MetadataBuilder; import org.apache.sis.util.ArraysExt; import org.apache.sis.util.ComparisonMode; @@ -72,7 +72,7 @@ final class ConcatenatedGridResource extends AggregatedResource implements GridC * <p>Whether a bit is set or not depends on three factors:</p> * <ul> * <li>Whether deferred loading has been requested by a call to {@link #setLoadingStrategy(RasterLoadingStrategy)}.</li> - * <li>Whether the resource is a {@link MemoryGridResource} instance, in which case it is not useful to delay.</li> + * <li>Whether the resource is a {@link MemoryGridCoverageResource} instance, in which case it is not useful to delay.</li> * <li>Whether the slice at the corresponding index can handle deferred loading itself. * In such case, we let the resource manages its own lazy loading.</li> * </ul> @@ -335,12 +335,12 @@ final class ConcatenatedGridResource extends AggregatedResource implements GridC /** * Returns whether the given slice should be ignored in the determination of a loading strategy. - * {@link MemoryGridResource} instances are ignored because they usually behave like "at get tile time", + * {@link MemoryGridCoverageResource} instances are ignored because they usually behave like "at get tile time", * even if their {@code setLoadingStrategy(…)} method rejects the value (because it cannot be guaranteed). * We also don't flag those instances as deferred for the same reason. */ private static boolean ignore(final GridCoverageResource slice) { - return slice instanceof MemoryGridResource; + return slice instanceof MemoryGridCoverageResource; } /** @@ -473,7 +473,7 @@ final class ConcatenatedGridResource extends AggregatedResource implements GridC * For all coverages that have been read immediately, wrap them in a memory resource. * This look cannot be inlined inside above loop because we need to know the adjusted domain. * This loop has some tolerance regarding coverages with a resolution different than expected. - * This is okay if `MemoryGridResource` applies the missing subsampling in its `read(…)` method. + * This is okay if `MemoryGridCoverageResource` applies the missing subsampling in its `read(…)` method. */ if (coverages != null) try { for (int i=0; i < selected.length; i++) { @@ -481,7 +481,7 @@ final class ConcatenatedGridResource extends AggregatedResource implements GridC if (coverage != null) { GridGeometry geometry = coverage.getGridGeometry(); GridExtent inGroup = domain.extentOf(geometry, GridSlice.CELL_ANCHOR, GridRoundingMode.NEAREST); - var resource = new MemoryGridResource(listeners, null, coverage, processor); + var resource = new MemoryGridCoverageResource(this, coverage, processor); selected[i] = selected[i].resolve(resource, geometry.getExtent(), inGroup); } } diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/CoverageAggregator.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/CoverageAggregator.java index 5de1f71862..92c3203e0a 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/CoverageAggregator.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/aggregate/CoverageAggregator.java @@ -44,7 +44,8 @@ import org.apache.sis.storage.DataStore; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.DataStoreContentException; import org.apache.sis.storage.GridCoverageResource; -import org.apache.sis.storage.base.MemoryGridResource; +import org.apache.sis.storage.MemoryGridCoverageResource; +import org.apache.sis.storage.base.PseudoResource; import org.apache.sis.storage.event.StoreListeners; import org.apache.sis.coverage.SampleDimension; import org.apache.sis.coverage.SubspaceNotSpecifiedException; @@ -188,6 +189,13 @@ public final class CoverageAggregator extends Group<GroupBySample> { return (listeners != null) ? listeners.getSourceName() : null; } + /** + * Returns this aggregator as a pseudo-resource, used only for passing the listeners. + */ + private PseudoResource asPseudoResource() { + return new PseudoResource(listeners, false); + } + /** * Adds the given coverage. This method can be invoked from any thread. * @@ -197,10 +205,10 @@ public final class CoverageAggregator extends Group<GroupBySample> { */ public void add(final GridCoverage coverage) { try { - add(new MemoryGridResource(listeners, null, coverage, processor)); + add(new MemoryGridCoverageResource(asPseudoResource(), coverage, processor)); } catch (DataStoreException e) { /* - * `DataStoreException` are never thrown by `MemoryGridResource`. + * `DataStoreException` are never thrown by `MemoryGridCoverageResource`. * The only case where we could get that exception with default * `add(GridCoverageResource)` is with non-invertible transform. */ @@ -520,7 +528,7 @@ search: synchronized (members) { */ public void addRangeAggregate(final GridCoverageResource[] sources, final int[][] bandsPerSource) throws DataStoreException { if (sources.length != 0) { - add(BandAggregateGridResource.create(listeners, sources, bandsPerSource, processor)); + add(BandAggregateGridResource.create(asPseudoResource(), sources, bandsPerSource, processor)); } } diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/PseudoResource.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/PseudoResource.java new file mode 100644 index 0000000000..9d14b40547 --- /dev/null +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/PseudoResource.java @@ -0,0 +1,72 @@ +/* + * 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.storage.base; + +import org.apache.sis.storage.Resource; +import org.apache.sis.storage.AbstractResource; +import org.apache.sis.storage.event.StoreListeners; +import org.opengis.metadata.Metadata; + + +/** + * A pseudo-resource used as a way to specify listeners to the {@link AbstractResource} constructor. + * Instances of this class are short-lived: no reference should be stored. + * This pseudo-resource should never be visible to users. + * + * @author Martin Desruisseaux (Geomatys) + */ +public final class PseudoResource implements Resource { + /** + * The listeners that {@link AbstractResource} should take. May be {@code null}. + */ + public final StoreListeners listeners; + + /** + * Whether the children of this pseudo-resource should be hidden. + * If {@code false} (the recommended value), then the children will have their own set of listeners + * and each child will be the {@linkplain StoreListeners#getSource() source of their own events}. + * It will be possible to add and remove listeners independently from the set of parent listeners. + * Conversely if {@code true}, then the {@linkplain #listeners} will be used directly and the + * children resource will not appear as the source of any event. + * + * <p>In any cases, the listeners of all parents (ultimately the data store that created the resource) + * will always be notified, either directly if {@code childrenAreHidden} is {@code true} or indirectly + * if {@code childrenAreHidden} is {@code false}.</p> + */ + public final boolean childrenAreHidden; + + /** + * Creates a new instance wrapping the given resources. + * + * @param listeners the listeners that {@link AbstractResource} should take, or {@code null}. + * @param childrenAreHidden whether the children of this pseudo-resource should be hidden. + */ + public PseudoResource(final StoreListeners listeners, final boolean childrenAreHidden) { + this.listeners = listeners; + this.childrenAreHidden = childrenAreHidden; + } + + /** + * Ignored. + * + * @return {@code null}. + */ + @Override + public Metadata getMetadata() { + return null; + } +} diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridResource.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridResource.java index 145daf7ae5..d2442b62cc 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridResource.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridResource.java @@ -45,7 +45,6 @@ import org.apache.sis.storage.Resource; import org.apache.sis.storage.AbstractGridCoverageResource; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.RasterLoadingStrategy; -import org.apache.sis.storage.event.StoreListeners; import org.apache.sis.measure.NumberRange; import org.apache.sis.util.ArraysExt; import org.apache.sis.util.internal.shared.Numerics; @@ -158,19 +157,6 @@ public abstract class TiledGridResource extends AbstractGridCoverageResource { super(parent); } - /** - * Creates a new resource. - * - * @param parent listeners of the parent resource, or {@code null} if none. - * This is usually the listeners of the {@link org.apache.sis.storage.DataStore} - * that created this resource. - * @param hidden {@code false} if this resource shall use its own {@link StoreListeners} - * with the specified parent, or {@code true} for using {@code parentListeners} directly. - */ - protected TiledGridResource(final StoreListeners parent, final boolean hidden) { - super(parent, hidden); - } - /** * Returns the size of tiles in this resource. * The length of the returned array is the number of dimensions, diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/WritableSingleImageStore.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/WritableSingleImageStore.java index 3c00dfd441..fa05ffb012 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/WritableSingleImageStore.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/image/WritableSingleImageStore.java @@ -25,11 +25,11 @@ import org.apache.sis.coverage.grid.GridCoverage; import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.GridCoverageResource; +import org.apache.sis.storage.MemoryGridCoverageResource; import org.apache.sis.storage.RasterLoadingStrategy; import org.apache.sis.storage.UnsupportedQueryException; import org.apache.sis.storage.WritableGridCoverageResource; import org.apache.sis.storage.Query; -import org.apache.sis.storage.base.MemoryGridResource; /** @@ -168,7 +168,7 @@ final class WritableSingleImageStore extends WritableStore implements WritableGr public void write(final GridCoverage coverage, final Option... options) throws DataStoreException { try { if (isMultiImages() == 0) { - add(new MemoryGridResource(listeners, null, coverage, null)); + add(new MemoryGridCoverageResource(this, coverage, null)); } else { delegate().write(coverage, options); } diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/package-info.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/package-info.java index acb177d843..4a846c5c9d 100644 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/package-info.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/package-info.java @@ -16,13 +16,11 @@ */ /** - * {@linkplain org.apache.sis.storage.DataStore Data store} base types for retrieving and saving geospatial data - * in various storage formats. - * - * <p>{@code DataStore} provides the methods for reading or writing geospatial data in a given storage. + * Data store base types for retrieving and saving geospatial data in various storage formats. + * {@link org.apache.sis.storage.DataStore} provides the methods for reading or writing geospatial data in a given storage. * A storage may be a file, a directory, a connection to a database or any other implementation specific mechanism. * Suitable {@code DataStore} implementation for a given storage can be discovered and opened by the static methods - * provided in {@link org.apache.sis.storage.DataStores}.</p> + * provided in {@link org.apache.sis.storage.DataStores}. * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) diff --git a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageSubsetTest.java b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageSubsetTest.java index 833577cd04..2d1fad781c 100644 --- a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageSubsetTest.java +++ b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/CoverageSubsetTest.java @@ -28,7 +28,6 @@ import org.apache.sis.coverage.grid.GridExtent; import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.coverage.grid.GridOrientation; import org.apache.sis.geometry.ImmutableEnvelope; -import org.apache.sis.storage.base.MemoryGridResource; import org.apache.sis.measure.Units; // Test dependencies @@ -46,6 +45,7 @@ import static org.apache.sis.referencing.Assertions.assertEquivalent; * @author Alexis Manin (Geomatys) * @author Martin Desruisseaux (Geomatys) */ +@SuppressWarnings("exports") public final class CoverageSubsetTest extends TestCase { /** * Size (in pixels) of the image to build for testing purpose. @@ -70,7 +70,7 @@ public final class CoverageSubsetTest extends TestCase { final var domain = new GridGeometry(extent, region, GridOrientation.HOMOTHETY); final var band = new SampleDimension.Builder().addQuantitative("101-based row-major order pixel number", 101, 105, 1, 0, Units.UNITY).build(); final var buffer = new DataBufferInt(values(), WIDTH * HEIGHT); - return new MemoryGridResource(null, null, new BufferedGridCoverage(domain, List.of(band), buffer), null); + return new MemoryGridCoverageResource(null, new BufferedGridCoverage(domain, List.of(band), buffer), null); } /** diff --git a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/DataStoreMock.java b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/DataStoreMock.java index 90d6ee2975..86c581c180 100644 --- a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/DataStoreMock.java +++ b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/DataStoreMock.java @@ -100,7 +100,7 @@ public final class DataStoreMock extends DataStore { * @return a dummy child. */ public Resource newChild() { - return new AbstractResource(listeners, false) { + return new AbstractResource(this) { }; } } diff --git a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/FeatureQueryTest.java b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/FeatureQueryTest.java index ac13d60d71..4642c8380d 100644 --- a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/FeatureQueryTest.java +++ b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/FeatureQueryTest.java @@ -24,7 +24,6 @@ import org.apache.sis.feature.Features; import org.apache.sis.feature.builder.FeatureTypeBuilder; import org.apache.sis.feature.builder.AttributeRole; import org.apache.sis.feature.internal.shared.AttributeConvention; -import org.apache.sis.storage.base.MemoryFeatureSet; import org.apache.sis.filter.DefaultFilterFactory; import org.apache.sis.util.iso.Names; diff --git a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/GridResourceMock.java b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/GridResourceMock.java index 306bcea036..7e33359497 100644 --- a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/GridResourceMock.java +++ b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/GridResourceMock.java @@ -23,6 +23,7 @@ import org.apache.sis.coverage.grid.GridCoverage; import org.apache.sis.coverage.grid.GridCoverage2D; import org.apache.sis.coverage.grid.GridExtent; import org.apache.sis.coverage.grid.GridGeometry; +import org.apache.sis.storage.MemoryGridCoverageResource; // Test dependencies import static org.junit.jupiter.api.Assertions.*; @@ -30,11 +31,10 @@ import static org.junit.jupiter.api.Assertions.*; /** * A resource for one-banded images generated on-the-fly when {@link #read(GridGeometry, int...)} is invoked. - * This class has some similarities with {@link org.apache.sis.storage.base.MemoryGridResource} except that - * the {@link GridCoverage} returned by {@link #read read(…)} is guaranteed to wrap an image having exactly the - * requested size (i.e. the size specified by {@link GridGeometry#getExtent()}). - * By contrast {@code org.apache.sis.storage.base.MemoryGridResource} may return images larger than requested, - * which make testing more difficult. + * This class has some similarities with {@link MemoryGridCoverageResource} except that the {@link GridCoverage} + * returned by the {@link #read read(…)} method is guaranteed to wrap an image having exactly the requested size + * (i.e. the size specified by {@link GridGeometry#getExtent()}). By contrast, {@link MemoryGridCoverageResource} + * may return images larger than requested, which make testing more difficult. * * @author Johann Sorel (Geomatys) */ @@ -53,7 +53,7 @@ final class GridResourceMock extends AbstractGridCoverageResource { * Creates a resource mock with the given grid geometry. */ GridResourceMock(final GridGeometry gridGeometry) { - super(null, false); + super(null); assertNotNull(gridGeometry); this.gridGeometry = gridGeometry; this.sampleDimensions = List.of(new SampleDimension.Builder().setName(0).build()); diff --git a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/base/MemoryGridResourceTest.java b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/MemoryGridCoverageResourceTest.java similarity index 80% rename from endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/base/MemoryGridResourceTest.java rename to endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/MemoryGridCoverageResourceTest.java index ef0750a4ae..eb59bca38f 100644 --- a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/base/MemoryGridResourceTest.java +++ b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/MemoryGridCoverageResourceTest.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.sis.storage.base; +package org.apache.sis.storage; import java.awt.image.BufferedImage; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -34,11 +34,12 @@ import static org.apache.sis.test.Assertions.assertEqualsIgnoreMetadata; /** - * Tests {@link MemoryGridResource}. + * Tests {@link MemoryGridCoverageResource}. * * @author Martin Desruisseaux (Geomatys) */ -public final class MemoryGridResourceTest extends TestCase { +@SuppressWarnings("exports") +public final class MemoryGridCoverageResourceTest extends TestCase { /** * Arbitrary size for the grid to test. */ @@ -57,24 +58,24 @@ public final class MemoryGridResourceTest extends TestCase { /** * The resource to be tested by each test method. */ - private final MemoryGridResource resource; + private final MemoryGridCoverageResource resource; /** * Creates a new test case. */ - public MemoryGridResourceTest() { + public MemoryGridCoverageResourceTest() { crs = HardCodedCRS.WGS84; gridToCRS = new AffineTransform2D(2, 0, 0, 3, 0, 0); - final GridGeometry grid = new GridGeometry(new GridExtent(WIDTH, HEIGHT), PixelInCell.CELL_CENTER, gridToCRS, crs); - final BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_BYTE_BINARY); - resource = new MemoryGridResource(null, null, new GridCoverage2D(grid, null, image), null); + final var grid = new GridGeometry(new GridExtent(WIDTH, HEIGHT), PixelInCell.CELL_CENTER, gridToCRS, crs); + final var image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_BYTE_BINARY); + resource = new MemoryGridCoverageResource(null, new GridCoverage2D(grid, null, image), null); } /** * Creates an arbitrary grid geometry included inside the {@linkplain #resource} extent. */ private GridGeometry createSubGrid() { - final GridExtent extent = new GridExtent(null, + final var extent = new GridExtent(null, new long[] {7, 4}, new long[] {WIDTH - 9, HEIGHT - 11}, true); @@ -82,7 +83,7 @@ public final class MemoryGridResourceTest extends TestCase { } /** - * Tests {@link MemoryGridResource#read(GridGeometry, int...)}. + * Tests {@link MemoryGridCoverageResource#read(GridGeometry, int[])}. */ @Test public void testRead() { diff --git a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/BandAggregateGridResourceTest.java b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/BandAggregateGridResourceTest.java index adc7968511..4c02d10c85 100644 --- a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/BandAggregateGridResourceTest.java +++ b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/BandAggregateGridResourceTest.java @@ -33,7 +33,7 @@ import org.apache.sis.coverage.grid.BufferedGridCoverage; import org.apache.sis.coverage.grid.GridCoverageProcessor; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.GridCoverageResource; -import org.apache.sis.storage.base.MemoryGridResource; +import org.apache.sis.storage.MemoryGridCoverageResource; // Test dependencies import org.junit.jupiter.api.Test; @@ -48,6 +48,7 @@ import org.apache.sis.referencing.crs.HardCodedCRS; * @author Alexis Manin (Geomatys) * @author Martin Desruisseaux (Geomatys) */ +@SuppressWarnings("exports") public final class BandAggregateGridResourceTest extends TestCase { /** * Width and height of images created for tests. @@ -65,7 +66,7 @@ public final class BandAggregateGridResourceTest extends TestCase { private final GridCoverageProcessor processor; /** - * Whether to hide {@link MemoryGridResource} in order to disable optimizations. + * Whether to hide {@link MemoryGridCoverageResource} in order to disable optimizations. */ private boolean opaque; @@ -153,7 +154,7 @@ public final class BandAggregateGridResourceTest extends TestCase { final var aggregator = new CoverageAggregator(null, processor); aggregator.addRangeAggregate(first, second); /* - * If the result is not an instance of `MemoryGridResource`, + * If the result is not an instance of `MemoryGridCoverageResource`, * this is a bug in `BandAggregateGridResource.create(…)`. */ final LocalName testName = Names.createLocalName(null, null, "test-name"); @@ -167,7 +168,7 @@ public final class BandAggregateGridResourceTest extends TestCase { } /** - * Tests the shortcut for {@link MemoryGridResource} instances. + * Tests the shortcut for {@link MemoryGridCoverageResource} instances. * {@link BandAggregateGridResource} should apply aggregations directly on the underlying grid coverages. * * @throws DataStoreException if an error occurred while reading a resource. @@ -200,7 +201,7 @@ public final class BandAggregateGridResourceTest extends TestCase { System.arraycopy(bandValues, 0, data, i, numBands); } final var values = new DataBufferInt(data, data.length); - final var r = new MemoryGridResource(null, null, new BufferedGridCoverage(domain, samples, values), null); + final var r = new MemoryGridCoverageResource(null, new BufferedGridCoverage(domain, samples, values), null); return opaque ? new OpaqueGridResource(r) : r; } diff --git a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/ConcatenatedFeatureSetTest.java b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/ConcatenatedFeatureSetTest.java index cd509bf382..f0e4fe4883 100644 --- a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/ConcatenatedFeatureSetTest.java +++ b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/ConcatenatedFeatureSetTest.java @@ -23,7 +23,7 @@ import org.apache.sis.feature.builder.FeatureTypeBuilder; import org.apache.sis.storage.DataStoreContentException; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.FeatureSet; -import org.apache.sis.storage.base.MemoryFeatureSet; +import org.apache.sis.storage.MemoryFeatureSet; // Test dependencies import org.junit.jupiter.api.Test; diff --git a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/CoverageMosaicTest.java b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/CoverageMosaicTest.java index dccd97d35c..cf337d3f82 100644 --- a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/CoverageMosaicTest.java +++ b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/CoverageMosaicTest.java @@ -52,6 +52,7 @@ import org.apache.sis.test.TestUtilities; * * @author Martin Desruisseaux (Geomatys) */ +@SuppressWarnings("exports") @TestInstance(TestInstance.Lifecycle.PER_CLASS) public final class CoverageMosaicTest extends TestCase { /** @@ -367,10 +368,10 @@ public final class CoverageMosaicTest extends TestCase { assertEquals(ranges, coverage.getSampleDimensions()); GridExtent extent = coverage.getGridGeometry().getExtent(); /* - * At the time of writing this test, the `MemoryGridResource.read(…)` implementation + * At the time of writing this test, the `MemoryGridCoverageResource.read(…)` implementation * does not apply subsampling. Therefore, the coverage is as `testReadTilesFully()`. * If a test failure happens below in a future version, this is not necessarily a bug. - * Maybe `MemoryGridResource` has been improved and this test should be adjusted. + * Maybe `MemoryGridCoverageResource` has been improved and this test should be adjusted. */ assertEquals(NUM_TILES*TILE_WIDTH, extent.getSize(0)); assertEquals(NUM_TILES*TILE_HEIGHT, extent.getSize(1)); diff --git a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/JoinFeatureSetTest.java b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/JoinFeatureSetTest.java index 2034ca8e58..a284783097 100644 --- a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/JoinFeatureSetTest.java +++ b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/JoinFeatureSetTest.java @@ -27,7 +27,7 @@ import org.apache.sis.feature.builder.FeatureTypeBuilder; import org.apache.sis.feature.internal.shared.AttributeConvention; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.FeatureSet; -import org.apache.sis.storage.base.MemoryFeatureSet; +import org.apache.sis.storage.MemoryFeatureSet; // Test dependencies import org.junit.jupiter.api.Test; diff --git a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/OpaqueGridResource.java b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/OpaqueGridResource.java index 671b6b3e83..4bb8c7272e 100644 --- a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/OpaqueGridResource.java +++ b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/aggregate/OpaqueGridResource.java @@ -18,13 +18,13 @@ package org.apache.sis.storage.aggregate; import org.apache.sis.coverage.grid.GridCoverage; import org.apache.sis.storage.GridCoverageResource; +import org.apache.sis.storage.MemoryGridCoverageResource; import org.apache.sis.storage.base.GridResourceWrapper; -import org.apache.sis.storage.base.MemoryGridResource; /** * Wraps a grid coverage resource without changing anything. This is used for disabling optimizations, - * in order to test different code paths that what would be used with {@code MemoryGridResource}. + * in order to test different code paths that what would be used with {@code MemoryGridCoverageResource}. * * @author Martin Desruisseaux (Geomatys) */ @@ -38,7 +38,7 @@ final class OpaqueGridResource extends GridResourceWrapper { * Creates a new wrapper for the given coverage. */ OpaqueGridResource(final GridCoverage source) { - this.source = new MemoryGridResource(null, null, source, null); + this.source = new MemoryGridCoverageResource(null, source, null); } /** diff --git a/incubator/src/org.apache.sis.portrayal.map/test/org/apache/sis/map/SEPortrayerTest.java b/incubator/src/org.apache.sis.portrayal.map/test/org/apache/sis/map/SEPortrayerTest.java index aeb8903057..06797449e3 100644 --- a/incubator/src/org.apache.sis.portrayal.map/test/org/apache/sis/map/SEPortrayerTest.java +++ b/incubator/src/org.apache.sis.portrayal.map/test/org/apache/sis/map/SEPortrayerTest.java @@ -20,7 +20,6 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Objects; -import java.util.Optional; import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -29,7 +28,6 @@ import org.locationtech.jts.geom.CoordinateXY; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Point; import org.locationtech.jts.geom.Polygon; -import org.opengis.util.GenericName; import org.opengis.geometry.Envelope; import org.opengis.metadata.Metadata; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -52,7 +50,7 @@ import org.apache.sis.storage.Aggregate; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.FeatureSet; import org.apache.sis.storage.Resource; -import org.apache.sis.storage.base.MemoryFeatureSet; +import org.apache.sis.storage.MemoryFeatureSet; import org.apache.sis.style.se1.FeatureTypeStyle; import org.apache.sis.style.se1.Symbology; import org.apache.sis.style.se1.StyleFactory; @@ -60,8 +58,6 @@ import org.apache.sis.style.se1.Symbolizer; import org.apache.sis.style.se1.SemanticType; import org.apache.sis.referencing.CRS; import org.apache.sis.referencing.CommonCRS; -import org.apache.sis.storage.event.StoreEvent; -import org.apache.sis.storage.event.StoreListener; import org.apache.sis.util.iso.Names; // Test dependencies @@ -543,21 +539,10 @@ public class SEPortrayerTest { return list; } - @Override - public Optional<GenericName> getIdentifier() throws DataStoreException { - return Optional.empty(); - } - @Override public Metadata getMetadata() throws DataStoreException { return null; } - - @Override - public <T extends StoreEvent> void addListener(Class<T> eventType, StoreListener<? super T> listener) {} - - @Override - public <T extends StoreEvent> void removeListener(Class<T> eventType, StoreListener<? super T> listener) {} }; final MapLayer aggLayer = new MapLayer(); diff --git a/incubator/src/org.apache.sis.portrayal.map/test/org/apache/sis/map/service/GraphicsPortrayerTest.java b/incubator/src/org.apache.sis.portrayal.map/test/org/apache/sis/map/service/GraphicsPortrayerTest.java index fa435f29b3..711db8eb5b 100644 --- a/incubator/src/org.apache.sis.portrayal.map/test/org/apache/sis/map/service/GraphicsPortrayerTest.java +++ b/incubator/src/org.apache.sis.portrayal.map/test/org/apache/sis/map/service/GraphicsPortrayerTest.java @@ -39,7 +39,7 @@ import org.apache.sis.map.SEPresentation; import org.apache.sis.referencing.CRS; import org.apache.sis.referencing.CommonCRS; import org.apache.sis.storage.FeatureSet; -import org.apache.sis.storage.base.MemoryFeatureSet; +import org.apache.sis.storage.MemoryFeatureSet; import org.apache.sis.style.se1.FeatureTypeStyle; import org.apache.sis.style.se1.LineSymbolizer; import org.apache.sis.style.se1.Rule; diff --git a/incubator/src/org.apache.sis.storage.coveragejson/test/org/apache/sis/storage/coveragejson/CoverageJsonStoreTest.java b/incubator/src/org.apache.sis.storage.coveragejson/test/org/apache/sis/storage/coveragejson/CoverageJsonStoreTest.java index eda64970b1..0a9d1d9027 100644 --- a/incubator/src/org.apache.sis.storage.coveragejson/test/org/apache/sis/storage/coveragejson/CoverageJsonStoreTest.java +++ b/incubator/src/org.apache.sis.storage.coveragejson/test/org/apache/sis/storage/coveragejson/CoverageJsonStoreTest.java @@ -34,10 +34,10 @@ import org.apache.sis.storage.Aggregate; import org.apache.sis.storage.DataStore; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.GridCoverageResource; +import org.apache.sis.storage.MemoryGridCoverageResource; import org.apache.sis.storage.Resource; import org.apache.sis.storage.StorageConnector; import org.apache.sis.storage.WritableAggregate; -import org.apache.sis.storage.base.MemoryGridResource; import org.apache.sis.referencing.CRS; import org.apache.sis.referencing.CommonCRS; @@ -132,7 +132,7 @@ public class CoverageJsonStoreTest { gcb.setValues(image); final GridCoverage coverage = gcb.build(); - final GridCoverageResource gcr = new MemoryGridResource(null, null, coverage, null); + final GridCoverageResource gcr = new MemoryGridCoverageResource(null, coverage, null); aggregate.add(gcr); diff --git a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/dataset/RootResource.java b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/dataset/RootResource.java index 8bcc1722ef..43466ea1de 100644 --- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/dataset/RootResource.java +++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/dataset/RootResource.java @@ -19,14 +19,10 @@ package org.apache.sis.gui.dataset; import java.util.AbstractList; import java.util.Collection; import java.util.List; -import java.util.Optional; import javafx.scene.control.TreeItem; import org.opengis.metadata.Metadata; -import org.opengis.util.GenericName; import org.apache.sis.storage.Aggregate; import org.apache.sis.storage.Resource; -import org.apache.sis.storage.event.StoreEvent; -import org.apache.sis.storage.event.StoreListener; /** @@ -109,14 +105,6 @@ final class RootResource implements Aggregate { }; } - /** - * Returns empty optional since this resource has no identifier. - */ - @Override - public Optional<GenericName> getIdentifier() { - return Optional.empty(); - } - /** * Returns null since this resource has no metadata. Returning null is normally * not allowed for this method, but {@link ResourceTree} is robust to this case. @@ -125,8 +113,4 @@ final class RootResource implements Aggregate { public Metadata getMetadata() { return null; } - - /** Ignored since this class does not emit any event. */ - @Override public <T extends StoreEvent> void addListener(Class<T> eventType, StoreListener<? super T> listener) {} - @Override public <T extends StoreEvent> void removeListener(Class<T> eventType, StoreListener<? super T> listener) {} }
