view artifacts/src/main/java/org/dive4elements/river/utils/ThemeUtil.java @ 6332:f5bb53106ae8

Remove createBarriersLayer and createBarriers The generated mapfiles did not work and were just confusing. This looks like historical cruft that was never deleted. The real barrier mapfiles are created in the Floodmap state
author Andre Heinecke <aheinecke@intevation.de>
date Thu, 13 Jun 2013 17:24:56 +0200
parents 8b03a7589101
children 7a9cbb3a3d5a
line wrap: on
line source
/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
 * Software engineering by Intevation GmbH
 *
 * This file is Free Software under the GNU AGPL (>=v3)
 * and comes with ABSOLUTELY NO WARRANTY! Check out the
 * documentation coming with Dive4Elements River for details.
 */

package org.dive4elements.river.utils;

import org.dive4elements.artifacts.CallMeta;
import org.dive4elements.artifacts.common.utils.XMLUtils;
import org.dive4elements.river.artifacts.model.MapserverStyle;
import org.dive4elements.river.artifacts.model.MapserverStyle.Clazz;
import org.dive4elements.river.artifacts.model.MapserverStyle.Expression;
import org.dive4elements.river.artifacts.model.MapserverStyle.Label;
import org.dive4elements.river.artifacts.model.MapserverStyle.Style;
import org.dive4elements.river.artifacts.resources.Resources;

import java.awt.Color;
import java.awt.Font;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;


/**
 * Utility to deal with themes and their representations.
 */
public class ThemeUtil {

    /** Private logger. */
    private static Logger logger =
            Logger.getLogger(ThemeUtil.class);

    private static final String MSG_ISOBATH_CLASS = "floodmap.isobath.class";

    private static final String MSG_ISOBATH_LASTCLASS = "floodmap.isobath.lastclass";

    public final static String XPATH_FILL_COLOR =
            "/theme/field[@name='fillcolor']/@default";

    public final static String XPATH_LINE_COLOR =
            "/theme/field[@name='linecolor']/@default";

    public final static String XPATH_AREA_LINE_COLOR =
            "/theme/field[@name='areabordercolor']/@default";

    public static final String XPATH_LINE_SIZE =
            "/theme/field[@name='linesize']/@default";

    public static final String XPATH_LINE_STYLE =
            "/theme/field[@name='linetype']/@default";

    public static final String XPATH_POINT_SIZE =
            "/theme/field[@name='pointsize']/@default";

    public static final String XPATH_POINT_COLOR =
            "/theme/field[@name='pointcolor']/@default";

    public final static String XPATH_SHOW_BORDER =
            "/theme/field[@name='showborder']/@default";

    public final static String XPATH_AREA_SHOW_BORDER =
            "/theme/field[@name='showborder']/@default";

    public final static String XPATH_SHOW_POINTS =
            "/theme/field[@name='showpoints']/@default";

    public final static String XPATH_SHOW_LINE =
            "/theme/field[@name='showlines']/@default";

    public final static String XPATH_SHOW_VERTICAL_LINE =
            "/theme/field[@name='showverticalline']/@default";

    public final static String XPATH_SHOW_HORIZONTAL_LINE =
            "/theme/field[@name='showhorizontalline']/@default";

    public final static String XPATH_SHOW_LINE_LABEL =
            "/theme/field[@name='showlinelabel']/@default";

    public final static String XPATH_SHOW_POINT_LABEL =
            "/theme/field[@name='showpointlabel']/@default";

    public final static String XPATH_SHOW_WIDTH =
            "/theme/field[@name='showwidth']/@default";

    public final static String XPATH_SHOW_LEVEL =
            "/theme/field[@name='showlevel']/@default";

    public final static String XPATH_TRANSPARENCY =
            "/theme/field[@name='transparency']/@default";

    public final static String XPATH_AREA_TRANSPARENCY =
            "/theme/field[@name='areatransparency']/@default";

    public final static String XPATH_SHOW_AREA =
            "/theme/field[@name='showarea']/@default";

    public final static String XPATH_SHOW_MIDDLE_HEIGHT =
            "/theme/field[@name='showmiddleheight']/@default";

    public final static String XPATH_LABEL_FONT_COLOR =
            "/theme/field[@name='labelfontcolor']/@default";

