Search in sources :

Example 1 with EvaluatedAssignmentImpl

use of com.evolveum.midpoint.model.impl.lens.EvaluatedAssignmentImpl in project midpoint by Evolveum.

the class AssignmentProcessor method evaluateConstructions.

private <F extends FocusType> void evaluateConstructions(LensContext<F> context, Collection<EvaluatedAssignmentImpl<F>> evaluatedAssignments, Task task, OperationResult result) throws SchemaException, ExpressionEvaluationException, ObjectNotFoundException {
    if (evaluatedAssignments == null) {
        return;
    }
    ObjectDeltaObject<F> focusOdo = null;
    LensFocusContext<F> focusContext = context.getFocusContext();
    if (focusContext != null) {
        focusOdo = focusContext.getObjectDeltaObject();
    }
    Iterator<EvaluatedAssignmentImpl<F>> iterator = evaluatedAssignments.iterator();
    while (iterator.hasNext()) {
        EvaluatedAssignmentImpl<F> evaluatedAssignment = iterator.next();
        try {
            evaluatedAssignment.evaluateConstructions(focusOdo, context.getSystemConfiguration(), task, result);
        } catch (ObjectNotFoundException ex) {
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Processing of assignment resulted in error {}: {}", ex, SchemaDebugUtil.prettyPrint(evaluatedAssignment.getAssignmentType()));
            }
            iterator.remove();
            if (!ModelExecuteOptions.isForce(context.getOptions())) {
                ModelUtils.recordFatalError(result, ex);
            }
        } catch (SchemaException ex) {
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Processing of assignment resulted in error {}: {}", ex, SchemaDebugUtil.prettyPrint(evaluatedAssignment.getAssignmentType()));
            }
            ModelUtils.recordFatalError(result, ex);
            String resourceOid = FocusTypeUtil.determineConstructionResource(evaluatedAssignment.getAssignmentType());
            if (resourceOid == null) {
                // This is a role assignment or something like that. Just throw the original exception for now.
                throw ex;
            }
            ResourceShadowDiscriminator rad = new ResourceShadowDiscriminator(resourceOid, FocusTypeUtil.determineConstructionKind(evaluatedAssignment.getAssignmentType()), FocusTypeUtil.determineConstructionIntent(evaluatedAssignment.getAssignmentType()));
            LensProjectionContext accCtx = context.findProjectionContext(rad);
            if (accCtx != null) {
                accCtx.setSynchronizationPolicyDecision(SynchronizationPolicyDecision.BROKEN);
            }
            iterator.remove();
        }
    }
}
Also used : EvaluatedAssignmentImpl(com.evolveum.midpoint.model.impl.lens.EvaluatedAssignmentImpl) SchemaException(com.evolveum.midpoint.util.exception.SchemaException) ObjectNotFoundException(com.evolveum.midpoint.util.exception.ObjectNotFoundException) LensProjectionContext(com.evolveum.midpoint.model.impl.lens.LensProjectionContext) ResourceShadowDiscriminator(com.evolveum.midpoint.schema.ResourceShadowDiscriminator)

Example 2 with EvaluatedAssignmentImpl

use of com.evolveum.midpoint.model.impl.lens.EvaluatedAssignmentImpl in project midpoint by Evolveum.

the class AssignmentProcessor method processAssignmentsProjectionsWithFocus.

/**
     * Processing focus-projection assignments (including roles).
     */
