Skip to content

Commit fcf0bf8

Browse files
committed
Added DateTimeValidator
1 parent 4a0c830 commit fcf0bf8

File tree

4 files changed

+285
-151
lines changed

4 files changed

+285
-151
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright (c) 2016 Network New Technologies Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.networknt.schema;
18+
19+
import com.fasterxml.jackson.databind.JsonNode;
20+
import org.slf4j.Logger;
21+
import org.slf4j.LoggerFactory;
22+
23+
import java.text.ParsePosition;
24+
import java.text.SimpleDateFormat;
25+
import java.util.Collections;
26+
import java.util.LinkedHashSet;
27+
import java.util.Set;
28+
import java.util.regex.PatternSyntaxException;
29+
30+
public class DateTimeValidator extends BaseJsonValidator implements JsonValidator {
31+
private static final Logger logger = LoggerFactory.getLogger(DateTimeValidator.class);
32+
33+
private final String DATE = "date";
34+
private final String DATE_TIME = "date-time";
35+
36+
private final String formatName;
37+
private final Format format;
38+
39+
public DateTimeValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext, String formatName, Format format) {
40+
super(schemaPath, schemaNode, parentSchema, ValidatorTypeCode.DATETIME, validationContext);
41+
this.formatName = formatName;
42+
this.format = format;
43+
parseErrorCode(getValidatorType().getErrorCodeKey());
44+
}
45+
46+
public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String at) {
47+
debug(logger, node, rootNode, at);
48+
49+
Set<ValidationMessage> errors = new LinkedHashSet<ValidationMessage>();
50+
51+
JsonType nodeType = TypeFactory.getValueNodeType(node);
52+
if (nodeType != JsonType.STRING) {
53+
return errors;
54+
}
55+
56+
if (formatName != null) {
57+
if (formatName.equals(DATE) && !isLegalDate(node.textValue()) || (formatName.equals(DATE_TIME) && !isLegalDateTime(node.textValue()))) {
58+
errors.add(buildValidationMessage(at, node.textValue(), formatName));
59+
}
60+
}
61+
62+
return Collections.unmodifiableSet(errors);
63+
}
64+
65+
private boolean isLegalDate(String string) {
66+
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
67+
sdf.setLenient(false);
68+
return sdf.parse(string, new ParsePosition(0)) != null;
69+
}
70+
71+
private boolean isLegalTime(String string) {
72+
String time = string.split("\\.")[0];
73+
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");
74+
sdf.setLenient(false);
75+
return sdf.parse(time, new ParsePosition(0)) != null;
76+
}
77+
78+
private boolean isLegalDateTime(String string) {
79+
// Check the format
80+
try {
81+
if (!format.matches(string)) {
82+
return false;
83+
}
84+
} catch (PatternSyntaxException pse) {
85+
// String is considered valid if pattern is invalid
86+
logger.error("Failed to apply pattern: Invalid RE syntax [" + format.getName() + "]", pse);
87+
}
88+
// Check the contents
89+
String[] dateTime = string.split("\\s|T|t", 2);
90+
String date = dateTime[0];
91+
String time = dateTime[1];
92+
return isLegalDate(date) && isLegalTime(time);
93+
}
94+
}

src/main/java/com/networknt/schema/FormatKeyword.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ public class FormatKeyword implements Keyword {
2626
private final ValidatorTypeCode type;
2727
private final Map<String, Format> formats;
2828

29+
private final String DATE = "date";
30+
private final String DATE_TIME = "date-time";
31+
2932
public FormatKeyword(ValidatorTypeCode type, Map<String, Format> formats) {
3033
this.type = type;
3134
this.formats = formats;
@@ -34,23 +37,24 @@ public FormatKeyword(ValidatorTypeCode type, Map<String, Format> formats) {
3437
Collection<Format> getFormats() {
3538
return Collections.unmodifiableCollection(formats.values());
3639
}
37-
40+
3841
@Override
3942
public JsonValidator newValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext)
4043
throws Exception {
4144
Format format = null;
4245
if (schemaNode != null && schemaNode.isTextual()) {
4346
String formatName = schemaNode.textValue();
4447
format = formats.get(formatName);
48+
// Validate date and time separately
49+
if (formatName.equals(DATE) || formatName.equals(DATE_TIME)) {
50+
return new DateTimeValidator(schemaPath, schemaNode, parentSchema, validationContext, formatName, format);
51+
}
4552
}
46-
4753
return new FormatValidator(schemaPath, schemaNode, parentSchema, validationContext, format);
4854
}
49-
55+
5056
@Override
5157
public String getValue() {
5258
return type.getValue();
5359
}
54-
55-
5660
}

0 commit comments

Comments
 (0)