package aimax.osm.reader; import java.io.File; import java.io.FileNotFoundException; import java.util.List; import aimax.osm.data.BoundingBox; import aimax.osm.data.EntityClassifier; import aimax.osm.data.MapBuilder; import aimax.osm.data.MapBuilderProxy; import aimax.osm.data.entities.EntityAttribute; import aimax.osm.data.impl.DefaultMapNode; import aimax.osm.data.impl.DefaultMapWay; public class FilteringOsmReader extends OsmReader { BoundingBox boundingBox; EntityClassifier<Boolean> attFilter; /** * Sets a bounding box for the next read action from file. Map nodes which * are not inside will be ignored. */ public void setFilter(BoundingBox bb) { boundingBox = bb; attFilter = null; } /** * Sets an attribute filter for the next read action from file. Map entities * for which the classifier returns null will be ignored. */ public void setFilter(EntityClassifier<Boolean> attFilter) { this.attFilter = attFilter; boundingBox = null; } /** * Reads all data from the file and send it to the sink. */ public void readMap(File file, MapBuilder builder) { try { MapBuilderProxy proxy; if (boundingBox != null) proxy = new BBBuilderProxy(builder, boundingBox); else if (attFilter != null) proxy = new FilteringBuilderProxy(builder, attFilter); else proxy = new MapBuilderProxy(builder); parseMap(createFileStream(file), proxy); if (proxy.nodeRefsWithoutDefsAdded()) { if (boundingBox != null || attFilter != null) { LOG.info("Starting to parse the map file a second time."); proxy.incrementCounter(); parseMap(createFileStream(file), proxy); } else { LOG .warning("Nodes were referenced in ways but not defined before."); } } } catch (FileNotFoundException e) { LOG.warning("File does not exist " + file); } catch (Exception e) { LOG.warning("The map could not be read. " + e); e.printStackTrace(); } finally { boundingBox = null; attFilter = null; } } // //////////////////////////////////////////////////////////////////// // inner classes /** Builder proxy used for bounding box filtering. */ private static class BBBuilderProxy extends MapBuilderProxy { BoundingBox bb; protected BBBuilderProxy(MapBuilder builder, BoundingBox bb) { super(builder); this.bb = bb; builder.setBoundingBox(bb); } /** Does nothing. */ @Override public void setBoundingBox(BoundingBox bb) { } @Override public void addNode(long id, String name, List<EntityAttribute> atts, float lat, float lon) { if (counter == 0 && lat >= bb.getLatMin() && lat <= bb.getLatMax() && lon >= bb.getLonMin() && lon <= bb.getLonMax()) super.addNode(id, name, atts, lat, lon); else if (counter == 1 && super.isNodeReferenced(id)) super.addNode(id, name, atts, lat, lon); } @Override public void addWay(long id, String name, List<EntityAttribute> atts, List<Long> wayNodeIds) { if (counter == 0) { for (long nodeId : wayNodeIds) if (builder.isNodeDefined(nodeId, bb)) { super.addWay(id, name, atts, wayNodeIds); break; } } } } /** Builder proxy used for attribute filtering. */ private static class FilteringBuilderProxy extends aimax.osm.data.MapBuilderProxy { EntityClassifier<Boolean> attFilter; protected FilteringBuilderProxy(MapBuilder builder, EntityClassifier<Boolean> attFilter) { super(builder); this.attFilter = attFilter; } @Override public void addNode(long id, String name, List<EntityAttribute> atts, float lat, float lon) { if (counter == 0) { DefaultMapNode node = new DefaultMapNode(id); node.setAttributes(atts); if (attFilter.classify(node) != null) super.addNode(id, name, atts, lat, lon); } else if (counter == 1 && super.isNodeReferenced(id)) super.addNode(id, name, atts, lat, lon); } @Override public void addWay(long id, String name, List<EntityAttribute> atts, List<Long> wayNodeIds) { if (counter == 0) { DefaultMapWay way = new DefaultMapWay(id); way.setAttributes(atts); if (attFilter.classify(way) != null) { super.addWay(id, name, atts, wayNodeIds); } } } } }