/** * Copyright 2007-2010 非也 * All rights reserved. * * This library is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License v3 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 Lesser General Public License along * with this library; if not, see http://www.gnu.org/licenses/lgpl.html. * */ package org.fireflow.pdl.fpdl.behavior.router; import java.util.List; import org.fireflow.client.WorkflowSession; import org.fireflow.client.impl.WorkflowSessionLocalImpl; import org.fireflow.engine.context.RuntimeContext; import org.fireflow.engine.modules.persistence.PersistenceService; import org.fireflow.engine.modules.persistence.TokenPersister; import org.fireflow.pdl.fpdl.misc.FpdlConstants; import org.fireflow.pdl.fpdl.process.Node; import org.fireflow.pdl.fpdl.process.Synchronizer; import org.fireflow.pdl.fpdl.process.Transition; import org.fireflow.pvm.kernel.Token; import org.fireflow.pvm.kernel.TokenState; /** * * @author 非也 nychen2000@163.com * Fire Workflow 官方网站:www.firesoa.com 或者 www.fireflow.org * */ public abstract class AbsJoinEvaluator implements JoinEvaluator { /* (non-Javadoc) * @see org.fireflow.pdl.fpdl.behavior.router.JoinEvaluator#canBeFired(org.fireflow.client.WorkflowSession, org.fireflow.pvm.kernel.Token, java.util.List, org.fireflow.pdl.fpdl.process.Synchronizer) */ /* * (non-Javadoc) * * @see org.fireflow.pdl.fpdl.behavior.router.JoinEvaluator#canBeFired() */ public int canBeFired(WorkflowSession session, Token current_token_for_router, List<Token> siblingTokens, Synchronizer node) { RuntimeContext ctx = ((WorkflowSessionLocalImpl) session) .getRuntimeContext(); PersistenceService persistenceStrategy = ctx.getEngineModule( PersistenceService.class, FpdlConstants.PROCESS_TYPE_FPDL20); TokenPersister tokenPersister = persistenceStrategy.getTokenPersister(); boolean multiEnteringTransitions = false;// 表示是否有多条输入边 if (node.getEnteringTransitions() != null && node.getEnteringTransitions().size() > 1) { multiEnteringTransitions = true; } // 1、通过elementInstanceId判断是否已经被执行 if (multiEnteringTransitions) { Token tokenFromDB = tokenPersister.fetch(Token.class, current_token_for_router.getId()); if (tokenFromDB.getElementInstanceId() != null && !tokenFromDB.getElementInstanceId().trim().equals("")) { // 说明已经执行过 tokenFromDB.setState(TokenState.COMPLETED); tokenPersister.saveOrUpdate(tokenFromDB); return -1; } }else{//如果只有一条输入边,则直接返回 return current_token_for_router.getStepNumber(); } // 2、判断汇聚是否完成 boolean canBeFired = false; if (multiEnteringTransitions) { if (this.hasAlivePreviousNode(session, current_token_for_router, node)) { canBeFired = false; } else { canBeFired = true; } } else {// 只有一条输入边的synchronizer直接启动 canBeFired = true; } if (!canBeFired){ return -1; } //表示汇聚完毕,返回stepnumber最大的值, Token tmpToken = current_token_for_router;//current_token_for_router; if (siblingTokens!=null){ for (Token sibling:siblingTokens){ if (tmpToken.getStepNumber()>sibling.getStepNumber()){ }else{ Token t = tmpToken; tmpToken = sibling; } if (!sibling.getId().equals(current_token_for_router.getId())){ sibling.setState(TokenState.COMPLETED); } } } return tmpToken.getStepNumber(); } /** * 汇聚计算,这是fpdl1.0,和fpdl2.0本质区别的地方。 * @param session * @param token * @param thisNode * @return */ protected boolean hasAlivePreviousNode(WorkflowSession session,Token token,Node thisNode){ RuntimeContext ctx = ((WorkflowSessionLocalImpl)session).getRuntimeContext(); PersistenceService persistenceStrategy = ctx.getEngineModule(PersistenceService.class, FpdlConstants.PROCESS_TYPE_FPDL20); TokenPersister tokenPersister = persistenceStrategy.getTokenPersister(); List<Transition> enteringTransitions = thisNode.getEnteringTransitions(); if (enteringTransitions==null || enteringTransitions.size()==0){ return false; } for (Transition transition:enteringTransitions){ if (!transition.isLoop()){//排除循环的情况 Node fromNode = transition.getFromNode(); int aliveCount = tokenPersister.countAliveToken(token.getProcessInstanceId(), fromNode.getId(),token.getOperationContextName()); if (aliveCount>0){ return true; } boolean b = hasAlivePreviousNode(session,token,fromNode); if (b){ return true; } } } return false; } }