Search in sources :

Example 1 with EvaluationOrder

use of com.evolveum.midpoint.model.api.context.EvaluationOrder in project midpoint by Evolveum.

the class AssignmentEvaluator method evaluateAssignment.

private void evaluateAssignment(AssignmentPathSegmentImpl segment, PlusMinusZero mode, boolean isValid, EvaluationContext ctx, FocusType targetType, QName relation, AssignmentType roleAssignment) throws SchemaException, ObjectNotFoundException, ExpressionEvaluationException, PolicyViolationException {
    ObjectType orderOneObject = getOrderOneObject(segment);
    if (ObjectTypeUtil.isDelegationRelation(relation)) {
        // We have to handle assignments as though they were inducements here.
        if (!isInducementAllowedByLimitations(segment, roleAssignment)) {
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Skipping application of delegated assignment {} because it is limited in the delegation", FocusTypeUtil.dumpAssignment(roleAssignment));
            }
            return;
        }
    }
    QName nextRelation = getRelation(roleAssignment);
    EvaluationOrder nextEvaluationOrder = segment.getEvaluationOrder().advance(nextRelation);
    EvaluationOrder nextEvaluationOrderForTarget = segment.getEvaluationOrderForTarget().advance(nextRelation);
    if (LOGGER.isTraceEnabled()) {
        LOGGER.trace("orig EO({}): follow assignment {} {}; new EO({})", segment.getEvaluationOrder().shortDump(), targetType, FocusTypeUtil.dumpAssignment(roleAssignment), nextEvaluationOrder);
    }
    ItemDeltaItem<PrismContainerValue<AssignmentType>, PrismContainerDefinition<AssignmentType>> roleAssignmentIdi = new ItemDeltaItem<>();
    roleAssignmentIdi.setItemOld(LensUtil.createAssignmentSingleValueContainerClone(roleAssignment));
    roleAssignmentIdi.recompute();
    String nextSourceDescription = targetType + " in " + segment.sourceDescription;
    AssignmentPathSegmentImpl nextSegment = new AssignmentPathSegmentImpl(targetType, nextSourceDescription, roleAssignmentIdi, true);
    nextSegment.setRelation(nextRelation);
    nextSegment.setEvaluationOrder(nextEvaluationOrder);
    nextSegment.setEvaluationOrderForTarget(nextEvaluationOrderForTarget);
    nextSegment.setOrderOneObject(orderOneObject);
    // TODO why??? this should depend on evaluation order
    if (targetType instanceof AbstractRoleType) {
        // evaluation order of an assignment is probably too high (TODO but not in case of inducements going back into zero or negative orders!)
        nextSegment.setProcessMembership(false);
    } else {
        // We want to process membership in case of deputy and similar user->user assignments
        nextSegment.setProcessMembership(true);
    }
    nextSegment.setPathToSourceValid(isValid);
    assert !ctx.assignmentPath.isEmpty();
    evaluateFromSegment(nextSegment, mode, ctx);
}
Also used : ItemDeltaItem(com.evolveum.midpoint.repo.common.expression.ItemDeltaItem) QName(javax.xml.namespace.QName) EvaluationOrder(com.evolveum.midpoint.model.api.context.EvaluationOrder)

Example 2 with EvaluationOrder

use of com.evolveum.midpoint.model.api.context.EvaluationOrder in project midpoint by Evolveum.

the class AssignmentEvaluator method adjustOrder.

