kopia lustrzana https://github.com/JOSM/MapWithAI
Create a special third-party case for ESRI servers
This currently supports groups (the id in the sources.json *must* be the group id) and specific FeatureServers. This should only be used when (a) permission is given for OpenStreetMap to use the data and (b) the server owner has given their OK. While the feature calls should be as efficient as possible, many server owners will be paying for data transfer. Signed-off-by: Taylor Smock <taylor.smock@kaart.com>pull/1/head
rodzic
dee0b13fc7
commit
5d883d8fd4
|
@ -15,6 +15,7 @@ import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
|
|||
import org.openstreetmap.josm.gui.progress.ProgressMonitor;
|
||||
import org.openstreetmap.josm.gui.util.GuiHelper;
|
||||
import org.openstreetmap.josm.io.BoundingBoxDownloader;
|
||||
import org.openstreetmap.josm.io.GeoJSONReader;
|
||||
import org.openstreetmap.josm.io.IllegalDataException;
|
||||
import org.openstreetmap.josm.io.OsmApiException;
|
||||
import org.openstreetmap.josm.io.OsmTransferException;
|
||||
|
@ -90,7 +91,15 @@ public class BoundingBoxMapWithAIDownloader extends BoundingBoxDownloader {
|
|||
|
||||
@Override
|
||||
protected DataSet parseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
|
||||
DataSet ds = OsmReaderCustom.parseDataSet(source, progressMonitor, true);
|
||||
DataSet ds;
|
||||
if (MapWithAIInfo.MapWithAIType.ESRI_FEATURE_SERVER.equals(this.info.getSourceType())) {
|
||||
ds = GeoJSONReader.parseDataSet(source, progressMonitor);
|
||||
if (info.getReplacementTags() != null) {
|
||||
GetDataRunnable.replaceKeys(ds, info.getReplacementTags());
|
||||
}
|
||||
} else {
|
||||
ds = OsmReaderCustom.parseDataSet(source, progressMonitor, true);
|
||||
}
|
||||
if (url != null && info.getUrl() != null && !info.getUrl().trim().isEmpty()) {
|
||||
GetDataRunnable.addMapWithAISourceTag(ds, getSourceTag(info));
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ public class MapWithAIInfo extends TileSourceInfo implements Comparable<MapWithA
|
|||
* Type of MapWithAI entry
|
||||
*/
|
||||
public enum MapWithAIType {
|
||||
FACEBOOK("facebook"), THIRD_PARTY("thirdParty");
|
||||
FACEBOOK("facebook"), THIRD_PARTY("thirdParty"), ESRI("esri"), ESRI_FEATURE_SERVER("esriFeatureServer");
|
||||
|
||||
private final String typeString;
|
||||
|
||||
|
@ -734,9 +734,15 @@ public class MapWithAIInfo extends TileSourceInfo implements Comparable<MapWithA
|
|||
StringBuilder sb = new StringBuilder();
|
||||
if (url != null && !url.trim().isEmpty()) {
|
||||
sb.append(url);
|
||||
List<String> parameters = getParametersString();
|
||||
if (!parameters.isEmpty()) {
|
||||
sb.append('&').append(String.join("&", parameters));
|
||||
if (MapWithAIType.ESRI_FEATURE_SERVER.equals(type)) {
|
||||
if (!url.endsWith("/")) {
|
||||
sb.append("/");
|
||||
}
|
||||
sb.append("query?geometryType=esriGeometryEnvelope&geometry={bbox}&inSR=4326&f=geojson&outfields=*");
|
||||
}
|
||||
List<String> parametersString = getParametersString();
|
||||
if (!parametersString.isEmpty()) {
|
||||
sb.append('&').append(String.join("&", parametersString));
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
|
|
|
@ -3,6 +3,7 @@ package org.openstreetmap.josm.plugins.mapwithai.data.mapwithai;
|
|||
|
||||
import static org.openstreetmap.josm.tools.I18n.tr;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -16,9 +17,20 @@ import java.util.Objects;
|
|||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.json.Json;
|
||||
import javax.json.JsonArray;
|
||||
import javax.json.JsonNumber;
|
||||
import javax.json.JsonObject;
|
||||
import javax.json.JsonReader;
|
||||
import javax.json.JsonStructure;
|
||||
import javax.json.JsonValue;
|
||||
|
||||
import org.openstreetmap.josm.data.StructUtils;
|
||||
import org.openstreetmap.josm.data.imagery.ImageryInfo;
|
||||
import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryBounds;
|
||||
import org.openstreetmap.josm.gui.PleaseWaitRunnable;
|
||||
import org.openstreetmap.josm.gui.util.GuiHelper;
|
||||
import org.openstreetmap.josm.io.CachedFile;
|
||||
|
@ -193,7 +205,11 @@ public class MapWithAILayerInfo {
|
|||
allDefaultLayers.clear();
|
||||
defaultLayers.addAll(newLayers);
|
||||
for (MapWithAIInfo layer : newLayers) {
|
||||
allDefaultLayers.add(layer);
|
||||
if (MapWithAIInfo.MapWithAIType.ESRI.equals(layer.getSourceType())) {
|
||||
allDefaultLayers.addAll(addEsriLayer(layer));
|
||||
} else {
|
||||
allDefaultLayers.add(layer);
|
||||
}
|
||||
}
|
||||
defaultLayerIds.clear();
|
||||
Collections.sort(defaultLayers);
|
||||
|
@ -210,6 +226,97 @@ public class MapWithAILayerInfo {
|
|||
}
|
||||
}
|
||||
|
||||
private static Collection<MapWithAIInfo> addEsriLayer(MapWithAIInfo layer) {
|
||||
Pattern startReplace = Pattern.compile("\\{start\\}");
|
||||
String search = "/search?sortField=added&sortOrder=desc&num=12&start={start}&f=json";
|
||||
String url = layer.getUrl();
|
||||
String group = layer.getId();
|
||||
if (!url.endsWith("/")) {
|
||||
url = url.concat("/");
|
||||
}
|
||||
|
||||
Collection<MapWithAIInfo> information = new HashSet<>();
|
||||
|
||||
String next = "1";
|
||||
String searchUrl = startReplace.matcher(search).replaceAll(next);
|
||||
while (!next.equals("-1")) {
|
||||
try (CachedFile layers = new CachedFile(url + "content/groups/" + group + searchUrl);
|
||||
BufferedReader i = layers.getContentReader();
|
||||
JsonReader reader = Json.createReader(i)) {
|
||||
JsonStructure parser = reader.read();
|
||||
if (parser.getValueType().equals(JsonValue.ValueType.OBJECT)) {
|
||||
JsonObject obj = parser.asJsonObject();
|
||||
next = obj.getString("nextStart", "-1");
|
||||
searchUrl = startReplace.matcher(search).replaceAll(next);
|
||||
JsonArray features = obj.getJsonArray("results");
|
||||
for (JsonObject feature : features.getValuesAs(JsonObject.class)) {
|
||||
MapWithAIInfo newInfo = new MapWithAIInfo();
|
||||
newInfo.setId(feature.getString("id"));
|
||||
if (feature.getString("type", "").equals("Feature Service")) {
|
||||
newInfo.setUrl(featureService(newInfo, feature.getString("url")));
|
||||
} else {
|
||||
newInfo.setUrl(feature.getString("url"));
|
||||
}
|
||||
newInfo.setName(feature.getString("title", feature.getString("name")));
|
||||
String[] extent = feature.getJsonArray("extent").getValuesAs(JsonArray.class).stream()
|
||||
.flatMap(array -> array.getValuesAs(JsonNumber.class).stream())
|
||||
.map(JsonNumber::doubleValue).map(Object::toString).toArray(String[]::new);
|
||||
ImageryBounds imageryBounds = new ImageryBounds(
|
||||
String.join(",", extent[1], extent[0], extent[3], extent[2]), ",");
|
||||
newInfo.setBounds(imageryBounds);
|
||||
newInfo.setSourceType(MapWithAIInfo.MapWithAIType.ESRI_FEATURE_SERVER);
|
||||
newInfo.setTermsOfUseText(feature.getString("licenseInfo", null));
|
||||
if (feature.containsKey("thumbnail")) {
|
||||
newInfo.setAttributionImageURL(url + "content/items/" + newInfo.getId() + "/info/"
|
||||
+ feature.getString("thumbnail"));
|
||||
}
|
||||
// TODO groupCategories
|
||||
// TODO snippet/description
|
||||
information.add(newInfo);
|
||||
}
|
||||
}
|
||||
} catch (ClassCastException | IOException e) {
|
||||
Logging.error(e);
|
||||
next = "-1";
|
||||
}
|
||||
}
|
||||
return information;
|
||||
}
|
||||
|
||||
private static String featureService(MapWithAIInfo mapwithaiInfo, String url) {
|
||||
String toGet = url.endsWith("pjson") ? url : url.concat("?f=pjson");
|
||||
try (CachedFile featureServer = new CachedFile(toGet);
|
||||
BufferedReader br = featureServer.getContentReader();
|
||||
JsonReader reader = Json.createReader(br)) {
|
||||
JsonObject info = reader.readObject();
|
||||
JsonArray layers = info.getJsonArray("layers");
|
||||
// TODO use all the layers?
|
||||
JsonObject layer = layers.get(0).asJsonObject();
|
||||
String partialUrl = (url.endsWith("/") ? url : url + "/") + layer.getInt("id");
|
||||
mapwithaiInfo.setReplacementTags(getReplacementTags(partialUrl));
|
||||
|
||||
return partialUrl;
|
||||
} catch (IOException e) {
|
||||
Logging.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, String> getReplacementTags(String layerUrl) {
|
||||
String toGet = layerUrl.endsWith("pjson") ? layerUrl : layerUrl.concat("?f=pjson");
|
||||
try (CachedFile featureServer = new CachedFile(toGet);
|
||||
BufferedReader br = featureServer.getContentReader();
|
||||
JsonReader reader = Json.createReader(br)) {
|
||||
JsonObject info = reader.readObject();
|
||||
|
||||
return info.getJsonArray("fields").getValuesAs(JsonObject.class).stream()
|
||||
.collect(Collectors.toMap(o -> o.getString("name"), o -> o.getString("alias", null)));
|
||||
} catch (IOException e) {
|
||||
Logging.error(e);
|
||||
}
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the mapping of unique ids to {@link ImageryInfo}s.
|
||||
*
|
||||
|
|
Ładowanie…
Reference in New Issue