org.springframework.webflow.engine.impl.FlowExecutionImplFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.webflow.engine.impl.FlowExecutionImplFactory.java

Source

/*
 * 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.engine.impl;

import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.CollectionUtils;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.core.collection.MutableAttributeMap;
import org.springframework.webflow.definition.FlowDefinition;
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
import org.springframework.webflow.engine.Flow;
import org.springframework.webflow.execution.FlowExecution;
import org.springframework.webflow.execution.FlowExecutionFactory;
import org.springframework.webflow.execution.FlowExecutionKey;
import org.springframework.webflow.execution.FlowExecutionKeyFactory;
import org.springframework.webflow.execution.factory.FlowExecutionListenerLoader;
import org.springframework.webflow.execution.factory.StaticFlowExecutionListenerLoader;

/**
 * A factory for instances of the {@link FlowExecutionImpl default flow execution} implementation.
 * @author Keith Donald
 */
public class FlowExecutionImplFactory implements FlowExecutionFactory {

    private static final Log logger = LogFactory.getLog(FlowExecutionImplFactory.class);

    private AttributeMap<Object> executionAttributes = CollectionUtils.EMPTY_ATTRIBUTE_MAP;

    private FlowExecutionListenerLoader executionListenerLoader = StaticFlowExecutionListenerLoader.EMPTY_INSTANCE;

    private FlowExecutionKeyFactory executionKeyFactory = new SimpleFlowExecutionKeyFactory();

    /**
     * Sets the attributes to apply to flow executions created by this factory. Execution attributes may affect flow
     * execution behavior.
     * @param executionAttributes flow execution system attributes
     */
    public void setExecutionAttributes(AttributeMap<Object> executionAttributes) {
        this.executionAttributes = executionAttributes;
    }

    /**
     * Sets the strategy for loading listeners that should observe executions of a flow definition. Allows full control
     * over what listeners should apply for executions of a flow definition.
     */
    public void setExecutionListenerLoader(FlowExecutionListenerLoader executionListenerLoader) {
        this.executionListenerLoader = executionListenerLoader;
    }

    /**
     * Sets the strategy for generating flow execution keys for persistent flow executions.
     */
    public void setExecutionKeyFactory(FlowExecutionKeyFactory executionKeyFactory) {
        this.executionKeyFactory = executionKeyFactory;
    }

    public FlowExecution createFlowExecution(FlowDefinition flowDefinition) {
        Assert.isInstanceOf(Flow.class, flowDefinition, "FlowDefinition is of the wrong type: ");
        if (logger.isDebugEnabled()) {
            logger.debug("Creating new execution of '" + flowDefinition.getId() + "'");
        }
        FlowExecutionImpl execution = new FlowExecutionImpl((Flow) flowDefinition);
        execution.setAttributes(executionAttributes);
        execution.setListeners(executionListenerLoader.getListeners(execution.getDefinition()));
        execution.setKeyFactory(executionKeyFactory);
        return execution;
    }

    public FlowExecution restoreFlowExecution(FlowExecution flowExecution, FlowDefinition flowDefinition,
            FlowExecutionKey flowExecutionKey, MutableAttributeMap<Object> conversationScope,
            FlowDefinitionLocator subflowDefinitionLocator) {
        Assert.isInstanceOf(FlowExecutionImpl.class, flowExecution, "FlowExecution is of the wrong type: ");
        Assert.isInstanceOf(Flow.class, flowDefinition, "FlowDefinition is of the wrong type: ");
        FlowExecutionImpl execution = (FlowExecutionImpl) flowExecution;
        Flow flow = (Flow) flowDefinition;
        execution.setFlow(flow);
        if (execution.hasSessions()) {
            FlowSessionImpl rootSession = execution.getRootSession();
            rootSession.setFlow(flow);
            rootSession.setState(flow.getStateInstance(rootSession.getStateId()));
            if (execution.hasSubflowSessions()) {
                for (Iterator<FlowSessionImpl> it = execution.getSubflowSessionIterator(); it.hasNext();) {
                    FlowSessionImpl subflowSession = it.next();
                    Flow subflowDef = (Flow) subflowDefinitionLocator.getFlowDefinition(subflowSession.getFlowId());
                    subflowSession.setFlow(subflowDef);
                    subflowSession.setState(subflowDef.getStateInstance(subflowSession.getStateId()));
                }
            }
        }
        execution.setKey(flowExecutionKey);
        if (conversationScope == null) {
            conversationScope = new LocalAttributeMap<Object>();
        }
        execution.setConversationScope(conversationScope);
        execution.setAttributes(executionAttributes);
        execution.setListeners(executionListenerLoader.getListeners(execution.getDefinition()));
        execution.setKeyFactory(executionKeyFactory);
        return execution;
    }

    /**
     * Simple key factory suitable for standalone usage and testing. Not expected to be used in a web environment.
     */
    private static class SimpleFlowExecutionKeyFactory implements FlowExecutionKeyFactory {

        private int sequence;

        public FlowExecutionKey getKey(FlowExecution execution) {
            if (execution.getKey() == null) {
                return new SimpleFlowExecutionKey(nextSequence());
            } else {
                // keep the same key
                return execution.getKey();
            }
        }

        public void removeAllFlowExecutionSnapshots(FlowExecution execution) {
        }

        public void removeFlowExecutionSnapshot(FlowExecution execution) {
        }

        public void updateFlowExecutionSnapshot(FlowExecution execution) {
        }

        private synchronized int nextSequence() {
            return ++sequence;
        }

        private static class SimpleFlowExecutionKey extends FlowExecutionKey {

            private int value;

            public SimpleFlowExecutionKey(int value) {
                this.value = value;
            }

            public boolean equals(Object o) {
                if (!(o instanceof SimpleFlowExecutionKey)) {
                    SimpleFlowExecutionKey key = (SimpleFlowExecutionKey) o;
                    return value == key.value;
                }
                return false;
            }

            public int hashCode() {
                return value;
            }

            public String toString() {
                return String.valueOf(value);
            }
        }
    }
}