/**
 * Copyright @ 2000 Peter Roßbach (pr@webapp.de) and Lars Röwekamp (Lars@openKnowlege.de)
 *
 * Source is only for non commercialand coaching usage.
 *
 * Not Warranty to use it.
 */
package de.ix.jspTutorial.model;
import java.sql.*;
import java.util.*;
import javax.servlet.* ;
import javax.servlet.http.* ;
import  de.ix.jspTutorial.database.* ;
import  de.ix.jspTutorial.constants.* ;

/**ne
 * Class declaration
 *
 *
 * @author Peter Rossbach (<a href="mailto://pr@webapp.de">pr@webapp.de</a>)
 * @version $Id:$
 */
public class PizzaAccessor
{

  /**
    * version of the source
    */
  public static String vcid = "$Id:$";

  /**
   * Connection to DB
   */
	private DatabaseConnection myConnection ;

  /**
   * Connection to the DB retriver object
   */
	private DatabaseRetriever myRetriever ;

  /**
   * Connection to the DB modifier
   */
	private DatabaseGenericModifier myModifier ;

  /**
   * The ServletContext
   */
	private ServletContext myApplication ;


  /**
    * Create a connection to the Instant DB Test DB. The connection
    * will be create once per application inside the PizzaServiceFC.jsp
    * and then released again.
    *
    * @param aAppliation current ServletContext
    *
    * @see de.ix.jspTutorial.controller.JspTutorialStartServlet
    */
	public PizzaAccessor(ServletContext aApplication) {
		String theDataSource =
		      	"jdbc:idb:" + aApplication.getRealPath("") + "\\WEB-INF\\config\\idb\\jspTutorial.prp" ;
		synchronized(PizzaAccessor.class) {
			try {
				myApplication = aApplication ;
				myConnection =
			    	 new DatabaseConnection(
			      	"jdbc.idbDriver",
			      	theDataSource,
			      	"jspTutorial"
			      	);
				Properties theProp = new Properties() ;
		    theProp.put("user","jsp") ;
		    theProp.put("password","tutorial");
		    myConnection.connect(theProp) ;
		    myRetriever = new DatabaseRetriever(myConnection) ;
		    myModifier = new DatabaseGenericModifier(myConnection) ;
			} catch ( Exception de) {
			  log("Have problems to connect datasource " + theDataSource , de) ;
			  throw new RuntimeException(de.getMessage()) ;
			}
		}
	}

	/**
	 * Create an access to a specified DB
         *
	 * @param aConnection database connection
	 */
	public PizzaAccessor(DatabaseConnection aConnection) {
    setConnection(aConnection) ;
    myRetriever = new DatabaseRetriever(aConnection) ;
	}

	/**
	 * setter method for the attribute <code>myConnection</code>
         *
	 * @param aConnection database connectionDatenbankverbindung
         *
         */
	public void setConnection(DatabaseConnection aConnection)
	{
		myConnection = aConnection ;
	}

	/**
	 * Getter method for the attribute <code>myConnection</code>
         *
	 * @return a database connection
	 */
	public DatabaseConnection getConnection() { return myConnection ; }

	/**
	 * Read list of all possible pizza types from the DB
         *
	 * @param aApplication  current servlet context
         *
	 * @return list of all possible pizza types
  	 */
	public synchronized TreeMap  readPizzaList(ServletContext aApplication)
	{
	   TreeMap theMap = new TreeMap() ;
	   try {
	   	  myConnection.begin() ;
	   		List theResult = myRetriever.retrieve(
	   			"SELECT id,name,size,baseprice FROM pizza",
	   			"pizza",
	   			new PizzaBinder()) ;
	   		for(Iterator it=theResult.iterator();it.hasNext();) {
	   		  Pizza thePizza = (Pizza) it.next() ;
	   		  theMap.put(new Long(thePizza.getId()),thePizza) ;
	   		}
	   		myConnection.commit() ;
	   } catch (Exception e ) {
	   	  try {
	   				myConnection.rollback() ;
	   	  } catch (DatabaseException de) {}
	   	}
	   	return theMap ;
	}

