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

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

findbugs - EQ_DOESNT_OVERRIDE_EQUALS, MS_MUTABLE_COLLECTION_PKGPROTECT

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