Skip to content

Commit

Permalink
Minor fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Sep 8, 2017
1 parent 4e4bf11 commit defeb1c
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 38 deletions.
Expand Up @@ -106,6 +106,13 @@ public static void initialize() {
// nothing to do here, we just make sure static initialization will take place
}

public static String debugDumpValue(int indent, Object value, PrismContext prismContext, QName elementName, String defaultLanguage) {
StringBuilder sb = new StringBuilder();
DebugUtil.indentDebugDump(sb, indent);
debugDumpValue(sb, indent, value, prismContext, elementName, defaultLanguage);
return sb.toString();
}

// TODO a better place? cannot be in DebugUtil, because of the missing dependency on prismContext
// Note that expectedIndent applies only to lines after the first one. The caller is responsible for preparing
// indentation for the first line.
Expand Down
Expand Up @@ -18,6 +18,7 @@

import com.evolveum.midpoint.prism.PrismContainer;
import com.evolveum.midpoint.prism.PrismContainerValue;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismValue;
import com.evolveum.midpoint.prism.util.CloneUtil;
import com.evolveum.midpoint.util.HeteroComparator;
Expand Down Expand Up @@ -347,13 +348,14 @@ interface ConstraintVisitor {
* Returns false if the process was stopped by the consumer.
* All references should be resolved.
*/
public static boolean accept(PolicyConstraintsType pc, ConstraintVisitor visitor, boolean deep, boolean alsoRoots, boolean ignoreRefs) {
public static boolean accept(PolicyConstraintsType pc, ConstraintVisitor visitor, boolean deep, boolean alsoRoots, QName rootElementName, boolean ignoreRefs) {
if (pc == null) {
return true;
}
boolean rv;
if (alsoRoots) {
rv = visit(Collections.singletonList(pc), F_AND, visitor);
assert rootElementName != null;
rv = visit(Collections.singletonList(pc), rootElementName, visitor);
} else {
rv = true;
}
Expand All @@ -379,12 +381,12 @@ && visit(pc.getOr(), F_OR, visitor)

if (deep) {
for (TransitionPolicyConstraintType transitionConstraint : pc.getTransition()) {
rv = rv && accept(transitionConstraint.getConstraints(), visitor, true, alsoRoots, ignoreRefs);
rv = rv && accept(transitionConstraint.getConstraints(), visitor, true, alsoRoots, F_AND, ignoreRefs);
}
rv = rv
&& accept(pc.getAnd(), visitor, alsoRoots, ignoreRefs)
&& accept(pc.getOr(), visitor, alsoRoots, ignoreRefs)
&& accept(pc.getNot(), visitor, alsoRoots, ignoreRefs);
&& accept(pc.getAnd(), visitor, alsoRoots, F_AND, ignoreRefs)
&& accept(pc.getOr(), visitor, alsoRoots, F_OR, ignoreRefs)
&& accept(pc.getNot(), visitor, alsoRoots, F_AND, ignoreRefs);
}
return rv;
}
Expand All @@ -398,9 +400,9 @@ private static boolean visit(List<? extends AbstractPolicyConstraintType> constr
return true;
}

private static boolean accept(List<PolicyConstraintsType> constraintsList, ConstraintVisitor matcher, boolean alsoRoots, boolean ignoreRefs) {
private static boolean accept(List<PolicyConstraintsType> constraintsList, ConstraintVisitor matcher, boolean alsoRoots, QName rootElementName, boolean ignoreRefs) {
for (PolicyConstraintsType constraints : constraintsList) {
if (!accept(constraints, matcher, true, alsoRoots, ignoreRefs)) {
if (!accept(constraints, matcher, true, alsoRoots, rootElementName, ignoreRefs)) {
return false;
}
}
Expand All @@ -409,7 +411,7 @@ private static boolean accept(List<PolicyConstraintsType> constraintsList, Const

public static List<JAXBElement<AbstractPolicyConstraintType>> toConstraintsList(PolicyConstraintsType pc, boolean deep, boolean ignoreRefs) {
List<JAXBElement<AbstractPolicyConstraintType>> rv = new ArrayList<>();
accept(pc, (name, c) -> { rv.add(toConstraintJaxbElement(name, c)); return true; }, deep, false, ignoreRefs);
accept(pc, (name, c) -> { rv.add(toConstraintJaxbElement(name, c)); return true; }, deep, false, null, ignoreRefs);
return rv;
}

Expand Down Expand Up @@ -444,13 +446,13 @@ public static boolean isApplicableToObject(PolicyRuleType rule) {

private static boolean hasAssignmentOnlyConstraint(PolicyRuleType rule) {
// 'accept' continues until isNotAssignmentOnly is false; and returns false then --> so we return true in that case (i.e. we have found assignmentOnly-constraint)
return !accept(rule.getPolicyConstraints(), PolicyRuleTypeUtil::isNotAssignmentOnly, true, true, false);
return !accept(rule.getPolicyConstraints(), PolicyRuleTypeUtil::isNotAssignmentOnly, true, true, F_AND, false);
}

// do we have a constraint that indicates a use against object?
private static boolean hasObjectRelatedConstraint(PolicyRuleType rule) {
// 'accept' continues until isNotObjectRelated is false; and returns false then --> so we return true in that case (i.e. we have found object-related constraint)
return !accept(rule.getPolicyConstraints(), PolicyRuleTypeUtil::isNotObjectRelated, true, true, false);
return !accept(rule.getPolicyConstraints(), PolicyRuleTypeUtil::isNotObjectRelated, true, true, F_AND, false);
}

private static final Set<Class<? extends AbstractPolicyConstraintType>> ASSIGNMENTS_ONLY_CONSTRAINTS_CLASSES =
Expand Down Expand Up @@ -486,11 +488,14 @@ public static class LazyMapConstraintsResolver implements ConstraintResolver {
// (in this class)
@NotNull private final List<Supplier<List<Map.Entry<String, JAXBElement<? extends AbstractPolicyConstraintType>>>>> constraintsSuppliers;
@NotNull private final Map<String, JAXBElement<? extends AbstractPolicyConstraintType>> constraintsMap = new HashMap<>();
@NotNull private final PrismContext prismContext;
private int usedSuppliers = 0;

@SafeVarargs
public LazyMapConstraintsResolver(
@NotNull PrismContext prismContext,
@NotNull Supplier<List<Map.Entry<String, JAXBElement<? extends AbstractPolicyConstraintType>>>>... constraintsSuppliers) {
this.prismContext = prismContext;
this.constraintsSuppliers = Arrays.asList(constraintsSuppliers);
}

Expand All @@ -514,6 +519,10 @@ public JAXBElement<? extends AbstractPolicyConstraintType> resolve(@NotNull Stri
if (existingElement != null) {
if (!QNameUtil.match(existingElement.getName(), newElement.getName())
|| !existingElement.getValue().equals(newElement.getValue())) {
LOGGER.error("Conflicting definitions of '{}' found:\n>>> new:\n{}\n>>> existing:\n{}",
newEntry.getKey(),
prismContext.xmlSerializer().serialize(newElement),
prismContext.xmlSerializer().serialize(existingElement));
throw new SchemaException("Conflicting definitions of '" + newEntry.getKey() + "' found.");
}
} else {
Expand All @@ -538,7 +547,7 @@ public static void resolveReferences(PolicyConstraintsType pc, ConstraintResolve
}
}
return true;
}, true, true, true);
}, true, true, F_AND, true);
}

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -583,8 +592,9 @@ private static void computePathToRoot(List<String> path, PrismContainerValue<? e
}
}

public static void resolveReferences(List<PolicyRuleType> rules, Collection<? extends PolicyRuleType> otherRules) throws SchemaException, ObjectNotFoundException {
LazyMapConstraintsResolver resolver = new LazyMapConstraintsResolver(createConstraintsSupplier(rules),
public static void resolveReferences(List<PolicyRuleType> rules, Collection<? extends PolicyRuleType> otherRules,
PrismContext prismContext) throws SchemaException, ObjectNotFoundException {
LazyMapConstraintsResolver resolver = new LazyMapConstraintsResolver(prismContext, createConstraintsSupplier(rules),
createConstraintsSupplier(otherRules));
for (PolicyRuleType rule : rules) {
resolveReferences(rule.getPolicyConstraints(), resolver);
Expand All @@ -602,7 +612,7 @@ private static Supplier<List<Map.Entry<String, JAXBElement<? extends AbstractPol
constraints.add(new AbstractMap.SimpleEntry<>(c.getName(), toConstraintJaxbElement(elementName, c)));
}
return true;
}, true, true,true);
}, true, true, F_AND, true);
}
return constraints;
};
Expand Down
Expand Up @@ -789,7 +789,7 @@
Prune action. The operation will proceed. Any other assignments that are in conflict with
this assignment that triggered the rule will be "pruned": they will be removed. The removal
of the conflicting assignments is automatic and silent. It will not be subject to approvals
or other policy contratints.
or other policy constraints.
This mechanism can be used for example to implement set of roles where only one of the roles
can be assigned at a time.
</xsd:documentation>
Expand Down
Expand Up @@ -276,7 +276,7 @@ public String toShortString() {
sb.append("->");
sb.append("(").append(PolicyRuleTypeUtil.toShortString(getActions())).append(")");
if (!getTriggers().isEmpty()) {
sb.append(" {T:");
sb.append(" # {T:");
sb.append(getTriggers().stream().map(EvaluatedPolicyRuleTrigger::toDiagShortcut)
.collect(Collectors.joining(", ")));
sb.append("}");
Expand Down
Expand Up @@ -147,7 +147,7 @@ public <F extends FocusType> void evaluateAssignmentPolicyRules(LensContext<F> c
private void resolveReferences(Collection<EvaluatedPolicyRule> evaluatedRules, Collection<? extends PolicyRuleType> otherRules)
throws SchemaException, ObjectNotFoundException {
List<PolicyRuleType> rules = evaluatedRules.stream().map(er -> er.getPolicyRule()).collect(Collectors.toList());
PolicyRuleTypeUtil.resolveReferences(rules, otherRules);
PolicyRuleTypeUtil.resolveReferences(rules, otherRules, prismContext);
}

//endregion
Expand Down
Expand Up @@ -17,6 +17,7 @@
package com.evolveum.midpoint.model.impl.lens.projector.policy.evaluators;

import com.evolveum.midpoint.model.api.context.EvaluatedPolicyRuleTrigger;
import com.evolveum.midpoint.model.api.context.ModelState;
import com.evolveum.midpoint.model.impl.lens.LensFocusContext;
import com.evolveum.midpoint.model.impl.lens.projector.policy.ObjectPolicyRuleEvaluationContext;
import com.evolveum.midpoint.model.impl.lens.projector.policy.PolicyRuleEvaluationContext;
Expand Down Expand Up @@ -57,8 +58,17 @@ public <F extends FocusType> EvaluatedPolicyRuleTrigger<?> evaluate(JAXBElement<
ObjectPolicyRuleEvaluationContext<F> ctx = (ObjectPolicyRuleEvaluationContext<F>) rctx;

if (modificationConstraintMatches(constraint.getValue(), ctx)) {
ModelState state = rctx.lensContext.getState();
String verb;
if (state == ModelState.INITIAL || state == ModelState.PRIMARY) {
verb = "is about to be";
} else if (state == ModelState.FINAL) {
verb = "was";
} else {
verb = "is being (or was)"; // TODO derive more precise information from executed deltas, if needed
}
return new EvaluatedPolicyRuleTrigger<>(PolicyConstraintKindType.OBJECT_MODIFICATION,
constraint.getValue(), "Object "+ ObjectTypeUtil.toShortString(ctx.focusContext.getObjectAny())+" was " + ctx.focusContext.getOperation().getPastTense());
constraint.getValue(), "Object "+ ObjectTypeUtil.toShortString(ctx.focusContext.getObjectAny())+" " + verb + " " + ctx.focusContext.getOperation().getPastTense());
} else {
return null;
}
Expand Down
Expand Up @@ -298,29 +298,30 @@ protected void afterFirstClockworkRun(Task rootTask, List<Task> subtasks, List<W
ObjectDelta realDelta0 = taskModelContext.getFocusContext().getPrimaryDelta();
assertTrue("Non-empty primary focus delta: " + realDelta0.debugDump(), realDelta0.isEmpty());
ExpectedTask expectedTask = new ExpectedTask(null, "Approve modification of employee");
// ExpectedWorkItem expectedWorkItem = new ExpectedWorkItem(userEmployeeOwnerOid, null, expectedTask);
ExpectedWorkItem expectedWorkItem = new ExpectedWorkItem(userEmployeeOwnerOid, null, expectedTask);
// assertWfContextAfterClockworkRun(rootTask, subtasks, workItems, result,
// null,
// Collections.singletonList(expectedTask),
// Collections.singletonList(expectedWorkItem));
//
// Collection<SelectorOptions<GetOperationOptions>> options =
// SelectorOptions.createCollection(new ItemPath(F_WORKFLOW_CONTEXT, F_WORK_ITEM), createRetrieve());
// Task opTask = taskManager.createTaskInstance();
// TaskType subtask = modelService.getObject(TaskType.class, subtasks.get(0).getOid(), options, opTask, result).asObjectable();
//
// WfContextType wfc = subtask.getWorkflowContext();
// ItemApprovalProcessStateType processState = WfContextUtil.getItemApprovalProcessInfo(wfc);
// assertEquals("Wrong # of attached policy rules entries", 1, processState.getPolicyRules().getEntry().size());
// SchemaAttachedPolicyRuleType attachedRule = processState.getPolicyRules().getEntry().get(0);
// assertEquals(1, attachedRule.getStageMin().intValue());
// assertEquals(1, attachedRule.getStageMax().intValue());
// assertEquals("Wrong # of attached triggers", 1, attachedRule.getRule().getTrigger().size());
// EvaluatedPolicyRuleTriggerType trigger = attachedRule.getRule().getTrigger().get(0);
// assertEquals("Wrong constraintKind in trigger", PolicyConstraintKindType.OBJECT_MODIFICATION, trigger.getConstraintKind());
//
// WorkItemType workItem = wfc.getWorkItem().get(0);
// assertEquals("Wrong # of additional information", 0, workItem.getAdditionalInformation().size());

Collection<SelectorOptions<GetOperationOptions>> options =
SelectorOptions.createCollection(new ItemPath(F_WORKFLOW_CONTEXT, F_WORK_ITEM), createRetrieve());
Task opTask = taskManager.createTaskInstance();
TaskType subtask = modelService.getObject(TaskType.class, subtasks.get(0).getOid(), options, opTask, result).asObjectable();
display("subtask", subtask);

WfContextType wfc = subtask.getWorkflowContext();
ItemApprovalProcessStateType processState = WfContextUtil.getItemApprovalProcessInfo(wfc);
assertEquals("Wrong # of attached policy rules entries", 1, processState.getPolicyRules().getEntry().size());
SchemaAttachedPolicyRuleType attachedRule = processState.getPolicyRules().getEntry().get(0);
assertEquals(1, attachedRule.getStageMin().intValue());
assertEquals(1, attachedRule.getStageMax().intValue());
assertEquals("Wrong # of attached triggers", 1, attachedRule.getRule().getTrigger().size());
EvaluatedPolicyRuleTriggerType trigger = attachedRule.getRule().getTrigger().get(0);
assertEquals("Wrong constraintKind in trigger", PolicyConstraintKindType.TRANSITION, trigger.getConstraintKind());

WorkItemType workItem = wfc.getWorkItem().get(0);
assertEquals("Wrong # of additional information", 0, workItem.getAdditionalInformation().size());
}

@Override
Expand Down

0 comments on commit defeb1c

Please sign in to comment.