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