/* 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.meta;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.w3c.dom.Element;
import org.w3c.dom.Node;


/**
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public class EJBDescriptor extends EJBDescriptorBase implements Cloneable {
    private EJBBundle bundle;
    private String displayName;
    private String smallIcon;
    private String largeIcon;
    private String ejbClassName;
    private List containerTransactions = new ArrayList();
    private List methodPermissions = new ArrayList();
    private List envEntries = new ArrayList();
    private List ejbReferences = new ArrayList();
    private List resourceReferences = new ArrayList();
    private List resourceEnvReferences = new ArrayList();
    private List roleReferences = new ArrayList();

    private Protocol remoteProtocol = Protocol.JRMP;
    private Protocol localProtocol = Protocol.LOCAL;

    public EJBDescriptor() {

    }

    public void processXML(Node node) throws EJBDescriptionException {
        super.processXML(node);
        setDisplayName(XmlUtil.getChildNodeValueOf(node, "display-name"));
        setSmallIcon(XmlUtil.getChildNodeValueOf(node, "small-icon"));
        setLargeIcon(XmlUtil.getChildNodeValueOf(node, "large-icon"));
        setEjbName(XmlUtil.getChildNodeValueOf(node, "ejb-name"));
        setHomeClassName(XmlUtil.getChildNodeValueOf(node, "home"));
        setRemoteClassName(XmlUtil.getChildNodeValueOf(node, "remote"));
        setEjbClassName(XmlUtil.getChildNodeValueOf(node, "ejb-class"));

        Iterator envEntries = XmlUtil.getElementsByTagName((Element) node, "env-entry");
        while(envEntries.hasNext()) {
            Element envEntry = (Element) envEntries.next();
            EnvEntryDescriptor eed = new EnvEntryDescriptor();
            eed.processXML(envEntry);
            addEnvtEntry(eed);
        }

        Iterator ejbRefs = XmlUtil.getElementsByTagName((Element) node, "ejb-ref");
        while(ejbRefs.hasNext()) {
            Element ejbRef = (Element) ejbRefs.next();
            EJBReferenceDescriptor erd = new EJBReferenceDescriptor();
            erd.processXML(ejbRef);
            addEJBReference(erd);
        }

        Iterator resRefs = XmlUtil.getElementsByTagName((Element) node, "resource-ref");
        while(resRefs.hasNext()) {
            Element resRef = (Element) resRefs.next();
            ResourceRefDescriptor rrd = new ResourceRefDescriptor();
            rrd.processXML(resRef);
            addResourceRef(rrd);
        }

        Iterator resourceEnvRefs = XmlUtil.getElementsByTagName((Element) node, "resource-env-ref");
        while(resourceEnvRefs.hasNext()) {
            Element resourceEnvRef = (Element) resourceEnvRefs.next();
            ResourceEnvRefDescriptor rerd = new ResourceEnvRefDescriptor();
            rerd.processXML(resourceEnvRef);
            addResourceEnvRef(rerd);
        }

        // security-role-ref not support now
/*
    Iterator secRefs = XmlUtil.getElementsByTagName((Element)node,"security-role-ref");
    while(secRefs.hasNext()){
      Element secRef = (Element)secRefs.next();
    }
*/
    }

    public String getType() {
        return "Session";
    }

    public EJBBundle getEJBBundle() {
        return bundle;
    }

    public void setEJBBundle(EJBBundle bundle) {
        this.bundle = bundle;
    }

    public boolean isBeanManagedTransaction() {
        return false;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public String getSmallIcon() {
        return smallIcon;
    }

    public void setSmallIcon(String smallIcon) {
        this.smallIcon = smallIcon;
    }

    public String getLargeIcon() {
        return largeIcon;
    }

    public void setLargeIcon(String largeIcon) {
        this.largeIcon = largeIcon;
    }

    public String getEjbClassName() {
        return ejbClassName;
    }

    public void setEjbClassName(String ejbClassName) {
        this.ejbClassName = ejbClassName;
    }

    public List getContainerTransactions() {
        return Collections.unmodifiableList(containerTransactions);
    }

    public List getMethodPermissions() {
        return Collections.unmodifiableList(methodPermissions);
    }

    public List getEnvEntries() {
        return Collections.unmodifiableList(envEntries);
    }

    public List getEjbReferences() {
        return Collections.unmodifiableList(ejbReferences);
    }

    public List getResourceReferences() {
        return Collections.unmodifiableList(resourceReferences);
    }

    public List getResourceEnvReferences() {
        return Collections.unmodifiableList(resourceEnvReferences);
    }

    public List getRoleReferences() {
        return Collections.unmodifiableList(roleReferences);
    }

    // TODO: performance !!!
    /**
     * get the Transaction Attribute of the method
     *
     * @param method
     * @return
     */
    public byte getMethodTransactionAttribute(Method method) {
        for(int i = 0; i < containerTransactions.size(); i++) {
            MethodTransaction mt = (MethodTransaction) containerTransactions.get(i);
            if(mt.getMethod().match(method)) {
                return mt.getTransactionAttr();
            }
        }
        return TransactionAttribute.TX_REQUIRED;
    }

    void addMethodTransaction(MethodTransaction mt) {
        containerTransactions.add(mt);
    }

    void addEnvtEntry(EnvEntryDescriptor eed) {
        envEntries.add(eed);
    }

    void addEJBReference(EJBReferenceDescriptor erd) {
        ejbReferences.add(erd);
    }

    void addResourceRef(ResourceRefDescriptor rrd) {
        resourceReferences.add(rrd);
    }

    void addResourceEnvRef(ResourceEnvRefDescriptor rerd) {
        resourceEnvReferences.add(rerd);
    }

    public Protocol getRemoteProtocol() {
        return remoteProtocol;
    }

    public void setRemoteProtocol(Protocol remoteProtocol) {
        this.remoteProtocol = remoteProtocol;
    }

    public Protocol getLocalProtocol() {
        return localProtocol;
    }

    public void setLocalProtocol(Protocol localProtocol) {
        this.localProtocol = localProtocol;
    }

    /**
     * becuase this object will passed to EJBMeta, so give it a clone
     *
     * @return
     * @throws CloneNotSupportedException
     */
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public static void main(String[] args) {

    }

}
