[PATCH 2 of 2] bundu.bezugswst worklflow incl. service impl for mainValues to be calculated
Wald Commits
scm-commit at wald.intevation.org
Tue Jul 24 10:39:13 CEST 2018
# HG changeset patch
# User gernotbelger
# Date 1532421543 -7200
# Node ID 82c67b859aa771de5df19776d2eb2bf1aa9415aa
# Parent 6c88ad449c832b809ae027b040d7f82caf0d43c7
bundu.bezugswst worklflow incl. service impl for mainValues to be calculated
diff -r 6c88ad449c83 -r 82c67b859aa7 artifacts/doc/conf/artifacts/bundu.xml
--- a/artifacts/doc/conf/artifacts/bundu.xml Tue Jul 24 10:36:18 2018 +0200
+++ b/artifacts/doc/conf/artifacts/bundu.xml Tue Jul 24 10:39:03 2018 +0200
@@ -327,7 +327,7 @@
<state id="state.bundu.yearselect" helpText="state.bundu.yearselect" description="state.bundu.yearselect" state="org.dive4elements.river.artifacts.bundu.bezugswst.FixationPeriod">
<data name="singleyear" type="String" />
- <data name="events_temp" type="intarray" /> <!--necessary, because they will be set automatically -->
+ <data name="events_temp" type="String" /> <!-- String. -->
</state>
@@ -390,8 +390,9 @@
</transition>
<state id="state.bundu.wst.qs" description="state.bundu.wst.qs" helpText="help.state.bundu.wst.qs" state="org.dive4elements.river.artifacts.bundu.bezugswst.BunduWstWQFixing">
- <data name="wq_isq" type="String" />
+ <data name="bundu.wst.mode" type="String" />
<data name="wq_values" type="WQTriple" />
+ <data name="bundu.wst.ud_value" type ="Integer"/>
</state>
diff -r 6c88ad449c83 -r 82c67b859aa7 artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BunduWstWQFixing.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BunduWstWQFixing.java Tue Jul 24 10:36:18 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BunduWstWQFixing.java Tue Jul 24 10:39:03 2018 +0200
@@ -12,7 +12,6 @@
import org.dive4elements.artifacts.CallContext;
import org.dive4elements.artifacts.common.utils.XMLUtils;
import org.dive4elements.river.artifacts.D4EArtifact;
-import org.dive4elements.river.artifacts.model.RangeWithValues;
import org.dive4elements.river.artifacts.states.WQAdapted;
import org.w3c.dom.Element;
@@ -23,6 +22,8 @@
*/
public class BunduWstWQFixing extends WQAdapted {
+ private static final long serialVersionUID = 1L;
+
/** The log used in this state. */
private static Logger log = Logger.getLogger(BunduWstWQFixing.class);
@@ -31,45 +32,30 @@
return "bundu_wst_wq_panel";
}
- /** Simple sanity check if values are positive numbers **/
@Override
public boolean validate(final Artifact artifact) throws IllegalArgumentException {
- log.debug("BunduWstWQFixing.validate");
- final RangeWithValues[] rwvs = extractInput(getData((D4EArtifact) artifact, "wq_values"));
-
- if (rwvs == null) {
- throw new IllegalArgumentException("error_missing_wq_data");
- }
-
- for (final RangeWithValues rwv : rwvs) {
- final double[] values = rwv.getValues();
- for (final double val : values) {
- if (val <= 0) {
- throw new IllegalArgumentException("error_validate_positive");
- }
- }
- }
-
+ // Validation is done on client side. No wrong inputs should arrive here.
+ // Validation in Super is not suitable for this case
return true;
}
// adding bezugsjahr and dauer to client
-
@Override
protected Element[] createItems(final XMLUtils.ElementCreator ec, final Artifact artifact, final String name, final CallContext context) {
final Element[] defaultElements = super.createItems(ec, artifact, name, context);
+ if (name.equals("bundu.wst.mode")) { // random-name eines DataItems vom state (s. bundu.xml), sodass verhindert wird, dass an alle DataItems
+ // length+bezugsjahr drangehängt werden
+ final BunduAccess access = new BunduAccess((D4EArtifact) artifact);
- final BunduAccess access = new BunduAccess((D4EArtifact) artifact);
+ final int bezugsjahr = access.getBezugsJahr();
+ final int qSeriesLength = access.getQSeriesLength();
+ final String[] keys = new String[] { "ignore_q_series_length", "ignore_bezugsjahr" };
+ final String[] values = new String[] { String.valueOf(qSeriesLength), String.valueOf(bezugsjahr) };
- final int bezugsjahr = access.getBezugsJahr();
- final int qSeriesLength = access.getQSeriesLength();
- final String[] keys = new String[] { "ignore_q_series_length", "ignore_bezugsjahr" };
- final String[] values = new String[] { String.valueOf(qSeriesLength), String.valueOf(bezugsjahr) };
-
- return FixationChoice.appendElements(ec, defaultElements, keys, values);
-
+ return FixationChoice.appendElements(ec, defaultElements, keys, values);
+ } else
+ return defaultElements;
}
-
-}
+}
\ No newline at end of file
diff -r 6c88ad449c83 -r 82c67b859aa7 artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/FixationChoice.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/FixationChoice.java Tue Jul 24 10:36:18 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/FixationChoice.java Tue Jul 24 10:39:03 2018 +0200
@@ -65,14 +65,15 @@
public static final Element[] appendElements(final ElementCreator ec, final Element[] defaultElements, final String[] keys, final String[] values) {
assert (values.length == keys.length);
// make bigger array
- final Element[] defaultAndAddedElements = new Element[defaultElements.length + values.length];
+ final int defaultLength = defaultElements == null ? 0 : defaultElements.length;
+ final Element[] defaultAndAddedElements = new Element[defaultLength + values.length];
- for (int i = 0; i < defaultElements.length; i++) {
+ for (int i = 0; i < defaultLength; i++) {
defaultAndAddedElements[i] = defaultElements[i];
}
// add the new values:
for (int j = 0; j < keys.length; j++) {
- defaultAndAddedElements[defaultElements.length + j] = createItem(ec, new String[] { keys[j], values[j] });
+ defaultAndAddedElements[defaultLength + j] = createItem(ec, new String[] { keys[j], values[j] });
}
return defaultAndAddedElements;
}
diff -r 6c88ad449c83 -r 82c67b859aa7 artifacts/src/main/java/org/dive4elements/river/artifacts/services/AbstractMainValuesService.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/AbstractMainValuesService.java Tue Jul 24 10:39:03 2018 +0200
@@ -0,0 +1,255 @@
+/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+
+package org.dive4elements.river.artifacts.services;
+
+import static org.dive4elements.river.backend.utils.EpsilonComparator.CMP;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.common.ArtifactNamespaceContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils;
+import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
+import org.dive4elements.river.artifacts.model.RiverFactory;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.MainValue;
+import org.dive4elements.river.model.MainValueType;
+import org.dive4elements.river.model.NamedMainValue;
+import org.dive4elements.river.model.OfficialLine;
+import org.dive4elements.river.model.Range;
+import org.dive4elements.river.model.River;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * @author <a href="mailto:ingo.weinzierl at intevation.de">Ingo Weinzierl</a>
+ */
+abstract class AbstractMainValuesService extends D4EService {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final class MainValuesServiceException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public MainValuesServiceException(final String message) {
+ super(message);
+ }
+ }
+
+ /** The log that is used by this service. */
+ private static Logger log = Logger.getLogger(AbstractMainValuesService.class);
+
+ /** XPath that points to the river definition of the incoming request. */
+ private static final String XPATH_RIVER = "/art:mainvalues/art:river/text()";
+
+ /** XPath that points to the start definition of the incoming request. */
+ private static final String XPATH_START = "/art:mainvalues/art:start/text()";
+
+ /** The XPath that points to the end definition of the incoming request. */
+ private static final String XPATH_END = "/art:mainvalues/art:end/text()";
+
+ protected static final Document error(final String msg) {
+ log.debug(msg);
+ return XMLUtils.newDocument();
+ }
+
+ /**
+ * This method extracts the river from the incoming request. If no river
+ * string was found or no river is found in the database based on this
+ * string a NullPointerException is thrown.
+ *
+ * @param data
+ * The incoming request data.
+ *
+ * @return the River object.
+ */
+ protected final River getRequestedRiver(final Document data) throws MainValuesServiceException {
+ log.debug("MainValuesService.getRequestedRiver");
+
+ String riverStr = XMLUtils.xpathString(data, XPATH_RIVER, ArtifactNamespaceContext.INSTANCE);
+
+ if (riverStr != null && (riverStr = riverStr.trim()).length() > 0)
+ return RiverFactory.getRiver(riverStr);
+
+ throw new MainValuesServiceException("no river found.");
+ }
+
+ protected final Gauge getRequestedGauge(final Document data, final River river) throws MainValuesServiceException {
+
+ final double[] minmax = getRequestedStartEnd(data, river);
+ final Gauge gauge = river.determineRefGauge(minmax, CMP.compare(minmax[0], minmax[1]) != 0);
+ if (gauge == null)
+ throw new MainValuesServiceException("no gauge found.");
+
+ return gauge;
+ }
+
+ /**
+ * This method extracts the start and end point from incoming request
+ * document and returns both values in an array.
+ * If no start and end strings
+ * are found in the document, the min/max values of the <i>river</i> are
+ * returned.
+ *
+ * @param data
+ * The incoming request data.
+ * @param river
+ * The river of the request.
+ *
+ * @return the start and end point.
+ */
+ private double[] getRequestedStartEnd(final Document data, final River river) {
+ log.debug("MainValuesService.getStartEnd");
+
+ final String startStr = XMLUtils.xpathString(data, XPATH_START, ArtifactNamespaceContext.INSTANCE);
+
+ final String endStr = XMLUtils.xpathString(data, XPATH_END, ArtifactNamespaceContext.INSTANCE);
+
+ if (startStr == null || endStr == null) {
+ return river.determineMinMaxDistance();
+ }
+
+ try {
+ final double start = Double.parseDouble(startStr);
+ final double end = Double.parseDouble(endStr);
+
+ if (log.isDebugEnabled()) {
+ log.debug("Found start: " + start);
+ log.debug("Found end: " + end);
+ }
+
+ return new double[] { start, end };
+ }
+ catch (final NumberFormatException nfe) {
+ log.warn(nfe, nfe);
+ return river.determineMinMaxDistance();
+ }
+ }
+
+ protected final Document buildDocument(final River river, final Gauge gauge, final List<MainValue> mainValues, final Object context) {
+ log.debug("MainValuesService.buildDocument");
+
+ final Document doc = XMLUtils.newDocument();
+
+ final ElementCreator cr = new ElementCreator(doc, ArtifactNamespaceContext.NAMESPACE_URI, ArtifactNamespaceContext.NAMESPACE_PREFIX);
+
+ final Element rootEl = cr.create("service");
+ cr.addAttr(rootEl, "name", "mainvalues");
+
+ doc.appendChild(rootEl);
+
+ appendMetaInformation(doc, rootEl, river, gauge, context);
+ appendMainValues(doc, rootEl, mainValues, river.getId(), context);
+
+ return doc;
+ }
+
+ /**
+ * This method appends some meta information to the result document.
+ * Currently, the river's and gauge's names and the gauge's range are
+ * appended.
+ *
+ * @param root
+ * The root element of the result document.
+ * @param river
+ * The river.
+ * @param gauge
+ * The gauge.
+ * @param context
+ * The context object.
+ */
+ private void appendMetaInformation(final Document doc, final Element root, final River river, final Gauge gauge, final Object context) {
+ log.debug("MainValuesService.appendMetaInformation");
+
+ final ElementCreator cr = new ElementCreator(doc, ArtifactNamespaceContext.NAMESPACE_URI, ArtifactNamespaceContext.NAMESPACE_PREFIX);
+
+ final Range range = gauge.getRange();
+
+ final Element riverEl = cr.create("river");
+ cr.addAttr(riverEl, "name", river.getName());
+
+ final Element gaugeEl = cr.create("gauge");
+ cr.addAttr(gaugeEl, "name", gauge.getName());
+ cr.addAttr(gaugeEl, "from", range.getA().toString());
+ cr.addAttr(gaugeEl, "to", range.getB().toString());
+
+ root.appendChild(riverEl);
+ root.appendChild(gaugeEl);
+ }
+
+ /** Checks i a main value has an official associated, */
+ private static boolean hasOfficialLine(final NamedMainValue nmv, final Integer riverId) {
+ for (final OfficialLine ol : nmv.getOfficialLines()) {
+ if (ol.getWstColumn().getWst().getRiver().getId().equals(riverId)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** Append xml representation of main values to document. */
+ private void appendMainValues(final Document doc, final Element root, final List<MainValue> mainValues, final Integer riverId, final Object context) {
+ log.debug("MainValuesService.appendMainValues");
+
+ final ElementCreator cr = new ElementCreator(doc, ArtifactNamespaceContext.NAMESPACE_URI, ArtifactNamespaceContext.NAMESPACE_PREFIX);
+
+ final Element list = cr.create("mainvalues");
+
+ for (final MainValue mainValue : mainValues) {
+ final Element newEl = buildMainValueElement(doc, mainValue, riverId, context);
+
+ if (newEl != null) {
+ list.appendChild(newEl);
+ }
+ }
+
+ root.appendChild(list);
+ }
+
+ /**
+ * This method builds a concrete mainvalue element. This element consists of
+ * three attributes: the value, its name and its type.
+ *
+ * @param doc
+ * The owner document.
+ * @param mainValue
+ * The mainvalue.
+ * @param context
+ * The context object.
+ *
+ * @return a mainvalue element.
+ */
+ private Element buildMainValueElement(final Document doc, final MainValue mainValue, final Integer riverId, final Object context) {
+ final ElementCreator cr = new ElementCreator(doc, ArtifactNamespaceContext.NAMESPACE_URI, ArtifactNamespaceContext.NAMESPACE_PREFIX);
+
+ final NamedMainValue namedMainValue = mainValue.getMainValue();
+ final MainValueType mainValueType = namedMainValue.getType();
+
+ final Element el = cr.create("mainvalue");
+
+ cr.addAttr(el, "value", mainValue.getValue().toString());
+ cr.addAttr(el, "name", namedMainValue.getName());
+ cr.addAttr(el, "type", mainValueType.getName());
+ if (mainValue.getTimeInterval() != null) {
+ if (mainValue.getTimeInterval().getStartTime() != null) {
+ cr.addAttr(el, "starttime", Long.toString(mainValue.getTimeInterval().getStartTime().getTime()));
+ }
+ if (mainValue.getTimeInterval().getStopTime() != null) {
+ cr.addAttr(el, "stoptime", Long.toString(mainValue.getTimeInterval().getStopTime().getTime()));
+ }
+ }
+
+ if (hasOfficialLine(namedMainValue, riverId)) {
+ cr.addAttr(el, "official", "true");
+ }
+
+ return el;
+ }
+}
\ No newline at end of file
diff -r 6c88ad449c83 -r 82c67b859aa7 artifacts/src/main/java/org/dive4elements/river/artifacts/services/DynamicMainValuesService.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/DynamicMainValuesService.java Tue Jul 24 10:39:03 2018 +0200
@@ -0,0 +1,146 @@
+/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+
+package org.dive4elements.river.artifacts.services;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+import org.dive4elements.artifacts.CallMeta;
+import org.dive4elements.artifacts.GlobalContext;
+import org.dive4elements.artifacts.common.ArtifactNamespaceContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.MainValue;
+import org.dive4elements.river.model.MainValueType;
+import org.dive4elements.river.model.MainValueType.MainValueTypeKey;
+import org.dive4elements.river.model.NamedMainValue;
+import org.dive4elements.river.model.OfficialLine;
+import org.dive4elements.river.model.River;
+import org.dive4elements.river.model.TimeInterval;
+import org.w3c.dom.Document;
+
+/**
+ * This service returns the main values of a river's gauge based on the start
+ * and end point of the river.
+ *
+ * @author <a href="mailto:ingo.weinzierl at intevation.de">Ingo Weinzierl</a>
+ */
+public class DynamicMainValuesService extends AbstractMainValuesService {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final String XPATH_START_YEAR = "/art:mainvalues/art:startYear/text()";
+
+ private static final String XPATH_END_YEAR = "/art:mainvalues/art:endYear/text()";
+
+ @Override
+ public Document doProcess(final Document data, final GlobalContext context, final CallMeta callMeta) {
+ try {
+
+ final River river = getRequestedRiver(data);
+ final Gauge gauge = getRequestedGauge(data, river);
+ final Date startTime = getRequestedStartYear(data);
+ final Date endTime = getRequestedEndYear(data);
+
+ final List<MainValue> mainValues = getMainValues(river, gauge, startTime, endTime);
+
+ return buildDocument(river, gauge, mainValues, context);
+ }
+ catch (final MainValuesServiceException e) {
+ e.printStackTrace();
+ return error(e.getMessage());
+ }
+ }
+
+ private Date getRequestedStartYear(final Document data) throws MainValuesServiceException {
+
+ final String startStr = XMLUtils.xpathString(data, XPATH_START_YEAR, ArtifactNamespaceContext.INSTANCE);
+
+ if (startStr == null)
+ throw new MainValuesServiceException("no start year");
+
+ try {
+ final int year = Integer.parseInt(startStr);
+
+ // FIXME: timezone? probably must match timezone of database
+ final Calendar cal = Calendar.getInstance();
+ cal.clear();
+ cal.set(year, 0, 1);
+ return cal.getTime();
+ }
+ catch (final NumberFormatException e) {
+ e.printStackTrace();
+ throw new MainValuesServiceException("invalid start year");
+ }
+ }
+
+ private Date getRequestedEndYear(final Document data) throws MainValuesServiceException {
+
+ final String endStr = XMLUtils.xpathString(data, XPATH_END_YEAR, ArtifactNamespaceContext.INSTANCE);
+
+ if (endStr == null)
+ throw new MainValuesServiceException("no end year");
+
+ try {
+ final int year = Integer.parseInt(endStr);
+
+ // FIXME: timezone? probably must match timezone of database
+ final Calendar cal = Calendar.getInstance();
+ cal.clear();
+ cal.set(year, 11, 31);
+ return cal.getTime();
+ }
+ catch (final NumberFormatException e) {
+ e.printStackTrace();
+ throw new MainValuesServiceException("invalid end year");
+ }
+ }
+
+ /**
+ * This method creates the result document that includes the main values of
+ * the specified <i>gauge</i>.
+ *
+ * @param river
+ * The river.
+ * @param gauge
+ * The gauge.
+ * @param endYear
+ * @param startYear
+ *
+ * @return a document that includes the main values of the specified river
+ * at the specified gauge.
+ */
+ protected List<MainValue> getMainValues(final River river, final Gauge gauge, final Date startTime, final Date endTime) {
+
+ // TODO: compute our own main values from the discharge timeseries.
+
+ // final List<MainValue> mainValues = gauge.getMainValues();
+ final List<MainValue> mainValues = new ArrayList<>();
+
+ final MainValue myMain = new MainValue();
+
+ // TODO: fetch real NamedMainValue from database: GLQ20, MNQ, MQ, MHQ, HQ5 + Dauerzahlen
+ final NamedMainValue mainValue = new NamedMainValue("Testname", new MainValueType(MainValueTypeKey.Q.getName()));
+ mainValue.setOfficialLines(new ArrayList<OfficialLine>());
+
+ myMain.setMainValue(mainValue);
+ // FIXME: compute value
+ myMain.setValue(new BigDecimal("1234.567"));
+
+ final TimeInterval timeInterval = new TimeInterval(startTime, endTime);
+ myMain.setTimeInterval(timeInterval);
+
+ mainValues.add(myMain);
+
+ return mainValues;
+ }
+}
\ No newline at end of file
diff -r 6c88ad449c83 -r 82c67b859aa7 artifacts/src/main/java/org/dive4elements/river/artifacts/services/MainValuesService.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/MainValuesService.java Tue Jul 24 10:36:18 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/MainValuesService.java Tue Jul 24 10:39:03 2018 +0200
@@ -11,29 +11,12 @@
import java.util.List;
import org.apache.log4j.Logger;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
import org.dive4elements.artifacts.CallMeta;
import org.dive4elements.artifacts.GlobalContext;
-
-import org.dive4elements.artifacts.common.ArtifactNamespaceContext;
-import org.dive4elements.artifacts.common.utils.XMLUtils;
-import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator;
-
import org.dive4elements.river.model.Gauge;
import org.dive4elements.river.model.MainValue;
-import org.dive4elements.river.model.MainValueType;
-import org.dive4elements.river.model.NamedMainValue;
-import org.dive4elements.river.model.OfficialLine;
-import org.dive4elements.river.model.Range;
import org.dive4elements.river.model.River;
-
-import org.dive4elements.river.artifacts.model.RiverFactory;
-
-import static org.dive4elements.river.backend.utils.EpsilonComparator.CMP;
-
+import org.w3c.dom.Document;
/**
* This service returns the main values of a river's gauge based on the start
@@ -41,143 +24,42 @@
*
* @author <a href="mailto:ingo.weinzierl at intevation.de">Ingo Weinzierl</a>
*/
-public class MainValuesService extends D4EService {
+public class MainValuesService extends AbstractMainValuesService {
- /** The log that is used by this service.*/
+ private static final long serialVersionUID = 1L;
+
+ /** The log that is used by this service. */
private static Logger log = Logger.getLogger(MainValuesService.class);
- /** XPath that points to the river definition of the incoming request.*/
- public static final String XPATH_RIVER =
- "/art:mainvalues/art:river/text()";
+ @Override
+ public Document doProcess(final Document data, final GlobalContext context, final CallMeta callMeta) {
+ try {
+ final River river = getRequestedRiver(data);
+ final Gauge gauge = getRequestedGauge(data, river);
- /** XPath that points to the start definition of the incoming request.*/
- public static final String XPATH_START =
- "/art:mainvalues/art:start/text()";
+ final List<MainValue> mainValues = getMainValues(river, gauge);
- /** The XPath that points to the end definition of the incoming request.*/
- public static final String XPATH_END = "/art:mainvalues/art:end/text()";
-
- protected CallMeta callMeta;
-
-
- /**
- * The default constructor.
- */
- public MainValuesService() {
- }
-
- private static final Document error(String msg) {
- log.debug(msg);
- return XMLUtils.newDocument();
- }
-
-
- @Override
- public Document doProcess(
- Document data,
- GlobalContext context,
- CallMeta callMeta
- ) {
- log.debug("MainValuesService.process");
-
- this.callMeta = callMeta;
-
- River river = getRequestedRiver(data);
- if (river == null) {
- return error("no river found.");
+ return buildDocument(river, gauge, mainValues, context);
}
-
- double[] minmax = getRequestedStartEnd(data, river);
- Gauge gauge = river.determineRefGauge(minmax,
- CMP.compare(minmax[0], minmax[1]) != 0);
-
- if (gauge == null) {
- return error("no gauge found.");
- }
-
- List<MainValue> mainValues = getMainValues(river, gauge);
-
- return buildDocument(river, gauge, mainValues, context);
- }
-
-
- /**
- * This method extracts the river from the incoming request. If no river
- * string was found or no river is found in the database based on this
- * string a NullPointerException is thrown.
- *
- * @param data The incoming request data.
- *
- * @return the River object.
- */
- protected River getRequestedRiver(Document data)
- throws NullPointerException
- {
- log.debug("MainValuesService.getRequestedRiver");
-
- String riverStr = XMLUtils.xpathString(
- data, XPATH_RIVER, ArtifactNamespaceContext.INSTANCE);
-
- return riverStr != null && (riverStr = riverStr.trim()).length() > 0
- ? RiverFactory.getRiver(riverStr)
- : null;
- }
-
-
- /**
- * This method extracts the start and end point from incoming request
- * document and returns both values in an array.
- * If no start and end strings
- * are found in the document, the min/max values of the <i>river</i> are
- * returned.
- *
- * @param data The incoming request data.
- * @param river The river of the request.
- *
- * @return the start and end point.
- */
- protected double[] getRequestedStartEnd(Document data, River river) {
- log.debug("MainValuesService.getStartEnd");
-
- String startStr = XMLUtils.xpathString(
- data, XPATH_START, ArtifactNamespaceContext.INSTANCE);
-
- String endStr = XMLUtils.xpathString(
- data, XPATH_END, ArtifactNamespaceContext.INSTANCE);
-
- if (startStr == null || endStr == null) {
- return river.determineMinMaxDistance();
- }
-
- try {
- double start = Double.parseDouble(startStr);
- double end = Double.parseDouble(endStr);
-
- if (log.isDebugEnabled()) {
- log.debug("Found start: " + start);
- log.debug("Found end: " + end);
- }
-
- return new double[] { start, end };
- }
- catch (NumberFormatException nfe) {
- log.warn(nfe, nfe);
- return river.determineMinMaxDistance();
+ catch (final MainValuesServiceException e) {
+ e.printStackTrace();
+ return error(e.getMessage());
}
}
-
/**
* This method creates the result document that includes the main values of
* the specified <i>gauge</i>.
*
- * @param river The river.
- * @param gauge The gauge.
+ * @param river
+ * The river.
+ * @param gauge
+ * The gauge.
*
* @return a document that includes the main values of the specified river
- * at the specified gauge.
+ * at the specified gauge.
*/
- protected List<MainValue> getMainValues(River river, Gauge gauge) {
+ protected List<MainValue> getMainValues(final River river, final Gauge gauge) {
if (log.isDebugEnabled()) {
log.debug("MainValuesService.buildMainValues");
@@ -185,7 +67,7 @@
log.debug("Gauge: " + gauge.getName());
}
- List<MainValue> mainValues = gauge.getMainValues();
+ final List<MainValue> mainValues = gauge.getMainValues();
if (log.isDebugEnabled()) {
log.debug(mainValues.size() + " main values found.");
@@ -193,167 +75,4 @@
return mainValues;
}
-
-
- protected Document buildDocument(
- River river,
- Gauge gauge,
- List<MainValue> mainValues,
- Object context)
- {
- log.debug("MainValuesService.buildDocument");
-
- Document doc = XMLUtils.newDocument();
-
- ElementCreator cr = new ElementCreator(
- doc,
- ArtifactNamespaceContext.NAMESPACE_URI,
- ArtifactNamespaceContext.NAMESPACE_PREFIX);
-
- Element rootEl = cr.create("service");
- cr.addAttr(rootEl, "name", "mainvalues");
-
- doc.appendChild(rootEl);
-
- appendMetaInformation(doc, rootEl, river, gauge, context);
- appendMainValues(doc, rootEl, mainValues, river.getId(), context);
-
- return doc;
- }
-
-
- /**
- * This method appends some meta information to the result document.
- * Currently, the river's and gauge's names and the gauge's range are
- * appended.
- *
- * @param root The root element of the result document.
- * @param river The river.
- * @param gauge The gauge.
- * @param context The context object.
- */
- protected void appendMetaInformation(
- Document doc,
- Element root,
- River river,
- Gauge gauge,
- Object context)
- {
- log.debug("MainValuesService.appendMetaInformation");
-
- ElementCreator cr = new ElementCreator(
- doc,
- ArtifactNamespaceContext.NAMESPACE_URI,
- ArtifactNamespaceContext.NAMESPACE_PREFIX);
-
- Range range = gauge.getRange();
-
- Element riverEl = cr.create("river");
- cr.addAttr(riverEl, "name", river.getName());
-
- Element gaugeEl = cr.create("gauge");
- cr.addAttr(gaugeEl, "name", gauge.getName());
- cr.addAttr(gaugeEl, "from", range.getA().toString());
- cr.addAttr(gaugeEl, "to", range.getB().toString());
-
- root.appendChild(riverEl);
- root.appendChild(gaugeEl);
- }
-
-
- /** Checks i a main value has an official associated, */
- protected static boolean hasOfficialLine(
- NamedMainValue nmv,
- Integer riverId
- ) {
- for (OfficialLine ol: nmv.getOfficialLines()) {
- if (
- ol.getWstColumn().getWst().getRiver().getId().equals(riverId)
- ) {
- return true;
- }
- }
- return false;
- }
-
-
- /** Append xml representation of main values to document. */
- protected void appendMainValues(
- Document doc,
- Element root,
- List<MainValue> mainValues,
- Integer riverId,
- Object context)
- {
- log.debug("MainValuesService.appendMainValues");
-
- ElementCreator cr = new ElementCreator(
- doc,
- ArtifactNamespaceContext.NAMESPACE_URI,
- ArtifactNamespaceContext.NAMESPACE_PREFIX);
-
- Element list = cr.create("mainvalues");
-
- for (MainValue mainValue: mainValues) {
- Element newEl = buildMainValueElement(
- doc, mainValue, riverId, context);
-
- if (newEl != null) {
- list.appendChild(newEl);
- }
- }
-
- root.appendChild(list);
- }
-
-
- /**
- * This method builds a concrete mainvalue element. This element consists of
- * three attributes: the value, its name and its type.
- *
- * @param doc The owner document.
- * @param mainValue The mainvalue.
- * @param context The context object.
- *
- * @return a mainvalue element.
- */
- protected Element buildMainValueElement(
- Document doc,
- MainValue mainValue,
- Integer riverId,
- Object context)
- {
- ElementCreator cr = new ElementCreator(
- doc,
- ArtifactNamespaceContext.NAMESPACE_URI,
- ArtifactNamespaceContext.NAMESPACE_PREFIX);
-
- NamedMainValue namedMainValue = mainValue.getMainValue();
- MainValueType mainValueType = namedMainValue.getType();
-
- Element el = cr.create("mainvalue");
-
- cr.addAttr(el, "value", mainValue.getValue().toString());
- cr.addAttr(el, "name", namedMainValue.getName());
- cr.addAttr(el, "type", mainValueType.getName());
- if (mainValue.getTimeInterval() != null) {
- if (mainValue.getTimeInterval().getStartTime() != null) {
- cr.addAttr(el, "starttime",
- Long.toString(
- mainValue.getTimeInterval().getStartTime().getTime()));
- }
- if (mainValue.getTimeInterval().getStopTime() != null) {
- cr.addAttr(el, "stoptime",
- Long.toString(
- mainValue.getTimeInterval().getStopTime().getTime()));
- }
- }
-
- if (hasOfficialLine(namedMainValue, riverId)) {
- cr.addAttr(el, "official", "true");
- }
-
- return el;
- }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ No newline at end of file
diff -r 6c88ad449c83 -r 82c67b859aa7 gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java Tue Jul 24 10:36:18 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java Tue Jul 24 10:39:03 2018 +0200
@@ -1586,4 +1586,8 @@
String bundu_bezugswst_auto_event_choice();
String years_general();
+
+ String bundu_bezugswst_mode_ud();
+
+ String bundu_bezugswst_validation_range();
}
\ No newline at end of file
diff -r 6c88ad449c83 -r 82c67b859aa7 gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties Tue Jul 24 10:36:18 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties Tue Jul 24 10:39:03 2018 +0200
@@ -846,6 +846,8 @@
bundu = Betrieb und Unterhaltung
bundu_bezugswst_fix_choice_title= Fixierungsauswahl
bundu_bezugswst_auto_event_choice = Automatische Ereignisauswahl
+bundu_bezugswst_mode_ud = UD am Pegel [d/a]
+bundu_bezugswst_validation_range = Die Eingabe muss eine Ganzzahl zwischen 0 und 364 sein.
chart_settings_export_metadata = Show Meta-Data
export_csv_title = Title:
diff -r 6c88ad449c83 -r 82c67b859aa7 gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties Tue Jul 24 10:36:18 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties Tue Jul 24 10:39:03 2018 +0200
@@ -835,7 +835,7 @@
uinfo_vegetation_zones_from = \u00dcfd von [d/a]
uinfo_vegetation_zones_to = \u00dcfd bis [d/a]
uinfo_vegetation_zones_validation_empty = Eingabefeld leer.
-uinfo_vegetation_zones_validation_range = Werte m\u00fcssen zwischen 0 und 365 liegen.
+uinfo_vegetation_zones_validation_range = Werte m\u00fcssen zwischen 0 und 365 liegen.
uinfo_vegetation_zones_validation_from_greater_to = Der Wert f\u00fcr "\u00dcfd von" muss kleiner als "\u00dcfd bis".
uinfo_salix_km_limit_exceed = Die Zahl ist au\u00dferhalb des g\u00fcltigen km-Bereichs.
uinfo_salix_km_overlap = Km-Bereiche \u00fcberlappen.
@@ -846,6 +846,8 @@
bundu = Betrieb und Unterhaltung
bundu_bezugswst_fix_choice_title= Fixierungsauswahl
bundu_bezugswst_auto_event_choice = Automatische Ereignisauswahl
+bundu_bezugswst_mode_ud = UD am Pegel [d/a]
+bundu_bezugswst_validation_range = Die Eingabe muss eine Ganzzahl zwischen 0 und 364 sein.
chart_settings_export_metadata = Metadaten anzeigen
export_csv_title = Titel:
diff -r 6c88ad449c83 -r 82c67b859aa7 gwt-client/src/main/java/org/dive4elements/river/client/client/services/DynamicMainValuesService.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/services/DynamicMainValuesService.java Tue Jul 24 10:39:03 2018 +0200
@@ -0,0 +1,29 @@
+/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+
+package org.dive4elements.river.client.client.services;
+
+import org.dive4elements.river.client.shared.exceptions.ServerException;
+import org.dive4elements.river.client.shared.model.WQInfoObject;
+
+import com.google.gwt.user.client.rpc.RemoteService;
+import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
+
+/**
+ * This service is used to fetch a list dynamically computed main values.
+ *
+ * @author <a href="mailto:raimund.renkert at intevation.de">Raimund Renkert</a>
+ */
+ at RemoteServiceRelativePath("dynamic-mainvalues")
+public interface DynamicMainValuesService extends RemoteService {
+
+ /**
+ * This method returns a list of DistanceInfoObjects for a specific river.
+ */
+ WQInfoObject[] getWQInfo(String locale, String river, double start, double end, int startYear, int endYear) throws ServerException;
+}
\ No newline at end of file
diff -r 6c88ad449c83 -r 82c67b859aa7 gwt-client/src/main/java/org/dive4elements/river/client/client/services/DynamicMainValuesServiceAsync.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/services/DynamicMainValuesServiceAsync.java Tue Jul 24 10:39:03 2018 +0200
@@ -0,0 +1,21 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by
+ * Björnsen Beratende Ingenieure GmbH
+ * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+package org.dive4elements.river.client.client.services;
+
+import org.dive4elements.river.client.shared.model.WQInfoObject;
+
+import com.google.gwt.user.client.rpc.AsyncCallback;
+
+/**
+ * @author Domenico Nardi Tironi
+ */
+public interface DynamicMainValuesServiceAsync {
+ void getWQInfo(String locale, String river, double start, double end, int startYear, int endYear, AsyncCallback<WQInfoObject[]> callback);
+}
\ No newline at end of file
diff -r 6c88ad449c83 -r 82c67b859aa7 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractUIProvider.java
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractUIProvider.java Tue Jul 24 10:36:18 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractUIProvider.java Tue Jul 24 10:39:03 2018 +0200
@@ -248,6 +248,7 @@
* @return the Data with the name <i>name</i>.
*/
protected Data getData(final List<Data> data, final String name) {
+
for (final Data d : data) {
if (name.equals(d.getLabel())) {
return d;
diff -r 6c88ad449c83 -r 82c67b859aa7 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractWQAdaptedInputPanel.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractWQAdaptedInputPanel.java Tue Jul 24 10:39:03 2018 +0200
@@ -0,0 +1,511 @@
+/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+
+package org.dive4elements.river.client.client.ui;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.dive4elements.river.client.client.Config;
+import org.dive4elements.river.client.client.FLYSConstants;
+import org.dive4elements.river.client.client.ui.wq.QDTable;
+import org.dive4elements.river.client.client.ui.wq.WTable;
+import org.dive4elements.river.client.shared.model.ArtifactDescription;
+import org.dive4elements.river.client.shared.model.Data;
+import org.dive4elements.river.client.shared.model.DataItem;
+import org.dive4elements.river.client.shared.model.DataList;
+import org.dive4elements.river.client.shared.model.DefaultData;
+import org.dive4elements.river.client.shared.model.DefaultDataItem;
+import org.dive4elements.river.client.shared.model.WQDataItem;
+import org.dive4elements.river.client.shared.model.WQInfoObject;
+import org.dive4elements.river.client.shared.model.WQInfoRecord;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.data.Record;
+import com.smartgwt.client.util.SC;
+import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
+import com.smartgwt.client.widgets.form.fields.events.BlurHandler;
+import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
+import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
+import com.smartgwt.client.widgets.grid.events.CellClickEvent;
+import com.smartgwt.client.widgets.grid.events.CellClickHandler;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
+import com.smartgwt.client.widgets.tab.TabSet;
+
+/**
+ * This UIProvider creates a widget to enter W or Q data for discharge
+ * longitudinal section computations.
+ *
+ * @author <a href="mailto:ingo.weinzierl at intevation.de">Ingo Weinzierl</a>
+ */
+abstract public class AbstractWQAdaptedInputPanel extends AbstractUIProvider implements ChangeHandler, BlurHandler {
+ private static final long serialVersionUID = -3218827566805476423L;
+
+ /** The message class that provides i18n strings. */
+ protected FLYSConstants MSG = GWT.create(FLYSConstants.class);
+ protected static final int ROW_HEIGHT = 20;
+
+ /** List of QDTables in inputhelper section. */
+ protected List<QDTable> qdTables;
+
+ private static final String GAUGE_SEPARATOR = ":";
+
+ private static final String GAUGE_PART_SEPARATOR = ";";
+
+ private static final String VALUE_SEPARATOR = ",";
+
+ /** Stores the input panels related to their keys. */
+ protected Map<String, DoubleArrayPanel> wqranges;
+
+ /** [startkm,endkm] per gauge in selected range. */
+ protected List<Double[]> gaugeRanges;
+
+ /** Stores the min/max values for each q range (gauge). */
+ protected Map<String, double[]> qranges;
+
+ /** The RadioGroupItem that determines the w/q input mode. */
+ protected DynamicForm modes;
+ /** List of doubleArrayPanels shown. */
+ protected final ArrayList<DoubleArrayPanel> doubleArrayPanels = new ArrayList<DoubleArrayPanel>();
+ /** List of wTables in inputhelper section. */
+ protected List<WTable> wTables;
+
+ /** Tabs in inputhelper area. */
+ protected TabSet tabs;
+
+ public AbstractWQAdaptedInputPanel() {
+ this.wqranges = new HashMap<String, DoubleArrayPanel>();
+ this.qranges = new HashMap<String, double[]>();
+ this.wTables = new ArrayList<WTable>();
+ this.qdTables = new ArrayList<QDTable>();
+ }
+
+ /** Inits the helper panel. */
+ // TODO duplicate in WQInputPanel
+ protected void initHelperPanel() {
+ this.tabs = new TabSet();
+ this.tabs.setWidth100();
+ this.tabs.setHeight100();
+
+ // For each gauge, add two tabs with helper tables.
+ createTabs();
+
+ this.helperContainer.addMember(this.tabs);
+ }
+
+ /** Create labels, canvasses, layouts. */
+ @Override
+ public Canvas create(final DataList data) {
+ beforeCreate(data);
+
+ readGaugeRanges(data);
+ initHelperPanel();
+
+ final Canvas submit = getNextButton();
+ final Canvas widget = createWidget(data);
+ final Label label = new Label(this.MSG.wqadaptedTitle());
+
+ label.setHeight(25);
+
+ final VLayout layout = new VLayout();
+ layout.setMembersMargin(10);
+ layout.setWidth(350);
+
+ layout.addMember(label);
+ layout.addMember(widget);
+ layout.addMember(submit);
+
+ fetchWQData();
+
+ initTableListeners();
+
+ afterCreate();
+
+ return layout;
+ }
+
+ protected abstract void createTabs();
+
+ protected abstract void beforeCreate(final DataList data);
+
+ protected abstract void afterCreate();
+
+ /**
+ * Initializes the listeners of the WQD tables.
+ */
+ // TODO dupe from WQInputPanel
+ protected void initTableListeners() {
+ int i = 0;
+ for (final QDTable qdTable : this.qdTables) {
+ // Register listener such that values are filled in on click.
+ final QDTable table = qdTable;
+ final int fi = i;
+ final CellClickHandler handler = new CellClickHandler() {
+ @Override
+ public void onCellClick(final CellClickEvent e) {
+ if (table.isDisabled() || table.isLocked()) {
+ return;
+ }
+
+ final Record r = e.getRecord();
+ final double val = r.getAttributeAsDouble("value");
+
+ AbstractWQAdaptedInputPanel.this.doubleArrayPanels.get(fi).setValues(new double[] { val });
+ // If a named value for first gauge is chosen,
+ // try to find and set
+ // the values to the other panels too.
+ if (fi == 0) {
+ final String valueName = r.getAttribute("name");
+ int oi = 0;
+ // TODO instead of oi use random access.
+ for (final QDTable otherQDTable : AbstractWQAdaptedInputPanel.this.qdTables) {
+ if (oi == 0) {
+ oi++;
+ continue;
+ }
+ final Double value = otherQDTable.findRecordValue(valueName);
+ if (value == null) {
+ SC.warn(AbstractWQAdaptedInputPanel.this.MSG.noMainValueAtGauge());
+ } else {
+ AbstractWQAdaptedInputPanel.this.doubleArrayPanels.get(oi).setValues(new double[] { value });
+ }
+ oi++;
+ }
+ } else {
+ // Focus next.
+ if (fi != AbstractWQAdaptedInputPanel.this.doubleArrayPanels.size() - 1) {
+ AbstractWQAdaptedInputPanel.this.doubleArrayPanels.get(fi + 1).focusInItem(1);
+ }
+ }
+ }
+ };
+
+ qdTable.addCellClickHandler(handler);
+ i++;
+ }
+
+ i = 0;
+ for (final WTable wTable : this.wTables) {
+ // Register listener such that values are filled in on click.
+ final WTable table = wTable;
+ final int fi = i;
+ final CellClickHandler handler = new CellClickHandler() {
+
+ @Override
+ public void onCellClick(final CellClickEvent e) {
+ if (table.isDisabled()) {
+ return;
+ }
+
+ final Record r = e.getRecord();
+ final double val = r.getAttributeAsDouble("value");
+
+ AbstractWQAdaptedInputPanel.this.doubleArrayPanels.get(fi).setValues(new double[] { val });
+ // If a named value for first gauge is chosen,
+ // try to find and set
+ // the values to the other panels too.
+ if (fi == 0) {
+ final String valueName = r.getAttribute("name");
+ int oi = 0;
+ // TODO instead of oi use random access.
+ for (final WTable otherWTable : AbstractWQAdaptedInputPanel.this.wTables) {
+ if (oi == 0) {
+ oi++;
+ continue;
+ }
+ final Double value = otherWTable.findRecordValue(valueName);
+ if (value == null) {
+ // TODO: afterwards it freaks out
+ SC.warn(AbstractWQAdaptedInputPanel.this.MSG.noMainValueAtGauge());
+ } else {
+ AbstractWQAdaptedInputPanel.this.doubleArrayPanels.get(oi).setValues(new double[] { value });
+ }
+ oi++;
+ }
+ } else {
+ // Focus next.
+ if (fi != AbstractWQAdaptedInputPanel.this.doubleArrayPanels.size() - 1) {
+ AbstractWQAdaptedInputPanel.this.doubleArrayPanels.get(fi + 1).focusInItem(1);
+ }
+ }
+ }
+
+ };
+
+ wTable.addCellClickHandler(handler);
+ i++;
+ }
+ }
+
+ /** Create area showing previously entered w or q data. */
+ protected final Canvas createOldWQValues(final Data wqData, final boolean isQ) {
+
+ final VLayout layout = new VLayout();
+ if (wqData != null) {
+ final DataItem item = wqData.getItems()[0];
+ final String value = item.getStringValue();
+
+ final String[] gauges = value.split(GAUGE_SEPARATOR);
+
+ final String unit = isQ ? "m³/s" : "cm";
+
+ for (final String gauge : gauges) {
+ final HLayout h = new HLayout();
+
+ final String[] parts = gauge.split(GAUGE_PART_SEPARATOR);
+ final String[] values = parts[3].split(VALUE_SEPARATOR);
+
+ final Label l = new Label(parts[2] + ": ");
+
+ final StringBuilder sb = new StringBuilder();
+ boolean first = true;
+
+ for (final String v : values) {
+ if (!first) {
+ sb.append(", ");
+ }
+
+ sb.append(v);
+ sb.append(" ");
+ sb.append(unit);
+
+ first = false;
+ }
+
+ final Label v = new Label(sb.toString());
+
+ l.setWidth(65);
+ v.setWidth(65);
+
+ h.addMember(l);
+ h.addMember(v);
+
+ layout.addMember(h);
+ }
+ }
+
+ return layout;
+ }
+
+ protected void initUserWQValues(final DataList dataList) {
+ final List<Data> allData = dataList.getAll();
+
+ final Data dDef = getData(allData, "wq_values");
+ final DataItem def = dDef != null ? dDef.getDefault() : null;
+ final String value = def != null ? def.getStringValue() : null;
+
+ if (value == null || value.length() == 0) {
+ return;
+ }
+
+ final String[] lines = value.split(GAUGE_SEPARATOR);
+
+ if (lines == null || lines.length == 0) {
+ return;
+ }
+
+ for (final String line : lines) {
+ final String[] cols = line.split(GAUGE_PART_SEPARATOR);
+ // final String title = createLineTitle(line);
+
+ if (cols == null || cols.length < 3) {
+ continue;
+ }
+
+ final String[] strValues = cols[2].split(VALUE_SEPARATOR);
+ final double[] values = new double[strValues.length];
+
+ int idx = 0;
+
+ for (final String strValue : strValues) {
+ try {
+ values[idx++] = Double.valueOf(strValue);
+ }
+ catch (final NumberFormatException nfe) {
+ // do nothing
+ }
+ }
+
+ final String key = cols[0] + GAUGE_PART_SEPARATOR + cols[1];
+ final DoubleArrayPanel dap = this.wqranges.get(key);
+
+ if (dap == null) {
+ continue;
+ }
+
+ dap.setValues(values);
+ }
+ }
+
+ /** Populate Gauge Ranges array. */
+ protected final void readGaugeRanges(final DataList dataList) {
+ final List<WQDataItem> items = getWQItems(dataList);
+ this.gaugeRanges = new ArrayList<Double[]>();
+
+ for (final DataItem item : items) {
+ if (item instanceof WQDataItem) {
+ final String[] startEndKm = item.getLabel().split(";");
+ final Double[] kvp = new Double[] { Double.parseDouble(startEndKm[0]), Double.parseDouble(startEndKm[1]) };
+ this.gaugeRanges.add(kvp);
+ }
+ }
+ }
+
+ /** Get items which are not WQ_MODE. */
+ protected List<WQDataItem> getWQItems(final DataList dataList) {
+ final List<Data> data = dataList.getAll();
+ final List<WQDataItem> results = new ArrayList<WQDataItem>();
+ for (final Data d : data) {
+ final DataItem[] items = d.getItems();
+ if (items != null) {
+ for (final Object item : items) {
+ if (item instanceof WQDataItem)
+ results.add((WQDataItem) item);
+ }
+ }
+ }
+ return results;
+ }
+
+ protected final Data getWQValues(final String dataKey) {
+ String wqvalue = null;
+
+ for (final Map.Entry<String, DoubleArrayPanel> entry : this.wqranges.entrySet()) {
+ final String key = entry.getKey();
+ final DoubleArrayPanel dap = entry.getValue();
+ final String label = dap.getItemTitle();
+
+ final double[] values = dap.getInputValues();
+ if (wqvalue == null) {
+ wqvalue = createValueString(key + ";" + label, values);
+ } else {
+ wqvalue += GAUGE_SEPARATOR + createValueString(key + ";" + label, values);
+ }
+ }
+
+ final DataItem valueItem = new DefaultDataItem(dataKey, dataKey, wqvalue);
+ final Data values = new DefaultData(dataKey, null, null, new DataItem[] { valueItem });
+
+ return values;
+ }
+
+ protected String createValueString(final String key, final double[] values) {
+ final StringBuilder sb = new StringBuilder();
+
+ boolean first = true;
+
+ for (final double value : values) {
+ if (!first) {
+ sb.append(",");
+ }
+
+ sb.append(Double.toString(value));
+
+ first = false;
+ }
+
+ return key + ";" + sb.toString();
+ }
+
+ @Override
+ public void onChange(final ChangeEvent event) {
+ // TODO IMPLEMENT ME
+ }
+
+ /** Store the currently focussed DoubleArrayPanel and focus helper tab. */
+
+ @Override
+ public final void onBlur(final BlurEvent event) {
+ final DoubleArrayPanel dap = (DoubleArrayPanel) event.getForm();
+ dap.validateForm(event.getItem());
+ }
+
+ /** Get the WQD data from service and stuck them up that tables. */
+ protected void fetchWQData() {
+ final Config config = Config.getInstance();
+ final String locale = config.getLocale();
+
+ final ArtifactDescription adescr = this.artifact.getArtifactDescription();
+ final DataList[] data = adescr.getOldData();
+
+ final String river = getRiverName(data);
+
+ int i = 0;
+
+ // Get Data for respective gauge.
+ for (final Double[] range : this.gaugeRanges) {
+ // Gauge ranges overlap, move start and end a bit closer
+ // to each other.
+ final double rDiff = (range[1] - range[0]) / 10d;
+ final int fi = i;
+
+ final AsyncCallback<WQInfoObject[]> cb = new AsyncCallback<WQInfoObject[]>() {
+ @Override
+ public void onFailure(final Throwable caught) {
+ GWT.log("Could not recieve wq informations.");
+ SC.warn(caught.getMessage());
+ }
+
+ @Override
+ public void onSuccess(final WQInfoObject[] wqi) {
+ final int num = wqi != null ? wqi.length : 0;
+ GWT.log("Received " + num + " wq informations (" + fi + ".");
+
+ if (num == 0) {
+ return;
+ }
+
+ addWQInfo(wqi, fi);
+ }
+ };
+
+ callMainValuesService(locale, river, range[0] + rDiff, range[1] - rDiff, cb);
+
+ i++;
+ }
+ }
+
+ protected abstract void callMainValuesService(String locale, String river, double start, double end, AsyncCallback<WQInfoObject[]> cb);
+
+ /** Add Info to helper table for gauge at index gaugeIdx. */
+ private void addWQInfo(final WQInfoObject[] wqi, final int gaugeIdx) {
+ for (final WQInfoObject wi : wqi) {
+ final WQInfoRecord rec = new WQInfoRecord(wi);
+
+ if (wi.getType().equals("W")) {
+ if (gaugeIdx < this.wTables.size())
+ this.wTables.get(gaugeIdx).addData(rec);
+ } else if (wi.getType().equals("Q")) {
+ if (gaugeIdx < this.qdTables.size())
+ this.qdTables.get(gaugeIdx).addData(rec);
+ }
+ }
+ }
+
+ /**
+ * Returns the name of the selected river.
+ *
+ * @param data
+ * The DataList with all data.
+ *
+ * @return the name of the current river.
+ */
+ protected String getRiverName(final DataList[] data) {
+ final ArtifactDescription adesc = this.artifact.getArtifactDescription();
+ return adesc.getRiver();
+ }
+
+ abstract protected Canvas createWidget(final DataList dataList);
+}
\ No newline at end of file
diff -r 6c88ad449c83 -r 82c67b859aa7 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WQAdaptedInputPanel.java
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WQAdaptedInputPanel.java Tue Jul 24 10:36:18 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WQAdaptedInputPanel.java Tue Jul 24 10:39:03 2018 +0200
@@ -14,13 +14,10 @@
import java.util.List;
import java.util.Map;
-import org.dive4elements.river.client.client.Config;
-import org.dive4elements.river.client.client.FLYSConstants;
import org.dive4elements.river.client.client.services.WQInfoService;
import org.dive4elements.river.client.client.services.WQInfoServiceAsync;
import org.dive4elements.river.client.client.ui.wq.QDTable;
import org.dive4elements.river.client.client.ui.wq.WTable;
-import org.dive4elements.river.client.shared.model.ArtifactDescription;
import org.dive4elements.river.client.shared.model.Data;
import org.dive4elements.river.client.shared.model.DataItem;
import org.dive4elements.river.client.shared.model.DataList;
@@ -28,12 +25,10 @@
import org.dive4elements.river.client.shared.model.DefaultDataItem;
import org.dive4elements.river.client.shared.model.WQDataItem;
import org.dive4elements.river.client.shared.model.WQInfoObject;
-import org.dive4elements.river.client.shared.model.WQInfoRecord;
import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.smartgwt.client.data.Record;
import com.smartgwt.client.types.TitleOrientation;
import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.util.SC;
@@ -41,18 +36,13 @@
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
-import com.smartgwt.client.widgets.form.fields.events.BlurEvent;
-import com.smartgwt.client.widgets.form.fields.events.BlurHandler;
import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
import com.smartgwt.client.widgets.form.fields.events.FocusEvent;
import com.smartgwt.client.widgets.form.fields.events.FocusHandler;
-import com.smartgwt.client.widgets.grid.events.CellClickEvent;
-import com.smartgwt.client.widgets.grid.events.CellClickHandler;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.VLayout;
import com.smartgwt.client.widgets.tab.Tab;
-import com.smartgwt.client.widgets.tab.TabSet;
/**
* This UIProvider creates a widget to enter W or Q data for discharge
@@ -60,257 +50,204 @@
*
* @author <a href="mailto:ingo.weinzierl at intevation.de">Ingo Weinzierl</a>
*/
-public class WQAdaptedInputPanel extends AbstractUIProvider implements ChangeHandler, BlurHandler, FocusHandler {
+public class WQAdaptedInputPanel extends AbstractWQAdaptedInputPanel implements FocusHandler {
private static final long serialVersionUID = -3218827566805476423L;
+ private static final String FIELD_WQ_MODE = "wq_isq";
+ private static final String FIELD_WQ_W = "W";
+ private static final String FIELD_WQ_Q = "Q";
- /** The message class that provides i18n strings. */
- protected FLYSConstants MESSAGE = GWT.create(FLYSConstants.class);
-
- public static final String FIELD_WQ_MODE = "wq_isq";
- public static final String FIELD_WQ_W = "W";
- public static final String FIELD_WQ_Q = "Q";
-
- public static final String GAUGE_SEPARATOR = ":";
-
- public static final String GAUGE_PART_SEPARATOR = ";";
-
- public static final String VALUE_SEPARATOR = ",";
-
- public static final int ROW_HEIGHT = 20;
-
- /** The constant field name for choosing w or q mode. */
- public static final String FIELD_WQ = "wq";
-
- /** The constant field name for choosing single values or range. */
- public static final String FIELD_MODE = "mode";
-
- /** The constant field value for range input mode. */
- public static final String FIELD_MODE_RANGE = "range";
+ /** Stores the min/max values for each w range (gauge). */
+ private final Map<String, double[]> wranges = new HashMap<String, double[]>();
/** Service to fetch W/Q MainValues. */
- protected WQInfoServiceAsync wqInfoService = GWT.create(WQInfoService.class);
-
- /** The message class that provides i18n strings. */
- protected FLYSConstants MSG = GWT.create(FLYSConstants.class);
-
- /** Stores the input panels related to their keys. */
- protected Map<String, DoubleArrayPanel> wqranges;
-
- /** List of doubleArrayPanels shown. */
- protected ArrayList<DoubleArrayPanel> doubleArrayPanels;
-
- /** [startkm,endkm] per gauge in selected range. */
- protected List<Double[]> gaugeRanges;
-
- /** Stores the min/max values for each q range (gauge). */
- protected Map<String, double[]> qranges;
-
- /** Stores the min/max values for each w range (gauge). */
- protected Map<String, double[]> wranges;
-
- /** The RadioGroupItem that determines the w/q input mode. */
- protected DynamicForm modes;
-
- /** List of wTables in inputhelper section. */
- protected List<WTable> wTables;
-
- /** List of QDTables in inputhelper section. */
- protected List<QDTable> qdTables;
-
- /** Tabs in inputhelper area. */
- protected TabSet tabs;
+ private final WQInfoServiceAsync wqInfoService = GWT.create(WQInfoService.class);
/** The currently focussed Input element. */
- protected DoubleArrayPanel itemWithFocus;
+ private DoubleArrayPanel itemWithFocus;
- public WQAdaptedInputPanel() {
- this.wqranges = new HashMap<String, DoubleArrayPanel>();
- this.doubleArrayPanels = new ArrayList<DoubleArrayPanel>();
- this.qranges = new HashMap<String, double[]>();
- this.wranges = new HashMap<String, double[]>();
- this.wTables = new ArrayList<WTable>();
- this.qdTables = new ArrayList<QDTable>();
+ private void enableWTabs() {
+ for (int i = 0; i < this.doubleArrayPanels.size(); i++) {
+ this.tabs.disableTab(2 * i);
+ this.tabs.enableTab(2 * i + 1);
+ }
}
- /** Create labels, canvasses, layouts. */
+ private void enableQTabs() {
+ for (int i = 0; i < this.doubleArrayPanels.size(); i++) {
+ this.tabs.enableTab(2 * i);
+ this.tabs.disableTab(2 * i + 1);
+ }
+ }
+
+ /**
+ * Create radio button for switching w and q input.
+ * Radiobutton-change also triggers helper panel tab selection.
+ */
+
+ private final Canvas createMode(final DataList dataList) {
+ final RadioGroupItem wq = new RadioGroupItem(FIELD_WQ_MODE);
+ wq.setShowTitle(false);
+ wq.setVertical(false);
+ wq.setWidth(200);
+
+ final LinkedHashMap<String, String> wqValues = new LinkedHashMap<String, String>();
+ wqValues.put(FIELD_WQ_W, this.MSG.wqW());
+ wqValues.put(WQAdaptedInputPanel.FIELD_WQ_Q, this.MSG.wqQatGauge());
+
+ wq.setValueMap(wqValues);
+
+ this.modes = new DynamicForm();
+ this.modes.setFields(wq);
+ this.modes.setWidth(200);
+ wq.addChangeHandler(new ChangeHandler() {
+ @Override
+ public void onChange(final ChangeEvent e) {
+ final DynamicForm form = e.getForm();
+
+ if (form.getValueAsString(FIELD_WQ_MODE).contains("Q")) {
+ WQAdaptedInputPanel.this.tabs.selectTab(0);
+ enableQTabs();
+ } else {
+ WQAdaptedInputPanel.this.tabs.selectTab(1);
+ enableWTabs();
+ }
+ }
+ });
+
+ final LinkedHashMap<String, String> initial = new LinkedHashMap<String, String>();
+ initial.put(FIELD_WQ_MODE, this.FIELD_WQ_Q);
+ this.modes.setValues(initial);
+ this.tabs.selectTab(1);
+ return this.modes;
+ }
+
@Override
- public Canvas create(final DataList data) {
- readGaugeRanges(data);
- initHelperPanel();
+ protected void createTabs() {
+ for (int i = 0; i < this.gaugeRanges.size(); i++) {
+ // Later the tabs title will get adjusted to include gauges name.
+ // TODO the tabs title becomes rather long through that (i18n).
- final Canvas submit = getNextButton();
- final Canvas widget = createWidget(data);
- final Label label = new Label(this.MSG.wqadaptedTitle());
+ final Tab wTab = new Tab(this.MSG.wq_table_w());
+ final WTable wTable = new WTable();
+ this.wTables.add(wTable);
+ wTable.showSelect();
+ wTab.setPane(wTable);
- label.setHeight(25);
+ final Tab qTab = new Tab(this.MSG.wq_table_q());
+ final QDTable qdTable = new QDTable();
+ this.qdTables.add(qdTable);
+ qTab.setPane(qdTable);
+ qdTable.showSelect();
- final VLayout layout = new VLayout();
- layout.setMembersMargin(10);
- layout.setWidth(350);
+ this.tabs.addTab(wTab, i * 2 + 0);
+ this.tabs.addTab(qTab, i * 2 + 1);
- layout.addMember(label);
- layout.addMember(widget);
- layout.addMember(submit);
+ }
- fetchWQData();
+ // Defaults at "Q", first input field.
+ this.tabs.selectTab(0);
+ enableQTabs();
+ }
- initTableListeners();
+ @Override
+ protected void beforeCreate(final DataList data) {
+ }
+ @Override
+ protected void afterCreate() {
// We actually want the first Q tab to be selected and all
// Q tabs to be enabled. I sense a bug in TabSet here, as
// the code in the W/Q radiogroup-changehandler behaves
// exactly vice versa (enabling Q, selecting tab 0).
enableWTabs();
this.tabs.selectTab(1);
+ }
+
+ @Override
+ protected Canvas createWidget(final DataList dataList) {
+ final VLayout layout = new VLayout();
+ final Canvas mode = createMode(dataList);
+ final Canvas list = createList(dataList);
+
+ final List<WQDataItem> items = getWQItems(dataList);
+ final int listHeight = ROW_HEIGHT * items.size();
+
+ mode.setHeight(25);
+ mode.setWidth(200);
+
+ layout.addMember(mode);
+ layout.addMember(list);
+
+ layout.setHeight(25 + listHeight);
+ layout.setWidth(350);
+
+ initUserDefaults(dataList);
return layout;
}
- /** Inits the helper panel. */
- // TODO duplicate in WQInputPanel
- protected void initHelperPanel() {
- this.tabs = new TabSet();
- this.tabs.setWidth100();
- this.tabs.setHeight100();
-
- // For each gauge, add two tabs with helper tables.
-
- for (int i = 0; i < this.gaugeRanges.size(); i++) {
- // Later the tabs title will get adjusted to include gauges name.
- // TODO the tabs title becomes rather long through that (i18n).
- final Tab wTab = new Tab(this.MESSAGE.wq_table_w());
- final Tab qTab = new Tab(this.MESSAGE.wq_table_q());
-
- final QDTable qdTable = new QDTable();
- final WTable wTable = new WTable();
-
- this.wTables.add(wTable);
- this.qdTables.add(qdTable);
-
- qdTable.showSelect();
- wTable.showSelect();
- wTab.setPane(wTable);
- qTab.setPane(qdTable);
-
- this.tabs.addTab(wTab, i * 2 + 0);
- this.tabs.addTab(qTab, i * 2 + 1);
- // tabs.disableTab(i*2+1);
- }
-
- // Defaults at "Q", first input field.
- this.tabs.selectTab(0);
- enableQTabs();
-
- this.helperContainer.addMember(this.tabs);
+ private void initUserDefaults(final DataList dataList) {
+ initUserWQValues(dataList);
+ initUserWQMode(dataList);
}
- /**
- * Initializes the listeners of the WQD tables.
- */
- // TODO dupe from WQInputPanel
- protected void initTableListeners() {
- int i = 0;
- for (final QDTable qdTable : this.qdTables) {
- // Register listener such that values are filled in on click.
- final QDTable table = qdTable;
- final int fi = i;
- final CellClickHandler handler = new CellClickHandler() {
- @Override
- public void onCellClick(final CellClickEvent e) {
- if (isWMode() || table.isLocked()) {
- return;
- }
+ private void initUserWQMode(final DataList dataList) {
+ final List<Data> allData = dataList.getAll();
- final Record r = e.getRecord();
- final double val = r.getAttributeAsDouble("value");
+ final Data dDef = getData(allData, "wq_mode");
+ final DataItem def = dDef != null ? dDef.getDefault() : null;
+ final String value = def != null ? def.getStringValue() : null;
- WQAdaptedInputPanel.this.doubleArrayPanels.get(fi).setValues(new double[] { val });
- // If a named value for first gauge is chosen,
- // try to find and set
- // the values to the other panels too.
- if (fi == 0) {
- final String valueName = r.getAttribute("name");
- int oi = 0;
- // TODO instead of oi use random access.
- for (final QDTable otherQDTable : WQAdaptedInputPanel.this.qdTables) {
- if (oi == 0) {
- oi++;
- continue;
- }
- final Double value = otherQDTable.findRecordValue(valueName);
- if (value == null) {
- SC.warn(WQAdaptedInputPanel.this.MSG.noMainValueAtGauge());
- } else {
- WQAdaptedInputPanel.this.doubleArrayPanels.get(oi).setValues(new double[] { value });
- }
- oi++;
- }
- } else {
- // Focus next.
- if (fi != WQAdaptedInputPanel.this.doubleArrayPanels.size() - 1) {
- WQAdaptedInputPanel.this.doubleArrayPanels.get(fi + 1).focusInItem(1);
- }
- }
- }
- };
-
- qdTable.addCellClickHandler(handler);
- i++;
- }
-
- i = 0;
- for (final WTable wTable : this.wTables) {
- // Register listener such that values are filled in on click.
- final WTable table = wTable;
- final int fi = i;
- final CellClickHandler handler = new CellClickHandler() {
- @Override
- public void onCellClick(final CellClickEvent e) {
- if (!isWMode() /* || table.isLocked() */) {
- return;
- }
-
- final Record r = e.getRecord();
- final double val = r.getAttributeAsDouble("value");
-
- WQAdaptedInputPanel.this.doubleArrayPanels.get(fi).setValues(new double[] { val });
- // If a named value for first gauge is chosen,
- // try to find and set
- // the values to the other panels too.
- if (fi == 0) {
- final String valueName = r.getAttribute("name");
- int oi = 0;
- // TODO instead of oi use random access.
- for (final WTable otherWTable : WQAdaptedInputPanel.this.wTables) {
- if (oi == 0) {
- oi++;
- continue;
- }
- final Double value = otherWTable.findRecordValue(valueName);
- if (value == null) {
- // TODO: afterwards it freaks out
- SC.warn(WQAdaptedInputPanel.this.MSG.noMainValueAtGauge());
- } else {
- WQAdaptedInputPanel.this.doubleArrayPanels.get(oi).setValues(new double[] { value });
- }
- oi++;
- }
- } else {
- // Focus next.
- if (fi != WQAdaptedInputPanel.this.doubleArrayPanels.size() - 1) {
- WQAdaptedInputPanel.this.doubleArrayPanels.get(fi + 1).focusInItem(1);
- }
- }
- }
- };
-
- wTable.addCellClickHandler(handler);
- i++;
+ if (value != null && value.equals(FIELD_WQ_W)) {
+ this.modes.setValue(FIELD_WQ_MODE, FIELD_WQ_W);
+ } else {
+ this.modes.setValue(FIELD_WQ_MODE, FIELD_WQ_Q);
}
}
+ private Canvas createList(final DataList dataList) {
+ final VLayout layout = new VLayout();
+
+ final List<WQDataItem> items = getWQItems(dataList);
+
+ int i = 0;
+
+ for (final DataItem item : items) {
+ if (item instanceof WQDataItem) {
+ final String title = item.getLabel(); // of form: 70.5;112.0
+ final String label = item.getStringValue();
+
+ // Rename W and Q tab to include gauges name.
+ this.tabs.getTab(i * 2).setTitle(this.tabs.getTab(i * 2).getTitle() + " (" + label + ")");
+ this.tabs.getTab(i * 2 + 1).setTitle(this.tabs.getTab(i * 2 + 1).getTitle() + " (" + label + ")");
+
+ final DoubleArrayPanel dap = new DoubleArrayPanel(label, null, this, this, TitleOrientation.LEFT);
+
+ this.wqranges.put(title, dap);
+ this.doubleArrayPanels.add(dap);
+
+ if (item instanceof WQDataItem) {
+ final WQDataItem wq = (WQDataItem) item;
+ final double[] mmQ = wq.getQRange();
+ final double[] mmW = wq.getWRange();
+
+ this.qranges.put(title, mmQ);
+ this.wranges.put(title, mmW);
+ }
+
+ layout.addMember(dap);
+ i++;
+ }
+
+ }
+
+ layout.setHeight(items.size() * ROW_HEIGHT);
+
+ return layout;
+ }
+
@Override
- public Canvas createOld(final DataList dataList) {
+ public Canvas createOld(final DataList dataList) { // TODO: OVERRIDE
final List<Data> all = dataList.getAll();
final Data wqData = getData(all, "wq_values");
final Data wqMode = getData(all, "wq_isq");
@@ -343,78 +280,6 @@
return vlayout;
}
- /** Create area showing previously entered w or q data. */
- protected Canvas createOldWQValues(final Data wqData, final boolean isQ) {
- final VLayout layout = new VLayout();
-
- final DataItem item = wqData.getItems()[0];
- final String value = item.getStringValue();
-
- final String[] gauges = value.split(GAUGE_SEPARATOR);
-
- final String unit = isQ ? "m³/s" : "cm";
-
- for (final String gauge : gauges) {
- final HLayout h = new HLayout();
-
- final String[] parts = gauge.split(GAUGE_PART_SEPARATOR);
- final String[] values = parts[3].split(VALUE_SEPARATOR);
-
- final Label l = new Label(parts[2] + ": ");
-
- final StringBuilder sb = new StringBuilder();
- boolean first = true;
-
- for (final String v : values) {
- if (!first) {
- sb.append(", ");
- }
-
- sb.append(v);
- sb.append(" ");
- sb.append(unit);
-
- first = false;
- }
-
- final Label v = new Label(sb.toString());
-
- l.setWidth(65);
- v.setWidth(65);
-
- h.addMember(l);
- h.addMember(v);
-
- layout.addMember(h);
- }
-
- return layout;
- }
-
- /** Create non-input helper part of the UI. */
- protected Canvas createWidget(final DataList dataList) {
- final VLayout layout = new VLayout();
-
- final Canvas mode = createMode(dataList);
- final Canvas list = createList(dataList);
-
- final DataItem[] items = getWQItems(dataList);
- final int listHeight = ROW_HEIGHT * items.length;
-
- mode.setHeight(25);
- mode.setWidth(200);
-
- layout.addMember(mode);
- layout.addMember(list);
-
- layout.setHeight(25 + listHeight);
- layout.setWidth(350);
-
- initUserDefaults(dataList);
-
- return layout;
- }
-
@Override
public List<String> validate() {
if (isWMode()) {
@@ -424,6 +289,12 @@
}
}
+ private boolean isWMode() {
+ final String mode = (String) this.modes.getValue(FIELD_WQ_MODE);
+
+ return FIELD_WQ_W.equals(mode);
+ }
+
protected List<String> validateRange(final Map<String, double[]> ranges) {
final List<String> errors = new ArrayList<String>();
final NumberFormat nf = NumberFormat.getDecimalFormat();
@@ -477,233 +348,7 @@
return errors;
}
- protected List<String> validateW() {
- return validateRange(this.wranges);
- }
-
- protected List<String> validateQ() {
- return validateRange(this.qranges);
- }
-
- protected void initUserDefaults(final DataList dataList) {
- initUserWQValues(dataList);
- initUserWQMode(dataList);
- }
-
- protected void initUserWQMode(final DataList dataList) {
- final List<Data> allData = dataList.getAll();
-
- final Data dDef = getData(allData, "wq_mode");
- final DataItem def = dDef != null ? dDef.getDefault() : null;
- final String value = def != null ? def.getStringValue() : null;
-
- if (value != null && value.equals(FIELD_WQ_W)) {
- this.modes.setValue(FIELD_WQ_MODE, FIELD_WQ_W);
- } else {
- this.modes.setValue(FIELD_WQ_MODE, FIELD_WQ_Q);
- }
- }
-
- protected void initUserWQValues(final DataList dataList) {
- final List<Data> allData = dataList.getAll();
-
- final Data dDef = getData(allData, "wq_values");
- final DataItem def = dDef != null ? dDef.getDefault() : null;
- final String value = def != null ? def.getStringValue() : null;
-
- if (value == null || value.length() == 0) {
- return;
- }
-
- final String[] lines = value.split(GAUGE_SEPARATOR);
-
- if (lines == null || lines.length == 0) {
- return;
- }
-
- for (final String line : lines) {
- final String[] cols = line.split(GAUGE_PART_SEPARATOR);
- final String title = createLineTitle(line);
-
- if (cols == null || cols.length < 3) {
- continue;
- }
-
- final String[] strValues = cols[2].split(VALUE_SEPARATOR);
- final double[] values = new double[strValues.length];
-
- int idx = 0;
-
- for (final String strValue : strValues) {
- try {
- values[idx++] = Double.valueOf(strValue);
- }
- catch (final NumberFormatException nfe) {
- // do nothing
- }
- }
-
- final String key = cols[0] + GAUGE_PART_SEPARATOR + cols[1];
- final DoubleArrayPanel dap = this.wqranges.get(key);
-
- if (dap == null) {
- continue;
- }
-
- dap.setValues(values);
- }
- }
-
- /** Populate Gauge Ranges array. */
- private void readGaugeRanges(final DataList dataList) {
- final DataItem[] items = getWQItems(dataList);
- this.gaugeRanges = new ArrayList<Double[]>();
-
- int i = 0;
-
- for (final DataItem item : items) {
- if (item instanceof WQDataItem) {
- final String[] startEndKm = item.getLabel().split(";");
- final Double[] kvp = new Double[] { Double.parseDouble(startEndKm[0]), Double.parseDouble(startEndKm[1]) };
- this.gaugeRanges.add(kvp);
- }
- i++;
- }
- }
-
- protected Canvas createList(final DataList dataList) {
- final VLayout layout = new VLayout();
-
- final DataItem[] items = getWQItems(dataList);
-
- int i = 0;
-
- for (final DataItem item : items) {
- if (item instanceof WQDataItem) {
- final String title = item.getLabel(); // of form: 70.5;112.0
- final String label = item.getStringValue();
-
- // Rename W and Q tab to include gauges name.
- this.tabs.getTab(i * 2).setTitle(this.tabs.getTab(i * 2).getTitle() + " (" + label + ")");
- this.tabs.getTab(i * 2 + 1).setTitle(this.tabs.getTab(i * 2 + 1).getTitle() + " (" + label + ")");
-
- final DoubleArrayPanel dap = new DoubleArrayPanel(label, null, this, this, TitleOrientation.LEFT);
-
- this.wqranges.put(title, dap);
- this.doubleArrayPanels.add(dap);
-
- if (item instanceof WQDataItem) {
- final WQDataItem wq = (WQDataItem) item;
- final double[] mmQ = wq.getQRange();
- final double[] mmW = wq.getWRange();
-
- this.qranges.put(title, mmQ);
- this.wranges.put(title, mmW);
- }
-
- layout.addMember(dap);
- }
- i++;
- }
-
- layout.setHeight(items.length * ROW_HEIGHT);
-
- return layout;
- }
-
- /** Get items which are not WQ_MODE. */
- protected DataItem[] getWQItems(final DataList dataList) {
- final List<Data> data = dataList.getAll();
-
- for (final Data d : data) {
- final String name = d.getLabel();
-
- if (name.equals(FIELD_WQ_MODE) || name.startsWith("ignore_")) {
- continue;
- }
-
- return d.getItems();
- }
-
- return null;
- }
-
- /**
- * Create radio button for switching w and q input.
- * Radiobutton-change also triggers helper panel tab selection.
- */
- protected Canvas createMode(final DataList dataList) {
- final RadioGroupItem wq = new RadioGroupItem(FIELD_WQ_MODE);
- wq.setShowTitle(false);
- wq.setVertical(false);
- wq.setWidth(200);
-
- final LinkedHashMap wqValues = new LinkedHashMap();
- wqValues.put(FIELD_WQ_W, this.MSG.wqW());
- wqValues.put(FIELD_WQ_Q, this.MSG.wqQatGauge());
-
- wq.setValueMap(wqValues);
-
- this.modes = new DynamicForm();
- this.modes.setFields(wq);
- this.modes.setWidth(200);
- wq.addChangeHandler(new ChangeHandler() {
- @Override
- public void onChange(final ChangeEvent e) {
- final DynamicForm form = e.getForm();
-
- if (form.getValueAsString(FIELD_WQ_MODE).contains("Q")) {
- WQAdaptedInputPanel.this.tabs.selectTab(0);
- enableQTabs();
- } else {
- WQAdaptedInputPanel.this.tabs.selectTab(1);
- enableWTabs();
- }
- }
- });
-
- final LinkedHashMap initial = new LinkedHashMap();
- initial.put(FIELD_WQ_MODE, FIELD_WQ_Q);
- this.modes.setValues(initial);
- this.tabs.selectTab(1);
- return this.modes;
- }
-
- public void enableWTabs() {
- for (int i = 0; i < this.doubleArrayPanels.size(); i++) {
- this.tabs.disableTab(2 * i);
- this.tabs.enableTab(2 * i + 1);
- }
- }
-
- public void enableQTabs() {
- for (int i = 0; i < this.doubleArrayPanels.size(); i++) {
- this.tabs.enableTab(2 * i);
- this.tabs.disableTab(2 * i + 1);
- }
- }
-
- public String createLineTitle(final String key) {
- final String[] splitted = key.split(";");
-
- return splitted[0] + " - " + splitted[1];
- }
-
- @Override
- public Data[] getData() {
- final Data mode = getWQMode();
- final Data values = getWQValues();
-
- return new Data[] { mode, values };
- }
-
- public boolean isWMode() {
- final String mode = (String) this.modes.getValue(FIELD_WQ_MODE);
-
- return FIELD_WQ_W.equals(mode);
- }
-
- protected Data getWQMode() {
+ private Data getWQMode() {
final String wqMode = this.modes.getValueAsString(FIELD_WQ_MODE);
String value = "false";
if (wqMode.equals("Q")) {
@@ -715,52 +360,22 @@
return mode;
}
- protected Data getWQValues() {
- String wqvalue = null;
+ @Override
+ public Data[] getData() {
+ final Data mode = getWQMode();
+ final Data values = getWQValues("wq_values");
- for (final Map.Entry<String, DoubleArrayPanel> entry : this.wqranges.entrySet()) {
- final String key = entry.getKey();
- final DoubleArrayPanel dap = entry.getValue();
- final String label = dap.getItemTitle();
-
- final double[] values = dap.getInputValues();
- if (wqvalue == null) {
- wqvalue = createValueString(key + ";" + label, values);
- } else {
- wqvalue += GAUGE_SEPARATOR + createValueString(key + ";" + label, values);
- }
- }
-
- final DataItem valueItem = new DefaultDataItem("wq_values", "wq_values", wqvalue);
- final Data values = new DefaultData("wq_values", null, null, new DataItem[] { valueItem });
-
- return values;
+ return new Data[] { mode, values };
}
- protected String createValueString(final String key, final double[] values) {
- final StringBuilder sb = new StringBuilder();
-
- boolean first = true;
-
- for (final double value : values) {
- if (!first) {
- sb.append(",");
- }
-
- sb.append(Double.toString(value));
-
- first = false;
- }
-
- return key + ";" + sb.toString();
+ private List<String> validateW() {
+ return validateRange(this.wranges);
}
- @Override
- public void onChange(final ChangeEvent event) {
- // TODO IMPLEMENT ME
+ private List<String> validateQ() {
+ return validateRange(this.qranges);
}
- /** Store the currently focussed DoubleArrayPanel and focus helper tab. */
@Override
public void onFocus(final FocusEvent event) {
this.itemWithFocus = (DoubleArrayPanel) event.getForm();
@@ -771,93 +386,8 @@
}
@Override
- public void onBlur(final BlurEvent event) {
- final DoubleArrayPanel dap = (DoubleArrayPanel) event.getForm();
- dap.validateForm(event.getItem());
+ protected void callMainValuesService(final String locale, final String river, final double start, final double end,
+ final AsyncCallback<WQInfoObject[]> cb) {
+ this.wqInfoService.getWQInfo(locale, river, start, end, cb);
}
-
- /** Get the WQD data from service and stuck them up that tables. */
- protected void fetchWQData() {
- final Config config = Config.getInstance();
- final String locale = config.getLocale();
-
- final ArtifactDescription adescr = this.artifact.getArtifactDescription();
- final DataList[] data = adescr.getOldData();
-
- final double[] mm = getMinMaxKM(data);
- final String river = getRiverName(data);
-
- int i = 0;
-
- // Get Data for respective gauge.
- for (final Double[] range : this.gaugeRanges) {
- // Gauge ranges overlap, move start and end a bit closer
- // to each other.
- final double rDiff = (range[1] - range[0]) / 10d;
- final int fi = i;
- this.wqInfoService.getWQInfo(locale, river, range[0] + rDiff, range[1] - rDiff, new AsyncCallback<WQInfoObject[]>() {
- @Override
- public void onFailure(final Throwable caught) {
- GWT.log("Could not recieve wq informations.");
- SC.warn(caught.getMessage());
- }
-
- @Override
- public void onSuccess(final WQInfoObject[] wqi) {
- final int num = wqi != null ? wqi.length : 0;
- GWT.log("Received " + num + " wq informations (" + fi + ".");
-
- if (num == 0) {
- return;
- }
-
- addWQInfo(wqi, fi);
- }
- });
- i++;
- }
- }
-
- /** Add Info to helper table for gauge at index gaugeIdx. */
- protected void addWQInfo(final WQInfoObject[] wqi, final int gaugeIdx) {
- for (final WQInfoObject wi : wqi) {
- final WQInfoRecord rec = new WQInfoRecord(wi);
-
- if (wi.getType().equals("W")) {
- this.wTables.get(gaugeIdx).addData(rec);
- } else {
- this.qdTables.get(gaugeIdx).addData(rec);
- }
- }
- }
-
- /**
- * Determines the min and max kilometer value selected in a former state. A
- * bit silly, but we need to run over each value of the "old data" to find
- * such values because it is not available here.
- *
- * @param data
- * The DataList which contains the whole data inserted for the
- * current artifact.
- *
- * @return a double array with [min, max].
- */
- protected double[] getMinMaxKM(final DataList[] data) {
- final ArtifactDescription adesc = this.artifact.getArtifactDescription();
- return adesc.getKMRange();
- }
-
- /**
- * Returns the name of the selected river.
- *
- * @param data
- * The DataList with all data.
- *
- * @return the name of the current river.
- */
- protected String getRiverName(final DataList[] data) {
- final ArtifactDescription adesc = this.artifact.getArtifactDescription();
- return adesc.getRiver();
- }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ No newline at end of file
diff -r 6c88ad449c83 -r 82c67b859aa7 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/bundu/BunduWstWQPanel.java
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/bundu/BunduWstWQPanel.java Tue Jul 24 10:36:18 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/bundu/BunduWstWQPanel.java Tue Jul 24 10:39:03 2018 +0200
@@ -9,17 +9,40 @@
package org.dive4elements.river.client.client.ui.bundu;
import java.util.ArrayList;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import org.dive4elements.river.client.client.services.DynamicMainValuesService;
+import org.dive4elements.river.client.client.services.DynamicMainValuesServiceAsync;
+import org.dive4elements.river.client.client.ui.AbstractWQAdaptedInputPanel;
import org.dive4elements.river.client.client.ui.DoubleArrayPanel;
-import org.dive4elements.river.client.client.ui.WQAdaptedInputPanel;
+import org.dive4elements.river.client.client.ui.wq.QDTable;
import org.dive4elements.river.client.shared.model.Data;
import org.dive4elements.river.client.shared.model.DataItem;
import org.dive4elements.river.client.shared.model.DataList;
+import org.dive4elements.river.client.shared.model.DefaultData;
+import org.dive4elements.river.client.shared.model.DefaultDataItem;
+import org.dive4elements.river.client.shared.model.WQDataItem;
+import org.dive4elements.river.client.shared.model.WQInfoObject;
+import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.NumberFormat;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.smartgwt.client.types.TitleOrientation;
+import com.smartgwt.client.types.VerticalAlignment;
+import com.smartgwt.client.types.Visibility;
import com.smartgwt.client.widgets.Canvas;
+import com.smartgwt.client.widgets.Label;
+import com.smartgwt.client.widgets.form.DynamicForm;
+import com.smartgwt.client.widgets.form.fields.RadioGroupItem;
+import com.smartgwt.client.widgets.form.fields.TextItem;
+import com.smartgwt.client.widgets.form.fields.events.ChangeEvent;
+import com.smartgwt.client.widgets.form.fields.events.ChangeHandler;
+import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator;
+import com.smartgwt.client.widgets.layout.HLayout;
+import com.smartgwt.client.widgets.layout.VLayout;
+import com.smartgwt.client.widgets.tab.Tab;
/**
* This UIProvider creates a widget to enter W or Q data for
@@ -27,33 +50,216 @@
*
* @author <a href="mailto:aheinecke at intevation.de">Andre Heinecke</a>
*/
-public class BunduWstWQPanel extends WQAdaptedInputPanel {
- private static final long serialVersionUID = -3218827566805476423L;
+public class BunduWstWQPanel extends AbstractWQAdaptedInputPanel {
+
+ private static final long serialVersionUID = -1L;
+
+ private static enum mode {
+ Q, UD
+ }
+
+ /** Service to fetch W/Q MainValues. */
+ private final DynamicMainValuesServiceAsync mainValueService = GWT.create(DynamicMainValuesService.class);
+
+ private final RadioGroupItem radiogroup = new RadioGroupItem();
private int bezugsjahr = 0;
+
private int qSeriesLength = 0;
- /** get bezugsjahr + range from server HERE **/
+ private Canvas list;
+
+ private final DynamicForm udForm = new DynamicForm();
+
+ private final TextItem udInputItem = new TextItem();
+
@Override
- public Canvas create(final DataList data) {
-
+ protected void beforeCreate(final DataList data) {
for (final Data container : data.getAll()) {
-
- for (final DataItem item : container.getItems()) {
- if ("ignore_bezugsjahr".equals(item.getLabel())) {
- this.bezugsjahr = Integer.valueOf(item.getStringValue());
- } else if ("ignore_q_series_length".equals(item.getLabel())) {
- this.qSeriesLength = Integer.valueOf(item.getStringValue());
+ final DataItem[] items = container.getItems();
+ if (items != null) {
+ for (final DataItem item : items) {
+ if ("ignore_bezugsjahr".equals(item.getLabel())) {
+ this.bezugsjahr = Integer.valueOf(item.getStringValue());
+ } else if ("ignore_q_series_length".equals(item.getLabel())) {
+ this.qSeriesLength = Integer.valueOf(item.getStringValue());
+ }
}
}
}
- return super.create(data);
}
- // TODO: ValidateRange verstehen und dann ggf. Löschen/Ändern/was auch immer
@Override
- protected List<String> validateRange(final Map<String, double[]> ranges) {
+ protected void afterCreate() {
+ }
+
+ @Override
+ protected Canvas createWidget(final DataList dataList) {
+ final VLayout layout = new VLayout();
+ final Canvas mode = createMode(dataList);
+
+ this.list = createList(dataList);
+
+ this.udInputItem.setShowTitle(false);
+ this.udInputItem.setWidth(120);
+ final IntegerRangeValidator validator = new IntegerRangeValidator();
+ validator.setMax(364);
+ validator.setMin(0);
+ validator.setErrorMessage(this.MSG.bundu_bezugswst_validation_range());
+ this.udInputItem.setRequiredMessage(this.MSG.bundu_bezugswst_validation_range());
+ this.udInputItem.setValidators(validator);
+ this.udInputItem.setValidateOnChange(true);
+ this.udForm.setFields(this.udInputItem);
+
+ final List<WQDataItem> items = getWQItems(dataList);
+ final int listHeight = ROW_HEIGHT * items.size();
+
+ mode.setHeight(25);
+ mode.setWidth(200);
+
+ layout.addMember(mode);
+ layout.addMember(this.list);
+ layout.addMember(this.udForm);
+ layout.setHeight(25 + listHeight);
+ layout.setWidth(350);
+ enableQ();
+ return layout;
+ }
+
+ /**
+ * Create radio button for switching
+ * Radiobutton-change also triggers helper panel tab selection.
+ */
+
+ private Canvas createMode(final DataList dataList) {
+ this.radiogroup.setShowTitle(false);
+ this.radiogroup.setVertical(false);
+ this.radiogroup.setWidth(200);
+
+ final LinkedHashMap<String, String> wqValues = new LinkedHashMap<String, String>();
+ wqValues.put(String.valueOf(mode.Q), this.MSG.wqQatGauge());
+ wqValues.put(String.valueOf(mode.UD), this.MSG.bundu_bezugswst_mode_ud());
+ this.radiogroup.setValueMap(wqValues);
+ this.radiogroup.setValue(String.valueOf(mode.Q));
+
+ this.modes = new DynamicForm();
+ this.modes.setFields(this.radiogroup);
+ this.modes.setWidth(200);
+ this.radiogroup.addChangeHandler(new ChangeHandler() {
+ @Override
+ public void onChange(final ChangeEvent e) {
+
+ final String value = e.getValue().toString();
+ if (value.equals(String.valueOf(mode.UD))) {
+ enableQ();
+ } else if (value.equals(String.valueOf(mode.Q))) {
+ enableUD();
+ }
+ }
+ });
+ return this.modes;
+ }
+
+ private void enableUD() {
+ BunduWstWQPanel.this.list.setVisibility(Visibility.VISIBLE);
+ BunduWstWQPanel.this.udForm.setVisibility(Visibility.HIDDEN);
+ BunduWstWQPanel.this.tabs.enable();
+ }
+
+ private void enableQ() {
+ BunduWstWQPanel.this.list.setVisibility(Visibility.HIDDEN);
+ BunduWstWQPanel.this.udForm.setVisibility(Visibility.VISIBLE);
+ BunduWstWQPanel.this.tabs.disable();
+ }
+
+ private final String getMode() {
+ return (String) this.radiogroup.getValue();
+ }
+
+ @Override
+ public Data[] getData() {
+ final Data[] data = new Data[2];
+ final String modeStr = getMode();
+ final DataItem item = new DefaultDataItem("bundu.wst.mode", "bundu.wst.mode", modeStr);
+ final Data modeData = new DefaultData("bundu.wst.mode", null, null, new DataItem[] { item });
+ data[0] = modeData;
+ if (modeStr.equals(mode.Q.toString())) {
+ data[1] = getWQValues("wq_values");
+ } else if (modeStr.equals(mode.UD.toString())) {
+ final String udValue = this.udInputItem.getValueAsString(); // in validate findet der int-check statt; er verhindert ein weitergehen, falls der Wert
+ // nicht int-kompatibel ist
+ final DataItem itemV = new DefaultDataItem("bundu.wst.ud_value", "bundu.wst.ud_value", udValue);
+ data[1] = new DefaultData("bundu.wst.ud_value", null, null, new DataItem[] { itemV });
+ }
+ return data;
+ }
+
+ @Override
+ protected void createTabs() {
+ for (int i = 0; i < this.gaugeRanges.size(); i++) {
+ final Tab qTab = new Tab(this.MSG.wq_table_q());
+ final QDTable qdTable = new QDTable();
+ this.qdTables.add(qdTable);
+ qdTable.showSelect();
+ qTab.setPane(qdTable);
+ this.tabs.addTab(qTab, i);
+ }
+ this.tabs.setSelectedTab(0);
+ }
+
+ private Canvas createList(final DataList dataList) {
+ final VLayout layout = new VLayout();
+
+ final List<WQDataItem> items = getWQItems(dataList);
+
+ int i = 0;
+ for (final DataItem item : items) {
+ if (item instanceof WQDataItem) {
+ final String title = item.getLabel();
+ final String label = item.getStringValue();
+
+ this.tabs.getTab(i).setTitle(this.tabs.getTab(i).getTitle() + " (" + label + ")");
+
+ final DoubleArrayPanel dap = new DoubleArrayPanel(label, null, this, null, TitleOrientation.LEFT);
+ this.wqranges.put(title, dap);
+ this.doubleArrayPanels.add(dap);
+ if (item instanceof WQDataItem) {
+ final WQDataItem wq = (WQDataItem) item;
+ final double[] mmQ = wq.getQRange();
+ this.qranges.put(title, mmQ);
+
+ }
+ layout.addMember(dap);
+ i++;
+ }
+ }
+
+ layout.setHeight(items.size() * ROW_HEIGHT);
+
+ return layout;
+ }
+
+ @Override
+ public List<String> validate() {
final List<String> errors = new ArrayList<String>();
+ if (getMode().equals(mode.Q.toString())) {
+ errors.addAll(this.validateRange(this.qranges));
+ } else if (getMode().equals(mode.UD.toString())) {
+ try {
+ if (this.udInputItem.validate()) {
+ errors.add(this.udInputItem.getRequiredMessage());
+ }
+ }
+ catch (final NumberFormatException e) {
+ errors.add(this.MSG.error_invalid_integer());
+ }
+ }
+ return errors;
+ }
+
+ private List<String> validateRange(final Map<String, double[]> ranges) {
+ final List<String> errors = new ArrayList<String>();
+
final NumberFormat nf = NumberFormat.getDecimalFormat();
for (final DoubleArrayPanel dap : this.wqranges.values()) {
@@ -90,5 +296,53 @@
}
return errors;
}
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+
+ @Override
+ public Canvas createOld(final DataList dataList) {
+ final List<Data> all = dataList.getAll();
+ final Data wqData = getData(all, "wq_values");
+ final Data wqMode = getData(all, "bundu.wst.mode");
+ final Data udValue = getData(all, "bundu.wst.ud_value");
+
+ final boolean isQ = wqMode.getItems()[0].getStringValue().equals(String.valueOf(mode.Q));
+ final Canvas back = getBackButton(dataList.getState());
+
+ final HLayout valLayout = new HLayout();
+ final HLayout modeLayout = new HLayout();
+ final VLayout vlayout = new VLayout();
+
+ final Label wqLabel = new Label(dataList.getLabel());
+ final Label modeLabel = new Label("");
+
+ wqLabel.setValign(VerticalAlignment.TOP);
+
+ wqLabel.setWidth(200);
+ wqLabel.setHeight(25);
+ modeLabel.setHeight(25);
+ modeLabel.setWidth(200);
+
+ valLayout.addMember(wqLabel);
+ if (isQ) {
+ valLayout.addMember(createOldWQValues(wqData, true));
+ } else {
+ valLayout.addMember(new Label(udValue.getItems()[0].getStringValue() + " [d/a]"));
+ }
+ valLayout.addMember(back);
+ modeLayout.addMember(modeLabel);
+
+ vlayout.addMember(valLayout);
+ vlayout.addMember(modeLayout);
+
+ return vlayout;
+ }
+
+ @Override
+ protected void callMainValuesService(final String locale, final String river, final double start, final double end,
+ final AsyncCallback<WQInfoObject[]> cb) {
+
+ final int startYear = this.bezugsjahr - this.qSeriesLength;
+ final int endYear = this.bezugsjahr;
+
+ this.mainValueService.getWQInfo(locale, river, start, end, startYear, endYear, cb);
+ }
+}
\ No newline at end of file
diff -r 6c88ad449c83 -r 82c67b859aa7 gwt-client/src/main/java/org/dive4elements/river/client/server/AbstractMainValuesServiceImpl.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/AbstractMainValuesServiceImpl.java Tue Jul 24 10:39:03 2018 +0200
@@ -0,0 +1,221 @@
+/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+
+package org.dive4elements.river.client.server;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Comparator;
+import java.util.List;
+
+import javax.xml.xpath.XPathConstants;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.common.ArtifactNamespaceContext;
+import org.dive4elements.artifacts.common.utils.XMLUtils;
+import org.dive4elements.artifacts.httpclient.exceptions.ConnectionException;
+import org.dive4elements.artifacts.httpclient.http.HttpClient;
+import org.dive4elements.artifacts.httpclient.http.HttpClientImpl;
+import org.dive4elements.river.client.shared.exceptions.ServerException;
+import org.dive4elements.river.client.shared.model.WQInfoObject;
+import org.dive4elements.river.client.shared.model.WQInfoObjectImpl;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import com.google.gwt.user.server.rpc.RemoteServiceServlet;
+
+/**
+ * @author <a href="mailto:ingo.weinzierl at intevation.de">Ingo Weinzierl</a>
+ */
+abstract class AbstractMainValuesServiceImpl extends RemoteServiceServlet {
+
+ private static final Logger log = Logger.getLogger(DynamicMainValuesServiceImpl.class);
+
+ private static final Comparator<WQInfoObject> WQ_INFO_OBJECT_CMP = new Comparator<WQInfoObject>() {
+ @Override
+ public int compare(final WQInfoObject a, final WQInfoObject b) {
+
+ // Descending by type: Qs before Ds
+ final int cmp = a.getType().compareTo(b.getType());
+ if (cmp < 0)
+ return +1;
+ if (cmp > 0)
+ return -1;
+
+ // Ascending by value
+ final double diff = a.getValue() - b.getValue();
+ if (diff < 0d)
+ return -1;
+ if (diff > 0d)
+ return +1;
+ return 0;
+ }
+ };
+
+ private static final String ERROR_NO_WQINFO_FOUND = "error_no_wqinfo_found";
+
+ private static final String XPATH_WQS = "art:service/art:mainvalues/art:mainvalue";
+
+ private static final long serialVersionUID = 1L;
+
+ protected final Document createInput(final String river, final double from, final double to, final Integer startYear, final Integer endYear) {
+
+ final Document input = XMLUtils.newDocument();
+
+ final XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator(input, ArtifactNamespaceContext.NAMESPACE_URI,
+ ArtifactNamespaceContext.NAMESPACE_PREFIX);
+
+ final Element mainvalues = ec.create("mainvalues");
+
+ final Element riverEl = ec.create("river");
+ riverEl.setTextContent(river);
+ mainvalues.appendChild(riverEl);
+
+ final Element startEl = ec.create("start");
+ startEl.setTextContent(Double.valueOf(from).toString());
+ mainvalues.appendChild(startEl);
+
+ final Element endEl = ec.create("end");
+ endEl.setTextContent(Double.valueOf(to).toString());
+ mainvalues.appendChild(endEl);
+
+ if (startYear != null) {
+ final Element startYearElement = ec.create("startYear");
+ startYearElement.setTextContent(Integer.toString(startYear));
+ mainvalues.appendChild(startYearElement);
+ }
+
+ if (endYear != null) {
+ final Element endYearElement = ec.create("endYear");
+ endYearElement.setTextContent(Integer.toString(endYear));
+ mainvalues.appendChild(endYearElement);
+ }
+
+ input.appendChild(mainvalues);
+
+ return input;
+ }
+
+ protected final WQInfoObject[] callService(final String serviceName, final Document input, final String locale) throws ServerException {
+ final String url = getServletContext().getInitParameter("server-url");
+
+ final HttpClient client = new HttpClientImpl(url, locale);
+
+ try {
+ final Document result = client.callService(url, serviceName, input);
+
+ log.debug("Extract wq info objects now.");
+ final WQInfoObject[] objects = extractWQInfoObjects(result);
+
+ if (objects.length > 0) {
+ return objects;
+ }
+ }
+ catch (final ConnectionException ce) {
+ log.error(ce, ce);
+ }
+
+ throw new ServerException(ERROR_NO_WQINFO_FOUND);
+ }
+
+ /**
+ * Extracts all wq info objects from <i>result</i> document.
+ *
+ * @param result
+ * The document retrieved by the server.
+ *
+ * @return a list of WQInfoObjects.
+ */
+ private WQInfoObject[] extractWQInfoObjects(final Document result) throws ServerException {
+ final NodeList list = (NodeList) XMLUtils.xpath(result, XPATH_WQS, XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE);
+
+ if (list == null || list.getLength() == 0) {
+ log.warn("No wq info found.");
+
+ throw new ServerException(ERROR_NO_WQINFO_FOUND);
+ }
+
+ final boolean debug = log.isDebugEnabled();
+
+ final int num = list.getLength();
+ if (debug) {
+ log.debug("Response contains " + num + " objects.");
+ }
+
+ final List<WQInfoObject> objects = new ArrayList<WQInfoObject>(num);
+
+ for (int i = 0; i < num; i++) {
+ final WQInfoObject obj = buildWQInfoObject(list.item(i));
+
+ if (obj != null) {
+ objects.add(obj);
+ }
+ }
+
+ if (debug) {
+ log.debug("Retrieved " + objects.size() + " wq values");
+ }
+
+ final WQInfoObject[] array = objects.toArray(new WQInfoObject[objects.size()]);
+
+ Arrays.sort(array, WQ_INFO_OBJECT_CMP);
+
+ return array;
+ }
+
+ /**
+ * Extracts information for a single wq info object and intializes an
+ * WQInfoObject with them.
+ *
+ * @param node
+ * The node that contains the information.
+ *
+ * @return a valid WQInfoObject.
+ */
+ private static WQInfoObject buildWQInfoObject(final Node node) {
+
+ final String name = XMLUtils.xpathString(node, "@name", ArtifactNamespaceContext.INSTANCE);
+
+ final String type = XMLUtils.xpathString(node, "@type", ArtifactNamespaceContext.INSTANCE);
+
+ final String value = XMLUtils.xpathString(node, "@value", ArtifactNamespaceContext.INSTANCE);
+
+ final String official = XMLUtils.xpathString(node, "@official", ArtifactNamespaceContext.INSTANCE);
+
+ final String starttime = XMLUtils.xpathString(node, "@starttime", ArtifactNamespaceContext.INSTANCE);
+
+ final String stoptime = XMLUtils.xpathString(node, "@stoptime", ArtifactNamespaceContext.INSTANCE);
+
+ if (name != null && type != null) {
+ try {
+ final Calendar cal = Calendar.getInstance();
+ java.util.Date start = null;
+ java.util.Date stop = null;
+ if (!starttime.equals("")) {
+ cal.setTimeInMillis(Long.parseLong(starttime));
+ start = cal.getTime();
+ }
+ if (!stoptime.equals("")) {
+ cal.setTimeInMillis(Long.parseLong(stoptime));
+ stop = cal.getTime();
+ }
+ return new WQInfoObjectImpl(name, type, new Double(value), official != null && official.equalsIgnoreCase("true"), start, stop);
+ }
+ catch (final NumberFormatException nfe) {
+ log.warn(nfe.getLocalizedMessage());
+ }
+ }
+
+ log.warn("Invalid wq info object found.");
+
+ return null;
+ }
+}
\ No newline at end of file
diff -r 6c88ad449c83 -r 82c67b859aa7 gwt-client/src/main/java/org/dive4elements/river/client/server/DynamicMainValuesServiceImpl.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/DynamicMainValuesServiceImpl.java Tue Jul 24 10:39:03 2018 +0200
@@ -0,0 +1,30 @@
+/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+
+package org.dive4elements.river.client.server;
+
+import org.dive4elements.river.client.client.services.DynamicMainValuesService;
+import org.dive4elements.river.client.shared.exceptions.ServerException;
+import org.dive4elements.river.client.shared.model.WQInfoObject;
+import org.w3c.dom.Document;
+
+/**
+ * @author <a href="mailto:ingo.weinzierl at intevation.de">Ingo Weinzierl</a>
+ */
+public class DynamicMainValuesServiceImpl extends AbstractMainValuesServiceImpl implements DynamicMainValuesService {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public WQInfoObject[] getWQInfo(final String locale, final String river, final double from, final double to, final int startYear, final int endYear)
+ throws ServerException {
+
+ final Document input = createInput(river, from, to, startYear, endYear);
+
+ return callService("dynamicMainvalues", input, locale);
+ }
+}
\ No newline at end of file
diff -r 6c88ad449c83 -r 82c67b859aa7 gwt-client/src/main/java/org/dive4elements/river/client/server/WQInfoServiceImpl.java
--- a/gwt-client/src/main/java/org/dive4elements/river/client/server/WQInfoServiceImpl.java Tue Jul 24 10:36:18 2018 +0200
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/WQInfoServiceImpl.java Tue Jul 24 10:39:03 2018 +0200
@@ -8,233 +8,26 @@
package org.dive4elements.river.client.server;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Comparator;
-import java.util.List;
-
-import javax.xml.xpath.XPathConstants;
-
+import org.apache.log4j.Logger;
+import org.dive4elements.river.client.client.services.WQInfoService;
+import org.dive4elements.river.client.shared.exceptions.ServerException;
+import org.dive4elements.river.client.shared.model.WQInfoObject;
import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import org.apache.log4j.Logger;
-
-import com.google.gwt.user.server.rpc.RemoteServiceServlet;
-
-import org.dive4elements.artifacts.common.ArtifactNamespaceContext;
-import org.dive4elements.artifacts.common.utils.XMLUtils;
-
-import org.dive4elements.artifacts.httpclient.exceptions.ConnectionException;
-import org.dive4elements.artifacts.httpclient.http.HttpClient;
-import org.dive4elements.artifacts.httpclient.http.HttpClientImpl;
-
-import org.dive4elements.river.client.shared.exceptions.ServerException;
-import org.dive4elements.river.client.client.services.WQInfoService;
-import org.dive4elements.river.client.shared.model.WQInfoObject;
-import org.dive4elements.river.client.shared.model.WQInfoObjectImpl;
-
/**
* @author <a href="mailto:ingo.weinzierl at intevation.de">Ingo Weinzierl</a>
*/
-public class WQInfoServiceImpl
-extends RemoteServiceServlet
-implements WQInfoService
-{
- private static final Logger log =
- Logger.getLogger(WQInfoServiceImpl.class);
+public class WQInfoServiceImpl extends AbstractMainValuesServiceImpl implements WQInfoService {
+ private static final long serialVersionUID = 1L;
- public static final String ERROR_NO_WQINFO_FOUND =
- "error_no_wqinfo_found";
+ private static final Logger log = Logger.getLogger(WQInfoServiceImpl.class);
- public static final String XPATH_WQS =
- "art:service/art:mainvalues/art:mainvalue";
-
-
- public WQInfoObject[] getWQInfo(
- String locale,
- String river,
- double from,
- double to)
- throws ServerException
- {
+ @Override
+ public WQInfoObject[] getWQInfo(final String locale, final String river, final double from, final double to) throws ServerException {
log.info("WQInfoServiceImpl.getWQInfo");
- String url = getServletContext().getInitParameter("server-url");
+ final Document input = createInput(river, from, to, null, null);
- Document doc = XMLUtils.newDocument();
-
- XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator(
- doc,
- ArtifactNamespaceContext.NAMESPACE_URI,
- ArtifactNamespaceContext.NAMESPACE_PREFIX);
-
- Element mainvalues = ec.create("mainvalues");
- Element riverEl = ec.create("river");
- Element startEl = ec.create("start");
- Element endEl = ec.create("end");
-
- riverEl.setTextContent(river);
- startEl.setTextContent(Double.valueOf(from).toString());
- endEl.setTextContent(Double.valueOf(to).toString());
-
- mainvalues.appendChild(riverEl);
- mainvalues.appendChild(startEl);
- mainvalues.appendChild(endEl);
-
- doc.appendChild(mainvalues);
-
- HttpClient client = new HttpClientImpl(url, locale);
-
- try {
- Document result = client.callService(url, "mainvalues", doc);
-
- log.debug("Extract wq info objects now.");
- WQInfoObject[] objects = extractWQInfoObjects(result);
-
- if (objects.length > 0) {
- return objects;
- }
- }
- catch (ConnectionException ce) {
- log.error(ce, ce);
- }
-
- throw new ServerException(ERROR_NO_WQINFO_FOUND);
+ return callService("mainvalues", input, locale);
}
-
-
- /**
- * Extracts all wq info objects from <i>result</i> document.
- *
- * @param result The document retrieved by the server.
- *
- * @return a list of WQInfoObjects.
- */
- protected WQInfoObject[] extractWQInfoObjects(Document result)
- throws ServerException
- {
- NodeList list = (NodeList) XMLUtils.xpath(
- result,
- XPATH_WQS,
- XPathConstants.NODESET,
- ArtifactNamespaceContext.INSTANCE);
-
- if (list == null || list.getLength() == 0) {
- log.warn("No wq info found.");
-
- throw new ServerException(ERROR_NO_WQINFO_FOUND);
- }
-
- boolean debug = log.isDebugEnabled();
-
- int num = list.getLength();
- if (debug) {
- log.debug("Response contains " + num + " objects.");
- }
-
- List<WQInfoObject> objects =
- new ArrayList<WQInfoObject>(num);
-
- for (int i = 0; i < num; i++) {
- WQInfoObject obj = buildWQInfoObject(list.item(i));
-
- if (obj != null) {
- objects.add(obj);
- }
- }
-
- if (debug) {
- log.debug("Retrieved " + objects.size() + " wq values");
- }
-
- WQInfoObject [] array = (WQInfoObject[])
- objects.toArray(new WQInfoObject[objects.size()]);
-
- Arrays.sort(array, WQ_INFO_OBJECT_CMP);
-
- return array;
- }
-
- public static final Comparator<WQInfoObject> WQ_INFO_OBJECT_CMP =
- new Comparator<WQInfoObject>() {
- @Override
- public int compare(WQInfoObject a, WQInfoObject b) {
-
- // Descending by type: Qs before Ds
- int cmp = a.getType().compareTo(b.getType());
- if (cmp < 0) return +1;
- if (cmp > 0) return -1;
-
- // Ascending by value
- double diff = a.getValue() - b.getValue();
- if (diff < 0d) return -1;
- if (diff > 0d) return +1;
- return 0;
- }
- };
-
- /**
- * Extracts information for a single wq info object and intializes an
- * WQInfoObject with them.
- *
- * @param node The node that contains the information.
- *
- * @return a valid WQInfoObject.
- */
- protected static WQInfoObject buildWQInfoObject(Node node) {
-
- String name = XMLUtils.xpathString(
- node, "@name", ArtifactNamespaceContext.INSTANCE);
-
- String type = XMLUtils.xpathString(
- node, "@type", ArtifactNamespaceContext.INSTANCE);
-
- String value = XMLUtils.xpathString(
- node, "@value", ArtifactNamespaceContext.INSTANCE);
-
- String official = XMLUtils.xpathString(
- node, "@official", ArtifactNamespaceContext.INSTANCE);
-
- String starttime = XMLUtils.xpathString(
- node, "@starttime", ArtifactNamespaceContext.INSTANCE);
-
- String stoptime = XMLUtils.xpathString(
- node, "@stoptime", ArtifactNamespaceContext.INSTANCE);
-
- if (name != null && type != null) {
- try {
- Calendar cal = Calendar.getInstance();
- java.util.Date start = null;
- java.util.Date stop = null;
- if (!starttime.equals("")) {
- cal.setTimeInMillis(Long.parseLong(starttime));
- start = cal.getTime();
- }
- if (!stoptime.equals("")) {
- cal.setTimeInMillis(Long.parseLong(stoptime));
- stop = cal.getTime();
- }
- return new WQInfoObjectImpl(
- name,
- type,
- new Double(value),
- official != null && official.equalsIgnoreCase("true"),
- start,
- stop);
- }
- catch (NumberFormatException nfe) {
- log.warn(nfe.getLocalizedMessage());
- }
- }
-
- log.warn("Invalid wq info object found.");
-
- return null;
- }
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ No newline at end of file
More information about the Dive4Elements-commits
mailing list