import java.util.*;
import java.io.*;
import java.net.*;
import java.rmi.*;

import javax.mail.*;
import javax.mail.internet.*;

import org.apache.soap.*;
import org.apache.soap.rpc.*;
import org.apache.soap.util.*;
import org.w3c.dom.*;
import javax.mail.*;

import org.apache.soap.transport.http.SOAPHTTPConnection;

public class Client2 {

    public Client2() {
	/*
	 * In case of using proxy, set proxy host and port, please!
	 */
	/*
	SOAPHTTPConnection conn = new SOAPHTTPConnection();
	conn.setProxyHost("***************");
	conn.setProxyPort(8080);
	call.setSOAPTransport(conn);
	*/
    }
    
    // Apache-Soap Access point
    private static String serviceUrlString="http://pdbjs8.protein.osaka-u.ac.jp/soap/servlet/messagerouter";

    // PDBjSOAPService URN
    private static String taminoSoapUrl="urn:PDBjSOAPServiceX";

    // PDBjSOAPService Database URL
    private static String dbURL = "http://pdbjs8.protein.osaka-u.ac.jp/tamino/pdbMLplus";

    // PDBjSOAPService Database Collection name
    private static String colName = "pdbMLplus_Collection";

    // Set Result Size
    private static int defResultNum = 16;

    private static URL serviceUrl=null;
    private Call call = new Call ();

    public static void printUsage()
    {
        System.out.println("Usage:java Client2 [pdbid]");
    }


    public static void main(String[] args) 
	throws SOAPException, MalformedURLException 
    {
	String xpath     = "";
	int    resultNum = 1;
	String pdbid = "";

	for (int i = 0 ; i < args.length ; ++i) {
            if (args[i].equalsIgnoreCase("-h") ||
                args[i].equalsIgnoreCase("-help")) {
                if (args[0].equals("-h") == true ||
                    args[0].equals("-help") == true) {
                    printUsage();
                    System.exit(0);
                }
            }
	    pdbid = args[0].toUpperCase();
        }
	
	if (pdbid.length() == 0) {
	    printUsage();
	    System.exit(0);
	}

	xpath = "/datablock[@datablockName='" + pdbid + "-noatom']";

	Client2 cl = new Client2();

	// Database connect
	cl.start();

	// send XPATH
	cl.query(xpath, resultNum);

	// Database disconnect
	cl.end();

    }

    /*
     * Database connect
     */
    public void start()
	throws SOAPException, MalformedURLException 
    {
	serviceUrl=new URL(serviceUrlString);
	Vector response=new Vector();
	
        // Database connect
	invoke("connect", new String[] { dbURL, "", "" }, response);
	
        // Set Collection name
	invoke("setaccesslocation", new String[]{ colName }, response);
	
    }

    /*------------ XPATH -------------*/
    /*
     * XPATH ( return value : Element )
     */
    public void query(String xpath)
	throws SOAPException, MalformedURLException 
    {
	query(xpath, defResultNum);
    }
    public void query(String xpath, int num)
	throws SOAPException, MalformedURLException 
    {
	Vector response=new Vector();

	if (num < 0) {
	    // get all search
	    invoke("xquery", 
		   new String[] {xpath, Integer.toString(defResultNum)}, 
		   response);
	    while (response.size()>0) {
		// get it
		Node child=(Element)response.get(0);
		while (child!=null) {

		    System.out.println(org.apache.soap.util.xml.DOMWriter.nodeToString(child));

		    child=child.getNextSibling();
		}

		// get next bunch of xml documents, max documents is 5
		invoke("nextresult", 
		       new String[]{ Integer.toString(defResultNum) },
		       response);
	    }

	} else {
	    // XPATH query
	    invoke("xquery", 
		   new String[] {xpath, Integer.toString(num)}, 
		   response);

	    if (response != null && response.size() > 0) {
		Element result=(Element)(response.get(0));
		int counter=0;
		Node child=result;
		while (child!=null) {
		    if (child instanceof Element) {
			System.out.println(org.apache.soap.util.xml.DOMWriter.nodeToString(child));
		    }
		    child=child.getNextSibling();
		}
	    }
	}
    }

    /**
     * Database disconnect
     */
    public void end()
	throws SOAPException, MalformedURLException 
    {
	Vector response=new Vector();

	// Database disconnect
	invoke("disconnect", null, response);
    }
	
    /*
     * SOAP Service call
     */
    public void invoke(String method, Object [] parms, Vector vec)
	throws SOAPException 
    {
    	// Set target URI
        call.setTargetObjectURI (taminoSoapUrl);

	// Set Soap method
        call.setMethodName (method);

	// Set Encoding Style
        call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);

	// Set Parameter
        call.setParams(null);
        if (parms!=null) {
	    Vector vecParms = new Vector ();
            for (int i=0;i<parms.length;i++) {

            	if ((parms[i] instanceof Element)) {
		    call.setEncodingStyleURI(Constants.NS_URI_LITERAL_XML);
            	}
            	Class parmClass=parms[i].getClass();

		if (parms[i] instanceof Element)
		    parmClass=Element.class;
		vecParms.addElement (new Parameter("parm", parmClass, parms[i], null));
            }
            // Set
            call.setParams (vecParms);
        }
        
        // Service call
        Response resp = call.invoke (serviceUrl, "");
        // error
        if (resp.generatedFault ()) {
          Fault fault = resp.getFault ();
          throw new SOAPException(fault.getFaultCode(),
				  fault.getFaultString());
        }

        vec.clear();
        
        // Set return value
        Parameter result = resp.getReturnValue ();
        if (result!=null && result.getValue()!=null) {
	    vec.add(result.getValue());
        }
	
        Vector internal=resp.getParams();
        if (internal!=null) {
	    for (int i=0;i<internal.size();i++) {
		vec.add(((Parameter)internal.get(i)).getValue());
	    }
        }
    	// copy multipart entries
        try {
	    for (int i=0;i<resp.getPartCount();i++) {
		// get the mimebodypart
		MimeBodyPart mbp=(MimeBodyPart)resp.getBodyPart(i);
		// and if it is not the same as the root (which is ignored, because it is already processed above)
		if (i==0)
		    continue;
		// add the bodypart as StringBuffer to the list
		// all StringBuffers can later be identified as Mime simply by their object type
		StringBuffer sb=new StringBuffer((String)mbp.getContent());
		vec.add(sb);
	    }
        }catch (Exception e) {System.err.println(e);}
        return;
    }
}

