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 java.time.Duration;
9   import java.time.ZoneOffset;
10  
11  import dev.metaschema.core.datatype.adapter.MetaschemaDataTypeProvider;
12  import dev.metaschema.core.metapath.function.DateTimeFunctionException;
13  import dev.metaschema.core.metapath.function.InvalidValueForCastFunctionException;
14  import dev.metaschema.core.metapath.item.atomic.impl.DayTimeDurationItemImpl;
15  import dev.metaschema.core.metapath.type.IAtomicOrUnionType;
16  import dev.metaschema.core.metapath.type.InvalidTypeMetapathException;
17  import dev.metaschema.core.util.ObjectUtils;
18  import edu.umd.cs.findbugs.annotations.NonNull;
19  
20  /**
21   * An atomic Metapath item containing a duration data value in days, hours, and
22   * seconds.
23   */
24  public interface IDayTimeDurationItem extends IDurationItem {
25    /**
26     * Get the type information for this item.
27     *
28     * @return the type information
29     */
30    @NonNull
31    static IAtomicOrUnionType<IDayTimeDurationItem> type() {
32      return MetaschemaDataTypeProvider.DAY_TIME_DURATION.getItemType();
33    }
34  
35    @Override
36    default IAtomicOrUnionType<IDayTimeDurationItem> getType() {
37      return type();
38    }
39  
40    /**
41     * Construct a new day time duration item using the provided string
42     * {@code value}.
43     *
44     * @param value
45     *          a string representing a day time duration
46     * @return the new item
47     * @throws InvalidTypeMetapathException
48     *           if the provided string value is not a day/time duration value
49     *           according to ISO 8601
50     */
51    @NonNull
52    static IDayTimeDurationItem valueOf(@NonNull String value) {
53      try {
54        return valueOf(MetaschemaDataTypeProvider.DAY_TIME_DURATION.parse(value));
55      } catch (IllegalArgumentException ex) {
56        throw new InvalidTypeMetapathException(
57            null,
58            String.format("Invalid day/time value '%s',",
59                value),
60            ex);
61      }
62    }
63  
64    /**
65     * Construct a new day time duration item using the provided {@code value}.
66     *
67     * @param value
68     *          a duration
69     * @return the new item
70     */
71    @NonNull
72    static IDayTimeDurationItem valueOf(@NonNull Duration value) {
73      return new DayTimeDurationItemImpl(value);
74    }
75  
76    /**
77     * Get the items wrapped value as a duration.
78     *
79     * @return the wrapped value as a duration
80     */
81    @NonNull
82    Duration asDuration();
83  
84    /**
85     * Get the "wrapped" duration value in seconds.
86     *
87     * @return the underlying duration in seconds
88     */
89    default long asSeconds() {
90      return asDuration().toSeconds();
91    }
92  
93    /**
94     * Returns a copy of this duration with the amount negated.
95     *
96     * @return this duration with the amount negated
97     */
98    @NonNull
99    default IDayTimeDurationItem negate() {
100     return valueOf(ObjectUtils.notNull(asDuration().negated()));
101   }
102 
103   /**
104    * Cast the provided type to this item type.
105    *
106    * @param item
107    *          the item to cast
108    * @return the original item if it is already this type, otherwise a new item
109    *         cast to this type
110    * @throws InvalidValueForCastFunctionException
111    *           if the provided {@code item} cannot be cast to this type
112    */
113   @NonNull
114   static IDayTimeDurationItem cast(@NonNull IAnyAtomicItem item) {
115     try {
116       return item instanceof IDayTimeDurationItem
117           ? (IDayTimeDurationItem) item
118           : valueOf(item.asString());
119     } catch (IllegalStateException | InvalidTypeMetapathException ex) {
120       // asString can throw IllegalStateException exception
121       throw new InvalidValueForCastFunctionException(ex);
122     }
123   }
124 
125   @Override
126   default IDayTimeDurationItem castAsType(IAnyAtomicItem item) {
127     return cast(item);
128   }
129 
130   /**
131    * Compares this value with the argument.
132    *
133    * @param item
134    *          the item to compare with this value
135    * @return a negative integer, zero, or a positive integer if this value is less
136    *         than, equal to, or greater than the {@code item}.
137    */
138   default int compareTo(@NonNull IDayTimeDurationItem item) {
139     return asDuration().compareTo(item.asDuration());
140 
141   }
142 
143   /**
144    * Get a zone offset for this duration.
145    *
146    * @return the offset
147    * @throws DateTimeFunctionException
148    *           with code
149    *           {@link DateTimeFunctionException#INVALID_TIME_ZONE_VALUE_ERROR} if
150    *           the offset is &lt; -PT14H or &gt; PT14H
151    */
152   @NonNull
153   ZoneOffset asZoneOffset();
154 }