@SuppressWarnings({ "rawtypes", "unchecked" })
private <F extends FocusType> void processAssignmentsProjectionsWithFocus(LensContext<F> context, XMLGregorianCalendar now, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, PolicyViolationException, CommunicationException, ConfigurationException, SecurityViolationException {
    // PREPARE ASSIGNMENT DELTA
    LensFocusContext<F> focusContext = context.getFocusContext();
    ObjectDelta<F> focusDelta = focusContext.getDelta();
    if (focusDelta != null && focusDelta.isDelete()) {
        processFocusDelete(context, result);
        return;
    }
    checkAssignmentDeltaSanity(context);
    // ASSIGNMENT EVALUATION
    // Initializing assignment evaluator. This will be used later to process all the assignments including the nested
    // assignments (roles).
    AssignmentEvaluator<F> assignmentEvaluator = createAssignmentEvaluator(context, now);
    ObjectType source = determineSource(focusContext);
    AssignmentTripleEvaluator<F> assignmentTripleEvaluator = new AssignmentTripleEvaluator<>();
    assignmentTripleEvaluator.setActivationComputer(activationComputer);
    assignmentTripleEvaluator.setAssignmentEvaluator(assignmentEvaluator);
    assignmentTripleEvaluator.setContext(context);
    assignmentTripleEvaluator.setNow(now);
    assignmentTripleEvaluator.setPrismContext(prismContext);
    assignmentTripleEvaluator.setResult(result);
    assignmentTripleEvaluator.setSource(source);
    assignmentTripleEvaluator.setTask(task);
    // Normal processing. The enforcement policy requires that assigned accounts should be added, so we need to figure out
    // which assignments were added. Do a complete recompute for all the enforcement modes. We can do that because this does
    // not create deltas, it just creates the triples. So we can decide what to do later when we convert triples to deltas.
    // Evaluates all assignments and sorts them to triple: added, removed and untouched assignments.
    // This is where most of the assignment-level action happens.
    DeltaSetTriple<EvaluatedAssignmentImpl<F>> evaluatedAssignmentTriple = assignmentTripleEvaluator.processAllAssignments();
    policyRuleProcessor.addGlobalPoliciesToAssignments(context, evaluatedAssignmentTriple, task, result);
    context.setEvaluatedAssignmentTriple((DeltaSetTriple) evaluatedAssignmentTriple);
    if (LOGGER.isTraceEnabled()) {
        LOGGER.trace("evaluatedAssignmentTriple:\n{}", evaluatedAssignmentTriple.debugDump());
    }
    // PROCESSING POLICIES
    policyRuleProcessor.processPolicies(context, evaluatedAssignmentTriple, result);
    boolean needToReevaluateAssignments = policyRuleProcessor.processPruning(context, evaluatedAssignmentTriple, result);
    if (needToReevaluateAssignments) {
        LOGGER.debug("Re-evaluating assignments because exclusion pruning rule was triggered");
        evaluatedAssignmentTriple = assignmentTripleEvaluator.processAllAssignments();
        context.setEvaluatedAssignmentTriple((DeltaSetTriple) evaluatedAssignmentTriple);
        policyRuleProcessor.addGlobalPoliciesToAssignments(context, evaluatedAssignmentTriple, task, result);
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("re-evaluatedAssignmentTriple:\n{}", evaluatedAssignmentTriple.debugDump());
        }
        policyRuleProcessor.processPolicies(context, evaluatedAssignmentTriple, result);
    }
    //policyRuleProcessor.storeAssignmentPolicySituation(context, evaluatedAssignmentTriple, result);
    // PROCESSING FOCUS
    Map<ItemPath, DeltaSetTriple<? extends ItemValueWithOrigin<?, ?>>> focusOutputTripleMap = new HashMap<>();
    collectFocusTripleFromMappings(evaluatedAssignmentTriple.getPlusSet(), focusOutputTripleMap, PlusMinusZero.PLUS);
    collectFocusTripleFromMappings(evaluatedAssignmentTriple.getMinusSet(), focusOutputTripleMap, PlusMinusZero.MINUS);
    collectFocusTripleFromMappings(evaluatedAssignmentTriple.getZeroSet(), focusOutputTripleMap, PlusMinusZero.ZERO);
    ObjectDeltaObject<F> focusOdo = focusContext.getObjectDeltaObject();
    Collection<ItemDelta<?, ?>> focusDeltas = objectTemplateProcessor.computeItemDeltas(focusOutputTripleMap, null, focusOdo.getObjectDelta(), focusOdo.getNewObject(), focusContext.getObjectDefinition(), "focus mappings in assignments of " + focusContext.getHumanReadableName());
    LOGGER.trace("Computed focus deltas: {}", focusDeltas);
    focusContext.applyProjectionWaveSecondaryDeltas(focusDeltas);
    focusContext.recompute();
    // PROCESSING PROJECTIONS
    // Evaluate the constructions in assignements now. These were not evaluated in the first pass of AssignmentEvaluator
    // because there may be interaction from focusMappings of some roles to outbound mappings of other roles.
    // Now we have complete focus with all the focusMappings so we can evaluate the constructions
    evaluateConstructions(context, evaluatedAssignmentTriple, task, result);
    ComplexConstructionConsumer<ResourceShadowDiscriminator, Construction<F>> consumer = new ComplexConstructionConsumer<ResourceShadowDiscriminator, Construction<F>>() {

        private boolean processOnlyExistingProjCxts;

        @Override
        public boolean before(ResourceShadowDiscriminator rat) {
            if (rat.getResourceOid() == null) {
                throw new IllegalStateException("Resource OID null in ResourceAccountType during assignment processing");
            }
            if (rat.getIntent() == null) {
                throw new IllegalStateException("Account type is null in ResourceAccountType during assignment processing");
            }
            processOnlyExistingProjCxts = false;
            if (ModelExecuteOptions.isLimitPropagation(context.getOptions())) {
                if (context.getTriggeredResourceOid() != null && !rat.getResourceOid().equals(context.getTriggeredResourceOid())) {
                    LOGGER.trace("Skipping processing construction for shadow identified by {} because of limitation to propagate changes only for resource {}", rat, context.getTriggeredResourceOid());
                    return false;
                }
                if (SchemaConstants.CHANGE_CHANNEL_DISCOVERY.equals(QNameUtil.uriToQName(context.getChannel()))) {
                    // TODO is this message OK? [med]
                    LOGGER.trace("Processing of shadow identified by {} will be skipped because of limitation for discovery channel.");
                    processOnlyExistingProjCxts = true;
                }
            }
            return true;
        }

        @Override
        public void onAssigned(ResourceShadowDiscriminator rat, String desc) {
            LensProjectionContext projectionContext = LensUtil.getOrCreateProjectionContext(context, rat);
            projectionContext.setAssigned(true);
            projectionContext.setAssignedOld(false);
            projectionContext.setLegalOld(false);
            AssignmentPolicyEnforcementType assignmentPolicyEnforcement = projectionContext.getAssignmentPolicyEnforcementType();
            if (assignmentPolicyEnforcement != AssignmentPolicyEnforcementType.NONE) {
                LOGGER.trace("Projection {} legal: assigned (valid)", desc);
                projectionContext.setLegal(true);
            }
        }

        @Override
        public void onUnchangedValid(ResourceShadowDiscriminator key, String desc) {
            LensProjectionContext projectionContext = context.findProjectionContext(key);
            if (projectionContext == null) {
                if (processOnlyExistingProjCxts) {
                    return;
                }
                // The projection should exist before the change but it does not
                // This happens during reconciliation if there is an inconsistency. 
                // Pretend that the assignment was just added. That should do.
                projectionContext = LensUtil.getOrCreateProjectionContext(context, key);
            }
            LOGGER.trace("Projection {} legal: unchanged (valid)", desc);
            projectionContext.setLegal(true);
            projectionContext.setLegalOld(true);
            projectionContext.setAssigned(true);
            projectionContext.setAssignedOld(true);
        }

        @Override
        public void onUnchangedInvalid(ResourceShadowDiscriminator rat, String desc) {
            LensProjectionContext projectionContext = context.findProjectionContext(rat);
            if (projectionContext == null) {
                if (processOnlyExistingProjCxts) {
                    return;
                }
                // The projection should exist before the change but it does not
                // This happens during reconciliation if there is an inconsistency. 
                // Pretend that the assignment was just added. That should do.
                projectionContext = LensUtil.getOrCreateProjectionContext(context, rat);
            }
            LOGGER.trace("Projection {} illegal: unchanged (invalid)", desc);
            projectionContext.setLegal(false);
            projectionContext.setLegalOld(false);
            projectionContext.setAssigned(false);
            projectionContext.setAssignedOld(false);
        }

        @Override
        public void onUnassigned(ResourceShadowDiscriminator rat, String desc) {
            if (accountExists(context, rat)) {
                LensProjectionContext projectionContext = context.findProjectionContext(rat);
                if (projectionContext == null) {
                    if (processOnlyExistingProjCxts) {
                        return;
                    }
                    projectionContext = LensUtil.getOrCreateProjectionContext(context, rat);
                }
                projectionContext.setAssigned(false);
                projectionContext.setAssignedOld(true);
                projectionContext.setLegalOld(true);
                AssignmentPolicyEnforcementType assignmentPolicyEnforcement = projectionContext.getAssignmentPolicyEnforcementType();
                // TODO: check for MARK and LEGALIZE enforcement policies ....add delete laso for relative enforcemenet
                if (assignmentPolicyEnforcement == AssignmentPolicyEnforcementType.FULL || assignmentPolicyEnforcement == AssignmentPolicyEnforcementType.RELATIVE) {
                    LOGGER.trace("Projection {} illegal: unassigned", desc);
                    projectionContext.setLegal(false);
                } else {
                    LOGGER.trace("Projection {} legal: unassigned, but allowed by policy ({})", desc, assignmentPolicyEnforcement);
                    projectionContext.setLegal(true);
                }
            } else {
                LOGGER.trace("Projection {} nothing: unassigned (valid->invalid) but not there", desc);
            // We have to delete something that is not there. Nothing to do.
            }
        }

        @Override
        public void after(ResourceShadowDiscriminator rat, String desc, DeltaMapTriple<ResourceShadowDiscriminator, ConstructionPack<Construction<F>>> constructionMapTriple) {
            PrismValueDeltaSetTriple<PrismPropertyValue<Construction>> projectionConstructionDeltaSetTriple = new PrismValueDeltaSetTriple<>(getConstructions(constructionMapTriple.getZeroMap().get(rat), true), getConstructions(constructionMapTriple.getPlusMap().get(rat), true), getConstructions(constructionMapTriple.getMinusMap().get(rat), false));
            LensProjectionContext projectionContext = context.findProjectionContext(rat);
            if (projectionContext != null) {
                // This can be null in a exotic case if we delete already deleted account
                if (LOGGER.isTraceEnabled()) {
                    LOGGER.trace("Construction delta set triple for {}:\n{}", rat, projectionConstructionDeltaSetTriple.debugDump(1));
                }
                projectionContext.setConstructionDeltaSetTriple(projectionConstructionDeltaSetTriple);
                if (isForceRecon(constructionMapTriple.getZeroMap().get(rat)) || isForceRecon(constructionMapTriple.getPlusMap().get(rat)) || isForceRecon(constructionMapTriple.getMinusMap().get(rat))) {
                    projectionContext.setDoReconciliation(true);
                }
            }
        }
    };
    constructionProcessor.processConstructions(context, evaluatedAssignmentTriple, evaluatedAssignment -> evaluatedAssignment.getConstructionTriple(), construction -> getConstructionMapKey(context, construction, task, result), consumer, task, result);
    removeIgnoredContexts(context);
    finishLegalDecisions(context);
}
Also used : PrismValueDeltaSetTriple(com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple) DeltaSetTriple(com.evolveum.midpoint.prism.delta.DeltaSetTriple) ItemDelta(com.evolveum.midpoint.prism.delta.ItemDelta) DeltaMapTriple(com.evolveum.midpoint.prism.delta.DeltaMapTriple) PrismPropertyValue(com.evolveum.midpoint.prism.PrismPropertyValue) Construction(com.evolveum.midpoint.model.impl.lens.Construction) PrismValueDeltaSetTriple(com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple) LensProjectionContext(com.evolveum.midpoint.model.impl.lens.LensProjectionContext) EvaluatedAssignmentImpl(com.evolveum.midpoint.model.impl.lens.EvaluatedAssignmentImpl) ItemValueWithOrigin(com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin) ResourceShadowDiscriminator(com.evolveum.midpoint.schema.ResourceShadowDiscriminator) ItemPath(com.evolveum.midpoint.prism.path.ItemPath)

