Search in sources :

Example 1 with CoreEvent

use of eu.bcvsolutions.idm.core.api.event.CoreEvent in project CzechIdMng by bcvsolutions.

the class DefaultFormService method saveFormInstance.

/**
 * {@inheritDoc}
 *
 * TODO: validations by given form definition? I don't think, it will not be
 * useful in synchronization etc. - only FE validations will be enough ...
 */
@Override
@Transactional
public IdmFormInstanceDto saveFormInstance(Identifiable owner, IdmFormDefinitionDto formDefinition, List<IdmFormValueDto> values) {
    FormableEntity ownerEntity = getOwnerEntity(owner);
    Assert.notNull(values, "Form values are required!");
    Assert.notNull(ownerEntity, "Form values owner is required!");
    formDefinition = checkDefaultDefinition(ownerEntity.getClass(), formDefinition);
    // 
    FormValueService<FormableEntity> formValueService = getFormValueService(ownerEntity);
    // 
    Map<UUID, IdmFormValueDto> previousValues = new HashMap<>();
    formValueService.getValues(ownerEntity, formDefinition).forEach(formValue -> {
        previousValues.put(formValue.getId(), formValue);
    });
    // 
    List<IdmFormValueDto> results = new ArrayList<>();
    for (IdmFormValueDto value : values) {
        // value could contant attribute id only
        UUID attributeId = value.getFormAttribute();
        Assert.notNull(attributeId, "Form attribute is required");
        IdmFormAttributeDto attribute = formDefinition.getMappedAttribute(attributeId);
        Assert.notNull(attribute, "Form attribute is required");
        // 
        value.setOwnerAndAttribute(ownerEntity, attribute);
        // 
        IdmFormValueDto previousValue = value.getId() == null ? null : previousValues.get(value.getId());
        if (previousValue != null) {
            // saved values will not be removed
            previousValues.remove(value.getId());
            // confidential value is always updated - only new values are sent from client
            if (value.isConfidential() || !value.isEquals(previousValue)) {
                // update value
                results.add(formValueService.save(value));
                LOG.trace("FormValue [{}:{}] for owner [{}] was updated", attribute.getCode(), value.getId(), ownerEntity);
            }
        } else {
            // create new value
            results.add(formValueService.save(value));
            LOG.trace("FormValue [{}:{}] for owner [{}] was created", attribute.getCode(), value.getId(), ownerEntity);
        }
    }
    // 
    // remove unsaved values by attribute definition (patch method is not
    // implemented now)
    previousValues.values().stream().filter(formValue -> {
        // they could not be sent with form (only changed values)
        return !formValue.isConfidential();
    }).forEach(value -> {
        formValueService.delete(value);
        LOG.trace("FormValue [{}:{}] for owner [{}] was deleted", value.getFormAttribute(), value.getId(), ownerEntity);
    });
    // publish event - eav was saved
    if (lookupService.getDtoLookup(ownerEntity.getClass()) == null) {
        // TODO: remove this branch after all agends will be rewritten to dto usage
        entityEventManager.process(new CoreEvent<>(CoreEventType.EAV_SAVE, ownerEntity));
    } else {
        entityEventManager.process(new CoreEvent<>(CoreEventType.EAV_SAVE, lookupService.lookupDto(ownerEntity.getClass(), ownerEntity.getId())));
    }
    // 
    return new IdmFormInstanceDto(ownerEntity, formDefinition, results);
}
Also used : FormableEntity(eu.bcvsolutions.idm.core.eav.api.entity.FormableEntity) OrderAwarePluginRegistry(org.springframework.plugin.core.OrderAwarePluginRegistry) IdmFormAttributeDto(eu.bcvsolutions.idm.core.eav.api.dto.IdmFormAttributeDto) PluginRegistry(org.springframework.plugin.core.PluginRegistry) Autowired(org.springframework.beans.factory.annotation.Autowired) HashMap(java.util.HashMap) FormService(eu.bcvsolutions.idm.core.eav.api.service.FormService) StringUtils(org.apache.commons.lang3.StringUtils) MessageFormat(java.text.MessageFormat) ArrayList(java.util.ArrayList) PersistentType(eu.bcvsolutions.idm.core.eav.api.domain.PersistentType) Introspector(java.beans.Introspector) CoreEvent(eu.bcvsolutions.idm.core.api.event.CoreEvent) Lists(com.google.common.collect.Lists) LookupService(eu.bcvsolutions.idm.core.api.service.LookupService) IdmFormValueDto(eu.bcvsolutions.idm.core.eav.api.dto.IdmFormValueDto) ResultCodeException(eu.bcvsolutions.idm.core.api.exception.ResultCodeException) Map(java.util.Map) IdmFormAttributeService(eu.bcvsolutions.idm.core.eav.api.service.IdmFormAttributeService) Pageable(org.springframework.data.domain.Pageable) IdmFormInstanceDto(eu.bcvsolutions.idm.core.eav.api.dto.IdmFormInstanceDto) Method(java.lang.reflect.Method) ConfigurationClass(eu.bcvsolutions.idm.core.api.domain.ConfigurationClass) ImmutableMap(com.google.common.collect.ImmutableMap) CoreException(eu.bcvsolutions.idm.core.api.exception.CoreException) ConfigurationClassProperty(eu.bcvsolutions.idm.core.api.domain.ConfigurationClassProperty) UUID(java.util.UUID) Page(org.springframework.data.domain.Page) Collectors(java.util.stream.Collectors) IntrospectionException(java.beans.IntrospectionException) Serializable(java.io.Serializable) InvocationTargetException(java.lang.reflect.InvocationTargetException) IdmFormDefinitionDto(eu.bcvsolutions.idm.core.eav.api.dto.IdmFormDefinitionDto) List(java.util.List) CoreResultCode(eu.bcvsolutions.idm.core.api.domain.CoreResultCode) FormValueService(eu.bcvsolutions.idm.core.eav.api.service.FormValueService) IdmFormDefinitionService(eu.bcvsolutions.idm.core.eav.api.service.IdmFormDefinitionService) PropertyDescriptor(java.beans.PropertyDescriptor) CoreEventType(eu.bcvsolutions.idm.core.api.event.CoreEvent.CoreEventType) Identifiable(eu.bcvsolutions.idm.core.api.domain.Identifiable) BaseDto(eu.bcvsolutions.idm.core.api.dto.BaseDto) PageImpl(org.springframework.data.domain.PageImpl) EntityEventManager(eu.bcvsolutions.idm.core.api.service.EntityEventManager) Transactional(org.springframework.transaction.annotation.Transactional) Assert(org.springframework.util.Assert) IdmFormInstanceDto(eu.bcvsolutions.idm.core.eav.api.dto.IdmFormInstanceDto) HashMap(java.util.HashMap) IdmFormAttributeDto(eu.bcvsolutions.idm.core.eav.api.dto.IdmFormAttributeDto) ArrayList(java.util.ArrayList) IdmFormValueDto(eu.bcvsolutions.idm.core.eav.api.dto.IdmFormValueDto) UUID(java.util.UUID) FormableEntity(eu.bcvsolutions.idm.core.eav.api.entity.FormableEntity) Transactional(org.springframework.transaction.annotation.Transactional)

