source: josm/trunk/src/org/openstreetmap/josm/data/validation/tests/InternetTags.java@ 14468

Last change on this file since 14468 was 13489, checked in by Don-vip, 6 years ago

fix #16044 - Autofix invalid URL with the wrong type of slashes

  • Property svn:eol-style set to native
File size: 5.7 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.marktr;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.util.function.Supplier;
8
9import org.openstreetmap.josm.command.ChangePropertyCommand;
10import org.openstreetmap.josm.command.Command;
11import org.openstreetmap.josm.data.osm.Node;
12import org.openstreetmap.josm.data.osm.OsmPrimitive;
13import org.openstreetmap.josm.data.osm.Relation;
14import org.openstreetmap.josm.data.osm.Way;
15import org.openstreetmap.josm.data.validation.Severity;
16import org.openstreetmap.josm.data.validation.Test;
17import org.openstreetmap.josm.data.validation.TestError;
18import org.openstreetmap.josm.data.validation.routines.AbstractValidator;
19import org.openstreetmap.josm.data.validation.routines.EmailValidator;
20import org.openstreetmap.josm.data.validation.routines.UrlValidator;
21
22/**
23 * Performs validation tests on internet-related tags (websites, e-mail addresses, etc.).
24 * @since 7489
25 */
26public class InternetTags extends Test {
27
28 /** Error code for an invalid URL */
29 public static final int INVALID_URL = 3301;
30 /** Error code for an invalid e-mail */
31 public static final int INVALID_EMAIL = 3302;
32
33 /**
34 * List of keys subject to URL validation.
35 */
36 private static final String[] URL_KEYS = new String[] {
37 "url", "source:url",
38 "website", "contact:website", "heritage:website", "source:website"
39 };
40
41 /**
42 * List of keys subject to email validation.
43 */
44 private static final String[] EMAIL_KEYS = new String[] {
45 "email", "contact:email"
46 };
47
48 /**
49 * Constructs a new {@code InternetTags} test.
50 */
51 public InternetTags() {
52 super(tr("Internet tags"), tr("Checks for errors in internet-related tags."));
53 }
54
55 /**
56 * Potentially validates a given primitive key against a given validator.
57 * @param p The OSM primitive to test
58 * @param k The key to validate
59 * @param keys The list of keys to check. If {@code k} is not inside this collection, do nothing
60 * @param validator The validator to run if {@code k} is inside {@code keys}
61 * @param code The error code to set if the validation fails
62 * @return {@code true} if the validation fails. In this case, a new error has been created.
63 */
64 private boolean doTest(OsmPrimitive p, String k, String[] keys, AbstractValidator validator, int code) {
65 for (String i : keys) {
66 if (i.equals(k)) {
67 TestError error = validateTag(p, k, validator, code);
68 if (error != null) {
69 errors.add(error);
70 }
71 break;
72 }
73 }
74 return false;
75 }
76
77 /**
78 * Validates a given primitive tag against a given validator.
79 * @param p The OSM primitive to test
80 * @param k The key to validate
81 * @param validator The validator to run
82 * @param code The error code to set if the validation fails
83 * @return The error if the validation fails, {@code null} otherwise
84 * @since 7824
85 */
86 public TestError validateTag(OsmPrimitive p, String k, AbstractValidator validator, int code) {
87 return doValidateTag(p, k, null, validator, code);
88 }
89
90 /**
91 * Validates a given primitive tag against a given validator.
92 * @param p The OSM primitive to test
93 * @param k The key to validate
94 * @param v The value to validate. May be {@code null} to use {@code p.get(k)}
95 * @param validator The validator to run
96 * @param code The error code to set if the validation fails
97 * @return The error if the validation fails, {@code null} otherwise
98 */
99 private TestError doValidateTag(OsmPrimitive p, String k, String v, AbstractValidator validator, int code) {
100 TestError error = null;
101 String value = v != null ? v : p.get(k);
102 if (!validator.isValid(value)) {
103 Supplier<Command> fix = null;
104 String errMsg = validator.getErrorMessage();
105 if (tr("URL contains an invalid protocol: {0}", (String) null).equals(errMsg)) {
106 // Special treatment to allow URLs without protocol. See UrlValidator#isValid
107 String proto = validator instanceof EmailValidator ? "mailto://" : "http://";
108 return doValidateTag(p, k, proto+value, validator, code);
109 } else if (tr("URL contains an invalid authority: {0}", (String) null).equals(errMsg)
110 && value.contains("\\") && validator.isValid(value.replaceAll("\\\\", "/"))) {
111 // Special treatment to autofix URLs with backslashes. See UrlValidator#isValid
112 errMsg = tr("URL contains backslashes instead of slashes");
113 fix = () -> new ChangePropertyCommand(p, k, value.replaceAll("\\\\", "/"));
114 }
115 error = TestError.builder(this, Severity.WARNING, code)
116 .message(validator.getValidatorName(), marktr("''{0}'': {1}"), k, errMsg)
117 .primitives(p)
118 .fix(fix)
119 .build();
120 }
121 return error;
122 }
123
124 private void test(OsmPrimitive p) {
125 for (String k : p.keySet()) {
126 // Test key against URL validator
127 if (!doTest(p, k, URL_KEYS, UrlValidator.getInstance(), INVALID_URL)) {
128 // Test key against e-mail validator only if the URL validator did not fail
129 doTest(p, k, EMAIL_KEYS, EmailValidator.getInstance(), INVALID_EMAIL);
130 }
131 }
132 }
133
134 @Override
135 public void visit(Node n) {
136 test(n);
137 }
138
139 @Override
140 public void visit(Way w) {
141 test(w);
142 }
143
144 @Override
145 public void visit(Relation r) {
146 test(r);
147 }
148}
Note: See TracBrowser for help on using the repository browser.