import javax.xml.soap.*;
import java.util.Iterator;
import java.net.URL;
import java.io.*;

public class Client {

    public static void main(String[] args) {
        try {
            SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
            SOAPConnection connection = soapConnectionFactory.createConnection();
            SOAPFactory soapFactory = SOAPFactory.newInstance();

            SOAPMessage message = prepareMessage();

            URL endpoint = new URL("https://opendap.co-ops.nos.noaa.gov/axis/services/HarmonicConstituents");
            SOAPMessage response = connection.call(message, endpoint);
            connection.close();

            System.out.print("\nPrinting the message that is being sent: \n\n");
            message.writeTo(System.out);
            System.out.println("\n\n");

            /*
            System.out.println("\nPrinting the respone that was recieved: \n\n" );
            response.writeTo(System.out);
             */

            //Uncoment this part if you want the response to be saved locally in an XML file
            /*
            FileOutputStream fout = new FileOutputStream ("SoapResponse.xml");
            response.writeTo(fout);
            fout.close();
             */

            //You can also store the response as a String
            /*
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            response.writeTo( out );
            String str = out.toString();  
             */

            System.out.println("\n\nIterating through the response object to get the values:\n\n");
            SOAPBody responseBody = response.getSOAPBody();

            //Checking for errors
            if (responseBody.hasFault()) {
                SOAPFault fault = responseBody.getFault();
                String actor = fault.getFaultActor();
                System.out.println("Fault contains: ");
                System.out.println("Fault code: " + fault.getFaultCodeAsName().getQualifiedName());
                System.out.println("Fault string: " + fault.getFaultString());
                if (actor != null) {
                    System.out.println("Actor: " + actor);
                }
            } else {
                Iterator iterator = responseBody.getChildElements();
                Iterator iterator2 = null;
                Iterator iterator3 = null;

                String tagName = null;
                SOAPElement se = null;

                if (iterator.hasNext()) {
                    se = (SOAPElement) iterator.next();
                    iterator = se.getChildElements();
                    while (iterator.hasNext()) {
                        se = (SOAPElement) iterator.next();
                        printMetadata(se);
                        tagName = se.getElementName().getLocalName();
                        if ("data".equals(tagName)) {
                            iterator2 = se.getChildElements();
                            while (iterator2.hasNext()) {
                                se = (SOAPElement) iterator2.next();
                                iterator3 = se.getChildElements();
                                while (iterator3.hasNext()) {
                                    se = (SOAPElement) iterator3.next();
                                    printData(se);
                                }
                            }
                        }
                    }
                }
            }

        } catch (SOAPException e) {
            System.err.println("ERROR: ******* " + e.toString());
        } catch (IOException io) {
            System.err.println("ERROR: ******* " + io.toString());
        }
    }

    public static SOAPMessage prepareMessage() {
        SOAPMessage message = null;
        try {
            SOAPFactory soapFactory = SOAPFactory.newInstance();
            MessageFactory factory = MessageFactory.newInstance();
            message = factory.createMessage();

            SOAPHeader header = message.getSOAPHeader();
            SOAPBody body = message.getSOAPBody();
            header.detachNode();
            message.getMimeHeaders().addHeader("SOAPAction", "");

            Name bodyName = soapFactory.createName("getHConstituentsAndMetadata", "HC",
                    "https://opendap.co-ops.nos.noaa.gov/axis/webservices/harmonicconstituents/wsdl");
            SOAPBodyElement bodyElement = body.addBodyElement(bodyName);

            ///Constructing the body for the request
            Name name = soapFactory.createName("stationId");
            SOAPElement symbol = bodyElement.addChildElement(name);    
            symbol.addTextNode("8454000");    
            name = soapFactory.createName("unit");    
            symbol = bodyElement.addChildElement(name);
            symbol.addTextNode("0");
            name = soapFactory.createName("timeZone");    
            symbol = bodyElement.addChildElement(name);
            symbol.addTextNode("0");    

        } catch (SOAPException e) {
            System.err.println("ERROR: ******* " + e.toString());
        }
        return message;
    }

    public static void printMetadata(SOAPElement se) {
        String tagName = se.getElementName().getLocalName();
        if (tagName != null) {
            if ("stationId".equals(tagName)) {
                System.out.println("Printing Metadata \n");
                System.out.println("Station ID       : " + se.getValue());
            } else if ("stationName".equals(tagName)) {
                System.out.println("station Name     : " + se.getValue());
            } else if ("latitude".equals(tagName)) {
                System.out.println("Latitude         : " + se.getValue());
            } else if ("longitude".equals(tagName)) {
                System.out.println("Longitude        : " + se.getValue());
            } else if ("state".equals(tagName)) {
                System.out.println("State            : " + se.getValue());
            } else if ("dataSource".equals(tagName)) {
                System.out.println("Data Source      : " + se.getValue());
            } else if ("COOPSDisclaimer".equals(tagName)) {
                System.out.println("COOPS Disclaimer : " + se.getValue());
            }  else if ("unit".equals(tagName)) {
                System.out.println("Unit             : " + se.getValue());
            } else if ("timeZone".equals(tagName)) {
                System.out.println("Time Zone        : " + se.getValue() + "\n");
                System.out.println("Printing the data \n");
            }
        }
    }

