/**
 * JaDOrT: JASMINe Deployment Orchestration Tool
 * Copyright (C) 2008-2009 Bull S.A.S.
 * Copyright (C) 2008-2009 France Telecom R&D
 * Contact: jasmine@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: ServerBean.java 4130 2009-06-23 15:42:39Z alitokmen $
 * --------------------------------------------------------------------------
 */
package org.ow2.jasmine.jadort.api.entities.topology;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.OneToOne;
import javax.persistence.Transient;

import org.ow2.jasmine.jadort.api.entities.deployment.ApplicationBean;

/**
 * Bean represents a application server
 * 
 * @author Malek Chahine
 * @author Remy Bresson
 * @author S. Ali Tokmen
 */
@Entity(name = "JaDOrT_ServerBean")
public class ServerBean implements Serializable {

    /**
     * Server type.<br>
     * <br>
     * We don't use an enum here to preserve compatibility with IIOP runtimes on
     * Java EE 5. You can check out the bug report and comments on
     * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6277781 for details.
     */
    public static final class Type implements Serializable {

        private static final long serialVersionUID = 8006861800369211346L;

        public static final Type JONAS = new Type("JONAS");

        public static final Type JBOSS = new Type("JBOSS");

        public static final Type GLASSFISH = new Type("GLASSFISH");

        public static final Type WEBLOGIC = new Type("WEBLOGIC");

        public static final Type WEBSPHERE = new Type("WEBSPHERE");

        public static final Type OSGI = new Type("OSGI");

        public static final Type DUMMY = new Type("DUMMY");

        private static final Type[] values = new Type[] {Type.JONAS, Type.JBOSS, Type.GLASSFISH, Type.WEBLOGIC, Type.WEBSPHERE,
            Type.OSGI, Type.DUMMY};

        private String type;

