Skip to content

Commit

Permalink
MSEARCH-393 Fix date query validation to support ISO date/time formats (
Browse files Browse the repository at this point in the history
#277)

(cherry picked from commit aa23acd)
  • Loading branch information
psmagin committed Jul 25, 2022
1 parent 9a5f37c commit 702bac9
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 8 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ if it is defined but doesn't match.
| `statusId` | term | `statusId == "123"` | Matches instances with the `123` status |
| `instanceFormatIds` | term | `instanceFormatIds == "123"` | Matches instances with the `123` format id |
| `languages` | term | `languages == "eng"` | Matches instances that have `eng` language |
| `metadata.createdDate` | term | `metadata.createdDate > "2020-12-12"` | Matches instances that were created after `2020-12-12` |
| `metadata.createdDate` | term | `metadata.createdDate > "2021-03-01T00:00:00.000+00:00"` | Matches instances that were created after `2020-12-12` |
| `metadata.updatedDate` | term | `metadata.updatedDate > "2020-12-12"` | Matches instances that were updated after `2020-12-12` |
| `modeOfIssuanceId` | term | `modeOfIssuanceId=="123"` | Matches instances that have `123` mode of issuance |
| `natureOfContentTermIds` | term | `natureOfContentTermIds=="123"` | Matches instances that have `123` nature of content |
Expand Down
27 changes: 24 additions & 3 deletions src/main/java/org/folio/search/cql/CqlTermQueryConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import static java.util.Collections.unmodifiableMap;
import static java.util.stream.Collectors.joining;
import static org.apache.commons.lang3.StringUtils.lowerCase;
import static org.apache.commons.validator.GenericValidator.isDate;
import static org.folio.search.utils.SearchUtils.ASTERISKS_SIGN;
import static org.opensearch.index.query.QueryBuilders.matchAllQuery;

import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
Expand Down Expand Up @@ -34,7 +34,16 @@ public class CqlTermQueryConverter {
public static final String WILDCARD_OPERATOR = "wildcard";
private static final String MATCH_ALL_CQL_QUERY = "cql.allRecords = 1";
private static final String KEYWORD_ALL_CQL_QUERY = "keyword = *";
private static final String STRICT_DATE_PATTERN = "yyyy-MM-dd";

private static final List<DateTimeFormatter> SUPPORTED_DATE_FORMATS = List.of(
DateTimeFormatter.ISO_DATE,
DateTimeFormatter.ISO_DATE_TIME,
DateTimeFormatter.ISO_LOCAL_DATE,
DateTimeFormatter.ISO_LOCAL_DATE_TIME,
DateTimeFormatter.ISO_OFFSET_DATE,
DateTimeFormatter.ISO_OFFSET_DATE_TIME,
DateTimeFormatter.ISO_INSTANT
);

private final SearchFieldProvider searchFieldProvider;
private final Map<String, TermQueryBuilder> termQueryBuilders;
Expand Down Expand Up @@ -143,11 +152,23 @@ private static Map<String, TermQueryBuilder> getTermQueryProvidersAsMap(List<Ter

private void validateIndexFormat(String index, CQLTermNode termNode) {
var value = termNode.getTerm();
if (index.equals("date") && !isDate(value, STRICT_DATE_PATTERN, true)) {
if (index.equals("date") && !isValidDate(value)) {
throw new ValidationException("Invalid date format", termNode.getIndex(), value);
}
}

private boolean isValidDate(String value) {
for (DateTimeFormatter dateFormat : SUPPORTED_DATE_FORMATS) {
try {
dateFormat.parse(value);
return true;
} catch (Exception ignored) {
// do nothing
}
}
return false;
}

private static boolean isMatchAllQuery(String cqlQuery) {
return MATCH_ALL_CQL_QUERY.equals(cqlQuery) || KEYWORD_ALL_CQL_QUERY.equals(cqlQuery);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ private static Stream<Arguments> filteredSearchQueriesProvider() {
arguments("(subjectHeadings==\"n\")", List.of(IDS[11], IDS[12])),

arguments("(metadata.createdDate >= 2021-03-01) ", List.of(IDS[0], IDS[1], IDS[2], IDS[3])),
arguments("(metadata.createdDate >= 2021-03-01T00:00:00.000) ", List.of(IDS[0], IDS[1], IDS[2], IDS[3])),
arguments("(metadata.createdDate >= 2021-03-01T00:00:00.000Z) ", List.of(IDS[0], IDS[1], IDS[2], IDS[3])),
arguments("(metadata.createdDate >= 2021-03-01T00:00:00.000+00:00) ", List.of(IDS[0], IDS[1], IDS[2], IDS[3])),
arguments("(metadata.createdDate > 2021-03-01) ", List.of(IDS[1], IDS[2], IDS[3])),
arguments("(metadata.createdDate >= 2021-03-01 and metadata.createdDate < 2021-03-10) ",
List.of(IDS[0], IDS[2])),
Expand All @@ -158,8 +161,7 @@ private static Stream<Arguments> invalidDateSearchQueriesProvider() {
arguments("metadata.createdDate", "2022-06-1"),
arguments("metadata.createdDate", "2022-06-40"),
arguments("metadata.updatedDate", "2022-15-01"),
arguments("metadata.updatedDate", "invalidDate"),
arguments("metadata.updatedDate", "2022-11-15T15:00:00.000")
arguments("metadata.updatedDate", "invalidDate")
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,8 +316,7 @@ private static Stream<Arguments> invalidDateSearchQueriesProvider() {
arguments("holdings.metadata.createdDate", "2022-15-01"),
arguments("holdings.metadata.updatedDate", "2022-06-40"),

arguments("item.metadata.updatedDate", "invalidDate"),
arguments("item.metadata.createdDate", "2022-06-15T15:00:00.000")
arguments("item.metadata.updatedDate", "invalidDate")
);
}

Expand Down

0 comments on commit 702bac9

Please sign in to comment.