View Javadoc
1   /*
2    * Copyright (C) 2020-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
3    */
4   package de.powerstat.validation.values;
5   
6   
7   import java.util.Objects;
8   
9   import de.powerstat.validation.interfaces.IValueObject;
10  
11  
12  /**
13   * Hour.
14   *
15   * Not DSGVO relevant.
16   *
17   * TODO Listener
18   * TODO minutesWithin = 60
19   * TODO min, max
20   */
21  public final class Hour implements Comparable<Hour>, IValueObject
22   {
23    /**
24     * Overflow constant.
25     */
26    private static final String OVERFLOW = "Overflow"; //$NON-NLS-1$
27  
28    /**
29     * Underflow contant.
30     */
31    private static final String UNDERFLOW = "Underflow"; //$NON-NLS-1$
32  
33    /* *
34     * Cache for singletons.
35     */
36    // private static final Map<Integer, Hour> CACHE = new WeakHashMap<>();
37  
38    /**
39     * Hour.
40     */
41    private final int hour;
42  
43  
44    /**
45     * Constructor.
46     *
47     * @param hour Hour 0-23
48     * @throws IndexOutOfBoundsException When the hour is less than 0 or greater than 23
49     */
50    private Hour(final int hour)
51     {
52      super();
53      if ((hour < 0) || (hour > 23))
54       {
55        throw new IndexOutOfBoundsException("Hour number out of range (0-23)!"); //$NON-NLS-1$
56       }
57      this.hour = hour;
58     }
59  
60  
61    /**
62     * Hour factory.
63     *
64     * @param hour Hour 0-23
65     * @return Hour object
66     */
67    public static Hour of(final int hour)
68     {
69      /*
70      synchronized (Hour.class)
71       {
72        Hour obj = Hour.CACHE.get(hour);
73        if (obj != null)
74         {
75          return obj;
76         }
77        obj = new Hour(hour);
78        Hour.CACHE.put(Integer.valueOf(hour), obj);
79        return obj;
80       }
81      */
82      return new Hour(hour);
83     }
84  
85  
86    /**
87     * Hour factory.
88     *
89     * @param value Hour 0-23 string
90     * @return Hour object
91     */
92    public static Hour of(final String value)
93     {
94      return of(Integer.parseInt(value));
95     }
96  
97  
98    /**
99     * Returns the value of this Hour as an int.
100    *
101    * @return The numeric value represented by this object after conversion to type int.
102    */
103   public int intValue()
104    {
105     return this.hour;
106    }
107 
108 
109   /**
110    * Returns the value of this Hour as a String.
111    *
112    * @return The numeric value represented by this object after conversion to type String.
113    */
114   @Override
115   public String stringValue()
116    {
117     return String.valueOf(this.hour);
118    }
119 
120 
121   /**
122    * Calculate hash code.
123    *
124    * @return Hash
125    * @see java.lang.Object#hashCode()
126    */
127   @Override
128   public int hashCode()
129    {
130     return Integer.hashCode(this.hour);
131    }
132 
133 
134   /**
135    * Is equal with another object.
136    *
137    * @param obj Object
138    * @return true when equal, false otherwise
139    * @see java.lang.Object#equals(java.lang.Object)
140    */
141   @Override
142   public boolean equals(final Object obj)
143    {
144     if (this == obj)
145      {
146       return true;
147      }
148     if (!(obj instanceof Hour))
149      {
150       return false;
151      }
152     final Hour other = (Hour)obj;
153     return this.hour == other.hour;
154    }
155 
156 
157   /**
158    * Returns the string representation of this Hour.
159    *
160    * The exact details of this representation are unspecified and subject to change, but the following may be regarded as typical:
161    *
162    * "Hour[hour=1]"
163    *
164    * @return String representation of this Hour
165    * @see java.lang.Object#toString()
166    */
167   @Override
168   public String toString()
169    {
170     final var builder = new StringBuilder();
171     builder.append("Hour[hour=").append(this.hour).append(']'); //$NON-NLS-1$
172     return builder.toString();
173    }
174 
175 
176   /**
177    * Compare with another object.
178    *
179    * @param obj Object to compare with
180    * @return 0: equal; 1: greater; -1: smaller
181    * @see java.lang.Comparable#compareTo(java.lang.Object)
182    */
183   @Override
184   public int compareTo(final Hour obj)
185    {
186     Objects.requireNonNull(obj, "obj"); //$NON-NLS-1$
187     return Integer.compare(this.hour, obj.hour);
188    }
189 
190 
191   /**
192    * Add hours to this hour.
193    *
194    * @param hours Hours to add to this hour
195    * @return New hour after adding the hours to this hour
196    * @throws ArithmeticException In case of an overflow
197    */
198   public Hour add(final Hours hours)
199    {
200     final int newHour = Math.toIntExact(Math.addExact(this.hour, hours.longValue()));
201     if (newHour > 23)
202      {
203       // TODO Listener
204       throw new ArithmeticException(Hour.OVERFLOW);
205      }
206     return Hour.of(newHour);
207    }
208 
209 
210   /**
211    * Subtract hours from this hour.
212    *
213    * @param hours Hours to subtract from this hour
214    * @return New hour after subtracting hours from this hour
215    * @throws ArithmeticException In case of an underflow
216    */
217   public Hour subtract(final Hours hours)
218    {
219     final int newHour = Math.toIntExact(Math.subtractExact(this.hour, hours.longValue()));
220     if (newHour < 0)
221      {
222       // TODO Listener
223       throw new ArithmeticException(Hour.UNDERFLOW);
224      }
225     return Hour.of(newHour);
226    }
227 
228 
229   /**
230    * Increment this hour.
231    *
232    * @return New hour after incrementing this hour
233    * @throws ArithmeticException In case of an overflow
234    */
235   public Hour increment()
236    {
237     final int newHour = Math.incrementExact(this.hour);
238     if (newHour == 24)
239      {
240       // TODO Listener
241       throw new ArithmeticException(Hour.OVERFLOW);
242      }
243     return Hour.of(newHour);
244    }
245 
246 
247   /**
248    * Decrement this hour.
249    *
250    * @return New hour after decrement this hour
251    * @throws ArithmeticException In case of an overflow
252    */
253   public Hour decrement()
254    {
255     final int newHour = Math.decrementExact(this.hour);
256     if (newHour == -1)
257      {
258       // TODO Listener
259       throw new ArithmeticException(Hour.UNDERFLOW);
260      }
261     return Hour.of(newHour);
262    }
263 
264  }