/*                                         
 *  T H E                                     Copyright (c) The Theory Center,
 *                                            Inc. 1997-1999. All Rights Re-
 * |||||  ||                                  served. Unpublished rights re-
 *   ||   ||                                  served under the copyright laws
 *   ||   ||||    |||    |||   |||||  |  ||   of the United States. The soft-
 *   ||   ||  |  |   |  ||  |  ||  |  |  ||   ware contained on this media is
 *   ||   ||  |  |||||  ||  |  ||     |  ||   proprietary to and embodies the
 *   ||   ||  |  |      ||  |  ||      ||||   confidential technology of
 *   ||   ||  |   |||    |||   ||         |   The Theory Center. The possession
 *                                     ||||   or receipt of this information
 *                                            does not convey any right to dis-
 *  |||                   ||                  close its contents, reproduce it,
 * ||  |                  ||                  or use,  or license the use, for
 * ||      |||   ||||    ||||   |||   |||||   manufacture or sale, the informa-
 * ||     |   |  ||  |    ||   |   |  ||  |   tion or anything described
 * ||     |||||  ||  |    ||   |||||  ||      therein. Any use, disclosure, or
 * ||  |  |      ||  |    ||   |      ||      reproduction without The Theory
 *  |||    |||   ||  |    ||    |||   ||      Center's prior written permission
 *                                            is strictly prohibited.
 *
 *
 * $JustDate:  8/17/99 $ $Revision: 10 $
 */
package examples.passbyvalue;

import javax.naming.*;
import javax.ejb.*;
import java.rmi.*;
import java.util.*;

import theory.smart.axiom.units.*;
import theory.smart.axiom.util.*;
import theory.smart.axiom.messaging.*;
import theory.smart.axiom.contact.*;
import theory.smart.axiom.workflow.*;
import theory.smart.axiom.accounting.*;
import theory.smart.ebusiness.customer.*;


/** 
 *
 * Pass-by-value example. This example shows how you can get and set
 * the atributes of an Entity eBSC by value.  What this means is that
 * instead of getting/setting one attribute at a time, you can request
 * that a local copy of all attributes be sent to you directly, in one
 * remote call.  You can then read and modify this "Value object" or
 * local copy, and send it back in one remote call. This has
 * tremendous performance advantages compared to accessing one
 * attribute at a time
 *
 * It is also important to be able to set many attributes within a
 * single transaction without having to begin/commit a JTS User
 * Transaction from the client. In short, pass-by-value is really
 * handy!  Our implementation is tightly-coupled: that means that at
 * compile time, we enforce type consistency for getting/setting
 * attributes in the value objects. This is a great advantage over
 * "parameter sets", or "late-binding" implementations where you pass
 * around a set of name/value pairs: in that case, if you change the
 * type of an attribute your client will still compile but crash at
 * runtime. That wouldn't happen using eBSCs, since the value object
 * would change accordingly and the client would not compile if an
 * assigment was illegal.
 *
 * And in case you're wondering, our value objects are
 * generated by Theory Center's SmartGenerator (based on a UML model), so they don't add 
 * any maintenance costs.
 *
 * @see theory.smart.ebusiness.customer.Customer
 *
 * @author Copyright (c) 1997-1999 by The Theory Center, Inc. All Rights Reserved. 
 *  */

public class PassByValueExample
{
   Context ctx = null;	 
   String user = null;
   String password = null;
   String url = "t3://localhost:7501";
   String customerKey = "TerrySmith";
   
   public PassByValueExample() {
      super();
   }      
   
