Click here to Skip to main content
15,886,199 members
Articles / Programming Languages / Java / Java SE

Java Generic Code - Power Of Reflection

Rate me:
Please Sign up or sign in to vote.
3.35/5 (7 votes)
30 Sep 2004CPOL3 min read 52.4K   1.2K   18  
Java's Reflection enables programs to automatically flesh out simple interfaces to create automated data objects
package dev.easyref.util;

import java.text.*;
import java.util.*;
import java.lang.reflect.*;

class Argument {
	protected Object array;

	protected Argument(Class objClass) {
		verifyClass(objClass);
	}

	protected void verifyClass(Class objClass) {
		if ((array == null) || (!objClass.equals(Array.get(array, 0).getClass()))) {
			array = Array.newInstance(objClass, 1);
		}
	}

	protected Object getData(boolean nullAsClass) {
		Object result = Array.get(array, 0);
		if (!nullAsClass && (result instanceof Class)) {
			result = null;
		}
		return result;
	}
}

public class Arguments extends Vector {
	protected boolean nullAsClass;
	protected boolean methodError;
	protected boolean showExceptions;
	protected SimpleDateFormat sdfTranslator;

	protected final static String[][] booleanStrings = new String[][] {
		new String[] {"true", "false"},
		new String[] {"yes", "no"},
		new String[] {"1", "0"}
	};

	public Arguments() {
		super();
		nullAsClass = false;
		displayExceptions();
		forceEmpty();
		setDateFormat("dd/MM/yyyy HH:mm:ss");
	}

	public Arguments(Object collectee) {
		this();
		collectData(collectee);
	}

	public void setDateFormat(String dateFormat) {
		sdfTranslator = new SimpleDateFormat(dateFormat);
	}

	public void displayExceptions() {
		showExceptions = true;
	}

	public void hideExceptions() {
		showExceptions = false;
	}

	public void forceEmpty() {
		methodError = false;
		removeAllElements();
		trimToSize();
	}

	public void collectData(Object dataObj) {
		Object data = null;
		Class c = dataObj.getClass();
		Field[] fList = c.getDeclaredFields();
		boolean af = false;
		try {
			for (int i = 0; i < fList.length; i++) {
				Field f = fList[i];
				af = f.isAccessible();
				if (!af) {
					f.setAccessible(true);
				}
				data = f.get(dataObj);
				if (!af) {
					f.setAccessible(false);
				}
				if (data != null) {
					addElement(data);
				} else {
					addNull(f.getType());
				}
			}
		} catch (Exception ex) {
			forceEmpty();
			ex.printStackTrace();
		}
	}

	public Class[] getArgumentsTypes() {
		Class[] result = null;
		if (!isEmpty()) {
			result = new Class[size()];
			int count = 0;
			Class classType = null;
			Enumeration enum = elements();
			Object obj = null;
			Argument arg = null;
			while (enum.hasMoreElements()) {
				obj = enum.nextElement();
				try {
					classType = obj.getClass();
					if (obj instanceof Argument) {
						arg = (Argument)obj;
						obj = arg.array;
						if (arg.getData(nullAsClass) == null) {
							classType = (Class)Array.get(obj, 0);
						} else {
							classType = obj.getClass().getComponentType();
						}
					}
				} catch (Exception ex) {
				}
				result[count++] = classType;
				classType = null;
			}
		}
		return result;
	}

	public String toString() {
		Object[] array = getArguments();
		Object obj = null;
		if (array == null) {
			return "[NULL]";
		} else {
			int length = Array.getLength(array);
			int lastItem = length - 1;
			StringBuffer sb = new StringBuffer("[");
			for (int i = 0; i < length; i++) {
				obj = Array.get(array, i);
				if (obj != null) {
					sb.append(obj);
				} else {
					sb.append("[NULL]");
				}
				if (i < lastItem) {
					sb.append(", ");
				}
			}
			sb.append("]");
			return sb.toString();
		}
	}

	public Object[] getArguments() {
		Object[] result = null;
		if (!isEmpty()) {
			result = new Object[size()];
			int count = 0;
			Object classData = null;
			Enumeration enum = elements();
			Object obj = null;
			while (enum.hasMoreElements()) {
				obj = enum.nextElement();
				try {
					classData = unWrapObject(obj);
				} catch (Exception ex) {
				}
				result[count++] = classData;
				classData = null;
			}
		}
		return result;
	}

