From e486fc57f51945787a28a21eda94f735b2bb7ad8 Mon Sep 17 00:00:00 2001 From: Clemens Portele Date: Fri, 26 Jun 2026 12:24:53 +0200 Subject: [PATCH] GML: fix objectTypeSuffixedProperties option All GML configuration options use the property id. objectTypeSuffixedProperties was an exception in that it used the XML element name (which might also be the alias). This change aligns the configuration option with the other GML configuration options. --- .../gml/domain/FeatureTokenDecoderGml.java | 6 +++++- .../FeatureTokenDecoderGmlInputProfile.java | 17 +++++++++-------- .../domain/FeatureTokenDecoderGmlSpec.groovy | 9 +++++---- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/domain/FeatureTokenDecoderGml.java b/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/domain/FeatureTokenDecoderGml.java index 1140cafd8..608dcb016 100644 --- a/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/domain/FeatureTokenDecoderGml.java +++ b/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/domain/FeatureTokenDecoderGml.java @@ -1030,7 +1030,11 @@ private Optional lookupChild( for (FeatureSchema p : parent.getProperties()) { String key = propertyKey(p, useAlias); String base = stripPrefix(key); - boolean suffixed = inputProfile.getObjectTypeSuffixedProperties().contains(base); + // The configured set holds property ids (technical full paths), not the on-the-wire + // name/alias, so membership is tested against the property's full path; the wire element + // base for the suffix match stays the name/alias the encoder emits. + boolean suffixed = + inputProfile.getObjectTypeSuffixedProperties().contains(p.getFullPathAsString()); if (!(wireLocalName.equals(base) || (suffixed && wireLocalName.startsWith(base + "_")))) { continue; } diff --git a/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/domain/FeatureTokenDecoderGmlInputProfile.java b/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/domain/FeatureTokenDecoderGmlInputProfile.java index c64edbf07..2d7254a67 100644 --- a/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/domain/FeatureTokenDecoderGmlInputProfile.java +++ b/xtraplatform-features-gml/src/main/java/de/ii/xtraplatform/features/gml/domain/FeatureTokenDecoderGmlInputProfile.java @@ -164,14 +164,15 @@ default String getFeatureMemberElementName() { Map> getValueWrap(); /** - * Reverse of {@code GmlConfiguration#objectTypeSuffixedProperties}: the name (or alias, when - * {@link #getUseAlias()}) of each FEATURE_REF property whose GML element on the wire is the base - * property name plus a {@code _} suffix naming the referenced feature type (e.g. base - * {@code gehoertZuBauwerk} → {@code gehoertZuBauwerk_AX_Turm}). For these properties the decoder - * accepts an element whose local name is the base name optionally followed by a {@code - * _} suffix and maps it to the base property. The suffix is ignored: the referenced - * object type is carried independently through the FEATURE_REF join, so it need not be captured - * from the wire. + * Reverse of {@code GmlConfiguration#objectTypeSuffixedProperties}: the property id (technical + * full path) of each FEATURE_REF property whose GML element on the wire is the base property + * name/alias plus a {@code _} suffix naming the referenced feature type (e.g. base + * element {@code gehoertZuBauwerk} → {@code gehoertZuBauwerk_AX_Turm}). Membership is tested + * against the property's technical full path, not its on-the-wire name/alias. For these + * properties the decoder accepts an element whose local name is the base name/alias optionally + * followed by a {@code _} suffix and maps it to the property. The suffix is ignored: the + * referenced object type is carried independently through the FEATURE_REF join, so it need not be + * captured from the wire. */ Set getObjectTypeSuffixedProperties(); diff --git a/xtraplatform-features-gml/src/test/groovy/de/ii/xtraplatform/features/gml/domain/FeatureTokenDecoderGmlSpec.groovy b/xtraplatform-features-gml/src/test/groovy/de/ii/xtraplatform/features/gml/domain/FeatureTokenDecoderGmlSpec.groovy index 5daca3a24..1d6e08af3 100644 --- a/xtraplatform-features-gml/src/test/groovy/de/ii/xtraplatform/features/gml/domain/FeatureTokenDecoderGmlSpec.groovy +++ b/xtraplatform-features-gml/src/test/groovy/de/ii/xtraplatform/features/gml/domain/FeatureTokenDecoderGmlSpec.groovy @@ -520,14 +520,15 @@ class FeatureTokenDecoderGmlSpec extends Specification { ImmutableFeatureTokenDecoderGmlInputProfile.builder() .useAlias(true) .featureRefTemplate("urn:adv:oid:{{value}}") - .addObjectTypeSuffixedProperties("istGebucht") + // Declared by property id "11001-21008", not the on-the-wire alias istGebucht. + .addObjectTypeSuffixedProperties("11001-21008") .build() def 'objectTypeSuffixedProperties: a _-suffixed element maps to the base feature-ref property'() { given: - // ALKIS NAS names this element adv:gehoertZuBauwerk_AX_Turm; istGebucht stands in here as a - // declared suffixed property. The _AX_Turm suffix is ignored and the href is reduced as for - // the plain element. + // ALKIS NAS names this element adv:gehoertZuBauwerk_AX_Turm; property "11001-21008" (alias + // istGebucht) stands in here as a declared suffixed property. The _AX_Turm suffix is ignored + // and the href is reduced as for the plain element. def decoder = newDecoder(axFlurstueckWithRefsSchema(), NAS_TEMPLATES_SUFFIXED) def xml = """