        /**
         * @param type Type.
         */
        private Type(final String type) {
            this.type = type;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public boolean equals(final Object object) {
            if ((object != null) && (object instanceof Type)) {
                Type type = (Type) object;
                if (type.type.equals(this.type)) {
                    return true;
                }
            }

            return false;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public int hashCode() {
            return this.type.hashCode();
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public String toString() {
            return this.type;
        }

        /**
         * @return All Type values.
         */
        public static Type[] values() {
            return Type.values;
        }

        /**
         * Get the Type for a string.
         * 
         * @param string Type string.
         * @return Type for that string.
         */
        public static Type valueOf(final String string) {
            for (Type type : Type.values) {
                if (type.type.equals(string)) {
                    return type;
                }
            }

            throw new IllegalArgumentException("Unknown value: " + string);
        }
    }

    /**
     * Auto-generated serial version ID.
     */
    private static final long serialVersionUID = -8338670679543686581L;

    /**
     * Auto-generated identifier of the ServerBean in the database.
     */
    @Id
    @GeneratedValue
    private Integer id;

    /**
     * Server name
     */
    private String name;

    /**
     * Server type
     */
    private Type type;

    /**
     * Server capacity
     */
    private int capacity;

    /**
     * Server JMX connnector
     */
    @OneToOne(cascade = CascadeType.ALL)
    @JoinTable(name = "JaDOrT_ServerBean_serverConnector")
    private ConnectorBean serverConnector;

    /**
     * Server manager's JMX connnector
     */
    @OneToOne(cascade = CascadeType.ALL)
    @JoinTable(name = "JaDOrT_ServerBean_managerConnector")
    private ConnectorBean managerConnector;

    /**
     * VM the server is running on
     */
    @OneToOne(cascade = CascadeType.ALL)
    private VMBean vm;

    /**
     * Target server (used when maintaining with a switch to another server
     * configuration)
     */
    @OneToOne(cascade = CascadeType.ALL)
    private ServerBean target;

    /**
     * <ul>
     * <li>If operation is in the Step.SELECT_SERVERS step or is currently
     * maintaining, gets the number of active sessions on all applications on
     * the server.</li>
     * <li>Else (therefore, if executing maintenance) gets the number of active
     * sessions on the old version. If no old version is present, sets the
     * number of active sessions to 0.</li>
     * </ul>
     */
    @Transient
    private int activeSessions;

    /**
     * Whether the server process maintain or migration is complete.
     */
    private boolean processed;

    /**
     * Application list deployed on this server. That value is re-set every time
     * the operation state changes on the stateful bean, and not persisted.
     */
    @Transient
    private List<ApplicationBean> applications = new ArrayList<ApplicationBean>();

    /**
     * Default ServerBean constructor
     */
    public ServerBean() {
        this.activeSessions = 0;
        this.processed = false;
    }

    /**
     * Get the server id
     * 
     * @return the server id
     */
    public Integer getId() {
        return this.id;
    }

    /**
     * Set the server id
     * 
     * @param id the server id
     */
    public void setId(final Integer id) {
        this.id = id;
    }

    /**
     * Get the server name
     * 
     * @return the server name
     */
    public String getName() {
        return this.name;
    }

    /**
     * Set the server name
     * 
     * @param name the server name
     */
    public void setName(final String name) {
        this.name = name;
    }

    /**
     * Get the server capacity
     * 
     * @return the server capacity
     */
    public int getCapacity() {
        return this.capacity;
    }

    /**
     * Set the server capacity
     * 
     * @param capacity the server capacity
     */
    public void setCapacity(final int capacity) {
        if (capacity < 0) {
            throw new IllegalArgumentException("Capacity must be positive");
        }

        this.capacity = capacity;
    }

    /**
     * Get the server connector
     * 
     * @return the server connector
     */
    public ConnectorBean getServerConnector() {
        return this.serverConnector;
    }

    /**
     * Set the server connector
     * 
     * @param serverConnector the server connector
     */
    public void setServerConnector(final ConnectorBean serverConnector) {
        this.serverConnector = serverConnector;
    }

    /**
     * Get the server manager connector
     * 
     * @return the server manager connector
     */
    public ConnectorBean getManagerConnector() {
        return this.managerConnector;
    }

    /**
     * Set the server manager connector
     * 
     * @param serverConnector the server manager connector
     */
    public void setManagerConnector(final ConnectorBean managerConnector) {
        this.managerConnector = managerConnector;
    }

    /**
     * @return The number of active sessions on this server:
     *         <ul>
     *         <li>If operation is in the Step.SELECT_SERVERS step or is
     *         currently maintaining, gets the number of active sessions on all
     *         applications on the server.</li>
     *         <li>Else (therefore, if executing maintenance) gets the number of
     *         active sessions on the old version. If no old version is present,
     *         sets the number of active sessions to 0.</li>
     *         </ul>
     *         This value is re-set every time the object is refreshed on the
     *         stateful bean, and not persisted.
     */
    public int getActiveSessions() {
        return this.activeSessions;
    }

    /**
     * @param activeSessions The number of active sessions on this server:
     *        <ul>
     *        <li>If operation is in the Step.SELECT_SERVERS step or is
     *        currently maintaining, gets the number of active sessions on all
     *        applications on the server.</li>
     *        <li>Else (therefore, if executing maintenance) gets the number of
     *        active sessions on the old version. If no old version is present,
     *        sets the number of active sessions to 0.</li>
     *        </ul>
     *        This value is re-set every time the object is refreshed on the
     *        stateful bean, and not persisted.
     */
    public void setActiveSessions(final int activeSessions) {
        if (activeSessions < 0) {
            throw new IllegalArgumentException("ActiveSessions must be positive");
        }

        this.activeSessions = activeSessions;
    }

    /**
     * @return Whether the server process (maintenance or migration) is
     *         complete.
     */
    public boolean getProcessed() {
        return this.processed;
    }

    /**
     * @return the Target server (used when maintaining with a switch to another
     *         server configuration).
     */
    public ServerBean getTarget() {
        return this.target;
    }

    /**
     * @param processed Whether the server process (maintenance or migration) is
     *        complete.
     */
    public void setProcessed(final boolean processed) {
        this.processed = processed;
    }

    /**
     * @return server type
     */
    public Type getType() {
        return this.type;
    }

    /**
     * @param type server type
     */
    public void setType(final Type type) {
        this.type = type;
    }

    /**
     * @param target Target server (used when maintaining with a switch to
     *        another server configuration)
     */
    public void setTarget(final ServerBean target) {
        this.target = target;
    }

    /**
     * Get the VM this server is running on
     * 
     * @return VM the server is running on
     */
    public VMBean getVm() {
        return this.vm;
    }

    /**
     * Set the VM this server is running on
     * 
     * @param vm VM the server is running on
     */
    public void setVm(final VMBean vm) {
        this.vm = vm;
    }

    /**
     * Get the applications list for this server. That value is re-set every
     * time the operation state changes on the stateful bean, and not persisted.
     * 
     * @return The applications list for this server
     */
    public List<ApplicationBean> getApplications() {
        return this.applications;
    }

    /**
     * Set the applications list for this server. That value is re-set every
     * time the operation state changes on the stateful bean, and not persisted.
     * 
     * @param applications The applications list to set for this server
     */
    public void setApplications(final List<ApplicationBean> applications) {
        this.applications = applications;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder(this.getClass().getSimpleName());
        sb.append("[name='");
        sb.append(this.name);
        sb.append("', type='");
        sb.append(this.type);
        sb.append("', hasManager='");
        sb.append(this.managerConnector != null);
        sb.append("']");
        return sb.toString();
    }

    /**
     * {@inheritDoc}
     * 
     * @return true if <code>obj</code> is a {@link ServerBean} and the
     *         {@link ServerBean#getId()} is the same for both objects, false
     *         otherwise.
     */
    @Override
    public boolean equals(final Object obj) {
        if (obj != null && obj instanceof ServerBean) {
            ServerBean other = (ServerBean) obj;
            if (this.id != null && other.id != null) {
                return this.id.equals(other.id);
            }
        }

        // Else not same type or some parts are null
        return false;
    }
}
