blob: 867f4c84c8c9f67eb104432f8d7ef554361d82d4 [file] [log] [blame]
/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.ofbiz.workflow.client;
import java.sql.Timestamp;
import java.util.Iterator;
import java.util.Map;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.Delegator;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.job.Job;
import org.ofbiz.service.job.JobManagerException;
import org.ofbiz.workflow.CannotStop;
import org.ofbiz.workflow.NotRunning;
import org.ofbiz.workflow.WfActivity;
import org.ofbiz.workflow.WfAssignment;
import org.ofbiz.workflow.WfException;
import org.ofbiz.workflow.WfExecutionObject;
import org.ofbiz.workflow.WfFactory;
import org.ofbiz.workflow.WfProcess;
import org.ofbiz.workflow.WfResource;
/**
* Workflow Client - Client API to the Workflow Engine.
*/
public class WorkflowClient {
public static final String module = WorkflowClient.class.getName();
protected Delegator delegator = null;
protected LocalDispatcher dispatcher = null;
protected WorkflowClient() {}
/**
* Get a new instance of the Workflow Client
* @param delegator the Delegator object which matchs the delegator used by the workflow engine.
* @param dispatcher a LocalDispatcher object to invoke the workflow services.
*/
public WorkflowClient(Delegator delegator, LocalDispatcher dispatcher) {
if (delegator == null)
throw new IllegalArgumentException("Delegator cannot be null");
if (dispatcher == null)
throw new IllegalArgumentException("LocalDispatcher cannot be null");
this.delegator = delegator;
this.dispatcher = dispatcher;
}
/**
* Get a new instance of the Workflow Client
* @param context A DispatchContext object.
* *** Note the delegator from this object must match the delegator used by the workflow engine.
*/
public WorkflowClient(DispatchContext context) {
this(context.getDelegator(), context.getDispatcher());
}
/**
* Create an activity assignment.
* @param workEffortId The WorkEffort entity ID for the activitiy.
* @param partyId The assigned / to be assigned users party ID.
* @param roleTypeId The assigned / to be assigned role type ID.
* @param append Append this assignment to the list, if others exist.
* @return The new assignment object.
* @throws WfException
*/
public WfAssignment assign(String workEffortId, String partyId, String roleTypeId, Timestamp fromDate, boolean append) throws WfException {
WfActivity activity = WfFactory.getWfActivity(delegator, workEffortId);
WfResource resource = WfFactory.getWfResource(delegator, null, null, partyId, roleTypeId);
if (!append) {
Iterator<WfAssignment> i = activity.getIteratorAssignment();
while (i.hasNext()) {
WfAssignment a = i.next();
a.remove();
}
}
return WfFactory.getWfAssignment(activity, resource, fromDate, true);
}
/**
* Accept an activity assignment.
* @param workEffortId The WorkEffort entity ID for the activitiy.
* @param partyId The assigned / to be assigned users party ID.
* @param roleTypeId The assigned / to be assigned role type ID.
* @param fromDate The assignment's from date.
* @throws WfException
*/
public void accept(String workEffortId, String partyId, String roleTypeId, Timestamp fromDate) throws WfException {
WfAssignment assign = WfFactory.getWfAssignment(delegator, workEffortId, partyId, roleTypeId, fromDate);
assign.accept();
}
/**
* Accept an activity assignment and begin processing.
* @param workEffortId The WorkEffort entity ID for the activitiy.
* @param partyId The assigned / to be assigned users party ID.
* @param roleTypeId The assigned / to be assigned role type ID.
* @param fromDate The assignment's from date.
* @throws WfException
*/
public void acceptAndStart(String workEffortId, String partyId, String roleTypeId, Timestamp fromDate) throws WfException {
accept(workEffortId, partyId, roleTypeId, fromDate);
start(workEffortId);
}
/**
* Delegate an activity assignment.
* @param workEffortId The WorkEffort entity ID for the activitiy.
* @param fromPartyId The current assignment partyId.
* @param fromRoleTypeId The current assignment roleTypeId.
* @param fromFromDate The current assignment fromDate.
* @param toPartyId The new delegated assignment partyId.
* @param toRoleTypeId The new delegated assignment roleTypeId.
* @param toFromDate The new delegated assignment fromDate.
* @return The new assignment object.
* @throws WfException
*/
public WfAssignment delegate(String workEffortId, String fromPartyId, String fromRoleTypeId, Timestamp fromFromDate, String toPartyId, String toRoleTypeId, Timestamp toFromDate) throws WfException {
WfActivity activity = WfFactory.getWfActivity(delegator, workEffortId);
WfAssignment fromAssign = null;
// check status and delegateAfterStart attribute
if (activity.state().equals("open.running") && !activity.getDefinitionObject().getBoolean("delegateAfterStart").booleanValue())
throw new WfException("This activity cannot be delegated once it has been started");
if (fromPartyId == null && fromRoleTypeId == null && fromFromDate == null) {
Iterator<WfAssignment> i = activity.getIteratorAssignment();
fromAssign = i.next();
if (i.hasNext()) {
throw new WfException("Cannot locate the assignment to delegate from, there is more then one " +
"assignment for this activity.");
}
}
if (fromAssign == null) {
fromAssign = WfFactory.getWfAssignment(delegator, workEffortId, fromPartyId, fromRoleTypeId, fromFromDate);
}
fromAssign.delegate();
// check for a restartOnDelegate
WfActivity newActivity = null;
if (activity.getDefinitionObject().getBoolean("restartOnDelegate").booleanValue()) {
// this only applies to running single assignment activities
if (activity.state().equals("open.running") && activity.howManyAssignment() == 0) {
try {
activity.abort();
} catch (CannotStop cs) {
throw new WfException("Cannot stop the current activity");
} catch (NotRunning nr) {
throw new WfException("Current activity is not running; cannot abort");
}
String parentProcessId = activity.container().runtimeKey();
newActivity = WfFactory.getWfActivity(activity.getDefinitionObject(), parentProcessId);
}
}
WfAssignment assign = null;
if (newActivity != null) {
assign = assign(newActivity.runtimeKey(), toPartyId, toRoleTypeId, toFromDate, true);
} else {
assign = assign(workEffortId, toPartyId, toRoleTypeId, toFromDate, true);
}
return assign;
}
/**
* Delegate and accept an activity assignment.
* @param workEffortId the WorkEffort entity ID for the activitiy.
* @param fromPartyId the from users party ID.
* @param fromRoleTypeId the from role type ID.
* @param fromFromDate the from date.
* @param toPartyId the assigned users party ID.
* @param toRoleTypeId the assigned role type ID.
* @param toFromDate the assignment's to date.
* @param start True to attempt to start the activity.
* @throws WfException
*/
public void delegateAndAccept(String workEffortId, String fromPartyId, String fromRoleTypeId, Timestamp fromFromDate, String toPartyId, String toRoleTypeId, Timestamp toFromDate, boolean start) throws WfException {
WfAssignment assign = delegate(workEffortId, fromPartyId, fromRoleTypeId, fromFromDate, toPartyId, toRoleTypeId, toFromDate);
assign.accept();
Debug.logVerbose("Delegated assignment.", module);
if (start) {
Debug.logVerbose("Starting activity.", module);
if (!activityRunning(assign.activity())) {
start(assign.activity().runtimeKey());
} else {
Debug.logWarning("Activity already running; not starting.", module);
}
} else {
Debug.logVerbose("Not starting assignment.", module);
}
}
/**
* Start the activity.
* @param workEffortId The WorkEffort entity ID for the activitiy.
* @throws WfException
*/
public void start(String workEffortId) throws WfException {
if (dispatcher == null) {
throw new WfException("LocalDispatcher is null; cannot create job for activity startup");
}
WfActivity activity = WfFactory.getWfActivity(delegator, workEffortId);
if (Debug.verboseOn()) Debug.logVerbose("Starting activity: " + activity.name(), module);
if (activityRunning(activity))
throw new WfException("Activity is already running");
Job job = new StartActivityJob(activity);
if (Debug.verboseOn()) Debug.logVerbose("Job: " + job, module);
try {
dispatcher.getJobManager().runJob(job);
} catch (JobManagerException e) {
throw new WfException(e.getMessage(), e);
}
}
/**
* Complete an activity assignment and follow the next transition(s).
* @param workEffortId The WorkEffort entity ID for the activity.
* @param partyId The assigned / to be assigned users party ID.
* @param roleTypeId The assigned / to be assigned role type ID.
* @param fromDate The assignment's from date.
* @param result The assignment result.
* @throws WfException
*/
public void complete(String workEffortId, String partyId, String roleTypeId, Timestamp fromDate, Map<String, Object> result) throws WfException {
WfAssignment assign = WfFactory.getWfAssignment(delegator, workEffortId, partyId, roleTypeId, fromDate);
if (UtilValidate.isNotEmpty(result))
assign.setResult(result);
assign.complete();
}
/**
* Suspend an activity
* @param workEffortId The WorkEffort entity key for the activity object
* @throws WfException
*/
public void suspend(String workEffortId) throws WfException {
WfActivity activity = WfFactory.getWfActivity(delegator, workEffortId);
if (Debug.verboseOn()) Debug.logVerbose("Suspending activity: " + activity.name(), module);
if (!activityRunning(activity))
throw new WfException("Activity is not running");
activity.suspend();
}
/**
* Resume an activity
* @param workEffortId The WorkEffort entity key for the activity object
* @throws WfException
*/
public void resume(String workEffortId) throws WfException {
WfActivity activity = WfFactory.getWfActivity(delegator, workEffortId);
if (Debug.verboseOn()) Debug.logVerbose("Resuming activity: " + activity.name(), module);
if (activityRunning(activity))
throw new WfException("Activity is already running");
activity.resume();
}
/**
* Abort a process
* @param workEffortId The workeffort entity key for the process to abort
* @throws WfException
*/
public void abortProcess(String workEffortId) throws WfException {
WfProcess process = WfFactory.getWfProcess(delegator, workEffortId);
process.abort();
}
/**
* Append data to the execution object's process context.
* @param workEffortId The WorkEffort entity key for the execution object.
* @param append The data to append.
* @throws WfException
*/
public void appendContext(String workEffortId, Map<String, Object> append) throws WfException {
WfExecutionObject obj = getExecutionObject(workEffortId);
if (obj != null) {
Map<String, Object> oCtx = obj.processContext();
oCtx.putAll(append);
obj.setProcessContext(oCtx);
if (Debug.verboseOn()) Debug.logVerbose("ProcessContext (" + workEffortId + ") => " + obj.processContext(), module);
}
}
/**
* Returns the process context of the execution object.
* @param workEffortId The WorkEffort entity key for the execution object.
* @throws WfException
*/
public Map<String, Object> getContext(String workEffortId) throws WfException {
WfExecutionObject obj = getExecutionObject(workEffortId);
if (obj == null) throw new WfException("Invalid Execution Object (null value)");
if (Debug.verboseOn()) Debug.logVerbose("ProcessContext (" + workEffortId + ") => " + obj.processContext(), module);
return obj.processContext();
}
/**
* Gets the state of the execution object defined by the work effort key.
* @param workEffortId The WorkEffort entity key for the execution object.
* @throws WfException
*/
public String getState(String workEffortId) throws WfException {
WfExecutionObject obj = getExecutionObject(workEffortId);
if (obj == null) throw new WfException("Invalid Execution Object (null value)");
if (Debug.verboseOn()) Debug.logVerbose("Current State (" + workEffortId + ") => " + obj.state(), module);
return obj.state();
}
/**
* Set the state of the execution object defined by the work effort key.
* @param workEffortId The WorkEffort entity key for the execution object.
* @param state The new state of the execution object.
* @throws WfException If state change is not allowed.
*/
public void setState(String workEffortId, String state) throws WfException {
WfExecutionObject obj = getExecutionObject(workEffortId);
if (obj == null) throw new WfException("Invalid Execution Object (null value)");
obj.changeState(state);
if (Debug.verboseOn()) Debug.logVerbose("Current State (" + workEffortId + ") => " + obj.state(), module);
}
/**
* Gets the priority of the execution object defined by the work effort key.
* @param workEffortId The WorkEffort entity key for the execution object.
* @return Priority of the execution object as a long.
* @throws WfException
*/
public long getPriority(String workEffortId) throws WfException {
WfExecutionObject obj = getExecutionObject(workEffortId);
if (obj == null) throw new WfException("Invalid Execution Object (null value)");
if (Debug.verboseOn()) Debug.logVerbose("Current Priority (" + workEffortId + ") => " + obj.priority(), module);
return obj.priority();
}
/**
* Set the priority of the execution object defined by the work effort key.
* @param workEffortId The WorkEffort entity key for the execution object.
* @param priority The new priority of the execution object.
* @throws WfException If state change is not allowed.
*/
public void setPriority(String workEffortId, long priority) throws WfException {
WfExecutionObject obj = getExecutionObject(workEffortId);
if (obj == null) throw new WfException("Invalid Execution Object (null value)");
obj.setPriority(priority);
if (Debug.verboseOn()) Debug.logVerbose("Current Priority (" + workEffortId + ") => " + obj.priority(), module);
}
// Get the execution object for the workeffort
private WfExecutionObject getExecutionObject(String workEffortId) {
WfExecutionObject obj = null;
try {
obj = WfFactory.getWfActivity(delegator, workEffortId);
} catch (WfException e) {// ingore
}
if (obj == null) {
try {
obj = WfFactory.getWfProcess(delegator, workEffortId);
} catch (WfException e) {// ignore
}
}
return obj;
}
// Test an activity for running state.
private boolean activityRunning(WfActivity activity) throws WfException {
if (activity.state().equals("open.running"))
return true;
return false;
}
}