/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2011 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.resource.internal.mbean;

// JOnAS imports
import java.util.Map;
import java.util.Properties;

import org.ow2.jonas.lib.management.javaee.J2EEManagedObject;
import org.ow2.jonas.resource.internal.cm.ConnectionManagerImpl;
import org.ow2.jonas.resource.internal.pool.Pool;


/**
 * MBean class for JCA Connection Factory Management
 *
 * @author Adriana Danes JSR 77 (J2EE Management Standard)
 *
 */
public class JCAConnectionFactory extends J2EEManagedObject {

    // JSR 77
    /**
     * Associated ManagedConnectionFactory
     */
    private String managedConnectionFactory = null;

    // JOnAS Specific
    /**
     * Description
     */
    private String description = null;
    /**
     * Jndi name
     */
    private String jndiname = null;
    /**
     * Properties associated with the ConnectionFactory
     */
    private Properties prop = null;

    /**
     * Associated connection manager
     */
    private ConnectionManagerImpl cm = null;

    /**
     * Pool associated to the connection manager
     */
    private Pool pool = null;

    private String fileName = null;
    /**
     * Value used as sequence number by reconfiguration notifications
     */
    private long sequenceNumber = 0;

    /**
     * Constructor
     * @param objectName String of object name
     * @param jndiname   String of ConnectionFactory
     * @param prop       Properties of the ConnectionFactory
     * @param description  String of ConnectionFactory description
     */
    public JCAConnectionFactory(final String objectName, final String jndiname, final String fileName, final Properties prop,
                                final String description, final ConnectionManagerImpl cm) {
        super(objectName);
        this.jndiname =  jndiname;
        this.prop = prop;
        this.description = description;
        this.cm = cm;
        this.pool = cm.getPool();
        this.fileName = fileName;
    }

    /**
     * return the description
     * @return String description
     */
    public String getDescription() {
        return description;
    }

    /**
     * return the jndi name
     * @return String jndi name
     */
    public String getJndiName() {
        return jndiname;
    }

    /**
     * Return the ManagedConnectionFactory object name
     * @return String of ManagedConnectionFactory name
     */
    public String getManagedConnectionFactory() {
        return managedConnectionFactory;
    }

    /**
     * return the ConnectionFactory Properties
     * @return Properties ConnectionFactory properties
     */
    public Properties getProperties() {
        return prop;
    }

    /**
     * Set the ManagedConnectionFactory object name
     *
     * @param managedConnectionFactoryObjectName String to set
     */
    public void setManagedConnectionFactory(final String managedConnectionFactoryObjectName) {
        managedConnectionFactory = managedConnectionFactoryObjectName;
    }

    // JDBC Connection Pool Configuration
    // -----------------------------------
    /**
     * @return true if there is a JDBC connection to manage
     */
    public boolean isJdbcConnSetUp() {
        return cm.isJdbcConnSetUp();
    }

    /**
     * @return JDBC connection checking level
     */
    public Integer getJdbcConnCheckLevel() {
        return new Integer(cm.getCheckLevel());
    }
    /**
     * Sets the JDBC connection checking level
     * @param level connection level
     */
    public void setJdbcConnCheckLevel(final Integer level) {
        cm.setCheckLevel(level.intValue());
    }

    /**
     * @return SQL query for JDBC connections test
     */
    public String getJdbcTestStatement() {
        return cm.getTestStatement();
    }
    /**
     * @param test SQL query for JDBC connections test
     */
    public void setJdbcTestStatement(final String test) {
        cm.setTestStatement(test);
    }

    /**
     * @return Returns the PrepareStatement cache max size
     */
    public Integer getPstmtMax() {
        return new Integer(cm.getMaxPstmtPoolSize());
    }

    /**
     *
     * @param size the PrepareStatement cache max size
     */
    public void setPstmtMax(final Integer size) {
        cm.setMaxPstmtPoolSize(size.intValue());
    }

    /**
     * @return Returns the PrepareStatement cache policy
     */
    public String getPstmtCachePolicy() {
        return cm.getPstmtCachePolicy();
    }

