# HG changeset patch # User Tom Gottfried # Date 1372080247 -7200 # Node ID df867072d003f23bf709c93a5980d51de78f8ce6 # Parent b95504c340608954a62d4bc9ef6218b875b52414# Parent 19066b1220b58158ec17ae66eaf377cb4e350009 merge changes from default into double-precision branch diff -r b95504c34060 -r df867072d003 artifacts/doc/conf/artifacts/minfo.xml --- a/artifacts/doc/conf/artifacts/minfo.xml Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/doc/conf/artifacts/minfo.xml Mon Jun 24 15:24:07 2013 +0200 @@ -508,6 +508,7 @@ + diff -r b95504c34060 -r df867072d003 artifacts/doc/conf/cache.xml --- a/artifacts/doc/conf/cache.xml Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/doc/conf/cache.xml Mon Jun 24 15:24:07 2013 +0200 @@ -142,6 +142,13 @@ memoryStoreEvictionPolicy="LRU" overflowToDisk="true" diskPersistent="true" + /> + + + - - - - - SELECT m.id AS a_id, - m.state AS a_state, - m.gid AS a_gid, - m.creation AS a_creation, - ardg.v AS gaugy, - arv.v AS wqsingle - FROM master_artifacts m, - artifact_data ardg, - artifact_data arv - WHERE m.collection_id = ${collection_id} - AND m.gid = CAST(${artifact-id} AS uuid) - AND ardg.artifact_id = m.id - AND ardg.k = 'ld_gaugename' - AND arv.artifact_id = m.id - AND arv.k = 'wq_single' - AND EXISTS ( - SELECT id - FROM artifact_data ad - WHERE ad.artifact_id = m.id - AND k = 'river' - AND v = ${river}) - - - - - SELECT ol.wst_id AS wstid, - ol.wst_column_pos AS wstcolpos, - ol.name AS olname, - ol.value AS oval - FROM official_q_values ol - WHERE ol.value = CAST(${wqsingle} AS NUMERIC(10,2)) - AND ol.gauge_name = ${gaugy} - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff -r b95504c34060 -r df867072d003 artifacts/doc/conf/themes.xml --- a/artifacts/doc/conf/themes.xml Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/doc/conf/themes.xml Mon Jun 24 15:24:07 2013 +0200 @@ -310,6 +310,7 @@ + diff -r b95504c34060 -r df867072d003 artifacts/doc/conf/themes/default.xml --- a/artifacts/doc/conf/themes/default.xml Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/doc/conf/themes/default.xml Mon Jun 24 15:24:07 2013 +0200 @@ -1145,6 +1145,17 @@ + + + + + + + + + + diff -r b95504c34060 -r df867072d003 artifacts/doc/conf/themes/second.xml --- a/artifacts/doc/conf/themes/second.xml Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/doc/conf/themes/second.xml Mon Jun 24 15:24:07 2013 +0200 @@ -1145,6 +1145,17 @@ + + + + + + + + + + diff -r b95504c34060 -r df867072d003 artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Recommendations.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Recommendations.java Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Recommendations.java Mon Jun 24 15:24:07 2013 +0200 @@ -45,6 +45,7 @@ import org.dive4elements.river.artifacts.datacage.templating.Builder; import org.dive4elements.river.artifacts.datacage.templating.BuilderPool; +import org.dive4elements.river.artifacts.model.OfficialLineFinder; /** @@ -136,7 +137,7 @@ } protected static void artifactToParameters( - D4EArtifact artifact, + D4EArtifact artifact, Map parameters ) { parameters.put("CURRENT-STATE-ID", artifact.getCurrentStateId()); @@ -150,6 +151,10 @@ String key = sd.getName().replace('.', '-').toUpperCase(); parameters.put(key, value); } + + // XXX: THIS IS THE HACK TO BRING THE OFFICIAL LINES INTO THE DATACAGE! + parameters.put( + "OFFICIAL-LINES", OfficialLineFinder.findOfficialLines(artifact)); } /** @@ -171,7 +176,7 @@ * @param extraParameters parameters (typicall example: 'recommended') */ public void recommend( - D4EArtifact artifact, + D4EArtifact artifact, String userId, String [] outs, Map extraParameters, diff -r b95504c34060 -r df867072d003 artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java Mon Jun 24 15:24:07 2013 +0200 @@ -12,6 +12,8 @@ import org.dive4elements.river.utils.Pair; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.sql.Connection; import java.sql.SQLException; @@ -164,6 +166,14 @@ * macros but not doing evaluation (e.g. of s). */ private Node findStatementNode(NodeList nodes) { + return findSelectNode(nodes, "statement"); + } + + private Node findPropertiesNode(NodeList nodes) { + return findSelectNode(nodes, "properties"); + } + + private Node findSelectNode(NodeList nodes, String selectName) { int S = nodes.getLength(); // Check direct children and take special care of macros. @@ -172,7 +182,7 @@ String ns; // Regular statement node. if (node.getNodeType() == Node.ELEMENT_NODE - && node.getLocalName().equals("statement") + && node.getLocalName().equals(selectName) && (ns = node.getNamespaceURI()) != null && ns.equals(DC_NAMESPACE_URI)) { return node; @@ -185,7 +195,7 @@ String macroName = ((Element)node).getAttribute("name"); Node inMacroNode = - findStatementNode(getMacroChildren(macroName)); + findSelectNode(getMacroChildren(macroName), selectName); if (inMacroNode != null) { return inMacroNode; } @@ -196,6 +206,131 @@ return null; } + private String[][] extractProperties(Element propertiesNode) { + ArrayList props = new ArrayList(); + NodeList list = propertiesNode.getElementsByTagNameNS( + DC_NAMESPACE_URI, "property"); + for (int i = 0, L = list.getLength(); i < L; ++i) { + Element property = (Element)list.item(i); + String name = property.getAttribute("name"); + if (name.isEmpty()) { + log.warn("dc:property without name"); + continue; + } + String alias = property.getAttribute("alias"); + if (alias.isEmpty()) { + alias = name; + } + props.add(new String [] { name, alias }); + } + return props.toArray(new String[props.size()][]); + } + + /** + * Handle a dc:context node. + */ + protected void containerContext(Node parent, Element current) + throws SQLException + { + log.debug("dc:container-context"); + + String container = expand(current.getAttribute("container")); + + if (container.isEmpty()) { + log.warn("dc:container-context: no 'container' attribute found"); + return; + } + + NodeList subs = current.getChildNodes(); + Node propertiesNode = findPropertiesNode(subs); + + if (propertiesNode == null) { + log.warn("dc:container-context: cannot find properties."); + return; + } + + String [][] properties = extractProperties((Element)propertiesNode); + + if (properties.length == 0) { + log.warn("dc:properties: No properties defined."); + } + + Object [] result = new Object[1]; + if (!frames.getStore(container, result)) { + log.warn("dc:container-context: cannot find container."); + return; + } + Object c = result[0]; + if (c instanceof Object []) { + c = Arrays.asList((Object [])c); + } + if (!(c instanceof Collection)) { + log.warn("dc:container-context: container is not a collection."); + return; + } + + Collection collection = (Collection)c; + + // only descent if there are results + if (collection.isEmpty()) { + return; + } + + String [] columnNames = new String[properties.length]; + for (int i = 0; i < columnNames.length; ++i) { + columnNames[i] = properties[i][1]; + } + + ResultData rd = new ResultData(columnNames); + + for (Object obj: collection) { + Object [] row = new Object[properties.length]; + for (int i = 0; i < properties.length; ++i) { + row[i] = getProperty(obj, properties[i][0]); + } + rd.add(row); + } + + // A bit of a fake because the data is not from a + // real connection. + NamedConnection connection = connectionsStack.isEmpty() + ? connections.get(0) + : connectionsStack.peek().getA(); + + connectionsStack.push( + new Pair(connection, rd)); + try { + for (int i = 0, S = subs.getLength(); i < S; ++i) { + build(parent, subs.item(i)); + } + } + finally { + connectionsStack.pop(); + } + } + + /** Poor man's bean access. */ + private Object getProperty(Object obj, String name) { + String mname = + "get" + Character.toUpperCase(name.charAt(0)) + + name.substring(1); + + try { + Method meth = obj.getClass().getMethod(mname); + return meth.invoke(obj); + } + catch (InvocationTargetException ite) { + log.warn(ite); + } + catch (IllegalAccessException iae) { + log.warn(iae); + } + catch (NoSuchMethodException nsme) { + log.warn(nsme); + } + return null; + } + /** * Handle a dc:context node. */ @@ -206,7 +341,6 @@ NodeList subs = current.getChildNodes(); Node stmntNode = findStatementNode(subs); - int S = subs.getLength(); if (stmntNode == null) { log.warn("dc:context: cannot find statement"); @@ -250,7 +384,7 @@ connectionsStack.push( new Pair(connection, rd)); try { - for (int i = 0; i < S; ++i) { + for (int i = 0, S = subs.getLength(); i < S; ++i) { build(parent, subs.item(i)); } } @@ -973,6 +1107,9 @@ else if ("context".equals(localName)) { context(parent, curr); } + else if ("container-context".equals(localName)) { + containerContext(parent, curr); + } else if ("if".equals(localName)) { ifClause(parent, curr); } diff -r b95504c34060 -r df867072d003 artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/FacetTypes.java Mon Jun 24 15:24:07 2013 +0200 @@ -112,7 +112,10 @@ return false; } public static boolean SEDIMENT_LOAD(String type) { - return type.startsWith("sedimentload"); + return type.startsWith("sedimentload") && !type.contains("unknown"); + } + public static boolean SEDIMENT_LOAD_UNKNOWN(String type) { + return type.equals("sedimentload.unknown"); } public static boolean SEDIMENT_LOAD_NO_FLOAT(String type) { return type.startsWith("sedimentload") && !type.contains("susp"); @@ -310,6 +313,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 SQ_OVERVIEW = "sq_overview"; diff -r b95504c34060 -r df867072d003 artifacts/src/main/java/org/dive4elements/river/artifacts/model/OfficialLineFinder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/OfficialLineFinder.java Mon Jun 24 15:24:07 2013 +0200 @@ -0,0 +1,329 @@ +/* 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; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.sf.ehcache.Cache; +import net.sf.ehcache.Element; + +import org.dive4elements.river.artifacts.D4EArtifact; +import org.dive4elements.river.artifacts.cache.CacheFactory; +import org.dive4elements.river.model.Gauge; +import org.dive4elements.river.model.MainValue; +import org.dive4elements.river.model.NamedMainValue; +import org.dive4elements.river.model.OfficialLine; +import org.dive4elements.river.model.River; +import org.dive4elements.river.model.Wst; +import org.dive4elements.river.model.WstColumn; + +public class OfficialLineFinder +{ + public static final String CACHE_NAME = "official-lines"; + + // We will only have one entry in this cache. + public static final String CACHE_KEY = CACHE_NAME; + + public static final double EPSILON = 1e-4; + + + public static class ValueRange extends Range { + + private double value; + private int wstId; + private int columnPos; + private String name; + + public ValueRange( + double start, + double end, + double value, + int wstId, + int columnPos, + String name + ) { + super(start, end); + this.value = value; + this.wstId = wstId; + this.columnPos = columnPos; + this.name = name; + } + + public boolean sameValue(double value) { + return Math.abs(value - this.value) < EPSILON; + } + + public int getWstId() { + return wstId; + } + + public int getColumnPos() { + return columnPos; + } + + public boolean intersectsValueRange(Range r) { + return r.inside(value); + } + + public String getName() { + return name; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ValueRange)) { + return false; + } + ValueRange r = (ValueRange)o; + return wstId == r.wstId && columnPos == r.columnPos; + } + } + + public OfficialLineFinder() { + } + + public static Map> getAll() { + Cache cache = CacheFactory.getCache(CACHE_NAME); + + if (cache == null) { + return getAllUncached(); + } + + Element element = cache.get(CACHE_KEY); + + if (element != null) { + return (Map>)element.getValue(); + } + + Map> result = getAllUncached(); + if (result != null) { + cache.put(new Element(CACHE_KEY, result)); + } + return result; + + } + + public static Map> getAllUncached() { + + Map> rivers2officialLines = + new HashMap>(); + + + for (OfficialLine line: OfficialLine.fetchAllOfficalLines()) { + String name = line.getNamedMainValue().getName(); + WstColumn wc = line.getWstColumn(); + Wst wst = wc.getWst(); + + List ranges = new ArrayList(); + + River river = wst.getRiver(); + List gauges = river.getGauges(); + for (Gauge gauge: gauges) { + List mainValues = gauge.getMainValues(); + for (MainValue mainValue: mainValues) { + NamedMainValue nmv = mainValue.getMainValue(); + if (nmv.getName().equalsIgnoreCase(name)) { + // found gauge with this main value + + double from = gauge.getRange().getA().doubleValue(); + double to = gauge.getRange().getA().doubleValue(); + double value = mainValue.getValue().doubleValue(); + int wstId = wst.getId(); + int pos = wc.getPosition(); + ValueRange range = + new ValueRange(from, to, value, wstId, pos, name); + ranges.add(range); + break; + } + } + } + + if (!ranges.isEmpty()) { + rivers2officialLines.put(river.getName(), ranges); + } + } + + return rivers2officialLines; + } + + public static final Range MAX_RANGE = new Range(-Double.MAX_VALUE, +Double.MAX_VALUE); + + private static final String nn(String s) { + return s != null ? s : ""; + } + + public static Range extractRange(D4EArtifact artifact) { + String mode = nn(artifact.getDataAsString("ld_mode")); + String locations = nn(artifact.getDataAsString("ld_locations")); + String from = nn(artifact.getDataAsString("ld_from")); + String to = nn(artifact.getDataAsString("ld_to")); + + if (mode.equals("location")) { + try { + String loc = locations.replace(" ", ""); + String[] split = loc.split(","); + if (split.length < 1) { + return MAX_RANGE; + } + double min = Double.parseDouble(split[0]); + double max = min; + for (int i = 1; i < split.length; ++i) { + double v = Double.parseDouble(split[i]); + if (v > max) max = v; + if (v < min) min = v; + } + return new Range(min, max); + } + catch (NumberFormatException nfe) { + return MAX_RANGE; + } + } + try { + return new Range(Double.parseDouble(from), Double.parseDouble(to)); + } + catch (NumberFormatException nfe) { + return MAX_RANGE; + } + } + + private static List filterByRange(Range range, List ranges) { + List list = new ArrayList(ranges.size()); + for (ValueRange r: ranges) { + if (r.intersects(range)) { + list.add(r); + } + } + return list; + } + + private static List filterByQRange(Range range, List ranges) { + List list = new ArrayList(ranges.size()); + for (ValueRange r: ranges) { + if (r.intersectsValueRange(range) && !list.contains(r)) { + list.add(r); + } + } + return list; + } + + private static boolean isQ(D4EArtifact artifact) { + Boolean b = artifact.getDataAsBoolean("wq_isq"); + return b != null && b; + } + + private static boolean isRange(D4EArtifact artifact) { + Boolean b = artifact.getDataAsBoolean("wq_isrange"); + return b != null && b; + } + + public static final Range Q_OUT_OF_RANGE = new Range(-10000, -9999); + + private static Range singleQs(D4EArtifact artifact) { + String singleData = nn(artifact.getDataAsString("wq_single")); + double min = Double.MAX_VALUE; + double max = -Double.MAX_VALUE; + + for (String value: singleData.split(" ")) { + try { + double x = Double.parseDouble(value); + if (x < min) min = x; + if (x > max) max = x; + } + catch (NumberFormatException nfe) { + } + } + + return min == Double.MAX_VALUE + ? Q_OUT_OF_RANGE + : new Range(min, max); + + } + + private static Range qRange(D4EArtifact artifact) { + try { + Double from = artifact.getDataAsDouble("wq_from"); + Double to = artifact.getDataAsDouble("wq_to"); + + if (from == null || to == null) { + return Q_OUT_OF_RANGE; + } + double f = from; + double t = to; + return new Range(Math.min(f, t), Math.max(f, t)); + } + catch (NumberFormatException nfe) { + return Q_OUT_OF_RANGE; + } + } + + private static Range tripleQRange(D4EArtifact artifact) { + String rangesData = nn(artifact.getDataAsString("wq_values")); + + double min = Double.MAX_VALUE; + double max = -Double.MAX_VALUE; + + for (String range: rangesData.split(":")) { + String [] parts = range.split(";"); + if (parts.length < 3) { + continue; + } + String [] values = parts[2].split(","); + for (String value: values) { + try { + double x = Double.parseDouble(value); + if (x < min) min = x; + if (x > max) max = x; + } + catch (NumberFormatException nfe) { + } + } + } + + return min == Double.MAX_VALUE + ? Q_OUT_OF_RANGE + : new Range(min, max); + } + + public static List findOfficialLines(D4EArtifact artifact) { + + if (!isQ(artifact)) { // Only handle Q calculations + return Collections.emptyList(); + } + + Map> rivers2officialLines = getAll(); + + String riverName = nn(artifact.getDataAsString("river")); + + List ranges = rivers2officialLines.get(riverName); + + if (ranges == null) { + return Collections.emptyList(); + } + + ranges = filterByRange(extractRange(artifact), ranges); + + if (ranges.isEmpty()) { + return Collections.emptyList(); + } + + Range qRange = isRange(artifact) + ? qRange(artifact) + : singleQs(artifact); + + if (qRange == Q_OUT_OF_RANGE) { + qRange = tripleQRange(artifact); + } + + return filterByQRange(qRange, ranges); + } +} diff -r b95504c34060 -r df867072d003 artifacts/src/main/java/org/dive4elements/river/artifacts/model/Range.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/Range.java Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/Range.java Mon Jun 24 15:24:07 2013 +0200 @@ -31,10 +31,19 @@ this.end = end; } + public void setStart(double start) { + this.start = start; + } + public double getStart() { return start; } + + public void setEnd(double end) { + this.end = end; + } + public double getEnd() { return end; } @@ -69,5 +78,38 @@ public boolean inside(double x) { return x > start-EPSILON && x < end+EPSILON; } + + public boolean contains(double x) { + return inside(x); + } + + + /** Hash Code. */ + @Override + public int hashCode() { + return new Double(this.start).hashCode() ^ + new Double(this.end).hashCode(); + } + + + /** + * Compares start and end values with some epsilon. + */ + @Override + public boolean equals(Object otherRange) { + if (otherRange instanceof Range) { + Range oRange = (Range) otherRange; + return + Math.abs(oRange.start - this.start) <= EPSILON + && Math.abs(oRange.end - this.end) <= EPSILON; + } + return false; + } + + /** Returns clone with same start and end values. */ + @Override + public Object clone() { + return new Range(this.start, this.end); + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r b95504c34060 -r df867072d003 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 Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoad.java Mon Jun 24 15:24:07 2013 +0200 @@ -13,6 +13,8 @@ import java.util.Set; import org.dive4elements.river.artifacts.model.NamedObjectImpl; +import org.dive4elements.river.artifacts.model.Range; + /** Gives access to Fractions (at kms). */ public class SedimentLoad @@ -22,6 +24,7 @@ protected Date start; protected Date end; protected boolean isEpoch; + protected String unit; protected HashMap kms; @@ -33,13 +36,15 @@ String description, Date start, Date end, - boolean isEpoch + boolean isEpoch, + String unit ) { this(); this.description = description; this.start = start; this.end = end; this.isEpoch = isEpoch; + this.unit = unit; } public String getDescription() { @@ -89,68 +94,79 @@ return kms.get(km); } - public void setCoarse(double km, double coarse) { + 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); - kms.put(km, f); - } - } - - public void setFineMiddle(double km, double fine_middle) { - if (kms.containsKey(km)) { - kms.get(km).setFine_middle(fine_middle); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setFine_middle(fine_middle); - kms.put(km, f); - } - } - - public void setSand(double km, double sand) { - if (kms.containsKey(km)) { - kms.get(km).setSand(sand); - } - else { - SedimentLoadFraction f = new SedimentLoadFraction(); - f.setSand(sand); + f.setCoarseRange(range); kms.put(km, f); } } - public void setSuspSand(double km, double susp_sand) { + public void setFineMiddle(double km, double fine_middle, Range range) { if (kms.containsKey(km)) { - kms.get(km).setSusp_sand(susp_sand); + kms.get(km).setFineMiddle(fine_middle); + kms.get(km).setFineMiddleRange(range); } else { SedimentLoadFraction f = new SedimentLoadFraction(); - f.setSusp_sand(susp_sand); + f.setFineMiddle(fine_middle); + f.setFineMiddleRange(range); kms.put(km, f); } } - public void setSuspSandBed(double km, double susp_sand_bed) { + public void setSand(double km, double sand, Range range) { if (kms.containsKey(km)) { - kms.get(km).setSusp_sand_bed(susp_sand_bed); + kms.get(km).setSand(sand); + kms.get(km).setSandRange(range); } else { SedimentLoadFraction f = new SedimentLoadFraction(); - f.setSusp_sand_bed(susp_sand_bed); + f.setSand(sand); + f.setSandRange(range); kms.put(km, f); } } - public void setSuspSediment(double km, double susp_sediment) { + public void setSuspSand(double km, double susp_sand, Range range) { if (kms.containsKey(km)) { - kms.get(km).setSusp_sediment(susp_sediment); + kms.get(km).setSuspSand(susp_sand); + kms.get(km).setSuspSandRange(range); } else { SedimentLoadFraction f = new SedimentLoadFraction(); - f.setSusp_sediment(susp_sediment); + f.setSuspSand(susp_sand); + f.setSuspSandRange(range); + kms.put(km, f); + } + } + + 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); + } + } + + 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); } } @@ -166,17 +182,40 @@ } } - public void setTotal(double km, double total) { + 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); } } + 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); + } + } + + public String getUnit() { + return unit; + } + + public void setUnit(String unit) { + this.unit = unit; + } + public boolean hasCoarse() { for (SedimentLoadFraction slf : kms.values()) { if (slf.getCoarse() > 0d) { @@ -188,7 +227,7 @@ public boolean hasFineMiddle() { for (SedimentLoadFraction slf : kms.values()) { - if (slf.getFine_middle() > 0d) { + if (slf.getFineMiddle() > 0d) { return true; } } @@ -206,7 +245,7 @@ public boolean hasSuspSand() { for (SedimentLoadFraction slf : kms.values()) { - if (slf.getSusp_sand() > 0d) { + if (slf.getSuspSand() > 0d) { return true; } } @@ -215,7 +254,7 @@ public boolean hasSuspSediment() { for (SedimentLoadFraction slf : kms.values()) { - if (slf.getSusp_sediment() > 0d) { + if (slf.getSuspSediment() > 0d) { return true; } } diff -r b95504c34060 -r df867072d003 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 Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadCalculation.java Mon Jun 24 15:24:07 2013 +0200 @@ -18,6 +18,7 @@ import org.dive4elements.river.artifacts.access.SedimentLoadAccess; import org.dive4elements.river.artifacts.model.Calculation; import org.dive4elements.river.artifacts.model.CalculationResult; +import org.dive4elements.river.artifacts.model.Range; /** Calculate sediment load. */ @@ -155,42 +156,42 @@ SedimentLoadFraction f = load.getFraction(km); if (f.getCoarse() > 0d) { double c = resLoad.getFraction(km).getCoarse(); - resLoad.setCoarse(km, c + f.getCoarse()); + resLoad.setCoarse(km, c + f.getCoarse(), f.getCoarseRange()); cSum++; } - if (f.getFine_middle() > 0d) { - double fm = resLoad.getFraction(km).getFine_middle(); - resLoad.setFineMiddle(km, fm + f.getFine_middle()); + 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()); + resLoad.setSand(km, s + f.getSand(), f.getSandRange()); sSum++; } - if (f.getSusp_sand() > 0d) { - double s = resLoad.getFraction(km).getSusp_sand(); - resLoad.setSuspSand(km, s + f.getSusp_sand()); + if (f.getSuspSand() > 0d) { + double s = resLoad.getFraction(km).getSuspSand(); + resLoad.setSuspSand(km, s + f.getSuspSand(), f.getSuspSandRange()); ssSum++; } - if (f.getSusp_sand_bed() > 0d) { - double s = resLoad.getFraction(km).getSusp_sand_bed(); - resLoad.setSuspSandBed(km, s + f.getSusp_sand_bed()); + if (f.getSuspSandBed() > 0d) { + double s = resLoad.getFraction(km).getSuspSandBed(); + resLoad.setSuspSandBed(km, s + f.getSuspSandBed(), f.getSuspSandBedRange()); ssbSum++; } - if (f.getSusp_sediment() > 0d) { - double s = resLoad.getFraction(km).getSusp_sediment(); - resLoad.setSuspSediment(km, s + f.getSusp_sediment()); + 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); - resLoad.setFineMiddle(km, fr.getFine_middle()/fmSum); - resLoad.setSand(km, fr.getSand()/sSum); - resLoad.setSuspSand(km, fr.getSusp_sand()/ssSum); - resLoad.setSuspSandBed(km, fr.getSusp_sand_bed()/ssbSum); - resLoad.setSuspSediment(km, fr.getSusp_sediment()/sseSum); + 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()); } resLoad.setDescription(""); resLoad.setEpoch(true); @@ -264,6 +265,7 @@ return result; } + /** Add up the loads of a year. */ private SedimentLoad calculateTotalLoad(SedimentLoad load, int year) { logger.debug("calculateTotalLoad"); boolean problemThisYear = false; @@ -291,39 +293,180 @@ logger.warn("Some problem, not calculating total load."); return load; } - for(double km : load.getKms()) { + return partialTotal(load); + } + + + /** Returns true if all fraction values except SuspSediment are unset. */ + private boolean hasOnlySuspValues(SedimentLoadFraction fraction) { + return (fraction.getSuspSediment() != 0d && + fraction.getSuspSand() != 0d && + fraction.getCoarse() == 0d && + fraction.getFineMiddle() == 0d && + fraction.getSand() == 0d); + } + + + /** Returns true if all fraction values except SuspSediment are set. */ + private boolean hasButSuspValues(SedimentLoadFraction fraction) { + return (fraction.getSuspSediment() == 0d && + fraction.getSuspSand() == 0d && + fraction.getCoarse() != 0d && + fraction.getFineMiddle() != 0d && + fraction.getSand() != 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 + * or all Geschiebe or just the Schwebstoff fractions are set. + * Merge these ranges and add (maybe new) respective fractions to + * load. + * @param load SedimentLoad to add total values (and ranges) to. + * @return input param load. + */ + private SedimentLoad partialTotal(SedimentLoad load) { + SedimentLoad fairLoad = load; + + Range lastOtherRange = null; + double lastOtherValue = 0d; + + Range lastSuspRange = null; + double lastSuspValue = 0d; + + for (double km: load.getKms()) { + logger.debug ("Trying to add at km " + km); SedimentLoadFraction fraction = load.getFraction(km); - double total = 0d; - if ((fraction.getCoarse() <= 0d && load.hasCoarse())){ - addProblem(km, "missing.data.coarse"); - continue; - } - if (fraction.getFine_middle() <= 0d && load.hasFineMiddle()) { - addProblem(km, "missing.data.fine_middle"); - continue; - } - if (fraction.getSand() <= 0d && load.hasSand()) { - addProblem(km, "missing data.sand"); - continue; + if (complete(fraction)) { + double total = fraction.getCoarse() + + fraction.getFineMiddle() + + fraction.getSand() + + fraction.getSuspSand() + + fraction.getSuspSediment(); + // Easiest case. Add values up and set'em. + if (fraction.getCoarseRange().equals( + fraction.getSuspSedimentRange())) { + lastOtherRange = null; + lastSuspRange = null; + fairLoad.setTotal(km, total, fraction.getCoarseRange()); + } + else { + // Need to split a range. + if (fraction.getCoarseRange().getEnd() + < fraction.getSuspSedimentRange().getEnd()) { + // Schwebstoff is longer. + // Adjust and remember schwebstoffs range and value. + lastSuspRange = (Range) fraction.getSuspSedimentRange().clone(); + lastSuspRange.setStart(fraction.getCoarseRange().getEnd()); + lastSuspValue = fraction.getSuspSediment() + fraction.getSuspSand(); + lastOtherRange = null; + fairLoad.setTotal(km, total, fraction.getCoarseRange()); + } + else { + // Geschiebe is longer. + // Adjust and remember other values. + lastOtherRange = (Range) fraction.getSuspSedimentRange().clone(); + lastOtherRange.setStart(fraction.getSuspSedimentRange().getEnd()); + lastOtherValue = (total - fraction.getSuspSediment()); + lastSuspRange = null; + fairLoad.setTotal(km, total, fraction.getSuspSedimentRange()); + } + } } - if (fraction.getSusp_sand() <= 0d && load.hasSuspSand()) { - addProblem(km, "missing.data.susp_sand"); - continue; - } - if (fraction.getSusp_sediment() <= 0d && load.hasSuspSediment()) { - addProblem(km, "missing.data.susp_sediment"); - continue; + else if (hasOnlySuspValues(fraction) && lastOtherRange != null) { + // Split stuff. + Range suspSedimentRange = fraction.getSuspSedimentRange(); + // if intersects with last other range, cool! merge and add! + if (lastOtherRange.contains(km)) { + double maxStart = 0d; + double minEnd = 0d; + maxStart = Math.max(suspSedimentRange.getStart(), + lastOtherRange.getStart()); + + minEnd = Math.min(suspSedimentRange.getEnd(), + lastOtherRange.getEnd()); + double total = lastOtherValue + fraction.getSuspSediment(); + Range totalRange = new Range(maxStart, minEnd); + if (suspSedimentRange.getEnd() > lastOtherRange.getEnd()) { + lastSuspRange = (Range) suspSedimentRange.clone(); + lastSuspRange.setStart(lastOtherRange.getEnd()); + lastSuspValue = fraction.getSuspSediment() + fraction.getSuspSand(); + lastOtherRange = null; + } + else { + // Other is "longer". + lastOtherRange.setStart(suspSedimentRange.getEnd()); + lastSuspRange = null; + } + if (Math.abs(suspSedimentRange.getEnd() - lastOtherRange.getEnd()) < 0.1d) { + lastOtherRange = null; + lastSuspRange = null; + } + fairLoad.setTotal(km, total + fraction.getSuspSediment(), totalRange); + } + else { + lastSuspRange = suspSedimentRange; + lastSuspValue = fraction.getSuspSediment() + fraction.getSuspSand(); + lastOtherRange = null; + } } - total += fraction.getCoarse() + - fraction.getFine_middle() + - fraction.getSand() + - fraction.getSusp_sand() + - fraction.getSusp_sediment(); - load.setTotal(km, total); + else if (hasButSuspValues(fraction) && lastSuspRange != null) { + // If intersects with last suspsed range, merge and add + double total = fraction.getCoarse() + + fraction.getFineMiddle() + + fraction.getSand() + + lastSuspValue; + double maxStart = Math.max(fraction.getCoarseRange().getStart(), + lastSuspRange.getStart()); + if (lastSuspRange.contains(km)) { + double minEnd = Math.min(fraction.getCoarseRange().getEnd(), + lastSuspRange.getEnd()); + Range totalRange = new Range(maxStart, minEnd); + if (lastSuspRange.getEnd() > fraction.getCoarseRange().getEnd()) { + // SuspSed longer. + lastSuspRange.setStart(fraction.getCoarseRange().getEnd()); + lastOtherRange = null; + } + else { + // Other longer + lastOtherRange = (Range) fraction.getCoarseRange().clone(); + lastOtherRange.setStart(lastSuspRange.getEnd()); + lastSuspRange = null; + lastOtherValue = total - lastSuspValue; + } + if (Math.abs(lastSuspRange.getEnd() - lastOtherRange.getEnd()) < 0.1d) { + lastOtherRange = null; + lastSuspRange = null; + } + fairLoad.setTotal(km, total, totalRange); + } + else { + // Ranges are disjoint. + lastOtherRange = fraction.getCoarseRange(); + lastOtherValue = total - fraction.getSuspSediment(); + lastSuspRange = null; + } + } + else { + // Some values are missing or no intersection with former values. + // Stay as we are. + } } - return load; + return fairLoad; } + private SedimentLoad calculateUnit(SedimentLoad load, int year) { SedimentDensity density = SedimentDensityFactory.getSedimentDensity(river, kmLow, kmUp, year); @@ -331,19 +474,19 @@ double dens = density.getDensity(km, year); SedimentLoadFraction fraction = load.getFraction(km); double coarse = fraction.getCoarse(); - double fineMiddle = fraction.getFine_middle(); + double fineMiddle = fraction.getFineMiddle(); double sand = fraction.getSand(); - double suspSand = fraction.getSusp_sand(); - double bedSand = fraction.getSusp_sand_bed(); - double sediment = fraction.getSusp_sediment(); + double suspSand = fraction.getSuspSand(); + double bedSand = fraction.getSuspSandBed(); + double sediment = fraction.getSuspSediment(); double total = fraction.getTotal(); - load.setCoarse(km, (coarse * dens)); - load.setFineMiddle(km, (fineMiddle * dens)); - load.setSand(km, (sand * dens)); - load.setSuspSand(km, (suspSand * dens)); - load.setSuspSandBed(km, (bedSand * dens)); - load.setSuspSediment(km, (sediment * dens)); - load.setTotal(km, (total * dens)); + load.setCoarse(km, (coarse * dens), fraction.getCoarseRange()); + load.setFineMiddle(km, (fineMiddle * dens), fraction.getFineMiddleRange()); + load.setSand(km, (sand * dens), fraction.getSandRange()); + load.setSuspSand(km, (suspSand * dens), fraction.getSuspSandRange()); + load.setSuspSandBed(km, (bedSand * dens), fraction.getSuspSandBedRange()); + load.setSuspSediment(km, (sediment * dens), fraction.getSuspSedimentRange()); + load.setTotal(km, (total * dens), fraction.getTotalRange()); } return load; } diff -r b95504c34060 -r df867072d003 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 Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFacet.java Mon Jun 24 15:24:07 2013 +0200 @@ -8,6 +8,8 @@ package org.dive4elements.river.artifacts.model.minfo; +import gnu.trove.TDoubleArrayList; + import org.dive4elements.artifactdatabase.state.Facet; import org.dive4elements.artifacts.Artifact; @@ -70,6 +72,11 @@ return null; } + // These complicated calculations were necessary because + // SedimentLoad/Fraction did not contain the ranges of the given + // values. Since this changed, the code is somewhat obsolete, but stable. + // For an example of easier calculation, see the "total" part below. + List sortedStarts = new ArrayList(); // Filter stations according to type. List stations = new ArrayList(); @@ -90,7 +97,31 @@ } Collections.sort(sortedStarts); - // Access data according to type. + // Handle sediment load differently, as it respects already + // the ranges that were added to SedimentLoad/Fraction. + if (getName().equals(FacetTypes.SEDIMENT_LOAD_TOTAL)) { + SedimentLoad load = result.getLoad(); + TDoubleArrayList xPos = new TDoubleArrayList(); + TDoubleArrayList yPos = new TDoubleArrayList(); + double lastX = -1d; + for (double km: load.getKms()) { + SedimentLoadFraction fraction = load.getFraction(km); + if (fraction.getTotal() != 0) { + if (Math.abs(lastX-km) >= EPSILON) { + xPos.add(Double.NaN); + yPos.add(Double.NaN); + } + xPos.add(km); + yPos.add(fraction.getTotal()); + xPos.add(fraction.getTotalRange().getEnd()); + yPos.add(fraction.getTotal()); + lastX = fraction.getTotalRange().getEnd(); + } + } + return new double[][] {xPos.toNativeArray(), yPos.toNativeArray()}; + } + + // Access data according to type (except total - see above). double[][] sd = getLoadData(result); // Sort by km. diff -r b95504c34060 -r df867072d003 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 Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFactory.java Mon Jun 24 15:24:07 2013 +0200 @@ -13,19 +13,22 @@ import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.TreeMap; import net.sf.ehcache.Cache; import net.sf.ehcache.Element; import org.apache.log4j.Logger; +import org.dive4elements.river.artifacts.cache.CacheFactory; +import org.dive4elements.river.artifacts.model.Range; +import org.dive4elements.river.artifacts.model.RiverFactory; +import org.dive4elements.river.artifacts.model.StaticSedimentLoadCacheKey; +import org.dive4elements.river.backend.SessionHolder; +import org.dive4elements.river.model.MeasurementStation; import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.type.StandardBasicTypes; -import org.dive4elements.river.artifacts.cache.CacheFactory; -import org.dive4elements.river.artifacts.model.StaticSedimentLoadCacheKey; -import org.dive4elements.river.backend.SessionHolder; - /** Pull Sediment Loads out of db. */ public class SedimentLoadFactory { @@ -53,11 +56,13 @@ "SELECT DISTINCT " + " sy.description AS description, " + " ti.start_time AS start, " + - " ti.stop_time AS end " + + " ti.stop_time AS end, " + + " u.name AS unit" + " 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 " + + " JOIN units u ON u.id = sy.unit_id " + " WHERE r.name = :name " + " AND ti.stop_time IS NOT NULL " + " AND syv.station BETWEEN :startKm AND :endKm"; @@ -67,17 +72,51 @@ " sy.description AS description, " + " ti.start_time AS year, " + " syv.value AS load, " + - " syv.station AS km " + + " syv.station AS km, " + + " u.name AS unit " + " FROM sediment_yield sy " + " JOIN rivers r ON sy.river_id = r.id " + " JOIN time_intervals ti ON sy.time_interval_id = ti.id " + " JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " + " JOIN grain_fraction gf ON sy.grain_fraction_id = gf.id " + + " JOIN units u ON u.id = sy.unit_id" + " WHERE r.name = :name " + " AND ti.start_time BETWEEN :begin AND :end " + " AND ti.stop_time IS NULL " + " AND gf.name = :grain " + - " AND syv.station BETWEEN :startKm AND :endKm"; + " AND syv.station BETWEEN :startKm AND :endKm " + + " ORDER BY syv.station"; + + public static final String SQL_SELECT_UNKNOWN_DATA = + "SELECT" + + " sy.description AS description, " + + " ti.start_time AS start, " + + " ti.stop_time AS end, " + + " syv.value AS load, " + + " syv.station AS km, " + + " u.name AS unit " + + " FROM sediment_yield sy " + + " JOIN rivers r ON sy.river_id = r.id " + + " JOIN time_intervals ti ON sy.time_interval_id = ti.id " + + " JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " + + " JOIN grain_fraction gf ON sy.grain_fraction_id = gf.id " + + " JOIN units u ON u.id = sy.unit_id" + + " WHERE r.name = :name " + + " AND sy.description = :descr " + + " AND gf.name = 'unknown' " + + " ORDER BY syv.station"; + + public static final String SQL_SELECT_UNKNOWN = + "SELECT DISTINCT " + + " sy.description AS description, " + + " ti.start_time AS start, " + + " ti.stop_time AS end " + + "FROM sediment_yield sy " + + " 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'"; public static final String SQL_SELECT_EPOCHS_DATA = "SELECT" + @@ -85,17 +124,20 @@ " ti.start_time AS startYear, " + " syv.value AS load, " + " syv.station AS km," + - " ti.stop_time AS endYear " + + " ti.stop_time AS endYear, " + + " u.name AS unit" + " FROM sediment_yield sy " + " JOIN rivers r ON sy.river_id = r.id " + " JOIN time_intervals ti ON sy.time_interval_id = ti.id " + " JOIN sediment_yield_values syv ON sy.id = syv.sediment_yield_id " + " JOIN grain_fraction gf ON sy.grain_fraction_id = gf.id " + + " JOIN units u ON u.id = sy.unit_id " + " WHERE r.name = :name " + " AND ti.start_time BETWEEN :sbegin AND :send " + " AND ti.stop_time BETWEEN :ebegin AND :eend " + " AND gf.name = :grain " + - " AND syv.station BETWEEN :startKm AND :endKm"; + " AND syv.station BETWEEN :startKm AND :endKm " + + " ORDER BY syv.station"; private SedimentLoadFactory() { } @@ -218,7 +260,8 @@ (String) row[0], (Date) row[1], null, - false); + false, + ""); } return loads; } @@ -239,7 +282,8 @@ (String) row[0], (Date) row[1], (Date) row[2], - true); + true, + ""); } return loads; } @@ -264,6 +308,22 @@ Session session = SessionHolder.HOLDER.get(); SQLQuery sqlQuery = null; + List allStations = RiverFactory.getRiver(river).getMeasurementStations(); + TreeMap floatStations = new TreeMap(); + TreeMap suspStations = new TreeMap(); + for (MeasurementStation measurementStation: allStations) { + if (measurementStation.getMeasurementType() == null || + measurementStation.getRange() == null) { + continue; + } + if (measurementStation.getMeasurementType().equals("Schwebstoff")) { + suspStations.put(measurementStation.getRange().getA().doubleValue(), measurementStation); + } + else if (measurementStation.getMeasurementType().equals("Geschiebe")) { + floatStations.put(measurementStation.getRange().getA().doubleValue(), measurementStation); + } + } + Calendar start = Calendar.getInstance(); start.set(syear - 1, 11, 31); Calendar end = Calendar.getInstance(); @@ -274,7 +334,8 @@ .addScalar("description", StandardBasicTypes.STRING) .addScalar("year", StandardBasicTypes.DATE) .addScalar("load", StandardBasicTypes.DOUBLE) - .addScalar("km", StandardBasicTypes.DOUBLE); + .addScalar("km", StandardBasicTypes.DOUBLE) + .addScalar("unit", StandardBasicTypes.STRING); sqlQuery.setString("name", river); sqlQuery.setDouble("startKm", startKm); sqlQuery.setDouble("endKm", endKm); @@ -288,13 +349,14 @@ (String) row[0], (Date) row[1], null, - false); - getValues("coarse", sqlQuery, load); - getValues("fine_middle", sqlQuery, load); - getValues("sand", sqlQuery, load); - getValues("suspended_sediment", sqlQuery, load); - getValues("susp_sand_bed", sqlQuery, load); - getValues("susp_sand", sqlQuery, load); + 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, suspStations); + getValues("susp_sand", sqlQuery, load, suspStations); return load; } @@ -308,7 +370,8 @@ .addScalar("startYear", StandardBasicTypes.DATE) .addScalar("load", StandardBasicTypes.DOUBLE) .addScalar("km", StandardBasicTypes.DOUBLE) - .addScalar("endYear", StandardBasicTypes.DATE); + .addScalar("endYear", StandardBasicTypes.DATE) + .addScalar("unit", StandardBasicTypes.STRING); sqlQuery.setString("name", river); sqlQuery.setDouble("startKm", startKm); sqlQuery.setDouble("endKm", endKm); @@ -327,19 +390,20 @@ (String) row[0], (Date) row[1], (Date) row[4], - true); + 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]); } - getValues("coarse", sqlQuery, load); - getValues("fine_middle", sqlQuery, load); - getValues("sand", sqlQuery, load); - getValues("suspended_sediment", sqlQuery, load); - getValues("susp_sand_bed", sqlQuery, load); - getValues("susp_sand", sqlQuery, load); + 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, suspStations); + getValues("susp_sand", sqlQuery, load, suspStations); return load; } return new SedimentLoad(); @@ -356,36 +420,151 @@ protected static void getValues ( String fraction, SQLQuery query, - SedimentLoad load + SedimentLoad load, + TreeMap stations ) { query.setString("grain", fraction); List results = query.list(); 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) { + 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()); + } + } double v = -1; if (row[2] != null) { v = ((Double)row[2]).doubleValue(); } if (fraction.equals("coarse")) { - load.setCoarse(km, v); + load.setCoarse(km, v, range); } else if (fraction.equals("sand")) { - load.setSand(km, v); + load.setSand(km, v, range); } else if (fraction.equals("fine_middle")) { - load.setFineMiddle(km, v); + load.setFineMiddle(km, v, range); } else if (fraction.equals("suspended_sediment")) { - load.setSuspSediment(km, v); + load.setSuspSediment(km, v, range); } else if (fraction.equals("susp_sand")) { - load.setSuspSand(km, v); + load.setSuspSand(km, v, range); } else if (fraction.equals("susp_sand_bed")) { - load.setSuspSandBed(km, v); + load.setSuspSandBed(km, v, range); } } } + + public static SedimentLoad getLoadUnknown( + String river, + String description + ) { + log.debug("SedimentLoadFactory.getLoadWithData"); + Cache cache = CacheFactory.getCache(LOAD_DATA_CACHE_NAME); + + if (cache == null) { + log.debug("Cache not configured."); + return getSedimentLoadUnknownUncached(river, description); + } + + StaticSedimentLoadCacheKey key = + new StaticSedimentLoadCacheKey(river, 0d, 0d, 0, 0); + + Element element = cache.get(key); + + if (element != null) { + log.debug("SedimentLoad found in cache"); + return (SedimentLoad)element.getValue(); + } + + SedimentLoad values = getSedimentLoadUnknownUncached(river, description); + + if (values != null && key != null) { + log.debug("Store static bed height values in cache."); + element = new Element(key, values); + cache.put(element); + } + return values; + } + + /** + * Get sediment loads with fraction 'unknown' from db. + * @param river the river + * @param type the sediment load type (year or epoch) + * @return according sediment loads. + */ + public static SedimentLoad getSedimentLoadUnknownUncached( + String river, + String description + ) { + log.debug("SedimentLoadFactory.getSedimentLoadWithDataUncached"); + Session session = SessionHolder.HOLDER.get(); + SQLQuery sqlQuery = null; + + sqlQuery = session.createSQLQuery(SQL_SELECT_UNKNOWN_DATA) + .addScalar("description", StandardBasicTypes.STRING) + .addScalar("start", StandardBasicTypes.DATE) + .addScalar("end", StandardBasicTypes.DATE) + .addScalar("load", StandardBasicTypes.DOUBLE) + .addScalar("km", StandardBasicTypes.DOUBLE) + .addScalar("unit", StandardBasicTypes.STRING); + sqlQuery.setString("name", river); + sqlQuery.setString("descr", description); + List results = sqlQuery.list(); + SedimentLoad load = new SedimentLoad(); + if (results.isEmpty()) { + return new SedimentLoad(); + } + Object[] row = results.get(0); + load = new SedimentLoad( + (String) row[0], + (Date) row[1], + (Date) row[2], + false, + (String)row[5]); + + for (int i = 0; i < results.size(); i++) { + row = results.get(i); + SedimentLoadFraction fraction = new SedimentLoadFraction(); + fraction.setUnknown((Double)row[3]); + load.addKm((Double)row[4], fraction); + } + return load; + } + + public static SedimentLoad[] getSedimentLoadUnknown(String river) { + Session session = SessionHolder.HOLDER.get(); + SQLQuery sqlQuery = session.createSQLQuery(SQL_SELECT_UNKNOWN) + .addScalar("description", StandardBasicTypes.STRING) + .addScalar("start", StandardBasicTypes.DATE) + .addScalar("end", StandardBasicTypes.DATE); + sqlQuery.setString("river", river); + List results = sqlQuery.list(); + SedimentLoad[] loads = new SedimentLoad[results.size()]; + int counter = 0; + for (Object[] row: results) { + loads[counter] = new SedimentLoad( + (String)row[0], (Date)row[1], (Date)row[2], false, ""); + counter++; + } + return loads; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r b95504c34060 -r df867072d003 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 Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadFraction.java Mon Jun 24 15:24:07 2013 +0200 @@ -9,28 +9,41 @@ package org.dive4elements.river.artifacts.model.minfo; import org.dive4elements.river.artifacts.model.NamedObjectImpl; +import org.dive4elements.river.artifacts.model.Range; - +/** One part of sedimentload. */ public class SedimentLoadFraction extends NamedObjectImpl { double sand; - double fine_middle; + double fineMiddle; double coarse; - double susp_sand; - double susp_sand_bed; - double susp_sediment; + double suspSand; + double suspSandBed; + double suspSediment; double loadTotal; 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; public SedimentLoadFraction() { sand = 0d; - fine_middle = 0d; + fineMiddle = 0d; coarse = 0d; - susp_sand = 0d; - susp_sand_bed = 0d; - susp_sediment = 0d; + suspSand = 0d; + suspSandBed = 0d; + suspSediment = 0d; loadTotal = 0d; + unknown = 0d; } public double getSand() { @@ -41,12 +54,28 @@ this.sand = sand; } - public double getFine_middle() { - return fine_middle; + public void setSandRange(Range range) { + this.sandRange = range; } - public void setFine_middle(double fine_middle) { - this.fine_middle = fine_middle; + public Range getSandRange() { + return this.sandRange; + } + + public double getFineMiddle() { + return fineMiddle; + } + + public void setFineMiddle(double fineMiddle) { + this.fineMiddle = fineMiddle; + } + + public void setFineMiddleRange(Range range) { + this.fineMiddleRange = range; + } + + public Range getFineMiddleRange() { + return this.fineMiddleRange; } public double getCoarse() { @@ -57,28 +86,60 @@ this.coarse = coarse; } - public double getSusp_sand() { - return susp_sand; - } - - public void setSusp_sand(double susp_sand) { - this.susp_sand = susp_sand; + public Range getCoarseRange() { + return this.coarseRange; } - public double getSusp_sand_bed() { - return susp_sand_bed; + public void setCoarseRange(Range range) { + this.coarseRange = range; } - public void setSusp_sand_bed(double susp_sand_bed) { - this.susp_sand_bed = susp_sand_bed; + public double getSuspSand() { + return suspSand; } - public double getSusp_sediment() { - return susp_sediment; + public void setSuspSand(double suspSand) { + this.suspSand = suspSand; } - public void setSusp_sediment(double susp_sediment) { - this.susp_sediment = susp_sediment; + public void setSuspSandRange(Range range) { + this.suspSandRange = range; + } + + public Range getSuspSandRange() { + return this.suspSandRange; + } + + public double getSuspSandBed() { + return suspSandBed; + } + + public void setSuspSandBed(double suspSandBed) { + this.suspSandBed = suspSandBed; + } + + public void setSuspSandBedRange(Range range) { + this.suspSandRange = range; + } + + public Range getSuspSandBedRange() { + return this.suspSandRange; + } + + public double getSuspSediment() { + return suspSediment; + } + + public void setSuspSediment(double suspSediment) { + this.suspSediment = suspSediment; + } + + public void setSuspSedimentRange(Range range) { + this.suspSedimentRange = range; + } + + public Range getSuspSedimentRange() { + return this.suspSedimentRange; } public double getTotal() { @@ -89,6 +150,14 @@ this.total = total; } + public void setTotalRange(Range range) { + this.totalRange = range; + } + + public Range getTotalRange() { + return this.totalRange; + } + public double getLoadTotal() { return loadTotal; } @@ -96,4 +165,25 @@ public void setLoadTotal(double total) { this.loadTotal = total; } + + public void setLoadTotalRange(Range range) { + this.loadTotalRange = range; + } + + public double getUnknown() { + return unknown; + } + + public void setUnknown(double unknown) { + this.unknown = unknown; + } + + public Range getUnknownRange() { + return unknownRange; + } + + public void setUnknownRange(Range unknownRange) { + this.unknownRange = unknownRange; + } } +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r b95504c34060 -r df867072d003 artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadResult.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadResult.java Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadResult.java Mon Jun 24 15:24:07 2013 +0200 @@ -39,6 +39,10 @@ this.load = load; } + public SedimentLoad getLoad() { + return this.load; + } + public int getStartYear() { return this.startYear; } @@ -94,9 +98,9 @@ TDoubleArrayList k = new TDoubleArrayList(); TDoubleArrayList fm = new TDoubleArrayList(); for (double km : kms) { - if (load.getFraction(km).getFine_middle() > 0d) { + if (load.getFraction(km).getFineMiddle() > 0d) { k.add(km); - fm.add(load.getFraction(km).getFine_middle()); + fm.add(load.getFraction(km).getFineMiddle()); } } return new double [][] { @@ -126,9 +130,9 @@ TDoubleArrayList k = new TDoubleArrayList(); TDoubleArrayList ss = new TDoubleArrayList(); for (double km : kms) { - if (load.getFraction(km).getSusp_sand() > 0d) { + if (load.getFraction(km).getSuspSand() > 0d) { k.add(km); - ss.add(load.getFraction(km).getSusp_sand()); + ss.add(load.getFraction(km).getSuspSand()); } } return new double [][] { @@ -142,9 +146,9 @@ TDoubleArrayList k = new TDoubleArrayList(); TDoubleArrayList ss = new TDoubleArrayList(); for (double km : kms) { - if (load.getFraction(km).getSusp_sand_bed() > 0d) { + if (load.getFraction(km).getSuspSandBed() > 0d) { k.add(km); - ss.add(load.getFraction(km).getSusp_sand_bed()); + ss.add(load.getFraction(km).getSuspSandBed()); } } return new double [][] { @@ -158,9 +162,9 @@ TDoubleArrayList k = new TDoubleArrayList(); TDoubleArrayList ss = new TDoubleArrayList(); for (double km : kms) { - if (load.getFraction(km).getSusp_sediment() > 0d) { + if (load.getFraction(km).getSuspSediment() > 0d) { k.add(km); - ss.add(load.getFraction(km).getSusp_sediment()); + ss.add(load.getFraction(km).getSuspSediment()); } } return new double [][] { diff -r b95504c34060 -r df867072d003 artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadUnknownFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/minfo/SedimentLoadUnknownFacet.java Mon Jun 24 15:24:07 2013 +0200 @@ -0,0 +1,66 @@ +package org.dive4elements.river.artifacts.model.minfo; + +import org.apache.log4j.Logger; +import org.dive4elements.artifactdatabase.state.Facet; +import org.dive4elements.artifacts.Artifact; +import org.dive4elements.artifacts.CallContext; +import org.dive4elements.river.artifacts.D4EArtifact; +import org.dive4elements.river.artifacts.access.SedimentLoadAccess; +import org.dive4elements.river.artifacts.model.DataFacet; +import org.dive4elements.river.artifacts.states.DefaultState.ComputeType; + + +public class SedimentLoadUnknownFacet +extends DataFacet +{ + /** Very own logger. */ + private static Logger logger = Logger.getLogger(SedimentLoadFacet.class); + + public SedimentLoadUnknownFacet() { + } + + public SedimentLoadUnknownFacet(int idx, String name, String description, + ComputeType type, String stateId, String hash) { + 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); + + D4EArtifact flys = (D4EArtifact) artifact; + + SedimentLoadAccess access = new SedimentLoadAccess(flys); + String river = access.getRiver(); + SedimentLoad[] unknown = + SedimentLoadFactory.getSedimentLoadUnknown(river); + + 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; + } + + /** Copy deeply. */ + @Override + public Facet deepCopy() { + SedimentLoadUnknownFacet copy = new SedimentLoadUnknownFacet(); + copy.set(this); + copy.hash = hash; + copy.stateId = stateId; + return copy; + } +} diff -r b95504c34060 -r df867072d003 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 Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/states/minfo/SedimentLoadCalculate.java Mon Jun 24 15:24:07 2013 +0200 @@ -9,10 +9,10 @@ package org.dive4elements.river.artifacts.states.minfo; import java.util.ArrayList; +import java.util.Date; import java.util.List; import org.apache.log4j.Logger; - import org.dive4elements.artifactdatabase.state.Facet; import org.dive4elements.artifactdatabase.state.FacetActivity; import org.dive4elements.artifacts.Artifact; @@ -21,14 +21,17 @@ 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; import org.dive4elements.river.artifacts.model.minfo.SedimentLoadCalculation; import org.dive4elements.river.artifacts.model.minfo.SedimentLoadFacet; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoadFactory; import org.dive4elements.river.artifacts.model.minfo.SedimentLoadResult; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoadUnknownFacet; import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.artifacts.states.DefaultState; +import org.dive4elements.river.utils.DateGuesser; public class SedimentLoadCalculate @@ -70,6 +73,42 @@ name.equals(SEDIMENT_LOAD_SUSP_SAND_BED)){ return Boolean.FALSE; } + else if (name.equals(SEDIMENT_LOAD_UNKOWN)) { + D4EArtifact d4e = (D4EArtifact)artifact; + SedimentLoadUnknownFacet f = + (SedimentLoadUnknownFacet) + d4e.getNativeFacet(facet, null); + SedimentLoad load = + (SedimentLoad)f.getData(artifact, null); + SedimentLoadAccess access = + new SedimentLoadAccess(d4e); + List dates = new ArrayList(); + if (access.getYearEpoch().equals("year")) { + dates.add(access.getPeriod()); + } + else { + int[][] epochs = access.getEpochs(); + for (int i = 0; i < epochs.length; i++) { + dates.add(epochs[i]); + } + } + for (int[] date: dates) { + try { + Date s = + DateGuesser.guessDate(String.valueOf(date[0])); + Date e = + DateGuesser.guessDate(String.valueOf(date[1])); + if (!(s.after(load.getEnd()) || + e.before(load.getStart()))) { + return Boolean.TRUE; + } + } + catch (IllegalArgumentException iae) { + return Boolean.FALSE; + } + } + return Boolean.FALSE; + } else { return null; } @@ -100,6 +139,10 @@ 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); @@ -114,6 +157,16 @@ if (res.getReport().hasProblems()) { newFacets.add(new ReportFacet(ComputeType.ADVANCE, hash, id)); } + + for (int i = 0; i < unknown.length; i++) { + newFacets.add(new SedimentLoadUnknownFacet( + i, + SEDIMENT_LOAD_UNKOWN, + unknown[i].getDescription(), + ComputeType.ADVANCE, + getID(), + hash)); + } facets.addAll(newFacets); return res; diff -r b95504c34060 -r df867072d003 artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/ComputedDischargeCurveGenerator.java Mon Jun 24 15:24:07 2013 +0200 @@ -199,7 +199,7 @@ Document theme, boolean visible ) { - logger.debug("ComputedDischargeCurveGenerator: doWQOut"); + logger.debug("ComputedDischargeCurveGenerator: doQOut"); XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme); StyledSeriesBuilder.addPointsQW(series, wqkms); diff -r b95504c34060 -r df867072d003 artifacts/src/main/java/org/dive4elements/river/exports/minfo/SedimentLoadLSGenerator.java --- a/artifacts/src/main/java/org/dive4elements/river/exports/minfo/SedimentLoadLSGenerator.java Fri Jun 21 14:35:18 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/minfo/SedimentLoadLSGenerator.java Mon Jun 24 15:24:07 2013 +0200 @@ -9,6 +9,7 @@ package org.dive4elements.river.exports.minfo; import java.util.Arrays; +import java.util.Set; import org.apache.log4j.Logger; import org.jfree.data.xy.XYSeries; @@ -24,6 +25,8 @@ import org.dive4elements.river.artifacts.model.WKms; import org.dive4elements.river.artifacts.model.minfo.BedDiffEpochResult; import org.dive4elements.river.artifacts.model.minfo.BedDiffYearResult; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoad; +import org.dive4elements.river.artifacts.model.minfo.SedimentLoadFraction; import org.dive4elements.river.exports.StyledSeriesBuilder; import org.dive4elements.river.exports.XYChartGenerator; import org.dive4elements.river.jfree.Bounds; @@ -145,6 +148,13 @@ attr, visible); } + else if (FacetTypes.IS.SEDIMENT_LOAD_UNKNOWN(name)) { + doSedimentLoadUnknownOut( + (SedimentLoad)bundle.getData(context), + bundle, + attr, + visible); + } else if (name.equals(FLOW_VELOCITY_TOTALCHANNEL)) { doFlowVelocityTotalOut( (FlowVelocityData) bundle.getData(context), @@ -257,6 +267,24 @@ addAxisSeries(series, YAXIS.L.idx, visible); } + protected void doSedimentLoadUnknownOut(SedimentLoad load, + ArtifactAndFacet aandf, Document theme, boolean visible) { + + Set kms = load.getKms(); + double[][] data = new double[2][kms.size()]; + int counter = 0; + for (Double km: kms) { + SedimentLoadFraction fraction = load.getFraction(km); + data[0][counter] = km; + data[1][counter] = fraction.getUnknown(); + counter++; + } + XYSeries series = new StyledXYSeries(aandf.getFacetDescription(), theme); + StyledSeriesBuilder.addPoints(series, data, false); + + addAxisSeries(series, YAXIS.L.idx, visible); + } + protected void doFlowVelocityMainOut( FlowVelocityData data, ArtifactAndFacet aandf, diff -r b95504c34060 -r df867072d003 backend/doc/schema/oracle.sql --- a/backend/doc/schema/oracle.sql Fri Jun 21 14:35:18 2013 +0200 +++ b/backend/doc/schema/oracle.sql Mon Jun 24 15:24:07 2013 +0200 @@ -351,9 +351,8 @@ id NUMBER(38,0) NOT NULL, wst_column_id NUMBER(38,0) NOT NULL, named_main_value_id NUMBER(38,0) NOT NULL, - - PRIMARY KEY (id), - UNIQUE (wst_column_id, named_main_value_id) + UNIQUE (wst_column_id, named_main_value_id), + PRIMARY KEY (id) ); -- WSTS diff -r b95504c34060 -r df867072d003 backend/src/main/java/org/dive4elements/river/importer/parsers/PRFParser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/PRFParser.java Fri Jun 21 14:35:18 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/PRFParser.java Mon Jun 24 15:24:07 2013 +0200 @@ -364,13 +364,13 @@ List kmData = data.get(station); - // When the station changed we know we are expecting skip/dummy lines. + // When the station changed (no data yet in line) we expect + // skip/dummy lines to follow if (kmData == null) { - //log.debug("found new km: " + station); kmData = new ArrayList(); data.put(station, kmData); // When a station change occurs, dummy lines will occur, too. - skip = lineSkipCount; + skip = lineSkipCount -1; continue; } diff -r b95504c34060 -r df867072d003 backend/src/main/java/org/dive4elements/river/model/OfficialLine.java --- a/backend/src/main/java/org/dive4elements/river/model/OfficialLine.java Fri Jun 21 14:35:18 2013 +0200 +++ b/backend/src/main/java/org/dive4elements/river/model/OfficialLine.java Mon Jun 24 15:24:07 2013 +0200 @@ -9,6 +9,7 @@ package org.dive4elements.river.model; import java.io.Serializable; +import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; @@ -20,6 +21,9 @@ import javax.persistence.SequenceGenerator; import javax.persistence.Table; +import org.dive4elements.river.backend.SessionHolder; +import org.hibernate.Session; + @Entity @Table(name = "official_lines") public class OfficialLine @@ -74,5 +78,10 @@ public void setNamedMainValue(NamedMainValue namedMainValue) { this.namedMainValue = namedMainValue; } + + public static List fetchAllOfficalLines() { + Session session = SessionHolder.HOLDER.get(); + return session.createQuery("from OfficialLine").list(); + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r b95504c34060 -r df867072d003 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 Fri Jun 21 14:35:18 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java Mon Jun 24 15:24:07 2013 +0200 @@ -1301,5 +1301,7 @@ String WATERBODY(); String FEDSTATE_KM(); + + String official_regulation(); } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r b95504c34060 -r df867072d003 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 Fri Jun 21 14:35:18 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties Mon Jun 24 15:24:07 2013 +0200 @@ -681,3 +681,5 @@ SOURCE = Source WATERBODY = Waterbody FEDSTATE_KM = Station (Federal State) + +official_regulation = official Regulation diff -r b95504c34060 -r df867072d003 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 Fri Jun 21 14:35:18 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties Mon Jun 24 15:24:07 2013 +0200 @@ -680,3 +680,4 @@ SOURCE = Quelle WATERBODY = Gewässer FEDSTATE_KM = Landes-Stationierung +official_regulation = amtl. Festlegung diff -r b95504c34060 -r df867072d003 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 Fri Jun 21 14:35:18 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties Mon Jun 24 15:24:07 2013 +0200 @@ -621,4 +621,4 @@ # Get Feature Info Window PATH = Path - +official_regulation = Official Regulation diff -r b95504c34060 -r df867072d003 gwt-client/src/main/java/org/dive4elements/river/client/client/ui/map/MapPrintPanel.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/map/MapPrintPanel.java Fri Jun 21 14:35:18 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/map/MapPrintPanel.java Mon Jun 24 15:24:07 2013 +0200 @@ -22,6 +22,7 @@ import org.dive4elements.river.client.shared.model.Property; import org.dive4elements.river.client.shared.model.PropertySetting; import org.dive4elements.river.client.shared.model.Settings; +import org.dive4elements.river.client.shared.MapUtils; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.Window; @@ -274,18 +275,19 @@ catch (MissingResourceException mre) { localized = props.getName(); } - url.append(toJavaEncodedString(localized)); + url.append(MapUtils.toSaveHTMLJavaString(localized)); url.append("="); - url.append(props.getValue()); + url.append(MapUtils.toSaveHTMLJavaString((String)props.getValue())); } } // O.o String river = findRiver(((MapOutputTab)mapToolbar.getOutputTab() ).getCollectionView().getArtifact()); - url.append("&" + toJavaEncodedString(MSG.getString(MAPFISH_RIVER)) + "=" + river); + url.append("&" + MapUtils.toSaveHTMLJavaString(MSG.getString(MAPFISH_RIVER)) + "=" + + MapUtils.toSaveHTMLJavaString(river)); } - // Copy of DatacageWindow's findRiver + // Copy of DatacageWindow's findRiver with added state for map.river protected String findRiver(Artifact artifact) { ArtifactDescription adescr = artifact.getArtifactDescription(); DataList [] data = adescr.getOldData(); @@ -293,7 +295,8 @@ if (data != null && data.length > 0) { for (int i = 0; i < data.length; i++) { DataList dl = data[i]; - if (dl.getState().equals("state.winfo.river")) { + if (dl.getState().equals("state.winfo.river") || + dl.getState().equals("state.map.river")) { for (int j = dl.size()-1; j >= 0; --j) { Data d = dl.get(j); DataItem [] di = d.getItems(); @@ -308,26 +311,6 @@ return ""; } - public static String toJavaEncodedString(String str) { - if (str == null) { - return null; - } - StringBuilder sb = new StringBuilder(); - for (int i = 0, len = str.length(); i < len; i++) { - int unipoint = Character.codePointAt(str, i); - if ((unipoint < 32) || (unipoint > 127)) { - sb.append("\\u"); - sb.append(Integer.toHexString((unipoint >> 3*4) & 0xf)); - sb.append(Integer.toHexString((unipoint >> 2*4) & 0xf)); - sb.append(Integer.toHexString((unipoint >> 1*4) & 0xf)); - sb.append(Integer.toHexString((unipoint >> 0*4) & 0xf)); - } else { - sb.append(str.charAt(i)); - } - } - return sb.toString(); - } - protected void updateCollection() { final Config config = Config.getInstance(); final String loc = config.getLocale(); @@ -335,16 +318,16 @@ GWT.log("MapPrintPanel.updateCollection via RPC now"); List properties = new ArrayList(); - properties.add(new PropertySetting(MAPFISH_MAPTITLE, toJavaEncodedString(pageTitle.getValueAsString()))); -// properties.add(new PropertySetting(MAPFISH_LAYOUT, toJavaEncodedString(pageFormat.getValueAsString()))); - properties.add(new PropertySetting(MAPFISH_SUBTITLE, toJavaEncodedString(pageSubtitle.getValueAsString()))); - properties.add(new PropertySetting(MAPFISH_RANGE, toJavaEncodedString(pageRange.getValueAsString()))); - properties.add(new PropertySetting(MAPFISH_STRETCH, toJavaEncodedString(pageStretch.getValueAsString()))); - properties.add(new PropertySetting(MAPFISH_INSTITUTION, toJavaEncodedString(pageInstitution.getValueAsString()))); - properties.add(new PropertySetting(MAPFISH_SOURCE, toJavaEncodedString(pageSource.getValueAsString()))); - properties.add(new PropertySetting(MAPFISH_CREATOR, toJavaEncodedString(pageCreator.getValueAsString()))); - properties.add(new PropertySetting(MAPFISH_DATEPLACE, toJavaEncodedString(pageDatePlace.getValueAsString()))); - properties.add(new PropertySetting(MAPFISH_LOGO, toJavaEncodedString(pageLogo.getValueAsString()))); + properties.add(new PropertySetting(MAPFISH_MAPTITLE, pageTitle.getValueAsString())); +// properties.add(new PropertySetting(MAPFISH_LAYOUT, pageFormat.getValueAsString())); + properties.add(new PropertySetting(MAPFISH_SUBTITLE, pageSubtitle.getValueAsString())); + properties.add(new PropertySetting(MAPFISH_RANGE, pageRange.getValueAsString())); + properties.add(new PropertySetting(MAPFISH_STRETCH, pageStretch.getValueAsString())); + properties.add(new PropertySetting(MAPFISH_INSTITUTION, pageInstitution.getValueAsString())); + properties.add(new PropertySetting(MAPFISH_SOURCE, pageSource.getValueAsString())); + properties.add(new PropertySetting(MAPFISH_CREATOR, pageCreator.getValueAsString())); + properties.add(new PropertySetting(MAPFISH_DATEPLACE, pageDatePlace.getValueAsString())); + properties.add(new PropertySetting(MAPFISH_LOGO, pageLogo.getValueAsString())); settings.setSettings("default", properties); collection.addSettings("print-settings", settings); diff -r b95504c34060 -r df867072d003 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 Fri Jun 21 14:35:18 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/wq/QDTable.java Mon Jun 24 15:24:07 2013 +0200 @@ -66,7 +66,7 @@ ListGridField type = new ListGridField("type", MESSAGE.type()); type.setType(ListGridFieldType.TEXT); - type.setWidth("20%"); + type.setWidth("10%"); final NumberFormat nf = NumberFormat.getDecimalFormat(); @@ -88,9 +88,14 @@ } } }); - value.setWidth("20%"); + value.setWidth("15%"); - setFields(addMax, addMin, select, name, type, value); + ListGridField official = new ListGridField("official", MESSAGE.official_regulation()); + official.setType(ListGridFieldType.TEXT); + official.setWidth("25%"); + + + setFields(addMax, addMin, select, name, type, value, official); } public void hideIconFields () { diff -r b95504c34060 -r df867072d003 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 Fri Jun 21 14:35:18 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/MapPrintServiceImpl.java Mon Jun 24 15:24:07 2013 +0200 @@ -212,7 +212,7 @@ Map legend = new LinkedHashMap(); List classes = new ArrayList(1); Map clazz = new LinkedHashMap(); - String lgu = MapUtils.getLegendGraphicUrl(layer.url, layer.layers, dpi); + String lgu = encode(MapUtils.getLegendGraphicUrl(layer.url, layer.layers, dpi)); clazz.put("icon", lgu); clazz.put("name", layer.description); classes.add(clazz); @@ -399,6 +399,7 @@ private static final String encode(String s) { try { + if (s == null) return null; return URLEncoder.encode(s, "UTF-8"); } catch (UnsupportedEncodingException usee) { diff -r b95504c34060 -r df867072d003 gwt-client/src/main/java/org/dive4elements/river/client/server/WQInfoServiceImpl.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/server/WQInfoServiceImpl.java Fri Jun 21 14:35:18 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/server/WQInfoServiceImpl.java Mon Jun 24 15:24:07 2013 +0200 @@ -195,12 +195,16 @@ String value = XMLUtils.xpathString( node, "@value", ArtifactNamespaceContext.INSTANCE); + String official = XMLUtils.xpathString( + node, "@official", ArtifactNamespaceContext.INSTANCE); + if (name != null && type != null) { try { return new WQInfoObjectImpl( name, type, - new Double(value)); + new Double(value), + official != null && official.equalsIgnoreCase("true")); } catch (NumberFormatException nfe) { logger.warn(nfe.getLocalizedMessage()); diff -r b95504c34060 -r df867072d003 gwt-client/src/main/java/org/dive4elements/river/client/shared/MapUtils.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/MapUtils.java Fri Jun 21 14:35:18 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/MapUtils.java Mon Jun 24 15:24:07 2013 +0200 @@ -10,6 +10,8 @@ import java.util.Date; +import com.google.gwt.safehtml.shared.SafeHtmlUtils; + public class MapUtils { @@ -47,5 +49,29 @@ return url; } + + public static String toSaveHTMLJavaString(String str) { + return str == null ? null : SafeHtmlUtils.htmlEscape(toJavaEncodedString(str)); + } + + public static String toJavaEncodedString(String str) { + if (str == null) { + return null; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0, len = str.length(); i < len; i++) { + int unipoint = Character.codePointAt(str, i); + if ((unipoint < 32) || (unipoint > 127)) { + sb.append("\\u"); + sb.append(Integer.toHexString((unipoint >> 3*4) & 0xf)); + sb.append(Integer.toHexString((unipoint >> 2*4) & 0xf)); + sb.append(Integer.toHexString((unipoint >> 1*4) & 0xf)); + sb.append(Integer.toHexString((unipoint >> 0*4) & 0xf)); + } else { + sb.append(str.charAt(i)); + } + } + return sb.toString(); + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r b95504c34060 -r df867072d003 gwt-client/src/main/java/org/dive4elements/river/client/shared/model/WQInfoObject.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/WQInfoObject.java Fri Jun 21 14:35:18 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/WQInfoObject.java Mon Jun 24 15:24:07 2013 +0200 @@ -21,5 +21,7 @@ String getType(); Double getValue(); + + boolean isOfficial(); } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r b95504c34060 -r df867072d003 gwt-client/src/main/java/org/dive4elements/river/client/shared/model/WQInfoObjectImpl.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/WQInfoObjectImpl.java Fri Jun 21 14:35:18 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/WQInfoObjectImpl.java Mon Jun 24 15:24:07 2013 +0200 @@ -20,6 +20,8 @@ protected Double value; + protected boolean isOfficial; + public WQInfoObjectImpl() { } @@ -28,26 +30,36 @@ public WQInfoObjectImpl( String name, String type, - Double value) - { + Double value, + boolean isOfficial + ) { this.name = name; this.type = type; this.value = value; + this.isOfficial = isOfficial; } + @Override public String getName() { return name; } + @Override public String getType() { return type; } + @Override public Double getValue() { return value; } + + @Override + public boolean isOfficial() { + return isOfficial; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r b95504c34060 -r df867072d003 gwt-client/src/main/java/org/dive4elements/river/client/shared/model/WQInfoRecord.java --- a/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/WQInfoRecord.java Fri Jun 21 14:35:18 2013 +0200 +++ b/gwt-client/src/main/java/org/dive4elements/river/client/shared/model/WQInfoRecord.java Mon Jun 24 15:24:07 2013 +0200 @@ -33,10 +33,8 @@ setName(info.getName()); setType(info.getType()); - if (info.getValue() != null) - setValue(info.getValue()); - else - setValue(info.getValue()); + setValue(info.getValue()); + setOfficial(info.isOfficial() ? "X" : ""); } @@ -68,6 +66,14 @@ return getAttributeAsDouble("value"); } + public void setOfficial(String value) { + setAttribute("official", value); + } + + public String getOfficial() { + return getAttributeAsString("official"); + } + public WQInfoObject getWQInfo() { return wqInfo; diff -r b95504c34060 -r df867072d003 gwt-client/src/main/webapp/images/FLYS_Karte_interactive.html --- a/gwt-client/src/main/webapp/images/FLYS_Karte_interactive.html Fri Jun 21 14:35:18 2013 +0200 +++ b/gwt-client/src/main/webapp/images/FLYS_Karte_interactive.html Mon Jun 24 15:24:07 2013 +0200 @@ -54,7 +54,7 @@
- +