// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.opendata.core.datasets;
import static org.openstreetmap.josm.plugins.opendata.core.io.OverpassApi.OaQueryType.NODE;
import static org.openstreetmap.josm.plugins.opendata.core.io.OverpassApi.OaQueryType.RELATION;
import static org.openstreetmap.josm.plugins.opendata.core.io.OverpassApi.OaQueryType.WAY;
import static org.openstreetmap.josm.plugins.opendata.core.io.OverpassApi.OaRecurseType.NODE_RELATION;
import static org.openstreetmap.josm.plugins.opendata.core.io.OverpassApi.OaRecurseType.RELATION_WAY;
import static org.openstreetmap.josm.plugins.opendata.core.io.OverpassApi.OaRecurseType.WAY_NODE;
import static org.openstreetmap.josm.plugins.opendata.core.io.OverpassApi.OaRecurseType.WAY_RELATION;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.openstreetmap.josm.data.osm.IPrimitive;
import org.openstreetmap.josm.data.osm.Tag;
import org.openstreetmap.josm.data.projection.Projection;
import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
import org.openstreetmap.josm.plugins.opendata.core.OdConstants;
import org.openstreetmap.josm.plugins.opendata.core.io.OverpassApi;
public abstract class SimpleDataSetHandler extends AbstractDataSetHandler {
protected static final Projection wgs84 = OdConstants.PRJ_WGS84.getProjection();
private final List<Tag> relevantTags = new ArrayList<>();
private final List<Tag> forbiddenTags = new ArrayList<>();
private final boolean relevantUnion;
public SimpleDataSetHandler() {
this.relevantUnion = false;
}
public SimpleDataSetHandler(String relevantTag) {
addRelevantTag(relevantTag);
this.relevantUnion = false;
Tag tag;
String[] kv = relevantTag.split("=");
if (kv != null && kv.length == 2) {
tag = new Tag(kv[0], kv[1]);
} else {
tag = new Tag(relevantTag);
}
setMenuIcon(MapPaintStyles.getNodeIcon(tag));
}
public SimpleDataSetHandler(boolean relevantUnion, String ... relevantTags) {
addRelevantTag(relevantTags);
this.relevantUnion = relevantUnion;
}
public SimpleDataSetHandler(String ... relevantTags) {
this(false, relevantTags);
}
public SimpleDataSetHandler(Tag relevantTag) {
addRelevantTag(relevantTag);
this.relevantUnion = false;
}
public SimpleDataSetHandler(boolean relevantUnion, Tag ... relevantTags) {
addRelevantTag(relevantTags);
this.relevantUnion = relevantUnion;
}
public SimpleDataSetHandler(Tag ... relevantTags) {
this(false, relevantTags);
}
public void addRelevantTag(String ... relevantTags) {
addTags(this.relevantTags, relevantTags);
}
public void addRelevantTag(Tag ... relevantTags) {
addTags(this.relevantTags, relevantTags);
}
public void addForbiddenTag(String ... forbiddenTags) {
addTags(this.forbiddenTags, forbiddenTags);
}
public void addForbiddenTag(Tag ... forbiddenTags) {
addTags(this.forbiddenTags, forbiddenTags);
}
private void addTags(final List<Tag> list, String ... tags) {
if (tags != null) {
for (String tag : tags) {
if (tag != null) {
if (tag.contains("=")) {
String[] tab = tag.split("=");
list.add(new Tag(tab[0], tab[1]));
} else {
list.add(new Tag(tag));
}
}
}
}
}
private void addTags(final List<Tag> list, Tag ... tags) {
if (tags != null) {
for (Tag tag : tags) {
if (tag != null) {
list.add(tag);
}
}
}
}
@Override
public boolean equals(IPrimitive p1, IPrimitive p2) {
for (Tag tag : this.relevantTags) {
if (!p1.get(tag.getKey()).equals(p2.get(tag.getKey()))) {
return false;
}
}
return true;
}
@Override
public boolean isRelevant(IPrimitive p) {
for (Tag tag : this.relevantTags) {
String value = p.get(tag.getKey());
if (value == null || (tag.getValue() != null && !tag.getValue().equals(value))) {
return false;
}
}
if (isForbidden(p)) {
return false;
}
return true;
}
@Override
public boolean isForbidden(IPrimitive p) {
for (Tag tag : this.forbiddenTags) {
String value = p.get(tag.getKey());
if (value != null && (tag.getValue() == null || tag.getValue().equals(value))) {
return true;
}
}
return false;
}
@Override
public boolean hasForbiddenTags() {
return !this.forbiddenTags.isEmpty();
}
protected final String[] getOverpassApiConditions() {
List<String> conditions = new ArrayList<>();
for (Tag tag : this.relevantTags) {
conditions.add(OverpassApi.hasKey(tag.getKey(), tag.getValue()));
}
return conditions.toArray(new String[0]);
}
protected String getOverpassApiQueries(String bbox, String ... conditions) {
String[] mpconditions = new String[conditions.length+1];
mpconditions[0] = OverpassApi.hasKey("type", "multipolygon");
for (int i = 0; i < conditions.length; i++) {
mpconditions[i+1] = conditions[i];
}
return OverpassApi.query(bbox, NODE, conditions) + "\n" + // Nodes
OverpassApi.recurse(NODE_RELATION, RELATION_WAY, WAY_NODE) + "\n" +
OverpassApi.query(bbox, WAY, conditions) + "\n" + // Full ways and their full relations
OverpassApi.recurse(WAY_NODE, "nodes") + "\n" +
OverpassApi.recurse(WAY_RELATION, RELATION_WAY, WAY_NODE) + "\n" +
OverpassApi.query(bbox, RELATION, mpconditions) + "\n" + // Full multipolygons
OverpassApi.recurse(RELATION_WAY, WAY_NODE);
}
@Override
protected String getOverpassApiRequest(String bbox) {
String result = "";
if (this.relevantUnion) {
for (Tag tag : this.relevantTags) {
result += getOverpassApiQueries(bbox, OverpassApi.hasKey(tag.getKey(), tag.getValue()));
}
result = OverpassApi.union(result);
} else {
result = OverpassApi.union(getOverpassApiQueries(bbox, getOverpassApiConditions()));
}
return result + OverpassApi.print();
}
@Override
protected Collection<String> getOsmXapiRequests(String bbox) {
String relevantTags = "";
for (Tag tag : this.relevantTags) {
relevantTags += "["+tag.getKey()+"="+(tag.getValue() == null ? "*" : tag.getValue())+"]";
}
String forbiddenTags = "";
for (Tag tag : this.forbiddenTags) {
forbiddenTags += "[not("+tag.getKey()+"="+(tag.getValue() == null ? "*" : tag.getValue())+")]";
}
return Collections.singleton("*[bbox="+bbox+"]"+relevantTags+forbiddenTags+"[@meta]");
}
}