    public static void printData(SOAPElement se) {
        String tagName = se.getElementName().getLocalName();
        if (tagName != null) {
            if (tagName.equals("constNum")) {
                System.out.println("Constituent # : " + se.getValue());
            } else if (tagName.equals("name")) {
                System.out.println("Name          : " + se.getValue());
            } else if (tagName.equals("amplitude")) {
                System.out.println("Amplitude     : " + se.getValue());
            } else if (tagName.equals("speed")) {
                System.out.println("Speed         : " + se.getValue() + "\n");
            }
        }
    }
}
/****************************************************
SAMPLE RUN
 
>java Client
 
Printing the message that is being sent:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Body>
        <HC:getHConstituentsAndMetadata xmlns:HC="https://opendap.co-ops.nos.noaa.gov/axis/webservices/harmonicconstituents/wsdl">
            <stationId>8454000</stationId>
            <unit>0</unit>
            <timeZone>0</timeZone>
        </HC:getHConstituentsAndMetadata>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
 
 
Iterating through the response object to get the values:

Printing Metadata 

Station ID       : 8454000
station Name     : Providence
Latitude         : 41.8071
Longitude        : -71.4012
State            : RI
Data Source      : USDOC/NOAA/NOS/COOPS(Center for Operational Oceanographic Products and Services)
Time Zone        : GMT
Unit             : Amplitudes are in Meters, Phases are in degrees, referenced to GMT, and Speed in degrees per hour

Printing the data 

Constituent # : 1
Name          : M2
Amplitude     : 0.643
Speed         : 28.9841042

Constituent # : 2
Name          : S2
Amplitude     : 0.138
Speed         : 30.0

Constituent # : 3
Name          : N2
Amplitude     : 0.152
Speed         : 28.4397295

Constituent # : 4
Name          : K1
Amplitude     : 0.073
Speed         : 15.0410686

Constituent # : 5
Name          : M4
Amplitude     : 0.103
Speed         : 57.9682084

Constituent # : 6
Name          : O1
Amplitude     : 0.056
Speed         : 13.9430356

Constituent # : 7
Name          : M6
Amplitude     : 0.027
Speed         : 86.9523127

Constituent # : 8
Name          : MK3
Amplitude     : 0.016
Speed         : 44.0251729

Constituent # : 9
Name          : S4
Amplitude     : 0.014
Speed         : 60.0

Constituent # : 10
Name          : MN4
Amplitude     : 0.044
Speed         : 57.4238337

Constituent # : 11
Name          : NU2
Amplitude     : 0.027
Speed         : 28.5125831

Constituent # : 12
Name          : S6
Amplitude     : 0.0
Speed         : 90.0

Constituent # : 13
Name          : MU2
Amplitude     : 0.031
Speed         : 27.9682084

Constituent # : 14
Name          : 2N2
Amplitude     : 0.022
Speed         : 27.8953548

Constituent # : 15
Name          : OO1
Amplitude     : 0.0020
Speed         : 16.1391017

Constituent # : 16
Name          : LAM2
Amplitude     : 0.0050
Speed         : 29.4556253

Constituent # : 17
Name          : S1
Amplitude     : 0.016
Speed         : 15.0

Constituent # : 18
Name          : M1
Amplitude     : 0.0050
Speed         : 14.4966939

Constituent # : 19
Name          : J1
Amplitude     : 0.0060
Speed         : 15.5854433

Constituent # : 20
Name          : MM
Amplitude     : 0.0
Speed         : 0.5443747

Constituent # : 21
Name          : SSA
Amplitude     : 0.0
Speed         : 0.0821373

Constituent # : 22
Name          : SA
Amplitude     : 0.06
Speed         : 0.0410686

Constituent # : 23
Name          : MSF
Amplitude     : 0.0
Speed         : 1.0158958

Constituent # : 24
Name          : MF
Amplitude     : 0.0
Speed         : 1.0980331

Constituent # : 25
Name          : RHO
Amplitude     : 0.0020
Speed         : 13.4715145

Constituent # : 26
Name          : Q1
Amplitude     : 0.016
Speed         : 13.3986609

Constituent # : 27
Name          : T2
Amplitude     : 0.013
Speed         : 29.9589333

Constituent # : 28
Name          : R2
Amplitude     : 0.0040
Speed         : 30.0410667

Constituent # : 29
Name          : 2Q1
Amplitude     : 0.0010
Speed         : 12.8542862

Constituent # : 30
Name          : P1
Amplitude     : 0.025
Speed         : 14.9589314

Constituent # : 31
Name          : 2SM2
Amplitude     : 0.0
Speed         : 31.0158958

Constituent # : 32
Name          : M3
Amplitude     : 0.012
Speed         : 43.4761563

Constituent # : 33
Name          : L2
Amplitude     : 0.012
Speed         : 29.5284789

Constituent # : 34
Name          : 2MK3
Amplitude     : 0.012
Speed         : 42.9271398

Constituent # : 35
Name          : K2
Amplitude     : 0.038
Speed         : 30.0821373

Constituent # : 36
Name          : M8
Amplitude     : 0.0050
Speed         : 115.9364166

Constituent # : 37
Name          : MS4
Amplitude     : 0.026
Speed         : 58.9841042

************************************************************/