Search in sources :

Example 1 with MappingParameters

use of org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters in project mod-inventory by folio-org.

the class CreateHoldingEventHandler method handle.

@Override
public CompletableFuture<DataImportEventPayload> handle(DataImportEventPayload dataImportEventPayload) {
    CompletableFuture<DataImportEventPayload> future = new CompletableFuture<>();
    try {
        dataImportEventPayload.setEventType(DI_INVENTORY_HOLDING_CREATED.value());
        HashMap<String, String> payloadContext = dataImportEventPayload.getContext();
        if (payloadContext == null || payloadContext.isEmpty() || StringUtils.isEmpty(payloadContext.get(MARC_BIBLIOGRAPHIC.value()))) {
            throw new EventProcessingException(CONTEXT_EMPTY_ERROR_MESSAGE);
        }
        if (dataImportEventPayload.getCurrentNode().getChildSnapshotWrappers().isEmpty()) {
            LOGGER.error(ACTION_HAS_NO_MAPPING_MSG);
            return CompletableFuture.failedFuture(new EventProcessingException(ACTION_HAS_NO_MAPPING_MSG));
        }
        Context context = constructContext(dataImportEventPayload.getTenant(), dataImportEventPayload.getToken(), dataImportEventPayload.getOkapiUrl());
        String jobExecutionId = dataImportEventPayload.getJobExecutionId();
        String recordId = payloadContext.get(RECORD_ID_HEADER);
        String chunkId = payloadContext.get(CHUNK_ID_HEADER);
        Future<RecordToEntity> recordToHoldingsFuture = idStorageService.store(recordId, UUID.randomUUID().toString(), dataImportEventPayload.getTenant());
        recordToHoldingsFuture.onSuccess(res -> {
            String holdingsId = res.getEntityId();
            mappingMetadataCache.get(jobExecutionId, context).map(parametersOptional -> parametersOptional.orElseThrow(() -> new EventProcessingException(format(MAPPING_METADATA_NOT_FOUND_MSG, jobExecutionId, recordId, chunkId)))).map(mappingMetadataDto -> {
                prepareEvent(dataImportEventPayload);
                MappingParameters mappingParameters = Json.decodeValue(mappingMetadataDto.getMappingParams(), MappingParameters.class);
                MappingManager.map(dataImportEventPayload, new MappingContext().withMappingParameters(mappingParameters));
                JsonObject holdingAsJson = new JsonObject(payloadContext.get(HOLDINGS.value()));
                if (holdingAsJson.getJsonObject(HOLDINGS_PATH_FIELD) != null) {
                    holdingAsJson = holdingAsJson.getJsonObject(HOLDINGS_PATH_FIELD);
                }
                holdingAsJson.put("id", holdingsId);
                holdingAsJson.put("sourceId", FOLIO_SOURCE_ID);
                fillInstanceIdIfNeeded(dataImportEventPayload, holdingAsJson);
                checkIfPermanentLocationIdExists(holdingAsJson);
                return Json.decodeValue(payloadContext.get(HOLDINGS.value()), HoldingsRecord.class);
            }).compose(holdingToCreate -> addHoldings(holdingToCreate, context)).onSuccess(createdHoldings -> {
                LOGGER.info("Created Holding record by jobExecutionId: '{}' and recordId: '{}' and chunkId: '{}'", jobExecutionId, recordId, chunkId);
                payloadContext.put(HOLDINGS.value(), Json.encodePrettily(createdHoldings));
                future.complete(dataImportEventPayload);
            }).onFailure(e -> {
                if (!(e instanceof DuplicateEventException)) {
                    LOGGER.error("Error creating inventory Holding record by jobExecutionId: '{}' and recordId: '{}' and chunkId: '{}' ", jobExecutionId, recordId, chunkId, e);
                }
                future.completeExceptionally(e);
            });
        }).onFailure(failure -> {
            LOGGER.error("Error creating inventory recordId and holdingsId relationship by jobExecutionId: '{}' and recordId: '{}' and chunkId: '{}' ", jobExecutionId, recordId, chunkId, failure);
            future.completeExceptionally(failure);
        });
    } catch (Exception e) {
        LOGGER.error(CREATE_HOLDING_ERROR_MESSAGE, e);
        future.completeExceptionally(e);
    }
    return future;
}
Also used : Context(org.folio.inventory.common.Context) EventHandlingUtil.constructContext(org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.constructContext) MappingContext(org.folio.processing.mapping.mapper.MappingContext) ParsedRecordUtil(org.folio.inventory.dataimport.util.ParsedRecordUtil) Json(io.vertx.core.json.Json) Context(org.folio.inventory.common.Context) EventHandler(org.folio.processing.events.services.handler.EventHandler) DI_INVENTORY_HOLDING_CREATED(org.folio.DataImportEventTypes.DI_INVENTORY_HOLDING_CREATED) MappingManager(org.folio.processing.mapping.MappingManager) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) ACTION_PROFILE(org.folio.rest.jaxrs.model.ProfileSnapshotWrapper.ContentType.ACTION_PROFILE) StringUtils(org.apache.commons.lang3.StringUtils) EventHandlingUtil.constructContext(org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.constructContext) HOLDINGS(org.folio.ActionProfile.FolioRecord.HOLDINGS) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection) UNIQUE_ID_ERROR_MESSAGE(org.folio.inventory.dataimport.util.DataImportConstants.UNIQUE_ID_ERROR_MESSAGE) EntityType(org.folio.rest.jaxrs.model.EntityType) JsonObject(io.vertx.core.json.JsonObject) IdStorageService(org.folio.inventory.services.IdStorageService) ActionProfile(org.folio.ActionProfile) RecordToEntity(org.folio.inventory.domain.relationship.RecordToEntity) StringUtils.isEmpty(org.apache.commons.lang3.StringUtils.isEmpty) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) MARC_BIBLIOGRAPHIC(org.folio.ActionProfile.FolioRecord.MARC_BIBLIOGRAPHIC) MappingContext(org.folio.processing.mapping.mapper.MappingContext) DuplicateEventException(org.folio.kafka.exception.DuplicateEventException) Record(org.folio.rest.jaxrs.model.Record) Promise(io.vertx.core.Promise) DataImportEventPayload(org.folio.DataImportEventPayload) UUID(java.util.UUID) Future(io.vertx.core.Future) HoldingsRecord(org.folio.HoldingsRecord) String.format(java.lang.String.format) StringUtils.isNotBlank(org.apache.commons.lang.StringUtils.isNotBlank) Storage(org.folio.inventory.storage.Storage) Logger(org.apache.logging.log4j.Logger) EventProcessingException(org.folio.processing.exceptions.EventProcessingException) StringUtils.isBlank(org.apache.commons.lang3.StringUtils.isBlank) Strings.isNotEmpty(org.apache.logging.log4j.util.Strings.isNotEmpty) LogManager(org.apache.logging.log4j.LogManager) MappingMetadataCache(org.folio.inventory.dataimport.cache.MappingMetadataCache) DuplicateEventException(org.folio.kafka.exception.DuplicateEventException) JsonObject(io.vertx.core.json.JsonObject) RecordToEntity(org.folio.inventory.domain.relationship.RecordToEntity) DuplicateEventException(org.folio.kafka.exception.DuplicateEventException) EventProcessingException(org.folio.processing.exceptions.EventProcessingException) DataImportEventPayload(org.folio.DataImportEventPayload) MappingContext(org.folio.processing.mapping.mapper.MappingContext) CompletableFuture(java.util.concurrent.CompletableFuture) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) EventProcessingException(org.folio.processing.exceptions.EventProcessingException)

