Search in sources :

Example 1 with HoldingsRecord

use of org.folio.HoldingsRecord in project mod-inventory by folio-org.

the class CreateHoldingEventHandler method addHoldings.

private Future<HoldingsRecord> addHoldings(HoldingsRecord holdings, Context context) {
    Promise<HoldingsRecord> promise = Promise.promise();
    HoldingsRecordCollection holdingsRecordCollection = storage.getHoldingsRecordCollection(context);
    holdingsRecordCollection.add(holdings, success -> promise.complete(success.getResult()), failure -> {
        // for now there is a solution via error-message contains. It will be improved via another solution by https://issues.folio.org/browse/RMB-899.
        if (isNotBlank(failure.getReason()) && failure.getReason().contains(UNIQUE_ID_ERROR_MESSAGE)) {
            LOGGER.info("Duplicated event received by InstanceId: {}. Ignoring...", holdings.getId());
            promise.fail(new DuplicateEventException(format("Duplicated event by Holding id: %s", holdings.getId())));
        } else {
            LOGGER.error(format("Error posting Holdings cause %s, status code %s", failure.getReason(), failure.getStatusCode()));
            promise.fail(failure.getReason());
        }
    });
    return promise.future();
}
Also used : DuplicateEventException(org.folio.kafka.exception.DuplicateEventException) HoldingsRecord(org.folio.HoldingsRecord) HoldingsRecordCollection(org.folio.inventory.domain.HoldingsRecordCollection)

Example 2 with HoldingsRecord

use of org.folio.HoldingsRecord in project mod-inventory by folio-org.

the class CreateHoldingEventHandler method fillInstanceIdIfNeeded.

private void fillInstanceIdIfNeeded(DataImportEventPayload dataImportEventPayload, JsonObject holdingAsJson) {
    if (isBlank(holdingAsJson.getString(INSTANCE_ID_FIELD))) {
        String instanceId = null;
        String instanceAsString = dataImportEventPayload.getContext().get(EntityType.INSTANCE.value());
        if (isNotEmpty(instanceAsString)) {
            JsonObject holdingsRecord = new JsonObject(instanceAsString);
            instanceId = holdingsRecord.getString("id");
        }
        if (isBlank(instanceId)) {
            String recordAsString = dataImportEventPayload.getContext().get(EntityType.MARC_BIBLIOGRAPHIC.value());
            Record record = Json.decodeValue(recordAsString, Record.class);
            instanceId = ParsedRecordUtil.getAdditionalSubfieldValue(record.getParsedRecord(), ParsedRecordUtil.AdditionalSubfields.I);
        }
        if (isBlank(instanceId)) {
            throw new EventProcessingException(PAYLOAD_DATA_HAS_NO_INSTANCE_ID_ERROR_MSG);
        }
        fillInstanceId(dataImportEventPayload, holdingAsJson, instanceId);
    }
}
Also used : JsonObject(io.vertx.core.json.JsonObject) Record(org.folio.rest.jaxrs.model.Record) HoldingsRecord(org.folio.HoldingsRecord) EventProcessingException(org.folio.processing.exceptions.EventProcessingException)

Example 3 with HoldingsRecord

use of org.folio.HoldingsRecord in project mod-inventory by folio-org.

