/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2009 Bull S.A.S
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.webapp.jonasadmin.service.ejb;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import javax.management.MBeanAttributeInfo;
import javax.management.ObjectName;
import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.ow2.jonas.management.extensions.base.api.J2EEMBeanAttributeInfo;
import org.ow2.jonas.webapp.jonasadmin.Jlists;

/**
 * @author Michel-Ange ANTON
 */
public class EjbForm extends ActionForm {

    // --------------------------------------------------------- Properties
    // variables

    /**
     * Parameters properties
     */
    private String type = null;

    private String fullType = null;

    private String file = null;

    private String name = null;

    private String objectName = null;

    private String action = null;

    /**
     * EJB3 support
     */
    private boolean ejb3 = false;

    /**
     * Global MBean Ejb properties
     */
    private int cacheSize = 0;

    private int maxCacheSize = 0;

    private int minPoolSize = 0;

    private int poolSize = 0;

    private String displayName = null;

    private String ejbClass = null;

    private String ejbFileName = null;

    private String ejbName = null;

    private String homeClass = null;

    private String jndiName = null;

    private String localClass = null;

    private String localHomeClass = null;

    private String remoteClass = null;

    private boolean dependency = false;

    private boolean databaseServiceActivated = false;

    private boolean resourceServiceActivated = false;

    private boolean dataSource = false;

    private HashMap dataSources = new HashMap();

    private HashMap jdbcRas = new HashMap();

    private boolean jmsServiceActivated = false;

    private boolean joramResourceLoaded = false;

    private boolean jmsConnection = false;

    private ArrayList jmsConnections = new ArrayList();

    private boolean jmsDestination = false;

    private ArrayList jmsDestinations = new ArrayList();

    private Hashtable jmsDestinationsTable = new Hashtable();

    private boolean mailServiceActivated = false;

    private boolean mailSession = false;

    private HashMap mailSessions = new HashMap();

    private boolean mailMime = false;

    private HashMap mailMimes = new HashMap();

    /**
     * Is the type already calculated ?
     */
    private boolean writable = true;

    /**
     * <code>true</code> if any attribute is writable.
     * @return
     */
    public boolean isWritable() {
        for (J2EEMBeanAttributeInfo attribute : attributes) {
            if (attribute.isWritable()) {
                // the "warningThreshold" attribute is defined for ejb2 only.
                writable = true;
                return writable;
            }
        }
        writable = false;
        return writable;
    }

    /**
     * @param writable the writable to set
     */
    public void setWritable(final boolean writable) {
        this.writable = writable;
    }

    /**
     * @return the attributes
     */
    public List<J2EEMBeanAttributeInfo> getAttributes() {
        return attributes;
    }

    /**
     * @param attributes the attributes to set
     */
    public void setAttributes(final J2EEMBeanAttributeInfo[] attributes) {
        this.attributes.clear();
        this.namingAttributes.clear();
        this.monitoringAttributes.clear();
        if (objectName != null) {
            try {
                // allow to display Bean type.
                ObjectName on = ObjectName.getInstance(objectName);
                String beanType = on.getKeyProperty("j2eeType");
                if (beanType != null) {
                    J2EEMBeanAttributeInfo atr = new J2EEMBeanAttributeInfo();
                    atr.setValue(beanType);
                    MBeanAttributeInfo infos = new MBeanAttributeInfo("Type", String.class.getName(),
                            "Bean type", true, false, false);
                    atr.setMbeanAttributeInfo(infos);
                    this.generalAttributes.add(atr);
                }
            } catch (Exception e) {
                ;// Do nothing
            }
        }
        for (J2EEMBeanAttributeInfo beanAttributeInfo : attributes) {
            if (!containsLabel(beanAttributeInfo.getLabel(), this.attributes)) {
                /**
                 * Filter some attributes
                 */
                if (!"stateManageable".equals(beanAttributeInfo.getName())
                        && !beanAttributeInfo.getName().contains("statistic")
                        && !"eventProvider".equals(beanAttributeInfo.getName())
                        && !"javaVMs".equals(beanAttributeInfo.getName())
                        && !"objectName".equals(beanAttributeInfo.getName())
                        && !"modelerType".equals(beanAttributeInfo.getName())) {
                    if (beanAttributeInfo.getName().contains("jndi") || beanAttributeInfo.getName().contains("lass")
                            || beanAttributeInfo.getName().contains("display")
                            || "name".equalsIgnoreCase(beanAttributeInfo.getName())
                            || beanAttributeInfo.getName().contains("file")
                            || beanAttributeInfo.getName().contains("modeler")) {
                        /**
                         * Naming attribute
                         */
                        this.namingAttributes.add(beanAttributeInfo);
                    } else {
                        /**
                         * Monitoring attribute.
                         */
                        monitoringAttributes.add(beanAttributeInfo);
                    }
                    /**
                     * Add the attribute.
                     */
                    this.attributes.add(beanAttributeInfo);
                }
            }
        }
    }