Example 3 with EvaluatedAssignmentImpl

use of com.evolveum.midpoint.model.impl.lens.EvaluatedAssignmentImpl in project midpoint by Evolveum.

the class NotificationChangeHook method emitPolicyRulesEvents.

private void emitPolicyRulesEvents(ModelContext<?> context, Task task, OperationResult result) {
    LensFocusContext<?> focusContext = (LensFocusContext<?>) context.getFocusContext();
    for (EvaluatedPolicyRule rule : focusContext.getPolicyRules()) {
        emitPolicyEventIfPresent(rule, context, task, result);
    }
    DeltaSetTriple<EvaluatedAssignmentImpl<?>> triple = ((LensContext<?>) context).getEvaluatedAssignmentTriple();
    if (triple != null) {
        for (EvaluatedAssignment<?> assignment : triple.getNonNegativeValues()) {
            for (EvaluatedPolicyRule rule : assignment.getAllTargetsPolicyRules()) {
                emitPolicyEventIfPresent(rule, context, task, result);
            }
        }
    }
}
Also used : EvaluatedPolicyRule(com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule) EvaluatedAssignmentImpl(com.evolveum.midpoint.model.impl.lens.EvaluatedAssignmentImpl) LensContext(com.evolveum.midpoint.model.impl.lens.LensContext) LensFocusContext(com.evolveum.midpoint.model.impl.lens.LensFocusContext)