the class CreateMarcHoldingsEventHandler 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_HOLDINGS.value()))) {
            return CompletableFuture.failedFuture(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());
        Record targetRecord = new JsonObject(payloadContext.get(EntityType.MARC_HOLDINGS.value())).mapTo(Record.class);
        prepareEvent(dataImportEventPayload);
        String jobExecutionId = dataImportEventPayload.getJobExecutionId();
        String recordId = payloadContext.get(RECORD_ID_HEADER);
        String chunkId = payloadContext.get(CHUNK_ID_HEADER);
        Future<RecordToEntity> recordToHoldingsFuture = idStorageService.store(targetRecord.getId(), 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)))).onSuccess(mappingMetadata -> defaultMapRecordToHoldings(dataImportEventPayload, mappingMetadata)).map(v -> processMappingResult(dataImportEventPayload, holdingsId)).compose(holdingJson -> findInstanceIdByHrid(dataImportEventPayload, holdingJson, context).compose(instanceId -> {
                fillInstanceId(dataImportEventPayload, holdingJson, instanceId);
                var holdingsRecords = storage.getHoldingsRecordCollection(context);
                HoldingsRecord holding = Json.decodeValue(payloadContext.get(HOLDINGS.value()), HoldingsRecord.class);
                return addHoldings(holding, holdingsRecords);
            })).onSuccess(createdHoldings -> {
                LOGGER.info("Created Holding record by jobExecutionId: '{}' and recordId: '{}' and chunkId: '{}' ", jobExecutionId, recordId, chunkId);
                dataImportEventPayload.getContext().put(HOLDINGS.value(), Json.encodePrettily(createdHoldings));
                future.complete(dataImportEventPayload);
            }).onFailure(e -> {
                if (!(e instanceof DuplicateEventException)) {
                    LOGGER.error("Error creating Holding by jobExecutionId: '{}' and recordId: '{}' and chunkId: '{}' ", jobExecutionId, recordId, chunkId, e);
                }
                future.completeExceptionally(e);
            });
        }).onFailure(failure -> {
            LOGGER.error(format(CREATING_INVENTORY_RELATIONSHIP_ERROR_MESSAGE, jobExecutionId, recordId, chunkId), failure);
            future.completeExceptionally(failure);
        });
    } catch (Exception e) {
        LOGGER.error("Failed to create 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) MappingMetadataDto(org.folio.MappingMetadataDto) Context(org.folio.inventory.common.Context) Json(io.vertx.core.json.Json) EventHandler(org.folio.processing.events.services.handler.EventHandler) DI_INVENTORY_HOLDING_CREATED(org.folio.DataImportEventTypes.DI_INVENTORY_HOLDING_CREATED) 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) JsonMappingException(org.folio.inventory.validation.exceptions.JsonMappingException) RecordMapperBuilder(org.folio.processing.mapping.defaultmapper.RecordMapperBuilder) EventHandlingUtil.constructContext(org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.constructContext) HOLDINGS(org.folio.ActionProfile.FolioRecord.HOLDINGS) DI_INVENTORY_HOLDINGS_CREATED_READY_FOR_POST_PROCESSING(org.folio.DataImportEventTypes.DI_INVENTORY_HOLDINGS_CREATED_READY_FOR_POST_PROCESSING) ParsedRecordUtil.getControlFieldValue(org.folio.inventory.dataimport.util.ParsedRecordUtil.getControlFieldValue) StringUtils.isBlank(org.apache.commons.lang.StringUtils.isBlank) 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) IdStorageService(org.folio.inventory.services.IdStorageService) JsonObject(io.vertx.core.json.JsonObject) StringUtils.isEmpty(org.apache.commons.lang3.StringUtils.isEmpty) ActionProfile(org.folio.ActionProfile) RecordToEntity(org.folio.inventory.domain.relationship.RecordToEntity) RecordMapper(org.folio.processing.mapping.defaultmapper.RecordMapper) MappingParameters(org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters) Holdings(org.folio.Holdings) DuplicateEventException(org.folio.kafka.exception.DuplicateEventException) Record(org.folio.rest.jaxrs.model.Record) Promise(io.vertx.core.Promise) DataImportEventPayload(org.folio.DataImportEventPayload) MARC_HOLDINGS(org.folio.ActionProfile.FolioRecord.MARC_HOLDINGS) UUID(java.util.UUID) HoldingsRecord(org.folio.HoldingsRecord) Future(io.vertx.core.Future) 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) UnsupportedEncodingException(java.io.UnsupportedEncodingException) LogManager(org.apache.logging.log4j.LogManager) PagingParameters(org.folio.inventory.common.api.request.PagingParameters) 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) JsonMappingException(org.folio.inventory.validation.exceptions.JsonMappingException) DuplicateEventException(org.folio.kafka.exception.DuplicateEventException) EventProcessingException(org.folio.processing.exceptions.EventProcessingException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) DataImportEventPayload(org.folio.DataImportEventPayload) HoldingsRecord(org.folio.HoldingsRecord) CompletableFuture(java.util.concurrent.CompletableFuture) Record(org.folio.rest.jaxrs.model.Record) HoldingsRecord(org.folio.HoldingsRecord) EventProcessingException(org.folio.processing.exceptions.EventProcessingException)

Example 4 with HoldingsRecord

use of org.folio.HoldingsRecord 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 5 with HoldingsRecord

use of org.folio.HoldingsRecord in project mod-inventory by folio-org.

the class HoldingsUpdateDelegate method mergeRecords.

private Future<HoldingsRecord> mergeRecords(HoldingsRecord existingRecord, Holdings mappedRecord) {
    try {
        mappedRecord.setId(existingRecord.getId());
        JsonObject existing = JsonObject.mapFrom(existingRecord);
        JsonObject mapped = JsonObject.mapFrom(mappedRecord);
        JsonObject merged = existing.mergeIn(mapped);
        HoldingsRecord mergedHoldingsRecord = merged.mapTo(HoldingsRecord.class);
        return Future.succeededFuture(mergedHoldingsRecord);
    } catch (Exception e) {
        LOGGER.error("Error updating holdings", e);
        return Future.failedFuture(e);
    }
}
Also used : HoldingsRecord(org.folio.HoldingsRecord) JsonObject(io.vertx.core.json.JsonObject) OptimisticLockingException(org.folio.inventory.dataimport.exceptions.OptimisticLockingException)

Aggregations

HoldingsRecord (org.folio.HoldingsRecord)44 JsonObject (io.vertx.core.json.JsonObject)27 Test (org.junit.Test)26 DataImportEventPayload (org.folio.DataImportEventPayload)24 HashMap (java.util.HashMap)23 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)22 Record (org.folio.rest.jaxrs.model.Record)18 Success (org.folio.inventory.common.domain.Success)17 Consumer (java.util.function.Consumer)14 ParsedRecord (org.folio.rest.jaxrs.model.ParsedRecord)14 PagingParameters (org.folio.inventory.common.api.request.PagingParameters)13 Context (org.folio.inventory.common.Context)12 MultipleRecords (org.folio.inventory.common.domain.MultipleRecords)12 EventHandler (org.folio.processing.events.services.handler.EventHandler)11 MappingParameters (org.folio.processing.mapping.defaultmapper.processor.parameters.MappingParameters)11 Async (io.vertx.ext.unit.Async)8 MappingMetadataDto (org.folio.MappingMetadataDto)8 MatchItemEventHandler (org.folio.inventory.dataimport.handlers.matching.MatchItemEventHandler)8 HoldingsRecordCollection (org.folio.inventory.domain.HoldingsRecordCollection)8 Before (org.junit.Before)8