       /**
	 * Read all possible ingreddients from the DB
         *
    	 * @param aApplication current servlet context
	 *
         * @return list of all possible ingredient tyesListe der Zutaten
         */
	public synchronized TreeMap  readIngredientList(ServletContext aApplication)
	{
	   TreeMap theMap = new TreeMap() ;
	   try {
	   	  myConnection.begin() ;
	   		List theResult = myRetriever.retrieve(
	   			"SELECT id,name,price FROM ingredient",
	   			"ingredient",
	   			new PizzaBinder()) ;
	   		for(Iterator it=theResult.iterator();it.hasNext();) {
	   		  Ingredient theIngredient = (Ingredient) it.next() ;
	   		  theMap.put(new Long(theIngredient.getId()),theIngredient) ;
	   		}
	   		myConnection.commit() ;
	   } catch (Exception e ) {
	   	  try {
	   				myConnection.rollback() ;
	   	  } catch (DatabaseException de) {}
	   }
	   	return theMap ;
	}

	/**
	 * Check if a given customer is part of the DB
         *
	 * @param aCustomerID unique id of the Pizza Service customer
         *
	 * @return true, if customer exist with the given customer id
  *      *         false else
	 */
	public synchronized boolean checkCustomer(Customer aCustomer)
	{
		  boolean isCustomer = false ;
	   try {
	   	  myConnection.begin() ;
	   		List theResult = (List)myRetriever.retrieve(
	   			"SELECT * FROM customer WHERE id = " + aCustomer.getId(),
	   			"customer",
	   			new PizzaBinder()) ;
	   		isCustomer = (theResult != null && theResult.size() == 1) ;
	   		if(isCustomer) {
	   			Customer theDbCustomer = (Customer)theResult.get(0) ;
	   			aCustomer.set(theDbCustomer) ;
	   		}
	   		log("Customer " + aCustomer + "--" + isCustomer) ;
	   		theResult = null ;
	   		myConnection.commit() ;
	   } catch (Exception e ) {
	   	  isCustomer = false ;
	   	  try {
	   				myConnection.rollback() ;
	   	  } catch (DatabaseException de) {}
	   }
		return isCustomer ;
	}

	/**
	 * Generate a <code>Customer</code> object with the help
  *      * of a HttpServletRequest
         *
	 * @param request a http request
  *      *
  *      * @return generated customer object
	 */
	public Customer generateCustomer(HttpServletRequest request) {
          Customer customer = new Customer();
          customer.setAddress1((String)request.getParameter(RequestParameterConstants.CUS_ADDRESS1));
          customer.setAddress2((String)request.getParameter(RequestParameterConstants.CUS_ADDRESS2));
          customer.setEmail((String)request.getParameter(RequestParameterConstants.CUS_EMAIL));
          customer.setFirstname((String)request.getParameter(RequestParameterConstants.CUS_FIRSTNAME));
          String id = (String)request.getParameter(RequestParameterConstants.CUS_ID) ;
          if(id != null)
      		customer.setId(Long.parseLong(id));
          customer.setLastname((String)request.getParameter(RequestParameterConstants.CUS_LASTNAME));
          customer.setTown((String)request.getParameter(RequestParameterConstants.CUS_TOWN));
          customer.setZip((String)request.getParameter(RequestParameterConstants.CUS_ZIP));
          return customer;
      }

