/* JFox, the OpenSource J2EE Application Server
 *
 * Distributable under GNU LGPL license by gun.org
 * more details please visit http://www.huihoo.org/jfox
 */

package org.jfox.ejb.handler;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import javax.ejb.EJBException;

import org.jfox.ejb.Bucket;
import org.jfox.ejb.Invocation;
import org.jfox.framework.extra.Managable;
import org.jfox.framework.extra.ManagementInfo;
import org.jfox.system.AbstractComponent;

/**
 * 对于一个 Bean 的调用链，Bucket 利用调用链来完成具体的操作
 *
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public abstract class HandlerChain extends AbstractComponent implements Managable {
    protected List invokers = new ArrayList();

    public HandlerChain() {

    }

    public static Object nextInvokeHome(Bucket bucket, Invocation invocation, Iterator iter) throws Exception {
        if(iter.hasNext()) {
            return ((Handler) iter.next()).invokeHome(bucket, invocation, iter);
        }
        else {
            throw new EJBException("No Invoker");
        }
    }

    public static Object nextInvokeBean(Bucket bucket, Invocation invocation, Iterator iter) throws Exception {
        if(iter.hasNext()) {
            return ((Handler) iter.next()).invokeBean(bucket, invocation, iter);
        }
        else {
            throw new EJBException("No Invoker");
        }
    }

    public synchronized void addHandler(Handler invoker) {
        for(int i = 0; i < invokers.size(); i++) {
            // already have
            if(invokers.get(i).getClass().getName().equals(invoker.getClass().getName())) {
                return;
            }
        }
        invokers.add(invoker);
        Collections.sort(invokers);
    }

    public synchronized void addHandler(String handler) {
        try {
            Object obj = Class.forName(handler).newInstance();
            if(obj instanceof Handler) {
                addHandler((Handler) obj);
            }
            else {
                logger.warn(handler + " not implements " + Handler.class.getName() + ", ignore it.");
            }
        }
        catch(ClassNotFoundException e) {
            logger.warn("can not load class " + handler, e);
        }
        catch(InstantiationException e) {
            logger.warn("instantate class " + handler + " error", e);
        }
        catch(IllegalAccessException e) {
            logger.warn(e);
        }
    }

    public synchronized void removeHandler(String invokerClassName) {
        for(int i = 0; i < invokers.size(); i++) {
            if(invokers.get(i).getClass().getName().equals(invokerClassName)) {
                invokers.remove(i);
                return;
            }
        }
    }

    public String[] listInvokers() {
        List invokerStringArray = new ArrayList();
        for(int i = 0; i < invokers.size(); i++) {
            invokerStringArray.add(invokers.get(i).getClass().getName());
        }
        return (String[]) invokerStringArray.toArray(new String[]{});
    }

    protected void doInit() throws Exception {
    }

    protected void doDestroy() throws Exception {
        invokers.clear();
    }

    public ManagementInfo getManagementInfo() {
        return ManagementInfo.exposePublic(this.getClass());
    }

    public abstract Object invokeHome(Bucket bucket, Invocation invocation) throws Exception;

    public abstract Object invokeBean(Bucket bucket, Invocation invocation) throws Exception;
}