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 342db9c59d Register an adapter for redirecting warnings from 
filter/expression to data store listeners.
342db9c59d is described below

commit 342db9c59da1ba574d928614504fdea025f9c0b9
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Wed Oct 29 00:33:54 2025 +0100

    Register an adapter for redirecting warnings from filter/expression to data 
store listeners.
---
 .../org/apache/sis/storage/AbstractFeatureSet.java | 27 ++++++++
 .../storage/aggregate/ConcatenatedFeatureSet.java  |  2 +-
 .../apache/sis/storage/base/WarningAdapter.java    | 77 ++++++++++++++++++++++
 .../apache/sis/storage/event/StoreListeners.java   |  2 +-
 .../sis/storage/shapefile/ShapefileStore.java      | 17 +++--
 5 files changed, 119 insertions(+), 6 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/AbstractFeatureSet.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/AbstractFeatureSet.java
index b3a0c166ca..c3fb323315 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/AbstractFeatureSet.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/AbstractFeatureSet.java
@@ -16,12 +16,16 @@
  */
 package org.apache.sis.storage;
 
+import java.util.Objects;
 import java.util.Optional;
 import java.util.OptionalLong;
+import java.util.function.Consumer;
 import org.opengis.util.GenericName;
 import org.opengis.metadata.Metadata;
 import org.apache.sis.storage.event.StoreListeners;
 import org.apache.sis.storage.base.MetadataBuilder;
+import org.apache.sis.storage.base.WarningAdapter;
+import org.apache.sis.filter.internal.shared.WarningEvent;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.feature.FeatureType;
@@ -100,6 +104,29 @@ public abstract class AbstractFeatureSet extends 
AbstractResource implements Fea
         return OptionalLong.empty();
     }
 
