// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.data.validation.tests; import static org.openstreetmap.josm.tools.I18n.marktr; import static org.openstreetmap.josm.tools.I18n.tr; import org.openstreetmap.josm.data.osm.Node; import org.openstreetmap.josm.data.osm.OsmPrimitive; import org.openstreetmap.josm.data.osm.Relation; import org.openstreetmap.josm.data.osm.Way; import org.openstreetmap.josm.data.validation.Severity; import org.openstreetmap.josm.data.validation.Test; import org.openstreetmap.josm.data.validation.TestError; import org.openstreetmap.josm.data.validation.routines.AbstractValidator; import org.openstreetmap.josm.data.validation.routines.EmailValidator; import org.openstreetmap.josm.data.validation.routines.UrlValidator; /** * Performs validation tests on internet-related tags (websites, e-mail addresses, etc.). * @since 7489 */ public class InternetTags extends Test { /** Error code for an invalid URL */ public static final int INVALID_URL = 3301; /** Error code for an invalid e-mail */ public static final int INVALID_EMAIL = 3302; /** * List of keys subject to URL validation. */ private static String[] URL_KEYS = new String[] { "url", "source:url", "website", "contact:website", "heritage:website", "source:website" }; /** * List of keys subject to email validation. */ private static String[] EMAIL_KEYS = new String[] { "email", "contact:email" }; /** * Constructs a new {@code InternetTags} test. */ public InternetTags() { super(tr("Internet tags"), tr("Checks for errors in internet-related tags.")); } /** * Potentially validates a given primitive key against a given validator. * @param p The OSM primitive to test * @param k The key to validate * @param keys The list of keys to check. If {@code k} is not inside this collection, do nothing * @param validator The validator to run if {@code k} is inside {@code keys} * @param code The error code to set if the validation fails * @return {@code true} if the validation fails. In this case, a new error has been created. */ private boolean doTest(OsmPrimitive p, String k, String[] keys, AbstractValidator validator, int code) { for (String i : keys) { if (i.equals(k)) { TestError error = validateTag(p, k, validator, code); if (error != null) { errors.add(error); } break; } } return false; } /** * Validates a given primitive tag against a given validator. * @param p The OSM primitive to test * @param k The key to validate * @param validator The validator to run * @param code The error code to set if the validation fails * @return The error if the validation fails, {@code null} otherwise * @since 7824 */ public TestError validateTag(OsmPrimitive p, String k, AbstractValidator validator, int code) { return doValidateTag(p, k, null, validator, code); } /** * Validates a given primitive tag against a given validator. * @param p The OSM primitive to test * @param k The key to validate * @param v The value to validate. May be {@code null} to use {@code p.get(k)} * @param validator The validator to run * @param code The error code to set if the validation fails * @return The error if the validation fails, {@code null} otherwise */ private TestError doValidateTag(OsmPrimitive p, String k, String v, AbstractValidator validator, int code) { TestError error = null; String value = v != null ? v : p.get(k); if (!validator.isValid(value)) { String errMsg = validator.getErrorMessage(); // Special treatment to allow URLs without protocol. See UrlValidator#isValid if (tr("URL contains an invalid protocol: {0}", (String) null).equals(errMsg)) { String proto = validator instanceof EmailValidator ? "mailto://" : "http://"; return doValidateTag(p, k, proto+value, validator, code); } error = TestError.builder(this, Severity.WARNING, code) .message(validator.getValidatorName(), marktr("''{0}'': {1}"), k, errMsg) .primitives(p) .build(); } return error; } private void test(OsmPrimitive p) { for (String k : p.keySet()) { // Test key against URL validator if (!doTest(p, k, URL_KEYS, UrlValidator.getInstance(), INVALID_URL)) { // Test key against e-mail validator only if the URL validator did not fail doTest(p, k, EMAIL_KEYS, EmailValidator.getInstance(), INVALID_EMAIL); } } } @Override public void visit(Node n) { test(n); } @Override public void visit(Way w) { test(w); } @Override public void visit(Relation r) { test(r); } }