diff flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/DistanceInfoService.java @ 3814:8083f6384023

merged flys-artifacts/pre2.6-2012-01-04
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:14:56 +0200
parents 26e19cdaed5e
children e92bc9b0ca1d
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/DistanceInfoService.java	Fri Sep 28 12:14:56 2012 +0200
@@ -0,0 +1,213 @@
+package de.intevation.flys.artifacts.services;
+
+import java.math.BigDecimal;
+import java.util.Iterator;
+
+import org.apache.log4j.Logger;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import de.intevation.artifacts.CallMeta;
+import de.intevation.artifacts.GlobalContext;
+
+import de.intevation.artifacts.common.ArtifactNamespaceContext;
+import de.intevation.artifacts.common.utils.XMLUtils;
+
+import de.intevation.flys.model.Annotation;
+import de.intevation.flys.model.Attribute;
+import de.intevation.flys.model.Position;
+import de.intevation.flys.model.Range;
+import de.intevation.flys.model.Edge;
+
+import de.intevation.flys.artifacts.model.AnnotationsFactory;
+
+import de.intevation.flys.artifacts.cache.CacheFactory;
+
+import net.sf.ehcache.Cache;
+
+/**
+ * This service provides information about distances of a specified river.
+ *
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class DistanceInfoService extends FLYSService {
+
+    private static enum DistanceFilter {
+        NONE, LOCATIONS, DISTANCES
+    }
+
+    /** The logger used in this service. */
+    private static Logger logger = Logger.getLogger(DistanceInfoService.class);
+
+    public static final String CACHE_NAME = "service-distanceinfo";
+
+    public static final String RIVER_XPATH = "/art:river/text()";
+
+    public static final String FILTER_XPATH = "/art:river/art:filter/text()";
+
+
+    /**
+     * The default constructor.
+     */
+    public DistanceInfoService() {
+    }
+
+
+    @Override
+    public Document doProcess(
+        Document      data,
+        GlobalContext globalContext,
+        CallMeta      callMeta
+    ) {
+        logger.debug("DistanceInfoService.process");
+
+        String river = XMLUtils.xpathString(
+            data, RIVER_XPATH, ArtifactNamespaceContext.INSTANCE);
+
+        String filter  = XMLUtils.xpathString(
+            data, FILTER_XPATH, ArtifactNamespaceContext.INSTANCE);
+
+        if (river == null || (river = river.trim()).length() == 0) {
+            logger.warn("No river specified. Cannot return distance info!");
+            return XMLUtils.newDocument();
+        }
+
+        logger.debug("Search distances for river: " + river);
+
+        Cache cache = CacheFactory.getCache(CACHE_NAME);
+
+        if (cache == null) {
+            logger.debug("no cache configured for distance info");
+            return getUncached(river, filter);
+        }
+
+
+        String key = getCacheKey(river, filter);
+
+        net.sf.ehcache.Element element = cache.get(key);
+
+        if (element != null) {
+            logger.debug("distance info found in cache");
+            return (Document)element.getValue();
+        }
+
+        Document result = getUncached(river, filter);
+
+        element = new net.sf.ehcache.Element(key, result);
+
+        logger.debug("store distance info found into cache");
+
+        cache.put(element);
+
+        return result;
+    }
+
+
+    protected String getCacheKey(String river, String filtertype) {
+        return filtertype != null && filtertype.length() > 0
+            ? river + "_" + filtertype
+            : river;
+    }
+
+
+    protected Document getUncached(String river, String filtertype) {
+
+        Document result = XMLUtils.newDocument();
+
+        Iterator<Annotation> iter =
+            AnnotationsFactory.getAnnotationsIterator(river);
+
+        Element all = result.createElement("distances");
+
+        DistanceFilter filter = getDistanceFilter(filtertype);
+
+        while (iter.hasNext()) {
+            Annotation a = iter.next();
+            Element distance = buildDistanceNode(result, a, filter);
+
+            if (distance != null) {
+                all.appendChild(distance);
+            }
+        }
+
+        result.appendChild(all);
+
+        return result;
+    }
+
+
+    protected static DistanceFilter getDistanceFilter(String type) {
+        if (type.equals("locations")) {
+            logger.debug("Found 'location' filter.");
+            return DistanceFilter.LOCATIONS;
+        }
+        else if (type.equals("distances")) {
+            logger.debug("Found 'distances' filter.");
+            return DistanceFilter.DISTANCES;
+        }
+
+        logger.debug("Do not use any filter at all.");
+
+        return DistanceFilter.NONE;
+    }
+
+
+    /**
+     * Builds an Element for a distance info.
+     *
+     * @param anno The Annotation that provides information about the distance.
+     *
+     * @return an Element that contains information about a distance.
+     */
+    protected static Element buildDistanceNode(
+        Document       document,
+        Annotation     anno,
+        DistanceFilter filter
+    ) {
+        Position   pos   = anno.getPosition();
+        Range      range = anno.getRange();
+        Attribute  attr  = anno.getAttribute();
+        Edge       edge  = anno.getEdge();
+        BigDecimal a     = range.getA();
+        BigDecimal b     = range.getB();
+
+        if (b == null && filter == DistanceFilter.DISTANCES) {
+            return null;
+        }
+
+        if (b != null && filter == DistanceFilter.LOCATIONS) {
+            return null;
+        }
+
+        Element distance = document.createElement("distance");
+
+        distance.setAttribute("description", pos.getValue());
+
+        String riverSide = attr.getValue();
+
+        if (riverSide != null && riverSide.length() > 0) {
+            distance.setAttribute("riverside", riverSide);
+        }
+
+        if (a != null) {
+            distance.setAttribute("from", a.toString());
+        }
+        if (b != null) {
+            distance.setAttribute("to", b.toString());
+        }
+        if (edge != null) {
+            BigDecimal bottom = edge.getBottom();
+            BigDecimal top    = edge.getTop();
+            if (bottom != null) {
+                distance.setAttribute("bottom", bottom.toString());
+            }
+            if (top != null) {
+                distance.setAttribute("top", top.toString());
+            }
+        }
+
+        return distance;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org