view gwt-client/src/main/java/org/dive4elements/river/client/client/ui/stationinfo/GaugeListGrid.java @ 9284:486b6160962f

Fixed: filtering of gauge list did not handle cases correctly, where fromKm > toKm
author gernotbelger
date Fri, 20 Jul 2018 16:03:40 +0200
parents ff9372d0cc1c
children 45908b79c079
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.stationinfo;

import java.util.ArrayList;
import java.util.List;

import org.dive4elements.river.client.client.Config;
import org.dive4elements.river.client.client.FLYS;
import org.dive4elements.river.client.client.services.AdvanceService;
import org.dive4elements.river.client.client.services.AdvanceServiceAsync;
import org.dive4elements.river.client.client.services.ArtifactService;
import org.dive4elements.river.client.client.services.ArtifactServiceAsync;
import org.dive4elements.river.client.client.services.CreateCollectionService;
import org.dive4elements.river.client.client.services.CreateCollectionServiceAsync;
import org.dive4elements.river.client.client.services.StepForwardService;
import org.dive4elements.river.client.client.services.StepForwardServiceAsync;
import org.dive4elements.river.client.client.ui.CollectionView;
import org.dive4elements.river.client.client.ui.StringArrayParseHelper;
import org.dive4elements.river.client.shared.model.Artifact;
import org.dive4elements.river.client.shared.model.Collection;
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.GaugeInfo;
import org.dive4elements.river.client.shared.model.RiverInfo;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
import com.smartgwt.client.widgets.grid.events.RecordClickHandler;

/**
 * @author <a href="mailto:bjoern.ricks@intevation.de">Björn Ricks</a>
 */
public class GaugeListGrid extends InfoListGrid implements RecordClickHandler {

    public static enum DisappearType {
        remove, collapse, stayVisible
    }

    private static final int ABFLUSSTAFEL_COLUMN = 6;

    /** The ArtifactService used to communicate with the Artifact server. */
    protected ArtifactServiceAsync artifactService = GWT.create(ArtifactService.class);

    /** The StepForwardService used to put data into an existing artifact. */
    protected StepForwardServiceAsync forwardService = GWT.create(StepForwardService.class);

    /** The ArtifactService used to communicate with the Artifact server. */
    protected CreateCollectionServiceAsync createCollectionService = GWT.create(CreateCollectionService.class);

    /** The StepForwardService used to put data into an existing artifact. */
    protected AdvanceServiceAsync advanceService = GWT.create(AdvanceService.class);

    private final List<GaugeInfo> gauges = new ArrayList<GaugeInfo>();

    public GaugeListGrid(final FLYS flys) {
        super(flys);
        // TODO i18n!!!
        final ListGridField nfield = new ListGridField("name", "Pegel");
        final ListGridField sfield = new ListGridField("kmstart", "Start [km]", 60);
        final ListGridField efield = new ListGridField("kmend", "Ende [km]", 60);
        final ListGridField stfield = new ListGridField("station", "Station [km]");
        final ListGridField lfield = new ListGridField("infolink", "Info");
        final ListGridField cfield = new ListGridField("curvelink", this.MSG.gauge_curve_link());
        cfield.addRecordClickHandler(this);

        this.setShowRecordComponents(true);
        this.setShowRecordComponentsByCell(true);
        this.setFields(nfield, sfield, efield, stfield, lfield, cfield);
    }

    @Override
    public void setRiverInfo(final RiverInfo riverinfo) {
        final List<GaugeInfo> gauges = riverinfo.getGauges();

        if (gauges != null && !gauges.isEmpty()) {

            final ArrayList<GaugeInfo> emptygauges = new ArrayList<GaugeInfo>();

            if (!riverinfo.isKmUp()) {
                for (final GaugeInfo gauge : gauges) {
                    addGauge(gauge, emptygauges);
                }
            } else {
                for (int i = gauges.size() - 1; i >= 0; i--) {
                    final GaugeInfo gauge = gauges.get(i);
                    addGauge(gauge, emptygauges);
                }
            }

            // put empty gauges to the end
            for (final GaugeInfo gauge : emptygauges) {
                addGauge(gauge);
            }
        }
    }

