| // *************************************************************************************************************************** |
| // * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * |
| // * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * |
| // * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * |
| // * with the License. You may obtain a copy of the License at * |
| // * * |
| // * http://www.apache.org/licenses/LICENSE-2.0 * |
| // * * |
| // * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * |
| // * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * |
| // * specific language governing permissions and limitations under the License. * |
| // *************************************************************************************************************************** |
| package org.apache.juneau.internal; |
| |
| import static org.apache.juneau.internal.ConverterUtils.*; |
| import static org.apache.juneau.internal.ExceptionUtils.*; |
| import static org.apache.juneau.internal.StringUtils.*; |
| |
| import java.lang.reflect.*; |
| import java.util.*; |
| |
| import org.apache.juneau.collections.*; |
| import org.apache.juneau.parser.*; |
| |
| /** |
| * Builder for lists. |
| * |
| * @param <E> Element type. |
| */ |
| public class ListBuilder<E> { |
| |
| private List<E> list; |
| private boolean unmodifiable = false, sparse = false; |
| private Comparator<E> comparator; |
| |
| private Class<E> elementType; |
| private Type[] elementTypeArgs; |
| |
| /** |
| * Constructor. |
| * |
| * @param elementType The element type. |
| * @param elementTypeArgs The element type generic arguments if there are any. |
| */ |
| public ListBuilder(Class<E> elementType, Type...elementTypeArgs) { |
| this.elementType = elementType; |
| this.elementTypeArgs = elementTypeArgs; |
| } |
| |
| /** |
| * Constructor. |
| * |
| * @param addTo The list to add to. |
| */ |
| public ListBuilder(List<E> addTo) { |
| this.list = addTo; |
| } |
| |
| /** |
| * Builds the list. |
| * |
| * @return A list conforming to the settings on this builder. |
| */ |
| public List<E> build() { |
| if (sparse) { |
| if (list != null && list.isEmpty()) |
| list = null; |
| } else { |
| if (list == null) |
| list = new ArrayList<>(0); |
| } |
| if (list != null) { |
| if (comparator != null) |
| Collections.sort(list, comparator); |
| if (unmodifiable) |
| list = Collections.unmodifiableList(list); |
| } |
| return list; |
| } |
| |
| /** |
| * When specified, the {@link #build()} method will return <jk>null</jk> if the list is empty. |
| * |
| * <p> |
| * Otherwise {@link #build()} will never return <jk>null</jk>. |
| * |
| * @return This object (for method chaining). |
| */ |
| public ListBuilder<E> sparse() { |
| this.sparse = true; |
| return this; |
| } |
| |
| /** |
| * When specified, {@link #build()} will return an unmodifiable list. |
| * |
| * @return This object (for method chaining). |
| */ |
| public ListBuilder<E> unmodifiable() { |
| this.unmodifiable = true; |
| return this; |
| } |
| |
| /** |
| * Forces the existing list to be copied instead of appended to. |
| * |
| * @return This object (for method chaining). |
| */ |
| public ListBuilder<E> copy() { |
| if (list != null) |
| list = new ArrayList<>(list); |
| return this; |
| } |
| |
| /** |
| * Sorts the contents of the list. |
| * |
| * @return This object (for method chaining). |
| */ |
| @SuppressWarnings("unchecked") |
| public ListBuilder<E> sorted() { |
| return sorted((Comparator<E>)Comparator.naturalOrder()); |
| } |
| |
| /** |
| * Sorts the contents of the list using the specified comparator. |
| * |
| * @param comparator The comparator to use for sorting. |
| * @return This object (for method chaining). |
| */ |
| public ListBuilder<E> sorted(Comparator<E> comparator) { |
| this.comparator = comparator; |
| return this; |
| } |
| |
| /** |
| * Appends the contents of the specified collection into this list. |
| * |
| * <p> |
| * This is a no-op if the value is <jk>null</jk>. |
| * |
| * @param value The collection to add to this list. |
| * @return This object (for method chaining). |
| */ |
| public ListBuilder<E> addAll(Collection<E> value) { |
| if (value != null) { |
| if (list == null) |
| list = new LinkedList<>(value); |
| else |
| list.addAll(value); |
| } |
| return this; |
| } |
| |
| /** |
| * Adds a single value to this list. |
| * |
| * @param value The value to add to this list. |
| * @return This object (for method chaining). |
| */ |
| public ListBuilder<E> add(E value) { |
| if (list == null) |
| list = new ArrayList<>(); |
| list.add(value); |
| return this; |
| } |
| |
| /** |
| * Adds multiple values to this list. |
| * |
| * @param values The values to add to this list. |
| * @return This object (for method chaining). |
| */ |
| @SuppressWarnings("unchecked") |
| public ListBuilder<E> add(E...values) { |
| for (E v : values) |
| add(v); |
| return this; |
| } |
| |
| /** |
| * Adds entries to this list via JSON array strings. |
| * |
| * @param values The JSON array strings to parse and add to this list. |
| * @return This object (for method chaining). |
| */ |
| public ListBuilder<E> addJson(String...values) { |
| return addAny((Object[])values); |
| } |
| |
| /** |
| * Adds arbitrary values to this list. |
| * |
| * <p> |
| * Objects can be any of the following: |
| * <ul> |
| * <li>The same type or convertible to the element type of this list. |
| * <li>Collections or arrays of anything on this list. |
| * <li>JSON array strings parsed and convertible to the element type of this list. |
| * </ul> |
| * |
| * @param values The values to add. |
| * @return This object (for method chaining). |
| */ |
| @SuppressWarnings("unchecked") |
| public ListBuilder<E> addAny(Object...values) { |
| if (elementType == null) |
| throw runtimeException("Unknown element type. Cannot use this method."); |
| try { |
| if (values != null) { |
| for (Object o : values) { |
| if (o != null) { |
| if (o instanceof Collection) { |
| for (Object o2 : (Collection<?>)o) |
| addAny(o2); |
| } else if (o.getClass().isArray()) { |
| for (int i = 0; i < Array.getLength(o); i++) |
| addAny(Array.get(o, i)); |
| } else if (isJsonArray(o, false)) { |
| for (Object o2 : new OList(o.toString())) |
| addAny(o2); |
| } else if (elementType.isInstance(o)) { |
| add((E)o); |
| } else { |
| add(toType(o, elementType, elementTypeArgs)); |
| } |
| } |
| } |
| } |
| } catch (ParseException e) { |
| throw runtimeException(e); |
| } |
| return this; |
| } |
| } |