teichmann@5835: package org.dive4elements.river.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: teichmann@5835: import org.dive4elements.artifacts.common.ArtifactNamespaceContext; teichmann@5835: import org.dive4elements.artifacts.common.utils.ClientProtocolUtils; teichmann@5835: import org.dive4elements.artifacts.common.utils.XMLUtils; ingo@535: teichmann@5835: import org.dive4elements.artifacts.httpclient.http.HttpClient; teichmann@5835: import org.dive4elements.artifacts.httpclient.http.HttpClientImpl; ingo@535: teichmann@5835: import org.dive4elements.river.client.shared.Transform2D; teichmann@5835: import org.dive4elements.river.client.shared.exceptions.ServerException; teichmann@5835: import org.dive4elements.river.client.shared.model.Axis; teichmann@5835: import org.dive4elements.river.client.shared.model.DateAxis; teichmann@5835: import org.dive4elements.river.client.shared.model.NumberAxis; teichmann@5835: import org.dive4elements.river.client.shared.model.ChartInfo; teichmann@5835: import org.dive4elements.river.client.shared.model.Collection; teichmann@5835: teichmann@5835: import org.dive4elements.river.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 Ingo Weinzierl 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@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 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 transformer = new ArrayList(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 :