/************************************************************************** OSMemory library for OSM data processing. Copyright (C) 2014 Aleś Bułojčyk <alex73mail@gmail.com> This is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. **************************************************************************/ package org.alex73.osmemory; import java.io.File; import java.nio.charset.Charset; import java.util.Arrays; import java.util.List; import java.util.Map; import osm.xmldatatypes.Member; import com.vividsolutions.jts.geom.Envelope; /** * This class reads XML file and stores all data into MemoryStorage. */ public class XMLReader extends BaseReader { public enum UPDATE_MODE { CREATE, MODIFY, DELETE }; public static void main(String[] aa) throws Exception { MemoryStorage st = new XMLReader().read(new File( "src-test/org/alex73/osmemory/geometry/multipolygon1.xml")); st.showStat(); } public XMLReader() { super(null); } public XMLReader(Envelope cropBox) { super(cropBox); } public XMLReader(MemoryStorage storage, double minLat, double maxLat, double minLon, double maxLon) { super(storage, new Envelope(minLon, maxLon, minLat, maxLat)); } public MemoryStorage read(File file) throws Exception { new XMLDriver(this).read(file); storage.finishLoading(); return storage; } void applyTags(XMLDriver driver, OsmBase obj) { for (int i = 0; i < driver.tags.size(); i++) { obj.tagKeys[i] = storage.getTagsPack().getTagCode(driver.tags.get(i).getK()); obj.tagValues[i] = bytes(driver.tags.get(i).getV()); } } void applyTags(Map<String, String> tags, OsmBase obj) { int i = 0; for (Map.Entry<String, String> en : tags.entrySet()) { obj.tagKeys[i] = storage.getTagsPack().getTagCode(en.getKey()); obj.tagValues[i] = bytes(en.getValue()); i++; } } /** * Add nodes inside specified crop box. */ void createNode(XMLDriver driver, long id, double dlat, double dlon, String user) { if (dlat > 90 || dlat < -90) { throw new RuntimeException("Wrong value for latitude: " + dlat); } if (dlon > 180 || dlon < -180) { throw new RuntimeException("Wrong value for longitude: " + dlon); } int lat = (int) Math.round(dlat / IOsmNode.DIVIDER); int lon = (int) Math.round(dlon / IOsmNode.DIVIDER); if (!isInsideCropBox(lat, lon)) { return; } if (driver.tags.size() > 0) { short userCode = storage.getUsersPack().getTagCode(user); OsmNode result = new OsmNode(id, driver.tags.size(), lat, lon, userCode); applyTags(driver, result); storage.nodes.add(result); } else { if (storage.simpleNodeCount >= storage.simpleNodeIds.length) { // extend storage.simpleNodeIds = Arrays.copyOf(storage.simpleNodeIds, storage.simpleNodeIds.length + 1024 * 1024); storage.simpleNodeLats = Arrays.copyOf(storage.simpleNodeLats, storage.simpleNodeLats.length + 1024 * 1024); storage.simpleNodeLons = Arrays.copyOf(storage.simpleNodeLons, storage.simpleNodeLons.length + 1024 * 1024); } int p = storage.simpleNodeCount++; storage.simpleNodeIds[p] = id; storage.simpleNodeLats[p] = lat; storage.simpleNodeLons[p] = lon; } } public void updateNode(UPDATE_MODE mode, long id, double dlat, double dlon, Map<String, String> tags, String user) { if (mode == UPDATE_MODE.DELETE) { storage.removeNode(id); } else { int lat = (int) Math.round(dlat / IOsmNode.DIVIDER); int lon = (int) Math.round(dlon / IOsmNode.DIVIDER); if (tags.isEmpty()) { storage.addSimpleNode(id, lat, lon); } else { short userCode = storage.getUsersPack().getTagCode(user); OsmNode n = new OsmNode(id, tags.size(), lat, lon, userCode); applyTags(tags, n); storage.addNode(n); } } } /** * Add ways that contains known nodes, i.e. inside specified crop box. */ void createWay(XMLDriver driver, long id, List<Long> nodes, String user) { short userCode = storage.getUsersPack().getTagCode(user); long[] ns = new long[nodes.size()]; for (int i = 0; i < ns.length; i++) { ns[i] = nodes.get(i); } OsmWay result = new OsmWay(id, driver.tags.size(), ns, userCode); boolean inside = false; for (int i = 0; i < ns.length; i++) { if (storage.getNodeById(ns[i]) != null) { inside = true; break; } } if (inside) { applyTags(driver, result); storage.ways.add(result); } } public void updateWay(UPDATE_MODE mode, long id, long[] nodes, Map<String, String> tags, String user) { if (mode == UPDATE_MODE.DELETE) { storage.removeWay(id); } else { short userCode = storage.getUsersPack().getTagCode(user); OsmWay w = new OsmWay(id, tags.size(), nodes, userCode); applyTags(tags, w); storage.addWay(w); } } /** * Add all relations. */ void createRelation(XMLDriver driver, long id, List<Member> members, String user) { short userCode = storage.getUsersPack().getTagCode(user); long[] memberIds = new long[members.size()]; byte[] memberTypes = new byte[members.size()]; for (int i = 0; i < members.size(); i++) { memberIds[i] = members.get(i).getRef(); switch (members.get(i).getType()) { case "node": memberTypes[i] = IOsmObject.TYPE_NODE; break; case "way": memberTypes[i] = IOsmObject.TYPE_WAY; break; case "relation": memberTypes[i] = IOsmObject.TYPE_RELATION; break; default: throw new RuntimeException(); } } OsmRelation result = new OsmRelation(id, driver.tags.size(), memberIds, memberTypes, userCode); for (int i = 0; i < result.memberRoles.length; i++) { result.memberRoles[i] = storage.getRelationRolesPack().getTagCode(members.get(i).getRole()); } applyTags(driver, result); storage.relations.add(result); } public void updateRelation(UPDATE_MODE mode, long id, long[] memberIDs, byte[] memberTypes, String[] memberRoles, Map<String, String> tags, String user) { if (mode == UPDATE_MODE.DELETE) { storage.removeRelation(id); } else { short userCode = storage.getUsersPack().getTagCode(user); OsmRelation r = new OsmRelation(id, tags.size(), memberIDs, memberTypes, userCode); for (int i = 0; i < r.memberRoles.length; i++) { r.memberRoles[i] = storage.getRelationRolesPack().getTagCode(memberRoles[i]); } applyTags(tags, r); storage.addRelation(r); } } static final Charset UTF8 = Charset.forName("UTF-8"); byte[] bytes(String str) { return str.getBytes(UTF8); } }