Skip to content

Commit 4cf6bb8

Browse files
Added support for the array:remove Metapath function.
1 parent 22f8701 commit 4cf6bb8

File tree

6 files changed

+198
-5
lines changed

6 files changed

+198
-5
lines changed

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ private static <T extends IItem> ISequence<IArrayItem<T>> execute(@NonNull IFunc
8686
* the Metapath item to append to the identified array
8787
* @return a new array containing the modification
8888
*/
89-
@SuppressWarnings("PMD.OnlyOneReturn")
9089
@NonNull
9190
public static <T extends IItem> IArrayItem<T> append(
9291
@NonNull IArrayItem<T> array,

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ private static ISequence<?> execute(@NonNull IFunction function,
8888
* @throws ArrayException
8989
* if the position is not in the range of 1 to array:size
9090
*/
91-
@SuppressWarnings("PMD.OnlyOneReturn")
9291
@NonNull
9392
public static <T extends IItem> T get(
9493
@NonNull List<T> target,

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,18 +98,16 @@ private static <T extends IItem> ISequence<IArrayItem<T>> execute(@NonNull IFunc
9898
* @throws ArrayException
9999
* if the position is not in the range of 1 to array:size
100100
*/
101-
@SuppressWarnings("PMD.OnlyOneReturn")
102101
@NonNull
103102
public static <T extends IItem> IArrayItem<T> put(
104103
@NonNull IArrayItem<T> array,
105104
@NonNull IIntegerItem positionItem,
106105
@NonNull T member) {
107-
return put(array, positionItem.asInteger().intValue(), member);
106+
return put(array, positionItem.asInteger().intValueExact(), member);
108107
}
109108

110109
@NonNull
111110
public static <T extends IItem> IArrayItem<T> put(@NonNull IArrayItem<T> array, int position, @NonNull T member) {
112-
113111
List<T> copy = new ArrayList<>(array);
114112
try {
115113
copy.set(position - 1, member);
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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.Collection;
42+
import java.util.HashSet;
43+
import java.util.List;
44+
import java.util.Set;
45+
import java.util.stream.Collectors;
46+
import java.util.stream.IntStream;
47+
48+
import edu.umd.cs.findbugs.annotations.NonNull;
49+
50+
public class ArrayRemove {
51+
@NonNull
52+
public static final IFunction SIGNATURE = IFunction.builder()
53+
.name("remove")
54+
.namespace(MetapathConstants.NS_METAPATH_FUNCTIONS_ARRAY)
55+
.argument(IArgument.builder()
56+
.name("array")
57+
.type(IArrayItem.class)
58+
.one()
59+
.build())
60+
.argument(IArgument.builder()
61+
.name("positions")
62+
.type(IIntegerItem.class)
63+
.zeroOrMore()
64+
.build())
65+
.returnType(IArrayItem.class)
66+
.returnOne()
67+
.functionHandler(ArrayRemove::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+
ISequence<? extends IIntegerItem> positions = FunctionUtils.asType(ObjectUtils.requireNonNull(arguments.get(1)));
79+
80+
return ISequence.of(removeItems(array, positions));
81+
}
82+
83+
/**
84+
* An implementation of XPath 3.1 <a href=
85+
* "https://www.w3.org/TR/xpath-functions-31/#func-array-remove">array:remove</a>.
86+
*
87+
* @param <T>
88+
* the type of items in the given Metapath array
89+
* @param array
90+
* the target Metapath array
91+
* @param positions
92+
* the integer position of the items to remove
93+
* @return a new array containing the modification
94+
* @throws ArrayException
95+
* if the position is not in the range of 1 to array:size
96+
*/
97+
@NonNull
98+
public static <T extends IItem> IArrayItem<T> removeItems(
99+
@NonNull IArrayItem<T> array,
100+
@NonNull Collection<? extends IIntegerItem> positions) {
101+
return remove(
102+
array,
103+
ObjectUtils.notNull(positions.stream()
104+
.map(position -> position.asInteger().intValueExact())
105+
.collect(Collectors.toSet())));
106+
}
107+
108+
@NonNull
109+
public static <T extends IItem> IArrayItem<T> remove(
110+
@NonNull IArrayItem<T> array,
111+
@NonNull Collection<Integer> positions) {
112+
Set<Integer> positionSet = positions instanceof Set ? (Set<Integer>) positions : new HashSet<Integer>(positions);
113+
114+
List<T> removed = ObjectUtils.notNull(IntStream.range(1, array.size() + 1)
115+
.filter(index -> !positionSet.contains(index))
116+
.mapToObj(index -> array.get(index - 1))
117+
.collect(Collectors.toList()));
118+
119+
return IArrayItem.ofCollection(removed);
120+
}
121+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,8 @@ public DefaultFunctionLibrary() { // NOPMD - intentional
204204
// https://www.w3.org/TR/xpath-functions-31/#func-array-subarray
205205
registerFunction(ArraySubarray.SIGNATURE_TWO_ARG);
206206
registerFunction(ArraySubarray.SIGNATURE_THREE_ARG);
207+
// https://www.w3.org/TR/xpath-functions-31/#func-array-remove
208+
registerFunction(ArrayRemove.SIGNATURE);
207209

208210
// xpath casting functions
209211
registerFunction(
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.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 ArrayRemoveTest
46+
extends ExpressionTestBase {
47+
private static Stream<Arguments> provideValues() { // NOPMD - false positive
48+
return Stream.of(
49+
Arguments.of(
50+
array(string("b"), string("c"), string("d")),
51+
"array:remove([\"a\", \"b\", \"c\", \"d\"], 1)"),
52+
Arguments.of(
53+
array(string("a"), string("c"), string("d")),
54+
"array:remove([\"a\", \"b\", \"c\", \"d\"], 2)"),
55+
Arguments.of(
56+
array(),
57+
"array:remove([\"a\"], 1)"),
58+
Arguments.of(
59+
array(string("d")),
60+
"array:remove([\"a\", \"b\", \"c\", \"d\"], 1 to 3)"),
61+
Arguments.of(
62+
array(string("a"), string("b"), string("c"), string("d")),
63+
"array:remove([\"a\", \"b\", \"c\", \"d\"], ())"));
64+
}
65+
66+
@ParameterizedTest
67+
@MethodSource("provideValues")
68+
void testExpression(@NonNull IItem expected, @NonNull String metapath) {
69+
70+
IItem result = MetapathExpression.compile(metapath)
71+
.evaluateAs(null, MetapathExpression.ResultType.NODE, newDynamicContext());
72+
assertEquals(expected, result);
73+
}
74+
}

0 commit comments

Comments
 (0)