    /**
     *
     * @param size the PrepareStatement cache max size
     */
    public void setPstmtCachePolicy(final String value) {
        cm.setPstmtCachePolicy(value);
    }
    // -----------------------------------
    /**
     * @return Connections maximum age
     */
    public Integer getConnMaxAge() {
        return new Integer(pool.getMaxAge());
    }
    /**
     * @param mn Connections maximum age
     */
    public void setConnMaxAge(final Integer mn) {
        pool.setMaxAge(mn.intValue());
    }

    /**
     * @return max maximum size of connection pool
     */
    public Integer getMaxSize() {
        return new Integer(pool.getMaxSize());
    }
    /**
     * @param max maximum size of connection pool
     */
    public void setMaxSize(final Integer max) {
        try {
          pool.setMaxSize(max.intValue());
        } catch(Exception ex) { }
    }

    /**
     * @return maximum opening time of connections
     */
    public Integer getMaxOpentime() {
        return new Integer(pool.getMaxOpentime());
    }
    /**
     * @param mn maximum opening time in minutes for connections
     */
    public void setMaxOpentime(final Integer mn) {
        pool.setMaxOpentime(mn.intValue());
    }

    /**
     * @return maximum nb of waiters allowed
     */
    public Integer getMaxWaiters() {
        return new Integer(pool.getMaxWaiters());
    }
    /**
     * @param max maximum nb of waiters allowed
     */
    public void setMaxWaiters(final Integer max) {
        pool.setMaxWaiters(max.intValue());
    }

    /**
     * @return maximum time to wait for a connection, in seconds
     */
    public Integer getMaxWaitTime() {
        return new Integer(pool.getMaxWaitTime());
    }

    /**
     * @param max maximum time to wait for a connection, in seconds
     */
    public void setMaxWaitTime(final Integer max) {
        pool.setMaxWaitTime(max.intValue());
    }

    /**
     * @return minimum size of connection pool
     */
    public Integer getMinSize() {
        return new Integer(pool.getMinSize());
    }

    /**
     * @return initial size of connection pool
     */
    public Integer getInitSize() {
        return new Integer(pool.getInitSize());
    }
    /**
     * MBean method allowing to set the minimum size of connection pool
     * @param min minimum size of connection pool
     */
    public void setMinSize(final Integer min) {
        try {
            pool.setMinSize(min.intValue());
        } catch (Exception ex) { }
    }

    /**
     * @return sampling period for refresching pool statistics
     */
    public Integer getSamplingPeriod() {
        return new Integer(pool.getSamplingPeriod());
    }

    /**
     * @param i sampling period for refresching pool statistics
     */
    public void setSamplingPeriod(final Integer i) {
        pool.setSamplingPeriod(i.intValue());
    }

    // JDBC Connection Pool Statistics

