source: josm/trunk/src/org/openstreetmap/josm/io/OsmJsonReader.java@ 14628

Last change on this file since 14628 was 14219, checked in by Don-vip, 6 years ago

fix #16695 - display remark from Overpass API when a download returns no data

  • Property svn:eol-style set to native
File size: 7.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.InputStream;
7import java.util.Collection;
8import java.util.Map.Entry;
9
10import javax.json.Json;
11import javax.json.JsonArray;
12import javax.json.JsonNumber;
13import javax.json.JsonObject;
14import javax.json.JsonString;
15import javax.json.JsonValue;
16import javax.json.stream.JsonParser;
17import javax.json.stream.JsonParser.Event;
18
19import org.openstreetmap.josm.data.osm.DataSet;
20import org.openstreetmap.josm.data.osm.PrimitiveData;
21import org.openstreetmap.josm.data.osm.Relation;
22import org.openstreetmap.josm.data.osm.RelationMemberData;
23import org.openstreetmap.josm.data.osm.Tagged;
24import org.openstreetmap.josm.data.osm.Way;
25import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
26import org.openstreetmap.josm.gui.progress.ProgressMonitor;
27import org.openstreetmap.josm.tools.Logging;
28import org.openstreetmap.josm.tools.UncheckedParseException;
29
30/**
31 * Parser for the Osm API (JSON output). Read from an input stream and construct a dataset out of it.
32 *
33 * For each json element, there is a dedicated method.
34 * @since 14086
35 */
36public class OsmJsonReader extends AbstractReader {
37
38 protected JsonParser parser;
39
40 /**
41 * constructor (for private and subclasses use only)
42 *
43 * @see #parseDataSet(InputStream, ProgressMonitor)
44 */
45 protected OsmJsonReader() {
46 // Restricts visibility
47 }
48
49 protected void setParser(JsonParser parser) {
50 this.parser = parser;
51 }
52
53 protected void parse() throws IllegalDataException {
54 while (parser.hasNext()) {
55 Event event = parser.next();
56 if (event == Event.START_OBJECT) {
57 parseRoot(parser.getObject());
58 }
59 }
60 parser.close();
61 }
62
63 private void parseRoot(JsonObject object) throws IllegalDataException {
64 parseVersion(object.get("version").toString());
65 parseDownloadPolicy("download", object.getString("download", null));
66 parseUploadPolicy("upload", object.getString("upload", null));
67 parseLocked(object.getString("locked", null));
68 parseElements(object.getJsonArray("elements"));
69 parseRemark(object.getString("remark", null));
70 }
71
72 private void parseRemark(String remark) {
73 ds.setRemark(remark);
74 }
75
76 private void parseElements(JsonArray jsonArray) throws IllegalDataException {
77 for (JsonValue value : jsonArray) {
78 if (value instanceof JsonObject) {
79 JsonObject item = (JsonObject) value;
80 switch (item.getString("type")) {
81 case "node":
82 parseNode(item);
83 break;
84 case "way":
85 parseWay(item);
86 break;
87 case "relation":
88 parseRelation(item);
89 break;
90 default:
91 parseUnknown(item);
92 }
93 } else {
94 throw new IllegalDataException("Unexpected JSON item: " + value);
95 }
96 }
97 }
98
99 /**
100 * Read out the common attributes and put them into current OsmPrimitive.
101 * @param item current JSON object
102 * @param current primitive to update
103 * @throws IllegalDataException if there is an error processing the underlying JSON source
104 */
105 private void readCommon(JsonObject item, PrimitiveData current) throws IllegalDataException {
106 try {
107 parseId(current, item.getJsonNumber("id").longValue());
108 parseTimestamp(current, item.getString("timestamp", null));
109 JsonNumber uid = item.getJsonNumber("uid");
110 if (uid != null) {
111 parseUser(current, item.getString("user", null), uid.longValue());
112 }
113 parseVisible(current, item.getString("visible", null));
114 JsonNumber version = item.getJsonNumber("version");
115 if (version != null) {
116 parseVersion(current, version.intValue());
117 }
118 parseAction(current, item.getString("action", null));
119 JsonNumber changeset = item.getJsonNumber("changeset");
120 if (changeset != null) {
121 parseChangeset(current, changeset.intValue());
122 }
123 } catch (UncheckedParseException e) {
124 throw new IllegalDataException(e);
125 }
126 }
127
128 private static void readTags(JsonObject item, Tagged t) {
129 JsonObject tags = item.getJsonObject("tags");
130 if (tags != null) {
131 for (Entry<String, JsonValue> entry : tags.entrySet()) {
132 t.put(entry.getKey(), ((JsonString) entry.getValue()).getString());
133 }
134 }
135 }
136
137 private void parseNode(JsonObject item) throws IllegalDataException {
138 parseNode(item.getJsonNumber("lat").doubleValue(),
139 item.getJsonNumber("lon").doubleValue(), nd -> readCommon(item, nd), n -> readTags(item, n));
140 }
141
142 private void parseWay(JsonObject item) throws IllegalDataException {
143 parseWay(wd -> readCommon(item, wd), (w, nodeIds) -> readWayNodesAndTags(item, w, nodeIds));
144 }
145
146 private static void readWayNodesAndTags(JsonObject item, Way w, Collection<Long> nodeIds) {
147 for (JsonValue v : item.getJsonArray("nodes")) {
148 nodeIds.add(((JsonNumber) v).longValue());
149 }
150 readTags(item, w);
151 }
152
153 private void parseRelation(JsonObject item) throws IllegalDataException {
154 parseRelation(rd -> readCommon(item, rd), (r, members) -> readRelationMembersAndTags(item, r, members));
155 }
156
157 private void readRelationMembersAndTags(JsonObject item, Relation r, Collection<RelationMemberData> members)
158 throws IllegalDataException {
159 for (JsonValue v : item.getJsonArray("members")) {
160 JsonObject o = v.asJsonObject();
161 members.add(parseRelationMember(r, ((JsonNumber) o.get("ref")).longValue(), o.getString("type"), o.getString("role")));
162 }
163 readTags(item, r);
164 }
165
166 protected void parseUnknown(JsonObject element, boolean printWarning) {
167 if (printWarning) {
168 Logging.info(tr("Undefined element ''{0}'' found in input stream. Skipping.", element));
169 }
170 }
171
172 private void parseUnknown(JsonObject element) {
173 parseUnknown(element, true);
174 }
175
176 @Override
177 protected DataSet doParseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
178 return doParseDataSet(source, progressMonitor, ir -> {
179 setParser(Json.createParser(ir));
180 parse();
181 });
182 }
183
184 /**
185 * Parse the given input source and return the dataset.
186 *
187 * @param source the source input stream. Must not be null.
188 * @param progressMonitor the progress monitor. If null, {@link NullProgressMonitor#INSTANCE} is assumed
189 *
190 * @return the dataset with the parsed data
191 * @throws IllegalDataException if an error was found while parsing the data from the source
192 * @throws IllegalArgumentException if source is null
193 */
194 public static DataSet parseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
195 return new OsmJsonReader().doParseDataSet(source, progressMonitor);
196 }
197}
Note: See TracBrowser for help on using the repository browser.