// This software is released into the Public Domain. See copying.txt for details. package org.openstreetmap.osmosis.tagfilter.v0_6; import java.util.Map; import org.openstreetmap.osmosis.core.container.v0_6.BoundContainer; import org.openstreetmap.osmosis.core.container.v0_6.EntityContainer; import org.openstreetmap.osmosis.core.container.v0_6.EntityProcessor; import org.openstreetmap.osmosis.core.container.v0_6.NodeContainer; import org.openstreetmap.osmosis.core.container.v0_6.RelationContainer; import org.openstreetmap.osmosis.core.container.v0_6.WayContainer; import org.openstreetmap.osmosis.core.domain.v0_6.EntityType; import org.openstreetmap.osmosis.core.domain.v0_6.Relation; import org.openstreetmap.osmosis.core.domain.v0_6.RelationMember; import org.openstreetmap.osmosis.core.domain.v0_6.Way; import org.openstreetmap.osmosis.core.domain.v0_6.WayNode; import org.openstreetmap.osmosis.core.filter.common.IdTracker; import org.openstreetmap.osmosis.core.filter.common.IdTrackerFactory; import org.openstreetmap.osmosis.core.filter.common.IdTrackerType; import org.openstreetmap.osmosis.core.lifecycle.ReleasableIterator; import org.openstreetmap.osmosis.core.store.SimpleObjectStore; import org.openstreetmap.osmosis.core.store.SingleClassObjectSerializationFactory; import org.openstreetmap.osmosis.core.task.v0_6.Sink; import org.openstreetmap.osmosis.core.task.v0_6.SinkSource; /** * Restricts output of nodes to those that are used in ways and relations. * * @author Brett Henderson * @author Karl Newman * @author Christoph Sommer * @author Bartosz Fabianowski */ public class UsedNodeFilter implements SinkSource, EntityProcessor { private Sink sink; private SimpleObjectStore<NodeContainer> allNodes; private SimpleObjectStore<WayContainer> allWays; private SimpleObjectStore<RelationContainer> allRelations; private IdTracker requiredNodes; /** * Creates a new instance. * * @param idTrackerType * Defines the id tracker implementation to use. */ public UsedNodeFilter(IdTrackerType idTrackerType) { allNodes = new SimpleObjectStore<NodeContainer>( new SingleClassObjectSerializationFactory(NodeContainer.class), "afnd", true); allWays = new SimpleObjectStore<WayContainer>( new SingleClassObjectSerializationFactory(WayContainer.class), "afwy", true); allRelations = new SimpleObjectStore<RelationContainer>( new SingleClassObjectSerializationFactory(RelationContainer.class), "afrl", true); requiredNodes = IdTrackerFactory.createInstance(idTrackerType); } /** * {@inheritDoc} */ public void initialize(Map<String, Object> metaData) { sink.initialize(metaData); } /** * {@inheritDoc} */ public void process(EntityContainer entityContainer) { // Ask the entity container to invoke the appropriate processing method // for the entity type. entityContainer.process(this); } /** * {@inheritDoc} */ public void process(BoundContainer boundContainer) { // By default, pass it on unchanged sink.process(boundContainer); } /** * {@inheritDoc} */ public void process(NodeContainer container) { allNodes.add(container); } /** * {@inheritDoc} */ public void process(WayContainer container) { Way way; // mark all nodes as required way = container.getEntity(); for (WayNode nodeReference : way.getWayNodes()) { long nodeId = nodeReference.getNodeId(); requiredNodes.set(nodeId); } allWays.add(container); } /** * {@inheritDoc} */ public void process(RelationContainer container) { Relation relation; // mark all nodes as required relation = container.getEntity(); for (RelationMember memberReference : relation.getMembers()) { if (memberReference.getMemberType() == EntityType.Node) { long nodeId = memberReference.getMemberId(); requiredNodes.set(nodeId); } } allRelations.add(container); } /** * {@inheritDoc} */ public void complete() { // send on all required nodes ReleasableIterator<NodeContainer> nodeIterator = allNodes.iterate(); while (nodeIterator.hasNext()) { NodeContainer nodeContainer = nodeIterator.next(); long nodeId = nodeContainer.getEntity().getId(); if (!requiredNodes.get(nodeId)) { continue; } sink.process(nodeContainer); } nodeIterator.close(); nodeIterator = null; // send on all ways ReleasableIterator<WayContainer> wayIterator = allWays.iterate(); while (wayIterator.hasNext()) { sink.process(wayIterator.next()); } wayIterator.close(); wayIterator = null; // send on all relations ReleasableIterator<RelationContainer> relationIterator = allRelations.iterate(); while (relationIterator.hasNext()) { sink.process(relationIterator.next()); } relationIterator.close(); relationIterator = null; // done sink.complete(); } /** * {@inheritDoc} */ public void close() { if (allNodes != null) { allNodes.close(); } if (allWays != null) { allWays.close(); } if (allRelations != null) { allRelations.close(); } sink.close(); } /** * {@inheritDoc} */ public void setSink(Sink sink) { this.sink = sink; } }