use of eu.bcvsolutions.idm.core.api.dto.ImportContext in project CzechIdMng by bcvsolutions.
the class DefaultImportManager method internalExecuteImport.
@Override
@Transactional
public ImportContext internalExecuteImport(IdmExportImportDto batch, boolean dryRun, AbstractLongRunningTaskExecutor<OperationResult> importTaskExecutor) {
Assert.notNull(batch, "Batch cannot be null!");
Assert.notNull(batch.getId(), "Batch ID cannot be null!");
LOG.info("Internal import [{}, dry-run: {}] starts ...", batch.toString(), dryRun);
// Delete all logs for this batch.
IdmImportLogFilter logFilter = new IdmImportLogFilter();
logFilter.setBatchId(batch.getId());
//
importLogService.findIds(logFilter, null).getContent().forEach(logId -> importLogService.deleteById(logId));
IdmAttachmentDto attachment = attachmentManager.get(batch.getData());
Path tempDirectory = null;
try {
tempDirectory = extractZip(attachment);
// Load manifest - batch contains order of import
IdmExportImportDto manifest = validate(tempDirectory);
ImportContext context = new ImportContext();
//
context.setTempDirectory(tempDirectory).setManifest(//
manifest).setExportDescriptors(//
manifest.getExportOrder()).setDryRun(//
dryRun).setBatch(//
batch).setImportTaskExecutor(importTaskExecutor);
// Set count of all files in the batch (minus manifest)
long countOfFiles = countOfFiles(tempDirectory);
context.getImportTaskExecutor().setCounter(0L);
context.getImportTaskExecutor().setCount(countOfFiles - 1);
// Import new and update exist DTOs.
manifest.getExportOrder().forEach(descriptor -> this.executeImportForType(descriptor, context));
// Delete redundant DTOs.
Lists.reverse(manifest.getExportOrder()).forEach(descriptor -> this.removeRedundant(descriptor, context));
return context;
} finally {
// Delete temp files.
if (tempDirectory != null) {
FileSystemUtils.deleteRecursively(tempDirectory.toFile());
}
LOG.info("Internal import [{}, dry-run: {}] ended", batch.toString(), dryRun);
}
}
use of eu.bcvsolutions.idm.core.api.dto.ImportContext in project CzechIdMng by bcvsolutions.
the class DefaultImportManager method removeRedundant.
/**
* Ensures delete redundant entities in target IdM. Deletes DTOs are within
* golden DTO type (super parent = typically system, role, ...).
*
* @param descriptor
* @param context
*/
private void removeRedundant(ExportDescriptorDto descriptor, ImportContext context) {
Class<? extends BaseDto> dtoClass = descriptor.getDtoClass();
// Does this DTO support the authoritative mode?
boolean supportsAuthoritativeMode = descriptor.isSupportsAuthoritativeMode();
if (!supportsAuthoritativeMode) {
return;
}
String superParentFilterProperty = descriptor.getSuperParentFilterProperty();
Assert.notNull(superParentFilterProperty, "For authoritative mode must be superParentFilterProperty defined!");
// Find super parent (gold) DTO (typically it is DTO for system, role ...)
Class<? extends AbstractDto> superParentDtoClass = getSuperParentDtoClass(descriptor, context);
Assert.notNull(superParentDtoClass, "Supper parent cannot be null here!");
Path superParentDtoTypePath = Paths.get(context.getTempDirectory().toString(), superParentDtoClass.getSimpleName());
try {
// Find all super parent IDs for this DTO type in batch.
Set<UUID> superParentIdsInBatch;
try (Stream<Path> paths = Files.walk(superParentDtoTypePath)) {
superParentIdsInBatch = //
paths.filter(//
Files::isRegularFile).map(path -> {
BaseDto dto = convertFileToDto(path.toFile(), superParentDtoClass, context);
return (UUID) dto.getId();
}).collect(Collectors.toSet());
}
Set<Class<? extends BaseDto>> inheritedClasses = getInheritedClasses(dtoClass, context.getManifest());
// Find all IDs for all children classes
Set<Serializable> childrenIdsInBatch = Sets.newHashSet();
for (Class<? extends BaseDto> inheritedClass : inheritedClasses) {
// Find all IDs for this DTO type in batch.
Path dtoTypePath = Paths.get(context.getTempDirectory().toString(), inheritedClass.getSimpleName());
try (Stream<Path> paths = Files.walk(dtoTypePath)) {
Set<Serializable> childrenIds = //
paths.filter(//
Files::isRegularFile).map(//
path -> convertFileToDto(path.toFile(), inheritedClass, context)).map(dto -> {
// If ID has been replaced, then we need to also replace it.
if (context.getReplacedIDs().containsKey((UUID) dto.getId())) {
return context.getReplacedIDs().get((UUID) dto.getId());
}
return dto.getId();
}).collect(Collectors.toSet());
childrenIdsInBatch.addAll(childrenIds);
}
}
superParentIdsInBatch.forEach(superParentId -> {
try {
Class<? extends BaseDto> serviceDtoClass = dtoClass;
if (dtoClass.isAnnotationPresent(Inheritable.class)) {
serviceDtoClass = dtoClass.getAnnotation(Inheritable.class).dtoService();
}
ReadWriteDtoService<BaseDto, BaseFilter> dtoService = getDtoService(serviceDtoClass);
BaseFilter filterBase = dtoService.getFilterClass().getDeclaredConstructor().newInstance();
// Fill super-parent-property by superParentId (call setter = check if filter is
// implemented).
new PropertyDescriptor(superParentFilterProperty, dtoService.getFilterClass()).getWriteMethod().invoke(filterBase, superParentId);
// Load all IDs in IdM for this parent ID.
List<UUID> childrenIdsInIdM = //
dtoService.find(filterBase, null).getContent().stream().map(//
childDto -> ((AbstractDto) childDto).getId()).collect(Collectors.toList());
// IDs to delete = entities missing in the batch.
Set<UUID> idsToDelete = //
childrenIdsInIdM.stream().filter(//
idmId -> !childrenIdsInBatch.contains(idmId)).collect(Collectors.toSet());
idsToDelete.forEach(id -> {
BaseDto baseDto = dtoService.get(id);
IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), baseDto, RequestOperationType.REMOVE, superParentId);
if (!context.isDryRun()) {
dtoService.delete(baseDto);
dtoLog.setResult(new OperationResultDto(OperationState.EXECUTED));
} else {
dtoLog.setResult(new OperationResultDto.Builder(OperationState.NOT_EXECUTED).setModel(//
new DefaultResultModel(CoreResultCode.IMPORT_EXECUTED_AS_DRYRUN)).build());
}
importLogService.saveDistinct(dtoLog);
});
} catch (ReflectiveOperationException | IllegalArgumentException | IntrospectionException e) {
throw new ResultCodeException(CoreResultCode.EXPORT_IMPORT_REFLECTION_FAILED, e);
}
});
} catch (IOException e) {
throw new ResultCodeException(CoreResultCode.EXPORT_IMPORT_IO_FAILED, e);
}
}
use of eu.bcvsolutions.idm.core.api.dto.ImportContext in project CzechIdMng by bcvsolutions.
the class DefaultImportManager method getParentDtoFromBatch.
/**
* Find parent DTO in the batch by parent field in given DTO.
*
* @param dto
* @param context
* @return
* @throws IOException
*/
private BaseDto getParentDtoFromBatch(BaseDto dto, ImportContext context) {
ExportDescriptorDto descriptor = this.getDescriptor(context, dto.getClass());
Assert.notNull(descriptor, "Descriptor cannot be null!");
Set<String> parentFields = descriptor.getParentFields();
if (parentFields.isEmpty()) {
return null;
}
for (String parentField : parentFields) {
try {
UUID parentId = this.getFieldUUIDValue(parentField, dto, dto.getClass());
Class<? extends AbstractDto> parentType = this.getDtoClassFromField(dto.getClass(), parentField);
Assert.notNull(parentType, "Parent type cannot be null!");
if (parentId == null) {
continue;
}
Path dtoTypePath = Paths.get(context.getTempDirectory().toString(), parentType.getSimpleName());
try (Stream<Path> paths = Files.walk(dtoTypePath)) {
BaseDto parentDto = //
paths.filter(//
Files::isRegularFile).map(//
path -> convertFileToDto(path.toFile(), parentType, context)).filter(//
d -> parentId.equals(d.getId())).findFirst().orElse(null);
if (parentDto != null) {
return parentDto;
}
}
} catch (IOException ex) {
throw new ResultCodeException(CoreResultCode.IMPORT_ZIP_EXTRACTION_FAILED, ex);
}
}
return null;
}
use of eu.bcvsolutions.idm.core.api.dto.ImportContext in project CzechIdMng by bcvsolutions.
the class DefaultImportManager method convertStringToDto.
/**
* Convert given DTO in string to the DTO
*
* @param dtoAsString
* @param dtoClass
* @param context
* @return
* @throws IOException
* @throws JsonMappingException
* @throws JsonParseException
*/
@SuppressWarnings("unchecked")
private <DTO> DTO convertStringToDto(String dtoAsString, Class<? extends BaseDto> dtoClass, ImportContext context) throws IOException {
String replacedDtoAsString = dtoAsString;
Map<UUID, UUID> replacedIDs = context.getReplacedIDs();
// Find IDs to replace
Set<UUID> idsToReplace = //
replacedIDs.keySet().stream().filter(//
oldId -> dtoAsString.contains(oldId.toString())).collect(//
Collectors.toSet());
// Replace found IDs
for (UUID idToReplace : idsToReplace) {
replacedDtoAsString = replacedDtoAsString.replace(idToReplace.toString(), replacedIDs.get(idToReplace).toString());
}
return (DTO) mapper.readValue(replacedDtoAsString, dtoClass);
}
use of eu.bcvsolutions.idm.core.api.dto.ImportContext in project CzechIdMng by bcvsolutions.
the class DefaultImportManager method validate.
/**
* Validate import batch
*
* @param tempDirectory
* @return
*/
private IdmExportImportDto validate(Path tempDirectory) {
Assert.notNull(tempDirectory, "Temp directory cannot be null!");
File manifest = Paths.get(tempDirectory.toString(), ExportManager.EXPORT_BATCH_FILE_NAME).toFile();
if (!manifest.exists()) {
throw new ResultCodeException(CoreResultCode.IMPORT_VALIDATION_FAILED_NO_MANIFEST, ImmutableMap.of("manifest", manifest.getAbsoluteFile()));
}
return (IdmExportImportDto) convertFileToDto(manifest, IdmExportImportDto.class, new ImportContext());
}
Aggregations