    private void addGauge(final GaugeInfo gauge, final List<GaugeInfo> empty) {
        if (gauge.getKmStart() != null && gauge.getKmEnd() != null) {
            addGauge(gauge);
        } else {
            empty.add(gauge);
        }
    }

    private void addGauge(final GaugeInfo gauge) {

        this.gauges.add(gauge);

        // this.addData(new GaugeRecord(gauge));

    }

    @Override
    public void open() {
        final ArrayList<Double> locations = new ArrayList<Double>();

        if (this.data != null && this.data.length > 0) {
            for (final DataList dl : this.data) {

                final String state = dl.getState();
                DisappearType type = DisappearType.collapse;
                if (state.contains("state.bundu.") || state.contains("state.fix.")) {
                    type = DisappearType.remove;
                }

                GWT.log("GaugeListGrid - open " + state);
                if (state.contains(".location_distance")) {
                    Double ldfrom = null;
                    Double ldto = null;

                    for (int j = dl.size() - 1; j >= 0; --j) {
                        final Data d = dl.get(j);
                        final String label = d.getLabel();
                        GWT.log("GaugeListGrid - setData - label " + label + " " + d.getStringValue());
                        if (label.equals("ld_from")) {
                            ldfrom = getDoubleValue(d);
                        } else if (label.equals("ld_to")) {
                            ldto = getDoubleValue(d);
                        } else if (label.equals("ld_locations")) {
                            getLocationsFromData(locations, d);
                            openOnLocations(locations);
                            return;
                        }
                    }
                    if (ldfrom != null) {

                        openOnDistance(ldfrom, ldto, type);
                        return;
                    }
                } else if (state.contains(".distance_only") || state.contains(".distance")
                        || state.contains(".location") && !state.contains(".location_distance")) {
                    Double ldfrom = null;
                    Double ldto = null;

                    for (int j = dl.size() - 1; j >= 0; --j) {
                        final Data d = dl.get(j);
                        final String label = d.getLabel();
                        GWT.log("GaugeListGrid - setData - label " + label + " " + d.getStringValue());
                        if (label.equals("ld_from")) {
                            ldfrom = getDoubleValue(d);
                        } else if (label.equals("ld_to")) {
                            ldto = getDoubleValue(d);
                        }
                    }

                    if (ldfrom != null) {
                        openOnDistance(ldfrom, ldto, type);
                        return;
                    }
                } else if (state.equals("state.winfo.location")) {
                    getLocations("ld_locations", locations, dl);
                    openOnLocations(locations);
                    return;
                } else if (state.equals("state.winfo.reference.curve.input.start")) {
                    getLocations("reference_startpoint", locations, dl);
                } else if (state.equals("state.winfo.reference.curve.input.end")) {
                    getLocations("reference_endpoint", locations, dl);
                } else if (state.equals("state.winfo.historicalq.reference_gauge")) {
                    for (int j = dl.size() - 1; j >= 0; --j) {
                        final Data d = dl.get(j);
                        final String label = d.getLabel();
                        if (label.equals("reference_gauge")) {
                            final String tmp = d.getStringValue();
                            if (tmp != null) {
                                final Long gaugereference = Long.valueOf(tmp);
                                if (gaugereference != null) {
                                    openOnReference(gaugereference);
                                    return;
                                }
                            }
                        }
                    }
                }
            }
        }
        if (!locations.isEmpty()) {
            openOnLocations(locations);
        } else if( this.data != null && this.data.length == 1 ){
            // During selection of calc-mode: all gauges should be collapsed
            collapseAll();
        }
        else {
            openAll();
        }
    }

    @Override
    public void openAll() {

        GWT.log("InfoListGrid - openAll");

        setData(new ListGridRecord[] {});
        for (final GaugeInfo gauge : this.gauges) {
            addExpandedRecord(gauge);
        }
    }