	public long[] getLongArray() {
		long[] result = new long[size()];
		try {
			int i = 0;
			Enumeration eId = elements();
			Object xObj = null;
			while (eId.hasMoreElements()) {
				xObj = unWrapObject(eId.nextElement());
				if (xObj instanceof Number) {
					result[i++] = ((Number)xObj).longValue();
				} else if (xObj instanceof String) {
					result[i++] = Long.parseLong((String)xObj);
				}
			}
		} catch (Exception ex) {
			result = null;
		}
		return result;
	}

	public Object getInstance(String objClassName) {
		Exception ex = null;
		Object result = null;
		Object[] args = null;
		Class[] argTypes = null;
		try {
			args = getArguments();
			argTypes = getArgumentsTypes();
			Class objClass = Class.forName(objClassName);
			Constructor con = objClass.getDeclaredConstructor(argTypes);
			boolean ia = con.isAccessible();
			if (!ia) {
				con.setAccessible(true);
			}
			result = con.newInstance(args);
			con.setAccessible(ia);
		} catch (Exception ex0) {
			ex = ex0;
			methodError = true;
			if (showExceptions) {
				ex.printStackTrace();
			}
		} finally {
			if (ex != null) {
				// Report failure..
				methodError = true;
				String pType = null;
				System.err.println("Constructor not found for class [" + objClassName + "] {");
				System.err.print("\t" + objClassName.substring(objClassName.lastIndexOf(".") + 1) + " (");
				for (int i = 0; i < argTypes.length; i++) {
					pType = argTypes[i].getName();
					pType = pType.substring(pType.lastIndexOf(".") + 1);
					System.err.print(pType + " " + "p" + i);
					if (i < argTypes.length - 1) {
						System.err.print(", ");
					}
				}
				System.err.println(");\r\n}");
				if (showExceptions) {
					ex.printStackTrace();
				}
			}
			return result;
		}
	}

	public Method getMethod(Object obj, String methodName) {
		return getMethod(obj.getClass(), methodName);
	}

	public Method getMethod(Class objClass, String methodName) {
		Exception ex = null;
		Method result = null;
		Class[] argTypes = null;
		try {
			argTypes = getArgumentsTypes();
			// Get the method directly declared by the instance's class..
			result = objClass.getDeclaredMethod(methodName, argTypes);
		} catch (NoSuchMethodException nmsex) {
			try {
				// Get the method inherited by the instance's class from its parents..
				result = objClass.getMethod(methodName, argTypes);
			} catch (NoSuchMethodException nmsex0) {
				ex = nmsex0;
			} catch (Exception ex0) {
				ex = ex0;
			}
		} catch (Exception ex1) {
			ex = ex1;
		} finally {
			if (ex != null) {
				// Report failure..
				methodError = true;
				String pType = null;
				System.err.println("Method not found for class [" + objClass.getName() + "] {");
				System.err.print("\t" + methodName + "(");
				if (argTypes != null) {
					for (int i = 0; i < argTypes.length; i++) {
						pType = argTypes[i].getName();
						pType = pType.substring(pType.lastIndexOf(".") + 1);
						System.err.print(pType + " " + "p" + i);
						if (i < argTypes.length - 1) {
							System.err.print(", ");
						}
					}
				}
				System.err.println(");\r\n}");
				if (showExceptions) {
					ex.printStackTrace();
				}
			}
			return result;
		}
	}

	public Object runMethod(Object obj, String methodName) {
		return runMethod(obj, getMethod(obj, methodName));
	}

	public boolean hadMethodError() {
		return methodError;
	}

	public Object runMethod(Object obj, Method method) {
		Object result = null;
		try {
			Class[] mTypes = method.getParameterTypes();
			Class[] aTypes = getArgumentsTypes();
			if (aTypes == null) {
				aTypes = new Class[0];
			}
			if (mTypes.length == aTypes.length) {
				for (int i = 0; i < aTypes.length; i++) {
					if (!mTypes[i].equals(aTypes[i])) {
						methodError = true;
						return null;
					}
				}
				Object[] args = getArguments();
				boolean ia = method.isAccessible();
				if (!ia) {
					method.setAccessible(true);
				}
				result = method.invoke(obj, args);
				method.setAccessible(ia);
			} else {
				methodError = true;
			}
		} catch (NullPointerException npe) {
			methodError = true;
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			return result;
		}
	}

