/// <summary>
        /// Find all the tokens for process instance ,and the nodeId of the token must equals to the second argument.
        /// </summary>
        /// <param name="processInstanceId">the id of the process instance</param>
        /// <param name="nodeId">if the nodeId is null ,then return all the tokens of the process instance.</param>
        /// <returns></returns>
        public List<IToken> FindTokensForProcessInstance(String processInstanceId, String nodeId)
        {
            if (String.IsNullOrEmpty(processInstanceId)) return null;
            QueryField queryField = new QueryField();
            queryField.Add(new QueryFieldInfo("processinstance_id", CSharpType.String, processInstanceId));
            queryField.Add(new QueryFieldInfo("node_id", CSharpType.String, nodeId));
            QueryInfo queryInfo = OracleHelper.GetFormatQuery(queryField);

            List<IToken> infos = new List<IToken>();
            using (OracleConnection connection = new OracleConnection(connectionString))
            {
                string select = String.Format("select * from t_ff_rt_token{0}", queryInfo.QueryStringWhere);
                OracleDataReader reader = null;
                try
                {
                    reader = OracleHelper.ExecuteReader(connection, CommandType.Text, select, ((List<OracleParameter>)queryInfo.ListQueryParameters).ToArray());
                    if (reader != null)
                    {
                        while (reader.Read())
                        {
                            IToken info = OracleDataReaderToInfo.GetToken(reader);
                            infos.Add(info);
                        }
                    }
                }
                finally
                {
                    reader.Close();
                }
            }
            return infos;
        }
        /// <summary>
        /// 获得操作员发起的工作流实例列表(运行中)(分页)
        /// publishUser如果为null,获取全部
        /// </summary>
        /// <param name="creatorId">操作员主键</param>
        /// <param name="publishUser">流程定义发布者</param>
        /// <param name="pageSize">每页显示的条数</param>
        /// <param name="pageNumber">当前页数</param>
        /// <returns></returns>
        public List<IProcessInstance> FindProcessInstanceListByCreatorId(String creatorId, String publishUser, int pageSize, int pageNumber)
        {
            int sum = 0;
            List<IProcessInstance> _IProcessInstances = new List<IProcessInstance>();

            QueryField queryField = new QueryField();
            queryField.Add(new QueryFieldInfo("a.creator_id", CSharpType.String, creatorId));
            queryField.Add(new QueryFieldInfo("b.publish_user", CSharpType.String, publishUser));
            QueryInfo queryInfo = OracleHelper.GetFormatQuery(queryField);

            OracleConnection conn = new OracleConnection(connectionString);
            OracleDataReader reader = null;
            try
            {
                reader = OracleHelper.ExecuteReader(conn, pageNumber, pageSize, out sum, 
                    "T_FF_RT_PROCESSINSTANCE a,t_ff_df_workflowdef b", 
                    "a.*,b.publish_user",
                    String.Format("a.process_id=b.process_id and a.version=b.version {0}", queryInfo.QueryStringAnd), 
                    "a.created_time desc",
                    queryInfo.ListQueryParameters == null ? null : queryInfo.ListQueryParameters.ToArray());

                if (reader != null)
                {
                    while (reader.Read())
                    {
                        IProcessInstance _IProcessInstance = OracleDataReaderToInfo.GetProcessInstance(reader);
                        _IProcessInstances.Add(_IProcessInstance);
                    }
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                if (reader != null) reader.Close();
                if (conn.State != ConnectionState.Closed)
                {
                    conn.Close();
                    conn.Dispose();
                }
            }
            return _IProcessInstances;
        }
        /// <summary>
        /// 查找操作员在某个流程某个任务上的已办工单。
        /// actorId,processId,taskId都可以为空(null或者""),为空的条件将被忽略
        ///  已办工单是指状态等于COMPLETED或CANCELED的工单
        ///  (Engine没有引用到该方法,提供给业务系统使用,20090303)
        /// </summary>
        public List<IWorkItem> FindHaveDoneWorkItems(String actorId, String processId, String taskId)
        {
            QueryField queryField = new QueryField();
            queryField.Add(new QueryFieldInfo("actor_id", CSharpType.String, actorId));
            queryField.Add(new QueryFieldInfo("process_id", CSharpType.String, processId));
            queryField.Add(new QueryFieldInfo("task_id", CSharpType.String, taskId));
            QueryInfo queryInfo = OracleHelper.GetFormatQuery(queryField);

            List<IWorkItem> infos = new List<IWorkItem>();
            using (OracleConnection connection = new OracleConnection(connectionString))
            {
                String select = String.Format(
                    "select a.*,b.* from t_ff_rt_workitem a,t_ff_rt_taskinstance b where a.taskinstance_id=b.id and a.state in ({0},{1}){2}",
                    (int)WorkItemEnum.COMPLETED,
                    (int)WorkItemEnum.CANCELED,
                    queryInfo.QueryStringAnd);

                OracleDataReader reader = null;
                try
                {
                    reader = OracleHelper.ExecuteReader(connection, CommandType.Text, select, ((List<OracleParameter>)queryInfo.ListQueryParameters).ToArray());
                    if (reader != null)
                    {
                        while (reader.Read())
                        {
                            IWorkItem info = OracleDataReaderToInfo.GetWorkItem(reader);
                            ITaskInstance iTaskInstance = OracleDataReaderToInfo.GetTaskInstance(reader); //FindTaskInstanceById(((WorkItem)info).TaskInstanceId);
                            ((WorkItem)info).TaskInstance=iTaskInstance;
                            infos.Add(info);
                        }
                    }
                }
                finally
                {
                    reader.Close();
                }
            }
            return infos;
        }