    private void collapseAll() {
        
        GWT.log("InfoListGrid - openAll");
        
        setData(new ListGridRecord[] {});
        for (final GaugeInfo gauge : this.gauges) {
            addCollapsedRecord(gauge);
        }
    }

    void getLocations(final String labelname, final List<Double> locations, final DataList dl) {
        for (int j = dl.size() - 1; j >= 0; --j) {
            final Data d = dl.get(j);
            final String label = d.getLabel();
            if (label.equals(labelname)) {
                getLocationsFromData(locations, d);
            }
        }
    }

    void getLocationsFromData(final List<Double> locations, final Data data) {
        final DataItem[] items = data.getItems();
        for (final DataItem item : items) {
            final String tmp = item.getStringValue();
            GWT.log("GaugeListGrid - getLocationsFromData " + tmp);
            if (tmp != null) {
                if (tmp.contains(" ")) {
                    // string contains several values ...
                    final String[] values = StringArrayParseHelper.getArrayFromRawString(tmp);
                    for (final String value2 : values) {
                        final Double value = Double.valueOf(value2);
                        if (value != null) {
                            locations.add(value);
                        }
                    }
                } else {
                    final Double value = Double.valueOf(tmp);
                    if (value != null) {
                        locations.add(value);
                    }
                }
            }
        }
    }

    public void openOnReference(final Long number) {
        GWT.log("GaugeListGrid - openOnReference " + number);

        setData(new ListGridRecord[] {});

        for (final GaugeInfo gauge : this.gauges) {

            if (gauge.getOfficialNumber().equals(number)) {
                this.addExpandedRecord(gauge);// (gauge);
            } else {
                this.addCollapsedRecord(gauge);
            }
        }
    }

    public void openOnDistance(final double start, final Double end, final DisappearType type) {
        GWT.log("GaugeListGrid - openOnDistance " + start + " " + end);

        setData(new ListGridRecord[] {});

        double to = end == null ? Double.MAX_VALUE: end;

        double from = Math.min(start, to);
        to = Math.max(start, to);
        
        for (final GaugeInfo gauge : this.gauges) {

            /* in earlier version, it was assumed that gaugeEnd may be null, but start not. */
            final Double gaugeStart = gauge.getKmStart();
            final Double gaugeEnd = gauge.getKmEnd() == null ? gaugeStart : gauge.getKmEnd();
            
            boolean expand;
            if( gaugeStart == null )
                expand = false;
            else {
                
                final double gaugeFrom = Math.min(gaugeStart, gaugeEnd);
                final double gaugeTo = Math.max(gaugeStart, gaugeEnd);
                
                expand = (from >= gaugeFrom && from <= gaugeTo) || (to >= gaugeFrom && to <= gaugeTo) || (from <= gaugeFrom && to >= gaugeEnd);
            }

            if( expand )
                addExpandedRecord(gauge);
            else
                removeOrCollapse(gauge, type);
        }
    }

    private void removeOrCollapse(final GaugeInfo gauge, final DisappearType type) {
        switch (type) {
        case remove:
            // Remove: gauge wird der datasource nicht hinzugefügt
            break;
        case collapse:
            addCollapsedRecord(gauge);
            break;
        case stayVisible: // TODO: check
            addExpandedRecord(gauge);
            break;
        }

    }

    /**
     * Open Gauge entry if a location fits to the gauge.
     */
    public void openOnLocations(final List<Double> locations) {
        GWT.log("GaugeListGrid - openOnLocations " + locations);

        setData(new ListGridRecord[] {});

        if (locations == null || locations.isEmpty()) {
            return;
        }

        for (final GaugeInfo gauge : this.gauges) {
            boolean isset = false;
            for (final Double location : locations) {
                if (locations == null) {
                    continue;
                }

                final Double start = gauge.getKmStart();
                final Double end = gauge.getKmEnd();
                if (start == null || end == null) {
                    // should not occur but avoid NullPointerException
                    continue;
                }

                if (location >= start && location <= end) {
                    isset = true;
                    break;
                }
            }
            if (isset) {
                addExpandedRecord(gauge);
            } else {
                addCollapsedRecord(gauge);
            }
        }
    }

