From 8751953796fd77bb0ae13235483c51020970193c Mon Sep 17 00:00:00 2001 From: Sulejman Karisik Date: Mon, 10 Jun 2024 15:32:07 +0200 Subject: [PATCH 1/5] feat:Add operators to search endpoint --- .../services/CkanDatasetsSearchService.java | 2 +- .../services/CkanFacetsQueryBuilder.java | 15 ++++---- .../discovery/services/Operator.java | 13 +++++++ .../discovery/services/OperatorMapper.java | 18 ++++++++++ src/main/openapi/discovery.yaml | 3 ++ .../services/CkanFacetsQueryBuilderTest.java | 36 +++++++++++++++++-- 6 files changed, 77 insertions(+), 10 deletions(-) create mode 100644 src/main/java/io/github/genomicdatainfrastructure/discovery/services/Operator.java create mode 100644 src/main/java/io/github/genomicdatainfrastructure/discovery/services/OperatorMapper.java diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanDatasetsSearchService.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanDatasetsSearchService.java index 13a63e2..36348fe 100644 --- a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanDatasetsSearchService.java +++ b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanDatasetsSearchService.java @@ -28,7 +28,7 @@ public CkanDatasetsSearchService( @Override public DatasetsSearchResponse search(DatasetSearchQuery query, String accessToken) { - var facetsQuery = CkanFacetsQueryBuilder.buildFacetQuery(query.getFacets()); + var facetsQuery = CkanFacetsQueryBuilder.buildFacetQuery(query); var response = ckanQueryApi.packageSearch( query.getQuery(), diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilder.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilder.java index 1f6269c..dfc139d 100644 --- a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilder.java +++ b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilder.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.Objects; +import io.github.genomicdatainfrastructure.discovery.model.DatasetSearchQuery; import io.github.genomicdatainfrastructure.discovery.model.DatasetSearchQueryFacet; import lombok.experimental.UtilityClass; @@ -21,9 +22,11 @@ public class CkanFacetsQueryBuilder { private final String CKAN_FACET_GROUP = "ckan"; private final String QUOTED_VALUE = "\"%s\""; private final String FACET_PATTERN = "%s:(%s)"; - private final String AND = " AND "; - public String buildFacetQuery(List facets) { + public String buildFacetQuery(DatasetSearchQuery query) { + var facets = query.getFacets(); + var operator = query.getOperator(); + var nonNullFacets = ofNullable(facets) .orElseGet(List::of) .stream() @@ -31,8 +34,8 @@ public String buildFacetQuery(List facets) { .collect(groupingBy(DatasetSearchQueryFacet::getFacet)); return nonNullFacets.entrySet().stream() - .map(entry -> getFacetQuery(entry.getKey(), entry.getValue())) - .collect(joining(AND)); + .map(entry -> getFacetQuery(entry.getKey(), entry.getValue(), operator)) + .collect(joining(OperatorMapper.getOperator(operator))); } private Boolean isCkanGroupAndFacetIsNotBlank(DatasetSearchQueryFacet facet) { @@ -43,10 +46,10 @@ private Boolean isCkanGroupAndFacetIsNotBlank(DatasetSearchQueryFacet facet) { !facet.getValue().isBlank(); } - private String getFacetQuery(String key, List facets) { + private String getFacetQuery(String key, List facets, String operator) { var values = facets.stream() .map(facet -> QUOTED_VALUE.formatted(facet.getValue())) - .collect(joining(AND)); + .collect(joining(OperatorMapper.getOperator(operator))); return FACET_PATTERN.formatted(key, values); } diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/Operator.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/Operator.java new file mode 100644 index 0000000..6824454 --- /dev/null +++ b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/Operator.java @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: 2024 PNED G.I.E. +// +// SPDX-License-Identifier: Apache-2.0 + +package io.github.genomicdatainfrastructure.discovery.services; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public class Operator { + public static final String Or = "or"; + public static final String And = "and"; +} \ No newline at end of file diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/OperatorMapper.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/OperatorMapper.java new file mode 100644 index 0000000..cdc9cc5 --- /dev/null +++ b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/OperatorMapper.java @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: 2024 PNED G.I.E. +// +// SPDX-License-Identifier: Apache-2.0 + +package io.github.genomicdatainfrastructure.discovery.services; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public class OperatorMapper { + + private final String AND = " AND "; + private final String OR = " OR "; + + public String getOperator(String operator) { + return operator.equals(Operator.Or) ? OR : AND; + } +} diff --git a/src/main/openapi/discovery.yaml b/src/main/openapi/discovery.yaml index ceec942..f2307b4 100644 --- a/src/main/openapi/discovery.yaml +++ b/src/main/openapi/discovery.yaml @@ -112,6 +112,9 @@ components: title: Offset in the complete result set default: 0 minimum: 0 + operator: + type: string + default: "and" DatasetSearchQueryFacet: type: object properties: diff --git a/src/test/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilderTest.java b/src/test/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilderTest.java index d7bf0ba..ae4403a 100644 --- a/src/test/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilderTest.java +++ b/src/test/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilderTest.java @@ -4,6 +4,7 @@ package io.github.genomicdatainfrastructure.discovery.services; +import io.github.genomicdatainfrastructure.discovery.model.DatasetSearchQuery; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.NullSource; @@ -20,7 +21,7 @@ class CkanFacetsQueryBuilderTest { @Test void can_parse_if_empty_list() { var expected = ""; - var actual = CkanFacetsQueryBuilder.buildFacetQuery(List.of()); + var actual = CkanFacetsQueryBuilder.buildFacetQuery(null); assertEquals(expected, actual); } @@ -34,7 +35,7 @@ void can_parse_if_null_list() { @ParameterizedTest @NullSource @ValueSource(strings = {"", " ", " "}) - void can_parse(String value) { + void can_parse_with_and_operator(String value) { var facets = List.of( new DatasetSearchQueryFacet("ckan", "field1", "value1"), new DatasetSearchQueryFacet("ckan", "field1", "value2"), @@ -47,8 +48,37 @@ void can_parse(String value) { new DatasetSearchQueryFacet(value, "field2", "value3") ); + var query = new DatasetSearchQuery(); + query.setFacets(facets); + query.setOperator(Operator.And); + var expected = "field1:(\"value1\" AND \"value2\") AND field2:(\"value3\")"; - var actual = CkanFacetsQueryBuilder.buildFacetQuery(facets); + var actual = CkanFacetsQueryBuilder.buildFacetQuery(query); + assertEquals(expected, actual); + } + + @ParameterizedTest + @NullSource + @ValueSource(strings = {"", " ", " "}) + void can_parse_with_or_operator(String value) { + var facets = List.of( + new DatasetSearchQueryFacet("ckan", "field1", "value1"), + new DatasetSearchQueryFacet("ckan", "field1", "value2"), + new DatasetSearchQueryFacet("ckan", "field2", "value3"), + new DatasetSearchQueryFacet("dummy", "field2", "value"), + new DatasetSearchQueryFacet(null, "field2", "value"), + new DatasetSearchQueryFacet(null, null, "value"), + new DatasetSearchQueryFacet("ckan", value, "value3"), + new DatasetSearchQueryFacet("ckan", "field2", value), + new DatasetSearchQueryFacet(value, "field2", "value3") + ); + + var query = new DatasetSearchQuery(); + query.setFacets(facets); + query.setOperator(Operator.Or); + + var expected = "field1:(\"value1\" OR \"value2\") OR field2:(\"value3\")"; + var actual = CkanFacetsQueryBuilder.buildFacetQuery(query); assertEquals(expected, actual); } } From 2ef5cb3d2cad686b28771ed2b6b95cbccf9bbbd5 Mon Sep 17 00:00:00 2001 From: Sulejman Karisik Date: Mon, 10 Jun 2024 15:59:45 +0200 Subject: [PATCH 2/5] feat: rename operator classes for more clarity --- .../discovery/services/{Operator.java => CkanQueryOperator.java} | 0 .../{OperatorMapper.java => CkanQueryOperatorMapper.java} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/main/java/io/github/genomicdatainfrastructure/discovery/services/{Operator.java => CkanQueryOperator.java} (100%) rename src/main/java/io/github/genomicdatainfrastructure/discovery/services/{OperatorMapper.java => CkanQueryOperatorMapper.java} (100%) diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/Operator.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperator.java similarity index 100% rename from src/main/java/io/github/genomicdatainfrastructure/discovery/services/Operator.java rename to src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperator.java diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/OperatorMapper.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperatorMapper.java similarity index 100% rename from src/main/java/io/github/genomicdatainfrastructure/discovery/services/OperatorMapper.java rename to src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperatorMapper.java From d644a4cb4a5dadc0fdc857b94cec468726a9db5a Mon Sep 17 00:00:00 2001 From: Sulejman Karisik Date: Mon, 10 Jun 2024 15:59:57 +0200 Subject: [PATCH 3/5] feat: rename operator classes for more clarity --- .../discovery/services/CkanFacetsQueryBuilder.java | 7 ++++--- .../discovery/services/CkanQueryOperator.java | 3 ++- .../discovery/services/CkanQueryOperatorMapper.java | 4 ++-- .../discovery/services/CkanFacetsQueryBuilderTest.java | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilder.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilder.java index dfc139d..779a200 100644 --- a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilder.java +++ b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilder.java @@ -35,7 +35,7 @@ public String buildFacetQuery(DatasetSearchQuery query) { return nonNullFacets.entrySet().stream() .map(entry -> getFacetQuery(entry.getKey(), entry.getValue(), operator)) - .collect(joining(OperatorMapper.getOperator(operator))); + .collect(joining(CkanQueryOperatorMapper.getOperator(operator))); } private Boolean isCkanGroupAndFacetIsNotBlank(DatasetSearchQueryFacet facet) { @@ -46,10 +46,11 @@ private Boolean isCkanGroupAndFacetIsNotBlank(DatasetSearchQueryFacet facet) { !facet.getValue().isBlank(); } - private String getFacetQuery(String key, List facets, String operator) { + private String getFacetQuery(String key, List facets, + String operator) { var values = facets.stream() .map(facet -> QUOTED_VALUE.formatted(facet.getValue())) - .collect(joining(OperatorMapper.getOperator(operator))); + .collect(joining(CkanQueryOperatorMapper.getOperator(operator))); return FACET_PATTERN.formatted(key, values); } diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperator.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperator.java index 6824454..8dac73e 100644 --- a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperator.java +++ b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperator.java @@ -7,7 +7,8 @@ import lombok.experimental.UtilityClass; @UtilityClass -public class Operator { +public class CkanQueryOperator { + public static final String Or = "or"; public static final String And = "and"; } \ No newline at end of file diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperatorMapper.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperatorMapper.java index cdc9cc5..9da756c 100644 --- a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperatorMapper.java +++ b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperatorMapper.java @@ -7,12 +7,12 @@ import lombok.experimental.UtilityClass; @UtilityClass -public class OperatorMapper { +public class CkanQueryOperatorMapper { private final String AND = " AND "; private final String OR = " OR "; public String getOperator(String operator) { - return operator.equals(Operator.Or) ? OR : AND; + return operator.equals(CkanQueryOperator.Or) ? OR : AND; } } diff --git a/src/test/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilderTest.java b/src/test/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilderTest.java index ae4403a..29101e0 100644 --- a/src/test/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilderTest.java +++ b/src/test/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilderTest.java @@ -50,7 +50,7 @@ void can_parse_with_and_operator(String value) { var query = new DatasetSearchQuery(); query.setFacets(facets); - query.setOperator(Operator.And); + query.setOperator(CkanQueryOperator.And); var expected = "field1:(\"value1\" AND \"value2\") AND field2:(\"value3\")"; var actual = CkanFacetsQueryBuilder.buildFacetQuery(query); @@ -75,7 +75,7 @@ void can_parse_with_or_operator(String value) { var query = new DatasetSearchQuery(); query.setFacets(facets); - query.setOperator(Operator.Or); + query.setOperator(CkanQueryOperator.Or); var expected = "field1:(\"value1\" OR \"value2\") OR field2:(\"value3\")"; var actual = CkanFacetsQueryBuilder.buildFacetQuery(query); From 5c68db7a6ce4c42666ea5a5c79fc87ee8b2b8f74 Mon Sep 17 00:00:00 2001 From: Sulejman Karisik Date: Mon, 10 Jun 2024 16:25:54 +0200 Subject: [PATCH 4/5] fix: tests and use enum --- .../discovery/services/CkanQueryOperator.java | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperator.java diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperator.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperator.java deleted file mode 100644 index 8dac73e..0000000 --- a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperator.java +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: 2024 PNED G.I.E. -// -// SPDX-License-Identifier: Apache-2.0 - -package io.github.genomicdatainfrastructure.discovery.services; - -import lombok.experimental.UtilityClass; - -@UtilityClass -public class CkanQueryOperator { - - public static final String Or = "or"; - public static final String And = "and"; -} \ No newline at end of file From 9e1bf29ecdbdeb22b8e45b07ea50ce03fe6c7b0d Mon Sep 17 00:00:00 2001 From: Sulejman Karisik Date: Mon, 10 Jun 2024 16:30:46 +0200 Subject: [PATCH 5/5] fix: tests and use enum --- .../discovery/services/CkanFacetsQueryBuilder.java | 2 +- .../discovery/services/CkanQueryOperatorMapper.java | 5 +++-- src/main/openapi/discovery.yaml | 6 +++++- .../discovery/services/CkanFacetsQueryBuilderTest.java | 10 ++++++---- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilder.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilder.java index 779a200..45a4719 100644 --- a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilder.java +++ b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilder.java @@ -47,7 +47,7 @@ private Boolean isCkanGroupAndFacetIsNotBlank(DatasetSearchQueryFacet facet) { } private String getFacetQuery(String key, List facets, - String operator) { + DatasetSearchQuery.OperatorEnum operator) { var values = facets.stream() .map(facet -> QUOTED_VALUE.formatted(facet.getValue())) .collect(joining(CkanQueryOperatorMapper.getOperator(operator))); diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperatorMapper.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperatorMapper.java index 9da756c..ea992d0 100644 --- a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperatorMapper.java +++ b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/CkanQueryOperatorMapper.java @@ -4,6 +4,7 @@ package io.github.genomicdatainfrastructure.discovery.services; +import io.github.genomicdatainfrastructure.discovery.model.DatasetSearchQuery; import lombok.experimental.UtilityClass; @UtilityClass @@ -12,7 +13,7 @@ public class CkanQueryOperatorMapper { private final String AND = " AND "; private final String OR = " OR "; - public String getOperator(String operator) { - return operator.equals(CkanQueryOperator.Or) ? OR : AND; + public String getOperator(DatasetSearchQuery.OperatorEnum operator) { + return operator.equals(DatasetSearchQuery.OperatorEnum.OR) ? OR : AND; } } diff --git a/src/main/openapi/discovery.yaml b/src/main/openapi/discovery.yaml index f2307b4..1d76080 100644 --- a/src/main/openapi/discovery.yaml +++ b/src/main/openapi/discovery.yaml @@ -113,8 +113,12 @@ components: default: 0 minimum: 0 operator: + title: Ckan query operator type: string - default: "and" + enum: + - AND + - OR + default: AND DatasetSearchQueryFacet: type: object properties: diff --git a/src/test/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilderTest.java b/src/test/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilderTest.java index 29101e0..1fb6a76 100644 --- a/src/test/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilderTest.java +++ b/src/test/java/io/github/genomicdatainfrastructure/discovery/services/CkanFacetsQueryBuilderTest.java @@ -20,15 +20,17 @@ class CkanFacetsQueryBuilderTest { @Test void can_parse_if_empty_list() { + var query = new DatasetSearchQuery(); + query.setFacets(List.of()); var expected = ""; - var actual = CkanFacetsQueryBuilder.buildFacetQuery(null); + var actual = CkanFacetsQueryBuilder.buildFacetQuery(query); assertEquals(expected, actual); } @Test void can_parse_if_null_list() { String expected = ""; - var actual = CkanFacetsQueryBuilder.buildFacetQuery(null); + var actual = CkanFacetsQueryBuilder.buildFacetQuery(new DatasetSearchQuery()); assertEquals(expected, actual); } @@ -50,7 +52,7 @@ void can_parse_with_and_operator(String value) { var query = new DatasetSearchQuery(); query.setFacets(facets); - query.setOperator(CkanQueryOperator.And); + query.setOperator(DatasetSearchQuery.OperatorEnum.AND); var expected = "field1:(\"value1\" AND \"value2\") AND field2:(\"value3\")"; var actual = CkanFacetsQueryBuilder.buildFacetQuery(query); @@ -75,7 +77,7 @@ void can_parse_with_or_operator(String value) { var query = new DatasetSearchQuery(); query.setFacets(facets); - query.setOperator(CkanQueryOperator.Or); + query.setOperator(DatasetSearchQuery.OperatorEnum.OR); var expected = "field1:(\"value1\" OR \"value2\") OR field2:(\"value3\")"; var actual = CkanFacetsQueryBuilder.buildFacetQuery(query);