1 16 package org.springframework.webflow.execution.repository.support; 17 18 import java.io.Serializable ; 19 20 import org.springframework.util.Assert; 21 import org.springframework.webflow.conversation.Conversation; 22 import org.springframework.webflow.conversation.ConversationException; 23 import org.springframework.webflow.conversation.ConversationId; 24 import org.springframework.webflow.conversation.ConversationManager; 25 import org.springframework.webflow.conversation.ConversationParameters; 26 import org.springframework.webflow.conversation.NoSuchConversationException; 27 import org.springframework.webflow.core.collection.MutableAttributeMap; 28 import org.springframework.webflow.definition.FlowDefinition; 29 import org.springframework.webflow.execution.FlowExecution; 30 import org.springframework.webflow.execution.repository.BadlyFormattedFlowExecutionKeyException; 31 import org.springframework.webflow.execution.repository.FlowExecutionKey; 32 import org.springframework.webflow.execution.repository.FlowExecutionLock; 33 import org.springframework.webflow.execution.repository.FlowExecutionRepositoryException; 34 import org.springframework.webflow.execution.repository.NoSuchFlowExecutionException; 35 36 45 public abstract class AbstractConversationFlowExecutionRepository extends AbstractFlowExecutionRepository { 46 47 50 private static final String SCOPE_ATTRIBUTE = "scope"; 51 52 56 private ConversationManager conversationManager; 57 58 63 protected AbstractConversationFlowExecutionRepository(FlowExecutionStateRestorer executionStateRestorer, 64 ConversationManager conversationManager) { 65 super(executionStateRestorer); 66 setConversationManager(conversationManager); 67 } 68 69 72 protected ConversationManager getConversationManager() { 73 return conversationManager; 74 } 75 76 80 private void setConversationManager(ConversationManager conversationManager) { 81 Assert.notNull(conversationManager, "The conversation manager is required"); 82 this.conversationManager = conversationManager; 83 } 84 85 public FlowExecutionKey generateKey(FlowExecution flowExecution) { 86 ConversationParameters parameters = createConversationParameters(flowExecution); 89 Conversation conversation = conversationManager.beginConversation(parameters); 90 onBegin(conversation); 91 return new CompositeFlowExecutionKey(conversation.getId(), generateContinuationId(flowExecution)); 92 } 93 94 public FlowExecutionKey getNextKey(FlowExecution flowExecution, FlowExecutionKey previousKey) { 95 CompositeFlowExecutionKey key = (CompositeFlowExecutionKey)previousKey; 96 return new CompositeFlowExecutionKey(key.getConversationId(), generateContinuationId(flowExecution)); 99 } 100 101 public FlowExecutionLock getLock(FlowExecutionKey key) throws FlowExecutionRepositoryException { 102 return new ConversationBackedFlowExecutionLock(getConversation(key)); 104 } 105 106 public abstract FlowExecution getFlowExecution(FlowExecutionKey key) throws FlowExecutionRepositoryException; 107 108 public abstract void putFlowExecution(FlowExecutionKey key, FlowExecution flowExecution) 109 throws FlowExecutionRepositoryException; 110 111 public void removeFlowExecution(FlowExecutionKey key) throws FlowExecutionRepositoryException { 112 Conversation conversation = getConversation(key); 114 conversation.end(); 115 onEnd(conversation); 116 } 117 118 public FlowExecutionKey parseFlowExecutionKey(String encodedKey) throws FlowExecutionRepositoryException { 119 Assert.hasText(encodedKey, "The string encoded flow execution key is required"); 120 String [] keyParts = CompositeFlowExecutionKey.keyParts(encodedKey); 121 122 ConversationId conversationId; 124 try { 125 conversationId = conversationManager.parseConversationId(keyParts[0]); 126 } 127 catch (ConversationException e) { 128 throw new BadlyFormattedFlowExecutionKeyException(encodedKey, 129 "The conversation id '" + keyParts[0] + "' contained in the composite flow execution key '" 130 + encodedKey + "' is invalid", e); 131 } 132 133 Serializable continuationId; 135 try { 136 continuationId = parseContinuationId(keyParts[1]); 137 } 138 catch (FlowExecutionRepositoryException e) { 139 throw new BadlyFormattedFlowExecutionKeyException(encodedKey, 140 "The continuation id '" + keyParts[1] + "' contained in the composite flow execution key '" 141 + encodedKey + "' is invalid", e); 142 } 143 144 return new CompositeFlowExecutionKey(conversationId, continuationId); 145 } 146 147 149 156 protected ConversationParameters createConversationParameters(FlowExecution flowExecution) { 157 FlowDefinition flow = flowExecution.getDefinition(); 158 return new ConversationParameters(flow.getId(), flow.getCaption(), flow.getDescription()); 159 } 160 161 167 protected void onBegin(Conversation conversation) { 168 } 169 170 177 protected void onEnd(Conversation conversation) { 178 } 179 180 185 protected ConversationId getConversationId(FlowExecutionKey key) { 186 return ((CompositeFlowExecutionKey)key).getConversationId(); 187 } 188 189 194 protected Serializable getContinuationId(FlowExecutionKey key) { 195 return ((CompositeFlowExecutionKey)key).getContinuationId(); 196 } 197 198 206 protected Conversation getConversation(FlowExecutionKey key) throws NoSuchFlowExecutionException { 207 try { 208 return getConversationManager().getConversation(getConversationId(key)); 209 } 210 catch (NoSuchConversationException e) { 211 throw new NoSuchFlowExecutionException(key, e); 212 } 213 } 214 215 222 protected MutableAttributeMap getConversationScope(FlowExecutionKey key) { 223 return (MutableAttributeMap)getConversation(key).getAttribute(SCOPE_ATTRIBUTE); 224 } 225 226 232 protected void putConversationScope(FlowExecutionKey key, MutableAttributeMap scope) { 233 Assert.notNull(scope, "The conversation scope attribute map is required"); 234 getConversation(key).putAttribute(SCOPE_ATTRIBUTE, scope); 235 } 236 237 239 245 protected abstract Serializable generateContinuationId(FlowExecution flowExecution); 246 247 252 protected abstract Serializable parseContinuationId(String encodedId) throws FlowExecutionRepositoryException; 253 254 } | Popular Tags |