/*                                         
 *  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: 19 $
 */

package examples.axiom;

import java.util.Properties;
import com.sun.java.util.collections.*;
import java.rmi.*;
import javax.ejb.*;
import javax.naming.*;


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.foundation.*;
import theory.smart.ebusiness.customer.*;

/**
 * 
 * Shows how to use Theory Center's Axiom package of eBusiness Smart Components.
 * 
 * This example illustrates how to use the different types of 
 * Axiom eBusiness Smart Components, including Belongings and 
 * Entities. You can also see how to use the abstract factory 
 * pattern and the Collections API<br>
 *
 * The Axiom package contains light weight components known
 * as belongings, as well as Entity and Session EJB
 * components. Belongings can be aggregated to other components by
 * value. EJBs are used alone or aggregated to other components by
 * reference or value.<br>
 * 
 * Belongings are local. Whether client or server-side, the Belonging is
 * local. They are always passed by value. Although not EJBs, belongings 
 * still are eBusiness Smart Components  and use the abstract factory 
 * pattern: you don't use <code>new()</code> to create one, instead, you 
 * use <code>Home.create()</code>.
 *
 * This example also shows the use of Remote Iterators, one of
 * Theory Center's collection APIs. You can iterate through a collection both
 * locally and remotely. Locally, the whole collection is sent to you
 * from the server and you can traverse it. This is good for small
 * collections where you need to iterate a lot.  For large
 * collections, you can use one or more remote iterators.  Remote
 * iterators traverse the collection in the server. That way, you only
 * bring over the net the values that you need saving bandwidth. They
 * also serve as "bookmarks" on a collection, since they "remember" in
 * what position you leave them.
 *
 * @see theory.smart.foundation.Belonging
 * @see theory.smart.foundation.RemoteIterator
 * @see theory.smart.axiom.contact.Email
 * @see theory.smart.axiom.contact.CreditCard
 * @see theory.smart.ebusiness.customer.Customer
 *
 * @author Copyright (c) 1997-1999 by The Theory Center, Inc. All Rights Reserved.
 * */
public class AxiomExample
{
   Context ctx = null;	 
   String user = null;
   String password = null;
   String url = "t3://localhost:7501";
   String customerKey = "TerrySmith";
   
   /**
    * The default constructor for the AxiomExample class
    */
   public AxiomExample() {
      super();
   }
   
   
   /**
    * Demonstrates the creation and use of Belongings
    * 
    * Demonstrates the use of the abstract factory pattern to
    * create belongings. The newly created belongings are then aggreagated
    * to an entity bean by value using the collection APIs.<br>
    *
    * In this method, we have a customer entity bean in our hands.
    * Let's add belongings. Belongings are Theory Center's lightweight components. 
    * They need to be "owned" by someone, and they only make sense within 
    * the context of their owner (e.g. Email is owned by a customer).
    * 
    * @param customer
    *
    */
   public void addBelongings(Customer customer)
   {
      
      // Create a credit card
         CreditCard myVisa = CreditCardHome.create();
      myVisa.setNumber("1234-5678-9999-0000");
      myVisa.setType("Visa");
      
      // Create some email addresses
         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");
      
      //
      // Now we are ready to add  belongings to our customer. 
      // If you look that the Customer API, you'll notice that 
      // it has "collections" of belongings. This collections 
      // have a rich API that we can use...
      //
      try
      {
         //
         // Add belogings
         //
         customer.putCreditCard("visa", myVisa);
         customer.putEmail("home", homeEmail);
         customer.putEmail("work", workEmail);
         customer.putEmail("free", freeEmail);
      }
      catch (RemoteException e)
      {
         exitExample("Got RemoteException adding belongings", e);
      }
      
      //
      // Now, get the belongings and print them.
      //
      try
      {
         //
         // Get the credit card
         //
         CreditCard aCreditCard = customer.getCreditCardByKey("visa");
         System.out.print("Customer " + customer.getFirstName() + " " + customer.getLastName());
         System.out.println(" has a creditcard: " + aCreditCard.getType() + " " + aCreditCard.getNumber());
         System.out.println("--------------------------------------------------------------");
         
         //
         // To make things interesting, lets use a collection API to get the emails.
         // You can iterate through a collection locally.
         // Locally, the whole collection is sent to you from the server and you can 
         // itereate through it. This is good for small collections where you need to 
         // iterate a lot.
	 // 
	 Collection collEmail = customer.getEmails().values();
	 Iterator it = collEmail.iterator();
	 while (it.hasNext()) {
	     Email anEmail =(Email)it.next();
	     System.out.println("Found an email: " + anEmail.getAddress() + " [" + anEmail.getDescription() + "]");
	 }
         System.out.println("--------------------------------------------------------------");

         // You can also find an email by key, like so:
         Email emailByKey = customer.getEmailByKey("work");
         System.out.println(customer.getIdentifier() + "'s work email is " + emailByKey.getAddress());
         System.out.println("--------------------------------------------------------------");
      }
      catch (RemoteException e)
      {
         exitExample("Got RemoteException getting belongings", e);
      }
   }
   
