felix@1047: package de.intevation.flys.artifacts;
felix@1047: 
felix@1047: import java.util.ArrayList;
felix@1047: import java.util.List;
felix@1047: 
felix@1047: import org.apache.log4j.Logger;
felix@1047: 
felix@1047: import org.w3c.dom.Document;
felix@1047: 
ingo@1095: import de.intevation.artifactdatabase.data.DefaultStateData;
felix@1078: import de.intevation.artifactdatabase.state.Facet;
sascha@3556: import de.intevation.artifactdatabase.state.FacetActivity;
felix@1078: import de.intevation.artifactdatabase.state.DefaultOutput;
felix@1078: import de.intevation.artifactdatabase.state.State;
felix@1078: 
felix@1065: import de.intevation.artifacts.Artifact;
felix@1047: import de.intevation.artifacts.ArtifactFactory;
felix@1047: import de.intevation.artifacts.CallMeta;
ingo@1095: 
ingo@1095: import de.intevation.flys.model.Gauge;
ingo@1095: import de.intevation.flys.model.MainValue;
ingo@1095: import de.intevation.flys.model.River;
felix@1078: 
felix@1101: import de.intevation.flys.artifacts.model.Calculation;
felix@1809: import de.intevation.flys.artifacts.model.FacetTypes;
felix@1089: import de.intevation.flys.artifacts.model.MainValuesQFacet;
felix@1085: import de.intevation.flys.artifacts.model.MainValuesWFacet;
felix@1089: import de.intevation.flys.artifacts.model.NamedDouble;
felix@1101: import de.intevation.flys.artifacts.model.WstValueTable;
felix@1101: import de.intevation.flys.artifacts.model.WstValueTableFactory;
felix@1101: 
felix@1072: import de.intevation.flys.artifacts.states.StaticState;
felix@1112: import de.intevation.flys.artifacts.resources.Resources;
felix@1101: 
ingo@1095: import de.intevation.flys.utils.FLYSUtils;
felix@1078: 
felix@1047: 
felix@1047: /**
felix@4126:  * Artifact to access main and extreme values of a river.
felix@1072:  * This artifact neglects (Static)FLYSArtifacts capabilities of interaction
felix@1072:  * with the StateEngine by overriding the getState*-methods.
felix@1047:  */
felix@1047: public class MainValuesArtifact
felix@1047: extends      StaticFLYSArtifact
felix@1809: implements   FacetTypes
sascha@1059: {
felix@1047:     /** The logger for this class. */
felix@1065:     private static Logger logger = Logger.getLogger(MainValuesArtifact.class);
felix@1047: 
felix@1047:     /** The name of the artifact. */
felix@1065:     public static final String ARTIFACT_NAME = "mainvalue";
felix@1072: 
felix@1771:     /** The name of the static state for this artifact. */
felix@1771:     public static final String STATIC_STATE_NAME = "state.mainvalue.static";
felix@1771: 
felix@1078:     /** One and only state to be in. */
felix@1078:     protected transient State state = null;
felix@1078: 
felix@1072: 
sascha@3558:     static {
sascha@3558:         // TODO: Move to configuration.
sascha@3558:         FacetActivity.Registry.getInstance().register(
sascha@3558:             ARTIFACT_NAME,
sascha@3558:             new FacetActivity() {
sascha@3558:                 @Override
sascha@3558:                 public Boolean isInitialActive(
sascha@3558:                     Artifact artifact,
sascha@3558:                     Facet    facet,
sascha@3558:                     String   outputName
sascha@3558:                 ) {
sascha@3558:                     return outputName.equals("computed_discharge_curve")
sascha@3558:                         || outputName.equals("duration_curve");
sascha@3558:                 }
sascha@3558:             });
sascha@3558:     }
sascha@3558: 
felix@1072:     /**
felix@1072:      * Trivial Constructor.
felix@1072:      */
felix@1047:     public MainValuesArtifact() {
felix@1072:         logger.debug("MainValuesArtifact.MainValuesartifact()");
felix@1047:     }
felix@1047: 
felix@1072: 
felix@1047:     /**
felix@1047:      * Gets called from factory, to set things up.
felix@1047:      */
felix@1047:     @Override
felix@1047:     public void setup(
felix@1047:         String          identifier,
felix@1047:         ArtifactFactory factory,
felix@1047:         Object          context,
felix@1047:         CallMeta        callMeta,
felix@1047:         Document        data)
felix@1047:     {
felix@1072:         logger.debug("MainValuesArtifact.setup");
felix@1787:         state = new StaticState(STATIC_STATE_NAME);
felix@1787: 
felix@4126:         List<Facet> fs = new ArrayList<Facet>();
felix@4126:         facets.put(state.getID(), fs);
felix@4126:         spawnState();
felix@4126:         super.setup(identifier, factory, context, callMeta, data);
felix@4126:         String restriction = getDatacageIDValue(data);
felix@4126:         logger.debug("mainvalue restriction " + restriction);
felix@4126:         boolean restricted = restriction.endsWith("q") || restriction.endsWith("w");
felix@4126:         if (!restricted || restriction.endsWith("q")) {
felix@4126:             Facet qfacet0 = new MainValuesQFacet(
felix@4126:                 DURATION_MAINVALUES_Q,
felix@4126:                 Resources.getMsg(
felix@4126:                     callMeta,
felix@4126:                     "facet.discharge_curves.mainvalues.q",
felix@4126:                     "facet.discharge_curves.mainvalues.q"),
felix@4126:                 false);
felix@4126:             Facet qfacet1 = new MainValuesQFacet(
felix@4126:                 COMPUTED_DISCHARGE_MAINVALUES_Q,
felix@4126:                 Resources.getMsg(
felix@4126:                     callMeta,
felix@4126:                     "facet.discharge_curves.mainvalues.q",
felix@4126:                     "facet.discharge_curves.mainvalues.q"),
felix@4126:                 false);
felix@4126:             Facet qfacet2 = new MainValuesQFacet(
felix@4126:                 MAINVALUES_Q,
felix@4126:                 Resources.getMsg(
felix@4126:                     callMeta,
felix@4126:                     "facet.discharge_curves.mainvalues.q",
felix@4126:                     "facet.discharge_curves.mainvalues.q"),
felix@4126:                 true);
felix@4126:             
felix@4126:             fs.add(qfacet0);
felix@4126:             fs.add(qfacet1);
felix@4126:             fs.add(qfacet2);
felix@4126:         }
felix@4126:         if (!restricted || restriction.endsWith("w")) {
felix@1809:         Facet wfacet1 = new MainValuesWFacet(
felix@1809:             COMPUTED_DISCHARGE_MAINVALUES_W,
felix@1809:             Resources.getMsg(
felix@1809:                 callMeta,
felix@1809:                 "facet.discharge_curves.mainvalues.w",
felix@1957:                 "facet.discharge_curves.mainvalues.w"),
felix@1957:             false);
felix@1809:         Facet wfacet2 = new MainValuesWFacet(
felix@1809:             MAINVALUES_W,
felix@1809:             Resources.getMsg(
felix@1809:                 callMeta,
felix@1809:                 "facet.discharge_curves.mainvalues.w",
felix@1957:                 "facet.discharge_curves.mainvalues.w"),
felix@1957:             true);
felix@4126:             fs.add(wfacet1);
felix@4126:             fs.add(wfacet2);
felix@4126:         }
felix@1080:     }
felix@1080: 
felix@1771: 
felix@1771:     /**
felix@1771:      * Create "the" state.
felix@1771:      */
felix@1112:     protected State spawnState() {
felix@1787:         state = new StaticState(STATIC_STATE_NAME);
felix@1771:         List<Facet> fs = (List<Facet>) facets.get(STATIC_STATE_NAME);
felix@1771: 
felix@1847:         DefaultOutput mainValuesOutput = new DefaultOutput(
felix@1765:             "computed_discharge_curve",
felix@1765:             "output.computed_discharge_curve", "image/png",
felix@1771:             fs,
felix@1765:             "chart");
felix@1112: 
felix@1847:         state.getOutputs().add(mainValuesOutput);
felix@1112:         return state;
felix@1112:     }
felix@1112: 
felix@1080: 
felix@1080:     @Override
felix@1080:     protected void initialize(Artifact artifact, Object context, CallMeta meta) {
felix@1080:         logger.debug("MainValuesArtifact.initialize");
raimund@2134:         FLYSArtifact winfo = (FLYSArtifact) artifact;
felix@1847:         double [] locations = FLYSUtils.getLocations(winfo);
felix@1847:         if (locations != null) {
felix@1847:             double location = locations[0];
felix@1847:             addData("location", new DefaultStateData("location", null, null,
felix@1085:                     String.valueOf(location)));
felix@1847:         }
felix@1847:         else {
felix@1847:             logger.warn("No location for mainvalues given.");
felix@1847:         }
felix@1922:         importData(winfo, "river");
felix@1047:     }
felix@1047: 
felix@1047: 
felix@1047:     /**
felix@1072:      * Get a list containing the one and only State.
felix@1085:      * @param  context ignored.
felix@1072:      * @return list with one and only state.
felix@1047:      */
felix@1072:     @Override
felix@1072:     protected List<State> getStates(Object context) {
felix@1072:         ArrayList<State> states = new ArrayList<State>();
felix@1112:         states.add(getState());
felix@1072:         return states;
felix@1072:     }
felix@1047: 
felix@1047: 
felix@1072:     /**
felix@1072:      * Get the "current" state.
felix@1072:      * @param cc ignored.
felix@1072:      * @return the "current" state.
felix@1072:      */
felix@1072:     @Override
ingo@1654:     public State getCurrentState(Object cc) {
felix@1072:         return getState();
felix@1072:     }
felix@1072: 
felix@1072: 
felix@1072:     /**
felix@1072:      * Get the only possible state.
felix@1072:      * @return the state.
felix@1072:      */
felix@1072:     protected State getState() {
felix@1072:         return getState(null, null);
felix@1072:     }
felix@1072: 
felix@1072: 
felix@1072:     /**
felix@1072:      * Get the state.
felix@1072:      * @param context ignored.
felix@1072:      * @param stateID ignored.
felix@1072:      * @return the state.
felix@1072:      */
felix@1072:     @Override
felix@1072:     protected State getState(Object context, String stateID) {
felix@1112:         if (state != null)
felix@1112:             return state;
felix@1112:         else
felix@1112:             return spawnState();
felix@1078:     }
felix@1078: 
felix@1093: 
felix@1085:     /**
felix@1089:      * Access the Gauge that the mainvalues are taken from.
felix@1089:      * @return Gauge that main values are taken from or null in case of
felix@1089:      *         invalid parameterization.
felix@1089:      */
felix@1085:     protected Gauge getGauge() {
felix@1100:         River river = FLYSUtils.getRiver(this);
felix@1065: 
felix@1847:         // TODO use helper to get location as double
felix@1847:         String locationStr = getDataAsString("location");
felix@1847: 
felix@1847:         if (river == null || locationStr == null) {
felix@1085:             return null;
felix@1072:         }
felix@1065: 
felix@1847:         double location = Double.parseDouble(locationStr);
felix@1079: 
felix@1085:         return river.determineGaugeByPosition(location);
felix@1085:     }
felix@1085: 
felix@1089: 
felix@1089:     /**
felix@1101:      * Get current location.
felix@1101:      * @return the location.
felix@1089:      */
felix@1101:     public double getLocation() {
felix@1847:         double location = Double.parseDouble(getDataAsString("location"));
felix@1101:         return location;
felix@1089:     }
felix@1089: 
felix@1089: 
felix@1089:     /**
felix@1089:      * Get a list of "Q" main values.
felix@1089:      * @return list of Q main values.
felix@1089:      */
felix@1957:     public List<NamedDouble> getMainValuesQ(boolean atGauge) {
felix@1089:         List<NamedDouble> filteredList = new ArrayList<NamedDouble>();
felix@1085:         Gauge gauge = getGauge();
felix@1101:         WstValueTable interpolator = WstValueTableFactory.getTable(FLYSUtils.getRiver(this));
felix@1101:         Calculation c = new Calculation();
felix@1101:         double w_out[] = {0.0f};
felix@1101:         double q_out[] = {0.0f};
felix@1101:         double kms[] = {getLocation()};
felix@1101:         double gaugeStation = gauge.getStation().doubleValue();
felix@1085:         if (gauge != null) {
felix@1085:             List<MainValue> orig = gauge.getMainValues();
felix@1085:             for (MainValue mv : orig) {
felix@1085:                 if (mv.getMainValue().getType().getName().equals("Q")) {
felix@1957:                     if (atGauge) {
felix@1957:                         q_out[0] = mv.getValue().doubleValue();
felix@1957:                     }
felix@1957:                     else {
felix@1957:                         interpolator.interpolate(mv.getValue().doubleValue(),
felix@1101:                             gaugeStation, kms, w_out, q_out, c);
felix@1957:                     }
felix@1089:                     filteredList.add(new NamedDouble(
felix@1089:                                 mv.getMainValue().getName(),
felix@1101:                                 q_out[0]
felix@1089:                                 ));
felix@1085:                 }
felix@1085:             }
felix@1065:         }
felix@1085:         return filteredList;
felix@1085:     }
felix@1085: 
felix@1089: 
felix@1089:     /**
felix@1089:      * Get a list of "W" main values.
felix@1957:      * @param atGauge if true, do not interpolate
felix@1089:      * @return list of W main values.
felix@1089:      */
felix@1957:     public List<NamedDouble> getMainValuesW(boolean atGauge) {
felix@1089:         List<NamedDouble> filteredList = new ArrayList<NamedDouble>();
felix@1085:         Gauge gauge = getGauge();
felix@1101:         WstValueTable interpolator = WstValueTableFactory.getTable(FLYSUtils.getRiver(this));
felix@1101:         Calculation c = new Calculation();
felix@1847: 
felix@1101:         double gaugeStation = gauge.getStation().doubleValue();
felix@1101:         double w_out[] = {0.0f};
felix@1101:         double q_out[] = {0.0f};
felix@1101:         double kms[] = {getLocation()};
felix@1085:         if (gauge != null) {
felix@1085:             List<MainValue> orig = gauge.getMainValues();
felix@1085:             for (MainValue mv : orig) {
felix@1957:                 if (atGauge) {
felix@1957:                     if (mv.getMainValue().getType().getName().equals("W")) {
felix@1957:                         filteredList.add(new NamedDouble(mv.getMainValue().getName(),
felix@1957:                                 mv.getValue().doubleValue()));
sascha@3076: 
felix@1957:                     }
felix@1957:                 } else
felix@1101:                 // We cannot interpolate the W values, so derive them
felix@1101:                 // from given Q values.
felix@1101:                 if (mv.getMainValue().getType().getName().equals("Q")) {
felix@1101:                     interpolator.interpolate(mv.getValue().doubleValue(),
felix@1101:                             gaugeStation, kms, w_out, q_out, c);
felix@1089:                     filteredList.add(new NamedDouble(
felix@1101:                                 "W(" + mv.getMainValue().getName() +")",
felix@1101:                                 w_out[0]
felix@1089:                                 ));
felix@1085:                 }
felix@1085:             }
felix@1065:         }
felix@1085:         return filteredList;
felix@1065:     }
felix@1047: }
felix@1809: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :