/** * 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.pvm.kernel.impl; import java.util.List; import org.fireflow.client.WorkflowSession; import org.fireflow.client.impl.WorkflowSessionLocalImpl; import org.fireflow.engine.context.RuntimeContext; import org.fireflow.pvm.kernel.BookMark; import org.fireflow.pvm.kernel.ExecutionEntrance; import org.fireflow.pvm.kernel.KernelException; import org.fireflow.pvm.kernel.KernelManager; import org.fireflow.pvm.kernel.NodeInstance; import org.fireflow.pvm.kernel.OperationContextName; import org.fireflow.pvm.kernel.PObject; import org.fireflow.pvm.kernel.PObjectKey; import org.fireflow.pvm.kernel.Token; import org.fireflow.pvm.kernel.TokenState; import org.fireflow.pvm.pdllogic.CompensationHandler; import org.fireflow.pvm.pdllogic.ExecuteResult; import org.fireflow.pvm.pdllogic.WorkflowBehavior; /** * @author 非也 * @version 2.0 */ public class NodeInstanceImpl extends AbstractPObject implements NodeInstance { // protected ArcInstance defaultLeavingArcInstance = null; // protected List<ArcInstance> leavingArcInstances = new ArrayList<ArcInstance>(); // protected List<ArcInstance> enteringArcInstances = new ArrayList<ArcInstance>(); // protected NodeInstance parentNodeInstance = null; // protected NetInstance netInstance = null; protected NodeInstance parentNodeInstance = null; public NodeInstanceImpl(PObjectKey key){ super(key); } ////////////////////////////////////////////////////////////////// /////////////// 结构逻辑 /////////////////////////////////// ///////////////////////////////////////////////////////////////// /* (non-Javadoc) * @see org.fireflow.pvm.kernel.NodeInstance#getEnteringArcInstances() */ // @Override // public List<ArcInstance> getEnteringArcInstances() { // return enteringArcInstances; // } // // public void addEnteringArcInstance(ArcInstance arc){ // this.enteringArcInstances.add(arc); // } /* (non-Javadoc) * @see org.fireflow.pvm.kernel.NodeInstance#getLeavingArcInstances() */ // @Override // public List<ArcInstance> getLeavingArcInstances() { // return leavingArcInstances; // } // // public void addLeavingArcInstance(ArcInstance arc){ // this.leavingArcInstances.add(arc); // } /* (non-Javadoc) * @see org.fireflow.pvm.kernel.NodeInstance#getDefaultLeavingArcInstance() */ // @Override // public ArcInstance getDefaultLeavingArcInstance() { // return this.defaultLeavingArcInstance; // } // public void setDefaultLeavingArcInstance(ArcInstance arc){ // this.defaultLeavingArcInstance = arc; // } /* (non-Javadoc) * @see org.fireflow.pvm.kernel.NodeInstance#getNetInstance() */ // @Override // public NetInstance getNetInstance() { // return this.netInstance; // } // // public void setNetInstance(NetInstance net){ // this.netInstance = net; // } /* (non-Javadoc) * @see org.fireflow.pvm.kernel.NodeInstance#getParentNodeInstance() */ // @Override // public NodeInstance getParentNodeInstance() { // return this.parentNodeInstance; // } // // public void setParentNodeInstance(NodeInstance node){ // this.parentNodeInstance = node; // } public boolean isAcceptCompensation(Token token,String compensationCode){ if (this.isCompensable()){ if (token.isContainer()){ return true; }else{ if (compensationCode==null || compensationCode.trim().equals("")){ if (this.defaultCompensationHandler!=null){ return true; } }else{ if (this.getCompensationHandler(compensationCode)!=null){ return true; } } } } return false; } ////////////////////////////////////////////////////////////////// /////////////// 行为逻辑 /////////////////////////////////// ///////////////////////////////////////////////////////////////// /* (non-Javadoc) * @see org.fireflow.pvm.kernel.ProcessObject#handlerCompensation(org.fireflow.engine.WorkflowSession, org.fireflow.pvm.kernel.Token) */ public void handleCompensation(WorkflowSession session, Token listenerToken, Token sourceToken, String compensationCode) { if (!this.isCompensable()) { return; } if (!listenerToken.getState().equals(TokenState.COMPLETED)) { throw new KernelException(this, "Illegal token state ,the TokenState.COMPLETED is expected,but it is " + listenerToken.getState().name()); } RuntimeContext ctx = ((WorkflowSessionLocalImpl) session) .getRuntimeContext(); KernelManager kernelManager = ctx .getDefaultEngineModule(KernelManager.class); boolean compensationDone = true;// 补偿操作是否已经完成 PObject processObject = null; if (compensationCode == null || compensationCode.trim().equals("")) { processObject = this.defaultCompensationHandler; } else { processObject = this.getCompensationHandler(compensationCode); } if (processObject != null) { Token newToken = new TokenImpl(sourceToken); newToken .setElementId(processObject.getKey().getWorkflowElementId()); newToken.setBusinessPermitted(true); newToken.setOperationContextName(OperationContextName.COMPENSATION); newToken.setCallbackTokenId(listenerToken.getId()); BookMark bookMark = new BookMark(); bookMark.setToken(newToken); bookMark.setExtraArg(BookMark.SOURCE_TOKEN, sourceToken); bookMark.setExecutionEntrance(ExecutionEntrance.TAKE_TOKEN); kernelManager.addBookMark(bookMark); compensationDone = false; } else { CompensationHandler compensationHandler = this .getWorkflowBehavior().getCompensationHandler( compensationCode); if (compensationHandler != null) { compensationHandler.handleCompensation(session, listenerToken, this.getWorkflowElement(), compensationCode); compensationDone = true; } else { // 下面的逻辑主要是针对子流程,如果当前的Node 的service是子流程的话,需要将补偿操作传递到子流程里面去。 if (listenerToken.isContainer()) { List<Token> children = kernelManager .getChildren4Compensation(listenerToken); if (children != null && children.size() > 0) { compensationDone = _handleCompensation(kernelManager, listenerToken, children, compensationCode, sourceToken); } } } } if (compensationDone){ listenerToken.setState(TokenState.COMPENSATED); kernelManager.saveOrUpdateToken(listenerToken); WorkflowBehavior behavior = this.getWorkflowBehavior(); behavior.onTokenStateChanged(session, listenerToken, this .getWorkflowElement()); // 通知父token(一般是父流程中的某个活动),使之从Compensating状态转移到compensated状态 Token parentToken = kernelManager.getParentToken(listenerToken); if (parentToken != null) { PObject parent = null; parent = kernelManager.getProcessObject(parentToken); if (parent != null) { BookMark bookMark = new BookMark(); bookMark.setToken(parentToken); bookMark.setExecutionEntrance(ExecutionEntrance.FORWARD_TOKEN); bookMark.setExtraArg(BookMark.SOURCE_TOKEN, listenerToken); kernelManager.addBookMark(bookMark); } } }else{ listenerToken.setState(TokenState.COMPENSATING); kernelManager.saveOrUpdateToken(listenerToken); WorkflowBehavior behavior = this.getWorkflowBehavior(); behavior.onTokenStateChanged(session, listenerToken, this.getWorkflowElement()); } } /** * (2012-02-05,该动作容易和handleTermination混淆,意义也不是特别大,暂且注销) * @param session * @param thisToken * @param sourceToken */ /* public void handleCancellation(WorkflowSession session, Token thisToken, Token sourceToken) { if (!this.isCancellable()){ return; } if (!thisToken.getState().equals(TokenState.INITIALIZED) && !thisToken.getState().equals(TokenState.RUNNING)){ throw new KernelException( "Illegal token state ,the TokenState.INITIALIZED or TokenState.RUNNING is expected,but it is " + thisToken.getState().name()); } RuntimeContext ctx = ((WorkflowSessionLocalImpl) session) .getRuntimeContext(); KernelManager kernelManager = ctx.getDefaultEngineModule(KernelManager.class); PObject processObject = this.getCancellationHandler(); if (processObject != null) { Token newToken = new TokenImpl(thisToken); newToken.setElementId(processObject.getKey().getWorkflowElementId()); newToken.setBusinessPermitted(true); newToken.setCallbackTokenId(thisToken.getId()); BookMark bookMark = new BookMark(); bookMark.setToken(newToken); bookMark.setExecutionEntrance(ExecutionEntrance.TAKE_TOKEN); kernelManager.addBookMark(bookMark); thisToken.setState(TokenState.CANCELLING); kernelManager.saveOrUpdateToken(thisToken); WorkflowBehavior behavior = this.getWorkflowBehavior(); behavior.onTokenStateChanged(session, thisToken, this.getWorkflowElement()); }else{ CancellationHandler cancellationHandler = this.getWorkflowBehavior().getCancellationHandler(); if (cancellationHandler!=null){ cancellationHandler.handleCancellation(session, thisToken, this.getWorkflowElement()); thisToken.setState(TokenState.CANCELLED); kernelManager.saveOrUpdateToken(thisToken); WorkflowBehavior behavior = this.getWorkflowBehavior(); behavior.onTokenStateChanged(session, thisToken, this.getWorkflowElement()); Token parentToken = kernelManager.getParentToken(thisToken); PObject parent = null; if (parentToken!=null){ parent = kernelManager.getProcessObject(parentToken); } if (parent!=null){ BookMark bookMark = new BookMark(); bookMark.setToken(parentToken); bookMark.setExtraArg(BookMark.SOURCE_TOKEN, thisToken); bookMark.setExecutionEntrance(ExecutionEntrance.FORWARD_TOKEN); kernelManager.addBookMark(bookMark); } }else{ List<Token> children = kernelManager.getChildren(thisToken); if (children!=null && children.size()>0){ for (Token childToken:children){ if ((childToken.getState().equals(TokenState.INITIALIZED) || childToken.getState().equals(TokenState.RUNNING)) && childToken.getOperationContextName().equals(OperationContextName.NORMAL)){ BookMark bookMark = new BookMark(); bookMark.setToken(childToken); bookMark.setExtraArg(BookMark.SOURCE_TOKEN, thisToken); bookMark.setExecutionEntrance(ExecutionEntrance.HANDLE_CANCELLATION); kernelManager.addBookMark(bookMark); } } thisToken.setState(TokenState.CANCELLING); kernelManager.saveOrUpdateToken(thisToken); WorkflowBehavior behavior = this.getWorkflowBehavior(); behavior.onTokenStateChanged(session, thisToken, this.getWorkflowElement()); } } } } */ /* (non-Javadoc) * @see org.fireflow.pvm.kernel.ProcessObject#complete(org.fireflow.engine.WorkflowSession, org.fireflow.pvm.kernel.Token) */ // protected void complete(WorkflowSession session, Token token) { // // List<ArcInstance> leavingArcs = this.getLeavingArcInstances(); // if (leavingArcs != null && leavingArcs.size() > 0) { // List<Token> newLeftTokens = new ArrayList<Token>();// 输出边上的token列表 // for (ArcInstance arc : leavingArcs) { // if (this.defaultLeavingArcInstance != null // && !arc.equals(this.defaultLeavingArcInstance)) { // Token newToken = new TokenImpl(token);// 产生新的token // newToken.setWorkflowElementId(arc.getKey() // .getWorkflowElementId()); // // arc.takeToken(session, newToken); // // newLeftTokens.add(newToken); // } // } // if (defaultLeavingArcInstance != null) { // if (token.isAlive()) { // Token newToken = new TokenImpl(token);// 产生新的token // newToken.setWorkflowElementId(defaultLeavingArcInstance // .getKey().getWorkflowElementId()); // for (Token _tmpToken : newLeftTokens) { // if (_tmpToken.isAlive()) { // newToken.setAlive(false); // break; // } // } // defaultLeavingArcInstance.takeToken(session, newToken); // newLeftTokens.add(newToken); // } else { // Token newToken = new TokenImpl(token);// 产生新的token // newToken.setWorkflowElementId(defaultLeavingArcInstance // .getKey().getWorkflowElementId()); // // defaultLeavingArcInstance.takeToken(session, newToken); // newLeftTokens.add(newToken); // } // } // } else if (this.parentNodeInstance != null) { // // 获得ParentNodeInstance对应的Token // Token parentToken = null; // this.parentNodeInstance.forwardToken(session, parentToken); // } // // 检查是否有callback processObject // // // 最后交给NetInstance // else if (this.netInstance != null) { // Token netInstanceToken = null; // this.netInstance.forwardToken(session, netInstanceToken); // } // // } /* (non-Javadoc) * @see org.fireflow.pvm.kernel.NodeInstance#catchFault(org.fireflow.engine.WorkflowSession, org.fireflow.pvm.kernel.Token) */ public void catchFault(WorkflowSession session, Token token, ExecuteResult behaviorResult) { String faultCode = behaviorResult.getErrorCode(); BookMark bookMark = new BookMark(); bookMark.setToken(token); bookMark.setExtraArg(BookMark.SOURCE_TOKEN, token); bookMark.setExecutionEntrance(ExecutionEntrance.HANDLE_FAULT); bookMark.setExtraArg(BookMark.ERROR_CODE, faultCode); RuntimeContext ctx = ((WorkflowSessionLocalImpl) session) .getRuntimeContext(); KernelManager kernelManager = ctx.getDefaultEngineModule(KernelManager.class); kernelManager.addBookMark(bookMark); } }