1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.metaschema.core.metapath;
7   
8   import gov.nist.secauto.metaschema.core.metapath.item.IItem;
9   import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
10  import gov.nist.secauto.metaschema.core.metapath.item.function.IArrayItem;
11  import gov.nist.secauto.metaschema.core.metapath.item.function.IMapItem;
12  import gov.nist.secauto.metaschema.core.util.ObjectUtils;
13  
14  import java.util.stream.Stream;
15  
16  import edu.umd.cs.findbugs.annotations.NonNull;
17  
18  /**
19   * A data value that can be a value in a Metapath array or map.
20   */
21  public interface ICollectionValue {
22    /**
23     * Get the collection value as a sequence.
24     * <p>
25     * If the value is already a sequence, the value is returned as a sequence.
26     * Otherwise, if the value is an item, a new sequence will be created containing
27     * only that item.
28     *
29     * @return the resulting sequence
30     */
31    // TODO: rename to toSequence and resolve conflicting methods?
32    @NonNull
33    default ISequence<?> toSequence() {
34      return this instanceof ISequence
35          // return the sequence
36          ? (ISequence<?>) this
37          // return the item as a new sequence
38          : ISequence.of((IItem) this);
39    }
40  
41    /**
42     * Get the collection value as a sequence.
43     * <p>
44     * If the value is already a sequence, the value is returned as a sequence.
45     * Otherwise, if the value is an item, what is returned depends on the item
46     * type:
47     * <ul>
48     * <li>{@link IArrayItem} or {@link IMapItem}: the contents of the returned
49     * sequence are the items of the array. Any member values that are a sequence
50     * are flattened.</li>
51     * <li>Any other item: A singleton sequence is returned containing the
52     * item.</li>
53     * </ul>
54     *
55     * @return the resulting sequence
56     */
57    // TODO: rename to toSequence and resolve conflicting methods?
58    @NonNull
59    ISequence<?> contentsAsSequence();
60  
61    /**
62     * Get the stream of items for the collection value.
63     * <p>
64     * If the collection value is a sequence, then the items in the collection are
65     * returned.
66     *
67     * @param value
68     *          the collection value
69     * @return the sequence of related items
70     */
71    @NonNull
72    static Stream<? extends IItem> normalizeAsItems(@NonNull ICollectionValue value) {
73      return value instanceof IItem
74          ? ObjectUtils.notNull(Stream.of((IItem) value))
75          : value.toSequence().stream();
76    }
77  
78    /**
79     * Produce a stream of atomic items based on the atomic value of these items.
80     * <p>
81     * Supports <a href="https://www.w3.org/TR/xpath-31/#id-atomization">item
82     * atomization</a>.
83     *
84     * @return a stream of atomized atomic items.
85     */
86    @NonNull
87    Stream<IAnyAtomicItem> atomize();
88  
89    /**
90     * Get the stream of items for the collection value.
91     * <p>
92     * If the collection value contains items, then these items are returned.
93     *
94     * @return a stream of related items
95     */
96    @NonNull
97    Stream<? extends IItem> flatten();
98  
99    /**
100    * Get a representation of the value based on its type signature.
101    *
102    * @return the signature
103    */
104   @NonNull
105   String toSignature();
106 }