package jas.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
/**
* The object factory is just a convenience class for creating
* objects from thier Class pointer. It hides some of the messiness
* of the java.lang.relect.* classes.
*/
public class ObjectFactory
{
/**
* Create an ObjectFactory capable of creating objects of a specific class.
*
* @param c The class of objects to be created.
*/
public ObjectFactory(Class c)
{
m_c = c;
}
/**
* Creates an object from the specified arguments
*/
public Object create() throws ObjectFactoryException
{
Object[] arg = new Object[0];
return create(arg);
}
/**
* Creates an object from the specified arguments
*/
public Object create(Object a1) throws ObjectFactoryException
{
Object[] arg = new Object[1];
arg[0] = a1;
return create(arg);
}
/**
* Creates an object from the specified arguments
*/
public Object create(Object a1,Object a2) throws ObjectFactoryException
{
Object[] arg = new Object[2];
arg[0] = a1;
arg[1] = a2;
return create(arg);
}
/**
* Creates an object from the specified arguments
*/
public Object create(Object a1,Object a2,Object a3) throws ObjectFactoryException
{
Object[] arg = new Object[3];
arg[0] = a1;
arg[1] = a2;
arg[2] = a3;
return create(arg);
}
/**
* Checks that the class is declared public.
*/
public boolean checkAccess()
{
return Modifier.isPublic(m_c.getModifiers());
}
/**
* Checks that the class inherits from baseClass
*/
public boolean inheritsFrom(Class baseClass)
{
return baseClass.isAssignableFrom(m_c);
}
/**
* Creates an object from the specified arguments
*/
public Object create(Object a1,Object a2,Object a3,Object a4) throws ObjectFactoryException
{
Object[] arg = new Object[4];
arg[0] = a1;
arg[1] = a2;
arg[2] = a3;
arg[3] = a4;
return create(arg);
}
/**
* Creates an object from the specified arguments
*/
public Object create(Object[] args) throws ObjectFactoryException
{
Class[] argc = argClass(args);
try
{
Constructor x = findConstructor(argc);
return x.newInstance(args);
}
catch (NoSuchMethodException e)
{
throw new ObjectFactoryException("Error creating object of class "+m_c,e);
}
catch (IllegalAccessException e)
{
throw new ObjectFactoryException("Error creating object of class "+m_c,e);
}
catch (InstantiationException e)
{
throw new ObjectFactoryException("Error creating object of class "+m_c,e);
}
catch (InvocationTargetException e)
{
throw new ObjectFactoryException(
"Invocation Target Exception for class"+m_c,e.getTargetException());
}
}
/**
* Determines if object can be constrcted from the specified types of arguments
*/
public boolean canBeCreatedFrom()
{
Class[] argc = new Class[0];
return canBeCreatedFrom(argc);
}
/**
* Determines if object can be constrcted from the specified types of arguments
*/
public boolean canBeCreatedFrom(Class c1)
{
Class[] argc = new Class[1];
argc[0] = c1;
return canBeCreatedFrom(argc);
}
/**
* Determines if object can be constrcted from the specified types of arguments
*/
public boolean canBeCreatedFrom(Class c1, Class c2)
{
Class[] argc = new Class[2];
argc[0] = c1;
argc[1] = c2;
return canBeCreatedFrom(argc);
}
/**
* Determines if object can be constrcted from the specified types of arguments
*/
public boolean canBeCreatedFrom(Class c1, Class c2, Class c3)
{
Class[] argc = new Class[3];
argc[0] = c1;
argc[1] = c2;
argc[2] = c3;
return canBeCreatedFrom(argc);
}
/**
* Determines if object can be constrcted from the specified types of arguments
*/
public boolean canBeCreatedFrom(Class c1, Class c2, Class c3, Class c4)
{
Class[] argc = new Class[4];
argc[0] = c1;
argc[1] = c2;
argc[2] = c3;
argc[3] = c4;
return canBeCreatedFrom(argc);
}
/**
* Determines if object can be constrcted from the specified types of arguments
*/
public boolean canBeCreatedFrom(Class[] argc)
{
try
{
findConstructor(argc);
return true;
}
catch (NoSuchMethodException e)
{
return false;
}
}
/**
* Construct a list of argument classes from a list of arguments
*/
private Class[] argClass(Object[] args)
{
Class[] result = new Class[args.length];
for (int i=0; i<args.length; i++)
{
result[i] = args[i].getClass();
if (result[i] == Double.class ) result[i] = Double.TYPE;
if (result[i] == Boolean.class ) result[i] = Boolean.TYPE;
if (result[i] == Integer.class ) result[i] = Integer.TYPE;
if (result[i] == Float.class ) result[i] = Float.TYPE;
if (result[i] == Byte.class ) result[i] = Byte.TYPE;
if (result[i] == Character.class) result[i] = Character.TYPE;
if (result[i] == Long.class ) result[i] = Long.TYPE;
if (result[i] == Short.class ) result[i] = Short.TYPE;
if (result[i] == Void.class ) result[i] = Void.TYPE;
}
return result;
}
/**
* This routine is more than just a copy of java.lang.reflect.getConstructor
* since it also takes into account allowed widening conversions of the arguments
*/
private Constructor findConstructor(Class[] argc) throws NoSuchMethodException
{
Constructor[] x = m_c.getConstructors();
outer: for (int i=0; i<x.length; i++)
{
Class[] c = x[i].getParameterTypes();
if (c.length != argc.length) continue;
for (int j=0; j<c.length; j++)
{
if (!c[j].isAssignableFrom(argc[j])) continue outer;
}
return x[i];
}
throw new NoSuchMethodException("No suitable constructor for class "+m_c);
}
public Class getSourceClass()
{
return m_c;
}
private Class m_c;
}