private void adjustOrder(Holder<EvaluationOrder> evaluationOrderHolder, Holder<EvaluationOrder> targetEvaluationOrderHolder, List<OrderConstraintsType> constraints, Integer order, AssignmentPathImpl assignmentPath, AssignmentPathSegmentImpl nextSegment) {
    if (constraints.isEmpty()) {
        if (order == null || order == 1) {
            return;
        } else if (order <= 0) {
            throw new IllegalStateException("Wrong inducement order: it must be positive but it is " + order + " instead");
        }
        // converting legacy -> new specification
        int currentOrder = evaluationOrderHolder.getValue().getSummaryOrder();
        if (order > currentOrder) {
            LOGGER.trace("order of the inducement ({}) is greater than the current evaluation order ({}), marking as undefined", order, currentOrder);
            makeUndefined(evaluationOrderHolder, targetEvaluationOrderHolder);
            return;
        }
        // i.e. currentOrder >= order, i.e. currentOrder > order-1
        int newOrder = currentOrder - (order - 1);
        assert newOrder > 0;
        constraints = Collections.singletonList(new OrderConstraintsType(prismContext).order(order).resetOrder(newOrder));
    }
    OrderConstraintsType summaryConstraints = ObjectTypeUtil.getConstraintFor(constraints, null);
    Integer resetSummaryTo = summaryConstraints != null && summaryConstraints.getResetOrder() != null ? summaryConstraints.getResetOrder() : null;
    if (resetSummaryTo != null) {
        int summaryBackwards = evaluationOrderHolder.getValue().getSummaryOrder() - resetSummaryTo;
        if (summaryBackwards < 0) {
            // or should we throw an exception?
            LOGGER.warn("Cannot move summary order backwards to a negative value ({}). Current order: {}, requested order: {}", summaryBackwards, evaluationOrderHolder.getValue().getSummaryOrder(), resetSummaryTo);
            makeUndefined(evaluationOrderHolder, targetEvaluationOrderHolder);
            return;
        } else if (summaryBackwards > 0) {
            //				MultiSet<QName> backRelations = new HashMultiSet<>();
            int assignmentsSeen = 0;
            int i = assignmentPath.size() - 1;
            while (assignmentsSeen < summaryBackwards) {
                if (i < 0) {
                    LOGGER.trace("Cannot move summary order backwards by {}; only {} assignments segment seen: {}", summaryBackwards, assignmentsSeen, assignmentPath);
                    makeUndefined(evaluationOrderHolder, targetEvaluationOrderHolder);
                    return;
                }
                AssignmentPathSegmentImpl segment = assignmentPath.getSegments().get(i);
                if (segment.isAssignment()) {
                    if (!ObjectTypeUtil.isDelegationRelation(segment.getRelation())) {
                        // backRelations.add(segment.getRelation());
                        assignmentsSeen++;
                        LOGGER.trace("Going back {}: relation at assignment -{} (position -{}): {}", summaryBackwards, assignmentsSeen, assignmentPath.size() - i, segment.getRelation());
                    }
                } else {
                    AssignmentType inducement = segment.getAssignment();
                    for (OrderConstraintsType constraint : inducement.getOrderConstraint()) {
                        if (constraint.getResetOrder() != null && constraint.getRelation() != null) {
                            LOGGER.debug("Going back {}: an inducement with non-summary resetting constraint found" + " in the chain (at position -{}): {} in {}", summaryBackwards, assignmentPath.size() - i, constraint, segment);
                            makeUndefined(evaluationOrderHolder, targetEvaluationOrderHolder);
                            return;
                        }
                    }
                    if (segment.getLastEqualOrderSegmentIndex() != null) {
                        i = segment.getLastEqualOrderSegmentIndex();
                        continue;
                    }
                }
                i--;
            }
            nextSegment.setLastEqualOrderSegmentIndex(i);
            evaluationOrderHolder.setValue(assignmentPath.getSegments().get(i).getEvaluationOrder());
            targetEvaluationOrderHolder.setValue(assignmentPath.getSegments().get(i).getEvaluationOrderForTarget());
        } else {
        // summaryBackwards is 0 - nothing to change
        }
        for (OrderConstraintsType constraint : constraints) {
            if (constraint.getRelation() != null && constraint.getResetOrder() != null) {
                LOGGER.warn("Ignoring resetOrder (with a value of {} for {}) because summary order was already moved backwards by {} to {}: {}", constraint.getResetOrder(), constraint.getRelation(), summaryBackwards, evaluationOrderHolder.getValue().getSummaryOrder(), constraint);
            }
        }
    } else {
        EvaluationOrder beforeChange = evaluationOrderHolder.getValue().clone();
        for (OrderConstraintsType constraint : constraints) {
            if (constraint.getResetOrder() != null) {
                // already processed above
                assert constraint.getRelation() != null;
                int currentOrder = evaluationOrderHolder.getValue().getMatchingRelationOrder(constraint.getRelation());
                int newOrder = constraint.getResetOrder();
                if (newOrder > currentOrder) {
                    LOGGER.warn("Cannot increase evaluation order for {} from {} to {}: {}", constraint.getRelation(), currentOrder, newOrder, constraint);
                } else if (newOrder < currentOrder) {
                    evaluationOrderHolder.setValue(evaluationOrderHolder.getValue().resetOrder(constraint.getRelation(), newOrder));
                    LOGGER.trace("Reset order for {} from {} to {} -> {}", constraint.getRelation(), currentOrder, newOrder, evaluationOrderHolder.getValue());
                } else {
                    LOGGER.trace("Keeping order for {} at {} -> {}", constraint.getRelation(), currentOrder, evaluationOrderHolder.getValue());
                }
            }
        }
        Map<QName, Integer> difference = beforeChange.diff(evaluationOrderHolder.getValue());
        targetEvaluationOrderHolder.setValue(targetEvaluationOrderHolder.getValue().applyDifference(difference));
    }
    if (evaluationOrderHolder.getValue().getSummaryOrder() <= 0) {
        makeUndefined(evaluationOrderHolder, targetEvaluationOrderHolder);
    }
    if (!targetEvaluationOrderHolder.getValue().isValid()) {
        // some extreme cases like the one described in TestAssignmentProcessor2.test520
        makeUndefined(targetEvaluationOrderHolder);
    }
    if (!evaluationOrderHolder.getValue().isValid()) {
        throw new AssertionError("Resulting evaluation order path is invalid: " + evaluationOrderHolder.getValue());
    }
}
Also used : EvaluationOrder(com.evolveum.midpoint.model.api.context.EvaluationOrder) QName(javax.xml.namespace.QName)

Aggregations

EvaluationOrder (com.evolveum.midpoint.model.api.context.EvaluationOrder)2 QName (javax.xml.namespace.QName)2 ItemDeltaItem (com.evolveum.midpoint.repo.common.expression.ItemDeltaItem)1