    public final static String XPATH_LABEL_FONT_SIZE =
            "/theme/field[@name='labelfontsize']/@default";

    public final static String XPATH_LABEL_FONT_FACE =
            "/theme/field[@name='labelfontface']/@default";

    public final static String XPATH_LABEL_FONT_STYLE =
            "/theme/field[@name='labelfontstyle']/@default";

    public final static String XPATH_TEXT_ORIENTATION =
            "/theme/field[@name='textorientation']/@default";

    public final static String XPATH_LABEL_BGCOLOR =
            "/theme/field[@name='labelbgcolor']/@default";

    public final static String XPATH_LABEL_SHOW_BACKGROUND =
            "/theme/field[@name='labelshowbg']/@default";

    public final static String XPATH_BACKGROUND_COLOR =
            "/theme/field[@name='backgroundcolor']/@default";

    public final static String XPATH_AREA_BACKGROUND_COLOR =
            "/theme/field[@name='areabgcolor']/@default";

    public final static String XPATH_SYMBOL =
            "/theme/field[@name='symbol']/@default";

    public final static String XPATH_SHOW_MINIMUM =
            "/theme/field[@name='showminimum']/@default";

    public final static String XPATH_SHOW_MAXIMUM =
            "/theme/field[@name='showmaximum']/@default";

    public final static String XPATH_WSPLGEN_FIELDS =
            "/theme[@name='WSPLGEN']/field";

    public final static String XPATH_WSPLGEN_STARTCOLOR =
            "/theme/field[@name='startcolor']/@default";

    public final static String XPATH_WSPLGEN_ENDCOLOR =
            "/theme/field[@name='endcolor']/@default";

    public final static String XPATH_WSPLGEN_NUMCLASSES =
            "/theme/field[@name='numclasses']/@default";

    /** XPATH to bandwidth field. */
    public final static String XPATH_BANDWIDTH =
            "/theme/field[@name='bandwidth']/@default";

    /** XPATH to find showextramark field. */
    public final static String XPATH_SHOWEXTRAMARK =
            "/theme/field[@name='showextramark']/@default";

    /** Parse string to be boolean with default if empty or unrecognized. */
    public static boolean parseBoolean(String value, boolean defaultsTo) {
        if (value == null || value.length() == 0) {
            return defaultsTo;
        }
        if (value.equals("false")) {
            return false;
        }
        else if (value.equals("true")) {
            return true;
        }
        else {
            return defaultsTo;
        }
    }


    /**
     * Attempt converting \param value to an integer, in failing cases,
     * return \param defaultsTo.
     * @param value String to be converted to integer.
     * @param defaultsTo Default to return if conversion failed.
     * @return \param value as integer or defaultsto if conversion failed.
     */
    public static int parseInteger(String value, int defaultsTo) {
        if (value == null || value.length() == 0) {
            return defaultsTo;
        }

        try {
            return Integer.parseInt(value);
        }
        catch (NumberFormatException nfe) {
            // do nothing
        }

        return defaultsTo;
    }


    /**
     * Attempt converting \param value to a double, in failing cases,
     * return \param defaultsTo.
     * @param value String to be converted to double.
     * @param defaultsTo Default to return if conversion failed.
     * @return \param value as integer or defaultsto if conversion failed.
     */
    public static double parseDouble(String value, double defaultsTo) {
        if (value == null || value.length() == 0) {
            return defaultsTo;
        }

        try {
            return Double.parseDouble(value);
        }
        catch (NumberFormatException nfe) {
            // do nothing
        }

        return defaultsTo;
    }


    /**
     * Parses line width, defaulting to 0.
     * @param theme the theme
     */
    public static int parseLineWidth(Document theme) {
        String size = XMLUtils.xpathString(theme, XPATH_LINE_SIZE, null);
        if (size == null || size.length() == 0) {
            return 0;
        }

        try {
            return Integer.parseInt(size);
        }
        catch (NumberFormatException nfe) {
            logger.warn("Unable to set line size from string: '" + size + "'");
        }
        return 0;
    }