    /**
     * @return number of connection failures
     */
    public Integer getConnectionFailures() {
        return new Integer(pool.getConnectionFailures());
    }
    /**
     * @return number of connection leaks
     */
    public Integer getConnectionLeaks() {
        return new Integer(pool.getConnectionLeaks());
    }
    /**
     * @return number of busy connections
     */
    public Integer getCurrentBusy() {
        return new Integer(pool.getCurrentBusy());
    }
    /**
     * @return number of busy connections
     */
    public Integer getBusyMax() {
        return new Integer(pool.getBusyMaxRecent());
    }
    /**
     * @return number of busy connections
     */
    public Integer getBusyMin() {
        return new Integer(pool.getBusyMinRecent());
    }
    /**
     * @return number of connections used in transactions
     */
    public Integer getCurrentInTx() {
        return new Integer(cm.getCurrentInTx());
    }
    /**
     * @return number of opened connections
     */
    public Integer getCurrentOpened() {
        return new Integer(pool.getCurrentOpened());
    }
    /**
     * @return current number of connection waiters
     */
    public Integer getCurrentWaiters() {
        return new Integer(pool.getCurrentWaiters());
    }
    /**
     * @return number of opened physical JDBC connections
     */
    public Integer getOpenedCount() {
        return new Integer(pool.getOpenedCount());
    }
    /**
     * @return number of open calls that were rejected because too many waiters
     */
    public Integer getRejectedFull() {
        return new Integer(pool.getRejectedFull());
    }
    /**
     * @return total number of open calls that were rejected
     */
    public Integer getRejectedOpen() {
        return new Integer(pool.getRejectedOpen());
    }
    /**
     * @return number of open calls that were rejected by an unknown reason
     */
    public Integer getRejectedOther() {
        return new Integer(pool.getRejectedOther());
    }
    /**
     * @return number of open calls that were rejected by timeout
     */
    public Integer getRejectedTimeout() {
        return new Integer(pool.getRejectedTimeout());
    }
    /**
     * @return number of xa connection served
     */
    public Integer getServedOpen() {
        return new Integer(pool.getServedOpen());
    }
    /**
     * @return total number of waiters since datasource creation.
     */
    public Integer getWaiterCount() {
        return new Integer(pool.getWaiterCount());
    }
    /**
     * @return Maximum number of waiters since datasource creation.
     */
    public Integer getWaitersHigh() {
        return new Integer(pool.getWaitersHigh());
    }
    /**
     * @return Maximum nb of waiters in last sampling period
     */
    public Integer getWaitersHighRecent() {
        return new Integer(pool.getWaitersHighRecent());
    }
    /**
     * @return Maximum waiting time (millisec) since datasource creation.
     */
    public Long getWaitingHigh() {
        return new Long(pool.getWaitingHigh());
    }
    /**
     * @return Maximum waiting time (millisec) in last sampling period
     */
    public Long getWaitingHighRecent() {
        return new Long(pool.getWaitingHighRecent());
    }
    /**
     * @return Total waiting time (millisec) since datasource creation.
     */
    public Long getWaitingTime() {
        return new Long(pool.getWaitingTime());
    }

    public int[] getOpenedConnections(final int seconds) {
        return cm.getOpenedConnections(seconds);
    }

    public int[] getOpenedConnections() {
        return cm.getOpenedConnections();
    }

    public Map getConnectionDetails(final int connectionId) {
        return cm.getConnectionDetails(connectionId);
    }

    public void forceCloseConnection(final int connectionId) {
        cm.forceCloseConnection(connectionId);
    }

    public void setObservable(final boolean observable) {
        cm.setObservable(observable);
    }

    public boolean isObservable() {
        return cm.isObservable();
    }

    /**
     * Gets the sequence number for reconfiguration opeartions
     * @return the sequence number for reconfiguration operations
     */
    protected long getSequenceNumber() {
        return ++sequenceNumber;
    }

    /**
     * @return Returns the fileName.
     */
    public String getFileName() {
        return fileName;
    }

    /**
     * @return Cache policy used to manage the prepared statement in memory.
     *
     */
    public String getPrepStmtCachePolicy() {
        return cm.getPstmtCachePolicy();
    }

    /**
     * @return Count of the number of times that the statement cache was accessed.
     *
     */
    public long getPrepStmtCacheAccessCount() {
        return cm.getPstmtStats().getPrepStmtCacheAccessCount();
    }

    /**
     * @return Count of the number of statements added to the statement cache.
     *
     */
    public long getPrepStmtCacheAddCount() {
        return cm.getPstmtStats().getPrepStmtCacheAddCount();
    }


    /**
     * @return Number of prepared statements currently cached in the statement cache.
     *
     */
    public long getPrepStmtCacheCurrentSize() {
        return cm.getPstmtStats().getPrepStmtCacheCurrentSize();
    }

    /**
     * @return Cumulative count of statements discarded from the cache.
     *
     */
    public long getPrepStmtCacheDeleteCount() {
        return cm.getPstmtStats().getPrepStmtCacheDeleteCount();
    }

    /**
     * @return Cumulative count of the number of times that statements from the cache were used.
     *
     */
    public long getPrepStmtCacheHitCount() {
        return cm.getPstmtStats().getPrepStmtCacheHitCount();
    }

    /**
     * @return  Number of times that a statement request could not be satisfied with a statement from the cache.
     *
     */
    public long getPrepStmtCacheMissCount() {
        return cm.getPstmtStats().getPrepStmtCacheMissCount();
    }
}
