Skip to content

Commit

Permalink
New workflow events, compilable version.
Browse files Browse the repository at this point in the history
  • Loading branch information
mederly committed Feb 3, 2017
1 parent 9253cc8 commit f3f7a5f
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 80 deletions.
Expand Up @@ -34,6 +34,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
Expand All @@ -42,7 +43,7 @@

import com.evolveum.midpoint.schema.GetOperationOptions;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.sun.tools.xjc.reader.xmlschema.bindinfo.BIConversion;
import com.evolveum.midpoint.web.util.ObjectTypeGuiDescriptor;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.apache.commons.lang.math.NumberUtils;
Expand Down Expand Up @@ -268,6 +269,21 @@ public static String nl2br(String text) {
return StringEscapeUtils.escapeHtml4(text).replace("\n", "<br/>");
}

public static String getTypeLocalized(ObjectReferenceType ref) {
ObjectTypes type = ref != null ? ObjectTypes.getObjectTypeFromTypeQName(ref.getType()) : null;
ObjectTypeGuiDescriptor descriptor = ObjectTypeGuiDescriptor.getDescriptor(type);
if (descriptor == null) {
return null;
}
return createStringResourceStatic(null, descriptor.getLocalizationKey()).getString();
}

public static String getReferencedObjectNames(List<ObjectReferenceType> refs, boolean showTypes) {
return refs.stream()
.map(ref -> getName(ref) + (showTypes ? (" (" + getTypeLocalized(ref) + ")") : ""))
.collect(Collectors.joining(", "));
}

public enum Channel {
// TODO: move this to schema component
LIVE_SYNC(SchemaConstants.CHANGE_CHANNEL_LIVE_SYNC_URI),
Expand Down
Expand Up @@ -219,8 +219,8 @@ private void initButtons(Form mainForm) {
}
String principalOid = principal.getOid();
return workItem.getAssigneeRef() != null
&& workItem.getAssigneeRef().getOid().equals(principalOid)
&& (!workItem.getCandidateUsersRef().isEmpty() || !workItem.getCandidateRolesRef().isEmpty());
&& workItem.getAssigneeRef().stream().anyMatch(ref -> ref.getOid().equals(principalOid))
&& (!workItem.getCandidateRef().isEmpty());
});

