Search in sources :

Example 6 with Record

use of org.folio.rest.jaxrs.model.Record 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 7 with Record

use of org.folio.rest.jaxrs.model.Record in project mod-inventory by folio-org.

the class MarcBibMatchedPostProcessingEventHandler method handle.

@Override
public CompletableFuture<DataImportEventPayload> handle(DataImportEventPayload dataImportEventPayload) {
    CompletableFuture<DataImportEventPayload> future = new CompletableFuture<>();
    try {
        HashMap<String, String> payloadContext = dataImportEventPayload.getContext();
        if (isNull(payloadContext)) {
            LOGGER.error(PAYLOAD_HAS_NO_DATA_MSG);
            future.completeExceptionally(new EventProcessingException(PAYLOAD_HAS_NO_DATA_MSG));
            return future;
        }
        if (isBlank(payloadContext.get(MATCHED_MARC_BIB_KEY))) {
            LOGGER.info(MATCHED_RECORD_NOT_EXISTS_MSG);
            future.complete(dataImportEventPayload);
            return future;
        }
        Record matchedRecord = new JsonObject(payloadContext.get(MATCHED_MARC_BIB_KEY)).mapTo(Record.class);
        String instanceId = ParsedRecordUtil.getAdditionalSubfieldValue(matchedRecord.getParsedRecord(), ParsedRecordUtil.AdditionalSubfields.I);
        Context context = EventHandlingUtil.constructContext(dataImportEventPayload.getTenant(), dataImportEventPayload.getToken(), dataImportEventPayload.getOkapiUrl());
        InstanceCollection instanceCollection = storage.getInstanceCollection(context);
        HoldingCollection holdingCollection = storage.getHoldingCollection(context);
        if (isBlank(instanceId)) {
            future.complete(dataImportEventPayload);
            return future;
        }
        instanceCollection.findById(instanceId).whenComplete((v, t) -> {
            if (t == null && v != null) {
                dataImportEventPayload.getContext().put(INSTANCE.value(), Json.encode(v));
                try {
                    holdingCollection.findByCql(format("instanceId=%s", v.getId()), PagingParameters.defaults(), findResult -> {
                        if (findResult.getResult() != null && findResult.getResult().totalRecords == 1) {
                            dataImportEventPayload.getContext().put(HOLDINGS.value(), Json.encode(findResult.getResult().records.get(0)));
                        }
                        future.complete(dataImportEventPayload);
                    }, failure -> {
                        LOGGER.error(ERROR_HOLDING_MSG + format(". StatusCode: %s. Message: %s", failure.getStatusCode(), failure.getReason()));
                        future.complete(dataImportEventPayload);
                    });
                } catch (UnsupportedEncodingException e) {
                    LOGGER.error(ERROR_HOLDING_MSG, e);
                    future.complete(dataImportEventPayload);
                }
            } else {
                LOGGER.error(ERROR_INSTANCE_MSG, t);
                future.complete(dataImportEventPayload);
            }
        });
    } catch (Exception e) {
        LOGGER.error(ERROR_INSTANCE_MSG, e);
        future.completeExceptionally(e);
    }
    return future;
}
Also used : Context(org.folio.inventory.common.Context) InstanceCollection(org.folio.inventory.domain.instances.InstanceCollection) JsonObject(io.vertx.core.json.JsonObject) UnsupportedEncodingException(java.io.UnsupportedEncodingException) EventProcessingException(org.folio.processing.exceptions.EventProcessingException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) DataImportEventPayload(org.folio.DataImportEventPayload) CompletableFuture(java.util.concurrent.CompletableFuture) HoldingCollection(org.folio.inventory.domain.HoldingCollection) Record(org.folio.rest.jaxrs.model.Record) EventProcessingException(org.folio.processing.exceptions.EventProcessingException)

Example 8 with Record

use of org.folio.rest.jaxrs.model.Record in project mod-inventory by folio-org.

the class MarcBibModifiedPostProcessingEventHandler method handle.