	/**
	 * Create a new customer inside the DB
  *      *
	 * @param aCustomer customers data
  *      *
  *      * @return true, if it was possible to create the new customer
  *      *         false else
	 */
	public synchronized boolean newCustomer(Customer aCustomer)
	{
		boolean isCreated = false ;
		if(aCustomer != null) {

	   try {
	   	  myConnection.begin() ;

	   	  // set
	   	  aCustomer.setId(myModifier.getNextSequenceNumber()) ;

	   	  DatabaseGenericObject theDbCustomer =
	   			aCustomer.getGenericObject() ;

	   	  // create
	   	  isCreated = myModifier.create(theDbCustomer,"customer") ;
	   	  log("new Customer " + theDbCustomer + "--" + isCreated) ;

	   	 if(isCreated)
   	    	myConnection.commit() ;
   	   else
   	  	 myConnection.rollback() ;
	   		theDbCustomer = null ;
	   } catch (Exception e ) {
	   	  isCreated = false ;
	   	  try {
	   				myConnection.rollback() ;
	   	  } catch (DatabaseException de) { log("Can't rollback",de) ;}
	   }
		}
		return isCreated ;
	}

	/**
	 * Create a new order record inside the db and change the depending
         * customer record if necessary.
         *
	 * @param aCustomer customer, who orderd the pizza
	 * @param aPersonalPizza base pizza plus additional ingredients
         *
         * @return Order, if it was possible to create a new order inside the DB
         *         null else
	 */
	public synchronized Order newOrder(Customer aCustomer,PersonalPizza aPersonalPizza)
	{
	    Order theOrder = null;

            if(aCustomer == null || aPersonalPizza == null)
			 throw new RuntimeException("Please setup Customer and Order") ;
		boolean isCreated = false ;
   try {
   	  myConnection.begin() ;

   	  theOrder = new Order(
   	  	myModifier.getNextSequenceNumber(),
   	  	aCustomer,
   	  	aPersonalPizza,
   	  	aPersonalPizza.calcTotalPrice()
   	  ) ;
	   	log("new Order " + theOrder ) ;
   	  // set

   	  I_DatabaseGenericObject theDbObject =
   		   aCustomer.getGenericObject() ;
  	  isCreated = myModifier.update(theDbObject,"customer","id") ;
	   	log("update DB Customer " + theDbObject  + "## " + isCreated ) ;
	   	if(isCreated) {
	   	  // create order
				theDbObject = theOrder.getGenericObject() ;
	   	  isCreated = myModifier.create(theDbObject,"pizzaorder") ;
		   log("new DB Order " + theDbObject  + "## " + isCreated ) ;
		   	if(isCreated) {
		   		// Pizza
		   		theDbObject = theOrder.getPizzaGenericObject() ;
		   		 isCreated = false ;
		   	  isCreated = myModifier.create(theDbObject,"personalpizza") ;
	  	   	log("new DB Pizza " + theDbObject  + "## " + isCreated ) ;
		   	  if(isCreated)
		   	  {
		   	  	  // ingredient
		   	  	  for(Iterator it=theOrder.getIngredientGenericObjects().iterator();isCreated && it.hasNext();)
		   	  	  {
		   	  	  	 isCreated = false ;
		   	  	  	 theDbObject = (I_DatabaseGenericObject)it.next() ;
		   	  			 isCreated = myModifier.create(theDbObject,"personalingredient") ;
			         log("new DB Ingredient " + theDbObject  + "## " + isCreated ) ;
	   	  	  }
		   	  }
		   	}
	   	}
	   	if(isCreated)
   	  	myConnection.commit() ;
   	  else
   	  	myConnection.rollback() ;
   		theDbObject = null ;
   } catch (Exception e ) {
   	  log("newOrder Error ", e);
          isCreated = false;
   	  try {
   				myConnection.rollback() ;
   	  } catch (DatabaseException de) {}
   }

                if (!isCreated)
                    theOrder = null;
		return theOrder ;
	}

 /**
   * Output of a message to the servlet log of the container
   *
   * @param msg the message e Nachrichten
   *
   */
  public void log(String msg)
  { myApplication.log(msg) ; }

 /**
   * Output of a message and an exception to the servlet log of the container
   *
   * @param msg the message e Nachrichten
   * @param throwable the exception
   *
   */
  public void log(String message, Throwable throwable)
  { myApplication.log(message,throwable) ; }

} // end of class


//
// History:
//
// $Log:$
//
//