package com.oreilly.jent.people.soap;

/**
 * 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.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.logging.Logger;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPMessage;

import com.oreilly.jent.people.PersonDAO;

/**
 * An example SAAJ client for the PeopleFinder SOAP service.
 * 
 * @author Jim Farley
 *
 */
public class PeopleFinderSAAJClient {
    private static Logger sLog =
        Logger.getLogger(PeopleFinderSAAJClient.class.getName());
    private static String sServiceURL = 
        "http://localhost:8080/JEnt-examples/pf-service";
    static final private String USAGE = 
        "PeopleFinderClient " +
        "[-first pattern] " +
        "[-last pattern] " +
        "[-email pattern]";
    /**
     * 
     */
    public PeopleFinderSAAJClient() {
        super();
    }
    
    private void invokeService(String[] args) {
        HashMap searchParams = new HashMap();
        // Parse the command-line arguments, construct the search
        // parameters name/value map along the way
        for (int i = 0; i < args.length; i++) {
            if (args[i].equals("-first")) {
                if (i >= args.length) {
                    sLog.info(USAGE);
                    return;
                }
                else {
                    i++;
                    searchParams.put(PersonDAO.FIRST_NAME, args[i]);
                }
            }
            else if (args[i].equals("-last")) {
                if (i >= args.length) {
                    sLog.info(USAGE);
                    return;
                }
                else {
                    i++;
                    searchParams.put(PersonDAO.LAST_NAME, args[i]);
                }
            }
            else if (args[i].equals("-email")) {
                if (i >= args.length) {
                    sLog.info(USAGE);
                    return;
                }
                else {
                    i++;
                    searchParams.put(PersonDAO.EMAIL, args[i]);
                }
            }
        }
        try {
            // Create a SOAP connection 
            SOAPConnection connection = 
                SOAPConnectionFactory.newInstance().createConnection();
            // Send the request, get the response
            URL endpoint = new URL(sServiceURL);
            SOAPMessage request = this.generateServiceRequest(searchParams);
            SOAPMessage response = connection.call(request, endpoint);
            
            // Print the response (either fault or results)
            SOAPBody respBody = response.getSOAPPart().getEnvelope().getBody();
            // If it's a fault, just print the code and the string
            if (respBody.hasFault()) {
                SOAPFault fault = respBody.getFault();
                String code = fault.getFaultCode();
                String fString = fault.getFaultString();
                sLog.severe("Error occured during service call, code = " + 
                            code + ", fault string = " + fString);
            }
            // If it's a response, the service encodes the person attributes
            // into a multiRef element, and the email addresses into a
            // separate multiRef element.  So we (sloppily) just print all
            // children of these two elements (their names and values).
            else {
                SOAPFactory soapFactory = SOAPFactory.newInstance();
                Name mrName = soapFactory.createName("multiRef");
                Iterator mIter = respBody.getChildElements(mrName);
                while (mIter.hasNext()) {
                    SOAPElement mr = (SOAPElement)mIter.next();
                    Iterator mcIter = mr.getChildElements();
                    while (mcIter.hasNext()) {
                        SOAPElement elem = (SOAPElement)mcIter.next();
                        if (elem.getValue() != null) {
                            sLog.info(elem.getElementName().getLocalName() + ": " +
                                      elem.getValue());
                        }
                        
                    }
                }
            }
        }
        catch (MalformedURLException mue) {
            sLog.severe("Bad endpoint URL: " + sServiceURL);
        }
        catch (SOAPException se) {
            sLog.severe("Error making SOAP call: " + se.getMessage());
            
        }
    }
    
    private SOAPMessage generateServiceRequest(HashMap searchArgs) {
        SOAPMessage message = null;
        try {
            // Create the SOAP message
            message = MessageFactory.newInstance().createMessage();
            
            // Get the body, add the root XML element
            SOAPBody body = message.getSOAPPart().getEnvelope().getBody();
            SOAPFactory soapFactory = SOAPFactory.newInstance();
            Name bodyName = 
                soapFactory.createName("findPeople",
                                       "pf", "http://rmi.people.staff.cscie162.harvard");
            SOAPBodyElement searchRequest =
                body.addBodyElement(bodyName);

            // Add the XML elements for the search arguments
            Name childName = soapFactory.createName("searchParams");
            SOAPElement params =
              searchRequest.addChildElement(childName);

            // For each search argument provided, add an "item" element
            // to the search parameters element, using the HashMap
            // encoding used by Axis
            Iterator kIter = searchArgs.keySet().iterator();
            while (kIter.hasNext()) {
                String key = (String)kIter.next();
                String val = (String)searchArgs.get(key);
                
                childName = soapFactory.createName("item");
                SOAPElement item = params.addChildElement(childName);
            
                childName = soapFactory.createName("key");
                SOAPElement keyElem = item.addChildElement(childName);
                keyElem.addTextNode(key);
                
                childName = soapFactory.createName("value");
                SOAPElement valElem = item.addChildElement(childName);
                valElem.addTextNode(val);
            }
        }
        catch (UnsupportedOperationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch (SOAPException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return message;
    }

    public static void main(String[] args) {
        PeopleFinderSAAJClient client = new PeopleFinderSAAJClient();
        client.invokeService(args);
    }
}
