content: package aimax.osm.data.impl;
  
  import java.util.ArrayList;
  import java.util.List;
  import java.util.logging.Logger;
  
  import aimax.osm.data.BoundingBox;
  import aimax.osm.data.EntityClassifier;
  import aimax.osm.data.MapBuilder;
  import aimax.osm.data.OsmMap;
  import aimax.osm.data.entities.EntityAttribute;
  import aimax.osm.data.entities.EntityViewInfo;
  import aimax.osm.data.entities.MapNode;
  
  public class DefaultMapBuilder implements MapBuilder {
  	private static Logger LOG = Logger.getLogger("aimax.osm");
  	private DefaultMap result;
  	private boolean nodeRefsWithoutDefsAdded;
  
  	public DefaultMapBuilder() {
  		result = new DefaultMap();
  	}
  
  	public DefaultMapBuilder(DefaultMap map) {
  		result = map;
  		result.clear();
  	}
  
  	/** {@inheritDoc} */
  	@Override
  	public void setEntityClassifier(EntityClassifier<EntityViewInfo> classifier) {
  		result.setEntityClassifier(classifier);
  	}
  
  	/** {@inheritDoc} */
  	@Override
  	public void setBoundingBox(BoundingBox bb) {
  		result.setBoundingBox(bb);
  	}
  
  	/** {@inheritDoc} */
  	@Override
  	public boolean isNodeDefined(long id, BoundingBox bb) {
  		MapNode node = result.getNode(id);
  		boolean result = (node != null && node.hasPosition());
  		if (result && bb != null)
  			result = bb.isInside(node.getLat(), node.getLon());
  		return result;
  	}
  	
  	/** {@inheritDoc} */
  	@Override
  	public boolean isNodeReferenced(long id) {
  		MapNode node = result.getNode(id);
  		return node != null && !node.getWayRefs().isEmpty();
  	}
  
  	/**
  	 * {@inheritDoc} If a node with the same ID but without position has already
  	 * been added, it is redefined with the new data.
  	 */
  	@Override
  	public void addNode(long id, String name, List<EntityAttribute> atts,
  			float lat, float lon) {
  		DefaultMapNode node = (DefaultMapNode) result.getNode(id);
  		if (node == null || !node.hasPosition()) {
  			if (node == null)
  				node = new DefaultMapNode(id);
  			node.setName(name);
  			node.setAttributes(atts);
  			node.setPosition(lat, lon);
  			result.addNode(node);
  			if (result.getNodeCount() % 500000 == 0)
  				LOG.fine("Nodes: " + result.getNodeCount());
  		}
  	}
  
  	/** {@inheritDoc} */
  	@Override
  	public boolean isWayDefined(long id) {
  		return result.getWay(id) != null;
  	}
  
  	/**
  	 * {@inheritDoc} Ways with less than two way nodes are ignored.
  	 */
  	@Override
  	public void addWay(long id, String name, List<EntityAttribute> atts,
  			List<Long> wayNodeIds) {
  		if (wayNodeIds.size() > 1) {
  			DefaultMapWay way = new DefaultMapWay(id);
  			way.setName(name);
  			way.setAttributes(atts);
  			List<MapNode> wayNodes = new ArrayList<>(wayNodeIds.size());
  			int i = 0;
  			for (long nodeId : wayNodeIds) {
  				DefaultMapNode node = (DefaultMapNode) result.getNode(nodeId);
  				if (node == null) {
  					node = new DefaultMapNode(nodeId);
  					result.addNode(node);
  					nodeRefsWithoutDefsAdded = true;
  				}
  				node.addWayRef(way, i++);
  				wayNodes.add(node);
  			}
  			way.setNodes(wayNodes);
  			result.addWay(way);
  			if (result.getWayCount() % 50000 == 0)
  				LOG.fine("Ways: " + result.getWayCount());
  		}
  	}
  
  	/** {@inheritDoc} */
  	@Override
  	public boolean nodeRefsWithoutDefsAdded() {
  		boolean result = nodeRefsWithoutDefsAdded;
  		nodeRefsWithoutDefsAdded = false;
  		return result;
  	}
  
  	/** {@inheritDoc} */
  	@Override
  	public OsmMap buildMap() {
  		result.compile();
  		if (!result.isEmpty())
  			LOG.fine("Loading completed. Ways: " + result.getWayCount()
  					+ ", Nodes: " + result.getNodeCount() + ", POIs: "
  					+ result.getPoiCount());
  		return result;
  	}
  }
  