// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.plugins.mapwithai.io.mapwithai; import javax.json.JsonArray; import javax.json.JsonObject; import javax.json.JsonString; import javax.json.JsonValue; import java.io.Closeable; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import org.openstreetmap.josm.data.imagery.ImageryInfo; import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryBounds; import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.CountryUtils; import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAICategory; import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAIInfo; import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAIType; import org.openstreetmap.josm.tools.Logging; import org.openstreetmap.josm.tools.Territories; /** * Reader to parse the list of available MapWithAI servers from an JSON * definition file. *

* The format is specified in the MapWithAI * source. */ public class MapWithAISourceReader extends CommonSourceReader> implements Closeable { /** * Constructs a {@code MapWithAISourceReader} from a given filename, URL or * internal resource. * * @param source can be: *

*/ public MapWithAISourceReader(String source) { super(source); } /** * Parses MapWithAI entry sources * * @param jsonObject The json of the data sources * @return The parsed entries */ @Override public List parseJson(JsonObject jsonObject) { return jsonObject.entrySet().stream().map(MapWithAISourceReader::parse).collect(Collectors.toList()); } private static MapWithAIInfo parse(Map.Entry entry) { String name = entry.getKey(); if (JsonValue.ValueType.OBJECT == entry.getValue().getValueType()) { JsonObject values = entry.getValue().asJsonObject(); String url = values.getString("url", ""); String type = values.getString("type", MapWithAIType.values()[0].getDefault().getTypeString()); String[] categories = values .getString("category", MapWithAICategory.values()[0].getDefault().getCategoryString()) .split(";", -1); String eula = values.getString("eula", ""); boolean conflation = values.getBoolean("conflate", false); String conflationUrl = values.getString("conflationUrl", null); String id = values.getString("id", name.replace(" ", "_")); String alreadyConflatedKey = values.getString("conflated_key", null); JsonValue countries = values.getOrDefault("countries", JsonValue.EMPTY_JSON_OBJECT); List bounds = getBounds(countries); MapWithAIInfo info = new MapWithAIInfo(name, url, type, eula, id); info.setDefaultEntry(values.getBoolean("default", false)); info.setParameters(values.getJsonArray("parameters")); info.setConflationParameters(values.getJsonArray("conflationParameters")); info.setConflation(conflation); info.setConflationUrl(conflationUrl); info.setSource(values.getString("source", null)); info.setAlreadyConflatedKey(alreadyConflatedKey); info.setAttributionText(values.getString("provider", null)); if (categories.length > 0) { info.setCategory(MapWithAICategory.fromString(categories[0])); if (categories.length > 1) { info.setAdditionalCategories(Stream.of(categories).skip(1).map(MapWithAICategory::fromString) .collect(Collectors.toList())); } } if (values.containsKey("conflation_ignore_categories")) { JsonArray ignore = values.getJsonArray("conflation_ignore_categories"); for (MapWithAICategory cat : ignore.getValuesAs(JsonString.class).stream().map(JsonString::getString) .map(MapWithAICategory::fromString).filter(Objects::nonNull).collect(Collectors.toList())) { info.addConflationIgnoreCategory(cat); } } if (values.containsKey("terms_of_use_url")) { info.setTermsOfUseURL(values.getString("terms_of_use_url")); } if (values.containsKey("privacy_policy_url")) { info.setPrivacyPolicyURL(values.getString("privacy_policy_url")); } if (!bounds.isEmpty()) { ImageryBounds bound = bounds.get(0); bounds.remove(0); bounds.forEach(bound::extend); bounds.forEach(b -> b.getShapes().forEach(bound::addShape)); info.setBounds(bound); } return info; } return new MapWithAIInfo(name); } private static List getBounds(JsonValue countries) { if (JsonValue.ValueType.OBJECT == countries.getValueType()) { Set codes; try { codes = Territories.getKnownIso3166Codes(); List bounds = new ArrayList<>(); for (Map.Entry country : countries.asJsonObject().entrySet()) { if (codes.contains(country.getKey())) { CountryUtils.getCountryShape(country.getKey()).ifPresent(bounds::add); } } return bounds; } catch (NullPointerException e) { Logging.error(e); } } return new ArrayList<>(); } }