Mercurial > dive4elements > river
diff gwt-client/src/main/java/org/dive4elements/river/client/client/ui/AbstractWQAdaptedInputPanel.java @ 9288:82c67b859aa7
bundu.bezugswst worklflow incl. service impl for mainValues to be calculated
author | gernotbelger |
---|---|
date | Tue, 24 Jul 2018 10:39:03 +0200 |
parents | |
children | 6174daaf5e56 |
line wrap: on
line diff
--- /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@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