EMMA Coverage Report (generated Fri Aug 21 15:59:46 BST 2009)
[all classes][org.springframework.batch.core.configuration.xml]

COVERAGE SUMMARY FOR SOURCE FILE [ChunkElementParser.java]

nameclass, %method, %block, %line, %
ChunkElementParser.java100% (1/1)100% (6/6)81%  (408/501)87%  (100/115)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ChunkElementParser100% (1/1)100% (6/6)81%  (408/501)87%  (100/115)
checkListenerElementAttributes (ParserContext, Element, Element, String, Stri... 100% (1/1)68%  (34/50)67%  (8/12)
parse (Element, AbstractBeanDefinition, ParserContext, boolean): void 100% (1/1)79%  (184/233)89%  (49/55)
handleStreamsElement (Element, MutablePropertyValues, ParserContext): void 100% (1/1)82%  (64/78)88%  (14/16)
handleRetryListenerElements (ParserContext, Element, ManagedList): void 100% (1/1)84%  (74/88)84%  (16/19)
ChunkElementParser (): void 100% (1/1)100% (3/3)100% (1/1)
handleRetryListenersElement (Element, MutablePropertyValues, ParserContext): ... 100% (1/1)100% (49/49)100% (12/12)

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 static org.springframework.batch.core.configuration.xml.AbstractStepParser.handleExceptionElement;
19 
20import java.util.List;
21 
22import org.springframework.beans.MutablePropertyValues;
23import org.springframework.beans.factory.config.BeanReference;
24import org.springframework.beans.factory.config.RuntimeBeanReference;
25import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
26import org.springframework.beans.factory.support.AbstractBeanDefinition;
27import org.springframework.beans.factory.support.ManagedList;
28import org.springframework.beans.factory.support.RootBeanDefinition;
29import org.springframework.beans.factory.xml.ParserContext;
30import org.springframework.util.StringUtils;
31import org.springframework.util.xml.DomUtils;
32import org.w3c.dom.Element;
33import org.w3c.dom.NamedNodeMap;
34 
35/**
36 * Internal parser for the <chunk/> element inside a step.
37 * 
38 * @author Thomas Risberg
39 * @since 2.0
40 */
41public class ChunkElementParser {
42 
43        private static final String ID_ATTR = "id";
44 
45        private static final String REF_ATTR = "ref";
46 
47        private static final String CLASS_ATTR = "class";
48 
49        private static final String MERGE_ATTR = "merge";
50 
51        private static final String COMMIT_INTERVAL_ATTR = "commit-interval";
52 
53        private static final String CHUNK_COMPLETION_POLICY_ATTR = "chunk-completion-policy";
54 
55        /**
56         * @param element
57         * @param parserContext
58         */
59        protected void parse(Element element, AbstractBeanDefinition bd, ParserContext parserContext, boolean underspecified) {
60 
61                MutablePropertyValues propertyValues = bd.getPropertyValues();
62 
63                propertyValues.addPropertyValue("hasChunkElement", Boolean.TRUE);
64 
65                String readerBeanId = element.getAttribute("reader");
66                if (StringUtils.hasText(readerBeanId)) {
67                        RuntimeBeanReference readerRef = new RuntimeBeanReference(readerBeanId);
68                        propertyValues.addPropertyValue("itemReader", readerRef);
69                }
70 
71                String processorBeanId = element.getAttribute("processor");
72                if (StringUtils.hasText(processorBeanId)) {
73                        RuntimeBeanReference processorRef = new RuntimeBeanReference(processorBeanId);
74                        propertyValues.addPropertyValue("itemProcessor", processorRef);
75                }
76 
77                String writerBeanId = element.getAttribute("writer");
78                if (StringUtils.hasText(writerBeanId)) {
79                        RuntimeBeanReference writerRef = new RuntimeBeanReference(writerBeanId);
80                        propertyValues.addPropertyValue("itemWriter", writerRef);
81                }
82 
83                String taskExecutorBeanId = element.getAttribute("task-executor");
84                if (StringUtils.hasText(taskExecutorBeanId)) {
85                        RuntimeBeanReference taskExecutorRef = new RuntimeBeanReference(taskExecutorBeanId);
86                        propertyValues.addPropertyValue("taskExecutor", taskExecutorRef);
87                }
88 
89                String commitInterval = element.getAttribute(COMMIT_INTERVAL_ATTR);
90                if (StringUtils.hasText(commitInterval)) {
91                        propertyValues.addPropertyValue("commitInterval", commitInterval);
92                }
93 
94                String completionPolicyRef = element.getAttribute(CHUNK_COMPLETION_POLICY_ATTR);
95                if (StringUtils.hasText(completionPolicyRef)) {
96                        RuntimeBeanReference completionPolicy = new RuntimeBeanReference(completionPolicyRef);
97                        propertyValues.addPropertyValue("chunkCompletionPolicy", completionPolicy);
98                }
99 
100                if (!underspecified
101                                && propertyValues.contains("commitInterval") == propertyValues.contains("chunkCompletionPolicy")) {
102                        if (propertyValues.contains("commitInterval")) {
103                                parserContext.getReaderContext().error(
104                                                "The <" + element.getNodeName() + "/> element must contain either '" + COMMIT_INTERVAL_ATTR
105                                                                + "' " + "or '" + CHUNK_COMPLETION_POLICY_ATTR + "', but not both.", element);
106                        }
107                        else {
108                                parserContext.getReaderContext().error(
109                                                "The <" + element.getNodeName() + "/> element must contain either '" + COMMIT_INTERVAL_ATTR
110                                                                + "' " + "or '" + CHUNK_COMPLETION_POLICY_ATTR + "'.", element);
111 
112                        }
113                }
114 
115                String skipLimit = element.getAttribute("skip-limit");
116                if (StringUtils.hasText(skipLimit)) {
117                        propertyValues.addPropertyValue("skipLimit", skipLimit);
118                }
119 
120                String retryLimit = element.getAttribute("retry-limit");
121                if (StringUtils.hasText(retryLimit)) {
122                        propertyValues.addPropertyValue("retryLimit", retryLimit);
123                }
124 
125                String cacheCapacity = element.getAttribute("cache-capacity");
126                if (StringUtils.hasText(cacheCapacity)) {
127                        propertyValues.addPropertyValue("cacheCapacity", cacheCapacity);
128                }
129 
130                String isReaderTransactionalQueue = element.getAttribute("is-reader-transactional-queue");
131                if (StringUtils.hasText(isReaderTransactionalQueue)) {
132                        propertyValues.addPropertyValue("isReaderTransactionalQueue", isReaderTransactionalQueue);
133                }
134 
135                handleExceptionElement(element, parserContext, propertyValues, "skippable-exception-classes",
136                                "skippableExceptionClasses");
137 
138                handleExceptionElement(element, parserContext, propertyValues, "retryable-exception-classes",
139                                "retryableExceptionClasses");
140 
141                handleExceptionElement(element, parserContext, propertyValues, "fatal-exception-classes",
142                                "fatalExceptionClasses");
143 
144                handleRetryListenersElement(element, propertyValues, parserContext);
145 
146                handleStreamsElement(element, propertyValues, parserContext);
147 
148        }
149 
150        private void handleRetryListenersElement(Element element, MutablePropertyValues propertyValues,
151                        ParserContext parserContext) {
152                Element listenersElement = DomUtils.getChildElementByTagName(element, "retry-listeners");
153                if (listenersElement != null) {
154                        CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(listenersElement.getTagName(),
155                                        parserContext.extractSource(element));
156                        parserContext.pushContainingComponent(compositeDef);
157                        ManagedList retryListenerBeans = new ManagedList();
158                        retryListenerBeans.setMergeEnabled(listenersElement.hasAttribute(MERGE_ATTR)
159                                        && Boolean.valueOf(listenersElement.getAttribute(MERGE_ATTR)));
160                        handleRetryListenerElements(parserContext, listenersElement, retryListenerBeans);
161                        propertyValues.addPropertyValue("retryListeners", retryListenerBeans);
162                        parserContext.popAndRegisterContainingComponent();
163                }
164        }
165 
166        @SuppressWarnings("unchecked")
167        private void handleRetryListenerElements(ParserContext parserContext, Element element, ManagedList beans) {
168                List<Element> listenerElements = DomUtils.getChildElementsByTagName(element, "listener");
169                if (listenerElements != null) {
170                        for (Element listenerElement : listenerElements) {
171                                String id = listenerElement.getAttribute(ID_ATTR);
172                                String listenerRef = listenerElement.getAttribute(REF_ATTR);
173                                String className = listenerElement.getAttribute(CLASS_ATTR);
174                                checkListenerElementAttributes(parserContext, element, listenerElement, id, listenerRef, className);
175                                if (StringUtils.hasText(listenerRef)) {
176                                        BeanReference bean = new RuntimeBeanReference(listenerRef);
177                                        beans.add(bean);
178                                }
179                                else if (StringUtils.hasText(className)) {
180                                        RootBeanDefinition beanDef = new RootBeanDefinition(className, null, null);
181                                        if (!StringUtils.hasText(id)) {
182                                                id = parserContext.getReaderContext().generateBeanName(beanDef);
183                                        }
184                                        beans.add(beanDef);
185                                }
186                                else {
187                                        parserContext.getReaderContext().error(
188                                                        "Neither '" + REF_ATTR + "' or '" + CLASS_ATTR + "' specified for <"
189                                                                        + listenerElement.getTagName() + "> element", element);
190                                }
191                        }
192                }
193        }
194 
195        private void checkListenerElementAttributes(ParserContext parserContext, Element element, Element listenerElement,
196                        String id, String listenerRef, String className) {
197                if (StringUtils.hasText(className) && StringUtils.hasText(listenerRef)) {
198                        NamedNodeMap attributeNodes = listenerElement.getAttributes();
199                        StringBuilder attributes = new StringBuilder();
200                        for (int i = 0; i < attributeNodes.getLength(); i++) {
201                                if (i > 0) {
202                                        attributes.append(" ");
203                                }
204                                attributes.append(attributeNodes.item(i));
205                        }
206                        parserContext.getReaderContext().error(
207                                        "Both '" + REF_ATTR + "' and '" + CLASS_ATTR + "' specified; use '" + CLASS_ATTR
208                                                        + "' with an optional '" + ID_ATTR + "' or just '" + REF_ATTR + "' for <"
209                                                        + listenerElement.getTagName() + "> element specified with attributes: " + attributes,
210                                        element);
211                }
212        }
213 
214        @SuppressWarnings("unchecked")
215        private void handleStreamsElement(Element element, MutablePropertyValues propertyValues, ParserContext parserContext) {
216                Element streamsElement = DomUtils.getChildElementByTagName(element, "streams");
217                if (streamsElement != null) {
218                        ManagedList streamBeans = new ManagedList();
219                        streamBeans.setMergeEnabled(streamsElement.hasAttribute(MERGE_ATTR)
220                                        && Boolean.valueOf(streamsElement.getAttribute(MERGE_ATTR)));
221                        List<Element> streamElements = DomUtils.getChildElementsByTagName(streamsElement, "stream");
222                        if (streamElements != null) {
223                                for (Element streamElement : streamElements) {
224                                        String streamRef = streamElement.getAttribute(REF_ATTR);
225                                        if (StringUtils.hasText(streamRef)) {
226                                                BeanReference bean = new RuntimeBeanReference(streamRef);
227                                                streamBeans.add(bean);
228                                        }
229                                        else {
230                                                parserContext.getReaderContext().error(
231                                                                REF_ATTR + " not specified for <" + streamElement.getTagName() + "> element", element);
232                                        }
233                                }
234                        }
235                        propertyValues.addPropertyValue("streams", streamBeans);
236                }
237        }
238 
239}

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