AjaxSubmitButton claim = new DefaultAjaxSubmitButton(ID_CLAIM, createStringResource("pageWorkItem.button.claim"),
Expand Down Expand Up @@ -292,7 +292,7 @@ private void delegateConfirmedPerformed(AjaxRequestTarget target, UserType deleg
try {
WorkItemDto dto = workItemDtoModel.getObject();
List<ObjectReferenceType> delegates = Collections.singletonList(ObjectTypeUtil.createObjectRef(delegate));
getWorkflowService().delegateWorkItem(dto.getWorkItemId(), delegates, WorkItemDelegationMethodType.ADD_DELEGATES, result);
getWorkflowService().delegateWorkItem(dto.getWorkItemId(), delegates, WorkItemDelegationMethodType.ADD_ASSIGNEES, result);
} catch (Exception ex) {
result.recordFatalError("Couldn't delegate work item.", ex);
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't delegate work item", ex);
Expand Down
Expand Up @@ -17,12 +17,13 @@
package com.evolveum.midpoint.web.page.admin.workflow.dto;

import com.evolveum.midpoint.prism.xml.XmlTypeConverter;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.web.component.util.Selectable;
import com.evolveum.midpoint.xml.ns._public.common.common_3.DecisionType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.WfProcessEventType;
import com.evolveum.midpoint.wf.util.ApprovalUtils;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.jetbrains.annotations.Nullable;

import javax.xml.datatype.XMLGregorianCalendar;
import java.util.Date;

/**
Expand All @@ -42,15 +43,8 @@ public class DecisionDto extends Selectable {
private String comment;
private Date time;

private DecisionDto(DecisionType decision) {
this.user = getNameFromRef(decision.getApproverRef());
outcome = decision.isApproved();
this.comment = decision.getComment();
this.time = XmlTypeConverter.toDate(decision.getDateTime());
}

// TODO deduplicate
private String getNameFromRef(ObjectReferenceType ref) {
// TODO deduplicate
private static String getNameFromRef(ObjectReferenceType ref) {
if (ref == null) {
return null;
} else if (ref.getTargetName() != null) {
Expand Down Expand Up @@ -80,20 +74,54 @@ public String getComment() {
return comment;
}

@Deprecated
public static DecisionDto create(DecisionType d) {
return new DecisionDto(d);
DecisionDto rv = new DecisionDto();
rv.user = getNameFromRef(d.getApproverRef());
rv.stage = null;
rv.outcome = d.isApproved();
rv.comment = d.getComment();
rv.time = XmlTypeConverter.toDate(d.getDateTime());
return rv;
}

@Nullable
public static DecisionDto create(WfProcessEventType e) {
e.getInitiatorRef()
if (decision.getStageDisplayName() != null) {
stage = decision.getStageDisplayName();
} else if (decision.getStageName() != null) {
stage = decision.getStageName();
} else if (decision.getStageNumber() != null) {
stage = String.valueOf(decision.getStageNumber());
}

// we want to show user decisions, automatic decisions and delegations
DecisionDto rv = new DecisionDto();
rv.user = getNameFromRef(e.getInitiatorRef());
rv.stage = MiscUtil.getFirstNonNullString(e.getStageDisplayName(), e.getStageName(), e.getStageNumber());
rv.time = XmlTypeConverter.toDate(e.getTimestamp());

if (e instanceof WorkItemCompletionEventType) {
WorkItemResultType result = ((WorkItemCompletionEventType) e).getResult();
if (result != null) {
rv.outcome = ApprovalUtils.approvalBooleanValue(result);
rv.comment = result.getComment();
// TODO what about additional delta?
}
return rv;
} else if (e instanceof WfStageCompletionEventType) {
WfStageCompletionEventType completion = (WfStageCompletionEventType) e;
AutomatedDecisionReasonType reason = completion.getAutomatedDecisionReason();
if (reason == null) {
return null; // not an automatic stage completion
}
ApprovalLevelOutcomeType outcome = completion.getOutcome();
if (outcome == ApprovalLevelOutcomeType.APPROVE || outcome == ApprovalLevelOutcomeType.REJECT) {
rv.outcome = outcome == ApprovalLevelOutcomeType.APPROVE;
rv.comment = String.valueOf(reason); // TODO
return rv;
} else {
return null; // SKIP (legal = should hide) or null (illegal)
}
} else if (e instanceof WorkItemDelegationEventType) {
WorkItemDelegationEventType delegation = (WorkItemDelegationEventType) e;
// delegation.getDelegatedTo()
return rv;
} else {
return null;
}
}
}
Expand Up @@ -173,38 +173,14 @@ public String getAssigneeOrCandidates() {
}

public String getAssignee() {
return WebComponentUtil.getName(workItem.getAssigneeRef());
return WebComponentUtil.getReferencedObjectNames(workItem.getAssigneeRef(), false);
}

public String getCandidates() {
StringBuilder sb = new StringBuilder();
boolean first = true;
for (ObjectReferenceType roleRef : workItem.getCandidateRolesRef()) {
if (!first) {
sb.append(", ");
} else {
first = false;
}
sb.append(WebComponentUtil.getName(roleRef));
if (RoleType.COMPLEX_TYPE.equals(roleRef.getType())) {
sb.append(" (role)");
} else if (OrgType.COMPLEX_TYPE.equals(roleRef.getType())) {
sb.append(" (org)");
}
}
for (ObjectReferenceType userRef : workItem.getCandidateUsersRef()) {
if (!first) {
sb.append(", ");
} else {
first = false;
}
sb.append(WebComponentUtil.getName(userRef));
sb.append(" (user)");
}
return sb.toString();
}
return WebComponentUtil.getReferencedObjectNames(workItem.getCandidateRef(), true);
}

public String getObjectName() {
public String getObjectName() {
return WebComponentUtil.getName(workItem.getObjectRef());
}

Expand Down
Expand Up @@ -1355,7 +1355,7 @@
<xsd:complexContent>
<xsd:extension base="tns:WorkItemEventType">
<xsd:sequence>
<xsd:element name="outcome" type="tns:WorkItemOutcomeType" minOccurs="0" />
<xsd:element name="result" type="tns:WorkItemResultType" minOccurs="0" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
Expand Down
15 changes: 15 additions & 0 deletions infra/util/src/main/java/com/evolveum/midpoint/util/MiscUtil.java
Expand Up @@ -547,4 +547,19 @@ public static Integer compareNullLast(Object o1, Object o2) {
throw new IllegalArgumentException("Both objects are non-null");
}
}

@SafeVarargs
public static <T> T getFirstNonNull(T... values) {
for (T value : values) {
if (value != null) {
return value;
}
}
return null;
}

public static String getFirstNonNullString(Object... values) {
Object value = getFirstNonNull(values);
return value != null ? value.toString() : null;
}
}
Expand Up @@ -17,6 +17,7 @@
package com.evolveum.midpoint.wf.util;

import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemOutcomeType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemResultType;

/**
* @author mederly
Expand Down Expand Up @@ -67,12 +68,20 @@ public static String makeNice(String decision) {
}

public static String approvalStringValue(WorkItemOutcomeType outcome) {
return approvalStringValue(approvalBooleanValue(outcome));
}

public static Boolean approvalBooleanValue(WorkItemResultType result) {
return result != null ? approvalBooleanValue(result.getOutcome()) : null;
}

private static Boolean approvalBooleanValue(WorkItemOutcomeType outcome) {
if (outcome == null) {
return null;
}
switch (outcome) {
case APPROVE: return DECISION_APPROVED;
case REJECT: return DECISION_REJECTED;
case APPROVE: return true;
case REJECT: return false;
default: throw new IllegalArgumentException("outcome: " + outcome);
}
}
Expand Down
Expand Up @@ -181,14 +181,14 @@ public DecisionType toDecisionType(PrismContext prismContext) throws SchemaExcep
decisionType.setComment(getComment());
decisionType.setDateTime(XmlTypeConverter.createXMLGregorianCalendar(getDate()));
decisionType.setApproverRef(createReference(approverOid, approverName));
decisionType.setOriginalAssigneeRef(createReference(originalAssigneeOid, originalAssigneeName));
decisionType.setStageNumber(stageNumber);
decisionType.setStageName(stageName);
decisionType.setStageDisplayName(stageDisplayName);
if (additionalDelta != null) {
decisionType.setAdditionalDelta(prismContext.parserFor(additionalDelta).parseRealValue(ObjectDeltaType.class));
}
decisionType.setAutomatedDecisionReason(automatedDecisionReason);
// decisionType.setOriginalAssigneeRef(createReference(originalAssigneeOid, originalAssigneeName));
// decisionType.setStageNumber(stageNumber);
// decisionType.setStageName(stageName);
// decisionType.setStageDisplayName(stageDisplayName);
// if (additionalDelta != null) {
// decisionType.setAdditionalDelta(prismContext.parserFor(additionalDelta).parseRealValue(ObjectDeltaType.class));
// }
// decisionType.setAutomatedDecisionReason(automatedDecisionReason);
return decisionType;
}

Expand Down
Expand Up @@ -74,9 +74,9 @@ public void prepareStartInstruction(WfTaskCreationInstruction instruction) {
decision.setResultAsString((String) variables.get(CommonProcessVariableNames.FORM_FIELD_DECISION));
decision.setApproved(ApprovalUtils.approvalBooleanValue(decision.getResultAsString()));
decision.setComment((String) variables.get(CommonProcessVariableNames.FORM_FIELD_COMMENT));
decision.setStageNumber(ActivitiUtil.getVariable(variables, CommonProcessVariableNames.VARIABLE_STAGE_NUMBER, Integer.class));
decision.setStageName(ActivitiUtil.getVariable(variables, CommonProcessVariableNames.VARIABLE_STAGE_NAME, String.class));
decision.setStageDisplayName(ActivitiUtil.getVariable(variables, CommonProcessVariableNames.VARIABLE_STAGE_DISPLAY_NAME, String.class));
// decision.setStageNumber(ActivitiUtil.getVariable(variables, CommonProcessVariableNames.VARIABLE_STAGE_NUMBER, Integer.class));
// decision.setStageName(ActivitiUtil.getVariable(variables, CommonProcessVariableNames.VARIABLE_STAGE_NAME, String.class));
// decision.setStageDisplayName(ActivitiUtil.getVariable(variables, CommonProcessVariableNames.VARIABLE_STAGE_DISPLAY_NAME, String.class));

// TODO - what with other fields (approver, dateTime)?

Expand Down
Expand Up @@ -87,19 +87,19 @@ public static void recordDecisionInTask(Decision decision, String taskOid) {
S_ItemEntry deltaBuilder = DeltaBuilder.deltaFor(TaskType.class, getPrismContext())
.item(decisionsPath, decisionsDefinition).add(decisionType);

if (decisionType.getAdditionalDelta() != null) {
PrismObject<TaskType> task = cacheRepositoryService.getObject(TaskType.class, taskOid, null, result);
WfPrimaryChangeProcessorStateType state = WfContextUtil
.getPrimaryChangeProcessorState(task.asObjectable().getWorkflowContext());
ObjectTreeDeltasType updatedDelta = ObjectTreeDeltas.mergeDeltas(state.getDeltasToProcess(),
decisionType.getAdditionalDelta(), prismContext);
ItemPath deltasToProcessPath = new ItemPath(F_WORKFLOW_CONTEXT, F_PROCESSOR_SPECIFIC_STATE, WfPrimaryChangeProcessorStateType.F_DELTAS_TO_PROCESS); // assuming it already exists!
ItemDefinition<?> deltasToProcessDefinition = getPrismContext().getSchemaRegistry()
.findContainerDefinitionByCompileTimeClass(WfPrimaryChangeProcessorStateType.class)
.findItemDefinition(WfPrimaryChangeProcessorStateType.F_DELTAS_TO_PROCESS);
deltaBuilder = deltaBuilder.item(deltasToProcessPath, deltasToProcessDefinition)
.replace(updatedDelta);
}
// if (decisionType.getAdditionalDelta() != null) {
// PrismObject<TaskType> task = cacheRepositoryService.getObject(TaskType.class, taskOid, null, result);
// WfPrimaryChangeProcessorStateType state = WfContextUtil
// .getPrimaryChangeProcessorState(task.asObjectable().getWorkflowContext());
// ObjectTreeDeltasType updatedDelta = ObjectTreeDeltas.mergeDeltas(state.getDeltasToProcess(),
// decisionType.getAdditionalDelta(), prismContext);
// ItemPath deltasToProcessPath = new ItemPath(F_WORKFLOW_CONTEXT, F_PROCESSOR_SPECIFIC_STATE, WfPrimaryChangeProcessorStateType.F_DELTAS_TO_PROCESS); // assuming it already exists!
// ItemDefinition<?> deltasToProcessDefinition = getPrismContext().getSchemaRegistry()
// .findContainerDefinitionByCompileTimeClass(WfPrimaryChangeProcessorStateType.class)
// .findItemDefinition(WfPrimaryChangeProcessorStateType.F_DELTAS_TO_PROCESS);
// deltaBuilder = deltaBuilder.item(deltasToProcessPath, deltasToProcessDefinition)
// .replace(updatedDelta);
// }

cacheRepositoryService.modifyObject(TaskType.class, taskOid, deltaBuilder.asItemDeltas(), result);
} catch (ObjectNotFoundException | SchemaException | ObjectAlreadyExistsException e) {
Expand Down

0 comments on commit f3f7a5f

Please sign in to comment.