package org.osm2world.core.osm.creation; import static org.openstreetmap.josm.plugins.graphview.core.data.EmptyTagGroup.EMPTY_TAG_GROUP; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.openstreetmap.josm.plugins.graphview.core.data.MapBasedTagGroup; import org.openstreetmap.josm.plugins.graphview.core.data.TagGroup; import org.openstreetmap.osmosis.core.container.v0_6.EntityContainer; import org.openstreetmap.osmosis.core.domain.v0_6.Bound; import org.openstreetmap.osmosis.core.domain.v0_6.Entity; import org.openstreetmap.osmosis.core.domain.v0_6.EntityType; import org.openstreetmap.osmosis.core.domain.v0_6.Node; import org.openstreetmap.osmosis.core.domain.v0_6.Relation; import org.openstreetmap.osmosis.core.domain.v0_6.Tag; import org.openstreetmap.osmosis.core.domain.v0_6.Way; import org.openstreetmap.osmosis.core.domain.v0_6.WayNode; import org.openstreetmap.osmosis.core.task.v0_6.RunnableSource; import org.openstreetmap.osmosis.core.task.v0_6.Sink; import org.osm2world.core.osm.data.OSMData; import org.osm2world.core.osm.data.OSMElement; import org.osm2world.core.osm.data.OSMMember; import org.osm2world.core.osm.data.OSMNode; import org.osm2world.core.osm.data.OSMRelation; import org.osm2world.core.osm.data.OSMWay; /** * reads OSM data from an osmosis {@link RunnableSource}. * Can also be used as a base class for other {@link OSMDataReader} implementations. */ public class OsmosisReader implements OSMDataReader { private final RunnableSource source; private boolean complete = false; private synchronized boolean isComplete() { return complete; } private synchronized void setCompleteTrue() { this.complete = true; } private List<Bound> bounds = new ArrayList<Bound>(); private Map<Long, Node> nodesById = new HashMap<Long, Node>(); private Map<Long, Way> waysById = new HashMap<Long, Way>(); private Map<Long, Relation> relationsById = new HashMap<Long, Relation>(); private Collection<OSMNode> ownNodes; private Collection<OSMWay> ownWays; private Collection<OSMRelation> ownRelations; private final Sink sinkImplementation = new Sink() { public void initialize(Map<String, Object> arg0) { /* do nothing */ } public void release() { /* do nothing */ } public void complete() { setCompleteTrue(); } public void process(EntityContainer entityContainer) { Entity entity = entityContainer.getEntity(); if (entity instanceof Node) { nodesById.put(entity.getId(), ((Node) entity)); } else if (entity instanceof Way) { waysById.put(entity.getId(), ((Way) entity)); } else if (entity instanceof Relation) { relationsById.put(entity.getId(), ((Relation) entity)); } else if (entity instanceof Bound) { bounds.add((Bound) entity); } } }; /* * @param source * a source providing the input data for the conversion */ protected OsmosisReader(RunnableSource source) { this.source = source; } private void convertToOwnRepresentation() { ownNodes = new ArrayList<OSMNode>(nodesById.size()); ownWays = new ArrayList<OSMWay>(waysById.size()); ownRelations = new ArrayList<OSMRelation>(relationsById.size()); Map<Node, OSMNode> nodeMap = new HashMap<Node, OSMNode>(); Map<Way, OSMWay> wayMap = new HashMap<Way, OSMWay>(); Map<Relation, OSMRelation> relationMap = new HashMap<Relation, OSMRelation>(); for (Node node : nodesById.values()) { OSMNode ownNode = new OSMNode(node.getLatitude(), node .getLongitude(), tagGroupForEntity(node), node.getId()); ownNodes.add(ownNode); nodeMap.put(node, ownNode); } for (Way way : waysById.values()) { List<WayNode> origWayNodes = way.getWayNodes(); List<OSMNode> wayNodes = new ArrayList<OSMNode>(origWayNodes.size()); for (WayNode origWayNode : origWayNodes) { Node origNode = nodesById.get(origWayNode.getNodeId()); if (origNode != null) { wayNodes.add(nodeMap.get(origNode)); } } OSMWay ownWay = new OSMWay(tagGroupForEntity(way), way.getId(), wayNodes); ownWays.add(ownWay); wayMap.put(way, ownWay); } for (Relation relation : relationsById.values()) { OSMRelation ownRelation = new OSMRelation( tagGroupForEntity(relation), relation.getId(), relation.getMembers().size()); ownRelations.add(ownRelation); relationMap.put(relation, ownRelation); } // add relation members // (needs to be done *after* creation because relations can be members // of other relations) for (Relation relation : relationMap.keySet()) { OSMRelation ownRelation = relationMap.get(relation); for (org.openstreetmap.osmosis.core.domain.v0_6.RelationMember member : relation .getMembers()) { OSMElement memberObject = null; if (member.getMemberType() == EntityType.Node) { memberObject = nodeMap.get(nodesById.get(member .getMemberId())); } else if (member.getMemberType() == EntityType.Way) { memberObject = wayMap.get(waysById .get(member.getMemberId())); } else if (member.getMemberType() == EntityType.Relation) { memberObject = relationMap.get(relationsById.get(member .getMemberId())); } else { continue; } if (memberObject != null) { OSMMember ownMember = new OSMMember(member .getMemberRole(), memberObject); ownRelation.relationMembers.add(ownMember); } } } // give up references to original collections nodesById = null; waysById = null; relationsById = null; } private TagGroup tagGroupForEntity(Entity entity) { if (entity.getTags().isEmpty()) { return EMPTY_TAG_GROUP; } else { Map<String, String> tagMap = new HashMap<String, String>(entity.getTags().size()); for (Tag tag : entity.getTags()) { tagMap.put(tag.getKey(), tag.getValue()); } return new MapBasedTagGroup(tagMap); } } @Override public OSMData getData() throws IOException { source.setSink(sinkImplementation); Thread readerThread = new Thread(source); readerThread.start(); while (readerThread.isAlive()) { try { readerThread.join(); } catch (InterruptedException e) { /* do nothing */ } } if (!isComplete()) { throw new IOException("couldn't read from data source"); } convertToOwnRepresentation(); return new OSMData(bounds, ownNodes, ownWays, ownRelations); } }