diff --git a/src/main/java/com/github/fge/jsonschema/format/common/DateAttribute.java b/src/main/java/com/github/fge/jsonschema/format/common/DateAttribute.java new file mode 100644 index 000000000..31073d946 --- /dev/null +++ b/src/main/java/com/github/fge/jsonschema/format/common/DateAttribute.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com) + * + * This software is dual-licensed under: + * + * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any + * later version; + * - the Apache Software License (ASL) version 2.0. + * + * The text of this file and of both licenses is available at the root of this + * project or, if you have the jar distribution, in directory META-INF/, under + * the names LGPL-3.0.txt and ASL-2.0.txt respectively. + * + * Direct link to the sources: + * + * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt + * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt + */ + +package com.github.fge.jsonschema.format.common; + +import static org.joda.time.DateTimeFieldType.dayOfMonth; +import static org.joda.time.DateTimeFieldType.monthOfYear; +import static org.joda.time.DateTimeFieldType.year; + +import com.github.fge.jackson.NodeType; +import com.github.fge.jsonschema.core.exceptions.ProcessingException; +import com.github.fge.jsonschema.core.report.ProcessingReport; +import com.github.fge.jsonschema.format.AbstractFormatAttribute; +import com.github.fge.jsonschema.format.FormatAttribute; +import com.github.fge.jsonschema.processors.data.FullData; +import com.github.fge.msgsimple.bundle.MessageBundle; +import com.google.common.collect.ImmutableList; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.DateTimeFormatterBuilder; + +import java.util.List; + +/** + * Validator for the {@code date} format attribute + */ +public final class DateAttribute + extends AbstractFormatAttribute +{ + private static final List FORMATS = ImmutableList.of( + "yyyy-MM-dd" + ); + private static final DateTimeFormatter FORMATTER; + + static { + + DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder() + .appendFixedDecimal(year(), 4) + .appendLiteral('-') + .appendFixedDecimal(monthOfYear(), 2) + .appendLiteral('-') + .appendFixedDecimal(dayOfMonth(), 2); + + FORMATTER = builder.toFormatter(); + } + + private static final FormatAttribute INSTANCE = new DateAttribute(); + + public static FormatAttribute getInstance() + { + return INSTANCE; + } + + private DateAttribute() + { + super("date", NodeType.STRING); + } + + @Override + public void validate(final ProcessingReport report, + final MessageBundle bundle, final FullData data) + throws ProcessingException + { + final String value = data.getInstance().getNode().textValue(); + + try { + FORMATTER.parseDateTime(value); + } catch (IllegalArgumentException ignored) { + report.error(newMsg(data, bundle, "err.format.invalidDate") + .putArgument("value", value).putArgument("expected", FORMATS)); + } + } +} diff --git a/src/main/java/com/github/fge/jsonschema/library/format/CommonFormatAttributesDictionary.java b/src/main/java/com/github/fge/jsonschema/library/format/CommonFormatAttributesDictionary.java index 97e9d884b..0b80856db 100644 --- a/src/main/java/com/github/fge/jsonschema/library/format/CommonFormatAttributesDictionary.java +++ b/src/main/java/com/github/fge/jsonschema/library/format/CommonFormatAttributesDictionary.java @@ -22,6 +22,7 @@ import com.github.fge.jsonschema.core.util.Dictionary; import com.github.fge.jsonschema.core.util.DictionaryBuilder; import com.github.fge.jsonschema.format.FormatAttribute; +import com.github.fge.jsonschema.format.common.DateAttribute; import com.github.fge.jsonschema.format.common.EmailAttribute; import com.github.fge.jsonschema.format.common.IPv6Attribute; import com.github.fge.jsonschema.format.common.RFC3339DateTimeAttribute; @@ -52,6 +53,10 @@ private CommonFormatAttributesDictionary() attribute = RFC3339DateTimeAttribute.getInstance(); builder.addEntry(name, attribute); + name = "date"; + attribute = DateAttribute.getInstance(); + builder.addEntry(name, attribute); + name = "email"; attribute = EmailAttribute.getInstance(); builder.addEntry(name, attribute); diff --git a/src/test/java/com/github/fge/jsonschema/format/common/DateTest.java b/src/test/java/com/github/fge/jsonschema/format/common/DateTest.java new file mode 100644 index 000000000..aed31bca8 --- /dev/null +++ b/src/test/java/com/github/fge/jsonschema/format/common/DateTest.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2014, Francis Galiegue (fgaliegue@gmail.com) + * + * This software is dual-licensed under: + * + * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any + * later version; + * - the Apache Software License (ASL) version 2.0. + * + * The text of this file and of both licenses is available at the root of this + * project or, if you have the jar distribution, in directory META-INF/, under + * the names LGPL-3.0.txt and ASL-2.0.txt respectively. + * + * Direct link to the sources: + * + * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt + * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt + */ + +package com.github.fge.jsonschema.format.common; + +import java.io.IOException; + +public final class DateTest + extends CommonFormatAttributeTest +{ + public DateTest() + throws IOException + { + super("date"); + } +} diff --git a/src/test/resources/format/common/date.json b/src/test/resources/format/common/date.json new file mode 100644 index 000000000..d2b6ef717 --- /dev/null +++ b/src/test/resources/format/common/date.json @@ -0,0 +1,80 @@ +[ + { + "data": "2012-12-02", + "valid": true + }, + { + "data": "2001-01-12", + "valid": true + }, + { + "data": "2012", + "valid": false, + "message": "err.format.invalidDate", + "msgData": { + "value": "2012", + "expected": [ "yyyy-MM-dd" ] + }, + "msgParams": [ "value", "expected" ] + }, + { + "data": "2012-01", + "valid": false, + "message": "err.format.invalidDate", + "msgData": { + "value": "2012-01", + "expected": [ "yyyy-MM-dd" ] + }, + "msgParams": [ "value", "expected" ] + }, + { + "data": "2012-01-32", + "valid": false, + "message": "err.format.invalidDate", + "msgData": { + "value": "2012-01-32", + "expected": [ "yyyy-MM-dd" ] + }, + "msgParams": [ "value", "expected" ] + }, + { + "data": "2012-09-31", + "valid": false, + "message": "err.format.invalidDate", + "msgData": { + "value": "2012-09-31", + "expected": [ "yyyy-MM-dd" ] + }, + "msgParams": [ "value", "expected" ] + }, + { + "data": "201202030", + "valid": false, + "message": "err.format.invalidDate", + "msgData": { + "value": "201202030", + "expected": [ "yyyy-MM-dd" ] + }, + "msgParams": [ "value", "expected" ] + }, + { + "data": "2012-12-02T13:05:00+0100", + "valid": false, + "message": "err.format.invalidDate", + "msgData": { + "value": "2012-12-02T13:05:00+0100", + "expected": [ "yyyy-MM-dd" ] + }, + "msgParams": [ "value", "expected" ] + }, + { + "data": "a", + "valid": false, + "message": "err.format.invalidDate", + "msgData": { + "value": "a", + "expected": [ "yyyy-MM-dd" ] + }, + "msgParams": [ "value", "expected" ] + } +]