Skip to content

Commit

Permalink
Almost fully implemented work item notifications.
Browse files Browse the repository at this point in the history
Properly generating lifecycle/allocation/custom notifications.
Added info about original assignee, actual initiator, escalation level to notifications.
Notifications before automatic completion/delegation/escapation of a work item.
  • Loading branch information
mederly committed Feb 8, 2017
1 parent 521e65a commit df04a24
Show file tree
Hide file tree
Showing 38 changed files with 1,027 additions and 330 deletions.
Expand Up @@ -298,6 +298,11 @@ public abstract class SchemaConstants {
public static final QName MODEL_EXTENSION_CLEANUP_POLICIES = new QName(NS_MODEL_EXTENSION,
"cleanupPolicies");

public static final QName MODEL_EXTENSION_WORK_ITEM_ID = new QName(NS_MODEL_EXTENSION, "workItemId");
public static final QName MODEL_EXTENSION_WORK_ITEM_ACTIONS = new QName(NS_MODEL_EXTENSION, "workItemActions");
public static final QName MODEL_EXTENSION_WORK_ITEM_ACTION = new QName(NS_MODEL_EXTENSION, "workItemAction");
public static final QName MODEL_EXTENSION_TIME_BEFORE_ACTION = new QName(NS_MODEL_EXTENSION, "timeBeforeAction");

public static final String NOOP_SCHEMA_URI = NS_MIDPOINT_PUBLIC + "/task/noop/handler-3";
public static final QName NOOP_DELAY_QNAME = new QName(NOOP_SCHEMA_URI, "delay");
public static final QName NOOP_STEPS_QNAME = new QName(NOOP_SCHEMA_URI, "steps");
Expand Down
Expand Up @@ -63,6 +63,26 @@ private static String getStageInfo(Integer stageNumber, Integer stageCount, Stri
return sb.toString();
}

@Nullable
public static String getEscalationInfo(WorkItemType workItem) {
if (workItem == null) {
return null;
}
return getEscalationInfo(workItem.getEscalationLevelNumber(), workItem.getEscalationLevelName(), workItem.getEscalationLevelDisplayName());
}

private static String getEscalationInfo(Integer levelNumber, String levelName, String levelDisplayName) {
if (levelNumber == null || levelNumber == 0) {
return null;
}
String name = levelDisplayName != null ? levelDisplayName : levelName;
if (name != null) {
return name + " (" + levelNumber + ")";
} else {
return String.valueOf(levelNumber);
}
}

public static boolean hasFinished(WfContextType wfc) {
return wfc.getEndTimestamp() != null;
}
Expand Down
Expand Up @@ -299,25 +299,6 @@
</xsd:sequence>
</xsd:complexType>

<!-- Elements to be stored in trigger extension -->
<!-- TODO is this ok? Is it really necessary for extension elements to reside outside common namespace? -->
<xsd:element name="workItemActions" type="tns:WorkItemActionsType">
<xsd:annotation>
<xsd:appinfo>
<a:minOccurs>0</a:minOccurs>
<a:maxOccurs>1</a:maxOccurs>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="workItemId" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<a:minOccurs>0</a:minOccurs>
<a:maxOccurs>1</a:maxOccurs>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>

<xsd:complexType name="AbstractWorkItemActionType">
<xsd:annotation>
<xsd:documentation>
Expand Down Expand Up @@ -386,8 +367,24 @@
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="tns:AbstractWorkItemActionType">
<!-- TODO some parameters could come here, like which notification to invoke. Maybe at least custom notifier. -->
<!-- Currently standard WorkItemEvent is produced -->
<xsd:sequence>
<xsd:element name="perAssignee" type="xsd:boolean" minOccurs="0" >
<xsd:annotation>
<xsd:documentation>
If true (the default) creates one notification event for each assignee. Otherwise,
creates a single notification event for the whole work item.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="handler" type="c:EventHandlerType" minOccurs="0" >
<xsd:annotation>
<xsd:documentation>
Ad-hoc event handler that will be used to process these event emitted. In addition to it,
a system-wide handler for workItemCustomEvent will be invoked.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
Expand Down Expand Up @@ -1836,7 +1833,7 @@
</xsd:appinfo>
</xsd:annotation>
<xsd:sequence>
<xsd:element ref="tns:workItemId">
<xsd:element name="workItemId" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Internal identifier of a work item, assigned by the underlying workflow engine
Expand Down Expand Up @@ -1964,6 +1961,16 @@
<a:since>3.6</a:since>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="completedByRef" type="tns:ObjectReferenceType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Who has completed this work item (null if unknown, not completed or completed automatically).
</xsd:documentation>
<xsd:appinfo>
<a:since>3.6</a:since>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="additionalInformation" type="tns:InformationType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
Expand Down Expand Up @@ -2096,4 +2103,70 @@
<!-- TODO process instance creation -->
</xsd:restriction>
</xsd:simpleType>

<xsd:simpleType name="WorkItemOperationKindType">
<xsd:annotation>
<xsd:documentation>
Kind of (explicit) operation. Implicit operations like "work item deletion when process instance finishes"
are not covered here.
</xsd:documentation>
<xsd:appinfo>
<a:since>3.6</a:since>
<jaxb:typesafeEnumClass/>
</xsd:appinfo>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="complete">
<xsd:annotation>
<xsd:documentation>
Complete (approve/reject) operation. (Explicit or automated.)
</xsd:documentation>
<xsd:appinfo>
<jaxb:typesafeEnumMember name="COMPLETE"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value="delegate">
<xsd:annotation>
<xsd:documentation>
Delegate operation. (Explicit or automated.)
</xsd:documentation>
<xsd:appinfo>
<jaxb:typesafeEnumMember name="DELEGATE"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value="escalate">
<xsd:annotation>
<xsd:documentation>
Escalate operation. (Explicit or automated.)
</xsd:documentation>
<xsd:appinfo>
<jaxb:typesafeEnumMember name="ESCALATE"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value="claim">
<xsd:annotation>
<xsd:documentation>
Claim operation.
</xsd:documentation>
<xsd:appinfo>
<jaxb:typesafeEnumMember name="CLAIM"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value="release">
<xsd:annotation>
<xsd:documentation>
Claim operation.
</xsd:documentation>
<xsd:appinfo>
<jaxb:typesafeEnumMember name="RELEASE"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>

</xsd:schema>
Expand Up @@ -27,7 +27,7 @@

<xsd:annotation>
<xsd:documentation>
Model object extension schema. Used mostly in task extensions.
Model object extension schema. Used mostly in task extensions. (Some of them in trigger extensions.)
</xsd:documentation>
</xsd:annotation>

Expand Down Expand Up @@ -166,7 +166,6 @@
</xsd:annotation>
</xsd:element>


<xsd:element name="objectclass" type="xsd:QName">
<xsd:annotation>
<xsd:documentation>
Expand Down Expand Up @@ -312,6 +311,47 @@
</xsd:annotation>
</xsd:element>

<!-- Elements to be stored in task trigger extension (used for workflows) -->
<xsd:element name="workItemActions" type="c:WorkItemActionsType">
<xsd:annotation>
<xsd:appinfo>
<a:minOccurs>0</a:minOccurs>
<a:maxOccurs>1</a:maxOccurs>
<a:since>3.6</a:since>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>

<xsd:element name="workItemAction" type="c:AbstractWorkItemActionType">
<xsd:annotation>
<xsd:appinfo>
<a:minOccurs>0</a:minOccurs>
<a:maxOccurs>1</a:maxOccurs>
<a:since>3.6</a:since>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>

<xsd:element name="workItemId" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<a:minOccurs>0</a:minOccurs>
<a:maxOccurs>1</a:maxOccurs>
<a:since>3.6</a:since>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>

<xsd:element name="timeBeforeAction" type="xsd:duration">
<xsd:annotation>
<xsd:appinfo>
<a:minOccurs>0</a:minOccurs>
<a:maxOccurs>1</a:maxOccurs>
<a:since>3.6</a:since>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>

</xsd:schema>


Expand Up @@ -473,6 +473,9 @@ public static String excerpt(String input, int maxChars) {
}

public static String fixIndentInMultiline(int indent, String indentString, String s) {
if (s == null) {
return null;
}
int cr = s.indexOf('\r');
int lf = s.indexOf('\n');
String searchFor;
Expand Down
Expand Up @@ -35,5 +35,5 @@ void stopProcessInstance(String instanceId, String username, OperationResult par
void releaseWorkItem(String workItemId, OperationResult parentResult) throws ObjectNotFoundException, SecurityViolationException;

void delegateWorkItem(String workItemId, List<ObjectReferenceType> delegates, WorkItemDelegationMethodType method,
OperationResult parentResult) throws ObjectNotFoundException, SecurityViolationException;
OperationResult parentResult) throws ObjectNotFoundException, SecurityViolationException, SchemaException;
}
Expand Up @@ -2029,7 +2029,7 @@ public void releaseWorkItem(String workItemId, OperationResult parentResult) thr

@Override
public void delegateWorkItem(String workItemId, List<ObjectReferenceType> delegates, WorkItemDelegationMethodType method,
OperationResult parentResult) throws ObjectNotFoundException, SecurityViolationException {
OperationResult parentResult) throws ObjectNotFoundException, SecurityViolationException, SchemaException {
getWorkflowManagerChecked().delegateWorkItem(workItemId, delegates, method, parentResult);
}
//endregion
Expand Down
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2010-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

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

import com.evolveum.midpoint.prism.delta.ChangeType;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.LightweightIdentifierGenerator;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.xml.datatype.Duration;
import javax.xml.namespace.QName;
import java.util.Map;

/**
* @author mederly
*/
public class WorkItemAllocationEvent extends WorkItemEvent {

private WorkItemNotificationActionType notificationAction;

public WorkItemAllocationEvent(LightweightIdentifierGenerator lightweightIdentifierGenerator, ChangeType changeType,
@NotNull WorkItemType workItem, @Nullable SimpleObjectRef assignee, WorkItemOperationKindType operationKind,
SimpleObjectRef initiator, WfContextType workflowContext,
Duration timeBefore) {
super(lightweightIdentifierGenerator, changeType, workItem, assignee, initiator, operationKind, workflowContext,
null);
}

@Override
public boolean isCategoryType(EventCategoryType eventCategoryType) {
return eventCategoryType == EventCategoryType.WORK_ITEM_ALLOCATION_EVENT
|| eventCategoryType == EventCategoryType.WORK_ITEM_EVENT
|| eventCategoryType == EventCategoryType.WORKFLOW_EVENT;
}

@Override
public void createExpressionVariables(Map<QName, Object> variables, OperationResult result) {
super.createExpressionVariables(variables, result);
}

@Override
public String toString() {
return "WorkItemCustomEvent:" + super.toString();
}

}

0 comments on commit df04a24

Please sign in to comment.