1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.core.metapath.item;
7   
8   import java.util.stream.Stream;
9   
10  import dev.metaschema.core.datatype.IDataTypeAdapter;
11  import dev.metaschema.core.metapath.function.InvalidTypeFunctionException;
12  import dev.metaschema.core.metapath.item.atomic.IAnyAtomicItem;
13  import dev.metaschema.core.metapath.type.IItemType;
14  import dev.metaschema.core.util.ObjectUtils;
15  import edu.umd.cs.findbugs.annotations.NonNull;
16  
17  /**
18   * The base interface inherited by all Metapath item implementations.
19   */
20  public interface IItem extends ICollectionValue {
21    /**
22     * Get the type information for this item.
23     *
24     * @return the type information
25     */
26    @NonNull
27    static IItemType type() {
28      return IItemType.item();
29    }
30  
31    /**
32     * Get the type information for the item.
33     *
34     * @return the item's type information
35     */
36    @NonNull
37    IItemType getType();
38  
39    /**
40     * Get the item's "wrapped" value. This "wrapped" value may be:
41     * <ul>
42     * <li>In the case of an Assembly, a Java object representing the fields and
43     * flags of the assembly.
44     * <li>In the case of a Field with flags, a Java object representing the field
45     * value and flags of the field.
46     * <li>In the case of a Field without flags or a flag, a Java type managed by a
47     * {@link IDataTypeAdapter} or a primitive type provided by the Java standard
48     * library.
49     * </ul>
50     *
51     * @return the value or {@code null} if the item has no available value
52     */
53    Object getValue();
54  
55    /**
56     * Determine if the item has an associated value.
57     *
58     * @return {@code true} if the item has a non-{@code null} value or
59     *         {@code false} otherwise
60     */
61    default boolean hasValue() {
62      return getValue() != null;
63    }
64  
65    @Override
66    default ISequence<?> toSequence() {
67      return ISequence.of(this);
68    }
69  
70    /**
71     * Get the atomic value for the item. This may be the same item if the item is
72     * an instance of {@link IAnyAtomicItem}.
73     * <p>
74     * An implementation of
75     * <a href="https://www.w3.org/TR/xpath-31/#id-atomization">item
76     * atomization</a>.
77     *
78     * @return the atomic value or {@code null} if the item has no available value
79     * @throws InvalidTypeFunctionException
80     *           with code
81     *           {@link InvalidTypeFunctionException#NODE_HAS_NO_TYPED_VALUE} if the
82     *           item does not have a typed value
83     */
84    // FIXME: get rid of the possible null result and throw
85    // InvalidTypeFunctionException#NODE_HAS_NO_TYPED_VALUE
86    IAnyAtomicItem toAtomicItem();
87  
88    /**
89     * {@inheritDoc}
90     *
91     * @throws InvalidTypeFunctionException
92     *           with code
93     *           {@link InvalidTypeFunctionException#NODE_HAS_NO_TYPED_VALUE} if the
94     *           item does not have a typed value
95     */
96    @Override
97    default Stream<IAnyAtomicItem> atomize() {
98      return ObjectUtils.notNull(Stream.of(this.toAtomicItem()));
99    }
100 
101   @SuppressWarnings("null")
102   @Override
103   default Stream<? extends IItem> flatten() {
104     return Stream.of(this);
105   }
106 
107   /**
108    * A visitor callback used to visit a variety of Metapath item types.
109    *
110    * @param visitor
111    *          the visitor to call back
112    */
113   void accept(@NonNull IItemVisitor visitor);
114 
115   @Override
116   default ISequence<?> contentsAsSequence() {
117     return toSequence();
118   }
119 }