	private boolean translateBoolean(String value) {
		for (int i = 0; i < booleanStrings.length; i++) {
			if (booleanStrings[i][0].equalsIgnoreCase(value)) {
				return true;
			} else if (booleanStrings[i][1].equalsIgnoreCase(value)) {
				return false;
			}
		}
		return false;
	}

	public void addElement(Object value, Class caster) {
		if (caster == Date.class) {
			try {
				super.addElement(sdfTranslator.parse(value.toString()));
			} catch (ParseException ex) {
			}
		} else if ((caster == boolean.class) || (caster == Boolean.class)) {
			addElement(translateBoolean(value.toString()));
		} else if ((caster == byte.class) || (caster == Byte.class)) {
			addElement(Byte.parseByte(value.toString()));
		} else if ((caster == double.class) || (caster == Double.class)) {
			addElement(Double.parseDouble(value.toString()));
		} else if ((caster == float.class) || (caster == Float.class)) {
			addElement(Float.parseFloat(value.toString()));
		} else if ((caster == int.class) || (caster == Integer.class)) {
			addElement(Integer.parseInt(value.toString()));
		} else if ((caster == long.class) || (caster == Long.class)) {
			addElement(Long.parseLong(value.toString()));
		} else if ((caster == short.class) || (caster == Short.class)) {
			addElement(Short.parseShort(value.toString()));
		} else {
			addElement(value);
		}
	}

	public void addElement(Object data) {
		Class caster = data.getClass();
		String value = String.valueOf(data);
		if ((caster == boolean.class) || (caster == Boolean.class)) {
			addElement(translateBoolean(value));
		} else if ((caster == byte.class) || (caster == Byte.class)) {
			addElement(Byte.parseByte(value));
		} else if ((caster == double.class) || (caster == Double.class)) {
			addElement(Double.parseDouble(value));
		} else if ((caster == float.class) || (caster == Float.class)) {
			addElement(Float.parseFloat(value));
		} else if ((caster == int.class) || (caster == Integer.class)) {
			addElement(Integer.parseInt(value));
		} else if ((caster == long.class) || (caster == Long.class)) {
			addElement(Long.parseLong(value));
		} else if ((caster == short.class) || (caster == Short.class)) {
			addElement(Short.parseShort(value));
		} else {
			super.addElement(data);
		}
	}

	public static char unWrapChar(Object obj) {
		return ((Character)unWrap(obj)).charValue();
	}

	public static boolean unWrapBoolean(Object obj) {
		return ((Boolean)unWrap(obj)).booleanValue();
	}

	public static byte unWrapByte(Object obj) {
		return ((Byte)unWrap(obj)).byteValue();
	}

	public static double unWrapDouble(Object obj) {
		return ((Double)unWrap(obj)).doubleValue();
	}

	public static float unWrapFloat(Object obj) {
		return ((Float)unWrap(obj)).floatValue();
	}

	public static int unWrapInteger(Object obj) {
		return ((Integer)unWrap(obj)).intValue();
	}

	public static long unWrapLong(Object obj) {
		return ((Long)unWrap(obj)).longValue();
	}

	public static short unWrapShort(Object obj) {
		return ((Short)unWrap(obj)).shortValue();
	}

	public static Object unWrap(Object obj) {
		return (obj instanceof Argument) ? ((Argument)obj).getData(false) : obj;
	}

	private Object unWrapObject(Object obj) {
		return (obj instanceof Argument) ? ((Argument)obj).getData(nullAsClass) : obj;
	}

	public void addElement(boolean value) {
		Argument o = createArrayObject(boolean.class);
		Array.setBoolean(o.array, 0, value);
		addElement(o);
	}

	public void addElement(byte value) {
		Argument o = createArrayObject(byte.class);
		Array.setByte(o.array, 0, value);
		addElement(o);
	}

	public void addElement(char value) {
		Argument o = createArrayObject(char.class);
		Array.setChar(o.array, 0, value);
		addElement(o);
	}

