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;
}
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);
}
}
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;
}
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();
}
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())))));
}
Aggregations