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