Example 2 with MappingParameters

use of org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters in project mod-inventory by folio-org.

the class HoldingsUpdateDelegate method handle.

public Future<HoldingsRecord> handle(Map<String, String> eventPayload, Record marcRecord, Context context) {
    try {
        JsonObject mappingRules = new JsonObject(eventPayload.get(MAPPING_RULES_KEY));
        MappingParameters mappingParameters = new JsonObject(eventPayload.get(MAPPING_PARAMS_KEY)).mapTo(MappingParameters.class);
        JsonObject parsedRecord = retrieveParsedContent(marcRecord.getParsedRecord());
        String holdingsId = marcRecord.getExternalIdsHolder().getHoldingsId();
        RecordMapper<Holdings> recordMapper = RecordMapperBuilder.buildMapper(MARC_FORMAT);
        var mappedHoldings = recordMapper.mapRecord(parsedRecord, mappingParameters, mappingRules);
        HoldingsRecordCollection holdingsRecordCollection = storage.getHoldingsRecordCollection(context);
        return getHoldingsRecordById(holdingsId, holdingsRecordCollection).onSuccess(existingHoldingsRecord -> fillVersion(existingHoldingsRecord, eventPayload)).compose(existingHoldingsRecord -> mergeRecords(existingHoldingsRecord, mappedHoldings)).compose(updatedHoldingsRecord -> updateHoldingsRecord(updatedHoldingsRecord, holdingsRecordCollection));
    } catch (Exception e) {
        LOGGER.error("Error updating inventory holdings", e);
        return Future.failedFuture(e);
    }
}
Also used : Context(org.folio.inventory.common.Context) Holdings(org.folio.Holdings) Record(org.folio.rest.jaxrs.model.Record) Promise(io.vertx.core.Promise) HttpStatus(org.apache.http.HttpStatus) Future(io.vertx.core.Future) HoldingsRecord(org.folio.HoldingsRecord) String.format(java.lang.String.format) RecordMapperBuilder(org.folio.processing.mapping.defaultmapper.RecordMapperBuilder) Storage(org.folio.inventory.storage.Storage) Logger(org.apache.logging.log4j.Logger) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection) Map(java.util.Map) JsonObject(io.vertx.core.json.JsonObject) OptimisticLockingException(org.folio.inventory.dataimport.exceptions.OptimisticLockingException) LogManager(org.apache.logging.log4j.LogManager) ParsedRecord(org.folio.rest.jaxrs.model.ParsedRecord) RecordMapper(org.folio.processing.mapping.defaultmapper.RecordMapper) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection) Holdings(org.folio.Holdings) JsonObject(io.vertx.core.json.JsonObject) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) OptimisticLockingException(org.folio.inventory.dataimport.exceptions.OptimisticLockingException)

