# HG changeset patch # User Tom Gottfried # Date 1378973589 -7200 # Node ID e0311aa32efba05637f706e93c76c8e54407e82a # Parent 04a84a9ab90346be8e65ce9c709debaf175b159c# Parent 17398e239c77164d51da229e4a79c7735dba8934 merged accidental head (nothing changed) diff -r 17398e239c77 -r e0311aa32efb .hgtags --- a/.hgtags Sat Jun 29 00:20:58 2013 +0200 +++ b/.hgtags Thu Sep 12 10:13:09 2013 +0200 @@ -55,3 +55,15 @@ eec895f6ec801a7faaed96e9f01721e1143e7bb8 3.0.8 41152c3a532d63a25e9fa348ca4286bdd76069ef 3.0.9 5f4893db41e4fed644ddbd91bf4cdf0ac7952161 3.0.10 +5f4893db41e4fed644ddbd91bf4cdf0ac7952161 3.0.10 +0000000000000000000000000000000000000000 3.0.10 +0000000000000000000000000000000000000000 3.0.10 +bfcb513c1fdace07ce39616bc9fda3899e8ee914 3.0.10 +63baa1873b1f86a78ab10d19ae4221ec01cc75a2 3.0.11 +3999162f474fb5a6bced33521f81c9ccf274c4e7 3.0.12 +3999162f474fb5a6bced33521f81c9ccf274c4e7 3.0.12 +0000000000000000000000000000000000000000 3.0.12 +0000000000000000000000000000000000000000 3.0.12 +da197a9236fde564d45379c0826510c69a5709ce 3.0.12 +71da3d4ffb4a46a2f8de7e6a9e1e4a32657802aa 3.0.13 +84b1e87e86692db4202c5d68e0c521185ef0f9d2 3.0.14 diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/artifacts/chart.xml --- a/artifacts/doc/conf/artifacts/chart.xml Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/artifacts/chart.xml Thu Sep 12 10:13:09 2013 +0200 @@ -58,8 +58,18 @@ + + + + + + + + + + @@ -70,6 +80,7 @@ + @@ -83,6 +94,13 @@ + + + + + + + diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/artifacts/fixanalysis.xml --- a/artifacts/doc/conf/artifacts/fixanalysis.xml Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/artifacts/fixanalysis.xml Thu Sep 12 10:13:09 2013 +0200 @@ -171,8 +171,8 @@ - - + + diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/artifacts/gaugedischarge.xml --- a/artifacts/doc/conf/artifacts/gaugedischarge.xml Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/artifacts/gaugedischarge.xml Thu Sep 12 10:13:09 2013 +0200 @@ -8,8 +8,15 @@ - - + + + + + + + + + diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/artifacts/gaugedischargecurve.xml --- a/artifacts/doc/conf/artifacts/gaugedischargecurve.xml Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/artifacts/gaugedischargecurve.xml Thu Sep 12 10:13:09 2013 +0200 @@ -6,11 +6,20 @@ - + - - + + + + + + + + + + + diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/artifacts/minfo.xml --- a/artifacts/doc/conf/artifacts/minfo.xml Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/artifacts/minfo.xml Thu Sep 12 10:13:09 2013 +0200 @@ -524,6 +524,14 @@ + + + + + + diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/artifacts/winfo.xml --- a/artifacts/doc/conf/artifacts/winfo.xml Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/artifacts/winfo.xml Thu Sep 12 10:13:09 2013 +0200 @@ -271,6 +271,14 @@ + + + + + + + + @@ -318,6 +326,8 @@ + + @@ -374,6 +384,8 @@ + + @@ -630,11 +642,12 @@ + - - + + diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/conf.xml --- a/artifacts/doc/conf/conf.xml Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/conf.xml Thu Sep 12 10:13:09 2013 +0200 @@ -363,6 +363,7 @@ org.dive4elements.river.exports.fixings.FixWQCurveGenerator org.dive4elements.river.exports.fixings.FixWQCurveInfoGenerator org.dive4elements.river.exports.minfo.SedimentLoadLSGenerator + org.dive4elements.river.exports.minfo.SedimentLoadExporter org.dive4elements.river.exports.minfo.SedimentLoadLSInfoGenerator org.dive4elements.river.exports.ReportGenerator diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/datacage.sql --- a/artifacts/doc/conf/datacage.sql Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/datacage.sql Thu Sep 12 10:13:09 2013 +0200 @@ -41,7 +41,7 @@ artifact_id INT NOT NULL REFERENCES artifacts(id) ON DELETE CASCADE, kind VARCHAR(256) NOT NULL, k VARCHAR(256) NOT NULL, - v VARCHAR(256), -- Maybe too short + v TEXT, UNIQUE (artifact_id, k) ); diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/jasper/sqrelation.jasper Binary file artifacts/doc/conf/jasper/sqrelation.jasper has changed diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/jasper/sqrelation_en.jasper Binary file artifacts/doc/conf/jasper/sqrelation_en.jasper has changed diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/mapserver/barrier_lines_class.vm --- a/artifacts/doc/conf/mapserver/barrier_lines_class.vm Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/mapserver/barrier_lines_class.vm Thu Sep 12 10:13:09 2013 +0200 @@ -1,6 +1,6 @@ CLASS NAME "Damm" - EXPRESSION ("[TYP]"="Damm") + EXPRESSION /damm/i STYLE SIZE 5 OUTLINECOLOR "#008000" @@ -8,7 +8,7 @@ END CLASS NAME "Rohr 1" - EXPRESSION ("[TYP]"="Rohr 1") + EXPRESSION /rohr.1/i STYLE SIZE 5 OUTLINECOLOR "#800080" @@ -16,7 +16,7 @@ END CLASS NAME "Rohr 2" - EXPRESSION ("[TYP]"="Rohr 2") + EXPRESSION /rohr.2/i STYLE SIZE 5 OUTLINECOLOR "#808080" @@ -24,7 +24,7 @@ END CLASS NAME "Graben" - EXPRESSION ("[TYP]"="Graben") + EXPRESSION /graben/i STYLE SIZE 5 OUTLINECOLOR "#800000" @@ -32,7 +32,7 @@ END CLASS NAME "Ringdeich" - EXPRESSION ("[TYP]"="Ringdeich") + EXPRESSION /ringdeich/i STYLE SIZE 5 OUTLINECOLOR "#800000" diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/mapserver/barrier_polygons_class.vm --- a/artifacts/doc/conf/mapserver/barrier_polygons_class.vm Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/mapserver/barrier_polygons_class.vm Thu Sep 12 10:13:09 2013 +0200 @@ -1,6 +1,6 @@ CLASS NAME "Ringdeich" - EXPRESSION ("[TYP]"="Ringdeich") + EXPRESSION /ringdeich/i STYLE SIZE 5 OUTLINECOLOR "#FF8000" diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/mapserver/mapfile.vm --- a/artifacts/doc/conf/mapserver/mapfile.vm Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/mapserver/mapfile.vm Thu Sep 12 10:13:09 2013 +0200 @@ -19,23 +19,27 @@ WEB METADATA "wms_title" "FLYS Web Map Service" - "wms_onlineresource" "$MAPSERVERURL" + "wms_onlineresource" "${MAPSERVERURL}user-wms" "wms_encoding" "UTF-8" "wms_accessconstraints" "none" "wms_fees" "none" "wms_addresstype" "postal" - "wms_address" "Any Street" - "wms_city" "Any City" - "wms_stateorprovince" "Any state" - "wms_postcode" "My Postalcode" - "wms_country" "Any Country" - "wms_contactperson" "Any Person" - "wms_contactorganization" "Any Orga" - "wms_contactelectronicmailaddress" "any-email@example.com" - "wms_contactvoicetelephone" "Any's telephone number" + "wms_address" "" + "wms_city" "" + "wms_stateorprovince" "" + "wms_postcode" "" + "wms_country" "" + "wms_contactperson" "" + "wms_contactorganization" "" + "wms_contactelectronicmailaddress" "" + "wms_contactvoicetelephone" "" "wms_srs" "EPSG:4326 EPSG:31466 EPSG:31467" "wms_feature_info_mime_type" "text/html" + "wms_getmap_formatlist" "image/png,image/png; mode=24bit,image/jpeg" "ows_enable_request" "*" + "ows_sld_enabled" "false" + "ows_title" "FLYS Web Map Service" + "ows_extent" "3233232 5303455 3421524 5585825" END END diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/mapserver/river-mapfile.vm --- a/artifacts/doc/conf/mapserver/river-mapfile.vm Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/mapserver/river-mapfile.vm Thu Sep 12 10:13:09 2013 +0200 @@ -19,7 +19,7 @@ WEB METADATA "wms_title" "FLYS Rivers Web Map Service" - #"wms_onlineresource" "http://localhost:7777/river-wms" # "$MAPSERVERURL" + "wms_onlineresource" "${MAPSERVERURL}river-wms" "wms_encoding" "UTF-8" "wms_accessconstraints" "none" "wms_fees" "none" diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/mapserver/shapefile_layer.vm --- a/artifacts/doc/conf/mapserver/shapefile_layer.vm Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/mapserver/shapefile_layer.vm Thu Sep 12 10:13:09 2013 +0200 @@ -21,6 +21,8 @@ "wms_group_title" "$LAYER.getGroupTitle()" #end END + + CLASSITEM "TYP" #if ( !$LAYER.getStyle() ) #if ( $LAYER.getGroupTitle() ) diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/mapserver/wsplgen_layer.vm --- a/artifacts/doc/conf/mapserver/wsplgen_layer.vm Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/mapserver/wsplgen_layer.vm Thu Sep 12 10:13:09 2013 +0200 @@ -19,6 +19,7 @@ "gml_include_items" "all" "ows_enable_request" "GetFeatureInfo" "wms_feature_info_mime_type" "gml" + "wms_srs" "EPSG:4326 EPSG:31466 EPSG:31467" #if ( $LAYER.getGroupTitle() ) "wms_group_title" "$LAYER.getGroupTitle()" #end diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/meta-data.xml --- a/artifacts/doc/conf/meta-data.xml Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/meta-data.xml Thu Sep 12 10:13:09 2013 +0200 @@ -36,6 +36,7 @@ + Generate system content with variables: {dc:dump-variables()} @@ -44,6 +45,7 @@ Recommendations (client shall load immediately). + Rec out iteration for: {$out} @@ -85,14 +87,20 @@ + + + + + + @@ -119,6 +127,7 @@ Non - Recommendations. + Non Rec out iteration for: {$out} @@ -135,12 +144,34 @@ + + + + + + + + + + + + + - + + + + + + + + + + @@ -157,14 +188,14 @@ + + - - @@ -250,11 +281,12 @@ - + + - - + + @@ -268,6 +300,16 @@ + + + + + + + + + + @@ -311,6 +353,7 @@ + @@ -319,6 +362,7 @@ + @@ -326,9 +370,6 @@ - - - @@ -340,16 +381,18 @@ + + + + + - - - @@ -358,7 +401,8 @@ - + + @@ -375,20 +419,20 @@ - + - + - + @@ -411,9 +455,10 @@ @@ -440,31 +485,50 @@ - - + + + + + + SELECT g.id AS gauge_id, + g.name AS gauge_name, + dt.id AS dt_id, + t.start_time AS start_time, + t.stop_time AS stop_time, + dt.description AS desc, + dt.bfg_id AS bfg_id + FROM gauges g + JOIN discharge_tables dt ON g.id = dt.gauge_id + LEFT JOIN time_intervals t ON dt.time_interval_id = t.id + WHERE g.river_id = ${river_id} + AND dt.kind <> 0 + AND ((g.station = ${fromkm} AND g.station = ${tokm}) + OR g.official_number = ${refgauge}) + ORDER BY start_time + - - - - - - - - - - - - + + + + + + + + - + + - + @@ -483,7 +547,7 @@ - + Aheinecke: Why is this grouping different from the rest? @@ -507,7 +571,7 @@ - + Aheinecke: Why is this grouping different from the rest? @@ -535,7 +599,7 @@ starts-with($facet_name, 'fix_reference_events_ls'))"> - + @@ -563,7 +627,7 @@ starts-with($facet_name, 'fix_sector_average_dwt'))"> - + @@ -588,7 +652,7 @@ starts-with($facet_name, 'fix_deviation_dwt'))"> - + @@ -611,7 +675,7 @@ - + @@ -638,7 +702,7 @@ $facet_name = 'fix_wq_curve')"> - + @@ -682,7 +746,7 @@ (not ($current-state-id = 'state.winfo.uesk.wsp' and $ld_m = 'location'))"> - + @@ -710,6 +774,77 @@ + + + + No diffs between beddiffs and others, for now. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No grouping in this? @@ -734,7 +869,7 @@ $facet_name = 'bed_longitudinal_section.bed_diameter_sublayer')"> - + @@ -758,7 +893,7 @@ $facet_name = 'bed_longitudinal_section.bedload_diameter'"> - + @@ -783,7 +918,7 @@ $facet_name = 'bed_longitudinal_section.sediment_density_sublayer')"> - + @@ -808,7 +943,7 @@ $facet_name = 'bed_longitudinal_section.porosity_sublayer')"> - + @@ -835,7 +970,7 @@ $facet_name = 'flow_velocity.mainchannel.filtered')"> - + @@ -858,7 +993,7 @@ - + @@ -877,35 +1012,35 @@ - + - - + + - - - + + + - + - + - + @@ -1193,36 +1328,27 @@ - SELECT id AS gauge_id, - name AS gauge_name - FROM gauges WHERE river_id = ${river_id} + SELECT g.id AS gauge_id, + g.name AS gauge_name, + t.start_time AS start_time, + t.stop_time AS stop_time + FROM gauges g + JOIN discharge_tables dt ON g.id = dt.gauge_id + LEFT JOIN time_intervals t ON dt.time_interval_id = t.id + WHERE g.river_id = ${river_id} + AND dt.kind = 0 + AND ((g.station = ${fromkm} AND g.station = ${tokm}) + OR g.official_number = ${refgauge}) - - - - - - - + + + - TODO: Why is this just a copy of the discharge_table_gauge? - - - - - TODO: Why is this just a copy of the discharge_table_gauge? - - - - @@ -1845,7 +1971,6 @@ FROM floodplain fp JOIN floodplain_kinds flk on fp.kind_id = flk.id WHERE river_id = ${river_id} - AND kind_id=1 @@ -2332,8 +2457,8 @@ + ids="official-wstv-{$wstcolpos}-{$wstid}" + factory="staticwqkms" target_out="{$out}"/> @@ -2367,17 +2492,21 @@ - Select collections and masterartifacts. + Select collections and masterartifacts. + XXX: The cast is a quick hack because the ld_* values are + now TEXT fields. To properly fix / asses the problems here + an SLT evaluation is needed. + SELECT c.name AS collection_name, ma.id AS a_id, ma.state AS a_state, ma.gid AS a_gid, ma.creation AS a_creation, - COALESCE(ma.ld_mode, '') AS ld_m, - COALESCE(ma.ld_locations, '') AS ld_l, - COALESCE(ma.ld_from, '') AS ld_f, - COALESCE(ma.ld_to, '') AS ld_t, + CAST(COALESCE(ma.ld_mode, '') AS VARCHAR(255)) AS ld_m, + CAST(COALESCE(ma.ld_locations, '') AS VARCHAR(255)) AS ld_l, + CAST(COALESCE(ma.ld_from, '') AS VARCHAR(255)) AS ld_f, + CAST(COALESCE(ma.ld_to, '') AS VARCHAR(255)) AS ld_t, o.name AS out_name, o.id AS out_id, f.name AS facet_name, diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/themes.xml --- a/artifacts/doc/conf/themes.xml Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/themes.xml Thu Sep 12 10:13:09 2013 +0200 @@ -177,9 +177,12 @@ + + + @@ -207,6 +210,7 @@ + @@ -273,6 +277,7 @@ + diff -r 17398e239c77 -r e0311aa32efb artifacts/doc/conf/themes/default.xml --- a/artifacts/doc/conf/themes/default.xml Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/doc/conf/themes/default.xml Thu Sep 12 10:13:09 2013 +0200 @@ -84,6 +84,8 @@ display="Punktbeschriftung anzeigen" default="false" hints="hidden" /> + @@ -116,6 +118,19 @@ + + + + + + + + + + + @@ -834,11 +849,26 @@ - + + + + + + + + /> + + + @@ -1124,7 +1154,7 @@ display="Beschriftung anzeigen" default="false" hints="hidden" /> - + @@ -1399,12 +1429,14 @@ - + + @@ -1442,6 +1474,20 @@ + + + + + + + + + + + @@ -1544,9 +1590,21 @@ + + + + + + + + + + - + - + - + - + + + + + + + + + + + + @@ -28,20 +42,6 @@ - - - - - - - - - - - @@ -834,11 +834,26 @@ - + + + + + + + + /> + + + @@ -1124,7 +1139,7 @@ display="Beschriftung anzeigen" default="false" hints="hidden" /> - + @@ -1399,12 +1414,14 @@ - + + @@ -1442,6 +1459,20 @@ + + + + + + + + + + + @@ -1544,9 +1575,21 @@ + + + + + + + + + + - + - + - + - + + + + + + + + + 0) { - min = range[0]; + this.addStringData(DATA_KM, Double.toString(range[0])); + this.addStringData(PARENT_KM, Double.toString(range[0])); } - this.addStringData(DATA_KM, Double.toString(min)); } @@ -242,6 +245,24 @@ /** + * Return position (km) from parent (initial km), 0 if not found. + */ + private double getParentKm() { + String val = getDataAsString(PARENT_KM); + if (val == null) { + logger.warn("Empty data: " + PARENT_KM); + return 0; + } + try { + return Double.valueOf(val); + } + catch (NumberFormatException e) { + logger.warn("Could not get data " + PARENT_KM + " as double", e); + return 0; + } + } + + /** * Return position (km) from data, 0 if not found. */ protected double getKm() { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/D4EArtifact.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/D4EArtifact.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/D4EArtifact.java Thu Sep 12 10:13:09 2013 +0200 @@ -1491,7 +1491,7 @@ /** * Method to dump the artifacts state/data. */ - protected void dumpArtifact() { + public void dumpArtifact() { log.debug("++++++++++++++ DUMP ARTIFACT DATA +++++++++++++++++"); // Include uuid, type, name log.debug(" - Name: " + getName()); @@ -1525,7 +1525,7 @@ } - protected void debugFacets() { + public void debugFacets() { log.debug("######### FACETS #########"); for (Map.Entry> entry: facets.entrySet()) { @@ -1541,7 +1541,7 @@ } - protected void dumpFilterFacets() { + public void dumpFilterFacets() { log.debug("######## FILTER FACETS ########"); if (filterFacets == null || filterFacets.isEmpty()) { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/FlowVelocityMeasurementArtifact.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/FlowVelocityMeasurementArtifact.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/FlowVelocityMeasurementArtifact.java Thu Sep 12 10:13:09 2013 +0200 @@ -8,6 +8,8 @@ package org.dive4elements.river.artifacts; +import java.text.DateFormat; + import java.util.ArrayList; import java.util.List; @@ -29,6 +31,8 @@ import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.utils.Formatter; + /** Artefact to access flow velocity measurements. */ public class FlowVelocityMeasurementArtifact @@ -111,13 +115,24 @@ List fs = new ArrayList(); String code = getDatacageIDValue(data); + DateFormat dateFormatter = Formatter.getDateFormatter( + callMeta, "dd.MM.yyy HH:mm"); if (code != null) { // parse code, interact with factory, add real facets. // store relevant parts of code as data. + FlowVelocityMeasurementValue.FastFlowVelocityMeasurementValue + flowVelocityMeasurement = + FlowVelocityMeasurementFactory.getFlowVelocityMeasurement( + Integer.parseInt(code)); + String name = flowVelocityMeasurement.getDescription(); + logger.debug ("datetime " + flowVelocityMeasurement.getDatetime()); + name += " - " + dateFormatter.format( + flowVelocityMeasurement.getDatetime()); + Facet facet = new FlowVelocityMeasurementFacet( FLOW_VELOCITY_MEASUREMENT, - "flowvelocity-name"); + name); fs.add(facet); addFacets(state.getID(), fs); addStringData(DATA_NAME, code); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/GaugeDischargeArtifact.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/GaugeDischargeArtifact.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/GaugeDischargeArtifact.java Thu Sep 12 10:13:09 2013 +0200 @@ -12,6 +12,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.HashMap; import org.apache.log4j.Logger; @@ -35,6 +36,7 @@ import org.dive4elements.river.model.Gauge; import org.dive4elements.river.model.River; +import org.dive4elements.river.model.DischargeTable; import org.dive4elements.river.utils.RiverUtils; @@ -52,6 +54,8 @@ /** The name of the artifact. */ public static final String ARTIFACT_NAME = "gaugedischarge"; + /** The name a facet should have */ + protected String facetWishName; /** * Trivial Constructor. @@ -79,6 +83,13 @@ String ids = StaticD4EArtifact.getDatacageIDValue(data); addStringData("ids", ids); logger.debug("id for gaugedischarge: " + ids); + String[] splitIds = ids.split(";"); + /* We assume that if an id's string with a ; is given that the + * format is ;; + * so that a specific discharge table can be selected */ + if (splitIds.length > 2) { + facetWishName = splitIds[2]; + } super.setup(identifier, factory, context, callMeta, data); } @@ -121,7 +132,10 @@ /** Get the Gauges name which came with datacage data-document. */ public String getGaugeName() { - return this.getDataAsString("ids"); + if (getDataAsString("ids") == null) { + return null; + } + return getDataAsString("ids").split(";")[0]; } @@ -166,13 +180,34 @@ } */ - DischargeTables dt = new DischargeTables(river.getName(), getDataAsString("ids")); + Map map; - Map map = dt.getValues(); + String[] ids = getDataAsString("ids").split(";"); + if (ids.length > 1) { + /* We assume that if an id's string with a ; is given that the + * format is ;; + * so that a specific discharge table can be selected */ + int tableId = 0; + try { + tableId = Integer.parseInt(ids[1]); + } catch (NumberFormatException e) { + logger.error("Discharge tables ids string is wrong." + + " Fromat is ;;" + + " Fix your Datacage!"); + // Let's rather break down completly then show the wrong data. + return null; + } + DischargeTable table = DischargeTable.getDischargeTableById(tableId); + map = new HashMap(); + map.put(getGaugeName(), DischargeTables.loadDischargeTableValues(table)); + } else { + DischargeTables dt = new DischargeTables(river.getName(), getGaugeName()); + map = dt.getValues(); + } ArrayList res = new ArrayList(); - Gauge gauge = river.determineGaugeByName(this.getDataAsString("ids")); + Gauge gauge = river.determineGaugeByName(getGaugeName()); String name = getGaugeName(); double [][] values = map.get(name); @@ -191,5 +226,13 @@ res.toArray(new WQKms[res.size()]), new Calculation()); } + + /** Gets the facet wish name. + * + * This is a hack to enable setting the name of the facet / theme in the + * UI from the datacage setting. */ + public String getFacetWishName() { + return facetWishName; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/MainValuesArtifact.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/MainValuesArtifact.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/MainValuesArtifact.java Thu Sep 12 10:13:09 2013 +0200 @@ -81,7 +81,10 @@ String outputName ) { return outputName.equals("computed_discharge_curve") - || outputName.equals("duration_curve"); + || outputName.equals("duration_curve") + || outputName.equals("discharge_curve") + || outputName.equals("fix_wq_curve") + || outputName.equals("historical_discharge_wq"); } }); } @@ -316,6 +319,21 @@ return spawnState(); } + /** + * Access the Gauge that the mainvalues are taken from. + * @return Gauge that main values are taken from or null in case of + * invalid parameterization. + */ + protected Gauge getGauge(double km) { + River river = RiverUtils.getRiver(this); + + if (river == null) { + logger.error("River is null"); + return null; + } + + return river.determineGaugeByPosition(km); + } /** * Access the Gauge that the mainvalues are taken from. @@ -358,6 +376,41 @@ * Get a list of "Q" main values. * @return list of Q main values. */ + public List getMainValuesQ(double[] kms) { + List filteredList = new ArrayList(); + boolean atGauge = false; + Gauge gauge = getGauge(kms[0]); + WstValueTable interpolator = WstValueTableFactory.getTable(RiverUtils.getRiver(this)); + Calculation c = new Calculation(); + double w_out[] = {0.0f}; + double q_out[] = {0.0f}; + if (gauge != null) { + double gaugeStation = gauge.getStation().doubleValue(); + atGauge = Math.abs(kms[0] - gaugeStation) < 1e-4; + List orig = gauge.getMainValues(); + for (MainValue mv : orig) { + if (mv.getMainValue().getType().getName().equals("Q")) { + if (atGauge) { + q_out[0] = mv.getValue().doubleValue(); + } + else { + interpolator.interpolate(mv.getValue().doubleValue(), + gaugeStation, kms, w_out, q_out, c); + } + filteredList.add(new NamedDouble( + mv.getMainValue().getName(), + q_out[0] + )); + } + } + } + return filteredList; + } + + /** + * Get a list of "Q" main values. + * @return list of Q main values. + */ public List getMainValuesQ(boolean atGauge) { List filteredList = new ArrayList(); Gauge gauge = getGauge(); @@ -366,8 +419,8 @@ double w_out[] = {0.0f}; double q_out[] = {0.0f}; double kms[] = {getLocation()}; - double gaugeStation = gauge.getStation().doubleValue(); if (gauge != null) { + double gaugeStation = gauge.getStation().doubleValue(); List orig = gauge.getMainValues(); for (MainValue mv : orig) { if (mv.getMainValue().getType().getName().equals("Q")) { @@ -389,21 +442,26 @@ } - /** - * Get a list of "W" main values. - * @param atGauge if true, do not interpolate - * @return list of W main values. - */ - public List getMainValuesW(boolean atGauge) { + /** Get main values of km. */ + public List getMainValuesW(double[] kms) { List filteredList = new ArrayList(); - Gauge gauge = getGauge(); + boolean atGauge = false; + double gaugeDatum = 0d; + Gauge gauge = getGauge(kms[0]); + if (gauge == null) { + return filteredList; + } + else if (Math.abs(kms[0] - gauge.getStation().doubleValue()) < 1e-4) { + atGauge = true; + gaugeDatum = gauge.getDatum().doubleValue(); + } + WstValueTable interpolator = WstValueTableFactory.getTable(RiverUtils.getRiver(this)); Calculation c = new Calculation(); double gaugeStation = gauge.getStation().doubleValue(); double w_out[] = {0.0f}; double q_out[] = {0.0f}; - double kms[] = {getLocation()}; if (gauge != null) { List orig = gauge.getMainValues(); for (MainValue mv : orig) { @@ -411,6 +469,41 @@ if (mv.getMainValue().getType().getName().equals("W")) { filteredList.add(new NamedDouble(mv.getMainValue().getName(), mv.getValue().doubleValue())); + } + } else + // We cannot interpolate the W values, so derive them + // from given Q values. + if (mv.getMainValue().getType().getName().equals("Q")) { + interpolator.interpolate(mv.getValue().doubleValue(), + gaugeStation, kms, w_out, q_out, c); + + filteredList.add(new NamedDouble( + "W(" + mv.getMainValue().getName() +")", + w_out[0] + )); + } + } + } + return filteredList; + } + + + public List getMainValuesW(boolean atGauge, double[] kms) { + List filteredList = new ArrayList(); + Gauge gauge = getGauge(); + WstValueTable interpolator = WstValueTableFactory.getTable(RiverUtils.getRiver(this)); + Calculation c = new Calculation(); + + double w_out[] = {0.0f}; + double q_out[] = {0.0f}; + if (gauge != null) { + double gaugeStation = gauge.getStation().doubleValue(); + List orig = gauge.getMainValues(); + for (MainValue mv : orig) { + if (atGauge) { + if (mv.getMainValue().getType().getName().equals("W")) { + filteredList.add(new NamedDouble(mv.getMainValue().getName(), + mv.getValue().doubleValue())); } } else @@ -431,6 +524,16 @@ /** + * Get a list of "W" main values. + * @param atGauge if true, do not interpolate + * @return list of W main values. + */ + public List getMainValuesW(boolean atGauge) { + return getMainValuesW(atGauge, new double[] {getLocation()}); + } + + + /** * Returns the name of this artifact ('mainvalue'). * * @return 'mainvalue' diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/RiverAxisArtifact.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/RiverAxisArtifact.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/RiverAxisArtifact.java Thu Sep 12 10:13:09 2013 +0200 @@ -91,6 +91,10 @@ super(artifact); } + private boolean isUnofficial() { + return getIdPart(2) != null && !getIdPart(2).equals("1"); + } + @Override protected String getFacetType() { return FLOODMAP_RIVERAXIS; @@ -98,12 +102,19 @@ @Override protected String getLayer() { + if (isUnofficial()) { + return super.getLayer(); + } return RiverFactory.getRiver(getRiverId()).getName(); } @Override protected String getUrl() { - return RiverUtils.getRiverWMSUrl(); + if (isUnofficial()) { + return RiverUtils.getUserWMSUrl(artifact.identifier()); + } else { + return RiverUtils.getRiverWMSUrl(); + } } @Override diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWKmsArtifact.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWKmsArtifact.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWKmsArtifact.java Thu Sep 12 10:13:09 2013 +0200 @@ -310,7 +310,7 @@ return -1; } - // Do linear interpolation + // Do linear interpolation. int mod = kmIncreasing ? -1 : +1; return Linear.linear(km, wkms.getKm(idx+mod), wkms.getKm(idx), wkms.getW(idx+mod), wkms.getW(idx)); } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWQKmsArtifact.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWQKmsArtifact.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/StaticWQKmsArtifact.java Thu Sep 12 10:13:09 2013 +0200 @@ -59,6 +59,8 @@ private static final String NAME = "staticwqkms"; + private boolean official = false; + static { // TODO: Move to configuration. FacetActivity.Registry.getInstance().register( @@ -85,6 +87,10 @@ /** * Gets called from factory, to set things up. + * + * If the id's string starts with official- it will be treated as + * an Artifact containing official data for the according special + * case handling. */ @Override public void setup( @@ -98,7 +104,7 @@ // Store the 'ids' (from datacage). if (logger.isDebugEnabled()) { - logger.debug("StaticWQKmsArtiact.setup" + XMLUtils.toString(data)); + logger.debug("StaticWQKmsArtifact.setup" + XMLUtils.toString(data)); } String code = getDatacageIDValue(data); @@ -106,6 +112,10 @@ if (code != null) { String [] parts = code.split("-"); + if (parts.length >= 1) { + official = parts[0].toLowerCase().equals("official"); + } + if (parts.length >= 4) { int col = Integer.parseInt(parts[2]); int wst = Integer.parseInt(parts[3]); @@ -222,5 +232,10 @@ return Lines.createWaterLines(points, wAtKm); } // TODO implement deepCopy. + + public boolean isOfficial() + { + return official; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/WINFOArtifact.java Thu Sep 12 10:13:09 2013 +0200 @@ -197,15 +197,26 @@ String calculationMode = getDataAsString("calculation_mode"); - if (calculationMode.equals("calc.discharge.longitudinal.section") - ) { - return getDischargeLongitudinalSectionData(); - } - else if (calculationMode.equals("calc.extreme.curve")) { - return (CalculationResult) - this.compute(context, ComputeType.ADVANCE, false); + // If this WINFO-Artifact has a calculation trait. + if (calculationMode != null) { + if (calculationMode.equals("calc.discharge.longitudinal.section") + ) { + return getDischargeLongitudinalSectionData(); + } + else if (calculationMode.equals("calc.extreme.curve")) { + return (CalculationResult) + this.compute(context, ComputeType.ADVANCE, false); + } + else if (calculationMode.equals("calc.w.differences")) { + return (CalculationResult) + this.compute(context, ComputeType.ADVANCE, true); + } + else { + logger.warn("Unhandled calculation_mode " + calculationMode); + } } + // Otherwise get it from parameterization. River river = RiverUtils.getRiver(this); if (river == null) { return error(new WQKms[0], "no.river.selected"); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/WQKmsInterpolArtifact.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/WQKmsInterpolArtifact.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/WQKmsInterpolArtifact.java Thu Sep 12 10:13:09 2013 +0200 @@ -132,7 +132,15 @@ name = STATIC_WKMS_INTERPOL; } else { - name = STATIC_WQ; + // If all Qs are zero, add different facet to + // signalize that we want data to be drawn as marks + // on axis. + if (wstValueHasZeroQ()) { + name = STATIC_W_INTERPOL; + } + else { + name = STATIC_WQ; + } } Facet wQFacet = new WQFacet(name, @@ -204,23 +212,51 @@ } + /** True if Wst has only 'fake' (zero) Q-ranges. */ + private boolean wstValueHasZeroQ() { + WstValueTable table = getValueTable(); + return table.hasEmptyQ(); + } + + + /** Get the WstValueTable that matches parameterization. */ + private WstValueTable getValueTable() { + // Get WstValueTable + int wstId = getDataAsInt("wst_id"); + if (getDataAsString("col_pos") != null) { + return WstValueTableFactory.getWstColumnTable( + wstId, getDataAsInt("col_pos")); + } + else { + return WstValueTableFactory.getTable(wstId); + } + } + + + /** + * Get WQ Values at a certain km, interpolating only if distance + * between two stations is smaller than given distance. + */ + public double [][] getWQAtKm( + Double currentKm, + double maxKmInterpolDistance + ) { + // TODO yet to be implemented (issue1378). + return null; + } + + /** * Get WQ at a given km. + * * @param currentKm the requested km. If NULL, ld_location data * will be used. + * @return [[q1,q2,q2],[w1,w2,w3]] ... */ public double [][] getWQAtKm(Double currentKm) { - WstValueTable interpolator = null; - // Get WstValueTable - if (getDataAsString("col_pos") != null) { - interpolator = WstValueTableFactory.getWstColumnTable( - getDataAsInt("wst_id"), getDataAsInt("col_pos")); - } - else { - interpolator = WstValueTableFactory.getTable( - getDataAsInt("wst_id")); - } + // TODO issue1378: only interpolate if dist <= 100m + WstValueTable interpolator = getValueTable(); Double tmp = (currentKm != null) ? currentKm diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/access/FixAnalysisAccess.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/access/FixAnalysisAccess.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/access/FixAnalysisAccess.java Thu Sep 12 10:13:09 2013 +0200 @@ -33,6 +33,7 @@ super(artifact); } + /** Access the reference date period, return null in case of 'errors'. */ public DateRange getReferencePeriod() { if (referencePeriod == null) { StateData refStart = artifact.getData("ref_start"); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/access/RangeAccess.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/access/RangeAccess.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/access/RangeAccess.java Thu Sep 12 10:13:09 2013 +0200 @@ -111,6 +111,14 @@ return locations.toNativeArray(); } + public boolean hasFrom() { + return from != null || (from = getDouble("ld_from")) != null; + } + + public boolean hasTo() { + return to != null || (to = getDouble("ld_to")) != null; + } + /** Return ld_from data (in km). */ public double getFrom() { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/access/SQRelationAccess.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/access/SQRelationAccess.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/access/SQRelationAccess.java Thu Sep 12 10:13:09 2013 +0200 @@ -9,11 +9,13 @@ package org.dive4elements.river.artifacts.access; import java.util.Date; +import java.util.List; import org.apache.log4j.Logger; import org.dive4elements.river.artifacts.D4EArtifact; import org.dive4elements.river.artifacts.model.DateRange; +import org.dive4elements.river.model.MeasurementStation; public class SQRelationAccess extends RiverAccess @@ -28,6 +30,8 @@ private String method; + protected MeasurementStation measurementStation; + public SQRelationAccess() { } @@ -80,5 +84,30 @@ } return method; } + + public String getMeasurementStationName() { + MeasurementStation station = getMeasurementStation(); + return station == null ? null : station.getName(); + } + + public String getMeasurementStationGaugeName() { + MeasurementStation station = getMeasurementStation(); + return station == null ? null : station.getGaugeName(); + } + + public MeasurementStation getMeasurementStation() { + if (measurementStation != null) { + return measurementStation; + } + List candidates = MeasurementStation.getStationsAtKM( + getRiver(), getLocation()); + if (candidates != null) { + // Just take the first one as we only use the name + // and that "should" be unique at the location + measurementStation = candidates.get(0); + } + + return measurementStation; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/access/SedimentLoadAccess.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/access/SedimentLoadAccess.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/access/SedimentLoadAccess.java Thu Sep 12 10:13:09 2013 +0200 @@ -91,6 +91,7 @@ return null; } + /** Returns the selected unit (t/a or m3/a). */ public String getUnit () { if (unit == null) { unit = getString("unit"); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/context/RiverContextFactory.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/context/RiverContextFactory.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/context/RiverContextFactory.java Thu Sep 12 10:13:09 2013 +0200 @@ -93,6 +93,8 @@ private static final String XPATH_DGM_PATH = "/artifact-database/options/dgm-path/text()"; + private static GlobalContext GLOBAL_CONTEXT_INSTANCE; + /** * Creates a new D4EArtifactContext object and initialize all @@ -115,9 +117,17 @@ configureZoomScales(config, context); configureDGMPath(config, context); + synchronized (RiverContextFactory.class) { + GLOBAL_CONTEXT_INSTANCE = context; + } + return context; } + public static synchronized GlobalContext getGlobalContext() { + return GLOBAL_CONTEXT_INSTANCE; + } + private void configureDGMPath(Document config, RiverContext context) { String dgmPath = (String) XMLUtils.xpath( diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Datacage.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Datacage.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Datacage.java Thu Sep 12 10:13:09 2013 +0200 @@ -70,6 +70,7 @@ private String SQL_ARTIFACT_ID_NEXTVAL = "artifact.id.nextval"; private String SQL_INSERT_ARTIFACT = "insert.artifact"; private String SQL_ARTIFACT_DATA_ID_NEXTVAL = "artifact.data.id.nextval"; + private String SQL_UPDATE_ARTIFACT_STATE = "update.artifact.state"; private String SQL_INSERT_ARTIFACT_DATA = "insert.artifact.data"; private String SQL_OUT_ID_NEXTVALUE = "out.id.nextval"; private String SQL_INSERT_OUT = "insert.out"; @@ -382,6 +383,7 @@ SQL_INSERT_ARTIFACT = sql.get(SQL_INSERT_ARTIFACT); SQL_ARTIFACT_DATA_ID_NEXTVAL = sql.get(SQL_ARTIFACT_DATA_ID_NEXTVAL); SQL_INSERT_ARTIFACT_DATA = sql.get(SQL_INSERT_ARTIFACT_DATA); + SQL_UPDATE_ARTIFACT_STATE = sql.get(SQL_UPDATE_ARTIFACT_STATE); SQL_OUT_ID_NEXTVALUE = sql.get(SQL_OUT_ID_NEXTVALUE); SQL_INSERT_OUT = sql.get(SQL_INSERT_OUT); SQL_FACET_ID_NEXTVAL = sql.get(SQL_FACET_ID_NEXTVAL); @@ -401,6 +403,7 @@ sql.get(SQL_DELETE_ARTIFACT_BY_GID); } + /** Sum over facets in outs. */ protected static final int numFacets(List outs) { int sum = 0; for (Output out: outs) { @@ -608,6 +611,7 @@ // write new data storeData(res[0], flys); storeOuts(res[0], flys, context); + storeState(res[0], flys); } public void createdUser( @@ -884,9 +888,30 @@ } } + /** Update state of artifact. */ + protected void storeState( + final int artifactId, + final D4EArtifact artifact) { + SQLExecutor.Instance exec = sqlExecutor.new Instance() { + @Override + public boolean doIt() throws SQLException { + prepareStatement(SQL_UPDATE_ARTIFACT_STATE); + stmnt.setString(1, artifact.getCurrentStateId()); + stmnt.setInt(2, artifactId); + stmnt.execute(); + conn.commit(); + return true; + } + }; + + if (!exec.runWrite()) { + log.error("storing state of artifact failed ("+artifactId+","+artifact.getCurrentStateId()+")"); + } + } + protected void storeData( - final int artifactId, - D4EArtifact artifact + final int artifactId, + D4EArtifact artifact ) { final Collection data = artifact.getAllData(); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/DatacageBackendListener.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/DatacageBackendListener.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/DatacageBackendListener.java Thu Sep 12 10:13:09 2013 +0200 @@ -61,6 +61,7 @@ } } + /** Stores the artifact in artifact-db, if any. */ @Override public void storedArtifact(Artifact artifact, Backend backend) { log.debug("storedArtifact"); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Recommendations.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Recommendations.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Recommendations.java Thu Sep 12 10:13:09 2013 +0200 @@ -142,6 +142,7 @@ ) { parameters.put("CURRENT-STATE-ID", artifact.getCurrentStateId()); parameters.put("ARTIFACT-ID", artifact.identifier()); + parameters.put("ARTIFACT-NAME", artifact.getName()); for (StateData sd: artifact.getAllData()) { Object value = sd.getValue(); @@ -173,7 +174,7 @@ /** * Append recommendations to \param result. - * @param extraParameters parameters (typicall example: 'recommended') + * @param extraParameters parameters (typical example: 'recommended') */ public void recommend( D4EArtifact artifact, diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java Thu Sep 12 10:13:09 2013 +0200 @@ -10,10 +10,12 @@ import java.text.SimpleDateFormat; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; import java.util.HashMap; +import java.util.Set; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -25,6 +27,10 @@ import javax.xml.xpath.XPathFunctionResolver; import org.apache.log4j.Logger; +import org.dive4elements.artifactdatabase.transition.TransitionEngine; +import org.dive4elements.artifacts.GlobalContext; +import org.dive4elements.river.artifacts.context.RiverContext; +import org.dive4elements.river.artifacts.context.RiverContextFactory; /** Resolves functions (e.g. dc:contains) in Datacage/Meta-Data system. */ @@ -151,6 +157,19 @@ return StackFrames.NULL; } }); + + addFunction("all-state-successors", 2, new XPathFunction() { + @Override + public Object evaluate(List args) throws XPathFunctionException { + Object artifactName = args.get(0); + Object stateId = args.get(1); + + return artifactName instanceof String + && stateId instanceof String + ? allStateSuccessors((String)artifactName, (String)stateId) + : Collections.emptySet(); + } + }); } /** @@ -378,5 +397,18 @@ } return ""; } + + public Set allStateSuccessors(String artifactName, String stateId) { + GlobalContext gc = RiverContextFactory.getGlobalContext(); + if (gc == null) { + return Collections.emptySet(); + } + Object o = gc.get(RiverContext.TRANSITION_ENGINE_KEY); + if (o instanceof TransitionEngine) { + TransitionEngine te = (TransitionEngine)o; + return te.allRecursiveSuccessorStateIds(artifactName, stateId); + } + return Collections.emptySet(); + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/math/MovingAverage.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/math/MovingAverage.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/math/MovingAverage.java Thu Sep 12 10:13:09 2013 +0200 @@ -37,7 +37,11 @@ return new double [][] { xs, ys }; } - public static double[][] weighted(double[][] values, double radius) { + /** Build moving average over values. Weight them. */ + public static double[][] weighted( + double[][] values, + double radius + ) { TreeMap map = toMap(values); int N = map.size(); double [] xs = new double[N]; @@ -62,6 +66,7 @@ return new double [][] { xs, ys }; } + /** From [x1,x2][y1,y2] makes {x1:y1,x2:y2}. Sorted by x! */ private static TreeMap toMap(double[][] values) { TreeMap map = new TreeMap(); double [] xs = values[0]; diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/math/StdDevOutlier.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/math/StdDevOutlier.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/math/StdDevOutlier.java Thu Sep 12 10:13:09 2013 +0200 @@ -10,9 +10,13 @@ import java.util.List; -import org.apache.commons.math.stat.descriptive.moment.StandardDeviation; +import org.apache.log4j.Logger; -import org.apache.log4j.Logger; +/* XXX: + * Warning: This class is called StdDevOutlier because it caculates the + * Standard Deviation method for outlier removal as the BFG calls it. + * But the actual calculation used to remove the outliers calculates + * the Standard Error and not the Standard Deviation! */ public class StdDevOutlier { @@ -30,12 +34,12 @@ public static Integer findOutlier( List values, double factor, - double [] stdDevResult + double [] stdErrResult ) { boolean debug = log.isDebugEnabled(); if (debug) { - log.debug("factor for std dev: " + factor); + log.debug("factor for std dev test (that calculates std err): " + factor); } int N = values.size(); @@ -48,31 +52,34 @@ return null; } - StandardDeviation stdDev = new StandardDeviation(); - double maxValue = -Double.MAX_VALUE; int maxIndex = -1; + + double squareSumResiduals = 0; + for (Double db: values) { + squareSumResiduals += Math.pow(db, 2); + } + + double stdErr = Math.sqrt(squareSumResiduals / (N - 2)); + + double accepted = factor * stdErr; + for (int i = N-1; i >= 0; --i) { double value = Math.abs(values.get(i)); - stdDev.increment(value); if (value > maxValue) { maxValue = value; maxIndex = i; } } - double sd = stdDev.getResult(); - - double accepted = factor * sd; - if (debug) { - log.debug("std dev: " + stdDev); + log.debug("std err: " + stdErr); log.debug("accepted: " + accepted); log.debug("max value: " + maxValue); } - if (stdDevResult != null) { - stdDevResult[0] = sd; + if (stdErrResult != null) { + stdErrResult[0] = stdErr; } return maxValue > accepted ? maxIndex : null; diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation6.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation6.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation6.java Thu Sep 12 10:13:09 2013 +0200 @@ -37,6 +37,7 @@ private long [] timerange; private double [] values; private Long officialGaugeNumber; + private String riverName; public Calculation6(HistoricalDischargeAccess access) { @@ -45,6 +46,7 @@ double [] vs = mode != null && mode == EvaluationMode.W ? access.getWs() : access.getQs(); + riverName = access.getRiver(); Long officialGaugeNumber = access.getOfficialGaugeNumber(); @@ -98,7 +100,8 @@ return null; } - Gauge gauge = Gauge.getGaugeByOfficialNumber(officialGaugeNumber); + Gauge gauge = Gauge.getGaugeByOfficialNumber(officialGaugeNumber, + riverName); if (gauge == null) { // TODO: i18n return error("hist.discharge.gauge.not.found"); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/CrossSectionFactory.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/CrossSectionFactory.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/CrossSectionFactory.java Thu Sep 12 10:13:09 2013 +0200 @@ -59,30 +59,6 @@ } - /** - * True if the given section is the "newest" for that river. - * @param section Given section - * @return true if the section has the most advanced end of its validity interval - * or the most advanced start of its validity interval. - */ - public static boolean isNewest(CrossSection section) { - Session session = SessionHolder.HOLDER.get(); - Query query = session.createQuery( - "from CrossSection where river.id = :riverid " - + " order by timeInterval.stopTime desc, timeInterval.startTime desc"); - query.setParameter("riverid", section.getRiver().getId()); - - List result = query.list(); - - if (result == null || result.isEmpty()) { - return true; - } - else { - CrossSection cs = (CrossSection) result.get(0); - return section.getId().equals(cs.getId()); - } - } - /** * Get a specific CrossSection from db. diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java Thu Sep 12 10:13:09 2013 +0200 @@ -240,6 +240,7 @@ String STATIC_WQKMS_W = "other.wqkms.w"; String STATIC_WQKMS_Q = "other.wqkms.q"; String STATIC_WKMS_INTERPOL = "other.wkms.interpol"; + String STATIC_W_INTERPOL = "other.w.interpol"; String HEIGHTMARKS_POINTS = "heightmarks_points"; @@ -313,7 +314,7 @@ String SEDIMENT_LOAD_SUSP_SEDIMENT = "sedimentload.susp_sediment"; String SEDIMENT_LOAD_TOTAL = "sedimentload.total"; String SEDIMENT_LOAD_TOTAL_LOAD = "sedimentload.total_load"; - String SEDIMENT_LOAD_UNKOWN = "sedimentload.unknown"; + String SEDIMENT_LOAD_UNKNOWN = "sedimentload.unknown"; String SQ_OVERVIEW = "sq_overview"; diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/FixingsOverview.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FixingsOverview.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FixingsOverview.java Thu Sep 12 10:13:09 2013 +0200 @@ -28,8 +28,10 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.dive4elements.river.utils.BatchLoader; -/** Generate Fixings Table chart. */ + +/** Generate Fixings Table overview data structure to be stored in cache. */ public class FixingsOverview implements Serializable { @@ -56,39 +58,156 @@ "WHERE" + " river_id = :river_id AND kind = 2"; - /** All columns from given wst. */ - public static final String SQL_FIXING_COLUMNS = - "SELECT" + - " wc.id AS wst_column_id," + - " ti.start_time AS start_time," + - " wc.name AS name " + - "FROM wst_columns wc" + - " JOIN time_intervals ti ON wc.time_interval_id = ti.id " + - "WHERE" + - " wc.wst_id = :wst_id " + - "ORDER BY position"; + public static final String SQL_FIXING_COLUMNS_BATCH = + "SELECT " + + "wc.wst_id AS wst_id," + + "wc.id AS wst_column_id," + + "ti.start_time AS start_time," + + "wc.name AS name " + + "FROM wst_columns wc " + + "JOIN time_intervals ti ON wc.time_interval_id = ti.id " + + "WHERE " + + "wc.wst_id IN ($IDS) " + + "ORDER BY wc.wst_id, position"; - public static final String SQL_FIXING_COLUMN_Q_RANGES = - "SELECT" + - " wqr.q AS q," + - " r.a AS start_km," + - " r.b AS stop_km " + - "FROM wst_column_q_ranges wcqr" + - " JOIN wst_q_ranges wqr ON wcqr.wst_q_range_id = wqr.id" + - " JOIN ranges r ON wqr.range_id = r.id " + - "WHERE" + - " wcqr.wst_column_id = :column_id " + - "ORDER BY r.a"; + public static final String SQL_FIXING_COLUMN_Q_RANGES_BATCH = + "SELECT " + + "wcqr.wst_column_id AS wst_column_id," + + "wqr.q AS q," + + "r.a AS start_km," + + "r.b AS stop_km " + + "FROM wst_column_q_ranges wcqr " + + "JOIN wst_q_ranges wqr ON wcqr.wst_q_range_id = wqr.id " + + "JOIN ranges r ON wqr.range_id = r.id " + + "WHERE " + + "wcqr.wst_column_id IN ($IDS) " + + "ORDER BY wcqr.wst_column_id, r.a"; - public static final String SQL_FIXING_COLUMN_KM_RANGE = - "SELECT" + - " MIN(position) AS start_km," + - " MAX(position) AS stop_km " + - "FROM" + - " wst_column_values " + - "WHERE" + - " wst_column_id = :column_id"; + public static final String SQL_FIXING_COLUMN_KM_RANGE_BATCH = + "SELECT " + + "wst_column_id," + + "MIN(position) AS start_km," + + "MAX(position) AS stop_km " + + "FROM " + + "wst_column_values " + + "WHERE " + + "wst_column_id IN ($IDS) " + + "GROUP BY wst_column_id"; + public static final class KMRangeLoader extends BatchLoader { + + public KMRangeLoader(List columns, Session session) { + super(columns, session, SQL_FIXING_COLUMN_KM_RANGE_BATCH); + } + + @Override + protected void fill(SQLQuery query) { + query + .addScalar("wst_column_id", StandardBasicTypes.INTEGER) + .addScalar("start_km", StandardBasicTypes.DOUBLE) + .addScalar("stop_km", StandardBasicTypes.DOUBLE); + + List ranges = query.list(); + for (Object [] r: ranges) { + Integer cid = (Integer)r[0]; + double [] vs = new double [] { (Double)r[1], (Double)r[2] }; + cache(cid, vs); + } + } + } // class KMRangeLoader + + public static final class ColumnQRangeLoader + extends BatchLoader> + { + public ColumnQRangeLoader(List columns, Session session) { + super(columns, session, SQL_FIXING_COLUMN_Q_RANGES_BATCH); + } + + @Override + protected void fill(SQLQuery query) { + query + .addScalar("wst_column_id", StandardBasicTypes.INTEGER) + .addScalar("q", StandardBasicTypes.DOUBLE) + .addScalar("start_km", StandardBasicTypes.DOUBLE) + .addScalar("stop_km", StandardBasicTypes.DOUBLE); + + int lastId = Integer.MIN_VALUE; + List column = new ArrayList(); + + List ranges = query.list(); + for (Object [] r: ranges) { + int cid = (Integer)r[0]; + + if (cid != lastId && !column.isEmpty()) { + cache(lastId, column); + column = new ArrayList(); + } + column.add(new double [] { + (Double)r[1], + (Double)r[2], + (Double)r[3] + }); + + lastId = cid; + } + + if (!column.isEmpty()) { + cache(lastId, column); + } + } + } // class ColumnQRangeLoader + + /** Helper class to store data from batching fixing columns. */ + private static final class FixColumn { + int columnId; + Date startTime; + String name; + + FixColumn(int columnId, Date startTime, String name) { + this.columnId = columnId; + this.startTime = startTime; + this.name = name; + } + } // class FixColumn + + public static final class FixColumnLoader + extends BatchLoader> + { + public FixColumnLoader(List columns, Session session) { + super(columns, session, SQL_FIXING_COLUMNS_BATCH); + } + + @Override + protected void fill(SQLQuery query) { + query + .addScalar("wst_id", StandardBasicTypes.INTEGER) + .addScalar("wst_column_id", StandardBasicTypes.INTEGER) + .addScalar("start_time", StandardBasicTypes.TIMESTAMP) + .addScalar("name", StandardBasicTypes.STRING); + + int lastId = Integer.MIN_VALUE; + List cols = new ArrayList(); + + List columns = query.list(); + for (Object [] c: columns) { + int wid = (Integer)c[0]; + + if (wid != lastId && !cols.isEmpty()) { + cache(lastId, cols); + cols = new ArrayList(); + } + cols.add(new FixColumn( + (Integer)c[1], + (Date) c[2], + (String) c[3])); + + lastId = wid; + } + if (!cols.isEmpty()) { + cache(lastId, cols); + } + } + } // class FixColumnLoader public static class QRange extends Range { @@ -255,34 +374,35 @@ } // for all Q ranges } - public void loadKmRange(SQLQuery query) { - query.setInteger("column_id", columnId); - - List kms = query.list(); + public void loadKmRange(KMRangeLoader loader) { - if (kms.isEmpty()) { + double [] range = loader.get(columnId); + + if (range == null) { log.warn("No km range for column " + columnId + "."); + return; } - else { - Object [] obj = kms.get(0); - start = (Double)obj[0]; - end = (Double)obj[1]; - } + start = range[0]; + end = range[1]; } public void loadQRanges( - SQLQuery query, - GaugeFinder gaugeFinder + ColumnQRangeLoader loader, + GaugeFinder gaugeFinder ) { - query.setInteger("column_id", columnId); - List list = query.list(); + List qrs = loader.get(columnId); + if (qrs == null) { + log.warn("No q ranges found for column " + columnId); + return; + } - List qRanges = new ArrayList(list.size()); + List qRanges = new ArrayList(qrs.size()); - for (Object [] row: list) { - double q = (Double)row[0]; - double start = (Double)row[1]; - double end = (Double)row[2]; + for (double [] qr: qrs) { + double q = qr[0]; + double start = qr[1]; + double end = qr[2]; + QRange qRange = new QRange(start, end, q); if (qRange.clip(this)) { qRanges.add(qRange); @@ -314,20 +434,26 @@ columns = new ArrayList(); } - public void loadColumns(SQLQuery query) { - query.setInteger("wst_id", wstId); - List list = query.list(); - for (Object [] row: list) { - int columnId = (Integer)row[0]; - Date startTime = (Date) row[1]; - String name = (String) row[2]; - columns.add(new Column(columnId, startTime, name)); + public void allColumnIds(List cIds) { + for (Column column: columns) { + cIds.add(column.columnId); } } - public void loadColumnsKmRange(SQLQuery query) { + public void loadColumns(FixColumnLoader loader) { + List fcs = loader.get(wstId); + if (fcs == null) { + log.warn("No columns for wst " + wstId); + return; + } + for (FixColumn fc: fcs) { + columns.add(new Column(fc.columnId, fc.startTime, fc.name)); + } + } + + public void loadColumnsKmRange(KMRangeLoader loader) { for (Column column: columns) { - column.loadKmRange(query); + column.loadKmRange(loader); } } @@ -338,11 +464,11 @@ } public void loadColumnsQRanges( - SQLQuery query, - GaugeFinder gaugeFinder + ColumnQRangeLoader loader, + GaugeFinder gaugeFinder ) { for (Column column: columns) { - column.loadQRanges(query, gaugeFinder); + column.loadQRanges(loader, gaugeFinder); } } @@ -427,23 +553,40 @@ } protected void loadFixingsColumns(Session session) { - SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMNS) - .addScalar("wst_column_id", StandardBasicTypes.INTEGER) - .addScalar("start_time", StandardBasicTypes.DATE) - .addScalar("name", StandardBasicTypes.STRING); + + FixColumnLoader loader = new FixColumnLoader( + allFixingIds(), + session); for (Fixing fixing: fixings) { - fixing.loadColumns(query); + fixing.loadColumns(loader); } } + protected List allFixingIds() { + List ids = new ArrayList(fixings.size()); + for (Fixing fixing: fixings) { + ids.add(fixing.getId()); + } + return ids; + } + + protected List allColumnIds() { + List cIds = new ArrayList(); + for (Fixing fixing: fixings) { + fixing.allColumnIds(cIds); + } + return cIds; + } + protected void loadFixingsColumnsKmRange(Session session) { - SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMN_KM_RANGE) - .addScalar("start_km", StandardBasicTypes.DOUBLE) - .addScalar("stop_km", StandardBasicTypes.DOUBLE); + + KMRangeLoader loader = new KMRangeLoader( + allColumnIds(), + session); for (Fixing fixing: fixings) { - fixing.loadColumnsKmRange(query); + fixing.loadColumnsKmRange(loader); } } @@ -451,13 +594,13 @@ Session session, GaugeFinder gaugeFinder ) { - SQLQuery query = session.createSQLQuery(SQL_FIXING_COLUMN_Q_RANGES) - .addScalar("q", StandardBasicTypes.DOUBLE) - .addScalar("start_km", StandardBasicTypes.DOUBLE) - .addScalar("stop_km", StandardBasicTypes.DOUBLE); + + ColumnQRangeLoader loader = new ColumnQRangeLoader( + allColumnIds(), + session); for (Fixing fixing: fixings) { - fixing.loadColumnsQRanges(query, gaugeFinder); + fixing.loadColumnsQRanges(loader, gaugeFinder); } } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesQFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesQFacet.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesQFacet.java Thu Sep 12 10:13:09 2013 +0200 @@ -25,6 +25,7 @@ import org.dive4elements.river.jfree.StickyAxisAnnotation; import org.dive4elements.river.exports.DurationCurveGenerator; +import org.dive4elements.river.exports.fixings.FixChartGenerator; /** @@ -89,7 +90,8 @@ * Returns the data this facet requires. * * @param artifact the owner artifact. - * @param context the CallContext (ignored). + * @param context the CallContext (can be used to find out if in + * navigable fixation-setting, or durationcurve). * * @return the data. */ @@ -105,6 +107,15 @@ getDataProvider(DurationCurveFacet.BB_DURATIONCURVE); if (providers.size() < 1) { logger.warn("Could not find durationcurve data provider."); + // Do we have a current km in context? + // If so, we are likely fetching data for a navigable + // diagram (i.e. in fixation branch). + if (context.getContextValue(FixChartGenerator.CURRENT_KM) != null) { + Double ckm = (Double) context.getContextValue(FixChartGenerator.CURRENT_KM); + // Return linearly interpolated values, in m if not at gauge, + // in cm if at gauge. + qs = mvArtifact.getMainValuesQ(new double[] {ckm}); + } } else { wqdays = (WQDay) providers.get(0).provideData( @@ -117,6 +128,10 @@ StickyAxisAnnotation annotation = null; if (this.name.equals(DURATION_MAINVALUES_Q)) { for (NamedDouble q: qs) { + if (Double.isNaN(q.getValue())) { + logger.warn("NaN MainValue " + q.getName()); + continue; + } annotation = new StickyAxisAnnotation( q.getName(), @@ -131,6 +146,10 @@ } else { for (NamedDouble q: qs) { + if (Double.isNaN(q.getValue())) { + logger.warn("NaN MainValue " + q.getName()); + continue; + } annotation = new StickyAxisAnnotation( q.getName(), diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesWFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesWFacet.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/MainValuesWFacet.java Thu Sep 12 10:13:09 2013 +0200 @@ -23,6 +23,7 @@ import org.dive4elements.river.artifacts.math.Linear; import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StickyAxisAnnotation; +import org.dive4elements.river.exports.fixings.FixChartGenerator; /** @@ -85,7 +86,8 @@ * Returns the data this facet provides. * * @param artifact the owner artifact. - * @param context the CallContext (ignored). + * @param context the CallContext (can be used to find out if in + * navigable fixation-setting, or durationcurve). * * @return the data. */ @@ -102,6 +104,15 @@ getDataProvider(DurationCurveFacet.BB_DURATIONCURVE); if (providers.size() < 1) { logger.warn("Could not find durationcurve data provider."); + // Do we have a current km in context? + // If so, we are likely fetching data for a navigable + // diagram (i.e. in fixation branch). + if (context.getContextValue(FixChartGenerator.CURRENT_KM) != null) { + Double ckm = (Double) context.getContextValue(FixChartGenerator.CURRENT_KM); + // Return linearly interpolated values, in m if not at gauge, + // in cm over datum if at gauge. + ws = mvArtifact.getMainValuesW(new double[] {ckm}); + } } else { wqdays = (WQDay) providers.get(0).provideData( @@ -111,6 +122,11 @@ } for (NamedDouble w: ws) { + logger.debug("W Annotation at " + w.getValue() + " ("+w.getName()+")"+ wqdays); + if (Double.isNaN(w.getValue())) { + logger.warn("NaN MainValue " + w.getName()); + continue; + } StickyAxisAnnotation annotation = new StickyAxisAnnotation( w.getName(), diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/ManagedFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/ManagedFacet.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/ManagedFacet.java Thu Sep 12 10:13:09 2013 +0200 @@ -16,7 +16,7 @@ import org.dive4elements.artifactdatabase.state.Facet; import org.dive4elements.artifacts.ArtifactNamespaceContext; import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; - +import org.dive4elements.river.utils.CompareUtil; /** * Facet with user-supplied theme-control-information (pos in list, @@ -140,5 +140,24 @@ return 0; } } + + /** + * Returns true if the other is likely the same facet. + * This happens if a facet is defined for two outs. + */ + public boolean isSame(Object other) { + if (!(other instanceof ManagedFacet)) { + return false; + } + ManagedFacet otherFacet = (ManagedFacet) other; + return this.getVisible() == otherFacet.getVisible() && + this.getActive() == otherFacet.getActive() && + CompareUtil.areSame(this.getArtifact(), otherFacet.getArtifact()) && + this.getIndex() == otherFacet.getIndex() && + CompareUtil.areSame(this.getName(), otherFacet.getName()) && + CompareUtil.areSame(this.getBoundToOut(), otherFacet.getBoundToOut()) && + CompareUtil.areSame(this.getDescription(), otherFacet.getDescription()); + // Missing properties are blackboard, data, position. + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/OfficialLineFinder.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/OfficialLineFinder.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/OfficialLineFinder.java Thu Sep 12 10:13:09 2013 +0200 @@ -114,7 +114,9 @@ " wstId: " + wstId + " pos: " + columnPos + " source: " + source + - " date: " + date +"]"; + " date: " + date + + " from: " + start + + " to: " + end + "]"; } } @@ -168,9 +170,8 @@ NamedMainValue tnmv = mainValue.getMainValue(); if (tnmv.getId().equals(mnvId)) { // found gauge with this main value - double from = gauge.getRange().getA().doubleValue(); - double to = gauge.getRange().getA().doubleValue(); + double to = gauge.getRange().getB().doubleValue(); double value = mainValue.getValue().doubleValue(); int wstId = wst.getId(); int pos = wc.getPosition(); @@ -273,6 +274,18 @@ return list; } + private static List filterByQValues(double[] values, List ranges) { + List list = new ArrayList(ranges.size()); + for (ValueRange r: ranges) { + for (double val: values) { + if (r.sameValue(val) && !list.contains(r)) { + list.add(r); + } + } + } + return list; + } + private static boolean isQ(D4EArtifact artifact) { Boolean b = artifact.getDataAsBoolean("wq_isq"); return b != null && b; @@ -285,25 +298,23 @@ public static final Range Q_OUT_OF_RANGE = new Range(-10000, -9999); - private static Range singleQs(D4EArtifact artifact) { + private static double[] singleQs(D4EArtifact artifact) { String singleData = nn(artifact.getDataAsString("wq_single")); - double min = Double.MAX_VALUE; - double max = -Double.MAX_VALUE; + String[] values = singleData.split(" "); + double[] ret = new double[values.length]; + int i = 0; - for (String value: singleData.split(" ")) { + for (String value: values) { try { - double x = Double.parseDouble(value); - if (x < min) min = x; - if (x > max) max = x; + ret[i] = Double.parseDouble(value); } catch (NumberFormatException nfe) { + ret[i] = -1; // INVALID_Q_VALUE } + i++; } - return min == Double.MAX_VALUE - ? Q_OUT_OF_RANGE - : new Range(min, max); - + return ret; } private static Range qRange(D4EArtifact artifact) { @@ -382,21 +393,20 @@ return Collections.emptyList(); } - Range qRange = isRange(artifact) - ? qRange(artifact) - : singleQs(artifact); - - if (qRange == Q_OUT_OF_RANGE) { - qRange = tripleQRange(artifact); + if (isRange(artifact)) { + Range qRange = qRange(artifact); + if (qRange == Q_OUT_OF_RANGE) { + qRange = tripleQRange(artifact); + } + ranges = filterByQRange(qRange, ranges); + if (debug) { + log.debug("Q range filter: " + qRange); + } + } else { + ranges = filterByQValues(singleQs(artifact), ranges); } if (debug) { - log.debug("Q range filter: " + qRange); - } - - ranges = filterByQRange(qRange, ranges); - - if (debug) { log.debug("After q range filter: " + ranges); } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/QRangeTree.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/QRangeTree.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/QRangeTree.java Thu Sep 12 10:13:09 2013 +0200 @@ -297,6 +297,7 @@ return max; } + /** @param pos the station (km). */ public double findQ(double pos) { return root != null ? root.findQ(pos) : Double.NaN; } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKms.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKms.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKms.java Thu Sep 12 10:13:09 2013 +0200 @@ -143,5 +143,15 @@ double to = getKm(size()-1); return from + " - " + to; } + + /** + * Returns an array of two double values the first and last kilometer. + * + * @return a double array with the first and last km + */ + public double[] getFirstLastKM() { + /* Behold the first km might be larger then the last! */ + return new double[] {getKm(0), getKm(size()-1)}; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKmsResult.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKmsResult.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WQKmsResult.java Thu Sep 12 10:13:09 2013 +0200 @@ -12,4 +12,4 @@ public interface WQKmsResult { public WQKms[] getWQKms(); } - +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTable.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTable.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/WstValueTable.java Thu Sep 12 10:13:09 2013 +0200 @@ -850,6 +850,12 @@ q, referenceKm, kms, ws, qs, 0, kms.length, errors); } + /** + * Interpolate Q at given positions. + * @param kms positions for which to calculate qs and ws + * @param ws [out] calculated ws for kms + * @param qs [out] looked up qs for kms. + */ public QPosition interpolate( double q, double referenceKm, @@ -1269,6 +1275,27 @@ } + /** True if no QRange is given or Q equals zero. */ + public boolean hasEmptyQ() { + for (Column column: columns) { + if (column.getQRangeTree() == null) { + return true; + } + else { + if (Math.abs(column.getQRangeTree().maxQ()) <= 0.01d) { + return true; + } + } + } + + if (columns.length == 0) { + log.warn("No columns in WstValueTable."); + } + + return false; + } + + /** Find ranges that are between km1 and km2 (inclusive?) */ public List findSegments(double km1, double km2) { return columns.length != 0 diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/DateUniqueMaker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/DateUniqueMaker.java Thu Sep 12 10:13:09 2013 +0200 @@ -0,0 +1,41 @@ +package org.dive4elements.river.artifacts.model.fixings; + +import java.util.Date; + +import gnu.trove.TIntObjectHashMap; +import gnu.trove.TLongHashSet; + +public class DateUniqueMaker { + + private TLongHashSet times; + private TIntObjectHashMap already; + + public DateUniqueMaker() { + times = new TLongHashSet(); + already = new TIntObjectHashMap(); + } + + public void makeUnique(T t) { + + // Map same index to same new value + if (already.containsKey(t.index)) { + t.date = (Date)already.get(t.index); + return; + } + long time = t.date.getTime(); + if (!times.add(time)) { // same found before + do { + time += 30L*1000L; // Add 30secs + } + while (!times.add(time)); + Date newDate = new Date(time); + already.put(t.index, newDate); + // Write back modified time. + t.date = newDate; + } + else { + // register as seen. + already.put(t.index, t.date); + } + } +} diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/Fitting.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/Fitting.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/Fitting.java Thu Sep 12 10:13:09 2013 +0200 @@ -121,8 +121,9 @@ double maxQ = -Double.MAX_VALUE; if (referenced != null) { for (QWI qw: referenced) { - if (qw.getQ() > maxQ) { - maxQ = qw.getQ(); + double q = qw.getQ(); + if (q > maxQ) { + maxQ = q; } } } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisCalculation.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisCalculation.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisCalculation.java Thu Sep 12 10:13:09 2013 +0200 @@ -101,6 +101,15 @@ fitResult.getOutliers(), analysisPeriods); + // Workaraound to deal with same dates in data set + far.makeReferenceEventsDatesUnique(); + far.remapReferenceIndicesToRank(); + + far.makeAnalysisEventsUnique(); + for (int i = 0; i < this.analysisPeriods.length; ++i) { + far.remapAnalysisEventsIndicesToRank(i); + } + return new CalculationResult(far, this); } @@ -172,7 +181,7 @@ ArrayList allQWDs = new ArrayList(); // for all Q sectors. - for (int qSector = qSectorStart; qSector < qSectorEnd; ++qSector) { + for (int qSector = qSectorStart; qSector <= qSectorEnd; ++qSector) { Filter filter = new AndFilter() .add(kmFilter) @@ -289,6 +298,7 @@ return results; } + /** Returns the mapped value of colIdx or the size of the hashmap. */ private static final int getIndex(TIntIntHashMap map, int colIdx) { if (map.containsKey(colIdx)) { return map.get(colIdx); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisEventsFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisEventsFacet.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisEventsFacet.java Thu Sep 12 10:13:09 2013 +0200 @@ -64,48 +64,47 @@ public Object getData(Artifact artifact, CallContext context) { logger.debug("FixAnalysisEventsFacet.getData"); - if (artifact instanceof D4EArtifact) { - D4EArtifact flys = (D4EArtifact)artifact; - - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - FixAnalysisResult result = (FixAnalysisResult) res.getData(); - double currentKm = getCurrentKm(context); - - KMIndex kmPeriods = result.getAnalysisPeriods(); - KMIndex.Entry kmPeriodsEntry = - kmPeriods.binarySearch(currentKm); - - if(kmPeriodsEntry == null) { - logger.debug("getData: kmPeriodsEntry == null"); - return null; - } - - AnalysisPeriod[] periods = kmPeriodsEntry.getValue(); - if (periods == null) { - logger.debug("getData: periods == null"); - return null; - } - int ndx = index >> 8; - QWD[] qwdData = periods[ndx].getQWDs(); - if (qwdData == null) { - return null; - } - int ndy = index & 255; - for (int i = 0; i < qwdData.length; i++) { - if (qwdData[i].getIndex() == ndy) { - return qwdData[i]; - } - } - return null; - } - else { + if (!(artifact instanceof D4EArtifact)) { logger.debug("Not an instance of FixationArtifact."); return null; } + D4EArtifact flys = (D4EArtifact)artifact; + + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + FixAnalysisResult result = (FixAnalysisResult) res.getData(); + double currentKm = getCurrentKm(context); + + KMIndex kmPeriods = result.getAnalysisPeriods(); + KMIndex.Entry kmPeriodsEntry = + kmPeriods.binarySearch(currentKm); + + if (kmPeriodsEntry == null) { + logger.debug("getData: kmPeriodsEntry == null"); + return null; + } + + AnalysisPeriod[] periods = kmPeriodsEntry.getValue(); + if (periods == null) { + logger.debug("getData: periods == null"); + return null; + } + int ndx = index >> 8; + QWD[] qwdData = periods[ndx].getQWDs(); + if (qwdData == null) { + return null; + } + int ndy = index & 255; + + for (QWD qwd: qwdData) { + if (qwd.getIndex() == ndy) { + return qwd; + } + } + return null; } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisResult.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisResult.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixAnalysisResult.java Thu Sep 12 10:13:09 2013 +0200 @@ -10,8 +10,10 @@ import java.util.Collection; import java.util.Date; +import java.util.TreeMap; import java.util.TreeSet; +import org.apache.log4j.Logger; import org.dive4elements.river.artifacts.model.Parameters; import org.dive4elements.river.utils.KMIndex; @@ -19,6 +21,9 @@ public class FixAnalysisResult extends FixResult { + private static Logger log = + Logger.getLogger(FixAnalysisResult.class); + protected KMIndex analysisPeriods; public FixAnalysisResult() { @@ -49,31 +54,65 @@ return result; } - public Collection getReferenceEventsDates() { - TreeSet dates = new TreeSet(); - for (KMIndex.Entry entry: referenced) { - QWD [] values = entry.getValue(); - for (int i = 0; i < values.length; i++) { - dates.add(values[i].date); + + public void makeAnalysisEventsUnique() { + // Actually it would be enough to make dates + // unique in one analysis period but to simplify things + // we make them unique in all periods. + DateUniqueMaker dum = new DateUniqueMaker(); + for (KMIndex.Entry entry: analysisPeriods) { + for (AnalysisPeriod ap: entry.getValue()) { + QWD [] qwds = ap.getQWDs(); + if (qwds != null) { + for (QWD qwd: qwds) { + dum.makeUnique(qwd); + } + } } } - return dates; } public Collection getAnalysisEventsDates(int analysisPeriod) { TreeSet dates = new TreeSet(); for (KMIndex.Entry entry: analysisPeriods) { QWD [] qwds = entry.getValue()[analysisPeriod].getQWDs(); - if (qwds == null) { - continue; - } - for (int i = 0; i < qwds.length; i++) { - dates.add(qwds[i].date); + if (qwds != null) { + for (QWD qwd: qwds) { + dates.add(qwd.date); + } } } return dates; } + public Collection getAnalysisEventsIndices(int analysisPeriod) { + TreeMap dates = new TreeMap(); + for (KMIndex.Entry entry: analysisPeriods) { + QWD [] qwds = entry.getValue()[analysisPeriod].getQWDs(); + if (qwds != null) { + for (QWD qwd: qwds) { + dates.put(qwd.date, qwd.index); + } + } + } + return dates.values(); + } + + public void remapAnalysisEventsIndicesToRank(int analysisPeriod) { + RankRemapper remapper = new RankRemapper(); + for (Integer index: getAnalysisEventsIndices(analysisPeriod)) { + remapper.toMap(index); + } + for (KMIndex.Entry entry: analysisPeriods) { + QWD [] qwds = entry.getValue()[analysisPeriod].getQWDs(); + if (qwds != null) { + for (QWD qwd: qwds) { + remapper.remap(qwd); + } + } + } + } + public KMIndex getAnalysisPeriods() { return analysisPeriods; } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixCalculation.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixCalculation.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixCalculation.java Thu Sep 12 10:13:09 2013 +0200 @@ -114,6 +114,10 @@ return index; } + public int getId() { + return meta.getId(); + } + public boolean getQW( double km, double [] qs, @@ -313,7 +317,7 @@ column.getDate(), interpolated[i], 0d, - column.getIndex()); + column.getId()); // Use database id here } } log.warn("cannot find column for (" + q + ", " + w + ")"); @@ -364,7 +368,9 @@ continue; } - referenced.add(km, fitting.referencedToArray()); + QWD [] refs = fitting.referencedToArray(); + + referenced.add(km, refs); if (fitting.hasOutliers()) { outliers.add(km, fitting.outliersToArray()); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixReferenceEventsFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixReferenceEventsFacet.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixReferenceEventsFacet.java Thu Sep 12 10:13:09 2013 +0200 @@ -61,38 +61,36 @@ public Object getData(Artifact artifact, CallContext context) { logger.debug("FixReferenceEventsFacet.getData"); - if (artifact instanceof D4EArtifact) { - D4EArtifact flys = (D4EArtifact)artifact; - - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - FixResult result = (FixResult) res.getData(); - double currentKm = getCurrentKm(context); - - logger.debug("current km in FRE: " + currentKm); - - KMIndex kmQWs = result.getReferenced(); - KMIndex.Entry kmQWsEntry = kmQWs.binarySearch(currentKm); - QWD[] qwds = null; - if (kmQWsEntry != null) { - int ndx = index & 255; - qwds = kmQWsEntry.getValue(); - for (int i = 0; i < qwds.length; i++) { - if (qwds[i].getIndex() == ndx) { - return qwds[i]; - } - } - return null; - } - return null; - } - else { + if (!(artifact instanceof D4EArtifact)) { logger.debug("Not an instance of FixationArtifact."); return null; } + + D4EArtifact flys = (D4EArtifact)artifact; + + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + FixResult result = (FixResult) res.getData(); + double currentKm = getCurrentKm(context); + + if (logger.isDebugEnabled()) { + logger.debug("current km in FRE: " + currentKm); + } + + KMIndex kmQWs = result.getReferenced(); + KMIndex.Entry kmQWsEntry = kmQWs.binarySearch(currentKm); + if (kmQWsEntry != null) { + int ndx = index & 255; + for (QWD qwd: kmQWsEntry.getValue()) { + if (qwd.getIndex() == ndx) { + return qwd; + } + } + } + return null; } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixResult.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixResult.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixResult.java Thu Sep 12 10:13:09 2013 +0200 @@ -8,15 +8,23 @@ package org.dive4elements.river.artifacts.model.fixings; +import org.apache.log4j.Logger; import org.dive4elements.river.artifacts.model.Parameters; import org.dive4elements.river.utils.KMIndex; import java.io.Serializable; +import java.util.Collection; +import java.util.Date; +import java.util.TreeMap; +import java.util.TreeSet; public class FixResult implements Serializable { + private static Logger log = + Logger.getLogger(FixResult.class); + protected Parameters parameters; protected KMIndex referenced; protected KMIndex outliers; @@ -42,6 +50,48 @@ this.referenced = referenced; } + public void makeReferenceEventsDatesUnique() { + DateUniqueMaker dum = new DateUniqueMaker(); + for (KMIndex.Entry entry: referenced) { + for (QWD ref: entry.getValue()) { + dum.makeUnique(ref); + } + } + } + + public Collection getReferenceEventsIndices() { + TreeMap dates = new TreeMap(); + for (KMIndex.Entry entry: referenced) { + for (QWD value: entry.getValue()) { + dates.put(value.date, value.index); + } + } + return dates.values(); + } + + public void remapReferenceIndicesToRank() { + RankRemapper remapper = new RankRemapper(); + for (Integer idx: getReferenceEventsIndices()) { + remapper.toMap(idx); + } + for (KMIndex.Entry entry: referenced) { + for (QWD value: entry.getValue()) { + remapper.remap(value); + } + } + } + + public Collection getReferenceEventsDates() { + TreeSet dates = new TreeSet(); + for (KMIndex.Entry entry: referenced) { + for (QWD qwd: entry.getValue()) { + dates.add(qwd.date); + } + } + return dates; + } + + public KMIndex getOutliers() { return outliers; } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixWQCurveFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixWQCurveFacet.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/FixWQCurveFacet.java Thu Sep 12 10:13:09 2013 +0200 @@ -66,57 +66,57 @@ */ @Override public Object getData(Artifact artifact, CallContext context) { - logger.debug("getData"); - if (artifact instanceof D4EArtifact) { - D4EArtifact flys = (D4EArtifact)artifact; - FixAnalysisAccess access = new FixAnalysisAccess(flys); - - CalculationResult res = - (CalculationResult) flys.compute(context, - ComputeType.ADVANCE, - false); - - FixResult result = (FixResult) res.getData(); - double currentKm = getCurrentKm(context); - - logger.debug("getData: km = " + currentKm); - - String function = access.getFunction(); - Function ff = FunctionFactory.getInstance().getFunction(function); - - if (ff == null) { - logger.warn("getData: ff == null"); - return null; - } - Parameters params = result.getParameters(); - String[] paramNames = ff.getParameterNames(); - - double [] coeffs = params.interpolate("km", currentKm, paramNames); - - if (coeffs == null) { - logger.warn("getData: coeffs == null"); - return null; - } - - org.dive4elements.river.artifacts.math.Function mf = - ff.instantiate(coeffs); - - double maxQ = FixFacetUtils.getMaxQ(params, currentKm); - logger.debug("getData: maxQ = " + maxQ); - - FixFunction fix = new FixFunction( - ff.getName(), - ff.getDescription(), - mf, - maxQ); - - return fix; - } - else { + logger.debug("getData"); + if (!(artifact instanceof D4EArtifact)) { logger.debug("Not an instance of D4EArtifact / FixationArtifact."); return null; } + + D4EArtifact flys = (D4EArtifact)artifact; + FixAnalysisAccess access = new FixAnalysisAccess(flys); + + CalculationResult res = + (CalculationResult) flys.compute(context, + ComputeType.ADVANCE, + false); + + FixResult result = (FixResult) res.getData(); + double currentKm = getCurrentKm(context); + + logger.debug("getData: km = " + currentKm); + + String function = access.getFunction(); + Function ff = FunctionFactory.getInstance().getFunction(function); + + if (ff == null) { + logger.warn("getData: ff == null"); + return null; + } + + Parameters params = result.getParameters(); + String[] paramNames = ff.getParameterNames(); + + double [] coeffs = params.interpolate("km", currentKm, paramNames); + + if (coeffs == null) { + logger.warn("getData: coeffs == null"); + return null; + } + + org.dive4elements.river.artifacts.math.Function mf = + ff.instantiate(coeffs); + + double maxQ = FixFacetUtils.getMaxQ(params, currentKm); + logger.debug("getData: maxQ = " + maxQ); + + FixFunction fix = new FixFunction( + ff.getName(), + ff.getDescription(), + mf, + maxQ); + + return fix; } /** diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/RankRemapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/RankRemapper.java Thu Sep 12 10:13:09 2013 +0200 @@ -0,0 +1,44 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.artifacts.model.fixings; + +import java.util.IdentityHashMap; + +import org.apache.log4j.Logger; + +import gnu.trove.TIntIntHashMap; + +public class RankRemapper { + + private static Logger log = Logger.getLogger(RankRemapper.class); + + private TIntIntHashMap index2rank; + private IdentityHashMap visited; + + public RankRemapper() { + index2rank = new TIntIntHashMap(); + visited = new IdentityHashMap(); + } + + public void toMap(int index) { + index2rank.put(index, index2rank.size()); + } + + public void remap(I qwi) { + if (!visited.containsKey(qwi)) { + int idx = qwi.index; + if (index2rank.containsKey(idx)) { + qwi.index = index2rank.get(idx); + } else if (log.isDebugEnabled()) { + log.debug("Cannot remap " + idx); + } + visited.put(qwi, true); + } + } +} diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffCalculation.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffCalculation.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffCalculation.java Thu Sep 12 10:13:09 2013 +0200 @@ -18,7 +18,10 @@ import org.dive4elements.river.artifacts.model.Calculation; import org.dive4elements.river.artifacts.model.CalculationResult; - +/** + * Perform calculation of differences of bed height (german Sohlhoehe). + * The input are either single year data or epochs. + */ public class BedDiffCalculation extends Calculation { @@ -84,6 +87,7 @@ */ } + /** Get two BedHeights from factory. */ private static BedHeight [] getHeightPair(int [] ids, String type) { return new BedHeight [] { BedHeightFactory.getHeight(type, ids[0], 0), @@ -176,3 +180,4 @@ s2.getName()); } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffYearResult.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffYearResult.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedDiffYearResult.java Thu Sep 12 10:13:09 2013 +0200 @@ -11,10 +11,10 @@ import gnu.trove.TDoubleArrayList; +/** Result of a bed diff year calculation. */ public class BedDiffYearResult extends BedDifferencesResult { - protected TDoubleArrayList bedHeights; protected TDoubleArrayList dataGap; protected TDoubleArrayList morphWidth; @@ -115,3 +115,4 @@ }; } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightFactory.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightFactory.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/BedHeightFactory.java Thu Sep 12 10:13:09 2013 +0200 @@ -24,6 +24,8 @@ import org.dive4elements.river.artifacts.model.StaticBedHeightCacheKey; import org.dive4elements.river.backend.SessionHolder; + +/** Create BedHeights from database. */ public class BedHeightFactory { /** Private logger to use here. */ private static Logger log = Logger.getLogger(BedHeightFactory.class); @@ -62,7 +64,7 @@ /** - * Get WKms for given column and wst_id, caring about the cache. + * Get BedHeight for given type and height_id, caring about the cache. */ public static BedHeight getHeight(String type, int height_id, int time) { log.debug("BedHeightFactory.getHeight"); @@ -92,7 +94,7 @@ return values; } - /** Get name for a WKms. */ + /** Get name for a BedHeight. */ public static String getHeightName(String type, int height_id) { log.debug("BedHeightFactory.getHeightName height_id/" + height_id); @@ -123,10 +125,9 @@ /** - * Get WKms from db. - * @param column the position columns value - * @param wst_id database id of the wst - * @return according WKms. + * Get BedHeight from db. + * @param height_id database id of the bed_height + * @return according BedHeight. */ public static BedHeight getBedHeightUncached( String type, diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/FlowVelocityMeasurementFactory.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/FlowVelocityMeasurementFactory.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/FlowVelocityMeasurementFactory.java Thu Sep 12 10:13:09 2013 +0200 @@ -8,12 +8,15 @@ package org.dive4elements.river.artifacts.model.minfo; +import java.util.Date; import java.util.List; import org.apache.log4j.Logger; import org.hibernate.SQLQuery; import org.hibernate.Session; +import org.hibernate.type.StandardBasicTypes; + import org.dive4elements.river.model.FlowVelocityMeasurementValue; import org.dive4elements.river.backend.SessionHolder; @@ -40,7 +43,13 @@ log.debug("FlowVelocityMeasurementFactory.getFlowVelocityMeasurementValue"); Session session = SessionHolder.HOLDER.get(); SQLQuery sqlQuery = null; - sqlQuery = session.createSQLQuery(SQL_SELECT_ONE); + sqlQuery = session.createSQLQuery(SQL_SELECT_ONE) + .addScalar("station", StandardBasicTypes.DOUBLE) + .addScalar("datetime", StandardBasicTypes.DATE) + .addScalar("w", StandardBasicTypes.DOUBLE) + .addScalar("q", StandardBasicTypes.DOUBLE) + .addScalar("v", StandardBasicTypes.DOUBLE) + .addScalar("description", StandardBasicTypes.STRING); sqlQuery.setParameter("id", id); List results = sqlQuery.list(); @@ -50,10 +59,12 @@ return null; } return FlowVelocityMeasurementValue.getUnmapped( - Double.parseDouble(row[0].toString()), - Double.parseDouble(row[2].toString()), - Double.valueOf(row[3].toString()), - Double.valueOf(row[4].toString()), null, row[5].toString()); + (Double) row[0], + (Double) row[2], + (Double) row[3], + (Double) row[4], + (Date) row[1], + (String) row[5]); } return null; } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurement.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurement.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurement.java Thu Sep 12 10:13:09 2013 +0200 @@ -11,8 +11,11 @@ import java.util.Date; import java.util.Map; +import org.apache.log4j.Logger; +/** A measurement of the bed quality, serving different diameter at given km. */ public class QualityMeasurement { + private static Logger logger = Logger.getLogger(QualityMeasurements.class); private double km; private Date date; @@ -20,7 +23,7 @@ private double depth2; private Map charDiameter; - public QualityMeasurement() { + private QualityMeasurement() { } @@ -61,8 +64,16 @@ this.charDiameter = charDiameter; } + /** + * Get the stored diameter for given key (e.g. d10). + * @return NaN if no data found in this measurement. + */ public double getDiameter(String key) { - return charDiameter.get(key); + Double diameter = charDiameter.get(key); + if (diameter == null) { + logger.warn("No Diameter at km " + km + " for " + key); + } + return (diameter != null) ? diameter : Double.NaN; } public void setDiameter(String key, double value) { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurementFactory.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurementFactory.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurementFactory.java Thu Sep 12 10:13:09 2013 +0200 @@ -86,14 +86,18 @@ " m.datum BETWEEN :start AND :end " + "ORDER BY m.km"; + /** Transform query result into objects, use INSTANCE singleton. */ public static final class QualityMeasurementResultTransformer extends BasicTransformerAdapter { - public static QualityMeasurementResultTransformer INSTANCE = new QualityMeasurementResultTransformer(); + // Make a singleton + public static QualityMeasurementResultTransformer INSTANCE = + new QualityMeasurementResultTransformer(); - public QualityMeasurementResultTransformer() { + private QualityMeasurementResultTransformer() { } + /** tuples is a row. */ @Override public Object transformTuple(Object[] tuple, String[] aliases) { Map map = new HashMap(); @@ -172,6 +176,7 @@ return new QualityMeasurements(query.list()); } + /** Get all measurements. */ public static QualityMeasurements getBedMeasurements( String river, double from, diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurements.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurements.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/QualityMeasurements.java Thu Sep 12 10:13:09 2013 +0200 @@ -56,3 +56,4 @@ this.measurements.add(qm); } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensity.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensity.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensity.java Thu Sep 12 10:13:09 2013 +0200 @@ -65,23 +65,25 @@ this.years = years; } + /** + * Get the density at year. + * measured densities are valid until the next measurement. + * if no measurement was found 1.8 is returned. + */ public double getDensity(double km, int year) { Collections.sort(this.years); - if (this.years.size() == 1) { - return getDensityAtKm(densities.get(year), km); + if (this.years.size() == 1 && years.get(0) <= year) { + logger.debug("get density from year " + year + " at km " + km); + return getDensityAtKm(densities.get(years.get(0)), km); } - else { + else if (this.years.size() > 1) { for (int i = 0; i < years.size() -1; i++) { int y1 = years.get(i); int y2 = years.get(i + 1); - int mid = Math.round((y1 + y2) / 2); - if (year < mid) { + if (year >= y1 && year < y2) { return getDensityAtKm(densities.get(y1), km); } - else if (i == years.size() -1) { - continue; - } - else { + else if (year >= y2 && i == years.size() -1) { return getDensityAtKm(densities.get(y2), km); } } @@ -93,15 +95,12 @@ List values, double km ) { - boolean found = true; SedimentDensityValue prev = null; SedimentDensityValue next = null; for (SedimentDensityValue sdv: values) { -logger.debug("year: " + sdv.getYear()); - if (sdv.getKm() == km) { - prev = sdv; - found = true; - break; + logger.debug("year: " + sdv.getYear()); + if (Math.abs(sdv.getKm() - km) < 0.00001) { + return prev.getDensity(); } if (sdv.getKm() > km) { next = sdv; @@ -109,32 +108,39 @@ } prev = sdv; } - if (found) { - return prev.getDensity(); - } - else { - return spline(prev, next, km); - } + return spline(prev, next, km); } - private double spline( + private static double spline( SedimentDensityValue prev, SedimentDensityValue next, double km ) { + if (prev == null && next == null) { + logger.warn("prev and next are null -> NaN"); + return Double.NaN; + } + + if (prev == null) return next.getDensity(); + if (next == null) return prev.getDensity(); + + // XXX: This is no spline interpolation! double lower = prev.getKm(); double upper = next.getKm(); double upperDensity = next.getDensity(); double lowerDensity = prev.getDensity(); - double m =(upperDensity - lowerDensity)/(upper - lower) * km; - double b = lowerDensity - - ((upperDensity - lowerDensity)/(upper - lower) * lower); - return (m * km) + b; + double m = (upperDensity - lowerDensity)/(upper - lower); + double b = lowerDensity - (m * lower); + return m * km + b; } + + /** If multiple values for same year and station are found, + * build and store average, dismiss multiple values. */ public void cleanUp() { Set keys = densities.keySet(); + // Walk over years for (Integer key : keys) { List list = densities.get(key); if (list.size() == 0) { @@ -146,6 +152,7 @@ int counter = 0; double sum = 0d; for (SedimentDensityValue value : list) { + // Apparently we can assume that values are ordered by km. if (value.getKm() == prevkm) { sum += value.getDensity(); counter++; @@ -164,3 +171,4 @@ } } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensityFactory.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensityFactory.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensityFactory.java Thu Sep 12 10:13:09 2013 +0200 @@ -79,14 +79,13 @@ int year ) { log.debug("getSedimentDensityUncached"); - List results = null; Session session = SessionHolder.HOLDER.get(); SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_DENSITY) .addScalar("km", StandardBasicTypes.DOUBLE) .addScalar("density", StandardBasicTypes.DOUBLE) .addScalar("year", StandardBasicTypes.INTEGER); sqlQuery.setString("name", river); - results = sqlQuery.list(); + List results = sqlQuery.list(); SedimentDensity density = new SedimentDensity(); for (Object[] row : results) { if (row[0] != null && row[1] != null && row[2] != null) { @@ -98,3 +97,4 @@ return density; } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensityValue.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensityValue.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentDensityValue.java Thu Sep 12 10:13:09 2013 +0200 @@ -8,7 +8,7 @@ package org.dive4elements.river.artifacts.model.minfo; - +/** A density value at a km, year. */ public class SedimentDensityValue { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoad.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoad.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoad.java Thu Sep 12 10:13:09 2013 +0200 @@ -9,11 +9,13 @@ package org.dive4elements.river.artifacts.model.minfo; import java.util.Date; -import java.util.HashMap; +import java.util.Map; import java.util.Set; +import java.util.TreeMap; import org.dive4elements.river.artifacts.model.NamedObjectImpl; import org.dive4elements.river.artifacts.model.Range; +import org.dive4elements.river.utils.EpsilonComparator; /** Gives access to Fractions (at kms). */ @@ -26,10 +28,10 @@ protected boolean isEpoch; protected String unit; - protected HashMap kms; + protected Map kms; public SedimentLoad() { - kms = new HashMap(); + kms = new TreeMap(EpsilonComparator.CMP); } public SedimentLoad( @@ -88,124 +90,71 @@ } public SedimentLoadFraction getFraction(double km) { - if (kms.get(km) == null) { - return new SedimentLoadFraction(); + SedimentLoadFraction f = kms.get(km); + if (f == null) { + f = new SedimentLoadFraction(); + kms.put(km, f); } - return kms.get(km); + return f; } public void setCoarse(double km, double coarse, Range range) { - if (kms.containsKey(km)) { - kms.get(km).setCoarse(coarse); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setCoarse(coarse); - f.setCoarseRange(range); - kms.put(km, f); - } + SedimentLoadFraction f = getFraction(km); + f.setCoarse(coarse); + f.setCoarseRange(range); } public void setFineMiddle(double km, double fine_middle, Range range) { - if (kms.containsKey(km)) { - kms.get(km).setFineMiddle(fine_middle); - kms.get(km).setFineMiddleRange(range); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setFineMiddle(fine_middle); - f.setFineMiddleRange(range); - kms.put(km, f); - } + SedimentLoadFraction f = getFraction(km); + f.setFineMiddle(fine_middle); + f.setFineMiddleRange(range); } + public void setSand(double km, double sand, Range range) { - if (kms.containsKey(km)) { - kms.get(km).setSand(sand); - kms.get(km).setSandRange(range); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setSand(sand); - f.setSandRange(range); - kms.put(km, f); - } + SedimentLoadFraction f = getFraction(km); + f.setSand(sand); + f.setSandRange(range); } public void setSuspSand(double km, double susp_sand, Range range) { - if (kms.containsKey(km)) { - kms.get(km).setSuspSand(susp_sand); - kms.get(km).setSuspSandRange(range); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setSuspSand(susp_sand); - f.setSuspSandRange(range); - kms.put(km, f); - } + SedimentLoadFraction f = getFraction(km); + f.setSuspSand(susp_sand); + f.setSuspSandRange(range); } public void setSuspSandBed(double km, double susp_sand_bed, Range range) { - if (kms.containsKey(km)) { - kms.get(km).setSuspSandBed(susp_sand_bed); - kms.get(km).setSuspSandBedRange(range); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setSuspSandBed(susp_sand_bed); - f.setSuspSandBedRange(range); - kms.put(km, f); - } + SedimentLoadFraction f = getFraction(km); + f.setSuspSandBed(susp_sand_bed); + f.setSuspSandBedRange(range); } public void setSuspSediment(double km, double susp_sediment, Range range) { - if (kms.containsKey(km)) { - kms.get(km).setSuspSediment(susp_sediment); - kms.get(km).setSuspSedimentRange(range); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setSuspSediment(susp_sediment); - f.setSuspSedimentRange(range); - kms.put(km, f); - } + SedimentLoadFraction f = getFraction(km); + f.setSuspSediment(susp_sediment); + f.setSuspSedimentRange(range); } public void setLoadTotal(double km, double total) { - if (kms.containsKey(km)) { - kms.get(km).setLoadTotal(total); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setLoadTotal(total); - kms.put(km, f); - } + setLoadTotal(km, total, null); + } + + public void setLoadTotal(double km, double total, Range range) { + SedimentLoadFraction f = getFraction(km); + f.setLoadTotal(total); + f.setLoadTotalRange(range); } public void setTotal(double km, double total, Range range) { - if (kms.containsKey(km)) { - kms.get(km).setTotal(total); - kms.get(km).setTotalRange(range); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setTotal(total); - f.setTotalRange(range); - kms.put(km, f); - } + SedimentLoadFraction f = getFraction(km); + f.setTotal(total); + f.setTotalRange(range); } public void setUnknown(double km, double unknown, Range range) { - if (kms.containsKey(km)) { - kms.get(km).setUnknown(unknown); - kms.get(km).setUnknownRange(range); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setUnknown(unknown); - f.setUnknownRange(range); - kms.put(km, f); - } + SedimentLoadFraction f = getFraction(km); + f.setUnknown(unknown); + f.setUnknownRange(range); } public String getUnit() { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadCalculation.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadCalculation.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadCalculation.java Thu Sep 12 10:13:09 2013 +0200 @@ -11,7 +11,6 @@ import gnu.trove.TDoubleArrayList; import java.util.ArrayList; -import java.util.TreeSet; import java.util.List; import org.apache.log4j.Logger; @@ -36,12 +35,14 @@ protected double kmUp; protected double kmLow; protected int[] period; + /** Years of chosen epochs. */ protected int[][] epoch; protected String unit; public SedimentLoadCalculation() { } + /** Returns CalculationResult with array of SedimentLoadResults. */ public CalculationResult calculate(SedimentLoadAccess access) { logger.info("SedimentLoadCalculation.calculate"); @@ -87,6 +88,7 @@ return new CalculationResult(); } + /** Returns CalculationResult with array of SedimentLoadResults. */ private CalculationResult internalCalculate() { logger.debug("internalCalulate; mode:" + yearEpoch); if (yearEpoch.equals("year")) { @@ -119,9 +121,85 @@ return new CalculationResult( results.toArray(new SedimentLoadResult[results.size()]), this); } + else { + logger.error("Unknown mode " + yearEpoch); + } return null; } + /** + * @param[out] resLoad resulting SedimentLoad + */ + private void calculateEpochKm( + List epochLoads, + SedimentLoad resLoad, + double km + ) { + int cSum = 0; + int fmSum = 0; + int sSum = 0; + int ssSum = 0; + int ssbSum = 0; + int sseSum = 0; + for (SedimentLoad load : epochLoads) { + SedimentLoadFraction f = load.getFraction(km); + if (f.getCoarse() > 0d) { + double c = resLoad.getFraction(km).getCoarse(); + resLoad.setCoarse(km, c + f.getCoarse(), f.getCoarseRange()); + cSum++; + } + if (f.getFineMiddle() > 0d) { + double fm = resLoad.getFraction(km).getFineMiddle(); + resLoad.setFineMiddle(km, fm + f.getFineMiddle(), f.getFineMiddleRange()); + fmSum++; + } + if (f.getSand() > 0d) { + double s = resLoad.getFraction(km).getSand(); + resLoad.setSand(km, s + f.getSand(), f.getSandRange()); + sSum++; + } + if (f.getSuspSand() > 0d) { + double s = resLoad.getFraction(km).getSuspSand(); + resLoad.setSuspSand(km, s + f.getSuspSand(), f.getSuspSandRange()); + ssSum++; + } + if (f.getSuspSandBed() > 0d) { + double s = resLoad.getFraction(km).getSuspSandBed(); + resLoad.setSuspSandBed(km, s + f.getSuspSandBed(), f.getSuspSandBedRange()); + ssbSum++; + } + if (f.getSuspSediment() > 0d) { + double s = resLoad.getFraction(km).getSuspSediment(); + resLoad.setSuspSediment(km, s + f.getSuspSediment(), f.getSuspSedimentRange()); + sseSum++; + } + } + + SedimentLoadFraction fr = resLoad.getFraction(km); + // Prevent divisions by zero, the fraction defaults to 0d. + if (cSum != 0) { + resLoad.setCoarse(km, fr.getCoarse()/cSum, fr.getCoarseRange()); + } + if (fmSum != 0) { + resLoad.setFineMiddle(km, fr.getFineMiddle()/fmSum, + fr.getFineMiddleRange()); + } + if (sSum != 0) { + resLoad.setSand(km, fr.getSand()/sSum, fr.getSandRange()); + } + if (ssSum != 0) { + resLoad.setSuspSand(km, fr.getSuspSand()/ssSum, + fr.getSuspSandRange()); + } + if (ssbSum != 0) { + resLoad.setSuspSandBed(km, fr.getSuspSandBed()/ssbSum, + fr.getSuspSandBedRange()); + } + if (sseSum != 0) { + resLoad.setSuspSediment(km, fr.getSuspSediment()/sseSum, fr.getSuspSedimentRange()); + } + } + private SedimentLoadResult calculateEpoch(int i) { List epochLoads = new ArrayList(); for (int j = epoch[i][0]; j < epoch[i][1]; j++) { @@ -146,53 +224,7 @@ } for (int j = 0; j < kms.size(); j++) { - int cSum = 0; - int fmSum = 0; - int sSum = 0; - int ssSum = 0; - int ssbSum = 0; - int sseSum = 0; - double km = kms.get(j); - for (SedimentLoad load : epochLoads) { - SedimentLoadFraction f = load.getFraction(km); - if (f.getCoarse() > 0d) { - double c = resLoad.getFraction(km).getCoarse(); - resLoad.setCoarse(km, c + f.getCoarse(), f.getCoarseRange()); - cSum++; - } - if (f.getFineMiddle() > 0d) { - double fm = resLoad.getFraction(km).getFineMiddle(); - resLoad.setFineMiddle(km, fm + f.getFineMiddle(), f.getFineMiddleRange()); - fmSum++; - } - if (f.getSand() > 0d) { - double s = resLoad.getFraction(km).getSand(); - resLoad.setSand(km, s + f.getSand(), f.getSandRange()); - sSum++; - } - if (f.getSuspSand() > 0d) { - double s = resLoad.getFraction(km).getSuspSand(); - resLoad.setSuspSand(km, s + f.getSuspSand(), f.getSuspSandRange()); - ssSum++; - } - if (f.getSuspSandBed() > 0d) { - double s = resLoad.getFraction(km).getSuspSandBed(); - resLoad.setSuspSandBed(km, s + f.getSuspSandBed(), f.getSuspSandBedRange()); - ssbSum++; - } - if (f.getSuspSediment() > 0d) { - double s = resLoad.getFraction(km).getSuspSediment(); - resLoad.setSuspSediment(km, s + f.getSuspSediment(), f.getSuspSedimentRange()); - sseSum++; - } - } - SedimentLoadFraction fr = resLoad.getFraction(km); - resLoad.setCoarse(km, fr.getCoarse()/cSum, fr.getCoarseRange()); - resLoad.setFineMiddle(km, fr.getFineMiddle()/fmSum, fr.getFineMiddleRange()); - resLoad.setSand(km, fr.getSand()/sSum, fr.getSandRange()); - resLoad.setSuspSand(km, fr.getSuspSand()/ssSum, fr.getSuspSandRange()); - resLoad.setSuspSandBed(km, fr.getSuspSandBed()/ssbSum, fr.getSuspSandBedRange()); - resLoad.setSuspSediment(km, fr.getSuspSediment()/sseSum, fr.getSuspSedimentRange()); + calculateEpochKm(epochLoads, resLoad, kms.get(j)); } resLoad.setDescription(""); resLoad.setEpoch(true); @@ -216,6 +248,10 @@ return result; } + /** + * Calculate/Fetch values at off. epochs. + * @param i index in epochs. + */ private SedimentLoadResult calculateOffEpoch(int i) { SedimentLoad load = SedimentLoadFactory.getLoadWithData( this.river, @@ -243,8 +279,11 @@ return result; } - /** Fetch loads for a single year, calculate total and - * return the result containing both. */ + /** + * Fetch loads for a single year, calculate total and + * return the result containing both. + * @param y year, e.g. 1980 + */ private SedimentLoadResult calculateYear(int y) { SedimentLoad load = SedimentLoadFactory.getLoadWithData( this.river, @@ -298,44 +337,18 @@ } - /** Returns true if all fraction values except SuspSediment are unset. */ - private boolean hasOnlySuspValues(SedimentLoadFraction fraction) { - return (fraction.getSuspSediment() != 0d && - fraction.getCoarse() == 0d && - fraction.getFineMiddle() == 0d && - fraction.getSand() == 0d && - fraction.getSuspSand() == 0d); - } - - - /** Returns true if all fraction values except SuspSediment are set. */ - private boolean hasButSuspValues(SedimentLoadFraction fraction) { - return (fraction.getSuspSediment() == 0d && - fraction.getCoarse() != 0d && - fraction.getFineMiddle() != 0d && - fraction.getSand() != 0d && - fraction.getSuspSand() != 0d); - } - - - /** Returns true if all fraction needed for total calculation are set. */ - private boolean complete(SedimentLoadFraction fraction) { - return (fraction.getCoarse() != 0d && - fraction.getFineMiddle() != 0d && - fraction.getSand() != 0d && - fraction.getSuspSand() != 0d && - fraction.getSuspSediment() != 0d); - } - /** * Set total values in load. - * Therefore, run over the kms and find ranges where either all + * + * Therefore, run over the sorted kms and find ranges where either all * or all Geschiebe or just the Schwebstoff fractions are set. * Merge these ranges and add (maybe new) respective fractions to - * load. + * load. In the process, remember any 'unfished' ends from measurements + * where the km-ranges did not completely match. + * * @param load SedimentLoad to add total values (and ranges) to. - * @return input param load. + * @return input param load, with total values set. */ private SedimentLoad partialTotal(SedimentLoad load) { SedimentLoad fairLoad = load; @@ -346,12 +359,10 @@ Range lastSuspRange = null; double lastSuspValue = 0d; - TreeSet kms = new TreeSet(load.getKms()); - - for (double km: kms) { + for (double km: load.getKms()) { // kms are already sorted! logger.debug ("Trying to add at km " + km); SedimentLoadFraction fraction = load.getFraction(km); - if (complete(fraction)) { + if (fraction.isComplete()) { double total = fraction.getCoarse() + fraction.getFineMiddle() + fraction.getSand() + @@ -387,7 +398,7 @@ } } } - else if (hasOnlySuspValues(fraction) && lastOtherRange != null) { + else if (fraction.hasOnlySuspValues() && lastOtherRange != null) { // Split stuff. Range suspSedimentRange = fraction.getSuspSedimentRange(); // if intersects with last other range, cool! merge and add! @@ -412,7 +423,8 @@ lastOtherRange.setStart(suspSedimentRange.getEnd()); lastSuspRange = null; } - if (Math.abs(suspSedimentRange.getEnd() - lastOtherRange.getEnd()) < 0.1d) { + if (lastOtherRange != null + && Math.abs(suspSedimentRange.getEnd() - lastOtherRange.getEnd()) < 0.1d) { lastOtherRange = null; lastSuspRange = null; } @@ -424,7 +436,7 @@ lastOtherRange = null; } } - else if (hasButSuspValues(fraction) && lastSuspRange != null) { + else if (fraction.hasButSuspValues() && lastSuspRange != null) { // If intersects with last suspsed range, merge and add double total = fraction.getCoarse() + fraction.getFineMiddle() + @@ -449,7 +461,9 @@ lastSuspRange = null; lastOtherValue = total - lastSuspValue; } - if (lastSuspRange != null && Math.abs(lastSuspRange.getEnd() - lastOtherRange.getEnd()) < 0.1d) { + if (lastSuspRange != null + && lastOtherRange != null + && Math.abs(lastSuspRange.getEnd() - lastOtherRange.getEnd()) < 0.1d) { lastOtherRange = null; lastSuspRange = null; } @@ -465,7 +479,7 @@ else { // Some values are missing or no intersection with former values. // Stay as we are. - if (hasButSuspValues(fraction)) { + if (fraction.hasButSuspValues()) { double total = fraction.getCoarse() + fraction.getFineMiddle() + fraction.getSand() + @@ -474,7 +488,7 @@ lastOtherValue = total; lastSuspRange = null; } - else if (hasOnlySuspValues(fraction)) { + else if (fraction.hasOnlySuspValues()) { lastSuspRange = fraction.getSuspSedimentRange(); lastSuspValue = fraction.getSuspSediment(); lastOtherRange = null; @@ -485,9 +499,20 @@ } + /** + * Transform values in load. + * Background is to transform values measured in + * t/a to m^3/a using the specific measured densities. + * + * @param load The load of which values should be transformed. + * @param year The year at which to look at density (e.g. 2003). + * + * @return parameter load with transformed values. + */ private SedimentLoad calculateUnit(SedimentLoad load, int year) { SedimentDensity density = SedimentDensityFactory.getSedimentDensity(river, kmLow, kmUp, year); + for (double km: load.getKms()) { double dens = density.getDensity(km, year); SedimentLoadFraction fraction = load.getFraction(km); @@ -498,6 +523,7 @@ double bedSand = fraction.getSuspSandBed(); double sediment = fraction.getSuspSediment(); double total = fraction.getTotal(); + double loadTotal = fraction.getLoadTotal(); load.setCoarse(km, (coarse * dens), fraction.getCoarseRange()); load.setFineMiddle(km, (fineMiddle * dens), fraction.getFineMiddleRange()); load.setSand(km, (sand * dens), fraction.getSandRange()); @@ -505,6 +531,7 @@ load.setSuspSandBed(km, (bedSand * dens), fraction.getSuspSandBedRange()); load.setSuspSediment(km, (sediment * dens), fraction.getSuspSedimentRange()); load.setTotal(km, (total * dens), fraction.getTotalRange()); + load.setLoadTotal(km, (loadTotal * dens), fraction.getLoadTotalRange()); } return load; } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFacet.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFacet.java Thu Sep 12 10:13:09 2013 +0200 @@ -31,6 +31,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.TreeSet; import java.util.TreeMap; import org.apache.log4j.Logger; @@ -55,6 +56,7 @@ super(idx, name, description, type, hash, stateId); } + @Override public Object getData(Artifact artifact, CallContext context) { logger.debug("Get data for sediment load at index: " + index); @@ -104,7 +106,7 @@ TDoubleArrayList xPos = new TDoubleArrayList(); TDoubleArrayList yPos = new TDoubleArrayList(); double lastX = -1d; - for (double km: load.getKms()) { + for (double km: new TreeSet(load.getKms())) { SedimentLoadFraction fraction = load.getFraction(km); if (fraction.getTotal() != 0) { if (Math.abs(lastX-km) >= EPSILON) { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFactory.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFactory.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFactory.java Thu Sep 12 10:13:09 2013 +0200 @@ -29,16 +29,19 @@ import org.hibernate.Session; import org.hibernate.type.StandardBasicTypes; + /** Pull Sediment Loads out of db. */ public class SedimentLoadFactory { /** Private logger to use here. */ private static Logger log = Logger.getLogger(SedimentLoadFactory.class); + // Cache name/keys public static final String LOADS_CACHE_NAME = "sedimentloads"; public static final String LOAD_DATA_CACHE_NAME = "sedimentload-data"; - /** Query to get km and ws for wst_id and column_pos. */ + /** Query to get description and start year of single type + * sediment_yields. */ public static final String SQL_SELECT_SINGLES = "SELECT DISTINCT " + " sy.description AS description, " + @@ -51,7 +54,23 @@ " AND ti.stop_time IS NULL " + " AND syv.station BETWEEN :startKm AND :endKm"; - /** Query to get name for wst_id and column_pos. */ + /** Query to get description, name and time range for official + * epoch-type sediment yields. */ + public static final String SQL_SELECT_OFFEPOCHS = + "SELECT DISTINCT " + + " ti.start_time AS startYear, " + + " ti.stop_time AS end " + + " FROM sediment_yield sy " + + " JOIN rivers r ON sy.river_id = r.id " + + " JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " + + " JOIN time_intervals ti ON sy.time_interval_id = ti.id " + + " WHERE r.name = :name " + + " AND ti.stop_time IS NOT NULL " + + " AND syv.station BETWEEN :startKm AND :endKm " + + " AND sy.kind = 1"; + + /** Query to get description, name and time range for epoch-type + * sediment yields. */ public static final String SQL_SELECT_EPOCHS = "SELECT DISTINCT " + " sy.description AS description, " + @@ -115,8 +134,11 @@ " JOIN rivers r ON sy.river_id = r.id " + " JOIN time_intervals ti ON sy.time_interval_id = ti.id " + " JOIN grain_fraction gf ON sy.grain_fraction_id = gf.id " + - "WHERE r.name = :river" + - " AND gf.name = 'unknown'"; + " JOIN units u ON sy.unit_id = u.id " + + "WHERE r.name = :river " + + " AND gf.name = 'unknown' " + + " AND sy.kind = :type " + + " AND u.name = :unit"; public static final String SQL_SELECT_EPOCHS_DATA = "SELECT" + @@ -143,7 +165,8 @@ } /** - * + * @param river name of river. + * @param type */ public static SedimentLoad[] getLoads( String river, @@ -180,6 +203,10 @@ return values; } + /** + * Get a sedimentLoad filled with data from db (or cache). + * @param type "epoch", "off_epoch" or "single" + */ public static SedimentLoad getLoadWithData( String river, String type, @@ -287,13 +314,37 @@ } return loads; } + else if (type.equals("off_epoch")) { + sqlQuery = session.createSQLQuery(SQL_SELECT_OFFEPOCHS) + .addScalar("startYear", StandardBasicTypes.DATE) + .addScalar("end", StandardBasicTypes.DATE); + sqlQuery.setString("name", river); + sqlQuery.setDouble("startKm", startKm); + sqlQuery.setDouble("endKm", endKm); + List results = sqlQuery.list(); + + SedimentLoad[] loads = new SedimentLoad[results.size()]; + for (int i = 0; i < results.size(); i++) { + Object[] row = results.get(i); + loads[i] = new SedimentLoad( + ((Date) row[0]).toString() + (Date) row[1], + (Date) row[0], + (Date) row[1], + true, + ""); + } + return loads; + } + else { + log.warn("getSedimentLoadsUncached does not understand type " + type); + } return new SedimentLoad[0]; } /** * Get sediment loads from db. * @param river the river - * @param type the sediment load type (year or epoch) + * @param type the sediment load type (year, epoch or off_epoch) * @return according sediment loads. */ public static SedimentLoad getSedimentLoadWithDataUncached( @@ -308,22 +359,35 @@ Session session = SessionHolder.HOLDER.get(); SQLQuery sqlQuery = null; - List allStations = RiverFactory.getRiver(river).getMeasurementStations(); - TreeMap floatStations = new TreeMap(); - TreeMap suspStations = new TreeMap(); + // Measurement stations: all, for float-stuff, for suspended stuff. + // Because they need fast sorted access, use TreeMaps. + // They map the starting validity range km to the station itself. + List allStations = + RiverFactory.getRiver(river).getMeasurementStations(); + TreeMap floatStations = + new TreeMap(); + TreeMap suspStations = + new TreeMap(); + + // From all stations, sort into the two kinds, skip undefined ones. for (MeasurementStation measurementStation: allStations) { if (measurementStation.getMeasurementType() == null || measurementStation.getRange() == null) { continue; } if (measurementStation.getMeasurementType().equals("Schwebstoff")) { - suspStations.put(measurementStation.getRange().getA().doubleValue(), measurementStation); + suspStations.put( + measurementStation.getRange().getA().doubleValue(), + measurementStation); } else if (measurementStation.getMeasurementType().equals("Geschiebe")) { - floatStations.put(measurementStation.getRange().getA().doubleValue(), measurementStation); + floatStations.put( + measurementStation.getRange().getA().doubleValue(), + measurementStation); } } + // Construct date constraint. Calendar start = Calendar.getInstance(); start.set(syear - 1, 11, 31); Calendar end = Calendar.getInstance(); @@ -344,27 +408,35 @@ sqlQuery.setString("grain", "total"); List results = sqlQuery.list(); SedimentLoad load = new SedimentLoad(); - Object[] row = results.get(0); - load = new SedimentLoad( - (String) row[0], - (Date) row[1], - null, - false, - (String) row[4]); - getValues("coarse", sqlQuery, load, floatStations); - getValues("fine_middle", sqlQuery, load, floatStations); - getValues("sand", sqlQuery, load, floatStations); - getValues("suspended_sediment", sqlQuery, load, suspStations); - getValues("susp_sand_bed", sqlQuery, load, floatStations); - getValues("susp_sand", sqlQuery, load, floatStations); + if (results.isEmpty()) { + log.warn("Empty result for year calculation."); + } + else { + Object[] row = results.get(0); + load = new SedimentLoad( + (String) row[0], //description + (Date) row[1], //start + null, //end + false, //isEpoch + (String) row[4]); //unit + } + load = getValues("coarse", sqlQuery, load, floatStations); + load = getValues("fine_middle", sqlQuery, load, floatStations); + load = getValues("sand", sqlQuery, load, floatStations); + load = getValues("suspended_sediment", sqlQuery, load, suspStations); + load = getValues("susp_sand_bed", sqlQuery, load, floatStations); + load = getValues("susp_sand", sqlQuery, load, floatStations); return load; } else if (type.equals("off_epoch")) { + // Set calendars to fetch the epochs by their start and end + // dates. Calendar toStart = Calendar.getInstance(); toStart.set(eyear - 1, 11, 31); Calendar toEnd = Calendar.getInstance(); - toEnd.set(eyear, 11, 30); + toEnd.set(eyear+1, 00, 01); + // Set query parameters. sqlQuery = session.createSQLQuery(SQL_SELECT_EPOCHS_DATA) .addScalar("description", StandardBasicTypes.STRING) .addScalar("startYear", StandardBasicTypes.DATE) @@ -377,47 +449,79 @@ sqlQuery.setDouble("endKm", endKm); sqlQuery.setDate("sbegin", start.getTime()); sqlQuery.setDate("send", end.getTime()); - sqlQuery.setDate("ebegin",toStart.getTime()); + sqlQuery.setDate("ebegin", toStart.getTime()); sqlQuery.setDate("eend", toEnd.getTime()); sqlQuery.setString("grain", "total"); List results = null; results = sqlQuery.list(); - SedimentLoad load = new SedimentLoad(); - Object[] row = results.get(0); - load = new SedimentLoad( - (String) row[0], - (Date) row[1], - (Date) row[4], - true, - (String)row[5]); - TDoubleArrayList kms = new TDoubleArrayList(); - for (int i = 0; i < results.size(); i++) { - row = results.get(i); - kms.add((Double)row[3]); - load.setLoadTotal((Double)row[3], (Double)row[2]); + SedimentLoad load = null; + if (results.isEmpty()) { + log.warn("No total results for off-epoch"); } - getValues("coarse", sqlQuery, load, floatStations); - getValues("fine_middle", sqlQuery, load, floatStations); - getValues("sand", sqlQuery, load, floatStations); - getValues("suspended_sediment", sqlQuery, load, suspStations); - getValues("susp_sand_bed", sqlQuery, load, floatStations); - getValues("susp_sand", sqlQuery, load, floatStations); + else { + Object[] row = results.get(0); + load = new SedimentLoad( + (String) row[0], + (Date) row[1], + (Date) row[4], + true, + (String)row[5]); + TDoubleArrayList kms = new TDoubleArrayList(); + for (int i = 0; i < results.size(); i++) { + row = results.get(i); + kms.add((Double)row[3]); + load.setLoadTotal((Double)row[3], (Double)row[2]); + } + } + load = getValues("coarse", sqlQuery, load, floatStations); + load = getValues("fine_middle", sqlQuery, load, floatStations); + load = getValues("sand", sqlQuery, load, floatStations); + load = getValues("suspended_sediment", sqlQuery, load, suspStations); + load = getValues("susp_sand_bed", sqlQuery, load, floatStations); + load = getValues("susp_sand", sqlQuery, load, floatStations); return load; } return new SedimentLoad(); } + protected static Range findMeasurementStationRange( + TreeMap stations, + double km + ) { + MeasurementStation station = stations.get(km); + if (station == null) { + return null; + } + + double endKm; + + if (stations.ceilingEntry(km + 0.1d) != null) { + MeasurementStation nextStation = stations.ceilingEntry(km + 0.1d).getValue(); + endKm = nextStation.getRange().getA().doubleValue(); + } + else { + // TODO end-of-river instead of B. + endKm = station.getRange().getB().doubleValue(); + } + + return new Range( + station.getRange().getA().doubleValue(), + endKm); + } /** * Run query with grain parameter set to fraction, feed result into - * load. + * load. Create load if null. + * * @param fraction value to set 'grain' parameter in query to. * @param query query in which to set 'grain' parameter and run. - * @param load[out] SedimentLoad which to populate with values. + * @param load[out] SedimentLoad which to populate with values. if null + * and values are found, return a new load. + * @return param load or new load if null. */ - protected static void getValues ( + protected static SedimentLoad getValues ( String fraction, SQLQuery query, SedimentLoad load, @@ -425,27 +529,25 @@ ) { query.setString("grain", fraction); List results = query.list(); + + // We have the first results for this query, create new load. + if (!results.isEmpty() && load == null) { + Object[] row = results.get(0); + load = new SedimentLoad( + (String) row[0], + (Date) row[1], + (Date) row[4], + true, + (String)row[5]); + } + for (int i = 0; i < results.size(); i++) { Object[] row = results.get(i); double km = (Double)row[3]; - MeasurementStation station = stations.get(km); - MeasurementStation nextStation = null; - if (stations.ceilingEntry(km + 0.1d) != null) { - nextStation = stations.ceilingEntry(km + 0.1d).getValue(); - } - Range range = null; - if (station == null) { + Range range = findMeasurementStationRange(stations, km); + if (range == null) { log.warn("No measurement station for " + fraction + " km " + km); - } - else { - if (nextStation != null) - range = new Range(station.getRange().getA().doubleValue(), - nextStation.getRange().getA().doubleValue()); - else { - // TODO end-of-river instead of B. - range = new Range(station.getRange().getA().doubleValue(), - station.getRange().getB().doubleValue()); - } + continue; } double v = -1; if (row[2] != null) { @@ -470,6 +572,8 @@ load.setSuspSandBed(km, v, range); } } + + return load; } public static SedimentLoad getLoadUnknown( @@ -549,13 +653,29 @@ return load; } - public static SedimentLoad[] getSedimentLoadUnknown(String river) { + /** + * Return sediment loads with 'unknown' fraction type. + * @param river Name of the river + * @param unit Restrict result set to those of given unit. + * @param type Type like year, epoch, off_epoch + */ + public static SedimentLoad[] getSedimentLoadUnknown( + String river, + String unit, + String type) { Session session = SessionHolder.HOLDER.get(); SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_UNKNOWN) .addScalar("description", StandardBasicTypes.STRING) .addScalar("startYear", StandardBasicTypes.DATE) .addScalar("end", StandardBasicTypes.DATE); sqlQuery.setString("river", river); + sqlQuery.setString("unit", unit); + if (type.equals("off_epoch")) { + sqlQuery.setInteger("type", 1); + } + else { + sqlQuery.setInteger("type", 0); + } List results = sqlQuery.list(); SedimentLoad[] loads = new SedimentLoad[results.size()]; int counter = 0; diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFraction.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFraction.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFraction.java Thu Sep 12 10:13:09 2013 +0200 @@ -25,15 +25,15 @@ double total; double unknown; /** Values are valid within this km range. */ - Range sandRange = null; - Range fineMiddleRange = null; - Range coarseRange = null; - Range suspSandRange = null; - Range suspSandBedRange = null; - Range suspSedimentRange = null; - Range loadTotalRange = null; - Range totalRange = null; - Range unknownRange = null; + Range sandRange; + Range fineMiddleRange; + Range coarseRange; + Range suspSandRange; + Range suspSandBedRange; + Range suspSedimentRange; + Range loadTotalRange; + Range totalRange; + Range unknownRange; public SedimentLoadFraction() { sand = 0d; @@ -166,6 +166,10 @@ this.loadTotal = total; } + public Range getLoadTotalRange() { + return this.loadTotalRange; + } + public void setLoadTotalRange(Range range) { this.loadTotalRange = range; } @@ -185,5 +189,35 @@ public void setUnknownRange(Range unknownRange) { this.unknownRange = unknownRange; } + + /** Returns true if all fraction values except SuspSediment are unset. */ + public boolean hasOnlySuspValues() { + return + getSuspSediment() != 0d && + getCoarse() == 0d && + getFineMiddle() == 0d && + getSand() == 0d && + getSuspSand() == 0d; + } + + /** Returns true if all fraction values except SuspSediment are set. */ + public boolean hasButSuspValues() { + return + getSuspSediment() == 0d && + getCoarse() != 0d && + getFineMiddle() != 0d && + getSand() != 0d && + getSuspSand() != 0d; + } + + /** Returns true if all fraction needed for total calculation are set. */ + public boolean isComplete() { + return + getCoarse() != 0d && + getFineMiddle() != 0d && + getSand() != 0d && + getSuspSand() != 0d && + getSuspSediment() != 0d; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadUnknownFacet.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadUnknownFacet.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadUnknownFacet.java Thu Sep 12 10:13:09 2013 +0200 @@ -14,7 +14,7 @@ extends DataFacet { /** Very own logger. */ - private static Logger logger = Logger.getLogger(SedimentLoadFacet.class); + private static Logger logger = Logger.getLogger(SedimentLoadUnknownFacet.class); public SedimentLoadUnknownFacet() { } @@ -24,6 +24,7 @@ super(idx, name, description, type, hash, stateId); } + /** Get data from SedimentLoad with unknown type, from factory. */ @Override public Object getData(Artifact artifact, CallContext context) { logger.debug("Get data for sediment load at index: " + index); @@ -32,25 +33,15 @@ SedimentLoadAccess access = new SedimentLoadAccess(flys); String river = access.getRiver(); + String unit = access.getUnit(); SedimentLoad[] unknown = - SedimentLoadFactory.getSedimentLoadUnknown(river); + SedimentLoadFactory.getSedimentLoadUnknown( + river, + unit.replace("_per_","/"), + access.getYearEpoch()); SedimentLoad load = SedimentLoadFactory.getLoadUnknown( river, unknown[index].getDescription()); - if (access.getUnit().equals("t/a") && load.getUnit().equals("m3/a")) { - for (Double km: load.getKms()) { - SedimentLoadFraction fraction = load.getFraction(km); - fraction.setUnknown(fraction.getUnknown() / 1.8); - load.addKm(km, fraction); - } - } - else if (access.getUnit().equals("m3/a") && load.getUnit().equals("t/a")) { - for (Double km: load.getKms()) { - SedimentLoadFraction fraction = load.getFraction(km); - fraction.setUnknown(fraction.getUnknown() * 1.8); - load.addKm(km, fraction); - } - } return load; } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java Thu Sep 12 10:13:09 2013 +0200 @@ -8,6 +8,7 @@ package org.dive4elements.river.artifacts.model.sq; +import org.dive4elements.artifacts.common.utils.StringUtils; import org.dive4elements.river.artifacts.math.fitting.Function; import java.util.ArrayList; @@ -18,12 +19,17 @@ import org.apache.commons.math.optimization.fitting.CurveFitter; import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer; +import org.apache.commons.math.stat.regression.SimpleRegression; import org.apache.log4j.Logger; public class Fitting implements Outlier.Callback { + // XXX: Hack to force linear fitting! + private static final boolean USE_NON_LINEAR_FITTING = + Boolean.getBoolean("minfo.sq.fitting.nonlinear"); + private static Logger log = Logger.getLogger(Fitting.class); public interface Callback { @@ -47,13 +53,15 @@ protected Callback callback; + protected SQ.View sqView; + public Fitting() { } - public Fitting(Function function, double stdDevFactor) { - this(); + public Fitting(Function function, double stdDevFactor, SQ.View sqView) { this.function = function; this.stdDevFactor = stdDevFactor; + this.sqView = sqView; } public Function getFunction() { @@ -75,12 +83,70 @@ @Override public void initialize(List sqs) throws MathException { - LevenbergMarquardtOptimizer lmo = + if (USE_NON_LINEAR_FITTING + || function.getParameterNames().length != 2) { + nonLinearFitting(sqs); + } + else { + linearFitting(sqs); + } + } + + protected void linearFitting(List sqs) { + coeffs = linearRegression(sqs); + instance = function.instantiate(coeffs); + } + + protected double [] linearRegression(List sqs) { + + String [] pns = function.getParameterNames(); + double [] result = new double[pns.length]; + + if (sqs.size() < 2) { + log.debug("not enough points"); + return result; + } + + SimpleRegression reg = new SimpleRegression(); + + for (SQ sq: sqs) { + double s = sqView.getS(sq); + double q = sqView.getQ(sq); + reg.addData(q, s); + } + + double m = reg.getIntercept(); + double b = reg.getSlope(); + + if (log.isDebugEnabled()) { + log.debug("m: " + m); + log.debug("b: " + b); + } + + int mIdx = StringUtils.indexOf("m", pns); + int bIdx = StringUtils.indexOf("b", pns); + + if (mIdx == -1 || bIdx == -1) { + log.error("index not found: " + mIdx + " " + bIdx); + return result; + } + + result[bIdx] = m; + result[mIdx] = b; + + return result; + } + + + protected void nonLinearFitting(List sqs) throws MathException { + + LevenbergMarquardtOptimizer optimizer = new LevenbergMarquardtOptimizer(); - CurveFitter cf = new CurveFitter(lmo); + CurveFitter cf = new CurveFitter(optimizer); + for (SQ sq: sqs) { - cf.addObservedPoint(sq.getQ(), sq.getS()); + cf.addObservedPoint(sqView.getQ(sq), sqView.getS(sq)); } coeffs = cf.fit( @@ -88,13 +154,13 @@ instance = function.instantiate(coeffs); - chiSqr = lmo.getChiSquare(); + chiSqr = optimizer.getChiSquare(); } @Override public double eval(SQ sq) { - double s = instance.value(sq.q); - return sq.s - s; + double s = instance.value(sqView.getQ(sq)); + return sqView.getS(sq) - s; } @Override @@ -119,28 +185,15 @@ chiSqr); } - protected static final List onlyValid(List sqs) { - - List good = new ArrayList(sqs.size()); - - for (SQ sq: sqs) { - if (sq.isValid()) { - good.add(sq); - } - } - - return good; - } - - public boolean fit(List sqs, String method, Callback callback) { - - sqs = onlyValid(sqs); + public boolean fit(List sqs, String method, Callback callback) { if (sqs.size() < 2) { log.warn("Too less points for fitting."); return false; } + sqs = new ArrayList(sqs); + this.callback = callback; try { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/LogSQ.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/LogSQ.java Thu Sep 12 10:13:09 2013 +0200 @@ -0,0 +1,68 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.artifacts.model.sq; + +public class LogSQ extends SQ { + + public static final View LOG_SQ_VIEW = new View() { + @Override + public double getS(SQ sq) { + return ((LogSQ)sq).getLogS(); + } + + @Override + public double getQ(SQ sq) { + return ((LogSQ)sq).getLogQ(); + } + }; + + public static final Factory LOG_SQ_FACTORY = new Factory() { + @Override + public SQ createSQ(double s, double q) { + return new LogSQ(s, q); + } + }; + + protected double logS; + protected double logQ; + + protected boolean logTrans; + + public LogSQ() { + } + + public LogSQ(double s, double q) { + super(s, q); + } + + /** important: We cannot process negative s/q. */ + @Override + public boolean isValid() { + return super.isValid() && s > 0d && q > 0d; + } + + protected void ensureLogTrans() { + if (!logTrans) { + logTrans = true; + logS = Math.log(s); + logQ = Math.log(q); + } + } + + public double getLogS() { + ensureLogTrans(); + return logS; + } + + public double getLogQ() { + ensureLogTrans(); + return logQ; + } +} + diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/MeasurementFactory.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/MeasurementFactory.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/MeasurementFactory.java Thu Sep 12 10:13:09 2013 +0200 @@ -58,32 +58,32 @@ "gp.LFDNR AS LFDNR," + "g.UFERABST AS UFERABST," + "g.UFERABLINKS AS UFERABLINKS," + - "m.TSCHWEB AS TSCHWEB," + - "m.TSAND AS TSAND," + - "gp.GTRIEB_F AS GTRIEB," + - "m.TGESCHIEBE AS TGESCHIEBE," + - "si.SIEB01 AS SIEB01, si.SIEB02 AS SIEB02," + - "si.SIEB03 AS SIEB03, si.SIEB04 AS SIEB04," + - "si.SIEB05 AS SIEB05, si.SIEB06 AS SIEB06," + - "si.SIEB07 AS SIEB07, si.SIEB08 AS SIEB08," + - "si.SIEB09 AS SIEB09, si.SIEB10 AS SIEB10," + - "si.SIEB11 AS SIEB11, si.SIEB12 AS SIEB12," + - "si.SIEB13 AS SIEB13, si.SIEB14 AS SIEB14," + - "si.SIEB15 AS SIEB15, si.SIEB16 AS SIEB16," + - "si.SIEB17 AS SIEB17, si.SIEB18 AS SIEB18," + - "si.SIEB19 AS SIEB19, si.SIEB20 AS SIEB20," + - "si.SIEB21 AS SIEB21," + - "gs.RSIEB01 AS RSIEB01, gs.RSIEB02 AS RSIEB02," + - "gs.RSIEB03 AS RSIEB03, gs.RSIEB04 AS RSIEB04," + - "gs.RSIEB05 AS RSIEB05, gs.RSIEB06 AS RSIEB06," + - "gs.RSIEB07 AS RSIEB07, gs.RSIEB08 AS RSIEB08," + - "gs.RSIEB09 AS RSIEB09, gs.RSIEB10 AS RSIEB10," + - "gs.RSIEB11 AS RSIEB11, gs.RSIEB12 AS RSIEB12," + - "gs.RSIEB13 AS RSIEB13, gs.RSIEB14 AS RSIEB14," + - "gs.RSIEB15 AS RSIEB15, gs.RSIEB16 AS RSIEB16," + - "gs.RSIEB17 AS RSIEB17, gs.RSIEB18 AS RSIEB18," + - "gs.RSIEB19 AS RSIEB19, gs.RSIEB20 AS RSIEB20," + - "gs.RSIEB21 AS RSIEB21, gs.REST AS REST " + + "COALESCE(m.TSCHWEB, 0) AS TSCHWEB," + + "COALESCE(m.TSAND, 0) AS TSAND," + + "COALESCE(gp.GTRIEB_F, 0) AS GTRIEB," + + "COALESCE(m.TGESCHIEBE, 0) AS TGESCHIEBE," + + "COALESCE(si.SIEB01, 0) AS SIEB01, COALESCE(si.SIEB02, 0) AS SIEB02," + + "COALESCE(si.SIEB03, 0) AS SIEB03, COALESCE(si.SIEB04, 0) AS SIEB04," + + "COALESCE(si.SIEB05, 0) AS SIEB05, COALESCE(si.SIEB06, 0) AS SIEB06," + + "COALESCE(si.SIEB07, 0) AS SIEB07, COALESCE(si.SIEB08, 0) AS SIEB08," + + "COALESCE(si.SIEB09, 0) AS SIEB09, COALESCE(si.SIEB10, 0) AS SIEB10," + + "COALESCE(si.SIEB11, 0) AS SIEB11, COALESCE(si.SIEB12, 0) AS SIEB12," + + "COALESCE(si.SIEB13, 0) AS SIEB13, COALESCE(si.SIEB14, 0) AS SIEB14," + + "COALESCE(si.SIEB15, 0) AS SIEB15, COALESCE(si.SIEB16, 0) AS SIEB16," + + "COALESCE(si.SIEB17, 0) AS SIEB17, COALESCE(si.SIEB18, 0) AS SIEB18," + + "COALESCE(si.SIEB19, 0) AS SIEB19, COALESCE(si.SIEB20, 0) AS SIEB20," + + "COALESCE(si.SIEB21, 0) AS SIEB21," + + "COALESCE(gs.RSIEB01, 0) AS RSIEB01, COALESCE(gs.RSIEB02, 0) AS RSIEB02," + + "COALESCE(gs.RSIEB03, 0) AS RSIEB03, COALESCE(gs.RSIEB04, 0) AS RSIEB04," + + "COALESCE(gs.RSIEB05, 0) AS RSIEB05, COALESCE(gs.RSIEB06, 0) AS RSIEB06," + + "COALESCE(gs.RSIEB07, 0) AS RSIEB07, COALESCE(gs.RSIEB08, 0) AS RSIEB08," + + "COALESCE(gs.RSIEB09, 0) AS RSIEB09, COALESCE(gs.RSIEB10, 0) AS RSIEB10," + + "COALESCE(gs.RSIEB11, 0) AS RSIEB11, COALESCE(gs.RSIEB12, 0) AS RSIEB12," + + "COALESCE(gs.RSIEB13, 0) AS RSIEB13, COALESCE(gs.RSIEB14, 0) AS RSIEB14," + + "COALESCE(gs.RSIEB15, 0) AS RSIEB15, COALESCE(gs.RSIEB16, 0) AS RSIEB16," + + "COALESCE(gs.RSIEB17, 0) AS RSIEB17, COALESCE(gs.RSIEB18, 0) AS RSIEB18," + + "COALESCE(gs.RSIEB19, 0) AS RSIEB19, COALESCE(gs.RSIEB20, 0) AS RSIEB20," + + "COALESCE(gs.RSIEB21, 0) AS RSIEB21, COALESCE(gs.REST , 0) AS REST " + "FROM MESSUNG m " + "JOIN STATION s ON m.STATIONID = s.STATIONID " + "JOIN GEWAESSER r ON s.GEWAESSERID = r.GEWAESSERID " + @@ -190,9 +190,10 @@ } public static Measurements getMeasurements( - String river, - double location, - DateRange dateRange + String river, + double location, + DateRange dateRange, + SQ.Factory sqFactory ) { Session session = SedDBSessionHolder.HOLDER.get(); try { @@ -202,7 +203,7 @@ List accumulated = loadFractions( session, river, location, dateRange); - return new Measurements(totals, accumulated); + return new Measurements(totals, accumulated, sqFactory); } finally { session.close(); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurements.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurements.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Measurements.java Thu Sep 12 10:13:09 2013 +0200 @@ -66,13 +66,17 @@ protected List measuments; protected List accumulated; + protected SQ.Factory sqFactory; + public Measurements() { } public Measurements( List measuments, - List accumulated + List accumulated, + SQ.Factory sqFactory ) { + this.sqFactory = sqFactory; if (log.isDebugEnabled()) { log.debug("number of measuments: " + measuments.size()); log.debug("number of accumulated: " + accumulated.size()); @@ -81,14 +85,14 @@ this.accumulated = accumulated; } - public static List extractSQ( + public List extractSQ( List measuments, SExtractor extractor ) { List result = new ArrayList(measuments.size()); int invalid = 0; for (Measurement measument: measuments) { - SQ sq = new SQ(extractor.getS(measument), measument.Q()); + SQ sq = sqFactory.createSQ(extractor.getS(measument), measument.Q()); if (sq.isValid()) { result.add(sq); } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQ.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQ.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQ.java Thu Sep 12 10:13:09 2013 +0200 @@ -11,8 +11,37 @@ import java.io.Serializable; +/** Represents S/Q pairs. They are immutable! */ public class SQ implements Serializable { + public interface Factory { + SQ createSQ(double s, double q); + } + + public static final Factory SQ_FACTORY = new Factory() { + @Override + public SQ createSQ(double s, double q) { + return new SQ(s, q); + } + }; + + public interface View { + double getS(SQ sq); + double getQ(SQ sq); + } + + public static final View SQ_VIEW = new View() { + @Override + public double getS(SQ sq) { + return sq.getS(); + } + + @Override + public double getQ(SQ sq) { + return sq.getQ(); + } + }; + protected double s; protected double q; @@ -29,19 +58,10 @@ return s; } - public void setS(double s) { - this.s = s; - } - - public double getQ() { return q; } - public void setQ(double q) { - this.q = q; - } - public boolean isValid() { return !Double.isNaN(s) && !Double.isNaN(q); } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationCalculation.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationCalculation.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationCalculation.java Thu Sep 12 10:13:09 2013 +0200 @@ -8,6 +8,7 @@ package org.dive4elements.river.artifacts.model.sq; +import org.dive4elements.artifacts.common.utils.StringUtils; import org.dive4elements.river.artifacts.access.SQRelationAccess; import org.dive4elements.river.artifacts.math.fitting.Function; @@ -21,6 +22,7 @@ import org.dive4elements.river.backend.SedDBSessionHolder; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.apache.log4j.Logger; @@ -30,7 +32,20 @@ private static final Logger log = Logger.getLogger(SQRelationCalculation.class); - public static final String SQ_FUNCTION_NAME = "sq-pow"; + public static final boolean NON_LINEAR_FITTING = + Boolean.getBoolean("minfo.sq.calcution.non.linear.fitting"); + + public static final String SQ_POW_FUNCTION_NAME = "sq-pow"; + public static final String SQ_LIN_FUNCTION_NAME = "linear"; + + public static final String [] EXTRA_PARAMETERS = { + "chi_sqr", + "std_dev", + "max_q", + "c_ferguson", + "c_duan", + "r2" + }; protected String river; protected double location; @@ -49,8 +64,6 @@ Double outliers = access.getOutliers(); String method = access.getOutlierMethod(); - //river = "Rhein"; - if (river == null) { // TODO: i18n addProblem("sq.missing.river"); @@ -102,31 +115,95 @@ } } + public interface TransformCoeffs { + double [] transform(double [] coeffs); + } + + public static final TransformCoeffs IDENTITY_TRANS = + new TransformCoeffs() { + @Override + public double [] transform(double [] coeffs) { + return coeffs; + } + }; + + public static final TransformCoeffs LINEAR_TRANS = + new TransformCoeffs() { + @Override + public double [] transform(double [] coeffs) { + log.debug("before transform: " + Arrays.toString(coeffs)); + if (coeffs.length == 2) { + coeffs = new double [] { Math.exp(coeffs[1]), coeffs[0] }; + } + log.debug("after transform: " + Arrays.toString(coeffs)); + return coeffs; + } + }; + protected CalculationResult internalCalculate() { - Function function = FunctionFactory + Function powFunction = FunctionFactory .getInstance() - .getFunction(SQ_FUNCTION_NAME); + .getFunction(SQ_POW_FUNCTION_NAME); - if (function == null) { - log.error("No '" + SQ_FUNCTION_NAME + "' function found."); + if (powFunction == null) { + log.error("No '" + SQ_POW_FUNCTION_NAME + "' function found."); // TODO: i18n addProblem("sq.missing.sq.function"); + return new CalculationResult(new SQResult[0], this); + } + + Function function; + SQ.View sqView; + SQ.Factory sqFactory; + ParameterCreator pc; + + if (NON_LINEAR_FITTING) { + log.debug("Use non linear fitting."); + sqView = SQ.SQ_VIEW; + sqFactory = SQ.SQ_FACTORY; + function = powFunction; + pc = new ParameterCreator( + powFunction.getParameterNames(), + powFunction.getParameterNames(), + powFunction, + sqView); + } + else { + log.debug("Use linear fitting."); + sqView = LogSQ.LOG_SQ_VIEW; + sqFactory = LogSQ.LOG_SQ_FACTORY; + function = FunctionFactory + .getInstance() + .getFunction(SQ_LIN_FUNCTION_NAME); + if (function == null) { + log.error("No '" + SQ_LIN_FUNCTION_NAME + "' function found."); + // TODO: i18n + addProblem("sq.missing.sq.function"); + return new CalculationResult(new SQResult[0], this); + } + pc = new LinearParameterCreator( + powFunction.getParameterNames(), + function.getParameterNames(), + function, + sqView); } Measurements measurements = - MeasurementFactory.getMeasurements(river, location, period); + MeasurementFactory.getMeasurements( + river, location, period, sqFactory); SQFractionResult [] fractionResults = new SQFractionResult[SQResult.NUMBER_FRACTIONS]; + for (int i = 0; i < fractionResults.length; ++i) { List sqs = measurements.getSQs(i); SQFractionResult fractionResult; List iterations = - doFitting(function, sqs); + doFitting(function, sqs, sqView, pc); if (iterations == null) { // TODO: i18n @@ -148,13 +225,15 @@ } protected List doFitting( - final Function function, - List sqs + final Function function, + List sqs, + SQ.View sqView, + final ParameterCreator pc ) { final List iterations = new ArrayList(); - boolean success = new Fitting(function, outliers).fit( + boolean success = new Fitting(function, outliers, sqView).fit( sqs, method, new Fitting.Callback() { @@ -166,11 +245,11 @@ double standardDeviation, double chiSqr ) { - Parameters parameters = createParameters( - function.getParameterNames(), + Parameters parameters = pc.createParameters( coeffs, standardDeviation, - chiSqr); + chiSqr, + measurements); iterations.add(new SQFractionResult.Iteration( parameters, measurements, @@ -181,22 +260,178 @@ return success ? iterations : null; } - public static final Parameters createParameters( - String [] names, - double [] values, - double standardDeviation, - double chiSqr - ) { - String [] columns = new String[names.length + 2]; - columns[0] = "chi_sqr"; - columns[1] = "std_dev"; - System.arraycopy(names, 0, columns, 2, names.length); - Parameters parameters = new Parameters(columns); - int row = parameters.newRow(); - parameters.set(row, names, values); - parameters.set(row, "chi_sqr", chiSqr); - parameters.set(row, "std_dev", standardDeviation); - return parameters; + public static class ParameterCreator { + + protected String [] origNames; + protected String [] proxyNames; + + protected Function function; + protected SQ.View view; + + public ParameterCreator( + String [] origNames, + String [] proxyNames, + Function function, + SQ.View view + ) { + this.origNames = origNames; + this.proxyNames = proxyNames; + this.function = function; + this.view = view; + } + + protected double [] transformCoeffs(double [] coeffs) { + return coeffs; + } + + private static double maxQ(SQ [] sqs) { + double max = -Double.MAX_VALUE; + for (SQ sq: sqs) { + double q = sq.getQ(); // Don't use view here! + if (q > max) { + max = q; + } + } + return Math.max(0d, max); + } + + private double cFerguson( + org.dive4elements.river.artifacts.math.Function instance, + SQ [] sqs + ) { + double sqrSum = 0d; + + for (SQ sq: sqs) { + double s = view.getS(sq); + double q = view.getQ(sq); + double diffS = s - instance.value(q); + sqrSum += diffS*diffS; + } + + return Math.exp(0.5d * sqrSum/(sqs.length-2)); + } + + private double cDuan( + org.dive4elements.river.artifacts.math.Function instance, + SQ [] sqs + ) { + double sum = 0d; + + for (SQ sq: sqs) { + double s = view.getS(sq); + double q = view.getQ(sq); + double diffS = s - instance.value(q); + sum += Math.exp(diffS); + } + return sum / sqs.length; + } + + private double r2( + org.dive4elements.river.artifacts.math.Function instance, + SQ [] sqs + ) { + double xm = 0; + double ym = 0; + for (SQ sq: sqs) { + double s = view.getS(sq); + double q = view.getQ(sq); + double fs = instance.value(q); + xm += s; + ym += fs; + } + xm /= sqs.length; + ym /= sqs.length; + + double mixXY = 0d; + double sumX = 0d; + double sumY = 0d; + + for (SQ sq: sqs) { + double s = view.getS(sq); + double q = view.getQ(sq); + double fs = instance.value(q); + + double xDiff = xm - s; + double yDiff = ym - fs; + + mixXY += xDiff*yDiff; + + sumX += xDiff*xDiff; + sumY += yDiff*yDiff; + } + + double r = mixXY/Math.sqrt(sumX*sumY); + return r*r; + } + + + public Parameters createParameters( + double [] coeffs, + double standardDeviation, + double chiSqr, + SQ [] measurements + ) { + String [] columns = StringUtils.join(EXTRA_PARAMETERS, origNames); + + Parameters parameters = new Parameters(columns); + int row = parameters.newRow(); + parameters.set(row, origNames, transformCoeffs(coeffs)); + parameters.set(row, "chi_sqr", chiSqr); + parameters.set(row, "std_dev", standardDeviation); + parameters.set(row, "max_q", maxQ(measurements)); + + // We need to instantiate the function to calculate + // the remaining values. + org.dive4elements.river.artifacts.math.Function f = + function.instantiate(coeffs); + + parameters.set(row, "c_ferguson", cFerguson(f, measurements)); + parameters.set(row, "c_duan", cDuan(f, measurements)); + parameters.set(row, "r2", r2(f, measurements)); + + return parameters; + } + } + + /** We need to transform the coeffs back to the original function. */ + public static class LinearParameterCreator extends ParameterCreator { + + public LinearParameterCreator( + String [] origNames, + String [] proxyNames, + Function function, + SQ.View view + ) { + super(origNames, proxyNames, function, view); + } + + @Override + protected double [] transformCoeffs(double [] coeffs) { + + int bP = StringUtils.indexOf("m", proxyNames); + int mP = StringUtils.indexOf("b", proxyNames); + + int aO = StringUtils.indexOf("a", origNames); + int bO = StringUtils.indexOf("b", origNames); + + if (bP == -1 || mP == -1 || aO == -1 || bO == -1) { + log.error("index not found: " + + bP + " " + mP + " " + + aO + " " + bO); + return coeffs; + } + + double [] ncoeffs = (double [])coeffs.clone(); + ncoeffs[aO] = Math.exp(coeffs[mP]); + ncoeffs[bO] = coeffs[bP]; + + if (log.isDebugEnabled()) { + log.debug("before transform: " + Arrays.toString(coeffs)); + log.debug("after transform: " + Arrays.toString(ncoeffs)); + } + + return ncoeffs; + } } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationJRDataSource.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationJRDataSource.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/SQRelationJRDataSource.java Thu Sep 12 10:13:09 2013 +0200 @@ -73,6 +73,12 @@ else if ("periods".equals(fieldName)) { value = metaData.get("periods"); } + else if ("msName".equals(fieldName)) { + value = metaData.get("msName"); + } + else if ("msGauge".equals(fieldName)) { + value = metaData.get("msGauge"); + } else if ("km".equals(fieldName)) { value = data.get(index)[0]; } @@ -86,12 +92,24 @@ value = data.get(index)[3]; } else if ("total".equals(fieldName)) { - value = data.get(index)[4]; + value = data.get(index)[7]; } else if ("out".equals(fieldName)) { + value = data.get(index)[8]; + } + else if ("sd".equals(fieldName)) { + value = data.get(index)[4]; + } + else if ("qmax".equals(fieldName)) { value = data.get(index)[5]; } - else if ("variance".equals(fieldName)) { + else if ("cferg".equals(fieldName)) { + value = data.get(index)[10]; + } + else if ("cduan".equals(fieldName)) { + value = data.get(index)[9]; + } + else if ("r2".equals(fieldName)) { value = data.get(index)[6]; } return value; diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/services/D4EService.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/D4EService.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/D4EService.java Thu Sep 12 10:13:09 2013 +0200 @@ -44,6 +44,7 @@ } + /** Override to do the meat work (called in processXML). */ protected abstract Document doProcess( Document data, GlobalContext globalContext, @@ -56,6 +57,7 @@ } + /** Called when processing done, close session. */ protected void shutdown() { logger.debug("shutdown"); Session session = SessionHolder.HOLDER.get(); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/services/DischargeInfoService.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/DischargeInfoService.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/DischargeInfoService.java Thu Sep 12 10:13:09 2013 +0200 @@ -40,6 +40,8 @@ public static final String GAUGE_XPATH = "/art:gauge/text()"; + public static final String RIVER_NAME_XPATH = "/art:gauge/art:river/text()"; + public DischargeInfoService() { } @@ -58,30 +60,39 @@ String gaugeNumber = XMLUtils.xpathString( data, GAUGE_XPATH, ArtifactNamespaceContext.INSTANCE); + String river = XMLUtils.xpathString( + data, RIVER_NAME_XPATH, ArtifactNamespaceContext.INSTANCE); + if (gaugeNumber == null || (gaugeNumber = gaugeNumber.trim()).length() == 0) { logger.warn("No gauge specified. Cannot return discharge info."); return XMLUtils.newDocument(); } - logger.debug("Getting discharge for gauge: " + gaugeNumber); + logger.debug("Getting discharge for gauge: " + gaugeNumber + " at river: " + river); long gn; try { gn = Long.parseLong(gaugeNumber); } catch (NumberFormatException nfe) { - logger.warn("Invalid gauge number. Cannot return discharg info."); + logger.warn("Invalid gauge number. Cannot return discharge info."); return XMLUtils.newDocument(); } - Gauge gauge = Gauge.getGaugeByOfficialNumber(gn); + Gauge gauge; + if (river == null || river.isEmpty()) { + gauge = Gauge.getGaugeByOfficialNumber(gn); + } else { + gauge = Gauge.getGaugeByOfficialNumber(gn, river); + } + if (gauge == null) { logger.warn("No such gauge found."); return XMLUtils.newDocument(); } - logger.debug("Found gauge: " + gauge.getName()); + logger.debug("Found gauge: " + gauge.getName() + " id: " + gauge.getId()); return buildDocument(gauge); } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/services/RiverInfoService.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/RiverInfoService.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/RiverInfoService.java Thu Sep 12 10:13:09 2013 +0200 @@ -37,6 +37,7 @@ protected River river; protected Element riverele; + @Override protected Document doProcess( Document data, GlobalContext globalContext, @@ -91,3 +92,4 @@ ? Double.toString(value.doubleValue()) : ""; } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/services/SedimentLoadInfoService.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/SedimentLoadInfoService.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/SedimentLoadInfoService.java Thu Sep 12 10:13:09 2013 +0200 @@ -22,6 +22,7 @@ import org.dive4elements.river.artifacts.model.minfo.SedimentLoadFactory; +/** Service delivering info about sediment loads. */ public class SedimentLoadInfoService extends D4EService { @@ -33,6 +34,10 @@ public static final String FROM_XPATH = "/art:river/art:location/art:from/text()"; public static final String TO_XPATH = "/art:river/art:location/art:to/text()"; + /** + * Create document with sedimentload infos, + * constrained by contents in data. + */ @Override protected Document doProcess( Document data, @@ -54,17 +59,18 @@ data, TO_XPATH, ArtifactNamespaceContext.INSTANCE); - double f, t; + double fromD, toD; try { - f = Double.parseDouble(from); - t = Double.parseDouble(to); + fromD = Double.parseDouble(from); + toD = Double.parseDouble(to); } catch (NumberFormatException nfe) { logger.warn("Invalid locations. Cannot return sediment loads."); return XMLUtils.newDocument(); } - SedimentLoad[] loads = SedimentLoadFactory.getLoads(river, type, f, t); + SedimentLoad[] loads = + SedimentLoadFactory.getLoads(river, type, fromD, toD); return buildDocument(loads); } @@ -98,3 +104,4 @@ return result; } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/states/FloodMapState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/FloodMapState.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/FloodMapState.java Thu Sep 12 10:13:09 2013 +0200 @@ -8,55 +8,35 @@ package org.dive4elements.river.artifacts.states; +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.LineString; +import com.vividsolutions.jts.geom.Polygon; + import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; - import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.log4j.Logger; - import org.apache.velocity.Template; - -import org.geotools.feature.FeatureCollection; -import org.geotools.feature.FeatureCollections; - -import org.geotools.feature.simple.SimpleFeatureBuilder; - -import org.hibernate.HibernateException; - -import org.opengis.feature.simple.SimpleFeature; -import org.opengis.feature.simple.SimpleFeatureType; - -import com.vividsolutions.jts.geom.Coordinate; -import com.vividsolutions.jts.geom.Geometry; -import com.vividsolutions.jts.geom.LineString; -import com.vividsolutions.jts.geom.Polygon; - import org.dive4elements.artifactdatabase.state.Facet; - import org.dive4elements.artifacts.Artifact; import org.dive4elements.artifacts.CallContext; import org.dive4elements.artifacts.CallMeta; import org.dive4elements.artifacts.GlobalContext; - import org.dive4elements.artifacts.common.utils.FileTools; - import org.dive4elements.river.artifacts.D4EArtifact; - import org.dive4elements.river.artifacts.access.RangeAccess; - import org.dive4elements.river.artifacts.context.RiverContext; - import org.dive4elements.river.artifacts.model.CalculationMessage; import org.dive4elements.river.artifacts.model.CalculationResult; import org.dive4elements.river.artifacts.model.FacetTypes; import org.dive4elements.river.artifacts.model.LayerInfo; import org.dive4elements.river.artifacts.model.WQKms; - import org.dive4elements.river.artifacts.model.map.HWS; import org.dive4elements.river.artifacts.model.map.HWSContainer; import org.dive4elements.river.artifacts.model.map.HWSFactory; @@ -64,24 +44,25 @@ import org.dive4elements.river.artifacts.model.map.WSPLGENCalculation; import org.dive4elements.river.artifacts.model.map.WSPLGENJob; import org.dive4elements.river.artifacts.model.map.WSPLGENReportFacet; - import org.dive4elements.river.artifacts.resources.Resources; - import org.dive4elements.river.exports.WstWriter; - import org.dive4elements.river.model.CrossSectionTrack; import org.dive4elements.river.model.DGM; import org.dive4elements.river.model.Floodplain; import org.dive4elements.river.model.RiverAxis; - import org.dive4elements.river.utils.ArtifactMapfileGenerator; -import org.dive4elements.river.utils.RiverUtils; import org.dive4elements.river.utils.GeometryUtils; import org.dive4elements.river.utils.MapfileGenerator; - +import org.dive4elements.river.utils.RiverUtils; import org.dive4elements.river.wsplgen.FacetCreator; import org.dive4elements.river.wsplgen.JobObserver; import org.dive4elements.river.wsplgen.Scheduler; +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.hibernate.HibernateException; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; public class FloodMapState extends DefaultState @@ -109,9 +90,9 @@ public static final String WSPLGEN_FLOODPLAIN = "talaue.shp"; public static final String WSPLGEN_WSP_FILE = "waterlevel.wst"; public static final String WSPLGEN_OUTPUT_FILE = "wsplgen.shp"; - public static final String WSPLGEN_USER_SHAPE = "user-rgd.shp"; - public static final String WSPLGEN_USER_ZIP = "user-rgd.zip"; - public static final String WSPLGEN_USER_FILENAME = "user-rgd"; + public static final String WSPLGEN_USER_RGD_SHAPE = "user-rgd.shp"; + public static final String WSPLGEN_USER_RGD_ZIP = "user-rgd.zip"; + public static final String WSPLGEN_USER_RGD = "user-rgd"; public static final String WSPLGEN_QPS_NAME = "qps"; @@ -428,7 +409,7 @@ createMapfile( artifact, artifactDir, - MapfileGenerator.MS_LAYER_PREFIX + "hws-lines", + MapfileGenerator.MS_LAYER_PREFIX + HWS_LINES, HWS_LINES_SHAPE, "LINE", "31467", @@ -441,7 +422,7 @@ } - private void createMapfile( + public static void createMapfile( D4EArtifact artifact, File artifactDir, String name, @@ -650,13 +631,13 @@ File dir, WSPLGENJob job ) { - File archive = new File(dir, WSPLGEN_USER_SHAPE); + File archive = new File(dir, WSPLGEN_USER_RGD_SHAPE); boolean exists = archive.exists(); logger.debug("shp file exists: " + exists); if (exists) { - job.addLin(dir + "/" + WSPLGEN_USER_SHAPE); + job.addLin(dir + "/" + WSPLGEN_USER_RGD_SHAPE); facetCreator.createShapeFacet(FacetCreator.I18N_USERSHAPE, - MapfileGenerator.MS_LAYER_PREFIX + "user-rgd", + MapfileGenerator.MS_LAYER_PREFIX + WSPLGEN_USER_RGD, FLOODMAP_USERSHAPE, 4); } @@ -901,11 +882,22 @@ Floodplain plain = Floodplain.getFloodplain(river); + if (plain == null) { + logger.debug("No flood plain for river '" + river + "'"); + return; + } + + Polygon polygon = plain.getGeom(); + if (polygon == null) { + logger.warn("Floodplain has no geometry."); + return; + } + SimpleFeatureType ft = GeometryUtils.buildFeatureType( "talaue", srs, Polygon.class); SimpleFeatureBuilder builder = new SimpleFeatureBuilder(ft); - builder.add(plain.getGeom()); + builder.add(polygon); FeatureCollection collection = FeatureCollections.newCollection(); collection.add(builder.buildFeature("0")); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeDischargeState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeDischargeState.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeDischargeState.java Thu Sep 12 10:13:09 2013 +0200 @@ -10,6 +10,8 @@ import java.util.List; +import java.text.DateFormat; + import org.apache.log4j.Logger; import org.dive4elements.artifacts.CallMeta; @@ -31,7 +33,10 @@ import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.DischargeTable; +import org.dive4elements.river.model.TimeInterval; +import org.dive4elements.river.utils.Formatter; /** * The only state for an GaugeDischargeState (River and km known). @@ -57,10 +62,25 @@ protected String createFacetName(GaugeDischargeArtifact artifact, CallMeta meta) { + if (artifact.getFacetWishName() != null) { + /* We let the Artifact overwrite our name as this allows + * injecting the facet name from the Datacage */ + return artifact.getFacetWishName(); + } + Gauge gauge = artifact.getGauge(); + DischargeTable mdt = gauge.fetchMasterDischargeTable(); + TimeInterval validity = mdt.getTimeInterval(); + DateFormat df = Formatter.getDateFormatter(meta, "dd.MM.yyyy"); + String start = validity.getStartTime() != null ? + df.format(validity.getStartTime()) : "Unknown"; + String stop = validity.getStopTime() != null ? + df.format(validity.getStopTime()) : ""; + Object[] args = new Object[] { gauge.getName(), - gauge.getStation() + start, + stop }; String name = Resources.getMsg( diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeTimerangeState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeTimerangeState.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/GaugeTimerangeState.java Thu Sep 12 10:13:09 2013 +0200 @@ -67,7 +67,8 @@ } } - logger.warn("Could not determine time range for gauge: " + gauge); + logger.warn("Could not determine time range for gauge: " + gauge.getName() + + " id: " + gauge.getId()); return null; } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/states/HWSBarriersState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/HWSBarriersState.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/HWSBarriersState.java Thu Sep 12 10:13:09 2013 +0200 @@ -9,51 +9,29 @@ package org.dive4elements.river.artifacts.states; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; - -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import org.apache.log4j.Logger; - -import org.apache.velocity.Template; - -import org.geotools.data.shapefile.ShapefileDataStore; - -import org.geotools.feature.FeatureCollection; -import org.geotools.feature.FeatureCollections; - -import org.opengis.feature.simple.SimpleFeatureType; - -import org.opengis.feature.type.GeometryDescriptor; - -import org.w3c.dom.Element; - import org.dive4elements.artifactdatabase.state.Facet; - import org.dive4elements.artifacts.Artifact; import org.dive4elements.artifacts.CallContext; - import org.dive4elements.artifacts.common.utils.FileTools; - import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; - import org.dive4elements.river.artifacts.D4EArtifact; - import org.dive4elements.river.artifacts.access.MapAccess; - -import org.dive4elements.river.artifacts.model.LayerInfo; - import org.dive4elements.river.artifacts.model.map.HWS; import org.dive4elements.river.artifacts.model.map.HWSContainer; import org.dive4elements.river.artifacts.model.map.HWSFactory; - -import org.dive4elements.river.utils.ArtifactMapfileGenerator; -import org.dive4elements.river.utils.RiverUtils; import org.dive4elements.river.utils.GeometryUtils; import org.dive4elements.river.utils.MapfileGenerator; +import org.dive4elements.river.utils.RiverUtils; +import org.geotools.data.shapefile.ShapefileDataStore; +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.feature.type.GeometryDescriptor; +import org.w3c.dom.Element; public class HWSBarriersState extends DefaultState @@ -63,9 +41,8 @@ private static Logger logger = Logger.getLogger(HWSBarriersState.class); private static final String HWS_SHAPEFILE_LINES = "hws-lines.shp"; private static final String HWS_SHAPEFILE_POINTS = "hws-points.shp"; - private static final String USER_RGD_SHAPE = "user-rgd.shp"; - private static final String USER_RGD_ZIP = "user-rgd.zip"; - private static final String USER_RGD_FILENAME = "user-rgd"; + + @Override protected String getUIProvider() { return "map_digitize"; @@ -146,7 +123,7 @@ } if (successLines) { - createMapfile( + FloodMapState.createMapfile( artifact, artifactDir, MapfileGenerator.MS_LAYER_PREFIX + "hws-lines", @@ -156,7 +133,7 @@ "hws"); } if (successPoints) { - createMapfile( + FloodMapState.createMapfile( artifact, artifactDir, MapfileGenerator.MS_LAYER_PREFIX + "hws-points", @@ -172,7 +149,7 @@ try { ShapefileDataStore store = new ShapefileDataStore( new File(artifactDir.getCanonicalPath() + - "/" + USER_RGD_SHAPE) + "/" + FloodMapState.WSPLGEN_USER_RGD_SHAPE) .toURI().toURL()); GeometryDescriptor desc = store.getSchema().getGeometryDescriptor(); @@ -201,14 +178,14 @@ else { type = "POINT"; } - createMapfile( + FloodMapState.createMapfile( artifact, artifactDir, - MapfileGenerator.MS_LAYER_PREFIX + USER_RGD_FILENAME, - USER_RGD_SHAPE, + MapfileGenerator.MS_LAYER_PREFIX + FloodMapState.WSPLGEN_USER_RGD, + FloodMapState.WSPLGEN_USER_RGD_SHAPE, type, epsg, - "user-rgd"); + FloodMapState.WSPLGEN_USER_RGD); } catch (IOException e) { logger.warn("No mapfile for user-rgd created!"); @@ -219,7 +196,7 @@ } private boolean extractUserShp(File dir) { - File archive = new File(dir, USER_RGD_ZIP); + File archive = new File(dir, FloodMapState.WSPLGEN_USER_RGD_ZIP); boolean exists = archive.exists(); logger.debug("Zip file exists: " + exists); if (exists) { @@ -231,7 +208,7 @@ } catch (IOException ioe) { logger.warn("Zip archive " + dir + "/" - + USER_RGD_ZIP + " could not be extracted."); + + FloodMapState.WSPLGEN_USER_RGD_ZIP + " could not be extracted."); return false; } } @@ -261,7 +238,7 @@ return true; } try { - FileTools.copyFile(file, new File(target, USER_RGD_FILENAME + "." + suffix)); + FileTools.copyFile(file, new File(target, FloodMapState.WSPLGEN_USER_RGD + "." + suffix)); } catch (IOException ioe) { logger.warn ("Error while copying file " + file.getName()); @@ -275,41 +252,6 @@ FileTools.deleteRecursive(source); } - private void createMapfile( - D4EArtifact artifact, - File artifactDir, - String name, - String hwsShapefile, - String type, - String srid, - String group - ) { - LayerInfo info = new LayerInfo(); - info.setName(name + artifact.identifier()); - info.setType(type); - info.setDirectory(artifact.identifier()); - info.setTitle(name); - info.setData(hwsShapefile); - info.setSrid(srid); - info.setGroupTitle(group); - MapfileGenerator generator = new ArtifactMapfileGenerator(); - Template tpl = generator.getTemplateByName(MapfileGenerator.SHP_LAYER_TEMPLATE); - try { - File layer = new File(artifactDir.getCanonicalPath() + "/" + name); - generator.writeLayer(info, layer, tpl); - List layers = new ArrayList(); - layers.add(layer.getAbsolutePath()); - generator.generate(); - } - catch(FileNotFoundException fnfe) { - logger.warn("Could not find mapfile for hws layer"); - } - catch (Exception ioe) { - logger.warn("Could not create mapfile for hws layer"); - logger.warn(Arrays.toString(ioe.getStackTrace())); - } - } - @Override public void endOfLife(Artifact artifact, Object callContext) { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WDifferencesState.java Thu Sep 12 10:13:09 2013 +0200 @@ -18,10 +18,12 @@ import org.dive4elements.artifacts.CallContext; import org.dive4elements.artifacts.Artifact; +import org.dive4elements.river.artifacts.ChartArtifact; import org.dive4elements.river.artifacts.D4EArtifact; +import org.dive4elements.river.artifacts.FixationArtifact; +import org.dive4elements.river.artifacts.MINFOArtifact; import org.dive4elements.river.artifacts.StaticWKmsArtifact; import org.dive4elements.river.artifacts.WINFOArtifact; -import org.dive4elements.river.artifacts.ChartArtifact; import org.dive4elements.river.artifacts.math.WKmsOperation; @@ -29,15 +31,16 @@ import org.dive4elements.river.artifacts.model.DataFacet; import org.dive4elements.river.artifacts.model.DifferenceCurveFacet; import org.dive4elements.river.artifacts.model.EmptyFacet; - import org.dive4elements.river.artifacts.model.FacetTypes; import org.dive4elements.river.artifacts.model.WKms; import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.fixings.FixRealizingResult; + import org.dive4elements.river.utils.RiverUtils; import org.dive4elements.river.utils.StringUtil; - +/** State of a WINFOArtifact to get differences of data of other artifacts. */ public class WDifferencesState extends DefaultState implements FacetTypes @@ -76,9 +79,10 @@ /** - * Access the data (wkms). + * Access the data (wkms) of an artifact, coded in mingle. */ protected WKms getWKms(String mingle, CallContext context) { + logger.debug("WDifferencesState.getWKms " + mingle); String[] def = mingle.split(";"); String uuid = def[0]; String name = def[1]; @@ -96,23 +100,45 @@ return wkms; } - WINFOArtifact flys = (WINFOArtifact) RiverUtils.getArtifact( + D4EArtifact d4eArtifact = RiverUtils.getArtifact( uuid, context); - if (flys == null) { + if (d4eArtifact == null) { logger.warn("One of the artifacts (1) for diff calculation could not be loaded"); return null; } - else{ - WQKms[] wqkms = (WQKms[]) flys.getWaterlevelData(). + + if (d4eArtifact instanceof WINFOArtifact) { + logger.debug("Get WKms from WINFOArtifact"); + WINFOArtifact flys = (WINFOArtifact) d4eArtifact; + + WKms[] wkms = (WKms[]) flys.getWaterlevelData(context). getData(); - if (wqkms == null) - logger.warn("not waterlevels in artifact"); - else if (wqkms.length < idx) - logger.warn("not enough waterlevels in artifact"); - return wqkms[idx]; + if (wkms == null || wkms.length == 0) { + logger.warn("no waterlevels in artifact"); + } + else if (wkms.length < idx+1) { + logger.warn("Not enough waterlevels in artifact."); + return new WQKms(); + } + return wkms[idx]; } + else if (d4eArtifact instanceof MINFOArtifact) { + logger.debug("Get WKms from MINFOArtifact"); + CalculationResult r = (CalculationResult) + d4eArtifact.compute(context, ComputeType.ADVANCE, false); + } + else if (d4eArtifact instanceof FixationArtifact) { + logger.debug ("Get WKms from FixationArtifact."); + CalculationResult r = (CalculationResult) + d4eArtifact.compute(context, ComputeType.ADVANCE, false); + FixRealizingResult frR = (FixRealizingResult) r.getData(); + return frR.getWQKms()[idx]; + } + + logger.error("Do not know how to handle (getWKms) minuend/subtrahend"); + return null; } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelState.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/WaterlevelState.java Thu Sep 12 10:13:09 2013 +0200 @@ -138,6 +138,7 @@ return res; } + /** Returns empty String if argument is null, argument itself otherwise. */ private static final String nn(String s) { return s != null ? s : ""; } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixAnalysisCompute.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixAnalysisCompute.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/fixation/FixAnalysisCompute.java Thu Sep 12 10:13:09 2013 +0200 @@ -9,6 +9,7 @@ package org.dive4elements.river.artifacts.states.fixation; import java.text.DateFormat; +import java.util.Collection; import java.util.Date; import java.util.List; @@ -41,7 +42,9 @@ import org.dive4elements.river.artifacts.model.fixings.FixWQCurveFacet; import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.utils.Formatter; import org.dive4elements.river.utils.IdGenerator; +import org.dive4elements.river.utils.UniqueDateFormatter; /** * @author Raimund Renkert @@ -76,8 +79,6 @@ "fix.hq5" }; - // TODO Why does this happen here? In other cases its implemented in the - // respective artifact, not State. static { // Active/deactivate facets. FacetActivity.Registry.getInstance().register( @@ -171,15 +172,15 @@ int qsS = access.getQSectorStart(); int qsE = access.getQSectorEnd(); - // TODO: i18n - DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM); + DateFormat df = Formatter.getDateFormatter(context.getMeta(), "dd.MM.yyyy"); + DateFormat lf = Formatter.getDateFormatter(context.getMeta(), "dd.MM.yyy'T'HH:mm"); DateRange [] periods = access.getAnalysisPeriods(); for (int i = 0; i < periods.length; i++) { DateRange period = periods[i]; String startDate = df.format(period.getFrom()); - String endDate = df.format(period.getTo()); + String endDate = df.format(period.getTo()); for (int j = qsS; j <= qsE; j++) { @@ -233,19 +234,22 @@ I18N_ANALYSIS, I18N_ANALYSIS); + Collection aeds = fr.getAnalysisEventsDates(i); + UniqueDateFormatter cf = new UniqueDateFormatter(df, lf, aeds); + int k = 0; - for (Date d: fr.getAnalysisEventsDates(i)) { + for (Date d: aeds) { int anaNdx = i << 8; anaNdx = anaNdx | k; facets.add(new FixAnalysisEventsFacet(anaNdx, FIX_ANALYSIS_EVENTS_DWT, - eventDesc + (i+1) + " - " + df.format(d))); + eventDesc + (i+1) + " - " + cf.format(d))); facets.add(new FixLongitudinalAnalysisFacet(anaNdx, FIX_ANALYSIS_EVENTS_LS, - eventDesc + (i+1) + " - " + df.format(d))); + eventDesc + (i+1) + " - " + cf.format(d))); facets.add(new FixAnalysisEventsFacet(anaNdx, FIX_ANALYSIS_EVENTS_WQ, - eventDesc + (i+1) +" - " + df.format(d))); + eventDesc + (i+1) +" - " + cf.format(d))); k++; } } @@ -259,27 +263,29 @@ I18N_REFERENCEDEVIATION, I18N_REFERENCEDEVIATION); + Collection reds = fr.getReferenceEventsDates(); + UniqueDateFormatter cf = new UniqueDateFormatter(df, lf, reds); + int i = 0; - for (Date d: fr.getReferenceEventsDates()) { + for (Date d: reds) { int refNdx = idg.next() << 8; refNdx |= i; facets.add(new FixReferenceEventsFacet(refNdx, FIX_REFERENCE_EVENTS_DWT, - i18n_ref + " - " + df.format(d))); + i18n_ref + " - " + cf.format(d))); refNdx = idg.next() << 8; refNdx = refNdx | i; facets.add(new FixLongitudinalReferenceFacet(refNdx, FIX_REFERENCE_EVENTS_LS, - i18n_ref + " - " + df.format(d))); + i18n_ref + " - " + cf.format(d))); refNdx = idg.next() << 8; refNdx |= i; facets.add(new FixReferenceEventsFacet(refNdx, FIX_REFERENCE_EVENTS_WQ, - i18n_ref + " - " + df.format(d))); + i18n_ref + " - " + cf.format(d))); i++; } - facets.add(new FixLongitudinalDeviationFacet(idg.next(), FIX_DEVIATION_LS, i18n_dev)); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/DifferencesState.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/DifferencesState.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/DifferencesState.java Thu Sep 12 10:13:09 2013 +0200 @@ -37,6 +37,7 @@ import org.dive4elements.river.utils.Formatter; /** + * State for BedDifferences. * @author Raimund Renkert */ public class DifferencesState @@ -68,7 +69,7 @@ @Override public Object computeAdvance(D4EArtifact artifact, String hash, CallContext context, List facets, Object old) { - logger.debug("BedQualityState.computeAdvance"); + logger.debug("DifferencesState.computeAdvance"); List newFacets = new ArrayList(); @@ -97,9 +98,15 @@ return res; } - protected void generateFacets(CallContext context, List newFacets, - BedDifferencesResult[] results, String stateId, String hash) { - logger.debug("BedQualityState.generateFacets"); + /** Generate Facets based on given results. */ + protected void generateFacets( + CallContext context, + List newFacets, + BedDifferencesResult[] results, + String stateId, + String hash + ) { + logger.debug("DifferencesState.generateFacets"); CallMeta meta = context.getMeta(); @@ -120,9 +127,7 @@ newFacets.add(new BedDiffYearFacet( idx, BED_DIFFERENCE_MORPH_WIDTH, - createBedDiffMorphDescription( - meta, - (BedDiffYearResult)results[idx]), + createBedDiffMorphDescription(meta), ComputeType.ADVANCE, stateId, hash)); @@ -335,12 +340,9 @@ } protected String createBedDiffMorphDescription( - CallMeta meta, - BedDiffYearResult result) { - String range = result.getStart() + " - " + result.getEnd(); - + CallMeta meta) { return Resources.getMsg(meta, I18N_FACET_BED_DIFF_MORPH, - I18N_FACET_BED_DIFF_MORPH, new Object[] { range }); + I18N_FACET_BED_DIFF_MORPH); } protected String createBedDiffAbsoluteDescription( @@ -412,3 +414,4 @@ }); } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadCalculate.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadCalculate.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadCalculate.java Thu Sep 12 10:13:09 2013 +0200 @@ -21,6 +21,7 @@ import org.dive4elements.river.artifacts.D4EArtifact; import org.dive4elements.river.artifacts.access.SedimentLoadAccess; import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.DataFacet; import org.dive4elements.river.artifacts.model.FacetTypes; import org.dive4elements.river.artifacts.model.ReportFacet; import org.dive4elements.river.artifacts.model.minfo.SedimentLoad; @@ -33,7 +34,7 @@ import org.dive4elements.river.artifacts.states.DefaultState; import org.dive4elements.river.utils.DateGuesser; - +/** State in which Sediment Load(s) are calculated/retrieved. */ public class SedimentLoadCalculate extends DefaultState implements FacetTypes @@ -73,7 +74,7 @@ name.equals(SEDIMENT_LOAD_SUSP_SAND_BED)){ return Boolean.FALSE; } - else if (name.equals(SEDIMENT_LOAD_UNKOWN)) { + else if (name.equals(SEDIMENT_LOAD_UNKNOWN)) { D4EArtifact d4e = (D4EArtifact)artifact; SedimentLoadUnknownFacet f = (SedimentLoadUnknownFacet) @@ -139,10 +140,6 @@ return res; } - String river = access.getRiver(); - SedimentLoad[] unknown = - SedimentLoadFactory.getSedimentLoadUnknown(river); - String type = access.getYearEpoch(); if (type.equals("year")) { generateYearFacets(context, newFacets, results, getID(), hash); @@ -154,6 +151,12 @@ generateOffEpochFacets(context, newFacets, results, getID(), hash); } logger.debug("Created " + newFacets.size() + " new Facets."); + + String river = access.getRiver(); + SedimentLoad[] unknown = + SedimentLoadFactory.getSedimentLoadUnknown(river, + access.getUnit().replace("_per_","/"), type); + if (res.getReport().hasProblems()) { newFacets.add(new ReportFacet(ComputeType.ADVANCE, hash, id)); } @@ -161,12 +164,16 @@ for (int i = 0; i < unknown.length; i++) { newFacets.add(new SedimentLoadUnknownFacet( i, - SEDIMENT_LOAD_UNKOWN, + SEDIMENT_LOAD_UNKNOWN, unknown[i].getDescription(), ComputeType.ADVANCE, getID(), hash)); } + + newFacets.add( + new DataFacet(CSV, "CSV data", ComputeType.ADVANCE, hash, id)); + facets.addAll(newFacets); return res; @@ -520,3 +527,4 @@ } } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadOffEpochSelect.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadOffEpochSelect.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadOffEpochSelect.java Thu Sep 12 10:13:09 2013 +0200 @@ -12,7 +12,7 @@ import org.dive4elements.river.artifacts.states.DefaultState; - +/** State in which official epoch is selected to calculate sediment load. */ public class SedimentLoadOffEpochSelect extends DefaultState { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/collections/AttributeParser.java --- a/artifacts/src/main/java/org/dive4elements/river/collections/AttributeParser.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/collections/AttributeParser.java Thu Sep 12 10:13:09 2013 +0200 @@ -51,6 +51,7 @@ protected CollectionAttribute attribute; + /** Just store reference to document. */ public AttributeParser(Document attributeDocument) { this.attributeDocument = attributeDocument; } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/collections/AttributeWriter.java --- a/artifacts/src/main/java/org/dive4elements/river/collections/AttributeWriter.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/collections/AttributeWriter.java Thu Sep 12 10:13:09 2013 +0200 @@ -46,7 +46,7 @@ protected List newFacets; /** - * "Compatibility matrix", mapws list of facet names to output names. + * "Compatibility matrix", maps list of facet names to output names. * Any facet that is not found in the list for a specific output will * not be added to the resulting document. */ @@ -211,7 +211,12 @@ ManagedFacet picked = pickFacet(facet, oldFacets); if (facet.equals(picked)) { - genuinelyNewFacets.add(picked); + if (!facetInTwoOuts(facet, genuinelyNewFacets)) { + genuinelyNewFacets.add(picked); + } + else { + logger.debug("Skip clone facet that shall be present in two outs"); + } } else { currentFacets.add(picked); @@ -260,17 +265,20 @@ // Preparations to be able to detect gaps. Map mfmap = new HashMap(); - int max = 0; + int maxPosition = 0; for (ManagedFacet mf: currentFacets) { int pos = mf.getPosition(); mfmap.put(Integer.valueOf(pos), mf); - if (pos > max) max = pos; + if (pos > maxPosition) maxPosition = pos; } - // Finally do gap correction. - if (max != currentFacets.size()) { + // TODO issue1458: debug what happens + + // Finally do gap correction + // (note that posistions start at 1, not at zero). + if (maxPosition != currentFacets.size()) { int gap = 0; - for (int i = 1; i <= max; i++) { + for (int i = 1; i <= maxPosition; i++) { ManagedFacet mf = mfmap.get(Integer.valueOf(i)); if (mf == null) { gap++; @@ -281,14 +289,27 @@ } // Now add all facets. - for (ManagedFacet oldMF: currentFacets) { - attribute.addFacet(outputName, oldMF); + for (ManagedFacet facet: currentFacets) { + attribute.addFacet(outputName, facet); } return !currentFacets.isEmpty(); } + /** Returns true if a likely clone of facet is + * contained in genuinelyNewFacets, as happens when same facet is defined + * for two outs. */ + private boolean facetInTwoOuts(ManagedFacet facet, List genuinelyNewFacets) { + for (ManagedFacet otherFacet: genuinelyNewFacets) { + if (facet.isSame(otherFacet)) { + return true; + } + } + return false; + } + + /** * Returns the facet to be added to Document. * Return the new facet only if the "same" facet was not present before. diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/collections/CollectionAttribute.java --- a/artifacts/src/main/java/org/dive4elements/river/collections/CollectionAttribute.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/collections/CollectionAttribute.java Thu Sep 12 10:13:09 2013 +0200 @@ -66,6 +66,7 @@ } + /** Remove outputs without facets from outputMap. */ public void cleanEmptyOutputs() { if (outputMap == null) { return; @@ -95,14 +96,14 @@ } if (outputMap == null) { - logger.warn("Tried to add facet but no Outputs are existing yet."); + logger.warn("Tried to add settings but no Outputs are existing yet."); return; } Output output = outputMap.get(outputKey); if (output == null) { - logger.warn("Tried to add facet for unknown Output: " + outputKey); + logger.warn("Tried to add settings for unknown Output: " + outputKey); return; } @@ -112,7 +113,7 @@ public void addFacet(String outputKey, Facet facet) { if (facet == null) { - logger.warn("Tried to add empty facet."); + logger.warn("Tried to add null facet."); return; } @@ -139,6 +140,7 @@ } + /** Empty facets list for outputKey output. */ public void clearFacets(String outputKey) { if (outputKey == null || outputKey.length() == 0) { logger.warn("Tried to clear Facets, but no Output key specified!"); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/collections/D4EArtifactCollection.java --- a/artifacts/src/main/java/org/dive4elements/river/collections/D4EArtifactCollection.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/collections/D4EArtifactCollection.java Thu Sep 12 10:13:09 2013 +0200 @@ -74,6 +74,22 @@ public static final String XPATH_LOADED_RECOMMENDATIONS = "/art:attribute/art:loaded-recommendations"; + private CallContext context; + + private ArtifactDatabase db; + + protected CallContext getContext() { + return this.context; + } + + protected ArtifactDatabase getArtifactDB() { + return this.db; + } + + protected void setContext(CallContext context) { + this.context = context; + this.db = context.getDatabase(); + } /** * Create and return description Document for this collection. @@ -82,26 +98,26 @@ public Document describe(CallContext context) { log.debug("D4EArtifactCollection.describe: " + identifier); + setContext(context); + CollectionDescriptionHelper helper = new CollectionDescriptionHelper( getName(), identifier(), getCreationTime(), getTTL(), context); - ArtifactDatabase db = context.getDatabase(); Document oldAttrs = getAttribute(); AttributeParser parser = new AttributeParser(oldAttrs); try { - String[] aUUIDs = getArtifactUUIDs(context); + String[] aUUIDs = getArtifactUUIDs(); - oldAttrs = removeAttributes(oldAttrs, context); + oldAttrs = removeAttributes(oldAttrs); parser = new AttributeParser(oldAttrs); - CollectionAttribute newAttr = mergeAttributes( - db, context, parser, aUUIDs); + CollectionAttribute newAttr = mergeAttributes(parser, aUUIDs); - if (checkOutputSettings(newAttr, context)) { - saveCollectionAttribute(db, context, newAttr); + if (checkOutputSettings(newAttr)) { + saveCollectionAttribute(newAttr); } helper.setAttribute(newAttr); @@ -129,13 +145,11 @@ * @param uuids Artifact uuids. */ protected CollectionAttribute mergeAttributes( - ArtifactDatabase db, - CallContext context, AttributeParser oldParser, String[] uuids ) { CollectionAttribute cAttribute = - buildOutAttributes(db, context, oldParser, uuids); + buildOutAttributes(oldParser, uuids); if (cAttribute == null) { log.warn("mergeAttributes: cAttribute == null"); @@ -145,13 +159,19 @@ cAttribute.setLoadedRecommendations( getLoadedRecommendations(oldParser.getAttributeDocument())); - saveCollectionAttribute(db, context, cAttribute); + saveCollectionAttribute(cAttribute); return cAttribute; } - protected Document removeAttributes(Document attrs, CallContext context) { + /** + * Remove those output-elements which have a name that does + * not appear in master artifacts out-list. + * @param attr[in,out] Document to clean and return. + * @return param attr. + */ + protected Document removeAttributes(Document attrs) { Node outs = (Node) XMLUtils.xpath( attrs, "/art:attribute/art:outputs", @@ -167,7 +187,7 @@ if (nodes != null) { for (int i = 0; i < nodes.getLength(); i++) { Element e = (Element)nodes.item(i); - if(!outputExists(e.getAttribute("name"), context)) { + if(!outputExists(e.getAttribute("name"))) { outs.removeChild(e); } } @@ -182,9 +202,9 @@ * @param context current context * @return true if current master artifact has given output. */ - protected boolean outputExists(String name, CallContext context) { - D4EArtifact master = getMasterArtifact(context); - List outList = master.getOutputs(context); + protected boolean outputExists(String name) { + D4EArtifact master = getMasterArtifact(); + List outList = master.getOutputs(getContext()); for (Output o : outList) { if (name.equals(o.getName())) { @@ -203,8 +223,6 @@ * @return true, if the transaction was successful, otherwise false. */ protected boolean saveCollectionAttribute( - ArtifactDatabase db, - CallContext context, CollectionAttribute attribute ) { log.info("Save new CollectionAttribute into database."); @@ -213,7 +231,7 @@ try { // Save the merged document into database. - db.setCollectionAttribute(identifier(), context.getMeta(), doc); + getArtifactDB().setCollectionAttribute(identifier(), getContext().getMeta(), doc); log.info("Saving CollectionAttribute was successful."); @@ -254,8 +272,7 @@ * @return true, if the CollectionAttribute was modified, otherwise false. */ protected boolean checkOutputSettings( - CollectionAttribute attribute, - CallContext cc + CollectionAttribute attribute ) { boolean modified = false; @@ -281,7 +298,7 @@ if (settings == null) { log.debug("No Settings set for Output '" + outName + "'."); output.setSettings( - createInitialOutputSettings(cc, attribute, outName)); + createInitialOutputSettings(attribute, outName)); modified = true; } @@ -302,11 +319,10 @@ * @return a default Settings object for the specified Output. */ protected Settings createInitialOutputSettings( - CallContext cc, CollectionAttribute attr, String out ) { - OutGenerator outGen = RiverContext.getOutGenerator(cc, out, null); + OutGenerator outGen = RiverContext.getOutGenerator(getContext(), out, null); if (outGen == null) { return null; @@ -314,13 +330,13 @@ // XXX NOTE: the outGen is not able to process its generate() operation, // because it has no OutputStream set! - outGen.init(XMLUtils.newDocument(), null, cc); - prepareMasterArtifact(outGen, cc); + outGen.init(XMLUtils.newDocument(), null, getContext()); + prepareMasterArtifact(outGen); try { - Document outAttr = getAttribute(cc, attr, out); + Document outAttr = getAttribute(attr, out); OutputHelper helper = new OutputHelper(identifier()); - helper.doOut(outGen, out, out, outAttr, cc); + helper.doOut(outGen, out, out, outAttr, getContext()); } catch (ArtifactDatabaseException adbe) { log.error(adbe, adbe); @@ -343,6 +359,8 @@ { boolean debug = log.isDebugEnabled(); + setContext(context); + long reqBegin = System.currentTimeMillis(); if (debug) { @@ -362,6 +380,8 @@ log.debug("-> Output subtype = " + subtype); } + // If type contains 'chartinfo' use a generator that + // just allow access to width, height etc. OutGenerator generator = null; if (type != null && type.length() > 0 @@ -400,10 +420,10 @@ generator.init(format, out, context); generator.setSettings(settings); generator.setCollection(this); - prepareMasterArtifact(generator, context); + prepareMasterArtifact(generator); try { - Document attr = getAttribute(context, cAttr, name); + Document attr = getAttribute(cAttr, name); OutputHelper helper = new OutputHelper(identifier()); if (name.equals("sq_overview")) { helper.doOut(generator, name, subtype, format, context); @@ -426,12 +446,11 @@ * Sets the master Artifact at the given generator. * * @param generator The generator that gets a master Artifact. - * @param cc The CallContext. */ - protected void prepareMasterArtifact(OutGenerator generator, CallContext cc + protected void prepareMasterArtifact(OutGenerator generator ) { // Get master artifact. - D4EArtifact master = getMasterArtifact(cc); + D4EArtifact master = getMasterArtifact(); if (master != null) { log.debug("Set master Artifact to uuid: " + master.identifier()); generator.setMasterArtifact(master); @@ -445,18 +464,18 @@ /** * @return masterartifact or null if exception/not found. */ - protected D4EArtifact getMasterArtifact(CallContext context) + protected D4EArtifact getMasterArtifact() { try { - ArtifactDatabase db = context.getDatabase(); - CallMeta callMeta = context.getMeta(); + ArtifactDatabase db = getArtifactDB(); + CallMeta callMeta = getContext().getMeta(); Document document = db.getCollectionsMasterArtifact( identifier(), callMeta); String masterUUID = XMLUtils.xpathString( document, XPATH_MASTER_UUID, ArtifactNamespaceContext.INSTANCE); D4EArtifact masterArtifact = - (D4EArtifact) getArtifact(masterUUID, context); + (D4EArtifact) getArtifact(masterUUID); return masterArtifact; } catch (ArtifactDatabaseException ade) { @@ -471,8 +490,6 @@ * @param uuids List of artifact uuids. */ protected CollectionAttribute buildOutAttributes( - ArtifactDatabase db, - CallContext context, AttributeParser aParser, String[] uuids) { @@ -485,14 +502,16 @@ return null; } - D4EArtifact masterArtifact = getMasterArtifact(context); + D4EArtifact masterArtifact = getMasterArtifact(); if (masterArtifact == null) { log.debug("buildOutAttributes: masterArtifact == null"); return null; } - OutputParser oParser = new OutputParser(db, context); + OutputParser oParser = new OutputParser( + getArtifactDB(), + getContext()); if (uuids != null) { for (String uuid: uuids) { @@ -508,7 +527,7 @@ aParser.parse(); AttributeWriter aWriter = new AttributeWriter( - db, + getArtifactDB(), aParser.getCollectionAttribute(), aParser.getOuts(), aParser.getFacets(), @@ -531,7 +550,6 @@ * @return the attribute for the desired output type. */ protected Document getAttribute( - CallContext context, CollectionAttribute cAttr, String output) throws ArtifactDatabaseException @@ -570,13 +588,13 @@ * * @return a list of uuids. */ - protected String[] getArtifactUUIDs(CallContext context) + protected String[] getArtifactUUIDs() throws ArtifactDatabaseException { log.debug("D4EArtifactCollection.getArtifactUUIDs"); - ArtifactDatabase db = context.getDatabase(); - CallMeta meta = context.getMeta(); + ArtifactDatabase db = getArtifactDB(); + CallMeta meta = getContext().getMeta(); Document itemList = db.listCollectionArtifacts(identifier(), meta); NodeList items = (NodeList) XMLUtils.xpath( @@ -617,7 +635,7 @@ * * @return an Artifact. */ - protected Artifact getArtifact(String uuid, CallContext context) + protected Artifact getArtifact(String uuid) throws ArtifactDatabaseException { log.debug("D4EArtifactCollection.getArtifact"); @@ -628,6 +646,44 @@ return persistent != null ? persistent.getArtifact() : null; } + /** + * Returns artifacts with name name. + * + * @param name The Artifact name to search + * @param context The CallContext + * + * @return a list of artifacts matching this name. + */ + public List getArtifactsByName(String name, CallContext context) + { + setContext(context); + return getArtifactsByName(name); + } + + /** + * Returns artifacts with name name. + * + * @param name The Artifact name to search + * + * @return a list of artifacts matching this name. + */ + protected List getArtifactsByName(String name) + { + log.debug("Searching for Artifacts: " + name); + List ret = new ArrayList(); + try { + for (String uuid: getArtifactUUIDs()) { + D4EArtifact subArt = (D4EArtifact) getArtifact(uuid); + if (subArt.getName() != null && subArt.getName().equals(name)) { + ret.add(subArt); + } + } + } catch (ArtifactDatabaseException e) { + log.error("Unexpected Error!", e); + } finally { + return ret; + } + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/ATExporter.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/ATExporter.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/ATExporter.java Thu Sep 12 10:13:09 2013 +0200 @@ -30,6 +30,7 @@ import org.dive4elements.river.model.Gauge; import org.dive4elements.river.model.River; import org.dive4elements.river.model.TimeInterval; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.RiverUtils; import org.dive4elements.river.artifacts.access.RangeAccess; @@ -71,8 +72,8 @@ @Override public void doOut( ArtifactAndFacet artifactf, - Document attr, - boolean visible + ThemeDocument attr, + boolean visible ) { data = (WQ)artifactf.getData(context); } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/AbstractExporter.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/AbstractExporter.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/AbstractExporter.java Thu Sep 12 10:13:09 2013 +0200 @@ -32,6 +32,7 @@ import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.collections.D4EArtifactCollection; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.Formatter; @@ -158,7 +159,7 @@ @Override public void doOut( ArtifactAndFacet artifactFacet, - Document attr, + ThemeDocument attr, boolean visible ) { String name = artifactFacet.getFacetName(); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -33,9 +33,8 @@ import org.dive4elements.river.model.River; import org.dive4elements.river.themes.LineStyle; import org.dive4elements.river.themes.TextStyle; -import org.dive4elements.river.themes.ThemeAccess; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.RiverUtils; -import org.dive4elements.river.utils.ThemeUtil; import java.awt.BasicStroke; import java.awt.Color; @@ -198,7 +197,7 @@ ChartArea area, LineStyle lineStyle, TextStyle textStyle, - Document theme + ThemeDocument theme ) { // OPTIMIZE pre-calculate area-related values final float TEXT_OFF = 0.03f; @@ -249,7 +248,7 @@ area2, annotation.getPos(), lineStyle); if (!Float.isNaN(annotation.getHitPoint()) && theme != null) { // New line annotation to hit curve. - if (ThemeUtil.parseShowVerticalLine(theme)) { + if (theme.parseShowVerticalLine()) { XYLineAnnotation hitLineAnnotation = createStickyLineAnnotation( StickyAxisAnnotation.SimpleAxis.X_AXIS, @@ -258,7 +257,7 @@ plot.getRenderer(rendererIndex).addAnnotation(hitLineAnnotation, org.jfree.ui.Layer.BACKGROUND); } - if (ThemeUtil.parseShowHorizontalLine(theme)) { + if (theme.parseShowHorizontalLine()) { XYLineAnnotation lineBackAnnotation = createStickyLineAnnotation( StickyAxisAnnotation.SimpleAxis.Y_AXIS2, @@ -277,7 +276,7 @@ lineAnnotation = createLeftStickAnnotation(area, annotation.getPos(), lineStyle); if (!Float.isNaN(annotation.getHitPoint()) && theme != null) { // New line annotation to hit curve. - if (ThemeUtil.parseShowHorizontalLine(theme)) { + if (theme.parseShowHorizontalLine()) { XYLineAnnotation hitLineAnnotation = createStickyLineAnnotation( StickyAxisAnnotation.SimpleAxis.Y_AXIS, @@ -286,7 +285,7 @@ plot.getRenderer(rendererIndex).addAnnotation(hitLineAnnotation, org.jfree.ui.Layer.BACKGROUND); } - if (ThemeUtil.parseShowVerticalLine(theme)) { + if (theme.parseShowVerticalLine()) { XYLineAnnotation lineBackAnnotation = createStickyLineAnnotation( StickyAxisAnnotation.SimpleAxis.X_AXIS, @@ -452,15 +451,14 @@ for (RiverAnnotation fa: annotations) { // Access text styling, if any. - Document theme = fa.getTheme(); + ThemeDocument theme = fa.getTheme(); TextStyle textStyle = null; LineStyle lineStyle = null; // Get Themeing information and add legend item. if (theme != null) { - ThemeAccess themeAccess = new ThemeAccess(theme); - textStyle = themeAccess.parseTextStyle(); - lineStyle = themeAccess.parseLineStyle(); + textStyle = theme.parseComplexTextStyle(); + lineStyle = theme.parseComplexLineStyle(); if (fa.getLabel() != null) { LegendItemCollection lic = new LegendItemCollection(); LegendItemCollection old = plot.getFixedLegendItems(); @@ -509,7 +507,7 @@ @Override public abstract void doOut( ArtifactAndFacet bundle, - Document attr, + ThemeDocument attr, boolean visible); @@ -619,10 +617,10 @@ * @param theme Theme document for given annotations. * @param visible The visibility of the annotations. */ - protected void doAnnotations( + public void doAnnotations( RiverAnnotation annotations, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ){ logger.debug("doAnnotations"); @@ -1834,11 +1832,14 @@ * * @return a new LegendItem instance. */ - public LegendItem createLegendItem(Document theme, String name) { + public LegendItem createLegendItem(ThemeDocument theme, String name) { // OPTIMIZE Pass font, parsed Theme items. - ThemeAccess themeAccess = new ThemeAccess(theme); - Color color = themeAccess.parseLineColorField(); + Color color = theme.parseLineColorField(); + if (color == null) { + color = Color.BLACK; + } + LegendItem legendItem = new LegendItem(name, color); legendItem.setLabelFont(createLegendLabelFont()); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/ChartInfoGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/ChartInfoGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartInfoGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -10,6 +10,7 @@ import org.dive4elements.river.collections.D4EArtifactCollection; import org.dive4elements.river.java2d.NOPGraphics2D; +import org.dive4elements.river.themes.ThemeDocument; import java.io.IOException; import java.io.OutputStream; @@ -106,9 +107,10 @@ /** * Dispatches the operation to the instantiated generator. */ + @Override public void doOut( ArtifactAndFacet artifactFacet, - Document attr, + ThemeDocument attr, boolean visible ) { generator.doOut(artifactFacet, attr, visible); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -16,10 +16,12 @@ import org.dive4elements.river.artifacts.model.FacetTypes; import org.dive4elements.river.artifacts.model.WKms; import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.exports.process.DischargeProcessor; import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StickyAxisAnnotation; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.RiverUtils; import java.awt.Font; @@ -32,11 +34,10 @@ import org.apache.log4j.Logger; -import org.w3c.dom.Document; - /** - * An OutGenerator that generates discharge curves. + * An OutGenerator that generates discharge curves, also at locations + * not at a gauge. * * @author Ingo Weinzierl */ @@ -104,6 +105,7 @@ * Create Y (range) axis for given index, here with a special axis * that depends on other axis (does translation and scaling for * special case at gauge in cm). + * @return A NumberAxis, possibly scaled. */ @Override protected NumberAxis createYAxis(int index) { @@ -138,7 +140,7 @@ @Override public void doOut( ArtifactAndFacet artifactFacet, - Document attr, + ThemeDocument attr, boolean visible ) { String name = artifactFacet.getFacetName(); @@ -150,9 +152,11 @@ return; } - //XXX DEAD CODE // Facet facet = artifactFacet.getFacet(); - - if (name.equals(COMPUTED_DISCHARGE_Q)) { + DischargeProcessor dProcessor = new DischargeProcessor(getRange()[0]); + if (dProcessor.canHandle(name)) { + dProcessor.doOut(this, artifactFacet, attr, visible, YAXIS.W.idx); + } + else if (name.equals(COMPUTED_DISCHARGE_Q)) { doDischargeQOut((WQKms) artifactFacet.getData(context), artifactFacet, attr, visible); } else if (name.equals(STATIC_WQ)) { @@ -165,18 +169,9 @@ attr, visible); } - else if (name.equals(COMPUTED_DISCHARGE_MAINVALUES_Q) - || name.equals(MAINVALUES_Q) - || name.equals(COMPUTED_DISCHARGE_MAINVALUES_W) - || name.equals(MAINVALUES_W) - ) { - RiverAnnotation mainValues = (RiverAnnotation) artifactFacet.getData(context); - translateRiverAnnotation(mainValues); - doAnnotations( - mainValues, - artifactFacet, attr, visible); - } - else if (name.equals(STATIC_WKMS_INTERPOL) || name.equals(HEIGHTMARKS_POINTS)) { + else if (STATIC_WKMS_INTERPOL.equals(name) || + HEIGHTMARKS_POINTS.equals(name) || + STATIC_WQKMS_W.equals(name)) { doWAnnotations( artifactFacet.getData(context), artifactFacet, @@ -212,16 +207,16 @@ /** * Add WQ Data to plot. - * @param wqkms data as double[][] + * @param wq data as double[][] */ protected void doWQOut( - Object wqkms, + Object wq, ArtifactAndFacet aaf, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("ComputedDischargeCurveGenerator: doWQOut"); - double [][] data = (double [][]) wqkms; + double [][] data = (double [][]) wq; XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); StyledSeriesBuilder.addPoints(series, data, true); @@ -238,7 +233,7 @@ protected void doDischargeQOut( WQKms wqkms, ArtifactAndFacet aaf, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("ComputedDischargeCurveGenerator: doDischargeQOut"); @@ -270,7 +265,7 @@ protected void doQOut( WQKms wqkms, ArtifactAndFacet aaf, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("ComputedDischargeCurveGenerator: doQOut (add W/Q data)."); @@ -289,7 +284,7 @@ protected void doWQAnnotations( Object wqkms, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { List xy = new ArrayList(); @@ -315,7 +310,7 @@ protected void doWAnnotations( Object wqkms, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { Facet facet = aandf.getFacet(); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/CrossSectionGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/CrossSectionGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/CrossSectionGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -21,7 +21,6 @@ import org.jfree.chart.annotations.XYTextAnnotation; import org.jfree.chart.plot.XYPlot; import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifacts.DataProvider; @@ -36,10 +35,9 @@ import org.dive4elements.river.model.FastCrossSectionLine; import org.dive4elements.river.themes.LineStyle; import org.dive4elements.river.themes.TextStyle; -import org.dive4elements.river.themes.ThemeAccess; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.RiverUtils; import org.dive4elements.river.utils.Formatter; -import org.dive4elements.river.utils.ThemeUtil; /** @@ -185,14 +183,13 @@ for(RiverAnnotation fa : this.annotations) { // Access text styling, if any. - Document theme = fa.getTheme(); + ThemeDocument theme = fa.getTheme(); TextStyle textStyle = null; // XXX: DEAD CODE // LineStyle lineStyle = null; // Get Themeing information and add legend item. if (theme != null) { - ThemeAccess themeAccess = new ThemeAccess(theme); - textStyle = themeAccess.parseTextStyle(); + textStyle = theme.parseComplexTextStyle(); // XXX: DEAD CODE // lineStyle = themeAccess.parseLineStyle(); if (fa.getLabel() != null) { LegendItemCollection lic = new LegendItemCollection(); @@ -258,7 +255,7 @@ @Override public void doOut( ArtifactAndFacet artifactFacet, - Document attr, + ThemeDocument attr, boolean visible ) { String name = artifactFacet.getFacetName(); @@ -332,7 +329,7 @@ protected void doCrossSectionWaterLineOut( Object o, String seriesName, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("CrossSectionGenerator.doCrossSectionWaterLineOut"); @@ -341,10 +338,10 @@ // DO NOT SORT DATA! This destroys the gaps indicated by NaNs. StyledXYSeries series = new StyledXYSeries(seriesName, false, theme); - if (!ThemeUtil.parseShowLineLabel(theme)) { + if (!theme.parseShowLineLabel()) { series.setLabel(""); } - if (ThemeUtil.parseShowWidth(theme)) { + if (theme.parseShowWidth()) { NumberFormat nf = Formatter.getMeterFormat(this.context); String labelAdd = "b=" + nf.format(lines.width) + "m"; if (series.getLabel().length() == 0) { @@ -354,7 +351,7 @@ series.setLabel(series.getLabel() + ", " + labelAdd); } } - if (ThemeUtil.parseShowLevel(theme) && lines.points.length > 1 + if (theme.parseShowLevel() && lines.points.length > 1 && lines.points[1].length > 0) { NumberFormat nf = Formatter.getMeterFormat(this.context); D4EArtifact flys = (D4EArtifact) master; @@ -369,7 +366,7 @@ series.setLabel(series.getLabel() + ", " + labelAdd); } } - if (ThemeUtil.parseShowMiddleHeight(theme) && lines.width != 0) { + if (theme.parseShowMiddleHeight() && lines.width != 0) { NumberFormat nf = Formatter.getMeterFormat(this.context); String labelAdd = "T=" + nf.format(lines.area / lines.width) + "m"; // : " + lines.area + "/" + lines.width); @@ -391,7 +388,7 @@ protected void doHyk( Object o, String seriesName, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("CrossSectionGenerator.doHyk"); @@ -419,7 +416,7 @@ protected void doCrossSectionOut( Object o, String seriesName, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("CrossSectionGenerator.doCrossSectionOut"); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/DischargeCurveGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/DischargeCurveGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/DischargeCurveGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -8,16 +8,22 @@ package org.dive4elements.river.exports; +import java.util.ArrayList; +import java.util.List; + import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.river.artifacts.D4EArtifact; import org.dive4elements.river.artifacts.model.FacetTypes; import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.exports.process.DischargeProcessor; +import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; import org.dive4elements.river.jfree.Bounds; import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StickyAxisAnnotation; import org.dive4elements.river.jfree.StyledXYSeries; import org.dive4elements.river.model.Gauge; import org.dive4elements.river.model.River; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.RiverUtils; import org.apache.log4j.Logger; @@ -26,7 +32,6 @@ import org.jfree.chart.plot.XYPlot; import org.jfree.data.Range; import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; /** @@ -38,6 +43,7 @@ extends XYChartGenerator implements FacetTypes { + /** Beware, in this implementation, the W axis is also in cm! */ public static enum YAXIS { WCm(0), W(1); @@ -72,9 +78,16 @@ * Returns the PNP (Datum) of gauge, if at gauge, 0 otherwise. */ public static double getCurrentGaugeDatum(double km, D4EArtifact artifact, double tolerance) { - // Code borrowed from FixATWriter. - Gauge gauge = RiverUtils.getGauge(artifact); + // Look if there is a gauge at chosen km: + // Get gauge which is defined for km + Gauge gauge = + RiverUtils.getRiver(artifact).determineGauge(km-0.1d, km+0.1d); + if (gauge == null) { + logger.error("No Gauge could be found at station " + km + "!"); + return 0d; + } double subtractPNP = 0d; + // Compare to km. if (Math.abs(km - gauge.getStation().doubleValue()) < tolerance) { subtractPNP = gauge.getDatum().doubleValue(); } @@ -82,12 +95,24 @@ } + /** Get the current Gauge datum with default distance tolerance. */ public double getCurrentGaugeDatum() { return getCurrentGaugeDatum(getRange()[0], (D4EArtifact) getMaster(), 1e-4); } + /** Overriden to show second axis also if no visible data present. */ + @Override + protected void adjustAxes(XYPlot plot) { + super.adjustAxes(plot); + if (getCurrentGaugeDatum() != 0d) { + // Show the W[*m] axis even if there is no data. + plot.setRangeAxis(1, createYAxis(YAXIS.W.idx)); + } + } + + public DischargeCurveGenerator() { super(); } @@ -142,6 +167,7 @@ return zoomin; } + /** Translate River annotations if a gauge. */ public void translateRiverAnnotation(RiverAnnotation riverAnnotation) { if (getCurrentGaugeDatum() == 0d) { return; @@ -163,13 +189,18 @@ @Override public void doOut( ArtifactAndFacet artifactFacet, - Document theme, + ThemeDocument theme, boolean visible ) { String name = artifactFacet.getFacetName(); logger.debug("DischargeCurveGenerator.doOut: " + name); - if (name.equals(DISCHARGE_CURVE) + DischargeProcessor dProcessor = new DischargeProcessor(getRange()[0]); + if (dProcessor.canHandle(name)) { + // In Base DischargeCurveGenerator, always at gauge, use WCm axis. + dProcessor.doOut(this, artifactFacet, theme, visible, YAXIS.WCm.idx); + } + else if (name.equals(DISCHARGE_CURVE) || name.equals(GAUGE_DISCHARGE_CURVE)) { doDischargeOut( (D4EArtifact)artifactFacet.getArtifact(), @@ -178,22 +209,17 @@ theme, visible); } - else if (name.equals(COMPUTED_DISCHARGE_MAINVALUES_Q) - || name.equals(MAINVALUES_Q) - || name.equals(COMPUTED_DISCHARGE_MAINVALUES_W) - || name.equals(MAINVALUES_W)) - { - RiverAnnotation mainValues = (RiverAnnotation) artifactFacet.getData(context); - translateRiverAnnotation(mainValues); - doAnnotations( - mainValues, - artifactFacet, theme, visible); - } else if (FacetTypes.IS.MANUALPOINTS(name)) { doPoints(artifactFacet.getData(context), artifactFacet, theme, visible, YAXIS.W.idx); } + else if (STATIC_WQ.equals(name)) { + doWQOut(artifactFacet.getData(context), + artifactFacet, + theme, + visible); + } else { logger.warn("DischargeCurveGenerator.doOut: Unknown facet name: " + name); return; @@ -208,9 +234,10 @@ D4EArtifact artifact, Object o, String description, - Document theme, + ThemeDocument theme, boolean visible) { + logger.debug("DischargeCurveGenerator.doDischargeOut"); WQKms wqkms = (WQKms) o; String gaugeName = wqkms.getName(); @@ -235,5 +262,134 @@ addAxisSeries(series, YAXIS.W.idx, visible); } + + /** + * Add W/Q-Series to plot. + * @param wqkms actual data + * @param theme theme to use. + */ + protected void doQOut( + Object wqkms, + ArtifactAndFacet aaf, + ThemeDocument theme, + boolean visible + ) { + logger.debug("DischargeCurveGenerator: doQOut (add W/Q data)."); + XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); + + StyledSeriesBuilder.addPointsQW(series, (WQKms) wqkms); + + addAxisSeries(series, YAXIS.W.idx, visible); + } + + + /** Add a point annotation at given x and y coordinates. */ + protected void addPointTextAnnotation( + String title, + double x, + double y, + ThemeDocument theme + ) { + List textAnnos = + new ArrayList(); + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + title, + x, + y); + textAnnos.add(anno); + RiverAnnotation flysAnno = new RiverAnnotation( + null, null, null, theme); + flysAnno.setTextAnnotations(textAnnos); + addAnnotations(flysAnno); + } + + + /** + * Return true if all values in data[0] are smaller than zero + * (in imported data they are set to -1 symbolically). + * Return false if data is null or empty + */ + private boolean hasNoDischarge(double[][] data) { + if (data == null || data.length == 0) { + return false; + } + + double[] qs = data[0]; + for (double q: qs) { + if (q > 0d) { + return false; + } + } + + return true; + } + + + /** + * Add WQ Data to plot. + * @param wq data as double[][] + */ + protected void doWQOut( + Object wq, + ArtifactAndFacet aaf, + ThemeDocument theme, + boolean visible + ) { + logger.debug("DischargeCurveGenerator: doWQOut"); + double [][] data = (double [][]) wq; + String title = aaf.getFacetDescription(); + + double translate = getCurrentGaugeDatum(); + + // If no Q values (i.e. all -1) found, add annotations. + if (hasNoDischarge(data)) { + List xy = new ArrayList(); + + for (double y: data[1]) { + if (translate != 0d) { + y = (y-translate)*100d; + } + + xy.add(new StickyAxisAnnotation( + title, + (float) y, + StickyAxisAnnotation.SimpleAxis.Y_AXIS)); + } + + doAnnotations( + new RiverAnnotation(title, xy), + aaf, theme, visible); + return; + } + + // Otherwise add points. + XYSeries series = new StyledXYSeries(title, theme); + + if (translate != 0d) { + StyledSeriesBuilder.addPointsQW(series, data, -translate, 100d); + addAxisSeries(series, YAXIS.W.idx, visible); + } + else { + StyledSeriesBuilder.addPoints(series, data, true); + addAxisSeries(series, YAXIS.W.idx, visible); + } + + if (visible && theme.parseShowPointLabel() + && data != null && data.length != 0) { + + double[] xs = data[0]; + double[] ys = data[1]; + for (int i = 0; i < xs.length; i++) { + double x = xs[i]; + double y = ys[i]; + + if (translate != 0d) { + y = (y-translate)*100d; + } + + addPointTextAnnotation(title, x, y, theme); + } + } + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/DischargeLongitudinalSectionGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/DischargeLongitudinalSectionGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/DischargeLongitudinalSectionGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -12,19 +12,18 @@ import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifactdatabase.state.Facet; import org.dive4elements.river.artifacts.model.FacetTypes; import org.dive4elements.river.artifacts.model.WQCKms; -import org.dive4elements.river.artifacts.model.WQKms; import org.dive4elements.river.exports.process.Processor; +import org.dive4elements.river.exports.process.QOutProcessor; import org.dive4elements.river.exports.process.WOutProcessor; import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; @@ -49,7 +48,7 @@ @Override public void doOut( ArtifactAndFacet artifactFacet, - Document attr, + ThemeDocument attr, boolean visible ) { logger.debug("DischargeLongitudinalSectionGenerator.doOut"); @@ -62,14 +61,7 @@ Facet facet = artifactFacet.getFacet(); - if (name.contains(DISCHARGE_LONGITUDINAL_Q)) { - doQOut( - (WQKms) artifactFacet.getData(context), - artifactFacet, - attr, - visible); - } - else if (name.equals(DISCHARGE_LONGITUDINAL_C)) { + if (name.equals(DISCHARGE_LONGITUDINAL_C)) { doCorrectedWOut( (WQCKms) artifactFacet.getData(context), facet, @@ -85,18 +77,15 @@ artifactFacet, attr, visible, YAXIS.W.idx); } - else if (name.equals(STATIC_WQKMS_Q)) { - doQOut( - (WQKms) artifactFacet.getData(context), - artifactFacet, - attr, - visible); - } else { Processor processor = new WOutProcessor(); + Processor qProcessor = new QOutProcessor(); if (processor.canHandle(name)) { processor.doOut(this, artifactFacet, attr, visible, YAXIS.W.idx); } + else if (qProcessor.canHandle(name)) { + qProcessor.doOut(this, artifactFacet, attr, visible, YAXIS.Q.idx); + } else { logger.warn("Unknown facet name: " + name); } @@ -111,10 +100,10 @@ * @param theme The theme that contains styling information. */ protected void doCorrectedWOut( - WQCKms wqckms, - Facet facet, - Document theme, - boolean visible + WQCKms wqckms, + Facet facet, + ThemeDocument theme, + boolean visible ) { logger.debug("DischargeLongitudinalSectionGenerator.doCorrectedWOut"); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/DurationCurveGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/DurationCurveGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/DurationCurveGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -14,6 +14,7 @@ import org.dive4elements.river.jfree.Bounds; import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import java.awt.Font; import java.awt.geom.Point2D; @@ -24,7 +25,6 @@ import org.jfree.chart.plot.XYPlot; import org.jfree.data.Range; import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; /** @@ -173,7 +173,7 @@ @Override public void doOut( ArtifactAndFacet artifactFacet, - Document attr, + ThemeDocument attr, boolean visible ) { String name = artifactFacet.getFacetName(); @@ -238,7 +238,7 @@ protected void doWOut( WQDay wqdays, ArtifactAndFacet aaf, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("DurationCurveGenerator.doWOut"); @@ -257,10 +257,10 @@ } protected void doPointOut( - Point2D point, + Point2D point, ArtifactAndFacet aandf, - Document theme, - boolean visible + ThemeDocument theme, + boolean visible ){ logger.debug("DurationCurveGenerator.doPointOut"); @@ -281,7 +281,7 @@ protected void doQOut( WQDay wqdays, ArtifactAndFacet aaf, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("DurationCurveGenerator.doQOut"); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/FlowVelocityGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/FlowVelocityGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/FlowVelocityGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -14,8 +14,6 @@ import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; - import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifactdatabase.state.Facet; @@ -33,6 +31,7 @@ import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.RiverUtils; @@ -209,7 +208,7 @@ */ public void doOut( ArtifactAndFacet artifactAndFacet, - Document attr, + ThemeDocument attr, boolean visible ) { String name = artifactAndFacet.getFacetName(); @@ -370,7 +369,7 @@ private void doBedQualityLoadDiameter( BedloadDiameterResult data, ArtifactAndFacet aandf, - Document attr, + ThemeDocument attr, boolean visible) { XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), attr); StyledSeriesBuilder.addPoints(series, data.getDiameterData(), true); @@ -382,7 +381,7 @@ private void doBedQualityTopLayerOut( BedDiameterResult data, ArtifactAndFacet aandf, - Document attr, + ThemeDocument attr, boolean visible) { XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), attr); StyledSeriesBuilder.addPoints(series, data.getDiameterSubData(), true); @@ -393,7 +392,7 @@ private void doBedQualitySubLayerOut( BedDiameterResult data, ArtifactAndFacet aandf, - Document attr, + ThemeDocument attr, boolean visible ) { logger.debug("Do beddiametersubout"); @@ -416,7 +415,7 @@ protected void doMainChannelOut( FlowVelocityData data, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("FlowVelocityGenerator.doMainChannelOut"); @@ -433,7 +432,7 @@ protected void doVPointOut ( Object data, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("FlowVelocityGenerator.doVPointOut"); @@ -456,7 +455,7 @@ protected void doTotalChannelOut( FlowVelocityData data, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("FlowVelocityGenerator.doTotalChannelOut"); @@ -486,10 +485,10 @@ protected void doQOut( FlowVelocityData data, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { - logger.debug("FlowVelocityGenerator.doTauOut"); + logger.debug("FlowVelocityGenerator.doQOut"); XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); @@ -509,7 +508,7 @@ protected void doTauOut( FlowVelocityData data, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("FlowVelocityGenerator.doTauOut"); @@ -543,10 +542,10 @@ * @param visible whether or not visible. */ protected void doArea( - Object o, + Object o, ArtifactAndFacet aandf, - Document theme, - boolean visible + ThemeDocument theme, + boolean visible ) { logger.debug("FlowVelocityGenerator.doArea"); logger.warn("TODO: Implement FlowVelocityGenerator.doArea"); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeCurveGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeCurveGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeCurveGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -25,6 +25,7 @@ import org.dive4elements.river.jfree.StyledTimeSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.RiverUtils; import org.jfree.chart.plot.XYPlot; @@ -36,8 +37,6 @@ import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; -import org.w3c.dom.Document; - /** * @author Ingo Weinzierl @@ -127,7 +126,7 @@ } @Override - public void doOut(ArtifactAndFacet artifactFacet, Document theme, + public void doOut(ArtifactAndFacet artifactFacet, ThemeDocument theme, boolean visible) { String name = artifactFacet.getFacetName(); logger.debug("HistoricalDischargeCurveGenerator.doOut: " + name); @@ -169,7 +168,7 @@ } protected void doHistoricalDischargeOutQ(D4EArtifact artifact, - Object data, String desc, Document theme, boolean visible) { + Object data, String desc, ThemeDocument theme, boolean visible) { logger.debug("doHistoricalDischargeOut(): description = " + desc); WQTimerange wqt = (WQTimerange) data; @@ -181,7 +180,7 @@ } protected void doHistoricalDischargeOutW(D4EArtifact artifact, - Object data, String desc, Document theme, boolean visible) { + Object data, String desc, ThemeDocument theme, boolean visible) { logger.debug("doHistoricalDischargeOut(): description = " + desc); WQTimerange wqt = (WQTimerange) data; @@ -193,7 +192,7 @@ } protected void doHistoricalDischargeDifferenceOutQ(D4EArtifact artifact, - Object data, String desc, Document theme, boolean visible) { + Object data, String desc, ThemeDocument theme, boolean visible) { logger.debug("doHistoricalDischargeDifferenceOut: desc = " + desc); HistoricalWQTimerange wqt = (HistoricalWQTimerange) data; @@ -205,7 +204,7 @@ } protected void doHistoricalDischargeDifferenceOutW(D4EArtifact artifact, - Object data, String desc, Document theme, boolean visible) { + Object data, String desc, ThemeDocument theme, boolean visible) { logger.debug("doHistoricalDischargeDifferenceOut: desc = " + desc); HistoricalWQTimerange wqt = (HistoricalWQTimerange) data; @@ -223,7 +222,7 @@ * looks like a "step chart". */ protected TimeSeriesCollection newTimeSeriesCollection( - Timerange[] timeranges, double[] values, Document theme, String desc) { + Timerange[] timeranges, double[] values, ThemeDocument theme, String desc) { logger.debug("Create new TimeSeriesCollection for: " + desc); TimeSeriesCollection tsc = new TimeSeriesCollection(); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeWQCurveGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeWQCurveGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/HistoricalDischargeWQCurveGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -10,7 +10,6 @@ import org.apache.log4j.Logger; import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.river.artifacts.D4EArtifact; @@ -22,6 +21,7 @@ import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StyledValueMarker; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.RiverUtils; @@ -105,7 +105,7 @@ } @Override - public void doOut(ArtifactAndFacet artifactFacet, Document theme, + public void doOut(ArtifactAndFacet artifactFacet, ThemeDocument theme, boolean visible) { String name = artifactFacet.getFacetName(); logger.debug("HistoricalDischargeWQCurveGenerator.doOut: " + name); @@ -124,7 +124,9 @@ artifactFacet.getData(context), artifactFacet.getFacetDescription(), theme, visible); } - else if (name.equals(HISTORICAL_DISCHARGE_WQ_CURVE)) { + else if (name.equals(HISTORICAL_DISCHARGE_WQ_CURVE) || + name.equals(DISCHARGE_CURVE) || + name.equals(GAUGE_DISCHARGE_CURVE)) { doHistoricalDischargeCurveOut( (D4EArtifact) artifactFacet.getArtifact(), artifactFacet.getData(context), @@ -134,11 +136,10 @@ doPoints(artifactFacet.getData(context), artifactFacet, theme, visible, YAXIS.W.idx); } - else if (HISTORICAL_DISCHARGE_MAINVALUES_Q.equals(name)) { - doAnnotations((RiverAnnotation) - artifactFacet.getData(context), artifactFacet, theme, visible); - } - else if (HISTORICAL_DISCHARGE_MAINVALUES_W.equals(name)) { + else if (name.equals(MAINVALUES_W) || + name.equals(MAINVALUES_Q) || + HISTORICAL_DISCHARGE_MAINVALUES_Q.equals(name) || + HISTORICAL_DISCHARGE_MAINVALUES_W.equals(name)) { doAnnotations((RiverAnnotation) artifactFacet.getData(context), artifactFacet, theme, visible); } @@ -149,19 +150,19 @@ } protected void doHistoricalDischargeOutQ(D4EArtifact artifact, - Object data, String desc, Document theme, boolean visible) { + Object data, String desc, ThemeDocument theme, boolean visible) { double value = Double.valueOf(data.toString()); addDomainMarker(new StyledValueMarker(value, theme), visible); } protected void doHistoricalDischargeOutW(D4EArtifact artifact, - Object data, String desc, Document theme, boolean visible) { + Object data, String desc, ThemeDocument theme, boolean visible) { double value = Double.valueOf(data.toString()); addValueMarker(new StyledValueMarker(value, theme), visible); } protected void doHistoricalDischargeCurveOut(D4EArtifact artifact, - Object data, String desc, Document theme, boolean visible) { + Object data, String desc, ThemeDocument theme, boolean visible) { XYSeries series = new StyledXYSeries(desc, theme); StyledSeriesBuilder.addPointsQW(series, (WQKms) data); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/LongitudinalSectionGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/LongitudinalSectionGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/LongitudinalSectionGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -16,10 +16,18 @@ import org.dive4elements.river.artifacts.model.FacetTypes; import org.dive4elements.river.artifacts.model.WKms; import org.dive4elements.river.artifacts.model.WQKms; + +import org.dive4elements.river.exports.process.Processor; +import org.dive4elements.river.exports.process.BedDiffHeightYearProcessor; +import org.dive4elements.river.exports.process.BedDiffYearProcessor; +import org.dive4elements.river.exports.process.BedheightProcessor; +import org.dive4elements.river.exports.process.QOutProcessor; import org.dive4elements.river.exports.process.WOutProcessor; + import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StyledAreaSeriesCollection; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.DataUtil; import org.dive4elements.river.utils.RiverUtils; import org.apache.log4j.Logger; @@ -27,7 +35,6 @@ import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.plot.XYPlot; import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; /** @@ -315,7 +322,7 @@ @Override public void doOut( ArtifactAndFacet artifactAndFacet, - Document attr, + ThemeDocument attr, boolean visible ) { String name = artifactAndFacet.getFacetName(); @@ -333,16 +340,26 @@ return; } - WOutProcessor processor = new WOutProcessor(); - if (processor.canHandle(name)) { - processor.doOut(this, artifactAndFacet, attr, visible, YAXIS.W.idx); + WOutProcessor wProcessor = new WOutProcessor(); + QOutProcessor qProcessor = new QOutProcessor(); + Processor bedp = new BedheightProcessor(); + Processor bdyProcessor = new BedDiffYearProcessor(); + Processor bdhyProcessor = new BedDiffHeightYearProcessor(); + + if (wProcessor.canHandle(name)) { + wProcessor.doOut(this, artifactAndFacet, attr, visible, YAXIS.W.idx); } - else if (name.equals(LONGITUDINAL_Q)) { - doQOut( - (WQKms) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); + if (qProcessor.canHandle(name)) { + qProcessor.doOut(this, artifactAndFacet, attr, visible, YAXIS.Q.idx); + } + else if (bedp.canHandle(name)) { + bedp.doOut(this, artifactAndFacet, attr, visible, YAXIS.W.idx); + } + else if (bdyProcessor.canHandle(name)) { + bdyProcessor.doOut(this, artifactAndFacet, attr, visible, YAXIS.W.idx); + } + else if (bdhyProcessor.canHandle(name)) { + bdhyProcessor.doOut(this, artifactAndFacet, attr, visible, YAXIS.W.idx); } else if (name.equals(LONGITUDINAL_ANNOTATION)) { doAnnotations( @@ -351,13 +368,6 @@ attr, visible); } - else if (name.equals(STATIC_WQKMS_Q)) { - doQOut( - (WQKms) artifactAndFacet.getData(context), - artifactAndFacet, - attr, - visible); - } else if (name.equals(W_DIFFERENCES)) { doWDifferencesOut( (WKms) artifactAndFacet.getData(context), @@ -392,7 +402,7 @@ protected void doWDifferencesOut( WKms wkms, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("WDifferencesCurveGenerator.doWDifferencesOut"); @@ -422,35 +432,6 @@ /** - * Process the output for Q facets in a longitudinal section curve. - * - * @param wqkms An array of WQKms values. - * @param aandf The facet and artifact. This facet does NOT support any data objects. Use - * D4EArtifact.getNativeFacet() instead to retrieve a Facet which supports - * data. - * @param theme The theme that contains styling information. - * @param visible The visibility of the curve. - */ - protected void doQOut( - WQKms wqkms, - ArtifactAndFacet aandf, - Document theme, - boolean visible - ) { - logger.debug("LongitudinalSectionGenerator.doQOut"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - - StyledSeriesBuilder.addStepPointsKmQ(series, wqkms); - - addAxisSeries(series, YAXIS.Q.idx, visible); - - if (needInvertAxis(wqkms)) { - setInverted(true); - } - } - - /** * This method determines - taking JFreeCharts auto x value ordering into * account - if the x axis need to be inverted. Waterlines in these charts * should decrease. @@ -517,7 +498,7 @@ protected void doArea( Object o, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("LongitudinalSectionGenerator.doArea"); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/MapGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/MapGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/MapGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -24,9 +24,9 @@ import org.dive4elements.river.artifacts.model.map.WSPLGENLayerFacet; import org.dive4elements.river.artifacts.states.WaterlevelGroundDifferences; import org.dive4elements.river.collections.D4EArtifactCollection; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.ArtifactMapfileGenerator; import org.dive4elements.river.utils.GeometryUtils; -import org.dive4elements.river.utils.ThemeUtil; import java.io.File; import java.io.FileNotFoundException; @@ -96,7 +96,7 @@ @Override public void doOut( ArtifactAndFacet artifactFacet, - Document attr, + ThemeDocument attr, boolean visible) { String name = artifactFacet.getFacetName(); @@ -120,9 +120,11 @@ setInitialExtent(extent); createWSPLGENLayer(flys, wms, attr); } - else if (FLOODMAP_USERSHAPE.equals(name)) { - createUserShapeLayer(flys, wms); - } + // FIXME: Already generated by HWSBarrierState + // wms has a wrong SRID which would break that layer + //else if (FLOODMAP_USERSHAPE.equals(name)) { + // createUserShapeLayer(flys, wms); + //} else { logger.debug("doOut: createDatabaseLayer for facet name: " + name); createDatabaseLayer(flys, wms, attr); @@ -135,9 +137,9 @@ protected void createWSPLGENLayer( - D4EArtifact flys, + D4EArtifact flys, WMSLayerFacet wms, - Document attr + ThemeDocument attr ) { try { if(wms instanceof WSPLGENLayerFacet) { @@ -158,7 +160,8 @@ mfg.createUeskLayer( flys, (WSPLGENLayerFacet) wms, - ThemeUtil.createDynamicMapserverStyle(attr, from, to, step, context.getMeta()), + attr.createDynamicMapserverStyle( + from, to, step, context.getMeta()), context); } else { @@ -188,9 +191,9 @@ protected void createDatabaseLayer( - D4EArtifact flys, + D4EArtifact flys, WMSLayerFacet wms, - Document attr + ThemeDocument attr ) { logger.debug("createDatabaseLayer for facet: " + wms.getName()); @@ -209,7 +212,7 @@ mfg.createDatabaseLayer( flys, (WMSDBLayerFacet) wms, - ThemeUtil.createMapserverStyle(attr)); + attr.createMapserverStyle()); } else { logger.warn("Cannot create DB layer from: " + wms.getClass()); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/MiddleBedHeightGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/MiddleBedHeightGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/MiddleBedHeightGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -10,19 +10,23 @@ import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifactdatabase.state.Facet; + import org.dive4elements.river.artifacts.D4EArtifact; import org.dive4elements.river.artifacts.model.FacetTypes; import org.dive4elements.river.artifacts.model.MiddleBedHeightData; +import org.dive4elements.river.artifacts.model.WQKms; + import org.dive4elements.river.exports.process.BedheightProcessor; import org.dive4elements.river.exports.process.Processor; +import org.dive4elements.river.exports.process.QOutProcessor; import org.dive4elements.river.exports.process.WOutProcessor; import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.RiverUtils; import org.apache.log4j.Logger; import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; // TODO Move class to org.dive4elements.river.exports.minfo /** @@ -35,7 +39,7 @@ implements FacetTypes { public enum YAXIS { - H(0), W(1), P(2); + H(0), W(1), P(2), Q(3); protected int idx; private YAXIS(int c) { idx = c; @@ -73,6 +77,9 @@ public static final String I18N_P_YAXIS_LABEL_DEFAULT = "Gepeilte Breite [m]"; public static final String I18N_P_YAXIS_LABEL = "chart.bedheight_middle.sounding.yaxis.label"; + public static final String I18N_Q_YAXIS_LABEL_DEFAULT = "Q [m\u00b3/s]"; + public static final String I18N_Q_YAXIS_LABEL = + "chart.longitudinal.section.yaxis.second.label"; @Override protected YAxisWalker getYAxisWalker() { @@ -139,6 +146,9 @@ else if (index == YAXIS.P.idx) { label = msg(I18N_P_YAXIS_LABEL, I18N_P_YAXIS_LABEL_DEFAULT); } + else if (index == YAXIS.Q.idx) { + label = msg(I18N_Q_YAXIS_LABEL, I18N_Q_YAXIS_LABEL_DEFAULT); + } return label; } @@ -166,7 +176,7 @@ @Override public void doOut( ArtifactAndFacet artifactAndFacet, - Document attr, + ThemeDocument attr, boolean visible ) { String name = artifactAndFacet.getFacetName(); @@ -186,11 +196,14 @@ Processor woutp = new WOutProcessor(); Processor bedp = new BedheightProcessor(); - WOutProcessor processor = new WOutProcessor(); - if (processor.canHandle(name)) { - processor.doOut(this, artifactAndFacet, attr, visible, YAXIS.W.idx); + Processor qoutp = new QOutProcessor(); + if (woutp.canHandle(name)) { + woutp.doOut(this, artifactAndFacet, attr, visible, YAXIS.W.idx); } - if (name.equals(MIDDLE_BED_HEIGHT_SINGLE) || name.equals(MIDDLE_BED_HEIGHT_EPOCH)) { + else if (qoutp.canHandle(name)) { + qoutp.doOut(this, artifactAndFacet, attr, visible, YAXIS.Q.idx); + } + else if (name.equals(MIDDLE_BED_HEIGHT_SINGLE) || name.equals(MIDDLE_BED_HEIGHT_EPOCH)) { doHeightOut( (MiddleBedHeightData) artifactAndFacet.getData(context), artifactAndFacet, @@ -226,6 +239,13 @@ attr, visible); } + else if (name.equals(STATIC_WQKMS_Q)) { + doQOut( + (WQKms) artifactAndFacet.getData(context), + artifactAndFacet, + attr, + visible); + } else if (bedp.canHandle(name)) { bedp.doOut(this, artifactAndFacet, attr, visible, YAXIS.P.idx); } @@ -249,7 +269,7 @@ protected void doHeightOut( MiddleBedHeightData data, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("MiddleBedHeightGenerator.doMainChannelOut"); @@ -283,13 +303,47 @@ * @param visible whether or not visible. */ protected void doArea( - Object o, + Object o, ArtifactAndFacet aandf, - Document theme, - boolean visible + ThemeDocument theme, + boolean visible ) { logger.debug("FlowVelocityGenerator.doArea"); logger.warn("TODO: Implement FlowVelocityGenerator.doArea"); } + + + // TODO method borrowed from LongitudinalSectionGenerator. + // Extract in an Processor + /** + * Process the output for Q facets in a longitudinal section curve. + * + * @param wqkms An array of WQKms values. + * @param aandf The facet and artifact. This facet does NOT support any data objects. Use + * D4EArtifact.getNativeFacet() instead to retrieve a Facet which supports + * data. + * @param theme The theme that contains styling information. + * @param visible The visibility of the curve. + */ + protected void doQOut( + WQKms wqkms, + ArtifactAndFacet aandf, + ThemeDocument theme, + boolean visible + ) { + logger.debug("MiddleBedHeightGenerator.doQOut"); + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + + StyledSeriesBuilder.addStepPointsKmQ(series, wqkms); + + addAxisSeries(series, YAXIS.Q.idx, visible); + + /* + if (needInvertAxis(wqkms)) { + setInverted(true); + } + */ + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/OutGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/OutGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/OutGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -18,6 +18,7 @@ import org.dive4elements.artifacts.Artifact; import org.dive4elements.artifacts.CallContext; import org.dive4elements.river.collections.D4EArtifactCollection; +import org.dive4elements.river.themes.ThemeDocument; /** @@ -63,7 +64,7 @@ * producing the output. * @param visible Specifies, if this output should be visible or not. */ - void doOut(ArtifactAndFacet bundle, Document attr, boolean visible); + void doOut(ArtifactAndFacet bundle, ThemeDocument attr, boolean visible); /** * Writes the collected output of all artifacts specified in the diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/OutputHelper.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/OutputHelper.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/OutputHelper.java Thu Sep 12 10:13:09 2013 +0200 @@ -40,6 +40,7 @@ import org.dive4elements.river.artifacts.model.ManagedDomFacet; import org.dive4elements.river.artifacts.model.ManagedFacet; import org.dive4elements.river.themes.Theme; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.themes.ThemeFactory; public class OutputHelper { @@ -71,11 +72,13 @@ boolean debug = log.isDebugEnabled(); if (debug) { - log.debug("D4EArtifactCollection.doOut: " + outName); + log.debug("OutputHelper.doOut: " + outName); } ThemeList themeList = new ThemeList(attributes); + ThemeDocument themeDoc = new ThemeDocument(attributes); + List dataProviders = doBlackboardPass(themeList, context, outName); @@ -109,7 +112,7 @@ if (outName.equals("sq_overview")) { generator.doOut( dataProviders.get(i), - attributes, + themeDoc, theme.getActive() == 1); } else { @@ -141,7 +144,7 @@ * * @return an attribute in form of a document. */ - protected Document getFacetThemeFromAttribute( + protected ThemeDocument getFacetThemeFromAttribute( String uuid, String outName, String facet, @@ -154,7 +157,7 @@ if (debug) { log.debug( - "D4EArtifactCollection.getFacetThemeFromAttribute(facet=" + "OutputHelper.getFacetThemeFromAttribute(facet=" + facet + ", index=" + index + ")"); } @@ -219,7 +222,7 @@ Document doc = XMLUtils.newDocument(); doc.appendChild(doc.importNode(theme, true)); - return doc; + return new ThemeDocument(doc); } /** * Adds the theme of a facet to a CollectionItem's attribute. @@ -235,7 +238,7 @@ Theme t, CallContext context) { - log.debug("D4EArtifactCollection.addThemeToAttribute: " + uuid); + log.debug("OutputHelper.addThemeToAttribute: " + uuid); if (t == null) { log.warn("Theme is empty - cancel adding it to attribute!"); @@ -380,7 +383,7 @@ protected Artifact getArtifact(String uuid, CallContext context) throws ArtifactDatabaseException { - log.debug("D4EArtifactCollection.getArtifact"); + log.debug("OutputHelper.getArtifact"); Backend backend = Backend.getInstance(); PersistentArtifact persistent = backend.getArtifact(uuid); @@ -409,7 +412,7 @@ boolean debug = log.isDebugEnabled(); if (debug) { - log.debug("D4EArtifactCollection.initItemAttribute"); + log.debug("OutputHelper.initItemAttribute"); } Theme t = getThemeForFacet(uuid, facet, pattern, index, outName, context); @@ -447,7 +450,7 @@ String outName, CallContext context) { - log.info("D4EArtifactCollection.getThemeForFacet: " + facet); + log.info("OutputHelper.getThemeForFacet: " + facet); RiverContext flysContext = context instanceof RiverContext ? (RiverContext) context diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/ReferenceCurveGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/ReferenceCurveGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/ReferenceCurveGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -15,6 +15,7 @@ import org.dive4elements.river.artifacts.model.WWAxisTypes; import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.Formatter; import java.awt.geom.Point2D; @@ -25,7 +26,6 @@ import org.jfree.chart.axis.TickUnits; import org.jfree.chart.axis.ValueAxis; import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; /** * An OutGenerator that generates reference curves. @@ -137,7 +137,7 @@ @Override public void doOut( ArtifactAndFacet artifactFacet, - Document theme, + ThemeDocument theme, boolean visible ) { String name = artifactFacet.getFacetName(); @@ -187,9 +187,9 @@ /** Register DataSeries with (maybe transformed) points. */ public void doReferenceOut( - Object data, - Document theme, - boolean visible + Object data, + ThemeDocument theme, + boolean visible ) { WW ww = (WW)data; @@ -216,10 +216,10 @@ // TODO resolve duplicate in DurationCurveGenerator protected void doPointOut( - Point2D point, + Point2D point, ArtifactAndFacet aandf, - Document theme, - boolean visible + ThemeDocument theme, + boolean visible ){ logger.debug("ReferenceCurveGenerator.doPointOut"); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/ReportGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/ReportGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/ReportGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -24,6 +24,7 @@ import org.dive4elements.river.artifacts.model.Calculation; import org.dive4elements.river.collections.D4EArtifactCollection; +import org.dive4elements.river.themes.ThemeDocument; import org.w3c.dom.Document; @@ -60,7 +61,7 @@ @Override public void doOut( ArtifactAndFacet artifactFacet, - Document attr, + ThemeDocument attr, boolean visible ) { logger.debug("doOut"); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/ShapeExporter.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/ShapeExporter.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/ShapeExporter.java Thu Sep 12 10:13:09 2013 +0200 @@ -14,6 +14,7 @@ import org.dive4elements.artifacts.common.utils.FileTools; import org.dive4elements.artifacts.common.utils.XMLUtils; import org.dive4elements.river.collections.D4EArtifactCollection; +import org.dive4elements.river.themes.ThemeDocument; import org.w3c.dom.Document; @@ -47,7 +48,7 @@ } @Override - public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { + public void doOut(ArtifactAndFacet bundle, ThemeDocument attr, boolean visible) { String name = bundle.getFacetName(); if (!isFacetValid(name)) { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/StyledSeriesBuilder.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/StyledSeriesBuilder.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/StyledSeriesBuilder.java Thu Sep 12 10:13:09 2013 +0200 @@ -40,14 +40,63 @@ /** + * Add points to series, create gaps if certain distance between + * points is met and scale the Y value. + * + * @param series Series to add points to. + * @param points Points to add to series, points[0] to 1st dim, points[1] + * to 2nd dim. + * @param skipNANs if true, skip NAN values in points parameter. Otherwise, + * the NaNs lead to gaps in graph. + * @param distance if two consecutive entries in points[0] are more + * than distance apart, create a NaN value to skip in display. + * Still, create a line segment. + * @param factor Factor by which to scale the y value (points[1]). + */ + public static void addPointsFactorY(XYSeries series, + double[][] points, + boolean skipNANs, + double distance, + double factor + ) { + if (points == null || points.length <= 1) { + return; + } + double [] xPoints = points[0]; + double [] yPoints = points[1]; + for (int i = 0; i < xPoints.length; i++) { + if (skipNANs && + (Double.isNaN(xPoints[i]) || Double.isNaN(yPoints[i]))) { + logger.warn ("Skipping NaN in StyledSeriesBuilder."); + continue; + } + // Create gap if distance >= distance. + if (i != 0 && Math.abs(xPoints[i-1] - xPoints[i]) >= distance) { + // Create at least a small segment for last point. + if (!Double.isNaN(yPoints[i-1])) { + series.add(xPoints[i-1]+0.99d*(distance)/2.d, yPoints[i-1]*factor, false); + } + + if (!Double.isNaN(yPoints[i-1]) && !Double.isNaN(yPoints[i])) { + series.add((xPoints[i-1]+xPoints[i])/2.d, Double.NaN, false); + } + } + series.add(xPoints[i], yPoints[i]*factor, false); + } + } + + + /** * Add points to series, create gaps if certain distance between points is met. * * @param series Series to add points to. * @param points Points to add to series, points[0] to 1st dim, points[1] * to 2nd dim. - * @param skipNANs if true, skip NAN values in points parameter. + * @param skipNANs if true, skip NAN values in points parameter. Otherwise, + * the NaNs lead to gaps in graph. * @param distance if two consecutive entries in points[0] are more * than distance apart, create a NaN value to skip in display. + * Still, create a line segment. */ public static void addPoints(XYSeries series, double[][] points, boolean skipNANs, double distance) { if (points == null || points.length <= 1) { @@ -63,6 +112,11 @@ } // Create gap if distance >= distance. if (i != 0 && Math.abs(xPoints[i-1] - xPoints[i]) >= distance) { + // Create at least a small segment for last point. + if (!Double.isNaN(yPoints[i-1])) { + series.add(xPoints[i-1]+0.99d*(distance)/2.d, yPoints[i-1], false); + } + if (!Double.isNaN(yPoints[i-1]) && !Double.isNaN(yPoints[i])) { series.add((xPoints[i-1]+xPoints[i])/2.d, Double.NaN, false); } @@ -250,6 +304,27 @@ * W values and scaling it with wScale. * * @param series Series to add points to. + * @param qws to add to series. + * @param wAdd Value to add to each Q while adding to series. + * @param wScale multiply with + */ + public static void addPointsQW(XYSeries series, double[][] qws, double wTrans, double wScale) { + if (qws == null || qws.length == 0) { + return; + } + + double x[] = qws[0]; + double y[] = qws[1]; + + for (int i = 0; i < x.length; i++) { + series.add(x[i], wScale * (y[i] + wTrans), false); + } + } + /** + * Add points to series (q to 1st dim, w to 2nd dim), adding wTrans to the + * W values and scaling it with wScale. + * + * @param series Series to add points to. * @param wqkms WQKms to add to series. * @param wAdd Value to add to each Q while adding to series. * @param wScale multiply with diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/SyncNumberAxis.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/SyncNumberAxis.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/SyncNumberAxis.java Thu Sep 12 10:13:09 2013 +0200 @@ -18,6 +18,7 @@ /** * Axis which is to be registered with other axis and tries * to clone its range. The cloned range is transformed. + * Keeps in sync via AxisChangedEvents. */ public class SyncNumberAxis extends IdentifiableNumberAxis implements AxisChangeListener diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/TimeseriesChartGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/TimeseriesChartGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/TimeseriesChartGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -16,6 +16,7 @@ import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StyledTimeSeries; import org.dive4elements.river.jfree.TimeBounds; +import org.dive4elements.river.themes.ThemeDocument; import java.awt.Color; import java.awt.Font; @@ -51,13 +52,13 @@ import org.jfree.ui.Layer; import org.json.JSONArray; import org.json.JSONException; -import org.w3c.dom.Document; /** + * Generator for diagrams with time on x axis. * @author Ingo Weinzierl */ -public abstract class TimeseriesChartGenerator extends ChartGenerator { - +public abstract class TimeseriesChartGenerator +extends ChartGenerator { /** * Inner class TimeseriesAxisDataset stores TimeSeriesCollection. @@ -691,7 +692,7 @@ protected void doPoints( Object o, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible, int axisIndex ) { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/WDifferencesCurveGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/WDifferencesCurveGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/WDifferencesCurveGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -8,9 +8,20 @@ package org.dive4elements.river.exports; +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifactdatabase.state.Facet; + import org.dive4elements.river.artifacts.model.FacetTypes; import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.exports.process.BedDiffYearProcessor; +import org.dive4elements.river.exports.process.BedDiffHeightYearProcessor; +import org.dive4elements.river.exports.process.BedheightProcessor; +import org.dive4elements.river.exports.process.Processor; +import org.dive4elements.river.themes.ThemeDocument; + import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.XYPlot; @@ -22,6 +33,9 @@ extends LongitudinalSectionGenerator implements FacetTypes { + /** The logger that is used in this generator. */ + private static Logger logger = Logger.getLogger(WDifferencesCurveGenerator.class); + public enum YAXIS { W(0), D(1), @@ -85,8 +99,46 @@ } + /** Handle additional facets (beddifferences). */ + @Override + public void doOut(ArtifactAndFacet bundle, ThemeDocument attr, boolean visible) { + super.doOut(bundle, attr, visible); + + String name = bundle.getFacetName(); + logger.debug("doOut: " + name); + + if (name == null) { + logger.error("No facet name for doOut(). No output generated!"); + return; + } + + Facet facet = bundle.getFacet(); + + if (facet == null) { + return; + } + + Processor bedp = new BedheightProcessor(); + Processor bdyProcessor = new BedDiffYearProcessor(); + Processor bdhyProcessor = new BedDiffHeightYearProcessor(); + + if (bedp.canHandle(name)) { + bedp.doOut(this, bundle, attr, visible, YAXIS.W.idx); + } + else if (bdyProcessor.canHandle(name)) { + bdyProcessor.doOut(this, bundle, attr, visible, YAXIS.W.idx); + } + else if (bdhyProcessor.canHandle(name)) { + bdhyProcessor.doOut(this, bundle, attr, visible, YAXIS.W.idx); + } + else { + logger.warn("WDifferencesCurveGenerator.doOut: unknown facet type " + name); + } + } + + /** - * + * Sets the zero base line visible. */ @Override public JFreeChart generateChart() { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/WaterlevelExporter.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/WaterlevelExporter.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/WaterlevelExporter.java Thu Sep 12 10:13:09 2013 +0200 @@ -34,6 +34,7 @@ import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.engine.JRException; +import org.dive4elements.artifacts.Artifact; import org.dive4elements.artifacts.CallContext; import org.dive4elements.artifacts.CallMeta; import org.dive4elements.artifacts.common.utils.Config; @@ -45,6 +46,7 @@ import org.dive4elements.river.artifacts.FixationArtifact; import org.dive4elements.river.artifacts.D4EArtifact; import org.dive4elements.river.artifacts.WINFOArtifact; +import org.dive4elements.river.artifacts.StaticWQKmsArtifact; import org.dive4elements.river.artifacts.model.CalculationResult; import org.dive4elements.river.artifacts.model.Segment; import org.dive4elements.river.artifacts.model.WQCKms; @@ -70,6 +72,9 @@ public static final String FACET_WST = "wst"; + /* This should be the same as in the StaticWQKmsArtifact */ + public static final String STATICWQKMSNAME = "staticwqkms"; + public static final String CSV_KM_HEADER = "export.waterlevel.csv.header.km"; @@ -134,16 +139,18 @@ public static final String PDF_HEADER_MODE = "export.waterlevel.pdf.mode"; public static final String JASPER_FILE = "export.waterlevel.pdf.file"; - /** The storage that contains all WQKms objects for the different facets.*/ + /** The storage that contains all WQKms objects that are calculated.*/ protected List data; + /** The storage that contains official fixings if available.*/ + protected List officalFixings; public void init(Document request, OutputStream out, CallContext context) { logger.debug("WaterlevelExporter.init"); super.init(request, out, context); - this.data = new ArrayList(); + data = new ArrayList(); } @@ -153,6 +160,37 @@ { logger.debug("WaterlevelExporter.generate"); + /* Check for official fixings. They should also be included in the + * export but only the calculation result is added with addData */ + + officalFixings = new ArrayList(); + + for (Artifact art: collection.getArtifactsByName(STATICWQKMSNAME, context)) { + if (art instanceof StaticWQKmsArtifact) { + StaticWQKmsArtifact sart = (StaticWQKmsArtifact) art; + if (!sart.isOfficial()) { + continue; + } + + /* Check that we add the data only once */ + WQKms toAdd = sart.getWQKms(); + String newName = toAdd.getName(); + + boolean exists = false; + for (WQKms wqkm: officalFixings) { + /* The same official fixing could be in two + artifacts/outs so let's deduplicate */ + if (wqkm.getName().equals(newName)) { + exists = true; + } + } + if (!exists) { + officalFixings.add(toAdd); + logger.debug("Adding additional offical fixing: " + newName); + } + } + } + if (facet != null && facet.equals(AbstractExporter.FACET_CSV)) { generateCSV(); } @@ -183,7 +221,7 @@ /** - * This method is used to prepare the column titles of waterlevel exports. + * Prepare the column titles of waterlevel exports. * Titles in this export include the Q value. If a Q value matches a named * main value (as HQ100 or MNQ) this named main value should be used as * title. This method resets the name of the wqkms object if such @@ -294,11 +332,80 @@ writeCSVMeta(writer); writeCSVHeader(writer, atGauge, isQ); + Double first = Double.NaN; + Double last = Double.NaN; + for (WQKms[] tmp: data) { for (WQKms wqkms: tmp) { wQKms2CSV(writer, wqkms, atGauge, isQ); + double[] firstLast = wqkms.getFirstLastKM(); + if (first.isNaN()) { + /* Initialize */ + first = firstLast[0]; + last = firstLast[1]; + } + if (firstLast[0] > firstLast[1]) { + /* Calculating upstream we assert that it is + * impossible that the direction changes during this + * loop */ + first = Math.max(first, firstLast[0]); + last = Math.min(last, firstLast[1]); + } else if (firstLast[0] < firstLast[1]) { + first = Math.min(first, firstLast[0]); + last = Math.max(last, firstLast[1]); + } else { + first = last = firstLast[0]; + } } } + /* Append the official fixing at the bottom */ + for (WQKms wqkms: officalFixings) { + wQKms2CSV(writer, filterWQKms(wqkms, first, last), atGauge, isQ); + } + } + + + /** Filter a wqkms object to a distance. + * + * To handle upstream / downstream and to limit + * the officialFixings to the calculation distance + * we create a new wqkms object here and fill it only + * with the relevant data. + * + * @param wqkms: The WQKms Object to filter + * @param first: The fist kilometer of the range + * @param last: The last kilometer of the range + * + * @return A new WQKms with the relevant data sorted by direction + */ + private WQKms filterWQKms(WQKms wqkms, Double first, Double last) { + if (first.isNaN() || last.isNaN()) { + logger.warn("Filtering official fixing without valid first/last."); + return wqkms; + } + int firstIdx = first > last ? wqkms.size() - 1 : 0; + int lastIdx = first > last ? 0 : wqkms.size() -1; + WQKms filtered = new WQKms (wqkms.size()); + filtered.setReferenceSystem(wqkms.getReferenceSystem()); + filtered.setName(wqkms.getName()); + double [] dp = new double [3]; + + if (first > last) { + for (int i = wqkms.size() - 1; i >= 0; i--) { + dp = wqkms.get(i, dp); + if (dp[2] <= first + 1E-5 && dp[2] > last - 1E-5) { + filtered.add(dp[0], dp[1], dp[2]); + } + } + } else { + for (int i = 0; i < wqkms.size(); i++) { + dp = wqkms.get(i, dp); + if (dp[2] < last + 1E-5 && dp[2] > first - 1E-5) { + filtered.add(dp[0], dp[1], dp[2]); + } + } + } + return filtered; } @@ -484,16 +591,14 @@ NumberFormat kmf = getKmFormatter(); NumberFormat wf = getWFormatter(); NumberFormat qf = getQFormatter(); - - writer.writeNext(new String[] { - kmf.format(wqkm[2]), - wf.format(wqkm[0]), - qf.format(wqkm[1]), - RiverUtils.getLocationDescription(flys, wqkm[2]) - }); + writer.writeNext(new String[] { + kmf.format(wqkm[2]), + wf.format(wqkm[0]), + qf.format(RiverUtils.roundQ(wqkm[1])), + RiverUtils.getLocationDescription(flys, wqkm[2]) + }); } - /** Write an csv-row at gauge location. */ private void writeRow6(CSVWriter writer, double wqkm[], String wOrQDesc, D4EArtifact flys, String gaugeName) { @@ -504,13 +609,47 @@ writer.writeNext(new String[] { kmf.format(wqkm[2]), wf.format(wqkm[0]), - qf.format(wqkm[1]), + qf.format(RiverUtils.roundQ(wqkm[1])), wOrQDesc, RiverUtils.getLocationDescription(flys, wqkm[2]), gaugeName }); } + private String getDesc(WQKms wqkms, boolean isQ) + { + D4EArtifact flys = (D4EArtifact) master; + String colDesc = ""; + + if (flys instanceof WINFOArtifact && isQ) { + colDesc = getCSVRowTitle((WINFOArtifact)flys, wqkms); + } + else if (!isQ) { + Double value = RiverUtils.getValueFromWQ(wqkms); + colDesc = (value != null) ? + Formatter.getWaterlevelW(context).format(value) : null; + } + + if (flys instanceof WINFOArtifact) { + if (wqkms != null && wqkms.getRawValue() != null) { + WINFOArtifact winfo = (WINFOArtifact) flys; + colDesc = RiverUtils.getNamedMainValue(winfo, wqkms.getRawValue()); + // For 'W am Pegel' s + if (colDesc == null) { + Double value = RiverUtils.getValueFromWQ(wqkms); + colDesc = (value != null) ? + Formatter.getWaterlevelW(context).format(value) : null; + } + } + } + if (colDesc != null) { + /* Quick hack. Can be removed when database strings are + * adapted or left in here as it should never be harmful. */ + colDesc = colDesc.replace("Amtl.Festlegung_", "Amtl. "); + } + + return colDesc == null ? "" : colDesc; + } /** * Write "rows" of csv data from wqkms with writer. @@ -543,35 +682,16 @@ String notinrange = msg( CSV_NOT_IN_GAUGE_RANGE, DEFAULT_CSV_NOT_IN_GAUGE_RANGE); + List segments = null; + boolean isFixRealize = false; double a = gauge.getRange().getA().doubleValue(); double b = gauge.getRange().getB().doubleValue(); - - if (flys instanceof WINFOArtifact && isQ) { - desc = getCSVRowTitle((WINFOArtifact)flys, wqkms); - } - else if (!isQ) { - Double value = RiverUtils.getValueFromWQ(wqkms); - desc = value != null - ? Formatter.getWaterlevelW(context).format(value) : null; - } - long startTime = System.currentTimeMillis(); - String colDesc = desc; - List segments = null; - boolean isFixRealize = false; - if (flys instanceof WINFOArtifact) { - if (wqkms != null && wqkms.getRawValue() != null) { - WINFOArtifact winfo = (WINFOArtifact) flys; - colDesc = RiverUtils.getNamedMainValue(winfo, wqkms.getRawValue()); - // For 'W am Pegel' s - if (colDesc == null) { - colDesc = ((D4EArtifact)master).getDataAsString("wq_single"); - } - } - } - else if (flys instanceof FixationArtifact) { + desc = getDesc(wqkms, isQ); + + if (flys instanceof FixationArtifact) { // Get W/Q input per gauge for this case. FixRealizingAccess fixAccess = new FixRealizingAccess(flys); segments = fixAccess.getSegments(); @@ -601,7 +721,7 @@ : findSegment(km, segments); if (found != null) { - colDesc = nf.format(found.getValues()[0]); + desc = nf.format(found.getValues()[0]); } lastSegment = found; } @@ -622,7 +742,7 @@ ? gaugeName : notinrange; } - writeRow6(writer, result, colDesc, flys, gaugeN); + writeRow6(writer, result, desc, flys, gaugeN); } } else { // Not at gauge. @@ -693,7 +813,7 @@ /** - * This method is used to register a new column at writer. The name / + * Register a new column at writer. The name / * title of the column depends on the Q or W value of wqkms. If a Q * was selected and the Q fits to a named main value, the title is set to * the named main value. Otherwise, the name returned by @@ -715,9 +835,6 @@ } - /** - * - */ @Override protected void writePDF(OutputStream out) { logger.debug("write PDF"); @@ -751,12 +868,38 @@ boolean atGauge = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.WGAUGE; boolean isQ = mode == WQ_MODE.QGAUGE || mode == WQ_MODE.QFREE; + Double first = Double.NaN; + Double last = Double.NaN; + addMetaData(source); for (WQKms[] tmp: data) { for (WQKms wqkms: tmp) { addWKmsData(wqkms, atGauge, isQ, source); + double[] firstLast = wqkms.getFirstLastKM(); + if (first.isNaN()) { + /* Initialize */ + first = firstLast[0]; + last = firstLast[1]; + } + if (firstLast[0] > firstLast[1]) { + /* Calculating upstream we assert that it is + * impossible that the direction changes during this + * loop */ + first = Math.max(first, firstLast[0]); + last = Math.min(last, firstLast[1]); + } else if (firstLast[0] < firstLast[1]) { + first = Math.min(first, firstLast[0]); + last = Math.max(last, firstLast[1]); + } else { + first = last = firstLast[0]; + } } } + + /* Append the official fixing at the bottom */ + for (WQKms wqkms: officalFixings) { + addWKmsData(filterWQKms(wqkms, first, last), atGauge, isQ, source); + } return source; } @@ -769,12 +912,14 @@ Locale locale = Resources.getLocale(meta); DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale); + NumberFormat kmf = getKmFormatter(); source.addMetaData("date", df.format(new Date())); RangeAccess rangeAccess = new RangeAccess(flys); double[] kms = rangeAccess.getKmRange(); - source.addMetaData("range", kms[0] + " - " + kms[kms.length-1]); + source.addMetaData("range", + kmf.format(kms[0]) + " - " + kmf.format(kms[kms.length-1])); source.addMetaData("gauge", RiverUtils.getGaugename(flys)); @@ -815,15 +960,7 @@ double a = gauge.getRange().getA().doubleValue(); double b = gauge.getRange().getB().doubleValue(); - if (flys instanceof WINFOArtifact && isQ) { - desc = getCSVRowTitle((WINFOArtifact)flys, wqkms); - } - else if (!isQ) { - Double value = RiverUtils.getValueFromWQ(wqkms); - desc = value != null - ? Formatter.getWaterlevelW(context).format(value) : null; - } - + desc = getDesc(wqkms, isQ); long startTime = System.currentTimeMillis(); for (int i = 0; i < size; i ++) { @@ -833,7 +970,7 @@ source.addData(new String[] { kmf.format(result[2]), wf.format(result[0]), - qf.format(result[1]), + qf.format(RiverUtils.roundQ(result[1])), desc, RiverUtils.getLocationDescription(flys, result[2]), result[2] >= a && result[2] <= b @@ -845,7 +982,7 @@ source.addData(new String[] { kmf.format(result[2]), wf.format(result[0]), - qf.format(result[1]), + qf.format(RiverUtils.roundQ(result[1])), desc, RiverUtils.getLocationDescription(flys, result[2]), result[2] >= a && result[2] <= b diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -38,7 +38,6 @@ import org.jfree.data.xy.XYSeriesCollection; import org.json.JSONArray; import org.json.JSONException; -import org.w3c.dom.Document; import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.river.jfree.Bounds; @@ -47,6 +46,7 @@ import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StyledAreaSeriesCollection; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; /** @@ -991,7 +991,7 @@ protected void doPoints( Object o, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible, int axisIndex ) { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/extreme/ExtremeWQCurveGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/extreme/ExtremeWQCurveGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/extreme/ExtremeWQCurveGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -14,9 +14,9 @@ import org.jfree.chart.JFreeChart; import org.jfree.chart.plot.Marker; import org.jfree.chart.plot.ValueMarker; +import org.jfree.chart.plot.XYPlot; import org.jfree.chart.title.TextTitle; import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifactdatabase.state.Facet; @@ -32,8 +32,8 @@ import org.dive4elements.river.jfree.JFreeUtil; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.RiverUtils; -import org.dive4elements.river.utils.ThemeUtil; /** @@ -75,7 +75,7 @@ /** First, ask parent to add data, then handle extreme_wq_curve(_base) data.*/ @Override - public boolean prepareChartData(ArtifactAndFacet aaf, Document theme, boolean visible) { + public boolean prepareChartData(ArtifactAndFacet aaf, ThemeDocument theme, boolean visible) { if (super.prepareChartData(aaf, theme, visible)) { return true; } @@ -92,8 +92,18 @@ return false; } + /** Overriden to show second axis also if no visible data present. */ + @Override + protected void adjustAxes(XYPlot plot) { + super.adjustAxes(plot); + if (getCurrentGaugeDatum() != 0d) { + // Show the W[*m] axis even if there is no data. + plot.setRangeAxis(1, createYAxis(YAXIS.W.idx)); + } + } + /** Do Extreme Curve nonextrapolated points out. */ - protected void doExtremeCurveBaseOut(ArtifactAndFacet aaf, Document theme, boolean visible) { + protected void doExtremeCurveBaseOut(ArtifactAndFacet aaf, ThemeDocument theme, boolean visible) { logger.debug("doExtremeCurveBaseOut"); ExtremeCurveFacet facet = (ExtremeCurveFacet) aaf.getFacet(); Curve curve = (Curve) facet.getData(aaf.getArtifact(), context); @@ -125,7 +135,7 @@ /** Do Extreme Curve out */ - protected void doExtremeCurveOut(ArtifactAndFacet aaf, Document theme, boolean visible) { + protected void doExtremeCurveOut(ArtifactAndFacet aaf, ThemeDocument theme, boolean visible) { logger.debug("doExtremeCurveOut"); ExtremeCurveFacet facet = (ExtremeCurveFacet) aaf.getFacet(); Curve curve = (Curve) facet.getData(aaf.getArtifact(), context); @@ -148,7 +158,7 @@ maxQ); // end // Add marker from where on its extrapolated. - if (ThemeUtil.parseShowExtraMark(theme)) { + if (theme.parseShowExtraMark()) { double[] qs = curve.getQs(); double extrapolateFrom = qs[qs.length-1]; diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixATExport.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixATExport.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixATExport.java Thu Sep 12 10:13:09 2013 +0200 @@ -16,6 +16,7 @@ import org.dive4elements.river.artifacts.access.FixAccess; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.RiverUtils; import org.dive4elements.river.artifacts.math.fitting.Function; @@ -37,7 +38,6 @@ import org.apache.log4j.Logger; -import org.w3c.dom.Document; import org.w3c.dom.NodeList; /** Export result of fixation analysis. */ @@ -52,7 +52,7 @@ @Override - public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { + public void doOut(ArtifactAndFacet bundle, ThemeDocument attr, boolean visible) { logger.debug("AT Export doOut()."); Object data = bundle.getData(context); if (data instanceof CalculationResult) { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixATWriter.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixATWriter.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixATWriter.java Thu Sep 12 10:13:09 2013 +0200 @@ -115,7 +115,7 @@ double wMin = minW(invInst, wMax, qMax[0]); - double wMinCM = wMin * 100d; + double wMinCM = wMin * 100d - subtractPNP; double wMaxCM = wMax * 100d; int wRow = ((int)wMinCM / 10) * 10; @@ -124,7 +124,7 @@ wMinCM = (int)wMinCM + 1d; } - double w = wMinCM / 100.0; + double w = (wMinCM + subtractPNP) / 100.0; int wcm = ((int)wMinCM) % 10; @@ -132,9 +132,10 @@ log.debug("wMinCM: " + wMinCM); log.debug("wMaxCM: " + wMaxCM); log.debug("wcm: " + wcm); + log.debug("subtractPNP: " + subtractPNP); } - out.printf(Locale.US, "%8d", wRow - subtractPNP); + out.printf(Locale.US, "%8d", wRow); for (int i = 0; i < wcm; i++) { out.print(ATWriter.EMPTY); @@ -158,7 +159,7 @@ if (w > wMax) { break; } - out.printf(Locale.US, "%8d", (wRow += 10) - subtractPNP); + out.printf(Locale.US, "%8d", (wRow += 10)); wcm = 0; } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDeltaWtGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDeltaWtGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDeltaWtGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -23,7 +23,7 @@ import org.dive4elements.river.jfree.StyledDomainMarker; import org.dive4elements.river.jfree.StyledTimeSeries; import org.dive4elements.river.jfree.StyledValueMarker; -import org.dive4elements.river.utils.ThemeUtil; +import org.dive4elements.river.themes.ThemeDocument; import java.io.OutputStream; import java.text.NumberFormat; @@ -35,13 +35,14 @@ import org.apache.log4j.Logger; import org.jfree.chart.annotations.XYTextAnnotation; -import org.jfree.data.time.Day; import org.jfree.data.time.RegularTimePeriod; import org.jfree.data.time.FixedMillisecond; import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; import org.w3c.dom.Document; +import gnu.trove.TLongHashSet; + /** * Generator for Delta W(t) charts. @@ -80,7 +81,10 @@ } - private D4EArtifact artifact = null; + private D4EArtifact artifact; + + // Used to make the dates collision free. + private TLongHashSet uniqueDates = new TLongHashSet(); @Override @@ -156,7 +160,7 @@ @Override public void doOut( ArtifactAndFacet artifactFacet, - Document theme, + ThemeDocument theme, boolean visible ) { String name = artifactFacet.getFacetName(); @@ -226,11 +230,11 @@ protected void doReferencePeriodsOut( - D4EArtifact artifact, - Object data, - String desc, - Document theme, - boolean visible) + D4EArtifact artifact, + Object data, + String desc, + ThemeDocument theme, + boolean visible) { logger.debug("doReferencePeriodsOut()"); @@ -248,13 +252,19 @@ } } + private long uniqueDate(long date) { + return uniqueDates.add(date) + ? date + : uniqueDate(date+30L*1000L); // add 30secs. + } + protected void doSectorAverageOut( - D4EArtifact artifact, - Object data, - String desc, - Document theme, - boolean visible) + D4EArtifact artifact, + Object data, + String desc, + ThemeDocument theme, + boolean visible) { logger.debug("doSectorAverageOut(): description = " + desc); @@ -270,16 +280,16 @@ // Draw a line spanning the analysis time. series.add(rtp, value); - rtp = new Day(qwd.dateRange.getFrom()); + rtp = new FixedMillisecond(qwd.dateRange.getFrom()); series.addOrUpdate(rtp, value); - rtp = new Day(qwd.dateRange.getTo()); + rtp = new FixedMillisecond(qwd.dateRange.getTo()); series.addOrUpdate(rtp, value); tsc.addSeries(series); addAxisDataset(tsc, 0, visible); - if (visible && ThemeUtil.parseShowLineLabel(theme)) { + if (visible && theme.parseShowLineLabel()) { List textAnnos = new ArrayList(); XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( "\u0394 W(t) [cm] " + (float)Math.round(qwd.qwd.getDeltaW() * 10000) / 10000, @@ -298,7 +308,7 @@ D4EArtifact artifact, Object data, String desc, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("doAnalysisEventsOut: desc = " + desc); @@ -308,7 +318,7 @@ } - protected void doQWDEventsOut(QWD qwd, String desc, Document theme, boolean visible) + protected void doQWDEventsOut(QWD qwd, String desc, ThemeDocument theme, boolean visible) { TimeSeriesCollection tsc = new TimeSeriesCollection(); @@ -324,7 +334,8 @@ int idxInterpol = 0; int idxRegular = 0; - RegularTimePeriod rtp = new FixedMillisecond(qwd.getDate()); + long time = uniqueDate(qwd.getDate().getTime()); + RegularTimePeriod rtp = new FixedMillisecond(time); double value = qwd.getDeltaW(); boolean interpolate = qwd.getInterpolated(); if (interpolate) { @@ -358,11 +369,11 @@ * @param annoIdxMap map of index in qwds to series/data item indices in tsc. */ protected void doQWDTextAnnotations(Map annoIdxMap, - TimeSeriesCollection tsc, QWD qwd, Document theme, + TimeSeriesCollection tsc, QWD qwd, ThemeDocument theme, boolean visible) { logger.debug("doQWDTextAnnotation()"); - if (!visible || !ThemeUtil.parseShowPointLabel(theme)) { + if (!visible || !theme.parseShowPointLabel()) { logger.debug("doQWDTextAnnotation: annotation not visible"); return; } @@ -390,11 +401,11 @@ protected void doReferenceEventsOut( - D4EArtifact artifact, - Object data, - String desc, - Document theme, - boolean visible + D4EArtifact artifact, + Object data, + String desc, + ThemeDocument theme, + boolean visible ) { logger.debug("doReferenceEventsOut: desc = " + desc); @@ -404,11 +415,11 @@ protected void doDeviationOut( - D4EArtifact artifact, - Object data, - String desc, - Document theme, - boolean visible + D4EArtifact artifact, + Object data, + String desc, + ThemeDocument theme, + boolean visible ) { logger.debug("doDeviationOut: desc = " + desc); @@ -427,10 +438,10 @@ protected void doAnalysisPeriodsOut( D4EArtifact artifact, - Object data, - String desc, - Document theme, - boolean visible) + Object data, + String desc, + ThemeDocument theme, + boolean visible) { DateRange[] ranges = (DateRange[]) data; if (ranges == null || !visible) { @@ -462,7 +473,9 @@ context.putContextValue("currentKm", currentKm); - StyledValueMarker marker = new StyledValueMarker(0, request); + // XXX: This looks hackish! + StyledValueMarker marker = + new StyledValueMarker(0, new ThemeDocument(request)); valueMarker.add(marker); } } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDerivedCurveGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDerivedCurveGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixDerivedCurveGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -9,7 +9,6 @@ package org.dive4elements.river.exports.fixings; import org.apache.log4j.Logger; -import org.w3c.dom.Document; import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.river.artifacts.model.FacetTypes; @@ -19,6 +18,7 @@ import org.dive4elements.river.exports.ChartGenerator; import org.dive4elements.river.jfree.JFreeUtil; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; /** * Generator for fixation derived function curve. @@ -65,7 +65,7 @@ @Override - public void doOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + public void doOut(ArtifactAndFacet aaf, ThemeDocument doc, boolean visible) { logger.debug("doOut"); if (FacetTypes.IS.MANUALPOINTS(aaf.getFacetName())) { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixLongitudinalSectionGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixLongitudinalSectionGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixLongitudinalSectionGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -27,13 +27,13 @@ import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StyledAreaSeriesCollection; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.DataUtil; import org.dive4elements.river.utils.KMIndex; import org.dive4elements.river.utils.RiverUtils; import org.jfree.chart.plot.Marker; import org.jfree.chart.plot.ValueMarker; import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; public class FixLongitudinalSectionGenerator extends FixChartGenerator @@ -81,7 +81,7 @@ } @Override - public void doOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + public void doOut(ArtifactAndFacet aaf, ThemeDocument doc, boolean visible) { String name = aaf.getFacetName(); logger.debug("FixLongitudinalSectionGenerator: doOut: " + name); @@ -136,7 +136,7 @@ protected void doQOut( WQKms wqkms, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("LongitudinalSectionGenerator.doQOut"); @@ -184,7 +184,7 @@ @SuppressWarnings("unchecked") protected void doSectorAverageDeviationOut( ArtifactAndFacet aaf, - Document doc, + ThemeDocument doc, boolean visible) { logger.debug("doSectorAverageOut" + aaf.getFacet().getIndex()); @@ -230,7 +230,7 @@ @SuppressWarnings("unchecked") protected void doReferenceDeviationOut( ArtifactAndFacet aaf, - Document doc, + ThemeDocument doc, boolean visible) { logger.debug("doReferenceOut"); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixWQCurveGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixWQCurveGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/fixings/FixWQCurveGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -21,12 +21,12 @@ import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.plot.Marker; import org.jfree.chart.plot.ValueMarker; +import org.jfree.chart.plot.XYPlot; import org.jfree.chart.title.TextTitle; import org.jfree.data.xy.XYSeries; import org.jfree.ui.RectangleAnchor; import org.jfree.ui.RectangleInsets; import org.jfree.ui.TextAnchor; -import org.w3c.dom.Document; import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifactdatabase.state.Facet; @@ -56,8 +56,8 @@ import org.dive4elements.river.jfree.StyledXYSeries; import org.dive4elements.river.model.Gauge; import org.dive4elements.river.model.River; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.RiverUtils; -import org.dive4elements.river.utils.ThemeUtil; /** * Generator for WQ fixing charts. @@ -153,18 +153,28 @@ return axis; } + /** Returns value != 0 if the current km is not at a gauge. */ public double getCurrentGaugeDatum() { if (context.getContextValue(CURRENT_KM) != null) { return DischargeCurveGenerator.getCurrentGaugeDatum( (Double) context.getContextValue(CURRENT_KM), - (D4EArtifact) getMaster(), 0.1d); + (D4EArtifact) getMaster(), 1e-4); } else return 0d; } + /** Overriden to show second axis also if no visible data present. */ + @Override + protected void adjustAxes(XYPlot plot) { + super.adjustAxes(plot); + if (getCurrentGaugeDatum() != 0d) { + // Show the W[*m] axis even if there is no data. + plot.setRangeAxis(1, createYAxis(YAXIS.W.idx)); + } + } @Override - public void doOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + public void doOut(ArtifactAndFacet aaf, ThemeDocument doc, boolean visible) { logger.debug("doOut: " + aaf.getFacetName()); if (!prepareChartData(aaf, doc, visible)) { logger.warn("Unknown facet, name " + aaf.getFacetName()); @@ -175,7 +185,7 @@ * Return true if data could be handled, * to be overridden to add more handled data. */ - public boolean prepareChartData(ArtifactAndFacet aaf, Document doc, boolean visible) { + public boolean prepareChartData(ArtifactAndFacet aaf, ThemeDocument doc, boolean visible) { String name = aaf.getFacetName(); this.artifact = (D4EArtifact) aaf.getArtifact(); @@ -226,8 +236,9 @@ visible); } else if (name.equals(MAINVALUES_W) || name.equals(MAINVALUES_Q)) { + RiverAnnotation mainValues = (RiverAnnotation) aaf.getData(context); doAnnotations( - ((RiverAnnotation) aaf.getData(context)), + mainValues, aaf, doc, visible); @@ -245,7 +256,7 @@ /** Add sector average points to chart. */ - protected void doSectorAverageOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + protected void doSectorAverageOut(ArtifactAndFacet aaf, ThemeDocument doc, boolean visible) { logger.debug("doSectorAverageOut"); QWDDateRange qwdd = (QWDDateRange) aaf.getData(context); @@ -260,7 +271,7 @@ } /** Add analysis event points to chart. */ - protected void doAnalysisEventsOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + protected void doAnalysisEventsOut(ArtifactAndFacet aaf, ThemeDocument doc, boolean visible) { logger.debug("doAnalysisEventsOut"); QWD qwd = (QWD)aaf.getData(context); @@ -280,7 +291,7 @@ textAnnos.add(anno); addAxisSeries(series, YAXIS.W.idx, visible); - if(visible && ThemeUtil.parseShowPointLabel(doc)) { + if(visible && doc.parseShowPointLabel()) { RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, doc); flysAnno.setTextAnnotations(textAnnos); addAnnotations(flysAnno); @@ -293,42 +304,42 @@ /** Add reference event points to chart. */ - protected void doReferenceEventsOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + protected void doReferenceEventsOut(ArtifactAndFacet aaf, ThemeDocument doc, boolean visible) { logger.debug("doReferenceEventsOut"); QWI qwd = (QWI)aaf.getData(context); - if(qwd != null) { - XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), doc); - List textAnnos = new ArrayList(); - - DateFormat dateFormat = DateFormat.getDateInstance( - DateFormat.SHORT); - - series.add(qwd.getQ(), qwd.getW()); + if (qwd == null) { + logger.debug("doReferenceEventsOut: qwds == null"); + return; + } - XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( - dateFormat.format(qwd.getDate()), - qwd.getQ(), - qwd.getW()); - textAnnos.add(anno); + XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), false, true, doc); + List textAnnos = new ArrayList(); - addAxisSeries(series, YAXIS.W.idx, visible); - if(visible && ThemeUtil.parseShowPointLabel(doc)) { - RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, doc); - flysAnno.setTextAnnotations(textAnnos); - addAnnotations(flysAnno); - } - } - else { - logger.debug("doReferenceEventsOut: qwds == null"); + DateFormat dateFormat = DateFormat.getDateInstance( + DateFormat.SHORT); + + series.add(qwd.getQ(), qwd.getW(), false); + + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + dateFormat.format(qwd.getDate()), + qwd.getQ(), + qwd.getW()); + textAnnos.add(anno); + + addAxisSeries(series, YAXIS.W.idx, visible); + if(visible && doc.parseShowPointLabel()) { + RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, doc); + flysAnno.setTextAnnotations(textAnnos); + addAnnotations(flysAnno); } } private void addPointFromWQKms(WQKms wqkms, - String title, - Document theme, - boolean visible + String title, + ThemeDocument theme, + boolean visible ) { XYSeries series = new StyledXYSeries(title, theme); Double ckm = (Double) context.getContextValue(CURRENT_KM); @@ -339,14 +350,25 @@ double[] kms = wqkms.getKms(); for (int i = 0 ; i< kms.length; i++) { if (Math.abs(kms[i] - ckm) <= EPSILON) { - series.add(wqkms.getQ(i), wqkms.getW(i)); + series.add(wqkms.getQ(i), wqkms.getW(i), false); addAxisSeries(series, YAXIS.W.idx, visible); + if(visible && theme.parseShowPointLabel()) { + List textAnnos = new ArrayList(); + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + title, + wqkms.getQ(i), + wqkms.getW(i)); + textAnnos.add(anno); + RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, theme); + flysAnno.setTextAnnotations(textAnnos); + addAnnotations(flysAnno); + } return; } } } - protected void doEventsOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + protected void doEventsOut(ArtifactAndFacet aaf, ThemeDocument doc, boolean visible) { logger.debug("doEventsOut"); // Find W/Q at km. addPointFromWQKms((WQKms) aaf.getData(context), @@ -354,7 +376,7 @@ } - protected void doWQCurveOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + protected void doWQCurveOut(ArtifactAndFacet aaf, ThemeDocument doc, boolean visible) { logger.debug("doWQCurveOut"); FixWQCurveFacet facet = (FixWQCurveFacet)aaf.getFacet(); @@ -385,6 +407,14 @@ addAxisSeries(series, YAXIS.W.idx, visible); } else { + StyledXYSeries series2 = JFreeUtil.sampleFunction2D( + func.getFunction(), + doc, + aaf.getFacetDescription(), + 500, // number of samples + 0.0 , // start + maxQ); // end + addAxisSeries(series2, YAXIS.W.idx, false); // Use second axis at cm if at gauge. for (int i = 0; i < series.getItemCount(); i++) { series.updateByIndex(i, new Double(factor*(series.getY(i).doubleValue()-gaugeDatum))); @@ -397,7 +427,7 @@ } } - protected void doOutlierOut(ArtifactAndFacet aaf, Document doc, boolean visible) { + protected void doOutlierOut(ArtifactAndFacet aaf, ThemeDocument doc, boolean visible) { logger.debug("doOutlierOut"); QWI[] qws = (QWI[])aaf.getData(context); @@ -406,7 +436,7 @@ /** Add markers for q sectors. */ - protected void doQSectorOut(ArtifactAndFacet aaf, Document theme, boolean visible) { + protected void doQSectorOut(ArtifactAndFacet aaf, ThemeDocument theme, boolean visible) { logger.debug("doQSectorOut"); if (!visible) { return; @@ -434,8 +464,8 @@ Marker m = new ValueMarker(qsector.getValue()); m.setPaint(Color.black); - float[] dashes = ThemeUtil.parseLineStyle(theme); - int size = ThemeUtil.parseLineWidth(theme); + float[] dashes = theme.parseLineStyle(); + int size = theme.parseLineWidth(); BasicStroke stroke; if (dashes.length <= 1) { stroke = new BasicStroke(size); @@ -450,12 +480,12 @@ } m.setStroke(stroke); - if (ThemeUtil.parseShowLineLabel(theme)) { + if (theme.parseShowLineLabel()) { m.setLabel(qsector.getName()); - m.setPaint(ThemeUtil.parseTextColor(theme)); - m.setLabelFont(ThemeUtil.parseTextFont(theme)); + m.setPaint(theme.parseTextColor()); + m.setLabelFont(theme.parseTextFont()); } - Color paint = ThemeUtil.parseLineColorField(theme); + Color paint = theme.parseLineColorField(); if (paint != null) { m.setPaint(paint); } @@ -473,10 +503,10 @@ * @param theme theme to use. */ protected void doWAnnotations( - Object wqkms, + Object wqkms, ArtifactAndFacet aandf, - Document theme, - boolean visible + ThemeDocument theme, + boolean visible ) { Facet facet = aandf.getFacet(); @@ -518,7 +548,7 @@ WINFOArtifact artifact, Object o, String description, - Document theme, + ThemeDocument theme, boolean visible) { WQKms wqkms = (WQKms) o; @@ -552,7 +582,7 @@ protected void doWQOut( Object wqkms, ArtifactAndFacet aaf, - Document theme, + ThemeDocument theme, boolean visible ) { logger.debug("FixWQCurveGenerator: doWQOut"); @@ -567,7 +597,7 @@ logger.debug("FixWQCurveGenerator: doWQOut: double[][]"); double [][] data = (double [][]) wqkms; - XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); + XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), false, true, theme); StyledSeriesBuilder.addPoints(series, data, true); addAxisSeries(series, YAXIS.W.idx, visible); @@ -578,14 +608,18 @@ protected void addQWSeries( QWI [] qws, ArtifactAndFacet aaf, - Document theme, + ThemeDocument theme, boolean visible ) { if (qws == null) { return; } - XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); + XYSeries series = new StyledXYSeries( + aaf.getFacetDescription(), + false, true, + theme); + List textAnnos = new ArrayList(qws.length); @@ -593,7 +627,7 @@ DateFormat.SHORT); for (QWI qw: qws) { - series.add(qw.getQ(), qw.getW()); + series.add(qw.getQ(), qw.getW(), false); XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( dateFormat.format(qw.getDate()), @@ -603,7 +637,7 @@ } addAxisSeries(series, YAXIS.W.idx, visible); - if (visible && ThemeUtil.parseShowPointLabel(theme)) { + if (visible && theme.parseShowPointLabel()) { RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, theme); flysAnno.setTextAnnotations(textAnnos); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDiffBaseGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDiffBaseGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -0,0 +1,59 @@ +/* Copyright (C) 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.exports.minfo; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.river.artifacts.model.minfo.BedDifferencesResult; +import org.dive4elements.river.jfree.Bounds; +import org.dive4elements.river.jfree.DoubleBounds; +import org.dive4elements.river.exports.fixings.FixChartGenerator; + +/** Base for BedDiff*Year*Generators, to avoid duplicate code of setContextBounds. */ +public abstract class BedDiffBaseGenerator +extends FixChartGenerator +{ + /** The logger that is used in this generator. */ + private static Logger logger = Logger.getLogger(BedDiffBaseGenerator.class); + + /** Set context values for something. */ + public void setContextBounds(ArtifactAndFacet bundle) { + Bounds xBounds = getXBounds(0); + if (xBounds != null && getDomainAxisRange() != null) { + Bounds bounds = + calculateZoom(xBounds, getDomainAxisRange()); + context.putContextValue("startkm", bounds.getLower()); + context.putContextValue("endkm", bounds.getUpper()); + } + else if (xBounds != null && getDomainAxisRange() == null) { + context.putContextValue("startkm", xBounds.getLower()); + context.putContextValue("endkm", xBounds.getUpper()); + } + else if (xBounds == null && getDomainAxisRange() == null) { + BedDifferencesResult data = (BedDifferencesResult)bundle.getData(context); + if (data.getKms().size() > 0) { + context.putContextValue("startkm", data.getKms().min()); + context.putContextValue("endkm", data.getKms().max()); + } + else { + logger.warn("No data to define start and end km"); + } + } + else if (xBounds == null && getDomainAxisRange() != null){ + BedDifferencesResult data = (BedDifferencesResult)bundle.getData(context); + Bounds b = new DoubleBounds(data.getKms().min(), data.getKms().max()); + Bounds bounds = + calculateZoom(b, getDomainAxisRange()); + context.putContextValue("startkm", bounds.getLower()); + context.putContextValue("endkm", bounds.getUpper()); + } + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDiffHeightYearGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDiffHeightYearGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDiffHeightYearGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -9,26 +9,20 @@ package org.dive4elements.river.exports.minfo; import org.apache.log4j.Logger; -import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifactdatabase.state.Facet; import org.dive4elements.river.artifacts.model.FacetTypes; -import org.dive4elements.river.artifacts.model.minfo.BedDiffYearResult; import org.dive4elements.river.artifacts.model.minfo.BedDifferencesResult; -import org.dive4elements.river.exports.StyledSeriesBuilder; -import org.dive4elements.river.exports.fixings.FixChartGenerator; +import org.dive4elements.river.exports.process.BedDiffHeightYearProcessor; import org.dive4elements.river.exports.process.KMIndexProcessor; import org.dive4elements.river.exports.process.Processor; -import org.dive4elements.river.jfree.Bounds; -import org.dive4elements.river.jfree.DoubleBounds; import org.dive4elements.river.jfree.RiverAnnotation; -import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; public class BedDiffHeightYearGenerator -extends FixChartGenerator +extends BedDiffBaseGenerator implements FacetTypes { public enum YAXIS { @@ -74,7 +68,7 @@ } @Override - public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { + public void doOut(ArtifactAndFacet bundle, ThemeDocument attr, boolean visible) { String name = bundle.getFacetName(); logger.debug("doOut: " + name); @@ -91,42 +85,12 @@ } if (bundle.getData(context) instanceof BedDifferencesResult) { - if (getXBounds(0) != null && getDomainAxisRange() != null) { - Bounds bounds = - calculateZoom(getXBounds(0), getDomainAxisRange()); - context.putContextValue("startkm", bounds.getLower()); - context.putContextValue("endkm", bounds.getUpper()); - } - else if (getXBounds(0) != null && getDomainAxisRange() == null) { - context.putContextValue("startkm", getXBounds(0).getLower()); - context.putContextValue("endkm", getXBounds(0).getUpper()); - } - else if (getXBounds(0) == null && getDomainAxisRange() == null) { - BedDifferencesResult data = (BedDifferencesResult)bundle.getData(context); - context.putContextValue("startkm", data.getKms().min()); - context.putContextValue("endkm", data.getKms().max()); - } - else if (getXBounds(0) == null && getDomainAxisRange() != null){ - BedDifferencesResult data = (BedDifferencesResult)bundle.getData(context); - Bounds b = new DoubleBounds(data.getKms().min(), data.getKms().max()); - Bounds bounds = - calculateZoom(b, getDomainAxisRange()); - context.putContextValue("startkm", bounds.getLower()); - context.putContextValue("endkm", bounds.getUpper()); - } + setContextBounds(bundle); } + Processor processor = new KMIndexProcessor(); - if (name.equals(BED_DIFFERENCE_HEIGHT_YEAR)) { - doBedDifferenceYearOut( - (BedDiffYearResult) bundle.getData(context), - bundle, attr, visible); - } - else if (name.equals(BED_DIFFERENCE_HEIGHT_YEAR_FILTERED)) { - doBedDifferenceYearOut( - (BedDiffYearResult) bundle.getData(context), - bundle, attr, visible); - } - else if (name.equals(LONGITUDINAL_ANNOTATION)) { + Processor bdyProcessor = new BedDiffHeightYearProcessor(); + if (name.equals(LONGITUDINAL_ANNOTATION)) { doAnnotations( (RiverAnnotation) bundle.getData(context), bundle, @@ -136,11 +100,15 @@ else if (processor.canHandle(name)) { processor.doOut(this, bundle, attr, visible, YAXIS.dW.idx); } + else if (bdyProcessor.canHandle(name)) { + bdyProcessor.doOut(this, bundle, attr, visible, YAXIS.D.idx); + } else { logger.warn("Unknown facet name " + name); } } + @Override protected String getDefaultChartTitle() { return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT); @@ -163,13 +131,4 @@ } return "default"; } - - protected void doBedDifferenceYearOut(BedDiffYearResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data.getHeightPerYearData(), true); - - addAxisSeries(series, YAXIS.D.idx, visible); - } } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceEpochGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceEpochGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceEpochGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -10,7 +10,6 @@ import org.apache.log4j.Logger; import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifactdatabase.state.Facet; @@ -28,6 +27,7 @@ import org.dive4elements.river.jfree.DoubleBounds; import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.DataUtil; import org.dive4elements.river.utils.RiverUtils; @@ -86,7 +86,7 @@ } @Override - public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { + public void doOut(ArtifactAndFacet bundle, ThemeDocument attr, boolean visible) { String name = bundle.getFacetName(); logger.debug("doOut: " + name); @@ -215,7 +215,7 @@ } protected void doBedDifferenceEpochOut(BedDiffEpochResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { + ArtifactAndFacet aandf, ThemeDocument theme, boolean visible) { XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); StyledSeriesBuilder.addPoints(series, data.getDifferencesData(), true); @@ -226,7 +226,7 @@ private void doBedDifferenceHeightsOut( BedDiffEpochResult data, ArtifactAndFacet bundle, - Document attr, + ThemeDocument attr, boolean visible, int idx) { logger.debug("doBedDifferenceHeightOut()"); @@ -245,7 +245,7 @@ protected void doWDifferencesOut( WKms wkms, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { if (wkms == null) { @@ -262,3 +262,4 @@ } } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceExporter.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceExporter.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceExporter.java Thu Sep 12 10:13:09 2013 +0200 @@ -1,3 +1,11 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + package org.dive4elements.river.exports.minfo; import java.io.IOException; @@ -75,8 +83,7 @@ NumberFormat kmf = Formatter.getCalculationKm(context.getMeta()); NumberFormat mf = Formatter.getMeterFormat(context); - for (int i = 0; i < results.length; i++) { - BedDifferencesResult result = results[i]; + for (BedDifferencesResult result : results) { double[][] kms = result.getDifferencesData(); for (int j = 0; j < kms[0].length; j++) { writer.writeNext(new String[] { @@ -184,3 +191,4 @@ } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceYearGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceYearGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedDifferenceYearGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -10,7 +10,6 @@ import org.apache.log4j.Logger; import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifactdatabase.state.Facet; @@ -21,24 +20,24 @@ import org.dive4elements.river.artifacts.model.minfo.BedDifferencesResult; import org.dive4elements.river.artifacts.model.minfo.MorphologicWidth; import org.dive4elements.river.exports.StyledSeriesBuilder; -import org.dive4elements.river.exports.fixings.FixChartGenerator; +import org.dive4elements.river.exports.process.BedDiffYearProcessor; +import org.dive4elements.river.exports.process.BedDiffHeightYearProcessor; import org.dive4elements.river.exports.process.KMIndexProcessor; import org.dive4elements.river.exports.process.Processor; import org.dive4elements.river.exports.process.WOutProcessor; -import org.dive4elements.river.jfree.Bounds; -import org.dive4elements.river.jfree.DoubleBounds; import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.DataUtil; import org.dive4elements.river.utils.RiverUtils; public class BedDifferenceYearGenerator -extends FixChartGenerator +extends BedDiffBaseGenerator implements FacetTypes { public enum YAXIS { - D(0), M(1), H(2), dW(3), W(4); + D(0), M(1), H(2), dW(3), W(4); protected int idx; @@ -58,7 +57,7 @@ public static final String I18N_CHART_TITLE_DEFAULT = "Sohlenhöhen Differenz"; public static final String I18N_XAXIS_LABEL_DEFAULT = "Fluss-Km"; - public static final String I18N_YAXIS_LABEL_DEFAULT = "delta S [m]"; + public static final String I18N_YAXIS_LABEL_DEFAULT = "delta S [cm]"; public static final String I18N_SECOND_YAXIS_LABEL_DEFAULT = "Breite [m]"; public static final String I18N_THIRD_YAXIS_LABEL_DEFAULT = "Höhe [m]"; public static final String I18N_DW_YAXIS_LABEL_DEFAULT = @@ -86,8 +85,9 @@ }; } + @Override - public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { + public void doOut(ArtifactAndFacet bundle, ThemeDocument attr, boolean visible) { String name = bundle.getFacetName(); logger.debug("doOut: " + name); @@ -103,66 +103,19 @@ return; } - if (getXBounds(0) != null && getDomainAxisRange() != null) { - Bounds bounds = - calculateZoom(getXBounds(0), getDomainAxisRange()); - context.putContextValue("startkm", bounds.getLower()); - context.putContextValue("endkm", bounds.getUpper()); - } - else if (getXBounds(0) != null && getDomainAxisRange() == null) { - context.putContextValue("startkm", getXBounds(0).getLower()); - context.putContextValue("endkm", getXBounds(0).getUpper()); + if (bundle.getData(context) instanceof BedDifferencesResult) { + setContextBounds(bundle); } - else if (getXBounds(0) == null && getDomainAxisRange() == null) { - BedDifferencesResult data = (BedDifferencesResult)bundle.getData(context); - context.putContextValue("startkm", data.getKms().min()); - context.putContextValue("endkm", data.getKms().max()); - } - else if (getXBounds(0) == null && getDomainAxisRange() != null){ - BedDifferencesResult data = (BedDifferencesResult)bundle.getData(context); - Bounds b = new DoubleBounds(data.getKms().min(), data.getKms().max()); - Bounds bounds = - calculateZoom(b, getDomainAxisRange()); - context.putContextValue("startkm", bounds.getLower()); - context.putContextValue("endkm", bounds.getUpper()); - } + Processor processor = new KMIndexProcessor(); Processor woutp = new WOutProcessor(); - if (name.equals(BED_DIFFERENCE_YEAR)) { - doBedDifferenceYearOut( - (BedDiffYearResult) bundle.getData(context), - bundle, attr, visible); - } - else if (name.equals(BED_DIFFERENCE_MORPH_WIDTH)) { + Processor bdhyProcessor = new BedDiffHeightYearProcessor(); + Processor bdyProcessor = new BedDiffYearProcessor(); + if (name.equals(BED_DIFFERENCE_MORPH_WIDTH)) { doBedDifferenceMorphWidthOut( (BedDiffYearResult) bundle.getData(context), bundle, attr, visible); } - else if (name.equals(BED_DIFFERENCE_YEAR_HEIGHT1)) { - doBedDifferenceHeightsOut( - (BedDiffYearResult)bundle.getData(context), - bundle, attr, visible, 0); - } - else if (name.equals(BED_DIFFERENCE_YEAR_HEIGHT2)) { - doBedDifferenceHeightsOut( - (BedDiffYearResult)bundle.getData(context), - bundle, attr, visible, 1); - } - else if (name.equals(BED_DIFFERENCE_YEAR_FILTERED)) { - doBedDifferenceYearOut( - (BedDiffYearResult) bundle.getData(context), - bundle, attr, visible); - } - else if (name.equals(BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED)) { - doBedDifferenceHeightsOut( - (BedDiffYearResult)bundle.getData(context), - bundle, attr, visible, 0); - } - else if (name.equals(BED_DIFFERENCE_YEAR_HEIGHT2_FILTERED)) { - doBedDifferenceHeightsOut( - (BedDiffYearResult)bundle.getData(context), - bundle, attr, visible, 1); - } else if (name.equals(MORPHOLOGIC_WIDTH)) { doMorphologicWidthOut( (MorphologicWidth)bundle.getData(context), @@ -181,6 +134,12 @@ attr, visible); } + else if (bdyProcessor.canHandle(name)) { + bdyProcessor.doOut(this, bundle, attr, visible, YAXIS.H.idx); + } + else if (bdhyProcessor.canHandle(name)) { + bdhyProcessor.doOut(this, bundle, attr, visible, YAXIS.D.idx); + } else if (woutp.canHandle(name)) { woutp.doOut(this, bundle, attr, visible, YAXIS.W.idx); } @@ -199,7 +158,7 @@ private void doMorphologicWidthOut( MorphologicWidth data, ArtifactAndFacet bundle, - Document attr, + ThemeDocument attr, boolean visible, int i) { XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), attr); @@ -208,24 +167,6 @@ addAxisSeries(series, YAXIS.M.idx, visible); } - private void doBedDifferenceHeightsOut( - BedDiffYearResult data, - ArtifactAndFacet bundle, - Document attr, - boolean visible, - int idx) { - logger.debug("doBedDifferenceYearOut()"); - - XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), attr); - if (idx == 0) { - StyledSeriesBuilder.addPoints(series, data.getHeights1Data(), true); - } - else { - StyledSeriesBuilder.addPoints(series, data.getHeights2Data(), true); - } - - addAxisSeries(series, YAXIS.H.idx, visible); - } @Override protected String getDefaultChartTitle() { @@ -267,18 +208,9 @@ return label; } - protected void doBedDifferenceYearOut(BedDiffYearResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { - logger.debug("doBedDifferenceYearOut()"); - - XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); - StyledSeriesBuilder.addPoints(series, data.getDifferencesData(), true); - - addAxisSeries(series, YAXIS.D.idx, visible); - } protected void doBedDifferenceMorphWidthOut(BedDiffYearResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { + ArtifactAndFacet aandf, ThemeDocument theme, boolean visible) { logger.debug("doBedDifferencesMorphWidthOut()"); XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); @@ -288,10 +220,10 @@ } protected void doWDifferencesOut( - WKms wkms, + WKms wkms, ArtifactAndFacet aandf, - Document theme, - boolean visible + ThemeDocument theme, + boolean visible ) { if (wkms == null) { logger.warn("No data to add to WDifferencesChart."); @@ -307,3 +239,4 @@ } } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/minfo/BedQualityGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -10,7 +10,6 @@ import org.apache.log4j.Logger; import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifactdatabase.state.Facet; @@ -23,6 +22,7 @@ import org.dive4elements.river.exports.XYChartGenerator; import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; /** @@ -140,8 +140,12 @@ * @param attr * theme for facet */ - public void doOut(ArtifactAndFacet artifactAndFacet, Document attr, - boolean visible) { + @Override + public void doOut( + ArtifactAndFacet artifactAndFacet, + ThemeDocument attr, + boolean visible + ) { String name = artifactAndFacet.getFacetName(); logger.debug("BedQualityGenerator.doOut: " + name); @@ -221,7 +225,7 @@ private void doBedDiameterDataOut( BedDiameterData data, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); @@ -231,7 +235,7 @@ } protected void doBedDiameterTopLayerOut(BedDiameterResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { + ArtifactAndFacet aandf, ThemeDocument theme, boolean visible) { logger.debug("BedQuality.doBedDiameterTopLayerOut"); XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); @@ -241,7 +245,7 @@ } protected void doBedDiameterSubLayerOut(BedDiameterResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { + ArtifactAndFacet aandf, ThemeDocument theme, boolean visible) { logger.debug("BedQuality.doBedDiameterSubLayerOut"); XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); @@ -251,7 +255,7 @@ } protected void doBedLoadDiameterOut(BedloadDiameterResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { + ArtifactAndFacet aandf, ThemeDocument theme, boolean visible) { logger.debug("BedQuality.doBedLoadDiameterOut"); XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); @@ -261,7 +265,7 @@ } protected void doPorosityTopLayerOut(BedParametersResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { + ArtifactAndFacet aandf, ThemeDocument theme, boolean visible) { logger.debug("BedQuality.doPorosityTopLayerOut"); XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); @@ -273,7 +277,7 @@ } protected void doPorositySubLayerOut(BedParametersResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { + ArtifactAndFacet aandf, ThemeDocument theme, boolean visible) { logger.debug("BedQuality.doPorositySubLayerOut"); XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); @@ -285,7 +289,7 @@ } protected void doDensityTopLayerOut(BedParametersResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { + ArtifactAndFacet aandf, ThemeDocument theme, boolean visible) { logger.debug("BedQuality.doDensityOut"); XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); @@ -297,7 +301,7 @@ } protected void doDensitySubLayerOut(BedParametersResult data, - ArtifactAndFacet aandf, Document theme, boolean visible) { + ArtifactAndFacet aandf, ThemeDocument theme, boolean visible) { logger.debug("BedQuality.doDensityOut"); XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/minfo/SedimentLoadExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/minfo/SedimentLoadExporter.java Thu Sep 12 10:13:09 2013 +0200 @@ -0,0 +1,176 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.exports.minfo; + +import java.util.LinkedList; +import java.util.List; +import java.util.TreeSet; + +import java.io.OutputStream; +import java.io.IOException; + +import java.text.NumberFormat; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import org.dive4elements.artifacts.CallContext; + +import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoad; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoadFraction; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoadResult; + +import org.dive4elements.river.exports.AbstractExporter; + +import org.dive4elements.river.utils.Formatter; + +import au.com.bytecode.opencsv.CSVWriter; + + +/** + * Do CSV export for sediment load calculations (will also be shown in + * client). */ +public class SedimentLoadExporter +extends AbstractExporter +{ + /** Private logger. */ + private static Logger logger = Logger.getLogger(SedimentLoadExporter.class); + + // i18n keys. + public static final String CSV_KM = + "export.sedimentload_ls.csv.header.km"; + + public static final String CSV_YEAR = + "export.sedimentload_ls.csv.header.year"; + + public static final String CSV_COARSE = + "export.sedimentload_ls.csv.header.coarse"; + + public static final String CSV_FINEMIDDLE = + "export.sedimentload_ls.csv.header.finemiddle"; + + public static final String CSV_SAND = + "export.sedimentload_ls.csv.header.sand"; + + public static final String CSV_SUSP_SAND = + "export.sedimentload_ls.csv.header.suspsand"; + + public static final String CSV_SUSP_SAND_BB = + "export.sedimentload_ls.csv.header.suspsandbb"; + + public static final String CSV_SUSP_SEDIMENT = + "export.sedimentload_ls.csv.header.suspsediment"; + + public static final String CSV_TOTAL = + "export.sedimentload_ls.csv.header.total"; + + + /** Collected results. */ + private SedimentLoadResult[] results; + + /** Empty constructor. */ + public SedimentLoadExporter() { + } + + /** Trivial init. */ + @Override + public void init(Document request, OutputStream out, CallContext context) { + super.init(request, out, context); + logger.debug("init"); + results = new SedimentLoadResult[0]; + } + + + /** Process all stored data and write csv. */ + @Override + protected void writeCSVData(CSVWriter writer) throws IOException { + writeCSVHeader(writer); + + for (SedimentLoadResult result: results) { + String years = (result.getEndYear() == 0) + ? result.getStartYear() + " " + : result.getStartYear() + "-" + result.getEndYear(); + SedimentLoad load = result.getLoad(); + // Put load.getName()+load.getDescription()}); somewhere? + for (double km: new TreeSet(load.getKms())) { + SedimentLoadFraction fraction = load.getFraction(km); + writeRecord(writer, km, years, fraction); + } + } + } + + /** Write a line. */ + private void writeRecord( + CSVWriter writer, + double km, + String years, + SedimentLoadFraction fraction + ) { + // year, total, susp sed, susp sandbed suspsand, sand, finemiddle, coarse + NumberFormat kmf = Formatter.getCalculationKm(context.getMeta()); + NumberFormat valf = Formatter.getFormatter(context.getMeta(), 0, 2); + writer.writeNext(new String[] { + kmf.format(km), + years, + valf.format(fraction.getSuspSediment()), + valf.format(fraction.getSuspSand()), + valf.format(fraction.getSuspSandBed()), + valf.format(fraction.getSand()), + valf.format(fraction.getFineMiddle()), + valf.format(fraction.getCoarse()), + valf.format(fraction.getTotal()) + }); + } + + /** Writes i18ned header for csv file/stream. */ + protected void writeCSVHeader(CSVWriter writer) { + logger.debug("writeCSVHeader()"); + + List header = new LinkedList(); + if (results != null) { + header.add(msg(CSV_KM, "km")); + header.add(msg(CSV_YEAR, "Jahr")); + header.add(msg(CSV_SUSP_SEDIMENT, "Schwebst.")); + header.add(msg(CSV_SUSP_SAND, "Susp.Sand")); + header.add(msg(CSV_SUSP_SAND_BB, "Susp.Sand(BB)")); + header.add(msg(CSV_SAND, "Sand")); + header.add(msg(CSV_FINEMIDDLE, "Kies(f+m)")); + header.add(msg(CSV_COARSE, "Kies(g)")); + header.add(msg(CSV_TOTAL, "Gesamt")); + } + writer.writeNext(header.toArray(new String[header.size()])); + } + + /** Store data internally, accepting only SedimentLoadResults[] in + * calculationresults data. */ + @Override + protected void addData(Object data) { + if (!(data instanceof CalculationResult)) { + logger.warn("Invalid data type."); + return; + } + Object[] d = (Object[])((CalculationResult)data).getData(); + + if (!(d instanceof SedimentLoadResult[])) { + logger.warn("Invalid result object."); + return; + } + logger.debug("addData: Data added."); + results = (SedimentLoadResult[])d; + } + + /** Write PDF to outputstream (not implemented yet). */ + @Override + protected void writePDF(OutputStream out) { + logger.warn("Not implemented."); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/minfo/SedimentLoadLSGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/minfo/SedimentLoadLSGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/minfo/SedimentLoadLSGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -13,7 +13,6 @@ import org.apache.log4j.Logger; import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifactdatabase.state.Facet; @@ -33,13 +32,16 @@ import org.dive4elements.river.jfree.DoubleBounds; import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.DataUtil; +/** Generator for Longitudinal Sections of SedimentLoad-Calculations. */ public class SedimentLoadLSGenerator extends XYChartGenerator implements FacetTypes { + /** Y-Axis enum defining the four possible axes. */ public enum YAXIS { L(0), D(1), @@ -73,8 +75,7 @@ public static final String I18N_YAXIS_D_LABEL_DEFAULT = "delta S [m]"; public static final String I18N_YAXIS_V_LABEL_DEFAULT = "Geschwindigkeit v [m/s]"; - private String yLabel = ""; - + /** Enumerator over y-axes. */ @Override protected YAxisWalker getYAxisWalker() { return new YAxisWalker() { @@ -93,7 +94,7 @@ } @Override - public void doOut(ArtifactAndFacet bundle, Document attr, boolean visible) { + public void doOut(ArtifactAndFacet bundle, ThemeDocument attr, boolean visible) { String name = bundle.getFacetName(); logger.debug("doOut: " + name); @@ -106,14 +107,6 @@ Facet facet = bundle.getFacet(); D4EArtifact artifact = (D4EArtifact)bundle.getArtifact(); - SedimentLoadAccess slaccess = new SedimentLoadAccess(artifact); - String unit = slaccess.getUnit(); - if (unit != null && unit.equals("m3_per_a")) { - yLabel = msg(I18N_YAXIS_LABEL_2, I18N_YAXIS_LABEL_DEFAULT_2); - } - else { - yLabel = msg(I18N_YAXIS_LABEL_1, I18N_YAXIS_LABEL_DEFAULT_1); - } if (facet == null) { return; } @@ -242,7 +235,15 @@ protected String getDefaultYAxisLabel(int pos) { String label = "default"; if (pos == YAXIS.L.idx) { - label = yLabel; + SedimentLoadAccess slaccess = + new SedimentLoadAccess((D4EArtifact) getMaster()); + String unit = slaccess.getUnit(); + if (unit != null && unit.equals("m3_per_a")) { + label = msg(I18N_YAXIS_LABEL_2, I18N_YAXIS_LABEL_DEFAULT_2); + } + else { + label = msg(I18N_YAXIS_LABEL_1, I18N_YAXIS_LABEL_DEFAULT_1); + } } else if (pos == YAXIS.V.idx) { label = msg(I18N_YAXIS_V_LABEL, I18N_YAXIS_V_LABEL_DEFAULT); @@ -258,7 +259,7 @@ } protected void doSedimentLoadOut(double[][] data, - ArtifactAndFacet aandf, Document theme, boolean visible) { + ArtifactAndFacet aandf, ThemeDocument theme, boolean visible) { // Allow for gaps (NaNs). XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), false, theme); @@ -268,7 +269,7 @@ } protected void doSedimentLoadUnknownOut(SedimentLoad load, - ArtifactAndFacet aandf, Document theme, boolean visible) { + ArtifactAndFacet aandf, ThemeDocument theme, boolean visible) { Set kms = load.getKms(); double[][] data = new double[2][kms.size()]; @@ -288,7 +289,7 @@ protected void doFlowVelocityMainOut( FlowVelocityData data, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); @@ -300,7 +301,7 @@ protected void doFlowVelocityTotalOut( FlowVelocityData data, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { if (data == null) { @@ -317,7 +318,7 @@ protected void doBedDifferenceYearOut( BedDiffYearResult data, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); @@ -329,7 +330,7 @@ protected void doBedDifferenceEpochOut( BedDiffEpochResult data, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); @@ -341,7 +342,7 @@ protected void doWDifferencesOut( WKms wkms, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible ) { if (wkms == null) { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffHeightYearProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffHeightYearProcessor.java Thu Sep 12 10:13:09 2013 +0200 @@ -0,0 +1,72 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.exports.process; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.minfo.BedDiffYearResult; +import org.dive4elements.river.exports.StyledSeriesBuilder; +import org.dive4elements.river.exports.XYChartGenerator; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; + + +public class BedDiffHeightYearProcessor implements Processor, FacetTypes { + + private final static Logger logger = + Logger.getLogger(BedDiffHeightYearProcessor.class); + + protected static double GAP_TOLERANCE = 0.101d; + + @Override + public void doOut( + XYChartGenerator generator, + ArtifactAndFacet aandf, + ThemeDocument theme, + boolean visible, + int index + ) { + CallContext context = generator.getCallContext(); + Object data = aandf.getData(context); + if (data instanceof BedDiffYearResult) { + doBedDifferenceYearOut( + generator, + (BedDiffYearResult) data, + aandf, theme, visible, index); + return; + } + logger.error("Can't process " + data.getClass().getName() + " objects"); + } + + @Override + public boolean canHandle(String facetType) { + return BED_DIFFERENCE_HEIGHT_YEAR.equals(facetType) // from BedDiffYearHeight + || BED_DIFFERENCE_HEIGHT_YEAR_FILTERED.equals(facetType) // from BedDiffYearHeight + || BED_DIFFERENCE_YEAR.equals(facetType) // from BedDifferencesYear + || BED_DIFFERENCE_YEAR_FILTERED.equals(facetType); // from BedDifferencesYear + } + + protected void doBedDifferenceYearOut(XYChartGenerator generator, + BedDiffYearResult data, + ArtifactAndFacet aandf, + ThemeDocument theme, + boolean visible, + int axidx) { + + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data.getHeightPerYearData(), false, GAP_TOLERANCE); + + generator.addAxisSeries(series, axidx, visible); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffYearProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedDiffYearProcessor.java Thu Sep 12 10:13:09 2013 +0200 @@ -0,0 +1,92 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.exports.process; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.minfo.BedDiffYearResult; +import org.dive4elements.river.exports.StyledSeriesBuilder; +import org.dive4elements.river.exports.XYChartGenerator; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; + + +public class BedDiffYearProcessor implements Processor, FacetTypes { + + private final static Logger logger = + Logger.getLogger(BedDiffYearProcessor.class); + + protected static double GAP_TOLERANCE = 0.101d; + + @Override + public void doOut( + XYChartGenerator generator, + ArtifactAndFacet aandf, + ThemeDocument theme, + boolean visible, + int axidx + ) { + CallContext context = generator.getCallContext(); + Object data = aandf.getData(context); + if (data instanceof BedDiffYearResult) { + String facetType = aandf.getFacetName(); + int index = + (BED_DIFFERENCE_YEAR_HEIGHT1.equals(facetType) + || BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED.equals(facetType))?0:1; + doBedDifferenceHeightsOut( + generator, + (BedDiffYearResult) data, + aandf, theme, visible, index, axidx); + return; + } + logger.error("Can't process " + data.getClass().getName() + " objects"); + } + + @Override + public boolean canHandle(String facetType) { + return + BED_DIFFERENCE_YEAR_HEIGHT1.equals(facetType) + || BED_DIFFERENCE_YEAR_HEIGHT2.equals(facetType) + || BED_DIFFERENCE_YEAR_HEIGHT1_FILTERED.equals(facetType) + || BED_DIFFERENCE_YEAR_HEIGHT2_FILTERED.equals(facetType); + } + + private void doBedDifferenceHeightsOut( + XYChartGenerator generator, + BedDiffYearResult data, + ArtifactAndFacet bundle, + ThemeDocument attr, + boolean visible, + int idx, + int axidx) { + logger.debug("doBedDifferenceHeightsOut()"); + + XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), attr); + double[][] points; + if (idx == 0) { + points = data.getHeights1Data(); + } + else { + points = data.getHeights2Data(); + } + + StyledSeriesBuilder.addPointsFactorY(series, + points, + false, + GAP_TOLERANCE, + 100d); + + generator.addAxisSeries(series, axidx, visible); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/process/BedheightProcessor.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/process/BedheightProcessor.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/BedheightProcessor.java Thu Sep 12 10:13:09 2013 +0200 @@ -12,7 +12,6 @@ import org.apache.log4j.Logger; import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifacts.CallContext; @@ -20,6 +19,7 @@ import org.dive4elements.river.exports.XYChartGenerator; import org.dive4elements.river.jfree.StyledXYSeries; import org.dive4elements.river.model.BedHeightSingleValue; +import org.dive4elements.river.themes.ThemeDocument; public class BedheightProcessor implements Processor { @@ -32,7 +32,7 @@ public void doOut( XYChartGenerator generator, ArtifactAndFacet aandf, - Document theme, + ThemeDocument theme, boolean visible, int index ) { @@ -50,9 +50,9 @@ } private void doBedheightSingeValuesOut(XYChartGenerator generator, - ArtifactAndFacet aandf, Document theme, int index, boolean visible, + ArtifactAndFacet aandf, ThemeDocument theme, int index, boolean visible, List data) { - logger.debug("doBedheightSingleOut"); + logger.debug("doBedheightSingeValuesOut"); XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); @@ -68,7 +68,7 @@ } public void doBedheightSingleOut(XYChartGenerator generator, - ArtifactAndFacet aandf, Document theme, int index, boolean visible, + ArtifactAndFacet aandf, ThemeDocument theme, int index, boolean visible, BedHeightSingle data) { double[] width = data.getMorphWidths(); double[] stations = data.getStations().toNativeArray(); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/process/DischargeProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/DischargeProcessor.java Thu Sep 12 10:13:09 2013 +0200 @@ -0,0 +1,201 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.exports.process; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.exports.DischargeCurveGenerator; +import org.dive4elements.river.exports.XYChartGenerator; +import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; +import org.dive4elements.river.jfree.RiverAnnotation; +import org.dive4elements.river.jfree.StickyAxisAnnotation; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; + +import org.jfree.chart.annotations.XYTextAnnotation; + + +/** Helper for data handling in discharge diagrams. */ +public class DischargeProcessor +implements Processor, FacetTypes { + + private final static Logger logger = + Logger.getLogger(DischargeProcessor.class); + + /** Station for which the diagram is shown. */ + private double km; + + /** Tolerance for comparison of kilometers. */ + public static final double KM_EPSILON = 0.001d; + + + /** This processor needs to be constructed with a given km. */ + private DischargeProcessor() { + km = Double.NaN; + } + + + public DischargeProcessor(double km) { + this.km = km; + } + + + /** Process data, add it to plot. */ + @Override + public void doOut( + XYChartGenerator generator, + ArtifactAndFacet aandf, + ThemeDocument theme, + boolean visible, + int axisIndex + ) { + CallContext context = generator.getCallContext(); + Object data = aandf.getData(context); + if (false && data instanceof WQKms) { + doWQKmsPointOut( + generator, (WQKms) data, aandf, theme, visible, axisIndex); + return; + } + else if (data instanceof RiverAnnotation) { + doRiverAnnotationOut( + generator, (RiverAnnotation) data, aandf, theme, visible); + return; + } + else if (data instanceof double[][]) { + doMarksOut( + generator, (double[][]) data, aandf, theme, visible); + return; + } + else { + logger.error("Can't process " + + data.getClass().getName() + " objects of facet " + + aandf.getFacetName()); + } + } + + + /** True if this processor knows how to deal with facetType. */ + @Override + public boolean canHandle(String facetType) { + return /*STATIC_WQKMS_W.equals(facetType) + ||*/ COMPUTED_DISCHARGE_MAINVALUES_Q.equals(facetType) + || MAINVALUES_Q.equals(facetType) + || COMPUTED_DISCHARGE_MAINVALUES_W.equals(facetType) + || MAINVALUES_W.equals(facetType) + || STATIC_W_INTERPOL.equals(facetType); + } + + + /** The station of the current calculation/view. */ + protected double getKm() { + return km; + } + + + /** Handle WQKms data by finding w/q values at given km. */ + protected void doWQKmsPointOut(XYChartGenerator generator, + WQKms wqkms, + ArtifactAndFacet aandf, + ThemeDocument theme, + boolean visible, + int axidx + ) { + logger.debug("doWQKmsPointOut"); + String title = aandf.getFacetDescription(); + XYSeries series = new StyledXYSeries( + title, + theme); + + double[] kms = wqkms.getKms(); + + for (int i = 0 ; i< kms.length; i++) { + if (Math.abs(kms[i] - getKm()) <= KM_EPSILON) { + series.add(wqkms.getQ(i), wqkms.getW(i)); + generator.addAxisSeries(series, axidx, visible); + if(visible && theme.parseShowPointLabel()) { + List textAnnos = new ArrayList(); + XYTextAnnotation anno = new CollisionFreeXYTextAnnotation( + title, + wqkms.getQ(i), + // TODO add a percentage to the extend of W axis + wqkms.getW(i)); + textAnnos.add(anno); + RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, theme); + flysAnno.setTextAnnotations(textAnnos); + generator.addAnnotations(flysAnno); + } + return; + } + } + + logger.warn("No WQ found for km " + getKm()); + } + + protected void doRiverAnnotationOut(XYChartGenerator generator, + RiverAnnotation annotations, + ArtifactAndFacet aandf, + ThemeDocument theme, + boolean visible + ) { + if (!(generator instanceof DischargeCurveGenerator)) { + logger.error("DischargeProcessor can only be used in " + + " in DischargeCurveGenerator-classes."); + return; + } + logger.debug("doRiverAnnotationOut"); + DischargeCurveGenerator dGenerator = + (DischargeCurveGenerator) generator; + + dGenerator.translateRiverAnnotation(annotations); + dGenerator.doAnnotations( + annotations, + aandf, theme, visible); + } + + + /** + * Put Sticky Axis Markers to Y-axis for each value. + * @param data [[-,y1],[-,y2],...] ('x'-coordinates ignored) + */ + protected void doMarksOut(XYChartGenerator generator, + double[][] data, + ArtifactAndFacet aandf, + ThemeDocument theme, + boolean visible + ) { + logger.debug("doMarksOut"); + + if (!visible) { + return; + } + + // TODO subtract gauge null point if at gauge. + String title = aandf.getFacetDescription(); + List yMarks = new ArrayList(); + + for (double yPos: data[1]) { + yMarks.add(new StickyAxisAnnotation( + title, + (float) yPos, + StickyAxisAnnotation.SimpleAxis.Y_AXIS)); + } + + generator.doAnnotations(new RiverAnnotation(title, yMarks), + aandf, theme, visible); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/process/KMIndexProcessor.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/process/KMIndexProcessor.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/KMIndexProcessor.java Thu Sep 12 10:13:09 2013 +0200 @@ -11,7 +11,6 @@ import org.apache.log4j.Logger; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; -import org.w3c.dom.Document; import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifacts.CallContext; @@ -20,6 +19,7 @@ import org.dive4elements.river.artifacts.model.fixings.QWD; import org.dive4elements.river.exports.XYChartGenerator; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.KMIndex; public class KMIndexProcessor implements Processor { @@ -28,7 +28,7 @@ @Override public void doOut(XYChartGenerator generator, ArtifactAndFacet aandf, - Document theme, boolean visible, int index) { + ThemeDocument theme, boolean visible, int index) { String facettype = aandf.getFacetName(); if (facettype.contains(FacetTypes.FIX_SECTOR_AVERAGE_LS)) { doSectorAverageOut(generator, aandf, theme, visible, index); @@ -58,7 +58,7 @@ } private void doSectorAverageOut(XYChartGenerator generator, ArtifactAndFacet aaf, - Document doc, boolean visible, int idx) { + ThemeDocument doc, boolean visible, int idx) { logger.debug("doSectorAverageOut" + aaf.getFacet().getIndex()); CallContext context = generator.getCallContext(); @@ -90,7 +90,7 @@ } private void doReferenceEventsOut(XYChartGenerator generator, - ArtifactAndFacet aaf, Document doc, boolean visible, int idx) { + ArtifactAndFacet aaf, ThemeDocument doc, boolean visible, int idx) { logger.debug("doReferenceEventOut"); CallContext context = generator.getCallContext(); @@ -120,7 +120,7 @@ } private void doAnalysisEventsOut(XYChartGenerator generator, - ArtifactAndFacet aaf, Document doc, boolean visible, int idx) { + ArtifactAndFacet aaf, ThemeDocument doc, boolean visible, int idx) { logger.debug("doAnalysisEventsOut"); CallContext context = generator.getCallContext(); @@ -148,3 +148,4 @@ generator.addAxisDataset(col, idx, visible); } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/process/Processor.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/process/Processor.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/Processor.java Thu Sep 12 10:13:09 2013 +0200 @@ -8,10 +8,9 @@ package org.dive4elements.river.exports.process; -import org.w3c.dom.Document; - import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.river.exports.XYChartGenerator; +import org.dive4elements.river.themes.ThemeDocument; /** * A processor is intended to generate an output e.g. curve in a chart diagramm from @@ -32,10 +31,10 @@ */ public void doOut( XYChartGenerator generator, - ArtifactAndFacet aandf, - Document theme, - boolean visible, - int index); + ArtifactAndFacet aandf, + ThemeDocument theme, + boolean visible, + int index); /** * Returns true if the Processor class is able to generate output for a facet type diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/process/QOutProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/QOutProcessor.java Thu Sep 12 10:13:09 2013 +0200 @@ -0,0 +1,131 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.exports.process; + +import org.apache.log4j.Logger; +import org.jfree.data.xy.XYSeries; + +import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.model.FacetTypes; +import org.dive4elements.river.artifacts.model.WKms; +import org.dive4elements.river.artifacts.model.WQKms; + +import org.dive4elements.river.exports.StyledSeriesBuilder; +import org.dive4elements.river.exports.XYChartGenerator; +import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; +import org.dive4elements.river.utils.DataUtil; + +/** + * Add data to chart/generator. + * + * @author Björn Ricks + */ +public class QOutProcessor implements Processor { + + /** Private logger. */ + private static final Logger logger = + Logger.getLogger(QOutProcessor.class); + + @Override + public void doOut( + XYChartGenerator generator, + ArtifactAndFacet aaf, + ThemeDocument theme, + boolean visible, + int index) + { + CallContext context = generator.getCallContext(); + WQKms wqkms = (WQKms) aaf.getData(context); + + doQOut(generator, wqkms, aaf, theme, visible, index); + } + + /** + * Returns true if facettype is q-type. + */ + @Override + public boolean canHandle(String facetType) { + if (facetType == null) { + return false; + } + + if (facetType.equals(FacetTypes.STATIC_WQKMS_Q) + || facetType.equals(FacetTypes.LONGITUDINAL_Q) + || facetType.equals(FacetTypes.DISCHARGE_LONGITUDINAL_Q)) { + return true; + } + return false; + } + + + /** + * Process the output for Q facets in a longitudinal section curve. + * + * @param generator Generator to use. + * @param wqkms An array of WQKms values. + * @param aandf The facet and artifact. This facet does NOT support any data objects. Use + * D4EArtifact.getNativeFacet() instead to retrieve a Facet which supports + * data. + * @param theme The theme that contains styling information. + * @param visible The visibility of the curve. + * @param index Axis index to add data to. + */ + protected void doQOut( + XYChartGenerator generator, + WQKms wqkms, + ArtifactAndFacet aaf, + ThemeDocument theme, + boolean visible, + int index + ) { + logger.debug("QProcessor.doOut"); + + XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); + + StyledSeriesBuilder.addStepPointsKmQ(series, wqkms); + + generator.addAxisSeries(series, index, visible); + + invertAxis(generator, wqkms); + } + + /** + * This method determines - taking JFreeCharts auto x value ordering into + * account - if the x axis need to be inverted. Waterlines in these charts + * should decrease. + * + * @param generator the generator to invert the axis or not. + * @param wkms The data object that stores the x and y values used for this + * chart. + */ + public void invertAxis(XYChartGenerator generator, WKms wkms) { + boolean wsUp = wkms.guessWaterIncreasing(); + boolean kmUp = DataUtil.guessWaterIncreasing(wkms.allKms()); + int size = wkms.size(); + boolean inv = ((wsUp && kmUp) || (!wsUp && !kmUp)) && size > 1; + + if (logger.isDebugEnabled()) { + logger.debug("(Wkms)Values : " + size); + if (size > 0) { + logger.debug("Start km: " + wkms.getKm(0)); + logger.debug("End km: " + wkms.getKm(size-1)); + } + logger.debug("wsUp: " + wsUp); + logger.debug("kmUp: " + kmUp); + if (size == 1) { + logger.debug("InvertAxis not inverting because we have just one km"); + } + logger.debug("inv: " + inv); + } + generator.setInverted(inv); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/process/WOutProcessor.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/process/WOutProcessor.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/WOutProcessor.java Thu Sep 12 10:13:09 2013 +0200 @@ -10,7 +10,6 @@ import org.apache.log4j.Logger; import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifacts.CallContext; @@ -20,8 +19,8 @@ import org.dive4elements.river.exports.XYChartGenerator; import org.dive4elements.river.jfree.StyledAreaSeriesCollection; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.dive4elements.river.utils.DataUtil; -import org.dive4elements.river.utils.ThemeUtil; /** * Add data to chart/generator. @@ -38,7 +37,7 @@ public void doOut( XYChartGenerator generator, ArtifactAndFacet aaf, - Document theme, + ThemeDocument theme, boolean visible, int index) { @@ -53,7 +52,7 @@ generator.addAxisSeries(series, index, visible); // If a "band around the curve shall be drawn, add according area. - double bandWidth = ThemeUtil.parseBandWidth(theme); + double bandWidth = theme.parseBandWidth(); if (bandWidth > 0 ) { XYSeries seriesDown = new StyledXYSeries( "band " + aaf.getFacetDescription(), false, theme); @@ -69,7 +68,13 @@ generator.addAreaSeries(area, index, visible); } - invertAxis(generator, wkms); + if (aaf.getFacetName().equals(FacetTypes.LONGITUDINAL_W) || + aaf.getFacetName().equals(FacetTypes.DISCHARGE_LONGITUDINAL_W) || + aaf.getFacetName().equals(FacetTypes.STATIC_WQKMS_W)) { + /* Only use W values to check if the diagram should be inverted + * see flys/issue1290 for details */ + invertAxis(generator, wkms); + } } /** @@ -104,9 +109,8 @@ public void invertAxis(XYChartGenerator generator, WKms wkms) { boolean wsUp = wkms.guessWaterIncreasing(); boolean kmUp = DataUtil.guessWaterIncreasing(wkms.allKms()); - boolean inv = (wsUp && kmUp) || (!wsUp && !kmUp); - int size = wkms.size(); + boolean inv = ((wsUp && kmUp) || (!wsUp && !kmUp)) && size > 1; if (logger.isDebugEnabled()) { logger.debug("(Wkms)Values : " + size); @@ -116,6 +120,9 @@ } logger.debug("wsUp: " + wsUp); logger.debug("kmUp: " + kmUp); + if (size == 1) { + logger.debug("InvertAxis not inverting because we have just one km"); + } logger.debug("inv: " + inv); } generator.setInverted(inv); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/sq/SQOverviewGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/sq/SQOverviewGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/sq/SQOverviewGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -38,6 +38,7 @@ import org.dive4elements.river.exports.ChartGenerator; import org.dive4elements.river.exports.OutGenerator; import org.dive4elements.river.exports.OutputHelper; +import org.dive4elements.river.themes.ThemeDocument; public class SQOverviewGenerator implements OutGenerator @@ -69,7 +70,7 @@ @Override public void doOut( ArtifactAndFacet artifactAndFacet, - Document attr, + ThemeDocument attr, boolean visible ) { logger.debug("doOut()"); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationExporter.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationExporter.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationExporter.java Thu Sep 12 10:13:09 2013 +0200 @@ -16,6 +16,7 @@ import java.util.Date; import java.util.Locale; import java.text.DateFormat; +import java.text.NumberFormat; import org.w3c.dom.Document; @@ -99,8 +100,11 @@ public static final String CSV_C_FERGUSON = "export.sqrelation.csv.header.c.ferguson"; - public static final String CSV_VARIANCE = - "export.sqrelation.csv.header.variance"; + public static final String CSV_QMAX = + "export.sqrelation.csv.header.qmax"; + + public static final String CSV_SD = + "export.sqrelation.csv.header.sd"; public static final String PDF_TITLE= "export.sqrelation.pdf.title"; @@ -136,9 +140,13 @@ msg(CSV_PARAMETER, CSV_PARAMETER), msg(CSV_COEFF_A , CSV_COEFF_A), msg(CSV_COEFF_B , CSV_COEFF_B), + msg(CSV_SD, CSV_SD), + msg(CSV_QMAX, CSV_QMAX), + msg(CSV_COEFF_R, CSV_COEFF_R), msg(CSV_N_TOTAL , CSV_N_TOTAL), msg(CSV_N_OUTLIERS, CSV_N_OUTLIERS), - msg(CSV_VARIANCE , CSV_VARIANCE) + msg(CSV_C_DUAN, CSV_C_DUAN), + msg(CSV_C_FERGUSON, CSV_C_FERGUSON) }); } @@ -160,6 +168,12 @@ ).format(result.getKm()); List retval = new ArrayList(); + NumberFormat sqAFormatter = Formatter.getSQRelationA(context); + NumberFormat sqBFormatter = Formatter.getSQRelationB(context); + NumberFormat fThreeFormatter = Formatter.getFormatter(context, 3, 3); + NumberFormat fTwoFormatter = Formatter.getFormatter(context, 2, 2); + NumberFormat fZeroFormatter = Formatter.getFormatter(context, 0, 0); + for (int i = 0; i < SQResult.NUMBER_FRACTIONS; ++i) { SQFractionResult fraction = result.getFraction(i); @@ -171,10 +185,17 @@ continue; } - String a, b, sd, o, t; - a = Formatter.getSQRelationA(context).format(parameters.getValue(0, "a")); - b = Formatter.getSQRelationB(context).format(parameters.getValue(0, "b")); - sd = Formatter.getVariance(context).format(Math.sqrt(parameters.getValue(0, "std_dev"))); + String a, b, sd, o, t, max_q, c_ferguson, c_duan, r2; + a = sqAFormatter.format(parameters.getValue(0, "a")); + b = sqBFormatter.format(parameters.getValue(0, "b")); + + /* The std_dev parameter contains the standard error actually */ + sd = fThreeFormatter.format(parameters.getValue(0, "std_dev")); + max_q = fZeroFormatter.format(parameters.getValue(0, "max_q")); + c_ferguson = fTwoFormatter.format(parameters.getValue(0, "c_ferguson")); + c_duan = fTwoFormatter.format(parameters.getValue(0, "c_duan")); + r2 = fTwoFormatter.format(parameters.getValue(0, "r2")); + o = String.valueOf(fraction.totalNumOutliers()); t = String.valueOf(fraction.numMeasurements() + o); @@ -184,9 +205,13 @@ name, a, b, - t, - o, - sd + sd, // 4 + max_q, // 5 + r2, // 6 + t, // 7 + o, // 8 + c_duan, // 9 + c_ferguson // 10 }); } return retval; @@ -229,12 +254,26 @@ source.addMetaData("outliertest", Resources.getMsg(meta, access.getOutlierMethod(), access.getOutlierMethod())); - source.addMetaData("outliers", access.getOutliers().toString()); + source.addMetaData("outliers", Formatter.getRawFormatter(context).format( + access.getOutliers())); source.addMetaData("calculation", Resources.getMsg( locale, PDF_HEADER_MODE, "SQRelation")); + + String measurementStationName = access.getMeasurementStationName(); + + if (measurementStationName != null) { + source.addMetaData("msName", measurementStationName); + } + + String measurementStationGaugeName = access.getMeasurementStationGaugeName(); + + if (measurementStationGaugeName != null) { + source.addMetaData("msGauge", measurementStationGaugeName); + } + } @Override diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/sq/SQRelationGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -11,6 +11,10 @@ import org.dive4elements.artifactdatabase.state.ArtifactAndFacet; import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.river.artifacts.D4EArtifact; + +import org.dive4elements.river.artifacts.access.SQRelationAccess; + import org.dive4elements.river.artifacts.model.FacetTypes; import org.dive4elements.river.artifacts.model.sq.SQ; @@ -20,6 +24,7 @@ import org.dive4elements.river.jfree.JFreeUtil; import org.dive4elements.river.jfree.StyledXYSeries; +import org.dive4elements.river.themes.ThemeDocument; import org.apache.log4j.Logger; @@ -28,7 +33,6 @@ import org.jfree.data.xy.XYSeries; -import org.w3c.dom.Document; /** * An OutGenerator that generates charts for MINFO sq relation. @@ -54,6 +58,11 @@ public static final String I18N_YAXIS_LABEL = "chart.sq_relation.yaxis.label"; + public static final String I18N_SUBTITLE = + "chart.computed.discharge.curve.subtitle"; + + /** Needed to access data to create subtitle. */ + protected D4EArtifact artifact; /** The logger that is used in this generator. */ private static Logger logger = Logger.getLogger(SQRelationGenerator.class); @@ -75,6 +84,23 @@ }; } + /** + * Returns the default subtitle for this chart. + * + * @return the default subtitle for this chart. + */ + @Override + protected String getDefaultChartSubtitle() { + SQRelationAccess sqAccess = new SQRelationAccess(artifact); + Object[] args = null; + args = new Object[] { + sqAccess.getRiver(), + sqAccess.getLocation() + }; + return msg(I18N_SUBTITLE, "", args); + } + + @Override public String getDefaultChartTitle() { @@ -109,11 +135,13 @@ @Override public void doOut( ArtifactAndFacet artifactAndFacet, - Document attr, + ThemeDocument attr, boolean visible ) { logger.debug("doOut"); + this.artifact = (D4EArtifact) artifactAndFacet.getArtifact(); + Facet facet = artifactAndFacet.getFacet(); String name = facet != null ? facet.getName() : null; @@ -144,7 +172,7 @@ protected void doSQCurveOut( ArtifactAndFacet artifactAndFacet, - Document attr, + ThemeDocument attr, boolean visible ) { String desc = artifactAndFacet.getFacetDescription(); @@ -180,7 +208,7 @@ protected void doSQOut( ArtifactAndFacet artifactAndFacet, - Document attr, + ThemeDocument attr, boolean visible ) { String desc = artifactAndFacet.getFacetDescription(); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/jfree/JFreeUtil.java --- a/artifacts/src/main/java/org/dive4elements/river/jfree/JFreeUtil.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/jfree/JFreeUtil.java Thu Sep 12 10:13:09 2013 +0200 @@ -16,9 +16,9 @@ import org.apache.log4j.Logger; import org.jfree.chart.entity.ChartEntity; import org.jfree.chart.entity.EntityCollection; -import org.w3c.dom.Document; import org.dive4elements.river.artifacts.math.Function; +import org.dive4elements.river.themes.ThemeDocument; public class JFreeUtil { @@ -107,7 +107,7 @@ public static StyledXYSeries sampleFunction2D( Function func, - Document theme, + ThemeDocument theme, String seriesKey, int samples, double start, @@ -127,7 +127,7 @@ public static StyledXYSeries sampleFunction2DPositive( Function func, - Document theme, + ThemeDocument theme, String seriesKey, int samples, double start, diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/jfree/RiverAnnotation.java --- a/artifacts/src/main/java/org/dive4elements/river/jfree/RiverAnnotation.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/jfree/RiverAnnotation.java Thu Sep 12 10:13:09 2013 +0200 @@ -9,12 +9,12 @@ package org.dive4elements.river.jfree; import org.dive4elements.river.artifacts.model.HYKFactory; +import org.dive4elements.river.themes.ThemeDocument; import java.util.Collections; import java.util.List; import org.jfree.chart.annotations.XYTextAnnotation; -import org.w3c.dom.Document; /** * List of Text- Annotations (Sticky to one axis or in space) @@ -32,7 +32,7 @@ protected List boxes; /** Styling information. */ - protected Document theme; + protected ThemeDocument theme; /** Chart-legend information. */ protected String label; @@ -53,7 +53,7 @@ /** Create annotations, parameter might be null. */ public RiverAnnotation(String label, List annotations, - List bAnnotations, Document theme + List bAnnotations, ThemeDocument theme ) { this.label = label; this.axisTextAnnotations = (annotations != null) @@ -92,11 +92,11 @@ return boxes; } - public void setTheme(Document theme) { + public void setTheme(ThemeDocument theme) { this.theme = theme; } - public Document getTheme() { + public ThemeDocument getTheme() { return theme; } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java --- a/artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java Thu Sep 12 10:13:09 2013 +0200 @@ -13,11 +13,8 @@ import java.awt.Stroke; import org.jfree.data.xy.XYSeriesCollection; -import org.w3c.dom.Document; -import org.dive4elements.river.themes.ThemeAccess; -import org.dive4elements.river.utils.ThemeUtil; - +import org.dive4elements.river.themes.ThemeDocument; /** * One or more dataseries to draw a polygon (either "open up/downwards", or @@ -36,13 +33,13 @@ protected FILL_MODE mode; /** The theme-document with attributes about actual visual representation. */ - protected Document theme; + protected ThemeDocument theme; /** * @param theme the theme-document. */ - public StyledAreaSeriesCollection(Document theme) { + public StyledAreaSeriesCollection(ThemeDocument theme) { this.theme = theme; this.mode = FILL_MODE.BETWEEN; } @@ -85,16 +82,15 @@ } // Apply text style. - new ThemeAccess(theme).parseTextStyle().apply(renderer); + theme.parseComplexTextStyle().apply(renderer); return renderer; } protected void applyFillColor(StableXYDifferenceRenderer renderer) { - Color paint = ThemeUtil.parseColor( - ThemeUtil.getAreaBackgroundColorString(theme)); + Color paint = theme.parseAreaBackgroundColor(); - int transparency = ThemeUtil.parseAreaTransparency(theme); + int transparency = theme.parseAreaTransparency(); if (transparency > 0 && paint != null) { paint = new Color( paint.getRed(), @@ -121,34 +117,35 @@ protected void applyShowShape(StableXYDifferenceRenderer renderer) { - boolean show = ThemeUtil.parseAreaShowBorder(theme); + boolean show = theme.parseAreaShowBorder(); renderer.setDrawOutline(show); } protected void applyShowLine(StableXYDifferenceRenderer renderer) { - boolean show = ThemeUtil.parseShowLine(theme); + boolean show = theme.parseShowLine(); renderer.setShapesVisible(show); } protected void applyOutlineColor(StableXYDifferenceRenderer renderer) { - Color c = ThemeUtil.parseLineColorField(theme); + Color c = theme.parseLineColorField(); renderer.setOutlinePaint(c); } protected void applyOutlineWidth(StableXYDifferenceRenderer renderer) { - int size = ThemeUtil.parseLineWidth(theme); + // int size = theme.parseLineWidth(); + // XXX: Why is this not set? } /** Inform renderer whether it should draw a label. */ protected void applyShowArea(StableXYDifferenceRenderer renderer) { - renderer.setLabelArea(ThemeUtil.parseShowArea(theme)); + renderer.setLabelArea(theme.parseShowArea()); } protected void applyOutlineStyle(StableXYDifferenceRenderer renderer) { - float[] dashes = ThemeUtil.parseLineStyle(theme); - int size = ThemeUtil.parseLineWidth(theme); + float[] dashes = theme.parseLineStyle(); + int size = theme.parseLineWidth(); Stroke stroke = null; diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/jfree/StyledDomainMarker.java --- a/artifacts/src/main/java/org/dive4elements/river/jfree/StyledDomainMarker.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StyledDomainMarker.java Thu Sep 12 10:13:09 2013 +0200 @@ -11,9 +11,8 @@ import java.awt.Color; import org.jfree.chart.plot.IntervalMarker; -import org.w3c.dom.Document; -import org.dive4elements.river.utils.ThemeUtil; +import org.dive4elements.river.themes.ThemeDocument; /** * Marker that represents a highlighted interval. @@ -26,19 +25,17 @@ private final Color backgroundColor, backgroundColor2; - public StyledDomainMarker(double start, double end, Document theme) { + public StyledDomainMarker(double start, double end, ThemeDocument theme) { super(start, end); - backgroundColor = ThemeUtil.parseColor( - ThemeUtil.getAreaBackgroundColorString(theme)); + backgroundColor = theme.parseAreaBackgroundColor(); backgroundColor2 = new Color( 255 - backgroundColor.getRed(), 255 - backgroundColor.getGreen(), 255 - backgroundColor.getBlue()); useSecondColor(false); - int alpha = 100 - ThemeUtil.parseInteger( - ThemeUtil.getAreaTransparencyString(theme), 50); + int alpha = 100 - theme.parseAreaTransparency(50); setAlpha(alpha / 100.0f); } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/jfree/StyledTimeSeries.java --- a/artifacts/src/main/java/org/dive4elements/river/jfree/StyledTimeSeries.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StyledTimeSeries.java Thu Sep 12 10:13:09 2013 +0200 @@ -9,8 +9,7 @@ package org.dive4elements.river.jfree; import org.apache.log4j.Logger; - -import org.w3c.dom.Document; +import org.dive4elements.river.themes.ThemeDocument; import org.jfree.data.time.TimeSeries; @@ -27,7 +26,7 @@ protected Style style; - public StyledTimeSeries(String key, Document theme) { + public StyledTimeSeries(String key, ThemeDocument theme) { super(key); setStyle(new XYStyle(theme)); } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/jfree/StyledValueMarker.java --- a/artifacts/src/main/java/org/dive4elements/river/jfree/StyledValueMarker.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StyledValueMarker.java Thu Sep 12 10:13:09 2013 +0200 @@ -8,13 +8,12 @@ package org.dive4elements.river.jfree; -import org.dive4elements.river.utils.ThemeUtil; +import org.dive4elements.river.themes.ThemeDocument; import java.awt.BasicStroke; import java.awt.Color; import org.jfree.chart.plot.ValueMarker; -import org.w3c.dom.Document; /** * Marker that represents a single value. @@ -24,16 +23,16 @@ private static final long serialVersionUID = -3607777705307785140L; - public StyledValueMarker(double value, Document theme) { + public StyledValueMarker(double value, ThemeDocument theme) { super(value); - Color color = ThemeUtil.parseAreaBackgroundColor(theme); + Color color = theme.parseAreaBackgroundColor(); if(color == null) { color = Color.BLACK; } this.setPaint(color); - int size = ThemeUtil.parsePointWidth(theme); + int size = theme.parsePointWidth(); setStroke(new BasicStroke(size)); } } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/jfree/StyledXYSeries.java --- a/artifacts/src/main/java/org/dive4elements/river/jfree/StyledXYSeries.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StyledXYSeries.java Thu Sep 12 10:13:09 2013 +0200 @@ -11,8 +11,7 @@ import java.util.List; import org.apache.log4j.Logger; - -import org.w3c.dom.Document; +import org.dive4elements.river.themes.ThemeDocument; import org.jfree.data.xy.XYDataItem; import org.jfree.data.xy.XYSeries; @@ -30,13 +29,13 @@ protected String label; - public StyledXYSeries(String key, Document theme) { + public StyledXYSeries(String key, ThemeDocument theme) { this(key, true, theme); this.label = key.toString(); } - public StyledXYSeries(String key, Document theme, XYSeries unstyledSeries) { + public StyledXYSeries(String key, ThemeDocument theme, XYSeries unstyledSeries) { this(key, theme); add(unstyledSeries); } @@ -47,12 +46,24 @@ * to one extrema which can cause problems in certain * algorithms. */ - public StyledXYSeries(String key, boolean sorted, Document theme) { + public StyledXYSeries(String key, boolean sorted, ThemeDocument theme) { super(key, sorted); setStyle(new XYStyle(theme)); this.label = key.toString(); } + public StyledXYSeries( + String key, + boolean sorted, + boolean allowDuplicateXValues, + ThemeDocument theme + ) { + super(key, sorted, allowDuplicateXValues); + setStyle(new XYStyle(theme)); + this.label = key.toString(); + } + + @Override public void setStyle(Style style) { diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/jfree/XYStyle.java --- a/artifacts/src/main/java/org/dive4elements/river/jfree/XYStyle.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/jfree/XYStyle.java Thu Sep 12 10:13:09 2013 +0200 @@ -8,7 +8,7 @@ package org.dive4elements.river.jfree; -import org.dive4elements.river.utils.ThemeUtil; +import org.dive4elements.river.themes.ThemeDocument; import java.awt.BasicStroke; import java.awt.Color; @@ -16,7 +16,6 @@ import org.apache.log4j.Logger; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.w3c.dom.Document; /** @@ -27,14 +26,13 @@ private static Logger logger = Logger.getLogger(XYStyle.class); - protected Document theme; + protected ThemeDocument theme; protected XYLineAndShapeRenderer renderer; - public XYStyle(Document theme) { + public XYStyle(ThemeDocument theme) { this.theme = theme; - this.renderer = null; } @@ -76,7 +74,7 @@ /** Set line color to renderer. */ protected void applyLineColor(XYLineAndShapeRenderer r, int idx) { - Color c = ThemeUtil.parseLineColorField(theme); + Color c = theme.parseLineColorField(); if(c != null) { logger.debug("applyLineColor " + c.toString()); r.setSeriesPaint(idx, c); @@ -92,10 +90,10 @@ if (!(r instanceof EnhancedLineAndShapeRenderer)) { return; } - boolean showLabelLine = ThemeUtil.parseShowLineLabel(theme); - boolean anyLabel = showLabelLine || ThemeUtil.parseShowWidth(theme) || - ThemeUtil.parseShowLevel(theme) || - ThemeUtil.parseShowMiddleHeight(theme); + boolean showLabelLine = theme.parseShowLineLabel(); + boolean anyLabel = showLabelLine || theme.parseShowWidth() || + theme.parseShowLevel() || + theme.parseShowMiddleHeight(); ((EnhancedLineAndShapeRenderer)r).setShowLineLabel(anyLabel, idx); } @@ -105,7 +103,7 @@ if (!(r instanceof EnhancedLineAndShapeRenderer)) { return; } - boolean showLabelLine = ThemeUtil.parseLabelShowBackground(theme); + boolean showLabelLine = theme.parseLabelShowBackground(); ((EnhancedLineAndShapeRenderer)r).setShowLineLabelBG(idx, showLabelLine); } @@ -116,7 +114,7 @@ return; } ((EnhancedLineAndShapeRenderer)r).setLineLabelFont( - ThemeUtil.parseTextFont(theme), idx); + theme.parseTextFont(), idx); } /** Tell the renderer which color to use for @@ -126,7 +124,7 @@ return; } ((EnhancedLineAndShapeRenderer)r).setLineLabelTextColor( - idx, ThemeUtil.parseTextColor(theme)); + idx, theme.parseTextColor()); } /** Tell the renderer which color to use for bg of @@ -136,12 +134,12 @@ return; } ((EnhancedLineAndShapeRenderer)r).setLineLabelBGColor(idx, - ThemeUtil.parseTextBackground(theme)); + theme.parseTextBackground()); } /** Set stroke of series. */ protected void applyLineSize(XYLineAndShapeRenderer r, int idx) { - int size = ThemeUtil.parseLineWidth(theme); + int size = theme.parseLineWidth(); r.setSeriesStroke( idx, new BasicStroke(size)); @@ -150,8 +148,8 @@ /** Set stroke strength of series. */ protected void applyLineType(XYLineAndShapeRenderer r, int idx) { - int size = ThemeUtil.parseLineWidth(theme); - float[] dashes = ThemeUtil.parseLineStyle(theme); + int size = theme.parseLineWidth(); + float[] dashes = theme.parseLineStyle(); // Do not apply the dashed style. if (dashes.length <= 1) { @@ -170,7 +168,7 @@ protected void applyPointSize(XYLineAndShapeRenderer r, int idx) { - int size = ThemeUtil.parsePointWidth(theme); + int size = theme.parsePointWidth(); int dim = 2 * size; r.setSeriesShape(idx, new Ellipse2D.Double(-size, -size, dim, dim)); @@ -178,7 +176,7 @@ protected void applyPointColor(XYLineAndShapeRenderer r, int idx) { - Color c = ThemeUtil.parsePointColor(theme); + Color c = theme.parsePointColor(); if (c != null) { r.setSeriesFillPaint(idx, c); @@ -192,7 +190,7 @@ * Sets form and visibility of points. */ protected void applyShowPoints(XYLineAndShapeRenderer r, int idx) { - boolean show = ThemeUtil.parseShowPoints(theme); + boolean show = theme.parseShowPoints(); r.setSeriesShapesVisible(idx, show); r.setDrawOutlines(true); @@ -200,7 +198,7 @@ protected void applyShowLine(XYLineAndShapeRenderer r, int idx) { - boolean show = ThemeUtil.parseShowLine(theme); + boolean show = theme.parseShowLine(); r.setSeriesLinesVisible(idx, show); } @@ -210,7 +208,7 @@ return; } - boolean visible = ThemeUtil.parseShowMinimum(theme); + boolean visible = theme.parseShowMinimum(); EnhancedLineAndShapeRenderer er = (EnhancedLineAndShapeRenderer) r; er.setIsMinimumShapeVisisble(idx, visible); @@ -222,7 +220,7 @@ return; } - boolean visible = ThemeUtil.parseShowMaximum(theme); + boolean visible = theme.parseShowMaximum(); EnhancedLineAndShapeRenderer er = (EnhancedLineAndShapeRenderer) r; er.setIsMaximumShapeVisible(idx, visible); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/themes/TextStyle.java --- a/artifacts/src/main/java/org/dive4elements/river/themes/TextStyle.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/themes/TextStyle.java Thu Sep 12 10:13:09 2013 +0200 @@ -37,12 +37,16 @@ } public void apply(XYTextAnnotation ta) { - ta.setPaint(textColor); - ta.setFont(font); - if (this.showBg) { + if (textColor != null) { + ta.setPaint(textColor); + } + if (font != null) { + ta.setFont(font); + } + if (showBg) { ta.setBackgroundPaint(bgColor); } - if (this.isVertical) { + if (isVertical) { ta.setRotationAngle(270f*Math.PI/180f); } else { @@ -57,4 +61,4 @@ renderer.setLabelBGColor(bgColor); } } -} \ No newline at end of file +} diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/themes/ThemeAccess.java --- a/artifacts/src/main/java/org/dive4elements/river/themes/ThemeAccess.java Sat Jun 29 00:20:58 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +0,0 @@ -/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde - * Software engineering by Intevation GmbH - * - * This file is Free Software under the GNU AGPL (>=v3) - * and comes with ABSOLUTELY NO WARRANTY! Check out the - * documentation coming with Dive4Elements River for details. - */ - -package org.dive4elements.river.themes; - -import org.dive4elements.river.utils.ThemeUtil; - -import java.awt.Color; -import java.awt.Font; - -import org.w3c.dom.Document; - - -public class ThemeAccess -{ - protected Document theme; - - protected Integer lineWidth; - - protected Color lineColor; - protected Color textColor; - protected Font font; - protected String textOrientation; - protected Color textBackground; - protected Boolean showTextBackground; - protected Color pointColor; - - - public ThemeAccess(Document theme) { - this.theme = theme; - } - - - public int parseLineWidth() { - if (lineWidth == null) { - lineWidth = ThemeUtil.parseLineWidth(theme); - } - return lineWidth; - } - - - public Color parseLineColorField() { - if (lineColor == null) { - lineColor = ThemeUtil.parseLineColorField(theme); - if (lineColor == null) { - lineColor = Color.BLACK; - } - } - return lineColor; - } - - - public Color parseTextColor() { - if (textColor == null) { - textColor = ThemeUtil.parseTextColor(theme); - if (textColor == null) { - textColor = Color.BLACK; - } - } - return textColor; - } - - - public Font parseTextFont() { - if (font == null) { - font = ThemeUtil.parseTextFont(theme); - if (font == null) { - font = new Font("Arial", Font.BOLD, 10); - } - } - return font; - } - - - public String parseTextOrientation() { - if (textOrientation == null) { - textOrientation = ThemeUtil.parseTextOrientation(theme); - } - return textOrientation; - } - - - public Color parseTextBackground() { - if (textBackground == null) { - textBackground = ThemeUtil.parseTextBackground(theme); - if (textBackground == null) { - textBackground = Color.WHITE; - } - } - return textBackground; - } - - public boolean parseLabelShowBackground() { - if (showTextBackground == null) { - showTextBackground = ThemeUtil.parseLabelShowBackground(theme); - } - return showTextBackground; - } - - - public Color parsePointColor() { - if (pointColor == null) { - pointColor = ThemeUtil.parsePointColor(theme); - - if (pointColor == null) { - return parseLineColorField(); - } - } - - return pointColor; - } - - - public LineStyle parseLineStyle() { - return new LineStyle(parseLineColorField(), Integer.valueOf(parseLineWidth())); - } - - public TextStyle parseTextStyle() { - return new TextStyle( - parseTextColor(), - parseTextFont(), - parseTextBackground(), - parseLabelShowBackground(), - !parseTextOrientation().equals("horizontal")); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/themes/ThemeDocument.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/themes/ThemeDocument.java Thu Sep 12 10:13:09 2013 +0200 @@ -0,0 +1,738 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.themes; + +import java.awt.Color; +import java.awt.Font; +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.dive4elements.artifacts.CallMeta; +import org.dive4elements.river.artifacts.model.MapserverStyle; +import org.dive4elements.river.artifacts.model.MapserverStyle.Clazz; +import org.dive4elements.river.artifacts.model.MapserverStyle.Expression; +import org.dive4elements.river.artifacts.model.MapserverStyle.Label; +import org.dive4elements.river.artifacts.model.MapserverStyle.Style; +import org.dive4elements.river.artifacts.resources.Resources; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +public class ThemeDocument +{ + private static Logger logger = Logger.getLogger(ThemeDocument.class); + + private static final String MSG_ISOBATH_CLASS = "floodmap.isobath.class"; + + private static final String MSG_ISOBATH_LASTCLASS = "floodmap.isobath.lastclass"; + + public final static String FILL_COLOR = "fillcolor"; + + public final static String LINE_COLOR = "linecolor"; + + public final static String AREA_LINE_COLOR = "areabordercolor"; + + public static final String LINE_SIZE = "linesize"; + + public static final String LINE_STYLE = "linetype"; + + public static final String POINT_SIZE = "pointsize"; + + public static final String POINT_COLOR = "pointcolor"; + + public final static String SHOW_BORDER = "showborder"; + + public final static String AREA_SHOW_BORDER = "showborder"; + + public final static String SHOW_POINTS = "showpoints"; + + public final static String SHOW_LINE = "showlines"; + + public final static String SHOW_VERTICAL_LINE = "showverticalline"; + + public final static String SHOW_HORIZONTAL_LINE = "showhorizontalline"; + + public final static String SHOW_LINE_LABEL = "showlinelabel"; + + public final static String SHOW_POINT_LABEL = "showpointlabel"; + + public final static String SHOW_WIDTH = "showwidth"; + + public final static String SHOW_LEVEL = "showlevel"; + + public final static String TRANSPARENCY = "transparency"; + + public final static String AREA_TRANSPARENCY = "areatransparency"; + + public final static String SHOW_AREA = "showarea"; + + public final static String SHOW_MIDDLE_HEIGHT = "showmiddleheight"; + + public final static String LABEL_FONT_COLOR = "labelfontcolor"; + + public final static String LABEL_FONT_SIZE = "labelfontsize"; + + public final static String LABEL_FONT_FACE = "labelfontface"; + + public final static String LABEL_FONT_STYLE = "labelfontstyle"; + + public final static String TEXT_ORIENTATION = "textorientation"; + + public final static String LABEL_BGCOLOR = "labelbgcolor"; + + public final static String LABEL_SHOW_BACKGROUND = "labelshowbg"; + + public final static String BACKGROUND_COLOR = "backgroundcolor"; + + public final static String AREA_BACKGROUND_COLOR = "areabgcolor"; + + public final static String SYMBOL = "symbol"; + + public final static String SHOW_MINIMUM = "showminimum"; + + public final static String SHOW_MAXIMUM = "showmaximum"; + + public final static String WSPLGEN_STARTCOLOR = "startcolor"; + + public final static String WSPLGEN_ENDCOLOR = "endcolor"; + + public final static String WSPLGEN_NUMCLASSES = "numclasses"; + + public final static String BANDWIDTH = "bandwidth"; + + public final static String SHOWEXTRAMARK = "showextramark"; + + + private Document document; + + private Map values; + + public ThemeDocument() { + } + + public ThemeDocument(Document document) { + this.document = document; + values = extractValues(document); + } + + public Document getDocument() { + return document; + } + + private String getValue(String key) { + return values.get(key); + } + + private static Map extractValues(Document document) { + Map values = new HashMap(); + if (document == null) { + logger.error("Invalid null document given."); + return values; + } + + NodeList fields = document.getElementsByTagName("field"); + for (int i = 0, N = fields.getLength(); i < N; ++i) { + Element field = (Element)fields.item(i); + String name = field.getAttribute("name"); + String value = field.getAttribute("default"); + if (!name.isEmpty() && !value.isEmpty()) { + values.put(name, value); + } + } + if (logger.isDebugEnabled()) { + logger.debug("Theme values: " + values); + } + return values; + } + + /** Parse string to be boolean with default if empty or unrecognized. */ + private static boolean parseBoolean(String value, boolean defaultsTo) { + if (value == null) { + return defaultsTo; + } + if (value.equals("false")) { + return false; + } + if (value.equals("true")) { + return true; + } + return defaultsTo; + } + + + /** + * Attempt converting \param value to an integer, in failing cases, + * return \param defaultsTo. + * @param value String to be converted to integer. + * @param defaultsTo Default to return if conversion failed. + * @return \param value as integer or defaultsto if conversion failed. + */ + private static int parseInteger(String value, int defaultsTo) { + if (value == null) { + return defaultsTo; + } + + try { + return Integer.parseInt(value); + } + catch (NumberFormatException nfe) { + // do nothing + } + + return defaultsTo; + } + + + /** + * Attempt converting \param value to a double, in failing cases, + * return \param defaultsTo. + * @param value String to be converted to double. + * @param defaultsTo Default to return if conversion failed. + * @return \param value as integer or defaultsto if conversion failed. + */ + private static double parseDouble(String value, double defaultsTo) { + if (value == null) { + return defaultsTo; + } + + try { + return Double.parseDouble(value); + } + catch (NumberFormatException nfe) { + // do nothing + } + + return defaultsTo; + } + + public boolean parseShowLineLabel() { + String show = getValue(SHOW_LINE_LABEL); + return parseBoolean(show, false); + } + + public boolean parseShowWidth() { + String show = getValue(SHOW_WIDTH); + return parseBoolean(show, false); + } + + public boolean parseShowLevel() { + String show = getValue(SHOW_LEVEL); + return parseBoolean(show, false); + } + + public String parseTextOrientation() { + String o = getValue(TEXT_ORIENTATION); + + return o != null && "true".equals(o) + ? "horizontal" + : "vertical"; + } + + public boolean parseShowMiddleHeight() { + String show = getValue(SHOW_MIDDLE_HEIGHT); + return parseBoolean(show, false); + } + + public boolean parseLabelShowBackground() { + String show = getValue(LABEL_SHOW_BACKGROUND); + return parseBoolean(show, false); + } + + public Font parseTextFont() { + String font = getValue(LABEL_FONT_FACE); + if (font == null) { + return null; + } + + int size = parseTextSize(); + int style = parseTextStyle(); + Font f = new Font(font, style, size); + return f; + } + + public Color parseTextColor() { + return parseRGB(getTextColorString()); + } + + private String getTextColorString() { + return getValue(LABEL_FONT_COLOR); + } + + public Color parseTextBackground() { + String color = getLabelBackgroundColorString(); + return color != null + ? parseRGB(color) + : Color.WHITE; + } + + private String getLabelBackgroundColorString() { + return getValue(LABEL_BGCOLOR); + } + + public int parseLineWidth() { + String size = getValue(LINE_SIZE); + if (size == null) { + return 0; + } + + try { + return Integer.parseInt(size); + } + catch (NumberFormatException nfe) { + logger.warn("Unable to set line size from string: '" + size + "'"); + } + return 0; + } + + public float [] parseLineStyle() { + String dash = getValue(LINE_STYLE); + + float[] def = {10}; + if (dash == null) { + return def; + } + + String[] pattern = dash.split(","); + if(pattern.length == 1) { + return def; + } + + try { + float[] dashes = new float[pattern.length]; + for (int i = 0; i < pattern.length; i++) { + dashes[i] = Float.parseFloat(pattern[i]); + } + return dashes; + } + catch (NumberFormatException nfe) { + logger.warn("Unable to set dash from string: '" + dash + "'"); + return def; + } + } + + public int parsePointWidth() { + String width = getValue(POINT_SIZE); + return parseInteger(width, 3); + } + + public Color parsePointColor() { + String color = getValue(POINT_COLOR); + return parseColor(color); + } + + public boolean parseShowPoints() { + String show = getValue(SHOW_POINTS); + return parseBoolean(show, false); + } + + public boolean parseShowLine() { + String show = getValue(SHOW_LINE); + return parseBoolean(show, true); + } + + public int parseTextStyle() { + String style = getValue(LABEL_FONT_STYLE); + if (style == null) { + return Font.PLAIN; + } + + if (style.equals("italic")) { + return Font.ITALIC; + } + if (style.equals("bold")) { + return Font.BOLD; + } + return Font.PLAIN; + } + + public TextStyle parseComplexTextStyle() { + return new TextStyle( + parseTextColor(), + parseTextFont(), + parseTextBackground(), + parseLabelShowBackground(), + !parseTextOrientation().equals("horizontal")); + } + + public LineStyle parseComplexLineStyle() { + return new LineStyle( + parseLineColorField(), + Integer.valueOf(parseLineWidth())); + } + + public boolean parseShowVerticalLine() { + String show = getValue(SHOW_VERTICAL_LINE); + return parseBoolean(show, true); + } + + public boolean parseShowHorizontalLine() { + String show = getValue(SHOW_HORIZONTAL_LINE); + return parseBoolean(show, true); + } + + public double parseBandWidth() { + String bandWidth = getValue(BANDWIDTH); + return parseDouble(bandWidth, 0); + } + + private static Color parseColor(String colorString) { + if (colorString == null) { + return null; + } + if (colorString.indexOf("#") == 0) { + return parseHexColor(colorString); + } + if (colorString.indexOf(",") >= 0) { + return parseRGB(colorString); + } + + return null; + } + + + /** + * Parse a string like "#00CC22" and return the corresponding color. + * + * @param hex The hex color value. + * + * @return a Color or null, if hex is empty. + */ + private static Color parseHexColor(String hex) { + return hex != null + ? Color.decode(hex) + : null; + } + + + public boolean parseShowArea() { + String show = getValue(SHOW_AREA); + return parseBoolean(show, false); + } + + public boolean parseShowPointLabel() { + String show = getValue(SHOW_POINT_LABEL); + return parseBoolean(show, false); + } + + public boolean parseShowExtraMark() { + String show = getValue(SHOWEXTRAMARK); + return parseBoolean(show, false); + } + + public int parseTextSize() { + String size = getValue(LABEL_FONT_SIZE); + if (size == null) { + return 10; + } + + try { + return Integer.parseInt(size); + } + catch (NumberFormatException nfe) { + // Do nothing + } + return 10; + } + + /** + * Parse a string like "103, 100, 0" and return a corresping color. + * @param rgbtext Color as string representation, e.g. "255,0,20". + * @return Color, null in case of issues. + */ + public static Color parseRGB(String rgbtext) { + if (rgbtext == null) { + return null; + } + String rgb[] = rgbtext.split(","); + try { + return new Color( + Integer.parseInt(rgb[0].trim()), + Integer.parseInt(rgb[1].trim()), + Integer.parseInt(rgb[2].trim())); + } + catch (NumberFormatException nfe) { + // Do nothing + } + return null; + } + + private String getLineColorString() { + return getValue(LINE_COLOR); + } + + + /** Get show border as string. */ + private String getShowBorderString() { + return getValue(SHOW_BORDER); + } + + + /** Get fill color as string. */ + private String getFillColorString() { + return getValue(FILL_COLOR); + } + + private String getSymbol() { + return getValue(SYMBOL); + } + + private String getTransparencyString() { + return getValue(TRANSPARENCY); + } + + + private String getAreaTransparencyString() { + return getValue(AREA_TRANSPARENCY); + } + + + private String getShowMinimum() { + return getValue(SHOW_MINIMUM); + } + + + private String getShowMaximum() { + return getValue(SHOW_MAXIMUM); + } + + /** + * Gets color from color field. + * @param theme the theme document. + * @return color. + */ + public Color parseFillColorField() { + return parseRGB(getFillColorString()); + } + + public boolean parseShowBorder() { + return parseBoolean(getShowBorderString(), false); + } + + public int parseTransparency() { + return parseInteger(getTransparencyString(), 50); + } + + + /** + * Gets color from color field. + * @return color. + */ + public Color parseLineColorField() { + String lineColorStr = getLineColorString(); + if (logger.isDebugEnabled()) { + logger.debug("parseLineColorField: lineColorStr = " + + (lineColorStr == null + ? "null" + : lineColorStr)); + } + return parseColor(lineColorStr); + } + + + public Color parseAreaLineColorField() { + String lineColorStr = getAreaLineColorString(); + if (logger.isDebugEnabled()) { + logger.debug("parseLineColorField: lineColorStr = " + + (lineColorStr == null + ? "null" + : lineColorStr)); + } + return parseColor(lineColorStr); + } + + + private String getAreaLineColorString() { + return getValue(AREA_LINE_COLOR); + } + + + public boolean parseShowMinimum() { + return parseBoolean(getShowMinimum(), false); + } + + + public boolean parseShowMaximum() { + return parseBoolean(getShowMaximum(), false); + } + + + /** + * Creates a MapserverStyle from the given XML theme. + * This method uses a start- and endcolor to interpolate a + * given number of color classes for the MapserverStyle. + * @param theme + * @return String representation of the MapserverStyle + */ + public String createDynamicMapserverStyle( + float from, + float to, + float step, + CallMeta meta + ) { + MapserverStyle ms = new MapserverStyle(); + + String strStartColor = getValue(WSPLGEN_STARTCOLOR); + Color startColor = strStartColor != null + ? parseColor(strStartColor) + : new Color(178, 201, 215); + String strEndColor = getValue(WSPLGEN_ENDCOLOR); + Color endColor = strEndColor != null + ? parseColor(strEndColor) + : new Color(2, 27, 42); + + to = to != 0 ? to : 9999; + step = step != 0 ? step : to; + + int numClasses = (int)((to - from) / step); + + float rd = (endColor.getRed() - startColor.getRed()) / (float)numClasses; + float gd = (endColor.getGreen() - startColor.getGreen()) / (float)numClasses; + float bd = (endColor.getBlue() - startColor.getBlue()) / (float)numClasses; + + if (numClasses > 1) { + // Desktop Flys always added a last "and larger class" + numClasses += 1; + } + + for (int n = 0; n < numClasses; n++) { + StringBuilder newColor = new StringBuilder(); + newColor.append(startColor.getRed() + Math.round(n * rd)); + newColor.append(' '); + newColor.append(startColor.getGreen() + Math.round(n * gd)); + newColor.append(' '); + newColor.append(startColor.getBlue() + Math.round(n * bd)); + + String expr = createWSPLGENClassExpression(from + n * step, step, n + 1, numClasses); + String name = createWSPLGENClassName(from + n * step, step, n + 1, numClasses, meta); + + Clazz c = new Clazz(name); + Style s = new Style(); + s.setColor(newColor.toString()); + s.setSize(5); + + c.addItem(new Expression("(" + expr + ")")); + c.addItem(s); + + ms.addClazz(c); + } + + return ms.toString(); + } + + + protected static String createWSPLGENClassExpression(float val, float step, int idx, int maxIdx) { + if (idx < maxIdx) { + return "[DIFF] >= " + val + " AND [DIFF] < " + (val + step); + } + else { + return "[DIFF] >= " + val; + } + } + + /** + * Creates a class name for the mapfile style that visualizes a floodmap. + * The class names are used in the map's legend. + * + * @param val Current isobath value. + * @param step Difference between to class values. + * @param idx Current class index that is being processed. + * @param maxIdx Highest class index. + * @param meta Caller meta object used to determine locale. + * @return + */ + protected static String createWSPLGENClassName( + float val, + float step, + int idx, + int maxIdx, + CallMeta meta + ) { + assert meta != null : "CallMeta instance is null"; + + if (idx < maxIdx) { + return Resources.getMsg(meta, MSG_ISOBATH_CLASS, + new Object[] {val, val + step}); + } + return Resources.getMsg(meta, MSG_ISOBATH_LASTCLASS, + new Object[] {val}); + } + + + public String createMapserverStyle() { + String symbol = getSymbol(); + String backcolor = getLabelBackgroundColorString(); + String linecolor = getLineColorString(); + if (linecolor == null) { + logger.warn("createMapserverStyle: linecolor String is empty"); + linecolor = "0,128,255"; + } + + int linewidth = parseLineWidth(); + + MapserverStyle ms = new MapserverStyle(); + + Clazz c = new Clazz(" "); + + Style s = new Style(); + s.setOutlineColor(linecolor.replace(",", " ")); + + if (backcolor != null) { + s.setColor(backcolor.replace(",", " ")); + } + + s.setSize(linewidth); + s.setSymbol(symbol); + c.addItem(s); + + String textcolor = getTextColorString(); + int textsize = parseTextSize(); + + if (textcolor != null && textsize > 0) { + Label l = new Label(); + l.setColor(textcolor.replace(",", " ")); + l.setSize(textsize); + c.addItem(l); + } + + ms.addClazz(c); + + return ms.toString(); + } + + + private String getAreaBackgroundColorString() { + return getValue(AREA_BACKGROUND_COLOR); + } + + + public Color parseAreaBackgroundColor() { + return parseColor(getAreaBackgroundColorString()); + } + + + public int parseAreaTransparency() { + return parseAreaTransparency(50); + } + + public int parseAreaTransparency(int alpha) { + return parseInteger(getAreaTransparencyString(), alpha); + } + + + public boolean parseAreaShowBorder() { + return parseBoolean(getAreaShowBorderString(), false); + } + + + private String getAreaShowBorderString() { + return getValue(AREA_SHOW_BORDER); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/themes/ThemeMapping.java --- a/artifacts/src/main/java/org/dive4elements/river/themes/ThemeMapping.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/themes/ThemeMapping.java Thu Sep 12 10:13:09 2013 +0200 @@ -133,7 +133,8 @@ } // Test. - if (artifact.getDataAsString(parts[0]).equals(parts[1])) { + String artData = artifact.getDataAsString(parts[0]); + if (artData != null && artData.equals(parts[1])) { logger.debug("Matches master Attribute."); return true; } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/utils/ArtifactMapfileGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/utils/ArtifactMapfileGenerator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/utils/ArtifactMapfileGenerator.java Thu Sep 12 10:13:09 2013 +0200 @@ -10,12 +10,13 @@ import org.dive4elements.artifacts.CallContext; import org.dive4elements.river.artifacts.D4EArtifact; -import org.dive4elements.river.artifacts.access.RiverAccess; +import org.dive4elements.river.artifacts.access.RangeAccess; import org.dive4elements.river.artifacts.model.LayerInfo; import org.dive4elements.river.artifacts.model.map.WMSDBLayerFacet; import org.dive4elements.river.artifacts.model.map.WMSLayerFacet; import org.dive4elements.river.artifacts.model.map.WSPLGENLayerFacet; import org.dive4elements.river.artifacts.resources.Resources; +import org.dive4elements.river.artifacts.states.FloodMapState; import java.io.File; import java.io.FileNotFoundException; @@ -32,6 +33,12 @@ private static Logger logger = Logger.getLogger(ArtifactMapfileGenerator.class); + public static final String FLOODMAP_UESK_KEY = + "floodmap.uesk"; + + public static final String FLOODMAP_UESK_DEF = + "Floodmap: {0}-km {1,number,####} - {2,number,####} - {3}"; + @Override protected String getVelocityLogfile() { return RiverUtils.getXPathString(RiverUtils.XPATH_FLOODMAP_VELOCITY_LOGFILE); @@ -77,17 +84,32 @@ { logger.debug("createUeskLayer"); + String identifier = flys.identifier(); + + RangeAccess access = new RangeAccess(flys); + LayerInfo layerinfo = new LayerInfo(); - layerinfo.setName(MS_WSPLGEN_PREFIX + flys.identifier()); + layerinfo.setName(MS_WSPLGEN_PREFIX + identifier); layerinfo.setType("POLYGON"); - layerinfo.setDirectory(flys.identifier()); + layerinfo.setDirectory(identifier); layerinfo.setData(WSPLGEN_RESULT_SHAPE); - layerinfo.setTitle(Resources.getMsg(Resources.getLocale(context.getMeta()), - "floodmap.uesk", - "Floodmap")); + + String river = access.getRiver(); + + double from = access.hasFrom() ? access.getFrom() : 0d; + double to = access.hasTo() ? access.getTo() : 0d; + + String title = Resources.format( + context.getMeta(), + FLOODMAP_UESK_KEY, + FLOODMAP_UESK_DEF, + river, + from, to, + identifier); + + layerinfo.setTitle(title); + layerinfo.setStyle(style); - RiverAccess access = new RiverAccess(flys); - String river = access.getRiver(); layerinfo.setSrid(RiverUtils.getRiverDGMSrid(river)); String name = MS_LAYER_PREFIX + wms.getName(); @@ -99,7 +121,7 @@ } try { - File dir = new File(getShapefileBaseDir(), flys.identifier()); + File dir = new File(getShapefileBaseDir(), identifier); writeLayer(layerinfo, new File(dir, name), template); } catch (FileNotFoundException fnfe) { @@ -135,11 +157,11 @@ ShapefileReader sfr = new ShapefileReader(sf, true, false, null); ShapefileHeader sfh = sfr.getHeader(); - String group = uuid + MS_USERSHAPE_PREFIX; + String group = MS_USERSHAPE_PREFIX + uuid; String groupTitle = "I18N_USER_SHAPE_TITLE"; LayerInfo info = new LayerInfo(); - info.setName(MS_USERSHAPE_PREFIX + uuid); + info.setName(MS_LAYER_PREFIX + FloodMapState.WSPLGEN_USER_RGD + uuid); if (sfh.getShapeType().isLineType()) { info.setType("LINE"); } @@ -156,7 +178,11 @@ info.setGroupTitle(groupTitle); info.setSrid(wms.getSrid()); - String nameUser = MS_LAYER_PREFIX + wms.getName(); + //String nameUser = MS_LAYER_PREFIX + wms.getName(); + // TODO: This rewrites the user-rgd mapfile fragment generated by + // HWSBarrierState. Otherwise we would have to fragments with same + // layer name. Should be refactored... + String nameUser = MS_LAYER_PREFIX + "user-rgd"; Template tpl = getTemplateByName(SHP_LAYER_TEMPLATE); if (tpl == null) { @@ -225,13 +251,12 @@ } @Override - protected String getMapfilePath() { - return RiverUtils.getXPathString(RiverUtils.XPATH_FLOODMAP_MAPFILE_PATH); - } + protected String getMapfilePath() { + return RiverUtils.getXPathString(RiverUtils.XPATH_FLOODMAP_MAPFILE_PATH); + } @Override - protected String getMapfileTemplate() { - return RiverUtils.getXPathString(RiverUtils.XPATH_FLOODMAP_MAPFILE_TEMPLATE); - } - + protected String getMapfileTemplate() { + return RiverUtils.getXPathString(RiverUtils.XPATH_FLOODMAP_MAPFILE_TEMPLATE); + } } diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/utils/BatchLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/utils/BatchLoader.java Thu Sep 12 10:13:09 2013 +0200 @@ -0,0 +1,116 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.utils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.hibernate.SQLQuery; +import org.hibernate.Session; + +/** To reduce the number of SQL queries send to the backend + * (mainly by the fixings overviews) we execute them in batches of ids + * and store the results in a small cache. + * TODO: It currently relies on dynamic SQL. + * Is there a way to use Hibernate with java.sql.Array + * in cross database compatible manner? + */ +public abstract class BatchLoader { + + private static Logger log = Logger.getLogger(BatchLoader.class); + + public static final int BATCH_SIZE = 100; + + private Map loaded; + private List rest; + private Session session; + private String sqlTemplate; + + public BatchLoader( + List columns, + Session session, + String sqlTemplate + ) { + rest = new ArrayList(columns.size()); + loaded = new HashMap(); + this.session = session; + this.sqlTemplate = sqlTemplate; + + // Insert in reverse order to minize searching. + for (int i = columns.size()-1; i >= 0; --i) { + rest.add(columns.get(i)); + } + } + + /** Searches for id and fill a batch to load containing the found id. */ + private List prepareBatch(int id) { + List batch = new ArrayList(BATCH_SIZE); + + boolean found = false; + + for (int i = rest.size()-1; batch.size() < BATCH_SIZE && i >= 0; --i) { + Integer cid = rest.get(i); + if (cid == id) { + found = true; + batch.add(cid); + rest.remove(i); + } + else if ((found && batch.size() < BATCH_SIZE) + || (!found && batch.size() < BATCH_SIZE-1)) { + batch.add(cid); + rest.remove(i); + } + } + + return batch; + } + + /** Converts id to a list of comma separated ints. */ + private static String idsAsString(List ids) { + StringBuilder sb = new StringBuilder(); + for (Iterator i = ids.iterator(); i.hasNext();) { + sb.append(i.next()); + if (i.hasNext()) { + sb.append(','); + } + } + return sb.toString(); + } + + /** Get data for id. */ + public T get(int id) { + T already = loaded.get(id); + if (already != null) { + return already; + } + + List batch = prepareBatch(id); + if (batch.isEmpty()) { + return null; + } + String sql = sqlTemplate.replace("$IDS", idsAsString(batch)); + if (log.isDebugEnabled()) { + log.debug(sql + " " + sql.length()); + } + fill(session.createSQLQuery(sql)); + return get(id); + } + + /** Call this from fill() to store data in the cache. */ + protected void cache(int key, T data) { + loaded.put(key, data); + } + + /** Override this to fill the cache */ + protected abstract void fill(SQLQuery query); +} diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/utils/CompareUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/utils/CompareUtil.java Thu Sep 12 10:13:09 2013 +0200 @@ -0,0 +1,25 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.utils; + +/** Utils to deal with Comparisons. */ +public class CompareUtil +{ + /** Singleton. */ + private CompareUtil() { + } + + /** Return true if a and b are either both null or equal(). */ + public static boolean areSame(T a, T b) { + if (a == null) return b == null; + if (b == null) return false; + return a.equals(b); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/utils/Formatter.java --- a/artifacts/src/main/java/org/dive4elements/river/utils/Formatter.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/utils/Formatter.java Thu Sep 12 10:13:09 2013 +0200 @@ -135,7 +135,7 @@ } /** - * Returns a formatter in engineering notation + * Returns a formatter in engineering notation. */ public static NumberFormat getEngFormatter(CallContext c) { NumberFormat nf = getRawFormatter(c); @@ -147,7 +147,7 @@ } /** - * Returns a number formatter that uses an exponent after max digits + * Returns a number formatter that uses an exponent after max digits. */ public static NumberFormat getScientificFormater(CallContext c, int min, int max) { NumberFormat nf = getRawFormatter(c); diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/utils/RiverUtils.java --- a/artifacts/src/main/java/org/dive4elements/river/utils/RiverUtils.java Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/utils/RiverUtils.java Thu Sep 12 10:13:09 2013 +0200 @@ -178,7 +178,7 @@ /** - * This method returns an WQ_MODE enum which is based on the parameters + * Returns an WQ_MODE enum which is based on the parameters * stored in flys Artifact. If there is no wq_isq parameter * existing, WQ_MODE.NONE is returned. * @@ -340,7 +340,7 @@ return ((WINFOArtifact) flys).getQs(); } - logger.warn("This method currently supports WINFOArtifact only!"); + logger.warn("This method (getQs) currently supports WINFOArtifact only!"); return null; } @@ -360,7 +360,7 @@ return ((WINFOArtifact) flys).getWs(); } - logger.warn("This method currently supports WINFOArtifact only!"); + logger.warn("This method (getWs) currently supports WINFOArtifact only!"); return null; } @@ -491,10 +491,14 @@ public static Gauge getReferenceGauge(D4EArtifact flys) { Long officialNumber = flys.getDataAsLong("reference_gauge"); + String river = getRivername(flys); - return officialNumber != null - ? Gauge.getGaugeByOfficialNumber(officialNumber) - : null; + if (officialNumber != null && river != null) { + return Gauge.getGaugeByOfficialNumber(officialNumber, river); + } else if (officialNumber != null) { + return Gauge.getGaugeByOfficialNumber(officialNumber); + } + return null; } @@ -697,7 +701,7 @@ /** - * This method returns the description for a given km for a specific + * Returns the description for a given km for a specific * river. The river is provided by the D4EArtifact flys. * * @param flys The D4EArtifact that provides a river. @@ -718,7 +722,7 @@ /** - * This method returns the differences for a w-differences calculation. + * Returns the differences for a w-differences calculation. * * @param winfo The WINFOArtifact. * @param context The context. @@ -806,7 +810,7 @@ /** - * This method transform a string into an int array. Therefore, the string + * Transform a string into an int array. Therefore, the string * raw must consist of int values separated by a ';'. * * @param raw The raw integer array as string separated by a ';'. @@ -837,7 +841,7 @@ /** - * This method transform a string into a long array. Therefore, the string + * Transform a string into a long array. Therefore, the string * raw must consist of int values separated by a ';'. * * @param raw The raw long array as string separated by a ';'. @@ -868,7 +872,7 @@ /** - * This method transform a string into an double array. Therefore, the + * Transform a string into an double array. Therefore, the * string raw must consist of double values separated by a * ';'. * @@ -925,5 +929,14 @@ return river.determineGauges(dist[0], dist[1]); } + + /** Round a Q in the AT format style **/ + public static double roundQ(double q) { + if (q < 10d) q = Math.rint((q*1000d)) / 1000d; + else if (q < 100d) q = Math.rint((q*100d)) / 100d; + else if (q < 1000d) q = Math.rint((q*10d)) / 10d; + else if (q >= 1000d) q = Math.rint(q); + return q; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/utils/ThemeUtil.java --- a/artifacts/src/main/java/org/dive4elements/river/utils/ThemeUtil.java Sat Jun 29 00:20:58 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,827 +0,0 @@ -/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde - * Software engineering by Intevation GmbH - * - * This file is Free Software under the GNU AGPL (>=v3) - * and comes with ABSOLUTELY NO WARRANTY! Check out the - * documentation coming with Dive4Elements River for details. - */ - -package org.dive4elements.river.utils; - -import org.dive4elements.artifacts.CallMeta; -import org.dive4elements.artifacts.common.utils.XMLUtils; -import org.dive4elements.river.artifacts.model.MapserverStyle; -import org.dive4elements.river.artifacts.model.MapserverStyle.Clazz; -import org.dive4elements.river.artifacts.model.MapserverStyle.Expression; -import org.dive4elements.river.artifacts.model.MapserverStyle.Label; -import org.dive4elements.river.artifacts.model.MapserverStyle.Style; -import org.dive4elements.river.artifacts.resources.Resources; - -import java.awt.Color; -import java.awt.Font; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; - - -/** - * Utility to deal with themes and their representations. - */ -public class ThemeUtil { - - /** Private logger. */ - private static Logger logger = - Logger.getLogger(ThemeUtil.class); - - private static final String MSG_ISOBATH_CLASS = "floodmap.isobath.class"; - - private static final String MSG_ISOBATH_LASTCLASS = "floodmap.isobath.lastclass"; - - public final static String XPATH_FILL_COLOR = - "/theme/field[@name='fillcolor']/@default"; - - public final static String XPATH_LINE_COLOR = - "/theme/field[@name='linecolor']/@default"; - - public final static String XPATH_AREA_LINE_COLOR = - "/theme/field[@name='areabordercolor']/@default"; - - public static final String XPATH_LINE_SIZE = - "/theme/field[@name='linesize']/@default"; - - public static final String XPATH_LINE_STYLE = - "/theme/field[@name='linetype']/@default"; - - public static final String XPATH_POINT_SIZE = - "/theme/field[@name='pointsize']/@default"; - - public static final String XPATH_POINT_COLOR = - "/theme/field[@name='pointcolor']/@default"; - - public final static String XPATH_SHOW_BORDER = - "/theme/field[@name='showborder']/@default"; - - public final static String XPATH_AREA_SHOW_BORDER = - "/theme/field[@name='showborder']/@default"; - - public final static String XPATH_SHOW_POINTS = - "/theme/field[@name='showpoints']/@default"; - - public final static String XPATH_SHOW_LINE = - "/theme/field[@name='showlines']/@default"; - - public final static String XPATH_SHOW_VERTICAL_LINE = - "/theme/field[@name='showverticalline']/@default"; - - public final static String XPATH_SHOW_HORIZONTAL_LINE = - "/theme/field[@name='showhorizontalline']/@default"; - - public final static String XPATH_SHOW_LINE_LABEL = - "/theme/field[@name='showlinelabel']/@default"; - - public final static String XPATH_SHOW_POINT_LABEL = - "/theme/field[@name='showpointlabel']/@default"; - - public final static String XPATH_SHOW_WIDTH = - "/theme/field[@name='showwidth']/@default"; - - public final static String XPATH_SHOW_LEVEL = - "/theme/field[@name='showlevel']/@default"; - - public final static String XPATH_TRANSPARENCY = - "/theme/field[@name='transparency']/@default"; - - public final static String XPATH_AREA_TRANSPARENCY = - "/theme/field[@name='areatransparency']/@default"; - - public final static String XPATH_SHOW_AREA = - "/theme/field[@name='showarea']/@default"; - - public final static String XPATH_SHOW_MIDDLE_HEIGHT = - "/theme/field[@name='showmiddleheight']/@default"; - - public final static String XPATH_LABEL_FONT_COLOR = - "/theme/field[@name='labelfontcolor']/@default"; - - public final static String XPATH_LABEL_FONT_SIZE = - "/theme/field[@name='labelfontsize']/@default"; - - public final static String XPATH_LABEL_FONT_FACE = - "/theme/field[@name='labelfontface']/@default"; - - public final static String XPATH_LABEL_FONT_STYLE = - "/theme/field[@name='labelfontstyle']/@default"; - - public final static String XPATH_TEXT_ORIENTATION = - "/theme/field[@name='textorientation']/@default"; - - public final static String XPATH_LABEL_BGCOLOR = - "/theme/field[@name='labelbgcolor']/@default"; - - public final static String XPATH_LABEL_SHOW_BACKGROUND = - "/theme/field[@name='labelshowbg']/@default"; - - public final static String XPATH_BACKGROUND_COLOR = - "/theme/field[@name='backgroundcolor']/@default"; - - public final static String XPATH_AREA_BACKGROUND_COLOR = - "/theme/field[@name='areabgcolor']/@default"; - - public final static String XPATH_SYMBOL = - "/theme/field[@name='symbol']/@default"; - - public final static String XPATH_SHOW_MINIMUM = - "/theme/field[@name='showminimum']/@default"; - - public final static String XPATH_SHOW_MAXIMUM = - "/theme/field[@name='showmaximum']/@default"; - - public final static String XPATH_WSPLGEN_FIELDS = - "/theme[@name='WSPLGEN']/field"; - - public final static String XPATH_WSPLGEN_STARTCOLOR = - "/theme/field[@name='startcolor']/@default"; - - public final static String XPATH_WSPLGEN_ENDCOLOR = - "/theme/field[@name='endcolor']/@default"; - - public final static String XPATH_WSPLGEN_NUMCLASSES = - "/theme/field[@name='numclasses']/@default"; - - /** XPATH to bandwidth field. */ - public final static String XPATH_BANDWIDTH = - "/theme/field[@name='bandwidth']/@default"; - - /** XPATH to find showextramark field. */ - public final static String XPATH_SHOWEXTRAMARK = - "/theme/field[@name='showextramark']/@default"; - - /** Parse string to be boolean with default if empty or unrecognized. */ - public static boolean parseBoolean(String value, boolean defaultsTo) { - if (value == null || value.length() == 0) { - return defaultsTo; - } - if (value.equals("false")) { - return false; - } - else if (value.equals("true")) { - return true; - } - else { - return defaultsTo; - } - } - - - /** - * Attempt converting \param value to an integer, in failing cases, - * return \param defaultsTo. - * @param value String to be converted to integer. - * @param defaultsTo Default to return if conversion failed. - * @return \param value as integer or defaultsto if conversion failed. - */ - public static int parseInteger(String value, int defaultsTo) { - if (value == null || value.length() == 0) { - return defaultsTo; - } - - try { - return Integer.parseInt(value); - } - catch (NumberFormatException nfe) { - // do nothing - } - - return defaultsTo; - } - - - /** - * Attempt converting \param value to a double, in failing cases, - * return \param defaultsTo. - * @param value String to be converted to double. - * @param defaultsTo Default to return if conversion failed. - * @return \param value as integer or defaultsto if conversion failed. - */ - public static double parseDouble(String value, double defaultsTo) { - if (value == null || value.length() == 0) { - return defaultsTo; - } - - try { - return Double.parseDouble(value); - } - catch (NumberFormatException nfe) { - // do nothing - } - - return defaultsTo; - } - - - /** - * Parses line width, defaulting to 0. - * @param theme the theme - */ - public static int parseLineWidth(Document theme) { - String size = XMLUtils.xpathString(theme, XPATH_LINE_SIZE, null); - if (size == null || size.length() == 0) { - return 0; - } - - try { - return Integer.parseInt(size); - } - catch (NumberFormatException nfe) { - logger.warn("Unable to set line size from string: '" + size + "'"); - } - return 0; - } - - - /** - * Parse band width, defaulting to 0. - * @param theme the theme. - */ - public static double parseBandWidth(Document theme) { - String bandWidth = XMLUtils.xpathString(theme, XPATH_BANDWIDTH, null); - - return parseDouble(bandWidth, 0); - } - - - public static int parsePointWidth(Document theme) { - String width = XMLUtils.xpathString(theme, XPATH_POINT_SIZE, null); - - return parseInteger(width, 3); - } - - - public static Color parsePointColor(Document theme) { - String color = XMLUtils.xpathString(theme, XPATH_POINT_COLOR, null); - logger.debug("parsePointColor(): color = " + color); - return parseColor(color); - } - - - /** - * Parses the line style, defaulting to '10'. - * @param theme The theme. - */ - public static float[] parseLineStyle(Document theme) { - String dash = XMLUtils.xpathString(theme, XPATH_LINE_STYLE, null); - - float[] def = {10}; - if (dash == null || dash.length() == 0) { - return def; - } - - String[] pattern = dash.split(","); - if(pattern.length == 1) { - return def; - } - - try { - float[] dashes = new float[pattern.length]; - for (int i = 0; i < pattern.length; i++) { - dashes[i] = Float.parseFloat(pattern[i]); - } - return dashes; - } - catch(NumberFormatException nfe) { - logger.warn("Unable to set dash from string: '" + dash + "'"); - return def; - } - } - - - /** - * Parses text size, defaulting to 10. - * @param theme The theme. - */ - public static int parseTextSize(Document theme, String path) { - String size = XMLUtils.xpathString(theme, path, null); - if (size == null || size.length() == 0) { - return 10; - } - - try { - return Integer.parseInt(size); - } - catch (NumberFormatException nfe) { - } - return 10; - } - - - public static int parseTextSize(Document theme) { - return parseTextSize(theme, XPATH_LABEL_FONT_SIZE); - } - - - /** - * Parses the attribute 'showextramark', defaults to false. - * @param theme The theme. - */ - public static boolean parseShowExtraMark(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOWEXTRAMARK, null); - return parseBoolean(show, false); - } - - /** - * Parses the attribute 'showpoints', defaults to false. - * @param theme The theme. - */ - public static boolean parseShowPoints(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_POINTS, null); - return parseBoolean(show, false); - } - - /** - * Parses the attribute 'showmiddleheight', defaults to false. - * @param theme The theme. - */ - public static boolean parseShowMiddleHeight(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_MIDDLE_HEIGHT, null); - return parseBoolean(show, false); - } - - /** - * Parses the attribute 'showarea', defaults to false. - * @param theme The theme. - */ - public static boolean parseShowArea(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_AREA, null); - return parseBoolean(show, false); - } - - /** - * Parses the attribute 'showverticalline', defaults to true. - * @param theme The theme. - */ - public static boolean parseShowVerticalLine(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_VERTICAL_LINE, null); - return parseBoolean(show, true); - } - - /** - * Parses the attribute 'showhorizontalline', defaults to true. - * @param theme The theme. - */ - public static boolean parseShowHorizontalLine(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_HORIZONTAL_LINE, null); - return parseBoolean(show, true); - } - - /** - * Parses the attribute 'showlines', defaults to true. - * @param theme The theme. - */ - public static boolean parseShowLine(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_LINE, null); - return parseBoolean(show, true); - } - - /** - * Parses the attribute 'showlinelabel', defaults to true. - * @param theme The theme. - */ - public static boolean parseShowLineLabel(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_LINE_LABEL, null); - return parseBoolean(show, false); - } - - public static boolean parseShowPointLabel(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_POINT_LABEL, null); - return parseBoolean(show, false); - } - - /** - * Parses text color. - * @param theme The theme. - */ - public static Color parseTextColor(Document theme) { - return parseRGB(getTextColorString(theme)); - } - - - /** - * Parses the font. - * @param theme The theme. - */ - public static Font parseTextFont(Document theme) { - String font = XMLUtils.xpathString(theme, XPATH_LABEL_FONT_FACE, null); - if (font == null || font.length() == 0) { - return null; - } - - int size = parseTextSize(theme); - int style = parseTextStyle(theme); - Font f = new Font (font, style, size); - return f; - } - - - /** - * Parses the text style, defaults to 'Font.PLAIN'. - * @param theme The theme. - */ - public static int parseTextStyle(Document theme, String path) { - String style = XMLUtils.xpathString(theme, path, null); - if (style == null || style.length() == 0) { - return Font.PLAIN; - } - - if (style.equals("italic")) { - return Font.ITALIC; - } - else if (style.equals("bold")) { - return Font.BOLD; - } - else { - return Font.PLAIN; - } - } - - - public static int parseTextStyle(Document theme) { - return parseTextStyle(theme, XPATH_LABEL_FONT_STYLE); - } - - - public static boolean parseShowWidth(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_WIDTH, null); - return parseBoolean(show, false); - } - - - public static boolean parseShowLevel(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_SHOW_LEVEL, null); - return parseBoolean(show, false); - } - - /** - * Parses the textorientation, defaults to 'vertical'. - * @param theme The theme. - */ - public static String parseTextOrientation(Document theme) { - String o = XMLUtils.xpathString(theme, XPATH_TEXT_ORIENTATION, null); - if ("true".equals(o)) { - return "horizontal"; - } - else { - return "vertical"; - } - } - - - /** - * Parses the text background color, defaults to white. - * @param theme The theme. - */ - public static Color parseTextBackground(Document theme) { - String color = getLabelBackgroundColorString(theme); - if (color == null || color.length() == 0) { - return Color.WHITE; - } - return parseRGB(color); - } - - - /** - * Parses the attribute whether to show background or not, defaults to - * false. - * @param theme The theme. - */ - public static boolean parseLabelShowBackground(Document theme) { - String show = XMLUtils.xpathString(theme, XPATH_LABEL_SHOW_BACKGROUND, null); - return parseBoolean(show, false); - } - - - public static Color parseColor(String colorString) { - if (colorString == null || colorString.length() == 0) { - return null; - } - else if (colorString.indexOf("#") == 0) { - return parseHexColor(colorString); - } - else if (colorString.indexOf(",") >= 0) { - return parseRGB(colorString); - } - - return null; - } - - - /** - * Parse a string like "#00CC22" and return the corresponding color. - * - * @param hex The hex color value. - * - * @return a Color or null, if hex is empty. - */ - public static Color parseHexColor(String hex) { - if (hex == null) { - return null; - } - - return Color.decode(hex); - } - - /** - * Parse a string like "103, 100, 0" and return a corresping color. - * @param rgbtext Color as string representation, e.g. "255,0,20". - * @return Color, null in case of issues. - */ - public static Color parseRGB(String rgbtext) { - if (rgbtext == null) { - return null; - } - String rgb[] = rgbtext.split(","); - Color c = null; - try { - c = new Color( - Integer.parseInt(rgb[0].trim()), - Integer.parseInt(rgb[1].trim()), - Integer.parseInt(rgb[2].trim())); - } - catch (NumberFormatException nfe) { - c = null; - } - return c; - } - - - public static String getLineColorString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_LINE_COLOR, null); - } - - - /** Get show border as string. */ - public static String getShowBorderString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_SHOW_BORDER, null); - } - - - /** Get fill color as string. */ - public static String getFillColorString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_FILL_COLOR, null); - } - - - public static String getLabelBackgroundColorString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_LABEL_BGCOLOR, null); - } - - - public static String getBackgroundColorString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_BACKGROUND_COLOR, null); - } - - - public static String getTextColorString(Document theme) { - String textColor = XMLUtils.xpathString(theme, XPATH_LABEL_FONT_COLOR, null); - return textColor; - } - - - public static String getSymbol(Document theme) { - return XMLUtils.xpathString(theme, XPATH_SYMBOL, null); - } - - - public static String getTransparencyString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_TRANSPARENCY, null); - } - - - public static String getAreaTransparencyString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_AREA_TRANSPARENCY, null); - } - - - public static String getShowMinimum(Document theme) { - return XMLUtils.xpathString(theme, XPATH_SHOW_MINIMUM, null); - } - - - public static String getShowMaximum(Document theme) { - return XMLUtils.xpathString(theme, XPATH_SHOW_MAXIMUM, null); - } - - - /** - * Gets color from color field. - * @param theme the theme document. - * @return color. - */ - public static Color parseFillColorField(Document theme) { - return parseRGB(getFillColorString(theme)); - } - - - public static boolean parseShowBorder(Document theme) { - return parseBoolean(getShowBorderString(theme), false); - } - - - public static int parseTransparency(Document theme) { - return parseInteger(getTransparencyString(theme), 50); - } - - - /** - * Gets color from color field. - * @param theme the theme document. - * @return color. - */ - public static Color parseLineColorField(Document theme) { - String lineColorStr = getLineColorString(theme); - logger.debug("parseLineColorField: lineColorStr = " + - (lineColorStr == null ? "null" : lineColorStr)); - return parseColor(lineColorStr); - } - - - public static Color parseAreaLineColorField(Document theme) { - String lineColorStr = getAreaLineColorString(theme); - logger.debug("parseLineColorField: lineColorStr = " + - (lineColorStr == null ? "null" : lineColorStr)); - return parseColor(lineColorStr); - } - - - private static String getAreaLineColorString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_AREA_LINE_COLOR, null); - } - - - public static boolean parseShowMinimum(Document theme) { - return parseBoolean(getShowMinimum(theme), false); - } - - - public static boolean parseShowMaximum(Document theme) { - return parseBoolean(getShowMaximum(theme), false); - } - - - /** - * Creates a MapserverStyle from the given XML theme. - * This method uses a start- and endcolor to interpolate a - * given number of color classes for the MapserverStyle. - * @param theme - * @return String representation of the MapserverStyle - */ - public static String createDynamicMapserverStyle(Document theme, - float from, float to, float step, CallMeta meta) - { - MapserverStyle ms = new MapserverStyle(); - - String strStartColor = XMLUtils.xpathString(theme, XPATH_WSPLGEN_STARTCOLOR, null); - Color startColor = strStartColor != null ? parseColor(strStartColor) : new Color(178, 201, 215); - String strEndColor = XMLUtils.xpathString(theme, XPATH_WSPLGEN_ENDCOLOR, null); - Color endColor = strEndColor != null? parseColor(strEndColor) : new Color(2, 27, 42); - - to = to != 0 ? to : 9999; - step = step != 0 ? step : to; - - int numClasses = (int)((to - from) / step); - - float rd = (endColor.getRed() - startColor.getRed()) / (float)numClasses; - float gd = (endColor.getGreen() - startColor.getGreen()) / (float)numClasses; - float bd = (endColor.getBlue() - startColor.getBlue()) / (float)numClasses; - - if (numClasses > 1) { - // Desktop Flys always added a last "and larger class" - numClasses += 1; - } - - for (int n = 0; n < numClasses; n++) { - StringBuilder newColor = new StringBuilder(); - newColor.append(startColor.getRed() + Math.round(n * rd)); - newColor.append(' '); - newColor.append(startColor.getGreen() + Math.round(n * gd)); - newColor.append(' '); - newColor.append(startColor.getBlue() + Math.round(n * bd)); - - String expr = createWSPLGENClassExpression(from + n * step, step, n + 1, numClasses); - String name = createWSPLGENClassName(from + n * step, step, n + 1, numClasses, meta); - - Clazz c = new Clazz(name); - Style s = new Style(); - s.setColor(newColor.toString()); - s.setSize(5); - - c.addItem(new Expression("(" + expr + ")")); - c.addItem(s); - - ms.addClazz(c); - } - - return ms.toString(); - } - - - protected static String createWSPLGENClassExpression(float val, float step, int idx, int maxIdx) { - if (idx < maxIdx) { - return "[DIFF] >= " + val + " AND [DIFF] < " + (val + step); - } - else { - return "[DIFF] >= " + val; - } - } - - /** - * Creates a class name for the mapfile style that visualizes a floodmap. - * The class names are used in the map's legend. - * - * @param val Current isobath value. - * @param step Difference between to class values. - * @param idx Current class index that is being processed. - * @param maxIdx Highest class index. - * @param meta Caller meta object used to determine locale. - * @return - */ - protected static String createWSPLGENClassName(float val, float step, int idx, int maxIdx, CallMeta meta) { - assert meta != null : "CallMeta instance is null"; - - if (idx < maxIdx) { - return Resources.getMsg(meta, MSG_ISOBATH_CLASS, - new Object[] {val, val + step}); - } - else { - return Resources.getMsg(meta, MSG_ISOBATH_LASTCLASS, - new Object[] {val}); - } - } - - - public static String createMapserverStyle(Document theme) { - String symbol = getSymbol(theme); - String backcolor = getLabelBackgroundColorString(theme); - String linecolor = getLineColorString(theme); - if (linecolor == null || "".equals(linecolor)) { - logger.warn("createMapserverStyle: linecolor String is empty"); - linecolor = "0,128,255"; - } - - int linewidth = parseLineWidth(theme); - - MapserverStyle ms = new MapserverStyle(); - - Clazz c = new Clazz(" "); - - Style s = new Style(); - s.setOutlineColor(linecolor.replace(",", " ")); - - if (backcolor != null && backcolor.length() > 0) { - s.setColor(backcolor.replace(",", " ")); - } - - s.setSize(linewidth); - s.setSymbol(symbol); - c.addItem(s); - - String textcolor = getTextColorString(theme); - int textsize = parseTextSize(theme); - - if (textcolor != null && textcolor.length() > 0 && textsize > 0) { - Label l = new Label(); - l.setColor(textcolor.replace(",", " ")); - l.setSize(textsize); - c.addItem(l); - } - - ms.addClazz(c); - - return ms.toString(); - } - - - public static String getAreaBackgroundColorString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_AREA_BACKGROUND_COLOR, null); - } - - - public static Color parseAreaBackgroundColor(Document theme) { - return parseColor(getAreaBackgroundColorString(theme)); - } - - - public static int parseAreaTransparency(Document theme) { - return parseInteger(getAreaTransparencyString(theme), 50); - } - - - public static boolean parseAreaShowBorder(Document theme) { - return parseBoolean(getAreaShowBorderString(theme), false); - } - - - private static String getAreaShowBorderString(Document theme) { - return XMLUtils.xpathString(theme, XPATH_AREA_SHOW_BORDER, null); - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/java/org/dive4elements/river/utils/UniqueDateFormatter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/utils/UniqueDateFormatter.java Thu Sep 12 10:13:09 2013 +0200 @@ -0,0 +1,59 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.utils; + +import java.text.DateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; + +public class UniqueDateFormatter { + + private static Logger log = Logger.getLogger(UniqueDateFormatter.class); + + private DateFormat df; + private DateFormat lf; + private Map collisions; + + public UniqueDateFormatter( + DateFormat df, + DateFormat lf, + Collection dates + ) { + this.df = df; + this.lf = lf; + collisions = build(dates); + } + + private Map build(Collection dates) { + Map collisions = new HashMap(); + for (Date d: dates) { + String s = df.format(d); + int [] count = collisions.get(s); + if (count == null) { + collisions.put(s, count = new int[1]); + } + if (++count[0] > 1) { + log.debug("date collsion found: " + d); + } + } + return collisions; + } + + public String format(Date date) { + String s = df.format(date); + int [] count = collisions.get(s); + return count == null || count[0] < 2 + ? s + : lf.format(date); + } +} diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/resources/datacage-sql/org-h2-driver.properties --- a/artifacts/src/main/resources/datacage-sql/org-h2-driver.properties Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/resources/datacage-sql/org-h2-driver.properties Thu Sep 12 10:13:09 2013 +0200 @@ -17,6 +17,7 @@ insert.out = INSERT INTO outs (id, artifact_id, name, description, out_type) VALUES (?, ?, ?, ?, ?) facet.id.nextval = SELECT NEXTVAL('FACETS_ID_SEQ') insert.facet = INSERT INTO facets (id, out_id, name, num, state, description) VALUES (?, ?, ?, ?, ?, ?) +update.artifact.state = UPDATE artifacts SET state = ? WHERE id = ? update.collection.name = UPDATE collections SET name = ? WHERE gid = ? delete.artifact.from.collection = DELETE FROM collection_items WHERE collection_id = ? AND artifact_id = ? diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/resources/messages.properties --- a/artifacts/src/main/resources/messages.properties Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/resources/messages.properties Thu Sep 12 10:13:09 2013 +0200 @@ -48,7 +48,7 @@ state.minfo.dischargestate = Selection of discharge state and channel state.minfo.sq.location=Location state.minfo.sq.period=Periods -state.minfo.sq.outliers=Outliers +state.minfo.sq.outliers=Tolerance state.minfo.sq.outlier-method=Outliertest state.minfo.bed.year_epoch=Year/Epoch state.minfo.bed.difference_select=Differences @@ -141,7 +141,7 @@ floodplain.inactive = Inactiv outlier.method.grubbs=Grubbs -outlier.method.std-dev=Standard deviation +outlier.method.std-dev=Residual standard error river = River calculation_mode = Calculation Mode @@ -171,7 +171,7 @@ chart.computed.discharge.curve.subtitle = {0}-km: {1,number,#.###} chart.computed.discharge.curve.yaxis.label = W [{0}] chart.computed.discharge.curve.curve.label = Discharge Curve {0} km {1} -chart.computed.discharge.curve.gauge = Discharge curve at gauge {0} (km {1}) +chart.computed.discharge.curve.gauge = current DC {0} {1} - {2} chart.duration.curve.title = Duration Curve chart.duration.curve.subtitle = {0}-km: {1,number,#.###} chart.duration.curve.xaxis.label = Duration of Non-Exceedence [Days] @@ -287,7 +287,7 @@ bedquality.toplayer = 0.0m - 0.3m bedquality.sublayer = 0.1m - 0.5m facet.bedheight.diff.year = Bedheight Difference {0} -facet.bedheight.diff.morph = sounding Width {0} +facet.bedheight.diff.morph = sounding Width facet.bedheight.diff.height1 = Original Height Minuend {0} facet.bedheight.diff.height2 = Original Height Subtrahend {0} facet.bedheight.diff.absolute = Bedheight Difference/Year {0} @@ -310,7 +310,7 @@ chart.beddifference.height.yaxis.label = Difference [cm/year] chart.beddifference.epoch.title = Bedheight Difference chart.beddifference.xaxis.label = {0}-km -chart.beddifference.yaxis.label.diff = Difference [m] +chart.beddifference.yaxis.label.diff = Difference [cm] chart.beddifference.yaxis.label.height = Absolute Height [{0}] chart.beddifference.year.title = Bedheight Difference chart.beddifference.yaxis.label.morph = Width [m] @@ -384,6 +384,15 @@ export.bedheight_middle.csv.header.soundingwidth = Sounding Width [m] export.bedheight_middle.csv.header.width = morphological active width [m] export.bedheight_middle.csv.header.locations = Location +export.sedimentload_ls.csv.header.km = km +export.sedimentload_ls.csv.header.year = year +export.sedimentload_ls.csv.header.coarse = coarse +export.sedimentload_ls.csv.header.finemiddle = finemiddle +export.sedimentload_ls.csv.header.sand = sand +export.sedimentload_ls.csv.header.suspsand = susp. sand +export.sedimentload_ls.csv.header.suspsediment = susp. sediment +export.sedimentload_ls.csv.header.suspsandbb = susp. sand (BB) +export.sedimentload_ls.csv.header.total = total export.sqrelation.csv.header.parameter = Parameter export.sqrelation.csv.header.station = Station export.sqrelation.csv.header.km = River-Km @@ -395,9 +404,10 @@ export.sqrelation.csv.header.coeff.r = r^2 export.sqrelation.csv.header.n.total = n total export.sqrelation.csv.header.n.outliers = n outliers -export.sqrelation.csv.header.c.duan = C (DUAN) -export.sqrelation.csv.header.c.ferguson = C (FERGUSON) -export.sqrelation.csv.header.variance = Standard variance +export.sqrelation.csv.header.c.duan = C (Duan) +export.sqrelation.csv.header.c.ferguson = C (Ferguson) +export.sqrelation.csv.header.sd = Standard error +export.sqrelation.csv.header.qmax = Q max,measured export.sqrelation.pdf.file = /jasper/sqrelation_en.jasper export.sqrelation.pdf.mode = Load Discharge Relation export.minfo.bedquality.km = km @@ -416,7 +426,7 @@ floodmap.wmsbackground = Background Map floodmap.riveraxis = River Axis -floodmap.uesk = Floodmap: {0}-km {1,number,####} - {2,number,####} +floodmap.uesk = Floodmap: {0}-km {1,number,####} - {2,number,####} - {3} floodmap.barriers = Digitized Objects floodmap.kms = Kilometrage floodmap.qps = Crosssection Tracks diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/resources/messages_de.properties --- a/artifacts/src/main/resources/messages_de.properties Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/resources/messages_de.properties Thu Sep 12 10:13:09 2013 +0200 @@ -48,7 +48,7 @@ state.minfo.dischargestate = Abflusszustand und Gerinne state.minfo.sq.location=Ort state.minfo.sq.period=Zeitraum -state.minfo.sq.outliers=Ausrei\u00dfer +state.minfo.sq.outliers=Toleranz state.minfo.sq.outlier-method=Ausrei\u00dfertest state.minfo.bed.year_epoch=Jahr/Epoche state.minfo.bed.difference_select=Differenzen @@ -142,7 +142,7 @@ floodplain.inactive = Inaktiv outlier.method.grubbs=Grubbs -outlier.method.std-dev=Standardabweichung +outlier.method.std-dev=Standardfehler der Residuen river = Fluss calculation_mode = Berechnungsart @@ -171,7 +171,7 @@ chart.computed.discharge.curve.subtitle = {0}-km: {1,number,#.###} chart.computed.discharge.curve.yaxis.label = W [{0}] chart.computed.discharge.curve.curve.label = Abflusskurve {0} km {1} -chart.computed.discharge.curve.gauge = Abflusskurve an Pegel {0} (km {1}) +chart.computed.discharge.curve.gauge = aktuelle AT {0} {1} - {2} chart.duration.curve.title = Dauerlinie chart.duration.curve.subtitle = {0}-km: {1,number,#.###} chart.duration.curve.xaxis.label = Unterschreitungsdauer [Tage] @@ -287,7 +287,7 @@ bedquality.toplayer = 0,0m - 0,3m bedquality.sublayer = 0,1m - 0,5m facet.bedheight.diff.year = Sohlh\u00f6hendifferenz {0} -facet.bedheight.diff.morph = gepeilte Breite {0} +facet.bedheight.diff.morph = gepeilte Breite facet.bedheight.diff.height1 = H\u00f6he Minuend {0} facet.bedheight.diff.height2 = H\u00f6he Subtrahend {0} facet.bedheight.diff.absolute = Sohlh\u00f6hendifferenz/Jahr {0} @@ -310,7 +310,7 @@ chart.beddifference.height.yaxis.label = Differenz [cm/Jahr] chart.beddifference.epoch.title = Sohlh\u00f6hendifferenz chart.beddifference.xaxis.label = {0}-km -chart.beddifference.yaxis.label.diff = Differenz [m] +chart.beddifference.yaxis.label.diff = Differenz [cm] chart.beddifference.yaxis.label.height = Absolute H\u00f6he [m] chart.beddifference.year.title = Sohlh\u00f6hendifferenz chart.beddifference.yaxis.label.morph = Breite [m] @@ -330,7 +330,7 @@ export.waterlevel.csv.meta.gauge = # Bezugspegel: {0} export.waterlevel.csv.meta.q = # Q (m\u00b3/s): {0} export.waterlevel.csv.meta.w = # W (NN + m): {0} - {1} -export.waterlevel.csv.not.in.gauge.range = au\u00dferhalb gew\u00e4hlter Bezugspegels +export.waterlevel.csv.not.in.gauge.range = au\u00dferh. d. Bez.pegels export.computed.discharge.curve.csv.header.w = W [{0}] export.computed.discharge.curve.csv.header.q = Q [m\u00b3/s] export.duration.curve.csv.header.duration = D [Tagen] @@ -384,6 +384,15 @@ export.bedheight_middle.csv.header.soundingwidth = Peilbreite [m] export.bedheight_middle.csv.header.width = morphologisch aktive Breite [m] export.bedheight_middle.csv.header.locations = Streckendaten +export.sedimentload_ls.csv.header.km = km +export.sedimentload_ls.csv.header.year = Jahr +export.sedimentload_ls.csv.header.coarse = Kies(g) +export.sedimentload_ls.csv.header.finemiddle = Kies(f+m) +export.sedimentload_ls.csv.header.sand = Sand +export.sedimentload_ls.csv.header.suspsand = susp.Sand +export.sedimentload_ls.csv.header.suspsandbb = susp.Sand(BB) +export.sedimentload_ls.csv.header.suspsediment = Schwebst. +export.sedimentload_ls.csv.header.total = Gesamt export.sqrelation.csv.header.parameter = Parameter export.sqrelation.csv.header.station = Station export.sqrelation.csv.header.km = Fluss-Km @@ -393,11 +402,12 @@ export.sqrelation.csv.header.coeff.b = b export.sqrelation.csv.header.coeff.q = Q export.sqrelation.csv.header.coeff.r = r^2 -export.sqrelation.csv.header.n.total = n gesamt +export.sqrelation.csv.header.n.total = n Gesamt export.sqrelation.csv.header.n.outliers = n Ausrei\u00dfer -export.sqrelation.csv.header.c.duan = C (DUAN) -export.sqrelation.csv.header.c.ferguson = C (FERGUSON) -export.sqrelation.csv.header.variance = Standardabweichung +export.sqrelation.csv.header.c.duan = C (Duan) +export.sqrelation.csv.header.c.ferguson = C (Ferguson) +export.sqrelation.csv.header.sd = Standardfehler +export.sqrelation.csv.header.qmax = Q max,gemessen export.sqrelation.pdf.file = /jasper/sqrelation.jasper export.sqrelation.pdf.mode = Transport-Abfluss Beziehung export.minfo.bedquality.km = km @@ -416,7 +426,7 @@ floodmap.wmsbackground = Hintergrundkarte floodmap.riveraxis = Flussachse -floodmap.uesk = \u00dcSG: {0}-km {1,number,####} - {2,number,####} +floodmap.uesk = \u00dcSG: {0}-km {1,number,####} - {2,number,####} - {3} floodmap.barriers = Digitalisierte Objekte floodmap.kms = Kilometrierung floodmap.qps = Querprofilspuren diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/resources/messages_de_DE.properties --- a/artifacts/src/main/resources/messages_de_DE.properties Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/resources/messages_de_DE.properties Thu Sep 12 10:13:09 2013 +0200 @@ -48,7 +48,7 @@ state.minfo.dischargestate = Abflusszustand und Gerinne state.minfo.sq.location=Ort state.minfo.sq.period=Zeitraum -state.minfo.sq.outliers=Ausrei\u00dfer +state.minfo.sq.outliers=Toleranz state.minfo.sq.outlier-method=Ausrei\u00dfertest state.minfo.bed.year_epoch=Jahr/Epoche state.minfo.bed.difference_select=Differenzen @@ -141,7 +141,7 @@ floodplain.inactive = Inaktiv outlier.method.grubbs=Grubbs -outlier.method.std-dev=Standardabweichung +outlier.method.std-dev=Standardfehler der Residuen river = Fluss calculation_mode = Berechnungsart @@ -170,7 +170,7 @@ chart.computed.discharge.curve.subtitle = {0}-km: {1,number,#.###} chart.computed.discharge.curve.yaxis.label = W [{0}] chart.computed.discharge.curve.curve.label = Abflusskurve {0} km {1} -chart.computed.discharge.curve.gauge = Abflusskurve an Pegel {0} (km {1}) +chart.computed.discharge.curve.gauge = aktuelle AT {0} {1} - {2} chart.duration.curve.title = Dauerlinie chart.duration.curve.subtitle = {0}-km: {1,number,#.###} chart.duration.curve.xaxis.label = Unterschreitungsdauer [Tage] @@ -286,7 +286,7 @@ bedquality.sublayer = 0,1m - 0,5m facet.bedheight.diff.year = Sohlh\u00f6hendifferenz {0} facet.bedheight.diff.year.raw = Sohlh\u00f6hendifferenz {0} (Rohdaten) -facet.bedheight.diff.morph = gepeilte Breite {0} +facet.bedheight.diff.morph = gepeilte Breite facet.bedheight.diff.height1 = H\u00f6he Minuend {0} facet.bedheight.diff.height2 = H\u00f6he Subtrahend {0} facet.bedheight.diff.absolute = Sohlh\u00f6hendifferenz/Jahr {0} @@ -308,7 +308,7 @@ chart.beddifference.height.yaxis.label = Differenz [cm/Jahr] chart.beddifference.epoch.title = Sohlh\u00f6hendifferenz chart.beddifference.xaxis.label = {0}-km -chart.beddifference.yaxis.label.diff = Differenz [m] +chart.beddifference.yaxis.label.diff = Differenz [cm] chart.beddifference.yaxis.label.height = Absolute H\u00f6he [{0}] chart.beddifference.year.title = Sohlh\u00f6hendifferenz chart.beddifference.yaxis.label.morph = Breite [m] @@ -328,7 +328,7 @@ export.waterlevel.csv.meta.gauge = # Bezugspegel: {0} export.waterlevel.csv.meta.q = # Q (m\u00b3/s): {0} export.waterlevel.csv.meta.w = # W (NN + m): {0} - {1} -export.waterlevel.csv.not.in.gauge.range = au\u00dferhalb gew\u00e4hlter Bezugspegels +export.waterlevel.csv.not.in.gauge.range = au\u00dferh. d. Bez.pegels export.computed.discharge.curve.csv.header.w = W [{0}] export.computed.discharge.curve.csv.header.q = Q [m\u00b3/s] export.duration.curve.csv.header.duration = D [Tagen] @@ -381,6 +381,15 @@ export.bedheight_middle.csv.header.soundingwidth = Peilbreite [m] export.bedheight_middle.csv.header.width = morphologisch aktive Breite [m] export.bedheight_middle.csv.header.locations = Streckendaten +export.sedimentload_ls.csv.header.km = km +export.sedimentload_ls.csv.header.year = Jahr +export.sedimentload_ls.csv.header.coarse = Kies(g) +export.sedimentload_ls.csv.header.finemiddle = Kies(f+m) +export.sedimentload_ls.csv.header.sand = Sand +export.sedimentload_ls.csv.header.suspsand = susp.Sand +export.sedimentload_ls.csv.header.suspsandbb = susp.Sand(BB) +export.sedimentload_ls.csv.header.suspsediment = Schwebst. +export.sedimentload_ls.csv.header.total = Gesamt export.sqrelation.csv.header.parameter = Parameter export.sqrelation.csv.header.station = Station export.sqrelation.csv.header.km = Fluss-Km @@ -390,11 +399,12 @@ export.sqrelation.csv.header.coeff.b = b export.sqrelation.csv.header.coeff.q = Q export.sqrelation.csv.header.coeff.r = r^2 -export.sqrelation.csv.header.n.total = n gesamt +export.sqrelation.csv.header.n.total = n Gesamt export.sqrelation.csv.header.n.outliers = n Ausrei\u00dfer -export.sqrelation.csv.header.c.duan = C (DUAN) -export.sqrelation.csv.header.c.ferguson = C (FERGUSON) -export.sqrelation.csv.header.variance = Standardabweichung +export.sqrelation.csv.header.c.duan = C (Duan) +export.sqrelation.csv.header.c.ferguson = C (Ferguson) +export.sqrelation.csv.header.sd = Standardfehler +export.sqrelation.csv.header.qmax = Q max,gemessen export.sqrelation.pdf.file = /jasper/sqrelation.jasper export.sqrelation.pdf.mode = Transport-Abfluss Beziehung export.minfo.bedquality.km = km @@ -413,7 +423,7 @@ floodmap.wmsbackground = Hintergrundkarte floodmap.riveraxis = Flussachse -floodmap.uesk = \u00dcSG: {0}-km {1,number,####} - {2,number,####} +floodmap.uesk = \u00dcSG: {0}-km {1,number,####} - {2,number,####} - {3} floodmap.barriers = Digitalisierte Objekte floodmap.kms = Kilometrierung floodmap.qps = Querprofilspuren diff -r 17398e239c77 -r e0311aa32efb artifacts/src/main/resources/messages_en.properties --- a/artifacts/src/main/resources/messages_en.properties Sat Jun 29 00:20:58 2013 +0200 +++ b/artifacts/src/main/resources/messages_en.properties Thu Sep 12 10:13:09 2013 +0200 @@ -48,7 +48,7 @@ state.minfo.dischargestate = Selection of discharge state and channel state.minfo.sq.location=Location state.minfo.sq.period=Periods -state.minfo.sq.outliers=Outliers +state.minfo.sq.outliers=Tolerance state.minfo.sq.outlier-method=Outliertest state.minfo.bed.year_epoch=Year/Epoch state.minfo.bed.difference_select=Differences @@ -141,7 +141,7 @@ floodplain.inactive = Inactiv outlier.method.grubbs=Grubbs -outlier.method.std-dev=Standard deviation +outlier.method.std-dev=Residual standard error river = River calculation_mode = Calculation Mode @@ -171,6 +171,7 @@ chart.computed.discharge.curve.subtitle = {0}-km: {1,number,#.###} chart.computed.discharge.curve.yaxis.label = W [{0}] chart.computed.discharge.curve.curve.label = Discharge Curve {0} km {1} +chart.computed.discharge.curve.gauge = current DC {0} {1} - {2} chart.duration.curve.title = Duration Curve chart.duration.curve.subtitle = {0}-km: {1,number,#.###} chart.duration.curve.xaxis.label = Duration of Non-Exceedence [Days] @@ -290,7 +291,7 @@ bedquality.toplayer = 0.0m - 0.3m bedquality.sublayer = 0.1m - 0.5m facet.bedheight.diff.year = Bedheight Difference {0} -facet.bedheight.diff.morph = sounding Width {0} +facet.bedheight.diff.morph = sounding Width facet.bedheight.diff.height1 = Original Height Minuend {0} facet.bedheight.diff.height2 = Original Height Subtrahend {0} facet.bedheight.diff.absolute = Bedheight Difference/Year {0} @@ -313,7 +314,7 @@ chart.beddifference.height.yaxis.label = Difference [cm/year] chart.beddifference.epoch.title = Bedheight Difference chart.beddifference.xaxis.label = {0}-km -chart.beddifference.yaxis.label.diff = Difference [m] +chart.beddifference.yaxis.label.diff = Difference [cm] chart.beddifference.yaxis.label.height = Absolute Height [m] chart.beddifference.year.title = Bedheight Difference chart.beddifference.yaxis.label.morph = Width [m] @@ -386,6 +387,15 @@ export.bedheight_middle.csv.header.soundingwidth = Sounding Width [m] export.bedheight_middle.csv.header.width = morphological active width [m] export.bedheight_middle.csv.header.locations = Location +export.sedimentload_ls.csv.header.km = km +export.sedimentload_ls.csv.header.year = year +export.sedimentload_ls.csv.header.coarse = coarse +export.sedimentload_ls.csv.header.finemiddle = finemiddle +export.sedimentload_ls.csv.header.sand = sand +export.sedimentload_ls.csv.header.suspsandbb = susp. sand (BB) +export.sedimentload_ls.csv.header.suspsand = susp. sand +export.sedimentload_ls.csv.header.suspsediment = susp. sediment +export.sedimentload_ls.csv.header.total = total export.sqrelation.csv.header.parameter = Parameter export.sqrelation.csv.header.station = Station export.sqrelation.csv.header.km = River-Km @@ -397,9 +407,10 @@ export.sqrelation.csv.header.coeff.r = r^2 export.sqrelation.csv.header.n.total = n total export.sqrelation.csv.header.n.outliers = n outliers -export.sqrelation.csv.header.c.duan = C (DUAN) -export.sqrelation.csv.header.c.ferguson = C (FERGUSON) -export.sqrelation.csv.header.variance = Standard variance +export.sqrelation.csv.header.c.duan = C (Duan) +export.sqrelation.csv.header.c.ferguson = C (Ferguson) +export.sqrelation.csv.header.sd = Standard error +export.sqrelation.csv.header.qmax = Q max,measured export.sqrelation.pdf.file = /jasper/sqrelation_en.jasper export.sqrelation.pdf.mode = Load Discharge Relation export.minfo.bedquality.km = km @@ -418,7 +429,7 @@ floodmap.wmsbackground = Background Map floodmap.riveraxis = River Axis -floodmap.uesk = Floodmap: {0}-km {1,number,####} - {2,number,####} +floodmap.uesk = Floodmap: {0}-km {1,number,####} - {2,number,####} - {3} floodmap.barriers = Digitized Objects floodmap.kms = Kilometrage floodmap.qps = Crosssection Tracks diff -r 17398e239c77 -r e0311aa32efb backend/doc/schema/oracle-minfo.sql --- a/backend/doc/schema/oracle-minfo.sql Sat Jun 29 00:20:58 2013 +0200 +++ b/backend/doc/schema/oracle-minfo.sql Thu Sep 12 10:13:09 2013 +0200 @@ -260,6 +260,7 @@ unit_id NUMBER(38,0) NOT NULL, time_interval_id NUMBER(38,0) NOT NULL, description VARCHAR(256), + kind NUMBER(38,0), PRIMARY KEY (id), CONSTRAINT fk_sy_river_id FOREIGN KEY (river_id) REFERENCES rivers(id) ON DELETE CASCADE, CONSTRAINT fk_sy_grain_fraction_id FOREIGN KEY (grain_fraction_id) REFERENCES grain_fraction(id), diff -r 17398e239c77 -r e0311aa32efb backend/doc/schema/postgresql-minfo.sql --- a/backend/doc/schema/postgresql-minfo.sql Sat Jun 29 00:20:58 2013 +0200 +++ b/backend/doc/schema/postgresql-minfo.sql Thu Sep 12 10:13:09 2013 +0200 @@ -260,6 +260,7 @@ unit_id int NOT NULL, time_interval_id int NOT NULL, description VARCHAR(256), + kind int, PRIMARY KEY (id), CONSTRAINT fk_sy_river_id FOREIGN KEY (river_id) REFERENCES rivers(id) ON DELETE CASCADE, CONSTRAINT fk_sy_grain_fraction_id FOREIGN KEY (grain_fraction_id) REFERENCES grain_fraction(id), diff -r 17398e239c77 -r e0311aa32efb backend/src/main/java/org/dive4elements/river/importer/ImportRiver.java --- a/backend/src/main/java/org/dive4elements/river/importer/ImportRiver.java Sat Jun 29 00:20:58 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/ImportRiver.java Thu Sep 12 10:13:09 2013 +0200 @@ -109,6 +109,8 @@ public static final String SEDIMENT_YIELD_EPOCH_DIR = "Epochen"; + public static final String SEDIMENT_YIELD_OFF_EPOCH_DIR = "amtliche Epochen"; + public static final String MINFO_FIXATIONS_DIR = "Fixierungsanalyse"; public static final String MINFO_WATERLEVELS_DIR = "Wasserspiegellagen"; @@ -502,6 +504,22 @@ } + private void parseSedimentYieldDir( + File[] files, + SedimentYieldParser parser + ) throws IOException { + for (File file: files) { + if (file.isDirectory()) { + for (File child: file.listFiles()) { + parser.parse(child); + } + } + else { + parser.parse(file); + } + } + } + protected void parseSedimentYield() throws IOException { if (Config.INSTANCE.skipSedimentYield()) { log.info("skip parsing sediment yield data"); @@ -513,11 +531,13 @@ File minfoDir = getMinfoDir(); File sedimentYieldDir = new File(minfoDir, SEDIMENT_YIELD_DIR); - File singleDir = new File(sedimentYieldDir, SEDIMENT_YIELD_SINGLE_DIR); - File epochDir = new File(sedimentYieldDir, SEDIMENT_YIELD_EPOCH_DIR); + File singleDir = new File(sedimentYieldDir, SEDIMENT_YIELD_SINGLE_DIR); + File epochDir = new File(sedimentYieldDir, SEDIMENT_YIELD_EPOCH_DIR); + File offEpochDir = new File(sedimentYieldDir, SEDIMENT_YIELD_OFF_EPOCH_DIR); - File[] singles = singleDir.listFiles(); - File[] epochs = epochDir.listFiles(); + File[] singles = singleDir.listFiles(); + File[] epochs = epochDir.listFiles(); + File[] offEpochs = offEpochDir.listFiles(); SedimentYieldParser parser = new SedimentYieldParser(); @@ -525,32 +545,21 @@ log.warn("Cannot read directory '" + singleDir + "'"); } else { - for (File file: singles) { - if (file.isDirectory()) { - for (File child: file.listFiles()) { - parser.parse(child); - } - } - else { - parser.parse(file); - } - } + parseSedimentYieldDir(singles, parser); } if (epochs == null || epochs.length == 0) { log.warn("Cannot read directory '" + epochDir + "'"); } else { - for (File file: epochs) { - if (file.isDirectory()) { - for (File child: file.listFiles()) { - parser.parse(child); - } - } - else { - parser.parse(file); - } - } + parseSedimentYieldDir(epochs, parser); + } + + if (offEpochs == null || offEpochs.length == 0) { + log.warn("Cannot read directory '" + offEpochDir + "'"); + } + else { + parseSedimentYieldDir(offEpochs, parser); } sedimentYields = parser.getSedimentYields(); diff -r 17398e239c77 -r e0311aa32efb backend/src/main/java/org/dive4elements/river/importer/ImportSedimentYield.java --- a/backend/src/main/java/org/dive4elements/river/importer/ImportSedimentYield.java Sat Jun 29 00:20:58 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/ImportSedimentYield.java Thu Sep 12 10:13:09 2013 +0200 @@ -35,6 +35,8 @@ private String description; + private Integer kind; + private List values; private SedimentYield peer; @@ -56,6 +58,10 @@ this.grainFraction = grainFraction; } + public void setKind(Integer kind) { + this.kind = kind; + } + public void addValue(ImportSedimentYieldValue value) { this.values.add(value); } @@ -116,6 +122,7 @@ log.debug("create new SedimentYield"); peer = new SedimentYield(river, u, ti, gf, description); + peer.setKind(this.kind); session.save(peer); } else { diff -r 17398e239c77 -r e0311aa32efb backend/src/main/java/org/dive4elements/river/importer/parsers/SedimentYieldParser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/SedimentYieldParser.java Sat Jun 29 00:20:58 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/SedimentYieldParser.java Thu Sep 12 10:13:09 2013 +0200 @@ -29,6 +29,7 @@ import org.dive4elements.river.model.GrainFraction; +/** Parses Sediment Yield files. */ public class SedimentYieldParser extends LineParser { private static final Logger log = @@ -241,15 +242,27 @@ } + /** Initialize SedimentYields from columns, set the kind + * with respect to file location (offical epoch or not?) */ private void initializeSedimentYields() { // skip first column (Fluss-km) and last column (Hinweise) current = new ImportSedimentYield[columnNames.length-2]; + Integer kind; + + if (inputFile.getAbsolutePath().contains("amtliche Epochen")) { + kind = new Integer(1); + } + else { + kind = new Integer(0); + } + for (int i = 0, n = columnNames.length; i < n-2; i++) { current[i] = new ImportSedimentYield(this.description); current[i].setTimeInterval(getTimeInterval(columnNames[i+1])); current[i].setUnit(unit); current[i].setGrainFraction(grainFraction); + current[i].setKind(kind); } } diff -r 17398e239c77 -r e0311aa32efb backend/src/main/java/org/dive4elements/river/importer/parsers/WaterlevelDifferencesParser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/WaterlevelDifferencesParser.java Sat Jun 29 00:20:58 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/WaterlevelDifferencesParser.java Thu Sep 12 10:13:09 2013 +0200 @@ -199,9 +199,12 @@ } - /** Handle one line of data, add one value for all columns. */ + /** Handle one line of data, add one value for all columns. + * @param line the line to parse + */ private void handleDataLine(String line) { - String[] cols = line.split(SEPERATOR_CHAR); + // Split by separator, do not exclude trailing empty string. + String[] cols = line.split(SEPERATOR_CHAR, -1); if (cols == null || cols.length < 2) { log.warn("skip invalid waterlevel-diff line: '" + line + "'"); @@ -209,6 +212,8 @@ } try { + // The first value in a line like 12,9;4,3;4,5 is the station, later + // real values. Double station = nf.parse(cols[0]).doubleValue(); for (int i = 0; i < columns.length; i++) { @@ -221,13 +226,15 @@ String value = cols[idx]; - try { - columns[i].addColumnValue( - new BigDecimal(station), - new BigDecimal(nf.parse(value).doubleValue())); - } - catch (ParseException pe) { - log.warn("Could not parse value: '" + value + "'"); + if (value != null && !value.equals("")) { + try { + columns[i].addColumnValue( + new BigDecimal(station), + new BigDecimal(nf.parse(value).doubleValue())); + } + catch (ParseException pe) { + log.warn("Could not parse value: '" + value + "'"); + } } } } diff -r 17398e239c77 -r e0311aa32efb backend/src/main/java/org/dive4elements/river/importer/parsers/WstParser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/WstParser.java Sat Jun 29 00:20:58 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/WstParser.java Thu Sep 12 10:13:09 2013 +0200 @@ -85,6 +85,7 @@ this.wst = wst; } + /** Returns a new ImportTimeInterval with a date guessed from string. */ public static ImportTimeInterval guessDate(String string) { try { Matcher m = YEAR_INTERVAL.matcher(string); diff -r 17398e239c77 -r e0311aa32efb backend/src/main/java/org/dive4elements/river/model/CrossSection.java --- a/backend/src/main/java/org/dive4elements/river/model/CrossSection.java Sat Jun 29 00:20:58 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/model/CrossSection.java Thu Sep 12 10:13:09 2013 +0200 @@ -38,11 +38,16 @@ import org.dive4elements.river.backend.SessionHolder; +import org.apache.log4j.Logger; + @Entity @Table(name = "cross_sections") public class CrossSection implements Serializable { + private static Logger logger = + Logger.getLogger(CrossSection.class); + public static final MathContext PRECISION = new MathContext(6); public static final String SQL_FAST_CROSS_SECTION_LINES = @@ -53,6 +58,20 @@ "km between :from_km AND :to_km " + "ORDER BY csl.km, csl.id, csp.col_pos"; + public static final String SQL_MIN_MAX = + "SELECT * FROM ( "+ + "SELECT cross_section_id, MIN(km) AS minkm, MAX(km) AS maxkm " + + "FROM cross_section_lines " + + "WHERE cross_section_id IN " + + " (SELECT id FROM cross_sections WHERE river_id = :river_id) " + + " GROUP BY cross_section_id" + + ") cs_ranges " + + "JOIN cross_sections cs ON cs_ranges.cross_section_id = cs.id " + + "LEFT OUTER JOIN time_intervals ON cs.time_interval_id = time_intervals.id " + + "WHERE :km BETWEEN minkm AND maxkm " + + "ORDER BY stop_time desc, start_time asc, :km - minkm"; + // Order by time interval missing. + private Integer id; private River river; private TimeInterval timeInterval; @@ -203,5 +222,39 @@ return lines; } + + /** + * True if the given section is the "newest" for that river and has values at km. + * @param km Given station. + * @return true if the section has the most advanced end of its validity interval + * or the most advanced start of its validity interval. + */ + public boolean shouldBeMaster(double km) { + Session session = SessionHolder.HOLDER.get(); + + SQLQuery sqlQuery = session.createSQLQuery(SQL_MIN_MAX) + .addScalar("cross_section_id", StandardBasicTypes.INTEGER); + + sqlQuery + .setInteger("river_id", getRiver().getId()) + .setDouble("km", km); + + List results = sqlQuery.list(); + + if (results.size() >= 1) { + Integer result = results.get(0); + if (result == getId()) { + return true; + } + } + else { + logger.warn("No CS found that could be master."); + } + + // TODO If there is none, might need a fallback. + // Formerly this was the most current CS (issue1157). + + return false; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb backend/src/main/java/org/dive4elements/river/model/DischargeTable.java --- a/backend/src/main/java/org/dive4elements/river/model/DischargeTable.java Sat Jun 29 00:20:58 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/model/DischargeTable.java Thu Sep 12 10:13:09 2013 +0200 @@ -24,6 +24,10 @@ import javax.persistence.SequenceGenerator; import javax.persistence.Table; +import org.hibernate.Session; +import org.hibernate.Query; +import org.dive4elements.river.backend.SessionHolder; + @Entity @Table(name = "discharge_tables") public class DischargeTable @@ -197,5 +201,16 @@ return 0; } } + + public static DischargeTable getDischargeTableById(int dtId) + { + Session session = SessionHolder.HOLDER.get(); + Query query = session.createQuery( + "from DischargeTable where id =:dtId"); + query.setParameter("dtId", dtId); + + List list = query.list(); + return list.isEmpty() ? null : list.get(0); + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb backend/src/main/java/org/dive4elements/river/model/Gauge.java --- a/backend/src/main/java/org/dive4elements/river/model/Gauge.java Sat Jun 29 00:20:58 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/model/Gauge.java Thu Sep 12 10:13:09 2013 +0200 @@ -223,7 +223,6 @@ this.mainValues = mainValues; } - public static Gauge getGaugeByOfficialNumber(long number) { Session session = SessionHolder.HOLDER.get(); @@ -237,6 +236,21 @@ return results.isEmpty() ? null : results.get(0); } + public static Gauge getGaugeByOfficialNumber(long number, String river_name) { + Session session = SessionHolder.HOLDER.get(); + + Query query = session.createQuery( + "from Gauge as gau " + + "where gau.officialNumber=:number and gau.river.name=:river_name"); + + query.setParameter("number", number); + query.setParameter("river_name", river_name); + + List results = query.list(); + + return results.isEmpty() ? null : results.get(0); + } + public DischargeTable fetchMasterDischargeTable() { for (DischargeTable dt: dischargeTables) { diff -r 17398e239c77 -r e0311aa32efb backend/src/main/java/org/dive4elements/river/model/MeasurementStation.java --- a/backend/src/main/java/org/dive4elements/river/model/MeasurementStation.java Sat Jun 29 00:20:58 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/model/MeasurementStation.java Thu Sep 12 10:13:09 2013 +0200 @@ -8,6 +8,8 @@ package org.dive4elements.river.model; +import java.util.List; + import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -18,6 +20,10 @@ import javax.persistence.SequenceGenerator; import javax.persistence.Table; +import org.hibernate.Session; +import org.hibernate.Query; + +import org.dive4elements.river.backend.SessionHolder; @Entity @Table(name = "measurement_station") @@ -176,4 +182,17 @@ public void setDescription(String description) { this.description = description; } + + public static List getStationsAtKM(String river, Double river_km) + { + Session session = SessionHolder.HOLDER.get(); + + Query query = session.createQuery( + "from MeasurementStation as ms " + + "where ms.river.name = :river_name and ms.station = :river_km"); + query.setParameter("river_name", river); + query.setParameter("river_km", river_km); + + return query.list(); + } } diff -r 17398e239c77 -r e0311aa32efb backend/src/main/java/org/dive4elements/river/model/SedimentYield.java --- a/backend/src/main/java/org/dive4elements/river/model/SedimentYield.java Sat Jun 29 00:20:58 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/model/SedimentYield.java Thu Sep 12 10:13:09 2013 +0200 @@ -25,6 +25,7 @@ import org.apache.log4j.Logger; +/** SedimentYield of a certain Fraction with possibly many values. */ @Entity @Table(name = "sediment_yield") public class SedimentYield @@ -46,6 +47,8 @@ private List values; + private Integer kind; + public SedimentYield() { this.values = new ArrayList(); @@ -149,5 +152,15 @@ public void setDescription(String description) { this.description = description; } + + /** kind == 0: "normal", kind == 1: "official epoch". */ + @Column(name = "kind") + public Integer getKind() { + return kind; + } + + public void setKind(Integer newKind) { + this.kind = newKind; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb backend/src/main/java/org/dive4elements/river/model/Wst.java --- a/backend/src/main/java/org/dive4elements/river/model/Wst.java Sat Jun 29 00:20:58 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/model/Wst.java Thu Sep 12 10:13:09 2013 +0200 @@ -33,6 +33,7 @@ import org.dive4elements.river.backend.SessionHolder; +/** DB-mapped WST. */ @Entity @Table(name = "wsts") public class Wst diff -r 17398e239c77 -r e0311aa32efb backend/src/main/java/org/dive4elements/river/utils/EpsilonComparator.java --- a/backend/src/main/java/org/dive4elements/river/utils/EpsilonComparator.java Sat Jun 29 00:20:58 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/utils/EpsilonComparator.java Thu Sep 12 10:13:09 2013 +0200 @@ -9,9 +9,10 @@ package org.dive4elements.river.utils; import java.util.Comparator; +import java.io.Serializable; /** Comparator with some tolerance (epsilon). */ -public class EpsilonComparator implements Comparator +public class EpsilonComparator implements Comparator, Serializable { public static final double EPSILON = 1e-4; diff -r 17398e239c77 -r e0311aa32efb contrib/make_flys_release/issue_overview.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contrib/make_flys_release/issue_overview.sh Thu Sep 12 10:13:09 2013 +0200 @@ -0,0 +1,31 @@ +#!/bin/sh + +# Use this on an exported query from roundup +# Known issue: Tiles with more then three , in them fail. +# Yes (ah) I do not know how to correctly handle the csv quoting... + +echo "-------------" +echo "Unter anderem wurden folgende issues bearbeitet und können getestet werden:" + +sed 's/"\(.*\),\(.*\)"/"\1§\2"/g' "$1" | \ +sed 's/"\(.*\),\(.*\)"/"\1§\2"/g' | \ +sed 's/"\(.*\),\(.*\)"/\1§\2/g' | \ +gawk -F, '$5 > 5 { +print "- flys/issue"$2 " ("$1")" +print "[https://roundup-intern.intevation.de/flys/issue"$2"]" +print "" +}' | sed 's/§/,/g' + + +echo "-------------" +echo "Desweiteren gab es fortschritte in folgenden Issues:" +echo "" +sed 's/"\(.*\),\(.*\)"/"\1§\2"/g' "$1" | \ +sed 's/"\(.*\),\(.*\)"/"\1§\2"/g' | \ +sed 's/"\(.*\),\(.*\)"/\1§\2/g' | \ +gawk -F, '$5 <= 5 && $5 > 0 { +print "- flys/issue"$2 " ("$1")" +print "[https://roundup-intern.intevation.de/flys/issue"$2"]" +print "" +}' | sed 's/§/,/g' + diff -r 17398e239c77 -r e0311aa32efb contrib/make_flys_release/make_release.sh --- a/contrib/make_flys_release/make_release.sh Sat Jun 29 00:20:58 2013 +0200 +++ b/contrib/make_flys_release/make_release.sh Thu Sep 12 10:13:09 2013 +0200 @@ -367,6 +367,11 @@ mv $WORK_DIR/datacagedb $WORK_DIR/server/ echo "INFO: create tarball" +if [ -d "$WORK_DIR/flys-$VERSION" ]; then + echo "INFO: removing old directory" + rm -rf "$WORK_DIR/flys-$VERSION" +fi + mkdir $WORK_DIR/flys-$VERSION mv $WORK_DIR/server $WORK_DIR/client $WORK_DIR/flys-$VERSION cd $WORK_DIR diff -r 17398e239c77 -r e0311aa32efb etl/src/main/java/org/dive4elements/river/etl/aft/River.java --- a/etl/src/main/java/org/dive4elements/river/etl/aft/River.java Sat Jun 29 00:20:58 2013 +0200 +++ b/etl/src/main/java/org/dive4elements/river/etl/aft/River.java Thu Sep 12 10:13:09 2013 +0200 @@ -15,9 +15,11 @@ import java.sql.SQLException; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.TreeMap; import org.apache.log4j.Logger; @@ -136,11 +138,25 @@ .clearParameters() .setInt("river_id", id1).executeQuery(); + TreeMap station2gaugeName = new TreeMap( + new Comparator() { + @Override + public int compare(Double a, Double b) { + double diff = a - b; + if (diff < -0.0001) return -1; + if (diff > 0.0001) return +1; + return 0; + } + }); + try { while (gaugesRs.next()) { int gaugeId = gaugesRs.getInt("id"); String name = gaugesRs.getString("name"); long number = gaugesRs.getLong("official_number"); + double station = gaugesRs.getDouble("station"); + station2gaugeName.put(station, name); + if (gaugesRs.wasNull()) { log.warn("FLYS: Gauge '" + name + "' has no official number. Ignored."); @@ -163,7 +179,8 @@ gaugesRs.close(); } - boolean modified = createGauges(context, aftDIPSGauges); + boolean modified = createGauges( + context, aftDIPSGauges, station2gaugeName); modified |= updateGauges(context, updateGauges); @@ -364,7 +381,8 @@ protected boolean createGauges( SyncContext context, - Map gauges + Map gauges, + Map station2gaugeName ) throws SQLException { @@ -385,6 +403,14 @@ log.info("Gauge '" + gauge.getAftName() + "' not in FLYS but in AFT/DIPS. -> Create"); + String flysGaugeName = station2gaugeName.get(gauge.getStation()); + if (flysGaugeName != null) { + log.warn("FLYS: AFT gauge " + gauge.getName() + + " has same station as FLYS gauge " + flysGaugeName + + " -> ignored."); + continue; + } + if (!gauge.hasDatums()) { log.warn("DIPS: Gauge '" + gauge.getAftName() + "' has no datum. Ignored."); diff -r 17398e239c77 -r e0311aa32efb etl/src/main/java/org/dive4elements/river/etl/aft/Rivers.java --- a/etl/src/main/java/org/dive4elements/river/etl/aft/Rivers.java Sat Jun 29 00:20:58 2013 +0200 +++ b/etl/src/main/java/org/dive4elements/river/etl/aft/Rivers.java Thu Sep 12 10:13:09 2013 +0200 @@ -14,9 +14,7 @@ import java.sql.SQLException; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.apache.log4j.Logger; @@ -27,6 +25,24 @@ public Rivers() { } + private static List findFLYSRivers( + List flysRivers, + String needle + ) { + List rivers = new ArrayList(); + + needle = needle.toLowerCase(); + + for (River river: rivers) { + String name = river.getName().toLowerCase(); + if (name.contains(needle)) { + rivers.add(river); + } + } + + return rivers; + } + public boolean sync(SyncContext context) throws SQLException { log.info("sync: rivers"); @@ -34,7 +50,7 @@ ConnectedStatements flysStatements = context.getFlysStatements(); ConnectedStatements aftStatements = context.getAftStatements(); - Map flysRivers = new HashMap(); + List flysRivers = new ArrayList(); ResultSet flysRs = flysStatements .getStatement("select.rivers").executeQuery(); @@ -45,7 +61,7 @@ String name = flysRs.getString("name"); double from = flysRs.getDouble("min_km"); double to = flysRs.getDouble("max_km"); - flysRivers.put(name.toLowerCase(), new River(id, name, from, to)); + flysRivers.add(new River(id, name, from, to)); } } finally { @@ -60,9 +76,8 @@ try { while (aftRs.next()) { String name = aftRs.getString("NAME"); - River river = flysRivers.get(name.toLowerCase()); - if (river != null) { - int id2 = aftRs.getInt("GEWAESSER_NR"); + int id2 = aftRs.getInt("GEWAESSER_NR"); + for (River river: findFLYSRivers(flysRivers, name)) { river.setId2(id2); commonRivers.add(river); } @@ -72,7 +87,6 @@ aftRs.close(); } - boolean modified = false; for (River river: commonRivers) { diff -r 17398e239c77 -r e0311aa32efb etl/src/main/resources/sql/flys-common.properties --- a/etl/src/main/resources/sql/flys-common.properties Sat Jun 29 00:20:58 2013 +0200 +++ b/etl/src/main/resources/sql/flys-common.properties Thu Sep 12 10:13:09 2013 +0200 @@ -7,7 +7,7 @@ WHERE w.kind = 0 \ GROUP BY r.id, r.name select.gauges = \ - SELECT id, name, official_number \ + SELECT id, name, official_number, station \ FROM gauges \ WHERE river_id = :river_id next.gauge.id = \ diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java Thu Sep 12 10:13:09 2013 +0200 @@ -822,6 +822,12 @@ String waterlevels(); + String beddifferences(); + + String bedheight_differences(); + + String vollmer_waterlevels(); + String old_calculations(); String officiallines(); @@ -1303,5 +1309,9 @@ String FEDSTATE_KM(); String official_regulation(); + + String historical_discharge_curves(); + + String current_gauge(); } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties Thu Sep 12 10:13:09 2013 +0200 @@ -220,6 +220,7 @@ computed_discharge_curves = Discharge Curves longitudinal_section = Longitudinal Section Curve duration_curve = Duration Curve +historical_discharge_curves = Historical Discharge Curve discharge_longitudinal_section = Discharge Longitudinal Section floodmap = Floodmap historical_discharge = Time-Chart @@ -277,6 +278,7 @@ pdf = PDF computed_dischargecurve_at_export = Discharge Curve Export gauge_discharge_curve_at_export = Gauge Discharge Curve +current_gauge = Current Gauge Discharge Curve gauge_class = Gauge Class eventselect = Eventselection events = Events @@ -367,7 +369,7 @@ error_gc_doc_not_valid = Capabilities document is not valid. error_malformed_url = The URL you have entered is not valid. error_no_dgm_selected = No DEM selected. -error_invalid_dgm_selected = You have selected an invalid DEM. +error_invalid_dgm_selected = An error occured while selecting the DEM. error_bad_dgm_range = You have selected a DEM with an invalid range. error_bad_dgm_river = You have selected a DEM for a wrong river. error_dialog_not_valid = One or more values are not valid. @@ -422,6 +424,9 @@ # data cage waterlevels = Waterlevels +beddifferences = Bedheight Differences +bedheight_differences = Bedheight Differences +vollmer_waterlevels = Vollmer Waterlevels old_calculations = Former Calculations officiallines = Official lines datacageAdd = Add data diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties Thu Sep 12 10:13:09 2013 +0200 @@ -216,8 +216,10 @@ discharge_curve = Abflusskurve am Pegel discharge_curve_gaugeless = Abflusskurve gauge_discharge_curve = Abflusstafel am Pegel +current_gauge = aktuelle Abflusstafel am Pegel computed_discharge_curve = Abflusskurve computed_discharge_curves = Abflusskurven +historical_discharge_curves = Historische Abflusskurven longitudinal_section = L\u00e4ngsschnitt duration_curve = Dauerlinie discharge_longitudinal_section = W f\u00fcr benutzerdefinierten Abflussl\u00e4ngsschnitt @@ -367,7 +369,7 @@ error_gc_doc_not_valid = Das Capabilities Dokument ist nicht valide. error_malformed_url = Die eingegebene URL ist ung\u00fcltig. error_no_dgm_selected = Sie haben kein DGM gew\u00e4hlt. -error_invalid_dgm_selected = Sie haben ein falsches DGM gew\u00e4hlt. +error_invalid_dgm_selected = Bei der Auswahl des DGMs ist ein Fehler aufgetreten. error_bad_dgm_range = Das gew\u00e4hlte DGM passt nicht zur gew\u00e4hlten Berechnungsstrecke. error_bad_dgm_river = Das gew\u00e4hlte DGM passt nicht zum gew\u00e4hlten Fluss. error_dialog_not_valid = Eine oder mehrere Daten sind nicht korrekt. @@ -426,6 +428,9 @@ # data cage waterlevels = Wasserst\u00e4nde +beddifferences = Sohlh\u00f6hendifferenzen +bedheight_differences = Sohlh\u00f6hendifferenzen +vollmer_waterlevels = Ausgelagerte WSPL. old_calculations = Fr\u00fchere Berechnungen officiallines = Amtliche Linien datacageAdd = Daten laden diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties Thu Sep 12 10:13:09 2013 +0200 @@ -213,6 +213,7 @@ static_sqrelation = SQ relation discharge_curve = Discharge Curve at Gauge discharge_curve_gaugeless = Discharge Curve +current_gauge = Current Gauge Discharge Curve gauge_discharge_curve = Discharge Table at Gauge computed_discharge_curve = Discharge Curve computed_discharge_curves = Discharge Curves @@ -221,6 +222,7 @@ discharge_longitudinal_section = Discharge Longitudinal Section floodmap = Floodmap historical_discharge = Time Chart +historical_discharge_curves = Historical Discharge Curve historical_discharge_wq = W/Q Chart flow_velocity = Flow Velocity flow_velocity_export = Flow Velocity Export @@ -365,7 +367,7 @@ error_gc_doc_not_valid = Capabilities document is not valid. error_malformed_url = The URL you have entered is not valid. error_no_dgm_selected = No DEM selected. -error_invalid_dgm_selected = You have selected an invalid DEM. +error_invalid_dgm_selected = An error occured while selecting the DEM. error_bad_dgm_range = You have selected a DEM with an invalid range. error_bad_dgm_river = You have selected a DEM for a wrong river. error_dialog_not_valid = One or more values are not valid. @@ -424,6 +426,9 @@ # data cage waterlevels = Waterlevels +beddifferences = Bedheight Differences +bedheight_differences = Bedheight Differences +vollmer_waterlevels = Vollmer Waterlevels old_calculations = Former Calculations officiallines = Official lines datacageAdd = Add data diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoService.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoService.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoService.java Thu Sep 12 10:13:09 2013 +0200 @@ -28,7 +28,8 @@ */ DischargeInfoObject[] getDischargeInfo( String locale, - long gauge) + long gauge, + String river) throws ServerException; } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoServiceAsync.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoServiceAsync.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/services/DischargeInfoServiceAsync.java Thu Sep 12 10:13:09 2013 +0200 @@ -21,6 +21,7 @@ void getDischargeInfo( String locale, long gauge, + String river, AsyncCallback cb); } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/CollectionView.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/CollectionView.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/CollectionView.java Thu Sep 12 10:13:09 2013 +0200 @@ -393,7 +393,8 @@ } /** - * Loads all information of a collection + * Loads all information of a collection. + * If 'recommendations' present, load these. * @param c the Collection */ private void loadCollection(Collection c) { @@ -641,7 +642,7 @@ ); } else { - // Create new collection and add artifact + // Create new collection and add artifact. final Artifact art = artifact; createCollectionService.create( locale, diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DatacageTwinPanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DatacageTwinPanel.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/DatacageTwinPanel.java Thu Sep 12 10:13:09 2013 +0200 @@ -175,7 +175,7 @@ VLayout layout = new VLayout(); HLayout helperLayout = new HLayout(); helperLayout.addMember(new DatacagePairWidget(this.artifact, - user, "waterlevels", differencesList)); + user, "differenceable", differencesList)); layout.addMember(widget); layout.addMember(submit); @@ -277,6 +277,29 @@ this.removedPairs.add(pr); } + /** + * Set factory of recommendation such that the correct artifacts will + * be cloned for difference calculations. + */ + public void adjustRecommendation(Recommendation recommendation) { + if (recommendation.getIDs() != null) { + GWT.log("Setting staticwkms factory for rec with ID " + + recommendation.getIDs()); + recommendation.setFactory("staticwkms"); + } + /* + // So far, we do not need to rewrite the factory anymore, + // except for staticwkms; probably other cases will pop up later. + else if (recommendation.getFactory().equals("winfo")) { + GWT.log("Setting waterlevel factory for a winfo rec."); + recommendation.setFactory("waterlevel"); + } + */ + else { + GWT.log("Leave rec. id " + recommendation.getIDs() + ", factory " + + recommendation.getFactory() + " untouched."); + } + } /** * Validates data, does nothing if invalid, otherwise clones new selected @@ -308,29 +331,10 @@ // Check whether one of those is a dike or similar. // TODO differentiate and merge: new clones, new, old. Recommendation firstR = r.getFirst(); - if(firstR.getIDs() != null) { - GWT.log("First IDs: " + firstR.getIDs() + " factory: " - + firstR.getFactory()); - } - if(firstR.getIDs() != null) { - // These do not get cloned but loaded ("spawned"). - firstR.setFactory("staticwkms"); - } - else { - firstR.setFactory("waterlevel"); - } + adjustRecommendation(firstR); + Recommendation secondR = r.getSecond(); - if(secondR.getIDs() != null) { - GWT.log("Second IDs: " + secondR.getIDs() + " factory: " - + secondR.getFactory()); - } - if (secondR.getIDs() != null) { - // These do not get cloned but loaded ("spawned"). - secondR.setFactory("staticwkms"); - } - else { - secondR.setFactory("waterlevel"); - } + adjustRecommendation(secondR); ar.add(firstR); ar.add(secondR); @@ -389,6 +393,7 @@ } // Clone new ones (and spawn statics), go forward. + parameterList.lockUI(); loadArtifactService.loadMany( this.collection, toClone, @@ -399,6 +404,7 @@ @Override public void onFailure(Throwable caught) { GWT.log("Failure of cloning with factories!"); + parameterList.unlockUI(); } @Override public void onSuccess(Artifact[] artifacts) { @@ -407,6 +413,7 @@ fireStepForwardEvent(new StepForwardEvent( getData(toClone, artifacts, toUse))); + parameterList.unlockUI(); } }); } diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/FLYSHeader.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/FLYSHeader.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/FLYSHeader.java Thu Sep 12 10:13:09 2013 +0200 @@ -12,6 +12,7 @@ import com.google.gwt.i18n.client.LocaleInfo; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.HTML; import com.smartgwt.client.types.Alignment; import com.smartgwt.client.types.VerticalAlignment; import com.smartgwt.client.util.BooleanCallback; @@ -135,14 +136,30 @@ info.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - GWT.log("Clicked 'info' button."); String wikiLink = Config.getInstance().getWikiUrl() + "/Info"; - Window.open(wikiLink, "_blank", null); + + // Create a form which contains the SAML session + // for the user which is currently logged in + String html = WikiLinks.imageLinkForm( + getFlys(), wikiLink, "", "wikiLinkForm"); + HTML htmlObj = new HTML(html); + info.addChild(htmlObj); + fireWikiLinkSubmit(); + htmlObj.removeFromParent(); } }); init(); } + /** + * Calls the JS submit() function on the dynamically added + * wikiLinkForm. This is a workaround for a SmartGWT issue(?) that + * clears all form fields when using DynamicForm.submit() or .submitForm(). + */ + protected native void fireWikiLinkSubmit() /*-{ + $doc.wikiLinkForm.submit(); + }-*/; + public void init() { setStyleName("header"); setWidth100(); diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/GaugeTimeRangePanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/GaugeTimeRangePanel.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/GaugeTimeRangePanel.java Thu Sep 12 10:13:09 2013 +0200 @@ -105,7 +105,8 @@ Config config = Config.getInstance(); String url = config.getServerUrl(); - yearTable.setDataSource(new DischargeInfoDataSource(url, gauge)); + String river = artifact.getArtifactDescription().getRiver(); + yearTable.setDataSource(new DischargeInfoDataSource(url, gauge, river)); helperContainer.addMember(createHelperPanel()); diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ImgLink.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ImgLink.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ImgLink.java Thu Sep 12 10:13:09 2013 +0200 @@ -12,6 +12,7 @@ import com.smartgwt.client.widgets.HTMLPane; +/** An image wrapped in a clickable link. */ public class ImgLink extends HTMLPane { protected int width; @@ -59,3 +60,4 @@ update(); } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/MultiPeriodPanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/MultiPeriodPanel.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/MultiPeriodPanel.java Thu Sep 12 10:13:09 2013 +0200 @@ -36,7 +36,7 @@ import java.util.List; /** - * This UIProvider creates a panel for location or distance input. + * This UIProvider creates a panel for input of multiple time periods. * * @author Raimund Renkert */ diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ParameterList.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ParameterList.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/ParameterList.java Thu Sep 12 10:13:09 2013 +0200 @@ -83,7 +83,7 @@ public static final String STYLENAME_OLD_PARAMETERS = "oldParameters"; - /** The message class that provides i18n strings.*/ + /** The message class that provides i18n strings. */ protected FLYSConstants MSG = GWT.create(FLYSConstants.class); /** The ArtifactService used to communicate with the Artifact server. */ @@ -103,7 +103,7 @@ GWT.create(ReportService.class); - /** The list of ParameterizationChangeHandler.*/ + /** The list of ParameterizationChangeHandler. */ protected List parameterHandlers; protected FLYS flys; @@ -568,7 +568,7 @@ /** - * This method refreshes the part displaying the data of the current state. + * Refreshes the part displaying the data of the current state. * The UI is created using the UIProvider stored in the Data object. */ public void refreshCurrent() { diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/QSegmentedInputPanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/QSegmentedInputPanel.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/QSegmentedInputPanel.java Thu Sep 12 10:13:09 2013 +0200 @@ -428,14 +428,14 @@ new AsyncCallback() { @Override public void onFailure(Throwable caught) { - GWT.log("Could not recieve wq informations."); + GWT.log("Could not receive wq informations."); SC.warn(caught.getMessage()); } @Override public void onSuccess(WQInfoObject[] wqi) { int num = wqi != null ? wqi.length :0; - GWT.log("Recieved " + num + " wq informations."); + GWT.log("Received " + num + " wq informations."); if (num == 0) { return; diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/RiverInfoPanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/RiverInfoPanel.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/RiverInfoPanel.java Thu Sep 12 10:13:09 2013 +0200 @@ -99,11 +99,9 @@ MSG.gauge_river_url() + number : MSG.gauge_river_url(); String wikiBaseUrl = Config.getInstance().getWikiUrl(); - DynamicForm infoLink = WikiLinks.linkHTML(this.flys, wikiBaseUrl + url, + DynamicForm infoLink = WikiLinks.linkDynamicForm(this.flys, wikiBaseUrl + url, MSG.gauge_river_info_link()); infoLink.setTop(5); - LinkItem item = (LinkItem)infoLink.getField("saml"); - item.setTextBoxStyle("font-size: large;"); add(infoLink); } diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WQAdaptedInputPanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WQAdaptedInputPanel.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WQAdaptedInputPanel.java Thu Sep 12 10:13:09 2013 +0200 @@ -140,6 +140,7 @@ } + /** Create labels, canvasses, layouts. */ @Override public Canvas create(DataList data) { readGaugeRanges(data); @@ -196,7 +197,7 @@ qdTables.add(qdTable); qdTable.showSelect(); - //wTable.showSelect(); + wTable.showSelect(); wTab.setPane(wTable); qTab.setPane(qdTable); @@ -267,6 +268,57 @@ qdTable.addCellClickHandler(handler); i++; } + + i = 0; + for (WTable wTable: wTables) { + // Register listener such that values are filled in on click. + final WTable table = wTable; + final int fi = i; + CellClickHandler handler = new CellClickHandler() { + @Override + public void onCellClick(CellClickEvent e) { + if (!isWMode() /*|| table.isLocked()*/) { + return; + } + + Record r = e.getRecord(); + double val = r.getAttributeAsDouble("value"); + + doubleArrayPanels.get(fi).setValues(new double[]{val}); + // If a named value for first gauge is chosen, try to find and set + // the values to the other panels too. + if (fi == 0) { + String valueName = r.getAttribute("name"); + int oi = 0; + // TODO instead of oi use random access. + for (WTable otherWTable: wTables) { + if (oi == 0) { + oi++; + continue; + } + Double value = otherWTable.findRecordValue(valueName); + if (value == null) { + // TODO: afterwards it freaks out + SC.warn(MSG.noMainValueAtGauge()); + } + else { + doubleArrayPanels.get(oi).setValues(new double[]{value}); + } + oi++; + } + } + else { + // Focus next. + if (fi != doubleArrayPanels.size()-1) { + doubleArrayPanels.get(fi+1).focusInItem(1); + } + } + } + }; + + wTable.addCellClickHandler(handler); + i++; + } } diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WQInputPanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WQInputPanel.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WQInputPanel.java Thu Sep 12 10:13:09 2013 +0200 @@ -1811,14 +1811,14 @@ new AsyncCallback() { @Override public void onFailure(Throwable caught) { - GWT.log("Could not recieve wq informations."); + GWT.log("Could not receive wq informations."); SC.warn(caught.getMessage()); } @Override public void onSuccess(WQInfoObject[] wqi) { int num = wqi != null ? wqi.length :0; - GWT.log("Recieved " + num + " wq informations."); + GWT.log("Received " + num + " wq informations."); if (num == 0) { return; diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WQSimpleArrayPanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WQSimpleArrayPanel.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WQSimpleArrayPanel.java Thu Sep 12 10:13:09 2013 +0200 @@ -265,13 +265,13 @@ new AsyncCallback() { @Override public void onFailure(Throwable caught) { - GWT.log("Could not recieve wq informations."); + GWT.log("Could not receive wq informations."); } @Override public void onSuccess(WQInfoObject[] wqi) { int num = wqi != null ? wqi.length :0; - GWT.log("Recieved " + num + " wq informations."); + GWT.log("Received " + num + " wq informations."); if (num == 0) { return; diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WikiImgLink.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WikiImgLink.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WikiImgLink.java Thu Sep 12 10:13:09 2013 +0200 @@ -24,7 +24,7 @@ @Override protected void update() { - setContents(WikiLinks.imageLinkHTML(instance, href, imgUrl)); + setContents(WikiLinks.imageLinkForm(instance, href, imgUrl, "wikiImgLink" + toString())); setWidth(width); setHeight(height); setOverflow(Overflow.VISIBLE); diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WikiLinks.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WikiLinks.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WikiLinks.java Thu Sep 12 10:13:09 2013 +0200 @@ -8,18 +8,21 @@ package org.dive4elements.river.client.client.ui; +import com.google.gwt.core.client.GWT; +import com.google.gwt.safehtml.shared.SafeHtmlUtils; import com.smartgwt.client.types.FormMethod; import com.smartgwt.client.widgets.form.DynamicForm; +import com.smartgwt.client.widgets.form.fields.HiddenItem; import com.smartgwt.client.widgets.form.fields.LinkItem; import com.smartgwt.client.widgets.form.fields.events.ClickEvent; import com.smartgwt.client.widgets.form.fields.events.ClickHandler; -import com.google.gwt.safehtml.shared.SafeHtmlUtils; import org.dive4elements.river.client.client.FLYS; +import org.dive4elements.river.client.shared.model.User; public class WikiLinks { - public static String imageLinkHTML(FLYS instance, String url, String imageUrl) { + public static String imageLinkForm(FLYS instance, String url, String imageUrl, String formName) { String saml = null; if (instance != null && instance.getCurrentUser() != null) { saml = instance.getCurrentUser().getSamlXMLBase64(); @@ -29,7 +32,7 @@ if (saml != null) { return "
" + + quotedUrl + "\" " + "name=\"" + formName + "\">" + "" + "" @@ -40,35 +43,67 @@ } } - public static DynamicForm linkHTML(FLYS flys, String url, String text) { - String saml = flys.getCurrentUser().getSamlXMLBase64(); + public static DynamicForm linkDynamicForm(FLYS flys, String url, String text) { + User currentUser = flys.getCurrentUser(); String quotedUrl = SafeHtmlUtils.htmlEscape(url); String quotedText = SafeHtmlUtils.htmlEscape(text); - if (saml != null) { - final DynamicForm form = new DynamicForm(); - form.setMethod(FormMethod.POST); - form.setTarget("_blank"); - form.setAction(quotedUrl); - form.setCanSubmit(true); - LinkItem item = new LinkItem("saml"); - item.setShowTitle(false); - item.setLinkTitle(quotedText); - item.setValue(SafeHtmlUtils.htmlEscape(saml)); - item.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - form.submitForm(); - } - }); - form.setFields(item); - return form; + + if (currentUser != null) { + String saml = currentUser.getSamlXMLBase64(); + if (saml != null) { + final DynamicForm form = new DynamicForm(); + form.setMethod(FormMethod.POST); + form.setTarget("_blank"); + form.setAction(quotedUrl); + form.setCanSubmit(true); + LinkItem item = new LinkItem("saml"); + item.setTextBoxStyle("font-size: large;"); + item.setShowTitle(false); + item.setLinkTitle(quotedText); + item.setValue(SafeHtmlUtils.htmlEscape(saml)); + item.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + form.submitForm(); + } + }); + form.setFields(item); + return form; + } } - else { - DynamicForm form = new DynamicForm(); - LinkItem item = new LinkItem(quotedText); - item.setShowTitle(false); - item.setTarget(quotedUrl); - return form; + DynamicForm form = new DynamicForm(); + LinkItem item = new LinkItem(quotedText); + item.setShowTitle(false); + item.setTarget(quotedUrl); + return form; + } + + public static DynamicForm dynamicForm(FLYS flys, String url) { + User currentUser = flys.getCurrentUser(); + String quotedUrl = SafeHtmlUtils.htmlEscape(url); + + if (currentUser != null) { + String saml = currentUser.getSamlXMLBase64(); + if (saml != null) { + saml = SafeHtmlUtils.htmlEscape(saml); + GWT.log("saml=" + saml); + DynamicForm form = new DynamicForm(); + form.setID("wikiDynamicForm"); + form.setMethod(FormMethod.POST); + form.setTarget("_blank"); + form.setAction(quotedUrl); + form.setCanSubmit(true); + HiddenItem item = new HiddenItem("saml"); + item.setDefaultValue(saml); + item.setValue(saml); + form.setFields(item); + //form.setValue("saml", saml); + return form; + } } + DynamicForm form = new DynamicForm(); + form.setTarget("_blank"); + form.setAction(quotedUrl); + return form; } } diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WspDatacagePanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WspDatacagePanel.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/WspDatacagePanel.java Thu Sep 12 10:13:09 2013 +0200 @@ -78,7 +78,7 @@ /** * We need to override this method (defined in AbstractUIProvider) because - * we have to create a new Artifact specified by the Datacage selection via + * we have to create a new Artifact specified by the Datacage selection via * Async request. * * @param e The ClickEvent. @@ -144,6 +144,7 @@ } + /** Returns a Data Array with one default item. */ protected Data[] getData(Recommendation r, Artifact newArtifact) { String uuid = newArtifact.getUuid(); r.setMasterArtifact(uuid); diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartPropertiesEditor.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartPropertiesEditor.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/ChartPropertiesEditor.java Thu Sep 12 10:13:09 2013 +0200 @@ -188,6 +188,17 @@ PropertyGroup origPg = (PropertyGroup)orig; if (pg.getName().equals("axis")) { + // Certain axis shall be skipped (W/Q-Diagrams cm-axis especially). + String outputName = tab.getOutputName(); + if (outputName.equals("fix_wq_curve") || outputName.equals("computed_discharge_curve") + || outputName.equals("extreme_wq_curve")) { + String labelString = ((StringProperty)origPg.getPropertyByName("label")).getValue(); + if(labelString.equals("W [cm]")) { + VLayout layout = new VLayout(); + layout.setHeight(0); + return layout; + } + } Label scale = new Label(MSG.scale() + " :"); scale.setHeight(25); scale.setMargin(2); diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/CrossSectionChartThemePanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/CrossSectionChartThemePanel.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/chart/CrossSectionChartThemePanel.java Thu Sep 12 10:13:09 2013 +0200 @@ -312,7 +312,7 @@ /** - * Feed a single artifact with the km of the crosssection to display. + * Feed artifacts with the km of the crosssection to display. * If its the selected master, also feed the collectionmaster. * * @param artifacts List of artifacts to feed. diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/fixation/FixGaugeSelectPanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/fixation/FixGaugeSelectPanel.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/fixation/FixGaugeSelectPanel.java Thu Sep 12 10:13:09 2013 +0200 @@ -30,7 +30,8 @@ import java.util.List; /** - * This UIProvider creates a panel for location or distance input. + * This UIProvider creates a panel to select discharge classes / sectors + * (german Abflussklassen). * * @author Raimund Renkert */ diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/minfo/SedLoadOffEpochPanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/minfo/SedLoadOffEpochPanel.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/minfo/SedLoadOffEpochPanel.java Thu Sep 12 10:13:09 2013 +0200 @@ -38,7 +38,7 @@ import org.dive4elements.river.client.shared.model.SedimentLoadInfoObject; import org.dive4elements.river.client.shared.model.SedimentLoadInfoRecord; - +/** Show input to select an official epoch. */ public class SedLoadOffEpochPanel extends PeriodPanel { @@ -47,6 +47,7 @@ private ListGrid sedLoadTable; + /** Creates layout with title. */ public Canvas createWidget(DataList data) { VLayout root = new VLayout(); @@ -58,6 +59,7 @@ return root; } + /** Create layout for data entered previously. */ @Override public Canvas createOld(DataList dataList) { HLayout layout = new HLayout(); @@ -104,6 +106,7 @@ return layout; } + /** Creates the helper grid in which off epochs can be selected. */ protected Canvas createHelper() { sedLoadTable = new ListGrid(); sedLoadTable.setShowHeaderContextMenu(false); @@ -119,15 +122,11 @@ date.setType(ListGridFieldType.TEXT); date.setWidth(100); - ListGridField descr = - new ListGridField("description", MSG.description()); - descr.setType(ListGridFieldType.TEXT); - descr.setWidth("*"); - - sedLoadTable.setFields(date, descr); + sedLoadTable.setFields(date); return sedLoadTable; } + /** Get data via listgrid selection. */ @Override public Data[] getData() { List data = new ArrayList(); @@ -153,9 +152,10 @@ return data.toArray(new Data[data.size()]); } + /** Fetch load info from service and populate table. */ protected void fetchSedimentLoadData() { - Config config = Config.getInstance(); - String locale = config.getLocale (); + Config config = Config.getInstance(); + String locale = config.getLocale (); ArtifactDescription adescr = artifact.getArtifactDescription(); DataList[] data = adescr.getOldData(); @@ -163,16 +163,16 @@ double[] km = artifact.getArtifactDescription().getKMRange(); String river = artifact.getArtifactDescription().getRiver(); - sedLoadInfoService.getSedimentLoadInfo(locale, river, "epoch", km[0], km[1], + sedLoadInfoService.getSedimentLoadInfo(locale, river, "off_epoch", km[0], km[1], new AsyncCallback() { public void onFailure(Throwable caught) { - GWT.log("Could not recieve sediment load informations."); + GWT.log("Could not receive sediment load informations."); SC.warn(caught.getMessage()); } public void onSuccess(SedimentLoadInfoObject[] sedLoad) { int num = sedLoad != null ? sedLoad.length :0; - GWT.log("Recieved " + num + " sediment load informations."); + GWT.log("Received " + num + " sediment load informations."); if (num == 0) { return; @@ -185,11 +185,12 @@ } + /** Add record to input helper listgrid. */ protected void addSedimentLoadInfo (SedimentLoadInfoObject[] sedLoad) { for(SedimentLoadInfoObject sl: sedLoad) { SedimentLoadInfoRecord rec = new SedimentLoadInfoRecord(sl); sedLoadTable.addData(rec); } } - } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/range/DischargeInfoDataSource.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/range/DischargeInfoDataSource.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/range/DischargeInfoDataSource.java Thu Sep 12 10:13:09 2013 +0200 @@ -20,7 +20,7 @@ public static final String XPATH_DISCHARGE_DEFAULT = "/discharges/discharge"; - public DischargeInfoDataSource(String url, long gauge) { + public DischargeInfoDataSource(String url, long gauge, String river) { setDataFormat(DSDataFormat.XML); setRecordXPath(XPATH_DISCHARGE_DEFAULT); @@ -37,15 +37,16 @@ "end", FieldType.TEXT, "end"); setFields(desc, bfgid, start, end); - setDataURL(getServiceURL(url, gauge)); + setDataURL(getServiceURL(url, gauge, river)); } - protected String getServiceURL(String server, long gauge) { + protected String getServiceURL(String server, long gauge, String river) { String url = GWT.getModuleBaseURL(); url += "dischargeinfoxml"; url += "?server=" + server; url += "&gauge=" + String.valueOf(gauge); + url += "&river=" + river; return url; } diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/stationinfo/InfoListGrid.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/stationinfo/InfoListGrid.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/stationinfo/InfoListGrid.java Thu Sep 12 10:13:09 2013 +0200 @@ -46,7 +46,7 @@ ) { String name = this.getFieldName(colNum); if (name.equals("infolink")) { - return WikiLinks.linkHTML( + return WikiLinks.linkDynamicForm( flys, record.getAttribute("link"), record.getLinkText()); diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/wq/QDTable.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/wq/QDTable.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/wq/QDTable.java Thu Sep 12 10:13:09 2013 +0200 @@ -22,7 +22,12 @@ /** - * Table showing Q and D main values, allowing for selection. + * Table showing Q and D main values, allowing for selection, if + * showSelect is called. In that case, a CellClickHandler should + * be registered. + * + * TODO becomes very similiar to WTable. Probably mergeable. + * * @author Ingo Weinzierl */ public class QDTable extends ListGrid { @@ -119,6 +124,7 @@ hideField("min"); } + /** Whether or not can be clicked on. */ public boolean isLocked() { return lockClick; } diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/client/ui/wq/WTable.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/wq/WTable.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/wq/WTable.java Thu Sep 12 10:13:09 2013 +0200 @@ -21,6 +21,8 @@ import org.dive4elements.river.client.client.FLYSConstants; /** + * Table showing W main values. + * TODO becomes very similiar to QDTable. Probably mergeable. * @author Ingo Weinzierl */ public class WTable extends ListGrid { @@ -30,6 +32,8 @@ public WTable() { + String baseUrl = GWT.getHostPageBaseURL(); + setWidth100(); setHeight100(); setSelectionType(SelectionStyle.NONE); @@ -68,7 +72,31 @@ } }); - setFields(name, type, value); + ListGridField select = new ListGridField("select", MESSAGE.selection()); + select.setType(ListGridFieldType.ICON); + select.setWidth(70); + select.setCellIcon(baseUrl + MESSAGE.markerGreen()); + + setFields(select, name, type, value); + hideField("select"); + } + + public void showSelect() { + showField("select"); + } + + + /** + * Search all records for one with attribute name equals to given name. + * @return null if none found. + * */ + public Double findRecordValue(String name) { + for (ListGridRecord record : getRecords()) { + if (record.getAttribute("name").equals(name)) { + return record.getAttributeAsDouble("value"); + } + } + return null; } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoServiceImpl.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoServiceImpl.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoServiceImpl.java Thu Sep 12 10:13:09 2013 +0200 @@ -48,9 +48,11 @@ public static final String XPATH_DISTANCES = "art:discharges/art:discharge"; + @Override public DischargeInfoObject[] getDischargeInfo( String locale, - long gauge) + long gauge, + String river) throws ServerException { logger.info("DichargeInfoServiceImpl.getDischargeInfo"); @@ -67,6 +69,10 @@ Element gaugeEl = ec.create("gauge"); gaugeEl.setTextContent(String.valueOf(gauge)); + Element riverEl = ec.create("river"); + riverEl.setTextContent(river); + + gaugeEl.appendChild(riverEl); doc.appendChild(gaugeEl); HttpClient client = new HttpClientImpl(url, locale); diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoXML.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoXML.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/DischargeInfoXML.java Thu Sep 12 10:13:09 2013 +0200 @@ -50,6 +50,8 @@ String gauge = req.getParameter("gauge"); + String river = req.getParameter("river"); + Document doc = XMLUtils.newDocument(); XMLUtils.ElementCreator ec = new XMLUtils.ElementCreator( @@ -60,6 +62,12 @@ Element gaugeEl = ec.create("gauge"); gaugeEl.setTextContent(gauge); + if (river != null && !river.isEmpty()) { + Element riverEl = ec.create("river"); + riverEl.setTextContent(river); + gaugeEl.appendChild(riverEl); + } + doc.appendChild(gaugeEl); HttpClient client = new HttpClientImpl(url); diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/server/FixingsOverviewServiceImpl.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/FixingsOverviewServiceImpl.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/FixingsOverviewServiceImpl.java Thu Sep 12 10:13:09 2013 +0200 @@ -33,8 +33,6 @@ import java.util.ArrayList; import java.util.List; -import javax.xml.xpath.XPathConstants; - import org.apache.log4j.Logger; import org.w3c.dom.Document; @@ -58,9 +56,6 @@ protected static final String XPATH_RFROM = "/fixings/river/@from"; protected static final String XPATH_RTO = "/fixings/river/@to"; - protected static final String XPATH_EVENT = "/fixings/events/event"; - - @Override public FixingsOverviewInfo generateOverview( String locale, @@ -193,18 +188,16 @@ protected List getFixEvents(Document doc) { List list = new ArrayList(); - NodeList events = (NodeList) XMLUtils.xpath( - doc, - XPATH_EVENT, - XPathConstants.NODESET, - null); + NodeList events = doc.getElementsByTagName("event"); - if (events == null || events.getLength() == 0) { + int E = events.getLength(); + + if (E == 0) { log.warn("No events in Overview!"); return list; } - for (int i = 0, E = events.getLength(); i < E; i++) { + for (int i = 0; i < E; i++) { Element n = (Element)events.item(i); List sectors = getSectors(n); String cid = n.getAttribute("cid"); @@ -218,13 +211,15 @@ protected List getSectors(Element event) { NodeList sectors = event.getElementsByTagName("sector"); - if (sectors.getLength() == 0) { + int S = sectors.getLength(); + + if (S == 0) { log.warn("No Sectors in Event!"); return null; } - List list = new ArrayList(); - for (int i = 0, S = sectors.getLength(); i < S; i++) { + List list = new ArrayList(S); + for (int i = 0; i < S; i++) { Element n = (Element)sectors.item(i); int cls = -1; double from = -1; diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/server/MapPrintServiceImpl.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/MapPrintServiceImpl.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/MapPrintServiceImpl.java Thu Sep 12 10:13:09 2013 +0200 @@ -212,7 +212,7 @@ Map legend = new LinkedHashMap(); List classes = new ArrayList(1); Map clazz = new LinkedHashMap(); - String lgu = encode(MapUtils.getLegendGraphicUrl(layer.url, layer.layers, dpi)); + String lgu = MapUtils.getLegendGraphicUrl(layer.url, encode(layer.layers), dpi); clazz.put("icon", lgu); clazz.put("name", layer.description); classes.add(clazz); @@ -427,6 +427,7 @@ // Currently this is not a problem because /flys/map-print // is whitelisted in GGInAFilter. GetMethod get = new GetMethod(url); + get.addRequestHeader("X_NO_GGINA_AUTH", "TRUE"); int result = client.executeMethod(get); InputStream in = get.getResponseBodyAsStream(); diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/server/SedimentLoadInfoServiceImpl.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/SedimentLoadInfoServiceImpl.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/SedimentLoadInfoServiceImpl.java Thu Sep 12 10:13:09 2013 +0200 @@ -29,9 +29,10 @@ import org.dive4elements.river.client.shared.model.SedimentLoadInfoObjectImpl; +/** Service to fetch info about sediment load. */ public class SedimentLoadInfoServiceImpl -extends RemoteServiceServlet -implements SedimentLoadInfoService +extends RemoteServiceServlet +implements SedimentLoadInfoService { private static final Logger logger = Logger.getLogger(SedimentLoadInfoServiceImpl.class); @@ -50,7 +51,7 @@ { logger.info("SedimentLoadInfoServiceImpl.getSedimentLoadInfo"); - String url = getServletContext().getInitParameter("server-url"); + String url = getServletContext().getInitParameter("server-url"); Document doc = XMLUtils.newDocument(); @@ -158,3 +159,4 @@ return null; } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/server/filter/GGInAFilter.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/filter/GGInAFilter.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/filter/GGInAFilter.java Thu Sep 12 10:13:09 2013 +0200 @@ -100,9 +100,12 @@ // Allow access to localhost if (isLocalAddress(req)) { - logger.debug("Request to localhost"); - chain.doFilter(req, resp); - return; + String noAuth = sreq.getHeader("X_NO_GGINA_AUTH"); + if (noAuth != null && noAuth.equals("TRUE")) { + logger.debug("Request to localhost"); + chain.doFilter(req, resp); + return; + } } // Allow access to login pages diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/shared/model/DefaultCollection.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/DefaultCollection.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/DefaultCollection.java Thu Sep 12 10:13:09 2013 +0200 @@ -284,6 +284,10 @@ } + /** + * Returns true if a recommendation with given factory and id + * is already member of this collection. + */ public boolean loadedRecommendation(Recommendation recommendation) { String factory = recommendation.getFactory(); String dbids = recommendation.getIDs(); @@ -307,7 +311,7 @@ } /** - * Returns the name of the collection or uuid if no name is set + * Returns the name of the collection or uuid if no name is set. */ @Override public String getDisplayName() { diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/shared/model/FixingsOverviewInfo.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/FixingsOverviewInfo.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/FixingsOverviewInfo.java Thu Sep 12 10:13:09 2013 +0200 @@ -61,9 +61,9 @@ } public FixEvent getEventByCId(String cid) { - for (int i = 0; i < events.size(); i++) { - if (events.get(i).getCId().equals(cid)) { - return events.get(i); + for (FixEvent event: events) { + if (event.getCId().equals(cid)) { + return event; } } return null; diff -r 17398e239c77 -r e0311aa32efb gwt-client/src/main/java/org/dive4elements/river/client/shared/model/ToLoad.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/ToLoad.java Sat Jun 29 00:20:58 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/ToLoad.java Thu Sep 12 10:13:09 2013 +0200 @@ -20,6 +20,7 @@ public class ToLoad implements Serializable { + /** Two strings. */ public class StringPair { public String first; public String second; @@ -51,16 +52,17 @@ } return key; } - public void add( - String artifactName, - String factory, - String out, - String name, - String ids, - String displayName - ) { - add(artifactName, factory, out, name, ids, displayName, null); - } + + public void add( + String artifactName, + String factory, + String out, + String name, + String ids, + String displayName + ) { + add(artifactName, factory, out, name, ids, displayName, null); + } public void add( String artifactName, @@ -114,7 +116,7 @@ for (Map.Entry entry: all.getValue().entrySet() ) { - StringPair pair = entry.getKey(); + StringPair pair = entry.getKey(); String factory = pair.first; ArtifactFilter artifactFilter = entry.getValue();