1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.core.metapath.item.atomic;
7   
8   import dev.metaschema.core.datatype.adapter.MetaschemaDataTypeProvider;
9   import dev.metaschema.core.metapath.function.InvalidValueForCastFunctionException;
10  import dev.metaschema.core.metapath.item.atomic.impl.QNameItemImpl;
11  import dev.metaschema.core.metapath.type.IAtomicOrUnionType;
12  import dev.metaschema.core.metapath.type.InvalidTypeMetapathException;
13  import dev.metaschema.core.qname.EQNameFactory;
14  import dev.metaschema.core.qname.IEnhancedQName;
15  import edu.umd.cs.findbugs.annotations.NonNull;
16  
17  /**
18   * An atomic Metapath item with a namespace qualified name value.
19   */
20  public interface IQNameItem extends IAnyAtomicItem {
21    /**
22     * Get the type information for this item.
23     *
24     * @return the type information
25     */
26    @NonNull
27    static IAtomicOrUnionType<IQNameItem> type() {
28      return MetaschemaDataTypeProvider.QNAME.getItemType();
29    }
30  
31    @Override
32    default IAtomicOrUnionType<IQNameItem> getType() {
33      return type();
34    }
35  
36    /**
37     * Construct a new QName item using the provided string {@code value}.
38     *
39     * @param value
40     *          a string representing a QName value
41     * @return the new item
42     */
43    // TODO: Review metaschema-framework/metaschema-java#396 and change accordingly.
44    @NonNull
45    static IQNameItem valueOf(@NonNull String value) {
46      return valueOf(EQNameFactory.instance().parseUriQualifiedName(value));
47    }
48  
49    /**
50     * Construct a new QName item using the provided {@code value}.
51     *
52     * @param value
53     *          a QName
54     * @return the new item
55     */
56    @NonNull
57    static IQNameItem valueOf(@NonNull IEnhancedQName value) {
58      return new QNameItemImpl(value);
59    }
60  
61    /**
62     * Cast the provided type to this item type.
63     *
64     * @param item
65     *          the item to cast
66     * @return the original item if it is already this type, otherwise a new item
67     *         cast to this type
68     * @throws InvalidValueForCastFunctionException
69     *           if the provided {@code item} cannot be cast to this type
70     */
71    @NonNull
72    static IQNameItem cast(@NonNull IAnyAtomicItem item) {
73      try {
74        return item instanceof IQNameItem
75            ? (IQNameItem) item
76            : valueOf(item.asString());
77      } catch (IllegalStateException | InvalidTypeMetapathException ex) {
78        // asString can throw IllegalStateException exception
79        throw new InvalidValueForCastFunctionException(ex);
80      }
81    }
82  
83    @Override
84    default IQNameItem castAsType(IAnyAtomicItem item) {
85      return cast(item);
86    }
87  
88    /**
89     * Get the "wrapped" EnhancedQName value.
90     *
91     * @return the underlying QName value
92     */
93    @NonNull
94    IEnhancedQName toEnhancedQName();
95  
96    /**
97     * Compares this value with the argument.
98     *
99     * @param item
100    *          the item to compare with this value
101    * @return a negative integer, zero, or a positive integer if this value is less
102    *         than, equal to, or greater than the {@code item}.
103    */
104   default int compareTo(@NonNull IQNameItem item) {
105     return toEnhancedQName().compareTo(item.toEnhancedQName());
106   }
107 }