/* * Copyright 2010-2011 the original author or authors. * * 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.googlecode.starflow.engine.service.impl; import java.util.Date; import org.springframework.transaction.TransactionStatus; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import com.googlecode.starflow.core.key.Keys; import com.googlecode.starflow.core.util.PrimaryKeyUtil; import com.googlecode.starflow.engine.ProcessEngine; import com.googlecode.starflow.engine.ProcessEngineException; import com.googlecode.starflow.engine.StarFlowState; import com.googlecode.starflow.engine.core.Constants; import com.googlecode.starflow.engine.event.support.EventUtil; import com.googlecode.starflow.engine.model.ProcessDefine; import com.googlecode.starflow.engine.model.ProcessInstance; import com.googlecode.starflow.engine.repository.IProcessDefineRepository; import com.googlecode.starflow.engine.repository.IProcessInstanceRepository; import com.googlecode.starflow.engine.service.IProcessInstanceService; import com.googlecode.starflow.engine.service.ProcessDefineNotFoundException; import com.googlecode.starflow.engine.support.TriggerProcessEventUtil; import com.googlecode.starflow.engine.transaction.TransactionCallback; import com.googlecode.starflow.engine.transaction.TransactionCallbackWithoutResult; import com.googlecode.starflow.engine.transaction.TransactionTemplate; import com.googlecode.starflow.service.filter.ProcessFilter; /** * * @author libinsong1204@gmail.com * @version 1.0 */ public class ProcessInstanceService implements IProcessInstanceService { //private final Logger logger = LoggerFactory.getLogger(ProcessInstanceService.class); private final ProcessEngine processEngine; private IProcessDefineRepository procDefRep; private IProcessInstanceRepository procInstRep; private TransactionTemplate transactionTemplate; public ProcessInstanceService(ProcessEngine processEngine) { Assert.notNull(processEngine); this.processEngine = processEngine; this.procDefRep = this.processEngine.getApplicationContext().getBean(IProcessDefineRepository.class); this.procInstRep = this.processEngine.getApplicationContext().getBean(IProcessInstanceRepository.class); this.transactionTemplate = processEngine.getTransactionTemplate(); } /** * {@inheritDoc} */ public ProcessInstance createProcess(String processDefName, String userId) { return innercreateProcess(processDefName, userId, -1, -1, -1, Constants.FLOW_ISNOT_SUBFLOW); } /** * {@inheritDoc} */ public ProcessInstance innerCreateSubProcess(String processDefName, String userId, final long mainProcInstId, long parentProcInstId, long activityInstId) { return innercreateProcess(processDefName, userId, mainProcInstId, parentProcInstId, activityInstId, Constants.FLOW_IS_SUBFLOW); } /** * {@inheritDoc} */ private ProcessInstance innercreateProcess(String processDefName, final String userId, final long mainProcInstId, final long parentProcInstId, final long activityInstId, final String subFlow) { if(!StringUtils.hasText(userId)) throw new IllegalArgumentException("创建流程时,必须指定用户 ID"); final ProcessDefine processDefine = procDefRep.findPublishProcessDefine(processDefName); if(processDefine == null) throw new ProcessDefineNotFoundException("没有创建流程,或者流程定义版本没有发布"); //流程启动前触发事件 TriggerProcessEventUtil.beforeStart(processEngine, processDefine, null, processDefine.getProcessElement().getEvents()); ProcessInstance processInstance = transactionTemplate.execute(new TransactionCallback<ProcessInstance>() { public ProcessInstance doInTransaction(TransactionStatus status) { ProcessInstance _processInstance = new ProcessInstance(); _processInstance.setProcessDefId(processDefine.getProcessDefId()); _processInstance.setProcessInstName(processDefine.getProcessDefName()); _processInstance.setCreator(userId); _processInstance.setCurrentState(StarFlowState.PROCESS_INST_START); _processInstance.setSubFlow(subFlow); _processInstance.setCreateTime(new Date()); _processInstance.setLimitNum(processDefine.getLimitTime()); long _id = PrimaryKeyUtil.getPrimaryKey(Keys.PROCESSINSTID); _processInstance.setProcessInstId(_id); if(mainProcInstId == -1 && parentProcInstId == -1) { _processInstance.setMainProcInstId(_id); _processInstance.setParentProcInstId(_id); } else { _processInstance.setMainProcInstId(mainProcInstId); _processInstance.setParentProcInstId(parentProcInstId); } if(activityInstId != -1) _processInstance.setActivityInstId(activityInstId); procInstRep.insertProcessInstance(_processInstance); return _processInstance; } }); for(ProcessFilter filter : this.processEngine.getProcessFilters()) { filter.processCreate(processInstance); } return processInstance; } /** * {@inheritDoc} */ public void startProcess(long processInstId) { final ProcessInstance processInstance = procInstRep.findProcessInstance(processInstId); //检查流程是否处于启动状态 if(StarFlowState.PROCESS_INST_START != processInstance.getCurrentState()) throw new ProcessEngineException("流程实例【"+processInstId+"】未处于启动状态,不能启动流程,当前状态为:" + processInstance.getCurrentState()); transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { EventUtil.publishProcessStartEvent(processEngine, processInstance); } }); } /** * {@inheritDoc} */ public ProcessInstance createAndStartProcess(String processDefName, String userId) { final ProcessInstance processInstance = this.createProcess(processDefName, userId); transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { startProcess(processInstance.getProcessInstId()); processInstance.setCurrentState(StarFlowState.PROCESS_INST_RUNNING); } }); return processInstance; } /** * {@inheritDoc} */ public void terminateProcess(long processInstId) { final ProcessInstance processInstance = procInstRep.findProcessInstance(processInstId); transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { EventUtil.publishProcessTerminalEvent(processEngine, processInstance); } }); } }