BATCH-1167: Create constants for element and attribute names in the namespace

This commit is contained in:
dhgarrette
2009-03-20 18:02:05 +00:00
parent 5d1d503a0d
commit 6efcda99d6
6 changed files with 164 additions and 111 deletions

View File

@@ -22,6 +22,12 @@ import org.w3c.dom.NamedNodeMap;
*/
public abstract class AbstractListenerParser {
private static final String ID_ATTR = "id";
private static final String REF_ATTR = "ref";
private static final String CLASS_ATTR = "class";
public AbstractBeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(getBeanClass());
doParse(element, parserContext, builder);
@@ -30,9 +36,9 @@ public abstract class AbstractListenerParser {
@SuppressWarnings("unchecked")
public void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
String id = element.getAttribute("id");
String listenerRef = element.getAttribute("ref");
String className = element.getAttribute("class");
String id = element.getAttribute(ID_ATTR);
String listenerRef = element.getAttribute(REF_ATTR);
String className = element.getAttribute(CLASS_ATTR);
checkListenerElementAttributes(parserContext, element, id, listenerRef, className);
if (StringUtils.hasText(listenerRef)) {
@@ -44,7 +50,8 @@ public abstract class AbstractListenerParser {
}
else {
parserContext.getReaderContext().error(
"Neither 'ref' or 'class' specified for <" + element.getTagName() + "> element", element);
"Neither '" + REF_ATTR + "' or '" + CLASS_ATTR + "' specified for <" + element.getTagName()
+ "> element", element);
}
ManagedMap metaDataMap = new ManagedMap();
@@ -69,8 +76,8 @@ public abstract class AbstractListenerParser {
attributes.append(attributeNodes.item(i));
}
parserContext.getReaderContext().error(
"Either 'ref' or 'class' may be specified, but not both; <" + element.getTagName()
+ "> element specified with attributes: " + attributes, element);
"Either '" + REF_ATTR + "' or '" + CLASS_ATTR + "' may be specified, but not both; <"
+ element.getTagName() + "> element specified with attributes: " + attributes, element);
}
}

View File

