org.hibernate.boot.jaxb.internal.stax.BufferedXMLEventReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-core Show documentation
Show all versions of hibernate-core Show documentation
Hibernate's core ORM functionality
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
package org.hibernate.boot.jaxb.internal.stax;
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
*/
public class BufferedXMLEventReader extends BaseXMLEventReader {
private final LinkedList eventBuffer = new LinkedList();
private int eventLimit;
private ListIterator bufferReader;
/**
* 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 {@link #mark(int)} with the specified event limit
* @see #mark(int)
*/
public BufferedXMLEventReader(XMLEventReader reader, int eventLimit) {
super(reader);
this.eventLimit = eventLimit;
}
/**
* @return A copy of the current buffer
*/
public List getBuffer() {
return new ArrayList(this.eventBuffer);
}
@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 {@link #mark(int)} with -1.
*/
public void mark() {
this.mark(-1);
}
/**
* 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.
*/
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();
}
/**
* @return The number of events in the buffer.
*/
public int bufferSize() {
return this.eventBuffer.size();
}
/**
* 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();
}
}