/**
* Copyright 2007-2010 非也
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation。
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses. *
*/
package org.fireflow.client;
import java.io.File;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.fireflow.engine.entity.repository.ProcessDescriptor;
import org.fireflow.engine.entity.repository.ProcessKey;
import org.fireflow.engine.entity.repository.RepositoryDescriptor;
//import org.fireflow.engine.entity.repository.ResourceDescriptor;
//import org.fireflow.engine.entity.repository.ResourceDescriptorProperty;
//import org.fireflow.engine.entity.repository.ServiceDescriptor;
//import org.fireflow.engine.entity.repository.ServiceDescriptorProperty;
import org.fireflow.engine.entity.runtime.ActivityInstance;
import org.fireflow.engine.entity.runtime.ProcessInstance;
import org.fireflow.engine.entity.runtime.Scope;
import org.fireflow.engine.entity.runtime.WorkItem;
import org.fireflow.engine.exception.EngineException;
import org.fireflow.engine.exception.InvalidOperationException;
import org.fireflow.engine.exception.WorkflowProcessNotFoundException;
import org.fireflow.engine.invocation.AssignmentHandler;
import org.fireflow.engine.invocation.impl.ReassignmentHandler;
import org.fireflow.model.InvalidModelException;
import org.fireflow.pvm.kernel.KernelException;
/**
* 使用模式:
* WorkflowStatement queryDelegate = workflowSession.createWorkflowStatement();
* queryDelegate.setAttribute("a","abc")
* .setDynamicAssignmentHandler("activity2",theAssigmentHandler)
* .startProcess("process1");
* ActivityInstance activityInstance = queryDelegate.getCurrentActivityInstance();
* List<WorkItem> workitemList = queryDelegate.getLatestCreatedWorkItems();
*
*
* @author 非也
* @version 2.0
*/
public interface WorkflowStatement {
/**
* 获得当前操作的流程类型
* @return
*/
public String getProcessType();
//获得当前的流程实例
//该方法在远程接口中不合理,因此在接口中注销
//public ProcessInstance getCurrentProcessInstance();
//获得当前的活动实例。
//该方法在远程接口中不合理,因此在接口中注销
// public ActivityInstance getCurrentActivityInstance();
//获得最近一次流程操作所创建的所有的工作项。
//该方法用于远程接口不合理,因为新产生的工作项可能非常多,通过该方法返回会导致
//网络通信障碍,因此在接口中注销。
//public List<WorkItem> getLatestCreatedWorkItems();
// /**
// * 设置一个动态任务分配处理句柄。该方法实质是调用WorkflowSession.setDynamicAssignmentHandler(String activityId,AssignmentHandler assignmentHandler);
// * @param dynamicAssignmentHandler
// */
// 通过调用completeWorkItem(...)或者completeWorkItemAndJumpTo(...)设置该参数,
// 不必单独暴露该方法
// public WorkflowStatement setDynamicAssignmentHandler(String activityId,
// AssignmentHandler dynamicAssignmentHandler);
//
// 类似HttpServletRequest的setAttribute,用于流程操作中传递参数。
// 该方法实质是调用,WorkflowSession.setAttribute(String name ,Object attr);
// @param name
// @param attr
// 在远程接口中,该方法不合理,因此从该接口注销。
// public WorkflowStatement setAttribute(String name ,Object attr);
/******************************************************************************/
/************ **********/
/************ 与process instance 相关的API **********/
/************ **********/
/************ **********/
/******************************************************************************/
/**
* 创建并启动流程。<br/>
* 该方法执行完毕后,可以通过WorkflowStatement.getCurrentProcessInstance(),
* WorkflowStatement.getCurrentActivityInstance(),WorkflowStatement.getLatestCreatedWorkItems()获得
* 当前的流程实例,活动实例和最新创建的工作项。注意,WorkflowStatement.getCurrentActivityInstance()返回的
* 活动实例不一定是流程第一个活动的实例;例如:如果流程第一个活动是一个java调用,而第二个活动是人工活动,
* 那么流程执行到人工活动才返回,所以WorkflowStatement.getCurrentActivityInstance()将返回人工活动的实例。
*
* @param workflowProcessId 流程的Id。
* @param version 流程版本号
* @param bizId 业务实体主键。
* @param variables 流程变量
* @return 新创建的流程实例
* @throws InvalidModelException
*/
public ProcessInstance startProcess(String workflowProcessId,int version,String bizId,Map<String,Object> variables) throws InvalidModelException,
WorkflowProcessNotFoundException,InvalidOperationException;
public ProcessInstance startProcess(String workflowProcessId,int version,String subProcessId,String bizId,Map<String,Object> variables) throws InvalidModelException,
WorkflowProcessNotFoundException,InvalidOperationException;
public ProcessInstance startProcess(String workflowProcessId,String subProcessId,String bizId,Map<String,Object> variables) throws InvalidModelException,
WorkflowProcessNotFoundException,InvalidOperationException;
/**
* 创建并启动流程。具体启动哪个版本需要根据外部策略决定。<br/>
* 该方法执行完毕后,可以通过WorkflowStatement.getCurrentProcessInstance(),
* WorkflowStatement.getCurrentActivityInstance(),WorkflowStatement.getLatestCreatedWorkItems()获得
* 当前的流程实例,活动实例和最新创建的工作项。注意,WorkflowStatement.getCurrentActivityInstance()返回的
* 活动实例不一定是流程第一个活动的实例;例如:如果流程第一个活动是一个java调用,而第二个活动是人工活动,
* 那么流程执行到人工活动才返回,所以WorkflowStatement.getCurrentActivityInstance()将返回人工活动的实例。
* TODO 流程版本策略待斟酌。
* @param workflowProcessId 流程Id
* @param bizId 业务实体主键
* @param variables 流程变量
* @return 新创建的流程实例
* @throws InvalidModelException
* @throws WorkflowProcessNotFoundException
* @throws InvalidOperationException
*/
public ProcessInstance startProcess(String workflowProcessId,String bizId,Map<String,Object> variables) throws InvalidModelException,
WorkflowProcessNotFoundException,InvalidOperationException;
/**
* 创建并启动流程。该方法执行完毕后,可以通过WorkflowStatement.getCurrentProcessInstance(),
* WorkflowStatement.getCurrentActivityInstance(),WorkflowStatement.getLatestCreatedWorkItems()获得
* 当前的流程实例,活动实例和最新创建的工作项。注意,WorkflowStatement.getCurrentActivityInstance()返回的
* 活动实例不一定是流程第一个活动的实例;例如:如果流程第一个活动是一个java调用,而第二个活动是人工活动,
* 那么流程执行到人工活动才返回,所以WorkflowStatement.getCurrentActivityInstance()将返回人工活动的实例。
* @param process 流程定义对象
* @param processType 流程类型,名称为XPDL,FPDL,BPEL等
* @param bizId 业务实体主键
* @param variables 流程变量
* @return 新创建的流程实例
* @throws InvalidModelException
* @throws WorkflowProcessNotFoundException
* @throws InvalidOperationException
*/
public ProcessInstance startProcess(Object process,String bizId,Map<String,Object> variables) throws InvalidModelException,
WorkflowProcessNotFoundException,InvalidOperationException;
public ProcessInstance createProcessInstance(String workflowProcessId) throws InvalidModelException ,WorkflowProcessNotFoundException;
public ProcessInstance createProcessInstance(Object process)throws InvalidModelException ;
public ProcessInstance createProcessInstance(String workflowProcessId,int version) throws InvalidModelException ,WorkflowProcessNotFoundException;
public ProcessInstance createProcessInstance(String workflowProcessId,int version,String subProcessId) throws InvalidModelException ,WorkflowProcessNotFoundException;
public ProcessInstance createProcessInstance(String workflowProcessId,String subProcessId)throws InvalidModelException ,WorkflowProcessNotFoundException;
public ProcessInstance runProcessInstance(String processInstanceId,String bizId,Map<String,Object> variables) ;
/**
* 撤销流程实例。将流程实例、活动的TaskInstance、活动的WorkItem的状态设置为ABORTED。
*
* @param processInstanceId 流程实例Id
* @param note 备注信息。
* @param 被撤销的流程实例
*/
public ProcessInstance abortProcessInstance(String processInstanceId,String note)throws InvalidOperationException;
/**
* 挂起流程实例
* @param processInstance
*/
public ProcessInstance suspendProcessInstance(String processInstanceId,String note)throws InvalidOperationException;
/**
* 恢复被挂起的流程实例
* @param processInstance
*/
public ProcessInstance restoreProcessInstance(String processInstanceId,String note)throws InvalidOperationException;
//
/******************************************************************************/
/************ **********/
/************ ActivityInstance相关的 API **********/
/************ **********/
/************ **********/
/******************************************************************************/
/**
* 将活动实例挂起
* @param activityInstanceId 活动实例Id
* @param 备注信息
* @return 被挂起的任务实例
*/
public ActivityInstance suspendActivityInstance(String activityInstanceId ,String note)throws InvalidOperationException;
/**
* 恢复被挂起的活动实例
* @param activityInstanceId 活动实例Id
* @param 备注信息
* @return
* @throws EngineException
*/
public ActivityInstance restoreActivityInstance(String activityInstanceId,String note)throws InvalidOperationException;
/**
* 撤销活动实例
* @param activityInstanceId 活动实例Id
* @param 备注信息
* @return
* @throws InvalidOperationException
*/
public ActivityInstance abortActivityInstance(String activityInstanceId,String note) throws InvalidOperationException;
/******************************************************************************/
/************ **********/
/************ workItem 相关的API **********/
/************ **********/
/************ **********/
/******************************************************************************/
/**
* 签收工作项。如果任务实例的分配模式是ANY,则同一个任务实例的其他工作项将被删除。
* 如果任务是里的分配模式是ALL,则此操作不影响同一个任务实例的其他工作项的状态。<br/>
* 如果签收成功,则返回一个新的WorkItem对象。<br/>
* 如果签收失败,则返回null。<br/>
* 例如:同一个TaskInstance被分配给Actor_1和Actor_2,且分配模式是ANY,即便Actor_1和Actor_2同时执行
* 签收操作,也必然有一个人签收失败。系统对这种竞争性操作进行了同步。<br/>
* 该方法和IWorkItem.claim()是等价的。
* @param workItemId 被签收的工作项的Id
* @return 如果签收成功,则返回被签收的IWorkItem对象;否则返回null
* @throws org.fireflow.engine.exception.EngineException
* @throws org.fireflow.kenel.KenelException
*
*/
public WorkItem claimWorkItem(String workItemId) throws InvalidOperationException ;
/**
*
* @param workItemId
* @param attachmentId
* @param attachmentType
* @param note
* @return 如果退签收成功,则返回被退签的WorkItem,否则返回null
* @throws InvalidOperationException
*/
public WorkItem disclaimWorkItem(String workItemId,String attachmentId, String attachmentType, String note) throws InvalidOperationException ;
/**
* 对已经结束的工作项执行取回操作。<br/>
* 只有满足如下约束才能正确执行取回操作:<br/>
* 1、下一个环节没有Tool类型或者Subflow类型的Task;<br/>
* 2、下一个环节Form类型的TaskInstance没有被签收。<br/>
* 如果在本WorkItem成功执行了jumpTo操作或者loopTo操作,只要满足上述条件,也可以
* 成功执行withdraw。<br/>
* 该方法和IWorkItem.withdraw()等价
* @param workItemId 工作项Id
* @return 如果取回成功,则创建一个新的WorkItem 并返回该WorkItem
* @throws EngineException
* @throws KernelException
*/
public WorkItem withdrawWorkItem(String workItemId)throws InvalidOperationException;
//
// /**
// * 执行“拒收”操作,可以对已经签收的或者未签收的WorkItem拒收。<br/>
// * 该操作必须满足如下条件:<br/>
// * 1、前驱环节中没有没有Tool类型和Subflow类型的Task;<br/>
// * 2、没有合当前TaskInstance并行的其他TaskInstance;<br/>
// * @param workItemId 工作项Id
// * @throws EngineException
// * @throws KernelException
// */
// public void rejectWorkItem(String workItemId)throws EngineException, KernelException;
//
// /**
// * 执行“拒收”操作,可以对已经签收的或者未签收的WorkItem拒收。<br/>
// * 该操作必须满足如下条件:<br/>
// * 1、前驱环节中没有没有Tool类型和Subflow类型的Task;<br/>
// * 2、没有合当前TaskInstance并行的其他TaskInstance;<br/>
// * @param workItemId 工作项Id
// * @param comments 备注信息
// * @throws EngineException
// * @throws KernelException
// */
// public void rejectWorkItem(String workItemId,String comments)throws EngineException, KernelException;
//
//
//
/**
* 结束当前WorkItem;并由工作流引擎根据流程定义决定下一步操作。引擎的执行规则如下<br/>
* 1、工作流引擎首先判断该WorkItem对应的TaskInstance是否可以结束。
* 如果TaskInstance的assignment策略为ANY,或者,assignment策略为ALL且它所有的WorkItem都已经完成
* 则结束当前TaskInstance<br/>
* 2、判断TaskInstance对应的ActivityInstance是否可以结束。如果ActivityInstance的complete strategy
* 为ANY,或者,complete strategy为ALL且他的所有的TaskInstance都已经结束,则结束当前ActivityInstance<br/>
* 3、根据流程定义,启动下一个Activity,并创建相关的TaskInstance和WorkItem
* @param workItemId 工作项Id
* @param attachmentId TODO
* @param attachmentType TODO
* @param note TODO
* @return TODO
* @throws org.fireflow.engine.exception.EngineException
* @throws org.fireflow.kenel.KenelException
*/
public WorkItem completeWorkItem(String workItemId,String attachmentId, String attachmentType, String note) throws InvalidOperationException;
public WorkItem completeWorkItem(String workItemId,Map<String,AssignmentHandler> assignmentStrategy,String attachmentId, String attachmentType, String note)throws InvalidOperationException;
//
/**
* 结束当前WorkItem,跳转到指定的Activity<br/>
* 只有满足如下条件的情况下,该方法才能成功执行,否则抛出EngineException,流程状态恢复到调用该方法之前的状态。<br/>
* 1)当前Activity和即将启动的Acitivty必须在同一个执行线上<br/>
* 2)当前Task的assignment为Task.ANY。或者当前Task的assignment为Task.ALL(汇签),且本WorkItem结束后可以使得TaskInstance结束;与之相反的情况是,
* 尚有其他参与汇签的操作者没有完成其工作项,这时engine拒绝跳转操作<br/>
* 3)当前TaskInstance结束后,可以使得当前的ActivityInstance结束。与之相反的情况是,当前Activity包含了多个Task,且Activity的Complete Strategy是ALL,
* 尚有其他的TaskInstance仍然处于活动状态,这种情况下执行jumpTo操作会被拒绝。
* @param workItemId 工作项Id
* @param targetActivityId 将要被启动的ActivityId
* @param attachmentId TODO
* @param attachmentType TODO
* @param note TODO
* @return TODO
* @throws org.fireflow.engine.exception.EngineException
* @throws org.fireflow.kenel.KenelException
*/
public WorkItem completeWorkItemAndJumpTo(String workItemId ,String targetActivityId,String attachmentId, String attachmentType, String note) throws InvalidOperationException;
public WorkItem completeWorkItemAndJumpTo(String workItemId ,String targetActivityId,Map<String,AssignmentHandler> assignmentStrategy,String attachmentId, String attachmentType, String note) throws InvalidOperationException;
//
/**
* 将工作项委派给其他人,自己的工作项变成CANCELED状态
* @param workItemId 工作项Id
* @param reassignHandler ReassignmentHandler实例
* @param attachmentId TODO
* @param attachmentType TODO
* @param note TODO
* @return 新创建的工作项
*/
public WorkItem reassignWorkItemTo(String workItemId, ReassignmentHandler reassignHandler,String attachmentId, String attachmentType, String note) throws InvalidOperationException;
//
// /**
// * 将工作项委派给其他人,自己的工作项变成CANCELED状态。返回新创建的工作项
// * @param actorId 接受任务的操作员Id
// * @param comments 相关的备注信息
// * @return 新创建的工作项
// */
// public WorkItem reassignWorkItemTo(String workItemId,String actorId,String comments) throws EngineException;
//
//
/**
* TODO 该方法需研究,斟酌。
*/
//public void updateWorkItem(WorkItem workItem)throws InvalidOperationException;
/*****************************************************************/
/*************** 流程定义相关的api ******************************/
/*****************************************************************/
//
/**
* 发布流程定义或者覆盖已有的流程定义。<br/>
*
* 当发布新的流程定义时,publishState默认取值为false,validDateFrom是当前时间,validDateTo是一个很大的日期数字2099-12-31,
* ownerId,ownerName,approver,approvedTime,updateLog均为空。<br/>
*
* 当覆盖已有的流程定义时,上述字段的值均维持原值不变。<br/>
*
* ProcessDescriptor相关字段含义如下:<br/>
* publishState:发布状态<br/>
* validDateFrom:流程有效期始<br/>
* validDateTo:流程有效期止<br/>
* ownerId:所有者id<br/>
* ownerName:所有者名称<br/>
* approver:审批人<br/>
* approvedTime:审批时间<br/>
* updateLog:发布日志<br/>
*
* @param processObject WorkflowProcess对象。
* @param version 版本号。如果该参数值为0,则表示发布新的版本,系统自动计算一个新的版本号。
* 否则表示覆盖版本号为version的已存在的流程定义,或者插入一个版本号为version的流程定义。<br/>
* @return 流程定义描述符
* @throws InvalidModelException
*/
public ProcessDescriptor uploadProcessObject(Object processObject,int version) throws InvalidModelException;
/**
* 发布流程定义或者覆盖已有的流程定义。<br/>
*
* 当发布新的流程定义时,publishState默认取值为false,validDateFrom是当前时间,validDateTo是一个很大的日期数字2099-12-31,
* ownerId,ownerName,approver,approvedTime,updateLog均为空。<br/>
*
* 当覆盖已有的流程定义时,上述字段的值均维持原值不变。<br/>
*
* ProcessDescriptor相关字段含义如下:<br/>
* publishState:发布状态<br/>
* validDateFrom:流程有效期始<br/>
* validDateTo:流程有效期止<br/>
* ownerId:所有者id<br/>
* ownerName:所有者名称<br/>
* approver:审批人<br/>
* approvedTime:审批时间<br/>
* updateLog:发布日志<br/>
*
* @param inStream input stream形态的流程定义文件。
* @param version 版本号。如果该参数值为0,则表示发布新的版本,系统自动计算一个新的版本号。
* 否则表示覆盖版本号为version的已存在的流程定义,或者插入一个版本号为version的流程定义。<br/>
* @return 流程定义描述符
* @throws InvalidModelException
*/
public ProcessDescriptor uploadProcessStream(InputStream inStream,int version) throws InvalidModelException;
/**
* 发布流程定义或者覆盖已有的流程定义。<br/>
*
* 当发布新的流程定义时,publishState默认取值为false,validDateFrom是当前时间,validDateTo是一个很大的日期数字2099-12-31,
* ownerId,ownerName,approver,approvedTime,updateLog均为空。<br/>
*
* 当覆盖已有的流程定义时,上述字段的值均维持原值不变。<br/>
*
* ProcessDescriptor相关字段含义如下:<br/>
* publishState:发布状态<br/>
* validDateFrom:流程有效期始<br/>
* validDateTo:流程有效期止<br/>
* ownerId:所有者id<br/>
* ownerName:所有者名称<br/>
* approver:审批人<br/>
* approvedTime:审批时间<br/>
* updateLog:发布日志<br/>
*
* @param processXml xml格式的流程定义文件
* @param version 版本号。如果该参数值为0,则表示发布新的版本,系统自动计算一个新的版本号。
* 否则表示覆盖版本号为version的已存在的流程定义,或者插入一个版本号为version的流程定义。<br/>
* @return 流程定义描述符
* @throws InvalidModelException
*/
public ProcessDescriptor uploadProcessXml(String processXml,int version)throws InvalidModelException;
/**
* 通过该方法更新process descriptor中的信息,相关字段的值如下:<br/>
* publishState:发布状态<br/>
* validDateFrom:流程有效期始<br/>
* validDateTo:流程有效期止<br/>
* ownerId:所有者id<br/>
* ownerName:所有者名称<br/>
* approver:审批人<br/>
* approvedTime:审批时间<br/>
* updateLog:发布日志<br/>
*
* @param processDescriptor 流程定义描述符
*/
public void updateProcessDescriptor(ProcessDescriptor processDescriptor);
/**
* 注意:Service repository废除了,2014-01-10
*/
/*
public List<ServiceDescriptor> uploadServicesStream(InputStream inStream,Boolean publishState, Map<ServiceDescriptorProperty,Object> metadata)throws InvalidModelException;
*/
/**
* 注意:Resource repository废除了,2014-01-10
*/
/*
public List<ResourceDescriptor> uploadResourcesStream(InputStream inStream,Boolean publishState, Map<ResourceDescriptorProperty,Object> metadata)throws InvalidModelException;
*/
/*****************************************************************/
/*************** 流程变量相关的api ******************************/
/*****************************************************************/
/**
* TODO XML数据用什么对象表达呢?
* 远程接口中,复杂的Object对象被Xtream转换成xml返回
*/
public Object getVariableValue(Scope scope,String name);
/**
* TODO Xml数据用什么对象表达呢~~~
* @param scope
* @param name
* @param value
* @throws InvalidOperationException
*/
public void setVariableValue(Scope scope,String name,Object value)throws InvalidOperationException;
/**
* TODO 该函数是否有必要?
* @param scope
* @param name
* @param value
* @param headers
* @throws InvalidOperationException
*/
public void setVariableValue(Scope scope,String name,Object value,Properties headers)throws InvalidOperationException;
public Map<String ,Object> getVariableValues(Scope scope);
//TODO 增加一个saveOrUpdateVariable(Variable var)吗?
/*****************************************************************/
/*************** 查询相关的api ******************************/
/*****************************************************************/
/**
* 通过ProcessKey从数据库中查询流程定义对象,
*/
public Object getWorkflowProcess(ProcessKey key) throws InvalidModelException;
public String getWorkflowProcessXml(ProcessKey key);
/**
* 通过ActivityInstance或者ProcessInstance查询对应的流程定义对象;
* 例如输入ActivityInstance返回与之对应的Activity;
* 输入ProcessInstance返回与之对应的SubProcess;
* 其他Scope类型参数均为非法,返回null
* @param scope ActivityInstance或者ProcessInstance
* @return 与scope对应的流程定义对象。
* @throws InvalidModelException
*/
public Object getWorkflowDefinitionElement(Scope scope)throws InvalidModelException;
}