package com.revolsys.record.io.format.openstreetmap.model; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.xml.namespace.QName; import com.revolsys.collection.map.LongHashMap; import com.revolsys.geometry.model.BoundingBox; import com.revolsys.geometry.model.Point; import com.revolsys.identifier.Identifier; import com.revolsys.record.io.format.xml.StaxReader; import com.revolsys.spring.resource.Resource; import com.revolsys.spring.resource.UrlResource; import com.revolsys.util.Property; public class OsmDocument implements OsmConstants { public static OsmDocument newDocument(final String serverUrl, BoundingBox boundingBox) { if (boundingBox != null) { boundingBox = boundingBox.convert(OsmConstants.WGS84_2D); if (!boundingBox.isEmpty()) { final StringBuilder url = new StringBuilder(serverUrl); url.append("map?bbox="); url.append(boundingBox.getMinX()); url.append(","); url.append(boundingBox.getMinY()); url.append(","); url.append(boundingBox.getMaxX()); url.append(","); url.append(boundingBox.getMaxY()); final Resource resource = new UrlResource(url.toString()); return new OsmDocument(resource); } } return new OsmDocument(); } private OsmApi api; private String attribution; private BoundingBox bounds; private OsmChangeset changeset; private String copyright; private String generator; private OsmGpxFile gpxFile; private String license; private final LongHashMap<OsmNode> nodeMap = new LongHashMap<>(); private final LongHashMap<Point> nodePointMap = new LongHashMap<>(); private final List<OsmNode> nodes = new ArrayList<>(); private OsmPreferences preferences; private final List<OsmElement> records = new ArrayList<>(); private final LongHashMap<OsmRelation> relationMap = new LongHashMap<>(); private final List<OsmRelation> relations = new ArrayList<>(); private OsmUser user; private String version; private final LongHashMap<OsmWay> wayMap = new LongHashMap<>(); private final List<OsmWay> ways = new ArrayList<>(); public OsmDocument() { } public OsmDocument(final Resource resource) { System.out.println(resource); final StaxReader xmlReader = StaxReader.newXmlReader(resource); parseDocument(xmlReader); } public void addNode(final OsmNode node) { if (node != null) { final long id = node.getId(); final Point point = node.getGeometry(); this.nodePointMap.put(id, point); if (node.isTagged()) { this.nodeMap.put(id, node); this.nodes.add(node); this.records.add(node); } } } public void addRelation(final OsmRelation relation) { if (relation != null) { final long id = relation.getId(); this.relationMap.put(id, relation); if (relation.isTagged()) { this.relations.add(relation); this.records.add(relation); } } } public void addRelations(final List<OsmRelation> relations) { for (final OsmRelation relation : relations) { addRelation(relation); } } public void addWay(final OsmWay way) { final long id = way.getId(); this.wayMap.put(id, way); if (way.isTagged()) { this.ways.add(way); this.records.add(way); } } public void addWays(final List<OsmWay> ways) { for (final OsmWay way : ways) { addWay(way); } } public OsmApi getApi() { return this.api; } public String getAttribution() { return this.attribution; } public BoundingBox getBounds() { return this.bounds; } public OsmChangeset getChangeset() { return this.changeset; } public String getCopyright() { return this.copyright; } public String getGenerator() { return this.generator; } public OsmGpxFile getGpxFile() { return this.gpxFile; } public String getLicense() { return this.license; } public OsmNode getNode(final long id) { return this.nodeMap.get(id); } public Point getNodePoint(final long id) { return this.nodePointMap.get(id); } public List<OsmNode> getNodes() { return this.nodes; } public OsmPreferences getPreferences() { return this.preferences; } public OsmElement getRecord(final Identifier identifier) { if (identifier instanceof OsmNodeIdentifier) { final Long id = identifier.getLong(0); return getNode(id); } else if (identifier instanceof OsmWayIdentifier) { final Long id = identifier.getLong(0); return getWay(id); } else if (identifier instanceof OsmRelationIdentifier) { final Long id = identifier.getLong(0); return getRelation(id); } else { return null; } } public List<OsmElement> getRecords() { return this.records; } public OsmRelation getRelation(final long id) { return this.relationMap.get(id); } public List<OsmRelation> getRelations() { return this.relations; } public OsmUser getUser() { return this.user; } public String getVersion() { return this.version; } public OsmWay getWay(final long id) { return this.wayMap.get(id); } public List<OsmWay> getWays() { return this.ways; } private void parseBounds(final StaxReader in) { final double minX = in.getDoubleAttribute(null, "minlon"); final double minY = in.getDoubleAttribute(null, "minlat"); final double maxX = in.getDoubleAttribute(null, "maxlon"); final double maxY = in.getDoubleAttribute(null, "maxlat"); final BoundingBox boundingBox = WGS84_2D.newBoundingBox(minX, minY, maxX, maxY); setBounds(boundingBox); in.skipSubTree(); } private void parseDocument(final StaxReader in) { final int depth = in.getDepth(); if (in.skipToStartElement(depth, OsmConstants.OSM)) { for (final String fieldName : Arrays.asList("version", "generator", "copyright", "attribution", "license")) { final String value = in.getAttributeValue(null, fieldName); Property.setSimple(this, fieldName, value); } while (in.skipToChildStartElements(OSM_XML_ELEMENTS)) { final QName name = in.getName(); if (name.equals(BOUNDS)) { parseBounds(in); } else if (name.equals(NODE)) { parseNode(in); } else if (name.equals(WAY)) { parseWay(in); } else if (name.equals(RELATION)) { parseRelation(in); } else { in.skipSubTree(); } } } else { throw new RuntimeException("Document does not contain an <osm> element"); } } private void parseNode(final StaxReader in) { final OsmNode node = new OsmNode(in); addNode(node); } private void parseRelation(final StaxReader in) { final OsmRelation relation = new OsmRelation(in); addRelation(relation); } private void parseWay(final StaxReader in) { final OsmWay way = new OsmWay(this, in); addWay(way); } public void setApi(final OsmApi api) { this.api = api; } public void setAttribution(final String attribution) { this.attribution = attribution; } public void setBounds(final BoundingBox bounds) { this.bounds = bounds; } public void setChangeset(final OsmChangeset changeset) { this.changeset = changeset; } public void setCopyright(final String copyright) { this.copyright = copyright; } public void setGenerator(final String generator) { this.generator = generator; } public void setGpxFile(final OsmGpxFile gpxFile) { this.gpxFile = gpxFile; } public void setLicense(final String license) { this.license = license; } public void setNodes(final List<OsmNode> nodes) { this.nodes.clear(); for (final OsmNode node : nodes) { addNode(node); } } public void setPreferences(final OsmPreferences preferences) { this.preferences = preferences; } public void setRelations(final List<OsmRelation> relations) { this.relations.clear(); addRelations(relations); } public void setUser(final OsmUser user) { this.user = user; } public void setVersion(final String version) { this.version = version; } public void setWays(final List<OsmWay> ways) { this.ways.clear(); addWays(ways); } }