teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.artifacts; felix@1896: felix@1896: import java.util.ArrayList; felix@1896: import java.util.List; felix@1896: felix@1896: import org.apache.log4j.Logger; felix@1896: felix@1896: import org.w3c.dom.Document; felix@1896: teichmann@5831: import org.dive4elements.artifactdatabase.state.Facet; teichmann@5831: import org.dive4elements.artifactdatabase.state.FacetActivity; teichmann@5831: import org.dive4elements.artifactdatabase.state.DefaultOutput; teichmann@5831: import org.dive4elements.artifactdatabase.state.State; felix@1896: teichmann@5831: import org.dive4elements.artifacts.Artifact; teichmann@5831: import org.dive4elements.artifacts.ArtifactFactory; teichmann@5831: import org.dive4elements.artifacts.CallMeta; felix@1896: teichmann@5831: import org.dive4elements.river.artifacts.model.FacetTypes; teichmann@5831: import org.dive4elements.river.artifacts.model.WQKms; teichmann@5831: import org.dive4elements.river.artifacts.model.WQFacet; teichmann@5831: import org.dive4elements.river.artifacts.model.WKmsFactory; teichmann@5831: import org.dive4elements.river.artifacts.model.WQKmsFactory; teichmann@5831: import org.dive4elements.river.artifacts.model.WstValueTable; teichmann@5831: import org.dive4elements.river.artifacts.model.WstValueTableFactory; teichmann@5831: teichmann@5831: import org.dive4elements.river.artifacts.states.StaticState; teichmann@5831: import org.dive4elements.river.artifacts.resources.Resources; felix@1896: felix@1896: felix@1896: /** felix@1896: * Artifact to access additional "waterlevel/discharge"-type of data, like felix@1896: * fixation measurements, but doing so with costy interpolation. felix@1896: * teichmann@5867: * This artifact neglects (Static)D4EArtifacts capabilities of interaction felix@1896: * with the StateEngine by overriding the getState*-methods. felix@1896: */ felix@1896: public class WQKmsInterpolArtifact teichmann@5867: extends StaticD4EArtifact felix@1896: implements FacetTypes felix@1896: { teichmann@8202: /** The log for this class. */ teichmann@8202: private static Logger log = felix@1896: Logger.getLogger(WQKmsInterpolArtifact.class); felix@1896: felix@3634: /** State name. */ felix@1896: public static final String STATIC_STATE_NAME = felix@1896: "state.additional_wqkms.interpol.static"; felix@1896: felix@3634: /** Artifact name. */ sascha@3556: private static final String NAME = "staticwqkmsinterpol"; sascha@3556: sascha@3556: static { sascha@3556: // TODO: Move to configuration. sascha@3556: FacetActivity.Registry.getInstance() sascha@3556: .register(NAME, FacetActivity.INACTIVE); sascha@3556: } sascha@3556: felix@1896: /** One and only state to be in. */ felix@1896: protected transient State state = null; felix@1896: felix@1896: felix@1896: /** felix@1896: * Trivial Constructor. felix@1896: */ felix@1896: public WQKmsInterpolArtifact() { teichmann@8202: log.debug("WQKmsInterpolArtifact.WQKmsInterpolArtifact"); felix@1896: } felix@1896: felix@1896: felix@3634: /** Return fixed artifact (types) name. */ sascha@3556: @Override sascha@3556: public String getName() { sascha@3556: return NAME; sascha@3556: } sascha@3556: sascha@3556: felix@1896: /** felix@1896: * Gets called from factory, to set things up. felix@1896: */ felix@1896: @Override felix@1896: public void setup( felix@1896: String identifier, felix@1896: ArtifactFactory factory, felix@1896: Object context, felix@1896: CallMeta callMeta, rrenkert@7842: Document data, rrenkert@7842: List loadFacets) felix@1896: { teichmann@8202: log.debug("WQKmsInterpolArtifact.setup"); felix@1896: felix@1896: state = new StaticState(STATIC_STATE_NAME); felix@1896: felix@1896: List fs = new ArrayList(); felix@2741: String code = getDatacageIDValue(data); felix@1896: felix@1896: // TODO Go for JSON, one day. felix@1896: //ex.: flood_protection-wstv-114-12 felix@1896: if (code != null) { felix@1896: String [] parts = code.split("-"); felix@1896: teichmann@8202: log.debug("WQKmsInterpolArtifact.setup: code " + code); felix@3634: felix@1896: if (parts.length >= 4) { sascha@3405: int wst = Integer.parseInt(parts[3]); felix@1910: int col = -1; felix@1910: String colpos = parts[2]; felix@1910: // Are we interested in a single column or in all columns? felix@1910: if (colpos.equals("A")) { felix@1910: ; // Take all. felix@1910: } felix@1910: else { sascha@3405: col = Integer.parseInt(colpos); felix@1910: addStringData("col_pos", parts[2]); felix@1910: } felix@1896: addStringData("wst_id", parts[3]); felix@3634: String wkmsName = (col >= 0) felix@1910: ? WKmsFactory.getWKmsName(col, wst) felix@1910: : WKmsFactory.getWKmsName(wst); felix@1920: String name; felix@1920: if (parts[0].startsWith("height")){ felix@1920: name = STATIC_WQ_ANNOTATIONS; felix@1920: } felix@1920: else if (parts[0].startsWith("flood")) { felix@1920: name = STATIC_WKMS_INTERPOL; felix@1920: } felix@1920: else { felix@6925: // If all Qs are zero, add different facet to felix@6925: // signalize that we want data to be drawn as marks felix@6925: // on axis. felix@6925: if (wstValueHasZeroQ()) { felix@6925: name = STATIC_W_INTERPOL; felix@6925: } felix@6925: else { felix@6925: name = STATIC_WQ; felix@6925: } felix@1920: } felix@1914: felix@3585: Facet wQFacet = new WQFacet(name, felix@1896: Resources.getMsg( felix@1896: callMeta, felix@1896: wkmsName, felix@1896: wkmsName)); felix@3585: fs.add(wQFacet); bjoern@4497: addFacets(state.getID(), fs); felix@1896: } felix@1896: } felix@3634: else { teichmann@8202: log.warn("WQKmsInterpolArtifact: no code"); felix@3634: } felix@1896: felix@1896: spawnState(); rrenkert@7842: super.setup(identifier, factory, context, callMeta, data, loadFacets); felix@1896: } felix@1896: felix@1896: felix@1896: /** felix@1896: * Initialize the static state with output. felix@1896: * @return static state felix@1896: */ felix@1896: protected State spawnState() { felix@1896: state = new StaticState(STATIC_STATE_NAME); bjoern@4497: List fs = getFacets(STATIC_STATE_NAME); felix@1896: DefaultOutput output = new DefaultOutput( felix@1896: "general", felix@1896: "general", felix@1896: "image/png", felix@1896: fs, felix@1896: "chart"); felix@1896: felix@1896: state.getOutputs().add(output); felix@1896: felix@1896: return state; felix@1896: } felix@1896: felix@1896: felix@1896: /** felix@1896: * Called via setup. felix@1896: * felix@1896: * @param artifact The master-artifact. felix@1896: */ felix@1896: @Override felix@1896: protected void initialize( felix@1896: Artifact artifact, felix@1896: Object context, felix@1896: CallMeta meta) felix@1896: { teichmann@8202: log.debug("WQKmsInterpolArtifact.initialize"); teichmann@5867: D4EArtifact winfo = (D4EArtifact) artifact; felix@1896: importData(winfo, "river"); felix@1906: importData(winfo, "ld_locations"); felix@1896: } felix@1896: felix@1896: felix@1896: /** felix@1896: * Get a list containing the one and only State. felix@1896: * @param context ignored. felix@1896: * @return list with one and only state. felix@1896: */ felix@1896: @Override felix@1896: protected List getStates(Object context) { felix@1896: ArrayList states = new ArrayList(); felix@1896: states.add(getState()); felix@1896: return states; felix@1896: } felix@1896: felix@1896: felix@6925: /** True if Wst has only 'fake' (zero) Q-ranges. */ felix@6925: private boolean wstValueHasZeroQ() { felix@6925: WstValueTable table = getValueTable(); felix@6925: return table.hasEmptyQ(); felix@6925: } felix@6925: felix@6925: felix@6925: /** Get the WstValueTable that matches parameterization. */ felix@6925: private WstValueTable getValueTable() { felix@6925: // Get WstValueTable felix@6925: int wstId = getDataAsInt("wst_id"); felix@6925: if (getDataAsString("col_pos") != null) { felix@6925: return WstValueTableFactory.getWstColumnTable( felix@6925: wstId, getDataAsInt("col_pos")); felix@6925: } felix@6925: else { felix@6925: return WstValueTableFactory.getTable(wstId); felix@6925: } felix@6925: } felix@6925: felix@6925: felix@6925: /** felix@6925: * Get WQ Values at a certain km, interpolating only if distance felix@6925: * between two stations is smaller than given distance. felix@6925: */ felix@6925: public double [][] getWQAtKm( felix@6925: Double currentKm, felix@6925: double maxKmInterpolDistance felix@6925: ) { felix@6925: // TODO yet to be implemented (issue1378). felix@6925: return null; felix@6925: } felix@6925: felix@6925: felix@1896: /** felix@1896: * Get WQ at a given km. felix@6924: * felix@3585: * @param currentKm the requested km. If NULL, ld_location data felix@3585: * will be used. felix@6924: * @return [[q1,q2,q2],[w1,w2,w3]] ... felix@1896: */ felix@3585: public double [][] getWQAtKm(Double currentKm) { felix@1910: felix@6925: // TODO issue1378: only interpolate if dist <= 100m felix@6925: WstValueTable interpolator = getValueTable(); felix@1896: felix@3585: Double tmp = (currentKm != null) felix@3585: ? currentKm felix@3585: : getDataAsDouble("ld_locations"); felix@3585: felix@1906: double [][] vs = interpolator.interpolateWQColumnwise( ingo@2701: tmp != null ? tmp : 0); felix@1896: felix@1896: for (int x = 0; x < vs[1].length; x++) { teichmann@8202: log.debug("getWQAtKm: Q/W " + vs[0][x] + " / " + vs[1][x]); felix@1896: } felix@1896: felix@1896: return vs; felix@1896: } felix@1896: felix@1896: felix@1896: /** felix@1896: * Get a DataItem casted to int (0 if fails). felix@1896: */ felix@1896: public int getDataAsInt(String dataName) { felix@1896: String val = getDataAsString(dataName); felix@1896: try { sascha@3405: return Integer.parseInt(val); felix@1896: } felix@1896: catch (NumberFormatException e) { teichmann@8202: log.warn("Could not get data " + dataName + " as int", e); felix@1896: return 0; felix@1896: } felix@1896: } felix@1896: felix@1896: felix@1896: /** felix@1896: * Get the "current" state (there is but one). felix@1896: * @param cc ignored. felix@1896: * @return the "current" (only possible) state. felix@1896: */ felix@1896: @Override felix@1896: public State getCurrentState(Object cc) { felix@1896: return getState(); felix@1896: } felix@1896: felix@1896: felix@1896: /** felix@1896: * Get the only possible state. felix@1896: * @return the state. felix@1896: */ felix@1896: protected State getState() { felix@1896: return getState(null, null); felix@1896: } felix@1896: felix@1896: felix@1896: /** felix@1896: * Get the state. felix@1896: * @param context ignored. felix@1896: * @param stateID ignored. felix@1896: * @return the state. felix@1896: */ felix@1896: @Override felix@1896: protected State getState(Object context, String stateID) { felix@1896: return (state != null) felix@1896: ? state felix@1896: : spawnState(); felix@1896: } felix@1896: felix@1896: felix@1896: /** felix@1896: * Get WQKms from factory. felix@3270: * @param idx param is not needed (TODO) felix@1896: * @return WQKms according to parameterization (can be null); felix@1896: */ felix@1896: public WQKms getWQKms(int idx) { teichmann@8202: log.debug("WQKmsInterpolArtifact.getWQKms"); teichmann@8202: log.warn("Stub, getWQKms not yet implemented."); felix@1896: felix@1896: return WQKmsFactory.getWQKms( sascha@3405: Integer.parseInt(getDataAsString("col_pos")), sascha@3405: Integer.parseInt(getDataAsString("wst_id"))); felix@1896: } felix@1896: } felix@1896: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :