Mercurial > dive4elements > river
changeset 160:27d3d0093993
merged flys-artifacts/0.1
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:07 +0200 |
parents | deaa50a8be82 (current diff) ea7bf9990973 (diff) |
children | 2b745b5e731c |
files | |
diffstat | 31 files changed, 3484 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/ChangeLog Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,473 @@ +2011-03-30 Ingo Weinzierl <ingo@intevation.de> + + * doc/conf/artifacts/winfo.xml: Renamed an output mode in the WINFO + artifact configuration. + +2011-03-29 Ingo Weinzierl <ingo@intevation.de> + + * src/main/resources/messages_de_DE.properties, + src/main/resources/messages_de.properties: Changed a german string. + +2011-03-29 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/states/CalculationSelect.java: + Modified the available calculation modes and its order in the DESCRIBE + document. + + * src/main/resources/messages.properties, + src/main/resources/messages_de_DE.properties, + src/main/resources/messages_en.properties, + src/main/resources/messages_de.properties: Adapted the names of + calculation modes. + +2011-03-28 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java: + Added the hash code of an artifact to the artifact part of the + collection's DESCRIBE document. + +2011-03-28 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: Changed + the background color of discharge curves to white. + +2011-03-28 Sascha L. Teichmann <sascha.teichmann@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/model/DischargeTables.java: + Cache the scale, too. Otherwise two calls to getValues() with + different arguments will result in the same output. + +2011-03-28 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/model/DischargeTables.java: + Introduced a 'scale' parameter in the getValues() method. + + * src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: Filled + the out() operation with code that draws a discharge table of one or + more gauges specified by the given range in entered in a previous state. + +2011-03-28 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/exports/ChartExportHelper.java: + New. A helper class to exports charts. + + * pom.xml: Added dependencies to iText, Batik and JFreeChart. + +2011-03-28 Sascha L. Teichmann <sascha.teichmann@intevation.de> + + * src/main/java/de/intevation/flys/importer/PegelGltParser.java: + Fixed swap of operands. + +2011-03-28 Sascha L. Teichmann <sascha.teichmann@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/model/GaugesFactory.java: + New. Load gauges for a river and filter them for given + ranges. + +2011-03-25 Sascha L. Teichmann <sascha.teichmann@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/model/DischargeTables.java: + Store data in a double [][] instead of interleaved double [] + to be compatible with org.jfree.data.xy.DefaultXYDataset. + +2011-03-25 Ingo Weinzierl <ingo@intevation.de> + + * TODO: Removed 'i18n' and 'step-back' TODOs and added an issue to remove + the Backend reference from FLYSArtifactCollection. + +2011-03-25 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java: + Added missing artifact namespace of an attribute in the DESCRIBE + document. + +2011-03-24 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java: + New. This ArtifactCollection overrides the DefaultArtifactCollection to + implement FLYS specific describe() and out() operations. + + * doc/conf/conf.xml: Use the FLYSArtifactCollection instead of the + DefaultArtifactCollection for this application. + +2011-03-24 Sascha L. Teichmann <sascha.teichmann@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/model/DischargeTables.java: + New. Fetches values of discharge tables in form of packed + w/q double arrays for given gauges. + + * src/main/java/de/intevation/flys/artifacts/model/RiverFactory.java: + Removed needless import. + +2011-03-24 Ingo Weinzierl <ingo@intevation.de> + + * src/main/resources/messages_de_DE.properties: Added a german resource + bundle to avoid exceptions in the flys artifacts. Sometimes, the + Resources class is not able to find a 'de_DE' bundle and throws an + exception. This is really strange, because it should use the 'de' bundle + in that case, but it doesn't. + +2011-03-23 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: Added + some code to append the output modes of previous states to the DESCRIBE + document. + + TODO: Determine if the current state is already filled with data and + append its output modes as well! + +2011-03-22 Ingo Weinzierl <ingo@intevation.de> + + * doc/conf/artifacts/winfo.xml: Enhanced the location_distance state with + an output mode 'discharge_table'. + +2011-03-21 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/states/DefaultState.java: + Write human readable strings as label attribute into the DESCRIBE + output. Those labels are used to be displayed in the GUI. + +2011-03-21 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/states/CalculationSelect.java: + Added some further calculation types. + + * src/main/resources/messages.properties, + src/main/resources/messages_en.properties, + src/main/resources/messages_de.properties: Added i18n strings for the + calculation types + +2011-03-21 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/FLYSArtifact.java: + Implemented the step-back part of the advance() operation. + +2011-03-21 Ingo Weinzierl <ingo@intevation.de> + + * src/main/resources/messages_de.properties: Fixed a german umlaut. + +2011-03-18 Ingo Weinzierl <ingo@intevation.de> + + * doc/conf/artifacts/winfo.xml: Added new states for entering a + location/distance and w/q. + + * src/main/resources/messages.properties, + src/main/resources/messages_en.properties, + src/main/resources/messages_de.properties: New string for the + location/distance and w/q input states. + +2011-03-18 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/states/WQSelect.java: + New. A state for the W/Q input of the WINFO parameterization. + +2011-03-18 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/states/DefaultState.java: + Append an attribute 'uiprovider' to the dynamic UI node. + + * src/main/java/de/intevation/flys/artifacts/states/LocationDistanceSelect.java: + New. A state for the location/distance selection of the WINFO + parameterization. + +2011-03-17 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/states/DefaultState.java: + Added a new method getUIProvider() that might be overriden by concreted + subclasses that should be rendered with a specific UIProvider. + +2011-03-17 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: + The static UI part is created by the previous states now. This makes it + possible to group the data objects (which is necessary to group the + objects in the ui). + + * src/main/java/de/intevation/flys/artifacts/states/DefaultState.java: + Added a describeStatic() method that creates a node that contains the + data of that state. + +2011-03-17 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/services/RiverService.java: + Removed TODO: the document contains the rivers provided by the backend + now. + +2011-03-17 Sascha L. Teichmann <sascha.teichmann@intevation.de> + + * pom.xml: Added dependency to flys backend. + + * src/main/java/de/intevation/flys/artifacts/model/River.java: + Removed. We are using the backend model now. + + * src/main/java/de/intevation/flys/artifacts/model/RiverFactory.java: + Fetches the rivers from the backend. + + * src/main/java/de/intevation/flys/artifacts/states/RiverSelect.java: + Import fixes. + +2011-03-15 Sascha L. Teichmann <sascha.teichmann@intevation.de> + + * doc/conf/conf.xml: Added section for database backend configuration. + +2011-03-15 Sascha L. Teichmann <sascha.teichmann@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/context/FLYSContextFactory.java: + Fixed build error coming from different import of XMLUtils. + +2011-03-14 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/states/DefaultState.java: + Appended the missing label node that contains the human readable name of + the data item. + +2011-03-14 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java, + src/main/java/de/intevation/flys/artifacts/states/DefaultState.java: + I18N of strings for the DESCRIBE document. + + * src/main/resources/messages.properties, + src/main/resources/messages_en.properties, + src/main/resources/messages_de.properties: I18N strings for the + calculcation mode state. + +2011-03-14 Ingo Weinzierl <ingo@intevation.de> + + * doc/conf/artifacts/winfo.xml: Modified the winfo states. + + * src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: Adapted + the artifact regarding the changes of the last commit. The states + describe() method creates the dynamic UI node - the artifact needs to + apply this node. + + * src/main/java/de/intevation/flys/artifacts/states/CalculationSelect.java: + New. The state for choosing the calculation mode. + + * src/main/resources/messages.properties, + src/main/resources/messages_en.properties, + src/main/resources/messages_de.properties: Added i18n strings for the + calculation mode state. + +2011-03-14 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/states/DefaultState.java: + New. This is the base state for the FLYS application. It provides a + method that creates the dynamic ui node for the DESCRIBE. + + * src/main/java/de/intevation/flys/artifacts/states/RiverSelect.java, + src/main/java/de/intevation/flys/artifacts/states/GaugeSelect.java: Both + classes extend the abstract base class DefaultState. + +2011-03-14 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/resources/Resources.java: + New. This class retrieves the i18n strings from a ResourceBundle. + + * src/main/resources/messages.properties, + src/main/resources/messages_en.properties, + src/main/resources/messages_de.properties: Resource files for german and + english translation. + +2011-03-10 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: Appended + the data that have been inserted in former states into the static node + of the DESCRIBE. + +2011-03-10 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/FLYSArtifact.java: The + operations feed() and advance() return the description of the artifact + using the describe() operation. This avoids additional server round trips + in the client - the clients gets to know about the new state of the + artifact immediately. + +2011-03-10 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/FLYSArtifact.java: + Implemented a part (step forward) of the advance operation. + + * TODO: Implement Step-Back in advance operation. + +2011-03-09 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: + Implemented the abstract method getName(). It returns the constant + 'winfo' string. + + * src/main/java/de/intevation/flys/artifacts/FLYSArtifact.java: + Implemented the feed action. The data of an incoming feed() operation is + stored in StateData objects that are saved in a map in the artifact. + + NOTE: There is no input validation and no i18n of error messages (see + TODO). + +2011-03-09 Ingo Weinzierl <ingo@intevation.de> + + * TODO: This file contains some open points that need to be done. + +2011-03-09 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/FLYSArtifact.java: New. This + artifact serves as the default artifact for the FLYS application. + + * src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: This + artifact now inherits from FLYSArtifact. Furthermore, there is one big + change: we don't store the State objects itself in the artifact, but + just the identifier of those. This makes the artifact smaller and more + compatible agains previous versions of the software. + +2011-03-08 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/services/RiverService.java: + New. This service will retrieve a list of provided rivers. + + * doc/conf/conf.xml: Added a configuration for the RiverService. + +2011-03-07 Ingo Weinzierl <ingo@intevation.de> + + * doc/conf/conf.xml: Added a section user-factory and collection-factory in + the factories part of the configuration. + +2011-03-01 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/states/RiverSelect.java: + Replaced the 'special' attribute from DESCRIBE with a 'uiprovider' + attribute. + +2011-02-08 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: The + RiverSelect state is called to create the UI part of the describe + document. + + * src/main/java/de/intevation/flys/artifacts/states/RiverSelect.java: + Implemented the dynamic UI part of describe(). The static part is not + inserted into the describe document at the moment. We need a reference to + the previous states for this. + +2011-02-08 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/model/RiverFactory.java, + src/main/java/de/intevation/flys/artifacts/model/River.java: New. A model + class that represents a river and its factory to create concrete river + instances. + NOTE: Currently, this is just a mockup. The factory just returns two + static rivers "Mosel" and "Saar" without a connection to a backend. + +2011-02-07 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/states/StateFactory.java: The + input data of a state is initialized with empty StateData objects after + the State has been created. + + * doc/conf/artifacts/winfo.xml: Renamed the input data nodes of the states + which now fits better to the class name of the implementation. + +2011-02-07 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: The + describe document returned by this artifact now contains the current state + and the reachable states. + +2011-02-07 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/context/FLYSContextFactory.java: + The transitions are put into the TransitionEngine with the ID of the state + - not longer with the artifact name. On this way, we are able to fetch + just the transitions for a specific state, instead of all the transitions + of an artifact. + +2011-02-04 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: Describe() + returns the artifact's uuid and hash value. The whole implementation of + describe() is still outstanding. + +2011-02-04 Ingo Weinzierl <ingo@intevation.de> + + * doc/conf/artifacts/winfo.xml: Removed useless config stuff. + + * src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: Removed + useless methods, and improved the init process - the first state is set as + the current state for this artifact. + + * src/main/java/de/intevation/flys/artifacts/states/RiverSelect.java, + src/main/java/de/intevation/flys/artifacts/states/GaugeSelect.java: New. + The states are used in the first two steps of the WINFOArtifact. + Currently, they just implement stubs of the necessary methods setup() and + describe(). + +2011-02-04 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/states/State.java, + src/main/java/de/intevation/flys/artifacts/transitions/TransitionEngine.java, + src/main/java/de/intevation/flys/artifacts/transitions/Transition.java: + Removed. These classes are placed in the artifact-database now. + + * src/main/java/de/intevation/flys/artifacts/transitions/DefaultTransition.java, + src/main/java/de/intevation/flys/artifacts/transitions/TransitionFactory.java: + Adapted imports of Transition. + + * src/main/java/de/intevation/flys/artifacts/states/StateFactory.java: New. + This factory should be used to create concrete State objects. + + * src/main/java/de/intevation/flys/artifacts/context/FLYSContext.java: Added + a constant key to store the StateEngine in the context. + + * src/main/java/de/intevation/flys/artifacts/context/FLYSContextFactory.java: + New method that initializes the states at application start. + +2011-02-03 Ingo Weinzierl <ingo@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/states/State.java: New. The + interface description of a state. + + * src/main/java/de/intevation/flys/artifacts/transitions/Transition.java, + src/main/java/de/intevation/flys/artifacts/transitions/DefaultTransition.java: + New. The interface description and a default implementation of a + transition. + + * src/main/java/de/intevation/flys/artifacts/transitions/TransitionEngine.java: + New. The TransitionEngine stores all transitions for each artifact and + should be used to determine, if an artifact can advance from one state to + another. + + * src/main/java/de/intevation/flys/artifacts/transitions/TransitionFactory.java: + New. Transitions should be created by using this class. + + * src/main/java/de/intevation/flys/artifacts/context/FLYSContext.java: New. + The Flys context. It currently defines keys to store important components + in the context. + + * src/main/java/de/intevation/flys/artifacts/context/FLYSContextFactory.java: + New. The context factory initializes the basic components of the + application. Currently, the TransitionEngine is created and all artifacts + with its transitions are read from the global configuration and stored in + the FLYSContext. + + * pom.xml: Added a dependency to the 'artifacts-common' package. + + * doc/conf/artifacts/winfo.xml: Corrected the classname of the + DefaultTransition. + + * doc/conf/conf.xml: Added FLYSContextFactory as context-factory. + +2011-02-02 Ingo Weinzierl <ingo@intevation.de> + + * doc/conf/conf.xml: An initial configuration file for the FLYS artifact + server. + + * doc/conf/artifacts/winfo.xml: An initial transition configuration of an + WINFO artifact. + + * src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: A stub of + an artifact for a WINFO parameterization. + + * pom.xml: Set the source code version to 1.5. + +2011-02-01 Sascha L. Teichmann <sascha.teichmann@intevation.de> + + * src/**, pom.xml: Added initial maven project. + * ChangeLog: new.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/TODO Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,4 @@ +- Validation of the input values of an incoming feed() call +- Remove the reference to Backend from FLYSArtifactCollection. Use the + methods of ArtifactDatabase (context.getDatabase()) to do the + necessary work.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/doc/conf/artifacts/winfo.xml Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<artifact name="winfo"> + <states> + + <state id="state.winfo.river" description="state.winfo.river" state="de.intevation.flys.artifacts.states.RiverSelect"> + <data name="river" type="String" /> + </state> + + <transition transition="de.intevation.flys.artifacts.transitions.DefaultTransition"> + <from state="state.winfo.river"/> + <to state="state.winfo.calculation_mode"/> + </transition> + + <state id="state.winfo.calculation_mode" description="state.winfo.calculation_mode" state="de.intevation.flys.artifacts.states.CalculationSelect"> + <data name="calculation_mode" type="String" /> + </state> + + <transition transition="de.intevation.flys.artifacts.transitions.DefaultTransition"> + <from state="state.winfo.calculation_mode"/> + <to state="state.winfo.location_distance"/> + </transition> + + <state id="state.winfo.location_distance" description="state.winfo.location_distance" state="de.intevation.flys.artifacts.states.LocationDistanceSelect"> + <data name="ld_from" type="Double" /> + <data name="ld_to" type="Double" /> + <data name="ld_step" type="Double" /> + + <outputmodes> + <outputmode name="discharge_curve" description="output.discharge_curve" mime-type="image/png"/> + </outputmodes> + </state> + + <transition transition="de.intevation.flys.artifacts.transitions.DefaultTransition"> + <from state="state.winfo.location_distance"/> + <to state="state.winfo.wq"/> + </transition> + + <state id="state.winfo.wq" description="state.winfo.wq" state="de.intevation.flys.artifacts.states.WQSelect"> + <data name="wq_mode" type="String" /> + <data name="wq_from" type="Double" /> + <data name="wq_to" type="Double" /> + <data name="wq_step" type="Double" /> + </state> + + <transition transition="de.intevation.flys.artifacts.transitions.DefaultTransition"> + <from state="state.winfo.wq"/> + <to state="state.winfo.calculation"/> + </transition> + + <state id="state.winfo.calculation" description="state.winfo.wq" state="de.intevation.flys.artifacts.states.WINFOOutputState"> + </state> + + </states> +</artifact>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/doc/conf/conf.xml Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,61 @@ +<artifact-database> + <export-secret>YOUR_SECRET</export-secret> + <factories> + <context-factory>de.intevation.flys.artifacts.context.FLYSContextFactory</context-factory> + + <collection-factory + name="DefaultArtifactCollectionFactory" + description="The default artifact collection factory" + ttl="60000" + artifact-collection="de.intevation.flys.collections.FLYSArtifactCollection">de.intevation.artifactdatabase.DefaultArtifactCollectionFactory</collection-factory> + + <artifact-factories> + <!-- All Artifactfactories which are available in this Database. + Each Artifactfactory represents one river. --> + <artifact-factory name="winfo" description="Factory to create an artifact to be used in WINFO" + ttl="3600000" + artifact="de.intevation.flys.artifacts.WINFOArtifact">de.intevation.artifactdatabase.DefaultArtifactFactory</artifact-factory> + </artifact-factories> + + <user-factory name="default" description="Factory to create new users">de.intevation.artifactdatabase.DefaultUserFactory</user-factory> + + <service-factories> + <service-factory + name="rivers" + service="de.intevation.flys.artifacts.services.RiverService" + description="This service returns a list of provided rivers by the artifact server.">de.intevation.artifactdatabase.DefaultServiceFactory</service-factory> + </service-factories> + + </factories> + + <artifacts> + <artifact name="winfo" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${artifacts.config.dir}/artifacts/winfo.xml" /> + </artifacts> + + <rest-server> + <!-- at this Point it is possible to Change the Port the ArtifactDatabase will bind to.--> + <port>8181</port> + <listen>localhost</listen> + </rest-server> + <!-- garbage collection of outdated artifacts --> + <cleaner> + <sleep-time>60000</sleep-time> + </cleaner> + <database> + <!-- This Section configures the Settings for connecting to the + Artifact-Database instance. e.g. SQLite --> + <user>SA</user> + <password></password> + <url>jdbc:h2:${artifacts.config.dir}/../artifactdb/artifacts.db</url> + </database> + <!-- This is the default backend db configuration --> + <!-- + <backend-database> + <user>flys</user> + <password>flys</password> + <dialect>org.hibernate.dialect.PostgreSQLDialect</dialect> + <driver>org.postgresql.Driver</driver> + <url>jdbc:postgresql://localhost:5432/flys</url> + </backend-database> + --> +</artifact-database>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/pom.xml Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,79 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>de.intevation.flys.artifacts</groupId> + <artifactId>flys-artifacts</artifactId> + <version>1.0-SNAPSHOT</version> + <packaging>jar</packaging> + + <name>flys-artifacts</name> + <url>http://maven.apache.org</url> + + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>2.0.2</version> + <configuration> + <source>1.5</source> + <target>1.5</target> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>jfree</groupId> + <artifactId>jfreechart</artifactId> + <version>1.0.13</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>3.8.1</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>de.intevation.bsh.artifact-database</groupId> + <artifactId>artifact-database</artifactId> + <version>1.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>de.intevation.artifacts.common</groupId> + <artifactId>artifacts-common</artifactId> + <version>1.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>de.intevation.flys</groupId> + <artifactId>flys-backend</artifactId> + <version>1.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>jfree</groupId> + <artifactId>jfreechart</artifactId> + <version>1.0.13</version> + </dependency> + <dependency> + <groupId>org.apache.xmlgraphics</groupId> + <artifactId>batik-dom</artifactId> + <version>1.7</version> + </dependency> + <dependency> + <groupId>org.apache.xmlgraphics</groupId> + <artifactId>batik-svggen</artifactId> + <version>1.7</version> + </dependency> + <dependency> + <groupId>com.lowagie</groupId> + <artifactId>itext</artifactId> + <version>2.1.7</version> + </dependency> + </dependencies> +</project>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/App.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,13 @@ +package de.intevation.flys.artifacts; + +/** + * Hello world! + * + */ +public class App +{ + public static void main( String[] args ) + { + System.out.println( "Hello World!" ); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/FLYSArtifact.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,437 @@ +package de.intevation.flys.artifacts; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import de.intevation.artifacts.ArtifactFactory; +import de.intevation.artifacts.CallContext; + +import de.intevation.artifacts.common.ArtifactNamespaceContext; +import de.intevation.artifacts.common.utils.XMLUtils; + +import de.intevation.artifactdatabase.DefaultArtifact; +import de.intevation.artifactdatabase.data.DefaultStateData; +import de.intevation.artifactdatabase.data.StateData; +import de.intevation.artifactdatabase.state.State; +import de.intevation.artifactdatabase.state.StateEngine; +import de.intevation.artifactdatabase.transition.TransitionEngine; + +import de.intevation.flys.artifacts.context.FLYSContext; + + +/** + * The defaul FLYS artifact. + * + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public abstract class FLYSArtifact extends DefaultArtifact { + + /** The logger that is used in this artifact.*/ + private static Logger logger = Logger.getLogger(FLYSArtifact.class); + + + /** The XPath that points to the input data elements of the FEED document.*/ + public static final String XPATH_FEED_INPUT = + "/art:action/art:data/art:input"; + + /** The XPath that points to the name of the target state of ADVANCE.*/ + public static final String XPATH_ADVANCE_TARGET = + "/art:action/art:target/@art:name"; + + /** The constant string that shows that an operation was successful.*/ + public static final String OPERATION_SUCCESSFUL = "SUCCESS"; + + /** The constant string that shows that an operation failed.*/ + public static final String OPERATION_FAILED = "FAILURE"; + + + /** The identifier of the current state. */ + protected String currentStateId; + + /** The identifiers of previous states on a stack.*/ + protected Vector<String> previousStateIds; + + /** The name of the artifact.*/ + protected String name; + + /** The data that have been inserted into this artifact.*/ + protected Map<String, StateData> data; + + + /** + * The default constructor that creates an empty FLYSArtifact. + */ + public FLYSArtifact() { + data = new HashMap<String, StateData>(); + previousStateIds = new Vector<String>(); + } + + + /** + * Returns the name of the concrete artifact. + * + * @return the name of the concrete artifact. + */ + public abstract String getName(); + + + /** + * Returns the FLYSContext from context object. + * + * @param context The CallContext or the FLYSContext. + * + * @return the FLYSContext. + */ + protected FLYSContext getFlysContext(Object context) { + return context instanceof FLYSContext + ? (FLYSContext) context + : (FLYSContext) ((CallContext) context).globalContext(); + } + + + /** + * Initialize the artifact and insert new data if <code>data</code> contains + * information necessary for this artifact. + * + * @param identifier The UUID. + * @param factory The factory that is used to create this artifact. + * @param context The CallContext. + * @param data Some optional data. + */ + @Override + public void setup( + String identifier, + ArtifactFactory factory, + Object context, + Document data) + { + logger.debug("Setup this artifact with the uuid: " + identifier); + + super.setup(identifier, factory, context, data); + + FLYSContext flysContext = (FLYSContext) context; + StateEngine engine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + + String name = getName(); + + logger.debug("Set initial state for artifact '" + name + "'"); + List<State> states = engine.getStates(name); + + setCurrentState(states.get(0)); + } + + + /** + * Insert new data included in <code>input</code> into the current state. + * + * @param target XML document that contains new data. + * @param context The CallContext. + * + * @return a document that contains a SUCCESS or FAILURE message. + */ + @Override + public Document feed(Document target, CallContext context) { + logger.info("FLYSArtifact.feed()"); + + Document doc = XMLUtils.newDocument(); + + XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element result = creator.create("result"); + doc.appendChild(result); + + try { + saveData(target, XPATH_FEED_INPUT); + return describe(target, context); + } + catch (IllegalArgumentException iae) { + creator.addAttr(result, "type", OPERATION_FAILED, true); + + // TODO I18N this message - getMessage() returns a lookup string, no + // human readable error message + result.setTextContent(iae.getMessage()); + } + + return doc; + } + + + /** + * This method handles request for changing the current state of an + * artifact. It is possible to step forward or backward. + * + * @param target The incoming ADVANCE document. + * @param context The CallContext. + * + * @return a document that contains a SUCCESS or FAILURE message. + */ + public Document advance(Document target, CallContext context) { + Document doc = XMLUtils.newDocument(); + + XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element result = ec.create("result"); + + String targetState = XMLUtils.xpathString( + target, XPATH_ADVANCE_TARGET, ArtifactNamespaceContext.INSTANCE); + + logger.info("FLYSArtifact.advance() to '" + targetState + "'"); + + if (isStateReachable(targetState, context)) { + logger.info("Advance: Step forward"); + + Vector<String> prev = getPreviousStateIds(); + prev.add(getCurrentStateId()); + + setCurrentStateId(targetState); + + return describe(target, context); + } + else if (isPreviousState(targetState, context)) { + logger.info("Advance: Step back to"); + + Vector<String> prevs = getPreviousStateIds(); + int targetIdx = prevs.indexOf(targetState); + int start = prevs.size() - 1; + + for (int i = start; i >= targetIdx; i--) { + String prev = prevs.get(i); + logger.debug("Remove state id '" + prev + "'"); + prevs.remove(prev); + } + + setCurrentStateId(targetState); + + return describe(target, context); + } + + logger.warn("Advance: Cannot advance to '" + targetState + "'"); + ec.addAttr(result, "type", OPERATION_FAILED, true); + + doc.appendChild(result); + + return doc; + } + + + /** + * Returns the identifier of the current state. + * + * @return the identifier of the current state. + */ + protected String getCurrentStateId() { + return currentStateId; + } + + + /** + * Sets the identifier of the current state. + * + * @param id the identifier of a state. + */ + protected void setCurrentStateId(String id) { + currentStateId = id; + } + + + /** + * Set the current state of this artifact. <b>NOTE</b>We don't store the + * State object itself - which is not necessary - but its identifier. So + * this method will just call the setCurrentStateId() method with the + * identifier of <i>state</i>. + * + * @param state The new current state. + */ + protected void setCurrentState(State state) { + setCurrentStateId(state.getID()); + } + + + /** + * Returns the current state of the artifact. + * + * @return the current State of the artifact. + */ + protected State getCurrentState(Object context) { + FLYSContext flysContext = getFlysContext(context); + StateEngine engine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + + return engine.getState(getCurrentStateId()); + } + + + /** + * Returns the vector of previous state identifiers. + * + * @return the vector of previous state identifiers. + */ + protected Vector<String> getPreviousStateIds() { + return previousStateIds; + } + + + /** + * Adds a new StateData item to the data pool of this artifact. + * + * @param name the name of the data object. + * @param data the data object itself. + */ + protected void addData(String name, StateData data) { + this.data.put(name, data); + } + + + /** + * This method returns a specific StateData object that is stored in the + * data pool of this artifact. + * + * @param name The name of the data object. + * + * @return the StateData object if existing, otherwise null. + */ + protected StateData getData(String name) { + return data.get(name); + } + + + /** + * This method stores the data that is contained in the FEED document. + * + * @param feed The FEED document. + * @param xpath The XPath that points to the data nodes. + */ + public void saveData(Document feed, String xpath) + throws IllegalArgumentException + { + if (feed == null || xpath == null || xpath.length() == 0) { + throw new IllegalArgumentException("feed.no.input.data"); + } + + NodeList nodes = (NodeList) XMLUtils.xpath( + feed, + xpath, + XPathConstants.NODESET, + ArtifactNamespaceContext.INSTANCE); + + if (nodes == null || nodes.getLength() == 0) { + throw new IllegalArgumentException("feed.no.input.data"); + } + + int count = nodes.getLength(); + logger.debug("Try to save " + count + " data items."); + + for (int i = 0; i < count; i++) { + Node node = nodes.item(i); + + String name = XMLUtils.xpathString( + node, "@art:name", ArtifactNamespaceContext.INSTANCE); + String value = XMLUtils.xpathString( + node, "@art:value", ArtifactNamespaceContext.INSTANCE); + + if (name != null && value != null) { + logger.debug("Save data item for '" + name + "' : " + value); + + // TODO ADD INPUT VALIDATION! + addData(name, new DefaultStateData(name, null, null, value)); + } + } + } + + + /** + * This method fills a state object with the data that have been inserted to + * this artifact. This is necessary to use the isStateReachable() method, + * because the Transitions need to know about the inserted data. + * + * @param state The state that needs to be filled with data. + * + * @return the filled state. + */ + protected State fillState(State state) { + Map<String, StateData> stateData = state.getData(); + + if (stateData == null) { + return state; + } + + Set<String> keys = stateData.keySet(); + + for (String key: keys) { + StateData tmp = getData(key); + + if (tmp != null) { + StateData data = stateData.get(key); + data.setValue(tmp.getValue()); + } + } + + return state; + } + + + /** + * Determines if the state with the identifier <i>stateId</i> is reachable + * from the current state. The determination itself takes place in the + * TransitionEngine. + * + * @param stateId The identifier of a state. + * @param context The context object. + * + * @return true, if the state specified by <i>stateId</i> is reacahble, + * otherwise false. + */ + protected boolean isStateReachable(String stateId, Object context) { + logger.debug("Determine if the state '" + stateId + "' is reachable."); + + FLYSContext flysContext = getFlysContext(context); + + State currentState = fillState(getCurrentState(context)); + StateEngine sEngine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + + TransitionEngine tEngine = (TransitionEngine) flysContext.get( + FLYSContext.TRANSITION_ENGINE_KEY); + + return tEngine.isStateReachable(stateId, currentState, sEngine); + } + + + /** + * Determines if the state with the identifier <i>stateId</i> is a previous + * state of the current state. + * + * @param stateId The target state identifier. + * @param context The context object. + */ + protected boolean isPreviousState(String stateId, Object context) { + logger.debug("Determine if the state '" + stateId + "' is old."); + + Vector<String> prevs = getPreviousStateIds(); + if (prevs.contains(stateId)) { + return true; + } + + return false; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,286 @@ +package de.intevation.flys.artifacts; + +import java.awt.Color; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.apache.log4j.Logger; + +import org.jfree.data.xy.DefaultXYDataset; + +import org.jfree.chart.ChartFactory; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.PlotOrientation; + +import de.intevation.artifacts.ArtifactNamespaceContext; +import de.intevation.artifacts.CallContext; + +import de.intevation.artifactdatabase.ProtocolUtils; +import de.intevation.artifactdatabase.state.Output; +import de.intevation.artifactdatabase.state.State; +import de.intevation.artifactdatabase.state.StateEngine; +import de.intevation.artifactdatabase.transition.TransitionEngine; + +import de.intevation.artifacts.common.utils.XMLUtils; + +import de.intevation.flys.model.Gauge; + +import de.intevation.flys.artifacts.model.DischargeTables; +import de.intevation.flys.artifacts.model.GaugesFactory; +import de.intevation.flys.artifacts.states.DefaultState; +import de.intevation.flys.artifacts.context.FLYSContext; +import de.intevation.flys.exports.ChartExportHelper; + + +/** + * The default WINFO artifact. + * + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class WINFOArtifact extends FLYSArtifact { + + /** The logger for this class */ + private static Logger logger = Logger.getLogger(WINFOArtifact.class); + + + /** The name of the artifact.*/ + public static final String ARTIFACT_NAME = "winfo"; + + /** XPath */ + public static final String XPATH_STATIC_UI ="/art:result/art:ui/art:static"; + + + /** + * The default constructor. + */ + public WINFOArtifact() { + } + + + /** + * This method returns a description of this artifact. + * + * @param data Some data. + * @param context The CallContext. + * + * @return the description of this artifact. + */ + public Document describe(Document data, CallContext context) { + logger.debug("Describe: the current state is: " + getCurrentStateId()); + + FLYSContext flysContext = null; + if (context instanceof FLYSContext) { + flysContext = (FLYSContext) context; + } + else { + flysContext = (FLYSContext) context.globalContext(); + } + + StateEngine stateEngine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + + TransitionEngine transitionEngine = (TransitionEngine) flysContext.get( + FLYSContext.TRANSITION_ENGINE_KEY); + + List<State> reachable = transitionEngine.getReachableStates( + getCurrentState(context), stateEngine); + + Document description = XMLUtils.newDocument(); + XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( + description, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element root = ProtocolUtils.createRootNode(creator); + description.appendChild(root); + + State current = getCurrentState(context); + + ProtocolUtils.appendDescribeHeader(creator, root, identifier(), hash()); + ProtocolUtils.appendState(creator, root, current); + ProtocolUtils.appendReachableStates(creator, root, reachable); + + Element ui = ProtocolUtils.createArtNode( + creator, "ui", null, null); + + Element staticUI = ProtocolUtils.createArtNode( + creator, "static", null, null); + + Element outs = ProtocolUtils.createArtNode( + creator, "outputmodes", null, null); + appendOutputModes(description, outs, context, identifier()); + + appendStaticUI(description, staticUI, context, identifier()); + + Element dynamic = current.describe( + description, + root, + context, + identifier()); + + if (dynamic != null) { + ui.appendChild(dynamic); + } + + ui.appendChild(staticUI); + + root.appendChild(ui); + root.appendChild(outs); + + return description; + } + + + @Override + public void out( + Document format, + OutputStream out, + CallContext context) + throws IOException + { + logger.info("WINFOArtifact.out"); + String river = (String) getData("river").getValue(); + String from = (String) getData("ld_from").getValue(); + String to = (String) getData("ld_to").getValue(); + + double f = Double.parseDouble(from); + double t = Double.parseDouble(to); + + List<double[]> ranges = new ArrayList<double[]>(); + ranges.add(new double [] { f, t }); + + List<Gauge> gauges = GaugesFactory.getGauges(river); + List<Gauge> filtered = GaugesFactory.filterRanges(gauges, ranges); + + if (logger.isDebugEnabled()) { + int numGauges = gauges != null ? gauges.size() : 0; + int numFiltered = filtered != null ? filtered.size() : 0; + + logger.debug("++++++++++++++++++++"); + logger.debug("Search gauges for river: " + river); + logger.debug("-> ... from range: " + from); + logger.debug("-> ... to range: " + to); + logger.debug("-> Found " + numGauges + " gauges in total."); + logger.debug("-> Found " + numFiltered + " gauges after filtering."); + logger.debug("++++++++++++++++++++"); + } + + String[] gaugeNames = new String[filtered.size()]; + int idx = 0; + for (Gauge gauge: filtered) { + gaugeNames[idx++] = gauge.getName(); + } + + DischargeTables dt = new DischargeTables(river, gaugeNames); + Map<String, double[][]> gaugeValues = dt.getValues(100d); + + DefaultXYDataset dataset = new DefaultXYDataset(); + + for (String gauge: gaugeNames) { + double[][] values = gaugeValues.get(gauge); + dataset.addSeries(gauge, values); + } + + JFreeChart chart = ChartFactory.createXYLineChart( + "Abflusskurven (" + river + ")", + "Q", "W", + dataset, + PlotOrientation.VERTICAL, + true, + false, + false); + + chart.setBackgroundPaint(Color.WHITE); + chart.getPlot().setBackgroundPaint(Color.WHITE); + + ChartExportHelper.exportImage( + out, + chart, + "png", + 600, 400); + } + + + /** + * Returns the name of the concrete artifact. + * + * @return the name of the concrete artifact. + */ + public String getName() { + return ARTIFACT_NAME; + } + + + protected void appendOutputModes( + Document doc, + Element outs, + CallContext context, + String uuid) + { + Vector<String> stateIds = getPreviousStateIds(); + + XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + FLYSContext flysContext = getFlysContext(context); + StateEngine engine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + + for (String stateId: stateIds) { + logger.debug("Append output modes for state: " + stateId); + State state = engine.getState(stateId); + + List<Output> list = state.getOutputs(); + if (list == null || list.size() == 0) { + continue; + } + + ProtocolUtils.appendOutputModes(creator, outs, list); + } + + // TODO If the current state is already filled with data, the output is + // available as well! So we need some code to append the outputs of the + // current already filled state. + } + + + /** + * This method appends the static data - that has already been inserted by + * the user - to the static node of the DESCRIBE document. + * + * @param doc The document. + * @param ui The root node. + * @param context The CallContext. + * @param uuid The identifier of the artifact. + */ + protected void appendStaticUI( + Document doc, + Node ui, + CallContext context, + String uuid) + { + Vector<String> stateIds = getPreviousStateIds(); + + FLYSContext flysContext = getFlysContext(context); + StateEngine engine = (StateEngine) flysContext.get( + FLYSContext.STATE_ENGINE_KEY); + + for (String stateId: stateIds) { + logger.debug("Append static data for state: " + stateId); + DefaultState state = (DefaultState) engine.getState(stateId); + ui.appendChild(state.describeStatic(doc, ui, context, uuid)); + } + + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/context/FLYSContext.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,44 @@ +package de.intevation.flys.artifacts.context; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; + +import de.intevation.artifactdatabase.DefaultArtifactContext; + + +/** + * This class is used to store application wide information in a global context. + * + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class FLYSContext extends DefaultArtifactContext { + + /** The logger used in this class */ + private static Logger logger = Logger.getLogger(FLYSContext.class); + + /** The key that is used to store the TransitionEngine in the context */ + public static final String TRANSITION_ENGINE_KEY = + "artifact.transition.engine"; + + /** The key that is used to store the StateEngine in the context */ + public static final String STATE_ENGINE_KEY = + "artifact.state.engine"; + + + /** + * The default constructor. + */ + public FLYSContext() { + super(); + } + + + /** + * A constructor with a config document. + */ + public FLYSContext(Document config) { + super(config); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/context/FLYSContextFactory.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,190 @@ +package de.intevation.flys.artifacts.context; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import de.intevation.artifacts.ArtifactContextFactory; + +import de.intevation.artifacts.common.utils.XMLUtils; +import de.intevation.artifacts.common.utils.Config; + +import de.intevation.artifactdatabase.state.State; +import de.intevation.artifactdatabase.state.StateEngine; +import de.intevation.artifactdatabase.transition.Transition; +import de.intevation.artifactdatabase.transition.TransitionEngine; + +import de.intevation.flys.artifacts.states.StateFactory; +import de.intevation.flys.artifacts.transitions.TransitionFactory; + + +/** + * The ArtifactContextFactory is used to initialize basic components and put + * them into the global context of the application. + * + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class FLYSContextFactory implements ArtifactContextFactory { + + /** The logger that is used in this class */ + private static Logger logger = Logger.getLogger(FLYSContextFactory.class); + + /** The XPath to the artifacts configured in the configuration. */ + public static final String XPATH_ARTIFACTS = + "/artifact-database/artifacts/artifact"; + + /** The XPath to the name of the artifact. */ + public static final String XPATH_ARTIFACT_NAME = "/artifact/@name"; + + /** The XPath to the xlink ref in an artifact configuration. */ + public static final String XPATH_XLINK = "xlink:href"; + + /** The XPath to the transitions configured in the artifact config. */ + public static final String XPATH_TRANSITIONS = + "/artifact/states/transition"; + + /** The XPath to the states configured in the artifact config. */ + public static final String XPATH_STATES = + "/artifact/states/state"; + + /** + * Creates a new FLYSArtifactContext object and initialize all + * components required by the application. + * + * @param config The artifact server configuration. + * @return a FLYSArtifactContext. + */ + public Object createArtifactContext(Document config) { + FLYSContext context = new FLYSContext(config); + + configureTransitions(config, context); + configureStates(config, context); + + return context; + } + + + /** + * This method initializes the transition configuration. + * + * @param config the config document. + * @param context the FLYSContext. + */ + protected void configureTransitions(Document config, FLYSContext context) { + TransitionEngine engine = new TransitionEngine(); + + Document[] artifacts = getArtifactConfigurations(config); + logger.info("Found " + artifacts.length + " artifacts in the config."); + + for (Document doc: artifacts) { + List<Transition> transitions = new ArrayList<Transition>(); + + String artName = (String) XMLUtils.xpath( + doc, XPATH_ARTIFACT_NAME, XPathConstants.STRING); + + NodeList list = (NodeList) XMLUtils.xpath( + doc, XPATH_TRANSITIONS, XPathConstants.NODESET); + + if (list == null) { + logger.warn("The artifact has no transitions configured."); + continue; + } + + int trans = list.getLength(); + + logger.info( + "Artifact '" + artName + "' has " + trans + " transitions."); + + for (int i = 0; i < trans; i++) { + Transition t = TransitionFactory.createTransition(list.item(i)); + String s = t.getFrom(); + engine.addTransition(s, t); + } + } + + context.put(FLYSContext.TRANSITION_ENGINE_KEY, engine); + } + + + /** + * This method returns all artifact documents defined in + * <code>config</code>. <br>NOTE: The artifact configurations need to be + * stored in own files referenced by an xlink. + * + * @param config The global configuration. + * + * @return an array of Artifact configurations. + */ + protected Document[] getArtifactConfigurations(Document config) { + NodeList artifacts = (NodeList) XMLUtils.xpath( + config, XPATH_ARTIFACTS, XPathConstants.NODESET); + + int count = artifacts.getLength(); + + Document[] artifactDocs = new Document[count]; + + for (int i = 0; i < count; i++) { + Element tmp = (Element) artifacts.item(i); + + String xlink = tmp.getAttribute(XPATH_XLINK); + xlink = Config.replaceConfigDir(xlink); + + File artifactFile = new File(xlink); + artifactDocs[i] = XMLUtils.parseDocument(artifactFile); + } + + return artifactDocs; + } + + + /** + * This method initializes the transition configuration. + * + * @param config the config document. + * @param context the FLYSContext. + */ + protected void configureStates(Document config, FLYSContext context) { + StateEngine engine = new StateEngine(); + + Document[] artifacts = getArtifactConfigurations(config); + logger.info("Found " + artifacts.length + " artifacts in the config."); + + for (Document doc: artifacts) { + List<State> states = new ArrayList<State>(); + + String artName = (String) XMLUtils.xpath( + doc, XPATH_ARTIFACT_NAME, XPathConstants.STRING); + + NodeList stateList = (NodeList) XMLUtils.xpath( + doc, XPATH_STATES, XPathConstants.NODESET); + + if (stateList == null) { + logger.warn("The artifact has no states configured."); + continue; + } + + int count = stateList.getLength(); + + logger.info( + "Artifact '" + artName + "' has " + count + " states."); + + for (int i = 0; i < count; i++) { + states.add(StateFactory.createState( + stateList.item(i))); + } + + engine.addStates(artName, states); + } + + context.put(FLYSContext.STATE_ENGINE_KEY, engine); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/DischargeTables.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,110 @@ +package de.intevation.flys.artifacts.model; + +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.Arrays; + +import java.io.Serializable; + +import org.hibernate.SessionFactory; +import org.hibernate.Session; +import org.hibernate.Query; + +import org.apache.log4j.Logger; + +import de.intevation.flys.backend.SessionFactoryProvider; + +import de.intevation.flys.model.Gauge; +import de.intevation.flys.model.DischargeTable; +import de.intevation.flys.model.DischargeTableValue; + +public class DischargeTables +implements Serializable +{ + private static Logger log = Logger.getLogger(DischargeTables.class); + + protected List<String> gaugeNames; + + protected String riverName; + + protected double scale; + + protected Map<String, double [][]> values; + + public DischargeTables() { + } + + public DischargeTables(String riverName, String [] gaugeNames) { + this(riverName, Arrays.asList(gaugeNames)); + } + + public DischargeTables(String riverName, List<String> gaugeNames) { + scale = Double.NaN; + this.riverName = riverName; + this.gaugeNames = gaugeNames; + } + + public Map<String, double [][]> getValues(double scale) { + if (values == null || scale != this.scale) { + values = loadValues(scale); + this.scale = scale; + } + return values; + } + + protected Map<String, double [][]> loadValues(double scale) { + Map<String, double [][]> values = new HashMap<String, double [][]>(); + + SessionFactory sf = SessionFactoryProvider.getSessionFactory(); + Session session = sf.openSession(); + + try { + Query gaugeQuery = session.createQuery( + "from Gauge where name=:gauge and river.name=:river"); + gaugeQuery.setParameter("river", riverName); + + for (String gaugeName: gaugeNames) { + gaugeQuery.setParameter("gauge", gaugeName); + List<Gauge> gauges = gaugeQuery.list(); + if (gauges.isEmpty()) { + log.warn( + "no gauge '"+gaugeName+"' at river '"+riverName+"'"); + continue; + } + Gauge gauge = gauges.get(0); + + List<DischargeTable> tables = gauge.getDischargeTables(); + + if (tables.isEmpty()) { + log.warn( + "no discharge table for gauge '" + gaugeName + "'"); + continue; + } + + // TODO: Filter by time interval + DischargeTable table = tables.get(0); + + List<DischargeTableValue> dtvs = + table.getDischargeTableValues(); + + double [][] vs = new double[2][dtvs.size()]; + + int idx = 0; + for (DischargeTableValue dtv: dtvs) { + vs[0][idx] = dtv.getQ().doubleValue() * scale; + vs[1][idx] = dtv.getW().doubleValue() * scale; + ++idx; + } + + values.put(gaugeName, vs); + } + + return values; + } + finally { + session.close(); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/GaugesFactory.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,65 @@ +package de.intevation.flys.artifacts.model; + +import java.util.List; +import java.util.ArrayList; + +import de.intevation.flys.backend.SessionFactoryProvider; + +import de.intevation.flys.model.River; +import de.intevation.flys.model.Gauge; +import de.intevation.flys.model.Range; + +import org.hibernate.SessionFactory; +import org.hibernate.Session; +import org.hibernate.Query; + +public class GaugesFactory +{ + public static List<Gauge> getGauges(River river) { + return getGauges(river.getName()); + } + + public static List<Gauge> getGauges(String river) { + SessionFactory sf = SessionFactoryProvider.getSessionFactory(); + Session session = sf.openSession(); + try { + Query query = session.createQuery( + "from Gauge where river.name=:name"); + query.setParameter("name", river); + return query.list(); + } + finally { + session.close(); + } + } + + public static List<Gauge> filterRanges( + List<Gauge> gauges, + List<double []> ranges + ) { + // XXX: Inefficent! + ArrayList<Range> rs = new ArrayList<Range>(); + for (double [] range: ranges) { + double a = range[0]; + double b = range[1]; + rs.add(new Range(Math.min(a, b), Math.max(a, b), null)); + } + return filter(gauges, rs); + } + + public static List<Gauge> filter(List<Gauge> gauges, List<Range> ranges) { + // TODO: Make it an HQL filter! + ArrayList<Gauge> out = new ArrayList<Gauge>(); + for (Gauge gauge: gauges) { + Range range = gauge.getRange(); + for (Range cmp: ranges) { + if (range.intersects(cmp)) { + out.add(gauge); + break; + } + } + } + return out; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/RiverFactory.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,40 @@ +package de.intevation.flys.artifacts.model; + + +import java.util.List; + +import de.intevation.flys.model.River; + +import de.intevation.flys.backend.SessionFactoryProvider; + +import org.hibernate.SessionFactory; +import org.hibernate.Session; + +/** + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class RiverFactory { + + /** We don't need to instantiate concrete objects of this class. */ + private RiverFactory() { + } + + + /** + * Returns all rivers that were found in the backend. + * + * @return all rivers. + */ + public static List<River> getRivers() { + SessionFactory sf = SessionFactoryProvider.getSessionFactory(); + Session session = sf.openSession(); + try { + return (List<River>)session + .createQuery("from River order by name").list(); + } + finally { + session.close(); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/resources/Resources.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,106 @@ +package de.intevation.flys.artifacts.resources; + +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.apache.log4j.Logger; + +import de.intevation.artifacts.CallMeta; + +/** + * This class provides methods for i18n. + * + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class Resources { + + /** The logger that is used in this class.*/ + private static Logger logger = Logger.getLogger(Resources.class); + + /** The singleton instance.*/ + private static Resources INSTANCE; + + /** The locales supported by this server.*/ + protected Locale[] locales; + + /** + * No instance of this class is necessary. + */ + private Resources() { + } + + + /** + * Returns the locales supported by this server. + * + * @return the supported locales. + */ + public Locale[] getLocales() { + if (locales == null) { + readLocales(); + } + + return locales; + } + + + /** + * Read the locales configured for this server. + */ + protected void readLocales() { + // TODO IMPLEMENT ME + + locales = new Locale[2]; + locales[0] = Locale.GERMANY; + locales[1] = Locale.ENGLISH; + } + + + /** + * This method returns the translated value for <i>key</i> or <i>def</i> if + * <i>key</i> is not existing in the resource bundle. + * + * @param meta The CallMeta object of the request that contains the + * preferred locale. + * @param key The key that should be translated. + * @param def A default value that is returned, if <i>key</i> was not found. + * + * @return the translated message. + */ + public static String getMsg(CallMeta meta, String key, String def) { + if (INSTANCE == null) { + INSTANCE = new Resources(); + } + + Locale[] locales = INSTANCE.getLocales(); + Locale locale = meta.getPreferredLocale(locales); + + return getMsg(locale, key, def); + } + + + /** + * This method returns the translated value for <i>key</i> or <i>def</i> if + * <i>key</i> is not existing in the resource bundle. + * + * @param locale The locale. + * @param key The key that should be translated. + * @param def A default value that is returned, if <i>key</i> was not found. + * + * @return the translated message. + */ + public static String getMsg(Locale locale, String key, String def) { + ResourceBundle bundle = ResourceBundle.getBundle("messages", locale); + + try { + return bundle.getString(key); + } + catch (MissingResourceException mre) { + logger.warn("No message found for key: " + key); + + return def; + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/RiverService.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,71 @@ +package de.intevation.flys.artifacts.services; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import de.intevation.artifacts.CallMeta; + +import de.intevation.artifacts.common.ArtifactNamespaceContext; +import de.intevation.artifacts.common.utils.XMLUtils; + +import de.intevation.artifactdatabase.DefaultService; + +import de.intevation.flys.model.River; + +import de.intevation.flys.artifacts.model.RiverFactory; + + +/** + * This service provides information about the supported rivers by this + * application. + * + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class RiverService extends DefaultService { + + /** The logger used in this service.*/ + private static Logger logger = Logger.getLogger(RiverService.class); + + + /** + * The default constructor. + */ + public RiverService() { + } + + + public Document process( + Document data, + Object globalContext, + CallMeta callMeta) + { + logger.debug("RiverService.process"); + + Document result = XMLUtils.newDocument(); + + XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( + result, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + List<River> allRivers = RiverFactory.getRivers(); + + Element rivers = ec.create("rivers"); + + for (River river: allRivers) { + Element r = ec.create("river"); + ec.addAttr(r, "name", river.getName(), true); + + rivers.appendChild(r); + } + + result.appendChild(rivers); + + return result; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/CalculationSelect.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,92 @@ +package de.intevation.flys.artifacts.states; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; + +import de.intevation.artifacts.CallContext; +import de.intevation.artifacts.CallMeta; + +import de.intevation.artifacts.common.utils.XMLUtils; + +import de.intevation.artifactdatabase.ProtocolUtils; + +import de.intevation.flys.artifacts.resources.Resources; + +/** + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class CalculationSelect extends DefaultState { + + /** The logger that is used in this class.*/ + private static Logger logger = Logger.getLogger(CalculationSelect.class); + + + /** Constant value for the reference line calculation.*/ + public static final String CALCULATION_SURFACE_CURVE = + "calc.surface.curve"; + + /** Constant value for the differences calculation.*/ + public static final String CALCULATION_DURATION_CURVE = + "calc.duration.curve"; + + /** Constant value for the flood map calculation.*/ + public static final String CALCULATION_FLOOD_MAP = + "calc.flood.map"; + + /** Constant value for the profile calculation.*/ + public static final String CALCULATION_DISCHARGE_LONGITUDINAL_CURVE = + "calc.discharge.longitudinal.section"; + + /** Constant value for the state discharge curve calculation.*/ + public static final String CALCULATION_DISCHARGE_CURVE = + "calc.discharge.curve"; + + /** An array that holds all available calculation modes.*/ + public static final String[] CALCULATIONS = { + CALCULATION_SURFACE_CURVE, + CALCULATION_FLOOD_MAP, + CALCULATION_DISCHARGE_CURVE, + CALCULATION_DURATION_CURVE, + CALCULATION_DISCHARGE_LONGITUDINAL_CURVE }; + + + protected Element[] createItems( + XMLUtils.ElementCreator cr, + String name, + CallContext context) + { + CallMeta meta = context.getMeta(); + Element[] calcs = new Element[CALCULATIONS.length]; + + int i = 0; + + for (String calc: CALCULATIONS) { + calcs[i++] = createItem( + cr, new String[] { + Resources.getMsg(meta, calc, calc), + calc + }); + } + + return calcs; + } + + + protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { + Element item = ProtocolUtils.createArtNode(cr, "item", null, null); + Element label = ProtocolUtils.createArtNode(cr, "label", null, null); + Element value = ProtocolUtils.createArtNode(cr, "value", null, null); + + String[] arr = (String[]) obj; + + label.setTextContent(arr[0]); + value.setTextContent(arr[1]); + + item.appendChild(label); + item.appendChild(value); + + return item; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/DefaultState.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,187 @@ +package de.intevation.flys.artifacts.states; + +import java.util.Collection; +import java.util.Map; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import de.intevation.artifacts.ArtifactNamespaceContext; +import de.intevation.artifacts.CallContext; +import de.intevation.artifacts.CallMeta; + +import de.intevation.artifacts.common.utils.XMLUtils; + +import de.intevation.artifactdatabase.ProtocolUtils; +import de.intevation.artifactdatabase.data.StateData; +import de.intevation.artifactdatabase.state.AbstractState; + +import de.intevation.flys.artifacts.resources.Resources; + + +/** + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public abstract class DefaultState extends AbstractState { + + /** The logger that is used in this class.*/ + private static Logger logger = Logger.getLogger(DefaultState.class); + + + public Element describeStatic( + Document document, + Node root, + CallContext context, + String uuid) + { + XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( + document, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + CallMeta meta = context.getMeta(); + + String label = Resources.getMsg(meta, getID(), getID()); + Element ui = ProtocolUtils.createArtNode( + creator, "state", + new String[] { "name", "uiprovider", "label" }, + new String[] { getID(), getUIProvider(), label }); + + Map<String, StateData> theData = getData(); + if (theData == null) { + return ui; + } + + Collection<StateData> dataItems = theData.values(); + + for (StateData data: dataItems) { + String name = data.getName(); + String value = (String) data.getValue(); + + logger.debug("Append element '" + name + "' (" + value + ")"); + + Element dataElement = creator.create("data"); + creator.addAttr(dataElement, "name", name, true); + creator.addAttr(dataElement, "type", data.getType(), true); + + Element itemElement = creator.create("item"); + creator.addAttr(itemElement, "value", value, true); + creator.addAttr( + itemElement, + "label", + Resources.getMsg(meta, value, value), + true); + + dataElement.appendChild(itemElement); + ui.appendChild(dataElement); + } + + return ui; + } + + + public Element describe( + Document document, + Node root, + CallContext context, + String uuid) + { + XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( + document, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Element ui = null; + String uiprovider = getUIProvider(); + if (uiprovider != null) { + ui = ProtocolUtils.createArtNode( + creator, "dynamic", + new String[] { "uiprovider" }, + new String[] { uiprovider }); + } + else { + ui = ProtocolUtils.createArtNode(creator, "dynamic", null, null); + } + + Map<String, StateData> theData = getData(); + if (theData == null) { + return ui; + } + + Collection<StateData> dataItems = theData.values(); + + for (StateData data: dataItems) { + String name = data.getName(); + Element select = createData(creator, data, context); + + Element choices = ProtocolUtils.createArtNode( + creator, "choices", null, null); + + select.appendChild(choices); + ui.appendChild(select); + + Element[] items = createItems(creator, name, context); + for (Element item: items) { + choices.appendChild(item); + } + } + + return ui; + } + + + /** + * This method creates the root node that contains the list of selectable + * items. + * + * @param cr The ElementCreator. + * @param name The name of the amount of data. + * + * @return the root node of the item list. + */ + protected Element createData( + XMLUtils.ElementCreator cr, + StateData data, + CallContext context) + { + Element select = ProtocolUtils.createArtNode( + cr, "select", null, null); + cr.addAttr(select, "name", data.getName(), true); + + Element label = ProtocolUtils.createArtNode( + cr, "label", null, null); + + select.appendChild(label); + + label.setTextContent(Resources.getMsg( + context.getMeta(), + getID(), + getID())); + + return select; + } + + + /** + * This method creates a list of items. These items represent the amount of + * input data that is possible for this state. + * + * @param cr The ElementCreator. + * @param name The name of the amount of data. + * + * @return a list of items. + */ + protected abstract Element[] createItems( + XMLUtils.ElementCreator cr, + String name, + CallContext context); + + + protected String getUIProvider() { + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/GaugeSelect.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,47 @@ +package de.intevation.flys.artifacts.states; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import de.intevation.artifacts.CallContext; + +import de.intevation.artifactdatabase.state.AbstractState; + + +/** + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class GaugeSelect extends AbstractState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(GaugeSelect.class); + + /** + * The default constructor that initializes an empty GaugeState object. + */ + public GaugeSelect() { + super(null, null); + } + + + public void setup(Node config) { + super.setup(config); + } + + + public Element describe( + Document document, + Node root, + CallContext context, + String uuid) + { + // TODO Implement me + logger.error("Currently not implemented."); + + return null; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/LocationDistanceSelect.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,105 @@ +package de.intevation.flys.artifacts.states; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; + +import de.intevation.artifacts.CallContext; + +import de.intevation.artifacts.common.utils.XMLUtils; + +import de.intevation.artifactdatabase.ProtocolUtils; +import de.intevation.artifactdatabase.data.StateData; + +import de.intevation.flys.artifacts.resources.Resources; + +/** + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class LocationDistanceSelect extends DefaultState { + + /** The logger used in this class.*/ + private static Logger logger = Logger.getLogger(LocationDistanceSelect.class); + + + /** The default step width.*/ + public static final String DEFAULT_STEP = "100"; + + /** + * The default constructor that initializes an empty State object. + */ + public LocationDistanceSelect() { + } + + protected Element createData( + XMLUtils.ElementCreator cr, + StateData data, + CallContext context) + { + Element select = ProtocolUtils.createArtNode( + cr, "select", null, null); + + cr.addAttr(select, "name", data.getName(), true); + + Element label = ProtocolUtils.createArtNode( + cr, "label", null, null); + + Element choices = ProtocolUtils.createArtNode( + cr, "choices", null, null); + + label.setTextContent(Resources.getMsg( + context.getMeta(), + data.getName(), + data.getName())); + + select.appendChild(label); + + return select; + } + + + protected Element[] createItems( + XMLUtils.ElementCreator cr, + String name, + CallContext context) + { + // TODO Insert correct min/max values! + + if (name.equals("ld_from")) { + Element min = createItem(cr, new String[] {"min", "1"}); + return new Element[] { min }; + } + else if (name.equals("ld_to")) { + Element max = createItem(cr, new String[] {"max", "10"}); + return new Element[] { max }; + } + else { + Element step = createItem(cr, new String[] {"step", DEFAULT_STEP}); + return new Element[] { step }; + } + + } + + + protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { + Element item = ProtocolUtils.createArtNode(cr, "item", null, null); + Element label = ProtocolUtils.createArtNode(cr, "label", null, null); + Element value = ProtocolUtils.createArtNode(cr, "value", null, null); + + String[] arr = (String[]) obj; + + label.setTextContent(arr[0]); + value.setTextContent(arr[1]); + + item.appendChild(label); + item.appendChild(value); + + return item; + } + + + protected String getUIProvider() { + return "location_distance_panel"; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/RiverSelect.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,115 @@ +package de.intevation.flys.artifacts.states; + +import java.util.List; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import de.intevation.artifacts.CallContext; + +import de.intevation.artifacts.common.utils.XMLUtils; + +import de.intevation.artifactdatabase.ProtocolUtils; +import de.intevation.artifactdatabase.data.StateData; + +import de.intevation.flys.model.River; + +import de.intevation.flys.artifacts.model.RiverFactory; + +import de.intevation.flys.artifacts.resources.Resources; + + +/** + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class RiverSelect extends DefaultState { + + /** The logger used in this class. */ + private static Logger logger = Logger.getLogger(RiverSelect.class); + + /** + * The default constructor that initializes an empty State object. + */ + public RiverSelect() { + } + + + /** + * Initialize the state based on the state node in the configuration. + * + * @param config The state configuration node. + */ + public void setup(Node config) { + super.setup(config); + } + + + protected Element createData( + XMLUtils.ElementCreator cr, + StateData data, + CallContext context) + { + Element select = ProtocolUtils.createArtNode( + cr, "select", + new String[] { "uiprovider" }, + new String[] { "select_with_map" }); + cr.addAttr(select, "name", data.getName()); + + Element label = ProtocolUtils.createArtNode( + cr, "label", null, null); + + Element choices = ProtocolUtils.createArtNode( + cr, "choices", null, null); + + label.setTextContent(Resources.getMsg( + context.getMeta(), + getID(), + getID())); + + return select; + } + + + protected Element[] createItems( + XMLUtils.ElementCreator cr, + String name, + CallContext context) + { + List<River> rivers = RiverFactory.getRivers(); + Element[] items = new Element[rivers.size()]; + + int idx = 0; + for (River river: rivers) { + items[idx++] = createRiverItem(cr, river); + } + + return items; + } + + + /** + * This method creates a node that represents a river item. This node + * contains the label and the value that describe the river. + * + * @param cr The ElementCreator. + * @param river The river. + * + * @return the element that contains the information about the river. + */ + protected Element createRiverItem(XMLUtils.ElementCreator cr, River river) { + Element item = ProtocolUtils.createArtNode(cr, "item", null, null); + Element label = ProtocolUtils.createArtNode(cr, "label", null, null); + Element value = ProtocolUtils.createArtNode(cr, "value", null, null); + + label.setTextContent(river.getName()); + value.setTextContent(river.getName()); + + item.appendChild(label); + item.appendChild(value); + + return item; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/StateFactory.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,121 @@ +package de.intevation.flys.artifacts.states; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import de.intevation.artifactdatabase.data.DefaultStateData; +import de.intevation.artifactdatabase.state.State; + +import de.intevation.artifacts.common.utils.XMLUtils; + + +/** + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class StateFactory { + + /** The logger used in this class */ + private static Logger logger = Logger.getLogger(StateFactory.class); + + /** The XPath to the classname of the state */ + public static final String XPATH_STATE = "@state"; + + /** The XPath to the data items of the state relative to the state node. */ + public static final String XPATH_DATA = "data"; + + /** The XPath to the data name relative to the data node.*/ + public static final String XPATH_DATA_NAME = "@name"; + + /** The XPath to the data type relative to the data node.*/ + public static final String XPATH_DATA_TYPE = "@type"; + + /** The XPath to the data description relative to the data node.*/ + public static final String XPATH_DATA_DESCRIPTION = "@description"; + + + /** + * Creates a new State based on the configured class provided by + * <code>stateConf</code>. + * + * @param stateConf The configuration of the state. + * + * @return a State. + */ + public static State createState(Node stateConf) { + String clazz = (String) XMLUtils.xpath( + stateConf, XPATH_STATE, XPathConstants.STRING); + + State state = null; + + try { + logger.debug("Create a new State for class: " + clazz); + state = (State) Class.forName(clazz).newInstance(); + state.setup(stateConf); + + initializeStateData(state, stateConf); + } + catch (InstantiationException ie) { + logger.error(ie, ie); + } + catch (IllegalAccessException iae) { + logger.error(iae, iae); + } + catch (ClassNotFoundException cnfe) { + logger.error(cnfe, cnfe); + } + + return state; + } + + + /** + * This method extracts the configured input data of a state and adds new + * StateData objects to the State. + * + * @param state The state. + * @param stateConf The state configuration node. + */ + protected static void initializeStateData(State state, Node stateConf) { + NodeList dataList = (NodeList) XMLUtils.xpath( + stateConf, XPATH_DATA, XPathConstants.NODESET); + + if (dataList == null || dataList.getLength() == 0) { + logger.debug("The state has no input data configured."); + + return; + } + + int items = dataList.getLength(); + + logger.debug("The state has " + items + " data items configured."); + + for (int i = 0; i < items; i++) { + Node data = dataList.item(i); + + String name = (String) XMLUtils.xpath( + data, XPATH_DATA_NAME, XPathConstants.STRING); + String type = (String) XMLUtils.xpath( + data, XPATH_DATA_TYPE, XPathConstants.STRING); + String desc = (String) XMLUtils.xpath( + data, XPATH_DATA_DESCRIPTION, XPathConstants.STRING); + + if (name == null || name.equals("")) { + logger.warn("No name for data item at pos " + i + " found."); + continue; + } + + if (type == null || type.equals("")) { + logger.warn("No type for data item at pos " + i + " found."); + logger.warn("Default type 'string' used."); + type = "string"; + } + + state.addData(name, new DefaultStateData(name, type, desc)); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WQSelect.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,110 @@ +package de.intevation.flys.artifacts.states; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Element; + +import de.intevation.artifacts.CallContext; + +import de.intevation.artifacts.common.utils.XMLUtils; + +import de.intevation.artifactdatabase.ProtocolUtils; +import de.intevation.artifactdatabase.data.StateData; + +import de.intevation.flys.artifacts.resources.Resources; + +/** + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class WQSelect extends DefaultState { + + /** The logger used in this class.*/ + private static Logger logger = Logger.getLogger(WQSelect.class); + + + /** The default step width for Qs.*/ + public static final String DEFAULT_STEP_Q = "50"; + + /** The default step width for Qs.*/ + public static final String DEFAULT_STEP_W = "30"; + + /** + * The default constructor that initializes an empty State object. + */ + public WQSelect() { + } + + protected Element createData( + XMLUtils.ElementCreator cr, + StateData data, + CallContext context) + { + Element select = ProtocolUtils.createArtNode( + cr, "select", null, null); + + cr.addAttr(select, "name", data.getName(), true); + + Element label = ProtocolUtils.createArtNode( + cr, "label", null, null); + + Element choices = ProtocolUtils.createArtNode( + cr, "choices", null, null); + + label.setTextContent(Resources.getMsg( + context.getMeta(), + data.getName(), + data.getName())); + + select.appendChild(label); + + return select; + } + + + protected Element[] createItems( + XMLUtils.ElementCreator cr, + String name, + CallContext context) + { + // TODO Insert correct min/max values! + + if (name.equals("wq_from")) { + Element minW = createItem(cr, new String[] {"minW", "250"}); + Element minQ = createItem(cr, new String[] {"minQ", "5.5"}); + return new Element[] { minW, minQ }; + } + else if (name.equals("wq_to")) { + Element maxW = createItem(cr, new String[] {"maxW", "850"}); + Element maxQ = createItem(cr, new String[] {"maxQ", "1530"}); + return new Element[] { maxW, maxQ }; + } + else { + Element stepW = createItem(cr, new String[] {"stepW", DEFAULT_STEP_W}); + Element stepQ = createItem(cr, new String[] {"stepQ", DEFAULT_STEP_Q}); + return new Element[] { stepW, stepQ }; + } + } + + + protected Element createItem(XMLUtils.ElementCreator cr, Object obj) { + Element item = ProtocolUtils.createArtNode(cr, "item", null, null); + Element label = ProtocolUtils.createArtNode(cr, "label", null, null); + Element value = ProtocolUtils.createArtNode(cr, "value", null, null); + + String[] arr = (String[]) obj; + + label.setTextContent(arr[0]); + value.setTextContent(arr[1]); + + item.appendChild(label); + item.appendChild(value); + + return item; + } + + + protected String getUIProvider() { + return "wq_panel"; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/transitions/DefaultTransition.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,90 @@ +package de.intevation.flys.artifacts.transitions; + +import de.intevation.artifactdatabase.state.State; +import de.intevation.artifactdatabase.transition.Transition; + +/** + * The default implementation of a <code>Transition</code>. + * + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class DefaultTransition implements Transition { + + /** The ID of the current state */ + protected String from; + + /** The ID of the target state */ + protected String to; + + + /** + * The default constructor. + */ + public DefaultTransition() { + } + + + /** + * The default constructor. + * + * @param from The current state. + * @param to The target state. + */ + public DefaultTransition(String from, String to) { + this.from = from; + this.to = to; + } + + + /** + * Returns the current state ID. + * + * @return the current state ID. + */ + public String getFrom() { + return from; + } + + + /** + * Returns the target state ID. + * + * @return the target state ID. + */ + public String getTo() { + return to; + } + + + /** + * Set the current state ID. + * + * @param to the current state ID. + */ + public void setFrom(String from) { + this.from = from; + } + + + /** + * Set the target state ID. + * + * @param to the target state ID. + */ + public void setTo(String to) { + this.to = to; + } + + + /** + * This method always returns <i>true</i>. + * + * @param state The target state. + * + * @return true. + */ + public boolean isValid(State state) { + return true; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/transitions/TransitionFactory.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,70 @@ +package de.intevation.flys.artifacts.transitions; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Node; + +import de.intevation.artifactdatabase.transition.Transition; + +import de.intevation.artifacts.common.utils.XMLUtils; + + +/** + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class TransitionFactory { + + /** The logger used in this class */ + private static Logger logger = Logger.getLogger(TransitionFactory.class); + + /** The XPath to the classname of the transition */ + public static final String XPATH_TRANSITION = "@transition"; + + /** The XPath to the current state ID */ + public static final String XPATH_CURRENT_STATE = "from/@state"; + + /** The XPath to the target state ID */ + public static final String XPATH_TARGET_STATE = "to/@state"; + + + /** + * Creates a new Transition based on the configured class provided by + * <code>transitionConf</code>. + * + * @param transitionConf The configuration of the transition. + * + * @return a Transition. + */ + public static Transition createTransition(Node transitionConf) { + String clazz = (String) XMLUtils.xpath( + transitionConf, XPATH_TRANSITION, XPathConstants.STRING); + + Transition transition = null; + + try { + transition = (Transition) Class.forName(clazz).newInstance(); + + String from = (String) XMLUtils.xpath( + transitionConf, XPATH_CURRENT_STATE, XPathConstants.STRING); + String to = (String) XMLUtils.xpath( + transitionConf, XPATH_TARGET_STATE, XPathConstants.STRING); + + transition.setFrom(from); + transition.setTo(to); + } + catch (InstantiationException ie) { + logger.error(ie, ie); + } + catch (IllegalAccessException iae) { + logger.error(iae, iae); + } + catch (ClassNotFoundException cnfe) { + logger.error(cnfe, cnfe); + } + + return transition; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/collections/FLYSArtifactCollection.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,117 @@ +package de.intevation.flys.collections; + +import java.util.Date; + +import javax.xml.xpath.XPathConstants; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import de.intevation.artifacts.Artifact; +import de.intevation.artifacts.ArtifactNamespaceContext; +import de.intevation.artifacts.CallContext; +import de.intevation.artifacts.CollectionItem; + +import de.intevation.artifacts.common.utils.XMLUtils; + +import de.intevation.artifactdatabase.DefaultArtifactCollection; +import de.intevation.artifactdatabase.Backend; +import de.intevation.artifactdatabase.Backend.PersistentArtifact; + + +/** + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class FLYSArtifactCollection extends DefaultArtifactCollection { + + /** The logger used in this class.*/ + private static Logger log = Logger.getLogger(FLYSArtifactCollection.class); + + + /** Constant XPath that points to the outputmodes of an artifact.*/ + public static final String XPATH_ARTIFACT_OUTPUTMODES = + "/art:result/art:outputmodes"; + + + @Override + public Document describe(CallContext context) { + log.debug("FLYSArtifactCollection.describe: " + identifier); + + Document doc = XMLUtils.newDocument(); + + XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( + doc, + ArtifactNamespaceContext.NAMESPACE_URI, + ArtifactNamespaceContext.NAMESPACE_PREFIX); + + Date creationTime = getCreationTime(); + String creation = creationTime != null + ? Long.toString(creationTime.getTime()) + : ""; + + Element collection = ec.create("artifact-collection"); + Element artifacts = ec.create("artifacts"); + + ec.addAttr(collection, "name", getName(), true); + ec.addAttr(collection, "uuid", identifier(), true); + ec.addAttr(collection, "creation", creation, true); + + collection.appendChild(artifacts); + doc.appendChild(collection); + + Document attribute = getAttribute(); + if (attribute != null) { + Node child = attribute.getFirstChild(); + collection.appendChild(doc.importNode(child, true)); + } + + Backend backend = Backend.getInstance(); + CollectionItem[] items = backend.listCollectionArtifacts(identifier()); + + for (CollectionItem item: items) { + artifacts.appendChild( + buildArtifactNode(item, backend, context, ec)); + } + + return doc; + } + + + protected Element buildArtifactNode( + CollectionItem item, + Backend backend, + CallContext context, + XMLUtils.ElementCreator ec) + { + String uuid = item.getArtifactIdentifier(); + + log.debug("Append artifact '"+ uuid +"' to collection description"); + + PersistentArtifact pArtifact = backend.getArtifact(uuid); + Artifact artifact = pArtifact.getArtifact(); + + Element ci = ec.create("artifact"); + ec.addAttr(ci, "uuid", uuid, true); + ec.addAttr(ci, "hash", artifact.hash(), true); + + // XXX I am not sure if it works well every time with an empty document + // in the describe operation of an artifact. + Document description = artifact.describe(null, context); + Node outputModes = (Node) XMLUtils.xpath( + description, + XPATH_ARTIFACT_OUTPUTMODES, + XPathConstants.NODE, + ArtifactNamespaceContext.INSTANCE); + + if (outputModes != null) { + Document doc = ci.getOwnerDocument(); + ci.appendChild(doc.importNode(outputModes, true)); + } + + return ci; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/ChartExportHelper.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2011 by Intevation GmbH + * + * This program is free software under the LGPL (>=v2.1) + * Read the file LGPL.txt coming with the software for details + * or visit http://www.gnu.org/licenses/ if it does not exist. + */ +package de.intevation.flys.exports; + +import com.lowagie.text.Document; +import com.lowagie.text.DocumentException; +import com.lowagie.text.PageSize; +import com.lowagie.text.Rectangle; + +import com.lowagie.text.pdf.PdfContentByte; +import com.lowagie.text.pdf.PdfTemplate; +import com.lowagie.text.pdf.PdfWriter; + +import java.awt.Graphics2D; +import java.awt.Transparency; + +import java.awt.geom.Rectangle2D.Double; + +import java.awt.geom.Rectangle2D; + +import java.awt.image.BufferedImage; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; + +import javax.imageio.ImageIO; + +import org.apache.batik.svggen.SVGGraphics2D; +import org.apache.batik.svggen.SVGGraphics2DIOException; + +import org.apache.log4j.Logger; + +import org.jfree.chart.JFreeChart; + +import de.intevation.artifacts.CallContext; + +import de.intevation.artifacts.common.utils.XMLUtils; + + +/** + * This class is a helper class which supports some methods to export charts + * into specific formats. + * + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class ChartExportHelper { + + /** + * Constant field to define A4 as default page size. + */ + private static final String DEFAULT_PAGE_SIZE = "A4"; + + /** + * Constant field to define UTF-8 as default encoding. + */ + private static final String DEFAULT_ENCODING = "UTF-8"; + + /** + * Logger used for logging with log4j. + */ + private static Logger log = Logger.getLogger(ChartExportHelper.class); + + + /** + * A method to export a <code>JFreeChart</code> as image to an + * <code>OutputStream</code> with a given format, width and height. + * + * @param out OutputStream + * @param chart JFreeChart object to be exported. + * @param format Format (e.g. png, gif, jpg) + * @param width Width, the image used to be + * @param height Height, the image used to be + * + * @throws IOException if writing image to OutputStream failed. + */ + public static void exportImage( + OutputStream out, + JFreeChart chart, + String format, + int width, + int height + ) + throws IOException + { + log.info("export chart as png"); + + ImageIO.write( + chart.createBufferedImage( + width, height, Transparency.BITMASK, null + ), + format, + out + ); + } + + + /** + * A method to export a <code>JFreeChart</code> as SVG to an + * <code>OutputStream</code>. + * + * @param out OutputStream + * @param chart JFreeChart to be exported + * @param encoding Encoding, defaults to {@link #DEFAULT_ENCODING} if null + * @param width Width the svg used to be + * @param height Height the svg used to be + */ + public static void exportSVG( + OutputStream out, + JFreeChart chart, + String encoding, + int width, + int height + ) { + log.info("export chart as svg"); + + if (encoding == null) + encoding = DEFAULT_ENCODING; + + org.w3c.dom.Document document = XMLUtils.newDocument(); + SVGGraphics2D graphics = new SVGGraphics2D(document); + + chart.draw(graphics, new Rectangle2D.Double(0.0D, 0.0D,width,height)); + + try { + graphics.stream(new OutputStreamWriter(out, encoding)); + } + catch (SVGGraphics2DIOException svge) { + log.error("Error while writing svg export to output stream.", svge); + } + catch (UnsupportedEncodingException uee) { + log.error("Unsupported encoding: " + encoding, uee); + } + } + + + /** + * A method to export a <code>JFreeChart</code> as PDF to an + * <code>OutputStream</code>. + * + * @param out OutputStream + * @param chart JFreeChart + * @param pageFormat String to specify a page format, {@link + * #DEFAULT_PAGE_SIZE} is used if no pageFormat is given + * @param landscape If this is true, the pdf is delivered in landscape + * format + * @param marginLeft Space to left border + * @param marginRight Space to right border + * @param marginTop Space to upper border + * @param marginBottom Space to lower border + */ + public static void exportPDF( + OutputStream out, + JFreeChart chart, + String pageFormat, + float marginLeft, + float marginRight, + float marginTop, + float marginBottom, + CallContext context + ) { + log.info("export chart as pdf."); + + if (pageFormat == null) + pageFormat = DEFAULT_PAGE_SIZE; + + // max size of the chart + Rectangle page = PageSize.getRectangle(pageFormat); + float pageWidth = page.getWidth(); + float pageHeight = page.getHeight(); + + // the chart width + int chartWidth = (Integer) context.getContextValue("chart.width"); + int chartHeight = (Integer) context.getContextValue("chart.height"); + + boolean landscape = chartWidth > chartHeight ? true : false; + + float width = 0; + float height = 0; + if (landscape) { + width = pageHeight; + height = pageWidth; + } + else { + width = pageWidth; + height = pageHeight; + } + + float spaceX = width - marginLeft - marginRight; + if (chartWidth > spaceX) { + log.warn("Width of the chart is too big for pdf -> resize it now."); + double ratio = ((double)spaceX) / chartWidth; + chartWidth *= ratio; + chartHeight *= ratio; + log.debug("Resized chart to " + chartWidth + "x" + chartHeight); + } + + float spaceY = height - marginTop - marginBottom; + if (chartHeight > spaceY) { + log.warn("Height of the chart is too big for pdf -> resize it now."); + double ratio = ((double)spaceY) / chartHeight; + chartWidth *= ratio; + chartHeight *= ratio; + log.debug("Resized chart to " + chartWidth + "x" + chartHeight); + } + + Document document = null; + if (landscape) { + document = new Document(page.rotate()); + log.debug("Create landscape pdf."); + } + else + document = new Document(page); + + try { + PdfWriter writer = PdfWriter.getInstance(document, out); + + document.addSubject(chart.getTitle().getText()); + document.addCreationDate(); + document.open(); + + PdfContentByte content = writer.getDirectContent(); + + PdfTemplate template = content.createTemplate(width, height); + Graphics2D graphics = template.createGraphics(width, height); + + double[] origin = getCenteredAnchor( + marginLeft, marginRight, marginBottom, marginTop, + width, height, + chartWidth, chartHeight); + + Rectangle2D area = new Rectangle2D.Double( + origin[0], origin[1], chartWidth, chartHeight); + + chart.draw(graphics, area); + graphics.dispose(); + content.addTemplate(template, 0f, 0f); + } + catch (DocumentException de) { + log.error("Error while exporting chart to pdf.", de); + } + finally { + document.close(); + } + } + + + /** + * This method returns the anchor of the chart so that the chart is centered + * according to the given parameters. + * + * @param mLeft Left margin + * @param mRight Right margin + * @param mBottom Bottom margin + * @param mTop Top margin + * @param width The complete width of the drawing area. + * @param height The complete height of the drawing area. + * @param chartWidth The width of the chart. + * @param chartHeight The height of the chart. + * + * @return an array that contains the anchor for a chart with the given + * parameters. The first value is the x point, the second value is the y + * point. + */ + public static double[] getCenteredAnchor( + double mLeft, double mRight, double mBottom, double mTop, + double width, double height, + double chartWidth, double chartHeight + ) { + if (log.isDebugEnabled()) { + log.debug("Calculate centered origin..."); + log.debug("-> PDF width : " + width); + log.debug("-> PDF height : " + height); + log.debug("-> Chart width : " + chartWidth); + log.debug("-> Chart height : " + chartHeight); + log.debug("-> margin left : " + mLeft); + log.debug("-> margin right : " + mRight); + log.debug("-> margin bottom: " + mBottom); + log.debug("-> margin top : " + mTop); + } + + double[] origin = new double[2]; + + double centerX = width / 2; + double centerY = height / 2; + + origin[0] = centerX - chartWidth / 2; + origin[1] = centerY - chartHeight / 2; + + origin[0] = origin[0] >= mLeft ? origin[0] : mLeft; + origin[1] = origin[1] >= mTop ? origin[1] : mTop; + + if (log.isDebugEnabled()) { + log.debug("==> centered left origin: " + origin[0]); + log.debug("==> centered top origin: " + origin[1]); + } + + return origin; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/resources/messages.properties Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,13 @@ +state.winfo.river = River +state.winfo.calculation_mode = Calculation Mode +state.winfo.location_distance = Location or distance selection +state.winfo.wq = Input for W/Q data + +calc.surface.curve = Water Level/Surface Curve +calc.flood.map = Flood Plain +calc.discharge.curve = State Discharge Curve/Stage Discharge Relation +calc.duration.curve = Duration Curve +calc.discharge.longitudinal.section = TODO (W bei...) + +river = River +calculation_mode = Calculation Mode
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/resources/messages_de.properties Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,13 @@ +state.winfo.river = Gew\u00e4sser +state.winfo.calculation_mode = Berechnungsart +state.winfo.location_distance = Wahl des Berechnungsortes/strecke +state.winfo.wq = Eingabe f\u00fcr W/Q Daten + +calc.surface.curve = Wasserstand/Wasserspiegellage +calc.flood.map = \u00dcberschwemmungsfl\u00e4che +calc.discharge.curve = Abflusskurve/Abflusstafel +calc.duration.curve = Dauerlinie +calc.discharge.longitudinal.section = W bei ungleichm\u00e4\u00dfigem Abflussl\u00e4ngsschnitt + +river = Fluss +calculation_mode = Berechnungsart
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/resources/messages_de_DE.properties Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,13 @@ +state.winfo.river = Gew\u00e4sser +state.winfo.calculation_mode = Berechnungsart +state.winfo.location_distance = Wahl des Berechnungsortes/strecke +state.winfo.wq = Eingabe f\u00fcr W/Q Daten + +calc.surface.curve = Wasserstand/Wasserspiegellage +calc.flood.map = \u00dcberschwemmungsfl\u00e4che +calc.discharge.curve = Abflusskurve/Abflusstafel +calc.duration.curve = Dauerlinie +calc.discharge.longitudinal.section = W bei ungleichm\u00e4\u00dfigem Abflussl\u00e4ngsschnitt + +river = Fluss +calculation_mode = Berechnungsart
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/resources/messages_en.properties Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,13 @@ +state.winfo.river = River +state.winfo.calculation_mode = Calculation Mode +state.winfo.location_distance = Location or distance selection +state.winfo.wq = Input for W/Q data + +calc.surface.curve = Water Level/Surface Curve +calc.flood.map = Flood Plain +calc.discharge.curve = State Discharge Curve/Stage Discharge Relation +calc.duration.curve = Duration Curve +calc.discharge.longitudinal.section = TODO (W bei...) + +river = River +calculation_mode = Calculation Mode
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/test/java/de/intevation/flys/artifacts/AppTest.java Fri Sep 28 12:14:07 2012 +0200 @@ -0,0 +1,38 @@ +package de.intevation.flys.artifacts; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +}