EMMA Coverage Report (generated Thu May 22 12:08:10 CDT 2014)
[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    @Override
81        public void markStartFragment() {
82                startFragmentFollows = true;
83                fragmentRootName = null;
84        }
85 
86    @Override
87        public boolean hasNext() {
88                try {
89                        if (peek() != null) {
90                                return true;
91                        }
92                }
93                catch (XMLStreamException e) {
94                        throw new DataAccessResourceFailureException("Error reading XML stream", e);
95                }
96                return false;
97        }
98 
99    @Override
100        public Object next() {
101                try {
102                        return nextEvent();
103                }
104                catch (XMLStreamException e) {
105                        throw new DataAccessResourceFailureException("Error reading XML stream", e);
106                }
107        }
108 
109    @Override
110        public XMLEvent nextEvent() throws XMLStreamException {
111                if (fakeDocumentEnd) {
112                        throw new NoSuchElementException();
113                }
114                XMLEvent event = wrappedEventReader.peek();
115                XMLEvent proxyEvent = alterEvent(event, false);
116                checkFragmentEnd(proxyEvent);
117                if (event == proxyEvent) {
118                        wrappedEventReader.nextEvent();
119                }
120 
121                return proxyEvent;
122        }
123 
124        /**
125         * Sets the endFragmentFollows flag to true if next event is the last event
126         * of the fragment.
127         * @param event peek() from wrapped event reader
128         */
129        private void checkFragmentEnd(XMLEvent event) {
130                if (event.isStartElement() && ((StartElement) event).getName().equals(fragmentRootName)) {
131                        matchCounter++;
132                }
133                else if (event.isEndElement() && ((EndElement) event).getName().equals(fragmentRootName)) {
134                        matchCounter--;
135                        if (matchCounter == 0) {
136                                endFragmentFollows = true;
137                        }
138                }
139        }
140 
141        /**
142         * @param event peek() from wrapped event reader
143         * @param peek if true do not change the internal state
144         * @return StartDocument event if peek() points to beginning of fragment
145         * EndDocument event if cursor is right behind the end of fragment original
146         * event otherwise
147         */
148        private XMLEvent alterEvent(XMLEvent event, boolean peek) {
149                if (startFragmentFollows) {
150                        fragmentRootName = ((StartElement) event).getName();
151                        if (!peek) {
152                                startFragmentFollows = false;
153                                insideFragment = true;
154                        }
155                        return startDocumentEvent;
156                }
157                else if (endFragmentFollows) {
158                        if (!peek) {
159                                endFragmentFollows = false;
160                                insideFragment = false;
161                                fakeDocumentEnd = true;
162                        }
163                        return endDocumentEvent;
164                }
165                return event;
166        }
167 
168    @Override
169        public XMLEvent peek() throws XMLStreamException {
170                if (fakeDocumentEnd) {
171                        return null;
172                }
173                return alterEvent(wrappedEventReader.peek(), true);
174        }
175 
176        /**
177         * Finishes reading the fragment in case the fragment was processed without
178         * being read until the end.
179         */
180    @Override
181        public void markFragmentProcessed() {
182                if (insideFragment|| startFragmentFollows) {
183                        try {
184                                while (!(nextEvent() instanceof EndDocument)) {
185                                        // just read all events until EndDocument
186                                }
187                        }
188                        catch (XMLStreamException e) {
189                                throw new DataAccessResourceFailureException("Error reading XML stream", e);
190                        }
191                }
192                fakeDocumentEnd = false;
193        }
194 
195    @Override
196        public void reset() {
197                insideFragment = false;
198                startFragmentFollows = false;
199                endFragmentFollows = false;
200                fakeDocumentEnd = false;
201                fragmentRootName = null;
202                matchCounter = 0;
203        }
204 
205}

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