use of de.symeda.sormas.api.importexport.InvalidColumnException in project SORMAS-Project by hzi-braunschweig.
the class ContactImporter method importDataFromCsvLine.
@Override
protected ImportLineResult importDataFromCsvLine(String[] values, String[] entityClasses, String[] entityProperties, String[][] entityPropertyPaths, boolean firstLine) throws IOException, InterruptedException {
// Check whether the new line has the same length as the header line
if (values.length > entityProperties.length) {
writeImportError(values, I18nProperties.getValidationError(Validations.importLineTooLong));
return ImportLineResult.ERROR;
}
// regenerate the UUID to prevent overwrite in case of export and import of the same entities
int uuidIndex = ArrayUtils.indexOf(entityProperties, ContactDto.UUID);
if (uuidIndex >= 0) {
values[uuidIndex] = DataHelper.createUuid();
}
final PersonDto newPersonTemp = PersonDto.buildImportEntity();
final ContactDto newContactTemp = caze != null ? ContactDto.build(caze) : ContactDto.build();
newContactTemp.setReportingUser(currentUser.toReference());
final List<VaccinationDto> vaccinations = new ArrayList<>();
ImportRelatedObjectsMapper.Builder relatedObjectsMapperBuilder = new ImportRelatedObjectsMapper.Builder();
if (FacadeProvider.getFeatureConfigurationFacade().isPropertyValueTrue(FeatureType.IMMUNIZATION_MANAGEMENT, FeatureTypeProperty.REDUCED)) {
relatedObjectsMapperBuilder.addMapper(VaccinationDto.class, vaccinations, () -> VaccinationDto.build(currentUser.toReference()), this::insertColumnEntryIntoRelatedObject);
}
ImportRelatedObjectsMapper relatedMapper = relatedObjectsMapperBuilder.build();
boolean contactHasImportError = insertRowIntoData(values, entityClasses, entityPropertyPaths, true, importColumnInformation -> {
try {
if (!relatedMapper.map(importColumnInformation)) {
// If the cell entry is not empty, try to insert it into the current contact or person object
if (!StringUtils.isEmpty(importColumnInformation.getValue())) {
insertColumnEntryIntoData(newContactTemp, newPersonTemp, importColumnInformation.getValue(), importColumnInformation.getEntityPropertyPath());
}
}
} catch (ImportErrorException | InvalidColumnException e) {
return e;
}
return null;
});
// try to assign the contact to an existing case
if (caze == null && newContactTemp.getCaseIdExternalSystem() != null) {
CaseDataDto existingCase = FacadeProvider.getCaseFacade().getCaseDataByUuid(newContactTemp.getCaseIdExternalSystem().trim());
if (existingCase != null) {
newContactTemp.assignCase(existingCase);
newContactTemp.setCaseIdExternalSystem(null);
}
}
// If the row does not have any import errors, call the backend validation of all associated entities
if (!contactHasImportError) {
try {
FacadeProvider.getPersonFacade().validate(newPersonTemp);
FacadeProvider.getContactFacade().validate(newContactTemp);
} catch (ValidationRuntimeException e) {
contactHasImportError = true;
writeImportError(values, e.getMessage());
}
}
PersonDto newPerson = newPersonTemp;
// Sanitize non-HOME address
PersonHelper.sanitizeNonHomeAddress(newPerson);
// if there are any, display a window to resolve the conflict to the user
if (!contactHasImportError) {
try {
ContactImportConsumer consumer = new ContactImportConsumer();
ImportSimilarityResultOption resultOption = null;
ContactImportLock personSelectLock = new ContactImportLock();
// We need to pause the current thread to prevent the import from continuing until the user has acted
synchronized (personSelectLock) {
// Call the logic that allows the user to handle the similarity; once this has been done, the LOCK should be notified
// to allow the importer to resume
handlePersonSimilarity(newPerson, result -> consumer.onImportResult(result, personSelectLock), (person, similarityResultOption) -> new ContactImportSimilarityResult(person, null, similarityResultOption), Strings.infoSelectOrCreatePersonForImport, currentUI);
try {
if (!personSelectLock.wasNotified) {
personSelectLock.wait();
}
} catch (InterruptedException e) {
logger.error("InterruptedException when trying to perform LOCK.wait() in contact import: " + e.getMessage());
throw e;
}
if (consumer.result != null) {
resultOption = consumer.result.getResultOption();
}
// If the user picked an existing person, override the contact person with it
if (ImportSimilarityResultOption.PICK.equals(resultOption)) {
newPerson = FacadeProvider.getPersonFacade().getPersonByUuid(consumer.result.getMatchingPerson().getUuid());
}
}
// or an existing person was picked, save the contact and person to the database
if (ImportSimilarityResultOption.SKIP.equals(resultOption)) {
return ImportLineResult.SKIPPED;
} else {
boolean skipPersonValidation = ImportSimilarityResultOption.PICK.equals(resultOption);
final PersonDto savedPerson = FacadeProvider.getPersonFacade().savePerson(newPerson, skipPersonValidation);
newContactTemp.setPerson(savedPerson.toReference());
ContactDto newContact = newContactTemp;
final ContactImportLock contactSelectLock = new ContactImportLock();
synchronized (contactSelectLock) {
handleContactSimilarity(newContactTemp, savedPerson, result -> consumer.onImportResult(result, contactSelectLock));
try {
if (!contactSelectLock.wasNotified) {
contactSelectLock.wait();
}
} catch (InterruptedException e) {
logger.error("InterruptedException when trying to perform LOCK.wait() in contact import: " + e.getMessage());
throw e;
}
if (consumer.result != null) {
resultOption = consumer.result.getResultOption();
}
if (ImportSimilarityResultOption.PICK.equals(resultOption)) {
newContact = FacadeProvider.getContactFacade().getByUuid(consumer.result.getMatchingContact().getUuid());
}
}
// Workaround: Reset the change date to avoid OutdatedEntityExceptions
newContact.setChangeDate(new Date());
FacadeProvider.getContactFacade().save(newContact, true, false);
for (VaccinationDto vaccination : vaccinations) {
FacadeProvider.getVaccinationFacade().createWithImmunization(vaccination, newContact.getRegion(), newContact.getDistrict(), newContact.getPerson(), newContact.getDisease());
}
consumer.result = null;
return ImportLineResult.SUCCESS;
}
} catch (ValidationRuntimeException e) {
writeImportError(values, e.getMessage());
return ImportLineResult.ERROR;
}
} else {
return ImportLineResult.ERROR;
}
}
use of de.symeda.sormas.api.importexport.InvalidColumnException in project SORMAS-Project by hzi-braunschweig.
the class EventImportFacadeEjb method insertColumnEntryIntoEventParticipantData.
/**
* Inserts the entry of a single cell into the event participant
*/
private void insertColumnEntryIntoEventParticipantData(EventParticipantDto eventParticipant, String entry, String[] entryHeaderPath) throws InvalidColumnException, ImportErrorException {
Object currentElement = eventParticipant;
for (int i = 0; i < entryHeaderPath.length; i++) {
String headerPathElementName = entryHeaderPath[i];
try {
if (i != entryHeaderPath.length - 1) {
currentElement = new PropertyDescriptor(headerPathElementName, currentElement.getClass()).getReadMethod().invoke(currentElement);
} else {
PropertyDescriptor pd = new PropertyDescriptor(headerPathElementName, currentElement.getClass());
Class<?> propertyType = pd.getPropertyType();
// according to the types of the sample or pathogen test fields
if (importFacade.executeDefaultInvoke(pd, currentElement, entry, entryHeaderPath, true)) {
continue;
} else if (propertyType.isAssignableFrom(DistrictReferenceDto.class)) {
List<DistrictReferenceDto> district = districtFacade.getByName(entry, ImportHelper.getRegionBasedOnDistrict(pd.getName(), eventParticipant, eventParticipant.getPerson(), currentElement), false);
if (district.isEmpty()) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importEntryDoesNotExistDbOrRegion, entry, importFacade.buildEntityProperty(entryHeaderPath)));
} else if (district.size() > 1) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importDistrictNotUnique, entry, importFacade.buildEntityProperty(entryHeaderPath)));
} else {
pd.getWriteMethod().invoke(currentElement, district.get(0));
}
} else if (propertyType.isAssignableFrom(CommunityReferenceDto.class)) {
List<CommunityReferenceDto> community = communityFacade.getByName(entry, ImportHelper.getDistrictBasedOnCommunity(pd.getName(), eventParticipant, eventParticipant.getPerson(), currentElement), false);
if (community.isEmpty()) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importEntryDoesNotExistDbOrDistrict, entry, importFacade.buildEntityProperty(entryHeaderPath)));
} else if (community.size() > 1) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importCommunityNotUnique, entry, importFacade.buildEntityProperty(entryHeaderPath)));
} else {
pd.getWriteMethod().invoke(currentElement, community.get(0));
}
} else if (propertyType.isAssignableFrom(FacilityReferenceDto.class)) {
DataHelper.Pair<DistrictReferenceDto, CommunityReferenceDto> infrastructureData = ImportHelper.getDistrictAndCommunityBasedOnFacility(pd.getName(), eventParticipant, eventParticipant.getPerson(), currentElement);
List<FacilityReferenceDto> facilities = facilityFacade.getByNameAndType(entry, infrastructureData.getElement0(), infrastructureData.getElement1(), getTypeOfFacility(pd.getName(), currentElement), false);
if (facilities.isEmpty()) {
if (infrastructureData.getElement1() != null) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importEntryDoesNotExistDbOrCommunity, entry, importFacade.buildEntityProperty(entryHeaderPath)));
} else {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importEntryDoesNotExistDbOrDistrict, entry, importFacade.buildEntityProperty(entryHeaderPath)));
}
} else if (facilities.size() > 1 && infrastructureData.getElement1() == null) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importFacilityNotUniqueInDistrict, entry, importFacade.buildEntityProperty(entryHeaderPath)));
} else if (facilities.size() > 1 && infrastructureData.getElement1() != null) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importFacilityNotUniqueInCommunity, entry, importFacade.buildEntityProperty(entryHeaderPath)));
} else {
pd.getWriteMethod().invoke(currentElement, facilities.get(0));
}
} else {
throw new UnsupportedOperationException(I18nProperties.getValidationError(Validations.importEventsPropertyTypeNotAllowed, propertyType.getName()));
}
}
} catch (IntrospectionException e) {
throw new InvalidColumnException(importFacade.buildEntityProperty(entryHeaderPath));
} catch (InvocationTargetException | IllegalAccessException e) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importErrorInColumn, importFacade.buildEntityProperty(entryHeaderPath)));
} catch (IllegalArgumentException e) {
throw new ImportErrorException(entry, importFacade.buildEntityProperty(entryHeaderPath));
} catch (ParseException e) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importInvalidDate, importFacade.buildEntityProperty(entryHeaderPath), DateHelper.getAllowedDateFormats(I18nProperties.getUserLanguage().getDateFormat())));
} catch (ImportErrorException e) {
throw e;
} catch (Exception e) {
LOGGER.error("Unexpected error when trying to import a case: " + e.getMessage());
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importCasesUnexpectedError));
}
}
}
use of de.symeda.sormas.api.importexport.InvalidColumnException in project SORMAS-Project by hzi-braunschweig.
the class EventImportFacadeEjb method insertColumnEntryIntoData.
/**
* Inserts the entry of a single cell into the event or its participant.
*/
private void insertColumnEntryIntoData(EventDto event, String entry, String[] entryHeaderPath) throws InvalidColumnException, ImportErrorException {
Object currentElement = event;
for (int i = 0; i < entryHeaderPath.length; i++) {
String headerPathElementName = entryHeaderPath[i];
try {
if (i != entryHeaderPath.length - 1) {
currentElement = new PropertyDescriptor(headerPathElementName, currentElement.getClass()).getReadMethod().invoke(currentElement);
} else {
PropertyDescriptor pd = new PropertyDescriptor(headerPathElementName, currentElement.getClass());
Class<?> propertyType = pd.getPropertyType();
// according to the types of the case or person fields
if (importFacade.executeDefaultInvoke(pd, currentElement, entry, entryHeaderPath, true)) {
continue;
} else if (propertyType.isAssignableFrom(EventReferenceDto.class)) {
EventDto referencedDto = eventFacade.getEventByUuid(entry, false);
if (referencedDto == null) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importEntryDoesNotExist, entry, importFacade.buildEntityProperty(entryHeaderPath)));
} else {
pd.getWriteMethod().invoke(currentElement, referencedDto.toReference());
}
} else if (propertyType.isAssignableFrom(DistrictReferenceDto.class)) {
List<DistrictReferenceDto> district = districtFacade.getByName(entry, ImportHelper.getRegionBasedOnDistrict(pd.getName(), event, currentElement), false);
if (district.isEmpty()) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importEntryDoesNotExistDbOrRegion, entry, importFacade.buildEntityProperty(entryHeaderPath)));
} else if (district.size() > 1) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importDistrictNotUnique, entry, importFacade.buildEntityProperty(entryHeaderPath)));
} else {
pd.getWriteMethod().invoke(currentElement, district.get(0));
}
} else if (propertyType.isAssignableFrom(CommunityReferenceDto.class)) {
List<CommunityReferenceDto> community = communityFacade.getByName(entry, ImportHelper.getDistrictBasedOnCommunity(pd.getName(), event, currentElement), false);
if (community.isEmpty()) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importEntryDoesNotExistDbOrDistrict, entry, importFacade.buildEntityProperty(entryHeaderPath)));
} else if (community.size() > 1) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importCommunityNotUnique, entry, importFacade.buildEntityProperty(entryHeaderPath)));
} else {
pd.getWriteMethod().invoke(currentElement, community.get(0));
}
} else if (propertyType.isAssignableFrom(FacilityReferenceDto.class)) {
DataHelper.Pair<DistrictReferenceDto, CommunityReferenceDto> infrastructureData = ImportHelper.getDistrictAndCommunityBasedOnFacility(pd.getName(), event, currentElement);
List<FacilityReferenceDto> facilities = facilityFacade.getByNameAndType(entry, infrastructureData.getElement0(), infrastructureData.getElement1(), getTypeOfFacility(pd.getName(), currentElement), false);
if (facilities.isEmpty()) {
if (infrastructureData.getElement1() != null) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importEntryDoesNotExistDbOrCommunity, entry, importFacade.buildEntityProperty(entryHeaderPath)));
} else {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importEntryDoesNotExistDbOrDistrict, entry, importFacade.buildEntityProperty(entryHeaderPath)));
}
} else if (facilities.size() > 1 && infrastructureData.getElement1() == null) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importFacilityNotUniqueInDistrict, entry, importFacade.buildEntityProperty(entryHeaderPath)));
} else if (facilities.size() > 1 && infrastructureData.getElement1() != null) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importFacilityNotUniqueInCommunity, entry, importFacade.buildEntityProperty(entryHeaderPath)));
} else {
pd.getWriteMethod().invoke(currentElement, facilities.get(0));
}
} else {
throw new UnsupportedOperationException(I18nProperties.getValidationError(Validations.importEventsPropertyTypeNotAllowed, propertyType.getName()));
}
}
} catch (IntrospectionException e) {
throw new InvalidColumnException(importFacade.buildEntityProperty(entryHeaderPath));
} catch (InvocationTargetException | IllegalAccessException e) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importErrorInColumn, importFacade.buildEntityProperty(entryHeaderPath)));
} catch (IllegalArgumentException e) {
throw new ImportErrorException(entry, importFacade.buildEntityProperty(entryHeaderPath));
} catch (ParseException e) {
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importInvalidDate, importFacade.buildEntityProperty(entryHeaderPath), DateHelper.getAllowedDateFormats(I18nProperties.getUserLanguage().getDateFormat())));
} catch (ImportErrorException e) {
throw e;
} catch (Exception e) {
LOGGER.error("Unexpected error when trying to import an event: " + e.getMessage(), e);
throw new ImportErrorException(I18nProperties.getValidationError(Validations.importCasesUnexpectedError));
}
}
}
use of de.symeda.sormas.api.importexport.InvalidColumnException in project SORMAS-Project by hzi-braunschweig.
the class CaseImportFacadeEjb method insertRowIntoData.
protected ImportLineResultDto<CaseImportEntities> insertRowIntoData(String[] values, String[] entityClasses, String[][] entityPropertyPaths, boolean ignoreEmptyEntries, Function<ImportCellData, Exception> insertCallback) {
String importError = null;
List<String> invalidColumns = new ArrayList<>();
for (int i = 0; i < values.length; i++) {
String value = StringUtils.trimToNull(values[i]);
if (ignoreEmptyEntries && (value == null || value.isEmpty())) {
continue;
}
String[] entityPropertyPath = entityPropertyPaths[i];
// Error description column is ignored
if (entityPropertyPath[0].equals(ERROR_COLUMN_NAME)) {
continue;
}
if (!(ignoreEmptyEntries && StringUtils.isEmpty(value))) {
Exception exception = insertCallback.apply(new ImportCellData(value, entityClasses != null ? entityClasses[i] : null, entityPropertyPath));
if (exception != null) {
if (exception instanceof ImportErrorException) {
importError = exception.getMessage();
StringBuilder additionalInfo = new StringBuilder();
for (int j = 0; j < entityPropertyPath.length; j++) {
additionalInfo.append(" ").append(entityPropertyPath[j]);
}
importError += additionalInfo;
importError += "value:" + value;
break;
} else if (exception instanceof InvalidColumnException) {
invalidColumns.add(((InvalidColumnException) exception).getColumnName());
}
}
}
}
if (invalidColumns.size() > 0) {
LOGGER.warn("Unhandled columns [{}]", String.join(", ", invalidColumns));
}
return importError != null ? ImportLineResultDto.errorResult(importError) : ImportLineResultDto.successResult();
}
use of de.symeda.sormas.api.importexport.InvalidColumnException in project SORMAS-Project by hzi-braunschweig.
the class CaseImportFacadeEjb method buildEntities.
private ImportLineResultDto<CaseImportEntities> buildEntities(String[] values, String[] entityClasses, String[][] entityPropertyPaths, boolean ignoreEmptyEntries, CaseImportEntities entities) {
final UserReferenceDto currentUserRef = userService.getCurrentUser().toReference();
final List<SampleDto> samples = entities.getSamples();
final List<PathogenTestDto> pathogenTests = entities.getPathogenTests();
final List<VaccinationDto> vaccinations = entities.getVaccinations();
ImportRelatedObjectsMapper.Builder relatedObjectsMapperBuilder = new ImportRelatedObjectsMapper.Builder().addMapper(SampleDto.class, samples, () -> SampleDto.build(currentUserRef, new CaseReferenceDto(entities.getCaze().getUuid())), this::insertColumnEntryIntoRelatedObject).addMapper(PathogenTestDto.class, pathogenTests, () -> {
if (samples.isEmpty()) {
return null;
}
SampleDto referenceSample = samples.get(samples.size() - 1);
return PathogenTestDto.build(new SampleReferenceDto(referenceSample.getUuid()), currentUserRef);
}, this::insertColumnEntryIntoRelatedObject);
if (featureConfigurationFacade.isPropertyValueTrue(FeatureType.IMMUNIZATION_MANAGEMENT, FeatureTypeProperty.REDUCED)) {
relatedObjectsMapperBuilder.addMapper(VaccinationDto.class, vaccinations, () -> VaccinationDto.build(currentUserRef), this::insertColumnEntryIntoRelatedObject);
}
ImportRelatedObjectsMapper relatedMapper = relatedObjectsMapperBuilder.build();
final ImportLineResultDto<CaseImportEntities> result = insertRowIntoData(values, entityClasses, entityPropertyPaths, ignoreEmptyEntries, (cellData) -> {
try {
CaseDataDto caze = entities.getCaze();
if (!relatedMapper.map(cellData)) {
if (StringUtils.isNotEmpty(cellData.getValue())) {
// If the cell entry is not empty, try to insert it into the current case or its person
insertColumnEntryIntoData(caze, entities.getPerson(), cellData.getValue(), cellData.getEntityPropertyPath());
}
}
} catch (ImportErrorException | InvalidColumnException e) {
return e;
}
return null;
});
// Sanitize non-HOME address
PersonHelper.sanitizeNonHomeAddress(entities.getPerson());
return result;
}
Aggregations