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 }