    /**
     * @return the namingAttributes.
     */
    public List<J2EEMBeanAttributeInfo> getNamingAttributes() {
        return namingAttributes;
    }

    /**
     * @param namingAttributes the namingAttributes to set.
     */
    public void setNamingAttributes(final J2EEMBeanAttributeInfo[] namingAttributes) {
        this.namingAttributes.clear();
        for (J2EEMBeanAttributeInfo beanAttributeInfo : namingAttributes) {
            this.namingAttributes.add(beanAttributeInfo);
        }
    }

    /**
     * @param monitoringAttributes the namingAttributes to set.
     */
    public void setMonitoringAttributes(final J2EEMBeanAttributeInfo[] monitoringAttributes) {
        this.monitoringAttributes.clear();
        for (J2EEMBeanAttributeInfo beanAttributeInfo : monitoringAttributes) {
            this.monitoringAttributes.add(beanAttributeInfo);
        }
    }

    /**
     * @param namingAttributes the namingAttributes to set.
     */
    public void setNamingAttributes(final List<J2EEMBeanAttributeInfo> namingAttributes) {
        this.namingAttributes = namingAttributes;
    }

    /**
     * @param monitoringAttributes the namingAttributes to set.
     */
    public void setMonitoringAttributes(final List<J2EEMBeanAttributeInfo> monitoringAttributes) {
        this.monitoringAttributes = monitoringAttributes;
    }

    /**
     * @return the monitoringAttributes
     */
    public List<J2EEMBeanAttributeInfo> getMonitoringAttributes() {
        return monitoringAttributes;
    }

    /**
     * Naming attributes.
     */
    private List<J2EEMBeanAttributeInfo> namingAttributes = new ArrayList<J2EEMBeanAttributeInfo>();

    /**
     * General attributes.
     */
    private List<J2EEMBeanAttributeInfo> generalAttributes = new ArrayList<J2EEMBeanAttributeInfo>();

    /**
     * The MBean attribute descriptors.
     */
    private List<J2EEMBeanAttributeInfo> monitoringAttributes = new ArrayList<J2EEMBeanAttributeInfo>();

    /**
     * All attributes.
     */
    private List<J2EEMBeanAttributeInfo> attributes = new ArrayList<J2EEMBeanAttributeInfo>();

    // --------------------------------------------------------- Public Methods

    /**
     * @return the generalAttributes
     */
    public List<J2EEMBeanAttributeInfo> getGeneralAttributes() {
        return generalAttributes;
    }

    /**
     * @param generalAttributes the generalAttributes to set
     */
    public void setGeneralAttributes(final List<J2EEMBeanAttributeInfo> generalAttributes) {
        this.generalAttributes = generalAttributes;
    }

    /**
     * Reset all properties to their default values.
     * @param mapping The mapping used to select this instance
     * @param request The servlet request we are processing
     */

    @Override
    public void reset(final ActionMapping mapping, final HttpServletRequest request) {
        // Parameters properties
        type = null;
        file = null;
        name = null;
        objectName = null;
        fullType = null;
        action = null;

        // Global MBean Ejb properties
        cacheSize = 0;
        maxCacheSize = 0;
        minPoolSize = 0;
        poolSize = 0;
        displayName = null;
        ejbClass = null;
        ejbFileName = null;
        ejbName = null;
        homeClass = null;
        jndiName = null;
        localClass = null;
        localHomeClass = null;
        remoteClass = null;

        dependency = false;
        databaseServiceActivated = false;
        resourceServiceActivated = false;
        dataSources = new HashMap();
        dataSource = false;
        jdbcRas = new HashMap();
        jmsServiceActivated = false;
        joramResourceLoaded = false;
        jmsConnection = false;
        jmsConnections = new ArrayList();
        jmsDestination = false;
        jmsDestinations = new ArrayList();
        jmsDestinationsTable = new Hashtable();
        mailServiceActivated = false;
        mailSession = false;
        mailSessions = new HashMap();
        mailMime = false;
        mailMimes = new HashMap();
    }

    /**
     * Validate the properties that have been set from this HTTP request, and
     * return an <code>ActionErrors</code> object that encapsulates any
     * validation errors that have been found. If no errors are found, return
     * <code>null</code> or an <code>ActionErrors</code> object with no recorded
     * error messages.
     * @param mapping The mapping used to select this instance
     * @param request The servlet request we are processing
     * @return List of errors or null
     */
    @Override
    public ActionErrors validate(final ActionMapping mapping, final HttpServletRequest request) {
        ActionErrors oErrors = new ActionErrors();
        return oErrors;
    }

