source: osm/applications/editors/josm/plugins/reltoolbox/src/relcontext/relationfix/AssociatedStreetFixer.java@ 36103

Last change on this file since 36103 was 36103, checked in by taylor.smock, 2 years ago

reltoolbox: Preferentially use the source relation dataset

If the source relation does not have a dataset, use the current edit dataset instead.

This also adds some basic tests.

File size: 6.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package relcontext.relationfix;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.ArrayList;
7import java.util.HashMap;
8import java.util.List;
9import java.util.Map;
10
11import org.openstreetmap.josm.command.ChangeCommand;
12import org.openstreetmap.josm.command.Command;
13import org.openstreetmap.josm.command.SequenceCommand;
14import org.openstreetmap.josm.data.osm.DataSet;
15import org.openstreetmap.josm.data.osm.Node;
16import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
17import org.openstreetmap.josm.data.osm.Relation;
18import org.openstreetmap.josm.data.osm.RelationMember;
19import org.openstreetmap.josm.data.osm.Way;
20import org.openstreetmap.josm.gui.MainApplication;
21import org.openstreetmap.josm.tools.Utils;
22
23public class AssociatedStreetFixer extends RelationFixer {
24
25 public AssociatedStreetFixer() {
26 super("associatedStreet");
27 }
28
29 @Override
30 public boolean isRelationGood(Relation rel) {
31 for (RelationMember m : rel.getMembers()) {
32 if (m.getType().equals(OsmPrimitiveType.NODE) && !"house".equals(m.getRole())) {
33 setWarningMessage(tr("Node without ''house'' role found"));
34 return false;
35 }
36 if (m.getType().equals(OsmPrimitiveType.WAY) && !("house".equals(m.getRole()) || "street".equals(m.getRole()))) {
37 setWarningMessage(tr("Way without ''house'' or ''street'' role found"));
38 return false;
39 }
40 if (m.getType().equals(OsmPrimitiveType.RELATION) && !"house".equals(m.getRole())) {
41 setWarningMessage(tr("Relation without ''house'' role found"));
42 return false;
43 }
44 }
45 // relation should have name
46 if (!rel.hasKey("name")) {
47 setWarningMessage(tr("Relation does not have name"));
48 return false;
49 }
50 // check that all street members have same name as relation (???)
51 String streetName = rel.get("name");
52 if (streetName == null) {
53 streetName = "";
54 }
55 for (RelationMember m : rel.getMembers()) {
56 if ("street".equals(m.getRole()) && !streetName.equals(m.getWay().get("name"))) {
57 String anotherName = m.getWay().get("name");
58 if (anotherName != null && !anotherName.isEmpty()) {
59 setWarningMessage(tr("Relation has streets with different names"));
60 return false;
61 }
62 }
63 }
64 clearWarningMessage();
65 return true;
66 }
67
68 @Override
69 public Command fixRelation(Relation source) {
70 // any way with highway tag -> street
71 // any way/point/relation with addr:housenumber=* or building=* or type=multipolygon -> house
72 // name - check which name is most used in street members and add to relation
73 // copy this name to the other street members (???)
74 Relation rel = new Relation(source);
75 boolean fixed = false;
76
77 for (int i = 0; i < rel.getMembersCount(); i++) {
78 RelationMember m = rel.getMember(i);
79
80 if (m.isNode()) {
81 Node node = m.getNode();
82 if (!"house".equals(m.getRole()) &&
83 (node.hasKey("building") || node.hasKey("addr:housenumber"))) {
84 fixed = true;
85 rel.setMember(i, new RelationMember("house", node));
86 }
87 } else if (m.isWay()) {
88 Way way = m.getWay();
89 if (!"street".equals(m.getRole()) && way.hasKey("highway")) {
90 fixed = true;
91 rel.setMember(i, new RelationMember("street", way));
92 } else if (!"house".equals(m.getRole()) &&
93 (way.hasKey("building") || way.hasKey("addr:housenumber"))) {
94 fixed = true;
95 rel.setMember(i, new RelationMember("house", way));
96 }
97 } else if (m.isRelation()) {
98 Relation relation = m.getRelation();
99 if (!"house".equals(m.getRole()) &&
100 (relation.hasKey("building") || relation.hasKey("addr:housenumber") || "multipolygon".equals(relation.get("type")))) {
101 fixed = true;
102 rel.setMember(i, new RelationMember("house", relation));
103 }
104 }
105 }
106
107 // fill relation name
108 Map<String, Integer> streetNames = new HashMap<>();
109 for (RelationMember m : rel.getMembers()) {
110 if ("street".equals(m.getRole()) && m.isWay()) {
111 String name = m.getWay().get("name");
112 if (name == null || name.isEmpty()) {
113 continue;
114 }
115
116 Integer count = streetNames.get(name);
117
118 streetNames.put(name, count != null ? count + 1 : 1);
119 }
120 }
121 String commonName = "";
122 Integer commonCount = 0;
123 for (Map.Entry<String, Integer> entry : streetNames.entrySet()) {
124 if (entry.getValue() > commonCount) {
125 commonCount = entry.getValue();
126 commonName = entry.getKey();
127 }
128 }
129
130 if (!rel.hasKey("name") && !commonName.isEmpty()) {
131 fixed = true;
132 rel.put("name", commonName);
133 } else {
134 commonName = ""; // set empty common name - if we already have name on relation, do not overwrite it
135 }
136
137 List<Command> commandList = new ArrayList<>();
138 if (fixed) {
139 final DataSet ds = Utils.firstNonNull(source.getDataSet(), MainApplication.getLayerManager().getEditDataSet());
140 commandList.add(new ChangeCommand(ds, source, rel));
141 }
142
143 /*if (!commonName.isEmpty())
144 // fill common name to streets
145 for (RelationMember m : rel.getMembers())
146 if ("street".equals(m.getRole()) && m.isWay()) {
147 String name = m.getWay().get("name");
148 if (commonName.equals(name)) continue;
149
150 // TODO: ask user if he really wants to overwrite street name??
151
152 Way oldWay = m.getWay();
153 Way newWay = new Way(oldWay);
154 newWay.put("name", commonName);
155
156 commandList.add(new ChangeCommand(MainApplication.getLayerManager().getEditDataSet(), oldWay, newWay));
157 }
158 */
159 // return results
160 if (commandList.isEmpty()) {
161 return null;
162 }
163 return SequenceCommand.wrapIfNeeded(tr("fix associatedStreet relation"), commandList);
164 }
165}
Note: See TracBrowser for help on using the repository browser.