+    /**
+     * Requests a subset of features and/or feature properties from this 
resource.
+     * The default implementation does the same work as the default method of 
the {@link FeatureSet} interface,
+     * except that warnings are redirected to the {@linkplain #listeners 
listeners}.
+     *
+     * @hidden
+     */
+    @Override
+    public FeatureSet subset(final Query query) throws 
UnsupportedQueryException, DataStoreException {
+        if (Objects.requireNonNull(query) instanceof FeatureQuery) {
+            final ThreadLocal<Consumer<WarningEvent>> context = 
WarningEvent.LISTENER;
+            final Consumer<WarningEvent> old = context.get();
+            try {
+                context.set(new WarningAdapter(listeners));
+                return ((FeatureQuery) query).execute(this);
+            } finally {
+                context.set(old);
+            }
+        } else {
+            throw new UnsupportedQueryException();
+        }
+    }
+
     /**
      * Invoked in a synchronized block the first time that {@code 
getMetadata()} is invoked.
      * The default implementation populates metadata based on information 
provided by
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 78a9582e76..f32afb8781 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
@@ -233,7 +233,7 @@ public class ConcatenatedFeatureSet extends 
AggregatedFeatureSet {
      */
     @Override
     public FeatureSet subset(final Query query) throws DataStoreException {
-        final FeatureSet[] subsets = new FeatureSet[sources.size()];
+        final var subsets = new FeatureSet[sources.size()];
         boolean modified = false;
         for (int i=0; i<subsets.length; i++) {
             FeatureSet source = sources.get(i);
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/WarningAdapter.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/WarningAdapter.java
new file mode 100644
index 0000000000..a29e9ff1e5
--- /dev/null
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/WarningAdapter.java
@@ -0,0 +1,77 @@
+/*
+ * 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 java.util.logging.Level;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+import org.apache.sis.storage.event.StoreListeners;
+import org.apache.sis.filter.internal.shared.WarningEvent;
+
+
+/**
+ * Forwards to resource listeners the warnings that occurred during the 
execution of expressions and filters.
+ * This is a bridge between the private filter/expression warning system to 
public resource warning system.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ */
+public final class WarningAdapter implements Consumer<WarningEvent> {
+    /**
+     * The listeners where to send the warnings.
+     */
+    private final StoreListeners listeners;
+
+    /**
+     * Creates a new adapter from filter warnings to resource warnings.
+     *
+     * @param  listeners  the listeners where to send the warnings.
+     */
+    public WarningAdapter(final StoreListeners listeners) {
+        this.listeners = listeners;
+    }
+
+    /**
+     * Invoked when a warning occurred during the execution of filters or 
expressions.
+     *
+     * @param  event  the warning event.
+     */
+    @Override
+    public void accept(final WarningEvent event) {
+        listeners.warning(event.recoverable ? Level.FINE : Level.WARNING, 
null, event.exception);
+    }
+
+    /**
+     * Executes the given action with a redirection of all warnings to the 
given listeners.
+     *
+     * @todo Replace by {@code ScopedValue.call(…)} when allowed to use JDK25.
+     *
+     * @param  <V>        the return value type of the given action.
+     * @param  action     the action to execute.
+     * @param  listeners  the listeners where to send the warnings.
+     * @return the return value of the given action.
+     */
+    public static <V> V execute(final Supplier<V> action, final StoreListeners 
listeners) {
+        final ThreadLocal<Consumer<WarningEvent>> context = 
WarningEvent.LISTENER;
+        final Consumer<WarningEvent> old = context.get();
+        try {
+            context.set(new WarningAdapter(listeners));
+            return action.get();
+        } finally {
+            context.set(old);
+        }
+    }
+}
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/event/StoreListeners.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/event/StoreListeners.java
index 4674576d1b..246165ab57 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/event/StoreListeners.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/event/StoreListeners.java
@@ -885,7 +885,7 @@ public class StoreListeners implements Localized {
      *
      * @since 1.2
      */
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({"unchecked", "element-type-mismatch"})
     public synchronized void setUsableEventTypes(final Class<?>... permitted) {
         ArgumentChecks.ensureNonEmpty("permitted", permitted);
         final Set<Class<? extends StoreEvent>> current = permittedEventTypes;
diff --git 
a/incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java
 
b/incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java
index 555d5ba7ef..877e9abb24 100644
--- 
a/incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java
+++ 
b/incubator/src/org.apache.sis.storage.shapefile/main/org/apache/sis/storage/shapefile/ShapefileStore.java
@@ -76,6 +76,7 @@ import org.apache.sis.filter.DefaultFilterFactory;
 import org.apache.sis.filter.Optimization;
 import org.apache.sis.filter.internal.shared.FunctionNames;
 import org.apache.sis.filter.internal.shared.ListingPropertyVisitor;
+import org.apache.sis.filter.internal.shared.WarningEvent;
 import org.apache.sis.io.stream.ChannelDataInput;
 import org.apache.sis.io.stream.ChannelDataOutput;
 import org.apache.sis.io.stream.IOUtilities;
@@ -127,6 +128,7 @@ import org.opengis.filter.LogicalOperatorName;
 import org.opengis.filter.SpatialOperatorName;
 import org.opengis.filter.ValueReference;
 import org.apache.sis.geometry.wrapper.*;
+import org.apache.sis.storage.base.WarningAdapter;
 
 
 /**
@@ -578,10 +580,17 @@ public final class ShapefileStore extends DataStore 
implements WritableFeatureSe
                     //run optimizations
                     final Optimization optimization = new Optimization();
                     optimization.setFeatureType(type);
-                    selection = optimization.apply(selection);
-                    final Entry<Envelope, Filter> split = 
extractBbox(selection);
-                    bbox = split.getKey();
-                    selection = split.getValue();
+                    final ThreadLocal<Consumer<WarningEvent>> context = 
WarningEvent.LISTENER;
+                    final Consumer<WarningEvent> old = context.get();
+                    try {
+                        context.set(new WarningAdapter(listeners));
+                        selection = optimization.apply(selection);
+                        final Entry<Envelope, Filter> split = 
extractBbox(selection);
+                        bbox = split.getKey();
+                        selection = split.getValue();
+                    } finally {
+                        context.set(old);
+                    }
                 }
 
                 //extract field names

Reply via email to