Package org.hibernate.internal.util.xml

Source Code of org.hibernate.internal.util.xml.BufferedXMLEventReader

/*
* 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
*/
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 {@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<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 {@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();
  }
}
TOP

Related Classes of org.hibernate.internal.util.xml.BufferedXMLEventReader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.