Example 2 with CoreEvent

use of eu.bcvsolutions.idm.core.api.event.CoreEvent in project CzechIdMng by bcvsolutions.

the class AbstractSynchronizationExecutor method startReconciliation.

/**
 * Start reconciliation. Is call after synchronization. Main purpose is find and
 * resolve missing accounts
 *
 * @param entityType
 * @param allAccountsSet
 * @param config
 * @param system
 * @param log
 * @param actionsLog
 */
protected void startReconciliation(SystemEntityType entityType, Set<String> allAccountsSet, AbstractSysSyncConfigDto config, SysSystemDto system, SysSyncLogDto log, List<SysSyncActionLogDto> actionsLog) {
    if (!log.isRunning()) {
        return;
    }
    AccAccountFilter accountFilter = new AccAccountFilter();
    accountFilter.setSystemId(system.getId());
    List<AccAccountDto> accounts = accountService.find(accountFilter, null).getContent();
    for (AccAccountDto account : accounts) {
        if (!log.isRunning()) {
            return;
        }
        String uid = account.getRealUid();
        if (!allAccountsSet.contains(uid)) {
            SysSyncItemLogDto itemLog = new SysSyncItemLogDto();
            try {
                // Default setting for log item
                itemLog.setIdentification(uid);
                itemLog.setDisplayName(uid);
                itemLog.setType(entityType.getEntityType().getSimpleName());
                // Do reconciliation for one item (produces event)
                // Start in new Transaction
                SynchronizationContext builder = new SynchronizationContext();
                builder.addUid(uid).addType(IcSyncDeltaTypeEnum.DELETE).addConfig(config).addSystem(system).addEntityType(entityType).addAccount(account).addLog(log).addLogItem(itemLog).addActionLogs(actionsLog);
                CoreEvent<SysSyncItemLogDto> event = new CoreEvent<>(SynchronizationEventType.START_ITEM, itemLog);
                event.getProperties().put(SynchronizationService.WRAPPER_SYNC_ITEM, builder);
                EventResult<SysSyncItemLogDto> lastResult = entityEventManager.process(event).getLastResult();
                boolean result = false;
                if (lastResult != null && lastResult.getEvent().getProperties().containsKey(SynchronizationService.RESULT_SYNC_ITEM)) {
                    result = (boolean) lastResult.getEvent().getProperties().get(SynchronizationService.RESULT_SYNC_ITEM);
                }
                // Update (increased counter) and check state of sync (maybe was cancelled from
                // sync or LRT)
                updateAndCheckState(result, log);
            } catch (Exception ex) {
                String message = MessageFormat.format("Reconciliation - error for uid [{0}]", uid);
                log.addToLog(message);
                log.addToLog(Throwables.getStackTraceAsString(ex));
                LOG.error(message, ex);
            } finally {
                config = synchronizationConfigService.save(config);
                boolean existingItemLog = existItemLogInActions(actionsLog, itemLog);
                actionsLog = saveActionLogs(actionsLog, log.getId());
                // 
                if (!existingItemLog) {
                    addToItemLog(itemLog, MessageFormat.format("Missing action log for UID [{0}]!", uid));
                    initSyncActionLog(SynchronizationActionType.UNKNOWN, OperationResultType.ERROR, itemLog, log, actionsLog);
                    syncItemLogService.save(itemLog);
                }
            }
        }
    }
}
Also used : SynchronizationContext(eu.bcvsolutions.idm.acc.domain.SynchronizationContext) AccAccountFilter(eu.bcvsolutions.idm.acc.dto.filter.AccAccountFilter) CoreEvent(eu.bcvsolutions.idm.core.api.event.CoreEvent) SysSyncItemLogDto(eu.bcvsolutions.idm.acc.dto.SysSyncItemLogDto) AccAccountDto(eu.bcvsolutions.idm.acc.dto.AccAccountDto) GuardedString(eu.bcvsolutions.idm.core.security.api.domain.GuardedString) IntrospectionException(java.beans.IntrospectionException) InvocationTargetException(java.lang.reflect.InvocationTargetException) CoreException(eu.bcvsolutions.idm.core.api.exception.CoreException) ProvisioningException(eu.bcvsolutions.idm.acc.exception.ProvisioningException)

