package aimax.osm.data.impl; import java.util.List; import java.util.StringTokenizer; import aimax.osm.data.BoundingBox; import aimax.osm.data.OsmMap; import aimax.osm.data.Position; import aimax.osm.data.entities.EntityAttribute; import aimax.osm.data.entities.MapEntity; import aimax.osm.data.entities.MapNode; import aimax.osm.data.entities.MapWay; public class DefaultEntityFinder extends AbstractEntityFinder { public DefaultEntityFinder(OsmMap storage) { super(storage); } /** * Searches for entities which comply to the current search specification * and stores them as results. */ @Override protected void find(boolean findMore) { BestMatchFinder bmf = new BestMatchFinder(pattern); List<MapEntity> results = getResults(); BoundingBox bb = new BoundingBox(position, nextRadius); if (!results.isEmpty()) bmf.checkMatchQuality(results.get(0)); if (mode.equals(Mode.ENTITY) || mode.equals(Mode.NODE)) { for (MapNode node : getStorage().getPois(bb)) { int match = bmf.checkMatchQuality(node); if (match >= 0) { if (match > 0) { results.clear(); bmf.useAsReference(node); } if (position.insertInAscendingDistanceOrder(results, node)) if (results.size() > 100) results.remove(99); } } } if (mode.equals(Mode.ENTITY) || mode.equals(Mode.WAY)) { for (MapWay way : getStorage().getWays(bb)) { int match = bmf.checkMatchQuality(way); if (match >= 0) { if (match > 0) { results.clear(); bmf.useAsReference(way); } if (position.insertInAscendingDistanceOrder(results, way)) if (results.size() > 100) results.remove(99); } } } if (mode.equals(Mode.ADDRESS)) { List<MapEntity> iResults = getIntermediateResults(); StringTokenizer tokenizer = new StringTokenizer(pattern, ","); String placeName = null; String wayName = null; if (tokenizer.hasMoreElements()) placeName = tokenizer.nextToken(); if (tokenizer.hasMoreElements()) wayName = tokenizer.nextToken().trim(); if (placeName != null && !findMore) { for (MapNode place : getStorage().getPlaces(placeName)) { position.insertInAscendingDistanceOrder( iResults, place); if (iResults.size() > 100) iResults.remove(99); } nextRadius = -1; } if (iResults.size() == 1 && wayName != null) { MapNode place = (MapNode) iResults.get(0); findWay(wayName, new Position(place.getLat(), place.getLon()), null); } } else { nextRadius *= 2; if (results.isEmpty() && getIntermediateResults().isEmpty() && nextRadius <= getMaxRadius()) find(true); } } /** * Helper class which is used to find the best match when searching for * special entities. * * @author Ruediger Lunde */ private static class BestMatchFinder { /** String, specifying the entity to be searched for. */ String searchPattern; /** * Value between 1 and 5 which classifies the reference match level. 1: * reference entity name equal to pattern; 2: reference entity has * attribute value which is identical with the pattern; 3: reference * entity has attribute name equal to pattern; 4: reference entity name * contains pattern; 5: no match found. */ int currMatchLevel = 5; /** Creates a match finder for a given search pattern. */ protected BestMatchFinder(String pattern) { searchPattern = pattern.toLowerCase(); } /** * Compares whether a given entity matches the search pattern better or * worse than the previously defined reference entity. * * @return Match level (-1: forget new entity, 0: new entity match * quality equal to reference entity, 1: new entity matches * better then reference entity) */ protected int checkMatchQuality(MapEntity entity) { int matchLevel = getMatchLevel(entity); int result = -1; if (matchLevel < 5) { if (matchLevel < currMatchLevel) result = 1; else if (matchLevel == currMatchLevel) { result = 0; } } return result; } /** Defines a new reference entity for search pattern match checks. */ protected void useAsReference(MapEntity entity) { currMatchLevel = getMatchLevel(entity); } private int getMatchLevel(MapEntity entity) { String name = entity.getName(); if (name != null) name = name.toLowerCase(); if (name != null && name.equals(searchPattern)) return 1; if (currMatchLevel >= 2) { for (EntityAttribute att : entity.getAttributes()) if (att.getValue().toLowerCase().equals(searchPattern)) return 2; } if (currMatchLevel >= 3) { for (EntityAttribute att : entity.getAttributes()) if (att.getKey().toLowerCase().equals(searchPattern)) return 3; } if (name != null && currMatchLevel >= 4 && name.contains(searchPattern)) return 4; return 5; } } }