// License: GPL. For details, see LICENSE file.
package relcontext.relationfix;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.openstreetmap.josm.command.ChangeCommand;
import org.openstreetmap.josm.command.Command;
import org.openstreetmap.josm.data.osm.MultipolygonBuilder;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
import org.openstreetmap.josm.data.osm.Relation;
import org.openstreetmap.josm.data.osm.RelationMember;
import org.openstreetmap.josm.data.osm.Way;
/**
* @see http://wiki.openstreetmap.org/wiki/Relation:multipolygon
*/
public class MultipolygonFixer extends RelationFixer {
public MultipolygonFixer() {
super("multipolygon");
}
protected MultipolygonFixer(String...types) {
super(types);
}
@Override
public boolean isRelationGood(Relation rel) {
for (RelationMember m : rel.getMembers()) {
if (m.getType().equals(OsmPrimitiveType.WAY) && !("outer".equals(m.getRole()) || "inner".equals(m.getRole()))) {
setWarningMessage(tr("Way without ''inner'' or ''outer'' role found"));
return false;
}
}
clearWarningMessage();
return true;
}
@Override
public Command fixRelation(Relation rel) {
Relation rr = fixMultipolygonRoles(rel);
return rr != null ? new ChangeCommand(rel, rr) : null;
}
/**
* Basically, created multipolygon from scratch, and if successful, replace roles with new ones.
*/
protected Relation fixMultipolygonRoles(Relation source) {
Collection<Way> ways = new ArrayList<>();
for (OsmPrimitive p : source.getMemberPrimitives()) {
if (p instanceof Way) {
ways.add((Way) p);
}
}
MultipolygonBuilder mpc = new MultipolygonBuilder();
String error = mpc.makeFromWays(ways);
if (error != null)
return null;
Relation r = new Relation(source);
boolean fixed = false;
Set<Way> outerWays = new HashSet<>();
for (MultipolygonBuilder.JoinedPolygon poly : mpc.outerWays) {
for (Way w : poly.ways) {
outerWays.add(w);
}
}
Set<Way> innerWays = new HashSet<>();
for (MultipolygonBuilder.JoinedPolygon poly : mpc.innerWays) {
for (Way w : poly.ways) {
innerWays.add(w);
}
}
for (int i = 0; i < r.getMembersCount(); i++) {
RelationMember m = r.getMember(i);
if (m.isWay()) {
String role = null;
if (outerWays.contains((Way)m.getMember())) {
role = "outer";
} else if (innerWays.contains((Way)m.getMember())) {
role = "inner";
}
if (role != null && !role.equals(m.getRole())) {
r.setMember(i, new RelationMember(role, m.getMember()));
fixed = true;
}
}
}
return fixed ? r : null;
}
}