Example 4 with EvaluatedAssignmentImpl

use of com.evolveum.midpoint.model.impl.lens.EvaluatedAssignmentImpl in project midpoint by Evolveum.

the class FocusProcessor method triggerAssignmentFocusPolicyRules.

// TODO: should we really do this? Focus policy rules (e.g. forbidden modifications) are irrelevant in this situation,
// TODO: i.e. if we are assigning the object into some other object [med]
private <F extends FocusType> void triggerAssignmentFocusPolicyRules(LensContext<F> context, String activityDescription, XMLGregorianCalendar now, Task task, OperationResult result) throws PolicyViolationException, SchemaException {
    LensFocusContext<F> focusContext = context.getFocusContext();
    DeltaSetTriple<EvaluatedAssignmentImpl<?>> evaluatedAssignmentTriple = context.getEvaluatedAssignmentTriple();
    if (evaluatedAssignmentTriple == null) {
        return;
    }
    for (EvaluatedAssignmentImpl<?> evaluatedAssignment : evaluatedAssignmentTriple.getNonNegativeValues()) {
        Collection<EvaluatedPolicyRule> policyRules = evaluatedAssignment.getFocusPolicyRules();
        for (EvaluatedPolicyRule policyRule : policyRules) {
            triggerRule(focusContext, policyRule);
        }
    }
}
Also used : EvaluatedAssignmentImpl(com.evolveum.midpoint.model.impl.lens.EvaluatedAssignmentImpl) EvaluatedPolicyRule(com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule)

