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; } }