Example 3 with MappingParameters

use of org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters in project mod-inventory by folio-org.

the class UpdateHoldingEventHandler method handle.

@Override
public CompletableFuture<DataImportEventPayload> handle(DataImportEventPayload dataImportEventPayload) {
    CompletableFuture<DataImportEventPayload> future = new CompletableFuture<>();
    try {
        dataImportEventPayload.setEventType(DI_INVENTORY_HOLDING_UPDATED.value());
        if (dataImportEventPayload.getContext() == null || isEmpty(dataImportEventPayload.getContext().get(HOLDINGS.value())) || isEmpty(dataImportEventPayload.getContext().get(MARC_BIBLIOGRAPHIC.value()))) {
            throw new EventProcessingException(CONTEXT_EMPTY_ERROR_MESSAGE);
        }
        if (dataImportEventPayload.getCurrentNode().getChildSnapshotWrappers().isEmpty()) {
            LOGGER.error(ACTION_HAS_NO_MAPPING_MSG);
            return CompletableFuture.failedFuture(new EventProcessingException(ACTION_HAS_NO_MAPPING_MSG));
        }
        LOGGER.info("Processing UpdateHoldingEventHandler starting with jobExecutionId: {}.", dataImportEventPayload.getJobExecutionId());
        HoldingsRecord tmpHoldingsRecord = retrieveHolding(dataImportEventPayload.getContext());
        String holdingId = tmpHoldingsRecord.getId();
        String hrid = tmpHoldingsRecord.getHrid();
        String instanceId = tmpHoldingsRecord.getInstanceId();
        String permanentLocationId = tmpHoldingsRecord.getPermanentLocationId();
        if (StringUtils.isAnyBlank(hrid, instanceId, permanentLocationId, holdingId)) {
            throw new EventProcessingException(EMPTY_REQUIRED_FIELDS_ERROR_MESSAGE);
        }
        Context context = constructContext(dataImportEventPayload.getTenant(), dataImportEventPayload.getToken(), dataImportEventPayload.getOkapiUrl());
        String jobExecutionId = dataImportEventPayload.getJobExecutionId();
        String recordId = dataImportEventPayload.getContext().get(RECORD_ID_HEADER);
        String chunkId = dataImportEventPayload.getContext().get(CHUNK_ID_HEADER);
        mappingMetadataCache.get(jobExecutionId, context).map(parametersOptional -> parametersOptional.orElseThrow(() -> new EventProcessingException(format(MAPPING_METADATA_NOT_FOUND_MESSAGE, jobExecutionId, recordId, chunkId)))).onSuccess(mappingMetadataDto -> {
            prepareEvent(dataImportEventPayload);
            MappingParameters mappingParameters = Json.decodeValue(mappingMetadataDto.getMappingParams(), MappingParameters.class);
            MappingManager.map(dataImportEventPayload, new MappingContext().withMappingParameters(mappingParameters));
            HoldingsRecordCollection holdingsRecords = storage.getHoldingsRecordCollection(context);
            HoldingsRecord holding = retrieveHolding(dataImportEventPayload.getContext());
            holdingsRecords.update(holding, holdingSuccess -> constructDataImportEventPayload(future, dataImportEventPayload, holding), failure -> {
                if (failure.getStatusCode() == HttpStatus.SC_CONFLICT) {
                    processOLError(dataImportEventPayload, future, holdingsRecords, holding, failure);
                } else {
                    dataImportEventPayload.getContext().remove(CURRENT_RETRY_NUMBER);
                    LOGGER.error(format(CANNOT_UPDATE_HOLDING_ERROR_MESSAGE, holding.getId(), jobExecutionId, recordId, chunkId, failure.getReason(), failure.getStatusCode()));
                    future.completeExceptionally(new EventProcessingException(format(UPDATE_HOLDING_ERROR_MESSAGE, jobExecutionId, recordId, chunkId)));
                }
            });
        }).onFailure(e -> {
            LOGGER.error("Error updating inventory Holdings by jobExecutionId: '{}'", jobExecutionId, e);
            future.completeExceptionally(e);
        });
    } catch (Exception e) {
        LOGGER.error("Failed to update Holdings", e);
        future.completeExceptionally(e);
    }
    return future;
}
Also used : Context(org.folio.inventory.common.Context) EventHandlingUtil.constructContext(org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.constructContext) MappingContext(org.folio.processing.mapping.mapper.MappingContext) Json(io.vertx.core.json.Json) Context(org.folio.inventory.common.Context) EventHandler(org.folio.processing.events.services.handler.EventHandler) MappingManager(org.folio.processing.mapping.MappingManager) HttpStatus(org.apache.http.HttpStatus) Failure(org.folio.inventory.common.domain.Failure) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) ACTION_PROFILE(org.folio.rest.jaxrs.model.ProfileSnapshotWrapper.ContentType.ACTION_PROFILE) StringUtils(org.apache.commons.lang3.StringUtils) EventHandlingUtil.constructContext(org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.constructContext) HOLDINGS(org.folio.ActionProfile.FolioRecord.HOLDINGS) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection) ProfileSnapshotWrapper(org.folio.rest.jaxrs.model.ProfileSnapshotWrapper) ObjectMapperTool(org.folio.dbschema.ObjectMapperTool) JsonObject(io.vertx.core.json.JsonObject) Objects.isNull(java.util.Objects.isNull) ActionProfile(org.folio.ActionProfile) StringUtils.isEmpty(org.apache.commons.lang3.StringUtils.isEmpty) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) MARC_BIBLIOGRAPHIC(org.folio.ActionProfile.FolioRecord.MARC_BIBLIOGRAPHIC) MappingContext(org.folio.processing.mapping.mapper.MappingContext) DataImportEventPayload(org.folio.DataImportEventPayload) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) HoldingsRecord(org.folio.HoldingsRecord) String.format(java.lang.String.format) DI_INVENTORY_HOLDING_UPDATED(org.folio.DataImportEventTypes.DI_INVENTORY_HOLDING_UPDATED) Storage(org.folio.inventory.storage.Storage) UPDATE(org.folio.ActionProfile.Action.UPDATE) Logger(org.apache.logging.log4j.Logger) EventProcessingException(org.folio.processing.exceptions.EventProcessingException) LogManager(org.apache.logging.log4j.LogManager) MappingMetadataCache(org.folio.inventory.dataimport.cache.MappingMetadataCache) MappingContext(org.folio.processing.mapping.mapper.MappingContext) HoldingsRecord(org.folio.HoldingsRecord) CompletableFuture(java.util.concurrent.CompletableFuture) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) EventProcessingException(org.folio.processing.exceptions.EventProcessingException) DataImportEventPayload(org.folio.DataImportEventPayload) EventProcessingException(org.folio.processing.exceptions.EventProcessingException)

