/* XXL: The eXtensible and fleXible Library for data processing
Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger
Head of the Database Research Group
Department of Mathematics and Computer Science
University of Marburg
Germany
This library 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 3 of the License, or (at your option) any later version.
This library 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 library; If not, see <http://www.gnu.org/licenses/>.
http://code.google.com/p/xxl/
*/
package xxl.core.util.reflect;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.Map.Entry;
import xxl.core.cursors.Cursor;
import xxl.core.cursors.mappers.Mapper;
import xxl.core.cursors.sources.Enumerator;
import xxl.core.functions.AbstractFunction;
import xxl.core.functions.Function;
import xxl.core.functions.Identity;
/**
* This class provides some static methods which make heavily use
* of the Java reflection mechanism.
*/
public class Reflections {
/**
* No instance of this class allowed, because it only contains
* static methods.
*/
private Reflections() {
// private access in order to ensure non-instantiability
}
/**
* Converts a given String into a type which is given by
* its class object.
* @param s String containing a value.
* @param type Class object of the desired return type.
* @return the value parsed from the String.
*/
public static Object convertStringToDifferentType(String s, Class<?> type) {
return type==String.class ?
s :
type==StringBuffer.class ?
new StringBuffer(s) :
type==Integer.TYPE || type==Integer.class ?
new Integer(s) :
type==Byte.TYPE || type==Byte.class ?
new Byte(s) :
type==Short.TYPE || type==Short.class ?
new Short(s) :
type==Long.TYPE || type==Long.class ?
new Long(s) :
type==Float.TYPE || type==Float.class ?
new Float(s) :
type==Double.TYPE || type==Double.class ?
new Double(s) :
type==Boolean.TYPE || type==Boolean.class ?
new Boolean(s) :
type==Character.TYPE || type==Character.class ?
new Character(s.charAt(0)) :
null;
}
/**
* Determines if the type is supported by the convertStringToDifferentType
* method above.
* @param type Class object of the desired return type.
* @return true iff the type is supported.
*/
public static boolean convertStringToDifferentTypeSupported(Class<?> type) {
return
type==String.class ||
type==StringBuffer.class ||
type==Integer.TYPE || type==Integer.class ||
type==Byte.TYPE || type==Byte.class ||
type==Short.TYPE || type==Short.class ||
type==Long.TYPE || type==Long.class ||
type==Float.TYPE || type==Float.class ||
type==Double.TYPE || type==Double.class ||
type==Boolean.TYPE || type==Boolean.class ||
type==Character.TYPE || type==Character.class;
}
/**
* Sets the static fields of a class cl with
* values which are given by a map.
* @param map Map containing the values to be set.
* @param cl Given class.
*/
public static void setStaticFields(Map<String, Object> map, Class<?> cl) {
for (Entry<String, Object> e : map.entrySet())
try {
cl.getField(e.getKey()).set(null, e.getValue());
}
catch (IllegalAccessException ex) {
// ignore
}
catch (NoSuchFieldException ex) {
// ignore
}
}
/**
* Returns a function which converts Number types into the
* desired Wrapper class type, which is given by returnClass.
* @param returnClass Desired return Class. If a primitive
* class is given, then also the associated wrapper class is
* used.
* @return The conversion function.
*/
public static Function<Number, ? extends Number> getNumberTypeConversionFunction(final Class<?> returnClass) {
return returnClass == Byte.TYPE || returnClass == Byte.class ?
new AbstractFunction<Number, Byte>() {
@Override
public Byte invoke(Number n) {
return n.byteValue();
}
} :
returnClass == Short.TYPE || returnClass == Short.class ?
new AbstractFunction<Number, Short>() {
@Override
public Short invoke(Number n) {
return n.shortValue();
}
} :
returnClass == Integer.TYPE || returnClass == Integer.class ?
new AbstractFunction<Number, Integer>() {
@Override
public Integer invoke(Number n) {
return n.intValue();
}
} :
returnClass == Long.TYPE || returnClass == Long.class ?
new AbstractFunction<Number, Long>() {
@Override
public Long invoke(Number n) {
return n.longValue();
}
} :
returnClass == Float.TYPE || returnClass == Float.class ?
new AbstractFunction<Number, Float>() {
@Override
public Float invoke(Number n) {
return n.floatValue();
}
} :
returnClass == Long.TYPE || returnClass == Long.class ?
new AbstractFunction<Number, Long>() {
@Override
public Long invoke(Number n) {
return n.longValue();
}
} :
new Identity<Number>();
}
/**
* Returns true iff the given class is a integral number type.
* @param clv Given class
* @return true iff the given class is a integral number type.
*/
public static boolean isIntegralType(Class<?> clv) {
return
clv == Integer.TYPE || clv == Short.TYPE || clv == Byte.TYPE || clv == Long.TYPE ||
clv == Integer.class || clv == Short.class || clv == Byte.class || clv == Long.class;
}
/**
* Returns true iff the given class is a real number type.
* @param clv Given class
* @return true iff the given class is a real number type.
*/
public static boolean isRealType(Class<?> clv) {
return
clv == Float.TYPE || clv == Double.TYPE ||
clv == Float.class || clv == Double.class;
}
/**
* Calls the main method of a class cl with a given parameter array.
* @param cl The class.
* @param args String array with parameters for the main method.
*/
public static void callMainMethod(Class<?> cl, String[] args) {
try {
cl.getMethod("main", new Class[]{String[].class}).invoke(null, new Object[]{args});
}
catch (SecurityException e) {
// ignore
}
catch (NoSuchMethodException e) {
// ignore
}
catch (IllegalArgumentException e) {
// ignore
}
catch (IllegalAccessException e) {
// ignore
}
catch (InvocationTargetException e) {
// ignore
}
}
/**
* Returns a Cursor iterating over the elements of the
* array. This method is applicable for all kinds of arrays.
* @param valuesArray Array of arbitrary base type.
* @return Cursor iterating over the elements of the array.
*/
public static Cursor<Object> typedArrayCursor(final Object valuesArray) {
return
new Mapper<Integer, Object>(
new AbstractFunction<Integer, Object> () {
@Override
public Object invoke(Integer index) {
return Array.get(valuesArray, index);
}
},
new Enumerator(Array.getLength(valuesArray))
);
}
}