/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* 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 the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>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.apereo.portal.xml.stream;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EntityDeclaration;
import javax.xml.stream.events.EntityReference;
import javax.xml.stream.events.XMLEvent;
import javax.xml.stream.util.EventReaderDelegate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Base for XMLEventReader that implements the {@link #getElementText()} and {@link #nextTag()} APIs
* in a way that is agnostic from the rest of the XMLEventReader implementation. Both will use the
* subclasses {@link #internalNextEvent()} as the exclusive way to read events.
*
*/
public abstract class BaseXMLEventReader extends EventReaderDelegate {
protected final Logger logger = LoggerFactory.getLogger(getClass());
private XMLEvent previousEvent;
public BaseXMLEventReader(XMLEventReader reader) {
super(reader);
}
/** Subclass's version of {@link #nextEvent()}, called by {@link #next()} */
protected abstract XMLEvent internalNextEvent() throws XMLStreamException;
/** @return The XMLEvent returned by the last call to {@link #internalNextEvent()} */
protected final XMLEvent getPreviousEvent() {
return this.previousEvent;
}
@Override
public final XMLEvent nextEvent() throws XMLStreamException {
this.previousEvent = this.internalNextEvent();
return this.previousEvent;
}
/* (non-Javadoc)
* @see java.util.Iterator#next()
*/
@Override
public final Object next() {
try {
return this.nextEvent();
} catch (XMLStreamException e) {
return null;
}
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLEventReader#getElementText()
*/
@Override
public final String getElementText() throws XMLStreamException {
XMLEvent event = this.previousEvent;
if (event == null) {
throw new XMLStreamException(
"Must be on START_ELEMENT to read next text, element was null");
}
if (!event.isStartElement()) {
throw new XMLStreamException(
"Must be on START_ELEMENT to read next text", event.getLocation());
}
final StringBuilder text = new StringBuilder();
while (!event.isEndDocument()) {
switch (event.getEventType()) {
case XMLStreamConstants.CHARACTERS:
case XMLStreamConstants.SPACE:
case XMLStreamConstants.CDATA:
{
final Characters characters = event.asCharacters();
text.append(characters.getData());
break;
}
case XMLStreamConstants.ENTITY_REFERENCE:
{
final EntityReference entityReference = (EntityReference) event;
final EntityDeclaration declaration = entityReference.getDeclaration();
text.append(declaration.getReplacementText());
break;
}
case XMLStreamConstants.COMMENT:
case XMLStreamConstants.PROCESSING_INSTRUCTION:
{
//Ignore
break;
}
default:
{
throw new XMLStreamException(
"Unexpected event type '"
+ XMLStreamConstantsUtils.getEventName(event.getEventType())
+ "' encountered. Found event: "
+ event,
event.getLocation());
}
}
event = this.nextEvent();
}
return text.toString();
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLEventReader#nextTag()
*/
@Override
public final XMLEvent nextTag() throws XMLStreamException {
XMLEvent event = this.nextEvent();
while ((event.isCharacters() && event.asCharacters().isWhiteSpace())
|| event.isProcessingInstruction()
|| event.getEventType() == XMLStreamConstants.COMMENT) {
event = this.nextEvent();
}
if (!event.isStartElement() && event.isEndElement()) {
throw new XMLStreamException(
"Unexpected event type '"
+ XMLStreamConstantsUtils.getEventName(event.getEventType())
+ "' encountered. Found event: "
+ event,
event.getLocation());
}
return event;
}
}