001: /*
002: * Copyright 2004-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.springframework.webflow.engine.impl;
017:
018: import java.util.ListIterator;
019: import java.util.Map;
020:
021: import org.springframework.util.Assert;
022: import org.springframework.webflow.core.collection.AttributeMap;
023: import org.springframework.webflow.core.collection.CollectionUtils;
024: import org.springframework.webflow.core.collection.LocalAttributeMap;
025: import org.springframework.webflow.core.collection.MutableAttributeMap;
026: import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
027: import org.springframework.webflow.engine.Flow;
028: import org.springframework.webflow.execution.FlowExecution;
029: import org.springframework.webflow.execution.factory.FlowExecutionListenerLoader;
030: import org.springframework.webflow.execution.factory.StaticFlowExecutionListenerLoader;
031: import org.springframework.webflow.execution.repository.support.FlowExecutionStateRestorer;
032:
033: /**
034: * Restores the transient state of deserialized {@link FlowExecutionImpl}
035: * objects.
036: *
037: * @author Keith Donald
038: */
039: public class FlowExecutionImplStateRestorer implements
040: FlowExecutionStateRestorer {
041:
042: /**
043: * Used to restore the flow execution's flow definition.
044: */
045: private FlowDefinitionLocator definitionLocator;
046:
047: /**
048: * Used to restore the flow execution's listeners.
049: */
050: private FlowExecutionListenerLoader executionListenerLoader = StaticFlowExecutionListenerLoader.EMPTY_INSTANCE;
051:
052: /**
053: * Used to restore the flow execution's system attributes.
054: */
055: private AttributeMap executionAttributes = CollectionUtils.EMPTY_ATTRIBUTE_MAP;
056:
057: /**
058: * Creates a new execution transient state restorer.
059: * @param definitionLocator the flow definition locator
060: */
061: public FlowExecutionImplStateRestorer(
062: FlowDefinitionLocator definitionLocator) {
063: Assert.notNull(definitionLocator,
064: "The flow definition locator is required");
065: this .definitionLocator = definitionLocator;
066: }
067:
068: /**
069: * Sets the attributes to apply to restored flow executions.
070: * Execution attributes may affect flow execution behavior.
071: * @param executionAttributes flow execution system attributes
072: */
073: public void setExecutionAttributes(AttributeMap executionAttributes) {
074: Assert.notNull(executionAttributes,
075: "The execution attributes map is required");
076: this .executionAttributes = executionAttributes;
077: }
078:
079: /**
080: * Sets the attributes to apply to restored flow executions.
081: * Execution attributes may affect flow execution behavior.
082: * <p>
083: * Convenience setter that takes a simple <code>java.util.Map</code> to ease
084: * bean style configuration.
085: * @param executionAttributes flow execution system attributes
086: */
087: public void setExecutionAttributesMap(Map executionAttributes) {
088: Assert.notNull(executionAttributes,
089: "The execution attributes map is required");
090: this .executionAttributes = new LocalAttributeMap(
091: executionAttributes);
092: }
093:
094: /**
095: * Sets the strategy for loading listeners that should observe executions of
096: * a flow definition. Allows full control over what listeners should apply.
097: * for executions of a flow definition.
098: */
099: public void setExecutionListenerLoader(
100: FlowExecutionListenerLoader executionListenerLoader) {
101: Assert.notNull(executionListenerLoader,
102: "The listener loader is required");
103: this .executionListenerLoader = executionListenerLoader;
104: }
105:
106: public FlowExecution restoreState(FlowExecution flowExecution,
107: MutableAttributeMap conversationScope) {
108: FlowExecutionImpl impl = (FlowExecutionImpl) flowExecution;
109: // the root flow should be a top-level flow visible by the flow def locator
110: Flow flow = (Flow) definitionLocator.getFlowDefinition(impl
111: .getFlowId());
112: impl.setFlow(flow);
113: if (impl.hasSessions()) {
114: FlowSessionImpl root = impl.getRootSession();
115: root.setFlow(flow);
116: root.setState(flow.getStateInstance(root.getStateId()));
117: if (impl.hasSubflowSessions()) {
118: Flow parent = flow;
119: for (ListIterator it = impl.getSubflowSessionIterator(); it
120: .hasNext();) {
121: FlowSessionImpl subflow = (FlowSessionImpl) it
122: .next();
123: Flow definition;
124: if (parent.containsInlineFlow(subflow.getFlowId())) {
125: // subflow is an inline flow of it's parent
126: definition = parent.getInlineFlow(subflow
127: .getFlowId());
128: } else {
129: // subflow is a top-level flow
130: definition = (Flow) definitionLocator
131: .getFlowDefinition(subflow.getFlowId());
132: }
133: subflow.setFlow(definition);
134: subflow.setState(definition
135: .getStateInstance(subflow.getStateId()));
136: parent = definition;
137: }
138: }
139: }
140: if (conversationScope == null) {
141: conversationScope = new LocalAttributeMap();
142: }
143: impl.setConversationScope(conversationScope);
144: impl.setListeners(new FlowExecutionListeners(
145: executionListenerLoader.getListeners(flow)));
146: impl.setAttributes(executionAttributes);
147: return flowExecution;
148: }
149: }
|