    private void addExpandedRecord(final GaugeInfo gauge) {
        final GaugeRecord record = new GaugeRecord(gauge);

        this.addData(record);

        expandRecord(record);
    }

    private void addCollapsedRecord(final GaugeInfo gauge) {
        final GaugeRecord record = new GaugeRecord(gauge);

        this.addData(record);

        collapseRecord(record);
    }

    @Override
    protected Canvas getExpandPanel(final ListGridRecord record) {
        final GaugeRecord item = (GaugeRecord) record;
        return new GaugeInfoPanel(item, this.flys);
    }

    /**
     * When clicked on the gauge discharge link, open new Gauge Discharge
     * Curve view.
     */
    @Override
    public void onRecordClick(final RecordClickEvent event) {
        final GaugeRecord gauge = (GaugeRecord) event.getRecord();
        final Config config = Config.getInstance();
        final String locale = config.getLocale();
        this.createCollectionService.create(locale, this.flys.getCurrentUser().identifier(), new AsyncCallback<Collection>() {
            @Override
            public void onFailure(final Throwable caught) {
                GWT.log("Could not create the new collection.");
                SC.warn(FLYS.getExceptionString(GaugeListGrid.this.MSG, caught));
            }

            @Override
            public void onSuccess(final Collection collection) {
                GWT.log("Successfully created a new collection.");
                createArtifact(collection, locale, gauge);
            }
        });
    }

    private void createArtifact(final Collection collection, final String locale, final GaugeRecord gauge) {
        this.artifactService.create(locale, "gaugedischargecurve", null, new AsyncCallback<Artifact>() {
            @Override
            public void onFailure(final Throwable caught) {
                GWT.log("Could not create the new artifact.");
                SC.warn(FLYS.getExceptionString(GaugeListGrid.this.MSG, caught));
            }

            @Override
            public void onSuccess(final Artifact artifact) {
                GWT.log("Successfully created a new artifact.");

                final DataItem riverItem = new DefaultDataItem("river", "river", gauge.getRiverName());
                final Data river = new DefaultData("river", null, null, new DataItem[] { riverItem });

                final DataItem refItem = new DefaultDataItem("reference_gauge", "reference_gauge", gauge.getOfficialNumber().toString());
                final Data ref = new DefaultData("reference_gauge", null, null, new DataItem[] { refItem });

                final DataItem locItem = new DefaultDataItem("ld_locations", "ld_locations", gauge.getStation().toString());
                final Data loc = new DefaultData("ld_locations", null, null, new DataItem[] { locItem });

                final DataItem nameItem = new DefaultDataItem("gauge_name", "gauge_name", gauge.getName());
                final Data name = new DefaultData("gauge_name", null, null, new DataItem[] { nameItem });

                final Data[] data = new Data[] { river, ref, loc, name };
                GaugeListGrid.this.forwardService.go(locale, artifact, data, new AsyncCallback<Artifact>() {
                    @Override
                    public void onFailure(final Throwable caught) {
                        GWT.log("Could not feed the artifact.");
                        SC.warn(caught.getMessage());
                    }

                    @Override
                    public void onSuccess(final Artifact artifact) {
                        GWT.log("Successfully feed the artifact.");
                        final CollectionView view = new CollectionView(GaugeListGrid.this.flys, collection, artifact);
                        GaugeListGrid.this.flys.getWorkspace().addView(collection.identifier(), view);
                        view.addArtifactToCollection(artifact);
                    }
                });
            }
        });
    }

    @Override
    public String getCellCSSText(final ListGridRecord record, final int rowNum, final int colNum) {
        if (colNum == ABFLUSSTAFEL_COLUMN) {
            // display the ablfusstafel cell like a link
            return "text-decoration: underline; color: #0000EE; " + "cursor: pointer;";
        } else {
            return super.getCellCSSText(record, rowNum, colNum);
        }
    }
}

http://dive4elements.wald.intevation.org