Open Source Repository

Home /spring/spring-core-3.0.5 | Repository Home


org/springframework/util/xml/AbstractXMLStreamReader.java
/*
 * Copyright 2002-2009 the original author or authors.
 *
 * Licensed 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.springframework.util.xml;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.springframework.util.Assert;

/**
 * Abstract base class for <code>XMLStreamReader</code>s.
 *
 @author Arjen Poutsma
 @since 3.0
 */
abstract class AbstractXMLStreamReader implements XMLStreamReader {

  public String getElementText() throws XMLStreamException {
    if (getEventType() != XMLStreamConstants.START_ELEMENT) {
      throw new XMLStreamException("parser must be on START_ELEMENT to read next text", getLocation());
    }
    int eventType = next();
    StringBuilder builder = new StringBuilder();
    while (eventType != XMLStreamConstants.END_ELEMENT) {
      if (eventType == XMLStreamConstants.CHARACTERS || eventType == XMLStreamConstants.CDATA ||
          eventType == XMLStreamConstants.SPACE || eventType == XMLStreamConstants.ENTITY_REFERENCE) {
        builder.append(getText());
      }
      else if (eventType == XMLStreamConstants.PROCESSING_INSTRUCTION ||
          eventType == XMLStreamConstants.COMMENT) {
        // skipping
      }
      else if (eventType == XMLStreamConstants.END_DOCUMENT) {
        throw new XMLStreamException("unexpected end of document when reading element text content",
            getLocation());
      }
      else if (eventType == XMLStreamConstants.START_ELEMENT) {
        throw new XMLStreamException("element text content may not contain START_ELEMENT", getLocation());
      }
      else {
        throw new XMLStreamException("Unexpected event type " + eventType, getLocation());
      }
      eventType = next();
    }
    return builder.toString();
  }

  public String getAttributeLocalName(int index) {
    return getAttributeName(index).getLocalPart();
  }

  public String getAttributeNamespace(int index) {
    return getAttributeName(index).getNamespaceURI();
  }

  public String getAttributePrefix(int index) {
    return getAttributeName(index).getPrefix();
  }

  public String getNamespaceURI() {
    int eventType = getEventType();
    if (eventType == XMLStreamConstants.START_ELEMENT || eventType == XMLStreamConstants.END_ELEMENT) {
      return getName().getNamespaceURI();
    }
    else {
      throw new IllegalStateException("parser must be on START_ELEMENT or END_ELEMENT state");
    }
  }

  public String getNamespaceURI(String prefix) {
    Assert.notNull(prefix, "No prefix given");
    return getNamespaceContext().getNamespaceURI(prefix);
  }

  public boolean hasText() {
    int eventType = getEventType();
    return eventType == XMLStreamConstants.SPACE || eventType == XMLStreamConstants.CHARACTERS ||
        eventType == XMLStreamConstants.COMMENT || eventType == XMLStreamConstants.CDATA ||
        eventType == XMLStreamConstants.ENTITY_REFERENCE;
  }

  public String getPrefix() {
    int eventType = getEventType();
    if (eventType == XMLStreamConstants.START_ELEMENT || eventType == XMLStreamConstants.END_ELEMENT) {
      return getName().getPrefix();
    }
    else {
      throw new IllegalStateException("parser must be on START_ELEMENT or END_ELEMENT state");
    }
  }

  public boolean hasName() {
    int eventType = getEventType();
    return eventType == XMLStreamConstants.START_ELEMENT || eventType == XMLStreamConstants.END_ELEMENT;
  }

  public boolean isWhiteSpace() {
    return getEventType() == XMLStreamConstants.SPACE;
  }

  public boolean isStartElement() {
    return getEventType() == XMLStreamConstants.START_ELEMENT;
  }

  public boolean isEndElement() {
    return getEventType() == XMLStreamConstants.END_ELEMENT;
  }

  public boolean isCharacters() {
    return getEventType() == XMLStreamConstants.CHARACTERS;
  }

  public int nextTag() throws XMLStreamException {
    int eventType = next();
    while (eventType == XMLStreamConstants.CHARACTERS && isWhiteSpace() ||
        eventType == XMLStreamConstants.CDATA && isWhiteSpace() || eventType == XMLStreamConstants.SPACE ||
        eventType == XMLStreamConstants.PROCESSING_INSTRUCTION || eventType == XMLStreamConstants.COMMENT) {
      eventType = next();
    }
    if (eventType != XMLStreamConstants.START_ELEMENT && eventType != XMLStreamConstants.END_ELEMENT) {
      throw new XMLStreamException("expected start or end tag", getLocation());
    }
    return eventType;
  }

  public void require(int expectedType, String namespaceURI, String localNamethrows XMLStreamException {
    int eventType = getEventType();
    if (eventType != expectedType) {
      throw new XMLStreamException("Expected [" + expectedType + "] but read [" + eventType + "]");
    }
  }

  public String getAttributeValue(String namespaceURI, String localName) {
    for (int i = 0; i < getAttributeCount(); i++) {
      QName name = getAttributeName(i);
      if (name.getLocalPart().equals(localName&&
          (namespaceURI == null || name.getNamespaceURI().equals(namespaceURI))) {
        return getAttributeValue(i);
      }
    }
    return null;
  }

  public boolean hasNext() throws XMLStreamException {
    return getEventType() != END_DOCUMENT;
  }

  public String getLocalName() {
    return getName().getLocalPart();
  }

  public char[] getTextCharacters() {
    return getText().toCharArray();
  }

  public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length)
      throws XMLStreamException {
    char[] source = getTextCharacters();
    length = Math.min(length, source.length);
    System.arraycopy(source, sourceStart, target, targetStart, length);
    return length;
  }

  public int getTextLength() {
    return getText().length();
  }
}