Skip to content

Commit

Permalink
Update default case notifier to correlation cases
Browse files Browse the repository at this point in the history
The notifier was treating all cases as approval ones. This is now
fixed, and the approval terminology will not be shown in correlation
and manual provisioning cases.

Work in progress: the content of notifications is still preliminary.
Moreover, the notifier will be - most probably - replaced by a default
message template.

Related changes:
- Renamed WorkflowEvent to CaseManagementEvent.
- Renamed WorkflowProcessEvent to CaseEvent.
- Introduced wf.caseOid auditing constant (replacing
wf.processInstanceId).

Unrelated changes:
- Renamed NotificationFunctions#getObjectType to getObject.
  • Loading branch information
mederly committed Feb 21, 2022
1 parent 29f703c commit 5acbd1d
Show file tree
Hide file tree
Showing 27 changed files with 386 additions and 180 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ public class PageAuditLogDetails extends PageBase {
AuditingConstants.AUDIT_REQUESTER_COMMENT,
AuditingConstants.AUDIT_COMMENT,
AuditingConstants.AUDIT_WORK_ITEM_ID,
AuditingConstants.AUDIT_CASE_OID,
AuditingConstants.AUDIT_PROCESS_INSTANCE_ID);

public PageAuditLogDetails(PageParameters params) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ public boolean isWarning() {
* @return true if the result is acceptable for further processing.
*/
public boolean isAcceptable() {
return (status != OperationResultStatus.FATAL_ERROR);
return status != OperationResultStatus.FATAL_ERROR;
}

public boolean isUnknown() {
Expand All @@ -664,8 +664,7 @@ public boolean isInProgress() {
}

public boolean isError() {
return status == OperationResultStatus.FATAL_ERROR ||
status == OperationResultStatus.PARTIAL_ERROR;
return status != null && status.isError();
}

public boolean isFatalError() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,18 @@ public enum OperationResultStatus {
public OperationResultStatusType createStatusType() {
return createStatusType(this);
}

/**
* Meaning "the operation completed in more-or-less successful way".
*/
public boolean isConsideredSuccess() {
return this == SUCCESS || this == WARNING || this == HANDLED_ERROR;
}

/**
* Meaning "the operation completely or partially failed".
*/
public boolean isError() {
return this == FATAL_ERROR || this == PARTIAL_ERROR;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ public boolean isClosing() {
return QNameUtil.match(SchemaConstants.CASE_STATE_CLOSING_QNAME, stateQName);
}

public boolean isClosed() {
return QNameUtil.match(SchemaConstants.CASE_STATE_CLOSED_QNAME, stateQName);
}

@Override
public String toString() {
return stateQName.getLocalPart();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

import com.evolveum.midpoint.xml.ns._public.common.common_3.*;

import org.apache.commons.collections.CollectionUtils;
import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.prism.PrismContainer;
Expand All @@ -23,6 +22,8 @@
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;

import org.jetbrains.annotations.Nullable;

/**
*
*/
Expand Down Expand Up @@ -69,14 +70,15 @@ public static String getRequesterComment(CaseType aCase) {
return businessContext != null ? businessContext.getComment() : null;
}

public static boolean isManualProvisioningCase(CaseType aCase){
if (aCase == null || CollectionUtils.isEmpty(aCase.getArchetypeRef())){
return false;
}
public static boolean isCorrelationCase(@Nullable CaseType aCase) {
return aCase != null && ObjectTypeUtil.hasArchetype(aCase, SystemObjectsType.ARCHETYPE_CORRELATION_CASE.value());
}

public static boolean isManualProvisioningCase(@Nullable CaseType aCase) {
return aCase != null && ObjectTypeUtil.hasArchetype(aCase, SystemObjectsType.ARCHETYPE_MANUAL_CASE.value());
}

public static boolean isApprovalCase(CaseType aCase) {
public static boolean isApprovalCase(@Nullable CaseType aCase) {
return aCase != null && ObjectTypeUtil.hasArchetype(aCase, SystemObjectsType.ARCHETYPE_APPROVAL_CASE.value());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2010-2022 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.schema.util.cases;

import com.evolveum.midpoint.schema.constants.SchemaConstants;

import org.jetbrains.annotations.NotNull;

import static com.evolveum.midpoint.util.QNameUtil.uriToQName;

public class CorrelationCaseUtil {

public static boolean isNewOwner(@NotNull String outcomeUri) {
return SchemaConstants.CORRELATION_NONE.equals(
getLocalPart(outcomeUri));
}

private static String getLocalPart(@NotNull String outcomeUri) {
return uriToQName(outcomeUri, true)
.getLocalPart();
}

public static String getExistingOwnerId(@NotNull String outcomeUri) {
String localPart = getLocalPart(outcomeUri);
if (localPart.startsWith(SchemaConstants.CORRELATION_OPTION_PREFIX)) {
return localPart.substring(SchemaConstants.CORRELATION_OPTION_PREFIX.length());
} else {
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (C) 2010-2022 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.schema.util.cases;

import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResultStatus;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultStatusType;

public class ManualCaseUtils {

// TODO
public static OperationResultStatus translateOutcomeToStatus(String outcome) {
if (outcome == null) {
return null;
}
for (OperationResultStatusType statusType : OperationResultStatusType.values()) {
if (outcome.equals(statusType.value())) {
return OperationResultStatus.parseStatusType(statusType);
}
}
// This is a hack... FIXME
if (QNameUtil.matchUri(outcome, SchemaConstants.MODEL_APPROVAL_OUTCOME_APPROVE)) {
return OperationResultStatus.SUCCESS;
} else if (QNameUtil.matchUri(outcome, SchemaConstants.MODEL_APPROVAL_OUTCOME_REJECT)) {
return OperationResultStatus.FATAL_ERROR;
} else if (QNameUtil.matchUri(outcome, SchemaConstants.MODEL_APPROVAL_OUTCOME_SKIP)) {
// Better make this "unknown" than non-applicable. Non-applicable can be misinterpreted.
return OperationResultStatus.UNKNOWN;
}
return OperationResultStatus.UNKNOWN;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public class AuditingConstants {
public static final String AUDIT_ESCALATION_LEVEL_NAME = "wf.escalationLevelName";
public static final String AUDIT_ESCALATION_LEVEL_DISPLAY_NAME = "wf.escalationLevelDisplayName";
public static final String AUDIT_WORK_ITEM_ID = "wf.workItemId";
public static final String AUDIT_PROCESS_INSTANCE_ID = "wf.processInstanceId"; // FIXME (case oid?)
public static final String AUDIT_CASE_OID = "wf.caseOid";
public static final String AUDIT_PROCESS_INSTANCE_ID = "wf.processInstanceId"; // Used before 4.5
public static final String AUDIT_REQUESTER_COMMENT = "wf.requesterComment";
public static final String AUDIT_CAUSE_TYPE = "wf.causeType";
public static final String AUDIT_CAUSE_NAME = "wf.causeName";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ private AuditEventRecord createCaseLevelRecord(@NotNull AuditEventStage stage, @
record.addPropertyValueIgnoreNull(AuditingConstants.AUDIT_STAGE_DISPLAY_NAME, ApprovalContextUtil.getStageDisplayName(aCase));
}
}
record.addPropertyValue(AuditingConstants.AUDIT_PROCESS_INSTANCE_ID, aCase.getOid());
record.addPropertyValue(AuditingConstants.AUDIT_CASE_OID, aCase.getOid());
record.addPropertyValueIgnoreNull(AuditingConstants.AUDIT_REQUESTER_COMMENT, ApprovalContextUtil.getRequesterComment(aCase));
return record;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ public boolean doesUseStages() {
@Override
public @NotNull StageClosingResult processStageClosing(CaseEngineOperation operation, OperationResult result) {

// There should be only a single work item, so the following is maybe an overkill
Set<String> allOutcomes = operation.getCurrentCase().getWorkItem().stream()
.filter(wi -> wi.getCloseTimestamp() != null)
.map(AbstractWorkItemType::getOutput)
Expand All @@ -87,7 +86,6 @@ public boolean doesUseStages() {
getOutcomeUri(allOutcomes));
}

// see ManualConnectorInstance.translateOutcome(..) method
private @NotNull String getOutcomeUri(Set<String> outcomes) {
if (outcomes.isEmpty()) {
return OperationResultStatusType.SUCCESS.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@

package com.evolveum.midpoint.notifications.api;

import com.evolveum.midpoint.schema.result.OperationResultStatus;
import com.evolveum.midpoint.xml.ns._public.common.common_3.EventStatusType;

/**
* The purpose of this class is unclear. Consider replacing by {@link OperationResultStatus}.
*/
public enum OperationStatus {
SUCCESS, IN_PROGRESS, FAILURE, OTHER;

Expand All @@ -23,4 +27,15 @@ public boolean matchesEventStatusType(EventStatusType eventStatusType) {
}
}

public static OperationStatus fromOperationResultStatus(OperationResultStatus status) {
if (status == null) {
return null;
} else if (status.isConsideredSuccess()) {
return SUCCESS;
} else if (status.isError()) {
return FAILURE; // TODO or only fatal error?
} else {
return OTHER;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@

package com.evolveum.midpoint.notifications.api.events;

public interface WorkflowProcessEvent extends Event {
/**
* Event related to a case (as a whole).
*/
public interface CaseEvent extends CaseManagementEvent {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2020 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.notifications.api.events;

import com.evolveum.midpoint.notifications.api.OperationStatus;
import com.evolveum.midpoint.prism.delta.ChangeType;
import com.evolveum.midpoint.schema.util.cases.CaseTypeUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ApprovalContextType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CaseType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.CorrelationContextType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ManualProvisioningContextType;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static com.evolveum.midpoint.prism.polystring.PolyString.getOrig;

/**
* Event related to case management: either case-level or work-item-level.
*/
public interface CaseManagementEvent extends Event {

@NotNull CaseType getCase();

@Deprecated
default String getProcessInstanceName1() {
return getCaseName();
}

default String getCaseName() {
return getOrig(getCase().getName());
}

OperationStatus getOperationStatus();

ChangeType getChangeType();

boolean isResultKnown();

boolean isApproved();

boolean isRejected();

@Nullable ApprovalContextType getApprovalContext();

default @Nullable ManualProvisioningContextType getManualProvisioningContext() {
return getCase().getManualProvisioningContext();
}

default @Nullable CorrelationContextType getCorrelationContext() {
return getCase().getCorrelationContext();
}

default boolean doesUseStages() {
return getApprovalContext() != null;
}

/** Returns true if this event is related to an approval case. */
default boolean isApproval() {
return CaseTypeUtil.isApprovalCase(getCase());
}

@Deprecated
default boolean isApprovalCase() {
return isApproval();
}

/** Returns true if this event is related to a manual provisioning case. */
default boolean isManualProvisioning() {
return CaseTypeUtil.isManualProvisioningCase(getCase());
}

@Deprecated
default boolean isManualResourceCase() {
return isManualProvisioning();
}

/** Returns true if this event is related to a correlation case. */
default boolean isCorrelation() {
return CaseTypeUtil.isCorrelationCase(getCase());
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,14 @@ private void executeNotifyAny(OperationStatus status, ResourceOperationDescripti
}

@NotNull
private ResourceObjectEventImpl createRequest(OperationStatus status,
private ResourceObjectEventImpl createRequest(
OperationStatus status,
ResourceOperationDescription operationDescription,
Task task,
OperationResult result) {

ResourceObjectEventImpl event = new ResourceObjectEventImpl(lightweightIdentifierGenerator,
operationDescription, status);
ResourceObjectEventImpl event = new ResourceObjectEventImpl(
lightweightIdentifierGenerator, operationDescription, status);

String accountOid = operationDescription.getObjectDelta().getOid();

Expand Down

0 comments on commit 5acbd1d

Please sign in to comment.