Skip to content

Commit 195d716

Browse files
iouakrimiouakrim
andauthored
add validator for duration format (#593)
Co-authored-by: iouakrim <[email protected]>
1 parent 1ecc9da commit 195d716

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.networknt.schema;
1818

1919
import com.fasterxml.jackson.databind.JsonNode;
20+
import com.networknt.schema.format.DurationValidator;
2021
import com.networknt.schema.format.EmailValidator;
2122

2223
import java.util.Collection;
@@ -31,6 +32,7 @@ public class FormatKeyword implements Keyword {
3132
private final String DATE_TIME = "date-time";
3233
private final String UUID = "uuid";
3334
private final String EMAIL = "email";
35+
private final String DURATION = "duration";
3436

3537
public FormatKeyword(ValidatorTypeCode type, Map<String, Format> formats) {
3638
this.type = type;
@@ -60,6 +62,9 @@ public JsonValidator newValidator(String schemaPath, JsonNode schemaNode, JsonSc
6062
} else if (formatName.equals(EMAIL)) {
6163
return new EmailValidator(schemaPath, schemaNode, parentSchema, validationContext, formatName);
6264
}
65+
else if (formatName.equals(DURATION)) {
66+
return new DurationValidator(schemaPath, schemaNode, parentSchema, validationContext, formatName);
67+
}
6368
}
6469
return new FormatValidator(schemaPath, schemaNode, parentSchema, validationContext, format);
6570
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package com.networknt.schema.format;
18+
19+
import com.fasterxml.jackson.databind.JsonNode;
20+
import com.networknt.schema.*;
21+
import org.slf4j.Logger;
22+
import org.slf4j.LoggerFactory;
23+
24+
import java.util.Collections;
25+
import java.util.LinkedHashSet;
26+
import java.util.Set;
27+
import java.util.regex.Matcher;
28+
import java.util.regex.Pattern;
29+
30+
/**
31+
*
32+
* <p>This class provides methods to validate a duration format .
33+
*
34+
* @version $Revision$
35+
* @since Validator 1.4
36+
*/
37+
public class DurationValidator extends BaseJsonValidator implements JsonValidator {
38+
private static final Logger logger = LoggerFactory.getLogger(DurationValidator.class);
39+
40+
private static final String DURATION_REGEX = "^(-?)P(?=\\d|T\\d)(?:(\\d+)Y)?(?:(\\d+)M)?(?:(\\d+)([DW]))?(?:T(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+(?:\\.\\d+)?)S)?)?$";
41+
private static final Pattern DURATION_PATTERN = Pattern.compile(DURATION_REGEX);
42+
private final String formatName;
43+
44+
45+
46+
/**
47+
* <p>Checks if a field has a valid duration.</p>
48+
*
49+
* @param duration The value validation is being performed on. A <code>null</code>
50+
* value is considered invalid.
51+
* @return true if the duration valid.
52+
*/
53+
public boolean isValid(String duration) {
54+
if (duration == null) {
55+
return false;
56+
}
57+
58+
Matcher durationMatcher = DURATION_PATTERN.matcher(duration);
59+
if (!durationMatcher.matches()) {
60+
return false;
61+
}
62+
63+
return true;
64+
}
65+
66+
public DurationValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentSchema, ValidationContext validationContext, String formatName) {
67+
super(schemaPath, schemaNode, parentSchema, ValidatorTypeCode.FORMAT, validationContext);
68+
this.formatName = formatName;
69+
this.validationContext = validationContext;
70+
parseErrorCode(getValidatorType().getErrorCodeKey());
71+
}
72+
73+
@Override
74+
public Set<ValidationMessage> validate(JsonNode node, JsonNode rootNode, String at) {
75+
debug(logger, node, rootNode, at);
76+
77+
Set<ValidationMessage> errors = new LinkedHashSet<ValidationMessage>();
78+
79+
JsonType nodeType = TypeFactory.getValueNodeType(node, this.validationContext.getConfig());
80+
if (nodeType != JsonType.STRING) {
81+
return errors;
82+
}
83+
if (!isValid(node.textValue())) {
84+
errors.add(buildValidationMessage(at, node.textValue(), formatName));
85+
}
86+
return Collections.unmodifiableSet(errors);
87+
88+
}
89+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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.core.JsonProcessingException;
20+
import com.fasterxml.jackson.databind.JsonNode;
21+
import com.fasterxml.jackson.databind.ObjectMapper;
22+
import org.junit.jupiter.api.Test;
23+
24+
import java.io.IOException;
25+
import java.util.Set;
26+
27+
import static org.junit.jupiter.api.Assertions.assertEquals;
28+
29+
public class DurationFormatValidatorTest {
30+
31+
@Test
32+
public void durationFormatValidatorTest() throws JsonProcessingException, IOException {
33+
ObjectMapper objectMapper = new ObjectMapper();
34+
final String schema = "{\"type\": \"string\", \"format\": \"duration\"}\n";
35+
final JsonNode validTargetNode = objectMapper.readTree("\"P1D\"");
36+
final JsonNode invalidTargetNode = objectMapper.readTree("\"INVALID_DURATION\"");
37+
38+
final JsonSchemaFactory validatorFactory = JsonSchemaFactory.builder(JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909)).build();
39+
final JsonSchema validatorSchema = validatorFactory.getSchema(schema);
40+
41+
Set<ValidationMessage> messages = validatorSchema.validate(validTargetNode);
42+
assertEquals(0, messages.size());
43+
44+
messages = validatorSchema.validate(invalidTargetNode);
45+
assertEquals(1, messages.size());
46+
47+
}
48+
}

0 commit comments

Comments
 (0)