view artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelFetcher.java @ 8881:6b93a2498e06

Slightly better abstraction for extraction waterlevels via datacage
author gernotbelger
date Fri, 09 Feb 2018 16:11:34 +0100
parents
children a536e1aacf0f
line wrap: on
line source
/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
 * Software engineering by
 *  Björnsen Beratende Ingenieure GmbH
 *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
 *
 * 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.states;

import java.util.List;

import org.apache.log4j.Logger;
import org.dive4elements.artifacts.CallContext;
import org.dive4elements.river.artifacts.D4EArtifact;
import org.dive4elements.river.artifacts.FixationArtifact;
import org.dive4elements.river.artifacts.StaticWKmsArtifact;
import org.dive4elements.river.artifacts.StaticWQKmsArtifact;
import org.dive4elements.river.artifacts.WINFOArtifact;
import org.dive4elements.river.artifacts.access.FixRealizingAccess;
import org.dive4elements.river.artifacts.model.CalculationResult;
import org.dive4elements.river.artifacts.model.Segment;
import org.dive4elements.river.artifacts.model.WKms;
import org.dive4elements.river.artifacts.model.WQKms;
import org.dive4elements.river.artifacts.model.fixings.FixRealizingResult;
import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
import org.dive4elements.river.utils.RiverUtils;

/**
 * Helper class that accesses existing waterlevels (in most cases) from the data-cage.
 * This is mainly a refaktoring of org.dive4elements.river.artifacts.states.WDifferencesState.getWKms(String,
 * CallContext, double, double), adding more infos to the fetched water levels.
 *
 * @author Gernot Belger
 */
public class WaterlevelFetcher {
    private static Logger log = Logger.getLogger(WaterlevelFetcher.class);

    public WaterlevelData findWaterlevel(final CallContext context, final String mingle, final double from,
            final double to) {

        final String[] def = mingle.split(";");
        final String uuid = def[0];
        final String name = def[1];
        final int idx = Integer.parseInt(def[2]);
        final D4EArtifact d4eArtifact = RiverUtils.getArtifact(uuid, context);

        final WaterlevelData data = fetchWaterlevelFromArtifact(context, d4eArtifact, idx, from, to);
        return data.withName(name);
    }

    private WaterlevelData fetchWaterlevelFromArtifact(final CallContext context, final D4EArtifact d4eArtifact,
            final int idx, final double from, final double to) {
        if (d4eArtifact == null) {
            log.warn("One of the artifacts (1) for diff calculation " + "could not be loaded");
            return null;
        }

        if (d4eArtifact instanceof StaticWKmsArtifact) {
            return fetchStaticWKmsArtifactWaterlevel((StaticWKmsArtifact) d4eArtifact, idx, from, to);
        }

        if (d4eArtifact instanceof StaticWQKmsArtifact) {
            return fetchStaticWQKmsArtifactWaterlevel((StaticWQKmsArtifact) d4eArtifact, from, to);
        }

        if (d4eArtifact instanceof WINFOArtifact)
            return fetchWINFOArtifactWaterlevel(context, (WINFOArtifact) d4eArtifact, idx, from, to);

        if (d4eArtifact instanceof FixationArtifact)
            return fetchFixationArtifactWaterlevel(context, (FixationArtifact) d4eArtifact, idx, from, to);

        log.warn(String.format("Get Waterlevel from %s not implemented! )", d4eArtifact.getClass().getSimpleName()));
        return null;
    }

    // REMARK/TODO: instead of several helper methods here this would be a good place for abstraction, in order to push
    // this logic back to the corresponding artifacts

    private WaterlevelData fetchStaticWKmsArtifactWaterlevel(final StaticWKmsArtifact staticWKms, final int idx,
            final double from, final double to) {

        log.debug("WDifferencesState obtain data from StaticWKms");

        final WKms wkms = staticWKms.getWKms(idx, from, to);

        if (wkms != null)
            return new WaterlevelData(wkms);

        log.error("No WKms from Static artifact for this range.");
        return null;
    }

    private WaterlevelData fetchStaticWQKmsArtifactWaterlevel(final StaticWQKmsArtifact staticWKms, final double from,
            final double to) {

        log.debug("WDifferencesState obtain data from StaticWQKms");

        final WQKms wkms = staticWKms.getWQKms(from, to);

        if (wkms != null)
            return new WaterlevelData(wkms);

        log.error("No WKms from Static artifact for this range.");
        return null;
    }

    private WaterlevelData fetchWINFOArtifactWaterlevel(final CallContext context, final WINFOArtifact flys,
            final int idx, final double from, final double to) {
        log.debug("Get WKms from WINFOArtifact");

        final WKms[] wkms = (WKms[]) flys.getWaterlevelData(context).getData();

        if (wkms == null || wkms.length == 0) {
            log.warn("no waterlevels in artifact");
            return null;
        }

        if (wkms.length < idx + 1) {
            log.warn("Not enough waterlevels in artifact.");
            return null;
        }

        return new WaterlevelData(wkms[idx]).filterByRange(from, to);
    }

    private WaterlevelData fetchFixationArtifactWaterlevel(final CallContext context,
            final FixationArtifact fixation, final int idx, final double from, final double to) {

        log.debug("Get WKms from FixationArtifact.");

        final CalculationResult r = (CalculationResult) fixation.compute(context, ComputeType.ADVANCE, false);
        final FixRealizingResult frR = (FixRealizingResult) r.getData();

        // Get W/Q input per gauge for this case.
        final FixRealizingAccess fixAccess = new FixRealizingAccess(fixation);
        final List<Segment> segments = fixAccess.getSegments();
        final boolean isFixRealize = (segments != null && !segments.isEmpty());

        // REMARK: same logic as in WaterlevelExporter
        final boolean showAllGauges = isFixRealize;

        return new WaterlevelData(frR.getWQKms()[idx], showAllGauges).filterByRange(from, to);
    }
}

http://dive4elements.wald.intevation.org