⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 undotest.java

📁 一个java工作流引擎
💻 JAVA
字号:
package org.jbpm.service;

import java.util.*;
import junit.framework.*;
import org.jbpm.*;
import org.jbpm.delegation.*;
import org.jbpm.model.definition.*;
import org.jbpm.model.execution.impl.*;
import org.jbpm.model.log.*;

public class UndoTest extends TestCase {
  
  public static TestHelper helper = new TestHelper();
  private ExecutionService executionService = helper.getExecutionService();
  
  static {
    helper.deployProcess( "process/undoableprocess.xml" );
    helper.deployProcess( "process/undoableactionprocess.xml" );
  }

  public void testStateUndo() throws Exception {
    // retrieve the definition
    Definition definition = executionService.getLatestDefinition( "the undoable process" );
    
    // start a process instance
    InvocationLog invocationLog = executionService.startProcessInstance( "start-actor", definition.getId() );
    ProcessInstanceImpl pi = (ProcessInstanceImpl) invocationLog.getProcessInstance(); 
    Long piId = pi.getId();
    Long tokenId = pi.getRoot().getId();

    Date date = new Date();
    
    // now we are going to execute the process like the procession of Echternach
    // thats a procession in which the participants take two steps forward and one step back :-)

    // one step forward
    assertEquals( "one", getStateName( tokenId ) );
    InvocationLog firstInvocationLog = executionService.endOfState( "actor-one", tokenId );
    assertEquals( "two", getStateName( tokenId ) );
    
    // one step back
    executionService.undo( "testrunner", piId, firstInvocationLog.getDate() );
    assertEquals( "one", getStateName( tokenId ) );
    
    // two steps forward
    firstInvocationLog = executionService.endOfState( "actor-two", tokenId );
    InvocationLog secondInvocationLog = executionService.endOfState( "actor-three", tokenId );
    assertEquals( "three", getStateName( tokenId ) );

    // one step back
    executionService.undo( "testrunner", piId, secondInvocationLog.getDate() );
    assertEquals( "two", getStateName( tokenId ) );

    // one step forward
    executionService.endOfState( "actor-four", tokenId );
    invocationLog = executionService.endOfState( "actor-five", tokenId );

    // check that the process has ended
    Date firstEndDate = invocationLog.getProcessInstance().getEnd();
    assertTrue( isPiEnded( piId ) );
    assertTrue( isRootEnded( piId ) );
    
    // two steps back
    executionService.undo( "testrunner", piId, date );
    assertEquals( "one", getStateName( tokenId ) );
    assertFalse( isPiEnded( piId ) );
    assertFalse( isRootEnded( piId ) );
    
    // three steps forward
    executionService.endOfState( "actor-three", tokenId );
    assertEquals( "two", getStateName( tokenId ) );
    executionService.endOfState( "actor-four", tokenId );
    assertEquals( "three", getStateName( tokenId ) );
    date = new Date();
    invocationLog = executionService.endOfState( "actor-five", tokenId );
    assertTrue( isPiEnded( piId ) );
    assertTrue( isRootEnded( piId ) );
    
    // one step back
    executionService.undo( "testrunner", piId, date );
    assertEquals( "three", getStateName( tokenId ) );
    assertFalse( isPiEnded( piId ) );
    assertFalse( isRootEnded( piId ) );
  }
  
  public boolean isPiEnded( Long processInstanceId ) {
    ProcessInstanceImpl pi = (ProcessInstanceImpl) executionService.getProcessInstance( processInstanceId, null );
    return pi.hasEnded();
  }

  public boolean isRootEnded( Long processInstanceId ) {
    ProcessInstanceImpl pi = (ProcessInstanceImpl) executionService.getProcessInstance( processInstanceId, null );
    return pi.getRoot().hasEnded();
  }

  public void testUndoException() throws Exception {
    // retrieve the definition
    Definition definition = executionService.getLatestDefinition( "the undoable process" );
    
    // start a process instance
    InvocationLog invocationLog = executionService.startProcessInstance( "start-actor", definition.getId() );
    ProcessInstanceImpl pi = (ProcessInstanceImpl) invocationLog.getProcessInstance(); 
    Long piId = pi.getId();
    Long tokenId = pi.getRoot().getId();

    // now we are going to execute the process like the procession of Echternach
    // thats a procession in which the participants take two steps forward and one step back :-)

    try {
			// rollback the process till 1900 somewhere 
			executionService.undo( "testrunner", piId, new Date( 0 ) );
      fail();
		} catch (UnUndoableException e) {
			// OK
		}

    try {
      // rollback the process till one minute in the future 
      executionService.undo( "testrunner", piId, new Date( new Date().getTime() + (1000*60) ) );
      fail();
    } catch (UnUndoableException e) {
      // OK
    }
  }
  
