/*
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999 Bull S.A.
 * Contact: jonas-team@objectweb.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.objectweb.jonas.jtests.beans.beanexc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.Vector;

import javax.ejb.EntityBean;
import javax.ejb.FinderException;
import javax.ejb.ObjectNotFoundException;
import javax.ejb.RemoveException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

import org.objectweb.util.monolog.api.BasicLevel;


/**
 * This is an entity bean with "bean managed persistence".
 * The state of an instance is stored into a relational database.
 * The table must exist.
 * @author Philippe Durieux, Philippe Coq
 */
public class AccountEB extends AccountEC implements EntityBean {

    static final String tableName = "beanexcAccountEB";

    // Database related information
    private DataSource dataSource = null;
    private static String dataSourceName;


    public void ejbLoad() {
        logger.log(BasicLevel.DEBUG, "");
        AccountPK pk = (AccountPK) entityContext.getPrimaryKey();
        PreparedStatement loadPstmt = null;
        Connection        conn      = null;
        try {
            conn = getConnection();
            loadPstmt = conn.prepareStatement("select c_number, c_customer, c_balance  from " + tableName + " where c_number=?");

            // PK fields
            loadPstmt.setInt(1, pk.number);
            ResultSet rs = loadPstmt.executeQuery();
            if (!rs.next()) {
                System.err.println("Fails to load bean from database");
                throw new javax.ejb.EJBException("Failed to load bean from database");
            }
            number    = rs.getInt("c_number");
            customer = rs.getString("c_customer");
            balance  = rs.getLong("c_balance");
        } catch (SQLException e) {
            System.err.println("Fails to load bean from database");
            throw new javax.ejb.EJBException("Failed to load bean from database" + e);
        } finally {
            try {
                loadPstmt.close();
                conn.close();
            } catch (Exception e) {
                System.err.println("ejbLoad: Ignore exception:" + e);
            }
        }

    }

    public void ejbStore() {
        AccountPK pk = (AccountPK) entityContext.getPrimaryKey();
        logger.log(BasicLevel.DEBUG, "pk=" + pk.number);
        PreparedStatement storePstmt = null;
        Connection conn = null;
        if (forceToFailEjbStore) {
            forceToFailEjbStore = false;
            throw new javax.ejb.EJBException("Failed to store bean to database");
        }

        try {
            conn = getConnection();
            storePstmt = conn.prepareStatement("update " + tableName + " set c_customer=?,c_balance=? where c_number=?");

            // non PK fields
            if (customer == null) {
                storePstmt.setNull(1, java.sql.Types.VARCHAR);
            } else {
                storePstmt.setString(1, customer);
            }
            storePstmt.setLong(2, balance);
            // PK fields
            storePstmt.setInt(3, number);
            storePstmt.executeUpdate();
        } catch (SQLException e) {
            throw new javax.ejb.EJBException("Failed to store bean to database");
        } finally {
            try {
                storePstmt.close();
                conn.close();
            } catch (Exception e) {
                System.err.println("ejbStore: Ignore exception:" + e);
            }
        }
    }

    public void ejbRemove()  throws RemoveException {
        logger.log(BasicLevel.DEBUG, "");

        // A RemoveException may be throwned depending on the PK value
        super.ejbRemove();

        AccountPK pk = (AccountPK) entityContext.getPrimaryKey();
        PreparedStatement removePstmt = null;
        Connection        conn        = null;
        try {
            conn = getConnection();
            removePstmt = conn.prepareStatement("delete from " + tableName + " where c_number=?");
            // PK fields
            removePstmt.setInt(1, pk.number);
            removePstmt.executeUpdate();
        } catch (SQLException e) {
            throw new javax.ejb.EJBException("Failed to delete bean from database");
        } finally {
            try {
                removePstmt.close();
                conn.close();
            } catch (Exception e) {
                System.err.println("ejbRemove: Ignore exception:" + e);
            }
        }
    }