   /**
    * Shows how to remove belongings from a larger component.
    *
    * It also shows how to obtain information about belonging collections
    * from a larger component.
    *
    * @param customer The customer that has the belongings
    *
    */
   public void removeBelongings(Customer customer)
   {
      //
      // Lets remove all emails and creditcards using the API
      //
      try
      {
         //
         // remove CreditCards
         //
         System.out.println("Customer " + customer.getIdentifier() + " has " + customer.getNumberOfCreditCards() + " creditcard before removing");
         System.out.println("--------------------------------------------------------------");
         customer.removeAllCreditCards();
         System.out.println("After removing, " + customer.getIdentifier() + " has " + customer.getNumberOfCreditCards() + " creditcards");
         System.out.println("--------------------------------------------------------------");
         
         //
         // remove Emails
         //
         System.out.println("Customer " + customer.getIdentifier() + " has " + customer.getNumberOfEmails() + " emails before removing");
         System.out.println("--------------------------------------------------------------");
         customer.removeAllEmails();
         System.out.println("After removing, " + customer.getIdentifier() + " has " + customer.getNumberOfEmails() + " emails");
         System.out.println("--------------------------------------------------------------");
      }
      catch (RemoteException e)
      {
         exitExample("Got RemoteException removing belongings", 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;
   }
   
   /**
    *
    * Controls the examples sequence.
    *
    * <ol>
    * <li> Finds (or creates) a customer.
    * <li> Adds belongings to this customer.
    * <li> It removes the belogings.
    * </ol>
    *
    * The customer object is not removed (so we can find it next time)
    *
    */
   public void run()
   {
      Customer customer = null;
      
      // find (or create) our customer
      customer = findOrCreateCustomer(customerKey);
      
      // Lets give our customer a name, shall we?
      try
      {
         customer.setFirstName("Terry");
         customer.setLastName("Smith");
      }
      catch (Exception e)
      {
         exitExample("Could not set customer's name", e);
      }
      
      // now that we have a customer, let's add some belongings to it.
      addBelongings(customer);
      
      // and now, remove the belongings...
      removeBelongings(customer);
      
      System.out.println("Example exits normally");
   }
   
   
   /**
    * Gets an initial context for the current user, password and url.
    *
    * @return                  Context
    * @exception               NamingException If the context provider can not 
    *                          be found while getting the Initial Context
    */
   public Context getInitialContext() throws NamingException 
   {
      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;
   }
   
   /** 
    *
    * Terminates the  program, displaying the message and exception
    *
    * @param message the exit message
    * @param e the exception that was raised
    *
    */
   
   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);
   }
   
   /**
    * Parses the command line and runs the example.
    *
    * The command-line arguments are optional, but if any are supplied,
    * they are interpreted in this order:
    * <ol> 
    * <li> customerKey:       Customer Key, default "TerrySmith"
    * <li> url:               URL such as "t3://localhost:7501" of Server
    * <li> user:              User name, default null
    * <li> password:          User password, default null
    * </ol>
    * You can also get the usage by passing -?
    *
    */
   public static void main(String[] args)
   {
      System.out.println("----------AxiomExample running---------");
      AxiomExample example = new AxiomExample();
      // Parse the argument list 
      if ((args != null) && (args.length > 0))
      {
         if (args[0].equals("-?"))
         {
            System.out.println("Usage: AxiomExample <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();
   }
}
