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 428ee02c5e942943502fce6cb935ca737761bbc1 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Mon May 5 17:07:38 2025 +0200 Add a `PropertyTypeBuilder.replaceBy(…)` method. --- .../sis/feature/builder/AttributeTypeBuilder.java | 14 +++++----- .../sis/feature/builder/FeatureTypeBuilder.java | 10 +++++-- .../sis/feature/builder/PropertyTypeBuilder.java | 32 ++++++++++++++++++++-- .../org/apache/sis/feature/internal/Resources.java | 5 ++++ .../sis/feature/internal/Resources.properties | 1 + .../sis/feature/internal/Resources_fr.properties | 1 + .../feature/builder/FeatureTypeBuilderTest.java | 29 ++++++++++++++++++++ 7 files changed, 79 insertions(+), 13 deletions(-) diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/AttributeTypeBuilder.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/AttributeTypeBuilder.java index 9a572459ef..ece724e014 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/AttributeTypeBuilder.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/AttributeTypeBuilder.java @@ -64,7 +64,7 @@ import org.opengis.feature.AttributeType; * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 0.8 + * @version 1.5 * * @param <V> the class of attribute values. * @@ -294,11 +294,11 @@ public final class AttributeTypeBuilder<V> extends PropertyTypeBuilder { if (type == valueClass) { return (AttributeTypeBuilder<N>) this; } - final AttributeTypeBuilder<N> newb = new AttributeTypeBuilder<>(this, type); + final var newb = new AttributeTypeBuilder<N>(this, type); for (final CharacteristicTypeBuilder<?> c : characteristics) { c.owner(newb); } - owner.replace(this, newb); + owner.replace(this, newb, true); dispose(); return newb; } @@ -343,7 +343,7 @@ public final class AttributeTypeBuilder<V> extends PropertyTypeBuilder { final V[] values = (V[]) Array.newInstance(valueClass, c.size()); int index = 0; for (final Object value : c) { - values[index++] = (V) value; // ArrayStoreException if 'value' is not the expected type. + values[index++] = (V) value; // ArrayStoreException if `value` is not the expected type. } return values; } @@ -589,14 +589,14 @@ public final class AttributeTypeBuilder<V> extends PropertyTypeBuilder { next = AttributeRole.IDENTIFIER_COMPONENT; break; } - index++; // Fall through for testing the case for next 'index' value. + index++; // Fall through for testing the case for next `index` value. } case 1: { if (owner().defaultGeometry == AttributeTypeBuilder.this) { next = AttributeRole.DEFAULT_GEOMETRY; break; } - index++; // Fall through for testing the case for next 'index' value. + index++; // Fall through for testing the case for next `index` value. } default: { return false; @@ -718,7 +718,7 @@ public final class AttributeTypeBuilder<V> extends PropertyTypeBuilder { public void remove() { if (isIdentifier) { isIdentifier = false; - owner().identifierCount--; // Owner should never be null since we set 'isIdentifier' to false. + owner().identifierCount--; // Owner should never be null since we set `isIdentifier` to false. } super.remove(); } diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/FeatureTypeBuilder.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/FeatureTypeBuilder.java index 22287ece14..a11ddf1654 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/FeatureTypeBuilder.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/FeatureTypeBuilder.java @@ -1001,11 +1001,15 @@ public class FeatureTypeBuilder extends TypeBuilder { /** * Replaces the given builder instance by a new instance, or delete the old instance. * This builder should contain exactly one instance of the given {@code old} builder. + * The {@code metadata} argument should generally be {@code true}, except when this + * method is invoked for removing a property only temporarily, e.g. before to move + * it to another location. * * @param old the instance to replace. * @param replacement the replacement, or {@code null} for deleting the old instance. + * @param metadata whether to update metadata such as {@link #defaultGeometry}. */ - final void replace(final PropertyTypeBuilder old, final PropertyTypeBuilder replacement) { + final void replace(final PropertyTypeBuilder old, final PropertyTypeBuilder replacement, final boolean metadata) { final int index = properties.lastIndexOf(old); if (index < 0 || (replacement != null ? properties.set(index, replacement) : properties.remove(index)) != old) { /* @@ -1014,8 +1018,8 @@ public class FeatureTypeBuilder extends TypeBuilder { */ throw new CorruptedObjectException(); } - if (old == defaultGeometry) { - defaultGeometry = (AttributeTypeBuilder<?>) replacement; + if (metadata && old == defaultGeometry) { + defaultGeometry = (replacement instanceof AttributeTypeBuilder<?>) ? (AttributeTypeBuilder<?>) replacement : null; } clearCache(); } diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/PropertyTypeBuilder.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/PropertyTypeBuilder.java index 0b4c088e8d..2c9405313e 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/PropertyTypeBuilder.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/builder/PropertyTypeBuilder.java @@ -18,6 +18,7 @@ package org.apache.sis.feature.builder; import org.opengis.util.GenericName; import org.apache.sis.util.resources.Errors; +import org.apache.sis.feature.internal.Resources; // Specific to the geoapi-3.1 and geoapi-4.0 branches: import org.opengis.feature.AttributeType; @@ -41,7 +42,7 @@ import org.opengis.feature.FeatureAssociationRole; * * @author Johann Sorel (Geomatys) * @author Martin Desruisseaux (Geomatys) - * @version 1.0 + * @version 1.5 * @since 0.8 */ public abstract class PropertyTypeBuilder extends TypeBuilder { @@ -80,7 +81,7 @@ public abstract class PropertyTypeBuilder extends TypeBuilder { owner = builder.owner; minimumOccurs = builder.minimumOccurs; maximumOccurs = builder.maximumOccurs; - // Do not copy the 'property' reference since the 'valueClass' is different. + // Do not copy the `property` reference since the `valueClass` is different. } /** @@ -312,8 +313,33 @@ public abstract class PropertyTypeBuilder extends TypeBuilder { @Override public void remove() { if (owner != null) { - owner.replace(this, null); + owner.replace(this, null, true); dispose(); } } + + /** + * Removes this property and moves the given replacement to the location previously occupied by this property. + * The replacement must have been built by the same {@link FeatureTypeBuilder} than this property. + * If the replacement is {@code null}, then this method is equivalent to {@link #remove()}. + * + * @param replacement the property to move to the location of this property, or {@code null} if none. + * @throws IllegalArgumentException if the replacement has not been built by the same {@link FeatureTypeBuilder} + * than this property. + * + * @since 1.5 + */ + public void replaceBy(final PropertyTypeBuilder replacement) { + @SuppressWarnings("LocalVariableHidesMemberVariable") + final FeatureTypeBuilder owner = owner(); + if (replacement != null) { + if (replacement.owner() != owner) { + throw new IllegalArgumentException(resources().getString(Resources.Keys.MismatchedParentFeature)); + } + owner.replace(replacement, null, false); + } + owner.replace(this, replacement, true); + dispose(); + remove(); // For subclasses that override this method. + } } diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources.java index c3ad59f00a..b887eda202 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources.java @@ -315,6 +315,11 @@ public class Resources extends IndexedResourceBundle { */ public static final short MismatchedImageSize_3 = 44; + /** + * The two properties are not members of the same feature. + */ + public static final short MismatchedParentFeature = 92; + /** * Mismatched type for “{0}” property. */ diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources.properties b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources.properties index 1aeaa4f3bf..2dd17c3f46 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources.properties +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources.properties @@ -70,6 +70,7 @@ MismatchedDataType = The bands store sample values using differen MismatchedGeometryLibrary_2 = Expected a geometry from {0} library but got {1}. MismatchedImageLocation = The two images have different size or pixel coordinates. MismatchedImageSize_3 = Image {0,choice,0#width|1#height} ({1,number} pixels) does not match the grid extent size ({2,number} cells). +MismatchedParentFeature = The two properties are not members of the same feature. MismatchedPropertyType_1 = Mismatched type for \u201c{0}\u201d property. MismatchedSampleModel = The two images use different sample models. MismatchedTileGrid = The two images have different tile grid. diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources_fr.properties b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources_fr.properties index b2b4f45237..13996cde79 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources_fr.properties +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/feature/internal/Resources_fr.properties @@ -75,6 +75,7 @@ MismatchedDataType = Les bandes stockent leurs valeurs en utilisa MismatchedGeometryLibrary_2 = Une g\u00e9om\u00e9tries {0} \u00e9tait attendue mais l\u2019objet re\u00e7u est de {1}. MismatchedImageLocation = Les deux images ont une taille ou des coordonn\u00e9es pixels diff\u00e9rentes. MismatchedImageSize_3 = La {0,choice,0#largeur|1#hauteur} de l\u2019image ({1,number} pixels) ne correspond pas \u00e0 l\u2019\u00e9tendue de la grille ({2,number} cellules). +MismatchedParentFeature = Les deux propri\u00e9t\u00e9s ne sont pas membres de la m\u00eame entit\u00e9. MismatchedPropertyType_1 = Le type de la propri\u00e9t\u00e9 \u00ab\u202f{0}\u202f\u00bb ne correspond pas. MismatchedSampleModel = Les deux images disposent les pixels diff\u00e9remment. MismatchedTileGrid = Les deux images utilisent des grilles de tuiles diff\u00e9rentes. diff --git a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/feature/builder/FeatureTypeBuilderTest.java b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/feature/builder/FeatureTypeBuilderTest.java index 3e4f9bb389..42cd33194a 100644 --- a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/feature/builder/FeatureTypeBuilderTest.java +++ b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/feature/builder/FeatureTypeBuilderTest.java @@ -259,6 +259,35 @@ public final class FeatureTypeBuilderTest extends TestCase { assertEquals(Integer.class, a2.getValueClass()); } + /** + * Tests {@link PropertyTypeBuilder#replaceBy(PropertyTypeBuilder)}. + */ + @Test + public void testReplace() { + final var builder = new FeatureTypeBuilder(); + assertSame(builder, builder.setName("City")); + final AttributeTypeBuilder<?> toReplace, replacement; + /* unmodified */ builder.addAttribute(String.class).setName("name"); + toReplace = builder.addAttribute(String.class).setName("someKey"); + /* unmodified */ builder.addAttribute(Integer.class).setName("population"); + replacement = builder.addAttribute(Integer.class).setName("someId"); + + var it = builder.build().getProperties(true).iterator(); + assertPropertyEquals("name", String.class, it.next()); + assertPropertyEquals("someKey", String.class, it.next()); + assertPropertyEquals("population", Integer.class, it.next()); + assertPropertyEquals("someId", Integer.class, it.next()); + assertFalse(it.hasNext()); + + toReplace.replaceBy(replacement); + assertMessageContains(assertThrows(IllegalStateException.class, () -> toReplace.setName("Foo"))); + it = builder.build().getProperties(true).iterator(); + assertPropertyEquals("name", String.class, it.next()); + assertPropertyEquals("someId", Integer.class, it.next()); + assertPropertyEquals("population", Integer.class, it.next()); + assertFalse(it.hasNext()); + } + /** * Tests creation of a builder from an existing feature type. * This method also acts as a test of {@code FeatureTypeBuilder} getter methods.