Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/Evolveum/midpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
KaterynaHonchar committed Sep 18, 2020
2 parents 837a51f + b019804 commit fb5731f
Show file tree
Hide file tree
Showing 24 changed files with 504 additions and 189 deletions.
Expand Up @@ -85,6 +85,12 @@ public static String toShortString(PolicyRuleType rule) {
}
}

public static String toShortString(JAXBElement<? extends AbstractPolicyConstraintType> constraint) {
StringBuilder sb = new StringBuilder();
toShortString(sb, constraint, ' ');
return sb.toString();
}

public static String toShortString(PolicyConstraintsType constraints) {
return toShortString(constraints, JOIN_AND);
}
Expand All @@ -96,34 +102,7 @@ public static String toShortString(PolicyConstraintsType constraints, char join)
StringBuilder sb = new StringBuilder();
// we ignore refs to be able to dump even unresolved policy rules
for (JAXBElement<AbstractPolicyConstraintType> constraint : toConstraintsList(constraints, false, true)) {
QName name = constraint.getName();
String abbreviation = CONSTRAINT_NAMES.get(name.getLocalPart());
if (sb.length() > 0) {
sb.append(join);
}
if (QNameUtil.match(name, PolicyConstraintsType.F_AND)) {
sb.append('(');
sb.append(toShortString((PolicyConstraintsType) constraint.getValue(), JOIN_AND));
sb.append(')');
} else if (QNameUtil.match(name, PolicyConstraintsType.F_OR)) {
sb.append('(');
sb.append(toShortString((PolicyConstraintsType) constraint.getValue(), JOIN_OR));
sb.append(')');
} else if (QNameUtil.match(name, PolicyConstraintsType.F_NOT)) {
sb.append('(');
sb.append(toShortString((PolicyConstraintsType) constraint.getValue(), JOIN_AND));
sb.append(')');
} else if (QNameUtil.match(name, PolicyConstraintsType.F_TRANSITION)) {
TransitionPolicyConstraintType trans = (TransitionPolicyConstraintType) constraint.getValue();
sb.append(SYMBOL_TRANSITION);
sb.append(toTransSymbol(trans.isStateBefore()));
sb.append(toTransSymbol(trans.isStateAfter()));
sb.append('(');
sb.append(toShortString(trans.getConstraints(), JOIN_AND));
sb.append(')');
} else {
sb.append(abbreviation != null ? abbreviation : name.getLocalPart());
}
toShortString(sb, constraint, join);
}
for (PolicyConstraintReferenceType ref : constraints.getRef()) {
if (sb.length() > 0) {
Expand All @@ -134,6 +113,37 @@ public static String toShortString(PolicyConstraintsType constraints, char join)
return sb.toString();
}

private static void toShortString(StringBuilder sb, JAXBElement<? extends AbstractPolicyConstraintType> constraint, char join) {
QName name = constraint.getName();
String abbreviation = CONSTRAINT_NAMES.get(name.getLocalPart());
if (sb.length() > 0) {
sb.append(join);
}
if (QNameUtil.match(name, PolicyConstraintsType.F_AND)) {
sb.append('(');
sb.append(toShortString((PolicyConstraintsType) constraint.getValue(), JOIN_AND));
sb.append(')');
} else if (QNameUtil.match(name, PolicyConstraintsType.F_OR)) {
sb.append('(');
sb.append(toShortString((PolicyConstraintsType) constraint.getValue(), JOIN_OR));
sb.append(')');
} else if (QNameUtil.match(name, PolicyConstraintsType.F_NOT)) {
sb.append('(');
sb.append(toShortString((PolicyConstraintsType) constraint.getValue(), JOIN_AND));
sb.append(')');
} else if (QNameUtil.match(name, PolicyConstraintsType.F_TRANSITION)) {
TransitionPolicyConstraintType trans = (TransitionPolicyConstraintType) constraint.getValue();
sb.append(SYMBOL_TRANSITION);
sb.append(toTransSymbol(trans.isStateBefore()));
sb.append(toTransSymbol(trans.isStateAfter()));
sb.append('(');
sb.append(toShortString(trans.getConstraints(), JOIN_AND));
sb.append(')');
} else {
sb.append(abbreviation != null ? abbreviation : name.getLocalPart());
}
}

private static String toTransSymbol(Boolean state) {
if (state != null) {
return state ? "1" : "0";
Expand Down
24 changes: 24 additions & 0 deletions infra/util/src/main/java/com/evolveum/midpoint/util/DebugUtil.java
Expand Up @@ -24,6 +24,8 @@

import javax.xml.namespace.QName;

import com.evolveum.midpoint.util.annotation.Experimental;

import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.FieldCallback;

Expand Down Expand Up @@ -768,4 +770,26 @@ public static <T> void shortDumpCollectionPrettyPrintOptionalBrackets(StringBuil
}
sb.append("]");
}

@Experimental
public static class LazilyDumpable {
private final Supplier<Object> supplier;
private String stringified;

private LazilyDumpable(Supplier<Object> supplier) {
this.supplier = supplier;
}

public static LazilyDumpable of(Supplier<Object> supplier) {
return new LazilyDumpable(supplier);
}

@Override
public String toString() {
if (stringified == null) {
stringified = supplier.toString();
}
return stringified;
}
}
}
Expand Up @@ -38,6 +38,12 @@ default boolean isTriggered() {
@NotNull
Collection<EvaluatedPolicyRuleTrigger<?>> getAllTriggers();

/**
* Returns all triggers of given type, stepping down to situation policy rules and composite triggers.
* An exception are composite "not" triggers: it is usually of no use to collect negated triggers.
*/
<T extends EvaluatedPolicyRuleTrigger<?>> Collection<T> getAllTriggers(Class<T> type);

String getName();

PolicyRuleType getPolicyRule();
Expand Down
Expand Up @@ -23,7 +23,6 @@
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;
import com.evolveum.midpoint.schema.util.PolicyRuleTypeUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.LocalizableMessage;
import com.evolveum.midpoint.util.TreeNode;
import com.evolveum.midpoint.util.exception.CommunicationException;
Expand All @@ -47,6 +46,7 @@
import java.util.stream.Collectors;

import static com.evolveum.midpoint.schema.constants.ExpressionConstants.VAR_RULE_EVALUATION_CONTEXT;
import static com.evolveum.midpoint.util.DebugUtil.*;
import static com.evolveum.midpoint.xml.ns._public.common.common_3.TriggeredPolicyRulesStorageStrategyType.FULL;

/**
Expand Down Expand Up @@ -179,6 +179,31 @@ public Collection<EvaluatedPolicyRuleTrigger<?>> getAllTriggers() {
return rv;
}

@Override
public <T extends EvaluatedPolicyRuleTrigger<?>> Collection<T> getAllTriggers(Class<T> type) {
List<T> selectedTriggers = new ArrayList<>();
collectTriggers(selectedTriggers, getAllTriggers(), type);
return selectedTriggers;
}

private <T extends EvaluatedPolicyRuleTrigger<?>> void collectTriggers(Collection<T> collected,
Collection<EvaluatedPolicyRuleTrigger<?>> all, Class<T> type) {
for (EvaluatedPolicyRuleTrigger<?> trigger : all) {
if (type.isAssignableFrom(trigger.getClass())) {
//noinspection unchecked
collected.add((T) trigger);
}
if (trigger instanceof EvaluatedCompositeTrigger) {
EvaluatedCompositeTrigger compositeTrigger = (EvaluatedCompositeTrigger) trigger;
if (compositeTrigger.getConstraintKind() != PolicyConstraintKindType.NOT) {
collectTriggers(collected, compositeTrigger.getInnerTriggers(), type);
} else {
// there is no use in collecting "negated" triggers
}
}
}
}

void addTriggers(Collection<EvaluatedPolicyRuleTrigger<?>> triggers) {
this.triggers.addAll(triggers);
}
Expand Down Expand Up @@ -281,16 +306,16 @@ private String getSituationFromConstraints(PolicyConstraintsType policyConstrain
@Override
public String debugDump(int indent) {
StringBuilder sb = new StringBuilder();
DebugUtil.debugDumpLabelLn(sb, "EvaluatedPolicyRule " + (getName() != null ? getName() + " " : "") + "(triggers: " + triggers.size() + ")", indent);
DebugUtil.debugDumpWithLabelLn(sb, "name", getName(), indent + 1);
DebugUtil.debugDumpLabelLn(sb, "policyRuleType", indent + 1);
DebugUtil.indentDebugDump(sb, indent + 2);
debugDumpLabelLn(sb, "EvaluatedPolicyRule " + (getName() != null ? getName() + " " : "") + "(triggers: " + triggers.size() + ")", indent);
debugDumpWithLabelLn(sb, "name", getName(), indent + 1);
debugDumpLabelLn(sb, "policyRuleType", indent + 1);
indentDebugDump(sb, indent + 2);
PrismPrettyPrinter.debugDumpValue(sb, indent + 2, policyRuleType, prismContextForDebugDump, PolicyRuleType.COMPLEX_TYPE, PrismContext.LANG_XML);
sb.append('\n');
DebugUtil.debugDumpWithLabelLn(sb, "assignmentPath", assignmentPath, indent + 1);
DebugUtil.debugDumpWithLabelLn(sb, "triggers", triggers, indent + 1);
DebugUtil.debugDumpWithLabelLn(sb, "directOwner", ObjectTypeUtil.toShortString(directOwner), indent + 1);
DebugUtil.debugDumpWithLabel(sb, "rootObjects", assignmentPath != null ? String.valueOf(assignmentPath.getFirstOrderChain()) : null, indent + 1);
debugDumpWithLabelLn(sb, "assignmentPath", assignmentPath, indent + 1);
debugDumpWithLabelLn(sb, "triggers", triggers, indent + 1);
debugDumpWithLabelLn(sb, "directOwner", ObjectTypeUtil.toShortString(directOwner), indent + 1);
debugDumpWithLabel(sb, "rootObjects", assignmentPath != null ? String.valueOf(assignmentPath.getFirstOrderChain()) : null, indent + 1);
return sb.toString();
}

Expand Down Expand Up @@ -465,7 +490,7 @@ public <AH extends AssignmentHolderType> void computeEnabledActions(@Nullable Po
LOGGER.trace("Accepting action {} ({}) because the condition evaluated to true", action.getName(), action.getClass().getSimpleName());
}
}
LOGGER.trace("Adding action {} into the enabled action list.", action);
LOGGER.trace("Adding action {} ({}) into the enabled action list.", action, action.getClass().getSimpleName());
enabledActions.add(action);
}
enabledActionsComputed = true;
Expand Down
Expand Up @@ -26,7 +26,7 @@ public class EvaluatedAssignmentTargetImpl implements EvaluatedAssignmentTarget

@NotNull private final PrismObject<? extends AssignmentHolderType> target;
private final boolean evaluateConstructions;
@NotNull private final AssignmentPathImpl assignmentPath; // TODO reconsider (maybe we should store only some lightweight information here)
@NotNull private final AssignmentPathImpl assignmentPath; // TODO reconsider (maybe we should store only some lightweight information here)
private final AssignmentType assignment;
private Collection<ExclusionPolicyConstraintType> exclusions = null;
private final boolean isValid;
Expand Down Expand Up @@ -130,4 +130,11 @@ public String debugDump(int indent) {
return sb.toString();
}

@Override
public String toString() {
return "EvaluatedAssignmentTargetImpl{" +
"target=" + target +
", isValid=" + isValid +
'}';
}
}
Expand Up @@ -203,7 +203,7 @@ private <AH extends AssignmentHolderType, F extends FocusType> void processAssig
// PROCESSING POLICIES

policyRuleProcessor.evaluateAssignmentPolicyRules(context, evaluatedAssignmentTriple, task, result);
boolean needToReevaluateAssignments = processPruning(context, evaluatedAssignmentTriple);
boolean needToReevaluateAssignments = processPruning(context, evaluatedAssignmentTriple, result);

if (needToReevaluateAssignments) {
LOGGER.debug("Re-evaluating assignments because exclusion pruning rule was triggered");
Expand Down Expand Up @@ -236,9 +236,9 @@ private <AH extends AssignmentHolderType, F extends FocusType> void processAssig
}

private <F extends AssignmentHolderType> boolean processPruning(LensContext<F> context,
DeltaSetTriple<EvaluatedAssignmentImpl<F>> evaluatedAssignmentTriple) throws SchemaException {
DeltaSetTriple<EvaluatedAssignmentImpl<F>> evaluatedAssignmentTriple, OperationResult result) throws SchemaException {
PruningOperation pruningOperation = new PruningOperation<>(context, evaluatedAssignmentTriple, beans);
return pruningOperation.execute();
return pruningOperation.execute(result);
}

private <AH extends AssignmentHolderType> void processProjections(LensContext<AH> context,
Expand Down
Expand Up @@ -17,6 +17,7 @@
import com.evolveum.midpoint.prism.PrismObjectDefinition;
import com.evolveum.midpoint.prism.delta.ContainerDelta;
import com.evolveum.midpoint.prism.delta.DeltaSetTriple;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;
import com.evolveum.midpoint.util.LocalizableMessageBuilder;
import com.evolveum.midpoint.util.SingleLocalizableMessage;
Expand All @@ -29,12 +30,14 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.PrunePolicyActionType;

import java.util.ArrayList;
import java.util.Collection;

public class PruningOperation<F extends AssignmentHolderType> {

private static final Trace LOGGER = TraceManager.getTrace(PruningOperation.class);

private static final String OP_EXECUTE = PruningOperation.class.getName() + ".execute";

private final LensContext<F> context;
private final DeltaSetTriple<EvaluatedAssignmentImpl<F>> evaluatedAssignmentTriple;
private final ModelBeans beans;
Expand Down Expand Up @@ -65,26 +68,39 @@ public PruningOperation(LensContext<F> context, DeltaSetTriple<EvaluatedAssignme
/**
* @return true if the assignments should be re-evaluated
*/
public boolean execute() throws SchemaException {
for (EvaluatedAssignmentImpl<F> existingOrNewAssignment: evaluatedAssignmentTriple.getNonNegativeValues()) {
// Note that we take assignments on "being added" condition i.e. ones which are added since objectOld.
// Taking simple "plus set" is not sufficient because of situations after wave 0 when all assignments
// look like being in zero set.
if (existingOrNewAssignment.getOrigin().isBeingAdded()) {
pruneNewAssignment(existingOrNewAssignment);
public boolean execute(OperationResult parentResult) throws SchemaException {
OperationResult result = parentResult.createMinorSubresult(OP_EXECUTE);
try {
for (EvaluatedAssignmentImpl<F> existingOrNewAssignment : evaluatedAssignmentTriple.getNonNegativeValues()) {
// Note that we take assignments on "being added" condition i.e. ones which are added since objectOld.
// Taking simple "plus set" is not sufficient because of situations after wave 0 when all assignments
// look like being in zero set.
if (existingOrNewAssignment.getOrigin().isBeingAdded()) {
pruneNewAssignment(existingOrNewAssignment);
}
}
}

return prunedViaSecondaryDelta && !enforcementOverrideGenerated;
return prunedViaSecondaryDelta && !enforcementOverrideGenerated;
} catch (Throwable t) {
result.recordFatalError(t);
throw t;
} finally {
result.computeStatusIfUnknown();
}
}

private void pruneNewAssignment(EvaluatedAssignmentImpl<F> newAssignment) {
newAssignment.getAllTargetsPolicyRules().stream()
.filter(rule -> rule.containsEnabledAction(PrunePolicyActionType.class))
.forEach(rule -> new ArrayList<>(rule.getTriggers()).stream() // cloning the list because it is modified inside
.filter(trigger -> trigger instanceof EvaluatedExclusionTrigger)
.map(trigger -> (EvaluatedExclusionTrigger) trigger)
.forEach(exclusionTrigger -> processPruneRuleExclusionTrigger(newAssignment, rule, exclusionTrigger)));
LOGGER.trace("Pruning new assignment: {}", newAssignment);
for (EvaluatedPolicyRuleImpl newAssignmentRule : newAssignment.getAllTargetsPolicyRules()) {
if (newAssignmentRule.containsEnabledAction(PrunePolicyActionType.class)) {
Collection<EvaluatedExclusionTrigger> exclusionTriggers =
newAssignmentRule.getAllTriggers(EvaluatedExclusionTrigger.class);
LOGGER.trace("Exclusion triggers: {}", exclusionTriggers);
for (EvaluatedExclusionTrigger exclusionTrigger : exclusionTriggers) {
processPruneRuleExclusionTrigger(newAssignment, newAssignmentRule, exclusionTrigger);
}
}
}
}

private void processPruneRuleExclusionTrigger(EvaluatedAssignmentImpl<F> newAssignment, EvaluatedPolicyRuleImpl pruneRule,
Expand Down

0 comments on commit fb5731f

Please sign in to comment.