package net.sourceforge.pain.logic.fn.factory;
import net.sourceforge.pain.data.*;
import net.sourceforge.pain.data.prototype.*;
import net.sourceforge.pain.logic.fn.util.*;
import net.sourceforge.pain.util.*;
import java.lang.reflect.*;
import java.util.*;
/**
* User: fmike * Date: Aug 21, 2003 * Time: 1:46:52 AM
*/
public final class GlobalFactory {
private final static String FACTORY_PACKAGE = "net.sourceforge.pain.logic.fn.factory.";
private static final Map roleDestructors = new HashMap();
private static Method stubDestructor = null;
private static final Object[] destructorParams = new Object[1];
private static final Class[] destructorArgs = new Class[1];
private static final Map roleConstructors = new HashMap();
private static final Object[] constructorParams = new Object[2];
private static final Class[] constructorArgs = new Class[2];
public static final void destroyObject(LogicalObject obj) throws Exception {
//Hungry loop:
boolean hasMoreRoles;
do {
hasMoreRoles = false;
// int i = 0;
for (Iterator it = obj.rolesIterator(); it.hasNext(); /*i++*/) {
Role role = (Role) it.next();
if (role.hasSubroles()) {
obj = role;
hasMoreRoles = true;
continue;
}
detachRole(role);
it.remove();
}
} while (hasMoreRoles);
}
private static void detachRole(Role role) throws Exception {
Class rClass = role.getClass();
Method m = (Method) roleDestructors.get(rClass);
if (m == null) {
m = lookupDestructorMethod(rClass);
roleDestructors.put(rClass, m);
}
destructorParams[0] = role;
m.invoke(null, destructorParams);
}
private static Method lookupDestructorMethod(Class rClass) throws Exception {
destructorArgs[0] = rClass;
try {
return Class.forName(FACTORY_PACKAGE + Utils.classNameWithoutPackage(rClass) + "Factory").getDeclaredMethod("destroy", destructorArgs);
} catch (Exception e) {
if (stubDestructor == null) {
stubDestructor = GlobalFactory.class.getDeclaredMethod("stubDestructor", new Class[]{Role.class});
}
}
return stubDestructor;
}
static void stubDestructor(Role role) {
// do nothing.
}
private static Method lookupConstructorMethod(Class protoClass, Class rClass) {
constructorArgs[0] = protoClass;
constructorArgs[1] = rClass;
final String className = FACTORY_PACKAGE + Utils.classNameWithoutPackage(rClass) + "Factory";
try {
return Class.forName(className).getDeclaredMethod("init", constructorArgs);
} catch (Exception e) {
throw new RuntimeException("Init method not found:" + className + "." + "init(" + Utils.classNameWithoutPackage(protoClass) + "," + Utils.classNameWithoutPackage(rClass) + ")");
}
}
public static LogicalObject createObject(Prototype proto) throws Exception {
LogicalObject obj = null;
for (Iterator it = proto.rolesIterator(); it.hasNext();) {
final Prototype p = (Prototype) it.next();
final Class prototypedRoleClass = p.getPrototypedRoleClass();
if (prototypedRoleClass == null) {
continue;
}
if (obj == null) {
obj = ObjectFactory.create(prototypedRoleClass);
} else {
final Role role = obj.getRole(prototypedRoleClass);
obj = role == null ? obj.addRole(prototypedRoleClass) : role;
}
Method m = (Method) roleConstructors.get(prototypedRoleClass);
if (m == null) {
m = lookupConstructorMethod(p.getClass(), prototypedRoleClass);
roleConstructors.put(prototypedRoleClass, m);
}
constructorParams[0] = p;
constructorParams[1] = obj;
Log.debug("GlobalFactory.create.invoke:" + m + " params: " + p.getClass() + ", " + obj.getClass());
m.invoke(null, constructorParams);
}
return obj;
}
}