    // --------------------------------------------------------- Properties
    // Methods

    // Parameters properties

    public String getFile() {
        return file;
    }

    public String getFilename() {
        String sFilename = null;
        if (file != null) {
            sFilename = file.replace('\\', '/');
            int iPos = sFilename.lastIndexOf('/');
            if (iPos > -1) {
                sFilename = sFilename.substring(iPos + 1);
            }
        }
        return sFilename;
    }

    public String getName() {
        return name;
    }

    public String getObjectName() {
        return objectName;
    }

    public String getType() {
        return type;
    }

    public void setFile(final String file) {
        this.file = file;
    }

    public void setName(final String name) {
        this.name = name;
    }

    public void setObjectName(final String objectName) {
        this.objectName = objectName;
    }

    public void setType(final String type) {
        this.type = type;
    }

    // Global MBean Ejb properties
    public String getDisplayName() {
        return displayName;
    }

    public String getEjbClass() {
        return ejbClass;
    }

    public String getEjbName() {
        return ejbName;
    }

    public String getHomeClass() {
        return homeClass;
    }

    public String getJndiName() {
        return jndiName;
    }

    public String getLocalClass() {
        return localClass;
    }

    public String getLocalHomeClass() {
        return localHomeClass;
    }

    public String getRemoteClass() {
        return remoteClass;
    }

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

    public void setEjbClass(final String ejbClass) {
        this.ejbClass = ejbClass;
    }

    public void setEjbName(final String ejbName) {
        this.ejbName = ejbName;
    }

    public void setHomeClass(final String homeClass) {
        this.homeClass = homeClass;
    }

    public void setJndiName(final String jndiName) {
        this.jndiName = jndiName;
    }

    public void setLocalClass(final String localClass) {
        this.localClass = localClass;
    }

    public void setLocalHomeClass(final String localHomeClass) {
        this.localHomeClass = localHomeClass;
    }

    public void setRemoteClass(final String remoteClass) {
        this.remoteClass = remoteClass;
    }

    public String getEjbFileName() {
        return ejbFileName;
    }

    public void setEjbFileName(final String ejbFileName) {
        this.ejbFileName = ejbFileName;
    }

    public String getFullType() {
        return fullType;
    }

    public void setFullType(final String fullType) {
        this.fullType = fullType;
    }

    public HashMap getDataSources() {
        return dataSources;
    }

    public void setDataSources(final HashMap dataSources) {
        this.dataSources = dataSources;
    }

    public boolean isDataSource() {
        return dataSource;
    }

    public void setDataSource(final boolean dataSource) {
        this.dataSource = dataSource;
    }

    public boolean isDependency() {
        return dependency;
    }

    public void setDependency(final boolean dependency) {
        this.dependency = dependency;
    }

    public boolean isJmsConnection() {
        return jmsConnection;
    }

    public void setJmsConnection(final boolean jmsConnection) {
        this.jmsConnection = jmsConnection;
    }

    public ArrayList getJmsConnections() {
        return jmsConnections;
    }

    public void setJmsConnections(final ArrayList jmsConnections) {
        this.jmsConnections = jmsConnections;
    }

    public boolean isJmsDestination() {
        return jmsDestination;
    }

    public void setJmsDestination(final boolean jmsDestination) {
        this.jmsDestination = jmsDestination;
    }

    public ArrayList getJmsDestinations() {
        return jmsDestinations;
    }

    public void setJmsDestinations(final ArrayList jmsDestinations) {
        this.jmsDestinations = jmsDestinations;
    }

    public HashMap getMailSessions() {
        return mailSessions;
    }

    public void setMailSessions(final HashMap mailSessions) {
        this.mailSessions = mailSessions;
    }

    public HashMap getMailMimes() {
        return mailMimes;
    }

    public void setMailMimes(final HashMap mailMimes) {
        this.mailMimes = mailMimes;
    }

    public boolean isMailSession() {
        return mailSession;
    }

    public void setMailSession(final boolean mailSession) {
        this.mailSession = mailSession;
    }

    public boolean isMailMime() {
        return mailMime;
    }

    public void setMailMime(final boolean mailMime) {
        this.mailMime = mailMime;
    }

    public boolean isDatabaseServiceActivated() {
        return databaseServiceActivated;
    }

    public void setDatabaseServiceActivated(final boolean databaseServiceActivated) {
        this.databaseServiceActivated = databaseServiceActivated;
    }

    public boolean isJmsServiceActivated() {
        return jmsServiceActivated;
    }

    public void setJmsServiceActivated(final boolean jmsServiceActivated) {
        this.jmsServiceActivated = jmsServiceActivated;
    }

    public boolean isMailServiceActivated() {
        return mailServiceActivated;
    }

    public void setMailServiceActivated(final boolean mailServiceActivated) {
        this.mailServiceActivated = mailServiceActivated;
    }

