From 43e28e0cc97b97d7e52939af3207207f31fdfa03 Mon Sep 17 00:00:00 2001 From: Adam Retter Date: Mon, 21 Jul 2025 22:54:24 +0200 Subject: [PATCH] [bugfix] Allow the filter functions used by the extract functions of the Compression Module to accept an xs:anyURI for their $path argument as this is used by various apps that relied on this behaviour in eXist-db 6.3.0. Restores compatibility with eXist-db 6.3.0. --- .../compression/AbstractExtractFunction.java | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/extensions/modules/compression/src/main/java/org/exist/xquery/modules/compression/AbstractExtractFunction.java b/extensions/modules/compression/src/main/java/org/exist/xquery/modules/compression/AbstractExtractFunction.java index 3a4df9d6e8..5525c350cb 100644 --- a/extensions/modules/compression/src/main/java/org/exist/xquery/modules/compression/AbstractExtractFunction.java +++ b/extensions/modules/compression/src/main/java/org/exist/xquery/modules/compression/AbstractExtractFunction.java @@ -104,7 +104,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro final FunctionSignature entryFilterFunctionSignature = entryFilterFunction.getSignature(); if (args.length < 5) { - if (!validateFunctionSignature(entryFilterFunctionSignature, new SequenceType(Type.BOOLEAN, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE))) { + if (!validateFunctionSignature(entryFilterFunctionSignature, new SequenceType(Type.BOOLEAN, Cardinality.EXACTLY_ONE), new SequenceType[]{ new SequenceType(Type.ANY_URI, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE) }, new SequenceType[]{ new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE) })) { throw new XPathException(this, "entry-filter function must have a signature that matches: entry-filter($path as xs:string, $data-type as xs:string) as xs:boolean"); } @@ -116,12 +116,12 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro entryDataFunction = (FunctionReference) args[2].itemAt(0); final FunctionSignature entryDataFunctionSignature = entryDataFunction.getSignature(); if (entryDataFunctionSignature.getArgumentCount() == 2) { - if (!validateFunctionSignature(entryDataFunctionSignature, new SequenceType(Type.ANY_URI, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE))) { + if (!validateFunctionSignature(entryDataFunctionSignature, new SequenceType(Type.ANY_URI, Cardinality.EXACTLY_ONE), new SequenceType[]{ new SequenceType(Type.ANY_URI, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE) }, new SequenceType[]{ new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE) })) { throw new XPathException(this, "entry-path function must have a signature that matches: entry-path($path as xs:string, $data-type as xs:string) as xs:anyURI"); } dataParams = new Sequence[2]; } else if (entryDataFunctionSignature.getArgumentCount() == 3) { - if (!validateFunctionSignature(entryDataFunctionSignature, new SequenceType(Type.ITEM, Cardinality.ZERO_OR_MORE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE), new SequenceType(Type.ITEM, Cardinality.ZERO_OR_ONE))) { + if (!validateFunctionSignature(entryDataFunctionSignature, new SequenceType(Type.ITEM, Cardinality.ZERO_OR_MORE), new SequenceType[]{ new SequenceType(Type.ANY_URI, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE) }, new SequenceType[]{ new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE) }, new SequenceType[]{ new SequenceType(Type.ITEM, Cardinality.ZERO_OR_ONE) })) { throw new XPathException(this, "entry-data function must have a signature that matches: entry-data($path as xs:string, $data-type as xs:string, $data as item()?) as item()*"); } dataParams = new Sequence[3]; @@ -136,7 +136,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro } } else { - if (!validateFunctionSignature(entryFilterFunctionSignature, new SequenceType(Type.BOOLEAN, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE), new SequenceType(Type.ITEM, Cardinality.ZERO_OR_MORE))) { + if (!validateFunctionSignature(entryFilterFunctionSignature, new SequenceType(Type.BOOLEAN, Cardinality.EXACTLY_ONE), new SequenceType[]{ new SequenceType(Type.ANY_URI, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE) }, new SequenceType[]{ new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE) }, new SequenceType[]{ new SequenceType(Type.ITEM, Cardinality.ZERO_OR_MORE) })) { throw new XPathException(this, "entry-filter function must have a signature that matches: entry-filter($path as xs:string, $data-type as xs:string, $param as item()*) as xs:boolean"); } @@ -149,13 +149,13 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro entryDataFunction = (FunctionReference) args[3].itemAt(0); final FunctionSignature entryDataFunctionSignature = entryDataFunction.getSignature(); if (entryDataFunctionSignature.getArgumentCount() == 3) { - if (!validateFunctionSignature(entryDataFunctionSignature, new SequenceType(Type.ANY_URI, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE), new SequenceType(Type.ITEM, Cardinality.ZERO_OR_MORE))) { + if (!validateFunctionSignature(entryDataFunctionSignature, new SequenceType(Type.ANY_URI, Cardinality.EXACTLY_ONE), new SequenceType[]{ new SequenceType(Type.ANY_URI, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE) }, new SequenceType[]{ new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE) }, new SequenceType[]{ new SequenceType(Type.ITEM, Cardinality.ZERO_OR_MORE) })) { throw new XPathException(this, "entry-path function must have a signature that matches: entry-path($path as xs:string, $data-type as xs:string, $param as item()*) as xs:anyURI"); } dataParams = new Sequence[3]; dataParams[2] = args[4]; } else if (entryDataFunctionSignature.getArgumentCount() == 4) { - if (!validateFunctionSignature(entryDataFunctionSignature, new SequenceType(Type.ITEM, Cardinality.ZERO_OR_MORE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE), new SequenceType(Type.ITEM, Cardinality.ZERO_OR_ONE), new SequenceType(Type.ITEM, Cardinality.ZERO_OR_MORE))) { + if (!validateFunctionSignature(entryDataFunctionSignature, new SequenceType(Type.ITEM, Cardinality.ZERO_OR_MORE), new SequenceType[]{ new SequenceType(Type.ANY_URI, Cardinality.EXACTLY_ONE), new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE) }, new SequenceType[]{ new SequenceType(Type.STRING, Cardinality.EXACTLY_ONE) }, new SequenceType[]{ new SequenceType(Type.ITEM, Cardinality.ZERO_OR_ONE) }, new SequenceType[]{ new SequenceType(Type.ITEM, Cardinality.ZERO_OR_MORE) })) { throw new XPathException(this, "entry-data function must have a signature that matches: entry-data($path as xs:string, $data-type as xs:string, $data as item()?, $param as item()*) as item()*"); } dataParams = new Sequence[4]; @@ -187,7 +187,7 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro } } - private boolean validateFunctionSignature(final FunctionSignature functionSignature, final SequenceType expectedReturnType, final SequenceType... expectedArgumentTypes) { + private boolean validateFunctionSignature(final FunctionSignature functionSignature, final SequenceType expectedReturnType, final SequenceType[]...expectedArgumentTypePossibilities) { final SequenceType actualReturnType = functionSignature.getReturnType(); if (!areSequenceTypesCompatible(expectedReturnType, actualReturnType)) { @@ -195,11 +195,29 @@ private boolean validateFunctionSignature(final FunctionSignature functionSignat } final SequenceType[] actualArgumentTypes = functionSignature.getArgumentTypes(); - for (int i = 0; i < expectedArgumentTypes.length; i++) { - final SequenceType expectedArgumentType = expectedArgumentTypes[i]; + if (actualArgumentTypes.length != expectedArgumentTypePossibilities.length) { + return false; + } + + // iterate through the actual argument types + for (int i = 0; i < actualArgumentTypes.length; i++) { final SequenceType actualArgumentType = actualArgumentTypes[i]; - if (!areSequenceTypesCompatible(expectedArgumentType, actualArgumentType)) { + // the actualArgumentType must match any one of the possibleExpectedArgumentTypes + final SequenceType[] possibleExpectedArgumentTypes = expectedArgumentTypePossibilities[i]; + + boolean actualArgumentTypeMatchedPossibleExpectedArgumentType = false; + for (int j = 0; j < possibleExpectedArgumentTypes.length; j++) { + final SequenceType possibleExpectedArgumentType = possibleExpectedArgumentTypes[j]; + + if (areSequenceTypesCompatible(possibleExpectedArgumentType, actualArgumentType)) { + actualArgumentTypeMatchedPossibleExpectedArgumentType = true; + break; + } + } + + if (!actualArgumentTypeMatchedPossibleExpectedArgumentType) { + // actual argument type did NOT match any of the possibleExpectedArgumentTypes return false; } }