flowexecutionmanager.java

来自「spring的WEB开发插件,支持多状态WEB开发」· Java 代码 · 共 577 行 · 第 1/2 页

JAVA
577
字号
		}
	}

	/**
	 * Add a listener that will listen to executions for all flows.
	 * @param listener the listener to add
	 */
	public void addListener(FlowExecutionListener listener) {
		addListener(listener, FlowExecutionListenerCriteriaFactory.allFlows());
	}
	
	/**
	 * Add a listener that wil listen to executions to flows matching the specified criteria
	 * @param listener the listener
	 * @param criteria the listener criteria
	 */
	public void addListener(FlowExecutionListener listener, FlowExecutionListenerCriteria criteria) {
		List registeredCriteria = (List)this.flowExecutionListeners.get(listener);
		registeredCriteria.add(criteria);
	}

	/**
	 * Remove the flow execution listener from the listener list.
	 * @param listener the listener
	 */
	public void removeListener(FlowExecutionListener listener) {
		this.flowExecutionListeners.remove(listener);
	}
	
	/**
	 * Returns the storage strategy used by the flow execution manager.
	 */
	protected FlowExecutionStorage getStorage() {
		return storage;
	}

	/**
	 * Set the storage strategy used by the flow execution manager.
	 */
	public void setStorage(FlowExecutionStorage storage) {
		Assert.notNull(storage, "The flow execution storage strategy is required");
		this.storage = storage;
	}

	/**
	 * Return the application transaction synchronization strategy to use.
	 * This defaults to a <i>synchronizer token</i> based transaction management
	 * system, as implemented by {@link FlowScopeTokenTransactionSynchronizer}.
	 */
	protected TransactionSynchronizer getTransactionSynchronizer() {
		return transactionSynchronizer;
	}

	/**
	 * Set the application transaction synchronization strategy to use.
	 */
	public void setTransactionSynchronizer(TransactionSynchronizer transactionSynchronizer) {
		this.transactionSynchronizer = transactionSynchronizer;
	}

	/**
	 * Returns the conversion service used by this flow execution manager.
	 */
	public ConversionService getConversionService() {
		return conversionService;
	}
	
	/**
	 * Set the conversion service used by this flow execution manager.
	 */
	public void setConversionService(ConversionService conversionService) {
		this.conversionService = conversionService;
	}

	/**
	 * Returns this flow execution manager's bean factory.
	 */
	protected BeanFactory getBeanFactory() {
		return this.beanFactory;
	}

	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		this.beanFactory = beanFactory;
		if (getFlowLocator() instanceof BeanFactoryAware) {
			// make the BeanFactoryFlowServiceLocator work
			((BeanFactoryAware)getFlowLocator()).setBeanFactory(beanFactory);
		}
	}

	// event processing

	/**
	 * Signal the occurence of the specified event - this is the entry point into the 
	 * webflow system for managing all executing flows.
	 * @param event the event that occured
	 * @return the view descriptor of the model and view to render
	 * @throws Exception in case of errors
	 */
	public ViewDescriptor onEvent(Event event) throws Exception {
		return onEvent(event, null);
	}

	/**
	 * Signal the occurence of the specified event - this is the entry point into the 
	 * webflow system for managing all executing flows.
	 * @param event the event that occured
	 * @param listener a listener interested in flow execution
	 *        lifecycle events that happen <i>while handling this event</i>
	 * @return the view descriptor of the model and view to render
	 * @throws Exception in case of errors
	 */
	public ViewDescriptor onEvent(Event event, FlowExecutionListener listener) throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug("New request received from client, source event is: "+ event);
		}
		FlowExecution flowExecution;
		ViewDescriptor viewDescriptor;
		Serializable id = getFlowExecutionId(event);
		if (id == null) {
			// start a new flow execution
			Flow flow = getFlow(event);
			flowExecution = createFlowExecution(flow);
			if (listener != null) {
				flowExecution.getListeners().add(listener);
			}
			flowExecution.getListeners().fireCreated(flowExecution);
			if (logger.isDebugEnabled()) {
				logger.debug("Created new flow execution for flow definition: '" + flow.getId() + "'");
			}
			viewDescriptor = flowExecution.start(event);
		}
		else {
			// client is participating in an existing flow execution,
			// retrieve information about it
			flowExecution = getStorage().load(id, event);
			// rehydrate the execution if neccessary (if it had been serialized out)
			flowExecution.rehydrate(getFlowLocator(), this, getTransactionSynchronizer());
			if (listener != null) {
				flowExecution.getListeners().add(listener);
			}
			flowExecution.getListeners().fireLoaded(flowExecution, id);
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded existing flow execution from storage with id: '" + id + "'");
			}
			// signal the event within the current state
			Assert.hasText(event.getId(), "No eventId could be obtained -- "
					+ "make sure the client provides the _eventId parameter as input; the parameters provided for this request were:" 
					+ StylerUtils.style(event.getParameters()));
			// see if the eventId was set to a static marker placeholder because
			// of a client configuration error
			if (event.getId().equals(getNotSetEventIdParameterMarker())) {
				throw new IllegalArgumentException("The received eventId was the 'not set' marker '"
						+ getNotSetEventIdParameterMarker()
						+ "' -- this is likely a view (jsp, etc) configuration error --"
						+ "the _eventId parameter must be set to a valid event");
			}
			viewDescriptor = flowExecution.signalEvent(event);
		}
		if (flowExecution.isActive()) {
			// save the flow execution for future use
			id = getStorage().save(id, flowExecution, event);
			flowExecution.getListeners().fireSaved(flowExecution, id);
			if (logger.isDebugEnabled()) {
				logger.debug("Saved flow execution out to storage with id: '" + id + "'");
			}
		}
		else {
			// event execution resulted in the entire flow execution ending, cleanup
			if (id != null) {
				getStorage().remove(id, event);
				flowExecution.getListeners().fireRemoved(flowExecution, id);
				if (logger.isDebugEnabled()) {
					logger.debug("Removed flow execution from storage with id: '" + id + "'");
				}
			}
		}
		if (listener != null) {
			flowExecution.getListeners().remove(listener);
		}
		viewDescriptor = prepareViewDescriptor(viewDescriptor, id, flowExecution);
		if (logger.isDebugEnabled()) {
			logger.debug("Returning selected view to client: " + viewDescriptor);
		}
		return viewDescriptor;
	}

	// subclassing hooks

	/**
	 * Create a new flow execution for given flow. Subclasses could redefine this
	 * if they wish to use a specialized FlowExecution implementation class.
	 * @param flow the flow
	 * @return the created flow execution
	 */
	protected FlowExecution createFlowExecution(Flow flow) {
		return new FlowExecutionImpl(flow, getListeners(flow), getTransactionSynchronizer());
	}

	/**
	 * Obtain a flow to use from given event. If there is a "_flowId" parameter
	 * specified in the event, the flow with that id will be returend after
	 * lookup using the flow locator. If no "_flowId" parameter is present in the
	 * event, the default top-level flow will be returned.
	 */
	protected Flow getFlow(Event event) {
		String flowId = ExternalEvent.verifySingleStringInputParameter(getFlowIdParameterName(), event.getParameter(getFlowIdParameterName()));
		if (!StringUtils.hasText(flowId)) {
			Assert.notNull(getFlow(),
					"This flow execution manager is not configured with a default top-level flow--that means "
							+ "the flow to launch must be provided by the client via the '"
							+ getFlowIdParameterName() + "' parameter, yet no such parameter was provided in this event." +
							" Parameters provided were: " + StylerUtils.style(event.getParameters()));
			return getFlow();
		}
		else {
			Assert.notNull(getFlowLocator(), "The flow locator is required to lookup the requested flow with id '"
					+ flowId + "'; however, the flowLocator property is null");
			return getFlowLocator().getFlow(flowId);
		}
	}

	/**
	 * Returns the name of the flow id parameter in the event ("_flowId").
	 */
	protected String getFlowIdParameterName() {
		return FLOW_ID_PARAMETER;
	}

	/**
	 * Obtain a unique flow execution id from given event.
	 * @param event the event
	 * @return the obtained id or <code>null</code> if not found
	 */
	protected String getFlowExecutionId(Event event) {
		return ExternalEvent.verifySingleStringInputParameter(getFlowExecutionIdParameterName(), event.getParameter(getFlowExecutionIdParameterName()));
	}

	/**
	 * Returns the name of the flow execution id parameter in the event
	 * ("_flowExecutionId").
	 */
	protected String getFlowExecutionIdParameterName() {
		return FLOW_EXECUTION_ID_PARAMETER;
	}

	/**
	 * Returns the marker value indicating that the event id parameter was not
	 * set properly in the event because of a view configuration error ("@NOT_SET@").
	 * <p>
	 * This is useful when a view relies on an dynamic means to set the eventId
	 * event parameter, for example, using javascript. This approach assumes
	 * the "not set" marker value will be a static default (a kind of fallback,
	 * submitted if the eventId does not get set to the proper dynamic value
	 * onClick, for example, if javascript was disabled).
	 */
	protected String getNotSetEventIdParameterMarker() {
		return NOT_SET_EVENT_ID;
	}

	/**
	 * Do any processing necessary before given view descriptor can be returned
	 * to the client of the flow execution manager. This implementation adds
	 * a number of <i>infrastructure attributes</i> to the model that will be
	 * exposed to the view. More specifically, it will add the
	 * {@link #FLOW_EXECUTION_CONTEXT_ATTRIBUTE}, {@link #FLOW_EXECUTION_ID_ATTRIBUTE}
	 * and {@link #CURRENT_STATE_ID_ATTRIBUTE}.
	 * @param viewDescriptor the view descriptor to be processed
	 * @param flowExecutionId the unique id of the flow execution
	 * @param flowExecutionContext the flow context providing info about the flow execution
	 * @return the processed view descriptor
	 */
	protected ViewDescriptor prepareViewDescriptor(ViewDescriptor viewDescriptor, Serializable flowExecutionId,
			FlowExecutionContext flowExecutionContext) {
		if (flowExecutionContext.isActive() && viewDescriptor != null) {
			if (viewDescriptor.isRedirect()) {
				viewDescriptor.addObject(getFlowExecutionIdParameterName(), flowExecutionId);
			}
			else {
				// make the entire flow execution context available in the model
				viewDescriptor.addObject(FLOW_EXECUTION_CONTEXT_ATTRIBUTE, flowExecutionContext);
				// make the unique flow execution id and current state id available in the model as convenience to views
				viewDescriptor.addObject(FLOW_EXECUTION_ID_ATTRIBUTE, flowExecutionId);
				viewDescriptor.addObject(CURRENT_STATE_ID_ATTRIBUTE, flowExecutionContext.getCurrentState().getId());
			}
		}
		return viewDescriptor;
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?