EMMA Coverage Report (generated Fri Jan 30 13:20:29 EST 2009)
[all classes][org.springframework.batch.item.xml]

COVERAGE SUMMARY FOR SOURCE FILE [StaxEventItemReader.java]

nameclass, %method, %block, %line, %
StaxEventItemReader.java100% (1/1)100% (10/10)88%  (156/178)93%  (46.4/50)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class StaxEventItemReader100% (1/1)100% (10/10)88%  (156/178)93%  (46.4/50)
StaxEventItemReader (): void 100% (1/1)64%  (9/14)88%  (2.6/3)
doClose (): void 100% (1/1)69%  (20/29)86%  (6.9/8)
moveCursorToNextFragment (XMLEventReader): boolean 100% (1/1)82%  (33/40)82%  (9/11)
<static initializer> 100% (1/1)91%  (10/11)90%  (0.9/1)
afterPropertiesSet (): void 100% (1/1)100% (9/9)100% (3/3)
doOpen (): void 100% (1/1)100% (37/37)100% (10/10)
doRead (): Object 100% (1/1)100% (26/26)100% (8/8)
setFragmentDeserializer (EventReaderDeserializer): void 100% (1/1)100% (4/4)100% (2/2)
setFragmentRootElementName (String): void 100% (1/1)100% (4/4)100% (2/2)
setResource (Resource): void 100% (1/1)100% (4/4)100% (2/2)

1package org.springframework.batch.item.xml;
2 
3import java.io.InputStream;
4 
5import javax.xml.namespace.QName;
6import javax.xml.stream.XMLEventReader;
7import javax.xml.stream.XMLInputFactory;
8import javax.xml.stream.XMLStreamException;
9import javax.xml.stream.events.StartElement;
10 
11import org.apache.commons.logging.Log;
12import org.apache.commons.logging.LogFactory;
13import org.springframework.batch.item.file.ResourceAwareItemReaderItemStream;
14import org.springframework.batch.item.support.AbstractBufferedItemReaderItemStream;
15import org.springframework.batch.item.xml.stax.DefaultFragmentEventReader;
16import org.springframework.batch.item.xml.stax.FragmentEventReader;
17import org.springframework.beans.factory.InitializingBean;
18import org.springframework.core.io.Resource;
19import org.springframework.dao.DataAccessResourceFailureException;
20import org.springframework.util.Assert;
21import org.springframework.util.ClassUtils;
22 
23/**
24 * Item reader for reading XML input based on StAX.
25 * 
26 * It extracts fragments from the input XML document which correspond to records
27 * for processing. The fragments are wrapped with StartDocument and EndDocument
28 * events so that the fragments can be further processed like standalone XML
29 * documents.
30 * 
31 * The implementation is *not* thread-safe.
32 * 
33 * @author Robert Kasanicky
34 */
35public class StaxEventItemReader extends AbstractBufferedItemReaderItemStream implements
36                ResourceAwareItemReaderItemStream, InitializingBean {
37        
38        private static final Log logger = LogFactory.getLog(StaxEventItemReader.class);
39 
40        private FragmentEventReader fragmentReader;
41 
42        private XMLEventReader eventReader;
43 
44        private EventReaderDeserializer eventReaderDeserializer;
45 
46        private Resource resource;
47 
48        private InputStream inputStream;
49 
50        private String fragmentRootElementName;
51 
52        private boolean noInput;
53 
54        public StaxEventItemReader() {
55                setName(ClassUtils.getShortName(StaxEventItemReader.class));
56        }
57 
58        public void setResource(Resource resource) {
59                this.resource = resource;
60        }
61 
62        /**
63         * @param eventReaderDeserializer maps xml fragments corresponding to
64         * records to objects
65         */
66        public void setFragmentDeserializer(EventReaderDeserializer eventReaderDeserializer) {
67                this.eventReaderDeserializer = eventReaderDeserializer;
68        }
69 
70        /**
71         * @param fragmentRootElementName name of the root element of the fragment
72         * TODO String can be ambiguous due to namespaces, use QName?
73         */
74        public void setFragmentRootElementName(String fragmentRootElementName) {
75                this.fragmentRootElementName = fragmentRootElementName;
76        }
77 
78        /**
79         * Ensure that all required dependencies for the ItemReader to run are
80         * provided after all properties have been set.
81         * 
82         * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
83         * @throws IllegalArgumentException if the Resource, FragmentDeserializer or
84         * FragmentRootElementName is null, or if the root element is empty.
85         * @throws IllegalStateException if the Resource does not exist.
86         */
87        public void afterPropertiesSet() throws Exception {
88                Assert.notNull(eventReaderDeserializer, "The FragmentDeserializer must not be null.");
89                Assert.hasLength(fragmentRootElementName, "The FragmentRootElementName must not be null");
90        }
91 
92        /**
93         * Responsible for moving the cursor before the StartElement of the fragment
94         * root.
95         * 
96         * This implementation simply looks for the next corresponding element, it
97         * does not care about element nesting. You will need to override this
98         * method to correctly handle composite fragments.
99         * 
100         * @return <code>true</code> if next fragment was found,
101         * <code>false</code> otherwise.
102         */
103        protected boolean moveCursorToNextFragment(XMLEventReader reader) {
104                try {
105                        while (true) {
106                                while (reader.peek() != null && !reader.peek().isStartElement()) {
107                                        reader.nextEvent();
108                                }
109                                if (reader.peek() == null) {
110                                        return false;
111                                }
112                                QName startElementName = ((StartElement) reader.peek()).getName();
113                                if (startElementName.getLocalPart().equals(fragmentRootElementName)) {
114                                        return true;
115                                }
116                                else {
117                                        reader.nextEvent();
118                                }
119                        }
120                }
121                catch (XMLStreamException e) {
122                        throw new DataAccessResourceFailureException("Error while reading from event reader", e);
123                }
124        }
125 
126        protected void doClose() throws Exception {
127                try {
128                        if (fragmentReader != null) {
129                                fragmentReader.close();
130                        }
131                        if (inputStream != null) {
132                                inputStream.close();
133                        }
134                }
135                finally {
136                        fragmentReader = null;
137                        inputStream = null;
138                }
139 
140        }
141 
142        protected void doOpen() throws Exception {
143                Assert.notNull(resource, "The Resource must not be null.");
144                
145                noInput = false;
146                if (!resource.exists()) {
147                        noInput = true;
148                        logger.warn("Input resource does not exist");
149                        return;
150                }
151 
152                inputStream = resource.getInputStream();
153                eventReader = XMLInputFactory.newInstance().createXMLEventReader(inputStream);
154                fragmentReader = new DefaultFragmentEventReader(eventReader);
155 
156        }
157 
158        /**
159         * Move to next fragment and map it to item.
160         */
161        protected Object doRead() throws Exception {
162                if (noInput) {
163                        return null;
164                }
165                
166                Object item = null;
167 
168                if (moveCursorToNextFragment(fragmentReader)) {
169                        fragmentReader.markStartFragment();
170                        item = eventReaderDeserializer.deserializeFragment(fragmentReader);
171                        fragmentReader.markFragmentProcessed();
172                }
173 
174                return item;
175        }
176 
177}

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