package examples.ejb.basic.containerManaged;

import java.io.Serializable;
import java.util.Enumeration;
import java.util.Vector;

import javax.ejb.CreateException;
import javax.ejb.DuplicateKeyException;
import javax.ejb.EJBException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
import javax.ejb.FinderException;
import javax.ejb.NoSuchEntityException;
import javax.ejb.ObjectNotFoundException;
import javax.ejb.RemoveException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;


/**
 * AccountBean is an EntityBean. This EJBean illustrates:
 * <ul>
 * <li> Container-managed JDBC persistence and transactions; 
 *      the code in this file never directly accesses the data storage.
 * <li> Application-defined exceptions.
 * <li> The use of the WebLogic extension isModified;
 *      methods that modify a container managed field set isDirty to true.
 *      ejbStore sets isModified to false at the end of the transaction.
 * </ul>
 *
 * @author Copyright (c) 1998 by WebLogic, Inc. All Rights Reserved.
 * @author Copyright (c) 1998-2000 by BEA Systems, Inc. All Rights Reserved.
 */
public class AccountBean implements EntityBean {

  final static boolean VERBOSE = true;

  private EntityContext ctx;

  public            String        accountId; // also the primary Key
  public            double        balance;
  public            String        accountType;
  private transient boolean       isDirty;   // flag to determine whether or not the
                                             // bean needs to be written to storage.
  /**
   * Sets the EntityContext for the EJBean.
   * 
   * @param ctx               EntityContext 
   */
  public void setEntityContext(EntityContext ctx) {
    log("setEntityContext called (" + id() + ")");
    this.ctx = ctx;
  }

  /**
   * Unsets the EntityContext for the EJBean.
   * 
   */
  public void unsetEntityContext() {
    log("AccountBean.unsetEntityContext (" + id() + ")");
    this.ctx = null;
  }

  /** 
   * Returns whether the EJBean has been modified or not.
   *
   * This method must be public for the container to be able to invoke it.
   * 
   * @return                  boolean isDirty
   */
  public boolean isModified() {
    log("isModified(): isDirty = " + (isDirty ? "true" : "false"));
    return isDirty;
  }

  /**
   * Sets the EJBean's modified flag.
   * 
   * @param flag              Modified Flag
   */
  public void setModified(boolean flag) {
    isDirty = flag;
    log("setModified(): " + id() + (String) (flag ? ": requires saving" 
                         : ": saving not required"));
  }

  /**
   * Returns the Primary Key identifying this EJBean.
   * 
   * @return                  String Identification
   */
  private String id() {
    return "" + System.identityHashCode(this) + ", PK = " + 
      (String) ((ctx == null) ? "nullctx" 
                 : ((ctx.getPrimaryKey() == null ?
                   "null" : ctx.getPrimaryKey().toString()))) +
                   "; isDirty = " + isDirty;
  }

  /**
   * This method is required by the EJB Specification,
   * but is not used by this example.
   * 
   */
  public void ejbActivate() {
      log("AccountBean.ejbActivate (" + id() + ")");
  }

  /**
   * This method is required by the EJB Specification,
   * but is not used by this example.
   * 
   */
  public void ejbPassivate() {
    log("AccountBean.ejbPassivate (" + id() + ")");
  }

  /**
   * This method is required by the EJB Specification,
   * but is not used by this example.
   * 
   */
  public void ejbLoad() {
    log("AccountBean.ejbLoad (" + id() +  ")");
  }

  /**
   * Sets the EJBean's modified flag to false.
   * set to false to "reset" the variable for the next transaction.
   * 
   */
  public void ejbStore() {
    log("AccountBean.ejbStore (" + id() + ")");

    setModified(false);
  }

  /**
   * This method is required by the EJB Specification,
   * but is not used by this example.
   * 
   * @exception               javax.ejb.RemoveException
   *                          if the EJBean does not allow removing the EJBean
   */
  public void ejbRemove()
    throws RemoveException
  {
    log("AccountBean.ejbRemove (" + id() + ")");
  }

  /**
   * This method corresponds to the create method in the home interface
   * "AccountHome.java". 
   * The parameter sets of the two methods are identical.  When the client calls
   * <code>AccountHome.create()</code>, the container (which in WebLogic EJB is
   * also the home) allocates an instance of this EJBean and
   * calls <code>AccountBean.ejbCreate()</code>.
   * <p>
   * For container-managed persistence, <code>ejbCreate()</code> returns 
   * a null, unlike the case of bean-managed
   * persistence, where it returns a primary key.
   *
   * @param accountID         String Account ID
   * @param initialBalance    double Initial Balance
   * @exception               javax.ejb.CreateException
   *                          if there is a problem creating the bean
   */
  public String ejbCreate(String accountId, double initialBalance, String type) 
    throws CreateException
  {
    log("AccountBean.ejbCreate( id = " + System.identityHashCode(this) + ", PK = " +
         accountId + ", " + "initial balance = $ " + initialBalance + ")");
    this.accountId = accountId;
    this.balance   = initialBalance;
    this.accountType   = type;
    return null;  // See 9.4.2 of the EJB 1.1 specification
  }

  /**
   * This method is required by the EJB Specification,
   * but is not used by this example.
   *
   * @param accountID         String Account Identification
   * @param initialBalance    double Initial Balance 
   * @param type              String Account type
   */
  public void ejbPostCreate(String accountId, double initialBalance, String type) 
  {
    log("AccountBean.ejbPostCreate (" + id() + ")");
  }

  // Application defined methods

  /**
   * Adds amount to balance.
   *
   * @param amount            double Amount
   * @return                  double balance 
   */
  public double deposit(double amount)
  {
    log("AccountBean.deposit: Depositing $" + amount + " into '" + accountId + "'");
    balance += amount;
    setModified(true);
    return balance;
  }

  /**
   * Subtracts amount from balance.
   *
   * @param amount            double Amount
   * @return                  double Balance 
   * @exception               ProcessingErrorException
   *                          if Amount &gt; Balance
   */
  public double withdraw(double amount)
    throws ProcessingErrorException
  {
    log("AccountBean.withdraw: Withdrawing $" + amount + " from '" + accountId + "'");
    if (amount > balance) {
      throw new ProcessingErrorException("Request to withdraw $" + amount +
                                         "; is more than balance $" + balance +
                                         " in account " + accountId);
    }
    balance -= amount;
    setModified(true);
    return balance;
  }

  /**
   * Returns current balance.
   *
   * @return                  double Balance 
   */
  public double balance() {
    log("AccountBean.balance (" + id() + ")");

    return balance;
  }

  /**
   * Returns the account type.
   *
   * @return                  String account Type 
   */
  public String accountType() {
    log("AccountBean.accountType (" + id() + ")");

    return accountType;
  }

  // You might also consider using WebLogic's log service
  private void log(String s) {
    if (VERBOSE) System.out.println(s);
  } 

}
