Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended authority mapping #769

Open
wants to merge 6 commits into
base: release/2024_R1_v20.2.0_Quesnelia
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## 20.2.7 2024-06-26
* [MODDATAIMP-1046](https://folio-org.atlassian.net/browse/MODDATAIMP-1046) Reorder only 00X fields while preserving system order for all other
* [MODINV-1071](https://folio-org.atlassian.net/browse/MODINV-1071) Extend Authority with Additional fields

## 20.2.6 2024-05-29
* [MODDATAIMP-1052](https://folio-org.atlassian.net/browse/MODDATAIMP-1052) Fix editing shared Instance via quickMARC from Member tenant
Expand Down
13 changes: 13 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,19 @@ After setup, it is good to check logs in all related modules for errors.
* DI_SRS_MARC_BIB_RECORD_MODIFIED_PARTITIONS
Default value for all partitions is 1

## Properties

`AUTHORITY_EXTENDED` environment variable enables extended mapping for Authority to support advanced references classification in 5xx fields:
* broader terms (`$wg` tag)
* narrower terms (`$wh` tag)
* earlier headings (`$wa` tag)
* later headings (`$wb` tag)
* saft*Trunc for every saft* field with "i" and numeric subfields excluded

Default value for `AUTHORITY_EXTENDED` is `false`.
The mapping itself is implemented in [data-import-processing-core](https://github.com/folio-org/data-import-processing-core).


# Making Requests

These modules provide HTTP based APIs rather than any UI themselves.
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@
<liquibase.version>4.9.1</liquibase.version>
<kafkaclients.version>3.1.0</kafkaclients.version>
<junit.version>4.13.2</junit.version>
<data-import-processing-core.version>4.2.0</data-import-processing-core.version>
<data-import-processing-core.version>4.2.5-LOC-SNAPSHOT</data-import-processing-core.version>
</properties>

<distributionManagement>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.apache.logging.log4j.Logger;

import org.folio.ActionProfile;
import org.folio.ActionProfile.FolioRecord;
import org.folio.Authority;
import org.folio.DataImportEventPayload;
import org.folio.MappingMetadataDto;
Expand Down Expand Up @@ -54,9 +55,11 @@ public abstract class AbstractAuthorityEventHandler implements EventHandler {

private static final String RECORD_ID_HEADER = "recordId";
private static final String CHUNK_ID_HEADER = "chunkId";
public static final String AUTHORITY_EXTENDED = "AUTHORITY_EXTENDED";

private final Storage storage;
private final MappingMetadataCache mappingMetadataCache;
public static boolean isAuthorityExtended = isAuthorityExtendedMode();

protected AbstractAuthorityEventHandler(Storage storage, MappingMetadataCache mappingMetadataCache) {
this.storage = storage;
Expand Down Expand Up @@ -161,7 +164,9 @@ private Future<Authority> mapAuthority(DataImportEventPayload payload, MappingMe
var mappingParameters = Json.decodeValue(mappingMetadata.getMappingParams(), MappingParameters.class);
var parsedRecord = new JsonObject((String) new JsonObject(payload.getContext().get(sourceRecordType().value()))
.mapTo(Record.class).getParsedRecord().getContent());
RecordMapper<Authority> recordMapper = RecordMapperBuilder.buildMapper(sourceRecordType().value());
RecordMapper<Authority> recordMapper = isAuthorityExtended
? RecordMapperBuilder.buildMapper(FolioRecord.MARC_AUTHORITY_EXTENDED.value())
: RecordMapperBuilder.buildMapper(sourceRecordType().value());
var authority = recordMapper.mapRecord(parsedRecord, mappingParameters, mappingRules);
authority.setSource(Authority.Source.MARC);
return Future.succeededFuture(authority);
Expand Down Expand Up @@ -215,4 +220,21 @@ private String constructMetaInfoMsg(DataImportEventPayload payload) {
getChunkIdHeader(payload)
);
}

private static boolean isAuthorityExtendedMode() {
return Boolean.parseBoolean(
System.getenv().getOrDefault(AUTHORITY_EXTENDED, "false"));
}

/**
* For test usage only.
*
* @param newIsAuthoritiesExtended New value for the env to set.
*/
public static void setAuthorityExtendedMode(boolean newIsAuthoritiesExtended) {
isAuthorityExtended = newIsAuthoritiesExtended;
}
public static boolean getIsAuthorityExtended() {
return isAuthorityExtended;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.apache.http.HttpStatus;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.folio.ActionProfile.FolioRecord;
import org.folio.Authority;
import org.folio.inventory.common.Context;
import org.folio.inventory.dataimport.exceptions.DataImportException;
Expand All @@ -21,6 +22,7 @@
import java.util.Map;

import static java.lang.String.format;
import static org.folio.inventory.dataimport.handlers.actions.AbstractAuthorityEventHandler.getIsAuthorityExtended;
import static org.folio.inventory.dataimport.util.LoggerUtil.logParametersUpdateDelegate;

public class AuthorityUpdateDelegate {
Expand Down Expand Up @@ -48,7 +50,9 @@ public Future<Authority> handle(Map<String, String> eventPayload, Record marcRec
JsonObject parsedRecord = retrieveParsedContent(marcRecord.getParsedRecord());
String authorityId = marcRecord.getExternalIdsHolder().getAuthorityId();
LOGGER.info("Authority update with authorityId: {}", authorityId);
RecordMapper<Authority> recordMapper = RecordMapperBuilder.buildMapper(MARC_FORMAT);
RecordMapper<Authority> recordMapper = getIsAuthorityExtended()
? RecordMapperBuilder.buildMapper(FolioRecord.MARC_AUTHORITY_EXTENDED.value())
: RecordMapperBuilder.buildMapper(MARC_FORMAT);
var mappedAuthority = recordMapper.mapRecord(parsedRecord, mappingParameters, mappingRules);
AuthorityRecordCollection authorityRecordCollection = storage.getAuthorityRecordCollection(context);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import io.vertx.core.Vertx;
import io.vertx.core.json.Json;
import io.vertx.core.json.JsonObject;
import java.util.Arrays;
import java.util.Collection;
import org.folio.ActionProfile;
import org.folio.Authority;
import org.folio.DataImportEventPayload;
Expand All @@ -28,9 +30,12 @@
import org.folio.rest.jaxrs.model.ParsedRecord;
import org.folio.rest.jaxrs.model.ProfileSnapshotWrapper;
import org.folio.rest.jaxrs.model.Record;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

Expand Down Expand Up @@ -70,11 +75,13 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(Parameterized.class)
public class UpdateAuthorityEventHandlerTest {

private static final String MAPPING_RULES_PATH = "src/test/resources/handlers/marc-authority-rules.json";
private static final String PARSED_AUTHORITY_RECORD = "src/test/resources/marc/authority/parsed-authority-record.json";
private static final String MAPPING_METADATA_URL = "/mapping-metadata";
private final boolean isAuthorityExtended;

private final Vertx vertx = Vertx.vertx();
@Rule
Expand Down Expand Up @@ -112,6 +119,15 @@ public class UpdateAuthorityEventHandlerTest {

private UpdateAuthorityEventHandler eventHandler;

public UpdateAuthorityEventHandlerTest(boolean isAuthorityExtended) {
this.isAuthorityExtended = isAuthorityExtended;
}

@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{{true}, {false}});
}

@Before
public void setUp() throws IOException {
MockitoAnnotations.openMocks(this);
Expand All @@ -130,6 +146,13 @@ public void setUp() throws IOException {
.willReturn(WireMock.ok().withBody(Json.encode(new MappingMetadataDto()
.withMappingParams(Json.encode(new MappingParameters()))
.withMappingRules(mappingRules.encode())))));

AbstractAuthorityEventHandler.setAuthorityExtendedMode(isAuthorityExtended);
}

@After
public void tearDown() {
AbstractAuthorityEventHandler.setAuthorityExtendedMode(false);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,19 @@

import io.vertx.core.Future;
import io.vertx.core.json.JsonObject;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.folio.inventory.dataimport.exceptions.OptimisticLockingException;
import org.folio.inventory.dataimport.handlers.actions.AbstractAuthorityEventHandler;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.junit.MockitoJUnit;

import org.folio.Authority;
import org.folio.inventory.TestUtil;
Expand All @@ -31,8 +35,9 @@
import org.folio.inventory.dataimport.handlers.quickmarc.UpdateAuthorityQuickMarcEventHandler;
import org.folio.inventory.domain.AuthorityRecordCollection;
import org.folio.inventory.storage.Storage;
import org.mockito.junit.MockitoRule;

@RunWith(MockitoJUnitRunner.class)
@RunWith(JUnitParamsRunner.class)
public class UpdateAuthorityQuickMarcEventHandlerTest {

private static final String MAPPING_RULES_PATH = "src/test/resources/handlers/authority-rules.json";
Expand All @@ -54,6 +59,9 @@ public class UpdateAuthorityQuickMarcEventHandlerTest {
private JsonObject record;
private Authority existingAuthority;

@Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();

@Before
public void setUp() throws IOException {
existingAuthority = new JsonObject(TestUtil.readFileFromPath(AUTHORITY_PATH)).mapTo(Authority.class);
Expand Down Expand Up @@ -83,7 +91,9 @@ record = new JsonObject(TestUtil.readFileFromPath(RECORD_PATH));
}

@Test
public void shouldProcessEvent() {
@Parameters({"true", "false"})
public void shouldProcessEvent(String isAuthorityExtendedMode) {
AbstractAuthorityEventHandler.setAuthorityExtendedMode(Boolean.parseBoolean(isAuthorityExtendedMode));
HashMap<String, String> eventPayload = new HashMap<>();
eventPayload.put("RECORD_TYPE", "MARC_AUTHORITY");
eventPayload.put("MARC_AUTHORITY", record.encode());
Expand All @@ -107,6 +117,7 @@ public void shouldProcessEvent() {
Assert.assertEquals("token", argument.getValue().getToken());
Assert.assertEquals("dummy", argument.getValue().getTenantId());
Assert.assertEquals("http://localhost", argument.getValue().getOkapiLocation());
AbstractAuthorityEventHandler.setAuthorityExtendedMode(false);
}

@Test
Expand Down