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 71c5b4f09b5dd40cad0ec90c14af80327100f675 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Mon Apr 28 14:34:23 2025 +0200 Add a `Features.getLinkTargets(PropertyType)` method in complement to `getLinkTarget(PropertyType)` method (plural versus singular). Bug fix in `SQLStore` where foreigner keys in queries were followed in the wrong directions (foreigner keys in tables were okay). Minor simplification in exception handling of `DeferredStream` and minor javadoc editions. --- .../apache/sis/cloud/aws/s3/ClientFileSystem.java | 2 +- .../org/apache/sis/feature/FeatureOperations.java | 27 ++++++++-------------- .../main/org/apache/sis/feature/Features.java | 25 +++++++++++++++++++- .../apache/sis/feature/StringJoinOperation.java | 14 +++++++++++ .../apache/sis/feature/builder/TypeBuilder.java | 2 +- .../org/apache/sis/storage/sql/feature/Table.java | 2 +- .../org/apache/sis/util/stream/DeferredStream.java | 10 +++----- .../sis/util/privy/UnmodifiableArrayList.java | 3 ++- 8 files changed, 55 insertions(+), 30 deletions(-) diff --git a/endorsed/src/org.apache.sis.cloud.aws/main/org/apache/sis/cloud/aws/s3/ClientFileSystem.java b/endorsed/src/org.apache.sis.cloud.aws/main/org/apache/sis/cloud/aws/s3/ClientFileSystem.java index 4e79d1f194..e28376cf7d 100644 --- a/endorsed/src/org.apache.sis.cloud.aws/main/org/apache/sis/cloud/aws/s3/ClientFileSystem.java +++ b/endorsed/src/org.apache.sis.cloud.aws/main/org/apache/sis/cloud/aws/s3/ClientFileSystem.java @@ -234,7 +234,7 @@ final class ClientFileSystem extends FileSystem { * Returns a filter that matches {@link KeyPath} string representation against a given pattern. * * @param syntaxAndPattern filtering criteria of the {@code syntax:pattern}. - * @return a {@kink KeyPath} matcher for the given pattern. + * @return a {@link KeyPath} matcher for the given pattern. * @throws PatternSyntaxException if the pattern is invalid. * @throws UnsupportedOperationException if the pattern syntax is not known to this implementation. */ diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/FeatureOperations.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/FeatureOperations.java index 4ab41f8df7..f1ca57ee9a 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/FeatureOperations.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/FeatureOperations.java @@ -58,48 +58,39 @@ import org.opengis.filter.Expression; * <th>Map key</th> * <th>Value type</th> * <th>Returned by</th> - * </tr> - * <tr> + * </tr><tr> * <td>{@value org.apache.sis.feature.AbstractIdentifiedType#NAME_KEY}</td> * <td>{@link GenericName} or {@link String}</td> * <td>{@link AbstractOperation#getName() Operation.getName()} (mandatory)</td> - * </tr> - * <tr> + * </tr><tr> * <td>{@value org.apache.sis.feature.AbstractIdentifiedType#DEFINITION_KEY}</td> * <td>{@link InternationalString} or {@link String}</td> * <td>{@link AbstractOperation#getDefinition() Operation.getDefinition()}</td> - * </tr> - * <tr> + * </tr><tr> * <td>{@value org.apache.sis.feature.AbstractIdentifiedType#DESIGNATION_KEY}</td> * <td>{@link InternationalString} or {@link String}</td> * <td>{@link AbstractOperation#getDesignation() Operation.getDesignation()}</td> - * </tr> - * <tr> + * </tr><tr> * <td>{@value org.apache.sis.feature.AbstractIdentifiedType#DESCRIPTION_KEY}</td> * <td>{@link InternationalString} or {@link String}</td> * <td>{@link AbstractOperation#getDescription() Operation.getDescription()}</td> - * </tr> - * <tr> + * </tr><tr> * <td>"result.name"</td> * <td>{@link GenericName} or {@link String}</td> * <td>{@link AbstractAttribute#getName() Attribute.getName()} on the {@linkplain AbstractOperation#getResult() result}</td> - * </tr> - * <tr> + * </tr><tr> * <td>"result.definition"</td> * <td>{@link InternationalString} or {@link String}</td> * <td>{@link DefaultAttributeType#getDefinition() Attribute.getDefinition()} on the {@linkplain AbstractOperation#getResult() result}</td> - * </tr> - * <tr> + * </tr><tr> * <td>"result.designation"</td> * <td>{@link InternationalString} or {@link String}</td> * <td>{@link DefaultAttributeType#getDesignation() Attribute.getDesignation()} on the {@linkplain AbstractOperation#getResult() result}</td> - * </tr> - * <tr> + * </tr><tr> * <td>"result.description"</td> * <td>{@link InternationalString} or {@link String}</td> * <td>{@link DefaultAttributeType#getDescription() Attribute.getDescription()} on the {@linkplain AbstractOperation#getResult() result}</td> - * </tr> - * <tr> + * </tr><tr> * <td>{@value org.apache.sis.referencing.AbstractIdentifiedObject#LOCALE_KEY}</td> * <td>{@link java.util.Locale}</td> * <td>(none)</td> diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/Features.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/Features.java index 32f9da66a3..00ad38f9d1 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/Features.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/Features.java @@ -17,6 +17,7 @@ package org.apache.sis.feature; import java.util.Map; +import java.util.List; import java.util.Optional; import java.util.IdentityHashMap; import org.opengis.util.GenericName; @@ -49,7 +50,7 @@ import org.opengis.feature.PropertyType; * @author Martin Desruisseaux (Geomatys) * @author Johann Sorel (Geomatys) * @author Alexis Manin (Geomatys) - * @version 1.4 + * @version 1.5 * @since 0.5 */ public final class Features extends Static { @@ -301,6 +302,28 @@ public final class Features extends Static { return Optional.empty(); } + /** + * If the given property is a link or a compound key, returns the name of the referenced properties. + * This method is similar to {@link #getLinkTarget(PropertyType)}, except that it recognizes also + * the operations created by {@link FeatureOperations#compound FeatureOperations.compound(…)}. + * + * @param property the property to test, or {@code null} if none. + * @return the referenced property names if {@code property} is a link or a compound key, + * or an empty list otherwise. + * + * @see FeatureOperations#compound(Map, String, String, String, PropertyType...) + * + * @since 1.5 + */ + public static List<String> getLinkTargets(final PropertyType property) { + return getLinkTarget(property).map(List::of).orElseGet(() -> { + if (property instanceof StringJoinOperation) { + return ((StringJoinOperation) property).getAttributeNames(); + } + return List.of(); + }); + } + /** * Ensures that all characteristics and property values in the given feature are valid. * An attribute is valid if it contains a number of values between the diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/StringJoinOperation.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/StringJoinOperation.java index b69708ecd0..703c02faac 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/StringJoinOperation.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/StringJoinOperation.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.Map; import java.util.Set; import java.util.Objects; +import java.util.List; import java.io.IOException; import java.io.Serializable; import org.opengis.parameter.ParameterDescriptorGroup; @@ -35,6 +36,7 @@ import org.apache.sis.util.privy.CollectionsExt; import org.apache.sis.converter.SurjectiveConverter; import org.apache.sis.feature.privy.AttributeConvention; import org.apache.sis.feature.internal.Resources; +import org.apache.sis.util.privy.UnmodifiableArrayList; import org.apache.sis.util.resources.Errors; // Specific to the geoapi-3.1 and geoapi-4.0 branches: @@ -129,6 +131,9 @@ final class StringJoinOperation extends AbstractOperation { /** * The name of the properties (attributes of operations producing attributes) * from which to get the values to concatenate. + * + * @see #getAttributeNames() + * @see #getDependencies() */ private final String[] attributeNames; @@ -289,6 +294,15 @@ final class StringJoinOperation extends AbstractOperation { return dependencies; } + /** + * Returns the name of the properties from which to get the values to concatenate. + * This is the same information as {@link #getDependencies()}, only in a different + * kind of collection. + */ + final List<String> getAttributeNames() { + return UnmodifiableArrayList.wrap(attributeNames); + } + /** * Formats the given value using the given converter. This method is a workaround for the presence * of the first {@code ?} in {@code ObjectConverter<?,?>}: defining a separated method allows us diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/TypeBuilder.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/TypeBuilder.java index 38914393d7..fbef910a6d 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/TypeBuilder.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/TypeBuilder.java @@ -186,7 +186,7 @@ public abstract class TypeBuilder implements Localized { /** * Returns the name of the {@code IdentifiedType} to create, or {@code null} if undefined. * This method returns the value built from the last call to a {@code setName(…)} method, - * or a default name or {@code null} if no name has been explicitly specified. + * or a default name, or {@code null} if no name has been explicitly specified. * * @return the name of the {@code IdentifiedType} to create (may be a default name or {@code null}). * diff --git a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Table.java b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Table.java index 808c4b80b7..65dc579abb 100644 --- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Table.java +++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Table.java @@ -253,7 +253,7 @@ final class Table extends AbstractFeatureSet { importedKeys[importedKeysCount++] = relation; continue; } - relation = source.getRelation(xpath, false); + relation = source.getRelation(xpath, true); if (relation != null) { exportedKeys[exportedKeysCount++] = relation; continue; diff --git a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/util/stream/DeferredStream.java b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/util/stream/DeferredStream.java index 1d39b8cf7b..027dd0f108 100644 --- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/util/stream/DeferredStream.java +++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/util/stream/DeferredStream.java @@ -120,18 +120,12 @@ public abstract class DeferredStream<T> extends StreamWrapper<T> { try { return createSourceIterator(); } catch (Exception cause) { - final BackingStoreException ex; - if (cause instanceof BackingStoreException) { - ex = (BackingStoreException) cause; - } else { - ex = new BackingStoreException(cause.getMessage(), Exceptions.unwrap(cause)); - } + throw cannotExecute(cause); /* * The close handler will be invoked later assuming that the user created the stream in a * `try ... finally` block. We could invoke the close handler here as a safety, but we do * not do that in order to have more predictable and consistent behavior. */ - throw ex; } } @@ -207,6 +201,8 @@ public abstract class DeferredStream<T> extends StreamWrapper<T> { final Exception unwrap = Exceptions.unwrap(cause); if (unwrap instanceof RuntimeException) { return (RuntimeException) unwrap; + } else if (cause instanceof RuntimeException) { + return (RuntimeException) cause; } else { return new BackingStoreException(cause.toString(), unwrap); } diff --git a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/UnmodifiableArrayList.java b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/UnmodifiableArrayList.java index 43152c5e69..be13369e4e 100644 --- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/UnmodifiableArrayList.java +++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/UnmodifiableArrayList.java @@ -58,6 +58,7 @@ import org.apache.sis.util.collection.CheckedContainer; * * @param <E> the type of elements in the list. */ +@SuppressWarnings("EqualsAndHashcode") public class UnmodifiableArrayList<E> extends AbstractList<E> implements RandomAccess, CheckedContainer<E>, Serializable { /** * For compatibility with different versions. @@ -421,7 +422,7 @@ public class UnmodifiableArrayList<E> extends AbstractList<E> implements RandomA if (!(object instanceof UnmodifiableArrayList<?>)) { return super.equals(object); } - final UnmodifiableArrayList<?> that = (UnmodifiableArrayList<?>) object; + final var that = (UnmodifiableArrayList<?>) object; int size = this.size(); if (size != that.size()) { return false;