Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/maven/org.openapitools-openapi-…
Browse files Browse the repository at this point in the history
…generator-maven-plugin-7.5.0
  • Loading branch information
viacheslavkol authored May 2, 2024
2 parents e166836 + 7b4d410 commit 33c015a
Show file tree
Hide file tree
Showing 9 changed files with 256 additions and 21 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
<maven-surefire-plugin.version>3.2.5</maven-surefire-plugin.version>
<maven-failsafe-plugin.version>3.2.5</maven-failsafe-plugin.version>
<maven-release-plugin.version>3.0.1</maven-release-plugin.version>
<checkstyle.version>10.15.0</checkstyle.version>
<checkstyle.version>10.16.0</checkstyle.version>
</properties>

<dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,12 @@ public <T> Set<InstanceSubResource> filterSubResourcesForConsortium(
var subResources = subResourceExtractor.apply(resource);
var contextTenantId = folioExecutionContext.getTenantId();
var centralTenantId = consortiumTenantService.getCentralTenant(contextTenantId);
if (centralTenantId.isEmpty() || contextTenantId.equals(centralTenantId.get())) {
if (centralTenantId.isEmpty()) {
return subResources;
} else if (contextTenantId.equals(centralTenantId.get())) {
return subResources.stream()
.filter(InstanceSubResource::getShared)
.collect(Collectors.toSet());
}

var sharedFilter = getBrowseSharedFilter(context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

import static org.folio.search.client.InventoryReferenceDataClient.ReferenceDataType.CALL_NUMBER_TYPES;
import static org.folio.search.model.client.CqlQueryParam.SOURCE;
import static org.folio.search.model.types.CallNumberTypeSource.LOCAL;
import static org.folio.search.service.browse.CallNumberBrowseService.FOLIO_CALL_NUMBER_TYPES_SOURCES;
import static org.folio.search.utils.CollectionUtils.toLinkedHashSet;
import static org.folio.search.utils.CollectionUtils.toStreamSafe;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
Expand All @@ -24,8 +22,6 @@
@RequiredArgsConstructor
public class CallNumberTypeProcessor implements FieldProcessor<Instance, Set<String>> {

static final List<String> LOCAL_CALL_NUMBER_TYPES_SOURCES = Collections.singletonList(LOCAL.getSource());

private final ReferenceDataService referenceDataService;

@Override
Expand All @@ -45,16 +41,15 @@ private String itemToCallNumberTypeString(Item item) {
}

private String callNumberTypeIdToString(String callNumberTypeId) {
if (isLocalCallNumberTypeId(callNumberTypeId)) {
return CallNumberType.LOCAL.toString();
}
return CallNumberType.fromId(callNumberTypeId)
.map(CallNumberType::toString)
.or(() -> isLocalCallNumberTypeId(callNumberTypeId)
? Optional.of(CallNumberType.LOCAL.toString()) : Optional.empty())
.orElse(null);
}

private boolean isLocalCallNumberTypeId(String callNumberTypeId) {
return referenceDataService.fetchReferenceData(CALL_NUMBER_TYPES, SOURCE, LOCAL_CALL_NUMBER_TYPES_SOURCES)
return !referenceDataService.fetchReferenceData(CALL_NUMBER_TYPES, SOURCE, FOLIO_CALL_NUMBER_TYPES_SOURCES)
.contains(callNumberTypeId);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package org.folio.search.controller;

import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
import static org.awaitility.Durations.TWO_HUNDRED_MILLISECONDS;
import static org.awaitility.Durations.TWO_MINUTES;
import static org.folio.search.support.base.ApiEndpoints.instanceSearchPath;
import static org.folio.search.support.base.ApiEndpoints.recordFacetsPath;
import static org.folio.search.utils.SearchUtils.getIndexName;
import static org.folio.search.utils.TestConstants.CENTRAL_TENANT_ID;
import static org.folio.search.utils.TestConstants.FOLIO_CN_TYPE;
import static org.folio.search.utils.TestConstants.LOCAL_CN_TYPE;
import static org.folio.search.utils.TestConstants.MEMBER_TENANT_ID;
import static org.folio.search.utils.TestUtils.array;
import static org.folio.search.utils.TestUtils.facet;
import static org.folio.search.utils.TestUtils.facetItem;
import static org.folio.search.utils.TestUtils.mapOf;
import static org.folio.search.utils.TestUtils.parseResponse;
import static org.folio.search.utils.TestUtils.randomId;
import static org.junit.jupiter.params.provider.Arguments.arguments;
import static org.opensearch.index.query.QueryBuilders.matchAllQuery;
import static org.opensearch.search.builder.SearchSourceBuilder.searchSource;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Stream;
import org.assertj.core.util.Lists;
import org.folio.search.domain.dto.Facet;
import org.folio.search.domain.dto.FacetResult;
import org.folio.search.domain.dto.Holding;
import org.folio.search.domain.dto.Instance;
import org.folio.search.domain.dto.Item;
import org.folio.search.domain.dto.ItemEffectiveCallNumberComponents;
import org.folio.search.domain.dto.RecordType;
import org.folio.search.support.base.BaseConsortiumIntegrationTest;
import org.folio.search.utils.SearchUtils;
import org.folio.spring.testing.type.IntegrationTest;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.opensearch.action.search.SearchRequest;
import org.opensearch.client.RequestOptions;
import org.opensearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;

@IntegrationTest
class BrowseCallNumberConsortiumIT extends BaseConsortiumIntegrationTest {


private static final String[] LOCATIONS = array("location 1", "location 2");
private static final Instance[] INSTANCES_CENTRAL = instancesCentral();
private static final Instance[] INSTANCES_MEMBER = instancesMember();


@BeforeAll
static void prepare(@Autowired RestHighLevelClient restHighLevelClient) throws InterruptedException {
setUpTenant(CENTRAL_TENANT_ID, INSTANCES_CENTRAL);
setUpTenant(MEMBER_TENANT_ID);
saveRecords(MEMBER_TENANT_ID, instanceSearchPath(), asList(INSTANCES_MEMBER),
4,
instance -> inventoryApi.createInstance(MEMBER_TENANT_ID, instance));

await().atMost(TWO_MINUTES).pollInterval(TWO_HUNDRED_MILLISECONDS).untilAsserted(() -> {
var searchRequest = new SearchRequest()
.source(searchSource().query(matchAllQuery()).trackTotalHits(true).from(0))
.indices(getIndexName(SearchUtils.INSTANCE_RESOURCE, CENTRAL_TENANT_ID));
var searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
assertThat(searchResponse.getHits().getTotalHits().value).isEqualTo(4);
});
}

@AfterAll
static void cleanUp() {
removeTenant();
}

@MethodSource("facetQueriesProvider")
@ParameterizedTest(name = "[{index}] query={0}, facets={1}")
@DisplayName("getFacetsForInstances_parameterized")
void getFacetsForInstances_positive(String tenantId, String query, String[] facets, Map<String, Facet> expected) {
var actual = parseResponse(
doGet(recordFacetsPath(RecordType.INSTANCES, query, facets), tenantId), FacetResult.class);

expected.forEach((facetName, expectedFacet) -> {
var actualFacet = actual.getFacets().get(facetName);

assertThat(actualFacet).isNotNull();
assertThat(actualFacet.getValues())
.containsExactlyInAnyOrderElementsOf(expectedFacet.getValues());
});
}

private static Stream<Arguments> facetQueriesProvider() {
return Stream.of(
arguments(CENTRAL_TENANT_ID, "cql.allRecords=1", array("item.effectiveLocationId"), mapOf(
"items.effectiveLocationId", facet(facetItem(LOCATIONS[0], 1), facetItem(LOCATIONS[1], 1)))),
arguments(CENTRAL_TENANT_ID, "cql.allRecords=1", array("holdings.tenantId"), mapOf(
"holdings.tenantId", facet(facetItem(CENTRAL_TENANT_ID, 1), facetItem(MEMBER_TENANT_ID, 1)))),
arguments(CENTRAL_TENANT_ID, "callNumberType=\"local\"", array("item.effectiveLocationId"), mapOf(
"items.effectiveLocationId", facet(facetItem(LOCATIONS[0], 1), facetItem(LOCATIONS[1], 1)))),
arguments(CENTRAL_TENANT_ID, "callNumberType=\"local\"", array("holdings.tenantId"), mapOf(
"holdings.tenantId", facet(facetItem(CENTRAL_TENANT_ID, 1), facetItem(MEMBER_TENANT_ID, 1)))),
arguments(MEMBER_TENANT_ID, "cql.allRecords=1", array("item.effectiveLocationId"), mapOf(
"items.effectiveLocationId", facet(facetItem(LOCATIONS[0], 3), facetItem(LOCATIONS[1], 1)))),
arguments(MEMBER_TENANT_ID, "cql.allRecords=1", array("holdings.tenantId"), mapOf(
"holdings.tenantId", facet(facetItem(CENTRAL_TENANT_ID, 1), facetItem(MEMBER_TENANT_ID, 3)))),
arguments(MEMBER_TENANT_ID, "callNumberType=\"local\"", array("item.effectiveLocationId"), mapOf(
"items.effectiveLocationId", facet(facetItem(LOCATIONS[0], 2), facetItem(LOCATIONS[1], 1)))),
arguments(MEMBER_TENANT_ID, "callNumberType=\"local\"", array("holdings.tenantId"), mapOf(
"holdings.tenantId", facet(facetItem(CENTRAL_TENANT_ID, 1), facetItem(MEMBER_TENANT_ID, 2))))
);
}

private static Instance[] instancesCentral() {
return Stream.of(
Lists.list("instance #01", CENTRAL_TENANT_ID, null, null, List.of()),
List.of("instance #02", CENTRAL_TENANT_ID, LOCAL_CN_TYPE, LOCATIONS[0], List.of("central")))
.map(BrowseCallNumberConsortiumIT::instance)
.toArray(Instance[]::new);
}

private static Instance[] instancesMember() {
return Stream.of(
List.of("instance #02", MEMBER_TENANT_ID, LOCAL_CN_TYPE, LOCATIONS[1], List.of("member 1", "member 2")),
List.of("instance #03", MEMBER_TENANT_ID, LOCAL_CN_TYPE, LOCATIONS[0], List.of("member 3")),
List.of("instance #04", MEMBER_TENANT_ID, FOLIO_CN_TYPE, LOCATIONS[0], List.of("member 4")))
.map(BrowseCallNumberConsortiumIT::instance)
.toArray(Instance[]::new);
}

@SuppressWarnings("unchecked")
private static Instance instance(List<Object> data) {
var tenantId = (String) data.get(1);
var items = ((List<String>) data.get(4)).stream()
.map(callNumber -> new Item()
.tenantId(tenantId)
.id(randomId())
.discoverySuppress(false)
.effectiveCallNumberComponents(new ItemEffectiveCallNumberComponents()
.callNumber(callNumber).typeId(String.valueOf(data.get(2))))
.effectiveLocationId(String.valueOf(data.get(3)))
.effectiveShelvingOrder(callNumber))
.toList();
var holdings = ((List<String>) data.get(4)).stream()
.map(callNumber -> new Holding()
.tenantId(tenantId)
.id(randomId())
)
.toList();

var title = (String) data.get(0);
return new Instance()
.id(title.equals("instance #02") ? "840d391f-ae06-4cbc-b66b-0ad317d193a2" : UUID.randomUUID().toString())
.title(title)
.staffSuppress(false)
.discoverySuppress(false)
.isBoundWith(false)
.shared(CENTRAL_TENANT_ID.equals(tenantId))
.tenantId(tenantId)
.items(items)
.holdings(holdings);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import static org.folio.search.model.types.CallNumberType.OTHER;
import static org.folio.search.model.types.CallNumberType.SUDOC;
import static org.folio.search.support.base.ApiEndpoints.instanceCallNumberBrowsePath;
import static org.folio.search.utils.TestConstants.FOLIO_CN_TYPE;
import static org.folio.search.utils.TestConstants.LOCAL_CN_TYPE;
import static org.folio.search.utils.TestConstants.TENANT_ID;
import static org.folio.search.utils.TestUtils.cnBrowseItem;
import static org.folio.search.utils.TestUtils.getShelfKeyFromCallNumber;
Expand Down Expand Up @@ -39,9 +41,7 @@
@IntegrationTest
class BrowseTypedCallNumberIT extends BaseIntegrationTest {

private static final String LOCAL_TYPE_1 = "6fd29f52-5c9c-44d0-b529-e9c5eb3a0aba";
private static final String LOCAL_TYPE_2 = "654d7565-b277-4dfa-8b7d-fbf306d9d0cd";
private static final String FOLIO_TYPE = "6e4d7565-b277-4dfa-8b7d-fbf306d9d0cd";
private static final Instance[] INSTANCES = instances();
private static final Map<String, Instance> INSTANCE_MAP =
Arrays.stream(INSTANCES).collect(toMap(Instance::getTitle, identity()));
Expand Down Expand Up @@ -289,17 +289,17 @@ private static List<List<Object>> callNumberBrowseInstanceData() {
List.of("instance #20", List.of(List.of("DA 3880 O6 L75", LC.getId()))),
List.of("instance #21", List.of(List.of("FC 17 B89", OTHER.getId()))),
List.of("instance #22", List.of(List.of("DA 3890 A2 B76 42002", LC.getId()))),
List.of("instance #23", List.of(List.of("DB 11 A66 SUPPL NO 11", LOCAL_TYPE_1))),
List.of("instance #23", List.of(List.of("DB 11 A66 SUPPL NO 11", LOCAL_CN_TYPE))),
List.of("instance #24", List.of(List.of("DA 3900 C39 NO 11", LC.getId()))),
List.of("instance #25", List.of(List.of("AC 11 A4 VOL 235", NLM.getId()))),
List.of("instance #26", List.of(List.of("PR 17 I55 42006", LOCAL_TYPE_1))),
List.of("instance #27", List.of(List.of("E 211 A506", LOCAL_TYPE_1), List.of("E 311 A506", FOLIO_TYPE))),
List.of("instance #26", List.of(List.of("PR 17 I55 42006", LOCAL_CN_TYPE))),
List.of("instance #27", List.of(List.of("E 211 A506", LOCAL_CN_TYPE), List.of("E 311 A506", FOLIO_CN_TYPE))),
List.of("instance #28", List.of(List.of("DB 11 A31 BD 3124", LOCAL_TYPE_2))),
List.of("instance #29", List.of(List.of("DA 3880 O6 D5", LC.getId()))),
List.of("instance #30", List.of(List.of("GA 16 G32 41557 V1", LOCAL_TYPE_2))),
List.of("instance #31", List.of(List.of("AB 14 C72 NO 220", LOCAL_TYPE_1))),
List.of("instance #31", List.of(List.of("AB 14 C72 NO 220", LOCAL_CN_TYPE))),
List.of("instance #32", List.of(List.of("DA 3880 O5 C3 V1", LC.getId()))),
List.of("instance #33", List.of(List.of("E 12.11 I2 298", LOCAL_TYPE_1))),
List.of("instance #33", List.of(List.of("E 12.11 I2 298", LOCAL_CN_TYPE))),
List.of("instance #34", List.of(List.of("DA 3900 C89 V1", LC.getId()))),
List.of("instance #35", List.of(List.of("E 12.11 I12 288 D", LOCAL_TYPE_2))),
List.of("instance #36", List.of(List.of("DA 3700 B91 L79", LC.getId()))),
Expand All @@ -312,7 +312,7 @@ private static List<List<Object>> callNumberBrowseInstanceData() {
List.of("instance #43", List.of(List.of("FA 42010 3546 256", OTHER.getId()))),
List.of("instance #44", List.of(List.of("1CE 16 B6713 X 41993", DEWEY.getId()))),
List.of("instance #45", List.of(List.of("1CE 16 B6724 41993", DEWEY.getId()))),
List.of("instance #46", List.of(List.of("F PR1866.S63 V.1 C.1", LOCAL_TYPE_1))),
List.of("instance #46", List.of(List.of("F PR1866.S63 V.1 C.1", LOCAL_CN_TYPE))),
List.of("instance #47", List.of(List.of("1CE 16 B6724 41993", DEWEY.getId()))),
List.of("instance #48", List.of(List.of("A 123.4", DEWEY.getId()))),
List.of("instance #49", List.of(List.of("A 123.5", DEWEY.getId())))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import static org.awaitility.Durations.FIVE_SECONDS;
import static org.awaitility.Durations.ONE_HUNDRED_MILLISECONDS;
import static org.awaitility.Durations.ONE_MINUTE;
import static org.awaitility.Durations.TEN_SECONDS;
import static org.folio.search.utils.KafkaConstants.AUTHORITY_LISTENER_ID;
import static org.folio.search.utils.KafkaConstants.EVENT_LISTENER_ID;
import static org.folio.search.utils.SearchResponseHelper.getSuccessIndexOperationResponse;
Expand Down Expand Up @@ -191,7 +190,7 @@ void handleInstanceEvents_positive_splittingBatchToTheParts() {
inventoryInstanceTopic(), KafkaMessageListenerIT::instanceEvent);

var expectedEvents = ids.stream().map(KafkaMessageListenerIT::instanceEvent).toList();
await().atMost(TEN_SECONDS).pollInterval(ONE_HUNDRED_MILLISECONDS).untilAsserted(() -> {
await().atMost(ONE_MINUTE).pollInterval(ONE_HUNDRED_MILLISECONDS).untilAsserted(() -> {
verify(resourceService).indexInstancesById(List.of(expectedEvents.get(0)));
verify(resourceService).indexInstancesById(List.of(expectedEvents.get(1)));
verify(resourceService, times(3)).indexInstancesById(List.of(expectedEvents.get(2)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,21 @@ void filterSubResourcesForConsortium_positive_notConsortiumTenant() {
assertThat(actual).isEqualTo(resource.getInstances());
}

@Test
void filterSubResourcesForConsortium_positive_centralTenant() {
when(context.getTenantId()).thenReturn(CENTRAL_TENANT_ID);
when(tenantService.getCentralTenant(CENTRAL_TENANT_ID)).thenReturn(Optional.of(CENTRAL_TENANT_ID));

var browseContext = browseContext(null, null);
var resource = new SubjectResource();
resource.setInstances(subResources());

var actual = consortiumSearchHelper.filterSubResourcesForConsortium(browseContext, resource,
SubjectResource::getInstances);

assertThat(actual).hasSize(2);
}

@Test
void filterSubResourcesForConsortium_positive_memberTenant() {
when(context.getTenantId()).thenReturn(TENANT_ID);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.folio.search.service.setter.item;

import static org.assertj.core.api.Assertions.assertThat;
import static org.folio.search.client.InventoryReferenceDataClient.ReferenceDataType.CALL_NUMBER_TYPES;
import static org.folio.search.model.client.CqlQueryParam.SOURCE;
import static org.folio.search.model.types.CallNumberType.LC;
import static org.folio.search.model.types.CallNumberType.LOCAL;
import static org.folio.search.service.browse.CallNumberBrowseService.FOLIO_CALL_NUMBER_TYPES_SOURCES;
import static org.mockito.Mockito.when;

import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.folio.search.domain.dto.Instance;
import org.folio.search.domain.dto.Item;
import org.folio.search.domain.dto.ItemEffectiveCallNumberComponents;
import org.folio.search.integration.ReferenceDataService;
import org.folio.spring.testing.type.UnitTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@UnitTest
@ExtendWith(MockitoExtension.class)
class CallNumberTypeProcessorTest {

private @Mock ReferenceDataService referenceDataService;
private @InjectMocks CallNumberTypeProcessor processor;

@Test
void getFieldValue_multipleValue_positive() {
var folioTypeId = UUID.randomUUID().toString();
var eventBody = instance(item("95467209-6d7b-468b-94df-0f5d7ad2747d"), item(folioTypeId),
item(UUID.randomUUID().toString()));
when(referenceDataService.fetchReferenceData(CALL_NUMBER_TYPES, SOURCE, FOLIO_CALL_NUMBER_TYPES_SOURCES))
.thenReturn(Set.of(folioTypeId));

var actual = processor.getFieldValue(eventBody);
assertThat(actual).containsExactly(LC.toString(), LOCAL.toString());
}

private static Instance instance(Item... items) {
return new Instance().items(List.of(items));
}

private static Item item(String typeId) {
return new Item().effectiveCallNumberComponents(new ItemEffectiveCallNumberComponents().typeId(typeId));
}
}
3 changes: 3 additions & 0 deletions src/test/java/org/folio/search/utils/TestConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ public class TestConstants {
public static final String INVENTORY_CLASSIFICATION_TYPE_TOPIC = "inventory.classification-type";
public static final String CONSORTIUM_INSTANCE_TOPIC = "search.consortium.instance";

public static final String LOCAL_CN_TYPE = "6fd29f52-5c9c-44d0-b529-e9c5eb3a0aba";
public static final String FOLIO_CN_TYPE = "6e4d7565-b277-4dfa-8b7d-fbf306d9d0cd";

public static final String LCCN_IDENTIFIER_TYPE_ID = randomId();
public static final String ISSN_IDENTIFIER_TYPE_ID = randomId();
public static final String ISBN_IDENTIFIER_TYPE_ID = randomId();
Expand Down

0 comments on commit 33c015a

Please sign in to comment.