Example 5 with EvaluatedAssignmentImpl

use of com.evolveum.midpoint.model.impl.lens.EvaluatedAssignmentImpl in project midpoint by Evolveum.

the class AssignmentTripleEvaluator method processAssignment.

private void processAssignment(DeltaSetTriple<EvaluatedAssignmentImpl<F>> evaluatedAssignmentTriple, ObjectDelta<F> focusDelta, ContainerDelta<AssignmentType> assignmentDelta, SmartAssignmentElement assignmentElement) throws SchemaException, ExpressionEvaluationException, PolicyViolationException {
    LensFocusContext<F> focusContext = context.getFocusContext();
    PrismContainerValue<AssignmentType> assignmentCVal = assignmentElement.getAssignmentCVal();
    AssignmentType assignmentType = assignmentCVal.asContainerable();
    PrismContainerValue<AssignmentType> assignmentCValOld = assignmentCVal;
    PrismContainerValue<AssignmentType> assignmentCValNew = assignmentCVal;
    ItemDeltaItem<PrismContainerValue<AssignmentType>, PrismContainerDefinition<AssignmentType>> assignmentIdi = new ItemDeltaItem<>();
    assignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(assignmentType));
    boolean presentInCurrent = assignmentElement.isCurrent();
    boolean presentInOld = assignmentElement.isOld();
    // This really means whether the WHOLE assignment was changed (e.g. added/delted/replaced). It tells nothing
    // about "micro-changes" inside assignment, these will be processed later.
    boolean isAssignmentChanged = assignmentElement.isChanged();
    boolean forceRecon = false;
    String assignmentPlacementDesc;
    if (isAssignmentChanged) {
        // Whole assignment added or deleted
        assignmentPlacementDesc = "delta for " + source;
    } else {
        assignmentPlacementDesc = source.toString();
        Collection<? extends ItemDelta<?, ?>> assignmentItemDeltas = getExecutionWaveAssignmentItemDeltas(focusContext, assignmentCVal.getId());
        if (assignmentItemDeltas != null && !assignmentItemDeltas.isEmpty()) {
            // Small changes inside assignment, but otherwise the assignment stays as it is (not added or deleted)
            assignmentIdi.setSubItemDeltas(assignmentItemDeltas);
            // The subItemDeltas above will handle some changes. But not other.
            // E.g. a replace of the whole construction will not be handled properly.
            // Therefore we force recon to sort it out.
            forceRecon = true;
            isAssignmentChanged = true;
            PrismContainer<AssignmentType> assContNew = focusContext.getObjectNew().findContainer(FocusType.F_ASSIGNMENT);
            assignmentCValNew = assContNew.getValue(assignmentCVal.getId());
        }
    }
    assignmentIdi.recompute();
    if (focusDelta != null && focusDelta.isDelete()) {
        // were not changed explicitly.
        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Processing focus delete for: {}", SchemaDebugUtil.prettyPrint(assignmentCVal));
        }
        EvaluatedAssignmentImpl<F> evaluatedAssignment = evaluateAssignment(assignmentIdi, PlusMinusZero.MINUS, false, context, source, assignmentEvaluator, assignmentPlacementDesc, task, result);
        if (evaluatedAssignment == null) {
            return;
        }
        evaluatedAssignment.setPresentInCurrentObject(presentInCurrent);
        evaluatedAssignment.setPresentInOldObject(presentInOld);
        collectToMinus(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon);
    } else {
        if (assignmentDelta.isReplace()) {
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Processing replace of all assignments for: {}", SchemaDebugUtil.prettyPrint(assignmentCVal));
            }
            // ASSIGNMENT REPLACE
            // Handling assignment replace delta. This needs to be handled specially as all the "old"
            // assignments should be considered deleted - except those that are part of the new value set
            // (remain after replace). As account delete and add are costly operations (and potentially dangerous)
            // we optimize here are consider the assignments that were there before replace and still are there
            // after it as unchanged.
            boolean hadValue = presentInCurrent;
            boolean willHaveValue = assignmentDelta.isValueToReplace(assignmentCVal, true);
            if (hadValue && willHaveValue) {
                // No change
                EvaluatedAssignmentImpl<F> evaluatedAssignment = evaluateAssignment(assignmentIdi, PlusMinusZero.ZERO, false, context, source, assignmentEvaluator, assignmentPlacementDesc, task, result);
                if (evaluatedAssignment == null) {
                    return;
                }
                evaluatedAssignment.setPresentInCurrentObject(presentInCurrent);
                evaluatedAssignment.setPresentInOldObject(presentInOld);
                collectToZero(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon);
            } else if (willHaveValue) {
                // add
                EvaluatedAssignmentImpl<F> evaluatedAssignment = evaluateAssignment(assignmentIdi, PlusMinusZero.PLUS, false, context, source, assignmentEvaluator, assignmentPlacementDesc, task, result);
                if (evaluatedAssignment == null) {
                    return;
                }
                evaluatedAssignment.setPresentInCurrentObject(presentInCurrent);
                evaluatedAssignment.setPresentInOldObject(presentInOld);
                collectToPlus(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon);
            } else if (hadValue) {
                // delete
                EvaluatedAssignmentImpl<F> evaluatedAssignment = evaluateAssignment(assignmentIdi, PlusMinusZero.MINUS, true, context, source, assignmentEvaluator, assignmentPlacementDesc, task, result);
                if (evaluatedAssignment == null) {
                    return;
                }
                evaluatedAssignment.setPresentInCurrentObject(presentInCurrent);
                evaluatedAssignment.setPresentInOldObject(presentInOld);
                collectToMinus(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon);
            } else if (assignmentElement.isOld()) {
                // This is OK, safe to skip. This is just an relic of earlier processing.
                return;
            } else {
                LOGGER.error("Whoops. Unexpected things happen. Assignment is neither current, old nor new (replace delta)\n{}", assignmentElement.debugDump(1));
                throw new SystemException("Whoops. Unexpected things happen. Assignment is neither current, old nor new (replace delta).");
            }
        } else {
            // Just sort assignments to sets: unchanged (zero), added (plus), removed (minus)
            if (isAssignmentChanged) {
                // There was some change
                boolean isAdd = assignmentDelta.isValueToAdd(assignmentCVal, true);
                boolean isDelete = assignmentDelta.isValueToDelete(assignmentCVal, true);
                if (isAdd & !isDelete) {
                    // Entirely new assignment is added
                    if (presentInCurrent && presentInOld) {
                        // Phantom add: adding assignment that is already there
                        if (LOGGER.isTraceEnabled()) {
                            LOGGER.trace("Processing changed assignment, phantom add: {}", SchemaDebugUtil.prettyPrint(assignmentCVal));
                        }
                        EvaluatedAssignmentImpl<F> evaluatedAssignment = evaluateAssignment(assignmentIdi, PlusMinusZero.ZERO, false, context, source, assignmentEvaluator, assignmentPlacementDesc, task, result);
                        if (evaluatedAssignment == null) {
                            return;
                        }
                        evaluatedAssignment.setPresentInCurrentObject(presentInCurrent);
                        evaluatedAssignment.setPresentInOldObject(presentInOld);
                        collectToZero(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon);
                    } else {
                        if (LOGGER.isTraceEnabled()) {
                            LOGGER.trace("Processing changed assignment, add: {}", SchemaDebugUtil.prettyPrint(assignmentCVal));
                        }
                        EvaluatedAssignmentImpl<F> evaluatedAssignment = evaluateAssignment(assignmentIdi, PlusMinusZero.PLUS, false, context, source, assignmentEvaluator, assignmentPlacementDesc, task, result);
                        if (evaluatedAssignment == null) {
                            return;
                        }
                        evaluatedAssignment.setPresentInCurrentObject(presentInCurrent);
                        evaluatedAssignment.setPresentInOldObject(presentInOld);
                        collectToPlus(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon);
                    }
                } else if (isDelete && !isAdd) {
                    // Existing assignment is removed
                    if (LOGGER.isTraceEnabled()) {
                        LOGGER.trace("Processing changed assignment, delete: {}", SchemaDebugUtil.prettyPrint(assignmentCVal));
                    }
                    EvaluatedAssignmentImpl<F> evaluatedAssignment = evaluateAssignment(assignmentIdi, PlusMinusZero.MINUS, true, context, source, assignmentEvaluator, assignmentPlacementDesc, task, result);
                    if (evaluatedAssignment == null) {
                        return;
                    }
                    evaluatedAssignment.setPresentInCurrentObject(presentInCurrent);
                    evaluatedAssignment.setPresentInOldObject(presentInOld);
                    collectToMinus(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon);
                } else {
                    // Small change inside an assignment
                    // The only thing that we need to worry about is assignment validity change. That is a cause
                    // of provisioning/deprovisioning of the projections. So check that explicitly. Other changes are
                    // not significant, i.e. reconciliation can handle them.
                    boolean isValidOld = LensUtil.isAssignmentValid(focusContext.getObjectOld().asObjectable(), assignmentCValOld.asContainerable(), now, activationComputer);
                    boolean isValid = LensUtil.isAssignmentValid(focusContext.getObjectNew().asObjectable(), assignmentCValNew.asContainerable(), now, activationComputer);
                    if (isValid == isValidOld) {
                        // The change is not significant for assignment applicability. Recon will sort out the details.
                        if (LOGGER.isTraceEnabled()) {
                            LOGGER.trace("Processing changed assignment, minor change (add={}, delete={}, valid={}): {}", new Object[] { isAdd, isDelete, isValid, SchemaDebugUtil.prettyPrint(assignmentCVal) });
                        }
                        EvaluatedAssignmentImpl<F> evaluatedAssignment = evaluateAssignment(assignmentIdi, PlusMinusZero.ZERO, false, context, source, assignmentEvaluator, assignmentPlacementDesc, task, result);
                        if (evaluatedAssignment == null) {
                            return;
                        }
                        evaluatedAssignment.setPresentInCurrentObject(presentInCurrent);
                        evaluatedAssignment.setPresentInOldObject(presentInOld);
                        collectToZero(evaluatedAssignmentTriple, evaluatedAssignment, true);
                    } else if (isValid) {
                        // Assignment became valid. We need to place it in plus set to initiate provisioning
                        if (LOGGER.isTraceEnabled()) {
                            LOGGER.trace("Processing changed assignment, assignment becomes valid (add={}, delete={}): {}", new Object[] { isAdd, isDelete, SchemaDebugUtil.prettyPrint(assignmentCVal) });
                        }
                        EvaluatedAssignmentImpl<F> evaluatedAssignment = evaluateAssignment(assignmentIdi, PlusMinusZero.PLUS, false, context, source, assignmentEvaluator, assignmentPlacementDesc, task, result);
                        if (evaluatedAssignment == null) {
                            return;
                        }
                        evaluatedAssignment.setPresentInCurrentObject(presentInCurrent);
                        evaluatedAssignment.setPresentInOldObject(presentInOld);
                        collectToPlus(evaluatedAssignmentTriple, evaluatedAssignment, true);
                    } else {
                        // Assignment became invalid. We need to place is in minus set to initiate deprovisioning
                        if (LOGGER.isTraceEnabled()) {
                            LOGGER.trace("Processing changed assignment, assignment becomes invalid (add={}, delete={}): {}", new Object[] { isAdd, isDelete, SchemaDebugUtil.prettyPrint(assignmentCVal) });
                        }
                        EvaluatedAssignmentImpl<F> evaluatedAssignment = evaluateAssignment(assignmentIdi, PlusMinusZero.MINUS, false, context, source, assignmentEvaluator, assignmentPlacementDesc, task, result);
                        if (evaluatedAssignment == null) {
                            return;
                        }
                        evaluatedAssignment.setPresentInCurrentObject(presentInCurrent);
                        evaluatedAssignment.setPresentInOldObject(presentInOld);
                        collectToMinus(evaluatedAssignmentTriple, evaluatedAssignment, true);
                    }
                }
            } else {
                // No change in assignment
                if (LOGGER.isTraceEnabled()) {
                    LOGGER.trace("Processing unchanged assignment {}", new Object[] { SchemaDebugUtil.prettyPrint(assignmentCVal) });
                }
                EvaluatedAssignmentImpl<F> evaluatedAssignment = evaluateAssignment(assignmentIdi, PlusMinusZero.ZERO, false, context, source, assignmentEvaluator, assignmentPlacementDesc, task, result);
                if (evaluatedAssignment == null) {
                    return;
                }
                evaluatedAssignment.setPresentInCurrentObject(presentInCurrent);
                evaluatedAssignment.setPresentInOldObject(presentInOld);
                collectToZero(evaluatedAssignmentTriple, evaluatedAssignment, forceRecon);
            }
        }
    }
}
Also used : PrismContainerValue(com.evolveum.midpoint.prism.PrismContainerValue) EvaluatedAssignmentImpl(com.evolveum.midpoint.model.impl.lens.EvaluatedAssignmentImpl) ItemDeltaItem(com.evolveum.midpoint.repo.common.expression.ItemDeltaItem) SystemException(com.evolveum.midpoint.util.exception.SystemException) AssignmentType(com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType) PrismContainerDefinition(com.evolveum.midpoint.prism.PrismContainerDefinition) PrismObject(com.evolveum.midpoint.prism.PrismObject)

