view artifacts/src/main/java/org/dive4elements/river/artifacts/model/CrossSectionWaterLineFacet.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 5e38e2924c07
children bd5f5d2220fa
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.model;

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

import org.apache.log4j.Logger;
import org.dive4elements.artifactdatabase.state.Facet;
import org.dive4elements.artifacts.Artifact;
import org.dive4elements.artifacts.CallContext;
import org.dive4elements.artifacts.DataProvider;
import org.dive4elements.river.artifacts.WaterLineArtifact;
import org.dive4elements.river.artifacts.geom.Lines;
import org.dive4elements.river.artifacts.geom.Lines.LineData;
import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
import org.dive4elements.river.model.FastCrossSectionLine;

/**
 * Facet for Waterlines in Cross Sections.
 */
public class CrossSectionWaterLineFacet extends DataFacet implements FacetTypes {

    private static final LineData NO_LINE_DATA = new Lines.LineData(new double[][] {}, 0d, 0d);

    private static final long serialVersionUID = 1L;

    /** Private log to use. */
    private static Logger log = Logger.getLogger(CrossSectionWaterLineFacet.class);

    private final Serializable waterLineIndex;

    /** Trivial constructor, set (maybe localized) description. */
    public CrossSectionWaterLineFacet(final int idx, final String description, final ComputeType type, final String hash, final String stateId,
            final Serializable waterLineIndex) {
        this(idx, CROSS_SECTION_WATER_LINE, description, type, hash, stateId, waterLineIndex);
    }

    /**
     * Trivial constructor, set (maybe localized) description.
     *
     * @param facetIndex
     *            Index of this facet.
     * @param waterLineIndex
     *            Determines which water-line the artifact will return. Depends on the implementation of the artifact.
     *            Is serializable because this class is, must be immutable because only the reference is copied in
     *            'deepCopy'
     * @param name
     *            'type' of this facet.
     * @param description
     *            (maybe) localized user-visible description.
     */
    public CrossSectionWaterLineFacet(final int facetIndex, final String name, final String description, final ComputeType type, final String hash,
            final String stateId, final Serializable waterLineIndex) {
        super(facetIndex, name, description, type, hash, stateId);

        this.waterLineIndex = waterLineIndex;
    }

    /**
     * Gets waterline (crossed with cross section) of waterlevel.
     * FIXME: the cross section facets delgate fetching the data to the artifact, which in turn (in most cases) re-calculate
     * the artifact on every call....
     * Instead this should work like other facets that rely on the hashed computation.
     */
    @Override
    public Object getData(final Artifact artifact, final CallContext context) {
        log.debug("Get data for cross section water line");

        final List<DataProvider> providers = context.getDataProvider(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA);
        if (providers.size() < 1) {
            log.warn("Could not find Cross-Section data provider.");
            return NO_LINE_DATA;
        }

        final DataProvider dataProvider = providers.get(0);

        final FastCrossSectionLine crossSection = (FastCrossSectionLine) dataProvider.provideData(CrossSectionFacet.BLACKBOARD_CS_MASTER_DATA, null, context);
        if (crossSection == null)
            return NO_LINE_DATA;

        Object nextKm = dataProvider.provideData(CrossSectionFacet.BLACKBOARD_CS_NEXT_KM, null, context);
        Object prevKm = dataProvider.provideData(CrossSectionFacet.BLACKBOARD_CS_PREV_KM, null, context);
        if (prevKm == null)
            prevKm = new Double(-1d);
        if (nextKm == null)
            nextKm = new Double(-1d);

        if (!(artifact instanceof WaterLineArtifact)) {
            log.error("CrossSectionWaterLineFacet needs WaterLineArtifact");
            return NO_LINE_DATA;
        }

        final WaterLineArtifact lineArtifact = (WaterLineArtifact) artifact;

        final double currentKm = crossSection.getKm();

        final double waterLevel = lineArtifact.getWaterLevel(this.type, this.hash, this.stateId, currentKm, this.waterLineIndex, (Double) nextKm,
                (Double) prevKm,
                context);
        if (Double.isNaN(waterLevel))
            return NO_LINE_DATA;

        return Lines.createWaterLines(crossSection.getPoints(), waterLevel);
    }

    /** Do a deep copy. */
    @Override
    public Facet deepCopy() {
        final CrossSectionWaterLineFacet copy = new CrossSectionWaterLineFacet(this.getIndex(), this.name, this.description, this.type, this.hash, this.stateId,
                this.waterLineIndex);
        copy.set(this);
        return copy;
    }
}

http://dive4elements.wald.intevation.org