EMMA Coverage Report (generated Thu May 22 12:08:10 CDT 2014)
[all classes][org.springframework.batch.core.configuration.xml]

COVERAGE SUMMARY FOR SOURCE FILE [AbstractStepParser.java]

nameclass, %method, %block, %line, %
AbstractStepParser.java100% (1/1)100% (6/6)95%  (463/485)95%  (117.8/124)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class AbstractStepParser100% (1/1)100% (6/6)95%  (463/485)95%  (117.8/124)
parseJob (Element, Element, AbstractBeanDefinition, ParserContext, boolean): ... 100% (1/1)90%  (54/60)87%  (13/15)
parsePartition (Element, Element, AbstractBeanDefinition, ParserContext, bool... 100% (1/1)92%  (141/153)90%  (35/39)
parseStep (Element, ParserContext, String): AbstractBeanDefinition 100% (1/1)98%  (220/224)100% (56.8/57)
<static initializer> 100% (1/1)100% (6/6)100% (1/1)
AbstractStepParser (): void 100% (1/1)100% (3/3)100% (1/1)
parseFlow (Element, Element, AbstractBeanDefinition, ParserContext, boolean):... 100% (1/1)100% (39/39)100% (11/11)

1/*
2 * Copyright 2006-2009 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.springframework.batch.core.configuration.xml;
17 
18import org.springframework.batch.core.listener.StepListenerMetaData;
19import org.springframework.beans.MutablePropertyValues;
20import org.springframework.beans.factory.config.BeanDefinition;
21import org.springframework.beans.factory.config.BeanDefinitionHolder;
22import org.springframework.beans.factory.config.RuntimeBeanReference;
23import org.springframework.beans.factory.config.TypedStringValue;
24import org.springframework.beans.factory.support.AbstractBeanDefinition;
25import org.springframework.beans.factory.support.BeanDefinitionBuilder;
26import org.springframework.beans.factory.support.GenericBeanDefinition;
27import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
28import org.springframework.beans.factory.xml.ParserContext;
29import org.springframework.util.StringUtils;
30import org.springframework.util.xml.DomUtils;
31import org.w3c.dom.Element;
32import org.w3c.dom.Node;
33import org.w3c.dom.NodeList;
34 
35/**
36 * Internal parser for the &lt;step/&gt; elements inside a job. A step element
37 * references a bean definition for a
38 * {@link org.springframework.batch.core.Step} and goes on to (optionally) list
39 * a set of transitions from that step to others with &lt;next on="pattern"
40 * to="stepName"/&gt;. Used by the {@link JobParser}.
41 *
42 * @author Dave Syer
43 * @author Thomas Risberg
44 * @author Josh Long
45 * @see JobParser
46 * @since 2.0
47 */
48public abstract class AbstractStepParser {
49 
50        protected static final String ID_ATTR = "id";
51 
52        private static final String PARENT_ATTR = "parent";
53 
54        private static final String REF_ATTR = "ref";
55        
56        private static final String ALLOW_START_ATTR = "allow-start-if-complete";
57 
58        private static final String TASKLET_ELE = "tasklet";
59 
60        private static final String PARTITION_ELE = "partition";
61 
62        private static final String JOB_ELE = "job";
63 
64        private static final String JOB_PARAMS_EXTRACTOR_ATTR = "job-parameters-extractor";
65 
66        private static final String JOB_LAUNCHER_ATTR = "job-launcher";
67 
68        private static final String STEP_ATTR = "step";
69 
70        private static final String STEP_ELE = STEP_ATTR;
71 
72        private static final String PARTITIONER_ATTR = "partitioner";
73 
74        private static final String AGGREGATOR_ATTR = "aggregator";
75 
76        private static final String HANDLER_ATTR = "handler";
77 
78        private static final String HANDLER_ELE = "handler";
79 
80        private static final String TASK_EXECUTOR_ATTR = "task-executor";
81 
82        private static final String GRID_SIZE_ATTR = "grid-size";
83 
84        private static final String FLOW_ELE = "flow";
85 
86        private static final String JOB_REPO_ATTR = "job-repository";
87 
88        private static final StepListenerParser stepListenerParser = new StepListenerParser(StepListenerMetaData.stepExecutionListenerMetaData());
89 
90        /**
91         * @param stepElement   The &lt;step/&gt; element
92         * @param parserContext
93         * @param jobFactoryRef the reference to the {@link JobParserJobFactoryBean}
94         *                      from the enclosing tag. Use 'null' if unknown.
95         */
96        protected AbstractBeanDefinition parseStep(Element stepElement, ParserContext parserContext, String jobFactoryRef) {
97 
98                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
99                AbstractBeanDefinition bd = builder.getRawBeanDefinition();
100 
101                // look at all nested elements
102                NodeList children = stepElement.getChildNodes();
103                
104                for (int i = 0; i < children.getLength(); i++) {
105                        Node nd = children.item(i);
106 
107                        if (nd instanceof Element) {
108                                Element nestedElement = (Element) nd;
109                                String name = nestedElement.getLocalName();
110 
111                                if (TASKLET_ELE.equals(name)) {
112                                        boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement);
113                                        new TaskletParser().parseTasklet(stepElement, nestedElement, bd, parserContext, stepUnderspecified);
114                                }
115                                else if (FLOW_ELE.equals(name)) {
116                                        boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement);
117                                        parseFlow(stepElement, nestedElement, bd, parserContext, stepUnderspecified);
118                                }
119                                else if (PARTITION_ELE.equals(name)) {
120                                        boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement);
121                                        parsePartition(stepElement, nestedElement, bd, parserContext, stepUnderspecified, jobFactoryRef);
122                                }
123                                else if (JOB_ELE.equals(name)) {
124                                        boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement);
125                                        parseJob(stepElement, nestedElement, bd, parserContext, stepUnderspecified);
126                                }
127                                else if ("description".equals(name)) {
128                                        bd.setDescription(nestedElement.getTextContent());
129                                }
130 
131                                // nested bean reference/declaration
132                                else {
133                                        String ns = nestedElement.getNamespaceURI();
134                                        Object value = null;
135                                        boolean skip = false;
136 
137                                        // Spring NS
138                                        if ((ns == null && name.equals(BeanDefinitionParserDelegate.BEAN_ELEMENT))
139                                                        || ns.equals(BeanDefinitionParserDelegate.BEANS_NAMESPACE_URI)) {
140                                                BeanDefinitionHolder holder = parserContext.getDelegate().parseBeanDefinitionElement(nestedElement);
141                                                value = parserContext.getDelegate().decorateBeanDefinitionIfRequired(nestedElement, holder);
142                                        }
143                                        // Spring Batch transitions
144                                        else if (ns.equals("http://www.springframework.org/schema/batch")) {
145                                                // don't parse
146                                                skip = true;
147                                        }
148                                        // Custom NS
149                                        else {
150                                                value = parserContext.getDelegate().parseCustomElement(nestedElement);
151                                        }
152                                        
153                                        if (!skip) {
154                                                bd.setBeanClass(StepParserStepFactoryBean.class);
155                                                bd.setAttribute("isNamespaceStep", true);
156                                                builder.addPropertyValue("tasklet", value);
157                                        }
158                                }
159                        }
160                }
161 
162                String parentRef = stepElement.getAttribute(PARENT_ATTR);
163                if (StringUtils.hasText(parentRef)) {
164                        bd.setParentName(parentRef);
165                }
166 
167                String isAbstract = stepElement.getAttribute("abstract");
168                if (StringUtils.hasText(isAbstract)) {
169                        bd.setAbstract(Boolean.valueOf(isAbstract));
170                }
171 
172                String jobRepositoryRef = stepElement.getAttribute(JOB_REPO_ATTR);
173                if (StringUtils.hasText(jobRepositoryRef)) {
174                        builder.addPropertyReference("jobRepository", jobRepositoryRef);
175                }
176 
177                if (StringUtils.hasText(jobFactoryRef)) {
178                        bd.setAttribute("jobParserJobFactoryBeanRef", jobFactoryRef);
179                }
180 
181                //add the allow parser here
182                String isAllowStart = stepElement.getAttribute(ALLOW_START_ATTR);
183                if (StringUtils.hasText(isAllowStart)) {
184                        //check if the value is already set from an inner element
185                        if (!bd.getPropertyValues().contains("allowStartIfComplete")) {
186                                //set the value as a property
187                                bd.getPropertyValues().add("allowStartIfComplete", Boolean.valueOf(isAllowStart));
188                        }//end if
189                }
190                
191                stepListenerParser.handleListenersElement(stepElement, bd, parserContext);
192                return bd;
193        }
194 
195        private void parsePartition(Element stepElement, Element partitionElement, AbstractBeanDefinition bd, ParserContext parserContext, boolean stepUnderspecified, String jobFactoryRef ) {
196 
197                bd.setBeanClass(StepParserStepFactoryBean.class);
198                bd.setAttribute("isNamespaceStep", true);
199                String stepRef = partitionElement.getAttribute(STEP_ATTR);
200                String partitionerRef = partitionElement.getAttribute(PARTITIONER_ATTR);
201                String aggregatorRef = partitionElement.getAttribute(AGGREGATOR_ATTR);
202                String handlerRef = partitionElement.getAttribute(HANDLER_ATTR);
203 
204                if (!StringUtils.hasText(partitionerRef)) {
205                        parserContext.getReaderContext().error("You must specify a partitioner", partitionElement);
206                        return;
207                }
208 
209                MutablePropertyValues propertyValues = bd.getPropertyValues();
210 
211                propertyValues.addPropertyValue("partitioner", new RuntimeBeanReference(partitionerRef));
212                if (StringUtils.hasText(aggregatorRef)) {
213                        propertyValues.addPropertyValue("stepExecutionAggregator", new RuntimeBeanReference(aggregatorRef));                        
214                }
215 
216                boolean customHandler = false;
217                if (!StringUtils.hasText(handlerRef)) {
218                        Element handlerElement = DomUtils.getChildElementByTagName(partitionElement, HANDLER_ELE);
219                        if (handlerElement != null) {
220                                String taskExecutorRef = handlerElement.getAttribute(TASK_EXECUTOR_ATTR);
221                                if (StringUtils.hasText(taskExecutorRef)) {
222                                        propertyValues.addPropertyValue("taskExecutor", new RuntimeBeanReference(taskExecutorRef));
223                                }
224                                String gridSize = handlerElement.getAttribute(GRID_SIZE_ATTR);
225                                if (StringUtils.hasText(gridSize)) {
226                                        propertyValues.addPropertyValue("gridSize", new TypedStringValue(gridSize));
227                                }
228                        }
229                } else {
230                        customHandler = true;
231                        BeanDefinition partitionHandler = BeanDefinitionBuilder.genericBeanDefinition().getRawBeanDefinition();
232                        partitionHandler.setParentName(handlerRef);
233                        propertyValues.addPropertyValue("partitionHandler", partitionHandler);
234                }
235 
236                Element inlineStepElement = DomUtils.getChildElementByTagName(partitionElement, STEP_ELE);
237                if (inlineStepElement == null && !StringUtils.hasText(stepRef) && !customHandler) {
238                        parserContext.getReaderContext().error("You must specify a step", partitionElement);
239                        return;
240                }
241 
242                if (StringUtils.hasText(stepRef)) {
243                        propertyValues.addPropertyValue("step", new RuntimeBeanReference(stepRef));
244                } else if( inlineStepElement!=null) {
245                        AbstractBeanDefinition stepDefinition = parseStep(inlineStepElement, parserContext, jobFactoryRef);
246                        stepDefinition.getPropertyValues().addPropertyValue("name", stepElement.getAttribute(ID_ATTR));
247                        propertyValues.addPropertyValue("step", stepDefinition );
248                }
249 
250        }
251 
252        private void parseJob(Element stepElement, Element jobElement, AbstractBeanDefinition bd, ParserContext parserContext, boolean stepUnderspecified) {
253 
254                bd.setBeanClass(StepParserStepFactoryBean.class);
255                bd.setAttribute("isNamespaceStep", true);
256                String jobRef = jobElement.getAttribute(REF_ATTR);
257 
258                if (!StringUtils.hasText(jobRef)) {
259                        parserContext.getReaderContext().error("You must specify a job", jobElement);
260                        return;
261                }
262 
263                MutablePropertyValues propertyValues = bd.getPropertyValues();
264                propertyValues.addPropertyValue("job", new RuntimeBeanReference(jobRef));
265 
266                String jobParametersExtractor = jobElement.getAttribute(JOB_PARAMS_EXTRACTOR_ATTR);
267                String jobLauncher = jobElement.getAttribute(JOB_LAUNCHER_ATTR);
268 
269                if (StringUtils.hasText(jobParametersExtractor)) {
270                        propertyValues.addPropertyValue("jobParametersExtractor", new RuntimeBeanReference(jobParametersExtractor));
271                }
272                if (StringUtils.hasText(jobLauncher)) {
273                        propertyValues.addPropertyValue("jobLauncher", new RuntimeBeanReference(jobLauncher));
274                }
275 
276        }
277 
278 
279        private void parseFlow(Element stepElement, Element flowElement, AbstractBeanDefinition bd,
280                               ParserContext parserContext, boolean stepUnderspecified) {
281 
282                bd.setBeanClass(StepParserStepFactoryBean.class);
283                bd.setAttribute("isNamespaceStep", true);
284                String flowRef = flowElement.getAttribute(PARENT_ATTR);
285                String idAttribute = stepElement.getAttribute(ID_ATTR);
286 
287                BeanDefinition flowDefinition = new GenericBeanDefinition();
288                flowDefinition.setParentName(flowRef);
289                MutablePropertyValues propertyValues = flowDefinition.getPropertyValues();
290                if (StringUtils.hasText(idAttribute)) {
291                        propertyValues.addPropertyValue("name", idAttribute);
292                }
293 
294                bd.getPropertyValues().addPropertyValue("flow", flowDefinition);
295 
296        }
297 
298}

[all classes][org.springframework.batch.core.configuration.xml]
EMMA 2.0.5312 (C) Vladimir Roubtsov