Package org.springframework.batch.core.configuration.xml

Source Code of org.springframework.batch.core.configuration.xml.SimpleFlowFactoryBean

/*
* Copyright 2012-2014 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.batch.core.configuration.xml;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.springframework.batch.core.job.flow.Flow;
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
import org.springframework.batch.core.job.flow.FlowExecutor;
import org.springframework.batch.core.job.flow.FlowHolder;
import org.springframework.batch.core.job.flow.State;
import org.springframework.batch.core.job.flow.support.SimpleFlow;
import org.springframework.batch.core.job.flow.support.StateTransition;
import org.springframework.batch.core.job.flow.support.state.AbstractState;
import org.springframework.batch.core.job.flow.support.state.StepState;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

/**
* Convenience factory for SimpleFlow instances for use in XML namespace. It
* replaces the states in the input with proxies that have a unique name formed
* from the flow name and the original state name (unless the name is already in
* that form, in which case it is not modified).
*
* @author Dave Syer
* @author Michael Minella
*/
public class SimpleFlowFactoryBean implements FactoryBean<SimpleFlow>, InitializingBean {

  private String name;

  private List<StateTransition> stateTransitions;

  private String prefix;

  private Comparator<StateTransition> stateTransitionComparator;

  private Class<SimpleFlow> flowType;

  /**
   * @param stateTransitionComparator {@link Comparator} implementation that addresses
   * the ordering of state evaluation
   */
  public void setStateTransitionComparator(Comparator<StateTransition> stateTransitionComparator) {
    this.stateTransitionComparator = stateTransitionComparator;
  }

  /**
   * @param flowType Used to inject the type of flow (regular Spring Batch or JSR-352)
   */
  public void setFlowType(Class<SimpleFlow> flowType) {
    this.flowType = flowType;
  }

  /**
   * The name of the flow that is created by this factory.
   *
   * @param name the value of the name
   */
  public void setName(String name) {
    this.name = name;
    this.prefix = name + ".";
  }

  /**
   * The raw state transitions for the flow. They will be transformed into
   * proxies that have the same behavior but unique names prefixed with the
   * flow name.
   *
   * @param stateTransitions the list of transitions
   */
  public void setStateTransitions(List<StateTransition> stateTransitions) {
    this.stateTransitions = stateTransitions;
  }

  /**
   * Check mandatory properties (name).
   *
   * @throws Exception
   */
  @Override
  public void afterPropertiesSet() throws Exception {
    Assert.hasText(name, "The flow must have a name");

    if(flowType == null) {
      flowType = SimpleFlow.class;
    }
  }

  /* (non-Javadoc)
   * @see org.springframework.beans.factory.FactoryBean#getObject()
   */
  @Override
  public SimpleFlow getObject() throws Exception {
    SimpleFlow flow = flowType.getConstructor(String.class).newInstance(name);

    flow.setStateTransitionComparator(stateTransitionComparator);

    List<StateTransition> updatedTransitions = new ArrayList<StateTransition>();
    for (StateTransition stateTransition : stateTransitions) {
      State state = getProxyState(stateTransition.getState());
      updatedTransitions.add(StateTransition.switchOriginAndDestination(stateTransition, state,
          getNext(stateTransition.getNext())));
    }

    flow.setStateTransitions(updatedTransitions);
    flow.afterPropertiesSet();
    return flow;

  }

  private String getNext(String next) {
    if (next == null) {
      return null;
    }
    return (next.startsWith(this.prefix) ? "" : this.prefix) + next;
  }

  /**
   * Convenience method to get a state that proxies the input but with a
   * different name, appropriate to this flow. If the state is a StepState
   * then the step name is also changed.
   *
   * @param state
   * @return
   */
  private State getProxyState(State state) {
    String oldName = state.getName();
    if (oldName.startsWith(prefix)) {
      return state;
    }
    String stateName = prefix + oldName;
    if (state instanceof StepState) {
      return createNewStepState(state, oldName, stateName);
    }
    return new DelegateState(stateName, state);
  }

  /**
   * Provides an extension point to provide alternative {@link StepState}
   * implementations within a {@link SimpleFlow}
   *
   * @param state The state that will be used to create the StepState
   * @param oldName The name to be replaced
   * @param stateName The name for the new State
   * @return
   */
  protected State createNewStepState(State state, String oldName,
      String stateName) {
    return new StepState(stateName, ((StepState) state).getStep(oldName));
  }

  @Override
  public Class<?> getObjectType() {
    return SimpleFlow.class;
  }

  @Override
  public boolean isSingleton() {
    return true;
  }

  /**
   * A State that proxies a delegate and changes its name but leaves its
   * behavior unchanged.
   *
   * @author Dave Syer
   *
   */
  public static class DelegateState extends AbstractState implements FlowHolder {
    private final State state;

    private DelegateState(String name, State state) {
      super(name);
      this.state = state;
    }

    public State getState() {
      return this.state;
    }

    @Override
    public boolean isEndState() {
      return state.isEndState();
    }

    @Override
    public FlowExecutionStatus handle(FlowExecutor executor) throws Exception {
      return state.handle(executor);
    }

    @Override
    public Collection<Flow> getFlows() {
      return (state instanceof FlowHolder) ? ((FlowHolder)state).getFlows() : Collections.<Flow>emptyList();
    }

  }

}
TOP

Related Classes of org.springframework.batch.core.configuration.xml.SimpleFlowFactoryBean

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.