Skip to content

Commit 8ec41fb

Browse files
Added support for the array:insert-before and array:join Metapath functions.
1 parent 4cf6bb8 commit 8ec41fb

File tree

5 files changed

+350
-0
lines changed

5 files changed

+350
-0
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* Portions of this software was developed by employees of the National Institute
3+
* of Standards and Technology (NIST), an agency of the Federal Government and is
4+
* being made available as a public service. Pursuant to title 17 United States
5+
* Code Section 105, works of NIST employees are not subject to copyright
6+
* protection in the United States. This software may be subject to foreign
7+
* copyright. Permission in the United States and in foreign countries, to the
8+
* extent that NIST may hold copyright, to use, copy, modify, create derivative
9+
* works, and distribute this software and its documentation without fee is hereby
10+
* granted on a non-exclusive basis, provided that this notice and disclaimer
11+
* of warranty appears in all copies.
12+
*
13+
* THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
14+
* EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
15+
* THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
16+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
17+
* INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
18+
* SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT
19+
* SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
20+
* INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
21+
* OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
22+
* CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
23+
* PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
24+
* OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
25+
*/
26+
27+
package gov.nist.secauto.metaschema.core.metapath.function.library;
28+
29+
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
30+
import gov.nist.secauto.metaschema.core.metapath.ISequence;
31+
import gov.nist.secauto.metaschema.core.metapath.MetapathConstants;
32+
import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils;
33+
import gov.nist.secauto.metaschema.core.metapath.function.IArgument;
34+
import gov.nist.secauto.metaschema.core.metapath.function.IFunction;
35+
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
36+
import gov.nist.secauto.metaschema.core.metapath.item.atomic.IIntegerItem;
37+
import gov.nist.secauto.metaschema.core.metapath.item.function.ArrayException;
38+
import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem;
39+
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
40+
41+
import java.util.List;
42+
43+
import edu.umd.cs.findbugs.annotations.NonNull;
44+
45+
public class ArrayInsertBefore {
46+
@NonNull
47+
public static final IFunction SIGNATURE = IFunction.builder()
48+
.name("insert-before")
49+
.namespace(MetapathConstants.NS_METAPATH_FUNCTIONS_ARRAY)
50+
.argument(IArgument.builder()
51+
.name("array")
52+
.type(IArrayItem.class)
53+
.one()
54+
.build())
55+
.argument(IArgument.builder()
56+
.name("position")
57+
.type(IIntegerItem.class)
58+
.one()
59+
.build())
60+
.argument(IArgument.builder()
61+
.name("member")
62+
.type(IItem.class)
63+
.zeroOrMore()
64+
.build())
65+
.returnType(IArrayItem.class)
66+
.returnOne()
67+
.functionHandler(ArrayInsertBefore::execute)
68+
.build();
69+
70+
@SuppressWarnings("unused")
71+
@NonNull
72+
private static <T extends IItem> ISequence<IArrayItem<T>> execute(@NonNull IFunction function,
73+
@NonNull List<ISequence<?>> arguments,
74+
@NonNull DynamicContext dynamicContext,
75+
IItem focus) {
76+
IArrayItem<T> array = FunctionUtils.asType(ObjectUtils.requireNonNull(
77+
arguments.get(0).getFirstItem(true)));
78+
IIntegerItem position = FunctionUtils.asType(ObjectUtils.requireNonNull(arguments.get(1).getFirstItem(true)));
79+
T member = FunctionUtils.asType(ObjectUtils.requireNonNull(arguments.get(2)).toArrayMember());
80+
81+
return ISequence.of(insertBefore(array, position, member));
82+
}
83+
84+
/**
85+
* An implementation of XPath 3.1 <a href=
86+
* "https://www.w3.org/TR/xpath-functions-31/#func-array-insert-before">array:insert-before</a>.
87+
*
88+
* @param <T>
89+
* the type of items in the given Metapath array
90+
* @param array
91+
* the target Metapath array
92+
* @param positionItem
93+
* the integer position of the item to insert before
94+
* @param member
95+
* the Metapath item to insert into the identified array
96+
* @return a new array containing the modification
97+
* @throws ArrayException
98+
* if the position is not in the range of 1 to array:size
99+
*/
100+
@NonNull
101+
public static <T extends IItem> IArrayItem<T> insertBefore(
102+
@NonNull IArrayItem<T> array,
103+
@NonNull IIntegerItem positionItem,
104+
@NonNull T member) {
105+
return insertBefore(array, positionItem.asInteger().intValueExact(), member);
106+
}
107+
108+
@NonNull
109+
public static <T extends IItem> IArrayItem<T> insertBefore(@NonNull IArrayItem<T> array, int position,
110+
@NonNull T member) {
111+
return ArrayJoin.join(ObjectUtils.notNull(List.of(
112+
ArraySubarray.subarray(array, 1, position - 1),
113+
IArrayItem.of(member),
114+
ArraySubarray.subarray(array, position))));
115+
}
116+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Portions of this software was developed by employees of the National Institute
3+
* of Standards and Technology (NIST), an agency of the Federal Government and is
4+
* being made available as a public service. Pursuant to title 17 United States
5+
* Code Section 105, works of NIST employees are not subject to copyright
6+
* protection in the United States. This software may be subject to foreign
7+
* copyright. Permission in the United States and in foreign countries, to the
8+
* extent that NIST may hold copyright, to use, copy, modify, create derivative
9+
* works, and distribute this software and its documentation without fee is hereby
10+
* granted on a non-exclusive basis, provided that this notice and disclaimer
11+
* of warranty appears in all copies.
12+
*
13+
* THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
14+
* EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
15+
* THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
16+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
17+
* INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
18+
* SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT
19+
* SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
20+
* INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
21+
* OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
22+
* CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
23+
* PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
24+
* OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
25+
*/
26+
27+
package gov.nist.secauto.metaschema.core.metapath.function.library;
28+
29+
import gov.nist.secauto.metaschema.core.metapath.DynamicContext;
30+
import gov.nist.secauto.metaschema.core.metapath.ISequence;
31+
import gov.nist.secauto.metaschema.core.metapath.MetapathConstants;
32+
import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils;
33+
import gov.nist.secauto.metaschema.core.metapath.function.IArgument;
34+
import gov.nist.secauto.metaschema.core.metapath.function.IFunction;
35+
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
36+
import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem;
37+
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
38+
39+
import java.util.Collection;
40+
import java.util.List;
41+
import java.util.stream.Collectors;
42+
43+
import edu.umd.cs.findbugs.annotations.NonNull;
44+
45+
public class ArrayJoin {
46+
@NonNull
47+
public static final IFunction SIGNATURE = IFunction.builder()
48+
.name("join")
49+
.namespace(MetapathConstants.NS_METAPATH_FUNCTIONS_ARRAY)
50+
.argument(IArgument.builder()
51+
.name("array")
52+
.type(IArrayItem.class)
53+
.zeroOrMore()
54+
.build())
55+
.returnType(IItem.class)
56+
.returnZeroOrOne()
57+
.functionHandler(ArrayJoin::execute)
58+
.build();
59+
60+
@SuppressWarnings("unused")
61+
@NonNull
62+
private static ISequence<? extends IArrayItem<?>> execute(@NonNull IFunction function,
63+
@NonNull List<ISequence<?>> arguments,
64+
@NonNull DynamicContext dynamicContext,
65+
IItem focus) {
66+
ISequence<? extends IArrayItem<?>> arrays = FunctionUtils.asType(ObjectUtils.requireNonNull(arguments.get(0)));
67+
68+
return ISequence.of((IArrayItem<?>) join(arrays));
69+
}
70+
71+
/**
72+
* An implementation of XPath 3.1 <a href=
73+
* "https://www.w3.org/TR/xpath-functions-31/#func-array-join">array:join</a>.
74+
*
75+
* @param <T>
76+
* the type of items in the given Metapath array
77+
* @param arrays
78+
* the arrays to join
79+
* @return a new combined array
80+
*/
81+
@NonNull
82+
public static <T extends IItem> IArrayItem<T> join(
83+
@NonNull Collection<? extends IArrayItem<T>> arrays) {
84+
return IArrayItem.ofCollection(ObjectUtils.notNull(arrays.stream()
85+
.flatMap(array -> array.stream())
86+
.collect(Collectors.toList())));
87+
}
88+
}

core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/DefaultFunctionLibrary.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ public DefaultFunctionLibrary() { // NOPMD - intentional
206206
registerFunction(ArraySubarray.SIGNATURE_THREE_ARG);
207207
// https://www.w3.org/TR/xpath-functions-31/#func-array-remove
208208
registerFunction(ArrayRemove.SIGNATURE);
209+
// https://www.w3.org/TR/xpath-functions-31/#func-array-insert-before
210+
registerFunction(ArrayInsertBefore.SIGNATURE);
211+
212+
// https://www.w3.org/TR/xpath-functions-31/#func-array-join
213+
registerFunction(ArrayJoin.SIGNATURE);
209214

210215
// xpath casting functions
211216
registerFunction(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Portions of this software was developed by employees of the National Institute
3+
* of Standards and Technology (NIST), an agency of the Federal Government and is
4+
* being made available as a public service. Pursuant to title 17 United States
5+
* Code Section 105, works of NIST employees are not subject to copyright
6+
* protection in the United States. This software may be subject to foreign
7+
* copyright. Permission in the United States and in foreign countries, to the
8+
* extent that NIST may hold copyright, to use, copy, modify, create derivative
9+
* works, and distribute this software and its documentation without fee is hereby
10+
* granted on a non-exclusive basis, provided that this notice and disclaimer
11+
* of warranty appears in all copies.
12+
*
13+
* THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
14+
* EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
15+
* THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
16+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
17+
* INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
18+
* SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT
19+
* SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
20+
* INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
21+
* OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
22+
* CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
23+
* PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
24+
* OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
25+
*/
26+
27+
package gov.nist.secauto.metaschema.core.metapath.function.library;
28+
29+
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.array;
30+
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.string;
31+
import static org.junit.jupiter.api.Assertions.assertEquals;
32+
33+
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
34+
import gov.nist.secauto.metaschema.core.metapath.MetapathExpression;
35+
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
36+
37+
import org.junit.jupiter.params.ParameterizedTest;
38+
import org.junit.jupiter.params.provider.Arguments;
39+
import org.junit.jupiter.params.provider.MethodSource;
40+
41+
import java.util.stream.Stream;
42+
43+
import edu.umd.cs.findbugs.annotations.NonNull;
44+
45+
class ArrayInsertBeforeTest
46+
extends ExpressionTestBase {
47+
private static Stream<Arguments> provideValues() { // NOPMD - false positive
48+
return Stream.of(
49+
Arguments.of(
50+
array(string("a"), string("b"), array(string("x"), string("y")), string("c"), string("d")),
51+
"array:insert-before([\"a\", \"b\", \"c\", \"d\"], 3, (\"x\", \"y\"))"),
52+
Arguments.of(
53+
array(string("a"), string("b"), string("c"), string("d"), array(string("x"), string("y"))),
54+
"array:insert-before([\"a\", \"b\", \"c\", \"d\"], 5, (\"x\", \"y\"))"),
55+
Arguments.of(
56+
array(array(string("x"), string("y")), string("a"), string("b"), string("c"), string("d")),
57+
"array:insert-before([\"a\", \"b\", \"c\", \"d\"], 1, (\"x\", \"y\"))"));
58+
}
59+
60+
@ParameterizedTest
61+
@MethodSource("provideValues")
62+
void testExpression(@NonNull IItem expected, @NonNull String metapath) {
63+
IItem result = MetapathExpression.compile(metapath)
64+
.evaluateAs(null, MetapathExpression.ResultType.NODE, newDynamicContext());
65+
assertEquals(expected, result);
66+
}
67+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Portions of this software was developed by employees of the National Institute
3+
* of Standards and Technology (NIST), an agency of the Federal Government and is
4+
* being made available as a public service. Pursuant to title 17 United States
5+
* Code Section 105, works of NIST employees are not subject to copyright
6+
* protection in the United States. This software may be subject to foreign
7+
* copyright. Permission in the United States and in foreign countries, to the
8+
* extent that NIST may hold copyright, to use, copy, modify, create derivative
9+
* works, and distribute this software and its documentation without fee is hereby
10+
* granted on a non-exclusive basis, provided that this notice and disclaimer
11+
* of warranty appears in all copies.
12+
*
13+
* THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
14+
* EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
15+
* THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
16+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
17+
* INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
18+
* SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT
19+
* SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
20+
* INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
21+
* OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
22+
* CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
23+
* PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
24+
* OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
25+
*/
26+
27+
package gov.nist.secauto.metaschema.core.metapath.function.library;
28+
29+
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.array;
30+
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.integer;
31+
import static gov.nist.secauto.metaschema.core.metapath.TestUtils.string;
32+
import static org.junit.jupiter.api.Assertions.assertEquals;
33+
34+
import gov.nist.secauto.metaschema.core.metapath.ExpressionTestBase;
35+
import gov.nist.secauto.metaschema.core.metapath.MetapathExpression;
36+
import gov.nist.secauto.metaschema.core.metapath.item.IItem;
37+
38+
import org.junit.jupiter.params.ParameterizedTest;
39+
import org.junit.jupiter.params.provider.Arguments;
40+
import org.junit.jupiter.params.provider.MethodSource;
41+
42+
import java.util.stream.Stream;
43+
44+
import edu.umd.cs.findbugs.annotations.NonNull;
45+
46+
class ArrayJoinTest
47+
extends ExpressionTestBase {
48+
private static Stream<Arguments> provideValues() { // NOPMD - false positive
49+
return Stream.of(
50+
Arguments.of(
51+
array(),
52+
"array:join(())"),
53+
Arguments.of(
54+
array(integer(1), integer(2), integer(3)),
55+
"array:join([1, 2, 3])"),
56+
Arguments.of(
57+
array(string("a"), string("b"), string("c"), string("d")),
58+
"array:join(([\"a\", \"b\"], [\"c\", \"d\"]))"),
59+
Arguments.of(
60+
array(string("a"), string("b"), string("c"), string("d")),
61+
"array:join(([\"a\", \"b\"], [\"c\", \"d\"], [ ]))"),
62+
Arguments.of(
63+
array(string("a"), string("b"), string("c"), string("d"), array(string("e"), string("f"))),
64+
"array:join(([\"a\", \"b\"], [\"c\", \"d\"], [[\"e\", \"f\"]]))"));
65+
}
66+
67+
@ParameterizedTest
68+
@MethodSource("provideValues")
69+
void testExpression(@NonNull IItem expected, @NonNull String metapath) {
70+
IItem result = MetapathExpression.compile(metapath)
71+
.evaluateAs(null, MetapathExpression.ResultType.NODE, newDynamicContext());
72+
assertEquals(expected, result);
73+
}
74+
}

0 commit comments

Comments
 (0)