view artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWQKmsArtifact.java @ 9425:3f49835a00c3

Extended CrossSectionFacet so it may fetch different data from within the artifact result. Also allows to have acces to the potentially already computed artifact result via its normal computation cache.
author gernotbelger
date Fri, 17 Aug 2018 15:31:02 +0200
parents 23264d1a528f
children
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.artifacts;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.dive4elements.artifactdatabase.state.Facet;
import org.dive4elements.artifactdatabase.state.FacetActivity;
import org.dive4elements.artifacts.Artifact;
import org.dive4elements.artifacts.ArtifactFactory;
import org.dive4elements.artifacts.CallContext;
import org.dive4elements.artifacts.CallMeta;
import org.dive4elements.artifacts.common.utils.XMLUtils;
import org.dive4elements.river.artifacts.model.FacetTypes;
import org.dive4elements.river.artifacts.model.WKms;
import org.dive4elements.river.artifacts.model.WKmsFactory;
import org.dive4elements.river.artifacts.model.WQKms;
import org.dive4elements.river.artifacts.model.WQKmsFactory;
import org.dive4elements.river.artifacts.states.DefaultState;
import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
import org.w3c.dom.Document;

/**
 * Artifact to access additional "waterlevel/discharge"-type of data, like
 * fixation measurements.
 *
 * This artifact neglects (Static)D4EArtifacts capabilities of interaction
 * with the StateEngine by overriding the getState*-methods.
 */
public class StaticWQKmsArtifact extends StaticD4EArtifact implements FacetTypes, WaterLineArtifact {
    /** The log for this class. */
    private static Logger log = Logger.getLogger(StaticWQKmsArtifact.class);

    public static final String STATIC_STATE_NAME = "state.additional_wqkms.static";

    private static final String NAME = "staticwqkms";

    static {
        // TODO: Move to configuration.
        FacetActivity.Registry.getInstance().register(NAME, new FacetActivity() {
            @Override
            public Boolean isInitialActive(final Artifact artifact, final Facet facet, final String outputName) {
                final String fname = facet.getName();
                return (fname.equals(STATIC_WQKMS) || fname.equals(STATIC_WQKMS_W));
            }
        });
    }

    /**
     * Trivial Constructor.
     */
    public StaticWQKmsArtifact() {
        log.debug("StaticWQKmsArtifact.StaticWQKmsArtifact");
    }

    /**
     * Gets called from factory, to set things up.
     *
     * If the id's string starts with official- it will be treated as
     * an Artifact containing official data for the according special
     * case handling.
     */
    @Override
    public void setup(final String identifier, final ArtifactFactory factory, final Object context, final CallMeta callMeta, final Document data,
            final List<Class> loadFacets) {
        log.debug("StaticWQKmsArtifact.setup");

        // Store the 'ids' (from datacage).
        if (log.isDebugEnabled()) {
            log.debug("StaticWQKmsArtifact.setup" + XMLUtils.toString(data));
        }

        final String code = getDatacageIDValue(data);
        addStringData("ids", code);
        if (code != null) {
            final String[] parts = code.split("-");

            if (parts.length >= 1) {
                final boolean official = parts[0].toLowerCase().startsWith("official");
                addStringData("official", official ? "1" : "0");
            }

            if (parts.length >= 4) {
                final int col = Integer.parseInt(parts[2]);
                final int wst = Integer.parseInt(parts[3]);

                addStringData("col_pos", parts[2]);
                addStringData("wst_id", parts[3]);
            }
        }

        // Do this AFTER we have set the col_pos etc.
        super.setup(identifier, factory, context, callMeta, data, loadFacets);
    }

    /**
     * Called via setup.
     *
     * @param artifact
     *            The master-artifact.
     */
    @Override
    protected void initialize(final Artifact artifact, final Object context, final CallMeta meta) {
        log.debug("StaticWQKmsArtifact.initialize");
        final D4EArtifact flys = (D4EArtifact) artifact;
        // TODO: The river is of no interest, so far., also use importData
        importData(flys, "river");

        final List<Facet> fs = new ArrayList<>();

        final DefaultState state = (DefaultState) getCurrentState(context);
        state.computeInit(this, hash(), context, meta, fs);
        if (!fs.isEmpty()) {
            log.debug("Facets to add in StaticWQKmsArtifact.initialize .");
            addFacets(getCurrentStateId(), fs);
        } else {
            log.debug("No facets to add in StaticWQKmsArtifact.initialize (" + state.getID() + ").");
        }
    }

    /**
     * Get WQKms from factory.
     *
     * @return WQKms according to parameterization (can be null);
     */
    public WQKms getWQKms() {
        log.debug("StaticWQKmsArtifact.getWQKms");

        final int col = Integer.parseInt(getDataAsString("col_pos"));
        final int wst = Integer.parseInt(getDataAsString("wst_id"));

        /** TODO do not run twice against db to do this. */
        final String wkmsName = WKmsFactory.getWKmsName(col, wst);

        final WQKms res = WQKmsFactory.getWQKms(col, wst);
        res.setName(wkmsName);
        return res;
    }

    /**
     * Get WQKms from factory.
     *
     * @return WQKms according to parameterization (can be null);
     */
    public WQKms getWQKms(final double from, final double to) {
        log.debug("StaticWQKmsArtifact.getWQKms");

        final int col = Integer.parseInt(getDataAsString("col_pos"));
        final int wst = Integer.parseInt(getDataAsString("wst_id"));

        /** TODO do not run twice against db to do this. */
        final String wkmsName = WKmsFactory.getWKmsName(col, wst);

        final WQKms res = WQKmsFactory.getWQKms(col, wst, from, to);
        res.setName(wkmsName);
        return res;
    }

    /** Return specific name. */
    @Override
    public String getName() {
        return NAME;
    }

    /**
     * Get points of line describing the surface of water at cross section.
     *
     * @param idx
     *            Index of facet and in wkms array.
     * @param csl
     *            FastCrossSectionLine to compute water surface agains.
     * @param next
     *            The km of the next crosssectionline.
     * @param prev
     *            The km of the previous crosssectionline.
     * @param context
     *            Ignored in this implementation.
     *
     * @return an array holding coordinates of points of surface of water (
     *         in the form {{x1, x2}, {y1, y2}} ).
     */
    @Override
    public double getWaterLevel(final ComputeType type, final String hash, final String stateId, final double currentKm, final Serializable waterLineIndex,
            final double nextKm, final double prevKm, final CallContext context) {

        final WKms wkms = getWQKms();

        // Find W at km.
        final double wAtKm = StaticWKmsArtifact.getWAtKm(wkms, currentKm);

        if (Double.isNaN(wAtKm)) {
            log.warn("Waterlevel at km " + currentKm + " unknown.");
            return Double.NaN;
        }

        return wAtKm;
    }
    // TODO implement deepCopy.
}

http://dive4elements.wald.intevation.org