View Javadoc
1   /*
2    * Copyright (C) 2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
3    */
4   package de.powerstat.validation.containers;
5   
6   
7   import java.util.Collection;
8   import java.util.Iterator;
9   import java.util.NoSuchElementException;
10  import java.util.Objects;
11  import java.util.Set;
12  import java.util.SortedSet;
13  import java.util.concurrent.ConcurrentSkipListSet;
14  import java.util.regex.Pattern;
15  
16  
17  /**
18   * Group of a specific type.
19   *
20   * @param <T> Use only entities
21   */
22  public class GroupOf<T> implements Set<T>
23   {
24    /**
25     * Group name regexp.
26     */
27    private static final Pattern GROUPNAME_REGEXP = Pattern.compile("^[\\p{L}][\\p{L}-]*$"); //$NON-NLS-1$
28  
29    /**
30     * Group name.
31     */
32    private final String name;
33  
34    /**
35     * Group.
36     */
37    private final SortedSet<T> group = new ConcurrentSkipListSet<>();
38  
39  
40    /**
41     * Constructor.
42     *
43     * @param groupName Group name (maximum 40 characters)
44     */
45    public GroupOf(final String groupName)
46     {
47      super();
48      Objects.requireNonNull(groupName, "groupName"); //$NON-NLS-1$
49      if ((groupName.length() < 1) || (groupName.length() > 40))
50       {
51        throw new IllegalArgumentException("groupName with wrong length"); //$NON-NLS-1$
52       }
53      if (!GroupOf.GROUPNAME_REGEXP.matcher(groupName).matches())
54       {
55        throw new IllegalArgumentException("groupName with wrong format"); //$NON-NLS-1$
56       }
57      this.name = groupName;
58     }
59  
60  
61    /**
62     * Returns the name of this GroupOf.
63     *
64     * @return The name of this group.
65     */
66    public String name()
67     {
68      return this.name;
69     }
70  
71  
72    /**
73     * Calculate hash code.
74     *
75     * @return Hash
76     * @see java.lang.Object#hashCode()
77     */
78    @Override
79    public int hashCode()
80     {
81      return Objects.hash(this.name, this.group);
82     }
83  
84  
85    /**
86     * Is equal with another object.
87     *
88     * @param obj Object
89     * @return true when equal, false otherwise
90     * @throws NoSuchElementException If there is no entry in this GroupOf
91     * @see java.lang.Object#equals(java.lang.Object)
92     */
93    @Override
94    public boolean equals(final Object obj)
95     {
96      if (this == obj)
97       {
98        return true;
99       }
100     if (!(obj instanceof GroupOf<?>))
101     // if ((obj == null) || (this.getClass() != obj.getClass()))
102      {
103       return false;
104      }
105     final GroupOf<T> other = (GroupOf<T>)obj;
106     return this.name.equals(other.name) && this.group.equals(other.group);
107    }
108 
109 
110   /**
111    * Returns the string representation of this GroupOf.
112    *
113    * The exact details of this representation are unspecified and subject to change, but the following may be regarded as typical:
114    *
115    * "GroupOf&lt;&gt;[, ...]"
116    *
117    * @return String representation of this GroupOf
118    * @see java.lang.Object#toString()
119    */
120   @Override
121   public String toString()
122    {
123     final var builder = new StringBuilder();
124     builder.append("GroupOf<>[name="); //$NON-NLS-1$
125     builder.append(this.name);
126     builder.append(", ");
127     final int initLength = builder.length();
128     for (final T entry : this.group)
129      {
130       builder.append(entry);
131       builder.append(", "); //$NON-NLS-1$
132      }
133     if (", ".equals(builder.substring(builder.length() - 2)))
134      {
135       builder.setLength(builder.length() - 2);
136      }
137     builder.append(']');
138     return builder.toString();
139    }
140 
141 
142   /**
143    * Returns the number of elements in this set (its cardinality).
144    *
145    * @return The number of elements in this set (its cardinality)
146    */
147   @Override
148   public int size()
149    {
150     return this.group.size();
151    }
152 
153 
154   /**
155    * Returns true if this set contains no elements.
156    *
157    * @return True if this set contains no elements
158    */
159   @Override
160   public boolean isEmpty()
161    {
162     return this.group.isEmpty();
163    }
164 
165 
166   /**
167    * Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).
168    *
169    * @param o Element whose presence in this set is to be tested
170    * @return true if this set contains the specified element
171    */
172   @Override
173   public boolean contains(final Object o)
174    {
175     return this.group.contains(o);
176    }
177 
178 
179   /**
180    * Returns an iterator over the elements in this set. The elements are returned in no particular order (unless this set is an instance of some class that provides a guarantee).
181    *
182    * @return An iterator over the elements in this set
183    */
184   @Override
185   public Iterator<T> iterator()
186    {
187     return this.group.iterator();
188    }
189 
190 
191   /**
192    * Returns an array containing all of the elements in this set. If this set makes any guarantees as to what order its elements are returned by its iterator, this method must return the elements in the same order.
193    *
194    * @return An array containing all the elements in this set
195    */
196   @Override
197   public Object[] toArray()
198    {
199     return this.group.toArray();
200    }
201 
202 
203   /**
204    * Returns an array containing all of the elements in this set; the runtime type of the returned array is that of the specified array. If the set fits in the specified array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this set.
205    *
206    * @param a The array into which the elements of this set are to be stored, if it is big enough; otherwise, a new array of the same runtime type is allocated for this purpose.
207    * @return An array containing all the elements in this set
208    */
209   @Override
210   public <T> T[] toArray(final T[] a)
211    {
212     return this.group.toArray(a);
213    }
214 
215 
216   /**
217    * Adds the specified element to this set if it is not already present.
218    *
219    * @param e Element to be added to this set
220    * @return true if this set did not already contain the specified element
221    */
222   @Override
223   public boolean add(final T e)
224    {
225     return this.group.add(e);
226    }
227 
228 
229   /**
230    * Removes the specified element from this set if it is present.
231    *
232    * @param o object to be removed from this set, if present
233    * @return true if this set contained the specified element
234    */
235   @Override
236   public boolean remove(final Object o)
237    {
238     return this.group.remove(o);
239    }
240 
241 
242   /**
243    * Returns true if this set contains all of the elements of the specified collection. If the specified collection is also a set, this method returns true if it is a subset of this set.
244    *
245    * @param c Collection to be checked for containment in this set
246    * @return true if this set contains all of the elements of the specified collection
247    */
248   @Override
249   public boolean containsAll(final Collection<?> c)
250    {
251     return this.group.containsAll(c);
252    }
253 
254 
255   /**
256    * Returns true if this set contains all of the elements of the specified collection. If the specified collection is also a set, this method returns true if it is a subset of this set.
257    *
258    * @param c Collection to be checked for containment in this set
259    * @return true if this set contains all of the elements of the specified collection
260    */
261   @Override
262   public boolean addAll(final Collection<? extends T> c)
263    {
264     return this.group.addAll(c);
265    }
266 
267 
268   /**
269    * Retains only the elements in this set that are contained in the specified collection.
270    *
271    * @param c Collection containing elements to be retained in this set
272    * @return true if this set changed as a result of the call
273    */
274   @Override
275   public boolean retainAll(final Collection<?> c)
276    {
277     return this.group.retainAll(c);
278    }
279 
280 
281   /**
282    * Removes from this set all of its elements that are contained in the specified collection.
283    *
284    * @param c Collection containing elements to be removed from this set
285    * @return true if this set changed as a result of the call
286    */
287   @Override
288   public boolean removeAll(final Collection<?> c)
289    {
290     return this.group.removeAll(c);
291    }
292 
293 
294   /**
295    * Removes all of the elements from this set (optional operation). The set will be empty after this call returns.
296    */
297   @Override
298   public void clear()
299    {
300     this.group.clear();
301    }
302 
303  }