1 16 package org.springframework.webflow.engine; 17 18 import java.util.Iterator ; 19 20 import org.springframework.core.style.StylerUtils; 21 import org.springframework.core.style.ToStringCreator; 22 import org.springframework.webflow.execution.Action; 23 import org.springframework.webflow.execution.Event; 24 import org.springframework.webflow.execution.FlowExecutionException; 25 import org.springframework.webflow.execution.RequestContext; 26 import org.springframework.webflow.execution.ViewSelection; 27 28 115 public class ActionState extends TransitionableState { 116 117 120 private ActionList actionList = new ActionList(); 121 122 130 public ActionState(Flow flow, String id) throws IllegalArgumentException { 131 super(flow, id); 132 } 133 134 139 public ActionList getActionList() { 140 return actionList; 141 } 142 143 152 public Transition getRequiredTransition(RequestContext context) throws NoMatchingTransitionException { 153 Transition transition = getTransitionSet().getTransition(context); 154 if (transition == null) { 155 throw new NoMatchingActionResultTransitionException(this, context.getLastEvent()); 156 } 157 return transition; 158 } 159 160 174 protected ViewSelection doEnter(RequestControlContext context) throws FlowExecutionException { 175 int executionCount = 0; 176 String [] eventIds = new String [actionList.size()]; 177 Iterator it = actionList.iterator(); 178 while (it.hasNext()) { 179 Action action = (Action)it.next(); 180 Event event = ActionExecutor.execute(action, context); 181 if (event != null) { 182 eventIds[executionCount] = event.getId(); 183 try { 184 return context.signalEvent(event); 186 } 187 catch (NoMatchingActionResultTransitionException e) { 188 if (logger.isDebugEnabled()) { 189 logger.debug("Action execution [" 190 + (executionCount + 1) 191 + "] resulted in no matching transition on event '" 192 + event.getId() 193 + "'" 194 + (it.hasNext() ? ": proceeding to the next action in the list" 195 : ": action list exhausted")); 196 } 197 } 198 } 199 else { 200 if (logger.isDebugEnabled()) { 201 logger.debug("Action execution [" 202 + (executionCount + 1) 203 + "] returned a [null] event" 204 + (it.hasNext() ? ": proceeding to the next action in the list" 205 : ": action list exhausted")); 206 } 207 eventIds[executionCount] = null; 208 } 209 executionCount++; 210 } 211 if (executionCount > 0) { 212 throw new NoMatchingTransitionException(getFlow().getId(), getId(), context.getLastEvent(), 213 "No transition was matched on the event(s) signaled by the [" + executionCount 214 + "] action(s) that executed in this action state '" + getId() + "' of flow '" 215 + getFlow().getId() + "'; transitions must be defined to handle action result outcomes -- " 216 + "possible flow configuration error? Note: the eventIds signaled were: '" 217 + StylerUtils.style(eventIds) 218 + "', while the supported set of transitional criteria for this action state is '" 219 + StylerUtils.style(getTransitionSet().getTransitionCriterias()) + "'"); 220 } 221 else { 222 throw new IllegalStateException ( 223 "No actions were executed, thus I cannot execute any state transition " 224 + "-- programmer configuration error; make sure you add at least one action to this state's action list"); 225 } 226 } 227 228 protected void appendToString(ToStringCreator creator) { 229 creator.append("actionList", actionList); 230 super.appendToString(creator); 231 } 232 233 240 private static class NoMatchingActionResultTransitionException extends NoMatchingTransitionException { 241 242 247 public NoMatchingActionResultTransitionException(ActionState state, Event resultEvent) { 248 super(state.getFlow().getId(), state.getId(), resultEvent, 249 "Cannot find a transition matching an action result event; continuing with next action..."); 250 } 251 } 252 } | Popular Tags |