  private String getStateName(Long tokenId) {
    TokenImpl token = (TokenImpl) executionService.getToken( tokenId, null );
		return token.getState().getName();
	}

	public void testVariablesUndo() throws Exception {
    // retrieve the definition
    Definition definition = executionService.getLatestDefinition( "the undoable process" );
    
    // create the variables
    Map variables = new HashMap();
    variables.put( "text", "this text wants to remain the same" );
    variables.put( "number", new Long(1) );
    variables.put( "overridden.text", "this text wants to be changed and undone" );
    variables.put( "overridden.number", new Long(2) );
    
    // start a process instance
    InvocationLog invocationLog = executionService.startProcessInstance( "start-actor", definition.getId(), variables );
    ProcessInstanceImpl pi = (ProcessInstanceImpl) invocationLog.getProcessInstance(); 
    Long piId = pi.getId();
    Long tokenId = pi.getRoot().getId();
    
    // check the process variables
    variables = executionService.getVariables( tokenId );
    checkVariablesInStateOne(variables);
    
    // remember the date for later rollback
    Date date = new Date();

    // one step forward
    variables = new HashMap();
    variables.put( "added.variable", "with a fresh value" );
    variables.put( "overridden.text", "undo me !" );
    variables.put( "overridden.number", new Long(13) ); // if even this number works, it *must* be correct 
    executionService.endOfState( "actor-one", tokenId, variables );
    
    // check the process variables
    variables = executionService.getVariables( tokenId );
    assertEquals( "this text wants to remain the same", variables.get( "text" )  );
    assertEquals( new Long(1), variables.get( "number" ) );
    assertEquals( "undo me !", variables.get( "overridden.text" )  );
    assertEquals( new Long(13), variables.get( "overridden.number" ) );
    assertEquals( "with a fresh value", variables.get( "added.variable" ) );

    // one step back
    executionService.undo( "testrunner", piId, date );

    // check the process variables
    variables = executionService.getVariables( tokenId );
    checkVariablesInStateOne(variables);
  }

  private void checkVariablesInStateOne(Map variables) {
		assertEquals( "this text wants to remain the same", variables.get( "text" )  );
    assertEquals( new Long(1), variables.get( "number" ) );
    assertEquals( "this text wants to be changed and undone", variables.get( "overridden.text" )  );
    assertEquals( new Long(2), variables.get( "overridden.number" ) );
    assertNull( variables.get( "added.variable" ) );
	}
  
  public static class UndoableTestActionHandler implements UndoableActionHandler {
    public static boolean hasBeenExecuted = false;
    public static boolean hasBeenUndone = false;
    public static Object variableValue = null;
    
		public void execute(ExecutionContext executionContext) {
      hasBeenExecuted = true;
      executionContext.setVariable( "action var", "the original value" );
    }

    public void undo(ExecutionContext executionContext) {
      hasBeenUndone = true;
      variableValue = executionContext.getVariable( "client var" );
      executionContext.setVariable( "action var", "undo value" );
    }
  }
  
	public void testUndoableActionHandler() throws Exception {
    // retrieve the definition
    Definition definition = executionService.getLatestDefinition( "the undoable action process" );
    
    // create the variables
    Map variables = new HashMap();
    variables.put( "client var", "the client value" );

    // start a process instance
    InvocationLog invocationLog = executionService.startProcessInstance( "start-actor", definition.getId(), variables );
    ProcessInstanceImpl pi = (ProcessInstanceImpl) invocationLog.getProcessInstance(); 
    Long piId = pi.getId();
    Long tokenId = pi.getRoot().getId();

    Date date = new Date();
    assertFalse( UndoableTestActionHandler.hasBeenExecuted );
    assertFalse( UndoableTestActionHandler.hasBeenUndone );
    
    executionService.endOfState( "actor-one", tokenId );

    variables = executionService.getVariables( tokenId );
    assertEquals( "the client value", variables.get( "client var" ) );
    assertEquals( "the original value", variables.get( "action var" ) );
    assertTrue( UndoableTestActionHandler.hasBeenExecuted );
    assertFalse( UndoableTestActionHandler.hasBeenUndone );
    
    executionService.undo( "actor-one", piId, date );

    variables = executionService.getVariables( tokenId );
    assertEquals( "the client value", variables.get( "client var" ) );
    // the action var variable instance is created in the action, that's why it should be null after the undo
    assertNull( variables.get( "action var" ) );
    assertEquals( "the client value", UndoableTestActionHandler.variableValue );
    assertTrue( UndoableTestActionHandler.hasBeenExecuted );
    assertTrue( UndoableTestActionHandler.hasBeenUndone );
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -