Mercurial > dive4elements > river
changeset 1749:f7d890f4855f
Added Service Service to lookup the Nth nearest neighbors for a set of given cross section ids and kms.
flys-artifacts/trunk@3049 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Thu, 20 Oct 2011 17:14:24 +0000 |
parents | d56b94325bec |
children | 415ec0223dff |
files | flys-artifacts/ChangeLog flys-artifacts/doc/conf/cache.xml flys-artifacts/doc/conf/conf.xml flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/CrossSectionKMService.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelPairSelectState.java |
diffstat | 6 files changed, 223 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog Thu Oct 20 14:26:22 2011 +0000 +++ b/flys-artifacts/ChangeLog Thu Oct 20 17:14:24 2011 +0000 @@ -1,3 +1,17 @@ +2011-10-20 Sascha L. Teichmann <sascha.teichmann@intevation.de> + + * src/main/java/de/intevation/flys/artifacts/services/CrossSectionKMService.java: + Service to lookup the Nth nearest neighbors for a set of given + cross section ids and kms. + + * doc/conf/conf.xml: Registered service. + + * doc/conf/cache.xml: Cache config. + + * src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java, + src/main/java/de/intevation/flys/artifacts/states/WaterlevelPairSelectState.java: + Removed superfluous imports. + 2011-10-20 Raimund Renkert <raimund.renkert@intevation.de> * src/main/java/de/intevation/flys/utils/ThemeUtil.java: @@ -61,7 +75,7 @@ requires a FLYSArtifact. * src/main/java/de/intevation/flys/artifacts/states/WQSelect.java: - Override createStaticData() to create titles for Qs manually - we want + Override createStaticData() to create titles for Qs manually - we want to display the named main values if existing for the selected Qs. 2011-10-19 Raimund Renkert <raimund.renkert@intevation.de>
--- a/flys-artifacts/doc/conf/cache.xml Thu Oct 20 14:26:22 2011 +0000 +++ b/flys-artifacts/doc/conf/cache.xml Thu Oct 20 17:14:24 2011 +0000 @@ -73,4 +73,12 @@ timeToLiveSeconds="7200" memoryStoreEvictionPolicy="LFU" /> + + <!-- This one is used for the cross section next neighbor lookup --> + <cache name="cross-section-kms" + maxElementsInMemory="50" + eternal="false" + timeToLiveSeconds="7200" + memoryStoreEvictionPolicy="LRU" + /> </ehcache>
--- a/flys-artifacts/doc/conf/conf.xml Thu Oct 20 14:26:22 2011 +0000 +++ b/flys-artifacts/doc/conf/conf.xml Thu Oct 20 17:14:24 2011 +0000 @@ -57,6 +57,10 @@ name="mapinfo" service="de.intevation.flys.artifacts.services.MapInfoService" description="The service provides some basic information to create a WMS for a specific river.">de.intevation.artifactdatabase.DefaultServiceFactory</service-factory> + <service-factory + name="cross-section-km" + service="de.intevation.flys.artifacts.services.CrossSectionKMService" + description="The service provides the N next neighbored kms and ids of cross section lines for given cross section id, km and N.">de.intevation.artifactdatabase.DefaultServiceFactory</service-factory> </service-factories> </factories>
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java Thu Oct 20 14:26:22 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java Thu Oct 20 17:14:24 2011 +0000 @@ -7,8 +7,6 @@ import org.w3c.dom.Document; -import de.intevation.artifactdatabase.data.DefaultStateData; - import de.intevation.artifactdatabase.state.Facet; import de.intevation.artifactdatabase.state.DefaultOutput; import de.intevation.artifactdatabase.state.State; @@ -20,17 +18,13 @@ import de.intevation.flys.artifacts.model.WKms; import de.intevation.flys.artifacts.model.WKmsFacet; -import de.intevation.flys.artifacts.model.WstValueTable; -import de.intevation.flys.artifacts.model.WstValueTableFactory; import de.intevation.flys.artifacts.model.WKmsFactory; import de.intevation.flys.artifacts.states.StaticState; import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.utils.FLYSUtils; import de.intevation.artifacts.common.utils.XMLUtils; - /** * Artifact to access additional "waterlevel"-type of data, like the height * of protective measures (dikes).
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/CrossSectionKMService.java Thu Oct 20 17:14:24 2011 +0000 @@ -0,0 +1,196 @@ +package de.intevation.flys.artifacts.services; + +import de.intevation.artifacts.CallMeta; +import de.intevation.artifacts.GlobalContext; + +import de.intevation.artifacts.common.utils.XMLUtils; + +import de.intevation.flys.artifacts.cache.CacheFactory; + +import de.intevation.flys.backend.SessionHolder; + +import de.intevation.flys.model.CrossSection; +import de.intevation.flys.model.CrossSectionLine; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.List; +import java.util.Map; +import java.util.NavigableMap; + +import java.util.concurrent.ConcurrentSkipListMap; + +import net.sf.ehcache.Cache; + +import org.apache.log4j.Logger; + +import org.hibernate.Query; +import org.hibernate.Session; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +public class CrossSectionKMService +extends FLYSService +{ + private static Logger logger = + Logger.getLogger(CrossSectionKMService.class); + + public static final String CACHE_NAME = "cross-section-kms"; + + public CrossSectionKMService() { + } + + @Override + public Document doProcess( + Document data, + GlobalContext globalContext, + CallMeta callMeta + ) { + logger.debug("CrossSectionKMService.doProcess"); + + NodeList crossSectionNodes = + data.getElementsByTagName("cross-section"); + + Cache cache = CacheFactory.getCache(CACHE_NAME); + + Document document = XMLUtils.newDocument(); + + Element all = document.createElement("cross-sections"); + + for (int i = 0, CS = crossSectionNodes.getLength(); i < CS; ++i) { + Element crossSectionElement = (Element)crossSectionNodes.item(i); + + String idString = crossSectionElement.getAttribute("id"); + String kmString = crossSectionElement.getAttribute("km"); + String neighborsString = crossSectionElement.getAttribute("n"); + + if (idString.length() == 0 || kmString.length() == 0) { + logger.debug("missing attributes in cross-section element"); + continue; + } + + double km; + Integer crossSectionId; + int N = 2; + + try { + km = Double.parseDouble(kmString); + crossSectionId = Integer.valueOf(idString); + + if (neighborsString.length() > 0) { + N = Integer.parseInt(neighborsString); + } + } + catch (NumberFormatException nfe) { + logger.debug("converting number failed", nfe); + continue; + } + + NavigableMap<Double, Integer> map; + + if (cache == null) { + map = getUncached(crossSectionId); + } + else { + net.sf.ehcache.Element element = cache.get(crossSectionId); + if (element == null) { + map = getUncached(crossSectionId); + if (map != null) { + element = new net.sf.ehcache.Element( + crossSectionId, map); + cache.put(element); + } + } + else { + map = (NavigableMap<Double, Integer>)element.getValue(); + } + } + + if (map == null) { + logger.debug("cannot find cross section " + crossSectionId); + continue; + } + + Deque<Map.Entry<Double, Integer>> result = + nearestNeighbors(map, km, N); + + if (!result.isEmpty()) { + Element csE = document.createElement("cross-section"); + csE.setAttribute("id", idString); + for (Map.Entry<Double, Integer> entry: result) { + Element lineE = document.createElement("line"); + lineE.setAttribute( + "line-id", String.valueOf(entry.getValue())); + lineE.setAttribute( + "km", String.valueOf(entry.getKey())); + csE.appendChild(lineE); + } + all.appendChild(csE); + } + } + + document.appendChild(all); + + return document; + } + + public static Deque<Map.Entry<Double, Integer>> nearestNeighbors( + NavigableMap<Double, Integer> map, + double km, + int N + ) { + Deque<Map.Entry<Double, Integer>> result = + new ArrayDeque<Map.Entry<Double, Integer>>(2*N); + + int i = 0; + for (Map.Entry<Double, Integer> entry: + map.headMap(km, false).descendingMap().entrySet()) { + if (i++ >= N) { + break; + } + result.addFirst(entry); + } + + i = 0; + for (Map.Entry<Double, Integer> entry: + map.tailMap(km, false).entrySet()) { + if (i++ >= N) { + break; + } + result.addLast(entry); + } + + return result; + } + + public static NavigableMap<Double, Integer> getUncached( + Integer crossSectionId + ) { + NavigableMap<Double, Integer> result = + new ConcurrentSkipListMap<Double, Integer>(); + + Session session = SessionHolder.HOLDER.get(); + Query query = session.createQuery( + "from CrossSection where id=:id"); + query.setParameter("id", crossSectionId); + + List<CrossSection> crossSections = query.list(); + if (crossSections.isEmpty()) { + return null; + } + + CrossSection crossSection = crossSections.get(0); + List<CrossSectionLine> lines = crossSection.getLines(); + + for (CrossSectionLine line: lines) { + Double km = line.getKm().doubleValue(); + Integer id = line.getId(); + result.put(km, id); + } + + return result; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelPairSelectState.java Thu Oct 20 14:26:22 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelPairSelectState.java Thu Oct 20 17:14:24 2011 +0000 @@ -15,12 +15,9 @@ import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator; import de.intevation.flys.artifacts.FLYSArtifact; -import de.intevation.flys.artifacts.model.CalculationResult; import de.intevation.flys.artifacts.model.FacetTypes; -import de.intevation.flys.artifacts.model.WQKms; import de.intevation.flys.artifacts.resources.Resources; -import de.intevation.flys.utils.FLYSUtils; import de.intevation.flys.utils.StringUtil; /**