Example 3 with CoreEvent

use of eu.bcvsolutions.idm.core.api.event.CoreEvent in project CzechIdMng by bcvsolutions.

the class DefaultProvisioningExecutor method executeInternal.

/**
 * We need to wait to transaction commit, when provisioning is executed - all accounts have to be prepared.
 * Next processing is executed outside a transaction
 * => operation states has to be saved in new transactions
 * => rollback on the target system is not possible anyway
 *
 * @param provisioningOperation
 * @return
 */
@TransactionalEventListener
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public SysProvisioningOperationDto executeInternal(SysProvisioningOperationDto provisioningOperation) {
    Assert.notNull(provisioningOperation, "Provisioning operation is required.");
    Assert.notNull(provisioningOperation.getSystemEntity(), "System entity is required.");
    Assert.notNull(provisioningOperation.getProvisioningContext(), "Provisioning context is required.");
    // 
    try {
        boolean checkNotExecuted = provisioningOperation.isSynchronousProvisioning();
        if (provisioningOperationService.isNew(provisioningOperation)) {
            provisioningOperation = persistOperation(provisioningOperation);
            checkNotExecuted = true;
        }
        if (checkNotExecuted && provisioningOperation.getResult() != null && OperationState.NOT_EXECUTED == provisioningOperation.getResult().getState()) {
            return provisioningOperation;
        }
        // 
        CoreEvent<SysProvisioningOperationDto> event = new CoreEvent<SysProvisioningOperationDto>(provisioningOperation.getOperationType(), provisioningOperation);
        try {
            // set a global provisioning timeout even for synchronous call
            FutureTask<EventContext<SysProvisioningOperationDto>> futureTask = new FutureTask<EventContext<SysProvisioningOperationDto>>(new Callable<EventContext<SysProvisioningOperationDto>>() {

                @Override
                public EventContext<SysProvisioningOperationDto> call() {
                    return entityEventManager.process(event);
                }
            });
            // thread pool is not used here
            Thread thread = new Thread(new DelegatingSecurityContextRunnable(new DelegatingTransactionContextRunnable(futureTask)));
            thread.start();
            // 
            // global timeout by configuration
            long timeout = provisioningConfiguration.getTimeout();
            try {
                // TODO: non blocking wait if possible (refactoring is needed + java 9 helps)
                EventContext<SysProvisioningOperationDto> context = futureTask.get(timeout, TimeUnit.MILLISECONDS);
                // 
                return context.getContent();
            } catch (InterruptedException ex) {
                futureTask.cancel(true);
                // propagate exception to upper catch
                throw ex;
            } catch (TimeoutException ex) {
                futureTask.cancel(true);
                // put thread into queue and wait => timeout too => retry mecchanism will work
                throw new ResultCodeException(AccResultCode.PROVISIONING_TIMEOUT, ImmutableMap.of("name", provisioningOperation.getSystemEntityUid(), "system", provisioningOperation.getSystem(), "operationType", provisioningOperation.getOperationType(), "objectClass", provisioningOperation.getProvisioningContext().getConnectorObject().getObjectClass(), "timeout", String.valueOf(timeout)), ex);
            }
        } catch (Exception ex) {
            return provisioningOperationService.handleFailed(provisioningOperation, ex);
        } finally {
            try {
                UUID roleRequestId = provisioningOperation.getRoleRequestId();
                if (roleRequestId != null) {
                    // Check of the state for whole request
                    // Create mock request -> we don't wont load request from DB -> optimization
                    IdmRoleRequestDto mockRequest = new IdmRoleRequestDto();
                    mockRequest.setId(roleRequestId);
                    mockRequest.setState(RoleRequestState.EXECUTED);
                    IdmRoleRequestDto returnedReqeust = roleRequestService.refreshSystemState(mockRequest);
                    OperationResultDto systemState = returnedReqeust.getSystemState();
                    if (systemState == null) {
                    // State on system of request was not changed (may be not all provisioning operations are
                    // resolved)
                    } else {
                        // We have final state on systems
                        IdmRoleRequestDto requestDto = roleRequestService.get(roleRequestId);
                        if (requestDto != null) {
                            requestDto.setSystemState(systemState);
                            roleRequestService.save(requestDto);
                        } else {
                            LOG.info(MessageFormat.format("Refresh role-request system state: Role-request with ID [{0}] was not found (maybe was deleted).", roleRequestId));
                        }
                    }
                }
            } catch (Exception ex) {
                return provisioningOperationService.handleFailed(provisioningOperation, ex);
            }
        }
    } finally {
        UUID eventId = provisioningOperation.getManualEventId();
        if (eventId != null) {
            IdmEntityEventDto startEvent = entityEventManager.getEvent(eventId);
            if (startEvent != null) {
                // Complete a manual event (for ensure end of the sync).
                entityEventManager.completeManualEvent(startEvent);
            }
        }
    }
}
Also used : ResultCodeException(eu.bcvsolutions.idm.core.api.exception.ResultCodeException) OperationResultDto(eu.bcvsolutions.idm.core.api.dto.OperationResultDto) TimeoutException(java.util.concurrent.TimeoutException) ResultCodeException(eu.bcvsolutions.idm.core.api.exception.ResultCodeException) EventContext(eu.bcvsolutions.idm.core.api.event.EventContext) FutureTask(java.util.concurrent.FutureTask) CoreEvent(eu.bcvsolutions.idm.core.api.event.CoreEvent) DelegatingSecurityContextRunnable(org.springframework.security.concurrent.DelegatingSecurityContextRunnable) UUID(java.util.UUID) SysProvisioningOperationDto(eu.bcvsolutions.idm.acc.dto.SysProvisioningOperationDto) DelegatingTransactionContextRunnable(eu.bcvsolutions.idm.core.config.DelegatingTransactionContextRunnable) IdmRoleRequestDto(eu.bcvsolutions.idm.core.api.dto.IdmRoleRequestDto) TimeoutException(java.util.concurrent.TimeoutException) IdmEntityEventDto(eu.bcvsolutions.idm.core.api.dto.IdmEntityEventDto) TransactionalEventListener(org.springframework.transaction.event.TransactionalEventListener) Transactional(org.springframework.transaction.annotation.Transactional)

