From aa8ce4d470ae5763938ab707abb11b4c49c5806e Mon Sep 17 00:00:00 2001
From: Keith Donald
* This class delegates to the standard NavigationHandler implementation when a navigation request does not pertain to a
* flow execution.
*
@@ -46,159 +33,43 @@ import org.springframework.webflow.executor.support.FlowExecutorArgumentExtracto
*
* If a flow execution has been restored in the current request:
* NavigationHandler that provides integration with Spring Web Flow.
- * Responsible for delegating to Spring Web Flow to launch and resume flow executions, treating JSF action outcomes
+ * Responsible for delegating to Spring Web Flow to resume flow executions by treating JSF action outcomes
* (like a command button click) as web flow events.
- *
+ *
- *
- *
- * If a flow execution has not been restored in the current request: - *
NavigationHandler implementation and return.
- * NavigationHandler this class decorates
*/
- private FlowExecutorArgumentExtractor argumentExtractor = new FlowNavigationHandlerArgumentExtractor();
-
- /**
- * The service responsible for mapping attributes of an {@link ExternalContext} to a new {@link FlowExecution}
- * during the {@link #launch(String, ExternalContext) launch flow} operation.
- *
- * This allows developers to control what attributes are made available in the inputMap to new
- * top-level flow executions. The starting execution may then choose to map that available input into its own local
- * scope.
- *
- * The default implementation simply exposes all request parameters as flow execution input attributes. May be null.
- */
- private AttributeMapper inputMapper = new RequestParameterInputMapper();
-
- /**
- * Create a new {@link FlowNavigationHandler} using the default constructor.
- */
- public FlowNavigationHandler() {
- super();
+ public FlowNavigationHandler(NavigationHandler delegateHandler) {
+ this.delegateHandler = delegateHandler;
}
- /**
- * Create a new {@link FlowNavigationHandler}, wrapping the specified standard navigation handler implementation.
- * @param originalNavigationHandler Standard NavigationHandler we are wrapping
- */
- public FlowNavigationHandler(NavigationHandler originalNavigationHandler) {
- super(originalNavigationHandler);
- }
-
- /**
- * Returns the argument extractor used by this navigation handler.
- */
- public FlowExecutorArgumentExtractor getArgumentExtractor() {
- return argumentExtractor;
- }
-
- /**
- * Sets the argument extractor to use by this navigation handler. Call to customize how flow id and event id
- * arguments are extracted.
- */
- public void setArgumentExtractor(FlowExecutorArgumentExtractor argumentExtractor) {
- this.argumentExtractor = argumentExtractor;
- }
-
- /**
- * Returns the configured flow execution input mapper.
- */
- public AttributeMapper getInputMapper() {
- return inputMapper;
- }
-
- /**
- * Sets the service responsible for mapping attributes of an {@link ExternalContext} to a new {@link FlowExecution}
- * during a launch flow operation.
- *
- * The default implementation simply exposes all request parameters as flow execution input attributes. May be null.
- * @see RequestParameterInputMapper
- */
- public void setInputMapper(AttributeMapper inputMapper) {
- this.inputMapper = inputMapper;
- }
-
- public void handleNavigation(FacesContext facesContext, String fromAction, String outcome,
- NavigationHandler originalNavigationHandler) {
- JsfExternalContext context = new JsfExternalContext(facesContext, fromAction, outcome);
+ public void handleNavigation(FacesContext facesContext, String fromAction, String outcome) {
if (FlowExecutionHolderUtils.isFlowExecutionRestored(facesContext)) {
- // the flow execution has been restored, now see if we need to signal an event against it
- if (argumentExtractor.isEventIdPresent(context)) {
- // a flow execution has been restored, signal an event in it
- String eventId = argumentExtractor.extractEventId(context);
- FlowExecutionHolder holder = FlowExecutionHolderUtils.getFlowExecutionHolder(facesContext);
- ViewSelection selectedView = holder.getFlowExecution().signalEvent(eventId, context);
- holder.setViewSelection(selectedView);
- }
+ // a flow execution has been restored - signal an event against it
+ FlowExecutionHolder holder = FlowExecutionHolderUtils.getFlowExecutionHolder(facesContext);
+ JsfExternalContext context = new JsfExternalContext(facesContext, fromAction, outcome);
+ ViewSelection selectedView = holder.getFlowExecution().signalEvent(outcome, context);
+ holder.setViewSelection(selectedView);
}
else {
- // no flow execution exists, see if we need to launch one if the flow id is present
- if (argumentExtractor.isFlowIdPresent(context)) {
- // a flow execution launch has been requested, start it
- String flowId = argumentExtractor.extractFlowId(context);
- FlowDefinition flowDefinition = getLocator(context).getFlowDefinition(flowId);
- FlowExecution flowExecution = getFactory(context).createFlowExecution(flowDefinition);
- FlowExecutionHolder holder = new FlowExecutionHolder(flowExecution);
- FlowExecutionHolderUtils.setFlowExecutionHolder(holder, facesContext);
- ViewSelection selectedView = flowExecution.start(createInput(context), context);
- holder.setViewSelection(selectedView);
- }
- else {
- // no flow id submitted, proceed with std navigation
- originalNavigationHandler.handleNavigation(facesContext, fromAction, outcome);
- }
+ // no flow execution is restored, proceed with std navigation
+ delegateHandler.handleNavigation(facesContext, fromAction, outcome);
}
}
-
- /**
- * Factory method that creates the input attribute map for a newly created {@link FlowExecution}. This
- * implementation uses the registered input mapper, if any.
- * @param context the external context
- * @return the input map, or null if no input
- */
- protected MutableAttributeMap createInput(ExternalContext context) {
- if (inputMapper != null) {
- MutableAttributeMap inputMap = new LocalAttributeMap();
- inputMapper.map(context, inputMap, null);
- return inputMap;
- }
- else {
- return null;
- }
- }
-
- // helpers
-
- private FlowDefinitionLocator getLocator(JsfExternalContext context) {
- return FlowFacesUtils.getDefinitionLocator(context.getFacesContext());
- }
-
- private FlowExecutionFactory getFactory(JsfExternalContext context) {
- return FlowFacesUtils.getExecutionFactory(context.getFacesContext());
- }
}
\ No newline at end of file
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowNavigationHandlerArgumentExtractor.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowNavigationHandlerArgumentExtractor.java
deleted file mode 100644
index faa3b707..00000000
--- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FlowNavigationHandlerArgumentExtractor.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2004-2007 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.webflow.executor.jsf;
-
-import org.springframework.util.StringUtils;
-import org.springframework.webflow.context.ExternalContext;
-import org.springframework.webflow.executor.support.FlowExecutorArgumentExtractionException;
-import org.springframework.webflow.executor.support.FlowExecutorArgumentExtractor;
-
-/**
- * An {@link FlowExecutorArgumentExtractor} that is aware of JSF outcomes that communicate requests to launch flow
- * executions and signal event in existing flow executions. Designed to be used wih a {@link FlowNavigationHandler}.
- *
- * Note: this class only implements flow id and event id extraction methods. A FlowNavigationHandler is not expected to
- * extract a flow execution key, as flow execution restoration is fully handled by the {@link FlowPhaseListener} and the
- * JSF restore view phase.
- *
- * @author Keith Donald
- */
-public class FlowNavigationHandlerArgumentExtractor implements FlowExecutorArgumentExtractor {
-
- /**
- * The default prefix of a JSF outcome string that indicates a new flow should be launched.
- */
- private static final String FLOW_ID_PREFIX = "flowId:";
-
- /**
- * The prefix for JSF outcome strings indicating a new flow should be launched.
- */
- private String flowIdPrefix = FLOW_ID_PREFIX;
-
- /**
- * Returns the configured prefix for outcome strings that indicate a new flow should be launched.
- */
- public String getFlowIdPrefix() {
- return flowIdPrefix;
- }
-
- /**
- * Sets the prefix of an outcome string that indicates a new flow should be launched.
- */
- public void setFlowIdPrefix(String flowIdPrefix) {
- this.flowIdPrefix = flowIdPrefix;
- }
-
- public boolean isFlowIdPresent(ExternalContext context) throws FlowExecutorArgumentExtractionException {
- String outcome = getOutcome(context);
- if (outcome != null && outcome.startsWith(getFlowIdPrefix())) {
- return true;
- }
- else {
- return false;
- }
- }
-
- public String extractFlowId(ExternalContext context) throws FlowExecutorArgumentExtractionException {
- // extract the flowId from a JSF outcome in format ${flowIdPrefix}${flowId}
- String outcome = getOutcome(context);
- int index = outcome.indexOf(getFlowIdPrefix());
- if (index == -1) {
- throw new FlowExecutorArgumentExtractionException(
- "Unable to extract flow id; make sure the JSF outcome is prefixed with '" + getFlowIdPrefix()
- + "' to launch a new flow execution");
- }
- String flowId = outcome.substring(getFlowIdPrefix().length());
- if (!StringUtils.hasText(flowId)) {
- throw new FlowExecutorArgumentExtractionException(
- "Unable to extract flow id; make sure the flow id is provided in the outcome string");
- }
- return flowId;
- }
-
- public boolean isEventIdPresent(ExternalContext context) {
- return StringUtils.hasText(getOutcome(context));
- }
-
- public String extractEventId(ExternalContext context) throws FlowExecutorArgumentExtractionException {
- // treat the action outcome string as the event id
- return getOutcome(context);
- }
-
- public boolean isFlowExecutionKeyPresent(ExternalContext context) {
- throw new UnsupportedOperationException("Should not be called by a FlowNavigationHandler");
- }
-
- public String extractFlowExecutionKey(ExternalContext context) throws FlowExecutorArgumentExtractionException {
- throw new UnsupportedOperationException("Should not be called by a FlowNavigationHandler");
- }
-
- // helpers
- private String getOutcome(ExternalContext context) {
- return ((JsfExternalContext) context).getOutcome();
- }
-}
\ No newline at end of file