   /**
    *
    * This method adds information to a given Customer using the 
    * CustomerValue object.
    * It  updates all  attributes of the customer in a single remote and a single
    * transaction
    *
    * @param customer The customer we want to modify
    *
    */
   public void addCustomerInfo(Customer customer)
   {
      CustomerValue value = null;
      try
      {
         //
         // Get the CustomerValue object from customer
         //
            value = customer.getCustomerByValue();
      }
      catch (RemoteException e)
      {
         exitExample("Got RemoteException getting the CustomerValue", e);
      }
      
      //
      // Now, lets add some info to our customer
      // We add the data to our value object, and at the end we store it back into
      // the Customer entity bean
      //
      System.out.println("Adding personal information");
      System.out.println("----------------------------------------------------");
      value.firstName = "Terry";
      value.middleName = "P";
      value.lastName = "Smith";
      value.maritalStatus = "married";
      value.motherMaidenName = "Robinson";
      value.ssn = "123-45-6789";
      value.title = "Ph.d";
      value.password = "littleSecret";
      
      //
      // And some stuff using collections too
      // a couple credit cards
      //
      System.out.println("Adding credit cards");
      System.out.println("----------------------------------------------------");
      CreditCard myVisa = CreditCardHome.create();
      myVisa.setNumber("1234-5678-9999-0000");
      myVisa.setType("Visa");
      CreditCard myAmex = CreditCardHome.create();
      myAmex.setNumber("5555-6666-7777-8888");
      myAmex.setType("Amex");
      value.creditCards.put("visa", myVisa);
      value.creditCards.put("amex", myAmex);
      
      //
      // some email addresses
      //
      System.out.println("Adding email addresses");
      System.out.println("----------------------------------------------------");
      Email homeEmail = EmailHome.create();
      homeEmail.setAddress("me@mywiredhome.net");
      homeEmail.setDescription("my cool home network");
      Email workEmail = EmailHome.create();
      workEmail.setAddress("me@theorycenter.com");
      workEmail.setDescription("work email-business only please!");
      Email freeEmail = EmailHome.create();
      freeEmail.setAddress("me@freeEmail.com");
      freeEmail.setDescription("web email-all spam goes here");
      value.emails.put("home", homeEmail);
      value.emails.put("work", workEmail);
      value.emails.put("free", freeEmail);
      
      try
      {
         //
         // now, set the values  This will put persist the attributes 
         // in the database (within one transaction)
         //
         customer.setCustomerByValue(value);
      }
      catch (RemoteException e)
      {
         exitExample("Got RemoteException setting the CustomerValue", e);
      }
   }
   /**
    *
    * Finds or Creates a customer with the given customerKey. 
    * 
    * @param customerKey the key for the customer
    * @return the customer's entity bean
    *
    */
   public Customer findOrCreateCustomer(String customerKey)
   {
      // Try to find our customer.
      // If we don't find the customer, create a new one
            
      CustomerHome customerHome = null;
      Customer customer = null;
      
      //
      // Get the customer's home using JNDI	
      //
      try
      {
         customerHome = (CustomerHome) 
            getInitialContext().lookup("theory.smart.ebusiness.customer.Customer");
      }
      catch (Exception e)
      {
         exitExample("Could not get Customer Home", e);
      }
      
      //
      // Try to find customer using primary key. We need to use a primary key object. 
      // Since the Customer entity EJB extends the Stakeholder entity EJB, 
      // we will use a StakeholderPk primary key object
      //
      CustomerPk customerPk = new CustomerPk();
      customerPk.identifier = customerKey;
      
      
      //
      // Since we'll be messaging numerous remote methods, we need to perform our work 
      // within a try catch to catch any java.rmi.RemoteExceptions that may get thrown
      //
      System.out.println("------------------------------------------------");
      try
      {
         customer = customerHome.findByPrimaryKey(customerPk);
         System.out.println("Found customer " + customerKey);
         System.out.println("--------------------------------------------------");
      }
      catch (FinderException fe)
      {
         //
         // Ok, customer does not exist. No sweat, we'll create one.
         //
         try
         {
            customer = customerHome.create(customerPk);
            System.out.println("Did not find customer " + customerKey + 
                               ", customer has been created");
            System.out.println("----------------------------------------------");
         }
         catch (Exception e)
         {
	    exitExample("Could not create Customer " + customerKey, e);
         }
      }
      catch (RemoteException e)
      {
         exitExample("Got RemoteException while finding", e);
      }
      return customer;
   }
   
   /**
    * Gets an initial context for the current user, password and url.
    *
    * @return                  Context
    * @exception               java.lang.Exception if there is 
    *                          an error in getting the Context
    */
   public Context getInitialContext() throws Exception
   {
      if (ctx == null)
      {
         Properties p = new Properties();
         p.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
         p.put(Context.PROVIDER_URL, url);
         if (user != null)
         {
	    p.put(Context.SECURITY_PRINCIPAL, user);
	    if (password == null)
               password = "";
	    p.put(Context.SECURITY_CREDENTIALS, password);
         }
         ctx = new InitialContext(p);
      }
      return ctx;
   }
   
