blob: be1c4082df678f76b7399b1ee6e2aba8d5c3bee1 [file] [log] [blame]
package org.apache.axis2.databinding.utils;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* 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.
*/
/**
* A state machine to read elements with simple content. Returns the text
* of the element and the stream reader will be one event beyond the
* end element at return
*/
public class SimpleElementReaderStateMachine implements States,Constants{
private QName elementNameToTest = null;
private int currentState = INIT_STATE;
private boolean nillable = false;
private String text="";
private String errorMessage = "";
private boolean elementSkipped = false;
public boolean isElementSkipped() {
return elementSkipped;
}
/**
*
*/
public String getText() {
return text;
}
/**
* sets the nillable flag
*/
public void setNillable(){
nillable = true;
}
/**
* the Qname of the element to be tested
* @param elementNameToTest
*/
public void setElementNameToTest(QName elementNameToTest) {
this.elementNameToTest = elementNameToTest;
}
/**
* Resets the state machine. Once the reset is called
* the state machine is good enough for a fresh run
*/
public void reset(){
elementNameToTest = null;
currentState = INIT_STATE;
nillable = false;
text="";
errorMessage = "";
}
/**
* public read method - reads a given reader to extract the text value
* @param reader
*/
public void read(XMLStreamReader reader) throws XMLStreamException {
do{
updateState(reader);
//test for the nillable attribute
if (currentState==START_ELEMENT_FOUND_STATE &&
nillable){
if (TRUE.equals(reader.getAttributeValue(XSI_NAMESPACE,NIL))){
text = null;
//force the state to be null found
currentState= NULLED_STATE;
}
}
if (currentState==TEXT_FOUND_STATE){
//read the text value and store it
text = reader.getText();
}
if (currentState!=FINISHED_STATE
&& currentState!= ILLEGAL_STATE){
reader.next();
}
}while(currentState!=FINISHED_STATE
&& currentState!= ILLEGAL_STATE);
if (currentState==ILLEGAL_STATE){
throw new RuntimeException("Illegal state!" + errorMessage);
}
}
/**
* Updates the state depending on the parser
* @param reader
*/
private void updateState(XMLStreamReader reader) throws XMLStreamException{
int event = reader.getEventType();
switch(currentState){
case INIT_STATE:
if (event==XMLStreamConstants.START_DOCUMENT){
currentState = STARTED_STATE;
//start element found at init
}else if (event==XMLStreamConstants.START_ELEMENT){
if (elementNameToTest.equals(reader.getName())){
currentState = START_ELEMENT_FOUND_STATE;
}else{
currentState = STARTED_STATE;
}
}else if (event==XMLStreamConstants.END_ELEMENT){
// an end element is found at the init state
// we should break the process here ?
currentState = FINISHED_STATE ;
elementSkipped = true;
}
break;
case STARTED_STATE:
if (event==XMLStreamConstants.START_ELEMENT ) {
if (elementNameToTest.equals(reader.getName())){
currentState = START_ELEMENT_FOUND_STATE;
}
}
break;
case START_ELEMENT_FOUND_STATE:
if (event==XMLStreamConstants.CHARACTERS){
currentState = TEXT_FOUND_STATE;
}else if (event==XMLStreamConstants.END_ELEMENT){
//force the text to be empty!
text = "";
if (elementNameToTest.equals(reader.getName())){
currentState = END_ELEMENT_FOUND_STATE;
}else{
currentState = ILLEGAL_STATE;
errorMessage = "Wrong element name " +reader.getName(); //todo I18n this
}
}
break;
case TEXT_FOUND_STATE:
if (event==XMLStreamConstants.END_ELEMENT){
if (elementNameToTest.equals(reader.getName())){
currentState = END_ELEMENT_FOUND_STATE;
}else{
currentState = ILLEGAL_STATE;
//set the error message
errorMessage = "Wrong element name " +reader.getName(); //todo I18n this
}
}else if (event==XMLStreamConstants.CHARACTERS){
text = text + reader.getText(); //append the text
//do not change the state
}
break;
case END_ELEMENT_FOUND_STATE:
currentState = FINISHED_STATE;
break;
//the element was found to be null and this state was forced.
//we are sure here that the parser was at the
//START_ELEMENT_FOUND_STATE before
//being forced. Hence we need to advance the parser upto the
// end element and set the state to be end element found
case NULLED_STATE:
while (event!= XMLStreamConstants.END_ELEMENT){
event=reader.next();
}
currentState = END_ELEMENT_FOUND_STATE;
break;
default:
if (event==XMLStreamConstants.CHARACTERS){
if (reader.getText().trim().length()==0){
//the text is empty - don't change the state
}else{
//we do NOT handle mixed content
currentState = ILLEGAL_STATE;
errorMessage = "Mixed Content " +reader.getText();
}
}else{
currentState = ILLEGAL_STATE;
errorMessage = "Current state is " + currentState ;
}
break;
}
}
}