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}