Skip to content

Commit

Permalink
Add focus, no-arg tests and refactor impl for #190
Browse files Browse the repository at this point in the history
  • Loading branch information
aj-stein-gsa committed Oct 19, 2024
1 parent 322b3ac commit 520fb7a
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
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.function.InvalidTypeFunctionException;
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
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.INodeItem;

import java.util.List;

Expand All @@ -25,61 +28,75 @@
* functions.
*/
public final class FnStringLength {
private static final String NAME = "string-length";
@NonNull
static final IFunction SIGNATURE_NO_ARG = IFunction.builder()
.name(NAME)
.namespace(MetapathConstants.NS_METAPATH_FUNCTIONS)
.deterministic()
.contextDependent()
.focusDependent()
.returnType(IIntegerItem.class)
.returnOne()
.functionHandler(FnStringLength::executeNoArg)
.build();
private static final String NAME = "string-length";
@NonNull
static final IFunction SIGNATURE_NO_ARG = IFunction.builder()
.name(NAME)
.namespace(MetapathConstants.NS_METAPATH_FUNCTIONS)
.deterministic()
.contextDependent()
.focusDependent()
.returnType(IIntegerItem.class)
.returnOne()
.functionHandler(FnStringLength::executeNoArg)
.build();

@NonNull
static final IFunction SIGNATURE_ONE_ARG = IFunction.builder()
.name(NAME)
.namespace(MetapathConstants.NS_METAPATH_FUNCTIONS)
.deterministic()
.contextIndependent()
.focusIndependent()
.argument(IArgument.builder()
.name("arg1")
.type(IStringItem.class)
.zeroOrOne()
.build())
.returnType(IIntegerItem.class)
.returnOne()
.functionHandler(FnStringLength::executeOneArg)
.build();
@NonNull
static final IFunction SIGNATURE_ONE_ARG = IFunction.builder()
.name(NAME)
.namespace(MetapathConstants.NS_METAPATH_FUNCTIONS)
.deterministic()
.contextIndependent()
.focusIndependent()
.argument(IArgument.builder()
.name("arg1")
.type(IStringItem.class)
.zeroOrOne()
.build())
.returnType(IIntegerItem.class)
.returnOne()
.functionHandler(FnStringLength::executeOneArg)
.build();

private FnStringLength() {
// disable construction
}
private FnStringLength() {
// disable construction
}

@SuppressWarnings("unused")
@NonNull
private static ISequence<IIntegerItem> executeNoArg(@NonNull IFunction function,
@NonNull List<ISequence<?>> arguments, @NonNull DynamicContext dynamicContext, IItem focus) {
// the focus should always be non-null, since the function if focus-dependent
assert focus != null;
return ISequence.of(IIntegerItem.valueOf(0));
}
@SuppressWarnings("unused")
@NonNull
private static ISequence<IIntegerItem> executeNoArg(@NonNull IFunction function,
@NonNull List<ISequence<?>> arguments, @NonNull DynamicContext dynamicContext, IItem focus) {
// the focus should always be non-null, since the function if focus-dependent
assert focus != null;
return ISequence.of(fnStringLength(focus));
}

@SuppressWarnings("unused")
@NonNull
private static ISequence<IIntegerItem> executeOneArg(@NonNull IFunction function,
@NonNull List<ISequence<?>> arguments, @NonNull DynamicContext dynamicContext, IItem focus) {
@SuppressWarnings("unused")
@NonNull
private static ISequence<IIntegerItem> executeOneArg(@NonNull IFunction function,
@NonNull List<ISequence<?>> arguments, @NonNull DynamicContext dynamicContext, IItem focus) {

// From the XPath 3.1 specification:
// If the value of $arg is the empty sequence, the function returns the xs:integer value zero (0).
if(arguments.get(0).size() == 0) {
return ISequence.of(IIntegerItem.valueOf(0));
}
// From the XPath 3.1 specification:
// If the value of $arg is the empty sequence, the function returns the
// xs:integer value zero (0).
if (arguments.get(0).size() == 0) {
return ISequence.of(IIntegerItem.valueOf(0));
}

IStringItem arg = FunctionUtils.asTypeOrNull(arguments.get(0).getFirstItem(true));
return ISequence.of(IIntegerItem.valueOf(arg.asString().length()));
}
IStringItem arg = FunctionUtils.asTypeOrNull(arguments.get(0).getFirstItem(true));
return ISequence.of(fnStringLength(arg));
}

/**
* An implementation of <a href=
* "https://www.w3.org/TR/xpath-functions-31/#func-string-length">fn:string-length</a>.
*
* @param item
* the item the string for which to compute the length
* @return the integer length value of string
*/
@NonNull
public static IIntegerItem fnStringLength(@NonNull IItem item) {
return IIntegerItem.valueOf(FnString.fnStringItem(item).asString().length());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.array;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.integer;
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.sequence;
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;

Expand All @@ -18,6 +19,7 @@
import gov.nist.secauto.metaschema.core.metapath.MetapathException;
import gov.nist.secauto.metaschema.core.metapath.MetapathExpression;
import gov.nist.secauto.metaschema.core.metapath.function.InvalidTypeFunctionException;
import gov.nist.secauto.metaschema.core.metapath.function.regex.RegularExpressionMetapathException;
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.util.CollectionUtil;
Expand Down Expand Up @@ -53,6 +55,17 @@ void testExpression(@NonNull IIntegerItem expected, @NonNull String metapath) {
assertEquals(expected, result);
}

@Test
void testFocusStringTest() {
assertEquals(
ISequence.of(integer(6)),
FunctionTestBase.executeFunction(
FnStringLength.SIGNATURE_NO_ARG,
newDynamicContext(),
ISequence.of(IStringItem.valueOf("000001")),
List.of()));
}

@Test
void testNoFocus() {
DynamicMetapathException throwable = assertThrows(DynamicMetapathException.class,
Expand Down

0 comments on commit 520fb7a

Please sign in to comment.