| /******************************************************************************* |
| * Copyright (c) 2009, 2010 Cloudsmith Inc. and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Cloudsmith Inc. - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.p2.core.helpers; |
| |
| import java.io.*; |
| import java.lang.reflect.Array; |
| import java.util.*; |
| |
| /** |
| * Helper class that provides some useful support when dealing with collections. |
| */ |
| public class CollectionUtils { |
| |
| /** |
| * A unmodifiable {@link List} implementation on top of an object array. |
| * @param <E> The element type. |
| */ |
| private static class UnmodifiableArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable { |
| private static final long serialVersionUID = 7435304230643855579L; |
| final E[] array; |
| |
| UnmodifiableArrayList(E[] array) { |
| this.array = array; |
| } |
| |
| public boolean contains(Object o) { |
| return indexOf(o) != -1; |
| } |
| |
| public E get(int index) { |
| return array[index]; |
| } |
| |
| public int indexOf(Object o) { |
| int size = array.length; |
| if (o == null) { |
| for (int i = 0; i < size; i++) |
| if (array[i] == null) |
| return i; |
| } else { |
| for (int i = 0; i < size; i++) |
| if (o.equals(array[i])) |
| return i; |
| } |
| return -1; |
| } |
| |
| public Iterator<E> iterator() { |
| return listIterator(); |
| } |
| |
| /** |
| * Rapid iterator, motivated by the fact that we don't need to check |
| * for concurrent modifications. |
| */ |
| public ListIterator<E> listIterator() { |
| return new ListIterator<E>() { |
| private int index = 0; |
| |
| public boolean hasNext() { |
| return index < array.length; |
| } |
| |
| public E next() { |
| if (index >= array.length) |
| throw new NoSuchElementException(); |
| return array[index++]; |
| } |
| |
| public boolean hasPrevious() { |
| return index > 0; |
| } |
| |
| public E previous() { |
| if (--index < 0) { |
| ++index; |
| throw new NoSuchElementException(); |
| } |
| return array[index]; |
| } |
| |
| public int nextIndex() { |
| return index; |
| } |
| |
| public int previousIndex() { |
| return index - 1; |
| } |
| |
| public void remove() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public void set(E e) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public void add(E e) { |
| throw new UnsupportedOperationException(); |
| } |
| }; |
| } |
| |
| public int lastIndexOf(Object o) { |
| int idx = array.length; |
| if (o == null) { |
| while (--idx >= 0) |
| if (array[idx] == null) |
| return idx; |
| } else { |
| while (--idx >= 0) |
| if (o.equals(array[idx])) |
| return idx; |
| } |
| return -1; |
| } |
| |
| public E set(int index, E element) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public int size() { |
| return array.length; |
| } |
| |
| public Object[] toArray() { |
| return array.clone(); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public <T> T[] toArray(T[] a) { |
| int size = array.length; |
| if (a.length < size) |
| a = (T[]) Array.newInstance(a.getClass().getComponentType(), size); |
| System.arraycopy(this.array, 0, a, 0, size); |
| while (size < a.length) |
| a[size++] = null; |
| return a; |
| } |
| } |
| |
| /** |
| * Creates a combined hash for an array of objects. |
| * @param objects The objects to hash |
| * @return The combined hashCode of the objects. |
| */ |
| public static int hashCode(Object objects[]) { |
| if (objects == null) |
| return 0; |
| |
| int result = 1; |
| int idx = objects.length; |
| while (--idx >= 0) { |
| Object object = objects[idx]; |
| result = 17 * result + (object == null ? 0 : object.hashCode()); |
| } |
| return result; |
| } |
| |
| /** |
| * The emptyList() method was introduced in Java 1.5 so we need this here to be able to |
| * down compile to 1.4. |
| * @param <T> The type of the elements |
| * @return An empty list |
| */ |
| @SuppressWarnings("unchecked") |
| public static <T> List<T> emptyList() { |
| return Collections.EMPTY_LIST; |
| } |
| |
| /** |
| * The emptySet() method was introduced in Java 1.5 so we need this here to be able to |
| * down compile to 1.4. |
| * @param <T> The type of the elements |
| * @return An empty set |
| */ |
| @SuppressWarnings("unchecked") |
| public static <T> Set<T> emptySet() { |
| return Collections.EMPTY_SET; |
| } |
| |
| /** |
| * The emptyMap() method was introduced in Java 1.5 so we need this here to be able to |
| * down compile to 1.4. |
| * @param <K> The type of the map keys |
| * @param <V> The type of the map values |
| * @return An empty set |
| */ |
| @SuppressWarnings("unchecked") |
| public static <K, V> Map<K, V> emptyMap() { |
| return Collections.EMPTY_MAP; |
| } |
| |
| /** |
| * Returns an unmodifiable list that is backed by the <code>array</code>. |
| * @param <T> The list element type |
| * @param array The array of elements |
| * @return The unmodifiable list |
| */ |
| public static <T> List<T> unmodifiableList(T[] array) { |
| return array == null || array.length == 0 ? CollectionUtils.<T> emptyList() : new UnmodifiableArrayList<T>(array); |
| } |
| |
| /** |
| * Reads a property list using the {@link Properties#load(InputStream)} method. The |
| * properties are stored in a map. |
| * @param stream The stream to read from |
| * @return The resulting map |
| * @throws IOException propagated from the load method. |
| */ |
| public static Map<String, String> loadProperties(InputStream stream) throws IOException { |
| Properties properties = new Properties(); |
| properties.load(stream); |
| return toMap(properties); |
| } |
| |
| /** |
| * Copies all elements from <code>properties</code> into a Map. The returned map might be unmodifiable |
| * @param properties |
| * @return The map containing all elements |
| */ |
| public static Map<String, String> toMap(Properties properties) { |
| if (properties == null || properties.isEmpty()) |
| return emptyMap(); |
| |
| Map<String, String> props = new HashMap<String, String>(properties.size()); |
| putAll(properties, props); |
| return props; |
| } |
| |
| /** |
| * Copies all elements from <code>properties</code> into the given <code>result</code>. |
| * @param properties |
| * @param result |
| */ |
| public static void putAll(Properties properties, Map<String, String> result) { |
| for (Enumeration<Object> keys = properties.keys(); keys.hasMoreElements();) { |
| String key = (String) keys.nextElement(); |
| result.put(key, properties.getProperty(key)); |
| } |
| } |
| |
| /** |
| * Stores the properties using {@link Properties#store(OutputStream, String)} on the given <code>stream</code>. |
| * @param properties The properties to store |
| * @param stream The stream to store to |
| * @param comment The comment to use |
| * @throws IOException |
| */ |
| public static void storeProperties(Map<String, String> properties, OutputStream stream, String comment) throws IOException { |
| Properties props = new Properties(); |
| props.putAll(properties); |
| props.store(stream, comment); |
| } |
| } |