Mercurial > dive4elements > river
diff flys-artifacts/src/main/java/de/intevation/flys/utils/FLYSUtils.java @ 3814:8083f6384023
merged flys-artifacts/pre2.6-2012-01-04
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:56 +0200 |
parents | 0cf60d64895c |
children | aa9cc91c8193 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/utils/FLYSUtils.java Fri Sep 28 12:14:56 2012 +0200 @@ -0,0 +1,610 @@ +package de.intevation.flys.utils; + +import org.apache.log4j.Logger; + +import java.text.NumberFormat; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.xpath.XPathConstants; + +import org.w3c.dom.Document; + +import org.hibernate.SessionFactory; +import org.hibernate.impl.SessionFactoryImpl; + +import gnu.trove.TDoubleArrayList; + +import de.intevation.artifacts.Artifact; +import de.intevation.artifacts.CallContext; + +import de.intevation.artifacts.common.utils.Config; +import de.intevation.artifacts.common.utils.XMLUtils; + +import de.intevation.flys.backend.SessionFactoryProvider; + +import de.intevation.flys.artifacts.context.FLYSContext; +import de.intevation.flys.artifacts.FLYSArtifact; +import de.intevation.flys.artifacts.WINFOArtifact; +import de.intevation.flys.artifacts.model.RiverFactory; +import de.intevation.flys.artifacts.model.LocationProvider; +import de.intevation.flys.artifacts.model.WQ; +import de.intevation.flys.model.Gauge; +import de.intevation.flys.model.MainValue; +import de.intevation.flys.model.River; + +public class FLYSUtils { + + /** The logger that is used in this utility. */ + private static Logger logger = Logger.getLogger(FLYSUtils.class); + + public static enum KM_MODE { RANGE, LOCATIONS, NONE }; + + /** + * An enum that represents the 5 possible WQ modes in FLYS. The 5 values are + * <i>QFREE</i> <i>QGAUGE</i> <i>WGAUGE</i> <i>WFREE</i> and <i>NONE</i>. + */ + public static enum WQ_MODE { QFREE, QGAUGE, WFREE, WGAUGE, NONE }; + + + public static final Pattern NUMBERS_PATTERN = + Pattern.compile("\\D*(\\d++.\\d*)\\D*"); + + public static final String XPATH_RIVER_PROJECTION = + "/artifact-database/floodmap/river[@name=$name]/srid/@value"; + + public static final String XPATH_SHAPEFILE_DIR = + "/artifact-database/floodmap/shapefile-path/@value"; + + public static final String XPATH_VELOCITY_LOGFILE = + "/artifact-database/floodmap/velocity/logfile/@path"; + + public static final String XPATH_MAPSERVER_URL = + "/artifact-database/floodmap/mapserver/server/@path"; + + public static final String XPATH_MAPFILE_PATH = + "/artifact-database/floodmap/mapserver/mapfile/@path"; + + public static final String XPATH_MAPFILE_TEMPLATE = + "/artifact-database/floodmap/mapserver/map-template/@path"; + + public static final String XPATH_MAPSERVER_TEMPLATE_PATH = + "/artifact-database/floodmap/mapserver/templates/@path"; + + + private FLYSUtils() { + } + + + /** + * Pulls Artifact with given UUID fromm database. + * @return FLYSArtifact with given UUID or null (in case of errors). + */ + public static FLYSArtifact getArtifact(String uuid, CallContext context) { + try { + Artifact artifact = context.getDatabase().getRawArtifact(uuid); + + if (artifact == null) { + logger.error("Artifact '" + uuid + "' does not exist."); + return null; + } + + if (!(artifact instanceof FLYSArtifact)) { + logger.error("Artifact '" +uuid+ "' is no valid FLYSArtifact."); + return null; + } + + return (FLYSArtifact) artifact; + } + // TODO: catch more selective + catch (Exception e) { + logger.error("Cannot get FLYSArtifact " + uuid + + " from database (" + e.getMessage() + ")."); + return null; + } + } + + + /** + * Returns the FLYSContext from context object. + * + * @param context The CallContext or the FLYSContext. + * + * @return the FLYSContext. + */ + public static FLYSContext getFlysContext(Object context) { + return context instanceof FLYSContext + ? (FLYSContext) context + : (FLYSContext) ((CallContext) context).globalContext(); + } + + + /** + * Convinience function to retrieve an XPath as string with replaced config + * directory. + * + * @param xpath The XPath expression. + * + * @return a string with replaced config directory. + */ + public static String getXPathString(String xpath) { + String tmp = Config.getStringXPath(xpath); + tmp = Config.replaceConfigDir(tmp); + + return tmp; + } + + + public static boolean isUsingOracle() { + SessionFactory sf = SessionFactoryProvider.getSessionFactory(); + + String d = SessionFactoryProvider.getDriver((SessionFactoryImpl) sf); + + return d != null ? d.indexOf("Oracle") >= 0 : false; + } + + + /** + * This method returns an WQ_MODE enum which is based on the parameters + * stored in <i>flys</i> Artifact. If there is no <i>wq_mode</i> parameter + * existing, WQ_MODE.NONE is returned. + * + * @param flys The FLYSArtifact that stores wq mode relevant parameters. + * + * @return an enum WQ_MODE. + */ + public static WQ_MODE getWQMode(FLYSArtifact flys) { + String mode = flys.getDataAsString("wq_mode"); + boolean free = flys.getDataAsBoolean("wq_free"); + + if (mode != null && mode.equals("Q")) { + return free ? WQ_MODE.QFREE : WQ_MODE.QGAUGE; + } + else if (mode != null && mode.equals("W")) { + return free ? WQ_MODE.WFREE : WQ_MODE.WGAUGE; + } + else { + return WQ_MODE.NONE; + } + } + + + public static KM_MODE getKmRangeMode(FLYSArtifact flys) { + String mode = flys.getDataAsString("ld_mode"); + + if (mode == null || mode.length() == 0) { + return KM_MODE.NONE; + } + else if (mode.equals("distance")) { + return KM_MODE.RANGE; + } + else if (mode.equals("locations")) { + return KM_MODE.LOCATIONS; + } + else { + return KM_MODE.NONE; + } + } + + /** + * Get min and max kilometer, independent of parametization + * (ld_from/to vs ld_locations). + */ + public static double[] getKmRange(FLYSArtifact flys) { + switch (getKmRangeMode(flys)) { + case RANGE: { + return getKmFromTo(flys); + } + + case LOCATIONS: { + double[] locs = getLocations(flys); + return new double[] { locs[0], locs[locs.length-1] }; + } + + case NONE: { + double[] locs = getLocations(flys); + if (locs != null) { + return new double[] { locs[0], locs[locs.length-1] }; + } + else { + return getKmFromTo(flys); + } + } + } + + return new double[] { Double.NaN, Double.NaN }; + } + + + public static double[] getKmFromTo(FLYSArtifact flys) { + String strFrom = flys.getDataAsString("ld_from"); + String strTo = flys.getDataAsString("ld_to"); + + if (strFrom == null || strTo == null) { + return null; + } + + try { + return new double[] { + Double.parseDouble(strFrom), + Double.parseDouble(strTo) }; + } + catch (NumberFormatException nfe) { + return null; + } + } + + + /** + * Return sorted array of locations at which stuff was calculated + * (from ld_locations data), null if not parameterized this way. + */ + public static double[] getLocations(FLYSArtifact flys) { + String locationStr = flys.getDataAsString("ld_locations"); + + if (locationStr == null || locationStr.length() == 0) { + return null; + } + + String[] tmp = locationStr.split(" "); + TDoubleArrayList locations = new TDoubleArrayList(); + + for (String l: tmp) { + try { + locations.add(Double.parseDouble(l)); + } + catch (NumberFormatException nfe) { + } + } + + locations.sort(); + + return locations.toNativeArray(); + } + + + /** + * Returns the Qs for a given FLYSArtifact. This method currently accepts + * only instances of WINFOArtifact. + * + * @param flys A FLYSArtifact. + * + * @return the Qs. + */ + public static double[] getQs(FLYSArtifact flys) { + double[] kmRange = getKmRange(flys); + + // XXX this is not nice! + if (flys instanceof WINFOArtifact) { + return ((WINFOArtifact) flys).getQs(kmRange); + } + + logger.warn("This method currently supports WINFOArtifact only!"); + + return null; + } + + + /** + * Returns the Ws for a given FLYSArtifact. This method currently accepts + * only instances of WINFOArtifact. + * + * @param flys A FLYSArtifact. + * + * @return the Ws. + */ + public static double[] getWs(FLYSArtifact flys) { + double[] kmRange = getKmRange(flys); + + // XXX this is not nice! + if (flys instanceof WINFOArtifact) { + return ((WINFOArtifact) flys).getWs(kmRange); + } + + logger.warn("This method currently supports WINFOArtifact only!"); + + return null; + } + + + /** + * Returns the selected River object based on the 'river' data that might + * have been inserted by the user. + * + * @return the selected River or null if no river has been chosen yet. + */ + public static River getRiver(FLYSArtifact flys) { + String sRiver = getRivername(flys); + + return (sRiver != null) + ? RiverFactory.getRiver(sRiver) + : null; + } + + + /** + * Returns the name of the river specified in the given <i>flys</i> + * Artifact. + * + * @param flys The FLYSArtifact that stores a river relevant information. + * + * @return the name of the specified river or null. + */ + public static String getRivername(FLYSArtifact flys) { + return flys != null ? flys.getDataAsString("river") : null; + } + + + /** + * Extracts the SRID defined in the global configuration for the river + * specified in <i>artifact</i>. + * + * @param artifact The FLYSArtifact that stores the name of the river. + * + * @return the SRID as string (e.g. "31466"). + */ + public static String getRiverSrid(FLYSArtifact artifact) { + String river = artifact.getDataAsString("river"); + + if (river == null || river.length() == 0) { + return null; + } + + return getRiverSrid(river); + } + + + public static String getRiverSrid(String rivername) { + Map<String, String> variables = new HashMap<String, String>(1); + variables.put("name", rivername); + + Document cfg = Config.getConfig(); + + return (String) XMLUtils.xpath( + cfg, + XPATH_RIVER_PROJECTION, + XPathConstants.STRING, + null, + variables); + } + + + public static Gauge getGauge(FLYSArtifact flys) { + River river = getRiver(flys); + + if (river == null) { + logger.debug("no river found"); + return null; + } + + double[] dist = getKmRange(flys); + + if (dist == null) { + logger.debug("no range found"); + return null; + } + + if (logger.isDebugEnabled()) { + logger.debug("Determine gauge for:"); + logger.debug("... river: " + river.getName()); + logger.debug("... distance: " + dist[0] + " - " + dist[1]); + } + + Gauge gauge = river.determineGauge(dist[0], dist[1]); + + String name = gauge != null ? gauge.getName() : "'n/a"; + logger.debug("Found gauge: " + name); + + return gauge; + } + + + public static String getGaugename(FLYSArtifact flys) { + Gauge gauge = getGauge(flys); + + return gauge != null ? gauge.getName() : null; + } + + + public static Double getValueFromWQ(WQ wq) { + if (wq == null) { + return null; + } + + Matcher m = NUMBERS_PATTERN.matcher(wq.getName()); + + if (m.matches()) { + logger.debug("Found a number."); + + String raw = m.group(1); + + try { + return Double.valueOf(raw); + } + catch (NumberFormatException nfe) { + } + } + + return null; + } + + + public static String createWspWTitle( + WINFOArtifact winfo, + CallContext cc, + String name + ) { + String[] parts = name.split("="); + + NumberFormat nf = Formatter.getWaterlevelW(cc); + + String namedMainValue = null; + + boolean isQ = winfo.isQ(); + boolean isFree = winfo.isFreeQ(); + + double v; + + try { + v = Double.valueOf(parts[1]); + + namedMainValue = getNamedMainValue(winfo.getGauge(), v); + } + catch (NumberFormatException nfe) { + logger.warn("Cannot parse Double of: '" + parts[1] + "'"); + return name; + } + + String prefix = null; + + if (isQ && !isFree && namedMainValue != null) { + return "W (" + namedMainValue + ")"; + } + + if (isQ) { + prefix = "Q="; + } + + return prefix == null + ? "W(" + nf.format(v) + ")" + : "W(" + prefix + nf.format(v) + ")"; + } + + + public static String createWspQTitle( + WINFOArtifact winfo, + CallContext cc, + String name + ) { + String[] parts = name.split("="); + + NumberFormat nf = Formatter.getWaterlevelQ(cc); + + String namedMainValue = null; + + boolean isQ = winfo.isQ(); + boolean isFree = winfo.isFreeQ(); + + double v; + + try { + v = Double.valueOf(parts[1]); + + namedMainValue = getNamedMainValue(winfo.getGauge(), v); + } + catch (NumberFormatException nfe) { + logger.warn("Cannot parse Double of: '" + parts[1] + "'"); + return name; + } + + String prefix = null; + + if (isQ && !isFree && namedMainValue != null) { + return namedMainValue; + } + + if (!isQ) { + prefix = "W="; + } + + return prefix == null + ? "Q(" + nf.format(v) + ")" + : "Q(" + prefix + nf.format(v) + ")"; + } + + + /** + * Returns the named main value if a Q was selected and if this Q fits to a + * named main value. Otherwise, this function returns null. + * + * @param winfo The WINFO Artifact. + * @param value The Q (or W) value. + * + * @return a named main value or null. + */ + public static String getNamedMainValue(WINFOArtifact winfo, double value) { + WQ_MODE wqmode = getWQMode(winfo); + + if (wqmode != WQ_MODE.QGAUGE) { + return null; + } + else { + return getNamedMainValue(winfo.getGauge(), value); + } + } + + + public static String getNamedMainValue(Gauge gauge, double value) { + List<MainValue> mainValues = gauge.getMainValues(); + logger.debug("Search named main value for: " + value); + + for (MainValue mv: mainValues) { + if (mv.getValue().doubleValue() == value) { + logger.debug("Found named main value: " + mv.getMainValue().getName()); + return mv.getMainValue().getName(); + } + } + + logger.debug("Did not find a named main value for: " + value); + return null; + } + + + /** + * + * @param nmv A string that represents a named main value. + * + * @throws NullPointerException if nmv is null. + */ + public static String stripNamedMainValue(String nmv) { + int startIndex = nmv.indexOf("("); + int endIndex = nmv.indexOf(")"); + + if (startIndex > 0 && endIndex > 0 && startIndex < endIndex) { + return nmv.substring(0, startIndex); + } + + return nmv; + } + + + /** + * Returns the URL of user mapfile for the owner of Artifact + * <i>artifactId</i>. + * + * @param artifactId The UUID of an artifact. + * + * @return the URL of the user wms. + */ + public static String getUserWMSUrl(String artifactId) { + String url = getXPathString(XPATH_MAPSERVER_URL); + url = url + "user-wms"; + + return url; + } + + + /** + * This method returns the description for a given <i>km</i> for a specific + * river. The river is provided by the FLYSArtifact <i>flys</i>. + * + * @param flys The FLYSArtifact that provides a river. + * @param km The kilometer. + * + * @return the description for <i>km</i> or an empty string if no + * description was found. + */ + public static String getLocationDescription(FLYSArtifact flys, double km) { + String river = getRivername(flys); + + if (river == null) { + return ""; + } + + return LocationProvider.getLocation(river, km); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :