001/* 002 * Copyright 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.jsr.configuration.xml; 017 018import java.util.Collection; 019import java.util.List; 020 021import org.springframework.beans.PropertyValue; 022import org.springframework.beans.factory.config.BeanDefinition; 023import org.springframework.beans.factory.config.RuntimeBeanReference; 024import org.springframework.beans.factory.support.BeanDefinitionBuilder; 025import org.springframework.beans.factory.support.BeanDefinitionRegistry; 026import org.springframework.beans.factory.support.ManagedList; 027import org.springframework.beans.factory.xml.ParserContext; 028import org.springframework.core.task.SimpleAsyncTaskExecutor; 029import org.springframework.util.xml.DomUtils; 030import org.w3c.dom.Element; 031 032/** 033 * Parses a <split /> element as defined in JSR-352. 034 * 035 * @author Michael Minella 036 * @author Chris Schaefer 037 * @since 3.0 038 */ 039public class JsrSplitParser { 040 private static final String TASK_EXECUTOR_PROPERTY_NAME = "taskExecutor"; 041 private static final String JSR_352_SPLIT_TASK_EXECUTOR_BEAN_NAME = "jsr352splitTaskExecutor"; 042 043 private String jobFactoryRef; 044 045 public JsrSplitParser(String jobFactoryRef) { 046 this.jobFactoryRef = jobFactoryRef; 047 } 048 049 public Collection<BeanDefinition> parse(Element element, ParserContext parserContext) { 050 051 String idAttribute = element.getAttribute("id"); 052 053 BeanDefinitionBuilder stateBuilder = BeanDefinitionBuilder 054 .genericBeanDefinition("org.springframework.batch.core.jsr.job.flow.support.state.JsrSplitState"); 055 056 List<Element> flowElements = DomUtils.getChildElementsByTagName(element, "flow"); 057 058 if (flowElements.size() < 2) { 059 parserContext.getReaderContext().error("A <split/> must contain at least two 'flow' elements.", element); 060 } 061 062 Collection<Object> flows = new ManagedList<Object>(); 063 int i = 0; 064 for (Element nextElement : flowElements) { 065 FlowParser flowParser = new FlowParser(idAttribute + "." + i, jobFactoryRef); 066 flows.add(flowParser.parse(nextElement, parserContext)); 067 i++; 068 } 069 070 stateBuilder.addConstructorArgValue(flows); 071 stateBuilder.addConstructorArgValue(idAttribute); 072 073 PropertyValue propertyValue = getSplitTaskExecutorPropertyValue(parserContext.getRegistry()); 074 stateBuilder.addPropertyValue(propertyValue.getName(), propertyValue.getValue()); 075 076 return FlowParser.getNextElements(parserContext, null, stateBuilder.getBeanDefinition(), element); 077 } 078 079 protected PropertyValue getSplitTaskExecutorPropertyValue(BeanDefinitionRegistry beanDefinitionRegistry) { 080 PropertyValue propertyValue; 081 082 if (hasBeanDefinition(beanDefinitionRegistry, JSR_352_SPLIT_TASK_EXECUTOR_BEAN_NAME)) { 083 propertyValue = new PropertyValue(TASK_EXECUTOR_PROPERTY_NAME, new RuntimeBeanReference(JSR_352_SPLIT_TASK_EXECUTOR_BEAN_NAME)); 084 } else { 085 propertyValue = new PropertyValue(TASK_EXECUTOR_PROPERTY_NAME, new SimpleAsyncTaskExecutor()); 086 } 087 088 return propertyValue; 089 } 090 091 private boolean hasBeanDefinition(BeanDefinitionRegistry beanDefinitionRegistry, String beanName) { 092 return beanDefinitionRegistry.containsBeanDefinition(beanName); 093 } 094}