   /**
    * Main driver. The comman line arguments are optional, but if any are supplied,
    * they are interpreted in this order:
    * 
    * customerKey       Customer Key, default "TerrySmith"
    * url               URL such as "t3://localhost:7501" of Server
    * user              User name, default null
    * password          User password, default null
    *
    * You can also get the usage by passing -?
    */
   public static void main(String[] args)
   {
      System.out.println("----------PassByValueExample running---------");
      
      PassByValueExample example = new PassByValueExample();
      // Parse the argument list 
      if ((args != null) && (args.length > 0))
      {
         if (args[0].equals("-?"))
         {
            System.out.println("Usage: PassByValueExample <customerKey> <url> <username> <password>");
            return;
         }
         else
         {
            for (int i = 0; i < args.length; i++)
            {
               switch (i)
               {
               case 0 :
                  example.customerKey = args[i];
                  break;
               case 1 :
                  example.url = args[i];
                  break;
               case 2 :
                  example.user = args[i];
                  break;
               case 3 :
                  example.password = args[i];
                  break;
               default :
               }
            }
         }
      }
      example.run();
   }
   
   /**
    *
    * Display the message and the exception and terminate the
    * the program
    * 
    * @param message The message to display upon termination
    * @param e The exception thrown or null if no exception was thrown
    *
    */
   public void exitExample(String message, Exception e)
   {
      if (message != null)
      {
         System.out.println("Example exited: " + message);
      }
      if (e != null)
      {
         System.out.println("Exception thrown: " + e);
         e.printStackTrace(System.out);
      }
      
      System.exit(-1);
   }
   
   /**
    *
    * This method prints customer information using a value object. 
    * It shows how to read attributes, including collections
    *
    * @param customer the customer entity
    *
    */
   public void printCustomerInfo(Customer customer)
   {
      CustomerValue value = null;
      
      //
      // first, get the values object from the customer
      //
      try
      {
         value = customer.getCustomerByValue();
         System.out.println("Retrived Customer by value");
      }
      catch (RemoteException e)
      {
         exitExample("Got RemoteException getting value object", e);
      }
      
      //
      // now, we can get all the info from the values object!
      //
      System.out.println("-------------------------------------------------------");
      System.out.println("Customer " + value.firstName + " " + value.middleName + 
                         " " + value.lastName + ", " + value.title);
      System.out.println("Has SSN: " + value.ssn + " and is " + value.maritalStatus+
                         ". Mother's maiden name is: " + value.motherMaidenName);
      System.out.println(" and password is: " + value.password);
      System.out.println("-------------------------------------------------------");
      
      //
      // get the credit cards. The collection is a map, so we can get them by key
      //
      CreditCard aVisa = (CreditCard) value.creditCards.get("visa");
      CreditCard anAmex = (CreditCard) value.creditCards.get("amex");
      System.out.print("Customer " + value.firstName + " " + value.lastName);
      System.out.println(" has a creditcard: " + aVisa.getType() + " " + 
                         aVisa.getNumber());
      System.out.println(" and a creditcard: " + anAmex.getType() + " " + 
                         anAmex.getNumber());
      System.out.println("-------------------------------------------------------");
      
      //
      // get the emails. to make it more interesting, 
      // let's iterate thru the collection...its easy!
      //
      com.sun.java.util.collections.Collection c = value.emails.values();
      com.sun.java.util.collections.Iterator it = c.iterator();
      while (it.hasNext())
      {
         Email anEmail = (Email) it.next();
         System.out.println("Found an email: " + anEmail.getAddress() + 
                            " [" + anEmail.getDescription() + "]");
      }
      System.out.println("-------------------------------------------------------");
   }
   
   /**
    *
    * This method runs the example. First it creates a Customer entity. 
    * Then, it gets the value object
    * It fills out the value object with information, 
    * and updates the Customer (by value)
    * Then, it retrives and prints the info (again, by value)
    *
    */
   public void run()
   {
      //
      // create (or find) our customer
      //
      System.out.println("\n -------> looking for customer");
      Customer customer = findOrCreateCustomer(customerKey);
      
      //
      // add attributes using the CustomerValues object (pass-by-value)
      //
      System.out.println("\n -------> setting attributes by value");
      addCustomerInfo(customer);
      
      //
      // now, retrive customer attributes using the CustomerValues 
      // object (pass-by-value)
      //
      System.out.println("\n -------> retrieving info");
      printCustomerInfo(customer);
      System.out.println("\n -------> Example exits normally");
   }
}
