package com.oreilly.jent.ejb.containerManaged;

/**
 * In general, you may use the code in this book in your programs and 
 * documentation. You do not need to contact us for permission unless 
 * you're reproducing a significant portion of the code. For example, 
 * writing a program that uses several chunks of code from this book does 
 * not require permission. Selling or distributing a CD-ROM of examples 
 * from O'Reilly books does require permission. Answering a question by 
 * citing this book and quoting example code does not require permission. 
 * Incorporating a significant amount of example code from this book into 
 * your product's documentation does require permission.
 * 
 * We appreciate, but do not require, attribution. An attribution usually 
 * includes the title, author, publisher, and ISBN. For example: 
 * 
 *   "Java Enterprise in a Nutshell, Third Edition, 
 *    by Jim Farley and William Crawford 
 *    with Prakash Malani, John G. Norman, and Justin Gehtland. 
 *    Copyright 2006 O'Reilly Media, Inc., 0-596-10142-2."
 *  
 *  If you feel your use of code examples falls outside fair use or the 
 *  permission given above, feel free to contact us at 
 *  permissions@oreilly.com.
 */

import java.rmi.RemoteException;

import javax.ejb.CreateException;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;
import javax.ejb.FinderException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.oreilly.jent.ejb.NoSuchPersonException;
import com.oreilly.jent.ejb.Profile;

// A PersonBean, which represents a person stored in our database.
abstract public class PersonBean implements EntityBean {
  //--------------------------------------------------
  // Persistent data properties
  //--------------------------------------------------

  // Name (primary key) of person (read-only)
  abstract public String getName();
  abstract public void setName(String name);
  
  // Container-managed accessors, not exposed through remote interface
  // First name of person
  abstract public String getFirstNameLocal();
  abstract public void setFirstNameLocal(String fname);
  // Remotely-accessible accessors
  public String getFirstName() { return getFirstNameLocal(); }
  public void setFirstName(String fname) { setFirstNameLocal(fname); }
  
  // Container-managed accessors, not exposed through remote interface
  // Last name of person
  abstract public String getLastNameLocal();
  abstract public void setLastNameLocal(String lname);
  // Remotely-accessible accessors
  public String getLastName() { return getLastNameLocal(); }
  public void setLastName(String lname) { setLastNameLocal(lname); }

  // Store context
  public EntityContext mContext = null;

  // Public empty constructor, to be used by the EJB container.
  public PersonBean() {}
  
  //--------------------------------------------------
  // Entity bean methods
  //--------------------------------------------------

  // No action required on activation of this bean.
  public void ejbActivate() {
    System.out.println("ProfileBean activated.");
  }

  // Load bean from persistent store.  In this case, there is no action needed
  // after container performs the database load for us.
  public void ejbLoad() throws RemoteException {}

  // Store bean to persistent store.  In this case, there is no action needed
  // before the container performs the database store for us.
  public void ejbStore() throws RemoteException {}
  
  // Remove the bean from persistent storage.  No action needed here before the
  // container does the removal for us.
  public void ejbRemove() {}

  // Pre-passivation callback.  No action needed here.
  public void ejbPassivate() {}

  // Get our context from the container.
  public void setEntityContext(EntityContext context) {
    mContext = context;
  }

  // Container is removing our context.
  public void unsetEntityContext() throws RemoteException {
    mContext = null;
  }

  // Create method (corresponds to the create() method on the
  // home interface).  Nothing to initialize in this case.
  public String ejbCreate() throws CreateException {
    System.out.println("Nameless PersonBean created.");
    setName(" ");
    setFirstName(" ");
    setLastName(" ");
    return null;
  }

  // Post-creation notification.  Nothing to do here, but we need
  // to provide an implementation.
  public void ejbPostCreate() {
    System.out.println("PersonBean post-create called.");
  }
   
  // Create method with name of person.
  public String ejbCreate(String name, String fname, String lname) 
    throws CreateException, NoSuchPersonException {
    setName(name);
    setFirstName(fname);
    setLastName(lname);
    return null;
  }

  // Post-creation notification.  Nothing to do here, what we need
  // to provide an implementation.
  public void ejbPostCreate(String name, String fname, String lname) {}
   
  //--------------------------------------------------
  // Business methods
  //--------------------------------------------------

  // Get/set local Profile using CMP relationships
  public abstract ProfileLocal getProfileLocal();
  public abstract void setProfileLocal(ProfileLocal profile);

  //Lookup the profile for this person and return it.  In this case, our
  // profile is an entity EJB, so we do a find on its home for our named
  // profile.  If no profile is found, or if an error of some kind occurs,
  // a null profile is returned.

  // Get remote Profile using remote home for ProfileBean
  public Profile getProfile() throws RemoteException {
    Profile myProfile = null;
    try {
      // Get profile home interface
      Context ctx = new InitialContext();
      ProfileHome pHome = (ProfileHome)ctx.lookup("ejb/CMP20-ProfileHome");
      // Do a find based on our name (first name concatenated with last name)
      try {
        myProfile = pHome.findByPrimaryKey(getFirstName() + " " + getLastName());
      }
      catch (FinderException fe) {
        System.out.println("Error occurred looking up profile for " +
                           getFirstName() + " " + getLastName());
	    // Try creating a new profile
        myProfile = pHome.create(getFirstName() + " " + getLastName());
      }
    }
    catch (NamingException ne) {
      System.out.println("Error occurred looking up profile home.");
      throw new RemoteException("Error looking up profile home", ne);
    }
    catch (CreateException ce) {
      System.out.println("Could neither find nor create a profile for "
			 + getFirstName() + getLastName());
      throw new RemoteException("Error accessing profile", ce);
    }
    catch (NoSuchPersonException nspe) {
      System.out.println("Could neither find nor create a profile for "
			 + getFirstName() + getLastName());
      throw new RemoteException("Error accessing profile", nspe);
    }
      
    return myProfile;
  }
}