    /**
     * Parse band width, defaulting to 0.
     * @param theme the theme.
     */
    public static double parseBandWidth(Document theme) {
        String bandWidth = XMLUtils.xpathString(theme, XPATH_BANDWIDTH, null);

        return parseDouble(bandWidth, 0);
    }


    public static int parsePointWidth(Document theme) {
        String width = XMLUtils.xpathString(theme, XPATH_POINT_SIZE, null);

        return parseInteger(width, 3);
    }


    public static Color parsePointColor(Document theme) {
        String color = XMLUtils.xpathString(theme, XPATH_POINT_COLOR, null);
        logger.debug("parsePointColor(): color = " + color);
        return parseColor(color);
    }


    /**
     * Parses the line style, defaulting to '10'.
     * @param theme The theme.
     */
    public static float[] parseLineStyle(Document theme) {
        String dash = XMLUtils.xpathString(theme, XPATH_LINE_STYLE, null);

        float[] def = {10};
        if (dash == null || dash.length() == 0) {
            return def;
        }

        String[] pattern = dash.split(",");
        if(pattern.length == 1) {
            return def;
        }

        try {
            float[] dashes = new float[pattern.length];
            for (int i = 0; i < pattern.length; i++) {
                dashes[i] = Float.parseFloat(pattern[i]);
            }
            return dashes;
        }
        catch(NumberFormatException nfe) {
            logger.warn("Unable to set dash from string: '" + dash + "'");
            return def;
        }
    }


    /**
     * Parses text size, defaulting to 10.
     * @param theme The theme.
     */
    public static int parseTextSize(Document theme, String path) {
        String size = XMLUtils.xpathString(theme, path, null);
        if (size == null || size.length() == 0) {
            return 10;
        }

        try {
            return Integer.parseInt(size);
        }
        catch (NumberFormatException nfe) {
        }
        return 10;
    }


    public static int parseTextSize(Document theme) {
        return parseTextSize(theme, XPATH_LABEL_FONT_SIZE);
    }


    /**
     * Parses the attribute 'showextramark', defaults to false.
     * @param theme The theme.
     */
    public static boolean parseShowExtraMark(Document theme) {
        String show = XMLUtils.xpathString(theme, XPATH_SHOWEXTRAMARK, null);
        return parseBoolean(show, false);
    }

    /**
     * Parses the attribute 'showpoints', defaults to false.
     * @param theme The theme.
     */
    public static boolean parseShowPoints(Document theme) {
        String show = XMLUtils.xpathString(theme, XPATH_SHOW_POINTS, null);
        return parseBoolean(show, false);
    }

    /**
     * Parses the attribute 'showmiddleheight', defaults to false.
     * @param theme The theme.
     */
    public static boolean parseShowMiddleHeight(Document theme) {
        String show = XMLUtils.xpathString(theme, XPATH_SHOW_MIDDLE_HEIGHT, null);
        return parseBoolean(show, false);
    }

    /**
     * Parses the attribute 'showarea', defaults to false.
     * @param theme The theme.
     */
    public static boolean parseShowArea(Document theme) {
        String show = XMLUtils.xpathString(theme, XPATH_SHOW_AREA, null);
        return parseBoolean(show, false);
    }

    /**
     * Parses the attribute 'showverticalline', defaults to true.
     * @param theme The theme.
     */
    public static boolean parseShowVerticalLine(Document theme) {
        String show = XMLUtils.xpathString(theme, XPATH_SHOW_VERTICAL_LINE, null);
        return parseBoolean(show, true);
    }

    /**
     * Parses the attribute 'showhorizontalline', defaults to true.
     * @param theme The theme.
     */
    public static boolean parseShowHorizontalLine(Document theme) {
        String show = XMLUtils.xpathString(theme, XPATH_SHOW_HORIZONTAL_LINE, null);
        return parseBoolean(show, true);
    }

    /**
     * Parses the attribute 'showlines', defaults to true.
     * @param theme The theme.
     */
    public static boolean parseShowLine(Document theme) {
        String show = XMLUtils.xpathString(theme, XPATH_SHOW_LINE, null);
        return parseBoolean(show, true);
    }

    /**
     * Parses the attribute 'showlinelabel', defaults to true.
     * @param theme The theme.
     */
    public static boolean parseShowLineLabel(Document theme) {
        String show = XMLUtils.xpathString(theme, XPATH_SHOW_LINE_LABEL, null);
        return parseBoolean(show, false);
    }

