Skip to content

Commit

Permalink
Add metaschema-framework#283 function-arity() and incomplete tests
Browse files Browse the repository at this point in the history
There appear to be some issues parsing, seemingly at the ANLTRv4 grammar
layer, with the following kinds of function expressions that are in the
spec for example test cases for this function in the XPath 3.1 spec.

`fn:function-arity(fn:substring#2)`
`let $initial := fn:substring(?, 1, 1) return fn:function-arity($initial) returns 1`

More investigation is needed and perhaps separate bugs must be filed.
  • Loading branch information
aj-stein-gsa committed Dec 23, 2024
1 parent 5f44dac commit da0aa02
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ public DefaultFunctionLibrary() { // NOPMD - intentional
// P2: https://www.w3.org/TR/xpath-functions-31/#func-format-integer
// P2: https://www.w3.org/TR/xpath-functions-31/#func-format-number
// P2: https://www.w3.org/TR/xpath-functions-31/#func-format-time
// https://www.w3.org/TR/xpath-functions-31/#func-function-arity
registerFunction(FnFunctionArity.SIGNATURE);
// P1: https://www.w3.org/TR/xpath-functions-31/#func-generate-id
// https://www.w3.org/TR/xpath-functions-31/#func-has-children
registerFunction(FnHasChildren.SIGNATURE_NO_ARG);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* SPDX-FileCopyrightText: none
* SPDX-License-Identifier: CC0-1.0
*/

package gov.nist.secauto.metaschema.core.metapath.function.library;

import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
import gov.nist.secauto.metaschema.core.metapath.MetapathConstants;
import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils;
import gov.nist.secauto.metaschema.core.metapath.function.IArgument;
import gov.nist.secauto.metaschema.core.metapath.function.IFunction;
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IIntegerItem;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

import java.util.List;

import edu.umd.cs.findbugs.annotations.NonNull;

/**
* /** Implements <a href=
* "https://www.w3.org/TR/xpath-functions-31/#func-function-arity">fn:function-arity</a>
* functions.
*/
public final class FnFunctionArity {
@NonNull
private static final String NAME = "function-arity";
@NonNull
static final IFunction SIGNATURE = IFunction.builder()
.name(NAME)
.namespace(MetapathConstants.NS_METAPATH_FUNCTIONS)
.deterministic()
.contextDependent()
.focusIndependent()
.argument(IArgument.builder()
.name("func")
.type(IItem.type())
.one()
.build())
.returnType(IIntegerItem.type())
.returnOne()
.functionHandler(FnFunctionArity::execute)
.build();

@SuppressWarnings("unused")
@NonNull
private static ISequence<IIntegerItem> execute(@NonNull IFunction function,
@NonNull List<ISequence<?>> arguments,
@NonNull DynamicContext dynamicContext,
IItem focus) {
try {
IFunction fn = FunctionUtils.asType(ObjectUtils.requireNonNull(arguments.get(0).getFirstItem(true)));
return ISequence.of(IIntegerItem.valueOf(fn.arity()));
} catch (Exception ex) {
// TODO: Spec is unclear for no function provided
return ISequence.empty();
}
}

private FnFunctionArity() {
// disable construction
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* SPDX-FileCopyrightText: none
* SPDX-License-Identifier: CC0-1.0
*/

package gov.nist.secauto.metaschema.core.metapath.function.library;

import static gov.nist.secauto.metaschema.core.metapath.TestUtils.integer;
import static org.junit.jupiter.api.Assertions.assertEquals;

import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression;
import gov.nist.secauto.metaschema.core.metapath.IMetapathExpression.ResultType;
import gov.nist.secauto.metaschema.core.metapath.item.IItem;


import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.stream.Stream;

import edu.umd.cs.findbugs.annotations.NonNull;

class FnFunctionArityTest extends ExpressionTestBase {

private static Stream<Arguments> provideValues() { // NOPMD - false positive
return Stream.of(
// Arguments.of(
// integer(2),
// "fn:function-arity(fn:substring#2)"),
Arguments.of(
integer(1),
"function-arity(function($node){name($node)})")//,
// Arguments.of(
// integer(1),
// "let $initial := fn:substring(?, 1, 1) return fn:function-arity($initial)")
);
}

@ParameterizedTest
@MethodSource("provideValues")
void test(@NonNull IItem expected, @NonNull String metapath) {
assertEquals(expected,
IMetapathExpression.compile(metapath).evaluateAs(null, ResultType.ITEM, newDynamicContext()));
}
}

0 comments on commit da0aa02

Please sign in to comment.