001 // License: GPL. See LICENSE file for details.
002 package org.openstreetmap.josm.data.validation.tests;
003
004 import static org.openstreetmap.josm.tools.I18n.marktr;
005 import static org.openstreetmap.josm.tools.I18n.tr;
006
007 import java.util.Collection;
008 import java.util.Map;
009
010 import org.openstreetmap.josm.command.Command;
011 import org.openstreetmap.josm.data.osm.Node;
012 import org.openstreetmap.josm.data.osm.OsmPrimitive;
013 import org.openstreetmap.josm.data.validation.Severity;
014 import org.openstreetmap.josm.data.validation.Test;
015 import org.openstreetmap.josm.data.validation.TestError;
016 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
017
018 /**
019 * Checks for nodes with uninteresting tags that are in no way
020 *
021 * @author frsantos
022 */
023 public class UntaggedNode extends Test {
024
025 protected static final int UNTAGGED_NODE_BLANK = 201;
026 protected static final int UNTAGGED_NODE_FIXME = 202;
027 protected static final int UNTAGGED_NODE_NOTE = 203;
028 protected static final int UNTAGGED_NODE_CREATED_BY = 204;
029 protected static final int UNTAGGED_NODE_WATCH = 205;
030 protected static final int UNTAGGED_NODE_SOURCE = 206;
031 protected static final int UNTAGGED_NODE_OTHER = 207;
032
033 /**
034 * Constructor
035 */
036 public UntaggedNode() {
037 super(tr("Untagged and unconnected nodes"),
038 tr("This test checks for untagged nodes that are not part of any way."));
039 }
040
041 @Override
042 public void startTest(ProgressMonitor monitor) {
043 super.startTest(monitor);
044 }
045
046 @Override
047 public void visit(Collection<OsmPrimitive> selection) {
048 for (OsmPrimitive p : selection) {
049 if (p.isUsable() && p instanceof Node) {
050 p.visit(this);
051 }
052 }
053 }
054
055 @Override
056 public void visit(Node n) {
057 if(n.isUsable() && !n.isTagged() && n.getReferrers().isEmpty()) {
058 if (!n.hasKeys()) {
059 String msg = marktr("No tags");
060 errors.add(new TestError(this, Severity.WARNING, tr("Unconnected nodes without physical tags"), tr(msg), msg, UNTAGGED_NODE_BLANK, n));
061 return;
062 }
063 for (Map.Entry<String, String> tag : n.getKeys().entrySet()) {
064 String key = tag.getKey();
065 if (contains(tag, "fixme") || contains(tag, "FIXME")) {
066 /* translation note: don't translate quoted words */
067 String msg = marktr("Has tag containing ''fixme'' or ''FIXME''");
068 errors.add(new TestError(this, Severity.WARNING, tr("Unconnected nodes without physical tags"),
069 tr(msg), msg, UNTAGGED_NODE_FIXME, n));
070 return;
071 }
072
073 String msg = null;
074 int code = 0;
075 if (key.startsWith("note") || key.startsWith("comment") || key.startsWith("description")) {
076 /* translation note: don't translate quoted words */
077 msg = marktr("Has key ''note'' or ''comment'' or ''description''");
078 code = UNTAGGED_NODE_NOTE;
079 } else if (key.startsWith("created_by") || key.startsWith("converted_by")) {
080 /* translation note: don't translate quoted words */
081 msg = marktr("Has key ''created_by'' or ''converted_by''");
082 code = UNTAGGED_NODE_CREATED_BY;
083 } else if (key.startsWith("watch")) {
084 /* translation note: don't translate quoted words */
085 msg = marktr("Has key ''watch''");
086 code = UNTAGGED_NODE_WATCH;
087 } else if (key.startsWith("source")) {
088 /* translation note: don't translate quoted words */
089 msg = marktr("Has key ''source''");
090 code = UNTAGGED_NODE_SOURCE;
091 }
092 if (msg != null) {
093 errors.add(new TestError(this, Severity.WARNING, tr("Unconnected nodes without physical tags"),
094 tr(msg), msg, code, n));
095 return;
096 }
097 }
098 // Does not happen, but just to be sure. Maybe definition of uninteresting tags changes in future.
099 errors.add(new TestError(this, Severity.WARNING, tr("Unconnected nodes without physical tags"),
100 tr("Other"), "Other", UNTAGGED_NODE_OTHER, n));
101 }
102 }
103
104 private boolean contains(Map.Entry<String, String> tag, String s) {
105 return tag.getKey().indexOf(s) != -1 || tag.getValue().indexOf(s) != -1;
106 }
107
108 @Override
109 public Command fixError(TestError testError) {
110 return deletePrimitivesIfNeeded(testError.getPrimitives());
111 }
112
113 @Override
114 public boolean isFixable(TestError testError) {
115 if (testError.getTester() instanceof UntaggedNode) {
116 int code = testError.getCode();
117 switch (code) {
118 case UNTAGGED_NODE_BLANK:
119 case UNTAGGED_NODE_CREATED_BY:
120 case UNTAGGED_NODE_WATCH:
121 case UNTAGGED_NODE_SOURCE:
122 return true;
123 }
124 }
125 return false;
126 }
127 }