	public void addElement(double value) {
		Argument o = createArrayObject(double.class);
		Array.setDouble(o.array, 0, value);
		addElement(o);
	}

	public void addElement(float value) {
		Argument o = createArrayObject(float.class);
		Array.setFloat(o.array, 0, value);
		addElement(o);
	}

	public void addElement(int value) {
		Argument o = createArrayObject(int.class);
		Array.setInt(o.array, 0, value);
		addElement(o);
	}

	public void addElement(long value) {
		Argument o = createArrayObject(long.class);
		Array.setLong(o.array, 0, value);
		addElement(o);
	}

	public void addElement(short value) {
		Argument o = createArrayObject(short.class);
		Array.setShort(o.array, 0, value);
		addElement(o);
	}

	public void setElementAt(boolean value, int index) {
		Argument o = createArrayObject(boolean.class, this, index);
		Array.setBoolean(o.array, 0, value);
	}

	public void setElementAt(byte value, int index) {
		Argument o = createArrayObject(byte.class, this, index);
		Array.setByte(o.array, 0, value);
	}

	public void setElementAt(char value, int index) {
		Argument o = createArrayObject(char.class, this, index);
		Array.setChar(o.array, 0, value);
	}

	public void setElementAt(double value, int index) {
		Argument o = createArrayObject(double.class, this, index);
		Array.setDouble(o.array, 0, value);
	}

	public void setElementAt(float value, int index) {
		Argument o = createArrayObject(float.class, this, index);
		Array.setFloat(o.array, 0, value);
	}

	public void setElementAt(int value, int index) {
		Argument o = createArrayObject(int.class, this, index);
		Array.setInt(o.array, 0, value);
	}

	public void setElementAt(long value, int index) {
		Argument o = createArrayObject(long.class, this, index);
		Array.setLong(o.array, 0, value);
	}

	public void setElementAt(short value, int index) {
		Argument o = createArrayObject(short.class, this, index);
		Array.setShort(o.array, 0, value);
	}

	public void insertElementAt(boolean value, int index) {
		Argument o = createArrayObject(boolean.class);
		Array.setBoolean(o.array, 0, value);
		insertElementAt(o, index);
	}

	public void insertElementAt(byte value, int index) {
		Argument o = createArrayObject(byte.class);
		Array.setByte(o.array, 0, value);
		insertElementAt(o, index);
	}

	public void insertElementAt(char value, int index) {
		Argument o = createArrayObject(char.class);
		Array.setChar(o.array, 0, value);
		insertElementAt(o, index);
	}

	public void insertElementAt(double value, int index) {
		Argument o = createArrayObject(double.class);
		Array.setDouble(o.array, 0, value);
		insertElementAt(o, index);
	}

	public void insertElementAt(float value, int index) {
		Argument o = createArrayObject(float.class);
		Array.setFloat(o.array, 0, value);
		insertElementAt(o, index);
	}

	public void insertElementAt(int value, int index) {
		Argument o = createArrayObject(int.class);
		Array.setInt(o.array, 0, value);
		insertElementAt(o, index);
	}

	public void insertElementAt(long value, int index) {
		Argument o = createArrayObject(long.class);
		Array.setLong(o.array, 0, value);
		insertElementAt(o, index);
	}

	public void insertElementAt(short value, int index) {
		Argument o = createArrayObject(short.class);
		Array.setShort(o.array, 0, value);
		insertElementAt(o, index);
	}

	public void addNull(Class classType) {
		Argument o = createArrayObject(Class.class);
		Array.set(o.array, 0, classType);
		addElement(o);
	}

	public void setNullAt(Class classType, int index) {
		Argument o = createArrayObject(Class.class);
		Array.set(o.array, 0, classType);
		setElementAt(o, index);
	}

	public void insertNullAt(Class classType, int index) {
		Argument o = createArrayObject(Class.class);
		Array.set(o.array, 0, classType);
		insertElementAt(o, index);
	}

	private static Argument createArrayObject(Class objClass, Arguments args, int index) {
		Argument result = null;
		Object x = args.elementAt(index);
		if (x instanceof Argument) {
			result = (Argument)x;
			result.verifyClass(objClass);
		} else {
			result = createArrayObject(objClass);
		}
		return result;
	}

	private static Argument createArrayObject(Class objClass) {
		return new Argument(objClass);
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions