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.internal.*;
021import org.apache.juneau.json.*;
022import org.apache.juneau.serializer.*;
023
024/**
025 * A fluent {@link ArrayList}.
026 *
027 * <p>
028 * Provides various convenience methods for creating and populating a list with minimal code.
029 *
030 * <h5 class='figure'>Examples:</h5>
031 * <p class='bcode w800'>
032 *    <jc>// A list of strings.</jc>
033 *    AList&lt;String&gt; l = AList.<jsm>of</jsm>(<js>"foo"</js>,<js>"bar"</js>);
034 *
035 *    <jc>// Append to list.</jc>
036 *    l.a(<js>"baz"</js>).a(<js>"qux"</js>);
037 *
038 *    <jc>// Create an unmodifiable view of this list.</jc>
039 *    List&lt;String&gt; l2 = l.unmodifiable();
040 *
041 *    <jc>// Convert it to an array.</jc>
042 *    String[] array = l.asArrayOf(String.<jk>class</jk>);
043 *
044 *    <jc>// Convert to simplified JSON.</jc>
045 *    String json = l.asString();
046 *
047 *    <jc>// Convert to XML.</jc>
048 *    String json = l.asString(XmlSerializer.<jsf>DEFAULT</jsm>);
049 * </p>
050 *
051 * @param <T> The entry type.
052 */
053@SuppressWarnings({"unchecked"})
054public final class AList<T> extends ArrayList<T> {
055
056   private static final long serialVersionUID = 1L;
057
058   //------------------------------------------------------------------------------------------------------------------
059   // Constructors.
060   //------------------------------------------------------------------------------------------------------------------
061
062   /**
063    * Constructor.
064    *
065    * <p>
066    * Creates an array list of default size.
067    */
068   public AList() {}
069
070   /**
071    * Constructor.
072    *
073    * <p>
074    * Creates an array list of default size.
075    * @param capacity Initial capacity.
076    */
077   public AList(int capacity) {
078      super(capacity);
079   }
080
081   /**
082    * Copy constructor.
083    *
084    * @param c Initial contents.  Can be <jk>null</jk>.
085    */
086   public AList(Collection<T> c) {
087      super(c == null ? emptyList() : c);
088   }
089
090   //------------------------------------------------------------------------------------------------------------------
091   // Creators.
092   //------------------------------------------------------------------------------------------------------------------
093
094   /**
095    * Convenience method for creating an empty list of objects.
096    *
097    * <p>
098    * Creates an array list of default size.
099    *
100    * @return A new list.
101    */
102   public static <T> AList<T> of() {
103      return new AList<>();
104   }
105
106   /**
107    * Convenience method for creating a list of objects.
108    *
109    * @param t The initial values.
110    * @return A new list.
111    */
112   @SafeVarargs
113   public static <T> AList<T> of(T...t) {
114      return new AList<T>(t.length).a(t);
115   }
116
117   /**
118    * Convenience method for creating a list of objects.
119    *
120    * <p>
121    * Identical to {@link #of(Object...)} but allows you to distinguish from {@link #of(Collection)} when creating
122    * multi-dimensional lists.
123    *
124    * @param t The initial values.
125    * @return A new list.
126    */
127   public static <T> AList<T> ofa(T...t) {
128      return new AList<T>(t.length).a(t);
129   }
130
131   /**
132    * Convenience method for creating a list of objects.
133    *
134    * <p>
135    * Creates a list with the same capacity as the array.
136    *
137    * @param c The initial values.
138    * @return A new list.
139    */
140   public static <T> AList<T> of(Collection<T> c) {
141      c = c == null ? emptyList() : c;
142      return new AList<T>(c.size()).aa(c);
143   }
144
145   /**
146    * Creates a copy of the collection if it's not <jk>null</jk>.
147    *
148    * @param c The initial values.
149    * @return A new list, or <jk>null</jk> if the collection is <jk>null</jk>.
150    */
151   public static <T> AList<T> nullable(Collection<T> c) {
152      return c == null ? null : of(c);
153   }
154
155   /**
156    * Convenience method for creating an unmodifiable list of objects.
157    *
158    * <p>
159    * Creates a list with the same capacity as the array.
160    *
161    * @param t The initial values.
162    * @return A new list.
163    */
164   public static <T> List<T> unmodifiable(T...t) {
165      return t.length == 0 ? emptyList() : of(t).unmodifiable();
166   }
167
168   /**
169    * Convenience method for creating an unmodifiable list out of the specified collection.
170    *
171    * @param c The collection to add.
172    * @param <T> The element type.
173    * @return An unmodifiable list, never <jk>null</jk>.
174    */
175   public static <T> List<T> unmodifiable(Collection<T> c) {
176      if (c == null || c.isEmpty())
177         return Collections.emptyList();
178      return new AList<T>(c.size()).aa(c).unmodifiable();
179   }
180
181   //------------------------------------------------------------------------------------------------------------------
182   // Appenders.
183   //------------------------------------------------------------------------------------------------------------------
184
185   /**
186    * Add.
187    *
188    * <p>
189    * Adds an entry to this list.
190    *
191    * @param t The entry to add to this list.
192    * @return This object (for method chaining).
193    */
194   public AList<T> a(T t) {
195      add(t);
196      return this;
197   }
198
199   /**
200    * Add.
201    *
202    * <p>
203    * Adds multiple entries to this list.
204    *
205    * @param t The entries to add to this list.
206    * @return This object (for method chaining).
207    */
208   public AList<T> a(T...t) {
209      Collections.addAll(this, t);
210      return this;
211   }
212
213   /**
214    * Add all.
215    *
216    * <p>
217    * Adds all the entries in the specified collection to this list.
218    *
219    * @param c The collection to add to this list.  Can be <jk>null</jk>.
220    * @return This object (for method chaining).
221    */
222   public AList<T> aa(Collection<? extends T> c) {
223      if (c != null)
224         addAll(c);
225      return this;
226   }
227
228   /**
229    * Add if.
230    *
231    * <p>
232    * Adds an entry to this list if the boolean flag is <jk>true</jk>.
233    *
234    * @param b The boolean flag.
235    * @param val The value to add.
236    * @return This object (for method chaining).
237    */
238   public AList<T> aif(boolean b, T val) {
239      if (b)
240         a(val);
241      return this;
242   }
243
244   /**
245    * Add if not null.
246    *
247    * <p>
248    * Adds entries to this list skipping <jk>null</jk> values.
249    *
250    * @param t The objects to add to the list.
251    * @return This object (for method chaining).
252    */
253   public AList<T> aifnn(T...t) {
254      for (T o2 : t)
255         if (o2 != null)
256            a(o2);
257      return this;
258   }
259
260   /**
261    * Add reverse.
262    *
263    * <p>
264    * Adds all the entries in the specified collection to this list in reverse order.
265    *
266    * @param c The collection to add to this list.
267    * @return This object (for method chaining).
268    */
269   public AList<T> arev(List<? extends T> c) {
270      for (ListIterator<? extends T> i = c.listIterator(c.size()); i.hasPrevious();)
271         add(i.previous());
272      return this;
273   }
274
275   /**
276    * Add reverse.
277    *
278    * <p>
279    * Adds the contents of the array to the list in reverse order.
280    *
281    * <p>
282    * i.e. add values from the array from end-to-start order to the end of the list.
283    *
284    * @param c The collection to add to this list.
285    * @return This object (for method chaining).
286    */
287   public AList<T> arev(T[] c) {
288      for (int i = c.length - 1; i >= 0; i--)
289         add(c[i]);
290      return this;
291   }
292
293   //------------------------------------------------------------------------------------------------------------------
294   // Other methods.
295   //------------------------------------------------------------------------------------------------------------------
296
297   /**
298    * Returns an unmodifiable view of this list.
299    *
300    * @return An unmodifiable view of this list.
301    */
302   public List<T> unmodifiable() {
303      return isEmpty() ? emptyList() : unmodifiableList(this);
304   }
305
306   /**
307    * Convert the contents of this list into a new array.
308    *
309    * @param c The component type of the array.
310    * @return A new array.
311    */
312   public <T2> T2[] asArrayOf(Class<T2> c) {
313      return toArray((T2[])Array.newInstance(c, size()));
314   }
315
316   /**
317    * Returns a reverse iterable over this list.
318    *
319    * @return An iterable over the collection.
320    */
321   public Iterable<T> riterable() {
322      return new ReverseIterable<>(this);
323   }
324
325   /**
326    * Convert to a string using the specified serializer.
327    *
328    * @param ws The serializer to use to serialize this collection.
329    * @return This collection serialized to a string.
330    */
331   public String asString(WriterSerializer ws) {
332      return ws.toString(this);
333   }
334
335   /**
336    * Convert to Simplified JSON.
337    *
338    * @return This collection serialized to a string.
339    */
340   public String asString() {
341      return SimpleJsonSerializer.DEFAULT.toString(this);
342   }
343
344   /**
345    * Convert to Simplified JSON.
346    */
347   @Override /* Object */
348   public String toString() {
349      return asString(SimpleJsonSerializer.DEFAULT);
350   }
351}