Changeset 18441 in josm for trunk/src/org/openstreetmap/josm/io
- Timestamp:
- 2022-05-10T17:30:28+02:00 (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/io/GeoJSONReader.java
r18007 r18441 12 12 import java.nio.charset.StandardCharsets; 13 13 import java.util.ArrayList; 14 import java.util. Arrays;14 import java.util.Collections; 15 15 import java.util.List; 16 16 import java.util.Map; … … 70 70 /** The record separator is 0x1E per RFC 7464 */ 71 71 private static final byte RECORD_SEPARATOR_BYTE = 0x1E; 72 private Projection projection = Projections.getProjectionByCode("EPSG:4326"); // WGS 84 72 /** 73 * WGS 84 is the specified CRS for geojson -- alternate coordinate systems are considered to be deprecated from 74 * GJ2008. 75 */ 76 private static final String CRS_GEOJSON = "EPSG:4326"; 77 private Projection projection = Projections.getProjectionByCode(CRS_GEOJSON); // WGS 84 73 78 74 79 GeoJSONReader() { … … 93 98 JsonValue.ValueType valueType = object.get(FEATURES).getValueType(); 94 99 CheckParameterUtil.ensureThat(valueType == JsonValue.ValueType.ARRAY, "features must be ARRAY, but is " + valueType); 95 parseFeatureCollection(object.getJsonArray(FEATURES) );100 parseFeatureCollection(object.getJsonArray(FEATURES), false); 96 101 break; 97 102 case "Feature": … … 99 104 break; 100 105 case "GeometryCollection": 101 parseGeometryCollection(null, object );106 parseGeometryCollection(null, object, false); 102 107 break; 103 108 default: … … 107 112 108 113 /** 109 * Parse CRS as per https://geojson.org/geojson-spec.html#coordinate-reference-system-objects. 114 * Parse CRS as per <a href="https://geojson.org/geojson-spec.html#coordinate-reference-system-objects"> 115 * https://geojson.org/geojson-spec.html#coordinate-reference-system-objects</a>. 110 116 * CRS are obsolete in RFC7946 but still allowed for interoperability with older applications. 111 117 * Only named CRS are supported. … … 117 123 if (crs != null) { 118 124 // Inspired by https://github.com/JOSM/geojson/commit/f13ceed4645244612a63581c96e20da802779c56 119 JsonObject properties = crs.getJsonObject( "properties");125 JsonObject properties = crs.getJsonObject(PROPERTIES); 120 126 if (properties != null) { 121 127 switch (crs.getString(TYPE)) { … … 124 130 if ("urn:ogc:def:crs:OGC:1.3:CRS84".equals(crsName)) { 125 131 // https://osgeo-org.atlassian.net/browse/GEOT-1710 126 crsName = "EPSG:4326";132 crsName = CRS_GEOJSON; 127 133 } else if (crsName.startsWith("urn:ogc:def:crs:EPSG:")) { 128 134 crsName = crsName.replace("urn:ogc:def:crs:", ""); 129 135 } 130 136 projection = Optional.ofNullable(Projections.getProjectionByCode(crsName)) 131 .orElse(Projections.getProjectionByCode( "EPSG:4326")); // WGS84137 .orElse(Projections.getProjectionByCode(CRS_GEOJSON)); // WGS84 132 138 break; 133 139 case LINK: // Not supported (security risk) … … 139 145 } 140 146 141 private void parseFeatureCollection(final JsonArray features) { 142 for (JsonValue feature : features) { 143 if (feature instanceof JsonObject) { 144 parseFeature((JsonObject) feature); 145 } 146 } 147 } 148 149 private void parseFeature(final JsonObject feature) { 147 private Optional<? extends OsmPrimitive> parseFeatureCollection(final JsonArray features, boolean createRelation) { 148 List<OsmPrimitive> primitives = features.stream().filter(JsonObject.class::isInstance).map(JsonObject.class::cast) 149 .map(this::parseFeature).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList()); 150 if (createRelation && primitives.size() > 1) { 151 Relation relation = new Relation(); 152 relation.setMembers(primitives.stream().map(osm -> new RelationMember("", osm)).collect(Collectors.toList())); 153 getDataSet().addPrimitive(relation); 154 return Optional.of(relation); 155 } else if (primitives.size() == 1) { 156 return Optional.of(primitives.get(0)); 157 } 158 return Optional.empty(); 159 } 160 161 private Optional<? extends OsmPrimitive> parseFeature(final JsonObject feature) { 150 162 JsonValue geometry = feature.get(GEOMETRY); 151 163 if (geometry != null && geometry.getValueType() == JsonValue.ValueType.OBJECT) { 152 parseGeometry(feature, geometry.asJsonObject());164 return parseGeometry(feature, geometry.asJsonObject()); 153 165 } else { 154 166 JsonValue properties = feature.get(PROPERTIES); 155 167 if (properties != null && properties.getValueType() == JsonValue.ValueType.OBJECT) { 156 parseNonGeometryFeature(feature, properties.asJsonObject());168 return parseNonGeometryFeature(feature, properties.asJsonObject()); 157 169 } else { 158 170 Logging.warn(tr("Relation/non-geometry feature without properties found: {0}", feature)); 159 171 } 160 172 } 161 } 162 163 private void parseNonGeometryFeature(final JsonObject feature, final JsonObject properties) { 173 return Optional.empty(); 174 } 175 176 private Optional<? extends OsmPrimitive> parseNonGeometryFeature(final JsonObject feature, final JsonObject properties) { 164 177 // get relation type 165 178 JsonValue type = properties.get(TYPE); 166 179 if (type == null || properties.getValueType() == JsonValue.ValueType.STRING) { 167 180 Logging.warn(tr("Relation/non-geometry feature without type found: {0}", feature)); 168 return; 181 if (!feature.containsKey(FEATURES)) { 182 return Optional.empty(); 183 } 169 184 } 170 185 171 186 // create misc. non-geometry feature 172 final Relation relation = new Relation(); 173 fillTagsFromFeature(feature, relation); 174 relation.put(TYPE, type.toString()); 175 getDataSet().addPrimitive(relation); 176 } 177 178 private void parseGeometryCollection(final JsonObject feature, final JsonObject geometry) { 187 OsmPrimitive primitive = null; 188 if (feature.containsKey(FEATURES) && feature.get(FEATURES).getValueType() == JsonValue.ValueType.ARRAY) { 189 Optional<? extends OsmPrimitive> osm = parseFeatureCollection(feature.getJsonArray(FEATURES), true); 190 if (osm.isPresent()) { 191 primitive = osm.get(); 192 fillTagsFromFeature(feature, primitive); 193 } 194 } 195 return Optional.ofNullable(primitive); 196 } 197 198 private Optional<Relation> parseGeometryCollection(final JsonObject feature, final JsonObject geometry, boolean createRelation) { 199 List<RelationMember> relationMembers = new ArrayList<>(geometry.getJsonArray("geometries").size()); 179 200 for (JsonValue jsonValue : geometry.getJsonArray("geometries")) { 180 parseGeometry(feature, jsonValue.asJsonObject()); 181 } 182 } 183 184 private void parseGeometry(final JsonObject feature, final JsonObject geometry) { 201 parseGeometry(feature, jsonValue.asJsonObject()).map(osm -> new RelationMember("", osm)).ifPresent(relationMembers::add); 202 } 203 if (createRelation) { 204 Relation relation = new Relation(); 205 relation.setMembers(relationMembers); 206 getDataSet().addPrimitive(relation); 207 return Optional.of(fillTagsFromFeature(feature, relation)); 208 } 209 return Optional.empty(); 210 } 211 212 private Optional<? extends OsmPrimitive> parseGeometry(final JsonObject feature, final JsonObject geometry) { 185 213 if (geometry == null) { 186 214 parseNullGeometry(feature); 187 return ;215 return Optional.empty(); 188 216 } 189 217 190 218 switch (geometry.getString(TYPE)) { 191 219 case "Point": 192 parsePoint(feature, geometry.getJsonArray(COORDINATES)); 193 break; 220 return parsePoint(feature, geometry.getJsonArray(COORDINATES)); 194 221 case "MultiPoint": 195 parseMultiPoint(feature, geometry); 196 break; 222 return parseMultiPoint(feature, geometry); 197 223 case "LineString": 198 parseLineString(feature, geometry.getJsonArray(COORDINATES)); 199 break; 224 return parseLineString(feature, geometry.getJsonArray(COORDINATES)); 200 225 case "MultiLineString": 201 parseMultiLineString(feature, geometry); 202 break; 226 return parseMultiLineString(feature, geometry); 203 227 case "Polygon": 204 parsePolygon(feature, geometry.getJsonArray(COORDINATES)); 205 break; 228 return parsePolygon(feature, geometry.getJsonArray(COORDINATES)); 206 229 case "MultiPolygon": 207 parseMultiPolygon(feature, geometry); 208 break; 230 return parseMultiPolygon(feature, geometry); 209 231 case "GeometryCollection": 210 parseGeometryCollection(feature, geometry); 211 break; 232 return parseGeometryCollection(feature, geometry, true); 212 233 default: 213 234 parseUnknown(geometry); 235 return Optional.empty(); 214 236 } 215 237 } … … 231 253 } 232 254 233 private void parsePoint(final JsonObject feature, final JsonArray coordinates) { 234 fillTagsFromFeature(feature, createNode(getLatLon(coordinates))); 235 } 236 237 private void parseMultiPoint(final JsonObject feature, final JsonObject geometry) { 255 private Optional<Node> parsePoint(final JsonObject feature, final JsonArray coordinates) { 256 return Optional.of(fillTagsFromFeature(feature, createNode(getLatLon(coordinates)))); 257 } 258 259 private Optional<Relation> parseMultiPoint(final JsonObject feature, final JsonObject geometry) { 260 List<RelationMember> nodes = new ArrayList<>(geometry.getJsonArray(COORDINATES).size()); 238 261 for (JsonValue coordinate : geometry.getJsonArray(COORDINATES)) { 239 parsePoint(feature, coordinate.asJsonArray()); 240 } 241 } 242 243 private void parseLineString(final JsonObject feature, final JsonArray coordinates) { 262 parsePoint(feature, coordinate.asJsonArray()).map(node -> new RelationMember("", node)).ifPresent(nodes::add); 263 } 264 Relation returnRelation = new Relation(); 265 returnRelation.setMembers(nodes); 266 getDataSet().addPrimitive(returnRelation); 267 return Optional.of(fillTagsFromFeature(feature, returnRelation)); 268 } 269 270 private Optional<Way> parseLineString(final JsonObject feature, final JsonArray coordinates) { 244 271 if (!coordinates.isEmpty()) { 245 createWay(coordinates, false) 246 .ifPresent(way -> fillTagsFromFeature(feature, way)); 247 } 248 } 249 250 private void parseMultiLineString(final JsonObject feature, final JsonObject geometry) { 272 Optional<Way> way = createWay(coordinates, false); 273 way.ifPresent(tWay -> fillTagsFromFeature(feature, tWay)); 274 return way; 275 } 276 return Optional.empty(); 277 } 278 279 private Optional<Relation> parseMultiLineString(final JsonObject feature, final JsonObject geometry) { 280 final List<RelationMember> ways = new ArrayList<>(geometry.getJsonArray(COORDINATES).size()); 251 281 for (JsonValue coordinate : geometry.getJsonArray(COORDINATES)) { 252 parseLineString(feature, coordinate.asJsonArray()); 253 } 254 } 255 256 private void parsePolygon(final JsonObject feature, final JsonArray coordinates) { 282 parseLineString(feature, coordinate.asJsonArray()).map(way -> new RelationMember("", way)).ifPresent(ways::add); 283 } 284 final Relation relation = new Relation(); 285 relation.setMembers(ways); 286 getDataSet().addPrimitive(relation); 287 return Optional.of(fillTagsFromFeature(feature, relation)); 288 } 289 290 private Optional<? extends OsmPrimitive> parsePolygon(final JsonObject feature, final JsonArray coordinates) { 257 291 final int size = coordinates.size(); 258 292 if (size == 1) { 259 createWay(coordinates.getJsonArray(0), true) 260 .ifPresent(way -> fillTagsFromFeature(feature, way)); 293 Optional<Way> optionalWay = createWay(coordinates.getJsonArray(0), true); 294 optionalWay.ifPresent(way -> fillTagsFromFeature(feature, way)); 295 return optionalWay; 261 296 } else if (size > 1) { 262 297 // create multipolygon … … 273 308 multipolygon.put(TYPE, "multipolygon"); 274 309 getDataSet().addPrimitive(multipolygon); 275 } 276 } 277 278 private void parseMultiPolygon(final JsonObject feature, final JsonObject geometry) { 310 return Optional.of(multipolygon); 311 } 312 return Optional.empty(); 313 } 314 315 private Optional<Relation> parseMultiPolygon(final JsonObject feature, final JsonObject geometry) { 316 List<RelationMember> relationMembers = new ArrayList<>(geometry.getJsonArray(COORDINATES).size()); 279 317 for (JsonValue coordinate : geometry.getJsonArray(COORDINATES)) { 280 parsePolygon(feature, coordinate.asJsonArray()); 281 } 318 parsePolygon(feature, coordinate.asJsonArray()).map(poly -> new RelationMember("", poly)).ifPresent(relationMembers::add); 319 } 320 Relation relation = new Relation(); 321 relation.setMembers(relationMembers); 322 return Optional.of(fillTagsFromFeature(feature, relation)); 282 323 } 283 324 … … 337 378 * @param feature the GeoJSON feature 338 379 * @param primitive the OSM primitive 380 * @param <O> The primitive type 381 * @return The primitive passed in as {@code primitive} for easier chaining 339 382 */ 340 private static void fillTagsFromFeature(final JsonObject feature, final OsmPrimitiveprimitive) {383 private static <O extends OsmPrimitive> O fillTagsFromFeature(final JsonObject feature, final O primitive) { 341 384 if (feature != null) { 342 385 TagCollection featureTags = getTags(feature); 343 386 primitive.setKeys(new TagMap(primitive.isTagged() ? mergeAllTagValues(primitive, featureTags) : featureTags)); 344 387 } 388 return primitive; 345 389 } 346 390 … … 348 392 TagCollection tags = TagCollection.from(primitive).union(featureTags); 349 393 TagConflictResolutionUtil.applyAutomaticTagConflictResolution(tags); 350 TagConflictResolutionUtil.normalizeTagCollectionBeforeEditing(tags, Arrays.asList(primitive));394 TagConflictResolutionUtil.normalizeTagCollectionBeforeEditing(tags, Collections.singletonList(primitive)); 351 395 TagConflictResolverModel tagModel = new TagConflictResolverModel(); 352 396 tagModel.populate(new TagCollection(tags), tags.getKeysWithMultipleValues()); … … 455 499 Way replacement = null; 456 500 for (OsmPrimitive p : e.getPrimitives()) { 457 if (p.isTagged() && p.referrers(Relation.class).count() == 0)501 if (p.isTagged() && !p.referrers(Relation.class).findAny().isPresent()) 458 502 replacement = (Way) p; 459 503 else if (p.referrers(Relation.class).anyMatch(Relation::isMultipolygon))
Note:
See TracChangeset
for help on using the changeset viewer.