/**
* Copyright (C) 2009 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.gatein.mop.core.util;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.ArrayList;
import java.util.List;
/**
* @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
* @version $Revision$
*/
public class Tools
{
public static <N> List<N> list(Iterator<N> iterable)
{
ArrayList<N> set = new ArrayList<N>();
while (iterable.hasNext())
{
set.add(iterable.next());
}
return set;
}
public static <N> Set<N> set(Iterable<N> iterable)
{
HashSet<N> set = new HashSet<N>();
for (N n : iterable)
{
set.add(n);
}
return set;
}
public static <N> Set<N> set(Iterator<N> iterator)
{
HashSet<N> set = new HashSet<N>();
while (iterator.hasNext())
{
set.add(iterator.next());
}
return set;
}
public static <N> Set<N> set()
{
return new HashSet<N>();
}
public static <N> Set<N> set(N object)
{
HashSet<N> set = new HashSet<N>();
set.add(object);
return set;
}
public static <N> Set<N> set(N... objects) throws NullPointerException
{
if (objects == null)
{
throw new NullPointerException();
}
HashSet<N> set = new HashSet<N>();
for (N object : objects)
{
set.add(object);
}
return set;
}
public static int max(int value, int... values)
{
int max = value;
for (int v : values)
{
if (v > max)
{
max = v;
}
}
return max;
}
public static <E> Iterator<E> iterator(final Iterator<? extends E>... iterators)
{
return new Iterator<E>()
{
int index = 0;
public boolean hasNext()
{
while (index < iterators.length)
{
if (iterators[index].hasNext())
{
return true;
}
index++;
}
return false;
}
public E next()
{
while (index < iterators.length)
{
if (iterators[index].hasNext())
{
return iterators[index].next();
}
index++;
}
throw new NoSuchElementException();
}
public void remove()
{
throw new UnsupportedOperationException();
}
};
}
/**
* A simplistic implementation, it may not handle all cases but it should handle enough.
*
* @param implementation the type for which the parameter requires a resolution
* @param type the type that owns the parameter
* @param parameterIndex the parameter index
* @return the resolved type
*/
public static Type resolve(Type implementation, Class<?> type, int parameterIndex) {
if (implementation == null) {
throw new NullPointerException();
}
//
if (implementation == type) {
TypeVariable<? extends Class<?>>[] tp = type.getTypeParameters();
if (parameterIndex < tp.length) {
return tp[parameterIndex];
} else {
throw new IllegalArgumentException();
}
} else if (implementation instanceof Class<?>) {
Class<?> c = (Class<?>) implementation;
Type gsc = c.getGenericSuperclass();
Type resolved = null;
if (gsc != null) {
resolved = resolve(gsc, type, parameterIndex);
if (resolved == null) {
// Try with interface
}
}
return resolved;
} else if (implementation instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) implementation;
Type[] typeArgs = pt.getActualTypeArguments();
Type rawType = pt.getRawType();
if (rawType == type) {
return typeArgs[parameterIndex];
} else if (rawType instanceof Class<?>) {
Class<?> classRawType = (Class<?>)rawType;
Type resolved = resolve(classRawType, type, parameterIndex);
if (resolved == null) {
return null;
} else if (resolved instanceof TypeVariable) {
TypeVariable resolvedTV = (TypeVariable)resolved;
TypeVariable[] a = classRawType.getTypeParameters();
for (int i = 0;i < a.length;i++) {
if (a[i].equals(resolvedTV)) {
return resolve(implementation, classRawType, i);
}
}
throw new AssertionError();
} else {
throw new UnsupportedOperationException("Cannot support resolution of " + resolved);
}
} else {
throw new UnsupportedOperationException();
}
} else {
throw new UnsupportedOperationException("todo " + implementation + " " + implementation.getClass());
}
}
}