gernotbelger@9288: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
gernotbelger@9288: * Software engineering by Intevation GmbH
gernotbelger@9288: *
gernotbelger@9288: * This file is Free Software under the GNU AGPL (>=v3)
gernotbelger@9288: * and comes with ABSOLUTELY NO WARRANTY! Check out the
gernotbelger@9288: * documentation coming with Dive4Elements River for details.
gernotbelger@9288: */
gernotbelger@9288:
gernotbelger@9288: package org.dive4elements.river.client.server;
gernotbelger@9288:
gernotbelger@9288: import java.util.ArrayList;
gernotbelger@9288: import java.util.Arrays;
gernotbelger@9288: import java.util.Calendar;
gernotbelger@9288: import java.util.Comparator;
gernotbelger@9288: import java.util.List;
gernotbelger@9288:
gernotbelger@9288: import javax.xml.xpath.XPathConstants;
gernotbelger@9288:
gernotbelger@9288: import org.apache.log4j.Logger;
gernotbelger@9288: import org.dive4elements.artifacts.common.ArtifactNamespaceContext;
gernotbelger@9288: import org.dive4elements.artifacts.common.utils.XMLUtils;
gernotbelger@9288: import org.dive4elements.artifacts.httpclient.exceptions.ConnectionException;
gernotbelger@9288: import org.dive4elements.artifacts.httpclient.http.HttpClient;
gernotbelger@9288: import org.dive4elements.artifacts.httpclient.http.HttpClientImpl;
gernotbelger@9288: import org.dive4elements.river.client.shared.exceptions.ServerException;
gernotbelger@9288: import org.dive4elements.river.client.shared.model.WQInfoObject;
gernotbelger@9288: import org.dive4elements.river.client.shared.model.WQInfoObjectImpl;
gernotbelger@9288: import org.w3c.dom.Document;
gernotbelger@9288: import org.w3c.dom.Element;
gernotbelger@9288: import org.w3c.dom.Node;
gernotbelger@9288: import org.w3c.dom.NodeList;
gernotbelger@9288:
gernotbelger@9288: import com.google.gwt.user.server.rpc.RemoteServiceServlet;
gernotbelger@9288:
gernotbelger@9288: /**
gernotbelger@9288: * @author Ingo Weinzierl
gernotbelger@9288: */
gernotbelger@9288: abstract class AbstractMainValuesServiceImpl extends RemoteServiceServlet {
gernotbelger@9288:
mschaefer@9409: private static final Logger log = Logger.getLogger(AbstractMainValuesServiceImpl.class);
gernotbelger@9288:
gernotbelger@9288: private static final Comparator WQ_INFO_OBJECT_CMP = new Comparator() {
gernotbelger@9288: @Override
gernotbelger@9288: public int compare(final WQInfoObject a, final WQInfoObject b) {
gernotbelger@9288:
gernotbelger@9288: // Descending by type: Qs before Ds
gernotbelger@9288: final int cmp = a.getType().compareTo(b.getType());
gernotbelger@9288: if (cmp < 0)
gernotbelger@9288: return +1;
gernotbelger@9288: if (cmp > 0)
gernotbelger@9288: return -1;
gernotbelger@9288:
gernotbelger@9288: // Ascending by value
gernotbelger@9288: final double diff = a.getValue() - b.getValue();
gernotbelger@9288: if (diff < 0d)
gernotbelger@9288: return -1;
gernotbelger@9288: if (diff > 0d)
gernotbelger@9288: return +1;
gernotbelger@9288: return 0;
gernotbelger@9288: }
gernotbelger@9288: };
gernotbelger@9288:
gernotbelger@9288: private static final String ERROR_NO_WQINFO_FOUND = "error_no_wqinfo_found";
gernotbelger@9288:
gernotbelger@9288: private static final String XPATH_WQS = "art:service/art:mainvalues/art:mainvalue";
gernotbelger@9288:
gernotbelger@9288: private static final long serialVersionUID = 1L;
gernotbelger@9288:
gernotbelger@9404: public static final Document createInput(final String river, final double from, final double to, final java.util.Date startDate,
gernotbelger@9404: final java.util.Date endDate) {
gernotbelger@9288:
gernotbelger@9288: final Document input = XMLUtils.newDocument();
gernotbelger@9288:
gernotbelger@9288: final XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator(input, ArtifactNamespaceContext.NAMESPACE_URI,
gernotbelger@9288: ArtifactNamespaceContext.NAMESPACE_PREFIX);
gernotbelger@9288:
gernotbelger@9288: final Element mainvalues = ec.create("mainvalues");
gernotbelger@9288:
gernotbelger@9288: final Element riverEl = ec.create("river");
gernotbelger@9288: riverEl.setTextContent(river);
gernotbelger@9288: mainvalues.appendChild(riverEl);
gernotbelger@9288:
gernotbelger@9288: final Element startEl = ec.create("start");
gernotbelger@9288: startEl.setTextContent(Double.valueOf(from).toString());
gernotbelger@9288: mainvalues.appendChild(startEl);
gernotbelger@9288:
gernotbelger@9288: final Element endEl = ec.create("end");
gernotbelger@9288: endEl.setTextContent(Double.valueOf(to).toString());
gernotbelger@9288: mainvalues.appendChild(endEl);
gernotbelger@9288:
gernotbelger@9404: if (startDate != null) { // IMPORTANT, MainValueService and DynamicMainValueService share this method. MainvalueService does not have Dates
gernotbelger@9404: final Element startDateElement = ec.create("startDate");
gernotbelger@9404: startDateElement.setTextContent(String.valueOf(startDate.getTime()));
gernotbelger@9404: mainvalues.appendChild(startDateElement);
gernotbelger@9288: }
gernotbelger@9404: if (endDate != null) {// IMPORTANT, MainValueService and DynamicMainValueService share this method. MainvalueService does not have Dates
gernotbelger@9404: final Element endDateElement = ec.create("endDate");
gernotbelger@9404: endDateElement.setTextContent(String.valueOf(endDate.getTime()));
gernotbelger@9404: mainvalues.appendChild(endDateElement);
gernotbelger@9288: }
gernotbelger@9288:
gernotbelger@9288: input.appendChild(mainvalues);
gernotbelger@9288:
gernotbelger@9288: return input;
gernotbelger@9288: }
gernotbelger@9288:
gernotbelger@9288: protected final WQInfoObject[] callService(final String serviceName, final Document input, final String locale) throws ServerException {
gernotbelger@9288: final String url = getServletContext().getInitParameter("server-url");
gernotbelger@9288:
gernotbelger@9288: final HttpClient client = new HttpClientImpl(url, locale);
gernotbelger@9288:
gernotbelger@9288: try {
gernotbelger@9288: final Document result = client.callService(url, serviceName, input);
gernotbelger@9288:
gernotbelger@9288: log.debug("Extract wq info objects now.");
gernotbelger@9288: final WQInfoObject[] objects = extractWQInfoObjects(result);
gernotbelger@9288:
gernotbelger@9288: if (objects.length > 0) {
gernotbelger@9288: return objects;
gernotbelger@9288: }
gernotbelger@9288: }
gernotbelger@9288: catch (final ConnectionException ce) {
gernotbelger@9288: log.error(ce, ce);
gernotbelger@9288: }
gernotbelger@9288:
gernotbelger@9288: throw new ServerException(ERROR_NO_WQINFO_FOUND);
gernotbelger@9288: }
gernotbelger@9288:
gernotbelger@9288: /**
gernotbelger@9288: * Extracts all wq info objects from result document.
gernotbelger@9288: *
gernotbelger@9288: * @param result
gernotbelger@9288: * The document retrieved by the server.
gernotbelger@9288: *
gernotbelger@9288: * @return a list of WQInfoObjects.
gernotbelger@9288: */
gernotbelger@9288: private WQInfoObject[] extractWQInfoObjects(final Document result) throws ServerException {
gernotbelger@9288: final NodeList list = (NodeList) XMLUtils.xpath(result, XPATH_WQS, XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE);
gernotbelger@9288:
gernotbelger@9288: if (list == null || list.getLength() == 0) {
gernotbelger@9288: log.warn("No wq info found.");
gernotbelger@9288:
gernotbelger@9288: throw new ServerException(ERROR_NO_WQINFO_FOUND);
gernotbelger@9288: }
gernotbelger@9288:
gernotbelger@9288: final boolean debug = log.isDebugEnabled();
gernotbelger@9288:
gernotbelger@9288: final int num = list.getLength();
gernotbelger@9288: if (debug) {
gernotbelger@9288: log.debug("Response contains " + num + " objects.");
gernotbelger@9288: }
gernotbelger@9288:
gernotbelger@9288: final List objects = new ArrayList(num);
gernotbelger@9288:
gernotbelger@9288: for (int i = 0; i < num; i++) {
gernotbelger@9288: final WQInfoObject obj = buildWQInfoObject(list.item(i));
gernotbelger@9288:
gernotbelger@9288: if (obj != null) {
gernotbelger@9288: objects.add(obj);
gernotbelger@9288: }
gernotbelger@9288: }
gernotbelger@9288:
gernotbelger@9288: if (debug) {
gernotbelger@9288: log.debug("Retrieved " + objects.size() + " wq values");
gernotbelger@9288: }
gernotbelger@9288:
gernotbelger@9288: final WQInfoObject[] array = objects.toArray(new WQInfoObject[objects.size()]);
gernotbelger@9288:
gernotbelger@9288: Arrays.sort(array, WQ_INFO_OBJECT_CMP);
gernotbelger@9288:
gernotbelger@9288: return array;
gernotbelger@9288: }
gernotbelger@9288:
gernotbelger@9288: /**
gernotbelger@9288: * Extracts information for a single wq info object and intializes an
gernotbelger@9288: * WQInfoObject with them.
gernotbelger@9288: *
gernotbelger@9288: * @param node
gernotbelger@9288: * The node that contains the information.
gernotbelger@9288: *
gernotbelger@9288: * @return a valid WQInfoObject.
gernotbelger@9288: */
gernotbelger@9288: private static WQInfoObject buildWQInfoObject(final Node node) {
gernotbelger@9288:
gernotbelger@9288: final String name = XMLUtils.xpathString(node, "@name", ArtifactNamespaceContext.INSTANCE);
gernotbelger@9288:
gernotbelger@9288: final String type = XMLUtils.xpathString(node, "@type", ArtifactNamespaceContext.INSTANCE);
gernotbelger@9288:
gernotbelger@9288: final String value = XMLUtils.xpathString(node, "@value", ArtifactNamespaceContext.INSTANCE);
gernotbelger@9288:
gernotbelger@9288: final String official = XMLUtils.xpathString(node, "@official", ArtifactNamespaceContext.INSTANCE);
gernotbelger@9288:
gernotbelger@9288: final String starttime = XMLUtils.xpathString(node, "@starttime", ArtifactNamespaceContext.INSTANCE);
gernotbelger@9288:
gernotbelger@9288: final String stoptime = XMLUtils.xpathString(node, "@stoptime", ArtifactNamespaceContext.INSTANCE);
gernotbelger@9288:
gernotbelger@9288: if (name != null && type != null) {
gernotbelger@9288: try {
gernotbelger@9288: final Calendar cal = Calendar.getInstance();
gernotbelger@9288: java.util.Date start = null;
gernotbelger@9288: java.util.Date stop = null;
gernotbelger@9288: if (!starttime.equals("")) {
gernotbelger@9288: cal.setTimeInMillis(Long.parseLong(starttime));
gernotbelger@9288: start = cal.getTime();
gernotbelger@9288: }
gernotbelger@9288: if (!stoptime.equals("")) {
gernotbelger@9288: cal.setTimeInMillis(Long.parseLong(stoptime));
gernotbelger@9288: stop = cal.getTime();
gernotbelger@9288: }
gernotbelger@9288: return new WQInfoObjectImpl(name, type, new Double(value), official != null && official.equalsIgnoreCase("true"), start, stop);
gernotbelger@9288: }
gernotbelger@9288: catch (final NumberFormatException nfe) {
gernotbelger@9288: log.warn(nfe.getLocalizedMessage());
gernotbelger@9288: }
gernotbelger@9288: }
gernotbelger@9288:
gernotbelger@9288: log.warn("Invalid wq info object found.");
gernotbelger@9288:
gernotbelger@9288: return null;
gernotbelger@9288: }
gernotbelger@9288: }