    public static boolean parseShowPointLabel(Document theme) {
        String show = XMLUtils.xpathString(theme, XPATH_SHOW_POINT_LABEL, null);
        return parseBoolean(show, false);
    }

    /**
     * Parses text color.
     * @param theme The theme.
     */
    public static Color parseTextColor(Document theme) {
        return parseRGB(getTextColorString(theme));
    }


    /**
     * Parses the font.
     * @param theme The theme.
     */
    public static Font parseTextFont(Document theme) {
        String font = XMLUtils.xpathString(theme, XPATH_LABEL_FONT_FACE, null);
        if (font == null || font.length() == 0) {
            return null;
        }

        int size = parseTextSize(theme);
        int style = parseTextStyle(theme);
        Font f = new Font (font, style, size);
        return f;
    }


    /**
     * Parses the text style, defaults to 'Font.PLAIN'.
     * @param theme The theme.
     */
    public static int parseTextStyle(Document theme, String path) {
        String style = XMLUtils.xpathString(theme, path, null);
        if (style == null || style.length() == 0) {
            return Font.PLAIN;
        }

        if (style.equals("italic")) {
            return Font.ITALIC;
        }
        else if (style.equals("bold")) {
            return Font.BOLD;
        }
        else {
            return Font.PLAIN;
        }
    }


    public static int parseTextStyle(Document theme) {
        return parseTextStyle(theme, XPATH_LABEL_FONT_STYLE);
    }


    public static boolean parseShowWidth(Document theme) {
        String show = XMLUtils.xpathString(theme, XPATH_SHOW_WIDTH, null);
        return parseBoolean(show, false);
    }


    public static boolean parseShowLevel(Document theme) {
        String show = XMLUtils.xpathString(theme, XPATH_SHOW_LEVEL, null);
        return parseBoolean(show, false);
    }

    /**
     * Parses the textorientation, defaults to 'vertical'.
     * @param theme The theme.
     */
    public static String parseTextOrientation(Document theme) {
        String o = XMLUtils.xpathString(theme, XPATH_TEXT_ORIENTATION, null);
        if ("true".equals(o)) {
            return "horizontal";
        }
        else {
            return "vertical";
        }
    }


    /**
     * Parses the text background color, defaults to white.
     * @param theme The theme.
     */
    public static Color parseTextBackground(Document theme) {
        String color = getLabelBackgroundColorString(theme);
        if (color == null || color.length() == 0) {
            return Color.WHITE;
        }
        return parseRGB(color);
    }


    /**
     * Parses the attribute whether to show background or not, defaults to
     * false.
     * @param theme The theme.
     */
    public static boolean parseLabelShowBackground(Document theme) {
        String show = XMLUtils.xpathString(theme, XPATH_LABEL_SHOW_BACKGROUND, null);
        return parseBoolean(show, false);
    }


    public static Color parseColor(String colorString) {
        if (colorString == null || colorString.length() == 0) {
            return null;
        }
        else if (colorString.indexOf("#") == 0) {
            return parseHexColor(colorString);
        }
        else if (colorString.indexOf(",") >= 0) {
            return parseRGB(colorString);
        }

        return null;
    }


    /**
     * Parse a string like "#00CC22" and return the corresponding color.
     *
     * @param hex The hex color value.
     *
     * @return a Color or null, if <i>hex</i> is empty.
     */
    public static Color parseHexColor(String hex) {
        if (hex == null) {
            return null;
        }

        return Color.decode(hex);
    }

    /**
     * Parse a string like "103, 100, 0" and return a corresping color.
     * @param rgbtext Color as string representation, e.g. "255,0,20".
     * @return Color, null in case of issues.
     */
    public static Color parseRGB(String rgbtext) {
        if (rgbtext == null) {
            return null;
        }
        String rgb[] = rgbtext.split(",");
        Color c = null;
        try {
            c = new Color(
                    Integer.parseInt(rgb[0].trim()),
                    Integer.parseInt(rgb[1].trim()),
                    Integer.parseInt(rgb[2].trim()));
        }
        catch (NumberFormatException nfe) {
            c = null;
        }
        return c;
    }


