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

COVERAGE SUMMARY FOR SOURCE FILE [DefaultFragmentEventReader.java]

nameclass, %method, %block, %line, %
DefaultFragmentEventReader.java100% (1/1)80%  (8/10)81%  (187/231)80%  (56/70)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class DefaultFragmentEventReader100% (1/1)80%  (8/10)81%  (187/231)80%  (56/70)
next (): Object 0%   (0/1)0%   (0/10)0%   (0/3)
reset (): void 0%   (0/1)0%   (0/13)0%   (0/5)
hasNext (): boolean 100% (1/1)53%  (8/15)67%  (4/6)
markFragmentProcessed (): void 100% (1/1)70%  (16/23)71%  (5/7)
DefaultFragmentEventReader (XMLEventReader): void 100% (1/1)84%  (38/45)87%  (13/15)
alterEvent (XMLEvent, boolean): XMLEvent 100% (1/1)100% (38/38)100% (13/13)
checkFragmentEnd (XMLEvent): void 100% (1/1)100% (40/40)100% (7/7)
markStartFragment (): void 100% (1/1)100% (7/7)100% (3/3)
nextEvent (): XMLEvent 100% (1/1)100% (28/28)100% (8/8)
peek (): XMLEvent 100% (1/1)100% (12/12)100% (3/3)

1package org.springframework.batch.item.xml.stax;
2 
3import java.util.NoSuchElementException;
4 
5import javax.xml.namespace.QName;
6import javax.xml.stream.XMLEventFactory;
7import javax.xml.stream.XMLEventReader;
8import javax.xml.stream.XMLStreamException;
9import javax.xml.stream.events.EndDocument;
10import javax.xml.stream.events.EndElement;
11import javax.xml.stream.events.StartDocument;
12import javax.xml.stream.events.StartElement;
13import javax.xml.stream.events.XMLEvent;
14 
15import org.springframework.dao.DataAccessResourceFailureException;
16 
17/**
18 * Default implementation of {@link FragmentEventReader}
19 * 
20 * @author Robert Kasanicky
21 */
22public class DefaultFragmentEventReader extends AbstractEventReaderWrapper implements FragmentEventReader {
23 
24        // true when the next event is the StartElement of next fragment
25        private boolean startFragmentFollows = false;
26 
27        // true when the next event is the EndElement of current fragment
28        private boolean endFragmentFollows = false;
29 
30        // true while cursor is inside fragment
31        private boolean insideFragment = false;
32 
33        // true when reader should behave like the cursor was at the end of document
34        private boolean fakeDocumentEnd = false;
35 
36        private StartDocument startDocumentEvent = null;
37 
38        private EndDocument endDocumentEvent = null;
39 
40        // fragment root name is remembered so that the matching closing element can
41        // be identified
42        private QName fragmentRootName = null;
43 
44        // counts the occurrences of current fragmentRootName (increased for
45        // StartElement, decreased for EndElement)
46        private int matchCounter = 0;
47 
48        /**
49         * Caches the StartDocument event for later use.
50         * @param wrappedEventReader the original wrapped event reader
51         */
52        public DefaultFragmentEventReader(XMLEventReader wrappedEventReader) {
53                super(wrappedEventReader);
54                try {
55                        startDocumentEvent = (StartDocument) wrappedEventReader.peek();
56                }
57                catch (XMLStreamException e) {
58                        throw new DataAccessResourceFailureException("Error reading start document from event reader", e);
59                }
60 
61                endDocumentEvent = XMLEventFactory.newInstance().createEndDocument();
62        }
63 
64        public void markStartFragment() {
65                startFragmentFollows = true;
66                fragmentRootName = null;
67        }
68 
69        public boolean hasNext() {
70                try {
71                        if (peek() != null) {
72                                return true;
73                        }
74                }
75                catch (XMLStreamException e) {
76                        throw new DataAccessResourceFailureException("Error reading XML stream", e);
77                }
78                return false;
79        }
80 
81        public Object next() {
82                try {
83                        return nextEvent();
84                }
85                catch (XMLStreamException e) {
86                        throw new DataAccessResourceFailureException("Error reading XML stream", e);
87                }
88        }
89 
90        public XMLEvent nextEvent() throws XMLStreamException {
91                if (fakeDocumentEnd) {
92                        throw new NoSuchElementException();
93                }
94                XMLEvent event = wrappedEventReader.peek();
95                XMLEvent proxyEvent = alterEvent(event, false);
96                checkFragmentEnd(proxyEvent);
97                if (event == proxyEvent) {
98                        wrappedEventReader.nextEvent();
99                }
100 
101                return proxyEvent;
102        }
103 
104        /**
105         * Sets the endFragmentFollows flag to true if next event is the last event
106         * of the fragment.
107         * @param event peek() from wrapped event reader
108         */
109        private void checkFragmentEnd(XMLEvent event) {
110                if (event.isStartElement() && ((StartElement) event).getName().equals(fragmentRootName)) {
111                        matchCounter++;
112                }
113                else if (event.isEndElement() && ((EndElement) event).getName().equals(fragmentRootName)) {
114                        matchCounter--;
115                        if (matchCounter == 0) {
116                                endFragmentFollows = true;
117                        }
118                }
119        }
120 
121        /**
122         * @param event peek() from wrapped event reader
123         * @param peek if true do not change the internal state
124         * @return StartDocument event if peek() points to beginning of fragment
125         * EndDocument event if cursor is right behind the end of fragment original
126         * event otherwise
127         */
128        private XMLEvent alterEvent(XMLEvent event, boolean peek) {
129                if (startFragmentFollows) {
130                        fragmentRootName = ((StartElement) event).getName();
131                        if (!peek) {
132                                startFragmentFollows = false;
133                                insideFragment = true;
134                        }
135                        return startDocumentEvent;
136                }
137                else if (endFragmentFollows) {
138                        if (!peek) {
139                                endFragmentFollows = false;
140                                insideFragment = false;
141                                fakeDocumentEnd = true;
142                        }
143                        return endDocumentEvent;
144                }
145                return event;
146        }
147 
148        public XMLEvent peek() throws XMLStreamException {
149                if (fakeDocumentEnd) {
150                        return null;
151                }
152                return alterEvent(wrappedEventReader.peek(), true);
153        }
154 
155        /**
156         * Finishes reading the fragment in case the fragment was processed without
157         * being read until the end.
158         */
159        public void markFragmentProcessed() {
160                if (insideFragment|| startFragmentFollows) {
161                        try {
162                                while (!(nextEvent() instanceof EndDocument)) {
163                                        // just read all events until EndDocument
164                                }
165                        }
166                        catch (XMLStreamException e) {
167                                throw new DataAccessResourceFailureException("Error reading XML stream", e);
168                        }
169                }
170                fakeDocumentEnd = false;
171        }
172 
173        public void reset() {
174                insideFragment = false;
175                startFragmentFollows = false;
176                endFragmentFollows = false;
177                fakeDocumentEnd = false;
178        }
179 
180}

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