@Override
public CompletableFuture<DataImportEventPayload> handle(DataImportEventPayload dataImportEventPayload) {
    CompletableFuture<DataImportEventPayload> future = new CompletableFuture<>();
    try {
        HashMap<String, String> payloadContext = dataImportEventPayload.getContext();
        if (isNull(payloadContext) || isBlank(payloadContext.get(MARC_BIBLIOGRAPHIC.value()))) {
            LOGGER.error(PAYLOAD_HAS_NO_DATA_MSG);
            return CompletableFuture.failedFuture(new EventProcessingException(PAYLOAD_HAS_NO_DATA_MSG));
        }
        LOGGER.info("Processing ReplaceInstanceEventHandler starting with jobExecutionId: {}.", dataImportEventPayload.getJobExecutionId());
        Record record = new JsonObject(payloadContext.get(MARC_BIBLIOGRAPHIC.value())).mapTo(Record.class);
        String instanceId = ParsedRecordUtil.getAdditionalSubfieldValue(record.getParsedRecord(), ParsedRecordUtil.AdditionalSubfields.I);
        if (isBlank(instanceId)) {
            return CompletableFuture.completedFuture(dataImportEventPayload);
        }
        record.setExternalIdsHolder(new ExternalIdsHolder().withInstanceId(instanceId));
        Context context = EventHandlingUtil.constructContext(dataImportEventPayload.getTenant(), dataImportEventPayload.getToken(), dataImportEventPayload.getOkapiUrl());
        Promise<Instance> instanceUpdatePromise = Promise.promise();
        mappingMetadataCache.get(dataImportEventPayload.getJobExecutionId(), context).map(parametersOptional -> parametersOptional.orElseThrow(() -> new EventProcessingException(format(MAPPING_METADATA_NOT_FOUND_MSG, dataImportEventPayload.getJobExecutionId())))).map(mappingMetadataDto -> buildPayloadForInstanceUpdate(dataImportEventPayload, mappingMetadataDto)).compose(payloadForUpdate -> instanceUpdateDelegate.handle(payloadForUpdate, record, context)).onSuccess(instanceUpdatePromise::complete).compose(updatedInstance -> precedingSucceedingTitlesHelper.getExistingPrecedingSucceedingTitles(updatedInstance, context)).map(precedingSucceedingTitles -> precedingSucceedingTitles.stream().map(titleJson -> titleJson.getString("id")).collect(Collectors.toSet())).compose(precedingSucceedingTitles -> precedingSucceedingTitlesHelper.deletePrecedingSucceedingTitles(precedingSucceedingTitles, context)).compose(ar -> precedingSucceedingTitlesHelper.createPrecedingSucceedingTitles(instanceUpdatePromise.future().result(), context)).onComplete(updateAr -> {
            if (updateAr.succeeded()) {
                dataImportEventPayload.getContext().remove(CURRENT_RETRY_NUMBER);
                Instance resultedInstance = instanceUpdatePromise.future().result();
                if (resultedInstance.getVersion() != null) {
                    int currentVersion = Integer.parseInt(resultedInstance.getVersion());
                    int incrementedVersion = currentVersion + 1;
                    resultedInstance.setVersion(String.valueOf(incrementedVersion));
                }
                dataImportEventPayload.getContext().put(INSTANCE.value(), Json.encode(resultedInstance));
                future.complete(dataImportEventPayload);
            } else {
                if (updateAr.cause() instanceof OptimisticLockingException) {
                    processOLError(dataImportEventPayload, future, updateAr);
                } else {
                    dataImportEventPayload.getContext().remove(CURRENT_RETRY_NUMBER);
                    LOGGER.error("Error updating inventory instance by id: '{}' by jobExecutionId: '{}'", instanceId, dataImportEventPayload.getJobExecutionId(), updateAr.cause());
                    future.completeExceptionally(updateAr.cause());
                }
            }
        });
    } catch (Exception e) {
        dataImportEventPayload.getContext().remove(CURRENT_RETRY_NUMBER);
        LOGGER.error("Error updating inventory instance", e);
        future.completeExceptionally(e);
    }
    return future;
}
Also used : Context(org.folio.inventory.common.Context) ParsedRecordUtil(org.folio.inventory.dataimport.util.ParsedRecordUtil) Json(io.vertx.core.json.Json) Context(org.folio.inventory.common.Context) MappingMetadataDto(org.folio.MappingMetadataDto) EventHandler(org.folio.processing.events.services.handler.EventHandler) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) MARC_BIBLIOGRAPHIC(org.folio.rest.jaxrs.model.EntityType.MARC_BIBLIOGRAPHIC) ExternalIdsHolder(org.folio.rest.jaxrs.model.ExternalIdsHolder) Map(java.util.Map) EntityType(org.folio.rest.jaxrs.model.EntityType) MAPPING_PROFILE(org.folio.rest.jaxrs.model.ProfileSnapshotWrapper.ContentType.MAPPING_PROFILE) JsonObject(io.vertx.core.json.JsonObject) Objects.isNull(java.util.Objects.isNull) AsyncResult(io.vertx.core.AsyncResult) MappingProfile(org.folio.MappingProfile) Record(org.folio.rest.jaxrs.model.Record) Promise(io.vertx.core.Promise) DataImportEventPayload(org.folio.DataImportEventPayload) Collectors(java.util.stream.Collectors) String.format(java.lang.String.format) Logger(org.apache.logging.log4j.Logger) EventProcessingException(org.folio.processing.exceptions.EventProcessingException) StringUtils.isBlank(org.apache.commons.lang3.StringUtils.isBlank) EventHandlingUtil(org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil) INSTANCE(org.folio.ActionProfile.FolioRecord.INSTANCE) Instance(org.folio.inventory.domain.instances.Instance) OptimisticLockingException(org.folio.inventory.dataimport.exceptions.OptimisticLockingException) LogManager(org.apache.logging.log4j.LogManager) DI_SRS_MARC_BIB_RECORD_MODIFIED_READY_FOR_POST_PROCESSING(org.folio.DataImportEventTypes.DI_SRS_MARC_BIB_RECORD_MODIFIED_READY_FOR_POST_PROCESSING) MappingMetadataCache(org.folio.inventory.dataimport.cache.MappingMetadataCache) ExternalIdsHolder(org.folio.rest.jaxrs.model.ExternalIdsHolder) Instance(org.folio.inventory.domain.instances.Instance) OptimisticLockingException(org.folio.inventory.dataimport.exceptions.OptimisticLockingException) JsonObject(io.vertx.core.json.JsonObject) EventProcessingException(org.folio.processing.exceptions.EventProcessingException) OptimisticLockingException(org.folio.inventory.dataimport.exceptions.OptimisticLockingException) DataImportEventPayload(org.folio.DataImportEventPayload) CompletableFuture(java.util.concurrent.CompletableFuture) Record(org.folio.rest.jaxrs.model.Record) EventProcessingException(org.folio.processing.exceptions.EventProcessingException)

