# HG changeset patch # User Sascha L. Teichmann # Date 1319130864 0 # Node ID f7d890f4855f2c3b68eeba1c399b5bdb5a583a74 # Parent d56b94325becdba37478327f7b5ebe0e26857582 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 diff -r d56b94325bec -r f7d890f4855f flys-artifacts/ChangeLog --- 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 + + * 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 * 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 diff -r d56b94325bec -r f7d890f4855f flys-artifacts/doc/conf/cache.xml --- 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" /> + + + diff -r d56b94325bec -r f7d890f4855f flys-artifacts/doc/conf/conf.xml --- 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 + de.intevation.artifactdatabase.DefaultServiceFactory diff -r d56b94325bec -r f7d890f4855f flys-artifacts/src/main/java/de/intevation/flys/artifacts/StaticWKmsArtifact.java --- 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). diff -r d56b94325bec -r f7d890f4855f flys-artifacts/src/main/java/de/intevation/flys/artifacts/services/CrossSectionKMService.java --- /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 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)element.getValue(); + } + } + + if (map == null) { + logger.debug("cannot find cross section " + crossSectionId); + continue; + } + + Deque> result = + nearestNeighbors(map, km, N); + + if (!result.isEmpty()) { + Element csE = document.createElement("cross-section"); + csE.setAttribute("id", idString); + for (Map.Entry 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> nearestNeighbors( + NavigableMap map, + double km, + int N + ) { + Deque> result = + new ArrayDeque>(2*N); + + int i = 0; + for (Map.Entry entry: + map.headMap(km, false).descendingMap().entrySet()) { + if (i++ >= N) { + break; + } + result.addFirst(entry); + } + + i = 0; + for (Map.Entry entry: + map.tailMap(km, false).entrySet()) { + if (i++ >= N) { + break; + } + result.addLast(entry); + } + + return result; + } + + public static NavigableMap getUncached( + Integer crossSectionId + ) { + NavigableMap result = + new ConcurrentSkipListMap(); + + Session session = SessionHolder.HOLDER.get(); + Query query = session.createQuery( + "from CrossSection where id=:id"); + query.setParameter("id", crossSectionId); + + List crossSections = query.list(); + if (crossSections.isEmpty()) { + return null; + } + + CrossSection crossSection = crossSections.get(0); + List 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 : diff -r d56b94325bec -r f7d890f4855f flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/WaterlevelPairSelectState.java --- 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; /**