Example 4 with MappingParameters

use of org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters in project mod-inventory by folio-org.

the class CreateItemEventHandlerTest method setUp.

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
    Mockito.when(fakeReaderFactory.createReader()).thenReturn(fakeReader);
    Mockito.when(fakeReader.read(any(MappingRule.class))).thenReturn(StringValue.of(AVAILABLE.value()), StringValue.of(UUID.randomUUID().toString()), StringValue.of(UUID.randomUUID().toString()), StringValue.of("645398607547"));
    Mockito.when(mockedStorage.getItemCollection(ArgumentMatchers.any(Context.class))).thenReturn(mockedItemCollection);
    Mockito.when(mappingMetadataCache.get(anyString(), any(Context.class))).thenReturn(Future.succeededFuture(Optional.of(new MappingMetadataDto().withMappingRules(new JsonObject().encode()).withMappingParams(Json.encode(new MappingParameters())))));
    createItemHandler = new CreateItemEventHandler(mockedStorage, mappingMetadataCache, itemIdStorageService);
    MappingManager.clearReaderFactories();
}
Also used : Context(org.folio.inventory.common.Context) JsonObject(io.vertx.core.json.JsonObject) MappingMetadataDto(org.folio.MappingMetadataDto) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) MappingRule(org.folio.rest.jaxrs.model.MappingRule) Before(org.junit.Before)