Example 9 with Record

use of org.folio.rest.jaxrs.model.Record in project mod-inventory by folio-org.

the class QuickMarcKafkaHandler method handle.

@Override
public Future<String> handle(KafkaConsumerRecord<String, String> record) {
    var params = new OkapiConnectionParams(kafkaHeadersToMap(record.headers()), vertx);
    var context = constructContext(params.getTenantId(), params.getToken(), params.getOkapiUrl());
    Event event = Json.decodeValue(record.value(), Event.class);
    LOGGER.info("Quick marc event payload has been received with event type: {}", event.getEventType());
    return getEventPayload(event).compose(eventPayload -> processPayload(eventPayload, context).compose(recordType -> sendEvent(eventPayload, getReplyEventType(recordType), params)).recover(throwable -> sendErrorEvent(params, eventPayload, throwable)).map(ar -> record.key()), th -> {
        LOGGER.error("Update record state was failed while handle event, {}", th.getMessage());
        return Future.failedFuture(th.getMessage());
    });
}
Also used : QM_INVENTORY_AUTHORITY_UPDATED(org.folio.inventory.dataimport.handlers.QMEventTypes.QM_INVENTORY_AUTHORITY_UPDATED) Json(io.vertx.core.json.Json) Context(org.folio.inventory.common.Context) AbstractQuickMarcEventHandler(org.folio.inventory.dataimport.handlers.quickmarc.AbstractQuickMarcEventHandler) EventMetadata(org.folio.rest.jaxrs.model.EventMetadata) KafkaTopicNameHelper.getDefaultNameSpace(org.folio.kafka.KafkaTopicNameHelper.getDefaultNameSpace) KafkaHeaderUtils.kafkaHeadersFromMap(org.folio.kafka.KafkaHeaderUtils.kafkaHeadersFromMap) HashMap(java.util.HashMap) KafkaProducer(io.vertx.kafka.client.producer.KafkaProducer) EventHandlingUtil.constructContext(org.folio.inventory.dataimport.handlers.matching.util.EventHandlingUtil.constructContext) UpdateHoldingsQuickMarcEventHandler(org.folio.inventory.dataimport.handlers.quickmarc.UpdateHoldingsQuickMarcEventHandler) HoldingsUpdateDelegate(org.folio.inventory.dataimport.handlers.actions.HoldingsUpdateDelegate) Map(java.util.Map) QM_INVENTORY_HOLDINGS_UPDATED(org.folio.inventory.dataimport.handlers.QMEventTypes.QM_INVENTORY_HOLDINGS_UPDATED) KafkaHeaderUtils.kafkaHeadersToMap(org.folio.kafka.KafkaHeaderUtils.kafkaHeadersToMap) QMEventTypes(org.folio.inventory.dataimport.handlers.QMEventTypes) Event(org.folio.rest.jaxrs.model.Event) PrecedingSucceedingTitlesHelper(org.folio.inventory.dataimport.handlers.actions.PrecedingSucceedingTitlesHelper) KafkaTopicNameHelper.formatTopicName(org.folio.kafka.KafkaTopicNameHelper.formatTopicName) Record(org.folio.rest.jaxrs.model.Record) Promise(io.vertx.core.Promise) Vertx(io.vertx.core.Vertx) UpdateInstanceQuickMarcEventHandler(org.folio.inventory.dataimport.handlers.quickmarc.UpdateInstanceQuickMarcEventHandler) UUID(java.util.UUID) UpdateAuthorityQuickMarcEventHandler(org.folio.inventory.dataimport.handlers.quickmarc.UpdateAuthorityQuickMarcEventHandler) AsyncRecordHandler(org.folio.kafka.AsyncRecordHandler) QM_INVENTORY_INSTANCE_UPDATED(org.folio.inventory.dataimport.handlers.QMEventTypes.QM_INVENTORY_INSTANCE_UPDATED) Future(io.vertx.core.Future) ParsedRecordDto(org.folio.rest.jaxrs.model.ParsedRecordDto) OkapiConnectionParams(org.folio.rest.util.OkapiConnectionParams) Storage(org.folio.inventory.storage.Storage) InstanceUpdateDelegate(org.folio.inventory.dataimport.handlers.actions.InstanceUpdateDelegate) AtomicLong(java.util.concurrent.atomic.AtomicLong) Logger(org.apache.logging.log4j.Logger) EventProcessingException(org.folio.processing.exceptions.EventProcessingException) KafkaConsumerRecord(io.vertx.kafka.client.consumer.KafkaConsumerRecord) AuthorityUpdateDelegate(org.folio.inventory.dataimport.handlers.actions.AuthorityUpdateDelegate) QM_ERROR(org.folio.inventory.dataimport.handlers.QMEventTypes.QM_ERROR) KafkaProducerRecord(io.vertx.kafka.client.producer.KafkaProducerRecord) LogManager(org.apache.logging.log4j.LogManager) ConsumerWrapperUtil(org.folio.inventory.dataimport.util.ConsumerWrapperUtil) KafkaConfig(org.folio.kafka.KafkaConfig) KafkaProducer.createShared(io.vertx.kafka.client.producer.KafkaProducer.createShared) Event(org.folio.rest.jaxrs.model.Event) OkapiConnectionParams(org.folio.rest.util.OkapiConnectionParams)

