/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.internal.util.xml;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
Buffers XML events for later re-reading
Note, copied from the uPortal project by permission of author. See
https://github.com/Jasig/uPortal/blob/master/uportal-war/src/main/java/org/jasig/portal/xml/stream/BufferedXMLEventReader.java
Author: Eric Dalquist
/**
* Buffers XML events for later re-reading
*
* Note, copied from the uPortal project by permission of author. See
* https://github.com/Jasig/uPortal/blob/master/uportal-war/src/main/java/org/jasig/portal/xml/stream/BufferedXMLEventReader.java
*
* @author Eric Dalquist
*/
public class BufferedXMLEventReader extends BaseXMLEventReader {
private final LinkedList<XMLEvent> eventBuffer = new LinkedList<XMLEvent>();
private int eventLimit;
private ListIterator<XMLEvent> bufferReader;
Create new buffering reader, no buffering is done until mark(int)
is called. /**
* Create new buffering reader, no buffering is done until {@link #mark(int)} is called.
*/
public BufferedXMLEventReader(XMLEventReader reader) {
super(reader);
}
Create new buffering reader. Calls mark(int)
with the specified event limit See Also:
/**
* Create new buffering reader. Calls {@link #mark(int)} with the specified event limit
* @see #mark(int)
*/
public BufferedXMLEventReader(XMLEventReader reader, int eventLimit) {
super(reader);
this.eventLimit = eventLimit;
}
Returns: A copy of the current buffer
/**
* @return A copy of the current buffer
*/
public List<XMLEvent> getBuffer() {
return new ArrayList<XMLEvent>(this.eventBuffer);
}
/* (non-Javadoc)
* @see org.jasig.portal.xml.stream.BaseXMLEventReader#internalNextEvent()
*/
@Override
protected XMLEvent internalNextEvent() throws XMLStreamException {
//If there is an iterator to read from reset was called, use the iterator
//until it runs out of events.
if (this.bufferReader != null) {
final XMLEvent event = this.bufferReader.next();
//If nothing left in the iterator, remove the reference and fall through to direct reading
if (!this.bufferReader.hasNext()) {
this.bufferReader = null;
}
return event;
}
//Get the next event from the underlying reader
final XMLEvent event = this.getParent().nextEvent();
//if buffering add the event
if (this.eventLimit != 0) {
this.eventBuffer.offer(event);
//If limited buffer size and buffer is too big trim the buffer.
if (this.eventLimit > 0 && this.eventBuffer.size() > this.eventLimit) {
this.eventBuffer.poll();
}
}
return event;
}
@Override
public boolean hasNext() {
return this.bufferReader != null || super.hasNext();
}
@Override
public XMLEvent peek() throws XMLStreamException {
if (this.bufferReader != null) {
final XMLEvent event = this.bufferReader.next();
this.bufferReader.previous(); //move the iterator back
return event;
}
return super.peek();
}
Same as calling mark(int)
with -1. /**
* Same as calling {@link #mark(int)} with -1.
*/
public void mark() {
this.mark(-1);
}
Start buffering events
Params: - eventLimit – the maximum number of events to buffer. -1 will buffer all events, 0 will buffer no events.
/**
* Start buffering events
* @param eventLimit the maximum number of events to buffer. -1 will buffer all events, 0 will buffer no events.
*/
public void mark(int eventLimit) {
this.eventLimit = eventLimit;
//Buffering no events now, clear the buffer and buffered reader
if (this.eventLimit == 0) {
this.eventBuffer.clear();
this.bufferReader = null;
}
//Buffering limited set of events, lets trim the buffer if needed
else if (this.eventLimit > 0) {
//If there is an iterator check its current position and calculate the new iterator start position
int iteratorIndex = 0;
if (this.bufferReader != null) {
final int nextIndex = this.bufferReader.nextIndex();
iteratorIndex = Math.max(0, nextIndex - (this.eventBuffer.size() - this.eventLimit));
}
//Trim the buffer until it is not larger than the limit
while (this.eventBuffer.size() > this.eventLimit) {
this.eventBuffer.poll();
}
//If there is an iterator re-create it using the newly calculated index
if (this.bufferReader != null) {
this.bufferReader = this.eventBuffer.listIterator(iteratorIndex);
}
}
}
Reset the reader to these start of the buffered events.
/**
* Reset the reader to these start of the buffered events.
*/
public void reset() {
if (this.eventBuffer.isEmpty()) {
this.bufferReader = null;
}
else {
this.bufferReader = this.eventBuffer.listIterator();
}
}
@Override
public void close() throws XMLStreamException {
this.mark(0);
super.close();
}
Returns: The number of events in the buffer.
/**
* @return The number of events in the buffer.
*/
public int bufferSize() {
return this.eventBuffer.size();
}
If reading from the buffer after a reset()
call an IllegalStateException
will be thrown. /**
* If reading from the buffer after a {@link #reset()} call an {@link IllegalStateException} will be thrown.
*/
@Override
public void remove() {
if (this.bufferReader != null && this.bufferReader.hasNext()) {
throw new IllegalStateException("Cannot remove a buffered element");
}
super.remove();
}
}