Skip to content

Commit

Permalink
Fixed MID-3576: Fix approver relation handling within approver schema
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Dec 7, 2016
1 parent 1303e38 commit adca426
Show file tree
Hide file tree
Showing 19 changed files with 167 additions and 109 deletions.
Expand Up @@ -50,7 +50,8 @@ public class ApprovalLevelImpl implements ApprovalLevel, Serializable {

private transient PrismContext prismContext;

public ApprovalLevelImpl(ApprovalLevelType levelType, PrismContext prismContext) {
public ApprovalLevelImpl(ApprovalLevelType levelType, PrismContext prismContext,
RelationResolver relationResolver) {

Validate.notNull(prismContext, "prismContext must not be null");

Expand All @@ -60,12 +61,9 @@ public ApprovalLevelImpl(ApprovalLevelType levelType, PrismContext prismContext)

setPrismContext(prismContext);

for (ObjectReferenceType approverRef : levelType.getApproverRef()) {
addApproverRef(approverRef);
}
for (ExpressionType approverExpression : levelType.getApproverExpression()) {
addApproverExpression(approverExpression);
}
levelType.getApproverRef().forEach(this::addApproverRef);
relationResolver.getApprovers(levelType.getApproverRelation()).forEach(this::addApproverRef);
levelType.getApproverExpression().forEach(this::addApproverExpression);
this.evaluationStrategy = levelType.getEvaluationStrategy();
setAutomaticallyApproved(levelType.getAutomaticallyApproved());
}
Expand All @@ -80,14 +78,10 @@ public ApprovalLevelImpl(List<ObjectReferenceType> approverRefList, List<Express
order = 0;

if (approverRefList != null) {
for (ObjectReferenceType approverRef : approverRefList) {
addApproverRef(approverRef);
}
approverRefList.forEach(this::addApproverRef);
}
if (approverExpressionList != null) {
for (ExpressionType expressionType : approverExpressionList) {
addApproverExpression(expressionType);
}
approverExpressionList.forEach(this::addApproverExpression);
}
setEvaluationStrategy(LevelEvaluationStrategyType.ALL_MUST_AGREE);
setAutomaticallyApproved(automaticallyApproved);
Expand Down
Expand Up @@ -51,52 +51,63 @@ private ApprovalRequestImpl(SerializationSafeContainer wrappedValue, PrismContex
setItemToApprove(wrappedValue);
}

public ApprovalRequestImpl(SerializationSafeContainer itemToApproveWrapped, PcpAspectConfigurationType config, PrismContext prismContext) {
this(itemToApproveWrapped, prismContext);
setSchemaFromConfig(config, prismContext);
}
// public ApprovalRequestImpl(SerializationSafeContainer itemToApproveWrapped, PcpAspectConfigurationType config, PrismContext prismContext) {
// this(itemToApproveWrapped, prismContext);
// setSchemaFromConfig(config, prismContext);
// }

public ApprovalRequestImpl(I itemToApprove, PcpAspectConfigurationType config, PrismContext prismContext) {
public ApprovalRequestImpl(I itemToApprove, PcpAspectConfigurationType config, PrismContext prismContext,
RelationResolver relationResolver) {
this(itemToApprove, prismContext);
setSchemaFromConfig(config, prismContext);
setSchemaFromConfig(config, prismContext, relationResolver);
}

protected void setSchemaFromConfig(PcpAspectConfigurationType config, PrismContext prismContext) {
protected void setSchemaFromConfig(PcpAspectConfigurationType config, PrismContext prismContext,
RelationResolver relationResolver) {
if (config != null) {
setApprovalSchema(new ApprovalSchemaImpl(config.getApprovalSchema(), config.getApproverRef(),
config.getApproverExpression(), config.getAutomaticallyApproved(), prismContext));
config.getApproverExpression(), config.getAutomaticallyApproved(), prismContext, relationResolver));
}
}

public ApprovalRequestImpl(I itemToApprove, ApprovalSchemaType approvalSchema, PrismContext prismContext) {
public ApprovalRequestImpl(I itemToApprove, ApprovalSchemaType approvalSchema, PrismContext prismContext,
RelationResolver relationResolver) {
this(itemToApprove, prismContext);
setApprovalSchema(new ApprovalSchemaImpl(approvalSchema, prismContext));
setApprovalSchema(new ApprovalSchemaImpl(approvalSchema, prismContext, relationResolver));
}


public ApprovalRequestImpl(SerializationSafeContainer itemToApproveWrapped, PcpAspectConfigurationType config, ApprovalSchemaType approvalSchema, List<ObjectReferenceType> approverRef, List<ExpressionType> approverExpression, ExpressionType automaticallyApproved, PrismContext prismContext) {
public ApprovalRequestImpl(SerializationSafeContainer itemToApproveWrapped, PcpAspectConfigurationType config,
ApprovalSchemaType approvalSchema, List<ObjectReferenceType> approverRef,
List<ExpressionType> approverExpression, ExpressionType automaticallyApproved,
PrismContext prismContext, RelationResolver relationResolver) {
this(itemToApproveWrapped, prismContext);
setSchemaFromConfigAndParameters(config, approvalSchema, approverRef, approverExpression, automaticallyApproved, prismContext);
setSchemaFromConfigAndParameters(config, approvalSchema, approverRef, approverExpression, automaticallyApproved,
prismContext, relationResolver);
}

public ApprovalRequestImpl(I itemToApprove, PcpAspectConfigurationType config, ApprovalSchemaType approvalSchema, List<ObjectReferenceType> approverRef, List<ExpressionType> approverExpression, ExpressionType automaticallyApproved, PrismContext prismContext) {
public ApprovalRequestImpl(I itemToApprove, PcpAspectConfigurationType config, ApprovalSchemaType approvalSchema,
List<ObjectReferenceType> approverRef, List<ExpressionType> approverExpression,
ExpressionType automaticallyApproved, PrismContext prismContext,
RelationResolver relationResolver) {
this(itemToApprove, prismContext);
setSchemaFromConfigAndParameters(config, approvalSchema, approverRef, approverExpression, automaticallyApproved, prismContext);
setSchemaFromConfigAndParameters(config, approvalSchema, approverRef, approverExpression, automaticallyApproved,
prismContext, relationResolver);
}

private void setSchemaFromConfigAndParameters(PcpAspectConfigurationType config, ApprovalSchemaType approvalSchema,
List<ObjectReferenceType> approverRef, List<ExpressionType> approverExpression, ExpressionType automaticallyApproved,
PrismContext prismContext) {
PrismContext prismContext, RelationResolver relationResolver) {
if (config != null &&
(!config.getApproverRef().isEmpty() ||
config.getApprovalSchema() != null ||
!config.getApproverExpression().isEmpty() ||
config.getAutomaticallyApproved() != null)) {
setApprovalSchema(new ApprovalSchemaImpl(config.getApprovalSchema(), config.getApproverRef(),
config.getApproverExpression(), config.getAutomaticallyApproved(), prismContext));
config.getApproverExpression(), config.getAutomaticallyApproved(), prismContext, relationResolver));
} else {
setApprovalSchema(new ApprovalSchemaImpl(approvalSchema, approverRef,
approverExpression, automaticallyApproved, prismContext));
approverExpression, automaticallyApproved, prismContext, relationResolver));
}
}

Expand Down
Expand Up @@ -39,16 +39,18 @@ public class ApprovalSchemaImpl implements ApprovalSchema, Serializable {

private transient PrismContext prismContext;

@SuppressWarnings("unused") // TODO check if not called from dynamic code
public ApprovalSchemaImpl(ApprovalSchemaType approvalSchemaType, PrismContext prismContext) {
public ApprovalSchemaImpl(ApprovalSchemaType approvalSchemaType, PrismContext prismContext,
RelationResolver relationResolver) {
setPrismContext(prismContext);
initFromApprovalSchemaType(approvalSchemaType);
initFromApprovalSchemaType(approvalSchemaType, relationResolver);
}

public ApprovalSchemaImpl(ApprovalSchemaType approvalSchema, List<ObjectReferenceType> approverRefList, List<ExpressionType> approverExpressionList, ExpressionType automaticallyApproved, PrismContext prismContext) {
public ApprovalSchemaImpl(ApprovalSchemaType approvalSchema, List<ObjectReferenceType> approverRefList,
List<ExpressionType> approverExpressionList, ExpressionType automaticallyApproved,
PrismContext prismContext, RelationResolver relationResolver) {
setPrismContext(prismContext);
if (approvalSchema != null) {
initFromApprovalSchemaType(approvalSchema);
initFromApprovalSchemaType(approvalSchema, relationResolver);
} else if ((approverRefList != null && !approverRefList.isEmpty()) || (approverExpressionList != null && !approverExpressionList.isEmpty())) {
ApprovalLevelImpl level = new ApprovalLevelImpl(approverRefList, approverExpressionList, automaticallyApproved, prismContext);
addLevel(level);
Expand All @@ -57,11 +59,12 @@ public ApprovalSchemaImpl(ApprovalSchemaType approvalSchema, List<ObjectReferenc
}
}

private void initFromApprovalSchemaType(ApprovalSchemaType approvalSchemaType) {
private void initFromApprovalSchemaType(ApprovalSchemaType approvalSchemaType,
RelationResolver relationResolver) {
this.name = approvalSchemaType.getName();
this.description = approvalSchemaType.getDescription();
for (ApprovalLevelType levelType : approvalSchemaType.getLevel()) {
addLevel(levelType);
addLevel(levelType, relationResolver);
}
}

Expand Down Expand Up @@ -122,8 +125,8 @@ public void addLevel(ApprovalLevelImpl level) {
levels.add(level);
}

public void addLevel(ApprovalLevelType levelType) {
addLevel(new ApprovalLevelImpl(levelType, prismContext));
public void addLevel(ApprovalLevelType levelType, RelationResolver relationResolver) {
addLevel(new ApprovalLevelImpl(levelType, prismContext, relationResolver));
}

@Override
Expand Down
@@ -0,0 +1,15 @@
package com.evolveum.midpoint.wf.impl.processes.itemApproval;

import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;

import javax.xml.namespace.QName;
import java.util.List;

/**
* @author pmederly
*/
@FunctionalInterface
public interface RelationResolver {
List<ObjectReferenceType> getApprovers(List<QName> relations);
}
Expand Up @@ -17,11 +17,22 @@
package com.evolveum.midpoint.wf.impl.processors.primary.aspect;

import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismReferenceValue;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.query.builder.QueryBuilder;
import com.evolveum.midpoint.prism.query.builder.S_AtomicFilterExit;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SystemException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.wf.impl.processes.itemApproval.RelationResolver;
import com.evolveum.midpoint.wf.impl.processors.BaseModelInvocationProcessingHelper;
import com.evolveum.midpoint.wf.impl.tasks.WfTaskUtil;
import com.evolveum.midpoint.wf.impl.messages.ProcessEvent;
Expand All @@ -32,14 +43,18 @@
import com.evolveum.midpoint.wf.impl.processors.primary.PcpWfTask;
import com.evolveum.midpoint.wf.impl.processors.primary.PrimaryChangeProcessor;
import com.evolveum.midpoint.wf.impl.util.MiscDataUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.PrimaryChangeProcessorConfigurationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import javax.annotation.PostConstruct;
import javax.xml.namespace.QName;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
* @author mederly
Expand Down Expand Up @@ -123,4 +138,40 @@ public boolean isEnabled(PrimaryChangeProcessorConfigurationType processorConfig
return primaryChangeAspectHelper.isEnabled(processorConfigurationType, this);
}

public RelationResolver createRelationResolver(ObjectType object, OperationResult result) {
return createRelationResolver(object != null ? object.asPrismObject() : null, result);
}

public RelationResolver createRelationResolver(PrismObject<?> object, OperationResult result) {
return relations -> {
if (object == null || object.getOid() == null || relations.isEmpty()) {
return Collections.emptyList();
}
S_AtomicFilterExit q = QueryBuilder.queryFor(FocusType.class, prismContext).none();
for (QName approverRelation : relations) {
PrismReferenceValue approverReference = new PrismReferenceValue(object.getOid());
approverReference.setRelation(QNameUtil.qualifyIfNeeded(approverRelation, SchemaConstants.NS_ORG));
q = q.or().item(FocusType.F_ROLE_MEMBERSHIP_REF).ref(approverReference);
}
ObjectQuery query = q.build();
LOGGER.trace("Looking for approvers for {} using query:\n{}", object, DebugUtil.debugDumpLazily(query));
List<PrismObject<FocusType>> objects = null;
try {
objects = repositoryService.searchObjects(FocusType.class, query, null, result);
} catch (SchemaException e) {
throw new SystemException("Couldn't retrieve approvers for " + object + ": " + e.getMessage(), e);
}
Set<PrismObject<FocusType>> distinctObjects = new HashSet<>(objects);
LOGGER.trace("Found {} approver(s): {}", distinctObjects.size(), DebugUtil.toStringLazily(distinctObjects));
return distinctObjects.stream()
.map(ObjectTypeUtil::createObjectRef)
.collect(Collectors.toList());
};
}

protected List<ObjectReferenceType> findApproversByReference(PrismObject<?> target, ApprovalPolicyActionType action,
OperationResult result) throws SchemaException {
return createRelationResolver(target, result)
.getApprovers(action.getApproverRelation());
}
}
Expand Up @@ -22,24 +22,22 @@
import com.evolveum.midpoint.model.api.context.ModelContext;
import com.evolveum.midpoint.model.impl.lens.LensContext;
import com.evolveum.midpoint.model.impl.lens.LensFocusContext;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.Objectable;
import com.evolveum.midpoint.prism.PrismContainerValue;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.delta.ChangeType;
import com.evolveum.midpoint.prism.delta.DeltaSetTriple;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.query.builder.QueryBuilder;
import com.evolveum.midpoint.prism.query.builder.S_AtomicFilterExit;
import com.evolveum.midpoint.prism.util.CloneUtil;
import com.evolveum.midpoint.schema.ObjectTreeDeltas;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;
import com.evolveum.midpoint.schema.util.OidUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
Expand All @@ -54,9 +52,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.xml.namespace.QName;
import java.util.*;
import java.util.stream.Collectors;

import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.createObjectRef;
import static com.evolveum.midpoint.wf.impl.util.MiscDataUtil.getFocusObjectName;
Expand Down Expand Up @@ -247,7 +243,8 @@ private void extractObjectBasedInstructions(@NotNull LensContext<?> modelContext
} else {
itemsProcessed = items;
}
ApprovalRequest<?> request = new ApprovalRequestImpl<>("dummy", entry.getValue(), prismContext);
ApprovalRequest<?> request = new ApprovalRequestImpl<>("dummy", entry.getValue(), prismContext,
createRelationResolver(object, result));
if (!request.getApprovalSchema().isEmpty()) {
instructions.add(
prepareObjectRelatedTaskInstruction(request, focusDelta, items, modelContext, requester, result));
Expand Down Expand Up @@ -297,33 +294,13 @@ private ApprovalRequest<AssignmentType> createAssignmentApprovalRequest(Evaluate
approvalSchema = addApprovalActionIntoApprovalSchema(approvalSchema, action, findApproversByReference(target, action, result));
}
if (approvalSchema != null) {
return new ApprovalRequestImpl<>(newAssignment.getAssignmentType(), approvalSchema, prismContext);
return new ApprovalRequestImpl<>(newAssignment.getAssignmentType(), approvalSchema, prismContext,
createRelationResolver(target, result));
} else {
return null;
}
}

private List<ObjectReferenceType> findApproversByReference(PrismObject<?> target, ApprovalPolicyActionType action,
OperationResult result) throws SchemaException {
if (target == null || target.getOid() == null || action.getApproverRelation().isEmpty()) {
return Collections.emptyList();
}
S_AtomicFilterExit q = QueryBuilder.queryFor(FocusType.class, prismContext).none();
for (QName approverRelation : action.getApproverRelation()) {
PrismReferenceValue approverReference = new PrismReferenceValue(target.getOid());
approverReference.setRelation(QNameUtil.qualifyIfNeeded(approverRelation, SchemaConstants.NS_ORG));
q = q.or().item(FocusType.F_ROLE_MEMBERSHIP_REF).ref(approverReference);
}
ObjectQuery query = q.build();
LOGGER.trace("Looking for approvers for {} using query:\n{}", target, DebugUtil.debugDumpLazily(query));
List<PrismObject<FocusType>> objects = repositoryService.searchObjects(FocusType.class, query, null, result);
Set<PrismObject<FocusType>> distinctObjects = new HashSet<>(objects);
LOGGER.trace("Found {} approver(s): {}", distinctObjects.size(), DebugUtil.toStringLazily(distinctObjects));
return distinctObjects.stream()
.map(ObjectTypeUtil::createObjectRef)
.collect(Collectors.toList());
}

private ApprovalSchemaType addApprovalActionIntoApprovalSchema(ApprovalSchemaType approvalSchema, ApprovalPolicyActionType action,
@Nullable List<ObjectReferenceType> additionalReviewers) {
if (action.getApprovalSchema() != null) {
Expand Down

0 comments on commit adca426

Please sign in to comment.