Package org.jasig.portal.xml.stream

Source Code of org.jasig.portal.xml.stream.FilteringXMLEventReader

/**
* Licensed to Jasig under one or more contributor license
* agreements. See the NOTICE file distributed with this work
* for additional information regarding copyright ownership.
* Jasig licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a
* copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.jasig.portal.xml.stream;

import java.util.Deque;
import java.util.LinkedList;
import java.util.NoSuchElementException;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

/**
* Base class for {@link XMLEventReader}s that want to modify or remove events from the reader stream.
* If a {@link StartElement} event is removed the subclass's {@link #filterEvent(XMLEvent, boolean)} will
* not see any events until after the matching {@link EndElement} event.
*
* @author Eric Dalquist
* @version $Revision$
*/
public abstract class FilteringXMLEventReader extends BaseXMLEventReader {
  private final Deque<QName> prunedElements = new LinkedList<QName>();
    private XMLEvent peekedEvent = null;
   
    public FilteringXMLEventReader(XMLEventReader reader) {
        super(reader);
    }

    @Override
    protected final XMLEvent internalNextEvent() throws XMLStreamException {
        return this.internalNext(false);
    }
   
    @Override
    public boolean hasNext() {
        try {
            return peekedEvent != null || (super.hasNext() && this.peek() != null);
        }
        catch (XMLStreamException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        catch (NoSuchElementException e) {
            return false;
        }
    }

    @Override
    public final XMLEvent peek() throws XMLStreamException {
        if (peekedEvent != null) {
            return peekedEvent;
        }
       
        peekedEvent = internalNext(true);
        return peekedEvent;
    }

    protected final XMLEvent internalNext(boolean peek) throws XMLStreamException {
        XMLEvent event = null;
       
        if (peekedEvent != null) {
            event = peekedEvent;
            peekedEvent = null;
            return event;
        }

        do {
            event = super.getParent().nextEvent();

            //If there are pruned elements in the queue filtering events is still needed
        if (!prunedElements.isEmpty()) {
            //If another start element add it to the queue
          if (event.isStartElement()) {
              final StartElement startElement = event.asStartElement();
            prunedElements.push(startElement.getName());
          }
          //If end element pop the newest name of the queue and double check that the start/end elements match up
          else if (event.isEndElement()) {
            final QName startElementName = prunedElements.pop();
           
            final EndElement endElement = event.asEndElement();
          final QName endElementName = endElement.getName();
         
          if (!startElementName.equals(endElementName)) {
              throw new IllegalArgumentException("Malformed XMLEvent stream. Expected end element for " + startElementName + " but found end element for " + endElementName);
            }
          }
         
          event = null;
        }
        else {
                final XMLEvent filteredEvent = this.filterEvent(event, peek);
               
                //If the event is being removed and it is a start element all elements until the matching
                //end element need to be removed as well
                if (filteredEvent == null && event.isStartElement()) {
                  final StartElement startElement = event.asStartElement();
                final QName name = startElement.getName();
              prunedElements.push(name);
              }
               
                event = filteredEvent;
        }
        }
        while (event == null);
       
        return event;
    }

    /**
     * @param event The current event
     * @param peek If the event is from a {@link #peek()} call
     * @return The event to return, if null is returned the event is dropped from the stream and the next event will be used.
     */
    protected abstract XMLEvent filterEvent(XMLEvent event, boolean peek);
}
TOP

Related Classes of org.jasig.portal.xml.stream.FilteringXMLEventReader

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.