source: josm/trunk/src/org/openstreetmap/josm/data/osm/DatasetConsistencyTest.java@ 12494

Last change on this file since 12494 was 11746, checked in by Don-vip, 7 years ago

PMD - Strict Exceptions

  • Property svn:eol-style set to native
File size: 8.4 KB
RevLine 
[2500]1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm;
3
[7500]4import static org.openstreetmap.josm.tools.I18n.tr;
5
[2500]6import java.io.PrintWriter;
7import java.io.StringWriter;
8import java.io.Writer;
9
[7500]10import org.openstreetmap.josm.Main;
[11746]11import org.openstreetmap.josm.tools.JosmRuntimeException;
[7500]12import org.openstreetmap.josm.tools.Utils;
[2500]13
14/**
[7500]15 * This class can be used to run consistency tests on dataset. Any errors found will be written to provided PrintWriter.
[2500]16 * <br>
[7500]17 * Texts here should not be translated because they're not intended for users but for josm developers.
18 * @since 2500
[2500]19 */
20public class DatasetConsistencyTest {
21
[2958]22 private static final int MAX_ERRORS = 100;
[2500]23 private final DataSet dataSet;
24 private final PrintWriter writer;
[2958]25 private int errorCount;
[2500]26
[7500]27 /**
28 * Constructs a new {@code DatasetConsistencyTest}.
29 * @param dataSet The dataset to test
30 * @param writer The writer used to write results
31 */
[2500]32 public DatasetConsistencyTest(DataSet dataSet, Writer writer) {
33 this.dataSet = dataSet;
34 this.writer = new PrintWriter(writer);
35 }
36
[2925]37 private void printError(String type, String message, Object... args) {
[2958]38 errorCount++;
39 if (errorCount <= MAX_ERRORS) {
[8846]40 writer.println('[' + type + "] " + String.format(message, args));
[2958]41 }
[2925]42 }
43
[7500]44 /**
45 * Checks that parent primitive is referred from its child members
46 */
[2958]47 public void checkReferrers() {
[7500]48 long startTime = System.currentTimeMillis();
[3274]49 // It's also error when referred primitive's dataset is null but it's already covered by referredPrimitiveNotInDataset check
[7500]50 for (Way way : dataSet.getWays()) {
[2521]51 if (!way.isDeleted()) {
[7500]52 for (Node n : way.getNodes()) {
[3274]53 if (n.getDataSet() != null && !n.getReferrers().contains(way)) {
[2925]54 printError("WAY NOT IN REFERRERS", "%s is part of %s but is not in referrers", n, way);
[2521]55 }
[2500]56 }
57 }
58 }
59
[7500]60 for (Relation relation : dataSet.getRelations()) {
[2521]61 if (!relation.isDeleted()) {
[7500]62 for (RelationMember m : relation.getMembers()) {
[3274]63 if (m.getMember().getDataSet() != null && !m.getMember().getReferrers().contains(relation)) {
[2925]64 printError("RELATION NOT IN REFERRERS", "%s is part of %s but is not in referrers", m.getMember(), relation);
[2521]65 }
[2500]66 }
67 }
68 }
[7500]69 printElapsedTime(startTime);
[2500]70 }
71
[7500]72 /**
73 * Checks for womplete ways with incomplete nodes.
74 */
[2958]75 public void checkCompleteWaysWithIncompleteNodes() {
[7500]76 long startTime = System.currentTimeMillis();
77 for (Way way : dataSet.getWays()) {
[2594]78 if (way.isUsable()) {
[7500]79 for (Node node : way.getNodes()) {
[2578]80 if (node.isIncomplete()) {
[2925]81 printError("USABLE HAS INCOMPLETE", "%s is usable but contains incomplete node '%s'", way, node);
[2500]82 }
83 }
84 }
85 }
[7500]86 printElapsedTime(startTime);
[2500]87 }
88
[7500]89 /**
90 * Checks for complete nodes without coordinates.
91 */
[2958]92 public void checkCompleteNodesWithoutCoordinates() {
[7500]93 long startTime = System.currentTimeMillis();
94 for (Node node : dataSet.getNodes()) {
[7828]95 if (!node.isIncomplete() && node.isVisible() && !node.isLatLonKnown()) {
[2925]96 printError("COMPLETE WITHOUT COORDINATES", "%s is not incomplete but has null coordinates", node);
[2500]97 }
98 }
[7500]99 printElapsedTime(startTime);
[2500]100 }
101
[7500]102 /**
103 * Checks that nodes can be retrieved through their coordinates.
104 */
[2958]105 public void searchNodes() {
[7500]106 long startTime = System.currentTimeMillis();
[7501]107 dataSet.getReadLock().lock();
108 try {
109 for (Node n : dataSet.getNodes()) {
110 // Call isDrawable() as an efficient replacement to previous checks (!deleted, !incomplete, getCoor() != null)
111 if (n.isDrawable() && !dataSet.containsNode(n)) {
[7502]112 printError("SEARCH NODES", "%s not found using Dataset.containsNode()", n);
[2500]113 }
114 }
[7501]115 } finally {
116 dataSet.getReadLock().unlock();
[2500]117 }
[7500]118 printElapsedTime(startTime);
[2500]119 }
120
[7500]121 /**
122 * Checks that ways can be retrieved through their bounding box.
123 */
[2958]124 public void searchWays() {
[7500]125 long startTime = System.currentTimeMillis();
[7501]126 dataSet.getReadLock().lock();
127 try {
128 for (Way w : dataSet.getWays()) {
129 if (!w.isIncomplete() && !w.isDeleted() && w.getNodesCount() >= 2 && !dataSet.containsWay(w)) {
[7502]130 printError("SEARCH WAYS", "%s not found using Dataset.containsWay()", w);
[7501]131 }
[2500]132 }
[7501]133 } finally {
134 dataSet.getReadLock().unlock();
[2500]135 }
[7500]136 printElapsedTime(startTime);
[2500]137 }
138
[2501]139 private void checkReferredPrimitive(OsmPrimitive primitive, OsmPrimitive parent) {
[3274]140 if (primitive.getDataSet() == null) {
141 printError("NO DATASET", "%s is referenced by %s but not found in dataset", primitive, parent);
142 } else if (dataSet.getPrimitiveById(primitive) == null) {
[2925]143 printError("REFERENCED BUT NOT IN DATA", "%s is referenced by %s but not found in dataset", primitive, parent);
[10378]144 } else if (dataSet.getPrimitiveById(primitive) != primitive) {
[2925]145 printError("DIFFERENT INSTANCE", "%s is different instance that referred by %s", primitive, parent);
[2501]146 }
[3274]147
[2501]148 if (primitive.isDeleted()) {
[2925]149 printError("DELETED REFERENCED", "%s refers to deleted primitive %s", parent, primitive);
[2501]150 }
151 }
152
[7500]153 /**
154 * Checks that referred primitives are present in dataset.
155 */
[2958]156 public void referredPrimitiveNotInDataset() {
[7500]157 long startTime = System.currentTimeMillis();
158 for (Way way : dataSet.getWays()) {
159 for (Node node : way.getNodes()) {
[2501]160 checkReferredPrimitive(node, way);
161 }
162 }
163
[7500]164 for (Relation relation : dataSet.getRelations()) {
165 for (RelationMember member : relation.getMembers()) {
[2501]166 checkReferredPrimitive(member.getMember(), relation);
167 }
168 }
[7500]169 printElapsedTime(startTime);
[2501]170 }
171
[7500]172 /**
173 * Checks for zero and one-node ways.
174 */
[2958]175 public void checkZeroNodesWays() {
[7500]176 long startTime = System.currentTimeMillis();
177 for (Way way : dataSet.getWays()) {
[3336]178 if (way.isUsable() && way.getNodesCount() == 0) {
[2925]179 printError("WARN - ZERO NODES", "Way %s has zero nodes", way);
[2527]180 } else if (way.isUsable() && way.getNodesCount() == 1) {
[2925]181 printError("WARN - NO NODES", "Way %s has only one node", way);
[2527]182 }
183 }
[7500]184 printElapsedTime(startTime);
[2527]185 }
186
[7500]187 private void printElapsedTime(long startTime) {
188 if (Main.isDebugEnabled()) {
189 StackTraceElement item = Thread.currentThread().getStackTrace()[2];
[8846]190 String operation = getClass().getSimpleName() + '.' + item.getMethodName();
[7500]191 long elapsedTime = System.currentTimeMillis() - startTime;
192 Main.debug(tr("Test ''{0}'' completed in {1}",
193 operation, Utils.getDurationString(elapsedTime)));
194 }
195 }
196
197 /**
198 * Runs test.
199 */
[2500]200 public void runTest() {
[2501]201 try {
[7500]202 long startTime = System.currentTimeMillis();
[3274]203 referredPrimitiveNotInDataset();
[2501]204 checkReferrers();
205 checkCompleteWaysWithIncompleteNodes();
206 checkCompleteNodesWithoutCoordinates();
207 searchNodes();
208 searchWays();
[2527]209 checkZeroNodesWays();
[7500]210 printElapsedTime(startTime);
[2958]211 if (errorCount > MAX_ERRORS) {
212 writer.println((errorCount - MAX_ERRORS) + " more...");
213 }
[7500]214
[11746]215 } catch (JosmRuntimeException | IllegalArgumentException | IllegalStateException e) {
[2501]216 writer.println("Exception during dataset integrity test:");
217 e.printStackTrace(writer);
[10627]218 Main.warn(e);
[2501]219 }
[2500]220 }
221
[7500]222 /**
223 * Runs test on the given dataset.
224 * @param dataSet the dataset to test
225 * @return the errors as string
226 */
[2500]227 public static String runTests(DataSet dataSet) {
228 StringWriter writer = new StringWriter();
229 new DatasetConsistencyTest(dataSet, writer).runTest();
230 return writer.toString();
231 }
232}
Note: See TracBrowser for help on using the repository browser.