@@ -44,6 +44,20 @@ import org.w3c.dom.Element;
*/
public abstract class AbstractStepParser {
protected static final String ID_ATTR = "id";
protected static final String PARENT_ATTR = "parent";
protected static final String TASKLET_ATTR = "tasklet";
protected static final String TASKLET_ELE = "tasklet";
protected static final String LISTENERS_ELE = "listeners";
protected static final String MERGE_ATTR = "merge";
private static final String TX_ATTRIBUTES_ELE = "transaction-attributes";
private TaskletElementParser taskletElementParser = new TaskletElementParser();
private StepListenerParser stepListenerParser = new StepListenerParser();
@@ -56,17 +70,17 @@ public abstract class AbstractStepParser {
protected AbstractBeanDefinition parseTasklet(Element stepElement, ParserContext parserContext,
String jobRepositoryRef) {
String taskletRef = stepElement.getAttribute("tasklet");
String taskletRef = stepElement.getAttribute(TASKLET_ATTR);
@SuppressWarnings("unchecked")
List<Element> taskletElements = (List<Element>) DomUtils.getChildElementsByTagName(stepElement, "tasklet");
List<Element> taskletElements = (List<Element>) DomUtils.getChildElementsByTagName(stepElement, TASKLET_ELE);
boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement);
AbstractBeanDefinition bd = null;
if (StringUtils.hasText(taskletRef)) {
if (taskletElements.size() > 0) {
parserContext.getReaderContext().error(
"The <" + taskletElements.get(0).getNodeName()
+ "> element can't be combined with the 'tasklet=\"" + taskletRef
+ "\"' attribute specification for <" + stepElement.getNodeName() + ">", stepElement);
"The <" + TASKLET_ELE + "/> element can't be combined with the '" + TASKLET_ATTR + "=\""
+ taskletRef + "\"' attribute specification for <" + stepElement.getNodeName() + "/>",
stepElement);
}
bd = parseTaskletRef(stepElement, taskletRef, parserContext, jobRepositoryRef);
}
@@ -76,7 +90,8 @@ public abstract class AbstractStepParser {
}
else if (taskletElements.size() > 1) {
parserContext.getReaderContext().error(
"The 'tasklet' element may not appear more than once in a single <step/>.", stepElement);
"The '<" + TASKLET_ELE + "/>' element may not appear more than once in a single <"
+ stepElement.getNodeName() + "/>.", stepElement);
}
if (bd != null) {
@@ -84,8 +99,8 @@ public abstract class AbstractStepParser {
}
else if (!stepUnderspecified) {
parserContext.getReaderContext().error(
"Step [" + stepElement.getAttribute("id")
+ "] has neither a <tasklet/> element nor a 'tasklet' attribute.", stepElement);
"Step [" + stepElement.getAttribute(ID_ATTR) + "] has neither a <" + TASKLET_ELE
+ "/> element nor a '" + TASKLET_ATTR + "' attribute.", stepElement);
}
return bd;
@@ -126,7 +141,7 @@ public abstract class AbstractStepParser {
RuntimeBeanReference transactionManagerBeanRef = new RuntimeBeanReference(transactionManagerRef);
bd.getPropertyValues().addPropertyValue("transactionManager", transactionManagerBeanRef);
List<Element> txAttrElements = DomUtils.getChildElementsByTagName(stepElement, "transaction-attributes");
List<Element> txAttrElements = DomUtils.getChildElementsByTagName(stepElement, TX_ATTRIBUTES_ELE);
if (txAttrElements.size() == 1) {
Element txAttrElement = txAttrElements.get(0);
String propagation = txAttrElement.getAttribute("propagation");
@@ -144,13 +159,14 @@ public abstract class AbstractStepParser {
}
else if (txAttrElements.size() > 1) {
parserContext.getReaderContext().error(
"The 'transaction-attributes' element may not appear more than once in a single <step/>.",
stepElement);
"The '" + TX_ATTRIBUTES_ELE + "' element may not appear more than once in a single <"
+ stepElement.getNodeName() + "/>.", stepElement);
}
handleListenersElement(stepElement, bd, parserContext);
handleExceptionElement(stepElement, parserContext, bd, "no-rollback-exception-classes", "noRollbackExceptionClasses");
handleExceptionElement(stepElement, parserContext, bd, "no-rollback-exception-classes",
"noRollbackExceptionClasses");
bd.setRole(BeanDefinition.ROLE_SUPPORT);
@@ -168,7 +184,7 @@ public abstract class AbstractStepParser {
String[] exceptionArray = StringUtils.tokenizeToStringArray(exceptions, ",\n");
if (exceptionArray.length > 0) {
ManagedList managedList = new ManagedList();
managedList.setMergeEnabled(Boolean.valueOf(child.getAttribute("merge")));
managedList.setMergeEnabled(Boolean.valueOf(child.getAttribute(MERGE_ATTR)));
managedList.addAll(Arrays.asList(exceptionArray));
bd.getPropertyValues().addPropertyValue(propertyName, managedList);
}
@@ -185,7 +201,7 @@ public abstract class AbstractStepParser {
if (StringUtils.hasText(allowStartIfComplete)) {
bd.getPropertyValues().addPropertyValue("allowStartIfComplete", allowStartIfComplete);
}
String parentRef = stepElement.getAttribute("parent");
String parentRef = stepElement.getAttribute(PARENT_ATTR);
if (StringUtils.hasText(parentRef)) {
bd.setParentName(parentRef);
}
@@ -193,14 +209,14 @@ public abstract class AbstractStepParser {
@SuppressWarnings("unchecked")
private void handleListenersElement(Element stepElement, BeanDefinition bd, ParserContext parserContext) {
List<Element> listenersElements = DomUtils.getChildElementsByTagName(stepElement, "listeners");
List<Element> listenersElements = DomUtils.getChildElementsByTagName(stepElement, LISTENERS_ELE);
if (listenersElements.size() == 1) {
Element listenersElement = listenersElements.get(0);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(listenersElement.getTagName(),
parserContext.extractSource(stepElement));
parserContext.pushContainingComponent(compositeDef);
ManagedList listenerBeans = new ManagedList();
listenerBeans.setMergeEnabled(Boolean.valueOf(listenersElement.getAttribute("merge")));
listenerBeans.setMergeEnabled(Boolean.valueOf(listenersElement.getAttribute(MERGE_ATTR)));
List<Element> listenerElements = DomUtils.getChildElementsByTagName(listenersElement, "listener");
if (listenerElements != null) {
for (Element listenerElement : listenerElements) {
@@ -211,8 +227,9 @@ public abstract class AbstractStepParser {
parserContext.popAndRegisterContainingComponent();
}
else if (listenersElements.size() > 1) {
parserContext.getReaderContext().error("The 'listeners' element may not appear more than once in a single <step/>.",
stepElement);
parserContext.getReaderContext().error(
"The '" + LISTENERS_ELE + "' element may not appear more than once in a single <"
+ stepElement.getNodeName() + "/>.", stepElement);
}
}

View File

@@ -39,13 +39,29 @@ import org.w3c.dom.NodeList;
*/
public class FlowParser extends AbstractSingleBeanDefinitionParser {
private static final String NEXT = "next";
private static final String STEP_ELE = "step";
private static final String END = "end";
private static final String DECISION_ELE = "decision";
private static final String FAIL = "fail";
private static final String SPLIT_ELE = "split";
private static final String STOP = "stop";
private static final String NEXT_ATTR = "next";
private static final String NEXT_ELE = "next";
private static final String END_ELE = "end";
private static final String FAIL_ELE = "fail";
private static final String STOP_ELE = "stop";
private static final String ON_ATTR = "on";
private static final String TO_ATTR = "to";
private static final String RESTART_ATTR = "restart";
private static final String EXIT_CODE_ATTR = "exit-code";
// For generating unique state names for end transitions
private static int endCounter = 0;
@@ -60,7 +76,7 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
*
* @param flowName the name of the flow
* @param jobRepositoryRef the reference to the jobRepository from the
* enclosing tag
* enclosing tag
*/
public FlowParser(String flowName, String jobRepositoryRef) {
this.flowName = flowName;
@@ -99,14 +115,14 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
Node node = children.item(i);
if (node instanceof Element) {
String nodeName = node.getLocalName();
if (nodeName.equals("step")) {
if (nodeName.equals(STEP_ELE)) {
stateTransitions.addAll(stepParser.parse((Element) node, parserContext, jobRepositoryRef));
stepExists = true;
}
else if (nodeName.equals("decision")) {
else if (nodeName.equals(DECISION_ELE)) {
stateTransitions.addAll(decisionParser.parse((Element) node, parserContext));
}
else if (nodeName.equals("split")) {
else if (nodeName.equals(SPLIT_ELE)) {
stateTransitions.addAll(splitParser.parse((Element) node, new ParserContext(parserContext
.getReaderContext(), parserContext.getDelegate(), builder.getBeanDefinition())));
stepExists = true;
@@ -117,7 +133,7 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
if (!stepExists && !CoreNamespaceUtils.isUnderspecified(element)) {
parserContext.getReaderContext().error("A flow must contain at least one step", element);
}
builder.addConstructorArgValue(flowName);
ManagedList managedList = new ManagedList();
@SuppressWarnings( { "unchecked", "unused" })
@@ -135,8 +151,8 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
* @param stateDef The bean definition for the current state
* @param element the &lt;step/gt; element to parse
* @return a collection of
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
* references
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
* references
*/
protected static Collection<BeanDefinition> getNextElements(ParserContext parserContext, BeanDefinition stateDef,
Element element) {
@@ -146,19 +162,19 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
/**
* @param parserContext the parser context for the bean factory
* @param stepId the id of the current state if it is a step state, null
* otherwise
* otherwise
* @param stateDef The bean definition for the current state
* @param element the &lt;step/gt; element to parse
* @return a collection of
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
* references
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
* references
*/
protected static Collection<BeanDefinition> getNextElements(ParserContext parserContext, String stepId,
BeanDefinition stateDef, Element element) {
Collection<BeanDefinition> list = new ArrayList<BeanDefinition>();
String shortNextAttribute = element.getAttribute(NEXT);
String shortNextAttribute = element.getAttribute(NEXT_ATTR);
boolean hasNextAttribute = StringUtils.hasText(shortNextAttribute);
if (hasNextAttribute) {
list.add(getStateTransitionReference(parserContext, stateDef, null, shortNextAttribute));
@@ -166,7 +182,7 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
boolean transitionElementExists = false;
List<String> patterns = new ArrayList<String>();
for (String transitionName : new String[] { NEXT, STOP, END, FAIL }) {
for (String transitionName : new String[] { NEXT_ELE, STOP_ELE, END_ELE, FAIL_ELE }) {
@SuppressWarnings("unchecked")
List<Element> transitionElements = (List<Element>) DomUtils.getChildElementsByTagName(element,
transitionName);
@@ -178,15 +194,17 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
}
if (!transitionElementExists) {
list.addAll(createTransition(FlowExecutionStatus.FAILED, FlowExecutionStatus.FAILED.getName(), null, null, stateDef, parserContext, false));
list.addAll(createTransition(FlowExecutionStatus.FAILED, FlowExecutionStatus.FAILED.getName(), null, null,
stateDef, parserContext, false));
if (!hasNextAttribute) {
list.addAll(createTransition(FlowExecutionStatus.COMPLETED, null, null, null, stateDef, parserContext,
false));
}
}
else if (hasNextAttribute) {
parserContext.getReaderContext().error("Step may not contain a 'next' attribute and a transition element",
element);
parserContext.getReaderContext().error(
"The <" + element.getNodeName() + "/> may not contain a '" + NEXT_ATTR
+ "' attribute and a transition element", element);
}
return list;
@@ -200,7 +218,7 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
*/
private static void verifyUniquePattern(Element transitionElement, List<String> patterns, Element element,
ParserContext parserContext) {
String onAttribute = transitionElement.getAttribute("on");
String onAttribute = transitionElement.getAttribute(ON_ATTR);
if (patterns.contains(onAttribute)) {
parserContext.getReaderContext().error("Duplicate transition pattern found for '" + onAttribute + "'",
element);
@@ -213,41 +231,39 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
* @param stateDef The bean definition for the current state
* @param parserContext the parser context for the bean factory
* @param a collection of
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
* references
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
* references
*/
private static Collection<BeanDefinition> parseTransitionElement(Element transitionElement, String stateId,
BeanDefinition stateDef, ParserContext parserContext) {
FlowExecutionStatus status = getBatchStatusFromEndTransitionName(transitionElement.getNodeName());
String onAttribute = transitionElement.getAttribute("on");
String nextAttribute = transitionElement.getAttribute("to");
String restartAttribute = transitionElement.getAttribute("restart");
nextAttribute = StringUtils.hasText(nextAttribute) ? nextAttribute : restartAttribute;
boolean abandon = false;
if (stateId != null && StringUtils.hasText(restartAttribute) && !restartAttribute.equals(stateId)) {
abandon = true;
String onAttribute = transitionElement.getAttribute(ON_ATTR);
String restartAttribute = transitionElement.getAttribute(RESTART_ATTR);
String nextAttribute = transitionElement.getAttribute(TO_ATTR);
if (!StringUtils.hasText(nextAttribute)) {
nextAttribute = restartAttribute;
}
String exitCodeAttribute = transitionElement.getAttribute("exit-code");
boolean abandon = stateId != null && StringUtils.hasText(restartAttribute) && !restartAttribute.equals(stateId);
String exitCodeAttribute = transitionElement.getAttribute(EXIT_CODE_ATTR);
return createTransition(status, onAttribute, nextAttribute, exitCodeAttribute, stateDef, parserContext,
abandon);
return createTransition(status, onAttribute, nextAttribute, exitCodeAttribute, stateDef, parserContext, abandon);
}
/**
* @param status The batch status that this transition will set. Use
* BatchStatus.UNKNOWN if not applicable.
* BatchStatus.UNKNOWN if not applicable.
* @param on The pattern that this transition should match. Use null for
* "no restriction" (same as "*").
* "no restriction" (same as "*").
* @param next The state to which this transition should go. Use null if not
* applicable.
* applicable.
* @param exitCode The exit code that this transition will set. Use null to
* default to batchStatus.
* default to batchStatus.
* @param stateDef The bean definition for the current state
* @param parserContext the parser context for the bean factory
* @param a collection of
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
* references
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
* references
*/
private static Collection<BeanDefinition> createTransition(FlowExecutionStatus status, String on, String next,
String exitCode, BeanDefinition stateDef, ParserContext parserContext, boolean abandon) {
@@ -266,9 +282,9 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
endBuilder.addConstructorArgValue(status);
endBuilder.addConstructorArgValue(exitCodeExists ? exitCode : status.getName());
String endName = (status == FlowExecutionStatus.STOPPED ? STOP
: status == FlowExecutionStatus.FAILED ? FAIL : END)
String endName = (status == FlowExecutionStatus.STOPPED ? STOP_ELE
: status == FlowExecutionStatus.FAILED ? FAIL_ELE : END_ELE)
+ (endCounter++);
endBuilder.addConstructorArgValue(endName);
@@ -297,13 +313,13 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
* @return the BatchStatus corresponding to the transition name
*/
private static FlowExecutionStatus getBatchStatusFromEndTransitionName(String elementName) {
if (STOP.equals(elementName)) {
if (STOP_ELE.equals(elementName)) {
return FlowExecutionStatus.STOPPED;
}
else if (END.equals(elementName)) {
else if (END_ELE.equals(elementName)) {
return FlowExecutionStatus.COMPLETED;
}
else if (FAIL.equals(elementName)) {
else if (FAIL_ELE.equals(elementName)) {
return FlowExecutionStatus.FAILED;
}
else {
@@ -317,7 +333,7 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser {
* @param on the pattern value
* @param next the next step id
* @return a bean definition for a
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
*/
public static BeanDefinition getStateTransitionReference(ParserContext parserContext,
BeanDefinition stateDefinition, String on, String next) {

View File

@@ -42,6 +42,8 @@ import org.w3c.dom.Element;
*/
public class InlineStepParser extends AbstractStepParser {
private static final String REF_ATTR = "ref";
/**
* Parse the step and turn it into a list of transitions.
*
@@ -57,37 +59,28 @@ public class InlineStepParser extends AbstractStepParser {
BeanDefinitionBuilder stateBuilder = BeanDefinitionBuilder
.genericBeanDefinition("org.springframework.batch.core.job.flow.support.state.StepState");
String stepId = element.getAttribute("id");
String stepRef = element.getAttribute("ref");
String taskletRef = element.getAttribute("tasklet");
String stepId = element.getAttribute(ID_ATTR);
String stepRef = element.getAttribute(REF_ATTR);
String taskletRef = element.getAttribute(TASKLET_ATTR);
@SuppressWarnings("unchecked")
List<Element> listOfTaskElements = (List<Element>) DomUtils.getChildElementsByTagName(element, "tasklet");
List<Element> listOfTaskElements = (List<Element>) DomUtils.getChildElementsByTagName(element, TASKLET_ELE);
@SuppressWarnings("unchecked")
List<Element> listOfListenersElements = (List<Element>) DomUtils
.getChildElementsByTagName(element, "listeners");
List<Element> listOfListenersElements = (List<Element>) DomUtils.getChildElementsByTagName(element,
LISTENERS_ELE);
if (StringUtils.hasText(stepRef)) {
if (StringUtils.hasText(taskletRef)) {
parserContext.getReaderContext().error(
"The 'tasklet' attribute can't be combined with the 'ref=\"" + stepRef
+ "\"' attribute specification for <" + element.getNodeName() + ">", element);
cantBeCombinedWithRef(TASKLET_ATTR, "attribute", element, parserContext);
}
if (listOfTaskElements.size() > 0) {
parserContext.getReaderContext().error(
"The <" + listOfTaskElements.get(0).getNodeName()
+ "> element can't be combined with the 'ref=\"" + stepRef
+ "\"' attribute specification for <" + element.getNodeName() + ">", element);
cantBeCombinedWithRef(TASKLET_ELE, "element", element, parserContext);
}
if (listOfListenersElements.size() > 0) {
parserContext.getReaderContext().error(
"The 'listeners' element can't be combined with the 'ref=\"" + stepRef
+ "\"' attribute specification for <" + element.getNodeName() + ">", element);
cantBeCombinedWithRef(LISTENERS_ELE, "element", element, parserContext);
}
if (StringUtils.hasText(element.getAttribute("parent"))) {
parserContext.getReaderContext().error(
"The 'parent' element can't be combined with the 'ref=\"" + stepRef
+ "\"' attribute specification for <" + element.getNodeName() + ">", element);
if (StringUtils.hasText(element.getAttribute(PARENT_ATTR))) {
cantBeCombinedWithRef(PARENT_ATTR, "attribute", element, parserContext);
}
BeanDefinitionBuilder stepBuilder = BeanDefinitionBuilder
.genericBeanDefinition("org.springframework.batch.core.configuration.xml.DelegatingStep");
@@ -109,4 +102,11 @@ public class InlineStepParser extends AbstractStepParser {
}
private void cantBeCombinedWithRef(String itemName, String itemType, Element element, ParserContext parserContext) {
parserContext.getReaderContext().error(
"The '" + itemName + "' " + itemType + " can't be combined with the '" + REF_ATTR + "=\""
+ element.getAttribute(REF_ATTR) + "\"' attribute specification for <" + element.getNodeName()
+ ">", element);
}
}

View File

@@ -37,6 +37,8 @@ import org.w3c.dom.Element;
*/
public class JobParser extends AbstractSingleBeanDefinitionParser {
private JobExecutionListenerParser jobListenerParser = new JobExecutionListenerParser();
@Override
protected Class<FlowJob> getBeanClass(Element element) {
return FlowJob.class;
@@ -89,7 +91,6 @@ public class JobParser extends AbstractSingleBeanDefinitionParser {
BeanDefinition flowDef = flowParser.parse(element, parserContext);
builder.addPropertyValue("flow", flowDef);
JobExecutionListenerParser listenerParser = new JobExecutionListenerParser();
List<Element> listenersElements = DomUtils.getChildElementsByTagName(element, "listeners");
if (listenersElements.size() == 1) {
Element listenersElement = listenersElements.get(0);
@@ -101,7 +102,7 @@ public class JobParser extends AbstractSingleBeanDefinitionParser {
List<Element> listenerElements = (List<Element>) DomUtils.getChildElementsByTagName(listenersElement,
"listener");
for (Element listenerElement : listenerElements) {
listeners.add(listenerParser.parse(listenerElement, parserContext));
listeners.add(jobListenerParser.parse(listenerElement, parserContext));
}
builder.addPropertyValue("jobExecutionListeners", listeners);
parserContext.popAndRegisterContainingComponent();
@@ -110,7 +111,7 @@ public class JobParser extends AbstractSingleBeanDefinitionParser {
parserContext.getReaderContext().error(
"The 'listeners' element may not appear more than once in a single <job/>.", element);
}
}
}

View File

@@ -42,6 +42,18 @@ import org.w3c.dom.NamedNodeMap;
*/
public class TaskletElementParser {
private static final String ID_ATTR = "id";
private static final String REF_ATTR = "ref";
private static final String CLASS_ATTR = "class";
private static final String MERGE_ATTR = "merge";
private static final String COMMIT_INTERVAL_ATTR = "commit-interval";
private static final String CHUNK_COMPLETION_POLICY_ATTR = "chunk-completion-policy";
/**
* @param element
* @param parserContext
@@ -54,7 +66,7 @@ public class TaskletElementParser {
MutablePropertyValues propertyValues = bd.getPropertyValues();
propertyValues.addPropertyValue("hasTaskletElement", Boolean.TRUE);
String readerBeanId = element.getAttribute("reader");
if (StringUtils.hasText(readerBeanId)) {
RuntimeBeanReference readerRef = new RuntimeBeanReference(readerBeanId);
@@ -79,12 +91,12 @@ public class TaskletElementParser {
propertyValues.addPropertyValue("taskExecutor", taskExecutorRef);
}
String commitInterval = element.getAttribute("commit-interval");
String commitInterval = element.getAttribute(COMMIT_INTERVAL_ATTR);
if (StringUtils.hasText(commitInterval)) {
propertyValues.addPropertyValue("commitInterval", commitInterval);
}
String completionPolicyRef = element.getAttribute("chunk-completion-policy");
String completionPolicyRef = element.getAttribute(CHUNK_COMPLETION_POLICY_ATTR);
if (StringUtils.hasText(completionPolicyRef)) {
RuntimeBeanReference completionPolicy = new RuntimeBeanReference(completionPolicyRef);
propertyValues.addPropertyValue("chunkCompletionPolicy", completionPolicy);
@@ -93,8 +105,8 @@ public class TaskletElementParser {
if (!underspecified
&& propertyValues.contains("commitInterval") == propertyValues.contains("chunkCompletionPolicy")) {
parserContext.getReaderContext().error(
"The 'tasklet' element must contain either 'commit-interval' "
+ "or 'chunk-completion-policy', but not both.", element);
"The '" + element.getNodeName() + "' element must contain either '" + COMMIT_INTERVAL_ATTR + "' "
+ "or '" + CHUNK_COMPLETION_POLICY_ATTR + "', but not both.", element);
}
String skipLimit = element.getAttribute("skip-limit");
@@ -141,7 +153,7 @@ public class TaskletElementParser {
String[] exceptionArray = StringUtils.tokenizeToStringArray(exceptions, ",\n");
if (exceptionArray.length > 0) {
ManagedList managedList = new ManagedList();
managedList.setMergeEnabled(Boolean.valueOf(child.getAttribute("merge")));
managedList.setMergeEnabled(Boolean.valueOf(child.getAttribute(MERGE_ATTR)));
managedList.addAll(Arrays.asList(exceptionArray));
bd.getPropertyValues().addPropertyValue(propertyName, managedList);
}
@@ -156,7 +168,7 @@ public class TaskletElementParser {
parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
ManagedList retryListenerBeans = new ManagedList();
retryListenerBeans.setMergeEnabled(Boolean.valueOf(listenersElement.getAttribute("merge")));
retryListenerBeans.setMergeEnabled(Boolean.valueOf(listenersElement.getAttribute(MERGE_ATTR)));
handleRetryListenerElements(parserContext, listenersElement, retryListenerBeans);
bd.getPropertyValues().addPropertyValue("retryListeners", retryListenerBeans);
parserContext.popAndRegisterContainingComponent();
@@ -168,9 +180,9 @@ public class TaskletElementParser {
List<Element> listenerElements = DomUtils.getChildElementsByTagName(element, "listener");
if (listenerElements != null) {
for (Element listenerElement : listenerElements) {
String id = listenerElement.getAttribute("id");
String listenerRef = listenerElement.getAttribute("ref");
String className = listenerElement.getAttribute("class");
String id = listenerElement.getAttribute(ID_ATTR);
String listenerRef = listenerElement.getAttribute(REF_ATTR);
String className = listenerElement.getAttribute(CLASS_ATTR);
checkListenerElementAttributes(parserContext, element, listenerElement, id, listenerRef, className);
if (StringUtils.hasText(listenerRef)) {
BeanReference bean = new RuntimeBeanReference(listenerRef);
@@ -185,8 +197,8 @@ public class TaskletElementParser {
}
else {
parserContext.getReaderContext().error(
"Neither 'ref' or 'class' specified for <" + listenerElement.getTagName() + "> element",
element);
"Neither '" + REF_ATTR + "' or '" + CLASS_ATTR + "' specified for <"
+ listenerElement.getTagName() + "> element", element);
}
}
}
@@ -194,7 +206,7 @@ public class TaskletElementParser {
private void checkListenerElementAttributes(ParserContext parserContext, Element element, Element listenerElement,
String id, String listenerRef, String className) {
if ((StringUtils.hasText(id) || StringUtils.hasText(className)) && StringUtils.hasText(listenerRef)) {
if (StringUtils.hasText(className) && StringUtils.hasText(listenerRef)) {
NamedNodeMap attributeNodes = listenerElement.getAttributes();
StringBuilder attributes = new StringBuilder();
for (int i = 0; i < attributeNodes.getLength(); i++) {
@@ -204,8 +216,8 @@ public class TaskletElementParser {
attributes.append(attributeNodes.item(i));
}
parserContext.getReaderContext().error(
"Both 'ref' and " + (StringUtils.hasText(id) ? "'id'" : "'class'")
+ " specified; use 'class' with an optional 'id' or just 'ref' for <"
"Both '" + REF_ATTR + "' and '" + CLASS_ATTR + "' specified; use '" + CLASS_ATTR
+ "' with an optional '" + ID_ATTR + "' or just '" + REF_ATTR + "' for <"
+ listenerElement.getTagName() + "> element specified with attributes: " + attributes,
element);
}
@@ -216,18 +228,18 @@ public class TaskletElementParser {
Element streamsElement = DomUtils.getChildElementByTagName(element, "streams");
if (streamsElement != null) {
ManagedList streamBeans = new ManagedList();
streamBeans.setMergeEnabled(Boolean.valueOf(streamsElement.getAttribute("merge")));
streamBeans.setMergeEnabled(Boolean.valueOf(streamsElement.getAttribute(MERGE_ATTR)));
List<Element> streamElements = DomUtils.getChildElementsByTagName(streamsElement, "stream");
if (streamElements != null) {
for (Element streamElement : streamElements) {
String streamRef = streamElement.getAttribute("ref");
String streamRef = streamElement.getAttribute(REF_ATTR);
if (StringUtils.hasText(streamRef)) {
BeanReference bean = new RuntimeBeanReference(streamRef);
streamBeans.add(bean);
}
else {
parserContext.getReaderContext().error(
"ref not specified for <" + streamElement.getTagName() + "> element", element);
REF_ATTR + " not specified for <" + streamElement.getTagName() + "> element", element);
}
}
}