V1_0.java [src/java/m/svap/svap05b_svaphydrob] Revision: default Date:
/*
* $Id$
*
* This baseFlowOutFile is part of the Cloud Services Integration Platform (CSIP),
* a Model-as-a-Service framework, API, and application suite.
*
* 2012-2017, OMSLab, Colorado State University.
*
* OMSLab licenses this baseFlowOutFile to you under the MIT license.
* See the LICENSE baseFlowOutFile in the project root for more information.
*/
package m.svap.svap05b_svaphydrob;
import csip.Client;
import csip.Config;
import csip.ModelDataService;
import csip.ServiceException;
import csip.annotations.Polling;
import csip.utils.JSONUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import javax.ws.rs.Path;
import csip.annotations.Description;
import csip.annotations.Name;
import org.apache.commons.io.IOUtils;
import org.apache.http.client.entity.EntityBuilder;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import svap.utils.SVAPUtils;
/**
* SVAP-05b: Get Stream Hydrology for Watershed Description
*
* This service computes the number of wetted monthlyCount if a stream is
* intermittent, or number of monthlyCount at baseflow if the stream is
* perennial.
*
* @author Rumpal Sidhu
*/
@Name("SVAP-05b: Get Stream Hydrology for Watershed Description")
@Description("This service computes the number of wetted months if a stream is "
+ "intermittent, or number of months at baseflow if the stream is perennial.")
@Path("m/svap/svaphydrob/1.0")
@Polling(first = 10000, next = 2000)
public class V1_0 extends ModelDataService {
private int assessmentId;
private String stationId, organization;
private ArrayList<StreamFlow> streamFlowList = new ArrayList();
private int[] monthlyCount = new int[12];
private int numberOfMonths;
private static final String BASEFLOW_URL = "http://csip.engr.colostate.edu:8088/csip-cfa/m/cfa/baseflow/1.0";
@Override
protected void preProcess() throws ServiceException {
assessmentId = parameter().getInt("assessment_id");
stationId = parameter().getString("station_id");
organization = parameter().getString("organization");
validateSource();
}
@Override
protected void doProcess() throws Exception {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String endDate = simpleDateFormat.format(calendar.getTime());
calendar.add(Calendar.YEAR, -1);
String beginDate = simpleDateFormat.format(calendar.getTime());
JSONObject requestJSON = createRequestJSON(beginDate, endDate);
JSONObject responseJSON = callBaseFlowService(requestJSON);
String baseFlowFileName = getBaseFlowFileName(responseJSON);
File baseFlowOutFile = getBaseFlowFile(baseFlowFileName);
parseBaseFlowFile(baseFlowOutFile);
if (isPerennial()) {
getBaseFlow();
} else {
getWettedMonths();
}
for (int i = 0; i < 12; i++) {
if (monthlyCount[i] > 0) {
numberOfMonths++;
}
}
}
@Override
protected void postProcess() throws JSONException {
results().put("assessment_id", assessmentId, "Assessment Identifier");
results().put("station_id", stationId, "Station Identifier");
results().put("organization", organization, "Organization that the flow station belongs to (USGS | STORET | CDSN)");
results().put("stream_type", isPerennial() ? "Perennial" : "Intermittent", "Stream type (intermittent or perennial)");
String name = "number_of_" + (isPerennial() ? "months_at_baseflow" : "wetted_months");
String description = "Number of " + (isPerennial() ? "months at baseflow" : "wetted months");
results().put(name, numberOfMonths, description);
JSONArray monthArray = new JSONArray();
name = "number_of_" + (isPerennial() ? "days_at_baseflow_" : "wetted_days_");
description = "Number of " + (isPerennial() ? "days at baseflow in " : "wetted days in ");
for (int i = 0; i < 12; i++) {
monthArray.put(JSONUtils.dataDesc(name + SVAPUtils.MONTH_NAMES[i].toLowerCase().substring(0, 3), monthlyCount[i], description + SVAPUtils.MONTH_NAMES[i]));
}
results().put("month_list", monthArray);
}
private void validateSource() throws ServiceException {
if (!organization.equals("USGS") && !organization.equals("STORET") && !organization.equals("CDSN")) {
throw new ServiceException("Invalid Database");
}
}
private JSONObject createRequestJSON(String beginDate, String endDate) throws ServiceException, JSONException {
JSONObject requestJSON = new JSONObject();
JSONObject metainfo = new JSONObject();
metainfo.put("MultipartRequest", "Bundled Service Request");
metainfo.put("OriginalSource", request().getHost());
metainfo.put("OriginalRequest", request().getURL());
metainfo.put("OriginalSUID", getSUID());
requestJSON.put("metainfo", metainfo);
JSONArray parameter = new JSONArray();
parameter.put(JSONUtils.data("database", organization));
parameter.put(JSONUtils.data("org_id", ""));
parameter.put(JSONUtils.data("station_id", stationId));
parameter.put(JSONUtils.data("station_name", ""));
parameter.put(JSONUtils.data("begin_date", beginDate));
parameter.put(JSONUtils.data("end_date", endDate));
parameter.put(JSONUtils.data("ndmin", 10));
parameter.put(JSONUtils.data("ndmax", 10));
parameter.put(JSONUtils.data("drainage_area", 0));
parameter.put(JSONUtils.data("model_type", "BFLOW"));
parameter.put(JSONUtils.data("merge_datasets", false));
parameter.put(JSONUtils.data("merge_method", ""));
parameter.put(JSONUtils.data("user_data", ""));
requestJSON.put("parameter", parameter);
return requestJSON;
}
private JSONObject callBaseFlowService(JSONObject requestJSON) throws Exception {
String url = Config.getString("service.csip.baseflow.url", BASEFLOW_URL);
EntityBuilder builder = EntityBuilder.create();
builder.setText(requestJSON.toString());
builder.setContentType(ContentType.APPLICATION_JSON);
HttpPost post = new HttpPost(url);
post.setEntity(builder.build());
String response;
try (CloseableHttpClient httpClient = HttpClientBuilder.create().build();) {
try (CloseableHttpResponse httpResponse = httpClient.execute(post)) {
InputStream responseStream = httpResponse.getEntity().getContent();
response = IOUtils.toString(responseStream);
} catch (IOException ex) {
throw new SQLException("Communication error with SDM host: " + ex.getMessage(), ex);
} finally {
post.releaseConnection();
post.completed();
}
}
return new JSONObject(response);
}
private String getBaseFlowFileName(JSONObject responseJSON) throws JSONException {
JSONArray resultArray = responseJSON.getJSONArray("result");
Map<String, JSONObject> topLevel = JSONUtils.preprocess(resultArray);
String fileName = JSONUtils.getStringParam(topLevel, "baseflow.out", null);
return fileName;
}
private File getBaseFlowFile(String fileName) throws Exception {
Client client = new Client();
File file = new File("test.txt");
client.doGET(fileName, file);
return file;
}
private void parseBaseFlowFile(File file) throws FileNotFoundException, IOException, ParseException {
BufferedReader br = new BufferedReader(new FileReader(file));
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
for (int i = 0; i < 2; i++) {
br.readLine();
}
String line;
while ((line = br.readLine()) != null) {
String[] split = line.split(",");
if (split.length > 0 && Integer.parseInt(split[0].trim()) > 0) {
Date date = formatter.parse(split[0].trim() + "-" + split[1].trim() + "-" + split[2].trim());
double streamFlow = Double.parseDouble(split[3].trim());
double baseflow = Double.parseDouble(split[4].trim());
streamFlowList.add(new StreamFlow(date, streamFlow, baseflow));
}
}
}
private boolean isPerennial() {
for (StreamFlow stm : streamFlowList) {
if (stm.streamFlow <= 0) {
return false;
}
}
return true;
}
private void getWettedMonths() {
for (StreamFlow stm : streamFlowList) {
if (stm.streamFlow > 0) {
Calendar cal = Calendar.getInstance();
cal.setTime(stm.date);
int month = cal.get(Calendar.MONTH);
monthlyCount[month]++;
}
}
}
private void getBaseFlow() {
for (StreamFlow stm : streamFlowList) {
if (stm.streamFlow == stm.baseFlow) {
Calendar cal = Calendar.getInstance();
cal.setTime(stm.date);
int month = cal.get(Calendar.MONTH);
monthlyCount[month]++;
}
}
}
static class StreamFlow {
Date date;
double streamFlow;
double baseFlow;
public StreamFlow(Date date, double streamFlow, double baseFlow) {
this.date = date;
this.streamFlow = streamFlow;
this.baseFlow = baseFlow;
}
}
}