Example 4 with CoreEvent

use of eu.bcvsolutions.idm.core.api.event.CoreEvent in project CzechIdMng by bcvsolutions.

the class AbstractSynchronizationExecutor method exportEntity.

/**
 * Start export item (entity) to target resource
 *
 * @param context
 * @param uidAttribute
 * @param entity
 */
protected void exportEntity(SynchronizationContext context, SysSystemAttributeMappingDto uidAttribute, AbstractDto entity) {
    SystemEntityType entityType = context.getEntityType();
    AbstractSysSyncConfigDto config = context.getConfig();
    SysSyncLogDto log = context.getLog();
    List<SysSyncActionLogDto> actionsLog = context.getActionLogs();
    SysSystemDto system = context.getSystem();
    SysSyncItemLogDto itemLog = new SysSyncItemLogDto();
    try {
        // Default setting for log item
        itemLog.setIdentification(entity.getId().toString());
        itemLog.setDisplayName(this.getDisplayNameForEntity(entity));
        itemLog.setType(entityType.getEntityType().getSimpleName());
        itemLog.addToLog(MessageFormat.format("Start export for entity [{0}].", this.getDisplayNameForEntity(entity)));
        UUID accountId = this.getAccountByEntity(entity.getId(), system.getId());
        if (accountId != null) {
            initSyncActionLog(SynchronizationActionType.CREATE_ACCOUNT, OperationResultType.IGNORE, itemLog, log, actionsLog);
            itemLog.addToLog(MessageFormat.format("For entity [{0}] AccAccount [{1}] was found. Export for this entity ends (only entity without AccAccount can be exported)!", this.getDisplayNameForEntity(entity), accountId));
            return;
        }
        String uid = systemAttributeMappingService.generateUid(entity, uidAttribute);
        // Do export for one item (produces event)
        // Start in new Transaction
        // 
        context.addUid(uid).addConfig(// 
        config).addSystem(// 
        system).addEntityType(// 
        entityType).addEntityId(entity.getId()).addLog(// 
        log).addLogItem(// 
        itemLog).addActionLogs(// 
        actionsLog).addExportAction(true);
        CoreEvent<SysSyncItemLogDto> event = new CoreEvent<>(SynchronizationEventType.START_ITEM, itemLog);
        event.getProperties().put(SynchronizationService.WRAPPER_SYNC_ITEM, context);
        EventResult<SysSyncItemLogDto> lastResult = entityEventManager.process(event).getLastResult();
        boolean result = false;
        if (lastResult != null && lastResult.getEvent().getProperties().containsKey(SynchronizationService.RESULT_SYNC_ITEM)) {
            result = (boolean) lastResult.getEvent().getProperties().get(SynchronizationService.RESULT_SYNC_ITEM);
        }
        // Update (increased counter) and check state of sync (maybe was cancelled from
        // sync or LRT)
        updateAndCheckState(result, log);
    } catch (Exception ex) {
        String message = MessageFormat.format("Export - error for entity [{0}]", entity.getId());
        log.addToLog(message);
        log.addToLog(Throwables.getStackTraceAsString(ex));
        LOG.error(message, ex);
    } finally {
        synchronizationConfigService.save(config);
        boolean existingItemLog = existItemLogInActions(actionsLog, itemLog);
        actionsLog = (List<SysSyncActionLogDto>) syncActionLogService.saveAll(actionsLog);
        // 
        if (!existingItemLog) {
            addToItemLog(itemLog, MessageFormat.format("Missing action log for entity [{0}]!", entity.getId()));
            initSyncActionLog(SynchronizationActionType.UNKNOWN, OperationResultType.ERROR, itemLog, log, actionsLog);
            syncItemLogService.save(itemLog);
        }
    }
}
Also used : SystemEntityType(eu.bcvsolutions.idm.acc.domain.SystemEntityType) GuardedString(eu.bcvsolutions.idm.core.security.api.domain.GuardedString) SysSystemDto(eu.bcvsolutions.idm.acc.dto.SysSystemDto) IntrospectionException(java.beans.IntrospectionException) InvocationTargetException(java.lang.reflect.InvocationTargetException) CoreException(eu.bcvsolutions.idm.core.api.exception.CoreException) ProvisioningException(eu.bcvsolutions.idm.acc.exception.ProvisioningException) SysSyncActionLogDto(eu.bcvsolutions.idm.acc.dto.SysSyncActionLogDto) AbstractSysSyncConfigDto(eu.bcvsolutions.idm.acc.dto.AbstractSysSyncConfigDto) CoreEvent(eu.bcvsolutions.idm.core.api.event.CoreEvent) SysSyncItemLogDto(eu.bcvsolutions.idm.acc.dto.SysSyncItemLogDto) UUID(java.util.UUID) SysSyncLogDto(eu.bcvsolutions.idm.acc.dto.SysSyncLogDto)

