view flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/extreme/ExtremeQInput.java @ 4174:eaf83d4ae6b1

Sorted gauges for reference gauge selection in historical discharge calculation based on their name. Now, Gauge implements the Java Comparable interface and takes its name into account.
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Thu, 18 Oct 2012 13:12:24 +0200
parents 4ffeccc5b5a1
children 810db532803a
line wrap: on
line source
package de.intevation.flys.artifacts.states.extreme;

import java.util.ArrayList;
import java.util.List;
import java.util.Comparator;
import java.util.Collections;

import org.apache.log4j.Logger;

import org.w3c.dom.Element;

import de.intevation.artifacts.Artifact;
import de.intevation.artifacts.CallContext;

import de.intevation.flys.artifacts.access.ExtremeAccess;

import de.intevation.artifactdatabase.ProtocolUtils;
import de.intevation.artifactdatabase.data.StateData;

import de.intevation.artifacts.common.utils.XMLUtils;

import de.intevation.flys.artifacts.model.RiverFactory;
import de.intevation.flys.artifacts.model.WstValueTable;
import de.intevation.flys.model.Gauge;
import de.intevation.flys.artifacts.model.Range;
import de.intevation.flys.model.River;
import de.intevation.flys.model.Wst;

import de.intevation.flys.artifacts.FLYSArtifact;

import de.intevation.flys.artifacts.model.RangeWithValues;
import de.intevation.flys.artifacts.states.DefaultState;
import de.intevation.flys.artifacts.model.WstValueTableFactory;
import de.intevation.flys.utils.FLYSUtils;


/** TODO Subclass WQAdapted. */

/**
 * State to input Q data in segments for extreme value calculations..
 * The data item ranges is expected to have this format <from1>;<to1>;<value1>:<from2>;<to2>;<value2>:...
 * (;;;:;;;:;;;:...)
 */
public class ExtremeQInput extends DefaultState {

    /** The logger used in this state.*/
    private static Logger logger = Logger.getLogger(ExtremeQInput.class);


    /** Trivial, empty constructor. */
    public ExtremeQInput() {
    }


    /**
     * Create one element for each 'segment' of the selected river that
     * is within the given kilometer range (TODO). Each element is a tuple of
     * (from;to) where <i>from</i> is the lower bounds of the segment or the
     * lower kilometer range. <i>to</i> is the upper bounds of the segment or
     * the upper kilometer range.
     *
     * @param cr The ElementCreator.
     * @param artifact The FLYS artifact.
     * @param name The name of the data item.
     * @param context The CallContext.
     *
     * @return a list of elements that consist of tuples of the intersected
     *         segments of the selected river.
     */
    @Override
    protected Element[] createItems(
        XMLUtils.ElementCreator cr,
        Artifact    artifact,
        String      name,
        CallContext context)
    {
        logger.debug("ExtremeQInput.createItems: " + name);

        FLYSArtifact flysArtifact = (FLYSArtifact) artifact;

        ExtremeAccess access = new ExtremeAccess(flysArtifact);
        River river = RiverFactory.getRiver(access.getRiver());
        WstValueTable wstValueTable = WstValueTableFactory.getTable(river);

        List<Range> ranges   = wstValueTable.findSegments(access.getFrom(),
            access.getTo());

        int num = ranges != null ? ranges.size() : 0;

        if (num == 0) {
            logger.warn("Selected distance matches no segments.");
            return null;
        }

        List<Element> elements = new ArrayList<Element>();

        for (Range range: ranges) {
            elements.add(createItem(
                cr, new String[] { range.getStart() + ";" + range.getEnd(), ""}, new double[] {0,100000}));
        }

        Element[] els = new Element[elements.size()];

        return elements.toArray(els);
    }


    /** Create sub-item ('row') of data thing. */
    protected Element createItem(
        XMLUtils.ElementCreator cr,
        Object   obj,
        double[] q
        )
    {
        Element item  = ProtocolUtils.createArtNode(cr, "item", null, null);
        Element label = ProtocolUtils.createArtNode(cr, "label", null, null);
        Element value = ProtocolUtils.createArtNode(cr, "value", null, null);

        String[] arr = (String[]) obj;

        label.setTextContent(arr[0]);
        value.setTextContent(arr[1]);

        item.appendChild(label);
        item.appendChild(value);

        if (q != null) {
            Element qRange = createRangeElement(cr, q, "Q");
            item.appendChild(qRange);
        }

        return item;
    }


    /**
     * Create elements to set min and max values of segments q (just min makes
     * sense for extremes.
     */
    protected Element createRangeElement(
        XMLUtils.ElementCreator cr,
        double[] mm,
        String   type)
    {
        Element range = ProtocolUtils.createArtNode(
            cr, "range",
            new String[] {"type"},
            new String[] {type});

        Element min = ProtocolUtils.createArtNode(cr, "min", null, null);
        min.setTextContent(String.valueOf(mm[0]));

        Element max = ProtocolUtils.createArtNode(cr, "max", null, null);
        max.setTextContent(String.valueOf(mm[1]));

        range.appendChild(min);
        range.appendChild(max);

        return range;
    }


    @Override
    protected String getUIProvider() {
        return "q_segmented_panel";
    }


    /** Validate given data (return true). */
    @Override
    public boolean validate(Artifact artifact)
    throws IllegalArgumentException
    {
        logger.debug("ExtremeQInput.validate");

        FLYSArtifact flys = (FLYSArtifact) artifact;
        logger.debug("ExtremeQInput: " + getData(flys, "ranges"));

        /*
        // TODO sort out what has to be validated (prevent negative values?).
        RangeWithValues[] rwvs = extractInput(getData(flys, "ranges"));

        if (rwvs == null) {
            throw new IllegalArgumentException("error_missing_wq_data");
        }

        List<Gauge> gauges = FLYSUtils.getGauges(flys);
        River        river = FLYSUtils.getRiver(flys);
        Wst            wst = WstFactory.getWst(river);

        for (Gauge gauge: gauges) {
            Range range  = gauge.getRange();
            double lower = range.getA().doubleValue();
            double upper = range.getB().doubleValue();

            for (RangeWithValues rwv: rwvs) {
                if (lower <= rwv.getStart() && upper >= rwv.getEnd()) {
                    compareQsWithGauge(wst, gauge, rwv.getValues());
                }
            }
        }
        */

        return true;
    }


    /** Form RangeWithValue-Array from state data. */
    protected RangeWithValues[] extractInput(StateData data) {
        if (data == null) {
            return null;
        }

        String dataString = (String) data.getValue();
        String[]   ranges = dataString.split(":");

        List<RangeWithValues> rwv = new ArrayList<RangeWithValues>();

        for (String range: ranges) {
            String[] parts = range.split(";");

            double lower = Double.parseDouble(parts[0]);
            double upper = Double.parseDouble(parts[1]);

            String[] values = parts[2].split(",");

            int      num = values.length;
            double[] res = new double[num];

            for (int i = 0; i < num; i++) {
                try {
                    res[i] = Double.parseDouble(values[i]);
                }
                catch (NumberFormatException nfe) {
                    logger.warn(nfe, nfe);
                }
            }

            rwv.add(new RangeWithValues(lower, upper, res));
        }

        return rwv.toArray(new RangeWithValues[rwv.size()]);
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org