// 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);
}
}