Example 5 with MappingParameters

use of org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters in project mod-inventory by folio-org.

the class CreateMarcHoldingsEventHandlerTest method setUp.

@Before
public void setUp() throws IOException {
    MockitoAnnotations.openMocks(this);
    MappingManager.clearReaderFactories();
    MappingMetadataCache mappingMetadataCache = new MappingMetadataCache(vertx, vertx.createHttpClient(), 3600);
    createMarcHoldingsEventHandler = new CreateMarcHoldingsEventHandler(storage, mappingMetadataCache, holdingsIdStorageService);
    mappingRules = new JsonObject(TestUtil.readFileFromPath(MAPPING_RULES_PATH));
    doAnswer(invocationOnMock -> {
        instanceId = String.valueOf(UUID.randomUUID());
        Instance instance = new Instance(instanceId, "2", String.valueOf(UUID.randomUUID()), String.valueOf(UUID.randomUUID()), String.valueOf(UUID.randomUUID()), String.valueOf(UUID.randomUUID()));
        List<Instance> instanceList = Collections.singletonList(instance);
        MultipleRecords<Instance> result = new MultipleRecords<>(instanceList, 1);
        Consumer<Success<MultipleRecords<Instance>>> successHandler = invocationOnMock.getArgument(2);
        successHandler.accept(new Success<>(result));
        return null;
    }).when(instanceRecordCollection).findByCql(anyString(), any(PagingParameters.class), any(Consumer.class), any(Consumer.class));
    doAnswer(invocationOnMock -> {
        HoldingsRecord holdingsRecord = invocationOnMock.getArgument(0);
        Consumer<Success<HoldingsRecord>> successHandler = invocationOnMock.getArgument(1);
        successHandler.accept(new Success<>(holdingsRecord));
        return null;
    }).when(holdingsRecordsCollection).add(any(), any(Consumer.class), any(Consumer.class));
    doAnswer(invocationOnMock -> {
        recordId = String.valueOf(UUID.randomUUID());
        holdingsId = String.valueOf(UUID.randomUUID());
        RecordToEntity recordToHoldings = RecordToEntity.builder().recordId(recordId).entityId(holdingsId).build();
        return Future.succeededFuture(recordToHoldings);
    }).when(holdingsIdStorageService).store(any(), any(), any());
    WireMock.stubFor(get(new UrlPathPattern(new RegexPattern(MAPPING_METADATA_URL + "/.*"), true)).willReturn(WireMock.ok().withBody(Json.encode(new MappingMetadataDto().withMappingParams(Json.encode(new MappingParameters())).withMappingRules(mappingRules.encode())))));
}
Also used : PagingParameters(org.folio.inventory.common.api.request.PagingParameters) Instance(org.folio.inventory.domain.instances.Instance) RegexPattern(com.github.tomakehurst.wiremock.matching.RegexPattern) JsonObject(io.vertx.core.json.JsonObject) MappingMetadataDto(org.folio.MappingMetadataDto) Success(org.folio.inventory.common.domain.Success) RecordToEntity(org.folio.inventory.domain.relationship.RecordToEntity) HoldingsRecord(org.folio.HoldingsRecord) Consumer(java.util.function.Consumer) UrlPathPattern(com.github.tomakehurst.wiremock.matching.UrlPathPattern) MappingMetadataCache(org.folio.inventory.dataimport.cache.MappingMetadataCache) MultipleRecords(org.folio.inventory.common.domain.MultipleRecords) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) Before(org.junit.Before)

Aggregations

MappingParameters (org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters)37 JsonObject (io.vertx.core.json.JsonObject)31 Before (org.junit.Before)18 RegexPattern (com.github.tomakehurst.wiremock.matching.RegexPattern)15 UrlPathPattern (com.github.tomakehurst.wiremock.matching.UrlPathPattern)15 HashMap (java.util.HashMap)15 Record (org.folio.rest.jaxrs.model.Record)15 Context (org.folio.inventory.common.Context)14 Test (org.junit.Test)13 MappingMetadataDto (org.folio.MappingMetadataDto)12 Success (org.folio.inventory.common.domain.Success)11 ParsedRecord (org.folio.rest.jaxrs.model.ParsedRecord)11 HoldingsRecord (org.folio.HoldingsRecord)10 MappingMetadataCache (org.folio.inventory.dataimport.cache.MappingMetadataCache)9 Async (io.vertx.ext.unit.Async)8 DataImportEventPayload (org.folio.DataImportEventPayload)8 Json (io.vertx.core.json.Json)7 String.format (java.lang.String.format)7 Consumer (java.util.function.Consumer)7 MappingMetadataDto (org.folio.rest.jaxrs.model.MappingMetadataDto)7