view gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WQAdaptedInputPanel.java @ 9278:717c9dc1859f

datatransfer bezugsjahr, qserieslength
author gernotbelger
date Fri, 20 Jul 2018 11:19:07 +0200
parents 5e38e2924c07
children 82c67b859aa7
line wrap: on
line source
/* 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.LinkedHashMap;
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;
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.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;
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.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
 * longitudinal section computations.
 *
 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
 */
public class WQAdaptedInputPanel extends AbstractUIProvider implements ChangeHandler, BlurHandler, FocusHandler {
    private static final long serialVersionUID = -3218827566805476423L;

    /** 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";

    /** 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;

    /** The currently focussed Input element. */
    protected 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>();
    }

    /** Create labels, canvasses, layouts. */
    @Override
    public Canvas create(final DataList 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();

        // 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);

        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);
    }

    /**
     * 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;
                    }

                    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 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++;
        }
    }

    @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, "wq_isq");
        final boolean isQ = wqMode.getItems()[0].getStringValue().equals("true");
        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);
        valLayout.addMember(createOldWQValues(wqData, isQ));

        valLayout.addMember(back);
        modeLayout.addMember(modeLabel);

        vlayout.addMember(valLayout);
        vlayout.addMember(modeLayout);

        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()) {
            return validateW();
        } else {
            return validateQ();
        }
    }

    protected List<String> validateRange(final Map<String, double[]> ranges) {
        final List<String> errors = new ArrayList<String>();
        final NumberFormat nf = NumberFormat.getDecimalFormat();

        for (final Map.Entry<String, DoubleArrayPanel> entry : this.wqranges.entrySet()) {

            final String key = entry.getKey();
            final DoubleArrayPanel dap = entry.getValue();

            if (!dap.validateForm()) {
                errors.add(this.MSG.error_invalid_double_value());
                return errors;
            }

            final double[] mm = ranges.get(key);
            if (mm == null) {
                SC.warn(this.MSG.error_read_minmax_values());
                continue;
            }

            final double[] values = dap.getInputValues();
            final double[] good = new double[values.length];

            int idx = 0;

            final List<String> tmpErrors = new ArrayList<String>();
            for (final double value : values) {
                if (value < mm[0] || value > mm[1]) {
                    String tmp = this.MSG.error_validate_range();
                    tmp = tmp.replace("$1", nf.format(value));
                    tmp = tmp.replace("$2", nf.format(mm[0]));
                    tmp = tmp.replace("$3", nf.format(mm[1]));
                    tmpErrors.add(tmp);
                } else {
                    good[idx++] = value;
                }
            }

            final double[] justGood = new double[idx];
            for (int i = 0; i < justGood.length; i++) {
                justGood[i] = good[i];
            }

            if (!tmpErrors.isEmpty()) {
                dap.setValues(justGood);

                errors.addAll(tmpErrors);
            }
        }

        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() {
        final String wqMode = this.modes.getValueAsString(FIELD_WQ_MODE);
        String value = "false";
        if (wqMode.equals("Q")) {
            value = "true";
        }
        final DataItem item = new DefaultDataItem("wq_isq", "wq_isq", value);
        final Data mode = new DefaultData("wq_isq", null, null, new DataItem[] { item });

        return mode;
    }

    protected Data getWQValues() {
        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("wq_values", "wq_values", wqvalue);
        final Data values = new DefaultData("wq_values", 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 void onFocus(final FocusEvent event) {
        this.itemWithFocus = (DoubleArrayPanel) event.getForm();
        // Switch to respective tab.
        // TODO which makes a focus loss
        final int inputIndex = this.doubleArrayPanels.indexOf(this.itemWithFocus);
        this.tabs.selectTab(inputIndex * 2 + (isWMode() ? 0 : 1));
    }

    @Override
    public 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 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 :

http://dive4elements.wald.intevation.org