001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.collections;
014
015import static java.util.Collections.*;
016
017import java.lang.reflect.*;
018import java.util.*;
019
020import org.apache.juneau.json.*;
021import org.apache.juneau.serializer.*;
022
023/**
024 * A fluent {@link LinkedHashSet}.
025 *
026 * <p>
027 * Provides various convenience methods for creating and populating a set with minimal code.
028 *
029 * <h5 class='figure'>Examples:</h5>
030 * <p class='bcode w800'>
031 *    <jc>// A set of strings.</jc>
032 *    ASet&lt;String&gt; s = ASet.<jsm>of</jsm>(<js>"foo"</js>,<js>"bar"</js>);
033 *
034 *    <jc>// Append to set.</jc>
035 *    s.a(<js>"baz"</js>).a(<js>"qux"</js>);
036 *
037 *    <jc>// Create an unmodifiable view of this set.</jc>
038 *    Set&lt;String&gt; s2 = s.unmodifiable();
039 *
040 *    <jc>// Convert it to an array.</jc>
041 *    String[] array = s.asArrayOf(String.<jk>class</jk>);
042 *
043 *    <jc>// Convert to simplified JSON.</jc>
044 *    String json = s.asString();
045 *
046 *    <jc>// Convert to XML.</jc>
047 *    String json = s.asString(XmlSerializer.<jsf>DEFAULT</jsm>);
048 * </p>
049 *
050 * @param <T> The entry type.
051 */
052@SuppressWarnings({"unchecked"})
053public final class ASet<T> extends LinkedHashSet<T> {
054
055   private static final long serialVersionUID = 1L;
056
057   //------------------------------------------------------------------------------------------------------------------
058   // Constructors.
059   //------------------------------------------------------------------------------------------------------------------
060
061   /**
062    * Constructor.
063    */
064   public ASet() {}
065
066   /**
067    * Copy constructor.
068    *
069    * @param c Initial contents.  Can be <jk>null</jk>.
070    */
071   public ASet(Collection<T> c) {
072      super(c == null ? emptySet() : c);
073   }
074
075   //------------------------------------------------------------------------------------------------------------------
076   // Creators.
077   //------------------------------------------------------------------------------------------------------------------
078
079   /**
080    * Convenience method for creating a list of objects.
081    *
082    * @param t The initial values.
083    * @return A new list.
084    */
085   @SafeVarargs
086   public static <T> ASet<T> of(T...t) {
087      return new ASet<T>().a(t);
088   }
089
090   /**
091    * Convenience method for creating a list of objects.
092    *
093    * @param c The initial values.
094    * @return A new list.
095    */
096   public static <T> ASet<T> of(Collection<T> c) {
097      return new ASet<T>().aa(c);
098   }
099
100   /**
101    * Convenience method for creating an unmodifiable set of objects.
102    *
103    * @param t The initial values.
104    * @return A new list.
105    */
106   public static <T> Set<T> unmodifiable(T...t) {
107      return t.length == 0 ? emptySet() : of(t).unmodifiable();
108   }
109
110   /**
111    * Convenience method for creating an unmodifiable sert out of the specified collection.
112    *
113    * @param c The collection to add.
114    * @param <T> The element type.
115    * @return An unmodifiable set, never <jk>null</jk>.
116    */
117   public static <T> Set<T> unmodifiable(Collection<T> c) {
118      if (c == null || c.isEmpty())
119         return Collections.emptySet();
120      return new ASet<T>().aa(c).unmodifiable();
121   }
122
123   //------------------------------------------------------------------------------------------------------------------
124   // Appenders.
125   //------------------------------------------------------------------------------------------------------------------
126
127   /**
128    * Add.
129    *
130    * <p>
131    * Adds an entry to this set.
132    *
133    * @param t The entry to add to this set.
134    * @return This object (for method chaining).
135    */
136   public ASet<T> a(T t) {
137      add(t);
138      return this;
139   }
140
141   /**
142    * Add.
143    *
144    * <p>
145    * Adds multiple entries to this set.
146    *
147    * @param t The entries to add to this set.
148    * @return This object (for method chaining).
149    */
150   public ASet<T> a(T...t) {
151      Collections.addAll(this, t);
152      return this;
153   }
154
155   /**
156    * Add all.
157    *
158    * <p>
159    * Adds multiple entries to this set.
160    *
161    * @param c The entries to add to this set.
162    * @return This object (for method chaining).
163    */
164   public ASet<T> aa(Collection<? extends T> c) {
165      if (c != null)
166         addAll(c);
167      return this;
168   }
169
170   /**
171    * Add if.
172    *
173    * <p>
174    * Adds a value to this set if the boolean value is <jk>true</jk>
175    *
176    * @param b The boolean value.
177    * @param t The value to add.
178    * @return This object (for method chaining).
179    */
180   public ASet<T> aif(boolean b, T t) {
181      if (b)
182         a(t);
183      return this;
184   }
185
186   /**
187    * Add if not null.
188    *
189    * <p>
190    * Adds entries to this set skipping <jk>null</jk> values.
191    *
192    * @param t The objects to add to the list.
193    * @return This object (for method chaining).
194    */
195   public ASet<T> aifnn(T...t) {
196      for (T o2 : t)
197         if (o2 != null)
198            a(o2);
199      return this;
200   }
201
202   //------------------------------------------------------------------------------------------------------------------
203   // Other methods.
204   //------------------------------------------------------------------------------------------------------------------
205
206   /**
207    * Returns an unmodifiable view of this set.
208    *
209    * @return An unmodifiable view of this set.
210    */
211   public Set<T> unmodifiable() {
212      return isEmpty() ? emptySet() : unmodifiableSet(this);
213   }
214
215   /**
216    * Convert the contents of this set into a new array.
217    *
218    * @param c The component type of the array.
219    * @return A new array.
220    */
221   public <T2> T2[] asArrayOf(Class<T2> c) {
222      return toArray((T2[])Array.newInstance(c, size()));
223   }
224
225   /**
226    * Convert to a string using the specified serializer.
227    *
228    * @param ws The serializer to use to serialize this collection.
229    * @return This collection serialized to a string.
230    */
231   public String asString(WriterSerializer ws) {
232      return ws.toString(this);
233   }
234
235   /**
236    * Convert to Simplified JSON.
237    *
238    * @return This collection serialized to a string.
239    */
240   public String asString() {
241      return SimpleJsonSerializer.DEFAULT.toString(this);
242   }
243
244   /**
245    * Convert to Simplified JSON.
246    */
247   @Override /* Object */
248   public String toString() {
249      return asString(SimpleJsonSerializer.DEFAULT);
250   }
251}