Example 5 with CoreEvent

use of eu.bcvsolutions.idm.core.api.event.CoreEvent in project CzechIdMng by bcvsolutions.

the class DefaultImportManager method executeImportForType.

/**
 * Ensures add new and update existed DTOs by given batch.
 *
 * @param descriptor
 * @param context
 */
private void executeImportForType(ExportDescriptorDto descriptor, ImportContext context) {
    Class<? extends BaseDto> dtoClass = descriptor.getDtoClass();
    Path dtoTypePath = Paths.get(context.getTempDirectory().toString(), dtoClass.getSimpleName());
    try {
        List<BaseDto> dtos;
        try (Stream<Path> paths = Files.walk(dtoTypePath)) {
            dtos = // 
            paths.filter(// 
            Files::isRegularFile).map(path -> {
                BaseDto dto = convertFileToDto(path.toFile(), dtoClass, context);
                Assert.notNull(dto, "DTO cannot be null after conversion from the batch!");
                return dto;
            }).collect(Collectors.toList());
        }
        if (dtos.isEmpty()) {
            return;
        }
        // Sorts all DTOs for this type (maybe it is tree).
        dtos = sortsDTOs(dtoClass, dtos);
        int i = 0;
        for (BaseDto dto : dtos) {
            // Flush Hibernate in batch - performance improving
            if (i % 20 == 0 && i > 0) {
                // Call hard hibernate session flush and clear
                if (getHibernateSession().isOpen()) {
                    getHibernateSession().flush();
                    getHibernateSession().clear();
                }
            }
            i++;
            // Increase counter and update state of import LRT.
            context.getImportTaskExecutor().increaseCounter();
            context.getImportTaskExecutor().updateState();
            BaseDto parentDto = getParentDtoFromBatch(dto, context);
            if (parentDto == null) {
                parentDto = dto;
            }
            BaseDto originalDto = dto;
            try {
                dto = makeAdvancedPairing(dto, context, dtoClass);
                if (dto == null) {
                    // If DTO after advanced pairing is null, then was not found and is optional ->
                    // skip.
                    IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), originalDto, RequestOperationType.ADD, (UUID) parentDto.getId());
                    ResultModel resultModel = new DefaultResultModel(CoreResultCode.IMPORT_DTO_SKIPPED, ImmutableMap.of("dto", originalDto.toString()));
                    dtoLog.setResult(new OperationResultDto.Builder(OperationState.CANCELED).setModel(resultModel).build());
                    importLogService.saveDistinct(dtoLog);
                    continue;
                }
            } catch (ResultCodeException ex) {
                if (context.isDryRun() && ex.getError() != null && ex.getError().getError() != null && CoreResultCode.IMPORT_ADVANCED_PARING_FAILED_NOT_FOUND.name().equals(ex.getError().getError().getStatusEnum())) {
                    // Not found DTO we will mark as skipped in dry run mode.
                    IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), originalDto, RequestOperationType.ADD, (UUID) parentDto.getId());
                    dtoLog.setResult(new OperationResultDto.Builder(OperationState.EXCEPTION).setException(ex).build());
                    importLogService.saveDistinct(dtoLog);
                    continue;
                } else if (ex.getError() != null && ex.getError().getError() != null && CoreResultCode.IMPORT_ADVANCED_PARING_NOT_FOUND_OPTIONAL.name().equals(ex.getError().getError().getStatusEnum())) {
                    // Not found DTO, but optional, we will mark as skipped.
                    IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), originalDto, RequestOperationType.ADD, (UUID) parentDto.getId());
                    dtoLog.setResult(new OperationResultDto.Builder(OperationState.CANCELED).setException(ex).build());
                    importLogService.saveDistinct(dtoLog);
                    continue;
                }
                throw ex;
            }
            Class<? extends BaseDto> serviceDtoClass = dtoClass;
            if (dto instanceof IdmFormInstanceDto) {
                // Form instance is very special here (doesn't have entity in DB).
                IdmFormInstanceDto formInstance = (IdmFormInstanceDto) dto;
                IdmFormDefinitionDto definition = formInstance.getFormDefinition();
                Assert.notNull(definition, "Definition cannot be null for import!");
                CoreEvent<IdmFormInstanceDto> event = new CoreEvent<>(CoreEventType.UPDATE, formInstance);
                // Check if owner exist (UPDATE/ADD)
                @SuppressWarnings("unchecked") Class<? extends BaseDto> ownerType = (Class<? extends BaseDto>) ((IdmFormInstanceDto) dto).getOwnerType();
                UUID ownerId = UUID.fromString((String) ((IdmFormInstanceDto) dto).getOwnerId());
                BaseDto ownerDto = this.getDtoService(ownerType).get(ownerId);
                IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), dto, ownerDto != null ? RequestOperationType.UPDATE : RequestOperationType.ADD, ownerId);
                if (!context.isDryRun()) {
                    formService.publish(event);
                    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);
                continue;
            }
            if (dto.getClass().isAnnotationPresent(Inheritable.class)) {
                serviceDtoClass = dto.getClass().getAnnotation(Inheritable.class).dtoService();
            }
            ReadWriteDtoService<BaseDto, ?> dtoService = getDtoService(serviceDtoClass);
            BaseDto currentDto = dtoService.get(dto.getId());
            if (currentDto != null) {
                // DTO with same ID already exists -> update.
                IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), dto, RequestOperationType.UPDATE, (UUID) parentDto.getId());
                // Resolve excluded fields
                dto = this.excludeFields(dto, currentDto, context);
                if (!context.isDryRun()) {
                    dtoService.save(dto);
                    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);
                continue;
            }
            if (dto instanceof Codeable) {
                // We try to find exists DTO by code.
                currentDto = lookupService.lookupDto(serviceDtoClass, ((Codeable) dto).getCode());
            }
            // Find target DTO by example source DTO (typically by more then one filter field).
            currentDto = findByExample(dto, null, context);
            if (dto instanceof IdmFormDefinitionDto) {
                IdmFormDefinitionDto definition = (IdmFormDefinitionDto) dto;
                // We try to find exists definition by code and type (IdmFormDefinitionDto is
                // not Codeable).
                currentDto = formService.getDefinition(definition.getType(), definition.getCode());
            }
            if (dto instanceof IdmFormAttributeDto) {
                IdmFormAttributeDto attribute = (IdmFormAttributeDto) dto;
                IdmFormDefinitionDto definition = formService.getDefinition(attribute.getFormDefinition());
                if (definition != null) {
                    // We try to find exists attribute definition by code and form definition.
                    currentDto = formService.getAttribute(definition, attribute.getCode());
                } else {
                    currentDto = null;
                }
            }
            if (currentDto != null) {
                // We found current DTO in IdM.
                // Save old and new ID for next DTOs.
                context.getReplacedIDs().put((UUID) dto.getId(), (UUID) currentDto.getId());
                // We have to change the ID in import DTO.
                dto.setId(currentDto.getId());
                // Update current DTO by batch DTO.
                IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), dto, RequestOperationType.UPDATE, (UUID) parentDto.getId());
                if (!context.isDryRun()) {
                    // Resolve excluded fields
                    dto = this.excludeFields(dto, currentDto, context);
                    // Save a DTO.
                    dtoService.save(dto);
                    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);
            } else {
                IdmImportLogDto dtoLog = new IdmImportLogDto(context.getBatch(), dto, RequestOperationType.ADD, (UUID) parentDto.getId());
                // No current DTO was found -> create.
                if (!context.isDryRun()) {
                    // Resolve excluded fields
                    dto = this.excludeFields(dto, null, context);
                    // Save new DTO.
                    dtoService.save(dto);
                    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 (IOException | IllegalArgumentException e) {
        throw new ResultCodeException(CoreResultCode.EXPORT_IMPORT_IO_FAILED, e);
    }
}
Also used : Codeable(eu.bcvsolutions.idm.core.api.domain.Codeable) BaseDto(eu.bcvsolutions.idm.core.api.dto.BaseDto) DefaultResultModel(eu.bcvsolutions.idm.core.api.dto.DefaultResultModel) ResultModel(eu.bcvsolutions.idm.core.api.dto.ResultModel) IdmFormAttributeDto(eu.bcvsolutions.idm.core.eav.api.dto.IdmFormAttributeDto) IdmImportLogDto(eu.bcvsolutions.idm.core.api.dto.IdmImportLogDto) UUID(java.util.UUID) Path(java.nio.file.Path) IdmFormInstanceDto(eu.bcvsolutions.idm.core.eav.api.dto.IdmFormInstanceDto) DefaultResultModel(eu.bcvsolutions.idm.core.api.dto.DefaultResultModel) ResultCodeException(eu.bcvsolutions.idm.core.api.exception.ResultCodeException) OperationResultDto(eu.bcvsolutions.idm.core.api.dto.OperationResultDto) IdmFormDefinitionDto(eu.bcvsolutions.idm.core.eav.api.dto.IdmFormDefinitionDto) IOException(java.io.IOException) CoreEvent(eu.bcvsolutions.idm.core.api.event.CoreEvent)

Aggregations

CoreEvent (eu.bcvsolutions.idm.core.api.event.CoreEvent)46 Test (org.junit.Test)27 AbstractIntegrationTest (eu.bcvsolutions.idm.test.api.AbstractIntegrationTest)17 IdmIdentityDto (eu.bcvsolutions.idm.core.api.dto.IdmIdentityDto)11 IdmRoleDto (eu.bcvsolutions.idm.core.api.dto.IdmRoleDto)10 ResultCodeException (eu.bcvsolutions.idm.core.api.exception.ResultCodeException)9 UUID (java.util.UUID)9 Transactional (org.springframework.transaction.annotation.Transactional)8 BaseDto (eu.bcvsolutions.idm.core.api.dto.BaseDto)7 IdmEntityEventDto (eu.bcvsolutions.idm.core.api.dto.IdmEntityEventDto)7 CoreEventType (eu.bcvsolutions.idm.core.api.event.CoreEvent.CoreEventType)7 IdmFormInstanceDto (eu.bcvsolutions.idm.core.eav.api.dto.IdmFormInstanceDto)7 AbstractUnitTest (eu.bcvsolutions.idm.test.api.AbstractUnitTest)7 Serializable (java.io.Serializable)7 RoleCodeEnvironmentProcessor (eu.bcvsolutions.idm.core.model.event.processor.role.RoleCodeEnvironmentProcessor)6 GuardedString (eu.bcvsolutions.idm.core.security.api.domain.GuardedString)6 IdmFormDefinitionDto (eu.bcvsolutions.idm.core.eav.api.dto.IdmFormDefinitionDto)5 TestContent (eu.bcvsolutions.idm.core.event.TestContent)5 ArrayList (java.util.ArrayList)5 IdmEntityEventFilter (eu.bcvsolutions.idm.core.api.dto.filter.IdmEntityEventFilter)4