view flys-client/src/main/java/de/intevation/flys/client/server/ChartServiceHelper.java @ 5779:ebec12def170

Datacage: Add a pool of builders to make it multi threadable. XML DOM is not thread safe. Therefore the old implementation only allowed one thread to use the builder at a time. As the complexity of the configuration has increased over time this has become a bottleneck of the whole application because it took quiet some time to build a result. Furthermore the builder code path is visited very frequent. So many concurrent requests were piled up resulting in long waits for the users. To mitigate this problem a round robin pool of builders is used now. Each of the pooled builders has an independent copy of the XML template and can be run in parallel. The number of builders is determined by the system property 'flys.datacage.pool.size'. It defaults to 4.
author Sascha L. Teichmann <teichmann@intevation.de>
date Sun, 21 Apr 2013 12:48:09 +0200
parents 1780841d79af
children
line wrap: on
line source
package de.intevation.flys.client.server;

import java.util.Map;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import org.apache.log4j.Logger;

import de.intevation.artifacts.common.ArtifactNamespaceContext;
import de.intevation.artifacts.common.utils.XMLUtils;
import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator;


/**
 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
 */
public class ChartServiceHelper {

    private static final Logger logger =
        Logger.getLogger(ChartServiceHelper.class);


    /** The default chart width if no value is specified in the request.*/
    public static final int DEFAULT_CHART_WIDTH  = 600;

    /** The default chart height if no value is specified in the request.*/
    public static final int DEFAULT_CHART_HEIGHT = 400;


    private ChartServiceHelper() {
    }

    /**
     * This method returns a document which might contain parameters to adjust
     * chart settings. The document is created using the information that are
     * contained in the request object.
     *
     * @param req The request document.
     *
     * @return a document to adjust chart settings.
     */
    protected static Document getChartAttributes(Map<String, String> req) {
        logger.debug("ChartServiceHelper.getChartAttributes");

        Document doc = XMLUtils.newDocument();

        ElementCreator ec = new ElementCreator(
            doc,
            ArtifactNamespaceContext.NAMESPACE_URI,
            ArtifactNamespaceContext.NAMESPACE_PREFIX);

        Element attributes = ec.create("attributes");

        appendChartSize(req, attributes, ec);
        appendFormat(req, attributes, ec);
        appendXRange(req, attributes, ec);
        appendYRange(req, attributes, ec);
        appendCurrentKm(req, attributes, ec);

        doc.appendChild(attributes);

        return doc;
    }


    /**
     * This method extracts the size (width/height) of a chart from request
     * object and append those values - if they exist - to the attribute
     * document used to adjust chart settings.
     *
     * @param req The request object that might contain the chart size.
     * @param attributes The attributes element used to adjust chart settings.
     * @param ec The ElementCreator that might be used to create new Elements.
     */
    protected static void appendChartSize(
        Map<String, String> req,
        Element             attributes,
        ElementCreator      ec)
    {
        logger.debug("ChartServiceHelper.appendChartSize");

        Element size = ec.create("size");

        String width  = req.get("width");
        String height = req.get("height");

        if (width == null || height == null) {
            width  = String.valueOf(DEFAULT_CHART_WIDTH);
            height = String.valueOf(DEFAULT_CHART_HEIGHT);
        }

        ec.addAttr(size, "width", width, true);
        ec.addAttr(size, "height", height, true);

        attributes.appendChild(size);
    }


    /**
     * This method extracts the x range for the chart from request object and
     * appends those range - if it exists - to the attribute document used to
     * adjust the chart settings.
     *
     * @param req The request object that might contain the chart size.
     * @param doc The attribute document used to adjust chart settings.
     * @param ec The ElementCreator that might be used to create new Elements.
     */
    protected static void appendXRange(
        Map<String, String> req,
        Element             attributes,
        ElementCreator      ec)
    {
        logger.debug("ChartServiceHelper.appendXRange");

        Element range = ec.create("xrange");

        String from = req.get("minx");
        String to   = req.get("maxx");

        if (from != null && to != null) {
            ec.addAttr(range, "from", from, true);
            ec.addAttr(range, "to", to, true);

            attributes.appendChild(range);
        }
    }


    /**
     * This method extracts the x range for the chart from request object and
     * appends those range - if it exists - to the attribute document used to
     * adjust the chart settings.
     *
     * @param req The request object that might contain the chart size.
     * @param doc The attribute document used to adjust chart settings.
     * @param ec The ElementCreator that might be used to create new Elements.
     */
    protected static void appendYRange(
        Map<String, String> req,
        Element             attributes,
        ElementCreator      ec)
    {
        logger.debug("ChartServiceHelper.appendYRange");

        Element range = ec.create("yrange");

        String from = req.get("miny");
        String to   = req.get("maxy");

        if (from != null && to != null) {
            ec.addAttr(range, "from", from, true);
            ec.addAttr(range, "to", to, true);

            attributes.appendChild(range);
        }
    }


    /**
     * This method extracts the format string from request object and appends
     * those format - if existing - to the attribute document used to adjust
     * the chart settings.
     *
     * @param req The request object that might contain the chart format.
     * @param doc The attribute document used to adjust chart settings.
     * @param ec The ElementCreator that might be used to create new Elements.
     */
    protected static void appendFormat(
        Map<String, String> req,
        Element             attributes,
        ElementCreator      ec

    ) {
        logger.debug("ChartServiceHelper.appendFormat");

        String formatStr = req.get("format");
        if (formatStr == null || formatStr.length() == 0) {
            return;
        }

        Element format = ec.create("format");
        ec.addAttr(format, "value", formatStr, true);

        attributes.appendChild(format);
    }


    /**
     * This method extracts the current km for the chart from request object and
     * appends this km - if it exists - to the attribute document used to
     * adjust the chart settings.
     *
     * @param req The request object that might contain the chart size.
     * @param doc The attribute document used to adjust chart settings.
     * @param ec The ElementCreator that might be used to create new Elements.
     */
    protected static void appendCurrentKm(
        Map<String, String> req,
        Element             attributes,
        ElementCreator      ec)
    {
        logger.debug("ChartServiceHelper.appendCurrentKm");

        Element currentKm = ec.create("currentKm");

        String km = req.get("km");

        if (km != null) {
            ec.addAttr(currentKm, "km", km, true);

            attributes.appendChild(currentKm);
        }
    }

}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org