/* * Copyright 2004-2012 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.execution.factory; import java.util.LinkedList; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.style.StylerUtils; import org.springframework.util.Assert; import org.springframework.webflow.definition.FlowDefinition; import org.springframework.webflow.execution.FlowExecutionListener; /** * A flow execution listener loader that stores listeners in a list-backed data structure and allows for configuration * of which listeners should apply to which flow definitions. For trivial listener loading, see * {@link StaticFlowExecutionListenerLoader}. * * @see FlowExecutionListenerCriteria * @see StaticFlowExecutionListenerLoader * * @author Keith Donald */ public class ConditionalFlowExecutionListenerLoader implements FlowExecutionListenerLoader { private final Log logger = LogFactory.getLog(ConditionalFlowExecutionListenerLoader.class); /** * The list of flow execution listeners containing {@link ConditionalFlowExecutionListenerHolder} objects. The list * determines the conditions in which a single flow execution listener applies. */ private List<ConditionalFlowExecutionListenerHolder> listeners = new LinkedList<ConditionalFlowExecutionListenerHolder>(); /** * Add a listener that will 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) { if (listener == null) { throw new IllegalArgumentException("The flow execution listener cannot be null"); } if (logger.isDebugEnabled()) { logger.debug("Adding flow execution listener " + listener + " with criteria " + criteria); } ConditionalFlowExecutionListenerHolder conditional = getHolder(listener); if (conditional == null) { conditional = new ConditionalFlowExecutionListenerHolder(listener); listeners.add(conditional); } if (criteria == null) { criteria = new FlowExecutionListenerCriteriaFactory().allFlows(); } conditional.add(criteria); } /** * Returns the array of flow execution listeners for specified flow. * @param flowDefinition the flow definition associated with the execution to be listened to * @return the flow execution listeners that apply */ public FlowExecutionListener[] getListeners(FlowDefinition flowDefinition) { Assert.notNull(flowDefinition, "The Flow to load listeners for cannot be null"); List<FlowExecutionListener> listenersToAttach = new LinkedList<FlowExecutionListener>(); for (ConditionalFlowExecutionListenerHolder listenerHolder : listeners) { if (listenerHolder.listenerAppliesTo(flowDefinition)) { listenersToAttach.add(listenerHolder.getListener()); } } if (logger.isDebugEnabled()) { logger.debug("Loaded [" + listenersToAttach.size() + "] of possible " + listeners.size() + " listeners for this execution request for flow '" + flowDefinition.getId() + "', the listeners to attach are " + StylerUtils.style(listenersToAttach)); } return listenersToAttach.toArray(new FlowExecutionListener[listenersToAttach.size()]); } // internal helpers /** * Lookup the listener criteria holder for the listener provided. * @param listener the listener * @return the holder, or null if not found */ private ConditionalFlowExecutionListenerHolder getHolder(FlowExecutionListener listener) { for (ConditionalFlowExecutionListenerHolder holder : listeners) { if (holder.getListener().equals(listener)) { return holder; } } return null; } }