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