teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.utils; ingo@1095: teichmann@5831: import org.dive4elements.artifactdatabase.state.State; teichmann@5831: import org.dive4elements.artifacts.Artifact; teichmann@5831: import org.dive4elements.artifacts.CallContext; teichmann@5831: import org.dive4elements.artifacts.common.utils.Config; teichmann@5831: import org.dive4elements.artifacts.common.utils.XMLUtils; teichmann@5867: import org.dive4elements.river.artifacts.D4EArtifact; teichmann@5831: import org.dive4elements.river.artifacts.StaticWKmsArtifact; teichmann@5831: import org.dive4elements.river.artifacts.WINFOArtifact; teichmann@5831: import org.dive4elements.river.artifacts.access.RangeAccess; teichmann@5866: import org.dive4elements.river.artifacts.context.RiverContext; teichmann@5831: import org.dive4elements.river.artifacts.model.LocationProvider; teichmann@5831: import org.dive4elements.river.artifacts.model.RiverFactory; teichmann@5831: import org.dive4elements.river.artifacts.model.WKms; teichmann@5831: import org.dive4elements.river.artifacts.model.WQ; teichmann@5831: import org.dive4elements.river.artifacts.model.WQKms; teichmann@5831: import org.dive4elements.river.artifacts.states.WDifferencesState; teichmann@5831: import org.dive4elements.river.artifacts.states.WaterlevelSelectState; teichmann@5831: import org.dive4elements.river.backend.SessionFactoryProvider; teichmann@5831: import org.dive4elements.river.model.Gauge; teichmann@5831: import org.dive4elements.river.model.MainValue; teichmann@5831: import org.dive4elements.river.model.River; christian@4648: christian@4648: import gnu.trove.TDoubleArrayList; christian@4648: import gnu.trove.TIntArrayList; christian@4648: import gnu.trove.TLongArrayList; ingo@1740: ingo@1740: import java.text.NumberFormat; ingo@1105: import java.util.HashMap; ingo@1740: import java.util.List; ingo@1105: import java.util.Map; ingo@2068: import java.util.regex.Matcher; ingo@2068: import java.util.regex.Pattern; ingo@1105: ingo@1105: import javax.xml.xpath.XPathConstants; ingo@1105: christian@4648: import org.apache.log4j.Logger; ingo@1845: import org.hibernate.SessionFactory; ingo@1845: import org.hibernate.impl.SessionFactoryImpl; christian@4648: import org.w3c.dom.Document; ingo@1095: felix@3047: bjoern@4635: /** teichmann@5867: * Static helper methods to e.g. access D4EArtifacts data. bjoern@4635: * teichmann@5865: * @deprecated Don't use RiverUtils to get data from an {@link Artifact} anymore. bjoern@4635: * Instead use and/or create a {@link Access} class hierarchy. bjoern@4635: **/ bjoern@4635: @Deprecated teichmann@5865: public class RiverUtils { ingo@1095: felix@1150: /** The logger that is used in this utility. */ teichmann@5865: private static Logger logger = Logger.getLogger(RiverUtils.class); felix@1150: ingo@2038: /** ingo@2038: * An enum that represents the 5 possible WQ modes in FLYS. The 5 values are ingo@2038: * QFREE QGAUGE WGAUGE WFREE and NONE. ingo@2038: */ ingo@2038: public static enum WQ_MODE { QFREE, QGAUGE, WFREE, WGAUGE, NONE }; ingo@2038: ingo@2422: /** ingo@2422: * An enum that represents the 4 possible WQ input modes in FLYS. The 4 ingo@2422: * values are ingo@2422: * ADAPTED SINGLE RANGE and NONE. ingo@2422: */ ingo@2422: public static enum WQ_INPUT { ADAPTED, SINGLE, RANGE, NONE }; ingo@2068: ingo@2068: public static final Pattern NUMBERS_PATTERN = ingo@2068: Pattern.compile("\\D*(\\d++.\\d*)\\D*"); ingo@2068: christian@4656: public static final String XPATH_FLOODMAP_RIVER_PROJECTION = ingo@1105: "/artifact-database/floodmap/river[@name=$name]/srid/@value"; ingo@1105: rrenkert@4994: public static final String XPATH_FLOODMAP_DGM_PROJECTION = rrenkert@4994: "/artifact-database/floodmap/river[@name=$name]/dgm-srid/@value"; rrenkert@4994: christian@4656: public static final String XPATH_FLOODMAP_SHAPEFILE_DIR = ingo@1129: "/artifact-database/floodmap/shapefile-path/@value"; ingo@1129: christian@4656: public static final String XPATH_FLOODMAP_VELOCITY_LOGFILE = ingo@1129: "/artifact-database/floodmap/velocity/logfile/@path"; ingo@1129: christian@4656: public static final String XPATH_FLOODMAP_MAPSERVER_URL = ingo@1129: "/artifact-database/floodmap/mapserver/server/@path"; ingo@1129: christian@4864: public static final String XPATH_RIVERMAP_MAPSERVER_URL = christian@4864: "/artifact-database/rivermap/mapserver/server/@path"; christian@4864: christian@4656: public static final String XPATH_FLOODMAP_MAPFILE_PATH = ingo@1129: "/artifact-database/floodmap/mapserver/mapfile/@path"; ingo@1129: christian@4656: public static final String XPATH_FLOODMAP_MAPFILE_TEMPLATE = ingo@1129: "/artifact-database/floodmap/mapserver/map-template/@path"; ingo@1129: christian@4656: public static final String XPATH_FLOODMAP_MAPSERVER_TEMPLATE_PATH = ingo@1129: "/artifact-database/floodmap/mapserver/templates/@path"; ingo@1129: ingo@1095: teichmann@5865: private RiverUtils() { ingo@1095: } ingo@1095: ingo@1095: felix@2017: /** felix@2017: * Pulls Artifact with given UUID fromm database. teichmann@5867: * @return D4EArtifact with given UUID or null (in case of errors). felix@2017: */ teichmann@5867: public static D4EArtifact getArtifact(String uuid, CallContext context) { felix@1150: try { ingo@1174: Artifact artifact = context.getDatabase().getRawArtifact(uuid); ingo@1174: ingo@1174: if (artifact == null) { ingo@1174: logger.error("Artifact '" + uuid + "' does not exist."); ingo@1174: return null; ingo@1174: } ingo@1174: teichmann@5867: if (!(artifact instanceof D4EArtifact)) { teichmann@5867: logger.error("Artifact '" +uuid+ "' is no valid D4EArtifact."); ingo@1174: return null; ingo@1174: } ingo@1174: teichmann@5867: return (D4EArtifact) artifact; felix@1150: } felix@1150: // TODO: catch more selective felix@1150: catch (Exception e) { teichmann@5867: logger.error("Cannot get D4EArtifact " + uuid felix@2017: + " from database (" + e.getMessage() + ")."); felix@1150: return null; felix@1150: } ingo@1118: } ingo@1118: ingo@1118: ingo@1129: /** teichmann@5866: * Returns the RiverContext from context object. felix@1777: * teichmann@5866: * @param context The CallContext or the RiverContext. teichmann@5866: * teichmann@5866: * @return the RiverContext. felix@1777: */ teichmann@5866: public static RiverContext getFlysContext(Object context) { teichmann@5866: return context instanceof RiverContext teichmann@5866: ? (RiverContext) context teichmann@5866: : (RiverContext) ((CallContext) context).globalContext(); felix@1777: } felix@1777: felix@1777: felix@1777: /** ingo@1129: * Convinience function to retrieve an XPath as string with replaced config ingo@1129: * directory. ingo@1129: * ingo@1129: * @param xpath The XPath expression. ingo@1129: * ingo@1129: * @return a string with replaced config directory. ingo@1129: */ ingo@1129: public static String getXPathString(String xpath) { ingo@1129: String tmp = Config.getStringXPath(xpath); ingo@1129: tmp = Config.replaceConfigDir(tmp); ingo@1129: ingo@1129: return tmp; ingo@1129: } ingo@1129: ingo@1129: ingo@1845: public static boolean isUsingOracle() { ingo@1845: SessionFactory sf = SessionFactoryProvider.getSessionFactory(); ingo@1845: ingo@1845: String d = SessionFactoryProvider.getDriver((SessionFactoryImpl) sf); ingo@1845: ingo@1845: return d != null ? d.indexOf("Oracle") >= 0 : false; ingo@1845: } ingo@1845: ingo@1845: ingo@2038: /** felix@6528: * Returns an WQ_MODE enum which is based on the parameters ingo@2423: * stored in flys Artifact. If there is no wq_isq parameter ingo@2038: * existing, WQ_MODE.NONE is returned. ingo@2038: * teichmann@5867: * @param flys The D4EArtifact that stores wq mode relevant parameters. ingo@2038: * ingo@2038: * @return an enum WQ_MODE. ingo@2038: */ teichmann@5867: public static WQ_MODE getWQMode(D4EArtifact flys) { ingo@2081: if (flys == null) { ingo@2081: return WQ_MODE.NONE; ingo@2081: } ingo@2081: ingo@2422: String values = flys.getDataAsString("wq_values"); felix@3444: Boolean isQ = flys.getDataAsBoolean("wq_isq"); ingo@2038: ingo@2422: if (values != null) { ingo@2422: return isQ ? WQ_MODE.QGAUGE : WQ_MODE.WGAUGE; ingo@2038: } ingo@2422: ingo@2423: Boolean isFree = flys.getDataAsBoolean("wq_isfree"); ingo@2422: felix@4413: if (isQ != null && isQ) { ingo@2422: return isFree ? WQ_MODE.QFREE : WQ_MODE.QGAUGE; ingo@2422: } felix@4413: else if (isQ != null && !isQ) { ingo@2422: return isFree ? WQ_MODE.WFREE : WQ_MODE.WGAUGE; ingo@2038: } ingo@2038: else { ingo@2038: return WQ_MODE.NONE; ingo@2038: } ingo@2038: } ingo@2038: ingo@2038: teichmann@5867: public static WQ_INPUT getWQInputMode(D4EArtifact flys) { ingo@2422: if (flys == null) { ingo@2422: return WQ_INPUT.NONE; ingo@2422: } ingo@2422: ingo@2423: Boolean selection = flys.getDataAsBoolean("wq_isrange"); ingo@2422: String adapted = flys.getDataAsString("wq_values"); ingo@2422: ingo@2422: if(adapted != null && adapted.length() > 0) { ingo@2422: return WQ_INPUT.ADAPTED; ingo@2422: } ingo@2422: ingo@2422: if (selection != null && selection) { ingo@2422: return WQ_INPUT.RANGE; ingo@2422: } ingo@2422: else { ingo@2422: return WQ_INPUT.SINGLE; ingo@2422: } ingo@2422: } ingo@2422: ingo@1095: felix@2235: /** felix@2235: * Get bounds for river of artifact. felix@2235: * @param flysArtifact artifact which has a "river" data. felix@2235: * @return double array. min is at[0], max at[1]. null if given artifact is null felix@2235: */ teichmann@5867: public static double[] getRiverMinMax(D4EArtifact flysArtifact) { felix@2235: if (flysArtifact == null) { felix@2235: return null; felix@2235: } felix@2235: felix@2235: String riverName = flysArtifact.getDataAsString("river"); felix@2235: felix@2235: if (riverName == null) { felix@2235: riverName = ""; felix@2235: } felix@2235: felix@2235: logger.debug("Search for the min/max distances of '" + riverName + "'"); felix@2235: felix@2235: River river = RiverFactory.getRiver(riverName); felix@2235: felix@2235: return river != null felix@2235: ? river.determineMinMaxDistance() felix@2235: : null; felix@2235: } felix@2235: felix@2235: teichmann@5867: public static double[] getKmFromTo(D4EArtifact flys) { ingo@1095: String strFrom = flys.getDataAsString("ld_from"); ingo@1095: String strTo = flys.getDataAsString("ld_to"); ingo@1095: felix@3444: if (strFrom == null) { felix@3444: strFrom = flys.getDataAsString("from"); felix@3444: } felix@3444: felix@3444: if (strTo == null) { felix@3444: strTo = flys.getDataAsString("to"); felix@3444: } felix@3444: ingo@1095: if (strFrom == null || strTo == null) { ingo@1095: return null; ingo@1095: } ingo@1095: ingo@1095: try { ingo@1095: return new double[] { ingo@1095: Double.parseDouble(strFrom), ingo@1095: Double.parseDouble(strTo) }; ingo@1095: } ingo@1095: catch (NumberFormatException nfe) { ingo@1095: return null; ingo@1095: } ingo@1095: } ingo@1095: ingo@1095: felix@2041: /** felix@2041: * Return sorted array of locations at which stuff was calculated felix@2041: * (from ld_locations data), null if not parameterized this way. felix@2041: */ felix@4851: // TODO moved to RangeAccess. Resolve remaining calls. teichmann@5867: private static double[] getLocations(D4EArtifact flys) { ingo@1095: String locationStr = flys.getDataAsString("ld_locations"); ingo@1095: ingo@1095: if (locationStr == null || locationStr.length() == 0) { felix@2765: if (flys instanceof WINFOArtifact) { felix@2765: WINFOArtifact winfo = (WINFOArtifact) flys; felix@4616: if (winfo.getReferenceStartKm() != null && winfo.getReferenceEndKms() != null) { felix@2765: return new double[] felix@2765: { felix@2765: winfo.getReferenceStartKm().doubleValue(), felix@2765: winfo.getReferenceEndKms()[0] felix@2765: }; felix@2765: } felix@2765: } ingo@1095: return null; ingo@1095: } ingo@1095: ingo@1095: String[] tmp = locationStr.split(" "); ingo@1095: TDoubleArrayList locations = new TDoubleArrayList(); ingo@1095: ingo@1095: for (String l: tmp) { ingo@1095: try { ingo@1095: locations.add(Double.parseDouble(l)); ingo@1095: } ingo@1095: catch (NumberFormatException nfe) { christian@4656: logger.debug(nfe.getLocalizedMessage(), nfe); ingo@1095: } ingo@1095: } ingo@1095: ingo@1095: locations.sort(); ingo@1095: ingo@1095: return locations.toNativeArray(); ingo@1095: } felix@1099: felix@1099: felix@1099: /** teichmann@5867: * Returns the Qs for a given D4EArtifact. This method currently accepts ingo@2045: * only instances of WINFOArtifact. ingo@2045: * teichmann@5867: * @param flys A D4EArtifact. ingo@2045: * ingo@2045: * @return the Qs. ingo@2045: */ teichmann@5867: public static double[] getQs(D4EArtifact flys) { ingo@2045: // XXX this is not nice! ingo@2045: if (flys instanceof WINFOArtifact) { ingo@2423: return ((WINFOArtifact) flys).getQs(); ingo@2045: } ingo@2045: felix@6529: logger.warn("This method (getQs) currently supports WINFOArtifact only!"); ingo@2045: ingo@2045: return null; ingo@2045: } ingo@2045: ingo@2045: ingo@2045: /** teichmann@5867: * Returns the Ws for a given D4EArtifact. This method currently accepts ingo@2045: * only instances of WINFOArtifact. ingo@2045: * teichmann@5867: * @param flys A D4EArtifact. ingo@2045: * ingo@2045: * @return the Ws. ingo@2045: */ teichmann@5867: public static double[] getWs(D4EArtifact flys) { ingo@2045: // XXX this is not nice! ingo@2045: if (flys instanceof WINFOArtifact) { ingo@2422: return ((WINFOArtifact) flys).getWs(); ingo@2045: } ingo@2045: felix@6529: logger.warn("This method (getWs) currently supports WINFOArtifact only!"); ingo@2045: ingo@2045: return null; ingo@2045: } ingo@2045: ingo@2045: ingo@2045: /** felix@1099: * Returns the selected River object based on the 'river' data that might felix@1099: * have been inserted by the user. felix@1099: * felix@1099: * @return the selected River or null if no river has been chosen yet. felix@1099: */ teichmann@5867: public static River getRiver(D4EArtifact flys) { ingo@2045: String sRiver = getRivername(flys); felix@1099: felix@1099: return (sRiver != null) felix@1099: ? RiverFactory.getRiver(sRiver) felix@1099: : null; felix@1099: } ingo@1105: ingo@1105: ingo@1105: /** ingo@2045: * Returns the name of the river specified in the given flys ingo@2045: * Artifact. ingo@2045: * teichmann@5867: * @param flys The D4EArtifact that stores a river relevant information. ingo@2045: * ingo@2045: * @return the name of the specified river or null. ingo@2045: */ teichmann@5867: public static String getRivername(D4EArtifact flys) { ingo@2045: return flys != null ? flys.getDataAsString("river") : null; ingo@2045: } ingo@2045: ingo@2045: ingo@2045: /** ingo@1105: * Extracts the SRID defined in the global configuration for the river ingo@1105: * specified in artifact. ingo@1105: * teichmann@5867: * @param artifact The D4EArtifact that stores the name of the river. ingo@1105: * ingo@1105: * @return the SRID as string (e.g. "31466"). ingo@1105: */ teichmann@5867: public static String getRiverSrid(D4EArtifact artifact) { ingo@1105: String river = artifact.getDataAsString("river"); ingo@1105: ingo@1105: if (river == null || river.length() == 0) { ingo@1105: return null; ingo@1105: } ingo@1105: ingo@1805: return getRiverSrid(river); ingo@1805: } ingo@1805: ingo@1805: ingo@1805: public static String getRiverSrid(String rivername) { ingo@1105: Map variables = new HashMap(1); ingo@1805: variables.put("name", rivername); ingo@1105: ingo@1105: Document cfg = Config.getConfig(); ingo@1105: ingo@1105: return (String) XMLUtils.xpath( ingo@1105: cfg, christian@4656: XPATH_FLOODMAP_RIVER_PROJECTION, ingo@1105: XPathConstants.STRING, ingo@1105: null, ingo@1105: variables); ingo@1105: } ingo@1740: rrenkert@4994: public static String getRiverDGMSrid(String rivername) { rrenkert@4994: Map variables = new HashMap(1); rrenkert@4994: variables.put("name", rivername); rrenkert@4994: rrenkert@4994: Document cfg = Config.getConfig(); rrenkert@4994: rrenkert@4994: String dgm = (String) XMLUtils.xpath( rrenkert@4994: cfg, rrenkert@4994: XPATH_FLOODMAP_DGM_PROJECTION, rrenkert@4994: XPathConstants.STRING, rrenkert@4994: null, rrenkert@4994: variables); rrenkert@4994: if (logger.isDebugEnabled()) { rrenkert@4994: logger.debug("Use EPSG:" + dgm + " for DGM"); rrenkert@4994: } rrenkert@4994: return dgm; rrenkert@4994: } ingo@1740: felix@3284: /** felix@3284: * Return the (first) Gauge corresponding to the given location(s) of felix@3284: * the artifact. felix@3284: * @param flys the artifact in question. felix@3284: * @return (First) gauge of locations of river of artifact. felix@3284: */ teichmann@5867: public static Gauge getGauge(D4EArtifact flys) { ingo@2045: River river = getRiver(flys); ingo@2045: ingo@2045: if (river == null) { ingo@2045: logger.debug("no river found"); ingo@2045: return null; ingo@2045: } ingo@2045: teichmann@6101: RangeAccess rangeAccess = new RangeAccess(flys); felix@4862: double[] dist = rangeAccess.getKmRange(); ingo@2045: ingo@2045: if (dist == null) { ingo@2045: logger.debug("no range found"); ingo@2045: return null; ingo@2045: } ingo@2045: ingo@2045: if (logger.isDebugEnabled()) { ingo@2045: logger.debug("Determine gauge for:"); ingo@2045: logger.debug("... river: " + river.getName()); ingo@2045: logger.debug("... distance: " + dist[0] + " - " + dist[1]); ingo@2045: } ingo@2045: ingo@2045: Gauge gauge = river.determineGauge(dist[0], dist[1]); ingo@2045: ingo@2045: String name = gauge != null ? gauge.getName() : "'n/a"; ingo@2045: logger.debug("Found gauge: " + name); ingo@2045: ingo@2045: return gauge; ingo@2045: } ingo@2045: ingo@2045: teichmann@5867: public static String getGaugename(D4EArtifact flys) { ingo@2045: Gauge gauge = getGauge(flys); ingo@2045: ingo@2045: return gauge != null ? gauge.getName() : null; ingo@2045: } ingo@2045: ingo@2045: teichmann@5867: public static Gauge getReferenceGauge(D4EArtifact flys) { ingo@2128: Long officialNumber = flys.getDataAsLong("reference_gauge"); aheinecke@6841: String river = getRivername(flys); ingo@2128: aheinecke@6841: if (officialNumber != null && river != null) { aheinecke@6841: return Gauge.getGaugeByOfficialNumber(officialNumber, river); aheinecke@6841: } else if (officialNumber != null) { aheinecke@6841: return Gauge.getGaugeByOfficialNumber(officialNumber); aheinecke@6841: } aheinecke@6841: return null; ingo@2128: } ingo@2128: ingo@2128: teichmann@5867: public static String getReferenceGaugeName(D4EArtifact flys) { ingo@2249: Gauge refGauge = getReferenceGauge(flys); ingo@2249: ingo@2249: return refGauge != null ingo@2249: ? refGauge.getName() ingo@2249: : "-- not found --"; ingo@2249: } ingo@2249: ingo@2249: ingo@2068: public static Double getValueFromWQ(WQ wq) { ingo@2068: if (wq == null) { ingo@2068: return null; ingo@2068: } ingo@2068: ingo@2068: Matcher m = NUMBERS_PATTERN.matcher(wq.getName()); ingo@2068: ingo@2068: if (m.matches()) { ingo@2068: logger.debug("Found a number."); ingo@2068: ingo@2068: String raw = m.group(1); ingo@2068: ingo@2068: try { ingo@2068: return Double.valueOf(raw); ingo@2068: } ingo@2068: catch (NumberFormatException nfe) { ingo@2068: } ingo@2068: } ingo@2068: ingo@2068: return null; ingo@2068: } ingo@2068: ingo@2068: felix@4363: /** Creates human-readable name for a wsp (waterlevel/longitudinal section). felix@4363: * @param name will be split at '='s. felix@4363: */ ingo@1740: public static String createWspWTitle( ingo@1740: WINFOArtifact winfo, ingo@1740: CallContext cc, ingo@1740: String name ingo@1740: ) { ingo@1740: String[] parts = name.split("="); ingo@1740: ingo@1740: NumberFormat nf = Formatter.getWaterlevelW(cc); ingo@1740: ingo@1740: String namedMainValue = null; ingo@1740: ingo@1740: boolean isQ = winfo.isQ(); ingo@1740: boolean isFree = winfo.isFreeQ(); ingo@1740: ingo@1740: double v; ingo@1740: ingo@1740: try { ingo@1740: v = Double.valueOf(parts[1]); ingo@1740: ingo@1740: namedMainValue = getNamedMainValue(winfo.getGauge(), v); ingo@1740: } ingo@1740: catch (NumberFormatException nfe) { ingo@1740: logger.warn("Cannot parse Double of: '" + parts[1] + "'"); ingo@1740: return name; ingo@1740: } ingo@1740: ingo@1740: String prefix = null; ingo@1740: ingo@1740: if (isQ && !isFree && namedMainValue != null) { ingo@1740: return "W (" + namedMainValue + ")"; ingo@1740: } ingo@1740: ingo@1740: if (isQ) { ingo@1740: prefix = "Q="; ingo@1740: } ingo@1740: ingo@1740: return prefix == null ingo@1740: ? "W(" + nf.format(v) + ")" ingo@1740: : "W(" + prefix + nf.format(v) + ")"; ingo@1740: } ingo@1740: ingo@1740: ingo@1740: public static String createWspQTitle( ingo@1740: WINFOArtifact winfo, ingo@1740: CallContext cc, ingo@1740: String name ingo@1740: ) { ingo@1740: String[] parts = name.split("="); ingo@1740: ingo@1740: NumberFormat nf = Formatter.getWaterlevelQ(cc); ingo@1740: ingo@1740: String namedMainValue = null; ingo@1740: ingo@1740: boolean isQ = winfo.isQ(); ingo@1740: boolean isFree = winfo.isFreeQ(); ingo@1740: ingo@1740: double v; ingo@1740: ingo@1740: try { ingo@1740: v = Double.valueOf(parts[1]); ingo@1740: ingo@1740: namedMainValue = getNamedMainValue(winfo.getGauge(), v); ingo@1740: } ingo@1740: catch (NumberFormatException nfe) { ingo@1740: logger.warn("Cannot parse Double of: '" + parts[1] + "'"); ingo@1740: return name; ingo@1740: } ingo@1740: ingo@1740: String prefix = null; ingo@1740: ingo@1740: if (isQ && !isFree && namedMainValue != null) { ingo@1740: return namedMainValue; ingo@1740: } ingo@1740: ingo@1740: if (!isQ) { ingo@1740: prefix = "W="; ingo@1740: } ingo@1740: ingo@1740: return prefix == null ingo@1740: ? "Q(" + nf.format(v) + ")" ingo@1740: : "Q(" + prefix + nf.format(v) + ")"; ingo@1740: } ingo@1740: ingo@1740: ingo@2038: /** ingo@2038: * Returns the named main value if a Q was selected and if this Q fits to a ingo@2038: * named main value. Otherwise, this function returns null. ingo@2038: * ingo@2038: * @param winfo The WINFO Artifact. ingo@2038: * @param value The Q (or W) value. ingo@2038: * ingo@2038: * @return a named main value or null. ingo@2038: */ ingo@2038: public static String getNamedMainValue(WINFOArtifact winfo, double value) { ingo@2038: WQ_MODE wqmode = getWQMode(winfo); ingo@2038: ingo@2038: if (wqmode != WQ_MODE.QGAUGE) { ingo@2038: return null; ingo@2038: } ingo@2038: else { ingo@2038: return getNamedMainValue(winfo.getGauge(), value); ingo@2038: } ingo@2038: } ingo@2038: ingo@2038: ingo@1740: public static String getNamedMainValue(Gauge gauge, double value) { ingo@1740: List mainValues = gauge.getMainValues(); ingo@1740: logger.debug("Search named main value for: " + value); ingo@1740: ingo@1740: for (MainValue mv: mainValues) { ingo@1740: if (mv.getValue().doubleValue() == value) { ingo@1740: logger.debug("Found named main value: " + mv.getMainValue().getName()); ingo@1740: return mv.getMainValue().getName(); ingo@1740: } ingo@1740: } ingo@1740: ingo@1740: logger.debug("Did not find a named main value for: " + value); ingo@1740: return null; ingo@1740: } ingo@1792: ingo@1792: ingo@1792: /** ingo@2035: * ingo@2035: * @param nmv A string that represents a named main value. ingo@2035: * ingo@2035: * @throws NullPointerException if nmv is null. ingo@2035: */ ingo@2035: public static String stripNamedMainValue(String nmv) { ingo@2035: int startIndex = nmv.indexOf("("); ingo@2035: int endIndex = nmv.indexOf(")"); ingo@2035: ingo@2035: if (startIndex > 0 && endIndex > 0 && startIndex < endIndex) { ingo@2035: return nmv.substring(0, startIndex); ingo@2035: } ingo@2035: ingo@2035: return nmv; ingo@2035: } ingo@2035: ingo@2035: ingo@2035: /** ingo@1792: * Returns the URL of user mapfile for the owner of Artifact ingo@1792: * artifactId. ingo@1792: * ingo@1792: * @param artifactId The UUID of an artifact. ingo@1792: * ingo@1792: * @return the URL of the user wms. ingo@1792: */ ingo@1792: public static String getUserWMSUrl(String artifactId) { christian@4656: String url = getXPathString(XPATH_FLOODMAP_MAPSERVER_URL); ingo@2296: url = url.endsWith("/") ? url + "user-wms" : url + "/" + "user-wms"; ingo@1792: ingo@1792: return url; ingo@1792: } ingo@2063: ingo@2063: christian@4864: public static String getRiverWMSUrl() { christian@4864: String url = getXPathString(XPATH_RIVERMAP_MAPSERVER_URL); christian@4864: url = url.endsWith("/") ? url + "river-wms" : url + "/" + "river-wms"; christian@4864: christian@4864: return url; christian@4864: } christian@4864: christian@4864: ingo@2063: /** felix@6528: * Returns the description for a given km for a specific teichmann@5867: * river. The river is provided by the D4EArtifact flys. ingo@2063: * teichmann@5867: * @param flys The D4EArtifact that provides a river. ingo@2063: * @param km The kilometer. ingo@2063: * ingo@2063: * @return the description for km or an empty string if no ingo@2063: * description was found. ingo@2063: */ teichmann@5867: public static String getLocationDescription(D4EArtifact flys, double km) { ingo@2063: String river = getRivername(flys); ingo@2063: ingo@2063: if (river == null) { ingo@2063: return ""; ingo@2063: } ingo@2063: ingo@2063: return LocationProvider.getLocation(river, km); ingo@2063: } raimund@2179: raimund@2179: raimund@2179: /** felix@6528: * Returns the differences for a w-differences calculation. raimund@2179: * raimund@2179: * @param winfo The WINFOArtifact. raimund@2179: * @param context The context. raimund@2179: * raimund@2179: * @return The differences as string separated by semicolon and linebreak. raimund@2179: */ raimund@2179: public static String getWDifferences( raimund@2179: WINFOArtifact winfo, raimund@2179: CallContext context) raimund@2179: { raimund@2179: State state = winfo.getCurrentState(context); raimund@2179: if(state instanceof WDifferencesState) { raimund@2179: String diffids = winfo.getDataAsString("diffids"); raimund@2179: String datas[] = diffids.split("#"); raimund@2179: raimund@2179: // Validate the Data-Strings. raimund@2179: for (String s: datas) { felix@4054: if (!WaterlevelSelectState.isValueValid(s)) { raimund@2179: return ""; raimund@2179: } raimund@2179: } raimund@2179: raimund@2179: if (datas.length < 2) { raimund@2179: return ""; raimund@2179: } raimund@2179: raimund@2179: String diffs = ""; raimund@2179: for(int i = 0; i < datas.length; i+=2) { raimund@2179: // e.g.: raimund@2179: // 42537f1e-3522-42ef-8968-635b03d8e9c6;longitudinal_section.w;1 raimund@2179: WKms minuendWKms = getWKms(StringUtil.unbracket(datas[i+0]), raimund@2179: context); raimund@2179: WKms subtrahendWKms = getWKms(StringUtil.unbracket(datas[i+1]), raimund@2179: context); raimund@2179: if (minuendWKms != null && subtrahendWKms != null) { sascha@3076: diffs += StringUtil.wWrap(minuendWKms.getName()) raimund@2179: + " - " + StringUtil.wWrap(subtrahendWKms.getName()); raimund@2179: } raimund@2179: diffs += ";\n"; raimund@2179: } raimund@2179: return diffs; raimund@2179: } raimund@2179: else { raimund@2179: logger.warn("Not a valid state for differences."); raimund@2179: return ""; raimund@2179: } raimund@2179: } raimund@2179: raimund@2179: raimund@2179: protected static WKms getWKms(String mingle, CallContext context) { raimund@2179: String[] def = mingle.split(";"); raimund@2179: String uuid = def[0]; raimund@2179: String name = def[1]; raimund@2179: int idx = Integer.parseInt(def[2]); raimund@2179: raimund@2179: if (name.startsWith("staticwkms")) { raimund@2179: StaticWKmsArtifact staticWKms = teichmann@5865: (StaticWKmsArtifact) RiverUtils.getArtifact( raimund@2179: uuid, raimund@2179: context); raimund@2179: WKms wkms = staticWKms.getWKms(idx); raimund@2179: if (wkms == null) raimund@2179: logger.error("No WKms from artifact."); raimund@2179: return wkms; raimund@2179: } raimund@2179: teichmann@5865: WINFOArtifact flys = (WINFOArtifact) RiverUtils.getArtifact( raimund@2179: uuid, raimund@2179: context); raimund@2179: raimund@2179: if (flys == null) { raimund@2179: logger.warn("One of the artifacts (1) for diff calculation could not be loaded"); raimund@2179: return null; raimund@2179: } raimund@2179: else{ raimund@2179: WQKms[] wqkms = (WQKms[]) flys.getWaterlevelData(). raimund@2179: getData(); raimund@2179: if (wqkms == null) raimund@2179: logger.warn("not waterlevels in artifact"); raimund@2179: else if (wqkms.length < idx) raimund@2179: logger.warn("not enough waterlevels in artifact"); raimund@2179: return wqkms[idx]; raimund@2179: } raimund@2179: } ingo@2216: ingo@2216: ingo@2216: /** felix@6528: * Transform a string into an int array. Therefore, the string ingo@2216: * raw must consist of int values separated by a ';'. ingo@2216: * ingo@2216: * @param raw The raw integer array as string separated by a ';'. ingo@2216: * ingo@2216: * @return an array of int values. ingo@2216: */ ingo@2216: public static int[] intArrayFromString(String raw) { ingo@2216: String[] splitted = raw != null ? raw.split(";") : null; ingo@2216: ingo@2216: if (splitted == null || splitted.length == 0) { ingo@2216: logger.warn("No integer values found in '" + raw + "'"); ingo@2216: return new int[0]; ingo@2216: } ingo@2216: ingo@2216: TIntArrayList integers = new TIntArrayList(splitted.length); ingo@2216: ingo@2216: for (String value: splitted) { ingo@2216: try { sascha@3405: integers.add(Integer.parseInt(value)); ingo@2216: } ingo@2216: catch (NumberFormatException nfe) { ingo@2216: logger.warn("Parsing integer failed: " + nfe); ingo@2216: } ingo@2216: } ingo@2216: ingo@2216: return integers.toNativeArray(); ingo@2216: } ingo@2216: ingo@2216: ingo@2216: /** felix@6528: * Transform a string into a long array. Therefore, the string raimund@2600: * raw must consist of int values separated by a ';'. raimund@2600: * raimund@2600: * @param raw The raw long array as string separated by a ';'. raimund@2600: * raimund@2600: * @return an array of int values. raimund@2600: */ raimund@2600: public static long[] longArrayFromString(String raw) { raimund@2600: String[] splitted = raw != null ? raw.split(";") : null; raimund@2600: raimund@2600: if (splitted == null || splitted.length == 0) { raimund@2600: logger.warn("No long values found in '" + raw + "'"); raimund@2600: return new long[0]; raimund@2600: } raimund@2600: raimund@2600: TLongArrayList longs = new TLongArrayList(splitted.length); raimund@2600: raimund@2600: for (String value: splitted) { raimund@2600: try { raimund@2600: longs.add(Long.valueOf(value)); raimund@2600: } raimund@2600: catch (NumberFormatException nfe) { raimund@2600: logger.warn("Parsing long failed: " + nfe); raimund@2600: } raimund@2600: } raimund@2600: raimund@2600: return longs.toNativeArray(); raimund@2600: } raimund@2600: raimund@2600: raimund@2600: /** felix@6528: * Transform a string into an double array. Therefore, the ingo@2216: * string raw must consist of double values separated by a ingo@2216: * ';'. ingo@2216: * ingo@2216: * @param raw The raw double array as string separated by a ';'. ingo@2216: * ingo@2216: * @return an array of double values. ingo@2216: */ ingo@2216: public static double[] doubleArrayFromString(String raw) { ingo@2216: String[] splitted = raw != null ? raw.split(";") : null; ingo@2216: ingo@2216: if (splitted == null || splitted.length == 0) { ingo@2216: logger.warn("No double values found in '" + raw + "'"); ingo@2216: return new double[0]; ingo@2216: } ingo@2216: ingo@2216: TDoubleArrayList doubles = new TDoubleArrayList(splitted.length); ingo@2216: ingo@2216: for (String value: splitted) { ingo@2216: try { ingo@2216: doubles.add(Double.valueOf(value)); ingo@2216: } ingo@2216: catch (NumberFormatException nfe) { ingo@2216: logger.warn("Parsing double failed: " + nfe); ingo@2216: } ingo@2216: } ingo@2216: ingo@2216: return doubles.toNativeArray(); ingo@2216: } felix@3444: felix@3444: felix@3444: /** felix@3444: * Returns the gauges that match the selected kilometer range. felix@3444: * felix@3444: * @param flys the flys artifact. felix@3444: * felix@3444: * @return the gauges based on the selected kilometer range (null if felix@3444: * none/no range set). felix@3444: */ teichmann@5867: public static List getGauges(D4EArtifact flys) { felix@3444: felix@3444: River river = getRiver(flys); felix@3444: if (river == null) { felix@3444: logger.debug("getGauges: no river!"); felix@3444: return null; felix@3444: } felix@3444: teichmann@6101: RangeAccess rangeAccess = new RangeAccess(flys); felix@4862: double[] dist = rangeAccess.getKmRange(); felix@3444: if (dist == null) { felix@3444: logger.debug("getGauges: no dist!"); felix@3444: return null; felix@3444: } felix@3444: logger.debug("getGauges: " + dist[0] + " - " + dist[1]); felix@3444: felix@3444: return river.determineGauges(dist[0], dist[1]); felix@3444: } aheinecke@6941: aheinecke@6941: /** Round a Q in the AT format style **/ aheinecke@6941: public static double roundQ(double q) { aheinecke@6941: if (q < 10d) q = Math.rint((q*1000d)) / 1000d; aheinecke@6941: else if (q < 100d) q = Math.rint((q*100d)) / 100d; aheinecke@6941: else if (q < 1000d) q = Math.rint((q*10d)) / 10d; aheinecke@6941: else if (q >= 1000d) q = Math.rint(q); aheinecke@6941: return q; aheinecke@6941: } ingo@1095: } ingo@1105: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :