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.executor;
017:
018: import java.io.Serializable;
019:
020: import org.springframework.core.style.ToStringCreator;
021: import org.springframework.util.Assert;
022: import org.springframework.webflow.execution.FlowExecutionContext;
023: import org.springframework.webflow.execution.ViewSelection;
024: import org.springframework.webflow.execution.support.ApplicationView;
025: import org.springframework.webflow.execution.support.ExternalRedirect;
026: import org.springframework.webflow.execution.support.FlowDefinitionRedirect;
027: import org.springframework.webflow.execution.support.FlowExecutionRedirect;
028:
029: /**
030: * Immutable value object that provides clients with information about a
031: * response to issue.
032: * <p>
033: * There are five different <i>types</i> of response instruction:
034: * <ul>
035: * <li>An {@link #isApplicationView() application view}.</li>
036: * <li>A {@link #isFlowExecutionRedirect() flow execution redirect}, showing
037: * an application view via a redirect that refreshes an ongoing flow
038: * execution.</li>
039: * <li>A {@link #isFlowDefinitionRedirect() flow definition redirect},
040: * launching an entirely new flow execution.</li>
041: * <li>An {@link #isExternalRedirect() external redirect}, redirecting
042: * to an external URL.</li>
043: * <li>A {@link #isNull() null view}, not showing a response at all.</li>
044: * </ul>
045: *
046: * @author Keith Donald
047: * @author Erwin Vervaet
048: */
049: public class ResponseInstruction implements Serializable {
050:
051: /**
052: * The persistent identifier of the flow execution that
053: * resulted in this response instruction.
054: */
055: private String flowExecutionKey;
056:
057: /**
058: * Basic state info on the flow execution.
059: */
060: private transient FlowExecutionContext flowExecutionContext;
061:
062: /**
063: * The view selection that was made.
064: */
065: private ViewSelection viewSelection;
066:
067: /**
068: * Create a new response instruction for a paused flow execution.
069: * @param flowExecutionKey the persistent identifier of the flow execution
070: * @param flowExecutionContext the current flow execution context
071: * @param viewSelection the selected view
072: */
073: public ResponseInstruction(String flowExecutionKey,
074: FlowExecutionContext flowExecutionContext,
075: ViewSelection viewSelection) {
076: Assert.notNull(flowExecutionKey,
077: "The flow execution key is required");
078: this .flowExecutionKey = flowExecutionKey;
079: init(flowExecutionContext, viewSelection);
080: }
081:
082: /**
083: * Create a new response instruction for an ended flow execution. No
084: * flow execution key needs to be provided since the flow execution no longer
085: * exists and cannot be referenced any longer.
086: * @param flowExecutionContext the current flow execution context (inactive)
087: * @param viewSelection the selected view
088: */
089: public ResponseInstruction(
090: FlowExecutionContext flowExecutionContext,
091: ViewSelection viewSelection) {
092: init(flowExecutionContext, viewSelection);
093: }
094:
095: /**
096: * Helper to initialize the flow execution context and view selection.
097: */
098: private void init(FlowExecutionContext flowExecutionContext,
099: ViewSelection viewSelection) {
100: Assert.notNull(flowExecutionContext,
101: "The flow execution context is required");
102: Assert.notNull(viewSelection, "The view selection is required");
103: this .flowExecutionContext = flowExecutionContext;
104: this .viewSelection = viewSelection;
105: }
106:
107: /**
108: * Returns the persistent identifier of the flow execution.
109: */
110: public String getFlowExecutionKey() {
111: return flowExecutionKey;
112: }
113:
114: /**
115: * Returns the flow execution context representing the current state of the
116: * execution. It could be that the returned flow execution is
117: * {@link FlowExecutionContext#isActive() inactive}.
118: */
119: public FlowExecutionContext getFlowExecutionContext() {
120: return flowExecutionContext;
121: }
122:
123: /**
124: * Returns the view selection selected by the flow execution.
125: */
126: public ViewSelection getViewSelection() {
127: return viewSelection;
128: }
129:
130: /**
131: * Returns true if this is an instruction to render an application view for
132: * an "active" (in progress) flow execution.
133: */
134: public boolean isActiveView() {
135: return isApplicationView() && flowExecutionContext.isActive();
136: }
137:
138: /**
139: * Returns true if this is an instruction to render an application view for
140: * an "ended" (inactive) flow execution from an end state.
141: */
142: public boolean isEndingView() {
143: return isApplicationView() && !flowExecutionContext.isActive();
144: }
145:
146: // response types
147:
148: /**
149: * Returns true if this is an "application view" (forward) response
150: * instruction.
151: */
152: public boolean isApplicationView() {
153: return viewSelection instanceof ApplicationView;
154: }
155:
156: /**
157: * Returns true if this is an instruction to perform a redirect to the
158: * current flow execution to render an application view.
159: */
160: public boolean isFlowExecutionRedirect() {
161: return viewSelection instanceof FlowExecutionRedirect;
162: }
163:
164: /**
165: * Returns true if this is an instruction to launch an entirely new
166: * (independent) flow execution.
167: */
168: public boolean isFlowDefinitionRedirect() {
169: return viewSelection instanceof FlowDefinitionRedirect;
170: }
171:
172: /**
173: * Returns true if this an instruction to perform a redirect to an external
174: * URL.
175: */
176: public boolean isExternalRedirect() {
177: return viewSelection instanceof ExternalRedirect;
178: }
179:
180: /**
181: * Returns true if this is a "null" response instruction, e.g.
182: * no response needs to be rendered.
183: */
184: public boolean isNull() {
185: return viewSelection == ViewSelection.NULL_VIEW;
186: }
187:
188: public boolean equals(Object o) {
189: if (!(o instanceof ResponseInstruction)) {
190: return false;
191: }
192: ResponseInstruction other = (ResponseInstruction) o;
193: if (getFlowExecutionKey() != null) {
194: return getFlowExecutionKey().equals(
195: other.getFlowExecutionKey())
196: && viewSelection.equals(other.viewSelection);
197: } else {
198: return other.getFlowExecutionKey() == null
199: && viewSelection.equals(other.viewSelection);
200: }
201: }
202:
203: public int hashCode() {
204: int hashCode = viewSelection.hashCode();
205: if (getFlowExecutionKey() != null) {
206: hashCode += getFlowExecutionKey().hashCode();
207: }
208: return hashCode;
209: }
210:
211: public String toString() {
212: return new ToStringCreator(this ).append("flowExecutionKey",
213: flowExecutionKey)
214: .append("viewSelection", viewSelection).append(
215: "flowExecutionContext", flowExecutionContext)
216: .toString();
217: }
218: }
|