Aggregations

EvaluatedAssignmentImpl (com.evolveum.midpoint.model.impl.lens.EvaluatedAssignmentImpl)5 EvaluatedPolicyRule (com.evolveum.midpoint.model.api.context.EvaluatedPolicyRule)2 LensProjectionContext (com.evolveum.midpoint.model.impl.lens.LensProjectionContext)2 ResourceShadowDiscriminator (com.evolveum.midpoint.schema.ResourceShadowDiscriminator)2 Construction (com.evolveum.midpoint.model.impl.lens.Construction)1 ItemValueWithOrigin (com.evolveum.midpoint.model.impl.lens.ItemValueWithOrigin)1 LensContext (com.evolveum.midpoint.model.impl.lens.LensContext)1 LensFocusContext (com.evolveum.midpoint.model.impl.lens.LensFocusContext)1 PrismContainerDefinition (com.evolveum.midpoint.prism.PrismContainerDefinition)1 PrismContainerValue (com.evolveum.midpoint.prism.PrismContainerValue)1 PrismObject (com.evolveum.midpoint.prism.PrismObject)1 PrismPropertyValue (com.evolveum.midpoint.prism.PrismPropertyValue)1 DeltaMapTriple (com.evolveum.midpoint.prism.delta.DeltaMapTriple)1 DeltaSetTriple (com.evolveum.midpoint.prism.delta.DeltaSetTriple)1 ItemDelta (com.evolveum.midpoint.prism.delta.ItemDelta)1 PrismValueDeltaSetTriple (com.evolveum.midpoint.prism.delta.PrismValueDeltaSetTriple)1 ItemPath (com.evolveum.midpoint.prism.path.ItemPath)1 ItemDeltaItem (com.evolveum.midpoint.repo.common.expression.ItemDeltaItem)1 ObjectNotFoundException (com.evolveum.midpoint.util.exception.ObjectNotFoundException)1 SchemaException (com.evolveum.midpoint.util.exception.SchemaException)1