    public static String getLineColorString(Document theme) {
        return XMLUtils.xpathString(theme, XPATH_LINE_COLOR, null);
    }


    /** Get show border as string. */
    public static String getShowBorderString(Document theme) {
        return XMLUtils.xpathString(theme, XPATH_SHOW_BORDER, null);
    }


    /** Get fill color as string. */
    public static String getFillColorString(Document theme) {
        return XMLUtils.xpathString(theme, XPATH_FILL_COLOR, null);
    }


    public static String getLabelBackgroundColorString(Document theme) {
        return XMLUtils.xpathString(theme, XPATH_LABEL_BGCOLOR, null);
    }


    public static String getBackgroundColorString(Document theme) {
        return XMLUtils.xpathString(theme, XPATH_BACKGROUND_COLOR, null);
    }


    public static String getTextColorString(Document theme) {
        String textColor = XMLUtils.xpathString(theme, XPATH_LABEL_FONT_COLOR, null);
        return textColor;
    }


    public static String getSymbol(Document theme) {
        return XMLUtils.xpathString(theme, XPATH_SYMBOL, null);
    }


    public static String getTransparencyString(Document theme) {
        return XMLUtils.xpathString(theme, XPATH_TRANSPARENCY, null);
    }


    public static String getAreaTransparencyString(Document theme) {
        return XMLUtils.xpathString(theme, XPATH_AREA_TRANSPARENCY, null);
    }


    public static String getShowMinimum(Document theme) {
        return XMLUtils.xpathString(theme, XPATH_SHOW_MINIMUM, null);
    }


    public static String getShowMaximum(Document theme) {
        return XMLUtils.xpathString(theme, XPATH_SHOW_MAXIMUM, null);
    }


    /**
     * Gets color from color field.
     * @param theme    the theme document.
     * @return color.
     */
    public static Color parseFillColorField(Document theme) {
        return parseRGB(getFillColorString(theme));
    }


    public static boolean parseShowBorder(Document theme) {
        return parseBoolean(getShowBorderString(theme), false);
    }


    public static int parseTransparency(Document theme) {
        return parseInteger(getTransparencyString(theme), 50);
    }


    /**
     * Gets color from color field.
     * @param theme    the theme document.
     * @return color.
     */
    public static Color parseLineColorField(Document theme) {
        String lineColorStr = getLineColorString(theme);
        logger.debug("parseLineColorField: lineColorStr = " +
                (lineColorStr == null ? "null" : lineColorStr));
        return parseColor(lineColorStr);
    }


    public static Color parseAreaLineColorField(Document theme) {
        String lineColorStr = getAreaLineColorString(theme);
        logger.debug("parseLineColorField: lineColorStr = " +
                (lineColorStr == null ? "null" : lineColorStr));
        return parseColor(lineColorStr);
    }


    private static String getAreaLineColorString(Document theme) {
        return XMLUtils.xpathString(theme, XPATH_AREA_LINE_COLOR, null);
    }


    public static boolean parseShowMinimum(Document theme) {
        return parseBoolean(getShowMinimum(theme), false);
    }


    public static boolean parseShowMaximum(Document theme) {
        return parseBoolean(getShowMaximum(theme), false);
    }


