From c4b6d8c0ca046da28ce5be6cca8982324b4a1416 Mon Sep 17 00:00:00 2001 From: Pavol Mederly Date: Thu, 10 Mar 2016 23:12:09 +0100 Subject: [PATCH] Removed almost all legacy dynamic variables-based code; almost all 'externalization' stuff. All process variables potentially over 4000 chars are gone. Everything is in the task. Tests are broken now. --- .../schema/MidPointPrismContextFactory.java | 10 +- .../midpoint/schema/util/ObjectTypeUtil.java | 7 + .../ns/public/common/common-workflows-3.xsd | 16 +- .../public/model/workflow/common-forms-3.xsd | 638 +++++++++--------- .../ns/public/model/workflow/extension-3.xsd | 390 +++++------ .../workflow/process-instance-state-3.xsd | 400 +++++------ .../api/NotificationManager.java | 6 +- .../api/events/WorkItemEvent.java | 11 +- .../api/events/WorkflowEvent.java | 100 +-- .../api/events/WorkflowEventCreator.java | 12 +- .../api/events/WorkflowProcessEvent.java | 5 +- .../impl/NotificationManagerImpl.java | 25 +- .../notifications/impl/WorkflowListener.java | 28 +- .../workflow/DefaultWorkflowEventCreator.java | 71 +- .../notifiers/SimpleWorkflowNotifier.java | 10 +- .../midpoint/wf/api/ProcessListener.java | 5 +- .../midpoint/wf/api/WorkItemListener.java | 7 +- model/workflow-impl/pom.xml | 5 + .../wf/impl/activiti/ActivitiInterface.java | 9 +- .../activiti/dao/ProcessInstanceProvider.java | 10 +- .../impl/activiti/dao/WorkItemProvider.java | 339 ++-------- .../wf/impl/jobs/ProcessInstruction.java | 32 + .../wf/impl/jobs/ProcessorInstruction.java | 32 + .../midpoint/wf/impl/jobs/WfTask.java | 58 +- .../wf/impl/jobs/WfTaskController.java | 240 +++---- .../impl/jobs/WfTaskCreationInstruction.java | 480 ++++++------- .../midpoint/wf/impl/jobs/WfTaskUtil.java | 129 +--- .../wf/impl/messages/StartProcessCommand.java | 13 +- .../DefaultProcessMidPointInterface.java | 9 +- .../processes/ProcessMidPointInterface.java | 6 +- .../itemApproval/ApprovalSchema.java | 2 + .../itemApproval/ApprovalSchemaImpl.java | 7 +- ...InitializeLoopThroughApproversInLevel.java | 2 +- .../itemApproval/ItemApprovalInstruction.java | 64 ++ .../ItemApprovalProcessInterface.java | 65 +- .../itemApproval/ProcessVariableNames.java | 4 +- .../RecordIndividualDecision.java | 8 +- .../wf/impl/processors/BaseAuditHelper.java | 76 +-- .../processors/BaseExternalizationHelper.java | 67 -- .../BaseModelInvocationProcessingHelper.java | 6 +- .../wf/impl/processors/ChangeProcessor.java | 61 +- .../general/GcpExternalizationHelper.java | 54 -- .../general/GeneralChangeProcessor.java | 50 +- .../GeneralChangeProcessorInstruction.java | 58 ++ .../scenarios/BaseGcpScenarioBean.java | 66 +- .../general/scenarios/GcpScenarioBean.java | 13 +- .../processors/primary/ObjectTreeDeltas.java | 8 + .../PcpChildWfTaskCreationInstruction.java | 122 +--- .../primary/PcpExternalizationHelper.java | 112 --- .../primary/PcpProcessVariableNames.java | 16 +- .../wf/impl/processors/primary/PcpWfTask.java | 7 + .../primary/PrimaryChangeProcessor.java | 128 ++-- .../PrimaryChangeProcessorInstruction.java | 54 ++ .../aspect/BasePrimaryChangeAspect.java | 8 - .../primary/aspect/PrimaryChangeAspect.java | 45 -- .../assignments/AddAssignmentAspect.java | 74 +- .../assignments/ModifyAssignmentAspect.java | 90 +-- .../entitlements/AddAssociationAspect.java | 62 +- .../primary/objects/AddObjectAspect.java | 52 +- .../primary/other/ChangePasswordAspect.java | 38 +- .../midpoint/wf/impl/util/MiscDataUtil.java | 56 +- .../processes/ItemApproval.bpmn20.xml | 4 +- .../midpoint/wf/impl/AbstractWfTest.java | 16 +- .../midpoint/wf/impl/TestAddAssociation.java | 4 +- .../wf/impl/TestCreateModifyUser.java | 4 +- .../midpoint/wf/impl/TestCreateOrg.java | 4 +- .../wf/impl/TestUserChangeApproval.java | 33 +- ...ovingDummyResourceChangesScenarioBean.java | 58 +- .../general/TestGeneralChangeProcessor.java | 144 ++-- .../repo/sql/util/SimpleTaskAdapter.java | 3 + .../com/evolveum/midpoint/task/api/Task.java | 2 + 71 files changed, 1943 insertions(+), 2907 deletions(-) create mode 100644 model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/ProcessInstruction.java create mode 100644 model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/ProcessorInstruction.java create mode 100644 model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ItemApprovalInstruction.java delete mode 100644 model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseExternalizationHelper.java create mode 100644 model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GeneralChangeProcessorInstruction.java delete mode 100644 model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpExternalizationHelper.java create mode 100644 model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessorInstruction.java diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/MidPointPrismContextFactory.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/MidPointPrismContextFactory.java index 5452cb5906b..b81d5a22700 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/MidPointPrismContextFactory.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/MidPointPrismContextFactory.java @@ -153,11 +153,11 @@ private void registerBuiltinSchemas(SchemaRegistry schemaRegistry) throws Schema schemaRegistry.registerPrismSchemaResource("xml/ns/public/model/workflow/extension-3.xsd", "wf"); - schemaRegistry.registerPrismSchemaResource("xml/ns/public/model/workflow/common-forms-3.xsd", "wfcf", - com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.ObjectFactory.class.getPackage()); - - schemaRegistry.registerPrismSchemaResource("xml/ns/public/model/workflow/process-instance-state-3.xsd", "wfpis", - com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ObjectFactory.class.getPackage()); +// schemaRegistry.registerPrismSchemaResource("xml/ns/public/model/workflow/common-forms-3.xsd", "wfcf", +// com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.ObjectFactory.class.getPackage()); +// +// schemaRegistry.registerPrismSchemaResource("xml/ns/public/model/workflow/process-instance-state-3.xsd", "wfpis", +// com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ObjectFactory.class.getPackage()); schemaRegistry.registerPrismSchemaResource("xml/ns/public/model/scripting/scripting-3.xsd", "s", com.evolveum.midpoint.xml.ns._public.model.scripting_3.ObjectFactory.class.getPackage()); diff --git a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectTypeUtil.java b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectTypeUtil.java index 91c29d7f94b..054c85a7240 100644 --- a/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectTypeUtil.java +++ b/infra/schema/src/main/java/com/evolveum/midpoint/schema/util/ObjectTypeUtil.java @@ -407,4 +407,11 @@ public static Objectable getObjectFromReference(ObjectReferenceType ref) { } return ref.asReferenceValue().getObject().asObjectable(); } + + public static PrismObject getPrismObjectFromReference(ObjectReferenceType ref) { + if (ref == null) { + return null; + } + return ref.asReferenceValue().getObject(); + } } \ No newline at end of file diff --git a/infra/schema/src/main/resources/xml/ns/public/common/common-workflows-3.xsd b/infra/schema/src/main/resources/xml/ns/public/common/common-workflows-3.xsd index a6ad43dbefe..3f365529c81 100644 --- a/infra/schema/src/main/resources/xml/ns/public/common/common-workflows-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/common/common-workflows-3.xsd @@ -709,6 +709,13 @@ + + + + Name of the process definition, e.g. "ItemApproval". + + + @@ -812,6 +819,13 @@ + + + + Contains name of class that provides an interface between wf process and midPoint ("process interface bean"). + + + @@ -951,7 +965,7 @@ - + diff --git a/infra/schema/src/main/resources/xml/ns/public/model/workflow/common-forms-3.xsd b/infra/schema/src/main/resources/xml/ns/public/model/workflow/common-forms-3.xsd index bc9b5bb788f..103883e87db 100644 --- a/infra/schema/src/main/resources/xml/ns/public/model/workflow/common-forms-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/model/workflow/common-forms-3.xsd @@ -48,334 +48,334 @@ - - - - Parent type for work item contents - the information that gets presented to the user and item(s) that - are elicited from the user. - - - - - - - - - The core of the request: a form that presents the user with request-specific question - and asks for request-specific answer. - - - tns:questionFormRef - - - - - - - tns:QuestionFormType - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - Generic work item contents for any process that approves a change to an object. - It contains object state before and after the change, the change itself, - any related objects, and a request-specific "question form". - - - - - - - - - Object before requested modification. - - - tns:objectOldRef - - - - - - - c:ObjectType - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - Object after requested modification. - - - tns:objectNewRef - - - - - - - c:ObjectType - - - + + + + + + + + + + + + + + + + + - - - - Delta to be approved by this work item. - - - + + + + + + + - - - - Any objects related to the request. E.g. if the request is to assign a role to the user, - in this attribute there is the role that is actually to be assigned. + + + + + - Due to current prism limitations, max count is set to 1. - - - tns:relatedObjectRef - - - - - - - c:ObjectType - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - TODO - - - - - - - - + + + + + + + + + + + + - - - - TODO - - - - - - - - - Owner (focus) name - 100 - read - - - - - - - Assigned object to be approved - 110 - read - - - - - - - Time interval - 120 - read - - - - - - - Requester's comment - 130 - read - - - - - - - Your comment - 140 - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - TODO - - - - - - - - - Owner (focus) name - 100 - read - - - - - - - Assigned object - 110 - read - - - - - - - - Changes to be approved - 120 - read - - - - - - - Requester's comment - 130 - read - - - - - - - Your comment - 140 - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - TODO - - - - - - - - - Object to be added - 100 - read - - - - - - - Requester's comment - 110 - read - - - - - - - Your comment - 120 - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - TODO - - - - - - - - - Owner (focus) name - 100 - read - - - - - - - Entitlement to be added - 110 - read - - - - - - - Your comment - 140 - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/infra/schema/src/main/resources/xml/ns/public/model/workflow/extension-3.xsd b/infra/schema/src/main/resources/xml/ns/public/model/workflow/extension-3.xsd index 2cfbad48fd1..1fbdb922180 100644 --- a/infra/schema/src/main/resources/xml/ns/public/model/workflow/extension-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/model/workflow/extension-3.xsd @@ -43,200 +43,200 @@ schemaLocation="http://midpoint.evolveum.com/xml/ns/public/common/common-3"> - - - - Contains deltaIn(i), i.e. delta(s) that has to be approved. - Valid for PrimaryChangeProcessor only. - - DEPRECATED. Replaced by deltasToProcess. - - - false - 0 - -1 - - - - - - - - Contains deltaIn(i), i.e. delta(s) that has to be approved. - Valid for PrimaryChangeProcessor only. - - - false - 0 - 1 - - - - - - - - Contains deltaOut(i), i.e. delta(s) that are the result of the approval process. The most - common situation is that deltaOut(i) = either deltaIn(i) (if approved), - or null/empty delta (if rejected). - - Valid for PrimaryChangeProcessor only. - - DEPRECATED. Replaced by resultingDeltas. - - - false - 0 - -1 - - - - - - - - Contains deltaOut(i), i.e. delta(s) that are the result of the approval process. The most - common situation is that deltaOut(i) = either deltaIn(i) (if approved), - or null/empty delta (if rejected). - - Valid for PrimaryChangeProcessor only. - - - false - 0 - 1 - - - - - - - - Contains a set of approvers who approved the delta(s). The wf code should put here those approvers - that will be stored into approvers list in metadata when the operation is really executed. - - - false - 0 - -1 - c:UserType - - - - - - - - Contains relevant activiti process instance ID (when known). - - - true - 0 - 1 - - - - - - - - Just a flag whether the process instance related to the task has already finished (used e.g. to - determine if the shadowing handler should end or not). - - - false - 0 - 1 - - - - - - - - OID of workflow root task that is stored into original task in the context of which the model operation was called. - - - true - 0 - 1 - - - - - - - - Contains name of class that manages this particular model operation ("change", thus "change processor"). - See https://wiki.evolveum.com/display/midPoint/Workflow+Management. - - - true - 0 - 1 - - - - - - - - The name of a class that provides an interface between midPoint and activiti process. - See https://wiki.evolveum.com/display/midPoint/Workflow+Management. - - Valid for PrimaryChangeProcessor only. - - - true - 0 - 1 - - - - - - - - Contains history of process status messages. Such messages can contain any process-related - messages that should be visible to the user (e.g. "your request was approved by engineering group, - and is being sent to the management"). For simple processes, the status has mostly the value - "Workflow process instance has proceeded". In order to be able to sort these status messages - chronologically, each is prefixed by a timestamp (long value + formatted string value). - - Storing of these wfStatus values can be simply turned off in WfTaskUtil class. - - - false - 0 - -1 - - - - - - - - A dump of recent process instance variables (for diagnostic purposes). - - - false - 0 - 1 - - - - - - - - String representation of recent process instance information (for diagnostic purposes). - - - false - 0 - 1 - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/infra/schema/src/main/resources/xml/ns/public/model/workflow/process-instance-state-3.xsd b/infra/schema/src/main/resources/xml/ns/public/model/workflow/process-instance-state-3.xsd index c544005e3d5..a5090d79b3a 100644 --- a/infra/schema/src/main/resources/xml/ns/public/model/workflow/process-instance-state-3.xsd +++ b/infra/schema/src/main/resources/xml/ns/public/model/workflow/process-instance-state-3.xsd @@ -48,211 +48,211 @@ - - - - - - - Generic process instance state, common to all workflow processes. - - - - - - - - - Name of the process instance. It is defined by the code that starts - the process instance and should describe the purpose of the process - instance as precisely as possible. An example: "Approving adding Webmaster to JoeDoe". - - - - - - - When the particular process instance started. - - - - - - - OID of process instance shadowing task in midPoint. (Process variable midPointTaskOid). - - - - - - - Class name of the midPoint change processor that manages this particular change request. - (Process variable midPointChangeProcessor.) - - - - - - - OID of the change requester. (Process variable midPointRequesterOid.) - - - - - - - OID of the object being changed (if applicable). (Process variable midPointObjectOid.) - - - - - - - Value of process variable "wfState" that should describe current state of - the process instance (e.g. "Request was approved by Engineering, passed now to - the Management Group"). - - - - - - - Value of process variable "wfAnswer" that should describe overall outcome - of the process instance. - - - - - - - State that is specific to a given change processor. - - - - - - - State that is specific to a given BPMN process. - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - Marker class for classes that describe states that are specific to a given change processor. - - - - + + + + + + + + + + + - - - - - - - TODO - - - - - - - - - - tns:objectToBeAddedRef - - - - - - - tns:ObjectType - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - TODO - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - Marker class for classes that describe states that are specific to a given BPMN process. - - - - + + + + + + + + + + + - - - - - - - TODO - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - - - TODO - - - - - - - - + + + + + + + + + + + + + + + diff --git a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/NotificationManager.java b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/NotificationManager.java index 1bf6b70bf79..b7ee4b6e1b6 100644 --- a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/NotificationManager.java +++ b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/NotificationManager.java @@ -19,11 +19,9 @@ import com.evolveum.midpoint.notifications.api.events.Event; import com.evolveum.midpoint.notifications.api.events.WorkflowEventCreator; import com.evolveum.midpoint.notifications.api.transports.Transport; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.xml.ns._public.common.common_3.EventHandlerType; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; /** * @author mederly @@ -34,9 +32,7 @@ public interface NotificationManager { void registerTransport(String name, Transport transport); Transport getTransport(String name); - void registerWorkflowEventCreator(Class clazz, WorkflowEventCreator workflowEventCreator); - - WorkflowEventCreator getWorkflowEventCreator(PrismObject instanceState); + WorkflowEventCreator getWorkflowEventCreator(Task wfTask); // event may be null void processEvent(Event event); diff --git a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkItemEvent.java b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkItemEvent.java index 56de7f13258..f5a092152c9 100644 --- a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkItemEvent.java +++ b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkItemEvent.java @@ -21,6 +21,9 @@ import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.LightweightIdentifierGenerator; import com.evolveum.midpoint.xml.ns._public.common.common_3.EventCategoryType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfContextType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType; +import org.apache.commons.lang.Validate; import javax.xml.namespace.QName; @@ -31,11 +34,15 @@ */ public class WorkItemEvent extends WorkflowEvent { + private final WorkItemNewType workItem; private String workItemName; private SimpleObjectRef assignee; - public WorkItemEvent(LightweightIdentifierGenerator lightweightIdentifierGenerator, ChangeType changeType) { - super(lightweightIdentifierGenerator, changeType); + public WorkItemEvent(LightweightIdentifierGenerator lightweightIdentifierGenerator, ChangeType changeType, WorkItemNewType workItem, + WfContextType workflowContext) { + super(lightweightIdentifierGenerator, changeType, workflowContext); + Validate.notNull(workItem); + this.workItem = workItem; } public String getWorkItemName() { diff --git a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkflowEvent.java b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkflowEvent.java index a809b7da008..beb7d535be4 100644 --- a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkflowEvent.java +++ b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkflowEvent.java @@ -17,68 +17,36 @@ package com.evolveum.midpoint.notifications.api.events; import com.evolveum.midpoint.notifications.api.OperationStatus; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ChangeType; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.task.api.LightweightIdentifierGenerator; import com.evolveum.midpoint.wf.util.ApprovalUtils; -import com.evolveum.midpoint.xml.ns._public.common.common_3.EventOperationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.EventStatusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; - -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ItemApprovalProcessState; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ItemApprovalRequestType; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.PrimaryChangeProcessorState; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessSpecificState; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessorSpecificState; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.apache.commons.lang.Validate; -import java.io.Serializable; - /** * @author mederly */ abstract public class WorkflowEvent extends BaseEvent { - private String processInstanceName; - private PrismObject processInstanceState; - private String operationStatusCustom; // exact string representation of the status (useful for work items that return custom statuses) - private ChangeType changeType; // ADD = process/task start, DELETE = process/task finish (for now) + private final WfContextType workflowContext; + private final ChangeType changeType; // ADD = process/task start, DELETE = process/task finish (for now) - public WorkflowEvent(LightweightIdentifierGenerator lightweightIdentifierGenerator, ChangeType changeType) { + public WorkflowEvent(LightweightIdentifierGenerator lightweightIdentifierGenerator, ChangeType changeType, WfContextType workflowContext) { super(lightweightIdentifierGenerator); Validate.notNull(changeType, "changeType is null"); this.changeType = changeType; + Validate.notNull(workflowContext, "workflowContext is null"); + this.workflowContext = workflowContext; } public String getProcessInstanceName() { - return processInstanceName; - } - - public void setProcessInstanceName(String processInstanceName) { - this.processInstanceName = processInstanceName; - } - - public PrismObject getProcessInstanceState() { - return processInstanceState; - } - - public void setProcessInstanceState(PrismObject processInstanceState) { - this.processInstanceState = processInstanceState; + return workflowContext.getProcessInstanceName(); } public OperationStatus getOperationStatus() { - return resultToStatus(changeType, operationStatusCustom); - } - - public String getOperationStatusCustom() { - return operationStatusCustom; - } - - public void setOperationStatusCustom(String operationStatusCustom) { - this.operationStatusCustom = operationStatusCustom; + return resultToStatus(changeType, workflowContext.getAnswer()); } @Override @@ -128,52 +96,28 @@ public boolean isRelatedToItem(ItemPath itemPath) { return false; } - public ProcessorSpecificState getProcessorSpecificState() { - if (processInstanceState == null) { - return null; - } - return ((ProcessInstanceState) processInstanceState.asObjectable()).getProcessorSpecificState(); + public WfProcessorSpecificStateType getProcessorSpecificState() { + return workflowContext.getProcessorSpecificState(); } - public ProcessSpecificState getProcessSpecificState() { - if (processInstanceState == null) { - return null; - } - return ((ProcessInstanceState) processInstanceState.asObjectable()).getProcessSpecificState(); + public WfProcessSpecificStateType getProcessSpecificState() { + return workflowContext.getProcessSpecificState(); } - public PrimaryChangeProcessorState getPrimaryChangeProcessorState() { - ProcessorSpecificState state = getProcessorSpecificState(); - if (state instanceof PrimaryChangeProcessorState) { - return (PrimaryChangeProcessorState) state; + public WfPrimaryChangeProcessorStateType getPrimaryChangeProcessorState() { + WfProcessorSpecificStateType state = getProcessorSpecificState(); + if (state instanceof WfPrimaryChangeProcessorStateType) { + return (WfPrimaryChangeProcessorStateType) state; } else { return null; } } // the following three methods are specific to ItemApproval process - public ItemApprovalProcessState getItemApprovalProcessState() { - ProcessSpecificState state = getProcessSpecificState(); - if (state instanceof ItemApprovalProcessState) { - return (ItemApprovalProcessState) state; - } else { - return null; - } - } - - public ItemApprovalRequestType getItemApprovalRequest() { - ItemApprovalProcessState state = getItemApprovalProcessState(); - if (state != null) { - return state.getApprovalRequest(); - } else { - return null; - } - } - - public Object getItemToApprove() { - ItemApprovalRequestType request = getItemApprovalRequest(); - if (request != null) { - return request.getItemToApprove(); + public ItemApprovalProcessStateType getItemApprovalProcessState() { + WfProcessSpecificStateType state = getProcessSpecificState(); + if (state instanceof ItemApprovalProcessStateType) { + return (ItemApprovalProcessStateType) state; } else { return null; } @@ -183,9 +127,9 @@ public Object getItemToApprove() { public String toString() { return "WorkflowEvent{" + "event=" + super.toString() + - ", processInstanceName='" + processInstanceName + '\'' + + ", processInstanceName='" + getProcessInstanceName() + '\'' + ", changeType=" + changeType + - ", operationStatusCustom=" + operationStatusCustom + + ", answer=" + workflowContext.getAnswer() + '}'; } diff --git a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkflowEventCreator.java b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkflowEventCreator.java index d11b6e28959..a8dc9617d7f 100644 --- a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkflowEventCreator.java +++ b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkflowEventCreator.java @@ -16,9 +16,9 @@ package com.evolveum.midpoint.notifications.api.events; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType; /** * Used to create (fill-in) a workflow event based on information passed from workflow module. @@ -35,11 +35,11 @@ */ public interface WorkflowEventCreator { - WorkflowProcessEvent createWorkflowProcessStartEvent(PrismObject instanceState, OperationResult result); + WorkflowProcessEvent createWorkflowProcessStartEvent(Task wfTask, OperationResult result); - WorkflowProcessEvent createWorkflowProcessEndEvent(PrismObject instanceState, OperationResult result); + WorkflowProcessEvent createWorkflowProcessEndEvent(Task wfTask, OperationResult result); - WorkItemEvent createWorkItemCreateEvent(String workItemName, String assigneeOid, PrismObject instanceState); + WorkItemEvent createWorkItemCreateEvent(WorkItemNewType workItem, Task wfTask, OperationResult result); - WorkItemEvent createWorkItemCompleteEvent(String workItemName, String assigneeOid, PrismObject instanceState, String decision); + WorkItemEvent createWorkItemCompleteEvent(WorkItemNewType workItem, Task wfTask, OperationResult result); } diff --git a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkflowProcessEvent.java b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkflowProcessEvent.java index eeb93646d1c..86e265eee15 100644 --- a/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkflowProcessEvent.java +++ b/model/notifications-api/src/main/java/com/evolveum/midpoint/notifications/api/events/WorkflowProcessEvent.java @@ -19,14 +19,15 @@ import com.evolveum.midpoint.prism.delta.ChangeType; import com.evolveum.midpoint.task.api.LightweightIdentifierGenerator; import com.evolveum.midpoint.xml.ns._public.common.common_3.EventCategoryType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfContextType; /** * @author mederly */ public class WorkflowProcessEvent extends WorkflowEvent { - public WorkflowProcessEvent(LightweightIdentifierGenerator lightweightIdentifierGenerator, ChangeType changeType) { - super(lightweightIdentifierGenerator, changeType); + public WorkflowProcessEvent(LightweightIdentifierGenerator lightweightIdentifierGenerator, ChangeType changeType, WfContextType workflowContext) { + super(lightweightIdentifierGenerator, changeType, workflowContext); } @Override diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationManagerImpl.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationManagerImpl.java index 33ca4e8c683..590a3f5e118 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationManagerImpl.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/NotificationManagerImpl.java @@ -22,7 +22,6 @@ import com.evolveum.midpoint.notifications.api.events.WorkflowEventCreator; import com.evolveum.midpoint.notifications.api.transports.Transport; import com.evolveum.midpoint.notifications.impl.events.workflow.DefaultWorkflowEventCreator; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; @@ -33,14 +32,10 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.EventHandlerType; import com.evolveum.midpoint.xml.ns._public.common.common_3.NotificationConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; -import javax.xml.bind.JAXBElement; - import java.util.HashMap; /** @@ -63,7 +58,6 @@ public class NotificationManagerImpl implements NotificationManager { private HashMap,EventHandler> handlers = new HashMap,EventHandler>(); private HashMap transports = new HashMap(); - private HashMap,WorkflowEventCreator> workflowEventCreators = new HashMap<>(); // key = class of type ProcessInstanceState public void registerEventHandler(Class clazz, EventHandler handler) { LOGGER.trace("Registering event handler " + handler + " for " + clazz); @@ -98,22 +92,9 @@ public Transport getTransport(String name) { } @Override - public void registerWorkflowEventCreator(Class clazz, WorkflowEventCreator workflowEventCreator) { - // TODO think again about this mechanism - if (workflowEventCreators.containsKey(clazz)) { - LOGGER.warn("Multiple registrations of workflow event creators for class {}", clazz.getName()); - } - workflowEventCreators.put(clazz, workflowEventCreator); - } - - @Override - public WorkflowEventCreator getWorkflowEventCreator(PrismObject instanceState) { - WorkflowEventCreator workflowEventCreator = workflowEventCreators.get(instanceState.asObjectable().getClass()); - if (workflowEventCreator == null) { - return defaultWorkflowEventCreator; - } else { - return workflowEventCreator; - } + public WorkflowEventCreator getWorkflowEventCreator(Task wfTask) { + // TODO + return defaultWorkflowEventCreator; } // event may be null diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/WorkflowListener.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/WorkflowListener.java index 795fbe92891..e8c85c9f2c9 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/WorkflowListener.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/WorkflowListener.java @@ -21,15 +21,15 @@ import com.evolveum.midpoint.notifications.api.events.WorkflowEvent; import com.evolveum.midpoint.notifications.api.events.WorkflowEventCreator; import com.evolveum.midpoint.notifications.api.events.WorkflowProcessEvent; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.wf.api.ProcessListener; import com.evolveum.midpoint.wf.api.WorkItemListener; import com.evolveum.midpoint.wf.api.WorkflowManager; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -67,30 +67,30 @@ public void init() { } @Override - public void onProcessInstanceStart(PrismObject instanceState, OperationResult result) { - WorkflowEventCreator workflowEventCreator = notificationManager.getWorkflowEventCreator(instanceState); - WorkflowProcessEvent event = workflowEventCreator.createWorkflowProcessStartEvent(instanceState, result); + public void onProcessInstanceStart(Task wfTask, OperationResult result) { + WorkflowEventCreator workflowEventCreator = notificationManager.getWorkflowEventCreator(wfTask); + WorkflowProcessEvent event = workflowEventCreator.createWorkflowProcessStartEvent(wfTask, result); processEvent(event, result); } @Override - public void onProcessInstanceEnd(PrismObject instanceState, OperationResult result) { - WorkflowEventCreator workflowEventCreator = notificationManager.getWorkflowEventCreator(instanceState); - WorkflowProcessEvent event = workflowEventCreator.createWorkflowProcessEndEvent(instanceState, result); + public void onProcessInstanceEnd(Task wfTask, OperationResult result) { + WorkflowEventCreator workflowEventCreator = notificationManager.getWorkflowEventCreator(wfTask); + WorkflowProcessEvent event = workflowEventCreator.createWorkflowProcessEndEvent(wfTask, result); processEvent(event, result); } @Override - public void onWorkItemCreation(String workItemName, String assigneeOid, PrismObject instanceState) { - WorkflowEventCreator workflowEventCreator = notificationManager.getWorkflowEventCreator(instanceState); - WorkItemEvent event = workflowEventCreator.createWorkItemCreateEvent(workItemName, assigneeOid, instanceState); + public void onWorkItemCreation(WorkItemNewType workItem, Task wfTask, OperationResult result) { + WorkflowEventCreator workflowEventCreator = notificationManager.getWorkflowEventCreator(wfTask); + WorkItemEvent event = workflowEventCreator.createWorkItemCreateEvent(workItem, wfTask, result); processEvent(event); } @Override - public void onWorkItemCompletion(String workItemName, String assigneeOid, PrismObject instanceState, String decision) { - WorkflowEventCreator workflowEventCreator = notificationManager.getWorkflowEventCreator(instanceState); - WorkItemEvent event = workflowEventCreator.createWorkItemCompleteEvent(workItemName, assigneeOid, instanceState, decision); + public void onWorkItemCompletion(WorkItemNewType workItem, Task wfTask, OperationResult result) { + WorkflowEventCreator workflowEventCreator = notificationManager.getWorkflowEventCreator(wfTask); + WorkItemEvent event = workflowEventCreator.createWorkItemCompleteEvent(workItem, wfTask, result); processEvent(event); } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/events/workflow/DefaultWorkflowEventCreator.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/events/workflow/DefaultWorkflowEventCreator.java index f29df4ab616..3bf3a45687e 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/events/workflow/DefaultWorkflowEventCreator.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/events/workflow/DefaultWorkflowEventCreator.java @@ -23,20 +23,15 @@ import com.evolveum.midpoint.notifications.api.events.WorkflowProcessEvent; import com.evolveum.midpoint.notifications.impl.NotificationsUtil; import com.evolveum.midpoint.notifications.impl.SimpleObjectRefImpl; -import com.evolveum.midpoint.prism.PrismObject; 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.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.PrimaryChangeProcessorState; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; - +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfContextType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; - /** * @author mederly */ @@ -52,64 +47,44 @@ public class DefaultWorkflowEventCreator implements WorkflowEventCreator { @Autowired private NotificationManager notificationManager; - @PostConstruct - public void init() { - notificationManager.registerWorkflowEventCreator(ProcessInstanceState.class, this); - } - @Override - public WorkflowProcessEvent createWorkflowProcessStartEvent(PrismObject instanceState, OperationResult result) { - return createWorkflowProcessEvent(instanceState, ChangeType.ADD, result); + public WorkflowProcessEvent createWorkflowProcessStartEvent(Task wfTask, OperationResult result) { + return createWorkflowProcessEvent(wfTask, ChangeType.ADD, result); } @Override - public WorkflowProcessEvent createWorkflowProcessEndEvent(PrismObject instanceState, OperationResult result) { - return createWorkflowProcessEvent(instanceState, ChangeType.DELETE, result); + public WorkflowProcessEvent createWorkflowProcessEndEvent(Task wfTask, OperationResult result) { + return createWorkflowProcessEvent(wfTask, ChangeType.DELETE, result); } - private WorkflowProcessEvent createWorkflowProcessEvent(PrismObject instanceState, ChangeType changeType, OperationResult result) { - WorkflowProcessEvent event = new WorkflowProcessEvent(lightweightIdentifierGenerator, changeType); - fillInEvent(event, instanceState.asObjectable().getProcessInstanceName(), instanceState, instanceState.asObjectable().getAnswer(), result); + private WorkflowProcessEvent createWorkflowProcessEvent(Task wfTask, ChangeType changeType, OperationResult result) { + WorkflowProcessEvent event = new WorkflowProcessEvent(lightweightIdentifierGenerator, changeType, wfTask.getWorkflowContext()); + fillInEvent(event, wfTask); return event; } - private void fillInEvent(WorkflowEvent event, String instanceName, PrismObject instanceState, String decision, OperationResult result) { - event.setProcessInstanceName(instanceName); - event.setOperationStatusCustom(decision); - event.setProcessInstanceState(instanceState); - event.setRequester(new SimpleObjectRefImpl(notificationsUtil, instanceState.asObjectable().getRequesterOid())); - if (instanceState.asObjectable().getObjectOid() != null) { - event.setRequestee(new SimpleObjectRefImpl(notificationsUtil, instanceState.asObjectable().getObjectOid())); - } - - // fill-in requestee (for primary approval process variables) - - if (event.getRequestee() == null && instanceState.asObjectable().getProcessorSpecificState() instanceof PrimaryChangeProcessorState) { - PrimaryChangeProcessorState pcpState = (PrimaryChangeProcessorState) instanceState.asObjectable().getProcessorSpecificState(); - if (pcpState.getObjectToBeAdded() != null) { - ObjectType objectToBeAdded = pcpState.getObjectToBeAdded(); - if (objectToBeAdded instanceof UserType) { - event.setRequestee(new SimpleObjectRefImpl(notificationsUtil, objectToBeAdded)); - } - } + private void fillInEvent(WorkflowEvent event, Task wfTask) { + WfContextType wfc = wfTask.getWorkflowContext(); + event.setRequester(new SimpleObjectRefImpl(notificationsUtil, wfc.getRequesterRef())); + if (wfc.getObjectRef() != null) { + event.setRequestee(new SimpleObjectRefImpl(notificationsUtil, wfc.getObjectRef())); } + // TODO what if requestee is yet to be created? } @Override - public WorkItemEvent createWorkItemCreateEvent(String workItemName, String assigneeOid, PrismObject instanceState) { - return createWorkItemEvent(workItemName, assigneeOid, instanceState, ChangeType.ADD, null); + public WorkItemEvent createWorkItemCreateEvent(WorkItemNewType workItem, Task wfTask, OperationResult result) { + return createWorkItemEvent(workItem, wfTask, ChangeType.ADD); } @Override - public WorkItemEvent createWorkItemCompleteEvent(String workItemName, String assigneeOid, PrismObject instanceState, String decision) { - return createWorkItemEvent(workItemName, assigneeOid, instanceState, ChangeType.DELETE, decision); + public WorkItemEvent createWorkItemCompleteEvent(WorkItemNewType workItem, Task wfTask, OperationResult result) { + return createWorkItemEvent(workItem, wfTask, ChangeType.DELETE); } - private WorkItemEvent createWorkItemEvent(String workItemName, String assigneeOid, PrismObject instanceState, ChangeType changeType, String decision) { - WorkItemEvent event = new WorkItemEvent(lightweightIdentifierGenerator, changeType); - event.setWorkItemName(workItemName); - event.setAssignee(new SimpleObjectRefImpl(notificationsUtil, assigneeOid)); - fillInEvent(event, instanceState.asObjectable().getProcessInstanceName(), instanceState, decision, new OperationResult("dummy")); + private WorkItemEvent createWorkItemEvent(WorkItemNewType workItemNewType, Task wfTask, ChangeType changeType) { + WorkItemEvent event = new WorkItemEvent(lightweightIdentifierGenerator, changeType, workItemNewType, wfTask.getWorkflowContext()); + fillInEvent(event, wfTask); return event; } } diff --git a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleWorkflowNotifier.java b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleWorkflowNotifier.java index 2f3a00f9c30..80c59e87d07 100644 --- a/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleWorkflowNotifier.java +++ b/model/notifications-impl/src/main/java/com/evolveum/midpoint/notifications/impl/notifiers/SimpleWorkflowNotifier.java @@ -103,11 +103,11 @@ protected String getBody(Event event, GeneralNotifierType generalNotifierType, S } body.append("Notification created on: ").append(new Date()).append("\n\n"); - if (techInfo) { - body.append("----------------------------------------\n"); - body.append("Technical information:\n\n"); - body.append(workflowEvent.getProcessInstanceState().debugDump()); - } +// if (techInfo) { +// body.append("----------------------------------------\n"); +// body.append("Technical information:\n\n"); +// body.append(workflowEvent.getProcessInstanceState().debugDump()); +// } return body.toString(); } diff --git a/model/workflow-api/src/main/java/com/evolveum/midpoint/wf/api/ProcessListener.java b/model/workflow-api/src/main/java/com/evolveum/midpoint/wf/api/ProcessListener.java index 01886bb6a49..1e5bb7640d5 100644 --- a/model/workflow-api/src/main/java/com/evolveum/midpoint/wf/api/ProcessListener.java +++ b/model/workflow-api/src/main/java/com/evolveum/midpoint/wf/api/ProcessListener.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; /** @@ -35,7 +36,7 @@ public interface ProcessListener { * @param instanceState externalized process instance variables * @param result implementer should report its result here */ - void onProcessInstanceStart(PrismObject instanceState, OperationResult result); + void onProcessInstanceStart(Task wfTask, OperationResult result); /** * This method is called by wf module when a process instance ends. @@ -43,5 +44,5 @@ public interface ProcessListener { * @param instanceState externalized process instance variables * @param result implementer should report its result here */ - void onProcessInstanceEnd(PrismObject instanceState, OperationResult result); + void onProcessInstanceEnd(Task wfTask, OperationResult result); } diff --git a/model/workflow-api/src/main/java/com/evolveum/midpoint/wf/api/WorkItemListener.java b/model/workflow-api/src/main/java/com/evolveum/midpoint/wf/api/WorkItemListener.java index f8acebbad52..cdbb83b35e6 100644 --- a/model/workflow-api/src/main/java/com/evolveum/midpoint/wf/api/WorkItemListener.java +++ b/model/workflow-api/src/main/java/com/evolveum/midpoint/wf/api/WorkItemListener.java @@ -17,6 +17,9 @@ package com.evolveum.midpoint.wf.api; import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType; import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; /** @@ -41,7 +44,7 @@ public interface WorkItemListener { * @param assigneeOid OID of the user to which the work item is assigned * @param instanceState externalized process instance state */ - public void onWorkItemCreation(String workItemName, String assigneeOid, PrismObject instanceState); + public void onWorkItemCreation(WorkItemNewType workItem, Task wfTask, OperationResult result); /** * This method is called by wf module when a work item is completed. @@ -51,5 +54,5 @@ public interface WorkItemListener { * @param instanceState externalized process instance state * @param decision decision of the user */ - public void onWorkItemCompletion(String workItemName, String assigneeOid, PrismObject instanceState, String decision); + public void onWorkItemCompletion(WorkItemNewType workItem, Task wfTask, OperationResult result); } diff --git a/model/workflow-impl/pom.xml b/model/workflow-impl/pom.xml index d9ba854ab2d..c0f6e1bc51b 100644 --- a/model/workflow-impl/pom.xml +++ b/model/workflow-impl/pom.xml @@ -85,6 +85,11 @@ org.activiti activiti-spring + + org.jetbrains + annotations-java5 + 15.0 + com.evolveum.midpoint.repo diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/ActivitiInterface.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/ActivitiInterface.java index bcd7b1859f5..04a6a213dec 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/ActivitiInterface.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/ActivitiInterface.java @@ -27,6 +27,7 @@ import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; +import com.evolveum.midpoint.wf.impl.activiti.dao.WorkItemProvider; import com.evolveum.midpoint.wf.impl.jobs.WfTaskController; import com.evolveum.midpoint.wf.impl.messages.ProcessEvent; import com.evolveum.midpoint.wf.impl.messages.ProcessFinishedEvent; @@ -40,6 +41,7 @@ import com.evolveum.midpoint.wf.impl.processes.ProcessInterfaceFinder; import com.evolveum.midpoint.wf.impl.processes.common.CommonProcessVariableNames; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType; import org.activiti.engine.HistoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.delegate.DelegateExecution; @@ -81,11 +83,13 @@ public class ActivitiInterface { @Autowired private ProcessInterfaceFinder processInterfaceFinder; + @Autowired + private WorkItemProvider workItemProvider; + public void startActivitiProcessInstance(StartProcessCommand spic, Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { Map map = new HashMap<>(); - map.put(CommonProcessVariableNames.VARIABLE_MIDPOINT_TASK_OID, spic.getTaskOid()); map.putAll(spic.getVariables()); String owner = spic.getProcessOwner(); @@ -226,7 +230,8 @@ public void notifyMidpointAboutTaskEvent(DelegateTask delegateTask) { } try { - wfTaskController.onTaskEvent(taskEvent, result); + WorkItemNewType workItem = workItemProvider.taskEventToWorkItemNew(taskEvent, null, true, true, true, result); + wfTaskController.onTaskEvent(workItem, taskEvent, result); } catch (Exception e) { // todo fix the exception processing e.g. think about situation where an event cannot be audited - should we allow to proceed? String message = "Couldn't process an event coming from the workflow management system"; LoggingUtils.logException(LOGGER, message, e); diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/ProcessInstanceProvider.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/ProcessInstanceProvider.java index 5abe9b6559e..31a36f24d51 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/ProcessInstanceProvider.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/ProcessInstanceProvider.java @@ -18,6 +18,7 @@ import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.path.ItemPath; +import com.evolveum.midpoint.prism.util.CloneUtil; import com.evolveum.midpoint.prism.xml.XmlTypeConverter; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SearchResultList; @@ -55,6 +56,7 @@ import java.util.List; import java.util.Map; +import static com.evolveum.midpoint.prism.util.CloneUtil.cloneCollectionMembers; import static com.evolveum.midpoint.wf.impl.processes.common.CommonProcessVariableNames.*; import static com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType.F_WORKFLOW_CONTEXT; import static com.evolveum.midpoint.xml.ns._public.common.common_3.WfContextType.F_WORK_ITEM; @@ -153,7 +155,7 @@ private WfContextType activitiToMidpointWfContextHistory(HistoricProcessInstance if (cp == null) { throw new SchemaException("No change processor information in process instance " + instance.getId()); } - wfc.setProcessorSpecificState(cp.externalizeProcessorSpecificState(vars)); + //wfc.setProcessorSpecificState(cp.externalizeProcessorSpecificState(vars)); wfc.setProcessSpecificState(pmi.externalizeProcessSpecificState(vars)); if (getWorkItems) { @@ -161,7 +163,7 @@ private WfContextType activitiToMidpointWfContextHistory(HistoricProcessInstance List tasks = ts.createTaskQuery() .processInstanceId(instance.getId()) .list(); - wfc.getWorkItem().addAll(workItemProvider.tasksToWorkItemsNew(tasks, vars, true, true, result)); // "no" to task forms, "yes" to assignee and candidate details + wfc.getWorkItem().addAll(workItemProvider.tasksToWorkItemsNew(tasks, vars, false, true, true, result)); // "no" to task forms, "yes" to assignee and candidate details } return wfc; @@ -191,8 +193,8 @@ public void augmentTaskObject(PrismObject object, return; } boolean retrieveWorkItems = SelectorOptions.hasToLoadPath(new ItemPath(F_WORKFLOW_CONTEXT, F_WORK_ITEM), options); - WfContextType wfContextType = getWfContextType(instanceId, retrieveWorkItems, result); - taskType.setWorkflowContext(wfContextType); + WfContextType wfContextType2 = getWfContextType(instanceId, retrieveWorkItems, result); + taskType.getWorkflowContext().getWorkItem().addAll(cloneCollectionMembers(wfContextType2.getWorkItem())); } catch (RuntimeException|SchemaException|ObjectNotFoundException|WorkflowException e) { result.recordFatalError(e.getMessage(), e); taskType.setFetchResult(result.createOperationResultType()); diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/WorkItemProvider.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/WorkItemProvider.java index f6781d68027..5d443b8bc5a 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/WorkItemProvider.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/activiti/dao/WorkItemProvider.java @@ -25,12 +25,8 @@ import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SearchResultList; import com.evolveum.midpoint.schema.SelectorOptions; -import com.evolveum.midpoint.schema.constants.ObjectTypes; -import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.MiscSchemaUtil; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SystemException; import com.evolveum.midpoint.util.logging.LoggingUtils; @@ -44,16 +40,15 @@ import com.evolveum.midpoint.wf.impl.activiti.ActivitiEngineDataHelper; import com.evolveum.midpoint.wf.impl.jobs.WfUtil; import com.evolveum.midpoint.wf.impl.messages.TaskEvent; +import com.evolveum.midpoint.wf.impl.processes.ProcessInterfaceFinder; +import com.evolveum.midpoint.wf.impl.processes.ProcessMidPointInterface; import com.evolveum.midpoint.wf.impl.processes.common.CommonProcessVariableNames; import com.evolveum.midpoint.wf.impl.processes.common.LightweightObjectRef; -import com.evolveum.midpoint.wf.impl.processors.ChangeProcessor; import com.evolveum.midpoint.wf.impl.util.MiscDataUtil; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; - +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType; import org.activiti.engine.ActivitiException; import org.activiti.engine.TaskService; -import org.activiti.engine.runtime.ProcessInstanceQuery; import org.activiti.engine.task.IdentityLink; import org.activiti.engine.task.IdentityLinkType; import org.activiti.engine.task.Task; @@ -62,15 +57,15 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; -import javax.xml.bind.JAXBException; - import java.util.*; -import static com.evolveum.midpoint.schema.util.ObjectQueryUtil.*; -import static com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType.F_ASSIGNEE_REF; -import static com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType.F_CANDIDATE_ROLES_REF; -import static com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType.F_WORK_ITEM_ID; -import static org.apache.commons.collections.CollectionUtils.*; +import static com.evolveum.midpoint.schema.constants.ObjectTypes.TASK; +import static com.evolveum.midpoint.schema.constants.ObjectTypes.USER; +import static com.evolveum.midpoint.schema.util.ObjectQueryUtil.FilterComponents; +import static com.evolveum.midpoint.schema.util.ObjectQueryUtil.factorOutQuery; +import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.createObjectRef; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType.*; +import static org.apache.commons.collections.CollectionUtils.isNotEmpty; import static org.apache.commons.lang3.ObjectUtils.defaultIfNull; /** @@ -99,6 +94,9 @@ public class WorkItemProvider { @Autowired private PrismContext prismContext; + @Autowired + private ProcessInterfaceFinder processInterfaceFinder; + @Autowired @Qualifier("cacheRepositoryService") private RepositoryService repositoryService; @@ -106,110 +104,14 @@ public class WorkItemProvider { private static final String DOT_CLASS = WorkflowManagerImpl.class.getName() + "."; private static final String DOT_INTERFACE = WorkflowManager.class.getName() + "."; - private static final String OPERATION_COUNT_WORK_ITEMS_RELATED_TO_USER = DOT_INTERFACE + "countWorkItemsRelatedToUser"; - private static final String OPERATION_LIST_WORK_ITEMS_RELATED_TO_USER = DOT_INTERFACE + "listWorkItemsRelatedToUser"; private static final String OPERATION_SEARCH_WORK_ITEMS = DOT_INTERFACE + "searchWorkItem"; private static final String OPERATION_COUNT_WORK_ITEMS = DOT_INTERFACE + "countWorkItem"; private static final String OPERATION_ACTIVITI_TASK_TO_WORK_ITEM = DOT_CLASS + "activitiTaskToWorkItem"; - private static final String OPERATION_ACTIVITI_DELEGATE_TASK_TO_WORK_ITEM = DOT_CLASS + "activitiDelegateTaskToWorkItem"; - private static final String OPERATION_GET_WORK_ITEM_DETAILS_BY_TASK_ID = DOT_CLASS + "getWorkItemDetailsById"; /* * ========================= PART 1 - main operations ========================= */ - /** - * Counts Work Items related to a user. - * - * @param userOid OID of the user - * @param assigned whether to count assigned (true) or assignable (false) work items - * @param parentResult - * @return number of relevant work items - * @throws WorkflowException - */ - public int countWorkItemsRelatedToUser(String userOid, boolean assigned, OperationResult parentResult) throws SchemaException, ObjectNotFoundException { - OperationResult result = parentResult.createSubresult(OPERATION_COUNT_WORK_ITEMS_RELATED_TO_USER); - result.addParam("userOid", userOid); - result.addParam("assigned", assigned); - try { - int count = (int) createQueryForTasksRelatedToUser(userOid, assigned, result).count(); - result.recordSuccess(); - return count; - } catch (ActivitiException e) { - result.recordFatalError("Couldn't count work items assigned/assignable to " + userOid, e); - throw new SystemException("Couldn't count work items assigned/assignable to " + userOid + " due to Activiti exception", e); - } - } - - /** - * Lists work items related to a user. - * - * @param userOid OID of the user - * @param assigned whether to count assigned (true) or assignable (false) work items - * @param first - * @param count - * @param parentResult - * @return list of work items - * @throws WorkflowException - */ - @Deprecated - public List listWorkItemsRelatedToUser(String userOid, boolean assigned, int first, int count, OperationResult parentResult) throws SchemaException, ObjectNotFoundException { - OperationResult result = parentResult.createSubresult(OPERATION_LIST_WORK_ITEMS_RELATED_TO_USER); - result.addParam("userOid", userOid); - result.addParam("assigned", assigned); - result.addParam("first", first); - result.addParam("count", count); - List tasks; - try { - tasks = createQueryForTasksRelatedToUser(userOid, assigned, result).listPage(first, count); - } catch (ActivitiException e) { - result.recordFatalError("Couldn't list work items assigned/assignable to " + userOid, e); - throw new SystemException("Couldn't list work items assigned/assignable to " + userOid + " due to Activiti exception", e); - } - - List retval = tasksToWorkItems(tasks, false, false, true, result); // there's no need to fill-in assignee details nor data forms; but candidates are necessary to fill-in - result.computeStatusIfUnknown(); - return retval; - } - - @Deprecated - public List listWorkItemsNewRelatedToUser(String userOid, boolean assigned, int first, int count, OperationResult parentResult) throws SchemaException, ObjectNotFoundException { - OperationResult result = parentResult.createSubresult(OPERATION_LIST_WORK_ITEMS_RELATED_TO_USER); - result.addParam("userOid", userOid); - result.addParam("assigned", assigned); - result.addParam("first", first); - result.addParam("count", count); - List tasks; - try { - tasks = createQueryForTasksRelatedToUser(userOid, assigned, result).listPage(first, count); - } catch (ActivitiException e) { - result.recordFatalError("Couldn't list work items assigned/assignable to " + userOid, e); - throw new SystemException("Couldn't list work items assigned/assignable to " + userOid + " due to Activiti exception", e); - } - - List retval = tasksToWorkItemsNew(tasks, null, false, true, result); // there's no need to fill-in assignee details nor data forms; but candidates are necessary to fill-in - result.computeStatusIfUnknown(); - return retval; - } - - private TaskQuery createQueryForTasksRelatedToUser(String oid, boolean assigned, OperationResult result) throws SchemaException, ObjectNotFoundException { - if (assigned) { - return activitiEngine.getTaskService().createTaskQuery() - .taskAssignee(oid) - .orderByTaskCreateTime().desc() - .includeTaskLocalVariables() - .includeProcessVariables(); - - } else { - return activitiEngine.getTaskService().createTaskQuery() - .taskUnassigned() - .taskCandidateGroupIn(miscDataUtil.getGroupsForUser(oid, result)) - .orderByTaskCreateTime().desc() - .includeTaskLocalVariables() - .includeProcessVariables(); - } - } - // primitive 'query interpreter' private TaskQuery createTaskQuery(ObjectQuery query, Collection> options, OperationResult result) throws SchemaException { FilterComponents components = factorOutQuery(query, F_ASSIGNEE_REF, F_CANDIDATE_ROLES_REF, F_WORK_ITEM_ID); @@ -272,27 +174,6 @@ private TaskQuery createTaskQuery(ObjectQuery query, Collection tasksToWorkItems(List tasks, boolean getTaskDetails, boolean getAssigneeDetails, boolean getCandidateDetails, OperationResult result) { - List retval = new ArrayList(); - for (Task task : tasks) { - try { - retval.add(taskToWorkItem(task, getTaskDetails, getAssigneeDetails, getCandidateDetails, result)); - } catch (WorkflowException e) { - LoggingUtils.logException(LOGGER, "Couldn't get information on activiti task {}", e, task.getId()); - } - } - return retval; - } - SearchResultList tasksToWorkItemsNew(List tasks, Map processVariables, - boolean getAssigneeDetails, boolean getCandidateDetails, OperationResult result) { + boolean resolveTask, boolean resolveAssignee, boolean resolveCandidates, OperationResult result) { SearchResultList retval = new SearchResultList<>(new ArrayList()); for (Task task : tasks) { try { - retval.add(taskToWorkItemNew(task, processVariables, getAssigneeDetails, getCandidateDetails, result)); + retval.add(taskToWorkItemNew(task, processVariables, resolveTask, resolveAssignee, resolveCandidates, result)); } catch (WorkflowException e) { LoggingUtils.logException(LOGGER, "Couldn't get information on activiti task {}", e, task.getId()); } @@ -373,7 +242,7 @@ public SearchResultList searchWorkItems(ObjectQuery // there's no need to fill-in assignee details ; but candidates are necessary to fill-in // TODO implement based on options (resolve names) - SearchResultList retval = tasksToWorkItemsNew(tasks, null, false, true, result); + SearchResultList retval = tasksToWorkItemsNew(tasks, null, false, false, true, result); result.computeStatusIfUnknown(); return (SearchResultList) retval; } @@ -512,52 +381,15 @@ public String toString() { } } - private WorkItemType taskToWorkItem(Task task, boolean getTaskDetails, boolean getAssigneeDetails, boolean getCandidateDetails, OperationResult parentResult) throws WorkflowException { - OperationResult result = parentResult.createSubresult(OPERATION_ACTIVITI_TASK_TO_WORK_ITEM); - result.addParam("task id", task.getId()); - result.addParam("getTaskDetails", getTaskDetails); - result.addParam("getAssigneeDetails", getAssigneeDetails); - - TaskExtract taskExtract = new TaskExtract(task); - WorkItemType wi = taskExtractToWorkItem(taskExtract, getAssigneeDetails, getCandidateDetails, result); - - // this could be moved to taskExtractToWorkType after changing ChangeProcessor interface to accept TaskExtract instead of Task - if (getTaskDetails) { - try { - Map variables = activitiEngineDataHelper.getProcessVariables(task.getId(), result); - ChangeProcessor cp = getChangeProcessor(taskExtract, variables); - - PrismObject requester = miscDataUtil.getRequester(variables, result); - wi.setRequester(requester.asObjectable()); - wi.setRequesterRef(MiscSchemaUtil.createObjectReference(requester.getOid(), SchemaConstants.C_USER_TYPE)); - - wi.setContents(asObjectable(cp.externalizeWorkItemContents(task, variables, result))); - - wi.setTrackingData(asObjectable(getTrackingData(taskExtract, variables, result))); - } catch (SchemaException e) { - throw new SystemException("Got unexpected schema exception when preparing information on Work Item", e); - } catch (ObjectNotFoundException e) { - throw new SystemException("Got unexpected object-not-found exception when preparing information on Work Item; perhaps the requester or a workflow task was deleted in the meantime.", e); - } catch (JAXBException e) { - throw new SystemException("Got unexpected JAXB exception when preparing information on Work Item", e); - } catch (WorkflowException e) { - result.recordFatalError("Couldn't set work item details for activiti task " + task.getId(), e); - throw e; - } - } - result.recordSuccessIfUnknown(); - return wi; - } - - private WorkItemNewType taskToWorkItemNew(Task task, Map processVariables, boolean getAssigneeDetails, - boolean getCandidateDetails, OperationResult parentResult) throws WorkflowException { + private WorkItemNewType taskToWorkItemNew(Task task, Map processVariables, boolean resolveTask, boolean resolveAssignee, + boolean resolveCandidates, OperationResult parentResult) throws WorkflowException { OperationResult result = parentResult.createSubresult(OPERATION_ACTIVITI_TASK_TO_WORK_ITEM); result.addParam("task id", task.getId()); - result.addParam("getAssigneeDetails", getAssigneeDetails); + result.addParam("getAssigneeDetails", resolveAssignee); try { TaskExtract taskExtract = new TaskExtract(task, processVariables); - WorkItemNewType wi = taskExtractToWorkItemNew(taskExtract, getAssigneeDetails, getCandidateDetails, result); + WorkItemNewType wi = taskExtractToWorkItemNew(taskExtract, resolveTask, resolveAssignee, resolveCandidates, result); return wi; } catch (RuntimeException|WorkflowException e) { throw e; @@ -566,66 +398,24 @@ private WorkItemNewType taskToWorkItemNew(Task task, Map process } } - // this method should reside outside activiti-related packages - // we'll deal with it when we implement support for multiple wf providers - public WorkItemType taskEventToWorkItem(TaskEvent taskEvent, boolean getAssigneeDetails, boolean getCandidateDetails, OperationResult parentResult) throws WorkflowException { - OperationResult result = parentResult.createSubresult(OPERATION_ACTIVITI_DELEGATE_TASK_TO_WORK_ITEM); + public WorkItemNewType taskEventToWorkItemNew(TaskEvent taskEvent, Map processVariables, boolean resolveTask, + boolean resolveAssignee, boolean resolveCandidates, OperationResult parentResult) throws WorkflowException { + OperationResult result = parentResult.createSubresult(OPERATION_ACTIVITI_TASK_TO_WORK_ITEM); result.addParam("task id", taskEvent.getTaskId()); - result.addParam("getAssigneeDetails", getAssigneeDetails); - - WorkItemType wi = taskExtractToWorkItem(new TaskExtract(taskEvent), getAssigneeDetails, getCandidateDetails, result); - result.recordSuccessIfUnknown(); - return wi; - } + result.addParam("getAssigneeDetails", resolveAssignee); - private WorkItemType taskExtractToWorkItem(TaskExtract task, boolean getAssigneeDetails, boolean getCandidateDetails, OperationResult result) throws WorkflowException { - WorkItemType wi = prismContext.createObject(WorkItemType.class).asObjectable(); try { - wi.setWorkItemId(task.getId()); - if (task.getAssignee() != null) { - wi.setAssigneeRef(MiscSchemaUtil.createObjectReference(task.getAssignee(), SchemaConstants.C_USER_TYPE)); - } - for (String candidateUser : task.getCandidateUsers()) { - wi.getCandidateUsersRef().add(MiscSchemaUtil.createObjectReference(candidateUser, SchemaConstants.C_USER_TYPE)); - } - for (String candidateGroup : task.getCandidateGroups()) { - wi.getCandidateRolesRef().add(miscDataUtil.groupIdToObjectReference(candidateGroup)); - } - wi.setName(new PolyStringType(task.getName())); - wi.setProcessInstanceId(task.getProcessInstanceId()); - wi.setChangeProcessor((String) task.getVariables().get(CommonProcessVariableNames.VARIABLE_CHANGE_PROCESSOR)); - MetadataType metadataType = new MetadataType(); - metadataType.setCreateTimestamp(XmlTypeConverter.createXMLGregorianCalendar(task.getCreateTime())); - wi.setMetadata(metadataType); - } catch (ActivitiException e) { // not sure if any of the above methods can throw this exception, but for safety we catch it here - result.recordFatalError("Couldn't get information on activiti task " + task.getId(), e); - throw new WorkflowException("Couldn't get information on activiti task " + task.getId(), e); - } - - if (getAssigneeDetails) { - PrismObject assignee = miscDataUtil.getUserByOid(task.getAssignee(), result); - if (assignee != null) { - wi.setAssignee(assignee.asObjectable()); - } - } - if (getCandidateDetails) { - for (ObjectReferenceType ort : wi.getCandidateUsersRef()) { - PrismObject obj = miscDataUtil.getUserByOid(ort.getOid(), result); - if (obj != null) { - wi.getCandidateUsers().add(obj.asObjectable()); - } - } - for (ObjectReferenceType ort : wi.getCandidateRolesRef()) { - PrismObject obj = miscDataUtil.resolveObjectReference(ort, result); - if (obj != null) { - wi.getCandidateRoles().add(obj.asObjectable()); - } - } + TaskExtract taskExtract = new TaskExtract(taskEvent); + WorkItemNewType wi = taskExtractToWorkItemNew(taskExtract, resolveTask, resolveAssignee, resolveCandidates, result); + return wi; + } catch (RuntimeException|WorkflowException e) { + throw e; + } finally { + result.computeStatusIfUnknown(); } - return wi; } - private WorkItemNewType taskExtractToWorkItemNew(TaskExtract task, boolean getAssigneeDetails, boolean getCandidateDetails, OperationResult result) throws WorkflowException { + public WorkItemNewType taskExtractToWorkItemNew(TaskExtract task, boolean resolveTask, boolean resolveAssignee, boolean resolveCandidates, OperationResult result) throws WorkflowException { WorkItemNewType wi = new WorkItemNewType(prismContext); try { final Map variables = task.getVariables(); @@ -636,62 +426,45 @@ private WorkItemNewType taskExtractToWorkItemNew(TaskExtract task, boolean getAs wi.setProcessStartedTimestamp(XmlTypeConverter.createXMLGregorianCalendar((Date) variables.get(CommonProcessVariableNames.VARIABLE_START_TIME))); String taskOid = (String) variables.get(CommonProcessVariableNames.VARIABLE_MIDPOINT_TASK_OID); if (taskOid != null) { - wi.setTaskRef(ObjectTypeUtil.createObjectRef(taskOid, ObjectTypes.TASK)); + wi.setTaskRef(createObjectRef(taskOid, TASK)); + if (resolveTask) { + miscDataUtil.resolveAndStoreObjectReference(wi.getTaskRef(), result); + } } if (task.getAssignee() != null) { - wi.setAssigneeRef(MiscSchemaUtil.createObjectReference(task.getAssignee(), SchemaConstants.C_USER_TYPE)); + wi.setAssigneeRef(createObjectRef(task.getAssignee(), USER)); + if (resolveAssignee) { + miscDataUtil.resolveAndStoreObjectReference(wi.getAssigneeRef(), result); + } } for (String candidateUser : task.getCandidateUsers()) { - wi.getCandidateUsersRef().add(MiscSchemaUtil.createObjectReference(candidateUser, SchemaConstants.C_USER_TYPE)); + wi.getCandidateUsersRef().add(createObjectRef(candidateUser, USER)); + if (resolveCandidates) { + for (ObjectReferenceType ref : wi.getCandidateUsersRef()) { + miscDataUtil.resolveAndStoreObjectReference(ref, result); + } + } } for (String candidateGroup : task.getCandidateGroups()) { wi.getCandidateRolesRef().add(miscDataUtil.groupIdToObjectReference(candidateGroup)); + if (resolveCandidates) { + for (ObjectReferenceType ref : wi.getCandidateRolesRef()) { + miscDataUtil.resolveAndStoreObjectReference(ref, result); + } + } } wi.setObjectRef(WfUtil.toObjectReferenceType((LightweightObjectRef) variables.get(CommonProcessVariableNames.VARIABLE_OBJECT_REF))); wi.setTargetRef(WfUtil.toObjectReferenceType((LightweightObjectRef) variables.get(CommonProcessVariableNames.VARIABLE_TARGET_REF))); + + ProcessMidPointInterface pmi = processInterfaceFinder.getProcessInterface(variables); + wi.setDecision(pmi.extractDecision(variables)); + } catch (ActivitiException e) { // not sure if any of the above methods can throw this exception, but for safety we catch it here throw new WorkflowException("Couldn't get information on activiti task " + task.getId(), e); } return wi; } - private T asObjectable(PrismObject prismObject) { - return prismObject != null ? prismObject.asObjectable() : null; - } - - private ChangeProcessor getChangeProcessor(TaskExtract task, Map variables) { - String cpClassName = (String) variables.get(CommonProcessVariableNames.VARIABLE_CHANGE_PROCESSOR); - if (cpClassName == null) { - throw new IllegalStateException("Change processor is unknown for task: " + task); - } - - return wfConfiguration.findChangeProcessor(cpClassName); - } - - private PrismObject getTrackingData(TaskExtract task, Map variables, OperationResult result) throws ObjectNotFoundException, SchemaException { - ProcessInstanceQuery piq = activitiEngine.getRuntimeService().createProcessInstanceQuery(); - piq.processInstanceId(task.getProcessInstanceId()); - org.activiti.engine.runtime.ProcessInstance processInstance = piq.singleResult(); - - PrismObjectDefinition formDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByType(TrackingDataType.COMPLEX_TYPE); - PrismObject formPrism = formDefinition.instantiate(); - TrackingDataType form = formPrism.asObjectable(); - - form.setTaskId(task.getId()); - form.setProcessInstanceId(task.getProcessInstanceId()); - form.setTaskAssignee(task.getAssignee()); - form.setTaskOwner(task.getOwner()); - //form.setTaskCandidates(getCandidatesAsString(task)); - form.setExecutionId(task.getExecutionId()); - form.setProcessDefinitionId(processInstance.getProcessDefinitionId()); - form.setShadowTaskOid((String) variables.get(CommonProcessVariableNames.VARIABLE_MIDPOINT_TASK_OID)); - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Resulting prism object instance = " + formPrism.debugDump()); - } - return formPrism; - } - // private List getCandidates(TaskExtract task) { // // List retval = new ArrayList(); diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/ProcessInstruction.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/ProcessInstruction.java new file mode 100644 index 00000000000..4fa3aff4582 --- /dev/null +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/ProcessInstruction.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2010-2016 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.wf.impl.jobs; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfProcessSpecificStateType; + +import java.util.Map; + +/** + * @author Pavol + */ +public interface ProcessInstruction { + + void createProcessVariables(Map map, PrismContext prismContext); + + WfProcessSpecificStateType createProcessSpecificState(); +} diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/ProcessorInstruction.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/ProcessorInstruction.java new file mode 100644 index 00000000000..19cae969501 --- /dev/null +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/ProcessorInstruction.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2010-2016 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.wf.impl.jobs; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfProcessorSpecificStateType; + +import java.util.Map; + +/** + * @author mederly + */ +public interface ProcessorInstruction { + + WfProcessorSpecificStateType createProcessorSpecificState(); + void createProcessVariables(Map map, PrismContext prismContext) throws SchemaException; +} diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTask.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTask.java index 6730a1ea019..3223455e927 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTask.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTask.java @@ -2,7 +2,9 @@ import com.evolveum.midpoint.model.api.context.ModelContext; import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; +import com.evolveum.midpoint.prism.xml.XmlTypeConverter; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.task.api.TaskExecutionStatus; @@ -13,14 +15,20 @@ import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.wf.impl.processors.ChangeProcessor; import com.evolveum.midpoint.wf.impl.processors.primary.ObjectTreeDeltas; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import org.apache.commons.lang3.Validate; +import javax.xml.datatype.XMLGregorianCalendar; import java.util.ArrayList; +import java.util.Date; import java.util.List; import static com.evolveum.midpoint.task.api.TaskExecutionStatus.WAITING; import static com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType.F_WORKFLOW_CONTEXT; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.WfContextType.F_END_TIMESTAMP; +import static com.evolveum.midpoint.xml.ns._public.common.common_3.WfContextType.F_PROCESS_INSTANCE_ID; import static com.evolveum.midpoint.xml.ns._public.common.common_3.WfContextType.F_STATE; /** @@ -35,7 +43,7 @@ public class WfTask { private WfTaskController wfTaskController; private Task task; // must be non-null - private String activitiId; // must be non-null for Activiti-related jobs (and may be filled-in later, when activiti process is started) + private String processInstanceId; // must be non-null for Activiti-related jobs (and may be filled-in later, when activiti process is started) private ChangeProcessor changeProcessor; // must be non-null //region Constructors and basic getters @@ -43,24 +51,24 @@ public class WfTask { this(wfTaskController, task, null, changeProcessor); } - WfTask(WfTaskController wfTaskController, Task task, String activitiId, ChangeProcessor changeProcessor) { + protected WfTask(WfTaskController wfTaskController, Task task, String processInstanceId, ChangeProcessor changeProcessor) { Validate.notNull(task, "Task"); Validate.notNull(changeProcessor, "Change processor"); this.wfTaskController = wfTaskController; this.task = task; - this.activitiId = activitiId; + this.processInstanceId = processInstanceId; this.changeProcessor = changeProcessor; } protected WfTask(WfTask original) { this.wfTaskController = original.wfTaskController; this.task = original.task; - this.activitiId = original.activitiId; + this.processInstanceId = original.processInstanceId; this.changeProcessor = original.changeProcessor; } - public String getActivitiId() { - return activitiId; + public String getProcessInstanceId() { + return processInstanceId; } public Task getTask() { @@ -77,7 +85,7 @@ public ChangeProcessor getChangeProcessor() { public String toString() { return "WfTask{" + "task=" + task + - ", activitiId='" + activitiId + '\'' + + ", processInstanceId='" + processInstanceId + '\'' + ", changeProcessor=" + changeProcessor + '}'; } @@ -99,13 +107,19 @@ public void startWaitingForSubtasks(OperationResult result) throws SchemaExcepti } public void setWfProcessId(String pid) throws SchemaException { - activitiId = pid; - wfTaskController.getWfTaskUtil().setWfProcessId(task, pid); + processInstanceId = pid; + task.addModification( + DeltaBuilder.deltaFor(TaskType.class, getPrismContext()) + .item(F_WORKFLOW_CONTEXT, F_PROCESS_INSTANCE_ID).replace(pid) + .asItemDelta()); } - public void setProcessInstanceFinishedImmediate(OperationResult result) - throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { - wfTaskController.getWfTaskUtil().setProcessInstanceFinishedImmediate(task, result); + public void setProcessInstanceEndTimestamp() throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { + XMLGregorianCalendar now = XmlTypeConverter.createXMLGregorianCalendar(new Date()); + task.addModification( + DeltaBuilder.deltaFor(TaskType.class, getPrismContext()) + .item(F_WORKFLOW_CONTEXT, F_END_TIMESTAMP).replace(now) + .asItemDelta()); } public TaskExecutionStatus getTaskExecutionStatus() { @@ -139,7 +153,7 @@ private WfTaskUtil getWfTaskUtil() { } public ModelContext retrieveModelContext(OperationResult result) throws SchemaException, ObjectNotFoundException, CommunicationException, ConfigurationException { - return getWfTaskUtil().retrieveModelContext(task, result); + return getWfTaskUtil().getModelContext(task, result); } public List listChildren(OperationResult result) throws SchemaException { @@ -155,7 +169,7 @@ public ObjectTreeDeltas retrieveResultingDeltas() throws SchemaException { } public void deleteModelOperationContext(OperationResult result) throws SchemaException, ObjectNotFoundException { - getWfTaskUtil().deleteModelOperationContext(task, result); + getWfTaskUtil().deleteModelOperationContext(task); } public void storeModelContext(ModelContext modelContext) throws SchemaException { @@ -190,4 +204,20 @@ void setProcessInstanceState(String stateDescription) throws SchemaException { private PrismContext getPrismContext() { return wfTaskController.getPrismContext(); } + + public String getProcessInstanceName() { + return task.getWorkflowContext() != null ? task.getWorkflowContext().getProcessInstanceName() : null; + } + + public String getAnswer() { + return task.getWorkflowContext() != null ? task.getWorkflowContext().getAnswer() : null; + } + + public PrismObject getRequesterIfExists(OperationResult result) { + if (task.getWorkflowContext() == null || task.getWorkflowContext().getRequesterRef() == null) { + return null; + } + ObjectReferenceType requesterRef = task.getWorkflowContext().getRequesterRef(); + return wfTaskController.getMiscDataUtil().resolveAndStoreObjectReference(requesterRef, result); + } } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskController.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskController.java index 3b912aa5163..f0af18c650c 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskController.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskController.java @@ -19,16 +19,11 @@ import com.evolveum.midpoint.audit.api.AuditEventRecord; import com.evolveum.midpoint.audit.api.AuditEventStage; import com.evolveum.midpoint.audit.api.AuditService; -import com.evolveum.midpoint.model.impl.controller.ModelOperationTaskHandler; -import com.evolveum.midpoint.model.impl.lens.LensContext; -import com.evolveum.midpoint.prism.Item; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.task.api.TaskCategory; -import com.evolveum.midpoint.task.api.TaskExecutionStatus; import com.evolveum.midpoint.task.api.TaskManager; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; @@ -42,14 +37,16 @@ import com.evolveum.midpoint.wf.api.WorkflowException; import com.evolveum.midpoint.wf.impl.WfConfiguration; import com.evolveum.midpoint.wf.impl.activiti.ActivitiInterface; -import com.evolveum.midpoint.wf.impl.activiti.dao.WorkItemProvider; import com.evolveum.midpoint.wf.impl.messages.*; import com.evolveum.midpoint.wf.impl.processes.ProcessInterfaceFinder; import com.evolveum.midpoint.wf.impl.processes.ProcessMidPointInterface; import com.evolveum.midpoint.wf.impl.processes.common.CommonProcessVariableNames; import com.evolveum.midpoint.wf.impl.processors.ChangeProcessor; +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.model.workflow.process_instance_state_3.ProcessInstanceState; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType; import org.apache.commons.lang.Validate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -66,8 +63,6 @@ * * This class provides a facade over ugly mess of code managing activiti + task pair describing a workflow process instance. * - * For working with tasks only (e.g. not touching Job structure) it uses wfTaskUtil. - * * @author mederly */ @Component @@ -75,7 +70,7 @@ public class WfTaskController { private static final Trace LOGGER = TraceManager.getTrace(WfTaskController.class); - private static final long TASK_START_DELAY = 5000L; + public static final long TASK_START_DELAY = 5000L; private static final Object DOT_CLASS = WfTaskController.class.getName() + "."; private Set processListeners = new HashSet<>(); @@ -107,9 +102,6 @@ public class WfTaskController { @Autowired private WfConfiguration wfConfiguration; - @Autowired - private WorkItemProvider workItemProvider; - @Autowired private PrismContext prismContext; //endregion @@ -133,13 +125,11 @@ public WfTask createWfTask(WfTaskCreationInstruction instruction, WfTask parentW * @param parentTask the task that will be the parent of the task of newly created job; it may be null */ public WfTask createWfTask(WfTaskCreationInstruction instruction, Task parentTask, OperationResult result) throws SchemaException, ObjectNotFoundException { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Processing start instruction: " + instruction.debugDump()); + LOGGER.trace("Processing start instruction:\n{}", instruction.debugDump()); } - Task task = createBackgroundTask(instruction, parentTask, result); - WfTask wfTask = new WfTask(this, task, instruction.getChangeProcessor()); + WfTask wfTask = recreateWfTask(task, instruction.getChangeProcessor()); if (!instruction.isNoProcess()) { startWorkflowProcessInstance(wfTask, instruction, result); } @@ -153,7 +143,16 @@ public WfTask createWfTask(WfTaskCreationInstruction instruction, Task parentTas * @return recreated job */ public WfTask recreateWfTask(Task task) { - return new WfTask(this, task, wfTaskUtil.getProcessId(task), wfTaskUtil.getChangeProcessor(task)); + return recreateWfTask(task, wfTaskUtil.getChangeProcessor(task)); + } + + public WfTask recreateWfTask(Task task, ChangeProcessor changeProcessor) { + String processInstanceId = wfTaskUtil.getProcessId(task); + if (changeProcessor instanceof PrimaryChangeProcessor) { + return new PcpWfTask(this, task, processInstanceId, changeProcessor); + } else { + return new WfTask(this, task, processInstanceId, changeProcessor); + } } /** @@ -178,65 +177,12 @@ public WfTask recreateRootWfTask(Task task) { //region Working with midPoint tasks private Task createBackgroundTask(WfTaskCreationInstruction instruction, Task parentTask, OperationResult result) throws SchemaException, ObjectNotFoundException { - - ChangeProcessor changeProcessor = instruction.getChangeProcessor(); - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("createBackgroundTask starting; parent task = " + parentTask); - } - - Task task; - if (parentTask != null) { - task = parentTask.createSubtask(); - } else { - task = taskManager.createTaskInstance(); - wfTaskUtil.setTaskOwner(task, instruction.getTaskOwner()); - } - - // initial execution state - if (instruction.isCreateTaskAsSuspended() && instruction.isCreateTaskAsWaiting()) { - throw new IllegalStateException("Both createSuspended and createWaiting attributes are set to TRUE."); - } - if (instruction.isCreateTaskAsSuspended()) { - task.setInitialExecutionStatus(TaskExecutionStatus.SUSPENDED); - } else if (instruction.isCreateTaskAsWaiting()) { - task.setInitialExecutionStatus(WAITING); - } - - if (instruction.getTaskObject() != null) { - task.setObjectRef(instruction.getTaskObject().getOid(), instruction.getTaskObject().getDefinition().getTypeName()); - } else if (parentTask != null && parentTask.getObjectRef() != null) { - task.setObjectRef(parentTask.getObjectRef()); - } - wfTaskUtil.setChangeProcessor(task, changeProcessor); - wfTaskUtil.setTaskNameIfEmpty(task, instruction.getTaskName()); - wfTaskUtil.setDefaultTaskOwnerIfEmpty(task, result, this); - task.setCategory(TaskCategory.WORKFLOW); - - // push the handlers, beginning with these that should execute last - wfTaskUtil.pushHandlers(task, instruction.getHandlersAfterModelOperation()); - if (instruction.isExecuteModelOperationHandler()) { - task.pushHandlerUri(ModelOperationTaskHandler.MODEL_OPERATION_TASK_URI, null, null); - } - wfTaskUtil.pushHandlers(task, instruction.getHandlersBeforeModelOperation()); - wfTaskUtil.pushHandlers(task, instruction.getHandlersAfterWfProcess()); - if (instruction.startsWorkflowProcess()) { - wfTaskUtil.pushProcessShadowHandler(instruction.isSimple(), task, TASK_START_DELAY, result); - } - - // put model context + task variables - if (instruction.getTaskModelContext() != null) { - task.setModelOperationContext(((LensContext) instruction.getTaskModelContext()).toLensContextType()); - } - instruction.tailorTask(task); - + Task wfTask = instruction.createTask(this, parentTask); if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Saving workflow monitoring/execution task: " + task.debugDump()); + LOGGER.trace("Switching workflow root or child task to background:\n{}", wfTask.debugDump()); } - - taskManager.switchToBackground(task, result); - - return task; + taskManager.switchToBackground(wfTask, result); + return wfTask; } /** @@ -266,25 +212,22 @@ public void unpauseTask(WfTask wfTask, OperationResult result) throws SchemaExce //region Working with Activiti process instances private void startWorkflowProcessInstance(WfTask wfTask, WfTaskCreationInstruction instruction, OperationResult parentResult) { - - OperationResult result = parentResult.createSubresult(DOT_CLASS + ".startWorkflowProcessInstance"); - + OperationResult result = parentResult.createSubresult(DOT_CLASS + "startWorkflowProcessInstance"); try { LOGGER.trace("startWorkflowProcessInstance starting; instruction = {}", instruction); - Task task = wfTask.getTask(); StartProcessCommand spc = new StartProcessCommand(); - spc.setTaskOid(task.getOid()); - spc.setProcessName(instruction.getProcessDefinitionKey()); + spc.setProcessName(instruction.getProcessName()); spc.setProcessInstanceName(instruction.getProcessInstanceName()); spc.setSendStartConfirmation(instruction.isSendStartConfirmation()); - spc.setVariablesFrom(instruction.getProcessVariables()); + spc.setVariablesFrom(instruction.getAllProcessVariables()); + spc.addVariable(CommonProcessVariableNames.VARIABLE_MIDPOINT_TASK_OID, task.getOid()); spc.setProcessOwner(task.getOwner().getOid()); activitiInterface.startActivitiProcessInstance(spc, task, result); - auditProcessStart(spc, wfTask, result); - notifyProcessStart(spc, wfTask, result); + auditProcessStart(wfTask, spc.getVariables(), result); + notifyProcessStart(wfTask, spc.getVariables(), result); } catch (SchemaException|RuntimeException|ObjectNotFoundException|ObjectAlreadyExistsException e) { LoggingUtils.logUnexpectedException(LOGGER, "Couldn't send a request to start a process instance to workflow management system", e); try { @@ -297,7 +240,6 @@ private void startWorkflowProcessInstance(WfTask wfTask, WfTaskCreationInstructi } finally { result.computeStatusIfUnknown(); } - LOGGER.trace("startWorkflowProcessInstance finished"); } @@ -307,7 +249,7 @@ public void onProcessEvent(ProcessEvent event, Task task, OperationResult result LOGGER.trace("Updating instance state and activiti process instance ID in task {}", task); - if (wfTask.getActivitiId() == null) { + if (wfTask.getProcessInstanceId() == null) { wfTask.setWfProcessId(event.getPid()); } @@ -337,10 +279,11 @@ private void onProcessFinishedEvent(ProcessEvent event, WfTask wfTask, Operation LOGGER.trace("onProcessFinishedEvent starting"); LOGGER.trace("Calling onProcessEnd on {}", wfTask.getChangeProcessor()); wfTask.getChangeProcessor().onProcessEnd(event, wfTask, result); - wfTask.setProcessInstanceFinishedImmediate(result); + wfTask.setProcessInstanceEndTimestamp(); + wfTask.commitChanges(result); - auditProcessEnd(event, wfTask, result); - notifyProcessEnd(event, wfTask, result); + auditProcessEnd(wfTask, event, result); + notifyProcessEnd(wfTask, event, result); // passive tasks can be 'let go' at this point if (wfTask.getTaskExecutionStatus() == WAITING) { @@ -363,29 +306,30 @@ private ChangeProcessor getChangeProcessor(TaskEvent taskEvent) { //endregion //region Processing work item (task) events - public void onTaskEvent(TaskEvent taskEvent, OperationResult result) throws WorkflowException { - // auditing & notifications + // workItem contains taskRef, assignee, candidates resolved (if possible) + public void onTaskEvent(WorkItemNewType workItem, TaskEvent taskEvent, OperationResult result) throws WorkflowException, SchemaException { + + final TaskType shadowTaskType = (TaskType) ObjectTypeUtil.getObjectFromReference(workItem.getTaskRef()); + if (shadowTaskType == null) { + LOGGER.warn("No task in workItem " + workItem + ", audit and notifications couldn't be performed."); + return; + } + final Task shadowTask = taskManager.createTaskInstance(shadowTaskType.asPrismObject(), result); + final WfTask wfTask = recreateWfTask(shadowTask); + + // auditing & notifications if (taskEvent instanceof TaskCreatedEvent) { - auditWorkItemEvent(taskEvent, AuditEventStage.REQUEST, result); + auditWorkItemEvent(workItem, wfTask, taskEvent, AuditEventStage.REQUEST, result); try { - notifyWorkItemCreated( - taskEvent.getTaskName(), - taskEvent.getAssigneeOid(), - taskEvent.getProcessInstanceName(), - taskEvent.getVariables()); + notifyWorkItemCreated(workItem, wfTask, result); } catch (SchemaException e) { LoggingUtils.logUnexpectedException(LOGGER, "Couldn't send notification about work item create event", e); } } else if (taskEvent instanceof TaskCompletedEvent) { - auditWorkItemEvent(taskEvent, AuditEventStage.EXECUTION, result); + auditWorkItemEvent(workItem, wfTask, taskEvent, AuditEventStage.EXECUTION, result); try { - notifyWorkItemCompleted( - taskEvent.getTaskName(), - taskEvent.getAssigneeOid(), - taskEvent.getProcessInstanceName(), - taskEvent.getVariables(), - (String) taskEvent.getVariables().get(CommonProcessVariableNames.FORM_FIELD_DECISION)); + notifyWorkItemCompleted(workItem, wfTask, result); } catch (SchemaException e) { LoggingUtils.logUnexpectedException(LOGGER, "Couldn't audit work item complete event", e); } @@ -394,86 +338,56 @@ public void onTaskEvent(TaskEvent taskEvent, OperationResult result) throws Work //endregion //region Auditing and notifications - private void auditProcessStart(StartProcessCommand spc, WfTask wfTask, OperationResult result) { - auditProcessStartEnd(spc.getVariables(), wfTask, AuditEventStage.REQUEST, result); + private void auditProcessStart(WfTask wfTask, Map variables, OperationResult result) { + auditProcessStartEnd(wfTask, AuditEventStage.REQUEST, variables, result); } - private void auditProcessEnd(ProcessEvent event, WfTask wfTask, OperationResult result) { - auditProcessStartEnd(event.getVariables(), wfTask, AuditEventStage.EXECUTION, result); + private void auditProcessEnd(WfTask wfTask, ProcessEvent event, OperationResult result) { + auditProcessStartEnd(wfTask, AuditEventStage.EXECUTION, event.getVariables(), result); } - private void auditProcessStartEnd(Map variables, WfTask wfTask, AuditEventStage stage, OperationResult result) { - AuditEventRecord auditEventRecord = getChangeProcessor(variables).prepareProcessInstanceAuditRecord(variables, wfTask, stage, result); + private void auditProcessStartEnd(WfTask wfTask, AuditEventStage stage, Map variables, OperationResult result) { + AuditEventRecord auditEventRecord = wfTask.getChangeProcessor().prepareProcessInstanceAuditRecord(wfTask, stage, variables, result); auditService.audit(auditEventRecord, wfTask.getTask()); } - private void notifyProcessStart(StartProcessCommand spc, WfTask wfTask, OperationResult result) throws SchemaException { - PrismObject state = wfTask.getChangeProcessor().externalizeProcessInstanceState(spc.getVariables()); + private void notifyProcessStart(WfTask wfTask, Map variables, OperationResult result) throws SchemaException { for (ProcessListener processListener : processListeners) { - processListener.onProcessInstanceStart(state, result); + processListener.onProcessInstanceStart(wfTask.getTask(), result); } } - private void notifyProcessEnd(ProcessEvent event, WfTask wfTask, OperationResult result) throws SchemaException { - PrismObject state = wfTask.getChangeProcessor().externalizeProcessInstanceState(event.getVariables()); + private void notifyProcessEnd(WfTask wfTask, ProcessEvent event, OperationResult result) throws SchemaException { for (ProcessListener processListener : processListeners) { - processListener.onProcessInstanceEnd(state, result); + processListener.onProcessInstanceEnd(wfTask.getTask(), result); } } - private void notifyWorkItemCreated(String workItemName, String assigneeOid, String processInstanceName, Map processVariables) throws SchemaException { - ChangeProcessor cp = getChangeProcessor(processVariables); - PrismObject state = cp.externalizeProcessInstanceState(processVariables); + private void notifyWorkItemCreated(WorkItemNewType workItem, WfTask wfTask, OperationResult result) throws SchemaException { for (WorkItemListener workItemListener : workItemListeners) { - workItemListener.onWorkItemCreation(workItemName, assigneeOid, state); + workItemListener.onWorkItemCreation(workItem, wfTask.getTask(), result); } } - private void notifyWorkItemCompleted(String workItemName, String assigneeOid, String processInstanceName, Map processVariables, String decision) throws SchemaException { - ChangeProcessor cp = getChangeProcessor(processVariables); - PrismObject state = cp.externalizeProcessInstanceState(processVariables); + private void notifyWorkItemCompleted(WorkItemNewType workItem, WfTask wfTask, OperationResult result) throws SchemaException { for (WorkItemListener workItemListener : workItemListeners) { - workItemListener.onWorkItemCompletion(workItemName, assigneeOid, state, decision); + workItemListener.onWorkItemCompletion(workItem, wfTask.getTask(), result); } } - private void auditWorkItemEvent(TaskEvent taskEvent, AuditEventStage stage, OperationResult result) throws WorkflowException { - - Task shadowTask; - try { - String taskOid = (String) taskEvent.getVariables().get(CommonProcessVariableNames.VARIABLE_MIDPOINT_TASK_OID); - if (taskOid == null) { - LOGGER.error("Shadow task OID is unknown for work item " + taskEvent.getDebugName() + ", no audit record will be produced."); - return; - } - shadowTask = taskManager.getTask(taskOid, result); - } catch (SchemaException e) { - LoggingUtils.logException(LOGGER, "Couldn't retrieve workflow-related task", e); - return; - } catch (ObjectNotFoundException e) { - LoggingUtils.logException(LOGGER, "Couldn't retrieve workflow-related task", e); - return; - } - - AuditEventRecord auditEventRecord = getChangeProcessor(taskEvent).prepareWorkItemAuditRecord(taskEvent, stage, result); - auditService.audit(auditEventRecord, shadowTask); + // workItem contains taskRef, assignee, candidates resolved (if possible) + private void auditWorkItemEvent(WorkItemNewType workItem, WfTask wfTask, TaskEvent taskEvent, AuditEventStage stage, OperationResult result) throws WorkflowException { + AuditEventRecord auditEventRecord = getChangeProcessor(taskEvent).prepareWorkItemAuditRecord(workItem, wfTask, taskEvent, stage, result); + auditService.audit(auditEventRecord, wfTask.getTask()); } -// private String getDebugName(WorkItemType workItemType) { -// return workItemType.getName() + " (id " + workItemType.getWorkItemId() + ")"; -// } - public void registerProcessListener(ProcessListener processListener) { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Registering process listener " + processListener); - } + LOGGER.trace("Registering process listener {}", processListener); processListeners.add(processListener); } public void registerWorkItemListener(WorkItemListener workItemListener) { - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Registering work item listener " + workItemListener); - } + LOGGER.trace("Registering work item listener {}", workItemListener); workItemListeners.add(workItemListener); } //endregion @@ -483,9 +397,21 @@ public WfTaskUtil getWfTaskUtil() { return wfTaskUtil; } - public PrismContext getPrismContext() { + public MiscDataUtil getMiscDataUtil() { + return miscDataUtil; + } + + public PrismContext getPrismContext() { return prismContext; } - //endregion + public TaskManager getTaskManager() { + return taskManager; + } + + public WfConfiguration getWfConfiguration() { + return wfConfiguration; + } + + //endregion } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskCreationInstruction.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskCreationInstruction.java index 00d5d398b73..94837c2c8c4 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskCreationInstruction.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskCreationInstruction.java @@ -17,125 +17,112 @@ package com.evolveum.midpoint.wf.impl.jobs; import com.evolveum.midpoint.model.api.context.ModelContext; -import com.evolveum.midpoint.prism.Item; +import com.evolveum.midpoint.model.impl.controller.ModelOperationTaskHandler; +import com.evolveum.midpoint.model.impl.lens.LensContext; +import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.PrismPropertyDefinition; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.task.api.TaskBinding; -import com.evolveum.midpoint.task.api.TaskRecurrence; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; +import com.evolveum.midpoint.task.api.*; import com.evolveum.midpoint.util.DebugDumpable; import com.evolveum.midpoint.util.DebugUtil; +import com.evolveum.midpoint.util.MiscUtil; import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.logging.Trace; +import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.wf.impl.processes.ProcessMidPointInterface; import com.evolveum.midpoint.wf.impl.processes.common.ActivitiUtil; +import com.evolveum.midpoint.wf.impl.processes.common.CommonProcessVariableNames; +import com.evolveum.midpoint.wf.impl.processes.common.LightweightObjectRef; import com.evolveum.midpoint.wf.impl.processes.common.LightweightObjectRefImpl; import com.evolveum.midpoint.wf.impl.processors.ChangeProcessor; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ScheduleType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UriStackEntry; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.midpoint.wf.impl.util.MiscDataUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; import org.apache.commons.lang.Validate; -import javax.xml.namespace.QName; -import java.io.Serializable; import java.util.*; +import static com.evolveum.midpoint.prism.xml.XmlTypeConverter.createXMLGregorianCalendar; import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.createObjectRef; import static com.evolveum.midpoint.wf.impl.processes.common.CommonProcessVariableNames.*; /** - * A generic instruction to start a workflow process and/or a task (using umbrella term "a job"). - * May be subclassed in order to add further information. + * A generic instruction to start a background task; with or without a workflow process instance. + * May be subclassed in order to add further functionality. * * @author mederly */ -public class WfTaskCreationInstruction implements DebugDumpable { +public class WfTaskCreationInstruction implements DebugDumpable { - private ChangeProcessor changeProcessor; + private static final Trace LOGGER = TraceManager.getTrace(WfTaskCreationInstruction.class); - private String processDefinitionKey; // name of wf process to be started (e.g. ItemApproval) - private String processInstanceName; + private final ChangeProcessor changeProcessor; + + private final WfContextType wfContext = new WfContextType(); // workflow context to be put into the task + private ModelContext taskModelContext; // model context to be put into the task + + private final Date processCreationTimestamp = new Date(); + + protected final PRI processorInstruction; + private final PCI processInstruction; - private Map processVariables = new HashMap<>(); // values of process variables - private ModelContext taskModelContext; // model context to be put into the task private PrismObject taskObject; // object to be attached to the task; this object must have its definition available private PrismObject taskOwner; // if null, owner from parent task will be taken (if there's no parent task, exception will be thrown) private PolyStringType taskName; // name of task to be created/updated (applies only if the task has no name already) - e.g. "Approve adding role R to U" - private boolean executeModelOperationHandler; // should the job contain model operation to be executed? - private boolean noProcess; // should the job provide no wf process (only direct execution of model operation)? + private boolean executeModelOperationHandler; // should the task contain model operation to be executed? + private boolean noProcess; // should the task provide no wf process (only direct execution of model operation)? - private boolean simple; // is workflow task simple? (i.e. such that requires periodic watching of its state) + private boolean simple; // is workflow process simple? (i.e. such that requires periodic watching of its state) private boolean sendStartConfirmation = true; // should we send explicit "process started" event when the process was started by midPoint? // for listener-enabled processes this can be misleading, because "process started" event could come // after "process finished" one (for immediately-finishing processes) // // unfortunately, it seems we have to live with this (unless we define a "process started" listener) - private boolean createTaskAsSuspended; // should the task be created in SUSPENDED state? - private boolean createTaskAsWaiting; // should the task be created in WAITING state? + private TaskExecutionStatus taskInitialState = TaskExecutionStatus.RUNNABLE; // what should be executed at a given occasion (in the order of being in this list) - private List handlersAfterModelOperation = new ArrayList<>(); - private List handlersBeforeModelOperation = new ArrayList<>(); - private List handlersAfterWfProcess = new ArrayList<>(); + private final List handlersAfterModelOperation = new ArrayList<>(); + private final List handlersBeforeModelOperation = new ArrayList<>(); + private final List handlersAfterWfProcess = new ArrayList<>(); //region Constructors - protected WfTaskCreationInstruction(ChangeProcessor changeProcessor) { + protected WfTaskCreationInstruction(ChangeProcessor changeProcessor, PRI processorInstruction, PCI processInstruction) { Validate.notNull(changeProcessor); this.changeProcessor = changeProcessor; + this.processorInstruction = processorInstruction; + this.processInstruction = processInstruction; } - protected WfTaskCreationInstruction(WfTask parentWfTask) { - this(parentWfTask.getChangeProcessor()); - } - - public static WfTaskCreationInstruction createModelOperationRootJob(ChangeProcessor changeProcessor, ModelContext modelContext) throws SchemaException { - WfTaskCreationInstruction instruction = new WfTaskCreationInstruction(changeProcessor); + public static WfTaskCreationInstruction createModelOnly(ChangeProcessor changeProcessor, ModelContext modelContext) throws SchemaException { + WfTaskCreationInstruction instruction = new WfTaskCreationInstruction(changeProcessor, null, null); instruction.setNoProcess(true); - instruction.addTaskModelContext(modelContext); + instruction.setTaskModelContext(modelContext); instruction.setExecuteModelOperationHandler(true); return instruction; } - public static WfTaskCreationInstruction createNoModelOperationRootJob(ChangeProcessor changeProcessor) throws SchemaException { - WfTaskCreationInstruction instruction = new WfTaskCreationInstruction(changeProcessor); - instruction.setNoProcess(true); - instruction.setExecuteModelOperationHandler(false); + public static WfTaskCreationInstruction createWfOnly(ChangeProcessor changeProcessor, + ProcessorInstruction processorInstruction, ProcessInstruction processInstruction) { + WfTaskCreationInstruction instruction = new WfTaskCreationInstruction(changeProcessor, processorInstruction, processInstruction); return instruction; } - public static WfTaskCreationInstruction createWfProcessChildJob(ChangeProcessor changeProcessor) { - WfTaskCreationInstruction jci = new WfTaskCreationInstruction(changeProcessor); - prepareWfProcessChildJobInternal(jci); - return jci; - } + public static WfTaskCreationInstruction createEmpty(ChangeProcessor changeProcessor) throws SchemaException { + WfTaskCreationInstruction instruction = new WfTaskCreationInstruction(changeProcessor, null, null); + instruction.setNoProcess(true); + return instruction; + } + //endregion - public static WfTaskCreationInstruction createWfProcessChildJob(WfTask parentWfTask) { - WfTaskCreationInstruction jci = new WfTaskCreationInstruction(parentWfTask); - prepareWfProcessChildJobInternal(jci); - return jci; - } + // region Getters and setters + public ChangeProcessor getChangeProcessor() { + return changeProcessor; + } - protected static void prepareWfProcessChildJobInternal(WfTaskCreationInstruction instruction) { - instruction.setNoProcess(false); - instruction.initializeCommonProcessVariables(); - } - - public static WfTaskCreationInstruction createModelOperationChildJob(WfTask parentWfTask, ModelContext modelContext) throws SchemaException { - WfTaskCreationInstruction instruction = new WfTaskCreationInstruction(parentWfTask); - instruction.setNoProcess(true); - instruction.addTaskModelContext(modelContext); - instruction.setExecuteModelOperationHandler(true); - return instruction; - } - //endregion - - // region Simple getters and setters - public boolean isSimple() { - return simple; - } + protected PrismContext getPrismContext() { return changeProcessor.getPrismContext(); } public void setSimple(boolean simple) { this.simple = simple; @@ -149,37 +136,21 @@ public void setSendStartConfirmation(boolean sendStartConfirmation) { this.sendStartConfirmation = sendStartConfirmation; } - public void setProcessDefinitionKey(String name) { - processDefinitionKey = name; - } + public String getProcessName() { + return wfContext.getProcessName(); + } - public String getProcessDefinitionKey() { - return processDefinitionKey; + public void setProcessName(String name) { + wfContext.setProcessName(name); } public String getProcessInstanceName() { - return processInstanceName; - } - - public Map getProcessVariables() { - return Collections.unmodifiableMap(processVariables); - } - - public void addProcessVariable(String name, Serializable value) { - processVariables.put(name, value); - } - - protected void removeProcessVariable(String name) { - processVariables.remove(name); + return wfContext.getProcessInstanceName(); } - public PolyStringType getTaskName() { - return taskName; - } - - public void setTaskName(PolyStringType taskName) { - this.taskName = taskName; - } + public void setProcessInstanceName(String name) { + wfContext.setProcessInstanceName(name); + } public void setTaskName(String taskName) { this.taskName = new PolyStringType(taskName); @@ -197,15 +168,15 @@ public void setNoProcess(boolean noProcess) { this.noProcess = noProcess; } - public void setCreateTaskAsSuspended(boolean createTaskAsSuspended) { - this.createTaskAsSuspended = createTaskAsSuspended; + public void setCreateTaskAsSuspended() { + this.taskInitialState = TaskExecutionStatus.SUSPENDED; } - public boolean isCreateTaskAsSuspended() { - return createTaskAsSuspended; - } + public void setCreateTaskAsWaiting() { + this.taskInitialState = TaskExecutionStatus.WAITING; + } - public List getHandlersAfterModelOperation() { + public List getHandlersAfterModelOperation() { return handlersAfterModelOperation; } @@ -217,138 +188,103 @@ public List getHandlersAfterWfProcess() { return handlersAfterWfProcess; } - public void setExecuteModelOperationHandler(boolean executeModelOperationHandler) { + public void setHandlersBeforeModelOperation(String... handlerUri) { + setHandlers(handlersBeforeModelOperation, createUriStackEntries(handlerUri)); + } + + public void setHandlersAfterModelOperation(String... handlerUri) { + setHandlers(handlersAfterModelOperation, createUriStackEntries(handlerUri)); + } + + public void setHandlersAfterWfProcess(String... handlerUri) { + setHandlers(handlersAfterWfProcess, createUriStackEntries(handlerUri)); + } + + public void addHandlersAfterWfProcessAtEnd(String... handlerUriArray) { + addHandlersAtEnd(handlersAfterWfProcess, createUriStackEntries(handlerUriArray)); + } + + private List createUriStackEntries(String[] handlerUriArray) { + List retval = new ArrayList(); + for (String handlerUri : handlerUriArray) { + retval.add(createUriStackEntry(handlerUri)); + } + return retval; + } + + private void addAtBeginningOfExecutionList(List list, String handlerUri, TaskRecurrence recurrence, ScheduleType scheduleType, TaskBinding taskBinding) { + list.add(0, createUriStackEntry(handlerUri, recurrence, scheduleType, taskBinding)); + } + + private void addAtEndOfExecutionList(List list, String handlerUri, TaskRecurrence recurrence, ScheduleType scheduleType, TaskBinding taskBinding) { + list.add(createUriStackEntry(handlerUri, recurrence, scheduleType, taskBinding)); + } + + private UriStackEntry createUriStackEntry(String handlerUri, TaskRecurrence recurrence, ScheduleType scheduleType, TaskBinding taskBinding) { + UriStackEntry uriStackEntry = new UriStackEntry(); + uriStackEntry.setHandlerUri(handlerUri); + uriStackEntry.setRecurrence(recurrence != null ? recurrence.toTaskType() : null); + uriStackEntry.setSchedule(scheduleType); + uriStackEntry.setBinding(taskBinding != null ? taskBinding.toTaskType() : null); + return uriStackEntry; + } + + private UriStackEntry createUriStackEntry(String handlerUri) { + return createUriStackEntry(handlerUri, TaskRecurrence.SINGLE, new ScheduleType(), null); + } + + private void setHandlers(List list, List uriStackEntry) { + list.clear(); + list.addAll(uriStackEntry); + } + + private void addHandlersAtEnd(List list, List uriStackEntry) { + list.addAll(uriStackEntry); + } + + public void setExecuteModelOperationHandler(boolean executeModelOperationHandler) { this.executeModelOperationHandler = executeModelOperationHandler; } - public boolean isExecuteModelOperationHandler() { - return executeModelOperationHandler; - } - - public void setTaskObject(PrismObject taskObject) { + public void setTaskObject(PrismObject taskObject) { this.taskObject = taskObject; } - public PrismObject getTaskObject() { - return taskObject; - } - - public void setCreateTaskAsWaiting(boolean createTaskAsWaiting) { - this.createTaskAsWaiting = createTaskAsWaiting; - } - - public boolean isCreateTaskAsWaiting() { - return createTaskAsWaiting; - } - - public ChangeProcessor getChangeProcessor() { - return changeProcessor; - } - - public PrismObject getTaskOwner() { - return taskOwner; - } - public void setTaskOwner(PrismObject taskOwner) { this.taskOwner = taskOwner; } - public ModelContext getTaskModelContext() { - return taskModelContext; - } - public void setTaskModelContext(ModelContext taskModelContext) { this.taskModelContext = taskModelContext; } - //endregion - - //region Setters for handlers - public void setHandlersBeforeModelOperation(String... handlerUri) { - setHandlers(handlersBeforeModelOperation, createUriStackEntries(handlerUri)); - } - public void setHandlersAfterModelOperation(String... handlerUri) { - setHandlers(handlersAfterModelOperation, createUriStackEntries(handlerUri)); - } + public void setObjectRef(ObjectReferenceType ref, OperationResult result) { + ref = getChangeProcessor().getWorkflowManager().getMiscDataUtil().resolveObjectReferenceName(ref, result); + wfContext.setObjectRef(ref); + } - public void setHandlersAfterWfProcess(String... handlerUri) { - setHandlers(handlersAfterWfProcess, createUriStackEntries(handlerUri)); - } + public void setObjectRef(ModelContext modelContext, OperationResult result) { + ObjectType focus = MiscDataUtil.getFocusObjectNewOrOld(modelContext); + setObjectRef(ObjectTypeUtil.createObjectRef(focus), result); + } - public void addHandlersAfterWfProcessAtEnd(String... handlerUriArray) { - addHandlersAtEnd(handlersAfterWfProcess, createUriStackEntries(handlerUriArray)); - } + public void setTargetRef(ObjectReferenceType ref, OperationResult result) { + ref = getChangeProcessor().getWorkflowManager().getMiscDataUtil().resolveObjectReferenceName(ref, result); + wfContext.setTargetRef(ref); + } - private List createUriStackEntries(String[] handlerUriArray) { - List retval = new ArrayList(); - for (String handlerUri : handlerUriArray) { - retval.add(createUriStackEntry(handlerUri)); - } - return retval; - } - - private void addAtBeginningOfExecutionList(List list, String handlerUri, TaskRecurrence recurrence, ScheduleType scheduleType, TaskBinding taskBinding) { - list.add(0, createUriStackEntry(handlerUri, recurrence, scheduleType, taskBinding)); - } - - private void addAtEndOfExecutionList(List list, String handlerUri, TaskRecurrence recurrence, ScheduleType scheduleType, TaskBinding taskBinding) { - list.add(createUriStackEntry(handlerUri, recurrence, scheduleType, taskBinding)); - } - - private UriStackEntry createUriStackEntry(String handlerUri, TaskRecurrence recurrence, ScheduleType scheduleType, TaskBinding taskBinding) { - UriStackEntry uriStackEntry = new UriStackEntry(); - uriStackEntry.setHandlerUri(handlerUri); - uriStackEntry.setRecurrence(recurrence != null ? recurrence.toTaskType() : null); - uriStackEntry.setSchedule(scheduleType); - uriStackEntry.setBinding(taskBinding != null ? taskBinding.toTaskType() : null); - return uriStackEntry; - } - - private void setHandlers(List list, List uriStackEntry) { - list.clear(); - list.addAll(uriStackEntry); - } - - private void addHandlersAtEnd(List list, List uriStackEntry) { - list.addAll(uriStackEntry); - } - - private UriStackEntry createUriStackEntry(String handlerUri) { - return createUriStackEntry(handlerUri, TaskRecurrence.SINGLE, new ScheduleType(), null); - } - //endregion - - //region Setters for task variables - public void addTaskModelContext(ModelContext modelContext) throws SchemaException { - Validate.notNull(modelContext, "model context cannot be null"); - setTaskModelContext(modelContext); - } - //endregion - - //region Setters for process variables - public void initializeCommonProcessVariables() { - addProcessVariable(VARIABLE_UTIL, new ActivitiUtil()); - addProcessVariable(VARIABLE_CHANGE_PROCESSOR, changeProcessor.getClass().getName()); - addProcessVariable(VARIABLE_START_TIME, new Date()); - } - - public void setRequesterOidAndRefInProcess(PrismObject requester) { - addProcessVariable(VARIABLE_REQUESTER_REF, new LightweightObjectRefImpl(createObjectRef(requester))); - } - - public void setProcessInstanceName(String name) { - processInstanceName = name; - addProcessVariable(VARIABLE_PROCESS_INSTANCE_NAME, name); + public void setRequesterRef(PrismObject requester) { + wfContext.setRequesterRef(createObjectRef(requester)); } public void setProcessInterfaceBean(ProcessMidPointInterface processInterfaceBean) { - addProcessVariable(VARIABLE_PROCESS_INTERFACE_BEAN_NAME, processInterfaceBean.getBeanName()); + wfContext.setProcessInterface(processInterfaceBean.getBeanName()); } //endregion //region Diagnostics public String toString() { - return "WfTaskCreationInstruction: processDefinitionKey = " + processDefinitionKey + ", simple: " + simple + ", variables: " + processVariables; + return "WfTaskCreationInstruction: processDefinitionKey = " + getProcessName() + ", simple: " + simple; } @Override @@ -356,37 +292,123 @@ public String debugDump() { return debugDump(0); } - @Override + @Override public String debugDump(int indent) { StringBuilder sb = new StringBuilder(); DebugUtil.indentDebugDump(sb, indent); - sb.append("WfTaskCreationInstruction: process: " + processDefinitionKey + " (" + - (simple ? "simple" : "smart") + ", " + - (noProcess ? "no-process" : "with-process") + - "), task = " + taskName + "\n"); - - if (!noProcess) { - DebugUtil.indentDebugDump(sb, indent); - sb.append("Process variables:\n"); - - for (Map.Entry entry : processVariables.entrySet()) { - DebugUtil.indentDebugDump(sb, indent); - sb.append(" - " + entry.getKey() + " = "); - Object value = entry.getValue(); - if (value instanceof DebugDumpable) { - sb.append("\n" + ((DebugDumpable) value).debugDump(indent+1)); - } else { - sb.append(value != null ? value.toString() : "null"); - } - sb.append("\n"); - } - } + sb.append("WfTaskCreationInstruction: process: ").append(getProcessName()).append("/").append(getProcessInstanceName()); + sb.append(" ").append(simple ? "simple" : "smart").append(", ").append(noProcess ? "no-process" : "with-process").append(", model-context: "); + sb.append(taskModelContext != null ? "YES" : "no").append(", task = ").append(taskName).append("\n"); + + DebugUtil.indentDebugDump(sb, indent); + sb.append("Workflow context:\n"); + sb.append(wfContext.asPrismContainerValue().debugDump(indent+2)); + + DebugUtil.debugDumpWithLabel(sb, "Change processor", changeProcessor.getClass().getName(), indent+1); + DebugUtil.debugDumpWithLabel(sb, "Process creation timestamp", String.valueOf(processCreationTimestamp), indent+1); + DebugUtil.debugDumpWithLabel(sb, "Task object", String.valueOf(taskObject), indent+1); + DebugUtil.debugDumpWithLabel(sb, "Task owner", String.valueOf(taskOwner), indent+1); + DebugUtil.debugDumpWithLabel(sb, "Task initial state", String.valueOf(taskInitialState), indent+1); + DebugUtil.debugDumpWithLabel(sb, "Send start confirmation", String.valueOf(sendStartConfirmation), indent+1); + DebugUtil.debugDumpWithLabel(sb, "Handlers after model operation", String.valueOf(handlersAfterModelOperation), indent+1); + DebugUtil.debugDumpWithLabel(sb, "Handlers before model operation", String.valueOf(handlersBeforeModelOperation), indent+1); + DebugUtil.debugDumpWithLabel(sb, "Handlers after wf process", String.valueOf(handlersAfterWfProcess), indent+1); + DebugUtil.debugDumpWithLabel(sb, "Processor instruction", String.valueOf(processorInstruction), indent+1); + DebugUtil.debugDumpWithLabel(sb, "Process instruction", String.valueOf(processInstruction), indent+1); + return sb.toString(); } //endregion - public void tailorTask(Task task) throws SchemaException { - } + //region "Output" methods + public Task createTask(WfTaskController taskController, Task parentTask) throws SchemaException { + + LOGGER.trace("createTask starting; parent task = {}", parentTask); + + final WfTaskUtil wfTaskUtil = taskController.getWfTaskUtil(); + + final Task task; + if (parentTask != null) { + task = parentTask.createSubtask(); + } else { + task = taskController.getTaskManager().createTaskInstance(); + if (taskOwner == null) { + throw new IllegalStateException("No task owner for " + task); + } + task.setOwner(taskOwner); + } + + task.setInitialExecutionStatus(taskInitialState); + task.setCategory(TaskCategory.WORKFLOW); + + if (taskObject != null) { + task.setObjectRef(taskObject.getOid(), taskObject.getDefinition().getTypeName()); + } else if (parentTask != null && parentTask.getObjectRef() != null) { + task.setObjectRef(parentTask.getObjectRef()); + } + if (task.getName() == null || task.getName().toPolyString().isEmpty()) { + task.setName(taskName); + } + + // push the handlers, beginning with these that should execute last + wfTaskUtil.pushHandlers(task, getHandlersAfterModelOperation()); + if (executeModelOperationHandler) { + task.pushHandlerUri(ModelOperationTaskHandler.MODEL_OPERATION_TASK_URI, null, null); + } + wfTaskUtil.pushHandlers(task, getHandlersBeforeModelOperation()); + wfTaskUtil.pushHandlers(task, getHandlersAfterWfProcess()); + if (!noProcess) { + if (simple) { + ScheduleType schedule = new ScheduleType(); + schedule.setInterval(taskController.getWfConfiguration().getProcessCheckInterval()); + schedule.setEarliestStartTime(MiscUtil.asXMLGregorianCalendar(new Date(System.currentTimeMillis() + WfTaskController.TASK_START_DELAY))); + task.pushHandlerUri(WfProcessInstanceShadowTaskHandler.HANDLER_URI, schedule, TaskBinding.LOOSE); + } else { + task.pushHandlerUri(WfProcessInstanceShadowTaskHandler.HANDLER_URI, new ScheduleType(), null); // note that this handler will not be actively used (at least for now) + task.makeWaiting(); + } + } + + // model and workflow context + if (taskModelContext != null) { + task.setModelOperationContext(((LensContext) taskModelContext).toLensContextType()); + } + wfContext.setChangeProcessor(changeProcessor.getClass().getName()); + wfContext.setStartTimestamp(createXMLGregorianCalendar(processCreationTimestamp)); + if (processorInstruction != null) { + wfContext.setProcessorSpecificState(processorInstruction.createProcessorSpecificState()); + } + if (processInstruction != null) { + wfContext.setProcessSpecificState(processInstruction.createProcessSpecificState()); + } + task.setWorkflowContext(wfContext); + + return task; + } + + public Map getAllProcessVariables() throws SchemaException { + Map map = new HashMap<>(); + map.put(VARIABLE_PROCESS_INSTANCE_NAME, wfContext.getProcessInstanceName()); + map.put(VARIABLE_START_TIME, processCreationTimestamp); + map.put(VARIABLE_OBJECT_REF, toLightweightObjectRef(wfContext.getObjectRef())); + map.put(VARIABLE_TARGET_REF, toLightweightObjectRef(wfContext.getTargetRef())); + map.put(VARIABLE_REQUESTER_REF, toLightweightObjectRef(wfContext.getRequesterRef())); + map.put(VARIABLE_CHANGE_PROCESSOR, changeProcessor.getClass().getName()); + map.put(VARIABLE_PROCESS_INTERFACE_BEAN_NAME, wfContext.getProcessInterface()); + map.put(VARIABLE_UTIL, new ActivitiUtil()); + if (processorInstruction != null) { + processorInstruction.createProcessVariables(map, getPrismContext()); + } + if (processInstruction != null) { + processInstruction.createProcessVariables(map, getPrismContext()); + } + return map; + } + + private LightweightObjectRef toLightweightObjectRef(ObjectReferenceType ref) { + return ref != null ? new LightweightObjectRefImpl(ref) : null; + } + //endregion } \ No newline at end of file diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskUtil.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskUtil.java index f5f57248f45..b2dee7268e5 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskUtil.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/jobs/WfTaskUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Evolveum + * Copyright (c) 2010-2016 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,13 +22,10 @@ import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; import com.evolveum.midpoint.prism.path.ItemPath; -import com.evolveum.midpoint.prism.xml.XmlTypeConverter; import com.evolveum.midpoint.provisioning.api.ProvisioningService; -import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.task.api.TaskBinding; -import com.evolveum.midpoint.util.MiscUtil; import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -37,14 +34,11 @@ import com.evolveum.midpoint.wf.impl.processors.primary.ObjectTreeDeltas; import com.evolveum.midpoint.wf.impl.processors.primary.aspect.PrimaryChangeAspect; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; -import org.apache.commons.lang.Validate; import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; -import javax.xml.datatype.XMLGregorianCalendar; import java.util.*; import static com.evolveum.midpoint.prism.util.CloneUtil.cloneListMembers; @@ -57,24 +51,17 @@ import static com.evolveum.midpoint.xml.ns._public.common.common_3.WfPrimaryChangeProcessorStateType.F_RESULTING_DELTAS; /** - * Handles low-level task operations, e.g. handling wf* properties in task extension. + * Handles low-level task operations. * * @author mederly - * */ @Component -//@DependsOn({ "prismContext" }) - public class WfTaskUtil { @Autowired private WfConfiguration wfConfiguration; - @Autowired - @Qualifier("cacheRepositoryService") - private RepositoryService repositoryService; - @Autowired private PrismContext prismContext; @@ -85,14 +72,17 @@ public class WfTaskUtil { public static final String WAIT_FOR_TASKS_HANDLER_URI = "<<< marker for calling pushWaitForTasksHandlerUri >>>"; - void setWfProcessId(Task task, String pid) throws SchemaException { - Validate.notEmpty(task.getOid(), "Task oid must not be null or empty (task must be persistent)."); - task.addModification( - DeltaBuilder.deltaFor(TaskType.class, prismContext) - .item(F_WORKFLOW_CONTEXT, F_PROCESS_INSTANCE_ID).replace(pid) - .asItemDelta()); - } + public static WfContextType getWorkflowContextChecked(Task task) { + if (task == null) { + throw new IllegalStateException("No task"); + } else if (task.getWorkflowContext() == null) { + throw new IllegalStateException("No workflow context in " + task); + } else { + return task.getWorkflowContext(); + } + } + @NotNull public PrimaryChangeAspect getPrimaryChangeAspect(Task task, Collection aspects) { WfContextType wfc = getWorkflowContextChecked(task); WfProcessorSpecificStateType pss = wfc.getProcessorSpecificState(); @@ -104,33 +94,15 @@ public PrimaryChangeAspect getPrimaryChangeAspect(Task task, Collection deltaTypePrismProperty = task.getTaskPrismObject().findProperty(new ItemPath(F_WORKFLOW_CONTEXT, F_PROCESSOR_SPECIFIC_STATE, F_RESULTING_DELTAS)); if (deltaTypePrismProperty == null) { @@ -212,21 +173,6 @@ public ObjectTreeDeltas retrieveResultingDeltas(Task task) throws SchemaExceptio return ObjectTreeDeltas.fromObjectTreeDeltasType(deltaTypePrismProperty.getRealValue(), prismContext); } - public void setTaskNameIfEmpty(Task t, PolyStringType taskName) { - if (t.getName() == null || t.getName().toPolyString().isEmpty()) { - t.setName(taskName); - } - } - - public void setProcessInstanceFinishedImmediate(Task task, OperationResult result) throws SchemaException, ObjectNotFoundException, ObjectAlreadyExistsException { - XMLGregorianCalendar now = XmlTypeConverter.createXMLGregorianCalendar(new Date()); - task.addModificationImmediate( - DeltaBuilder.deltaFor(TaskType.class, prismContext) - .item(F_WORKFLOW_CONTEXT, F_END_TIMESTAMP).replace(now) - .asItemDelta(), - result); - } - public boolean isProcessInstanceFinished(Task task) { return task.getWorkflowContext() != null && task.getWorkflowContext().getEndTimestamp() != null; } @@ -248,12 +194,12 @@ public String getRootTaskOid(Task task) { return ref != null ? ref.getOid() : null; } - public void deleteModelOperationContext(Task task, OperationResult result) throws SchemaException, ObjectNotFoundException { + public void deleteModelOperationContext(Task task) throws SchemaException, ObjectNotFoundException { task.setModelOperationContext(null); } public void addApprovedBy(Task task, ObjectReferenceType referenceType) throws SchemaException { - addApprovedBy(task, Arrays.asList(referenceType)); + addApprovedBy(task, Collections.singletonList(referenceType)); } public void addApprovedBy(Task task, Collection referenceTypes) throws SchemaException { @@ -297,13 +243,6 @@ public List getApprovedByFromTaskTree(Task task, return retval; } - void setTaskOwner(Task task, PrismObject owner) { - if (owner == null) { - throw new IllegalStateException("Couldn't create a job task because the owner is not set."); - } - task.setOwner(owner); - } - // handlers are stored in the list in the order they should be executed; so the last one has to be pushed first void pushHandlers(Task task, List handlers) { for (int i = handlers.size()-1; i >= 0; i--) { @@ -318,38 +257,4 @@ void pushHandlers(Task task, List handlers) { } } } - - /** - * Makes a task active, i.e. a task that actively queries wf process instance about its status. - * - * OR - * - * Creates a passive task, i.e. a task that stores information received from WfMS about a process instance. - * - * We expect task to be transient at this moment! - * @param active - * @param t - * @param result - */ - void pushProcessShadowHandler(boolean active, Task t, long taskStartDelay, OperationResult result) throws SchemaException, ObjectNotFoundException { - - if (active) { - - ScheduleType schedule = new ScheduleType(); - schedule.setInterval(wfConfiguration.getProcessCheckInterval()); - schedule.setEarliestStartTime(MiscUtil.asXMLGregorianCalendar(new Date(System.currentTimeMillis() + taskStartDelay))); - t.pushHandlerUri(WfProcessInstanceShadowTaskHandler.HANDLER_URI, schedule, TaskBinding.LOOSE); - - } else { - - t.pushHandlerUri(WfProcessInstanceShadowTaskHandler.HANDLER_URI, new ScheduleType(), null); // note that this handler will not be actively used (at least for now) - t.makeWaiting(); - } - } - - void setDefaultTaskOwnerIfEmpty(Task t, OperationResult result, WfTaskController wfTaskController) throws SchemaException, ObjectNotFoundException { - if (t.getOwner() == null) { - t.setOwner(repositoryService.getObject(UserType.class, SystemObjectsType.USER_ADMINISTRATOR.value(), null, result)); - } - } } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/messages/StartProcessCommand.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/messages/StartProcessCommand.java index 36cda1aa8b9..325475ef244 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/messages/StartProcessCommand.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/messages/StartProcessCommand.java @@ -28,7 +28,6 @@ public class StartProcessCommand extends MidPointToActivitiMessage { private String processName; private String processInstanceName; private String processOwner; - private String taskOid; private boolean sendStartConfirmation; public String getProcessName() { @@ -55,14 +54,6 @@ public void setSendStartConfirmation(boolean sendStartConfirmation) { this.sendStartConfirmation = sendStartConfirmation; } - public String getTaskOid() { - return taskOid; - } - - public void setTaskOid(String taskOid) { - this.taskOid = taskOid; - } - public Map getVariables() { return variables; } @@ -72,7 +63,7 @@ public void setVariables(Map variables) { } public void setVariablesFrom(Map variables) { - this.variables = new HashMap(variables); + this.variables = new HashMap<>(variables); } public void addVariable(String name, Object value) { @@ -92,6 +83,6 @@ public void setProcessOwner(String processOwner) { @Override public String toString() { - return this.getClass().getSimpleName() + "[process=" + processName + "/" + processInstanceName + ", task=" + taskOid + ", variables=" + variables + ", sendStartConfirmation=" + sendStartConfirmation + "]"; + return this.getClass().getSimpleName() + "[process=" + processName + "/" + processInstanceName + ", variables=" + variables + ", sendStartConfirmation=" + sendStartConfirmation + "]"; } } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/DefaultProcessMidPointInterface.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/DefaultProcessMidPointInterface.java index ff595124637..18d961d7d3a 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/DefaultProcessMidPointInterface.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/DefaultProcessMidPointInterface.java @@ -17,11 +17,9 @@ package com.evolveum.midpoint.wf.impl.processes; import com.evolveum.midpoint.wf.impl.messages.ProcessEvent; +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.WfProcessSpecificStateType; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessSpecificState; -import com.sun.corba.se.spi.ior.iiop.ORBTypeComponent; - import org.springframework.stereotype.Component; import java.util.ArrayList; @@ -37,12 +35,11 @@ public class DefaultProcessMidPointInterface extends BaseProcessMidPointInterface { @Override - public ProcessSpecificState externalizeProcessInstanceState(Map variables) { + public WfProcessSpecificStateType externalizeProcessSpecificState(Map variables) { return null; } - @Override - public WfProcessSpecificStateType externalizeProcessSpecificState(Map variables) { + @Override public DecisionType extractDecision(Map variables) { return null; } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/ProcessMidPointInterface.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/ProcessMidPointInterface.java index efbc1a90e0b..14004658e3a 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/ProcessMidPointInterface.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/ProcessMidPointInterface.java @@ -17,9 +17,9 @@ package com.evolveum.midpoint.wf.impl.processes; import com.evolveum.midpoint.wf.impl.messages.ProcessEvent; +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.WfProcessSpecificStateType; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessSpecificState; import java.util.List; import java.util.Map; @@ -33,10 +33,10 @@ public interface ProcessMidPointInterface { String getState(Map variables); - ProcessSpecificState externalizeProcessInstanceState(Map variables); - WfProcessSpecificStateType externalizeProcessSpecificState(Map variables); + DecisionType extractDecision(Map variables); + String getBeanName(); List prepareApprovedBy(ProcessEvent event); diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ApprovalSchema.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ApprovalSchema.java index 6de85316013..ab6ad0ecf82 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ApprovalSchema.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ApprovalSchema.java @@ -37,4 +37,6 @@ public interface ApprovalSchema { void setPrismContext(PrismContext prismContext); void toApprovalSchemaType(ApprovalSchemaType approvalSchemaType); // expects empty (newly created) ApprovalSchemaType instance + + ApprovalSchemaType toApprovalSchemaType(); } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ApprovalSchemaImpl.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ApprovalSchemaImpl.java index eb0206146eb..c6035067ffe 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ApprovalSchemaImpl.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ApprovalSchemaImpl.java @@ -17,7 +17,6 @@ package com.evolveum.midpoint.wf.impl.processes.itemApproval; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.xjc.PrismForJAXBUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import java.io.Serializable; @@ -111,6 +110,12 @@ public void toApprovalSchemaType(ApprovalSchemaType approvalSchemaType) { } } + @Override public ApprovalSchemaType toApprovalSchemaType() { + ApprovalSchemaType ast = new ApprovalSchemaType(); + toApprovalSchemaType(ast); + return ast; + } + public void addLevel(ApprovalLevelImpl level) { levels.add(level); } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/InitializeLoopThroughApproversInLevel.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/InitializeLoopThroughApproversInLevel.java index 0eb4f75c714..a7b11acf5eb 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/InitializeLoopThroughApproversInLevel.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/InitializeLoopThroughApproversInLevel.java @@ -220,7 +220,7 @@ private ExpressionVariables getDefaultVariables(DelegateExecution execution, Tas ObjectDelta objectDelta = null; try { - objectDelta = miscDataUtil.getFocusPrimaryDelta(execution.getVariables(), true); + objectDelta = miscDataUtil.getFocusPrimaryDelta(wfTask.getWorkflowContext(), true); } catch (JAXBException e) { throw new SchemaException("Couldn't get object delta: " + e.getMessage(), e); } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ItemApprovalInstruction.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ItemApprovalInstruction.java new file mode 100644 index 00000000000..68801e683b6 --- /dev/null +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ItemApprovalInstruction.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2010-2016 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.wf.impl.processes.itemApproval; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.wf.impl.jobs.ProcessInstruction; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ItemApprovalProcessStateType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfProcessSpecificStateType; + +import java.util.Map; + +/** + * @author mederly + */ +public class ItemApprovalInstruction implements ProcessInstruction { + + private String taskName; + private ApprovalSchema approvalSchema; + + public void setTaskName(String taskName) { + this.taskName = taskName; + } + + public String getTaskName() { + return taskName; + } + + @Override public void createProcessVariables(Map map, PrismContext prismContext) { + map.put(ProcessVariableNames.APPROVAL_TASK_NAME, taskName); + if (approvalSchema != null) { + map.put(ProcessVariableNames.APPROVAL_SCHEMA, approvalSchema); + } + } + + public void setApprovalSchema(ApprovalSchema approvalSchema) { + this.approvalSchema = approvalSchema; + } + + public ApprovalSchema getApprovalSchema() { + return approvalSchema; + } + + @Override + public WfProcessSpecificStateType createProcessSpecificState() { + ItemApprovalProcessStateType state = new ItemApprovalProcessStateType(); + state.asPrismContainerValue().setConcreteType(ItemApprovalProcessStateType.COMPLEX_TYPE); + state.setApprovalSchema(approvalSchema != null ? approvalSchema.toApprovalSchemaType() : null); + return state; + } +} diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ItemApprovalProcessInterface.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ItemApprovalProcessInterface.java index fbc82c94441..821c70c8fef 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ItemApprovalProcessInterface.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ItemApprovalProcessInterface.java @@ -16,22 +16,18 @@ package com.evolveum.midpoint.wf.impl.processes.itemApproval; -import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContainerDefinition; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.schema.constants.SchemaConstants; import com.evolveum.midpoint.schema.util.MiscSchemaUtil; import com.evolveum.midpoint.wf.impl.jobs.WfTaskCreationInstruction; import com.evolveum.midpoint.wf.impl.messages.ProcessEvent; import com.evolveum.midpoint.wf.impl.processes.BaseProcessMidPointInterface; +import com.evolveum.midpoint.wf.impl.processes.common.CommonProcessVariableNames; import com.evolveum.midpoint.wf.util.ApprovalUtils; import com.evolveum.midpoint.xml.ns._public.common.common_3.ApprovalSchemaType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.DecisionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ItemApprovalProcessStateType; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ItemApprovalProcessState; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ItemApprovalRequestType; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessSpecificState; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -50,61 +46,26 @@ public class ItemApprovalProcessInterface extends BaseProcessMidPointInterface { @Autowired private PrismContext prismContext; - public void prepareStartInstruction(WfTaskCreationInstruction instruction, ApprovalRequest approvalRequest, String approvalTaskName) { - instruction.setProcessDefinitionKey(PROCESS_DEFINITION_KEY); + public void prepareStartInstruction(WfTaskCreationInstruction instruction) { + instruction.setProcessName(PROCESS_DEFINITION_KEY); instruction.setSimple(false); instruction.setSendStartConfirmation(true); - instruction.addProcessVariable(ProcessVariableNames.APPROVAL_REQUEST, approvalRequest); - instruction.addProcessVariable(ProcessVariableNames.APPROVAL_TASK_NAME, approvalTaskName); instruction.setProcessInterfaceBean(this); } - @Deprecated - @Override - public ProcessSpecificState externalizeProcessInstanceState(Map variables) { - PrismContainerDefinition extDefinition = prismContext.getSchemaRegistry().findContainerDefinitionByType(ItemApprovalProcessState.COMPLEX_TYPE); - PrismContainer extStateContainer = extDefinition.instantiate(); - ItemApprovalProcessState extState = extStateContainer.createNewValue().asContainerable(); - - PrismContainer extRequestContainer = extDefinition.findContainerDefinition(ItemApprovalProcessState.F_APPROVAL_REQUEST).instantiate(); - ItemApprovalRequestType extRequestType = (ItemApprovalRequestType) extRequestContainer.createNewValue().asContainerable(); - - ApprovalRequest intApprovalRequest = (ApprovalRequest) variables.get(ProcessVariableNames.APPROVAL_REQUEST); - intApprovalRequest.setPrismContext(prismContext); - - ApprovalSchemaType approvalSchemaType = (ApprovalSchemaType) extRequestContainer.getDefinition().findContainerDefinition(ItemApprovalRequestType.F_APPROVAL_SCHEMA).instantiate().createNewValue().asContainerable(); - intApprovalRequest.getApprovalSchema().toApprovalSchemaType(approvalSchemaType); - extRequestType.setApprovalSchema(approvalSchemaType); - extRequestType.setItemToApprove(intApprovalRequest.getItemToApprove()); - extState.setApprovalRequest(extRequestType); - - List intDecisions = (List) variables.get(ProcessVariableNames.ALL_DECISIONS); - if (intDecisions != null) { - for (Decision intDecision : intDecisions) { - extState.getDecisions().add(intDecision.toDecisionType()); - } - } - - extState.asPrismContainerValue().setConcreteType(ItemApprovalProcessState.COMPLEX_TYPE); - return extState; - } - @Override public ItemApprovalProcessStateType externalizeProcessSpecificState(Map variables) { ItemApprovalProcessStateType extState = new ItemApprovalProcessStateType(prismContext); com.evolveum.midpoint.xml.ns._public.common.common_3.ItemApprovalRequestType extRequestType = new com.evolveum.midpoint.xml.ns._public .common.common_3.ItemApprovalRequestType(prismContext); - ApprovalRequest intApprovalRequest = (ApprovalRequest) variables.get(ProcessVariableNames.APPROVAL_REQUEST); - intApprovalRequest.setPrismContext(prismContext); + ApprovalSchema intApprovalSchema = (ApprovalSchema) variables.get(ProcessVariableNames.APPROVAL_SCHEMA); + intApprovalSchema.setPrismContext(prismContext); ApprovalSchemaType approvalSchemaType = new ApprovalSchemaType(prismContext); - intApprovalRequest.getApprovalSchema().toApprovalSchemaType(approvalSchemaType); + intApprovalSchema.toApprovalSchemaType(approvalSchemaType); extRequestType.setApprovalSchema(approvalSchemaType); - extRequestType.setItemToApprove(intApprovalRequest.getItemToApprove()); - extState.setApprovalRequest(extRequestType); - List intDecisions = (List) variables.get(ProcessVariableNames.ALL_DECISIONS); if (intDecisions != null) { for (Decision intDecision : intDecisions) { @@ -116,6 +77,18 @@ public ItemApprovalProcessStateType externalizeProcessSpecificState(Map variables) { + DecisionType decision = new DecisionType(); + + decision.setResultAsString((String) variables.get(CommonProcessVariableNames.FORM_FIELD_DECISION)); + decision.setApproved(ApprovalUtils.approvalBooleanValue(decision.getResultAsString())); + decision.setComment((String) variables.get(CommonProcessVariableNames.FORM_FIELD_COMMENT)); + + // TODO - what with other fields (approver, dateTime)? + + return decision; + } + @Override public List prepareApprovedBy(ProcessEvent event) { List retval = new ArrayList(); diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ProcessVariableNames.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ProcessVariableNames.java index 20ae03f54ce..25479782149 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ProcessVariableNames.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/ProcessVariableNames.java @@ -21,8 +21,8 @@ */ public class ProcessVariableNames { - // A data structure that describes the request to approve something. Contains item that has to be approved (e.g. assignment) and approval schema. - public static final String APPROVAL_REQUEST = "approvalRequest"; // of type ApprovalRequest + // A data structure that describes the approval schema. + public static final String APPROVAL_SCHEMA = "approvalSchema"; // of type ApprovalSchema // How the user task (work item) should be named. public static final String APPROVAL_TASK_NAME = "approvalTaskName"; // of type String diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/RecordIndividualDecision.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/RecordIndividualDecision.java index 8fe5287ef78..cadc8d4f848 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/RecordIndividualDecision.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processes/itemApproval/RecordIndividualDecision.java @@ -25,10 +25,8 @@ import com.evolveum.midpoint.wf.impl.processes.BaseProcessMidPointInterface; import com.evolveum.midpoint.wf.impl.processes.common.CommonProcessVariableNames; import com.evolveum.midpoint.wf.impl.processes.common.SpringApplicationContextHolder; -import com.evolveum.midpoint.wf.impl.util.MiscDataUtil; import com.evolveum.midpoint.wf.util.ApprovalUtils; import com.evolveum.midpoint.xml.ns._public.common.common_3.LevelEvaluationStrategyType; - import org.activiti.engine.delegate.DelegateExecution; import org.activiti.engine.delegate.JavaDelegate; import org.apache.commons.lang.Validate; @@ -47,10 +45,6 @@ public class RecordIndividualDecision implements JavaDelegate { public void execute(DelegateExecution execution) { - ApprovalRequest approvalRequest = (ApprovalRequest) execution.getVariable(ProcessVariableNames.APPROVAL_REQUEST); - Validate.notNull(approvalRequest, "approvalRequest is null"); - approvalRequest.setPrismContext(SpringApplicationContextHolder.getPrismContext()); - List decisionList = (List) execution.getVariable(ProcessVariableNames.DECISIONS_IN_LEVEL); Validate.notNull(decisionList, "decisionList is null"); @@ -105,7 +99,7 @@ public void execute(DelegateExecution execution) { } if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Logged decision '" + approved + "' for " + approvalRequest); + LOGGER.trace("Logged decision '" + approved + "'"); LOGGER.trace("Resulting decision list = " + decisionList); LOGGER.trace("All decisions = " + allDecisions); } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseAuditHelper.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseAuditHelper.java index 8eab97d43bc..f0e8705f527 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseAuditHelper.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseAuditHelper.java @@ -23,33 +23,30 @@ import com.evolveum.midpoint.repo.api.RepositoryService; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.result.OperationResultStatus; +import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.security.api.MidPointPrincipal; import com.evolveum.midpoint.security.api.SecurityEnforcer; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SecurityViolationException; -import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.wf.api.WorkflowException; import com.evolveum.midpoint.wf.impl.activiti.dao.WorkItemProvider; import com.evolveum.midpoint.wf.impl.jobs.WfTask; import com.evolveum.midpoint.wf.impl.messages.TaskEvent; -import com.evolveum.midpoint.wf.impl.processes.common.CommonProcessVariableNames; -import com.evolveum.midpoint.wf.impl.processes.common.LightweightObjectRef; import com.evolveum.midpoint.wf.impl.util.MiscDataUtil; +import com.evolveum.midpoint.xml.ns._public.common.common_3.DecisionType; import com.evolveum.midpoint.xml.ns._public.common.common_3.GenericObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType; import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import java.util.Map; +import static com.evolveum.midpoint.audit.api.AuditEventType.WORKFLOW_PROCESS_INSTANCE; + /** * @author mederly */ @@ -71,26 +68,16 @@ public class BaseAuditHelper { @Qualifier("cacheRepositoryService") private RepositoryService repositoryService; - public AuditEventRecord prepareProcessInstanceAuditRecord(Map variables, WfTask wfTask, AuditEventStage stage, OperationResult result) { + public AuditEventRecord prepareProcessInstanceAuditRecord(WfTask wfTask, AuditEventStage stage, Map variables, OperationResult result) { AuditEventRecord auditEventRecord = new AuditEventRecord(); - auditEventRecord.setEventType(AuditEventType.WORKFLOW_PROCESS_INSTANCE); + auditEventRecord.setEventType(WORKFLOW_PROCESS_INSTANCE); auditEventRecord.setEventStage(stage); - - String requesterOid = wfTask.getRequesterOid(); - if (requesterOid != null) { - try { - auditEventRecord.setInitiator(miscDataUtil.getRequester(variables, result)); - } catch (SchemaException e) { - LoggingUtils.logException(LOGGER, "Couldn't retrieve the workflow process instance requester information", e); - } catch (ObjectNotFoundException e) { - LoggingUtils.logException(LOGGER, "Couldn't retrieve the workflow process instance requester information", e); - } - } + auditEventRecord.setInitiator(wfTask.getRequesterIfExists(result)); PrismObject processInstanceObject = new PrismObject<>(GenericObjectType.COMPLEX_TYPE, GenericObjectType.class); - processInstanceObject.asObjectable().setName(new PolyStringType((String) variables.get(CommonProcessVariableNames.VARIABLE_PROCESS_INSTANCE_NAME))); - processInstanceObject.asObjectable().setOid(wfTask.getActivitiId()); + processInstanceObject.asObjectable().setName(new PolyStringType(wfTask.getProcessInstanceName())); + processInstanceObject.asObjectable().setOid(wfTask.getProcessInstanceId()); auditEventRecord.setTarget(processInstanceObject); auditEventRecord.setOutcome(OperationResultStatus.SUCCESS); @@ -98,44 +85,22 @@ public AuditEventRecord prepareProcessInstanceAuditRecord(Map va return auditEventRecord; } - public AuditEventRecord prepareWorkItemAuditRecord(TaskEvent taskEvent, AuditEventStage stage, OperationResult result) throws WorkflowException { + // workItem contains taskRef, assignee, candidates resolved (if possible) + public AuditEventRecord prepareWorkItemAuditRecord(WorkItemNewType workItem, WfTask wfTask, TaskEvent taskEvent, AuditEventStage stage, + OperationResult result) throws WorkflowException { AuditEventRecord auditEventRecord = new AuditEventRecord(); auditEventRecord.setEventType(AuditEventType.WORK_ITEM); auditEventRecord.setEventStage(stage); + auditEventRecord.setInitiator(wfTask.getRequesterIfExists(result)); - Map variables = taskEvent.getVariables(); - LightweightObjectRef requesterRef = (LightweightObjectRef) variables.get(CommonProcessVariableNames.VARIABLE_REQUESTER_REF); - if (requesterRef != null) { - try { - auditEventRecord.setInitiator(miscDataUtil.getRequester(variables, result)); - } catch (SchemaException e) { - LoggingUtils.logException(LOGGER, "Couldn't retrieve the workflow process instance requester information", e); - } catch (ObjectNotFoundException e) { - LoggingUtils.logException(LOGGER, "Couldn't retrieve the workflow process instance requester information", e); - } - } - - WorkItemType workItemType = workItemProvider.taskEventToWorkItem(taskEvent, false, false, result); - - // temporary hacking (work items in audit are not supported) PrismObject targetObject = new PrismObject<>(GenericObjectType.COMPLEX_TYPE, GenericObjectType.class); - targetObject.asObjectable().setName(workItemType.getName()); - targetObject.asObjectable().setOid(workItemType.getWorkItemId()); + targetObject.asObjectable().setName(new PolyStringType(workItem.getName())); + targetObject.asObjectable().setOid(workItem.getWorkItemId()); auditEventRecord.setTarget(targetObject); -// auditEventRecord.setTarget(workItemType.asPrismObject()); - String assigneeOid = taskEvent.getAssigneeOid(); if (stage == AuditEventStage.REQUEST) { - if (assigneeOid != null) { - try { - auditEventRecord.setTargetOwner(repositoryService.getObject(UserType.class, assigneeOid, null, result)); - } catch (ObjectNotFoundException e) { - LoggingUtils.logException(LOGGER, "Couldn't retrieve the work item assignee information", e); - } catch (SchemaException e) { - LoggingUtils.logException(LOGGER, "Couldn't retrieve the work item assignee information", e); - } - } + auditEventRecord.setTargetOwner((PrismObject) ObjectTypeUtil.getPrismObjectFromReference(workItem.getAssigneeRef())); } else { MidPointPrincipal principal; try { @@ -148,8 +113,11 @@ public AuditEventRecord prepareWorkItemAuditRecord(TaskEvent taskEvent, AuditEve auditEventRecord.setOutcome(OperationResultStatus.SUCCESS); if (stage == AuditEventStage.EXECUTION) { - auditEventRecord.setResult((String) variables.get(CommonProcessVariableNames.FORM_FIELD_DECISION)); - auditEventRecord.setMessage((String) variables.get(CommonProcessVariableNames.FORM_FIELD_COMMENT)); + DecisionType decision = workItem.getDecision(); + if (decision != null) { + auditEventRecord.setResult(decision.getResultAsString()); + auditEventRecord.setMessage(decision.getComment()); + } } return auditEventRecord; diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseExternalizationHelper.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseExternalizationHelper.java deleted file mode 100644 index 12081e02b29..00000000000 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseExternalizationHelper.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2010-2014 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.wf.impl.processors; - -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectDefinition; -import com.evolveum.midpoint.prism.xml.XmlTypeConverter; -import com.evolveum.midpoint.wf.impl.processes.ProcessInterfaceFinder; -import com.evolveum.midpoint.wf.impl.processes.ProcessMidPointInterface; -import com.evolveum.midpoint.wf.impl.processes.common.CommonProcessVariableNames; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.Date; -import java.util.Map; - -/** - * Helps with process state externalization. - * - * (Will probably acquire additional duties later.) - * - * @author mederly - */ -@Component -public class BaseExternalizationHelper { - - @Autowired - private PrismContext prismContext; - - @Autowired - private ProcessInterfaceFinder processInterfaceFinder; - - public PrismObject externalizeState(Map variables) { - PrismObjectDefinition extDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByType(ProcessInstanceState.COMPLEX_TYPE); - PrismObject extStateObject = extDefinition.instantiate(); - ProcessInstanceState extState = extStateObject.asObjectable(); - - extState.setProcessInstanceName((String) variables.get(CommonProcessVariableNames.VARIABLE_PROCESS_INSTANCE_NAME)); - extState.setStartTime(XmlTypeConverter.createXMLGregorianCalendar((Date) variables.get(CommonProcessVariableNames.VARIABLE_START_TIME))); - extState.setShadowTaskOid((String) variables.get(CommonProcessVariableNames.VARIABLE_MIDPOINT_TASK_OID)); - extState.setChangeProcessor((String) variables.get(CommonProcessVariableNames.VARIABLE_CHANGE_PROCESSOR)); - - ProcessMidPointInterface processMidPointInterface = processInterfaceFinder.getProcessInterface(variables); - extState.setAnswer(processMidPointInterface.getAnswer(variables)); - extState.setState(processMidPointInterface.getState(variables)); - - return extStateObject; - } -} diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseModelInvocationProcessingHelper.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseModelInvocationProcessingHelper.java index 3f9f6db2593..f49c46df7fd 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseModelInvocationProcessingHelper.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/BaseModelInvocationProcessingHelper.java @@ -71,15 +71,15 @@ public WfTaskCreationInstruction createInstructionForRoot(ChangeProcessor change WfTaskCreationInstruction instruction; if (contextForRoot != null) { - instruction = WfTaskCreationInstruction.createModelOperationRootJob(changeProcessor, contextForRoot); + instruction = WfTaskCreationInstruction.createModelOnly(changeProcessor, contextForRoot); } else { - instruction = WfTaskCreationInstruction.createNoModelOperationRootJob(changeProcessor); + instruction = WfTaskCreationInstruction.createEmpty(changeProcessor); } instruction.setTaskName(determineRootTaskName(modelContext)); instruction.setTaskObject(determineRootTaskObject(modelContext)); instruction.setTaskOwner(taskFromModel.getOwner()); - instruction.setCreateTaskAsWaiting(true); + instruction.setCreateTaskAsWaiting(); return instruction; } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/ChangeProcessor.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/ChangeProcessor.java index 3049c8371cb..fc0e187d185 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/ChangeProcessor.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/ChangeProcessor.java @@ -21,7 +21,6 @@ import com.evolveum.midpoint.model.api.context.ModelContext; import com.evolveum.midpoint.model.api.hooks.HookOperationMode; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; @@ -33,11 +32,7 @@ import com.evolveum.midpoint.wf.impl.messages.ProcessEvent; import com.evolveum.midpoint.wf.impl.messages.TaskEvent; import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.WfProcessorSpecificStateType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.WorkItemContents; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; - -import javax.xml.bind.JAXBException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType; import java.util.Map; @@ -91,66 +86,36 @@ public interface ChangeProcessor { * Should leave the task in saved state (if finishing successfully). * * @param event - * @param task + * @param wfTask * @param result Here should be stored information about whether the finalization was successful or not * @throws SchemaException */ void onProcessEnd(ProcessEvent event, WfTask wfTask, OperationResult result) throws SchemaException, ObjectAlreadyExistsException, ObjectNotFoundException; - /** - * Externalizes internal state of the process instance. Typically, uninteresting (auxiliary) data elements - * are thrown away, internal representation suitable for workflow processing is replaced by "clean" prism - * object structure, and untyped Map[String,Object] is replaced by typed prism data. - * - * @param variables internal process state represented by a map - * @return external representation in the form of PrismObject - */ - PrismObject externalizeProcessInstanceState(Map variables) throws SchemaException; - - /** - * TODO - * @param variables - * @return - * @throws SchemaException - */ - WfProcessorSpecificStateType externalizeProcessorSpecificState(Map variables) throws SchemaException; - - /** - * Prepares a displayable work item contents. For example, in case of primary change processor, - * it returns a GeneralChangeApprovalWorkItemContents containing original object state - * (objectOld), to-be object state (objectNew), delta, additional object, and a situation-specific - * question form. - * - * @param task activiti task corresponding to the work item for which the contents is to be prepared - * @param processInstanceVariables variables of the process instance of which this task is a part - * @param result here the method stores its result - * @return - * @throws JAXBException - * @throws ObjectNotFoundException - * @throws SchemaException - */ - PrismObject externalizeWorkItemContents(org.activiti.engine.task.Task task, Map processInstanceVariables, OperationResult result) throws JAXBException, ObjectNotFoundException, SchemaException; - /** * Prepares a process instance-related audit record. * - * @param variables * @param wfTask * @param stage + * @param variables * @param result * @return */ - AuditEventRecord prepareProcessInstanceAuditRecord(Map variables, WfTask wfTask, AuditEventStage stage, OperationResult result); + AuditEventRecord prepareProcessInstanceAuditRecord(WfTask wfTask, AuditEventStage stage, Map variables, OperationResult result); /** * Prepares a work item-related audit record. * - * @param taskEvent - * @param stage - * @param result - * @return + * + * @param workItem + * @param wfTask + * @param taskEvent + * @param stage + * @param result + * @return */ - AuditEventRecord prepareWorkItemAuditRecord(TaskEvent taskEvent, AuditEventStage stage, OperationResult result) throws WorkflowException; + // workItem contains taskRef, assignee, candidates resolved (if possible) + AuditEventRecord prepareWorkItemAuditRecord(WorkItemNewType workItem, WfTask wfTask, TaskEvent taskEvent, AuditEventStage stage, OperationResult result) throws WorkflowException; /** * Auxiliary method to access autowired Spring beans from within non-spring java objects. diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GcpExternalizationHelper.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GcpExternalizationHelper.java index a78f3ec290b..ad51a24b6a7 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GcpExternalizationHelper.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GcpExternalizationHelper.java @@ -17,33 +17,12 @@ package com.evolveum.midpoint.wf.impl.processors.general; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectDefinition; -import com.evolveum.midpoint.prism.PrismProperty; -import com.evolveum.midpoint.prism.PrismPropertyDefinition; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.util.DOMUtil; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.wf.impl.activiti.ActivitiEngine; -import com.evolveum.midpoint.wf.impl.processes.common.CommonProcessVariableNames; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.WorkItemContents; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; - -import org.activiti.engine.form.FormProperty; -import org.activiti.engine.form.TaskFormData; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.xml.bind.JAXBException; -import javax.xml.namespace.QName; - -import java.util.Map; - /** * @author mederly */ @@ -58,38 +37,5 @@ public class GcpExternalizationHelper { @Autowired private ActivitiEngine activitiEngine; - public PrismObject createNewProcessInstanceState() { - return (PrismObject) prismContext.getSchemaRegistry().findObjectDefinitionByType(ProcessInstanceState.COMPLEX_TYPE).instantiate(); - } - - public PrismObject createNewWorkItemContents() { - PrismObjectDefinition wicDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByType(WorkItemContents.COMPLEX_TYPE); - PrismObject wicPrism = wicDefinition.instantiate(); - - PrismObjectDefinition formDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByType(QuestionFormType.COMPLEX_TYPE); - PrismObject formPrism = formDefinition.instantiate(); - - wicPrism.asObjectable().setQuestionForm(formPrism.asObjectable()); - return wicPrism; - } - - public void fillInQuestionForm(PrismObject formPrism, org.activiti.engine.task.Task task, Map processInstanceVariables, OperationResult result) throws JAXBException, ObjectNotFoundException, SchemaException { - TaskFormData data = activitiEngine.getFormService().getTaskFormData(task.getId()); - for (FormProperty formProperty : data.getFormProperties()) { - if (formProperty.isReadable() && !formProperty.getId().startsWith(CommonProcessVariableNames.FORM_BUTTON_PREFIX)) { - LOGGER.trace("- processing property {} having value {}", formProperty.getId(), formProperty.getValue()); - if (formProperty.getValue() != null) { - QName propertyName = new QName(SchemaConstants.NS_WFCF, formProperty.getId()); - PrismPropertyDefinition prismPropertyDefinition = new PrismPropertyDefinition<>(propertyName, DOMUtil.XSD_STRING, prismContext); - PrismProperty prismProperty = prismPropertyDefinition.instantiate(); - prismProperty.addRealValue(formProperty.getValue()); - formPrism.add(prismProperty); - } - } - } - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Resulting prism object instance = " + formPrism.debugDump()); - } - } } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GeneralChangeProcessor.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GeneralChangeProcessor.java index 54d4d47d6b7..96f9b0e11dc 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GeneralChangeProcessor.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GeneralChangeProcessor.java @@ -6,42 +6,29 @@ import com.evolveum.midpoint.model.api.hooks.HookOperationMode; import com.evolveum.midpoint.model.impl.lens.LensContext; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.CommunicationException; -import com.evolveum.midpoint.util.exception.ConfigurationException; -import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.wf.impl.activiti.ActivitiEngine; import com.evolveum.midpoint.wf.api.WorkflowException; +import com.evolveum.midpoint.wf.impl.activiti.ActivitiEngine; import com.evolveum.midpoint.wf.impl.jobs.WfTask; import com.evolveum.midpoint.wf.impl.jobs.WfTaskController; import com.evolveum.midpoint.wf.impl.jobs.WfTaskCreationInstruction; import com.evolveum.midpoint.wf.impl.jobs.WfTaskUtil; import com.evolveum.midpoint.wf.impl.messages.ProcessEvent; import com.evolveum.midpoint.wf.impl.messages.TaskEvent; -import com.evolveum.midpoint.wf.impl.processors.BaseAuditHelper; -import com.evolveum.midpoint.wf.impl.processors.BaseChangeProcessor; -import com.evolveum.midpoint.wf.impl.processors.BaseConfigurationHelper; -import com.evolveum.midpoint.wf.impl.processors.BaseExternalizationHelper; -import com.evolveum.midpoint.wf.impl.processors.BaseModelInvocationProcessingHelper; +import com.evolveum.midpoint.wf.impl.processors.*; import com.evolveum.midpoint.wf.impl.processors.general.scenarios.DefaultGcpScenarioBean; import com.evolveum.midpoint.wf.impl.processors.general.scenarios.GcpScenarioBean; import com.evolveum.midpoint.wf.impl.util.SerializationSafeContainer; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.WorkItemContents; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessSpecificState; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; -import javax.xml.bind.JAXBException; import java.util.Map; /** @@ -67,9 +54,6 @@ public class GeneralChangeProcessor extends BaseChangeProcessor { @Autowired private BaseModelInvocationProcessingHelper baseModelInvocationProcessingHelper; - @Autowired - private BaseExternalizationHelper baseExternalizationHelper; - @Autowired private BaseConfigurationHelper baseConfigurationHelper; @@ -206,34 +190,16 @@ public void onProcessEnd(ProcessEvent event, WfTask wfTask, OperationResult resu } //endregion - //region Externalization methods (including auditing) - @Override - public PrismObject externalizeWorkItemContents(org.activiti.engine.task.Task task, Map processInstanceVariables, OperationResult result) throws JAXBException, ObjectNotFoundException, SchemaException { - return getScenarioBean(processInstanceVariables).externalizeWorkItemContents(task, processInstanceVariables, result); - } - - @Override - public PrismObject externalizeProcessInstanceState(Map variables) throws SchemaException { - PrismObject state = baseExternalizationHelper.externalizeState(variables); - ProcessSpecificState processSpecificState = getScenarioBean(variables).externalizeInstanceState(variables); - state.asObjectable().setProcessSpecificState(processSpecificState); - return state; - } - - @Override - public WfProcessorSpecificStateType externalizeProcessorSpecificState(Map variables) - throws SchemaException { - throw new UnsupportedOperationException("Not implemented yet."); - } - + //region Auditing @Override - public AuditEventRecord prepareProcessInstanceAuditRecord(Map variables, WfTask wfTask, AuditEventStage stage, OperationResult result) { + public AuditEventRecord prepareProcessInstanceAuditRecord(WfTask wfTask, AuditEventStage stage, Map variables, OperationResult result) { return getScenarioBean(variables).prepareProcessInstanceAuditRecord(variables, wfTask, stage, result); } @Override - public AuditEventRecord prepareWorkItemAuditRecord(TaskEvent taskEvent, AuditEventStage stage, OperationResult result) throws WorkflowException { - return getScenarioBean(taskEvent.getVariables()).prepareWorkItemAuditRecord(taskEvent, stage, result); + public AuditEventRecord prepareWorkItemAuditRecord(WorkItemNewType workItem, WfTask wfTask, TaskEvent taskEvent, AuditEventStage stage, + OperationResult result) throws WorkflowException { + return getScenarioBean(taskEvent.getVariables()).prepareWorkItemAuditRecord(workItem, wfTask, taskEvent, stage, result); } //endregion } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GeneralChangeProcessorInstruction.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GeneralChangeProcessorInstruction.java new file mode 100644 index 00000000000..be63c585452 --- /dev/null +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/GeneralChangeProcessorInstruction.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2010-2016 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.wf.impl.processors.general; + +import com.evolveum.midpoint.model.api.context.ModelContext; +import com.evolveum.midpoint.model.impl.lens.LensContext; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.wf.impl.jobs.ProcessorInstruction; +import com.evolveum.midpoint.wf.impl.util.JaxbValueContainer; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfProcessorSpecificStateType; + +import java.util.Map; + +/** + * @author mederly + */ +public class GeneralChangeProcessorInstruction implements ProcessorInstruction { + + private String scenarioBeanName; + private LensContext modelContext; + + public GeneralChangeProcessorInstruction(LensContext context) { + this.modelContext = context; + } + + public void setScenarioBeanName(String scenarioBeanName) { + this.scenarioBeanName = scenarioBeanName; + } + + @Override public WfProcessorSpecificStateType createProcessorSpecificState() { + return null; + } + + @Override + public void createProcessVariables(Map map, PrismContext prismContext) throws SchemaException { + if (scenarioBeanName != null) { + map.put(GcpProcessVariableNames.VARIABLE_MIDPOINT_SCENARIO_BEAN_NAME, scenarioBeanName); + } + if (modelContext != null) { + map.put(GcpProcessVariableNames.VARIABLE_MODEL_CONTEXT, new JaxbValueContainer<>(modelContext.toLensContextType(), prismContext)); + } + } +} diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/scenarios/BaseGcpScenarioBean.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/scenarios/BaseGcpScenarioBean.java index df868f03383..bc2c46efdd8 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/scenarios/BaseGcpScenarioBean.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/scenarios/BaseGcpScenarioBean.java @@ -21,9 +21,7 @@ import com.evolveum.midpoint.model.api.context.ModelContext; import com.evolveum.midpoint.model.impl.lens.LensContext; import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.wf.api.WorkflowException; import com.evolveum.midpoint.wf.impl.jobs.WfTask; @@ -31,22 +29,14 @@ import com.evolveum.midpoint.wf.impl.messages.TaskEvent; import com.evolveum.midpoint.wf.impl.processes.DefaultProcessMidPointInterface; import com.evolveum.midpoint.wf.impl.processes.ProcessInterfaceFinder; -import com.evolveum.midpoint.wf.impl.processes.common.CommonProcessVariableNames; import com.evolveum.midpoint.wf.impl.processors.BaseAuditHelper; import com.evolveum.midpoint.wf.impl.processors.general.GcpExternalizationHelper; -import com.evolveum.midpoint.wf.impl.processors.general.GcpProcessVariableNames; -import com.evolveum.midpoint.wf.impl.util.JaxbValueContainer; +import com.evolveum.midpoint.wf.impl.processors.general.GeneralChangeProcessorInstruction; import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralChangeProcessorScenarioType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.LensContextType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.WorkItemContents; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessSpecificState; - -import org.activiti.engine.task.Task; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import javax.xml.bind.JAXBException; - import java.util.Map; /** @@ -78,46 +68,46 @@ public boolean determineActivation(GeneralChangeProcessorScenarioType scenarioTy return true; } - @Override - public PrismObject externalizeWorkItemContents(Task task, Map processInstanceVariables, OperationResult result) throws JAXBException, ObjectNotFoundException, SchemaException { - PrismObject prism = gcpExternalizationHelper.createNewWorkItemContents(); - gcpExternalizationHelper.fillInQuestionForm(prism.asObjectable().getQuestionForm().asPrismObject(), task, processInstanceVariables, result); - return prism; - } - - @Override - public ProcessSpecificState externalizeInstanceState(Map variables) throws SchemaException { - if (variables.containsKey(CommonProcessVariableNames.VARIABLE_PROCESS_INTERFACE_BEAN_NAME)) { - return processInterfaceFinder.getProcessInterface(variables).externalizeProcessInstanceState(variables); - } else { - return null; - } - } +// @Override +// public PrismObject externalizeWorkItemContents(Task task, Map processInstanceVariables, OperationResult result) throws JAXBException, ObjectNotFoundException, SchemaException { +// PrismObject prism = gcpExternalizationHelper.createNewWorkItemContents(); +// gcpExternalizationHelper.fillInQuestionForm(prism.asObjectable().getQuestionForm().asPrismObject(), task, processInstanceVariables, result); +// return prism; +// } + +// @Override +// public ProcessSpecificState externalizeInstanceState(Map variables) throws SchemaException { +// if (variables.containsKey(CommonProcessVariableNames.VARIABLE_PROCESS_INTERFACE_BEAN_NAME)) { +// return processInterfaceFinder.getProcessInterface(variables).externalizeProcessInstanceState(variables); +// } else { +// return null; +// } +// } @Override public AuditEventRecord prepareProcessInstanceAuditRecord(Map variables, WfTask wfTask, AuditEventStage stage, OperationResult result) { - return baseAuditHelper.prepareProcessInstanceAuditRecord(variables, wfTask, stage, result); + return baseAuditHelper.prepareProcessInstanceAuditRecord(wfTask, stage, variables, result); // TODO what with missing data (delta, result)? We could at least attempt to determine them ... } @Override - public AuditEventRecord prepareWorkItemAuditRecord(TaskEvent taskEvent, AuditEventStage stage, OperationResult result) throws WorkflowException { - return baseAuditHelper.prepareWorkItemAuditRecord(taskEvent, stage, result); + public AuditEventRecord prepareWorkItemAuditRecord(WorkItemNewType workItem, WfTask wfTask, TaskEvent taskEvent, AuditEventStage stage, + OperationResult result) throws WorkflowException { + return baseAuditHelper.prepareWorkItemAuditRecord(workItem, wfTask, taskEvent, stage, result); // TODO fill-in missing delta somehow } @Override public WfTaskCreationInstruction prepareJobCreationInstruction(GeneralChangeProcessorScenarioType scenarioType, LensContext context, WfTask rootWfTask, com.evolveum.midpoint.task.api.Task taskFromModel, OperationResult result) throws SchemaException { - WfTaskCreationInstruction instruction = WfTaskCreationInstruction.createWfProcessChildJob(rootWfTask); - instruction.setProcessDefinitionKey(scenarioType.getProcessName()); - if (scenarioType.getBeanName() != null) { - instruction.addProcessVariable(GcpProcessVariableNames.VARIABLE_MIDPOINT_SCENARIO_BEAN_NAME, scenarioType.getBeanName()); - } - instruction.setRequesterOidAndRefInProcess(taskFromModel.getOwner()); + + GeneralChangeProcessorInstruction processorInstruction = new GeneralChangeProcessorInstruction(context); + processorInstruction.setScenarioBeanName(scenarioType.getBeanName()); + + WfTaskCreationInstruction instruction = WfTaskCreationInstruction.createWfOnly(rootWfTask.getChangeProcessor(), processorInstruction, null); + instruction.setProcessName(scenarioType.getProcessName()); + instruction.setRequesterRef(taskFromModel.getOwner()); instruction.setTaskName("Workflow-monitoring task"); instruction.setProcessInterfaceBean(defaultProcessMidPointInterface); - LensContextType lensContextType = context.toLensContextType(); - instruction.addProcessVariable(GcpProcessVariableNames.VARIABLE_MODEL_CONTEXT, new JaxbValueContainer<>(lensContextType, prismContext)); return instruction; } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/scenarios/GcpScenarioBean.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/scenarios/GcpScenarioBean.java index 9f5963b7836..7cf45f02501 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/scenarios/GcpScenarioBean.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/general/scenarios/GcpScenarioBean.java @@ -20,20 +20,15 @@ import com.evolveum.midpoint.audit.api.AuditEventStage; import com.evolveum.midpoint.model.api.context.ModelContext; import com.evolveum.midpoint.model.impl.lens.LensContext; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.wf.api.WorkflowException; import com.evolveum.midpoint.wf.impl.jobs.WfTask; import com.evolveum.midpoint.wf.impl.jobs.WfTaskCreationInstruction; import com.evolveum.midpoint.wf.impl.messages.TaskEvent; import com.evolveum.midpoint.xml.ns._public.common.common_3.GeneralChangeProcessorScenarioType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.WorkItemContents; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessSpecificState; - -import javax.xml.bind.JAXBException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WorkItemNewType; import java.util.Map; @@ -54,13 +49,9 @@ public interface GcpScenarioBean { */ boolean determineActivation(GeneralChangeProcessorScenarioType scenarioType, ModelContext context, Task taskFromModel, OperationResult result); - PrismObject externalizeWorkItemContents(org.activiti.engine.task.Task task, Map processInstanceVariables, OperationResult result) throws JAXBException, ObjectNotFoundException, SchemaException; - - ProcessSpecificState externalizeInstanceState(Map variables) throws SchemaException; - AuditEventRecord prepareProcessInstanceAuditRecord(Map variables, WfTask wfTask, AuditEventStage stage, OperationResult result); - AuditEventRecord prepareWorkItemAuditRecord(TaskEvent taskEvent, AuditEventStage stage, OperationResult result) throws WorkflowException; + AuditEventRecord prepareWorkItemAuditRecord(WorkItemNewType workItem, WfTask wfTask, TaskEvent taskEvent, AuditEventStage stage, OperationResult result) throws WorkflowException; WfTaskCreationInstruction prepareJobCreationInstruction(GeneralChangeProcessorScenarioType scenarioType, LensContext context, WfTask rootWfTask, Task taskFromModel, OperationResult result) throws SchemaException; } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/ObjectTreeDeltas.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/ObjectTreeDeltas.java index 48998a71d8f..3e009b09c59 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/ObjectTreeDeltas.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/ObjectTreeDeltas.java @@ -148,6 +148,14 @@ public static String toObjectTreeDeltasTypeXml(ObjectTreeDeltas objectTreeDeltas return objectTreeDeltas != null ? objectTreeDeltas.toObjectTreeDeltasTypeXml() : null; } + public static String toObjectTreeDeltasTypeXml(ObjectTreeDeltasType objectTreeDeltasType, PrismContext prismContext) throws SchemaException { + if (objectTreeDeltasType != null) { + return prismContext.serializeAtomicValue(objectTreeDeltasType, SchemaConstantsGenerated.C_OBJECT_TREE_DELTAS, PrismContext.LANG_XML); + } else { + return null; + } + } + public static ObjectTreeDeltasType toObjectTreeDeltasType(ObjectTreeDeltas objectTreeDeltas) throws SchemaException { return objectTreeDeltas != null ? objectTreeDeltas.toObjectTreeDeltasType() : null; } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpChildWfTaskCreationInstruction.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpChildWfTaskCreationInstruction.java index e964455d673..e1ae5b93d20 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpChildWfTaskCreationInstruction.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpChildWfTaskCreationInstruction.java @@ -19,127 +19,73 @@ import com.evolveum.midpoint.model.api.ModelExecuteOptions; import com.evolveum.midpoint.model.api.context.ModelContext; import com.evolveum.midpoint.model.impl.lens.LensContext; -import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ObjectDelta; -import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.ObjectTypeUtil; -import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.DebugUtil; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.exception.SystemException; +import com.evolveum.midpoint.wf.impl.jobs.ProcessInstruction; import com.evolveum.midpoint.wf.impl.jobs.WfTask; import com.evolveum.midpoint.wf.impl.jobs.WfTaskCreationInstruction; -import com.evolveum.midpoint.wf.impl.processes.common.CommonProcessVariableNames; -import com.evolveum.midpoint.wf.impl.processes.common.LightweightObjectRefImpl; -import com.evolveum.midpoint.wf.impl.processes.common.StringHolder; +import com.evolveum.midpoint.wf.impl.processes.itemApproval.ApprovalRequest; +import com.evolveum.midpoint.wf.impl.processes.itemApproval.ItemApprovalInstruction; import com.evolveum.midpoint.wf.impl.processors.ChangeProcessor; import com.evolveum.midpoint.wf.impl.processors.primary.aspect.PrimaryChangeAspect; -import com.evolveum.midpoint.wf.impl.util.MiscDataUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import static com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType.F_WORKFLOW_CONTEXT; -import static com.evolveum.midpoint.xml.ns._public.common.common_3.WfContextType.F_PROCESSOR_SPECIFIC_STATE; - /** * @author mederly */ -public class PcpChildWfTaskCreationInstruction extends WfTaskCreationInstruction { - - private String aspectClassName; - private ObjectTreeDeltasType deltasToProcess; - private boolean executeApprovedChangeImmediately; // should the child job execute approved change immediately (i.e. executeModelOperationHandler must be set as well!) - - protected PcpChildWfTaskCreationInstruction(ChangeProcessor changeProcessor) { - super(changeProcessor); - } - - protected PcpChildWfTaskCreationInstruction(WfTask parentWfTask) { - super(parentWfTask); - } +public class PcpChildWfTaskCreationInstruction extends WfTaskCreationInstruction { - public static PcpChildWfTaskCreationInstruction createInstruction(ChangeProcessor changeProcessor) { - PcpChildWfTaskCreationInstruction pcpjci = new PcpChildWfTaskCreationInstruction(changeProcessor); - prepareWfProcessChildJobInternal(pcpjci); - return pcpjci; + protected PcpChildWfTaskCreationInstruction(ChangeProcessor changeProcessor, PI processInstruction) { + super(changeProcessor, new PrimaryChangeProcessorInstruction(changeProcessor.getPrismContext()), processInstruction); } - public static PcpChildWfTaskCreationInstruction createInstruction(WfTask parentWfTask) { - PcpChildWfTaskCreationInstruction pcpjci = new PcpChildWfTaskCreationInstruction(parentWfTask); - prepareWfProcessChildJobInternal(pcpjci); - return pcpjci; - } + // useful shortcut + public static PcpChildWfTaskCreationInstruction createItemApprovalInstruction(ChangeProcessor changeProcessor, String approvalTaskName, + ApprovalRequest approvalRequest) { + ItemApprovalInstruction itemApprovalInstruction = new ItemApprovalInstruction(); + itemApprovalInstruction.setTaskName(approvalTaskName); + itemApprovalInstruction.setApprovalSchema(approvalRequest.getApprovalSchema()); + PcpChildWfTaskCreationInstruction pcpjci = new PcpChildWfTaskCreationInstruction(changeProcessor, itemApprovalInstruction); + return pcpjci; + } public boolean isExecuteApprovedChangeImmediately() { - return executeApprovedChangeImmediately; - } - - public void setExecuteApprovedChangeImmediately(boolean executeApprovedChangeImmediately) { - this.executeApprovedChangeImmediately = executeApprovedChangeImmediately; + return processorInstruction.isExecuteApprovedChangeImmediately(); } public void prepareCommonAttributes(PrimaryChangeAspect aspect, ModelContext modelContext, String objectOid, PrismObject requester) throws SchemaException { - setRequesterOidAndRefInProcess(requester); + setRequesterRef(requester); - setExecuteApprovedChangeImmediately(ModelExecuteOptions.isExecuteImmediatelyAfterApproval(((LensContext) modelContext).getOptions())); + processorInstruction.setExecuteApprovedChangeImmediately(ModelExecuteOptions.isExecuteImmediatelyAfterApproval(((LensContext) modelContext).getOptions())); - addProcessVariable(PcpProcessVariableNames.VARIABLE_MIDPOINT_CHANGE_ASPECT, aspect.getClass().getName()); - aspectClassName = aspect.getClass().getName(); + processorInstruction.createProcessorSpecificState().setChangeAspect(aspect.getClass().getName()); if (isExecuteApprovedChangeImmediately()) { // actually, context should be emptied anyway; but to be sure, let's do it here as well - addTaskModelContext(((PrimaryChangeProcessor) getChangeProcessor()).contextCopyWithNoDelta((LensContext) modelContext)); + setTaskModelContext(((PrimaryChangeProcessor) getChangeProcessor()).contextCopyWithNoDelta((LensContext) modelContext)); setExecuteModelOperationHandler(true); } } @Deprecated - public void setDeltaProcessAndTaskVariables(ObjectDelta delta) { - setObjectTreeDeltasProcessAndTaskVariables(new ObjectTreeDeltas(delta, getChangeProcessor().getPrismContext())); + public void setDeltasToProcess(ObjectDelta delta) { + setDeltasToProcesses(new ObjectTreeDeltas(delta, getChangeProcessor().getPrismContext())); } - public void setObjectTreeDeltasProcessAndTaskVariables(ObjectTreeDeltas objectTreeDeltas) { + public void setDeltasToProcesses(ObjectTreeDeltas objectTreeDeltas) { try { - addProcessVariable(PcpProcessVariableNames.VARIABLE_MIDPOINT_OBJECT_TREE_DELTAS, - new StringHolder(ObjectTreeDeltas.toObjectTreeDeltasTypeXml(objectTreeDeltas))); - } catch (SchemaException e) { - throw new SystemException("Couldn't store primary delta(s) into the process variable due to schema exception", e); - } - - try { - deltasToProcess = ObjectTreeDeltas.toObjectTreeDeltasType(objectTreeDeltas); + processorInstruction.createProcessorSpecificState().setDeltasToProcess(ObjectTreeDeltas.toObjectTreeDeltasType(objectTreeDeltas)); } catch (SchemaException e) { throw new SystemException("Couldn't store primary delta(s) into the task variable due to schema exception", e); } } - public void setObjectRefVariable(ObjectReferenceType ref, OperationResult result) { - if (ref != null) { - ref = getChangeProcessor().getWorkflowManager().getMiscDataUtil().resolveObjectReferenceName(ref, result); - addProcessVariable(CommonProcessVariableNames.VARIABLE_OBJECT_REF, new LightweightObjectRefImpl(ref)); - } else { - removeProcessVariable(CommonProcessVariableNames.VARIABLE_OBJECT_REF); - } - } - - public void setObjectRefVariable(ModelContext modelContext, OperationResult result) { - ObjectType focus = MiscDataUtil.getFocusObjectNewOrOld(modelContext); - setObjectRefVariable(ObjectTypeUtil.createObjectRef(focus), result); - } - - public void setTargetRefVariable(ObjectReferenceType ref, OperationResult result) { - if (ref != null) { - ref = getChangeProcessor().getWorkflowManager().getMiscDataUtil().resolveObjectReferenceName(ref, result); - addProcessVariable(CommonProcessVariableNames.VARIABLE_TARGET_REF, new LightweightObjectRefImpl(ref)); - } else { - removeProcessVariable(CommonProcessVariableNames.VARIABLE_TARGET_REF); - } - } - - public String getAspectClassName() { - return aspectClassName; + public String getAspectClassName() { + return processorInstruction.createProcessorSpecificState().getChangeAspect(); } @Override @@ -148,24 +94,10 @@ public String debugDump(int indent) { DebugUtil.indentDebugDump(sb, indent); sb.append("PrimaryChangeProcessor ChildJobCreationInstruction: (execute approved change immediately = ") - .append(executeApprovedChangeImmediately) + .append(isExecuteApprovedChangeImmediately()) .append(")\n"); sb.append(super.debugDump(indent+1)); return sb.toString(); } - @Override - public void tailorTask(Task task) throws SchemaException { - super.tailorTask(task); - - PrismContext prismContext = getChangeProcessor().getPrismContext(); - WfPrimaryChangeProcessorStateType state = new WfPrimaryChangeProcessorStateType(); - state.setChangeAspect(aspectClassName); - state.setDeltasToProcess(deltasToProcess); - state.asPrismContainerValue().setConcreteType(WfPrimaryChangeProcessorStateType.COMPLEX_TYPE); - task.addModification( - DeltaBuilder.deltaFor(TaskType.class, prismContext) - .item(F_WORKFLOW_CONTEXT, F_PROCESSOR_SPECIFIC_STATE).replace(state) - .asItemDelta()); - } } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpExternalizationHelper.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpExternalizationHelper.java deleted file mode 100644 index 8a18c0d8a40..00000000000 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpExternalizationHelper.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2010-2014 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.wf.impl.processors.primary; - -import com.evolveum.midpoint.prism.PrismContainer; -import com.evolveum.midpoint.prism.PrismContainerDefinition; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.MiscSchemaUtil; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.wf.impl.util.MiscDataUtil; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.WfPrimaryChangeProcessorStateType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.GeneralChangeApprovalWorkItemContents; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.WorkItemContents; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.PrimaryChangeProcessorState; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.xml.bind.JAXBException; - -import java.util.Map; - -/** - * @author mederly - */ -@Component -public class PcpExternalizationHelper { - - @Autowired - private PcpRepoAccessHelper pcpRepoAccessHelper; - - @Autowired - private PrismContext prismContext; - - @Autowired - private PrimaryChangeProcessor primaryChangeProcessor; - - @Autowired - private MiscDataUtil miscDataUtil; - - @Deprecated - public PrimaryChangeProcessorState externalizeState(Map variables) throws SchemaException { - PrismContainerDefinition extDefinition = prismContext.getSchemaRegistry().findContainerDefinitionByType(PrimaryChangeProcessorState.COMPLEX_TYPE); - PrismContainer extStateContainer = extDefinition.instantiate(); - PrimaryChangeProcessorState state = extStateContainer.createNewValue().asContainerable(); - - state.setChangeAspect((String) variables.get(PcpProcessVariableNames.VARIABLE_MIDPOINT_CHANGE_ASPECT)); - - String objectXml = (String) variables.get(PcpProcessVariableNames.VARIABLE_MIDPOINT_OBJECT_TO_BE_ADDED); - if (objectXml != null) { - ObjectType objectToBeAdded = (ObjectType) prismContext.parseObject(objectXml, PrismContext.LANG_XML).asObjectable(); - state.setObjectToBeAdded(objectToBeAdded); - } - //state.setFocusDelta(miscDataUtil.getFocusPrimaryObjectDeltaType(variables, true)); - state.asPrismContainerValue().setConcreteType(PrimaryChangeProcessorState.COMPLEX_TYPE); - return state; - } - - public WfPrimaryChangeProcessorStateType externalizeStateNew(Map variables) throws SchemaException { - WfPrimaryChangeProcessorStateType state = new WfPrimaryChangeProcessorStateType(prismContext); - - state.setChangeAspect((String) variables.get(PcpProcessVariableNames.VARIABLE_MIDPOINT_CHANGE_ASPECT)); - state.setDeltasToProcess(miscDataUtil.getObjectTreeDeltaType(variables, true)); - - state.asPrismContainerValue().setConcreteType(WfPrimaryChangeProcessorStateType.COMPLEX_TYPE); - return state; - } - - public PrismObject externalizeWorkItemContents(org.activiti.engine.task.Task task, Map processInstanceVariables, OperationResult result) throws JAXBException, ObjectNotFoundException, SchemaException { - - PrismObject wicPrism = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(GeneralChangeApprovalWorkItemContents.class).instantiate(); - GeneralChangeApprovalWorkItemContents wic = wicPrism.asObjectable(); - - wic.setObjectDelta(miscDataUtil.getFocusPrimaryObjectDeltaType(processInstanceVariables, true)); - - wic.setQuestionForm(asObjectable(getQuestionForm(task, processInstanceVariables, result))); - return wicPrism; - } - - private PrismObject getQuestionForm(org.activiti.engine.task.Task task, Map variables, OperationResult result) throws SchemaException, ObjectNotFoundException { - return primaryChangeProcessor.getChangeAspect(variables).prepareQuestionForm(task, variables, result); - } - - private PrismObject getRelatedObject(org.activiti.engine.task.Task task, Map variables, OperationResult result) throws SchemaException, ObjectNotFoundException { - return primaryChangeProcessor.getChangeAspect(variables).prepareRelatedObject(task, variables, result); - } - - private T asObjectable(PrismObject prismObject) { - return prismObject != null ? prismObject.asObjectable() : null; - } - -} diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpProcessVariableNames.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpProcessVariableNames.java index d9f5723487e..20980080621 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpProcessVariableNames.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpProcessVariableNames.java @@ -23,14 +23,14 @@ */ public class PcpProcessVariableNames { - // Java class name of the process aspect (the same as wf:primaryChangeAspect task property) [String] - public static final String VARIABLE_MIDPOINT_CHANGE_ASPECT = "midPointChangeAspect"; + // Java class name of the process aspect [String] + public static final String VARIABLE_CHANGE_ASPECT = "changeAspect"; - // Object that is about to be added (for ADD operation). [ObjectType] - public static final String VARIABLE_MIDPOINT_OBJECT_TO_BE_ADDED = "midPointObjectToBeAdded"; +// // Object that is about to be added (for ADD operation). [ObjectType] +// public static final String VARIABLE_MIDPOINT_OBJECT_TO_BE_ADDED = "midPointObjectToBeAdded"; - // XML representation of the deltas to be approved. (Note that technically a process - // can approve more than one focus/projection deltas; if necessary, this variable would have to be changed.) - // [StringHolder] - public static final String VARIABLE_MIDPOINT_OBJECT_TREE_DELTAS = "midPointObjectTreeDeltas"; +// // XML representation of the deltas to be approved. (Note that technically a process +// // can approve more than one focus/projection deltas; if necessary, this variable would have to be changed.) +// // [StringHolder] +// public static final String VARIABLE_MIDPOINT_OBJECT_TREE_DELTAS = "midPointObjectTreeDeltas"; } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpWfTask.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpWfTask.java index 38dca5c9db1..7a944fc321a 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpWfTask.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PcpWfTask.java @@ -1,8 +1,11 @@ package com.evolveum.midpoint.wf.impl.processors.primary; +import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.wf.impl.jobs.WfTask; +import com.evolveum.midpoint.wf.impl.jobs.WfTaskController; import com.evolveum.midpoint.wf.impl.jobs.WfTaskUtil; +import com.evolveum.midpoint.wf.impl.processors.ChangeProcessor; import com.evolveum.midpoint.wf.impl.processors.primary.aspect.PrimaryChangeAspect; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; @@ -19,6 +22,10 @@ public class PcpWfTask extends WfTask { super(original); } + public PcpWfTask(WfTaskController wfTaskController, Task task, String processInstanceId, ChangeProcessor changeProcessor) { + super(wfTaskController, task, processInstanceId, changeProcessor); + } + public PrimaryChangeAspect getChangeAspect() { return getWfTaskUtil().getPrimaryChangeAspect(getTask(), getPcp().getAllChangeAspects()); } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java index 90f78187162..f8e0764086f 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessor.java @@ -23,18 +23,12 @@ import com.evolveum.midpoint.model.api.hooks.HookOperationMode; import com.evolveum.midpoint.model.impl.lens.LensContext; import com.evolveum.midpoint.model.impl.lens.LensProjectionContext; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.schema.ObjectDeltaOperation; import com.evolveum.midpoint.schema.ResourceShadowDiscriminator; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.CommunicationException; -import com.evolveum.midpoint.util.exception.ConfigurationException; -import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SystemException; +import com.evolveum.midpoint.util.exception.*; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; @@ -49,31 +43,22 @@ import com.evolveum.midpoint.wf.impl.processors.BaseAuditHelper; import com.evolveum.midpoint.wf.impl.processors.BaseChangeProcessor; import com.evolveum.midpoint.wf.impl.processors.BaseConfigurationHelper; -import com.evolveum.midpoint.wf.impl.processors.BaseExternalizationHelper; import com.evolveum.midpoint.wf.impl.processors.BaseModelInvocationProcessingHelper; import com.evolveum.midpoint.wf.impl.processors.primary.aspect.PrimaryChangeAspect; import com.evolveum.midpoint.wf.impl.util.MiscDataUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.WorkItemContents; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessInstanceState; import org.apache.commons.lang.Validate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; -import javax.xml.bind.JAXBException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; +import static com.evolveum.midpoint.audit.api.AuditEventStage.EXECUTION; +import static com.evolveum.midpoint.audit.api.AuditEventStage.REQUEST; import static com.evolveum.midpoint.model.api.context.ModelState.PRIMARY; import static com.evolveum.midpoint.wf.impl.processors.primary.ObjectTreeDeltas.extractFromModelContext; -import static com.evolveum.midpoint.wf.impl.processors.primary.PrimaryChangeProcessor.ExecutionMode.ALL_AFTERWARDS; -import static com.evolveum.midpoint.wf.impl.processors.primary.PrimaryChangeProcessor.ExecutionMode.ALL_IMMEDIATELY; -import static com.evolveum.midpoint.wf.impl.processors.primary.PrimaryChangeProcessor.ExecutionMode.MIXED; +import static com.evolveum.midpoint.wf.impl.processors.primary.PrimaryChangeProcessor.ExecutionMode.*; /** * @author mederly @@ -92,15 +77,9 @@ public class PrimaryChangeProcessor extends BaseChangeProcessor { @Autowired private BaseModelInvocationProcessingHelper baseModelInvocationProcessingHelper; - @Autowired - private BaseExternalizationHelper baseExternalizationHelper; - @Autowired private BaseAuditHelper baseAuditHelper; - @Autowired - private PcpExternalizationHelper pcpExternalizationHelper; - @Autowired private WfTaskUtil wfTaskUtil; @@ -191,18 +170,19 @@ private List gatherStartInstructions(ModelCon // tweaking the instructions returned from aspects a bit... // if we are adding a new object, we have to set OBJECT_TO_BE_ADDED variable in all instructions - ObjectDelta focusChange = changesBeingDecomposed.getFocusChange(); - if (focusChange != null && focusChange.isAdd() && focusChange.getObjectToAdd() != null) { - String objectToBeAdded; - try { - objectToBeAdded = MiscDataUtil.serializeObjectToXml(focusChange.getObjectToAdd()); - } catch (SystemException e) { - throw new SystemException("Couldn't serialize object to be added to XML", e); - } - for (PcpChildWfTaskCreationInstruction instruction : startProcessInstructions) { - instruction.addProcessVariable(PcpProcessVariableNames.VARIABLE_MIDPOINT_OBJECT_TO_BE_ADDED, objectToBeAdded); - } - } +// ObjectDelta focusChange = changesBeingDecomposed.getFocusChange(); +// if (focusChange != null && focusChange.isAdd() && focusChange.getObjectToAdd() != null) { +// String objectToBeAdded; +// try { +// objectToBeAdded = MiscDataUtil.serializeObjectToXml(focusChange.getObjectToAdd()); +// } catch (SystemException e) { +// throw new SystemException("Couldn't serialize object to be added to XML", e); +// } +// for (PcpChildWfTaskCreationInstruction instruction : startProcessInstructions) { +// //instruction.addProcessVariable(PcpProcessVariableNames.VARIABLE_MIDPOINT_OBJECT_TO_BE_ADDED, objectToBeAdded); +// SPRAV S TYMTO NIECO +// } +// } for (PcpChildWfTaskCreationInstruction instruction : startProcessInstructions) { if (instruction.startsWorkflowProcess() && instruction.isExecuteApprovedChangeImmediately()) { @@ -294,12 +274,12 @@ private WfTask createRootJob(ModelContext context, ObjectTreeDeltas changesWitho private WfTask createJob0(ModelContext context, ObjectTreeDeltas changesWithoutApproval, WfTask rootWfTask, ExecutionMode executionMode, OperationResult result) throws SchemaException, ObjectNotFoundException { if (changesWithoutApproval != null && !changesWithoutApproval.isEmpty() && executionMode != ALL_AFTERWARDS) { ModelContext modelContext = contextCopyWithDeltaReplaced(context, changesWithoutApproval); - WfTaskCreationInstruction instruction0 = WfTaskCreationInstruction.createModelOperationChildJob(rootWfTask, modelContext); + WfTaskCreationInstruction instruction0 = WfTaskCreationInstruction.createModelOnly(rootWfTask.getChangeProcessor(), modelContext); instruction0.setTaskName("Executing changes that do not require approval"); if (context.getFocusContext().getPrimaryDelta().isAdd()) { instruction0.setHandlersAfterModelOperation(WfPropagateTaskObjectReferenceTaskHandler.HANDLER_URI); // for add operations we have to propagate ObjectOID } - instruction0.setCreateTaskAsSuspended(true); // task0 should execute only after all subtasks are created, because when it finishes, it + instruction0.setCreateTaskAsSuspended(); // task0 should execute only after all subtasks are created, because when it finishes, it // writes some information to all dependent tasks (i.e. they must exist at that time) return wfTaskController.createWfTask(instruction0, rootWfTask, result); } else { @@ -382,46 +362,23 @@ public void onProcessEnd(ProcessEvent event, WfTask wfTask, OperationResult resu pcpJob.storeResultingDeltas(aspect.prepareDeltaOut(event, pcpJob, result)); pcpJob.addApprovedBy(aspect.prepareApprovedBy(event, pcpJob, result)); - pcpJob.commitChanges(result); - } - //endregion - - @Override - public PrismObject externalizeProcessInstanceState(Map variables) throws SchemaException { - - PrismObject processInstanceStatePrismObject = baseExternalizationHelper.externalizeState(variables); - processInstanceStatePrismObject.asObjectable().setProcessorSpecificState(pcpExternalizationHelper.externalizeState(variables)); - processInstanceStatePrismObject.asObjectable().setProcessSpecificState(getChangeAspect(variables).externalizeProcessInstanceState(variables)); - return processInstanceStatePrismObject; - } - - @Override - public WfProcessorSpecificStateType externalizeProcessorSpecificState(Map variables) throws SchemaException { - return pcpExternalizationHelper.externalizeStateNew(variables); - } - - @Override - public PrismObject externalizeWorkItemContents(org.activiti.engine.task.Task task, Map processInstanceVariables, OperationResult result) throws JAXBException, ObjectNotFoundException, SchemaException { - return pcpExternalizationHelper.externalizeWorkItemContents(task, processInstanceVariables, result); } //endregion //region Auditing @Override - public AuditEventRecord prepareProcessInstanceAuditRecord(Map variables, WfTask wfTask, AuditEventStage stage, OperationResult result) { - AuditEventRecord auditEventRecord = baseAuditHelper.prepareProcessInstanceAuditRecord(variables, wfTask, stage, result); + public AuditEventRecord prepareProcessInstanceAuditRecord(WfTask wfTask, AuditEventStage stage, Map variables, OperationResult result) { + AuditEventRecord auditEventRecord = baseAuditHelper.prepareProcessInstanceAuditRecord(wfTask, stage, variables, result); - ObjectTreeDeltas deltas = null; + ObjectTreeDeltas deltas = null; try { - if (stage == AuditEventStage.REQUEST) { + if (stage == REQUEST) { deltas = wfTaskUtil.retrieveDeltasToProcess(wfTask.getTask()); - //LOGGER.info("### deltas to process = {}", deltas); } else { deltas = wfTaskUtil.retrieveResultingDeltas(wfTask.getTask()); - //LOGGER.info("### resulting deltas = {}", deltas); } } catch (SchemaException e) { - LoggingUtils.logException(LOGGER, "Couldn't retrieve delta(s) from task " + wfTask.getTask(), e); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't retrieve delta(s) from task " + wfTask.getTask(), e); } if (deltas != null) { List deltaList = deltas.getDeltaList(); @@ -430,29 +387,32 @@ public AuditEventRecord prepareProcessInstanceAuditRecord(Map va } } - if (stage == AuditEventStage.EXECUTION) { - auditEventRecord.setResult(processInterfaceFinder.getProcessInterface(variables).getAnswer(variables)); + if (stage == EXECUTION) { + auditEventRecord.setResult(wfTask.getAnswer()); } return auditEventRecord; } @Override - public AuditEventRecord prepareWorkItemAuditRecord(TaskEvent taskEvent, AuditEventStage stage, OperationResult result) throws WorkflowException { - AuditEventRecord auditEventRecord = baseAuditHelper.prepareWorkItemAuditRecord(taskEvent, stage, result); - ObjectTreeDeltas deltas = null; + public AuditEventRecord prepareWorkItemAuditRecord(WorkItemNewType workItem, WfTask wfTask, TaskEvent taskEvent, AuditEventStage stage, + OperationResult result) throws WorkflowException { + AuditEventRecord auditEventRecord = baseAuditHelper.prepareWorkItemAuditRecord(workItem, wfTask, taskEvent, stage, result); + + ObjectTreeDeltas deltas = null; try { - deltas = miscDataUtil.getObjectTreeDeltas(taskEvent.getVariables(), true); - if (deltas != null) { - List deltaList = deltas.getDeltaList(); - for (ObjectDelta delta : deltaList) { - auditEventRecord.addDelta(new ObjectDeltaOperation(delta)); - } - } - } catch (JAXBException|SchemaException e) { - LoggingUtils.logException(LOGGER, "Couldn't retrieve delta to be approved", e); + deltas = getWfTaskUtil().retrieveDeltasToProcess(wfTask.getTask()); + } catch (SchemaException e) { + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't retrieve deltas to be put into audit record", e); } - return auditEventRecord; + + if (deltas != null) { + for (ObjectDelta delta : deltas.getDeltaList()) { + auditEventRecord.addDelta(new ObjectDeltaOperation(delta)); + } + } + + return auditEventRecord; } //endregion @@ -463,7 +423,7 @@ public Collection getAllChangeAspects() { } PrimaryChangeAspect getChangeAspect(Map variables) { - String aspectClassName = (String) variables.get(PcpProcessVariableNames.VARIABLE_MIDPOINT_CHANGE_ASPECT); + String aspectClassName = (String) variables.get(PcpProcessVariableNames.VARIABLE_CHANGE_ASPECT); return findPrimaryChangeAspect(aspectClassName); } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessorInstruction.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessorInstruction.java new file mode 100644 index 00000000000..6036e249098 --- /dev/null +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/PrimaryChangeProcessorInstruction.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2010-2016 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.wf.impl.processors.primary; + +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.wf.impl.jobs.ProcessorInstruction; +import com.evolveum.midpoint.xml.ns._public.common.common_3.WfPrimaryChangeProcessorStateType; + +import java.util.Map; + +/** + * @author mederly + */ +public class PrimaryChangeProcessorInstruction implements ProcessorInstruction { + + private final WfPrimaryChangeProcessorStateType processorState; + private boolean executeApprovedChangeImmediately; // should the child job execute approved change immediately (i.e. executeModelOperationHandler must be set as well!) + + public PrimaryChangeProcessorInstruction(PrismContext prismContext) { + processorState = new WfPrimaryChangeProcessorStateType(prismContext); + processorState.asPrismContainerValue().setConcreteType(WfPrimaryChangeProcessorStateType.COMPLEX_TYPE); + } + + public WfPrimaryChangeProcessorStateType createProcessorSpecificState() { + return processorState; + } + + public boolean isExecuteApprovedChangeImmediately() { + return executeApprovedChangeImmediately; + } + + public void setExecuteApprovedChangeImmediately(boolean executeApprovedChangeImmediately) { + this.executeApprovedChangeImmediately = executeApprovedChangeImmediately; + } + + @Override public void createProcessVariables(Map map, PrismContext prismContext) throws SchemaException { + map.put(PcpProcessVariableNames.VARIABLE_CHANGE_ASPECT, processorState.getChangeAspect()); + } +} diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/BasePrimaryChangeAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/BasePrimaryChangeAspect.java index 3799149e3ff..0009487a7ab 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/BasePrimaryChangeAspect.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/BasePrimaryChangeAspect.java @@ -32,15 +32,12 @@ import com.evolveum.midpoint.wf.impl.processors.primary.PrimaryChangeProcessor; 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.model.workflow.process_instance_state_3.ProcessSpecificState; - 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 java.util.List; -import java.util.Map; /** * @author mederly @@ -100,11 +97,6 @@ public List prepareApprovedBy(ProcessEvent event, PcpWfTask return processInterfaceFinder.getProcessInterface(event.getVariables()).prepareApprovedBy(event); } - @Override - public ProcessSpecificState externalizeProcessInstanceState(Map variables) { - return processInterfaceFinder.getProcessInterface(variables).externalizeProcessInstanceState(variables); - } - public PrimaryChangeProcessor getChangeProcessor() { return changeProcessor; } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/PrimaryChangeAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/PrimaryChangeAspect.java index 56d20e1a6af..c3bfc7f745e 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/PrimaryChangeAspect.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/aspect/PrimaryChangeAspect.java @@ -17,7 +17,6 @@ package com.evolveum.midpoint.wf.impl.processors.primary.aspect; import com.evolveum.midpoint.model.api.context.ModelContext; -import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; @@ -28,14 +27,10 @@ import com.evolveum.midpoint.wf.impl.processors.primary.PcpChildWfTaskCreationInstruction; import com.evolveum.midpoint.wf.impl.processors.primary.PcpWfTask; import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; import com.evolveum.midpoint.xml.ns._public.common.common_3.PrimaryChangeProcessorConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType; -import com.evolveum.midpoint.xml.ns.model.workflow.process_instance_state_3.ProcessSpecificState; import java.util.List; -import java.util.Map; /** * @@ -101,46 +96,6 @@ public interface PrimaryChangeAspect { */ List prepareApprovedBy(ProcessEvent event, PcpWfTask job, OperationResult result); - /** - * Returns a PrismObject containing information about a work item to be processed by the user. For example, for 'approve role addition' process - * here is the RoleApprovalFormType prism object, having the following items: - * - user: to whom is a role being requested, - * - role: which role was requested to be added, - * - timeInterval: what is the validity time of the assignment that was requested, - * - requesterComment: a text that the requester entered when he requested the operation to be carried out, - * - comment - here the approver writes his comments on approving or rejecting the work item. - * - * @param task activiti task corresponding to the work item that is being displayed - * @param variables process instance variables at the point of invoking the work item (activiti task) - * @param result operation result where the operation status should be reported - * @return PrismObject containing the specific information about work item - * @throws SchemaException if any of key objects cannot be retrieved because of schema exception - * @throws ObjectNotFoundException if any of key objects cannot be found - */ - PrismObject prepareQuestionForm(org.activiti.engine.task.Task task, Map variables, OperationResult result) throws SchemaException, ObjectNotFoundException; - - /** - * Returns a object related to the work item at hand. E.g. for 'approve role addition' process this method returns corresponding role object. - * - * @param task activiti task corresponding to the work item that is being displayed - * @param variables process instance variables at the point of invoking the work item (activiti task) - * @param result operation result where the operation status should be reported - * @return PrismObject containing the object related to the work item - * @throws SchemaException if the object cannot be retrieved because of schema exception - * @throws ObjectNotFoundException if the object cannot be found - */ - PrismObject prepareRelatedObject(org.activiti.engine.task.Task task, Map variables, OperationResult result) throws SchemaException, ObjectNotFoundException; - - /** - * Externalizes internal state of the process instance. Typically, uninteresting (auxiliary) data elements - * are thrown away, internal representation suitable for workflow processing is replaced by "clean" prism - * object structure, and untyped Map[String,Object] is replaced by typed prism data. - * - * @param variables internal process state represented by a map - * @return external representation - */ - ProcessSpecificState externalizeProcessInstanceState(Map variables); - /** * Returns true if this aspect is enabled by default, i.e. even if not listed in primary change processor configuration. */ diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/assignments/AddAssignmentAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/assignments/AddAssignmentAspect.java index e36f83c05a6..a9ab8047bfe 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/assignments/AddAssignmentAspect.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/assignments/AddAssignmentAspect.java @@ -22,7 +22,6 @@ import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.prism.delta.ChangeType; import com.evolveum.midpoint.prism.delta.ContainerDelta; import com.evolveum.midpoint.prism.delta.ItemDelta; @@ -31,27 +30,17 @@ import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.wf.impl.processes.addrole.AddRoleVariableNames; import com.evolveum.midpoint.wf.impl.processes.itemApproval.ApprovalRequest; import com.evolveum.midpoint.wf.impl.processes.itemApproval.ItemApprovalProcessInterface; -import com.evolveum.midpoint.wf.impl.processes.itemApproval.ProcessVariableNames; import com.evolveum.midpoint.wf.impl.processors.primary.ObjectTreeDeltas; import com.evolveum.midpoint.wf.impl.processors.primary.PcpChildWfTaskCreationInstruction; import com.evolveum.midpoint.wf.impl.processors.primary.PrimaryChangeProcessor; import com.evolveum.midpoint.wf.impl.processors.primary.aspect.BasePrimaryChangeAspect; import com.evolveum.midpoint.wf.impl.util.MiscDataUtil; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.PcpAspectConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.AssignmentCreationApprovalFormType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.apache.commons.lang.Validate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -61,7 +50,6 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import java.util.Map; /** * Aspect for adding assignments of any type (abstract role or resource). @@ -234,19 +222,21 @@ private List prepareJobCreateInstructions(Mod String targetName = target.getName() != null ? target.getName().getOrig() : "(unnamed)"; + String approvalTaskName = "Approve adding " + targetName + " to " + assigneeName; + // create a JobCreateInstruction for a given change processor (primaryChangeProcessor in this case) PcpChildWfTaskCreationInstruction instruction = - PcpChildWfTaskCreationInstruction.createInstruction(getChangeProcessor()); + PcpChildWfTaskCreationInstruction.createItemApprovalInstruction(getChangeProcessor(), approvalTaskName, approvalRequest); // set some common task/process attributes instruction.prepareCommonAttributes(this, modelContext, assigneeOid, requester); // prepare and set the delta that has to be approved ObjectDelta delta = assignmentToDelta(modelContext, assignmentType, assigneeOid); - instruction.setDeltaProcessAndTaskVariables(delta); + instruction.setDeltasToProcess(delta); - instruction.setObjectRefVariable(modelContext, result); - instruction.setTargetRefVariable(ObjectTypeUtil.createObjectRef(target), result); + instruction.setObjectRef(modelContext, result); + instruction.setTargetRef(ObjectTypeUtil.createObjectRef(target), result); // set the names of midPoint task and activiti process instance String andExecuting = instruction.isExecuteApprovedChangeImmediately() ? "and executing " : ""; @@ -254,11 +244,7 @@ private List prepareJobCreateInstructions(Mod instruction.setProcessInstanceName("Adding " + targetName + " to " + assigneeName); // setup general item approval process - String approvalTaskName = "Approve adding " + targetName + " to " + assigneeName; - itemApprovalProcessInterface.prepareStartInstruction(instruction, approvalRequest, approvalTaskName); - - // set some aspect-specific variables - instruction.addProcessVariable(AddRoleVariableNames.FOCUS_NAME, assigneeName); + itemApprovalProcessInterface.prepareStartInstruction(instruction); instructions.add(instruction); } @@ -283,39 +269,6 @@ private ObjectDelta assignmentToDelta(ModelContext mode //region ------------------------------------------------------------ Things that execute when item is being approved - @Override - public PrismObject prepareQuestionForm(org.activiti.engine.task.Task task, Map variables, OperationResult result) throws SchemaException, ObjectNotFoundException { - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("prepareQuestionForm starting: execution id {}, pid {}, variables = {}", task.getExecutionId(), task.getProcessInstanceId(), variables); - } - - // todo check type compatibility - ApprovalRequest request = (ApprovalRequest) variables.get(ProcessVariableNames.APPROVAL_REQUEST); - request.setPrismContext(prismContext); - Validate.notNull(request, "Approval request is not present among process variables"); - - AssignmentType assignment = (AssignmentType) request.getItemToApprove(); - Validate.notNull(assignment, "Approval request does not contain as assignment"); - - T target = getAssignmentApprovalTarget(assignment, result); // may throw an (unchecked) exception - - PrismObjectDefinition formDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByType(AssignmentCreationApprovalFormType.COMPLEX_TYPE); - PrismObject formPrism = formDefinition.instantiate(); - AssignmentCreationApprovalFormType form = formPrism.asObjectable(); - - String focusName = (String) variables.get(AddRoleVariableNames.FOCUS_NAME); - form.setFocusName(focusName); // TODO disginguish somehow between users/roles/orgs - form.setAssignedObjectName(getTargetDisplayName(target)); - form.setRequesterComment(assignment.getDescription()); - form.setTimeInterval(formatTimeIntervalBrief(assignment)); - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Resulting prism object instance = {}", formPrism.debugDump()); - } - return formPrism; - } - public static String formatTimeIntervalBrief(AssignmentType assignment) { StringBuilder sb = new StringBuilder(); if (assignment != null && assignment.getActivation() != null && @@ -340,17 +293,6 @@ private static String formatTime(XMLGregorianCalendar time) { return formatter.format(time.toGregorianCalendar().getTime()); } - @Override - public PrismObject prepareRelatedObject(org.activiti.engine.task.Task task, Map variables, OperationResult result) throws SchemaException, ObjectNotFoundException { - - ApprovalRequest approvalRequest = (ApprovalRequest) variables.get(ProcessVariableNames.APPROVAL_REQUEST); - approvalRequest.setPrismContext(prismContext); - if (approvalRequest == null) { - throw new IllegalStateException("No approval request in activiti task " + task); - } - T target = getAssignmentApprovalTarget(approvalRequest.getItemToApprove(), result); - return target != null ? target.asPrismObject() : null; - } //endregion //region ------------------------------------------------------------ Things to override in concrete aspect classes diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/assignments/ModifyAssignmentAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/assignments/ModifyAssignmentAspect.java index c7e20a4ecd9..59631944a17 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/assignments/ModifyAssignmentAspect.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/assignments/ModifyAssignmentAspect.java @@ -22,7 +22,6 @@ import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.prism.delta.ChangeType; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; @@ -33,40 +32,23 @@ import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.schema.util.ObjectTypeUtil; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.wf.impl.processes.addrole.AddRoleVariableNames; import com.evolveum.midpoint.wf.impl.processes.itemApproval.ApprovalRequest; import com.evolveum.midpoint.wf.impl.processes.itemApproval.ItemApprovalProcessInterface; -import com.evolveum.midpoint.wf.impl.processes.itemApproval.ProcessVariableNames; import com.evolveum.midpoint.wf.impl.processes.modifyAssignment.AssignmentModification; import com.evolveum.midpoint.wf.impl.processors.primary.ObjectTreeDeltas; import com.evolveum.midpoint.wf.impl.processors.primary.PcpChildWfTaskCreationInstruction; import com.evolveum.midpoint.wf.impl.processors.primary.aspect.BasePrimaryChangeAspect; import com.evolveum.midpoint.wf.impl.util.MiscDataUtil; -import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.PcpAspectConfigurationType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.AssignmentModificationApprovalFormType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType; -import com.evolveum.prism.xml.ns._public.types_3.ChangeTypeType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.prism.xml.ns._public.types_3.ItemDeltaType; -import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; import org.apache.commons.lang.Validate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Change aspect that manages assignment modification approval. @@ -222,19 +204,21 @@ private List prepareJobCreateInstructions(Mod String focusOid = primaryChangeAspectHelper.getObjectOid(modelContext); PrismObject requester = primaryChangeAspectHelper.getRequester(taskFromModel, result); + String approvalTaskName = "Approve modifying assignment of " + targetName + " to " + focusName; + // create a JobCreateInstruction for a given change processor (primaryChangeProcessor in this case) PcpChildWfTaskCreationInstruction instruction = - PcpChildWfTaskCreationInstruction.createInstruction(getChangeProcessor()); + PcpChildWfTaskCreationInstruction.createItemApprovalInstruction(getChangeProcessor(), approvalTaskName, approvalRequest); // set some common task/process attributes instruction.prepareCommonAttributes(this, modelContext, focusOid, requester); // prepare and set the delta that has to be approved ObjectDelta delta = requestToDelta(modelContext, approvalRequest, focusOid); - instruction.setDeltaProcessAndTaskVariables(delta); + instruction.setDeltasToProcess(delta); - instruction.setObjectRefVariable(modelContext, result); - instruction.setTargetRefVariable(ObjectTypeUtil.createObjectRef(target), result); + instruction.setObjectRef(modelContext, result); + instruction.setTargetRef(ObjectTypeUtil.createObjectRef(target), result); // set the names of midPoint task and activiti process instance String andExecuting = instruction.isExecuteApprovedChangeImmediately() ? "and executing " : ""; @@ -242,11 +226,7 @@ private List prepareJobCreateInstructions(Mod instruction.setProcessInstanceName("Modifying assignment of " + targetName + " to " + focusName); // setup general item approval process - String approvalTaskName = "Approve modifying assignment of " + targetName + " to " + focusName; - itemApprovalProcessInterface.prepareStartInstruction(instruction, approvalRequest, approvalTaskName); - - // set some aspect-specific variables - instruction.addProcessVariable(AddRoleVariableNames.FOCUS_NAME, focusName); + itemApprovalProcessInterface.prepareStartInstruction(instruction); instructions.add(instruction); } @@ -265,58 +245,6 @@ private ObjectDelta requestToDelta(ModelContext modelCo //region ------------------------------------------------------------ Things that execute when item is being approved - @Override - public PrismObject prepareQuestionForm(org.activiti.engine.task.Task task, Map variables, OperationResult result) throws SchemaException, ObjectNotFoundException { - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("prepareQuestionForm starting: execution id {}, pid {}, variables = {}", task.getExecutionId(), task.getProcessInstanceId(), variables); - } - - PrismObjectDefinition formDefinition = - prismContext.getSchemaRegistry().findObjectDefinitionByType(AssignmentModificationApprovalFormType.COMPLEX_TYPE); - PrismObject formPrism = formDefinition.instantiate(); - AssignmentModificationApprovalFormType form = formPrism.asObjectable(); - - form.setFocusName((String) variables.get(AddRoleVariableNames.FOCUS_NAME)); // TODO disginguish somehow between users/roles/orgs - - // todo check type compatibility - ApprovalRequest request = (ApprovalRequest) variables.get(ProcessVariableNames.APPROVAL_REQUEST); - request.setPrismContext(prismContext); - Validate.notNull(request, "Approval request is not present among process variables"); - - AssignmentModification itemToApprove = (AssignmentModification) request.getItemToApprove(); - Validate.notNull(itemToApprove, "Approval request does not contain an item to approve"); - - T target = (T) itemToApprove.getTarget(); // TODO shouldn't we retrieve fresh value from repo? - String targetDisplayName = getTargetDisplayName(target); - form.setAssignedObjectName(targetDisplayName); - //TODO form.setRequesterComment(itemToApprove.getDescription()); - - ObjectDeltaType objectDeltaType = new ObjectDeltaType(); - objectDeltaType.setOid("?"); - objectDeltaType.setChangeType(ChangeTypeType.MODIFY); - objectDeltaType.setObjectType(UserType.COMPLEX_TYPE); // TODO - objectDeltaType.getItemDelta().addAll(itemToApprove.getModifications()); - form.setModification(objectDeltaType); - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Resulting prism object instance = {}", formPrism.debugDump()); - } - return formPrism; - } - - @Override - public PrismObject prepareRelatedObject(org.activiti.engine.task.Task task, Map variables, OperationResult result) throws SchemaException, ObjectNotFoundException { - - ApprovalRequest approvalRequest = (ApprovalRequest) - variables.get(ProcessVariableNames.APPROVAL_REQUEST); - approvalRequest.setPrismContext(prismContext); - if (approvalRequest == null) { - throw new IllegalStateException("No approval request in activiti task " + task); - } - - return approvalRequest.getItemToApprove().getTarget().asPrismObject(); - } //endregion diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/entitlements/AddAssociationAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/entitlements/AddAssociationAspect.java index 1ab0be653b6..d852c56ec15 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/entitlements/AddAssociationAspect.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/entitlements/AddAssociationAspect.java @@ -22,7 +22,6 @@ import com.evolveum.midpoint.prism.PrismContainerValue; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.prism.delta.ItemDelta; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.builder.DeltaBuilder; @@ -36,11 +35,9 @@ import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.wf.impl.processes.addrole.AddRoleVariableNames; import com.evolveum.midpoint.wf.impl.processes.itemApproval.ApprovalRequest; import com.evolveum.midpoint.wf.impl.processes.itemApproval.ApprovalRequestImpl; import com.evolveum.midpoint.wf.impl.processes.itemApproval.ItemApprovalProcessInterface; -import com.evolveum.midpoint.wf.impl.processes.itemApproval.ProcessVariableNames; import com.evolveum.midpoint.wf.impl.processors.primary.ObjectTreeDeltas; import com.evolveum.midpoint.wf.impl.processors.primary.PcpChildWfTaskCreationInstruction; import com.evolveum.midpoint.wf.impl.processors.primary.aspect.BasePrimaryChangeAspect; @@ -48,19 +45,13 @@ import com.evolveum.midpoint.wf.impl.processors.primary.assignments.AssignmentHelper; import com.evolveum.midpoint.wf.impl.util.MiscDataUtil; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.AssociationCreationApprovalFormType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType; import org.apache.commons.lang.Validate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.xml.datatype.XMLGregorianCalendar; import java.text.DateFormat; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * Aspect for adding associations. @@ -254,19 +245,21 @@ private boolean existsEquivalentValue(PrismObject shadowOld, PrismCo String targetName = target.getName() != null ? target.getName().getOrig() : "(unnamed)"; + String approvalTaskName = "Approve adding " + targetName + " to " + assigneeName; + // create a JobCreateInstruction for a given change processor (primaryChangeProcessor in this case) PcpChildWfTaskCreationInstruction instruction = - PcpChildWfTaskCreationInstruction.createInstruction(getChangeProcessor()); + PcpChildWfTaskCreationInstruction.createItemApprovalInstruction(getChangeProcessor(), approvalTaskName, approvalRequest); // set some common task/process attributes instruction.prepareCommonAttributes(this, modelContext, assigneeOid, requester); // prepare and set the delta that has to be approved ObjectTreeDeltas objectTreeDeltas = associationAdditionToDelta(modelContext, associationAddition, assigneeOid); - instruction.setObjectTreeDeltasProcessAndTaskVariables(objectTreeDeltas); + instruction.setDeltasToProcesses(objectTreeDeltas); - instruction.setObjectRefVariable(modelContext, result); - instruction.setTargetRefVariable(ObjectTypeUtil.createObjectRef(target), result); + instruction.setObjectRef(modelContext, result); + instruction.setTargetRef(ObjectTypeUtil.createObjectRef(target), result); // set the names of midPoint task and activiti process instance String andExecuting = instruction.isExecuteApprovedChangeImmediately() ? "and executing " : ""; @@ -274,11 +267,7 @@ private boolean existsEquivalentValue(PrismObject shadowOld, PrismCo instruction.setProcessInstanceName("Adding " + targetName + " to " + assigneeName); // setup general item approval process - String approvalTaskName = "Approve adding " + targetName + " to " + assigneeName; - itemApprovalProcessInterface.prepareStartInstruction(instruction, approvalRequest, approvalTaskName); - - // set some aspect-specific variables - instruction.addProcessVariable(AddRoleVariableNames.FOCUS_NAME, assigneeName); + itemApprovalProcessInterface.prepareStartInstruction(instruction); instructions.add(instruction); } @@ -304,46 +293,11 @@ private ObjectTreeDeltas associationAdditionToDelta(ModelContext modelContext //region ------------------------------------------------------------ Things that execute when item is being approved - @Override - public PrismObject prepareQuestionForm(org.activiti.engine.task.Task task, Map variables, OperationResult result) throws SchemaException, ObjectNotFoundException { - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("prepareQuestionForm starting: execution id {}, pid {}, variables = {}", task.getExecutionId(), task.getProcessInstanceId(), variables); - } - - // todo check type compatibility - ApprovalRequest request = (ApprovalRequest) variables.get(ProcessVariableNames.APPROVAL_REQUEST); - request.setPrismContext(prismContext); - Validate.notNull(request, "Approval request is not present among process variables"); - - AssociationAdditionType aat = (AssociationAdditionType) request.getItemToApprove(); - Validate.notNull(aat, "Approval request does not contain the association addition information"); - - ShadowType target = getAssociationApprovalTarget(aat.getAssociation(), result); // may throw an (unchecked) exception - - PrismObjectDefinition formDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByType(AssociationCreationApprovalFormType.COMPLEX_TYPE); - PrismObject formPrism = formDefinition.instantiate(); - AssociationCreationApprovalFormType form = formPrism.asObjectable(); - - String focusName = (String) variables.get(AddRoleVariableNames.FOCUS_NAME); - form.setFocusName(focusName); // TODO distinguish somehow between users/roles/orgs - form.setAssociatedObjectName(getTargetDisplayName(target)); - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Resulting prism object instance = {}", formPrism.debugDump()); - } - return formPrism; - } - private static String formatTime(XMLGregorianCalendar time) { DateFormat formatter = DateFormat.getDateInstance(); return formatter.format(time.toGregorianCalendar().getTime()); } - @Override - public PrismObject prepareRelatedObject(org.activiti.engine.task.Task task, Map variables, OperationResult result) throws SchemaException, ObjectNotFoundException { - return null; - } //endregion protected boolean isAssociationRelevant(PcpAspectConfigurationType config, AssociationAdditionType itemToApprove, diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/objects/AddObjectAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/objects/AddObjectAspect.java index 226cd42047f..05abbac844e 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/objects/AddObjectAspect.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/objects/AddObjectAspect.java @@ -18,18 +18,15 @@ import com.evolveum.midpoint.model.api.context.ModelContext; import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismObjectDefinition; import com.evolveum.midpoint.prism.delta.ChangeType; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.wf.impl.processes.itemApproval.ApprovalRequest; import com.evolveum.midpoint.wf.impl.processes.itemApproval.ApprovalRequestImpl; -import com.evolveum.midpoint.wf.impl.processes.itemApproval.ProcessVariableNames; import com.evolveum.midpoint.wf.impl.processors.primary.ObjectTreeDeltas; import com.evolveum.midpoint.wf.impl.processors.primary.PcpChildWfTaskCreationInstruction; import com.evolveum.midpoint.wf.impl.processors.primary.aspect.BasePrimaryChangeAspect; @@ -37,14 +34,11 @@ import com.evolveum.midpoint.xml.ns._public.common.common_3.PcpAspectConfigurationType; import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.AddObjectApprovalFormType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType; import org.apache.commons.lang.Validate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map; /** * Change aspect that manages addition of an object. @@ -111,19 +105,21 @@ private List prepareJobCreateInstructions(Mod PrismObject requester = primaryChangeAspectHelper.getRequester(taskFromModel, result); + String approvalTaskName = "Approve creating " + objectLabel; + // create a JobCreateInstruction for a given change processor (primaryChangeProcessor in this case) PcpChildWfTaskCreationInstruction instruction = - PcpChildWfTaskCreationInstruction.createInstruction(getChangeProcessor()); + PcpChildWfTaskCreationInstruction.createItemApprovalInstruction(getChangeProcessor(), approvalTaskName, approvalRequest); // set some common task/process attributes instruction.prepareCommonAttributes(this, modelContext, null, requester); // objectOid is null (because object does not exist yet) // prepare and set the delta that has to be approved ObjectDelta delta = assignmentToDelta(modelContext); - instruction.setDeltaProcessAndTaskVariables(delta); + instruction.setDeltasToProcess(delta); - instruction.setObjectRefVariable(modelContext, result); - instruction.setTargetRefVariable(null, result); + instruction.setObjectRef(modelContext, result); + instruction.setTargetRef(null, result); // set the names of midPoint task and activiti process instance String andExecuting = instruction.isExecuteApprovedChangeImmediately() ? "and executing " : ""; @@ -131,8 +127,7 @@ private List prepareJobCreateInstructions(Mod instruction.setProcessInstanceName("Creating " + objectLabel); // setup general item approval process - String approvalTaskName = "Approve creating " + objectLabel; - itemApprovalProcessInterface.prepareStartInstruction(instruction, approvalRequest, approvalTaskName); + itemApprovalProcessInterface.prepareStartInstruction(instruction); instructions.add(instruction); } @@ -147,38 +142,5 @@ private ObjectDelta assignmentToDelta(ModelContext prepareQuestionForm(org.activiti.engine.task.Task task, Map variables, OperationResult result) throws SchemaException, ObjectNotFoundException { - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("getRequestSpecific starting: execution id {}, pid {}, variables = {}", task.getExecutionId(), task.getProcessInstanceId(), variables); - } - - PrismObjectDefinition formDefinition = prismContext.getSchemaRegistry().findObjectDefinitionByType(AddObjectApprovalFormType.COMPLEX_TYPE); - PrismObject formPrism = formDefinition.instantiate(); - AddObjectApprovalFormType form = formPrism.asObjectable(); - - ApprovalRequest request = (ApprovalRequest) variables.get(ProcessVariableNames.APPROVAL_REQUEST); - request.setPrismContext(prismContext); - Validate.notNull(request, "Approval request is not present among process variables"); - form.setObjectToAdd(getObjectLabel(request.getItemToApprove())); - - form.setRequesterComment(null); // TODO - - if (LOGGER.isTraceEnabled()) { - LOGGER.trace("Resulting prism object instance = {}", formPrism.debugDump()); - } - return formPrism; - } - - @Override - public PrismObject prepareRelatedObject(org.activiti.engine.task.Task task, Map variables, OperationResult result) throws SchemaException, ObjectNotFoundException { - - ApprovalRequest request = (ApprovalRequest) variables.get(ProcessVariableNames.APPROVAL_REQUEST); - request.setPrismContext(prismContext); - Validate.notNull(request, "Approval request is not present among process variables"); - return request.getItemToApprove().asPrismObject(); - } - //endregion } \ No newline at end of file diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/ChangePasswordAspect.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/ChangePasswordAspect.java index 142c24972a9..b6d1a699ea3 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/ChangePasswordAspect.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/processors/primary/other/ChangePasswordAspect.java @@ -29,7 +29,6 @@ import com.evolveum.midpoint.util.exception.SchemaException; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; -import com.evolveum.midpoint.wf.impl.processes.addrole.AddRoleVariableNames; import com.evolveum.midpoint.wf.impl.processes.itemApproval.ApprovalRequest; import com.evolveum.midpoint.wf.impl.processes.itemApproval.ApprovalRequestImpl; import com.evolveum.midpoint.wf.impl.processes.itemApproval.ItemApprovalProcessInterface; @@ -37,22 +36,13 @@ import com.evolveum.midpoint.wf.impl.processors.primary.PcpChildWfTaskCreationInstruction; import com.evolveum.midpoint.wf.impl.processors.primary.aspect.BasePrimaryChangeAspect; import com.evolveum.midpoint.wf.impl.util.MiscDataUtil; -import com.evolveum.midpoint.xml.ns._public.common.common_3.CredentialsType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.PasswordType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemObjectsType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.WfConfigurationType; -import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType; - +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import java.util.Map; /** * This is a preliminary version of 'password approval' process aspect. The idea is that in some cases, a user may request @@ -110,16 +100,6 @@ public List prepareJobCreationInstructions(Mo return instructions; } - @Override - public PrismObject prepareQuestionForm(org.activiti.engine.task.Task task, Map variables, OperationResult result) { - return null; // todo implement this - } - - @Override - public PrismObject prepareRelatedObject(org.activiti.engine.task.Task task, Map variables, OperationResult result) { - return null; // todo implement this - } - private ApprovalRequest createApprovalRequest(ItemDelta delta) { ObjectReferenceType approverRef = new ObjectReferenceType(); @@ -138,29 +118,27 @@ private PcpChildWfTaskCreationInstruction createStartProcessInstruction(ModelCon String objectOid = primaryChangeAspectHelper.getObjectOid(modelContext); PrismObject requester = primaryChangeAspectHelper.getRequester(taskFromModel, result); + String approvalTaskName = "Approve changing password for " + userName; + // create a JobCreateInstruction for a given change processor (primaryChangeProcessor in this case) PcpChildWfTaskCreationInstruction instruction = - PcpChildWfTaskCreationInstruction.createInstruction(getChangeProcessor()); + PcpChildWfTaskCreationInstruction.createItemApprovalInstruction(getChangeProcessor(), approvalTaskName, approvalRequest); // set some common task/process attributes instruction.prepareCommonAttributes(this, modelContext, objectOid, requester); // prepare and set the delta that has to be approved - instruction.setDeltaProcessAndTaskVariables(itemDeltaToObjectDelta(objectOid, delta)); + instruction.setDeltasToProcess(itemDeltaToObjectDelta(objectOid, delta)); - instruction.setObjectRefVariable(modelContext, result); - instruction.setTargetRefVariable(null, result); + instruction.setObjectRef(modelContext, result); + instruction.setTargetRef(null, result); // set the names of midPoint task and activiti process instance instruction.setTaskName("Workflow for approving password change for " + userName); instruction.setProcessInstanceName("Changing password for " + userName); // setup general item approval process - String approvalTaskName = "Approve changing password for " + userName; - itemApprovalProcessInterface.prepareStartInstruction(instruction, approvalRequest, approvalTaskName); - - // set some aspect-specific variables - instruction.addProcessVariable(AddRoleVariableNames.FOCUS_NAME, userName); + itemApprovalProcessInterface.prepareStartInstruction(instruction); return instruction; } diff --git a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/util/MiscDataUtil.java b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/util/MiscDataUtil.java index 886363cefa7..2874acfacb5 100644 --- a/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/util/MiscDataUtil.java +++ b/model/workflow-impl/src/main/java/com/evolveum/midpoint/wf/impl/util/MiscDataUtil.java @@ -131,39 +131,27 @@ public String getUserNameByOid(String oid, OperationResult result) { } } - public PrismObject getRequester(Map variables, OperationResult result) throws SchemaException, ObjectNotFoundException { - LightweightObjectRef ref = (LightweightObjectRef) variables.get(CommonProcessVariableNames.VARIABLE_REQUESTER_REF); - return repositoryService.getObject(UserType.class, ref.getOid(), null, result); - } - - public ObjectTreeDeltas getObjectTreeDeltas(Map variables, boolean mayBeNull) throws JAXBException, SchemaException { - ObjectTreeDeltasType deltas = getObjectTreeDeltaType(variables, mayBeNull); - return deltas != null ? ObjectTreeDeltas.fromObjectTreeDeltasType(deltas, prismContext) : null; - } - - public ObjectDelta getFocusPrimaryDelta(Map variables, boolean mayBeNull) throws JAXBException, SchemaException { - ObjectDeltaType objectDeltaType = getFocusPrimaryObjectDeltaType(variables, mayBeNull); + public ObjectDelta getFocusPrimaryDelta(WfContextType workflowContext, boolean mayBeNull) throws JAXBException, SchemaException { + ObjectDeltaType objectDeltaType = getFocusPrimaryObjectDeltaType(workflowContext, mayBeNull); return objectDeltaType != null ? DeltaConvertor.createObjectDelta(objectDeltaType, prismContext) : null; } // mayBeNull=false means that the corresponding variable must be present (not that focus must be non-null) // TODO: review/correct this! - public ObjectDeltaType getFocusPrimaryObjectDeltaType(Map variables, boolean mayBeNull) throws JAXBException, SchemaException { - ObjectTreeDeltasType deltas = getObjectTreeDeltaType(variables, mayBeNull); + public ObjectDeltaType getFocusPrimaryObjectDeltaType(WfContextType workflowContext, boolean mayBeNull) throws JAXBException, SchemaException { + ObjectTreeDeltasType deltas = getObjectTreeDeltaType(workflowContext, mayBeNull); return deltas != null ? deltas.getFocusPrimaryDelta() : null; } - public ObjectTreeDeltasType getObjectTreeDeltaType(Map variables, boolean mayBeNull) throws SchemaException { - StringHolder deltasXml = (StringHolder) variables.get(PcpProcessVariableNames.VARIABLE_MIDPOINT_OBJECT_TREE_DELTAS); - if (deltasXml == null) { - if (mayBeNull) { - return null; - } else { - throw new IllegalStateException("There's no " + PcpProcessVariableNames.VARIABLE_MIDPOINT_OBJECT_TREE_DELTAS + " in process variables"); - } - } - return prismContext.parseAtomicValue( - deltasXml.getValue(), ObjectTreeDeltasType.COMPLEX_TYPE, PrismContext.LANG_XML); + public ObjectTreeDeltasType getObjectTreeDeltaType(WfContextType workflowContext, boolean mayBeNull) throws SchemaException { + WfProcessorSpecificStateType state = workflowContext.getProcessorSpecificState(); + if (mayBeNull && state == null) { + return null; + } + if (!(state instanceof WfPrimaryChangeProcessorStateType)) { + throw new IllegalStateException("Expected WfPrimaryChangeProcessorStateType but got " + state); + } + return ((WfPrimaryChangeProcessorStateType) state).getDeltasToProcess(); } public static String serializeObjectToXml(PrismObject object) { @@ -362,7 +350,15 @@ public List getGroupsForUser(String oid, OperationResult result) throws return retval; } - public PrismObject resolveObjectReference(ObjectReferenceType ref, OperationResult result) { + public PrismObject resolveObjectReference(ObjectReferenceType ref, OperationResult result) { + return resolveObjectReference(ref, false, result); + } + + public PrismObject resolveAndStoreObjectReference(ObjectReferenceType ref, OperationResult result) { + return resolveObjectReference(ref, true, result); + } + + private PrismObject resolveObjectReference(ObjectReferenceType ref, boolean storeBack, OperationResult result) { if (ref == null) { return null; } @@ -370,14 +366,18 @@ public PrismObject resolveObjectReference(ObjectReferenceType ref, OperationResu return ref.asReferenceValue().getObject(); } try { - return repositoryService.getObject((Class) prismContext.getSchemaRegistry().getCompileTimeClass(ref.getType()), ref.getOid(), null, result); + PrismObject object = repositoryService.getObject((Class) prismContext.getSchemaRegistry().getCompileTimeClass(ref.getType()), ref.getOid(), null, result); + if (storeBack) { + ref.asReferenceValue().setObject(object); + } + return object; } catch (ObjectNotFoundException e) { // there should be a note in result by now LoggingUtils.logException(LOGGER, "Couldn't get reference {} details because it couldn't be found", e, ref); return null; } catch (SchemaException e) { // there should be a note in result by now - LoggingUtils.logException(LOGGER, "Couldn't get reference {} details due to schema exception", e, ref); + LoggingUtils.logUnexpectedException(LOGGER, "Couldn't get reference {} details due to schema exception", e, ref); return null; } } diff --git a/model/workflow-impl/src/main/resources/processes/ItemApproval.bpmn20.xml b/model/workflow-impl/src/main/resources/processes/ItemApproval.bpmn20.xml index bf3e8af4f7f..407cab22e8f 100644 --- a/model/workflow-impl/src/main/resources/processes/ItemApproval.bpmn20.xml +++ b/model/workflow-impl/src/main/resources/processes/ItemApproval.bpmn20.xml @@ -30,7 +30,7 @@