001    /*
002     * Copyright (C) 2007 Google Inc.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package com.google.common.collect;
018    
019    import com.google.common.annotations.GwtCompatible;
020    import com.google.common.annotations.GwtIncompatible;
021    
022    import java.lang.reflect.Array;
023    import java.util.Collection;
024    
025    import javax.annotation.Nullable;
026    
027    /**
028     * Static utility methods pertaining to object arrays.
029     *
030     * @author Kevin Bourrillion
031     * @since 2 (imported from Google Collections Library)
032     */
033    @GwtCompatible(emulated = true)
034    public final class ObjectArrays {
035      private ObjectArrays() {}
036    
037      /**
038       * Returns a new array of the given length with the specified component type.
039       *
040       * @param type the component type
041       * @param length the length of the new array
042       */
043      @SuppressWarnings("unchecked")
044      public static <T> T[] newArray(Class<T> type, int length) {
045        return Platform.newArray(type, length);
046      }
047    
048      /**
049       * Returns a new array of the given length with the same type as a reference
050       * array.
051       *
052       * @param reference any array of the desired type
053       * @param length the length of the new array
054       */
055      public static <T> T[] newArray(T[] reference, int length) {
056        return Platform.newArray(reference, length);
057      }
058    
059      /**
060       * Returns a new array that contains the concatenated contents of two arrays.
061       *
062       * @param first the first array of elements to concatenate
063       * @param second the second array of elements to concatenate
064       * @param type the component type of the returned array
065       */
066      @GwtIncompatible("Array.newInstance(Class, int)")
067      public static <T> T[] concat(T[] first, T[] second, Class<T> type) {
068        T[] result = newArray(type, first.length + second.length);
069        Platform.unsafeArrayCopy(first, 0, result, 0, first.length);
070        Platform.unsafeArrayCopy(second, 0, result, first.length, second.length);
071        return result;
072      }
073    
074      /**
075       * Returns a new array that prepends {@code element} to {@code array}.
076       *
077       * @param element the element to prepend to the front of {@code array}
078       * @param array the array of elements to append
079       * @return an array whose size is one larger than {@code array}, with
080       *     {@code element} occupying the first position, and the
081       *     elements of {@code array} occupying the remaining elements.
082       */
083      public static <T> T[] concat(@Nullable T element, T[] array) {
084        T[] result = newArray(array, array.length + 1);
085        result[0] = element;
086        Platform.unsafeArrayCopy(array, 0, result, 1, array.length);
087        return result;
088      }
089    
090      /**
091       * Returns a new array that appends {@code element} to {@code array}.
092       *
093       * @param array the array of elements to prepend
094       * @param element the element to append to the end
095       * @return an array whose size is one larger than {@code array}, with
096       *     the same contents as {@code array}, plus {@code element} occupying the
097       *     last position.
098       */
099      public static <T> T[] concat(T[] array, @Nullable T element) {
100        T[] result = arraysCopyOf(array, array.length + 1);
101        result[array.length] = element;
102        return result;
103      }
104    
105      /** GWT safe version of Arrays.copyOf. */
106      private static <T> T[] arraysCopyOf(T[] original, int newLength) {
107        T[] copy = newArray(original, newLength);
108        Platform.unsafeArrayCopy(
109            original, 0, copy, 0, Math.min(original.length, newLength));
110        return copy;
111      }
112    
113      /**
114       * Returns an array containing all of the elements in the specified
115       * collection; the runtime type of the returned array is that of the specified
116       * array. If the collection fits in the specified array, it is returned
117       * therein. Otherwise, a new array is allocated with the runtime type of the
118       * specified array and the size of the specified collection.
119       *
120       * <p>If the collection fits in the specified array with room to spare (i.e.,
121       * the array has more elements than the collection), the element in the array
122       * immediately following the end of the collection is set to null. This is
123       * useful in determining the length of the collection <i>only</i> if the
124       * caller knows that the collection does not contain any null elements.
125       *
126       * <p>This method returns the elements in the order they are returned by the
127       * collection's iterator.
128       *
129       * <p>TODO: Support concurrent collections whose size can change while the
130       * method is running.
131       *
132       * @param c the collection for which to return an array of elements
133       * @param array the array in which to place the collection elements
134       * @throws ArrayStoreException if the runtime type of the specified array is
135       *     not a supertype of the runtime type of every element in the specified
136       *     collection
137       */
138      static <T> T[] toArrayImpl(Collection<?> c, T[] array) {
139        int size = c.size();
140        if (array.length < size) {
141          array = newArray(array, size);
142        }
143        fillArray(c, array);
144        if (array.length > size) {
145          array[size] = null;
146        }
147        return array;
148      }
149    
150      /**
151       * Returns an array containing all of the elements in the specified
152       * collection. This method returns the elements in the order they are returned
153       * by the collection's iterator. The returned array is "safe" in that no
154       * references to it are maintained by the collection. The caller is thus free
155       * to modify the returned array.
156       *
157       * <p>This method assumes that the collection size doesn't change while the
158       * method is running.
159       *
160       * <p>TODO: Support concurrent collections whose size can change while the
161       * method is running.
162       *
163       * @param c the collection for which to return an array of elements
164       */
165      static Object[] toArrayImpl(Collection<?> c) {
166        return fillArray(c, new Object[c.size()]);
167      }
168    
169      private static Object[] fillArray(Iterable<?> elements, Object[] array) {
170        int i = 0;
171        for (Object element : elements) {
172          array[i++] = element;
173        }
174        return array;
175      }
176    }