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 0c3c6c5f2..6489d5179 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 @@ -1853,7 +1853,10 @@ class FeatureTokenDecoderGmlSpec extends Specification { .putProperties2("rol", new ImmutableFeatureSchema.Builder() .sourcePath("qag__dpl_prs_pro_resp_rol_cdv") .type(SchemaBase.Type.STRING) - .alias("role"))) + .alias("role") + .constraints(new ImmutableSchemaConstraints.Builder() + .codelist("CI_RoleCode") + .build()))) .putProperties2("src", new ImmutableFeatureSchema.Builder() .type(SchemaBase.Type.OBJECT) .objectType("LI_Source") @@ -1952,6 +1955,7 @@ class FeatureTokenDecoderGmlSpec extends Specification { // - dateTime wraps — gmd/gco auto-detected // - organisationName wraps — auto-detected // - role wraps — auto-detected; text content used + // (rol has a codelist constraint, but the gmd text path wins; see the focused test below) // - source/description wraps — explicit valueWrap // The sibling at AX_DQPunktort level exercises a scalar that // sits next to the deep dpl subtree. @@ -2012,6 +2016,48 @@ class FeatureTokenDecoderGmlSpec extends Specification { valueAtPath(tokens, ["qag", "gst"]) == "2100" } + def 'a codelist-constrained role still decodes from the gmd:CI_RoleCode text, not as an xlink:href'() { + given: + // Regression guard for the ISO 19139 codelist encoding (GmlConfiguration#codeListUriTemplateIso19139). + // The `rol` property carries a `codelist` constraint, which makes the decoder treat it as a + // codelist property eligible for xlink:href routing. The ISO 19139 wire, however, carries the + // value in the gmd:CI_RoleCode text content (and the codeListValue attribute), with no + // xlink:href on the property element — so the codelist routing finds no href and the gmd + // value-wrapper text is used. The codeList URI must not leak into the decoded value. + def decoder = newPunktortAuDecoder(nasNamespaceProfile()) + def xml = """ + + + + + + + + + + processor + + + + + + + + + + """ + + when: + def tokens = runDecoder(decoder, xml) + + then: + valueAtPath(tokens, ["qag", "dpl", "prs", "pro", "rol"]) == "processor" + !tokens.contains("https://schemas.isotc211.org/19139/resources/codelists/gmxCodelists.xml/gmxCodelists.xml#CI_RoleCode") + } + def 'LI_ProcessStep children written in the wrong namespace are skipped'() { given: // Sanity check: with objectTypeNamespaces[LI_ProcessStep] = gmd, an LI_ProcessStep