    public AccountPK ejbCreate(int val_number, String val_customer, long val_balance) throws javax.ejb.CreateException {
        logger.log(BasicLevel.DEBUG, "");

        super.ejbCreate(val_number, val_customer, val_balance);

        PreparedStatement createPstmt = null;
        Connection        conn        = null;
        AccountPK pk = new AccountPK(val_number);

        // persistence management
        try {
            conn = getConnection();
            createPstmt = conn.prepareStatement("insert into " + tableName + " values (?, ?, ?)");
            // all fields
            createPstmt.setInt(1, pk.number);
            if (customer == null) {
                createPstmt.setNull(2, java.sql.Types.VARCHAR);
            } else {
                createPstmt.setString(2, customer);
            }
            createPstmt.setLong(3, balance);
            createPstmt.executeUpdate();
        } catch (SQLException e) {
            throw new javax.ejb.EJBException("Failed to create bean in database" + e);
        } finally {
            try {
                createPstmt.close();
                conn.close();
            } catch (Exception e) {
                logger.log(BasicLevel.ERROR, "ejbCreate: Ignore exception:" + e);
            }
        }
        return pk;
    }

    /**
     * creer une instance bidon le flag sert pour savoir quelle exception lever
     */
    public AccountPK ejbCreate(int flag) throws javax.ejb.CreateException,  AppException  {
        logger.log(BasicLevel.DEBUG, "");
        AccountPK pk = super.ejbCreate(flag);
        return pk;
    }

    public AccountPK ejbCreate(boolean flag) throws javax.ejb.CreateException, AppException {
        logger.log(BasicLevel.DEBUG, "");
        AccountPK pk = super.ejbCreate(flag);
        return pk;
    }

    public void ejbPostCreate(int val_number, String val_customer, long val_balance) {
        logger.log(BasicLevel.DEBUG, "");
    }

    public AccountPK ejbFindByPrimaryKey(AccountPK pk) throws ObjectNotFoundException, FinderException {
        logger.log(BasicLevel.DEBUG, "");
        PreparedStatement loadPstmt = null;
        Connection        conn      = null;
        try {
            conn      = getConnection();
            loadPstmt = conn.prepareStatement("select c_customer, c_balance from " + tableName + " where c_number=?");
            loadPstmt.setInt(1, pk.number);
            ResultSet rs = loadPstmt.executeQuery();
            if (!rs.next()) {
                throw new javax.ejb.ObjectNotFoundException("primary key");
            }
        } catch (SQLException e) {
            System.err.println("Fails to executeQuery " + e);
            throw new javax.ejb.FinderException("Failed to executeQuery " + e);
        } finally {
            try {
                loadPstmt.close();
                conn.close();
            } catch (Exception e) {
                logger.log(BasicLevel.ERROR, "ejbFindByPrimaryKey: Ignore exception:" + e);
            }
        }
        return pk;
    }

    public AccountPK ejbFindByNoAccount(int number) 
        throws ObjectNotFoundException, FinderException {
        logger.log(BasicLevel.DEBUG, "");
        PreparedStatement loadPstmt = null;
        Connection conn = null;
        AccountPK pk = new AccountPK(number);
        try {
            conn = getConnection();
            loadPstmt = conn.prepareStatement("select c_customer,c_balance from " + tableName + " where c_number=?");
            loadPstmt.setInt(1, pk.number);
            ResultSet rs = loadPstmt.executeQuery();
            if (!rs.next()) {
                logger.log(BasicLevel.ERROR, "Object Not Found primary key : " + pk.number);
                throw new javax.ejb.ObjectNotFoundException("primary key : " + pk.number);
            }
        } catch (SQLException e) {
            System.err.println("Fails to executeQuery " + e);
            throw new javax.ejb.FinderException("Failed to executeQuery " + e);
        } finally {
            try {
                loadPstmt.close();
                conn.close();
            } catch (Exception e) {
                logger.log(BasicLevel.ERROR, "ejbFindByNoAccount: Ignore exception:" + e);
            }
        }
        return pk;
    }

