ingo@301: package de.intevation.flys.artifacts.services;
ingo@301:
ingo@301: import java.math.BigDecimal;
sascha@644: import java.util.Iterator;
ingo@301:
ingo@301: import org.apache.log4j.Logger;
ingo@301:
ingo@301: import org.w3c.dom.Document;
ingo@301: import org.w3c.dom.Element;
ingo@301:
ingo@301: import de.intevation.artifacts.CallMeta;
ingo@301:
ingo@301: import de.intevation.artifacts.common.ArtifactNamespaceContext;
ingo@301: import de.intevation.artifacts.common.utils.XMLUtils;
ingo@301: import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator;
ingo@301:
ingo@301: import de.intevation.artifactdatabase.DefaultService;
ingo@301:
ingo@316: import de.intevation.flys.backend.SessionHolder;
ingo@301: import de.intevation.flys.model.Annotation;
ingo@301: import de.intevation.flys.model.Attribute;
ingo@301: import de.intevation.flys.model.Position;
ingo@301: import de.intevation.flys.model.Range;
ingo@301:
ingo@301: import de.intevation.flys.artifacts.model.AnnotationsFactory;
ingo@301:
sascha@314: import org.hibernate.Session;
ingo@301:
sascha@644: import de.intevation.flys.artifacts.cache.CacheFactory;
sascha@644:
sascha@644: import net.sf.ehcache.Cache;
sascha@644:
ingo@301: /**
ingo@301: * This service provides information about distances of a specified river.
ingo@301: *
ingo@301: * @author Ingo Weinzierl
ingo@301: */
ingo@301: public class DistanceInfoService extends DefaultService {
ingo@301:
ingo@301: /** The logger used in this service.*/
ingo@301: private static Logger logger = Logger.getLogger(DistanceInfoService.class);
ingo@301:
sascha@644: public static final String CACHE_NAME = "service-distanceinfo";
sascha@644:
sascha@644: public static final String RIVER_XPATH = "/art:river/text()";
sascha@644:
ingo@301:
ingo@301: /**
ingo@301: * The default constructor.
ingo@301: */
ingo@301: public DistanceInfoService() {
ingo@301: }
ingo@301:
ingo@301:
ingo@301: public Document process(
ingo@301: Document data,
ingo@301: Object globalContext,
ingo@301: CallMeta callMeta)
ingo@301: {
ingo@301: logger.debug("DistanceInfoService.process");
ingo@301:
ingo@301: String river = XMLUtils.xpathString(
sascha@644: data, RIVER_XPATH, ArtifactNamespaceContext.INSTANCE);
ingo@301:
sascha@644: if (river == null || (river = river.trim()).length() == 0) {
ingo@301: logger.warn("No river specified. Cannot return distance info!");
sascha@644: return XMLUtils.newDocument();
ingo@301: }
ingo@301:
ingo@301: logger.debug("Search distances for river: " + river);
ingo@301:
sascha@644: Cache cache = CacheFactory.getCache(CACHE_NAME);
sascha@644:
sascha@644: if (cache == null) {
sascha@644: logger.debug("no cache configured for distance info");
sascha@644: return getUncached(river);
sascha@644: }
sascha@644:
sascha@644: net.sf.ehcache.Element element = cache.get(river);
sascha@644:
sascha@644: if (element != null) {
sascha@644: logger.debug("distance info found in cache");
sascha@644: return (Document)element.getValue();
sascha@644: }
sascha@644:
sascha@644: Document result = getUncached(river);
sascha@644:
sascha@644: element = new net.sf.ehcache.Element(river, result);
sascha@644:
sascha@644: logger.debug("store distance info found into cache");
sascha@644:
sascha@644: cache.put(element);
sascha@644:
sascha@644: return result;
sascha@644: }
sascha@644:
sascha@644: protected Document getUncached(String river) {
sascha@644:
sascha@644: Document result = XMLUtils.newDocument();
sascha@644:
ingo@301: ElementCreator ec = new ElementCreator(
ingo@301: result,
ingo@301: ArtifactNamespaceContext.NAMESPACE_URI,
ingo@301: ArtifactNamespaceContext.NAMESPACE_PREFIX);
ingo@301:
sascha@314: Session session = SessionHolder.acquire();
ingo@301:
sascha@644: try {
sascha@644: Iterator iter =
sascha@644: AnnotationsFactory.getAnnotationsIterator(river);
ingo@301:
sascha@314: Element all = ec.create("distances");
sascha@314:
sascha@644: while (iter.hasNext()) {
sascha@644: Annotation a = iter.next();
sascha@314: Element distance = buildDistanceNode(ec, a);
sascha@644: all.appendChild(distance);
ingo@301: }
sascha@314:
sascha@314: result.appendChild(all);
ingo@301: }
sascha@314: finally {
sascha@314: session.close();
sascha@314: SessionHolder.release();
sascha@314: }
ingo@301:
ingo@301: return result;
ingo@301: }
ingo@301:
ingo@301:
ingo@301: /**
ingo@301: * This method build an Element for a distance info.
ingo@301: *
ingo@301: * @param ec The ElementCreator.
ingo@301: * @param anno The Annotation that provides information about the distance.
ingo@301: *
ingo@301: * @return an Element that contains information about a distance.
ingo@301: */
sascha@644: protected static Element buildDistanceNode(ElementCreator ec, Annotation anno) {
ingo@301: Position pos = anno.getPosition();
ingo@301: Range range = anno.getRange();
ingo@301: Attribute attr = anno.getAttribute();
ingo@301:
ingo@301: BigDecimal a = range.getA();
ingo@301: BigDecimal b = range.getB();
ingo@301:
ingo@301: Element distance = ec.create("distance");
ingo@301: ec.addAttr(distance, "description", pos.getValue(), true);
ingo@301: ec.addAttr(distance, "from", a != null ? a.toString() : "", true);
ingo@301: ec.addAttr(distance, "to", b != null ? b.toString() : "", true);
ingo@301: ec.addAttr(distance, "riverside", attr.getValue(), true);
ingo@301:
ingo@301: return distance;
ingo@301: }
ingo@301: }
ingo@301: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :