view flys-client/src/main/java/de/intevation/flys/client/server/ChartInfoServiceImpl.java @ 2461:4e81439ffa28

Fix flys/issue462 flys-client/trunk@4167 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Tue, 20 Mar 2012 10:09:14 +0000
parents 8c1f90e380a3
children 0de61fc9d281
line wrap: on
line source
package de.intevation.flys.client.server;

import java.io.InputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.xml.xpath.XPathConstants;

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

import org.apache.log4j.Logger;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

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

import de.intevation.artifacts.httpclient.http.HttpClient;
import de.intevation.artifacts.httpclient.http.HttpClientImpl;

import de.intevation.flys.client.shared.Transform2D;
import de.intevation.flys.client.shared.exceptions.ServerException;
import de.intevation.flys.client.shared.model.Axis;
import de.intevation.flys.client.shared.model.DateAxis;
import de.intevation.flys.client.shared.model.NumberAxis;
import de.intevation.flys.client.shared.model.ChartInfo;
import de.intevation.flys.client.shared.model.Collection;

import de.intevation.flys.client.client.services.ChartInfoService;


/**
 * This service fetches a document that contains meta information for a specific
 * chart.
 *
 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
 */
public class ChartInfoServiceImpl
extends      RemoteServiceServlet
implements   ChartInfoService
{
    private static final Logger logger =
        Logger.getLogger(ChartInfoServiceImpl.class);


    public static final String XPATH_TRANSFORM_MATRIX =
        "/art:chartinfo/art:transformation-matrix/art:matrix";

    public static final String XPATH_X_AXES =
        "/art:chartinfo/art:axes/art:domain";

    public static final String XPATH_Y_AXES =
        "/art:chartinfo/art:axes/art:range";

    public static final String EXCEPTION_STRING = "error_chart_info_service";


    public ChartInfo getChartInfo(
        Collection          collection,
        String              locale,
        String              type,
        Map<String, String> attr)
    throws ServerException
    {
        logger.info("ChartInfoServiceImpl.getChartInfo");

        String url  = getServletContext().getInitParameter("server-url");

        Document request = ClientProtocolUtils.newOutCollectionDocument(
                collection.identifier(),
                type,
                type,
                ChartServiceHelper.getChartAttributes(attr));

        try {
            HttpClient client = new HttpClientImpl(url, locale);
            InputStream in    = client.collectionOut(
                request,
                collection.identifier(),
                type + "_chartinfo");

            Document info = XMLUtils.parseDocument(in);

            return parseInfoDocument(info);
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
        catch (Exception e) {
            e.printStackTrace();
        }

        logger.debug("Error while fetching chart info.");

        throw new ServerException(EXCEPTION_STRING);
    }


    protected ChartInfo parseInfoDocument(Document doc) {
        Transform2D[] transformer = parseTransformationMatrix(doc);
        Axis[]      xAxes         = parseXAxes(doc);
        Axis[]      yAxes         = parseYAxes(doc);

        return new ChartInfo(xAxes, yAxes, transformer);
    }


    protected Axis[] parseXAxes(Document doc) {
        logger.debug("ChartInfoServiceImpl.parseXAxes");

        NodeList axes = (NodeList) XMLUtils.xpath(
            doc,
            XPATH_X_AXES,
            XPathConstants.NODESET,
            ArtifactNamespaceContext.INSTANCE);

        return parseAxes(axes);
    }


    protected Axis[] parseYAxes(Document doc) {
        logger.debug("ChartInfoServiceImpl.parseYAxes");

        NodeList axes = (NodeList) XMLUtils.xpath(
            doc,
            XPATH_Y_AXES,
            XPathConstants.NODESET,
            ArtifactNamespaceContext.INSTANCE);

        return parseAxes(axes);
    }


    protected Axis[] parseAxes(NodeList axes) {
        logger.debug("ChartInfoServiceImpl.parseAxes");

        int count = axes != null ? axes.getLength() : 0;

        logger.debug("Chart has " + count + " axes.");

        if (count == 0) {
            return null;
        }

        Axis[] result = new Axis[count];

        String ns = ArtifactNamespaceContext.NAMESPACE_URI;

        for (int i = 0; i < count; i++) {
            Element node = (Element) axes.item(i);

            String posStr   = node.getAttributeNS(ns, "pos");
            String fromStr  = node.getAttributeNS(ns, "from");
            String toStr    = node.getAttributeNS(ns, "to");
            String minStr   = node.getAttributeNS(ns, "min");
            String maxStr   = node.getAttributeNS(ns, "max");
            String axisType = node.getAttributeNS(ns, "axistype");

            try {
                int    pos  = Integer.parseInt(posStr);

                if (pos >= result.length) {
                    // this should never happen
                    logger.debug("The axis is out of valid range: " + pos);
                    continue;
                }

                if (axisType != null && axisType.equals(DateAxis.TYPE)) {
                    long from = Long.parseLong(fromStr);
                    long to   = Long.parseLong(toStr);
                    long min  = Long.parseLong(minStr);
                    long max  = Long.parseLong(maxStr);

                    if (logger.isDebugEnabled()) {
                        logger.debug("date axis from: " + new Date(from));
                        logger.debug("date axis to  : " + new Date(to));
                        logger.debug("date axis min : " + new Date(min));
                        logger.debug("date axis max : " + new Date(max));
                    }

                    result[pos] = new DateAxis(pos, from, to, min, max);
                }
                else {
                    double from = Double.parseDouble(fromStr);
                    double to   = Double.parseDouble(toStr);
                    double min  = Double.parseDouble(minStr);
                    double max  = Double.parseDouble(maxStr);

                    result[pos] = new NumberAxis(pos, from, to, min, max);
                }
            }
            catch (NumberFormatException nfe) {
                nfe.printStackTrace();
            }
        }

        logger.debug("Parsed " + result.length + " axes");

        return result;
    }


    /**
     * Parses the chart info document and extract the Transform2D values.
     *
     * @param doc The chart info document.
     *
     * @return a Transform2D object to transfrom pixel coordinates into chart
     * coordinates.
     */
    protected Transform2D[] parseTransformationMatrix(Document doc) {
        logger.debug("ChartInfoServiceImpl.parseTransformationMatrix");

        NodeList matrix = (NodeList) XMLUtils.xpath(
            doc,
            XPATH_TRANSFORM_MATRIX,
            XPathConstants.NODESET,
            ArtifactNamespaceContext.INSTANCE);

        int num = matrix != null ? matrix.getLength() : 0;

        List<Transform2D> transformer = new ArrayList<Transform2D>(num);

        for (int i = 0; i < num; i++) {
            Transform2D t = createTransformer((Element) matrix.item(i));

            if (t == null) {
                logger.warn("Broken transformation matrix at pos: " + i);
                continue;
            }

            transformer.add(t);
        }

        return (Transform2D[]) transformer.toArray(new Transform2D[num]);
    }


    protected Transform2D createTransformer(Element matrix) {
        String ns = ArtifactNamespaceContext.NAMESPACE_URI;

        String sx    = matrix.getAttributeNS(ns, "sx");
        String sy    = matrix.getAttributeNS(ns, "sy");
        String tx    = matrix.getAttributeNS(ns, "tx");
        String ty    = matrix.getAttributeNS(ns, "ty");
        String xType = matrix.getAttributeNS(ns, "xtype");
        String yType = matrix.getAttributeNS(ns, "ytype");

        xType = xType == null || xType.length() == 0 ? "number" : xType;
        yType = yType == null || yType.length() == 0 ? "number" : yType;

        if (sx != null && sy != null && tx != null && ty != null) {
            try {
                logger.debug("Create new Transform2D with x format: " + xType);
                logger.debug("Create new Transform2D with y format: " + yType);

                return new Transform2D(
                    Double.parseDouble(sx),
                    Double.parseDouble(sy),
                    Double.parseDouble(tx),
                    Double.parseDouble(ty),
                    xType, yType);
            }
            catch (NumberFormatException nfe) {
                logger.warn("Error while parsing matrix values.");
            }
        }

        logger.warn("No matrix values found.");

        return new Transform2D(1d, 1d, 0d, 0d);
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org