    public Enumeration ejbFindCustomerAccounts(String name) throws FinderException {
        logger.log(BasicLevel.DEBUG, "");
        PreparedStatement loadPstmt = null;
        Connection conn = null;
        Vector pkV = new Vector();
        try {
            conn = getConnection();
            loadPstmt = conn.prepareStatement("select c_number from " + tableName + " where c_customer=?");
            loadPstmt.setString(1, name);
            ResultSet rs = loadPstmt.executeQuery();
            while (rs.next()) {
                int b = rs.getInt("c_number");
                AccountPK pk = new AccountPK(b);
                pkV.addElement((Object) pk);
            }

        } catch (SQLException e) {
            System.err.println("Fails to executeQuery " + e);
            throw new javax.ejb.FinderException("Failed to executeQuery " + e);
        } finally {
            try {
                loadPstmt.close();
                conn.close();
            } catch (Exception e) {
                logger.log(BasicLevel.ERROR, "ejbFindCustomerAccounts: Ignore exception:" + e);
            }
        }
        return (pkV.elements());
    }

    public Enumeration ejbFindBigAccounts(long minBalance) throws FinderException {
        logger.log(BasicLevel.DEBUG, "");
        PreparedStatement loadPstmt = null;
        Connection conn = null;
        Vector pkV = new Vector();
        try {
            conn = getConnection();
            loadPstmt = conn.prepareStatement("select c_number from " + tableName + " where c_balance>?");
            loadPstmt.setLong(1, minBalance);
            ResultSet rs = loadPstmt.executeQuery();
            while (rs.next()) {
                int b = rs.getInt("c_number");
                AccountPK pk = new AccountPK(b);
                pkV.addElement((Object) pk);
            }
        } catch (SQLException e) {
            System.err.println("Fails to executeQuery " + e);
            throw new javax.ejb.FinderException("Failed to executeQuery " + e);
        } finally {
            try {
                loadPstmt.close();
                conn.close();
            } catch (Exception e) {
                logger.log(BasicLevel.ERROR, "ejbFindBigAccounts: Ignore exception:" + e);
            }
        }
        return (pkV.elements());
    }

    public Enumeration ejbFindAllAccounts() throws FinderException {
        logger.log(BasicLevel.DEBUG, "");
        PreparedStatement loadPstmt = null;
        Connection conn = null;
        Vector pkV = new Vector();
        try {
            conn = getConnection();
            loadPstmt = conn.prepareStatement("select c_number from " + tableName);
            ResultSet rs = loadPstmt.executeQuery();
            while (rs.next()) {
                int b = rs.getInt("c_number");
                AccountPK pk = new AccountPK(b);
                pkV.addElement((Object) pk);
            }
        } catch (SQLException e) {
            System.err.println("Fails to executeQuery " + e);
            throw new javax.ejb.FinderException("Failed to executeQuery " + e);
        } finally {
            try {
                loadPstmt.close();
                conn.close();
            } catch (Exception e) {
                logger.log(BasicLevel.ERROR, "ejbFindAllAccounts: Ignore exception:" + e);
            }
        }
        return (pkV.elements());
    }

    private Connection getConnection() throws java.sql.SQLException {
        logger.log(BasicLevel.DEBUG, "");
        if (dataSource == null) {
            // Finds DataSource from JNDI
            Context    initialContext = null;
            try {
                initialContext = new InitialContext();
                dataSource = (DataSource) initialContext.lookup("java:comp/env/jdbc/AccountEB");
            } catch (Exception e) {
                logger.log(BasicLevel.ERROR, "Pb with naming context");
                throw new javax.ejb.EJBException("Pb with naming context ");
            }
        }
        Connection ret = dataSource.getConnection();
        if (ret == null) {
            throw new javax.ejb.EJBException("dataSource.getConnection() returned null");
        }
        return ret;
    }
}
