package examples.xml.http;

import java.util.*;
import java.net.*;
import org.xml.sax.*;
import java.io.*;
import org.xml.sax.helpers.ParserFactory;

/**
 * This example works with <tt>StockServlet</tt> included in this package
 * to demonstrate how XML data is created, manipulated, and passed between 
 * a client and a servlet. This class accepts user input to define 
 * a stock trade transaction. XML data is generated and sent to 
 * <tt>StockServlet</tt> via a HTTP POST. The resulting XML data 
 * returned from <tt>StockServlet</tt> is parsed and displayed in 
 * the console.
 * @author Copyright (c) 2000 by BEA Systems, Inc. All Rights Reserved.  
 */

public class StockClient extends HandlerBase {

  /** Default parser name. */
  private static final String 
      DEFAULT_PARSER_NAME = "com.sun.xml.parser.ValidatingParser";

  /** Print writer. */
  private PrintWriter out;

  /** Default constructor. */
  public StockClient() {
      try {
          out = new PrintWriter(new OutputStreamWriter(System.out, "UTF8"));
      } catch (UnsupportedEncodingException e) {
      }
  }

  /**
   * Runs this exmaple from the command line.
   * <p>
   * <tt>java examples.xml.sax.StockClient t3://localhost:7001/stock BEAS</tt>
   * <p>
   * @param url               URL of the servlet such as "http://localhost:7001/StockServlet"
   */

  public static void main(String[] args) {
    if ((args.length < 1)|| (args[0].indexOf("StockServlet")== -1)) {
      System.out.println("Usage:  java examples.xml.http.StockClient "
                         + "ServletURL");
      System.out.println("Example:java examples.xml.http.StockClient "
                         + "http://localhost:7001/StockServlet");
      
    }
    else {
       try {
         URL url = new URL(args[0]);

         String serverURL = args[0];
         // remove the servlet name from this String. This will be used to locate the dtd
         serverURL = serverURL.substring(0, serverURL.indexOf("StockServlet"));

         BufferedReader msgStream = new BufferedReader(new InputStreamReader(System.in));
         String line=null;
         boolean quitNow = false;
         boolean buy = false;
         boolean sell = false;
         boolean beas = false;
         boolean msft = false;
         boolean transactionSent = false;

         do {
           transactionSent = false;

           //get action from user
           System.out.print("Action (\"Buy\" or \"Sell\", \"quit\" to quit): ");
           line = msgStream.readLine();
           if (line != null && line.trim().length() != 0) {
             quitNow = line.equalsIgnoreCase("quit");
             buy = line.equalsIgnoreCase("buy");
             sell = line.equalsIgnoreCase("sell");
             if ((buy || sell) && !quitNow) {
               do {

                 //get stock symbol from user
                 System.out.print("Symbol (\"BEAS\" or \"MSFT\", \"quit\" to quit): ");
                 line = msgStream.readLine();
                 if (line != null && line.trim().length() != 0) {
                   quitNow = line.equalsIgnoreCase("quit");
                   beas = line.equalsIgnoreCase("BEAS");
                   msft = line.equalsIgnoreCase("MSFT");
                   if ((beas || msft) && !quitNow) {
                     do {

                       // get number of shares from user
                       System.out.print("Number of shares (\"quit\" to quit): ");
                       line = msgStream.readLine();
                       if (line != null && line.trim().length() != 0) {
                         quitNow = line.equalsIgnoreCase("quit");
                         if (!quitNow) {

                           // make sure user input is an integer
                           boolean isInteger = false;
                           try {
                             Integer.parseInt(line);
                             isInteger = true;
                           } catch (NumberFormatException nfe) {
                             isInteger = false;
                           }
                           if (isInteger) {
                             System.out.println("Sending trade information...");
                             URLConnection urlc = url.openConnection();
                             urlc.setDoOutput(true);
                             urlc.setDoInput(true);
                             PrintWriter pw = new PrintWriter(new 
                                    OutputStreamWriter(urlc.getOutputStream()), true);

                             // send xml to servlet
                             pw.println("<?xml version='1.0'?>");
                             
                             // set document type declaration
                             pw.println("<!DOCTYPE stocktrade SYSTEM '"+serverURL+"stocktrade.dtd'>");

                             // set stock trade instructions
                             pw.print("<stocktrade ");
                             pw.print("action = "+ (buy ? "'buy' " : "'sell' "));
                             pw.print("symbol = "+ (beas ? "'BEAS' " : "'MSFT' ")); 
                             pw.print("numShares = '"+ line +"'"); 
                             pw.println(" />");

                             // parse xml returned from servlet
                             HandlerBase handler = new StockClient();

                             Parser parser = ParserFactory.makeParser(DEFAULT_PARSER_NAME);
                             parser.setDocumentHandler(handler);
                             parser.setErrorHandler(handler);
                             parser.parse(new InputSource(new BufferedReader(
                                     new InputStreamReader(urlc.getInputStream()))));
                             transactionSent = true;
                           }
                         }
                       }
                     } while ( !quitNow && !transactionSent);
                   }
                 }
               } while ( !quitNow && !transactionSent);
             }
           }
        } while (! quitNow);

       }
       catch (FileNotFoundException fnfe) {
         System.out.println("[DTD not found] Please place the appropriate dtd "+
                            "file in WebLogic Server's document root.");
         fnfe.printStackTrace();
       } catch (Exception e) {
          e.printStackTrace();
       }
    }

  }

  //
  // DocumentHandler methods
  //


  /** Start document. */
  public void startDocument() throws SAXException {
    out.println("");
    out.println("Trade results:");
  } // startDocument()

  /** Start element. */
  public void startElement(String name, AttributeList attrs) throws SAXException {

      if (attrs != null) {
          int len = attrs.getLength();
          for (int i = 0; i < len; i++) {
              out.print(attrs.getName(i));
              out.print("=");
              out.println(attrs.getValue(i));
          }
          out.println(" ");
      }
  } 


  /** End document. */
  public void endDocument() throws SAXException {
      out.flush();

  }

  //
  // ErrorHandler methods
  //

  /** Warning. */
  public void warning(SAXParseException ex) {
      System.err.println("[Warning] "+
                         getLocationString(ex)+": "+
                         ex.getMessage());
  }

  /** Error. */
  public void error(SAXParseException ex) {
      System.err.println("[Error] "+
                         getLocationString(ex)+": "+
                         ex.getMessage());
  }

  /** Fatal error. */
  public void fatalError(SAXParseException ex) throws SAXException {
      System.err.println("[Fatal Error] "+
                         getLocationString(ex)+": "+
                         ex.getMessage());
      throw ex;
  }

  /** Returns a string of the location. */
  private String getLocationString(SAXParseException ex) {
      StringBuffer str = new StringBuffer();

      String systemId = ex.getSystemId();
      if (systemId != null) {
          int index = systemId.lastIndexOf('/');
          if (index != -1) 
              systemId = systemId.substring(index + 1);
          str.append(systemId);
      }
      str.append(':');
      str.append(ex.getLineNumber());
      str.append(':');
      str.append(ex.getColumnNumber());   
      return str.toString();

  } 
}
