ingo@535: package de.intevation.flys.client.server;
ingo@535: 
ingo@535: import java.io.InputStream;
ingo@535: import java.io.IOException;
ingo@561: import java.util.ArrayList;
ingo@1597: import java.util.Date;
ingo@561: import java.util.List;
ingo@549: import java.util.Map;
ingo@535: 
ingo@535: import javax.xml.xpath.XPathConstants;
ingo@535: 
ingo@535: import org.w3c.dom.Document;
ingo@1597: import org.w3c.dom.Element;
ingo@552: import org.w3c.dom.NodeList;
ingo@535: 
ingo@1367: import org.apache.log4j.Logger;
ingo@1367: 
ingo@535: import com.google.gwt.user.server.rpc.RemoteServiceServlet;
ingo@535: 
ingo@535: import de.intevation.artifacts.common.ArtifactNamespaceContext;
ingo@535: import de.intevation.artifacts.common.utils.ClientProtocolUtils;
ingo@535: import de.intevation.artifacts.common.utils.XMLUtils;
ingo@535: 
ingo@535: import de.intevation.artifacts.httpclient.http.HttpClient;
ingo@535: import de.intevation.artifacts.httpclient.http.HttpClientImpl;
ingo@535: 
ingo@535: import de.intevation.flys.client.shared.Transform2D;
ingo@535: import de.intevation.flys.client.shared.exceptions.ServerException;
ingo@552: import de.intevation.flys.client.shared.model.Axis;
ingo@1597: import de.intevation.flys.client.shared.model.DateAxis;
ingo@1597: import de.intevation.flys.client.shared.model.NumberAxis;
ingo@552: import de.intevation.flys.client.shared.model.ChartInfo;
ingo@535: import de.intevation.flys.client.shared.model.Collection;
ingo@535: 
ingo@535: import de.intevation.flys.client.client.services.ChartInfoService;
ingo@535: 
ingo@535: 
ingo@535: /**
ingo@535:  * This service fetches a document that contains meta information for a specific
ingo@535:  * chart.
ingo@535:  *
ingo@535:  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
ingo@535:  */
ingo@535: public class ChartInfoServiceImpl
ingo@535: extends      RemoteServiceServlet
ingo@535: implements   ChartInfoService
ingo@535: {
ingo@1367:     private static final Logger logger =
ingo@1367:         Logger.getLogger(ChartInfoServiceImpl.class);
ingo@1367: 
ingo@1367: 
ingo@535:     public static final String XPATH_TRANSFORM_MATRIX =
ingo@561:         "/art:chartinfo/art:transformation-matrix/art:matrix";
ingo@535: 
ingo@552:     public static final String XPATH_X_AXES =
ingo@552:         "/art:chartinfo/art:axes/art:domain";
ingo@552: 
ingo@552:     public static final String XPATH_Y_AXES =
ingo@552:         "/art:chartinfo/art:axes/art:range";
ingo@552: 
ingo@535:     public static final String EXCEPTION_STRING = "error_chart_info_service";
ingo@535: 
ingo@535: 
ingo@552:     public ChartInfo getChartInfo(
ingo@549:         Collection          collection,
ingo@549:         String              locale,
ingo@549:         String              type,
ingo@549:         Map<String, String> attr)
ingo@535:     throws ServerException
ingo@535:     {
ingo@1367:         logger.info("ChartInfoServiceImpl.getChartInfo");
ingo@535: 
raimund@1425:         String url  = getServletContext().getInitParameter("server-url");
raimund@1425: 
ingo@535:         Document request = ClientProtocolUtils.newOutCollectionDocument(
ingo@535:                 collection.identifier(),
ingo@535:                 type,
ingo@535:                 type,
ingo@549:                 ChartServiceHelper.getChartAttributes(attr));
ingo@535: 
ingo@535:         try {
ingo@535:             HttpClient client = new HttpClientImpl(url, locale);
ingo@535:             InputStream in    = client.collectionOut(
ingo@535:                 request,
ingo@535:                 collection.identifier(),
ingo@535:                 type + "_chartinfo");
ingo@535: 
ingo@535:             Document info = XMLUtils.parseDocument(in);
ingo@535: 
ingo@535:             return parseInfoDocument(info);
ingo@535:         }
ingo@535:         catch (IOException ioe) {
ingo@556:             ioe.printStackTrace();
ingo@556:         }
ingo@556:         catch (Exception e) {
ingo@556:             e.printStackTrace();
ingo@535:         }
ingo@535: 
ingo@1367:         logger.debug("Error while fetching chart info.");
ingo@535: 
ingo@535:         throw new ServerException(EXCEPTION_STRING);
ingo@535:     }
ingo@535: 
ingo@535: 
felix@4053:     /**
felix@4053:      * Parse ChartInfo-Part of document, create Transforms and axes
felix@4053:      * from it.
felix@4053:      */
ingo@552:     protected ChartInfo parseInfoDocument(Document doc) {
ingo@561:         Transform2D[] transformer = parseTransformationMatrix(doc);
ingo@561:         Axis[]      xAxes         = parseXAxes(doc);
ingo@561:         Axis[]      yAxes         = parseYAxes(doc);
ingo@552: 
ingo@552:         return new ChartInfo(xAxes, yAxes, transformer);
ingo@552:     }
ingo@552: 
ingo@552: 
ingo@552:     protected Axis[] parseXAxes(Document doc) {
ingo@1367:         logger.debug("ChartInfoServiceImpl.parseXAxes");
ingo@552: 
ingo@552:         NodeList axes = (NodeList) XMLUtils.xpath(
ingo@552:             doc,
ingo@552:             XPATH_X_AXES,
ingo@552:             XPathConstants.NODESET,
ingo@552:             ArtifactNamespaceContext.INSTANCE);
ingo@552: 
ingo@552:         return parseAxes(axes);
ingo@552:     }
ingo@552: 
ingo@552: 
ingo@552:     protected Axis[] parseYAxes(Document doc) {
ingo@1367:         logger.debug("ChartInfoServiceImpl.parseYAxes");
ingo@552: 
ingo@552:         NodeList axes = (NodeList) XMLUtils.xpath(
ingo@552:             doc,
ingo@552:             XPATH_Y_AXES,
ingo@552:             XPathConstants.NODESET,
ingo@552:             ArtifactNamespaceContext.INSTANCE);
ingo@552: 
ingo@552:         return parseAxes(axes);
ingo@552:     }
ingo@552: 
ingo@552: 
ingo@552:     protected Axis[] parseAxes(NodeList axes) {
ingo@1367:         logger.debug("ChartInfoServiceImpl.parseAxes");
ingo@552: 
ingo@552:         int count = axes != null ? axes.getLength() : 0;
ingo@552: 
ingo@1367:         logger.debug("Chart has " + count + " axes.");
ingo@552: 
ingo@552:         if (count == 0) {
ingo@552:             return null;
ingo@552:         }
ingo@552: 
ingo@552:         Axis[] result = new Axis[count];
ingo@552: 
ingo@1597:         String ns = ArtifactNamespaceContext.NAMESPACE_URI;
ingo@552: 
ingo@1597:         for (int i = 0; i < count; i++) {
ingo@1597:             Element node = (Element) axes.item(i);
ingo@552: 
ingo@1597:             String posStr   = node.getAttributeNS(ns, "pos");
ingo@1597:             String fromStr  = node.getAttributeNS(ns, "from");
ingo@1597:             String toStr    = node.getAttributeNS(ns, "to");
ingo@1597:             String minStr   = node.getAttributeNS(ns, "min");
ingo@1597:             String maxStr   = node.getAttributeNS(ns, "max");
ingo@1597:             String axisType = node.getAttributeNS(ns, "axistype");
ingo@561: 
ingo@552:             try {
ingo@552:                 int    pos  = Integer.parseInt(posStr);
ingo@552: 
ingo@556:                 if (pos >= result.length) {
ingo@556:                     // this should never happen
ingo@1367:                     logger.debug("The axis is out of valid range: " + pos);
ingo@556:                     continue;
ingo@556:                 }
ingo@556: 
ingo@1597:                 if (axisType != null && axisType.equals(DateAxis.TYPE)) {
ingo@1597:                     long from = Long.parseLong(fromStr);
ingo@1597:                     long to   = Long.parseLong(toStr);
ingo@1597:                     long min  = Long.parseLong(minStr);
ingo@1597:                     long max  = Long.parseLong(maxStr);
ingo@1597: 
ingo@1597:                     if (logger.isDebugEnabled()) {
ingo@1597:                         logger.debug("date axis from: " + new Date(from));
ingo@1597:                         logger.debug("date axis to  : " + new Date(to));
ingo@1597:                         logger.debug("date axis min : " + new Date(min));
ingo@1597:                         logger.debug("date axis max : " + new Date(max));
ingo@1597:                     }
ingo@1597: 
ingo@1597:                     result[pos] = new DateAxis(pos, from, to, min, max);
ingo@1597:                 }
ingo@1597:                 else {
ingo@1597:                     double from = Double.parseDouble(fromStr);
ingo@1597:                     double to   = Double.parseDouble(toStr);
ingo@1597:                     double min  = Double.parseDouble(minStr);
ingo@1597:                     double max  = Double.parseDouble(maxStr);
ingo@1597: 
ingo@1597:                     result[pos] = new NumberAxis(pos, from, to, min, max);
ingo@1597:                 }
ingo@552:             }
ingo@552:             catch (NumberFormatException nfe) {
ingo@552:                 nfe.printStackTrace();
ingo@552:             }
ingo@552:         }
ingo@552: 
ingo@1367:         logger.debug("Parsed " + result.length + " axes");
ingo@552: 
ingo@552:         return result;
ingo@552:     }
ingo@552: 
ingo@552: 
ingo@535:     /**
ingo@535:      * Parses the chart info document and extract the Transform2D values.
ingo@535:      *
ingo@535:      * @param doc The chart info document.
ingo@535:      *
ingo@535:      * @return a Transform2D object to transfrom pixel coordinates into chart
ingo@535:      * coordinates.
ingo@535:      */
ingo@561:     protected Transform2D[] parseTransformationMatrix(Document doc) {
ingo@1367:         logger.debug("ChartInfoServiceImpl.parseTransformationMatrix");
ingo@535: 
ingo@561:         NodeList matrix = (NodeList) XMLUtils.xpath(
ingo@535:             doc,
ingo@535:             XPATH_TRANSFORM_MATRIX,
ingo@561:             XPathConstants.NODESET,
ingo@535:             ArtifactNamespaceContext.INSTANCE);
ingo@535: 
ingo@561:         int num = matrix != null ? matrix.getLength() : 0;
ingo@561: 
ingo@561:         List<Transform2D> transformer = new ArrayList<Transform2D>(num);
ingo@561: 
ingo@561:         for (int i = 0; i < num; i++) {
ingo@1598:             Transform2D t = createTransformer((Element) matrix.item(i));
ingo@561: 
ingo@561:             if (t == null) {
ingo@1367:                 logger.warn("Broken transformation matrix at pos: " + i);
ingo@561:                 continue;
ingo@561:             }
ingo@561: 
ingo@561:             transformer.add(t);
ingo@535:         }
ingo@535: 
sascha@3379:         return transformer.toArray(new Transform2D[num]);
ingo@561:     }
ingo@561: 
ingo@561: 
ingo@1598:     protected Transform2D createTransformer(Element matrix) {
ingo@1598:         String ns = ArtifactNamespaceContext.NAMESPACE_URI;
ingo@535: 
ingo@1598:         String sx    = matrix.getAttributeNS(ns, "sx");
ingo@1598:         String sy    = matrix.getAttributeNS(ns, "sy");
ingo@1598:         String tx    = matrix.getAttributeNS(ns, "tx");
ingo@1598:         String ty    = matrix.getAttributeNS(ns, "ty");
ingo@1598:         String xType = matrix.getAttributeNS(ns, "xtype");
ingo@1598:         String yType = matrix.getAttributeNS(ns, "ytype");
ingo@535: 
ingo@1598:         xType = xType == null || xType.length() == 0 ? "number" : xType;
ingo@1598:         yType = yType == null || yType.length() == 0 ? "number" : yType;
ingo@535: 
ingo@535:         if (sx != null && sy != null && tx != null && ty != null) {
ingo@535:             try {
ingo@1598:                 logger.debug("Create new Transform2D with x format: " + xType);
ingo@1598:                 logger.debug("Create new Transform2D with y format: " + yType);
ingo@1598: 
ingo@535:                 return new Transform2D(
ingo@535:                     Double.parseDouble(sx),
ingo@535:                     Double.parseDouble(sy),
ingo@535:                     Double.parseDouble(tx),
ingo@1598:                     Double.parseDouble(ty),
ingo@1598:                     xType, yType);
ingo@535:             }
ingo@535:             catch (NumberFormatException nfe) {
ingo@1367:                 logger.warn("Error while parsing matrix values.");
ingo@535:             }
ingo@535:         }
ingo@535: 
ingo@1367:         logger.warn("No matrix values found.");
ingo@535: 
ingo@535:         return new Transform2D(1d, 1d, 0d, 0d);
ingo@535:     }
ingo@535: }
ingo@535: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :