/*
 * 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
 */
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(); } }