1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.core.metapath.function.library;
7   
8   import java.util.List;
9   
10  import dev.metaschema.core.metapath.DynamicContext;
11  import dev.metaschema.core.metapath.MetapathConstants;
12  import dev.metaschema.core.metapath.function.FunctionUtils;
13  import dev.metaschema.core.metapath.function.IArgument;
14  import dev.metaschema.core.metapath.function.IFunction;
15  import dev.metaschema.core.metapath.item.ICollectionValue;
16  import dev.metaschema.core.metapath.item.IItem;
17  import dev.metaschema.core.metapath.item.ISequence;
18  import dev.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
19  import dev.metaschema.core.metapath.item.atomic.IBooleanItem;
20  import dev.metaschema.core.metapath.item.function.IMapItem;
21  import dev.metaschema.core.util.ObjectUtils;
22  import edu.umd.cs.findbugs.annotations.NonNull;
23  
24  /**
25   * Implements the XPath 3.1 <a href=
26   * "https://www.w3.org/TR/xpath-functions-31/#func-map-contains">map:contains</a>
27   * function.
28   */
29  public final class MapContains {
30    private static final String NAME = "contains";
31    @NonNull
32    static final IFunction SIGNATURE = IFunction.builder()
33        .name(NAME)
34        .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS_MAP)
35        .deterministic()
36        .contextIndependent()
37        .focusIndependent()
38        .argument(IArgument.builder()
39            .name("map")
40            .type(IMapItem.type())
41            .one()
42            .build())
43        .argument(IArgument.builder()
44            .name("key")
45            .type(IAnyAtomicItem.type())
46            .one()
47            .build())
48        .returnType(IBooleanItem.type())
49        .returnOne()
50        .functionHandler(MapContains::execute)
51        .build();
52  
53    private MapContains() {
54      // disable construction
55    }
56  
57    @SuppressWarnings("unused")
58    @NonNull
59    private static ISequence<?> execute(@NonNull IFunction function,
60        @NonNull List<ISequence<?>> arguments,
61        @NonNull DynamicContext dynamicContext,
62        IItem focus) {
63      IMapItem<?> map = FunctionUtils.asType(ObjectUtils.requireNonNull(arguments.get(0).getFirstItem(true)));
64      IAnyAtomicItem key = FunctionUtils.asType(ObjectUtils.requireNonNull(arguments.get(1).getFirstItem(true)));
65  
66      return IBooleanItem.valueOf(contains(map, key)).toSequence();
67    }
68  
69    /**
70     * An implementation of XPath 3.1 <a href=
71     * "https://www.w3.org/TR/xpath-functions-31/#func-map-contains">map:contains</a>.
72     *
73     * @param <V>
74     *          the type of items in the given Metapath map
75     * @param map
76     *          the map of Metapath items that is the target of retrieval
77     * @param key
78     *          the key for the item to retrieve
79     * @return {@code true} if the key exists in the map, or {@code false} otherwise
80     */
81    public static <V extends ICollectionValue> boolean contains(
82        @NonNull IMapItem<V> map,
83        @NonNull IAnyAtomicItem key) {
84      return map.get(key.asMapKey()) != null;
85    }
86  }