Example 10 with Record

use of org.folio.rest.jaxrs.model.Record in project mod-inventory by folio-org.

the class CreateInstanceEventHandlerTest method shouldReturnFailedFutureIfCurrentActionProfileHasNoMappingProfile.

@Test
public void shouldReturnFailedFutureIfCurrentActionProfileHasNoMappingProfile() {
    HashMap<String, String> context = new HashMap<>();
    context.put(MARC_BIBLIOGRAPHIC.value(), Json.encode(new Record().withParsedRecord(new ParsedRecord().withContent(PARSED_CONTENT))));
    DataImportEventPayload dataImportEventPayload = new DataImportEventPayload().withEventType(DI_SRS_MARC_BIB_RECORD_CREATED.value()).withContext(context).withCurrentNode(new ProfileSnapshotWrapper().withContentType(ACTION_PROFILE).withContent(actionProfile));
    CompletableFuture<DataImportEventPayload> future = createInstanceEventHandler.handle(dataImportEventPayload);
    ExecutionException exception = Assert.assertThrows(ExecutionException.class, future::get);
    Assert.assertEquals("Action profile to create an Instance requires a mapping profile by jobExecutionId: 'null' and recordId: 'null'", exception.getCause().getMessage());
}
Also used : HashMap(java.util.HashMap) ParsedRecord(org.folio.rest.jaxrs.model.ParsedRecord) Record(org.folio.rest.jaxrs.model.Record) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) ParsedRecord(org.folio.rest.jaxrs.model.ParsedRecord) ExecutionException(java.util.concurrent.ExecutionException) DataImportEventPayload(org.folio.DataImportEventPayload) ProfileSnapshotWrapper(org.folio.rest.jaxrs.model.ProfileSnapshotWrapper) Test(org.junit.Test)

Aggregations

Record (org.folio.rest.jaxrs.model.Record)320 ParsedRecord (org.folio.rest.jaxrs.model.ParsedRecord)266 Test (org.junit.Test)253 RawRecord (org.folio.rest.jaxrs.model.RawRecord)164 Async (io.vertx.ext.unit.Async)154 JsonObject (io.vertx.core.json.JsonObject)149 HashMap (java.util.HashMap)125 DataImportEventPayload (org.folio.DataImportEventPayload)116 ErrorRecord (org.folio.rest.jaxrs.model.ErrorRecord)116 SourceRecord (org.folio.rest.jaxrs.model.SourceRecord)76 ExternalIdsHolder (org.folio.rest.jaxrs.model.ExternalIdsHolder)74 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)69 UUID (java.util.UUID)66 ArrayList (java.util.ArrayList)64 List (java.util.List)62 Before (org.junit.Before)60 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)58 SnapshotDaoUtil (org.folio.dao.util.SnapshotDaoUtil)55 TestContext (io.vertx.ext.unit.TestContext)52 RunWith (org.junit.runner.RunWith)51