    /**
     * @return Returns the joramResourceLoaded.
     */
    public boolean isJoramResourceLoaded() {
        return joramResourceLoaded;
    }

    /**
     * @param joramResourceLoaded The joramResourceLoaded to set.
     */
    public void setJoramResourceLoaded(final boolean joramResourceLoaded) {
        this.joramResourceLoaded = joramResourceLoaded;
    }

    /**
     * @return Returns the action.
     */
    public String getAction() {
        return action;
    }

    /**
     * @param action The action to set.
     */
    public void setAction(final String action) {
        this.action = action;
    }

    /**
     * Helper method to check that it is a required number and is a valid
     * integer within the given range. (min, max).
     * @param field The field name in the form for which this error occured.
     * @param numText The string representation of the number.
     * @param rangeCheck Boolean value set to true of reange check should be
     *        performed.
     * @param min The lower limit of the range
     * @param max The upper limit of the range
     *        error.webapp.setting.sessionTimeout.required
     */
    protected void numberCheck(final ActionErrors p_Errors, final String field, final String numText, final boolean rangeCheck,
            final int min, final int max) {
        // Check for 'is required'
        if ((numText == null) || (numText.length() < 1)) {
            p_Errors.add(field, new ActionMessage("error.ejb.type.session." + field + ".required"));
        } else {

            // check for 'must be a number' in the 'valid range'
            try {
                int num = Integer.parseInt(numText);
                // perform range check only if required
                if (rangeCheck) {
                    if ((num < min) || (num > max)) {
                        p_Errors.add(field, new ActionMessage("error.ejb.type.session." + field + ".range"));
                    }
                }
            } catch (NumberFormatException e) {
                p_Errors.add(field, new ActionMessage("error.ejb.type.session." + field + ".format"));
            }
        }
    }

    /**
     * @return Returns the jmsDestinationsTable.
     */
    public Hashtable getJmsDestinationsTable() {
        return jmsDestinationsTable;
    }

    /**
     * @param jmsDestinationsTable The jmsDestinationsTable to set.
     */
    public void setJmsDestinationsTable(final Hashtable jmsDestinationsTable) {
        this.jmsDestinationsTable = jmsDestinationsTable;
    }

    /**
     * @return Returns the cacheSize.
     */
    public int getCacheSize() {
        return cacheSize;
    }

    /**
     * @param cacheSize The cacheSize to set.
     */
    public void setCacheSize(final int cacheSize) {
        this.cacheSize = cacheSize;
    }

    /**
     * @return Returns the maxCacheSize.
     */
    public int getMaxCacheSize() {
        return maxCacheSize;
    }

    /**
     * @param maxCacheSize The maxCacheSize to set.
     */
    public void setMaxCacheSize(final int maxCacheSize) {
        this.maxCacheSize = maxCacheSize;
    }

    /**
     * @return Returns the minPoolSize.
     */
    public int getMinPoolSize() {
        return minPoolSize;
    }

    /**
     * @param minPoolSize The minPoolSize to set.
     */
    public void setMinPoolSize(final int minPoolSize) {
        this.minPoolSize = minPoolSize;
    }

    /**
     * @return Returns the poolSize.
     */
    public int getPoolSize() {
        return poolSize;
    }

    /**
     * @param poolSize The poolSize to set.
     */
    public void setPoolSize(final int poolSize) {
        this.poolSize = poolSize;
    }

    public boolean isResourceServiceActivated() {
        return resourceServiceActivated;
    }

    public void setResourceServiceActivated(final boolean resourceServiceActivated) {
        this.resourceServiceActivated = resourceServiceActivated;
    }

    public HashMap getJdbcRas() {
        return jdbcRas;
    }

    public void setJdbcRas(final HashMap jdbcRas) {
        this.jdbcRas = jdbcRas;
    }

    public boolean isEjb3() {
        return ejb3;
    }

    public void setEjb3(final boolean ejb3) {
        this.ejb3 = ejb3;
    }

    /**
     * Get boolean values.
     * @return boolean values.
     */
    public List getBooleanValues() {
        return Jlists.getBooleanValues();
    }

    /**
     * Checks if the given label is already registered in the given set of
     * attributes.
     * @param label The label to check
     * @param attributes attributes to check in.
     * @return true if the given label is already registered in the given set of
     *         attributes.
     */
    private static boolean containsLabel(final String label, final List<J2EEMBeanAttributeInfo> attributes) {
        for (Iterator<J2EEMBeanAttributeInfo> iterator = attributes.iterator(); iterator.hasNext();) {
            J2EEMBeanAttributeInfo beanAttributeInfo = iterator.next();
            if (beanAttributeInfo.getLabel().equals(label)) {
                return true;
            }
        }
        return false;
    }

}
