Skip to content

Commit

Permalink
Add seconds-from-duration impl and tests for #284
Browse files Browse the repository at this point in the history
  • Loading branch information
aj-stein-gsa committed Mar 1, 2025
1 parent edd10f1 commit caa6f06
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ public DefaultFunctionLibrary() { // NOPMD - intentional
// https://www.w3.org/TR/xpath-functions-31/#func-seconds-from-dateTime
registerFunction(FnSecondsFromDateTime.SIGNATURE);
// https://www.w3.org/TR/xpath-functions-31/#func-seconds-from-duration
registerFunction(FnSecondsFromDuration.SIGNATURE);
// https://www.w3.org/TR/xpath-functions-31/#func-seconds-from-time
registerFunction(FnSecondsFromTime.SIGNATURE);
// https://www.w3.org/TR/xpath-functions-31/#func-starts-with
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* 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.IDayTimeDurationItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDecimalItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IDurationItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IIntegerItem;
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IYearMonthDurationItem;

import java.time.Duration;
import java.util.List;

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

/**
* Implements the XPath 3.1 <a href=
* "https://www.w3.org/TR/xpath-functions-31/#func-seconds-from-duration">fn:seconds-from-duration</a>.
* function.
*/
public final class FnSecondsFromDuration {
private static final String NAME = "seconds-from-duration";
@NonNull
static final IFunction SIGNATURE = IFunction.builder()
.name(NAME)
.namespace(MetapathConstants.NS_METAPATH_FUNCTIONS)
.deterministic()
.contextIndependent()
.focusIndependent()
.argument(IArgument.builder()
.name("arg")
.type(IDurationItem.type())
.zeroOrOne()
.build())
.returnType(IIntegerItem.type())
.returnZeroOrOne()
.functionHandler(FnSecondsFromDuration::execute)
.build();

private FnSecondsFromDuration() {
// disable construction
}

@SuppressWarnings("unused")
@NonNull
private static ISequence<IDecimalItem> execute(@NonNull IFunction function,
@NonNull List<ISequence<?>> arguments,
@NonNull DynamicContext dynamicContext,
IItem focus) {
IDurationItem arg = FunctionUtils.asTypeOrNull(arguments.get(0).getFirstItem(true));
if(arg instanceof IYearMonthDurationItem) {
return ISequence.of(IIntegerItem.valueOf(0));
}
return arg == null ? ISequence.empty() : ISequence.of(fnSecondsFromDuration((IDayTimeDurationItem)arg));
}

/**
* Implements <a href=
* "https://www.w3.org/TR/xpath-functions-31/#func-seconds-from-duration">fn:seconds-from-duration</a>.
*
* @param arg
* the meta:duration item from which to extract the second component
* @return the second component from the duration as integer item
*/
@NonNull
public static IDecimalItem fnSecondsFromDuration(IDayTimeDurationItem arg) {
Duration duration= arg.asDuration();
return IDecimalItem.valueOf((duration.getSeconds() % 60) + (duration.getNano() / 1_000_000_000.0));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* 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.decimal;
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.item.atomic.IDecimalItem;

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 FnSecondsFromDurationTest
extends ExpressionTestBase {
private static Stream<Arguments> provideValues() { // NOPMD - false positive
return Stream.of(
Arguments.of(
decimal(12.5),
"fn:seconds-from-duration(meta:day-time-duration('P3DT10H12.5S'))"),
Arguments.of(
decimal(-16.0),
"fn:seconds-from-duration(meta:day-time-duration('-PT256S'))"));
}

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

0 comments on commit caa6f06

Please sign in to comment.