001/*
002 * Copyright 2013-2018 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.jsr.configuration.xml;
017
018import org.springframework.batch.core.jsr.configuration.support.BatchArtifactType;
019import org.springframework.batch.core.jsr.job.flow.support.state.JsrStepState;
020import org.springframework.beans.factory.config.BeanDefinition;
021import org.springframework.beans.factory.config.RuntimeBeanReference;
022import org.springframework.beans.factory.parsing.BeanComponentDefinition;
023import org.springframework.beans.factory.support.AbstractBeanDefinition;
024import org.springframework.beans.factory.support.BeanDefinitionBuilder;
025import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
026import org.springframework.beans.factory.xml.ParserContext;
027import org.springframework.util.StringUtils;
028import org.w3c.dom.Element;
029import org.w3c.dom.Node;
030import org.w3c.dom.NodeList;
031
032import java.util.Collection;
033
034/**
035 * Parser for the <step /> element defined by JSR-352.
036 *
037 * @author Michael Minella
038 * @author Glenn Renfro
039 * @author Chris Schaefer
040 * @author Mahmoud Ben Hassine
041 * @since 3.0
042 */
043public class StepParser extends AbstractSingleBeanDefinitionParser {
044        private static final String CHUNK_ELEMENT = "chunk";
045        private static final String BATCHLET_ELEMENT = "batchlet";
046        private static final String ALLOW_START_IF_COMPLETE_ATTRIBUTE = "allow-start-if-complete";
047        private static final String START_LIMIT_ATTRIBUTE = "start-limit";
048        private static final String SPLIT_ID_ATTRIBUTE = "id";
049        private static final String PARTITION_ELEMENT = "partition";
050
051        protected Collection<BeanDefinition> parse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
052                BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition();
053                AbstractBeanDefinition bd = defBuilder.getRawBeanDefinition();
054                bd.setBeanClass(StepFactoryBean.class);
055                bd.getPropertyValues().addPropertyValue("batchPropertyContext", new RuntimeBeanReference("batchPropertyContext"));
056
057                BeanDefinitionBuilder stateBuilder = BeanDefinitionBuilder.genericBeanDefinition(JsrStepState.class);
058
059                String stepName = element.getAttribute(SPLIT_ID_ATTRIBUTE);
060                builder.addPropertyValue("name", stepName);
061
062                parserContext.registerBeanComponent(new BeanComponentDefinition(bd, stepName));
063                stateBuilder.addConstructorArgReference(stepName);
064
065                String startLimit = element.getAttribute(START_LIMIT_ATTRIBUTE);
066                if(StringUtils.hasText(startLimit)) {
067                        bd.getPropertyValues().addPropertyValue("startLimit", startLimit);
068                }
069
070                String allowStartIfComplete = element.getAttribute(ALLOW_START_IF_COMPLETE_ATTRIBUTE);
071                boolean allowStartIfCompleteValue = false;
072                if(StringUtils.hasText(allowStartIfComplete)) {
073                        bd.getPropertyValues().addPropertyValue("allowStartIfComplete",
074                                        allowStartIfComplete);
075                        allowStartIfCompleteValue = Boolean.valueOf(allowStartIfComplete);
076                }
077
078                new ListenerParser(JsrStepListenerFactoryBean.class, "listeners").parseListeners(element, parserContext, bd, stepName);
079                new PropertyParser(stepName, parserContext, BatchArtifactType.STEP, stepName).parseProperties(element);
080
081                // look at all nested elements
082                NodeList children = element.getChildNodes();
083
084                for (int i = 0; i < children.getLength(); i++) {
085                        Node nd = children.item(i);
086
087                        if (nd instanceof Element) {
088                                Element nestedElement = (Element) nd;
089                                String name = nestedElement.getLocalName();
090
091                                if(name.equalsIgnoreCase(BATCHLET_ELEMENT)) {
092                                        new BatchletParser().parseBatchlet(nestedElement, bd, parserContext, stepName);
093                                } else if(name.equals(CHUNK_ELEMENT)) {
094                                        new ChunkParser().parse(nestedElement, bd, parserContext, stepName);
095                                } else if(name.equals(PARTITION_ELEMENT)) {
096                                        new PartitionParser(stepName, allowStartIfCompleteValue).parse(nestedElement, bd, parserContext, stepName);
097                                }
098                        }
099                }
100
101                return FlowParser.getNextElements(parserContext, stepName, stateBuilder.getBeanDefinition(), element);
102        }
103}