package org.springframework.webflow.execution.repository.impl;
import java.util.HashMap;
import java.util.Map;
import junit.framework.TestCase;
import org.springframework.webflow.conversation.Conversation;
import org.springframework.webflow.conversation.ConversationException;
import org.springframework.webflow.conversation.ConversationId;
import org.springframework.webflow.conversation.ConversationManager;
import org.springframework.webflow.conversation.ConversationParameters;
import org.springframework.webflow.conversation.NoSuchConversationException;
import org.springframework.webflow.conversation.impl.BadlyFormattedConversationIdException;
import org.springframework.webflow.conversation.impl.SimpleConversationId;
import org.springframework.webflow.definition.FlowDefinition;
import org.springframework.webflow.definition.registry.FlowDefinitionConstructionException;
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
import org.springframework.webflow.definition.registry.NoSuchFlowDefinitionException;
import org.springframework.webflow.engine.Flow;
import org.springframework.webflow.engine.StubViewFactory;
import org.springframework.webflow.engine.Transition;
import org.springframework.webflow.engine.ViewState;
import org.springframework.webflow.engine.impl.FlowExecutionImplFactory;
import org.springframework.webflow.engine.support.DefaultTargetStateResolver;
import org.springframework.webflow.execution.FlowExecution;
import org.springframework.webflow.execution.FlowExecutionKey;
import org.springframework.webflow.execution.repository.BadlyFormattedFlowExecutionKeyException;
import org.springframework.webflow.execution.repository.FlowExecutionLock;
import org.springframework.webflow.execution.repository.FlowExecutionRestorationFailureException;
import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException;
import org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshotFactory;
import org.springframework.webflow.test.MockExternalContext;
public class DefaultFlowExecutionRepositoryTests extends TestCase {
private Flow flow;
private ConversationManager conversationManager;
private DefaultFlowExecutionRepository repository;
FlowExecutionImplFactory executionFactory = new FlowExecutionImplFactory();
protected void setUp() throws Exception {
flow = new Flow("myFlow");
ViewState s1 = new ViewState(flow, "state", new StubViewFactory());
s1.getTransitionSet().add(new Transition(new DefaultTargetStateResolver("state2")));
new ViewState(flow, "state2", new StubViewFactory());
conversationManager = new StubConversationManager();
FlowDefinitionLocator locator = new FlowDefinitionLocator() {
public FlowDefinition getFlowDefinition(String flowId) throws NoSuchFlowDefinitionException,
FlowDefinitionConstructionException {
return flow;
}
};
SerializedFlowExecutionSnapshotFactory snapshotFactory = new SerializedFlowExecutionSnapshotFactory(
executionFactory, locator);
repository = new DefaultFlowExecutionRepository(conversationManager, snapshotFactory);
executionFactory.setExecutionKeyFactory(repository);
}
public void testParseFlowExecutionKey() {
String key = "e12345s54321";
FlowExecutionKey k = repository.parseFlowExecutionKey(key);
assertEquals(key, k.toString());
}
public void testParseBadlyFormattedFlowExecutionKey() {
String key = "e12345";
try {
repository.parseFlowExecutionKey(key);
fail("Should have failed");
} catch (BadlyFormattedFlowExecutionKeyException e) {
assertEquals("e12345", e.getInvalidKey());
assertNotNull(e.getFormat());
}
}
public void testParseBadlyFormattedFlowExecutionKeyBadContinuationId() {
String key = "c12345vaaaa";
try {
repository.parseFlowExecutionKey(key);
fail("Should have failed");
} catch (BadlyFormattedFlowExecutionKeyException e) {
assertEquals("c12345vaaaa", e.getInvalidKey());
assertNotNull(e.getFormat());
}
}
public void testGetLock() {
FlowExecutionKey key = repository.parseFlowExecutionKey("e12345s54321");
FlowExecutionLock lock = repository.getLock(key);
assertNotNull(lock);
lock.unlock();
}
public void testGetLockNoSuchFlowExecution() {
FlowExecutionKey key = repository.parseFlowExecutionKey("e99999s54321");
try {
repository.getLock(key);
fail("should have failed");
} catch (NoSuchFlowExecutionException e) {
e.printStackTrace();
}
}
public void testPutFlowExecution() {
FlowExecution execution = executionFactory.createFlowExecution(flow);
execution.start(null, new MockExternalContext());
assertNotNull(execution.getKey());
repository.putFlowExecution(execution);
String key = execution.getKey().toString();
FlowExecutionKey parsedKey = repository.parseFlowExecutionKey(key);
FlowExecution execution2 = repository.getFlowExecution(parsedKey);
assertSame(execution.getDefinition(), execution2.getDefinition());
assertEquals(execution.getActiveSession().getState().getId(), execution2.getActiveSession().getState().getId());
}
public void testPutFlowExecutionNextSnapshotId() {
FlowExecution execution = executionFactory.createFlowExecution(flow);
execution.start(null, new MockExternalContext());
assertNotNull(execution.getKey());
repository.putFlowExecution(execution);
String key = execution.getKey().toString();
FlowExecutionKey parsedKey = repository.parseFlowExecutionKey(key);
FlowExecution execution2 = repository.getFlowExecution(parsedKey);
assertSame(execution.getDefinition(), execution2.getDefinition());
assertEquals(execution.getActiveSession().getState().getId(), execution2.getActiveSession().getState().getId());
MockExternalContext context = new MockExternalContext();
context.setEventId("foo");
execution2.resume(context);
repository.putFlowExecution(execution2);
assertNotSame(execution.getKey(), execution2.getKey());
}
public void testPutFlowExecutionNoKeyAssigned() {
FlowExecution execution = executionFactory.createFlowExecution(flow);
try {
repository.putFlowExecution(execution);
fail("Should have failed");
} catch (IllegalStateException e) {
}
}
public void testRemoveFlowExecution() {
FlowExecution execution = executionFactory.createFlowExecution(flow);
execution.start(null, new MockExternalContext());
assertNotNull(execution.getKey());
repository.putFlowExecution(execution);
repository.removeFlowExecution(execution);
try {
repository.getFlowExecution(execution.getKey());
fail("Should have failed");
} catch (NoSuchFlowExecutionException e) {
}
}
public void testRemoveKeyNotSet() {
FlowExecution execution = executionFactory.createFlowExecution(flow);
try {
repository.removeFlowExecution(execution);
fail("Should have failed");
} catch (IllegalStateException e) {
}
}
public void testRemoveNoSuchFlowExecution() {
FlowExecution execution = executionFactory.createFlowExecution(flow);
execution.start(null, new MockExternalContext());
try {
repository.removeFlowExecution(execution);
repository.removeFlowExecution(execution);
fail("Should have failed");
} catch (NoSuchFlowExecutionException e) {
}
}
public void testGetKey() {
FlowExecution execution = executionFactory.createFlowExecution(flow);
assertEquals("e12345s1", repository.getKey(execution).toString());
assertEquals("e12345s2", repository.getKey(execution).toString());
assertEquals("e12345s3", repository.getKey(execution).toString());
}
public void testUpdate() {
FlowExecution execution = executionFactory.createFlowExecution(flow);
execution.start(null, new MockExternalContext());
repository.putFlowExecution(execution);
execution.getActiveSession().getScope().put("foo", "bar");
repository.updateFlowExecutionSnapshot(execution);
FlowExecution execution2 = repository.getFlowExecution(execution.getKey());
assertEquals("bar", execution2.getActiveSession().getScope().get("foo"));
}
public void testRemove() {
FlowExecution execution = executionFactory.createFlowExecution(flow);
execution.start(null, new MockExternalContext());
repository.putFlowExecution(execution);
repository.removeFlowExecutionSnapshot(execution);
try {
repository.getFlowExecution(execution.getKey());
fail("Should have failed");
} catch (FlowExecutionRestorationFailureException e) {
}
}
public void testRemoveAll() {
FlowExecution execution = executionFactory.createFlowExecution(flow);
execution.start(null, new MockExternalContext());
repository.putFlowExecution(execution);
repository.removeAllFlowExecutionSnapshots(execution);
try {
repository.getFlowExecution(execution.getKey());
fail("Should have failed");
} catch (FlowExecutionRestorationFailureException e) {
}
}
public void testUpdateNothingToDo() {
FlowExecution execution = executionFactory.createFlowExecution(flow);
repository.updateFlowExecutionSnapshot(execution);
}
public void testRemoveNothingToDo() {
FlowExecution execution = executionFactory.createFlowExecution(flow);
repository.removeFlowExecutionSnapshot(execution);
}
public void testRemoveAllSnapshotsNothingToDo() {
FlowExecution execution = executionFactory.createFlowExecution(flow);
repository.removeAllFlowExecutionSnapshots(execution);
}
public static class StubConversationManager implements ConversationManager {
/**
* The single conversation managed by the manager.
*/
private final StubConversation INSTANCE = new StubConversation();
public Conversation beginConversation(ConversationParameters conversationParameters)
throws ConversationException {
return INSTANCE;
}
public Conversation getConversation(ConversationId id) throws ConversationException {
if (id.equals(INSTANCE.getId()) && !INSTANCE.hasEnded()) {
return INSTANCE;
} else {
throw new NoSuchConversationException(id);
}
}
public ConversationId parseConversationId(String encodedId) throws ConversationException {
try {
return new SimpleConversationId(Integer.parseInt(encodedId));
} catch (NumberFormatException e) {
throw new BadlyFormattedConversationIdException(encodedId, e);
}
}
private static class StubConversation implements Conversation {
private final ConversationId ID = new SimpleConversationId(12345);
private boolean ended;
private Map<Object, Object> attributes = new HashMap<Object, Object>();
public boolean hasEnded() {
return ended;
}
public ConversationId getId() {
return ID;
}
public void lock() {
}
public Object getAttribute(Object name) {
return attributes.get(name);
}
public void putAttribute(Object name, Object value) {
attributes.put(name, value);
}
public void removeAttribute(Object name) {
attributes.remove(name);
}
public void end() {
ended = true;
}
public void unlock() {
}
}
}
}