CDWR_Data.java [src/java/cfa] Revision: ffc412d47d72be5013c8a0a59c535082523410cb Date: Tue Dec 16 12:11:46 MST 2014
package cfa;
import java.util.ArrayList;
import java.util.Iterator;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
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.SOAPEnvelope;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
/**
* Last Updated: 16-December-2014
* @author Tyler Wible
* @since 7-July-2014
* For more information on all of CDWR's water services, go to:
* http://www.dwr.state.co.us/SurfaceWater/ColoradoWaterSMS.pdf
*/
public class CDWR_Data {
public final String serverURI = "http://www.dwr.state.co.us/";
public final String waterSMSURI = "http://www.dwr.state.co.us/SMS_WebService/ColoradoWaterSMS.asmx";
/**
* Finds discharge data for the specified station and start/end dates out of the Colorado Division of Water Resource Database
* @param stationID the abbreviation of the name for the CDWR station
* @param beginDate the user specified begin date for the station (yyyy-MM-dd format)
* @param endDate the user specified end date for the station (yyyy-MM-dd format)
* @param dataType a flag for extraction of either "hourly" or "daily" flow data from CDWR
* @return a String[][] containing column1 = date(if dataType = "daily": yyyy-MM-dd format, if dataType = "hourly": yyyy-MM-dd HH:mm format), column2 = flowValue
* @throws Exception
*/
public Object[] getCDWRflowData(String stationID, String beginDate, String endDate, String dataType) throws Exception {
//Artificial limit due to the touchy-ness of CDWR to begin dates before the station data begins
if(dataType.equalsIgnoreCase("15-min")){
if(beginDate.compareToIgnoreCase("2007-10-01") < 0){
beginDate = "2007-10-01";
}
if(endDate.compareToIgnoreCase("2007-10-01") < 0){
endDate = "2007-10-01";
}
}
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server
SOAPMessage dataMessage = GetSMSProvisionalData(stationID, "DISCHRG", beginDate, endDate, dataType);
SOAPMessage dataResponse = soapConnection.call(dataMessage, waterSMSURI);
//System.out.print("Station Data:");
//dataResponse.writeTo(System.out);
SOAPBody replyBody = dataResponse.getSOAPBody();
Iterator<?> iter1 = replyBody.getChildElements();
ArrayList<String> stationData = new ArrayList<String>();
while (iter1.hasNext()) {
//Open <GetSMSTransmittingStationsResponse>
SOAPBodyElement bodyElement = (SOAPBodyElement)iter1.next();
Iterator<?> iter2 = bodyElement.getChildElements();
while (iter2.hasNext()) {
//Open <GetSMSTransmittingStationsResult>
SOAPElement child2 = (SOAPElement)iter2.next();
Iterator<?> iter3 = child2.getChildElements();
while (iter3.hasNext()) {
//Open <Station>
SOAPElement child3 = (SOAPElement)iter3.next();
Iterator<?> iter4 = child3.getChildElements();
//Hopefully ever station has 7 attributes (div, wd, abbrev, variable, transDateTime, resultCount, amount)
SOAPElement child4_0 = (SOAPElement)iter4.next();
SOAPElement child4_1 = (SOAPElement)iter4.next();
SOAPElement child4_2 = (SOAPElement)iter4.next();
SOAPElement child4_3 = (SOAPElement)iter4.next();
SOAPElement child4_4 = (SOAPElement)iter4.next();
SOAPElement child4_5 = (SOAPElement)iter4.next();
SOAPElement child4_6 = (SOAPElement)iter4.next();
//if the result is not null or -999, keep it
if(!child4_5.getValue().equalsIgnoreCase(null) && !child4_5.getValue().equalsIgnoreCase("-999")){
stationData.add(child4_0.getValue() + "\t" +
child4_1.getValue() + "\t" +
child4_2.getValue() + "\t" +
child4_3.getValue() + "\t" +
child4_4.getValue() + "\t" +
child4_5.getValue() + "\t" +
child4_6.getValue() + "\t");
}
// while (iter4.hasNext()) {
// SOAPElement child4 = (SOAPElement)iter4.next();
// String content = child4.getValue();
// System.out.println(content);
// }
}
}
}
soapConnection.close();
//Reformat data
String[][] stringArray = new String[stationData.size()][2];
for(int i=0; i<stationData.size(); i++){
String[] currentStationData = stationData.get(i).split("\t");
//Pull out only the data needed to pass between sub-functions
stringArray[i][0] = reformatDate(currentStationData[4], dataType);//date
stringArray[i][1] = currentStationData[5];//value
}
//Add header to stationData and shift all other data in the list down one index (+1)
stationData.add(0, "div\twd\tStationNameAbbrev\tvariable\tDateTime\tvalue\tNumberOfTransmissionsAggregatedTo" + dataType + "Data");
//Save analysis results
String start = "-1";
String end = "-1";
if(stringArray.length > 0){
start = stringArray[0][0];
end = stringArray[stringArray.length - 1][0];
}
Object[] returnArray = {stationData, stringArray, start, end};
return returnArray;
}
/**
* Creates a SOAP Call to CDWR for "GetSMSProvisionalData" for the specified inputs
* @param station the SEO abbreviation for the CDWR station
* @param variable the variable desired from this station (ex. "DISCHRG", "GAGE_HT", "AIR_TEMP")
* @param beginDate the start date of data desired (yyyy-mm-dd)
* @param endDate the end date of date desired (yyyy-mm-dd)
* @param aggregation the aggregation of data desired (ex. "Hourly", "Daily", "15-min")
* @return the response SOAP message from CDWR
* @throws Exception
*/
public SOAPMessage GetSMSProvisionalData(String station, String variable, String beginDate, String endDate, String aggregation) throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("dwr", serverURI);
/*
Constructed SOAP Request Message:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dwr="http://www.dwr.state.co.us/">
<soapenv:Header/>
<soapenv:Body>
<dwr:GetSMSProvisionalData>
<!--Optional:-->
<dwr:Abbrev>CLAGRECO</dwr:Abbrev>
<!--Optional:-->
<dwr:Variable>DISCHRG</dwr:Variable>
<!--Optional:-->
<dwr:StartDate>2013-06-05</dwr:StartDate>
<!--Optional:-->
<dwr:EndDate>2013-06-06</dwr:EndDate>
<!--Optional:-->
<dwr:Aggregation>Hourly</dwr:Aggregation>
</dwr:GetSMSProvisionalData>
</soapenv:Body>
</soapenv:Envelope>
*/
// SOAP Body
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyMethod = soapBody.addChildElement("GetSMSProvisionalData", "dwr");
SOAPElement abbrev = soapBodyMethod.addChildElement("Abbrev", "dwr");
abbrev.addTextNode(station);
SOAPElement soapVariable = soapBodyMethod.addChildElement("Variable", "dwr");
soapVariable.addTextNode(variable);
SOAPElement startDate_soap = soapBodyMethod.addChildElement("StartDate", "dwr");
startDate_soap.addTextNode(beginDate);
SOAPElement endDate_soap = soapBodyMethod.addChildElement("EndDate", "dwr");
endDate_soap.addTextNode(endDate);
if(!aggregation.equalsIgnoreCase("15-min")){
SOAPElement soapAggregation = soapBodyMethod.addChildElement("Aggregation", "dwr");
soapAggregation.addTextNode(aggregation);
}
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", serverURI + "GetSMSProvisionalData");
soapMessage.saveChanges();
// Print the request message
//System.out.print("Request SOAP Message:");
//soapMessage.writeTo(System.out);
//System.out.println();
return soapMessage;
}
/**
* Reformats the date from CDWR's "m/d/yyyy hh:mm am/pm" format to yyyy-MM-dd or yyyy-MM-dd HH:mm depending on the value of dataType
* @param date the current date
* if dataType = "daily" the format is "m/d/yyyy hh:mm am/pm"
* if datatype = "hourly" the format is "m/d/yyyy HH:mm"
* @param dataType the type of date format desired either "daily" or "hourly"
* @return the date parsed into one of the following date formats:
* if dataType = "daily" the format is "yyyy-MM-dd"
* if datatype = "hourly" the format is "yyyy-MM-dd HH:mm"
*/
private String reformatDate(String date, String dataType){
String newDate = "1900-01-01";
//Get portions of date
int index1 = date.indexOf("/");
int index2 = date.indexOf("/", index1 + 1);
int index3 = date.indexOf(" ");
String month = date.substring(0, index1);
String day = date.substring(index1 + 1, index2);
String year = date.substring(index2 + 1, index3);
//check month size
if(month.length() < 2){
month = "0" + month;
}
//check day size
if(day.length() < 2){
day = "0" + day;
}
//Create new date format
if(dataType.equalsIgnoreCase("Daily")){
//Assemble new date format
newDate = year + "-" + month + "-" + day;
}else if(dataType.equalsIgnoreCase("Hourly") || dataType.equalsIgnoreCase("15-min")){
//Hourly data returns as m/d/yyyy HH:mm which matches
//USGS 15-minute data is zero-based military time (24hr day from 00:00 to 23:00)
int index4 = date.indexOf(":");
int index5 = date.indexOf(":", index4 + 1);
int index6 = date.indexOf(" ", index3 + 1);
String hour = date.substring(index3 + 1, index4);
String minute = date.substring(index4 + 1, index5);
String amPM = date.substring(index6 + 1);
//Convert AM/PM
int hour_int = (int) Double.parseDouble(hour);
if(amPM.equalsIgnoreCase("PM")){
hour = String.valueOf(hour_int-1 + 12);
}else{
hour = String.valueOf(hour_int-1);
}
//check hour size
if(hour.length() < 2){
hour = "0" + hour;
}
//check minute size
if(minute.length() < 2){
minute = "0" + minute;
}
newDate = year + "-" + month + "-" + day + " " + hour + ":" + minute;
}
return newDate;
}
/**
* Finds rating curve data for the specified station from the Colorado Division of Water Resource Database
* @param stationID the abbreviation of the name for the CDWR station
* @return a double[][] containing column1 = discharge(ft3/s), column2 = depth(ft)
* @throws Exception
*/
public Object[] getCDWRratingCurve(String stationID) throws Exception {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection soapConnection = soapConnectionFactory.createConnection();
// Send SOAP Message to SOAP Server
SOAPMessage dataMessage = GetSMSCurrentRatingTable(stationID);
SOAPMessage dataResponse = soapConnection.call(dataMessage, waterSMSURI);
//System.out.print("Rating Curve Data:");
//dataResponse.writeTo(System.out);
SOAPBody replyBody = dataResponse.getSOAPBody();
Iterator<?> iter1 = replyBody.getChildElements();
ArrayList<String> stationData = new ArrayList<String>();
while(iter1.hasNext()){
//Open <GetSMSCurrentRatingTableResponse >
SOAPBodyElement bodyElement = (SOAPBodyElement)iter1.next();
//System.out.println(bodyElement.getValue());
Iterator<?> iter2 = bodyElement.getChildElements();
while(iter2.hasNext()){
//Open <GetSMSCurrentRatingTableResult>
SOAPElement child2 = (SOAPElement)iter2.next();
//System.out.println(child2.getValue());
Iterator<?> iter3 = child2.getChildElements();
while(iter3.hasNext()){
//Open <tableName>
SOAPElement child3 = (SOAPElement)iter3.next();
//System.out.println(child3.getValue());
//Open <tablePoints>
SOAPElement child3b = (SOAPElement)iter3.next();
//System.out.println(child3b.getValue());
Iterator<?> iter4 = child3b.getChildElements();
while(iter4.hasNext()){
//Open <RatingTablePoints>
SOAPElement child4 = (SOAPElement)iter4.next();
//System.out.println(child4.getValue());
Iterator<?> iter5 = child4.getChildElements();
//Hopefully RatingTablePoint only has 2 attributes (x, y)
SOAPElement child5x = (SOAPElement)iter5.next();
SOAPElement child5y = (SOAPElement)iter5.next();
//System.out.println(child5x.getValue());
//System.out.println(child5y.getValue());
stationData.add(child5y.getValue() + "\t" + child5x.getValue());//the discharge value followed by the stage value
}
}
}
}
soapConnection.close();
//Reformat data
double[][] stringArray = new double[stationData.size()][2];
for(int i=0; i<stationData.size(); i++){
String[] currentStationData = stationData.get(i).split("\t");
//currentStationData[0] = discharge
//currentStationData[1] = stage
stringArray[i][0] = Double.parseDouble(currentStationData[0]);
stringArray[i][1] = Double.parseDouble(currentStationData[1]);
}
//Add header to stationData and shift all other data in the list down one index (+1)
stationData.add(0, "x\ty");
Object[] returnArray = {stationData, stringArray};
return returnArray;
}
/**
* Creates a SOAP Call to CDWR for "GetSMSCurrentRatingTable" for the specified inputs
* @param station the SEO abbreviation for the CDWR station
* @return the response SOAP message from CDWR
* @throws Exception
*/
private SOAPMessage GetSMSCurrentRatingTable(String station) throws Exception {
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration("dwr", serverURI);
/*
Constructed SOAP Request Message:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dwr="http://www.dwr.state.co.us/">
<soapenv:Header/>
<soapenv:Body>
<dwr:GetSMSCurrentRatingTable>
<dwr:Abbrev>CLAGRECO</dwr:Abbrev>
<dwr:Variable>DISCHRG</dwr:Variable>
</dwr:GetSMSCurrentRatingTable>
</soapenv:Body>
</soapenv:Envelope>
*/
// SOAP Body
SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyMethod = soapBody.addChildElement("GetSMSCurrentRatingTable", "dwr");
SOAPElement abbrev = soapBodyMethod.addChildElement("Abbrev", "dwr");
abbrev.addTextNode(station);
SOAPElement soapVariable = soapBodyMethod.addChildElement("Variable", "dwr");
soapVariable.addTextNode("DISCHRG");
MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction", serverURI + "GetSMSCurrentRatingTable");
soapMessage.saveChanges();
//Print the request message
//System.out.print("Request SOAP Message:");
//soapMessage.writeTo(System.out);
return soapMessage;
}
}