EMMA Coverage Report (generated Thu Jan 24 13:37:04 CST 2013)
[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)79%  (187/237)78%  (56/72)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class DefaultFragmentEventReader100% (1/1)80%  (8/10)79%  (187/237)78%  (56/72)
next (): Object 0%   (0/1)0%   (0/10)0%   (0/3)
reset (): void 0%   (0/1)0%   (0/19)0%   (0/7)
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)

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

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