Skip to content

Commit

Permalink
[WIP] Add function-lookup impl and tests for metaschema-framework#301
Browse files Browse the repository at this point in the history
  • Loading branch information
aj-stein-gsa committed Dec 20, 2024
1 parent f457b9f commit 0541b88
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
import gov.nist.secauto.metaschema.core.metapath.StaticMetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.IFunction;
import gov.nist.secauto.metaschema.core.metapath.function.library.ArrayGet;
import gov.nist.secauto.metaschema.core.metapath.function.library.MapGet;
import gov.nist.secauto.metaschema.core.metapath.item.ICollectionValue;
Expand Down Expand Up @@ -84,7 +85,11 @@ public ISequence<? extends IItem> accept(DynamicContext dynamicContext, ISequenc
.collect(Collectors.toUnmodifiableList())),
dynamicContext,
focus);
}
} else if (collection instanceof IFunction) {
return ((IFunction) collection).execute( ObjectUtils.notNull(getArguments().stream()
.map(expr -> expr.accept(dynamicContext, focus))
.collect(Collectors.toUnmodifiableList())), dynamicContext, focus);
}

// the value to find, which will be the key for a map or the index for an array
IExpression argument = getArguments().stream().findFirst()
Expand Down
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-lookup
registerFunction(FnFunctionLookup.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,86 @@
/*
* 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.StaticContext;
import gov.nist.secauto.metaschema.core.metapath.StaticMetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.FunctionLibrary;
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.metapath.item.atomic.IStringItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.IDefinitionNodeItem;
import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem;
import gov.nist.secauto.metaschema.core.metapath.type.IItemType;
import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
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-lookup">fn:function-lookup</a>
* functions.
*/
public final class FnFunctionLookup {
@NonNull
private static final String NAME = "function-lookup";

@NonNull
static final IFunction SIGNATURE= IFunction.builder()
.name(NAME)
.namespace(MetapathConstants.NS_METAPATH_FUNCTIONS)
.deterministic()
.contextIndependent()
.focusIndependent()
.argument(IArgument.builder()
.name("name")
.type(IStringItem.type())
.one()
.build())
.argument(IArgument.builder()
.name("arity")
.type(IIntegerItem.type())
.one()
.build())
.returnType(IItemType.function())
.returnZeroOrOne()
.functionHandler(FnFunctionLookup::execute)
.build();

@SuppressWarnings("unused")
@NonNull
private static ISequence<IFunction> execute(@NonNull IFunction function,
@NonNull List<ISequence<?>> arguments,
@NonNull DynamicContext dynamicContext,
IItem focus) {
IStringItem name = FunctionUtils.asType(ObjectUtils.requireNonNull(arguments.get(0).getFirstItem(true)));
IIntegerItem arity = FunctionUtils.asType(ObjectUtils.requireNonNull(arguments.get(1).getFirstItem(true)));
IFunction matchingFunction;

try {
matchingFunction = dynamicContext.getStaticContext().lookupFunction(name.asString(), arity.asInteger().intValueExact());
} catch (StaticMetapathException ex) {
if (ex.getCode() != StaticMetapathException.NO_FUNCTION_MATCH) {
throw ex;
}
matchingFunction = null;
}

return ISequence.of(matchingFunction);
}

private FnFunctionLookup() {
// disable construction
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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.string;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

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.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.function.regex.RegularExpressionMetapathException;
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
import gov.nist.secauto.metaschema.core.metapath.item.ISequence;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;

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

import java.util.List;
import java.util.stream.Stream;

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

class FnFunctionLookupTest
extends ExpressionTestBase {

private static Stream<Arguments> provideValues() { // NOPMD - false positive
return Stream.of(
Arguments.of(
string("bcd"),
"function-lookup('substring', 2)('abcd', 2)"));
}

@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 0541b88

Please sign in to comment.