| 1 | /******************************************************************************* |
| 2 | * Copyright (c) 2011 Ericsson |
| 3 | * |
| 4 | * All rights reserved. This program and the accompanying materials are |
| 5 | * made available under the terms of the Eclipse Public License v1.0 which |
| 6 | * accompanies this distribution, and is available at |
| 7 | * http://www.eclipse.org/legal/epl-v10.html |
| 8 | * |
| 9 | * Contributors: |
| 10 | * Francois Godin (copelnug@gmail.com) - Initial design and implementation |
| 11 | * Mathieu Denis (mathieu.denis@polymtl.ca) - Correction and refactoring |
| 12 | *******************************************************************************/ |
| 13 | |
| 14 | package org.eclipse.linuxtools.tmf.util; |
| 15 | |
| 16 | import java.lang.reflect.Array; |
| 17 | import java.util.AbstractList; |
| 18 | import java.util.Arrays; |
| 19 | import java.util.List; |
| 20 | import java.util.RandomAccess; |
| 21 | |
| 22 | /** |
| 23 | * <h4>Allow to create a List object that contain an already existing array.</h4> |
| 24 | * <p>Works like {@link java.util.Arrays#asList} but offers more functions : |
| 25 | * <ul> |
| 26 | * <li>{@link #hashCode()}</li> |
| 27 | * <li>{@link #equals(Object)}</li> |
| 28 | * </ul></p> |
| 29 | * <p>Those functions allow to use the FixedArray as the key of a {@link java.util.HashMap}.</p> |
| 30 | * |
| 31 | * @param <T> Type of the array content. |
| 32 | */ |
| 33 | public final class TmfFixedArray<T> extends AbstractList<T> implements RandomAccess { |
| 34 | /** |
| 35 | * Replace {@link java.util.Arrays#copyOf(Object[], int)} that do not exist in java 5. |
| 36 | * @param <E> Content of the array. |
| 37 | * @param array Original array to copy from. |
| 38 | * @param newLength Length of the copy to be returned. |
| 39 | * @return A new array consisting of the elements specified. |
| 40 | */ |
| 41 | @SuppressWarnings("unchecked") |
| 42 | private static <E> E[] copyOf(final E[] array, int newLength) { |
| 43 | E[] result = (E[])Array.newInstance(array.getClass().getComponentType(), newLength); // Is it useful to use newInstance? |
| 44 | System.arraycopy(array, 0, result, 0, Math.min(array.length, newLength)); |
| 45 | return result; |
| 46 | } |
| 47 | /** |
| 48 | * Replace {@link java.util.Arrays#copyOf(Object[], int, Class)} that do not exist in java 5. |
| 49 | * @param <E> Content of the array. |
| 50 | * @param array Original array to copy from. |
| 51 | * @param newLength Length of the copy to be returned. |
| 52 | * @param newType Type of the array to be returned. |
| 53 | * @return A new array consisting of the elements specified. |
| 54 | */ |
| 55 | @SuppressWarnings("unchecked") |
| 56 | private static <E, U> E[] copyOf(final U[] array, int newLength, Class<? extends E[]> newType) { |
| 57 | E[] result = (E[])Array.newInstance(newType.getComponentType(), newLength); |
| 58 | System.arraycopy(array, 0, result, 0, Math.min(array.length, newLength)); |
| 59 | return result; |
| 60 | } |
| 61 | /** |
| 62 | * Replace {@link java.util.Arrays#copyOfRange(Object[], int, int)} that do not exist in java 5. |
| 63 | * @param <E> Content of the array. |
| 64 | * @param array Original array to copy from. |
| 65 | * @param start Starting position of the range, inclusive. |
| 66 | * @param end Ending position of the range, exclusive. |
| 67 | * @return A new array consisting of the elements specified. The length of the new array is equal to end-start |
| 68 | */ |
| 69 | @SuppressWarnings("unchecked") |
| 70 | private static <E> E[] copyOfRange(final E[] array, int start, int end) { |
| 71 | E[] result = (E[])Array.newInstance(array.getClass().getComponentType(), end - start); |
| 72 | System.arraycopy(array, start, result, 0, end - start); |
| 73 | return result; |
| 74 | } |
| 75 | /** |
| 76 | * The array. |
| 77 | */ |
| 78 | private final T[] fArray; |
| 79 | /** |
| 80 | * Constructor. |
| 81 | * @param array Array to use. WILL NOT BE COPIED. |
| 82 | */ |
| 83 | public TmfFixedArray(final T... array) { |
| 84 | fArray = array; |
| 85 | } |
| 86 | /** |
| 87 | * Append a FixedArray to this FixedArray. |
| 88 | * @param value The FixedArray to append. |
| 89 | * @return A new FixedArray with the elements of the two FixedArray. |
| 90 | */ |
| 91 | public TmfFixedArray<T> append(final TmfFixedArray<T> value) { |
| 92 | TmfFixedArray<T> result = new TmfFixedArray<T>(copyOf(fArray, fArray.length + value.size())); |
| 93 | System.arraycopy(value.fArray, 0, result.fArray, fArray.length, value.fArray.length); |
| 94 | return result; |
| 95 | } |
| 96 | /** |
| 97 | * Append in order many FixedArray to this FixedArray. |
| 98 | * @param values The FixedArrays to append. |
| 99 | * @return A new FixedArray with the element of all the FixedArray. |
| 100 | */ |
| 101 | public TmfFixedArray<T> append(final TmfFixedArray<T>... values) { |
| 102 | int newLength = 0; |
| 103 | for(TmfFixedArray<T> value : values) |
| 104 | newLength += value.size(); |
| 105 | TmfFixedArray<T> result = new TmfFixedArray<T>(copyOf(fArray, fArray.length + newLength)); |
| 106 | newLength = fArray.length; |
| 107 | for(TmfFixedArray<T> value : values) |
| 108 | { |
| 109 | System.arraycopy(value.fArray, 0, result.fArray, newLength, value.fArray.length); |
| 110 | newLength += value.fArray.length; |
| 111 | } |
| 112 | return result; |
| 113 | } |
| 114 | /** |
| 115 | * Append an element to the array. |
| 116 | * @param value Element to append. |
| 117 | * @return A new FixedArray with the element appended. |
| 118 | */ |
| 119 | public TmfFixedArray<T> append(final T value) { |
| 120 | TmfFixedArray<T> result = new TmfFixedArray<T>(copyOf(fArray, fArray.length + 1)); |
| 121 | result.set(fArray.length, value); |
| 122 | return result; |
| 123 | } |
| 124 | /** |
| 125 | * Append an array of element to the array. |
| 126 | * @param values Elements array to append. |
| 127 | * @return A new FixedArray with the elements appended. |
| 128 | */ |
| 129 | public TmfFixedArray<T> append(final T... values) { |
| 130 | TmfFixedArray<T> result = new TmfFixedArray<T>(copyOf(fArray, fArray.length + values.length)); |
| 131 | for(int i = 0; i < values.length; ++i) |
| 132 | result.set(fArray.length + i, values[i]); |
| 133 | return result; |
| 134 | } |
| 135 | /* |
| 136 | * (non-Javadoc) |
| 137 | * @see java.lang.Object#clone() |
| 138 | */ |
| 139 | @Override |
| 140 | public Object clone() |
| 141 | { |
| 142 | return new TmfFixedArray<T>(copyOf(fArray, fArray.length)); |
| 143 | } |
| 144 | /* |
| 145 | * (non-Javadoc) |
| 146 | * @see java.util.AbstractList#equals(java.lang.Object) |
| 147 | */ |
| 148 | @Override |
| 149 | public boolean equals(Object o) { |
| 150 | if(o instanceof TmfFixedArray<?>) |
| 151 | return Arrays.equals(fArray, ((TmfFixedArray<?>)o).fArray); |
| 152 | if(!(o instanceof List)) |
| 153 | return false; |
| 154 | for(int i = 0; i < fArray.length; ++i) |
| 155 | if(!fArray[i].equals((List<?>)o)) |
| 156 | return false; |
| 157 | return true; |
| 158 | } |
| 159 | /* |
| 160 | * (non-Javadoc) |
| 161 | * @see java.util.AbstractList#get(int) |
| 162 | */ |
| 163 | @Override |
| 164 | public T get(int index) { |
| 165 | return fArray[index]; |
| 166 | } |
| 167 | /** |
| 168 | * Get the array reference. |
| 169 | * @return The array reference. |
| 170 | * @see #toArray FixedArray.toArray() to get a copy of the array. |
| 171 | */ |
| 172 | public T[] getArray() { |
| 173 | return fArray; |
| 174 | } |
| 175 | /* |
| 176 | * (non-Javadoc) |
| 177 | * @see java.util.AbstractList#hashCode() |
| 178 | */ |
| 179 | @Override |
| 180 | public int hashCode() { |
| 181 | return Arrays.hashCode(fArray); |
| 182 | } |
| 183 | /* |
| 184 | * (non-Javadoc) |
| 185 | * @see java.util.AbstractList#set(int, java.lang.Object) |
| 186 | */ |
| 187 | @Override |
| 188 | public T set(int index, T element) { |
| 189 | T temp = fArray[index]; |
| 190 | fArray[index] = element; |
| 191 | return temp; |
| 192 | } |
| 193 | /* |
| 194 | * (non-Javadoc) |
| 195 | * @see java.util.AbstractCollection#size() |
| 196 | */ |
| 197 | @Override |
| 198 | public int size() { |
| 199 | return fArray.length; |
| 200 | } |
| 201 | /** |
| 202 | * Get a array covering only a part of the array. |
| 203 | * @param start Starting position of the new array. |
| 204 | * @return A new array covering the elements specified. |
| 205 | */ |
| 206 | public TmfFixedArray<T> subArray(int start) { |
| 207 | return new TmfFixedArray<T>(copyOfRange(fArray, start, fArray.length)); |
| 208 | } |
| 209 | /** |
| 210 | * Get a array covering only a part of the array. |
| 211 | * @param start Starting position of the new array. |
| 212 | * @param length Number of element to include in the new array. |
| 213 | * @return A new array covering the elements specified. |
| 214 | */ |
| 215 | public TmfFixedArray<T> subArray(int start, int length) { |
| 216 | return new TmfFixedArray<T>(copyOfRange(fArray, start, length + start)); |
| 217 | } |
| 218 | /* |
| 219 | * (non-Javadoc) |
| 220 | * @see java.util.AbstractCollection#toArray() |
| 221 | */ |
| 222 | @Override |
| 223 | public T[] toArray() |
| 224 | { |
| 225 | return copyOf(fArray, fArray.length); |
| 226 | } |
| 227 | /* |
| 228 | * (non-Javadoc) |
| 229 | * @see java.util.AbstractCollection#toArray(T[]) |
| 230 | */ |
| 231 | @Override |
| 232 | @SuppressWarnings("unchecked") |
| 233 | public <E> E[] toArray(E[] array) |
| 234 | { |
| 235 | if(array.length < fArray.length) |
| 236 | return copyOf(fArray, fArray.length,(Class<? extends E[]>)array.getClass()); |
| 237 | System.arraycopy(fArray, 0, array, 0, fArray.length); |
| 238 | if(array.length > fArray.length) |
| 239 | array[fArray.length] = null; |
| 240 | return array; |
| 241 | } |
| 242 | /* |
| 243 | * (non-Javadoc) |
| 244 | * @see java.util.AbstractCollection#toString() |
| 245 | */ |
| 246 | @Override |
| 247 | public String toString() { |
| 248 | return Arrays.toString(fArray); |
| 249 | } |
| 250 | } |