001/* 002 * Copyright 2012-2013 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.springframework.batch.core.job.builder; 017 018import java.util.ArrayList; 019import java.util.List; 020 021import org.springframework.batch.core.Job; 022import org.springframework.batch.core.Step; 023import org.springframework.batch.core.job.SimpleJob; 024import org.springframework.batch.core.job.flow.JobExecutionDecider; 025import org.springframework.core.task.TaskExecutor; 026import org.springframework.util.Assert; 027 028/** 029 * @author Dave Syer 030 * 031 * @since 2.2 032 * 033 */ 034public class SimpleJobBuilder extends JobBuilderHelper<SimpleJobBuilder> { 035 036 private List<Step> steps = new ArrayList<Step>(); 037 038 private JobFlowBuilder builder; 039 040 /** 041 * Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used. 042 * 043 * @param parent the parent to use 044 */ 045 public SimpleJobBuilder(JobBuilderHelper<?> parent) { 046 super(parent); 047 } 048 049 public Job build() { 050 if (builder != null) { 051 return builder.end().build(); 052 } 053 SimpleJob job = new SimpleJob(getName()); 054 super.enhance(job); 055 job.setSteps(steps); 056 try { 057 job.afterPropertiesSet(); 058 } 059 catch (Exception e) { 060 throw new JobBuilderException(e); 061 } 062 return job; 063 } 064 065 /** 066 * Start the job with this step. 067 * 068 * @param step a step to start with 069 * @return this for fluent chaining 070 */ 071 public SimpleJobBuilder start(Step step) { 072 if (steps.isEmpty()) { 073 steps.add(step); 074 } 075 else { 076 steps.set(0, step); 077 } 078 return this; 079 } 080 081 /** 082 * Branch into a flow conditional on the outcome of the current step. 083 * 084 * @param pattern a pattern for the exit status of the current step 085 * @return a builder for fluent chaining 086 */ 087 public FlowBuilder.TransitionBuilder<FlowJobBuilder> on(String pattern) { 088 Assert.state(steps.size() > 0, "You have to start a job with a step"); 089 for (Step step : steps) { 090 if (builder == null) { 091 builder = new JobFlowBuilder(new FlowJobBuilder(this), step); 092 } 093 else { 094 builder.next(step); 095 } 096 } 097 return builder.on(pattern); 098 } 099 100 /** 101 * Start with this decider. Returns a flow builder and when the flow is ended a job builder will be returned to 102 * continue the job configuration if needed. 103 * 104 * @param decider a decider to execute first 105 * @return builder for fluent chaining 106 */ 107 public JobFlowBuilder start(JobExecutionDecider decider) { 108 if (builder == null) { 109 builder = new JobFlowBuilder(new FlowJobBuilder(this), decider); 110 } 111 else { 112 builder.start(decider); 113 } 114 if (!steps.isEmpty()) { 115 steps.remove(0); 116 } 117 for (Step step : steps) { 118 builder.next(step); 119 } 120 return builder; 121 } 122 123 /** 124 * Continue with this decider if the previous step was successful. Returns a flow builder and when the flow is ended 125 * a job builder will be returned to continue the job configuration if needed. 126 * 127 * @param decider a decider to execute next 128 * @return builder for fluent chaining 129 */ 130 public JobFlowBuilder next(JobExecutionDecider decider) { 131 for (Step step : steps) { 132 if (builder == null) { 133 builder = new JobFlowBuilder(new FlowJobBuilder(this), step); 134 } 135 else { 136 builder.next(step); 137 } 138 } 139 if (builder == null) { 140 builder = new JobFlowBuilder(new FlowJobBuilder(this), decider); 141 } 142 else { 143 builder.next(decider); 144 } 145 return builder; 146 } 147 148 /** 149 * Continue or end a job with this step if the previous step was successful. 150 * 151 * @param step a step to execute next 152 * @return this for fluent chaining 153 */ 154 public SimpleJobBuilder next(Step step) { 155 steps.add(step); 156 return this; 157 } 158 159 /** 160 * @param executor instance of {@link TaskExecutor} to be used. 161 * @return builder for fluent chaining 162 */ 163 public JobFlowBuilder.SplitBuilder<FlowJobBuilder> split(TaskExecutor executor) { 164 for (Step step : steps) { 165 if (builder == null) { 166 builder = new JobFlowBuilder(new FlowJobBuilder(this), step); 167 } 168 else { 169 builder.next(step); 170 } 171 } 172 if (builder == null) { 173 builder = new JobFlowBuilder(new FlowJobBuilder(this)); 174 } 175 return builder.split(executor); 176 } 177 178}