source: josm/trunk/src/org/openstreetmap/josm/data/validation/tests/PowerLines.java@ 10234

Last change on this file since 10234 was 10234, checked in by Don-vip, 8 years ago

findbugs - DB_DUPLICATE_SWITCH_CLAUSES + REC_CATCH_EXCEPTION + UC_USELESS_CONDITION + OS_OPEN_STREAM_EXCEPTION_PATH + ICAST_INTEGER_MULTIPLY_CAST_TO_LONG

  • Property svn:eol-style set to native
File size: 8.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.validation.tests;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.ArrayList;
7import java.util.Arrays;
8import java.util.Collection;
9import java.util.HashMap;
10import java.util.Iterator;
11import java.util.List;
12import java.util.Map;
13
14import org.openstreetmap.josm.Main;
15import org.openstreetmap.josm.command.ChangePropertyCommand;
16import org.openstreetmap.josm.command.Command;
17import org.openstreetmap.josm.data.osm.Node;
18import org.openstreetmap.josm.data.osm.OsmPrimitive;
19import org.openstreetmap.josm.data.osm.Relation;
20import org.openstreetmap.josm.data.osm.Way;
21import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon;
22import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.JoinedWay;
23import org.openstreetmap.josm.data.osm.visitor.paint.relations.MultipolygonCache;
24import org.openstreetmap.josm.data.validation.Severity;
25import org.openstreetmap.josm.data.validation.Test;
26import org.openstreetmap.josm.data.validation.TestError;
27import org.openstreetmap.josm.gui.progress.ProgressMonitor;
28import org.openstreetmap.josm.tools.Geometry;
29
30/**
31 * Checks for nodes in power lines/minor_lines that do not have a power=tower/pole tag.<br>
32 * See #7812 for discussions about this test.
33 */
34public class PowerLines extends Test {
35
36 protected static final int POWER_LINES = 2501;
37
38 /** Values for {@code power} key interpreted as power lines */
39 protected static final Collection<String> POWER_LINE_TAGS = Arrays.asList("line", "minor_line");
40 /** Values for {@code power} key interpreted as power towers */
41 protected static final Collection<String> POWER_TOWER_TAGS = Arrays.asList("tower", "pole");
42 /** Values for {@code power} key interpreted as power stations */
43 protected static final Collection<String> POWER_STATION_TAGS = Arrays.asList("station", "sub_station", "substation", "plant", "generator");
44 /** Values for {@code power} key interpreted as allowed power items */
45 protected static final Collection<String> POWER_ALLOWED_TAGS = Arrays.asList("switch", "transformer", "busbar", "generator", "switchgear",
46 "portal", "terminal", "insulator");
47
48 private final Map<Way, String> towerPoleTagMap = new HashMap<>();
49
50 private final List<PowerLineError> potentialErrors = new ArrayList<>();
51
52 private final List<OsmPrimitive> powerStations = new ArrayList<>();
53
54 /**
55 * Constructs a new {@code PowerLines} test.
56 */
57 public PowerLines() {
58 super(tr("Power lines"), tr("Checks for nodes in power lines that do not have a power=tower/pole tag."));
59 }
60
61 @Override
62 public void visit(Way w) {
63 if (w.isUsable()) {
64 if (isPowerLine(w) && !w.hasTag("location", "underground")) {
65 String fixValue = null;
66 boolean erroneous = false;
67 boolean canFix = false;
68 for (Node n : w.getNodes()) {
69 if (!isPowerTower(n)) {
70 if (!isPowerAllowed(n) && IN_DOWNLOADED_AREA.evaluate(n)) {
71 if (!w.isFirstLastNode(n) || !isPowerStation(n)) {
72 potentialErrors.add(new PowerLineError(this, n, w));
73 erroneous = true;
74 }
75 }
76 } else if (fixValue == null) {
77 // First tower/pole tag found, remember it
78 fixValue = n.get("power");
79 canFix = true;
80 } else if (!fixValue.equals(n.get("power"))) {
81 // The power line contains both "tower" and "pole" -> cannot fix this error
82 canFix = false;
83 }
84 }
85 if (erroneous && canFix) {
86 towerPoleTagMap.put(w, fixValue);
87 }
88 } else if (w.isClosed() && isPowerStation(w)) {
89 powerStations.add(w);
90 }
91 }
92 }
93
94 @Override
95 public void visit(Relation r) {
96 if (r.isMultipolygon() && isPowerStation(r)) {
97 powerStations.add(r);
98 }
99 }
100
101 @Override
102 public void startTest(ProgressMonitor progressMonitor) {
103 super.startTest(progressMonitor);
104 towerPoleTagMap.clear();
105 powerStations.clear();
106 potentialErrors.clear();
107 }
108
109 @Override
110 public void endTest() {
111 for (PowerLineError e : potentialErrors) {
112 Node n = e.getNode();
113 if (n != null && !isInPowerStation(n)) {
114 errors.add(e);
115 }
116 }
117 potentialErrors.clear();
118 super.endTest();
119 }
120
121 protected final boolean isInPowerStation(Node n) {
122 for (OsmPrimitive station : powerStations) {
123 List<List<Node>> nodesLists = new ArrayList<>();
124 if (station instanceof Way) {
125 nodesLists.add(((Way) station).getNodes());
126 } else if (station instanceof Relation) {
127 Multipolygon polygon = MultipolygonCache.getInstance().get(Main.map.mapView, (Relation) station);
128 if (polygon != null) {
129 for (JoinedWay outer : Multipolygon.joinWays(polygon.getOuterWays())) {
130 nodesLists.add(outer.getNodes());
131 }
132 }
133 }
134 for (List<Node> nodes : nodesLists) {
135 if (Geometry.nodeInsidePolygon(n, nodes)) {
136 return true;
137 }
138 }
139 }
140 return false;
141 }
142
143 @Override
144 public Command fixError(TestError testError) {
145 if (testError instanceof PowerLineError && isFixable(testError)) {
146 // primitives list can be empty if all primitives have been purged
147 Iterator<? extends OsmPrimitive> it = testError.getPrimitives().iterator();
148 if (it.hasNext()) {
149 return new ChangePropertyCommand(it.next(),
150 "power", towerPoleTagMap.get(((PowerLineError) testError).line));
151 }
152 }
153 return null;
154 }
155
156 @Override
157 public boolean isFixable(TestError testError) {
158 return testError instanceof PowerLineError && towerPoleTagMap.containsKey(((PowerLineError) testError).line);
159 }
160
161 /**
162 * Determines if the specified way denotes a power line.
163 * @param w The way to be tested
164 * @return {@code true} if power key is set and equal to line/minor_line
165 */
166 protected static final boolean isPowerLine(Way w) {
167 return isPowerIn(w, POWER_LINE_TAGS);
168 }
169
170 /**
171 * Determines if the specified primitive denotes a power station.
172 * @param p The primitive to be tested
173 * @return {@code true} if power key is set and equal to station/sub_station/plant
174 */
175 protected static final boolean isPowerStation(OsmPrimitive p) {
176 return isPowerIn(p, POWER_STATION_TAGS);
177 }
178
179 /**
180 * Determines if the specified node denotes a power tower/pole.
181 * @param n The node to be tested
182 * @return {@code true} if power key is set and equal to tower/pole
183 */
184 protected static final boolean isPowerTower(Node n) {
185 return isPowerIn(n, POWER_TOWER_TAGS);
186 }
187
188 /**
189 * Determines if the specified node denotes a power infrastructure allowed on a power line.
190 * @param n The node to be tested
191 * @return True if power key is set and equal to switch/tranformer/busbar/generator
192 */
193 protected static final boolean isPowerAllowed(Node n) {
194 return isPowerIn(n, POWER_ALLOWED_TAGS);
195 }
196
197 /**
198 * Helper function to check if power tags is a certain value.
199 * @param p The primitive to be tested
200 * @param values List of possible values
201 * @return {@code true} if power key is set and equal to possible values
202 */
203 private static boolean isPowerIn(OsmPrimitive p, Collection<String> values) {
204 String v = p.get("power");
205 return v != null && values != null && values.contains(v);
206 }
207
208 protected static class PowerLineError extends TestError {
209 private final Way line;
210
211 public PowerLineError(PowerLines tester, Node n, Way line) {
212 super(tester, Severity.WARNING,
213 tr("Missing power tower/pole within power line"), POWER_LINES, n);
214 this.line = line;
215 }
216
217 public final Node getNode() {
218 // primitives list can be empty if all primitives have been purged
219 Iterator<? extends OsmPrimitive> it = getPrimitives().iterator();
220 return it.hasNext() ? (Node) it.next() : null;
221 }
222 }
223}
Note: See TracBrowser for help on using the repository browser.