Skip to content

Commit b51d1ad

Browse files
committed
new_feature_release
1 parent 8838cd4 commit b51d1ad

File tree

7 files changed

+141
-23
lines changed

7 files changed

+141
-23
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
<groupId>com.americanexpress.unify.jdocs</groupId>
2121
<artifactId>unify-jdocs</artifactId>
22-
<version>1.3.9</version>
22+
<version>1.4.0</version>
2323
<packaging>jar</packaging>
2424

2525
<name>unify-jdocs</name>

readme.md

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ JDocs is available as a jar file in Maven central with the following latest Mave
1515
````pom
1616
<groupId>com.americanexpress.unify.jdocs</groupId>
1717
<artifactId>unify-jdocs</artifactId>
18-
<version>1.3.9</version>
18+
<version>1.4.0</version>
1919
````
2020

2121
---
@@ -392,9 +392,9 @@ public interface Document {
392392
*/
393393
boolean pathExists(String path, String... vargs);
394394

395-
/**
396-
* Used to determine if the specified path is an array in the document
397-
*
395+
/**
396+
* Used to determine if the specified path to a leaf node is an array in the document
397+
*
398398
* @param path the path
399399
* @param vargs the values to replace the % characters in path
400400
* @return true if the path is an array else false
@@ -1236,17 +1236,43 @@ d.setString("$.start_date", "15-Apr-2019") // incorrect date format
12361236
d.setString("$.phones[0].number", "111111") // incorrect data type
12371237
```
12381238

1239-
As regards constraints, the validation is done against the specified regular expression. If a match
1240-
returns true, the validation is assumed to succeed else an exception is thrown.
1239+
As regards constraints, the validation is done against the specified regular expression. If a match returns true, the
1240+
validation is assumed to succeed else an exception is thrown.
12411241

12421242
The following attributes are implemented as part of specifying a constraint on a path:
12431243

12441244
S. No. | Field Name | Description | Type | Mandatory?
12451245
------ | --------------- | ------------| ---- | ----------
12461246
1 | type | Defines the type of the field. Possible values are string, integer, long, decimal, boolean, date | String | Yes
1247-
2 | null_allowed | Specifies if null is a valid value for the field. If not specified, default is no null allowed | boolean | No
1248-
3 | regex | The pattern against which the value will be validated | string | No
1249-
4 | format | Only applicable for date type. Specification is as per DateTimeFormatter | string | Yes only for date type
1247+
2 | regex | The pattern against which the value will be validated | string | No
1248+
3 | null_allowed | Specifies if null is a valid value for the field. If not specified, default is null not allowed. If value is null and allowed, regex will be ignored | boolean | No
1249+
4 | ignore_regex_if_empty_string | If not specified, default is false. If specified to true, regex will be ignored if value is empty. Applicable only for string type fields | boolean | No
1250+
5 | format | Only applicable for date type. Specification is as per DateTimeFormatter | string | Yes
1251+
6 | empty_date_allowed | Only applicable for date type fields. If not specified, default is true. If allowed format check is ignored | boolean | No
1252+
1253+
**Validating typed documents**
1254+
1255+
By default, typed documents are validated when they are created and when any read / write operation is performed on
1256+
them. However there may be cases, when we do not want to validate the document at the time of creation but only at the
1257+
time of reading and writing. This is a typical scenario in the use of APIs which can return extra blocks and paths which
1258+
may not be present in the model document and which we may not be interested in. If we were to validate at the time of
1259+
creating the document, the model validations would fail unless we kept the model document in sync with all the changes
1260+
happening on the API side. Most of the times this is not possible as the teams are separate and there is no reason that
1261+
adding fields to the response which we are not interested in should cause a failure. To take care of this scenario, we
1262+
have two alternatives:
1263+
1264+
1. Use the overloaded JDocument constructor to specify that the validation should only be done while reading / writing
1265+
paths. This way the default behaviour will not change but can be set at a per document level
1266+
2. Specify the default behaviour of JDocs to do the validation only while reading / writing paths. This can be set using
1267+
the public static init method while initializing JDocs. Of course this can be overridden as desired by using the
1268+
JDocument overloaded constructor
1269+
1270+
The two methods are shown below:
1271+
1272+
```java
1273+
public JDocument(String type,String json,boolean validateAtReadWriteOnly);
1274+
public static void init(boolean defaultValidateAtReadWriteOnly);
1275+
```
12501276

12511277
---
12521278

src/main/java/com/americanexpress/unify/jdocs/CONSTS_JDOCS.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ public class FORMAT_FIELDS {
3232
public static final String REGEX = "regex";
3333
public static final String FORMAT = "format"; // used only for date
3434
public static final String NULL_ALLOWED = "null_allowed";
35+
public static final String IGNORE_REGEX_IF_EMPTY_STRING = "ignore_regex_if_empty_string";
36+
public static final String EMPTY_DATE_ALLOWED = "empty_date_allowed";
3537

3638
}
3739

src/main/java/com/americanexpress/unify/jdocs/ERRORS_JDOCS.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ public static void load() {
9090
map.put("jdoc_err_67", "Name value pair not allowed in this method. Path is -> {0}");
9191
map.put("jdoc_err_68", "Path does not exist in document. Path -> {0}");
9292
map.put("jdoc_err_69", "Path specified cannot be a leaf node. Path -> {0}");
93+
map.put("jdoc_err_70", "Empty value not allowed for a date at path -> {0}");
94+
map.put("jdoc_err_71", "Date format missing for path -> {0}");
9395
}
9496

9597
}

src/main/java/com/americanexpress/unify/jdocs/JDocument.java

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939
import java.util.regex.Pattern;
4040
import java.util.stream.Collectors;
4141

42+
import static com.americanexpress.unify.jdocs.DataType.DATE;
43+
import static com.americanexpress.unify.jdocs.DataType.STRING;
44+
4245
/*
4346
* @author Deepak Arora
4447
*/
@@ -2219,6 +2222,18 @@ private static void validateField(String format, Object value, String path, List
22192222
JsonNode node = getFormatNode(type, path, format);
22202223

22212224
while (true) {
2225+
// check that the format field is specified if we are dealing with a date
2226+
DataType dataType = DataType.valueOf(node.get(CONSTS_JDOCS.FORMAT_FIELDS.TYPE).asText().toUpperCase());
2227+
2228+
// check that a date field has to have a format. Whether the format is correct or not will be validated later
2229+
if (dataType == DATE) {
2230+
String formatValue = node.get(CONSTS_JDOCS.FORMAT_FIELDS.FORMAT).asText();
2231+
if (formatValue.isEmpty() == true) {
2232+
throwExceptionOrSetErrorList("jdoc_err_71", path, errorList);
2233+
break;
2234+
}
2235+
}
2236+
22222237
// if the value is null, check if nulls are allowed
22232238
if (value == null) {
22242239
JsonNode node1 = node.get(CONSTS_JDOCS.FORMAT_FIELDS.NULL_ALLOWED);
@@ -2233,7 +2248,6 @@ private static void validateField(String format, Object value, String path, List
22332248
}
22342249

22352250
// check data types
2236-
DataType dataType = DataType.valueOf(node.get(CONSTS_JDOCS.FORMAT_FIELDS.TYPE).asText().toUpperCase());
22372251
switch (dataType) {
22382252
case STRING:
22392253
if ((value instanceof String) == false) {
@@ -2278,6 +2292,45 @@ private static void validateField(String format, Object value, String path, List
22782292
break;
22792293
}
22802294

2295+
// check if value is empty and if so do we need to ignore regex
2296+
if (dataType == STRING) {
2297+
String s = value.toString();
2298+
if (s.isEmpty()) {
2299+
JsonNode node1 = node.get(CONSTS_JDOCS.FORMAT_FIELDS.IGNORE_REGEX_IF_EMPTY_STRING);
2300+
2301+
// by default do not ignore. Historically we have been disallowing an empty string if it does not match
2302+
// regex pattern. The new requirement is to be able to ignore regex if the value is empty
2303+
boolean ignoreRegex = false;
2304+
if (node1 != null) {
2305+
ignoreRegex = node.get(CONSTS_JDOCS.FORMAT_FIELDS.IGNORE_REGEX_IF_EMPTY_STRING).booleanValue();
2306+
}
2307+
if (ignoreRegex == true) {
2308+
break;
2309+
}
2310+
}
2311+
}
2312+
2313+
// check if value is empty and if it is allowed
2314+
if (dataType == DATE) {
2315+
String s = value.toString();
2316+
if (s.isEmpty()) {
2317+
JsonNode node1 = node.get(CONSTS_JDOCS.FORMAT_FIELDS.EMPTY_DATE_ALLOWED);
2318+
2319+
// by default we ignore. Historically we have been ignoring the format if an empty date value
2320+
// is provided. The new requirement is to not allow an empty date value
2321+
boolean emptyDateAllowed = true;
2322+
if (node1 != null) {
2323+
emptyDateAllowed = node.get(CONSTS_JDOCS.FORMAT_FIELDS.EMPTY_DATE_ALLOWED).booleanValue();
2324+
}
2325+
if (emptyDateAllowed == true) {
2326+
break;
2327+
}
2328+
else {
2329+
throwExceptionOrSetErrorList("jdoc_err_70", path, errorList);
2330+
}
2331+
}
2332+
}
2333+
22812334
// check against regex pattern and format
22822335
switch (dataType) {
22832336
case STRING:
@@ -2305,17 +2358,13 @@ private static void validateField(String format, Object value, String path, List
23052358

23062359
case DATE:
23072360
// Match input date with the format provided
2308-
String fieldValue = node.get(CONSTS_JDOCS.FORMAT_FIELDS.FORMAT).asText();
2309-
if (fieldValue.isEmpty() == false) {
2310-
try {
2311-
DateTimeFormatter dfs = DateTimeFormatter.ofPattern(fieldValue).withResolverStyle(ResolverStyle.STRICT);
2312-
if (value.toString().isEmpty() == false) {
2313-
dfs.parse(value.toString());
2314-
}
2315-
}
2316-
catch (Exception e) {
2317-
throwExceptionOrSetErrorList("jdoc_err_51", path, errorList);
2318-
}
2361+
String formatValue = node.get(CONSTS_JDOCS.FORMAT_FIELDS.FORMAT).asText();
2362+
try {
2363+
DateTimeFormatter dfs = DateTimeFormatter.ofPattern(formatValue).withResolverStyle(ResolverStyle.STRICT);
2364+
dfs.parse(value.toString());
2365+
}
2366+
catch (Exception e) {
2367+
throwExceptionOrSetErrorList("jdoc_err_51", path, errorList);
23192368
}
23202369
break;
23212370

@@ -2702,7 +2751,7 @@ else if (fieldNode.isLong()) {
27022751

27032752
case STRING:
27042753
value = fieldNode.asText();
2705-
dt = DataType.STRING;
2754+
dt = STRING;
27062755
break;
27072756

27082757
default:

src/test/java/com/americanexpress/unify/jdocs/DocumentTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,4 +1202,37 @@ void testMergeDelete() {
12021202
d = getTypedDocument("sample_24_model", "/jdocs/sample_24.json");
12031203
}
12041204

1205+
@Test
1206+
void testIgnoreRegexIfEmpty() {
1207+
setDocModel("sample_26_model");
1208+
Document d = new JDocument("sample_26_model", null);
1209+
1210+
d.setString("$.id1", "GO2");
1211+
assertEquals(true, true);
1212+
1213+
UnifyException e = assertThrows(UnifyException.class, () -> {
1214+
d.setString("$.id1", "");
1215+
});
1216+
1217+
d.setString("$.id2", "");
1218+
assertEquals(true, true);
1219+
1220+
d.setString("$.id2", "GNA");
1221+
assertEquals(true, true);
1222+
1223+
e = assertThrows(UnifyException.class, () -> {
1224+
d.setString("$.id2", "hhh");
1225+
});
1226+
1227+
d.setString("$.id3", "2023-Jan-26");
1228+
assertEquals(true, true);
1229+
1230+
d.setString("$.id3", "");
1231+
assertEquals(true, true);
1232+
1233+
e = assertThrows(UnifyException.class, () -> {
1234+
d.setString("$.id4", "");
1235+
});
1236+
}
1237+
12051238
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"id1": "{\"type\":\"string\", \"regex\":\"^(GNA|GO2)\"}",
3+
"id2": "{\"type\":\"string\", \"regex\":\"^(GNA|GO2)\", \"ignore_regex_if_empty_string\":true}",
4+
"id3": "{\"type\":\"date\", \"format\":\"uuuu-MMM-dd\"}",
5+
"id4": "{\"type\":\"date\", \"format\":\"uuuu-MMM-dd\", \"empty_date_allowed\":false}"
6+
}

0 commit comments

Comments
 (0)