    /**
     * Creates a MapserverStyle from the given XML theme.
     * This method uses a start- and endcolor to interpolate a
     * given number of color classes for the MapserverStyle.
     * @param theme
     * @return String representation of the MapserverStyle
     */
    public static String createDynamicMapserverStyle(Document theme,
            float from, float to, float step, CallMeta meta)
    {
        MapserverStyle ms = new MapserverStyle();

        String strStartColor = XMLUtils.xpathString(theme, XPATH_WSPLGEN_STARTCOLOR, null);
        Color startColor = strStartColor != null ? parseColor(strStartColor) : new Color(178, 201, 215);
        String strEndColor = XMLUtils.xpathString(theme, XPATH_WSPLGEN_ENDCOLOR, null);
        Color endColor = strEndColor != null? parseColor(strEndColor) : new Color(2, 27, 42);

        to = to != 0 ? to : 9999;
        step = step != 0 ? step : to;

        int numClasses = (int)((to - from) / step);

        float rd = (endColor.getRed()   - startColor.getRed())   / (float)numClasses;
        float gd = (endColor.getGreen() - startColor.getGreen()) / (float)numClasses;
        float bd = (endColor.getBlue()  - startColor.getBlue())  / (float)numClasses;

        if (numClasses > 1) {
            // Desktop Flys always added a last "and larger class"
            numClasses += 1;
        }

        for (int n = 0; n < numClasses; n++) {
            StringBuilder newColor = new StringBuilder();
            newColor.append(startColor.getRed()   + Math.round(n * rd));
            newColor.append(' ');
            newColor.append(startColor.getGreen() + Math.round(n * gd));
            newColor.append(' ');
            newColor.append(startColor.getBlue()  + Math.round(n * bd));

            String expr = createWSPLGENClassExpression(from + n * step, step, n + 1, numClasses);
            String name = createWSPLGENClassName(from + n * step, step, n + 1, numClasses, meta);

            Clazz c = new Clazz(name);
            Style s = new Style();
            s.setColor(newColor.toString());
            s.setSize(5);

            c.addItem(new Expression("(" + expr + ")"));
            c.addItem(s);

            ms.addClazz(c);
        }

        return ms.toString();
    }


    protected static String createWSPLGENClassExpression(float val, float step, int idx, int maxIdx) {
        if (idx < maxIdx) {
            return "[DIFF] >= " + val + " AND  [DIFF] < " + (val + step);
        }
        else {
            return "[DIFF] >= " + val;
        }
    }

    /**
     * Creates a class name for the mapfile style that visualizes a floodmap.
     * The class names are used in the map's legend.
     *
     * @param val       Current isobath value.
     * @param step      Difference between to class values.
     * @param idx       Current class index that is being processed.
     * @param maxIdx    Highest class index.
     * @param meta      Caller meta object used to determine locale.
     * @return
     */
    protected static String createWSPLGENClassName(float val, float step, int idx, int maxIdx, CallMeta meta) {
        assert meta != null : "CallMeta instance is null";

        if (idx < maxIdx) {
            return Resources.getMsg(meta, MSG_ISOBATH_CLASS,
                    new Object[] {val, val + step});
        }
        else {
            return Resources.getMsg(meta, MSG_ISOBATH_LASTCLASS,
                    new Object[] {val});
        }
    }


    public static String createMapserverStyle(Document theme) {
        String symbol    = getSymbol(theme);
        String backcolor = getLabelBackgroundColorString(theme);
        String linecolor = getLineColorString(theme);
        if (linecolor == null || "".equals(linecolor)) {
            logger.warn("createMapserverStyle: linecolor String is empty");
            linecolor = "0,128,255";
        }

        int linewidth = parseLineWidth(theme);

        MapserverStyle ms = new MapserverStyle();

        Clazz c = new Clazz(" ");

        Style s = new Style();
        s.setOutlineColor(linecolor.replace(",", " "));

        if (backcolor != null && backcolor.length() > 0) {
            s.setColor(backcolor.replace(",", " "));
        }

        s.setSize(linewidth);
        s.setSymbol(symbol);
        c.addItem(s);

        String textcolor = getTextColorString(theme);
        int    textsize  = parseTextSize(theme);

        if (textcolor != null && textcolor.length() > 0 && textsize > 0) {
            Label l = new Label();
            l.setColor(textcolor.replace(",", " "));
            l.setSize(textsize);
            c.addItem(l);
        }

        ms.addClazz(c);

        return ms.toString();
    }


    public static String getAreaBackgroundColorString(Document theme) {
        return XMLUtils.xpathString(theme, XPATH_AREA_BACKGROUND_COLOR, null);
    }


    public static Color parseAreaBackgroundColor(Document theme) {
        return parseColor(getAreaBackgroundColorString(theme));
    }


    public static int parseAreaTransparency(Document theme) {
        return parseInteger(getAreaTransparencyString(theme), 50);
    }


    public static boolean parseAreaShowBorder(Document theme) {
        return parseBoolean(getAreaShowBorderString(theme), false);
    }


    private static String getAreaShowBorderString(Document theme) {
        return XMLUtils.xpathString(theme, XPATH_AREA_SHOW_BORDER, null);
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org