blob: 7a303e591f51db138b5bfd6923650ba852111c09 [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;
import java.util.ArrayList;
import java.util.List;
/*
* 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 that reads arrays with simple content. returns a string array
*/
public class SimpleArrayReaderStateMachine implements States,Constants {
private QName elementNameToTest = null;
private int currentState = INIT_STATE;
private boolean nillable = false;
private boolean canbeAbsent = false;
private List list = new ArrayList();
/**
* @return an array of strings
*/
public String[] getTextArray() {
return (String[])list.toArray(new String[list.size()]);
}
public void setNillable(){
nillable = true;
}
public boolean isCanbeAbsent() {
return canbeAbsent;
}
public void setCanbeAbsent(boolean canbeAbsent) {
this.canbeAbsent = canbeAbsent;
}
/**
* 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;
list=new ArrayList();
}
public void setElementNameToTest(QName elementNameToTest) {
this.elementNameToTest = elementNameToTest;
}
/**
* 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))){
list.add(null);
//force the state to be null found
currentState= NULLED_STATE;
}
}
if (currentState==TEXT_FOUND_STATE){
//read the text value and store it in the list
list.add(reader.getText());
}
//increment the parser only if the state is
//not finished
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!");
}
}
private void updateState(XMLStreamReader reader) throws XMLStreamException{
int event = reader.getEventType();
switch (currentState){
case INIT_STATE:
if (event== XMLStreamConstants.START_DOCUMENT){
currentState = STARTED_STATE;
}else if (event== XMLStreamConstants.START_ELEMENT){
if (elementNameToTest.equals(reader.getName())){
currentState = START_ELEMENT_FOUND_STATE;
}else{
//we found a start element that does not have
//the name of the element
currentState = canbeAbsent?
FINISHED_STATE:
STARTED_STATE;
}
}else if (event==XMLStreamConstants.END_ELEMENT){
// an end element is found at the init state
// we should break the process here ?
if (!elementNameToTest.equals(reader.getName())){
currentState = FINISHED_STATE ;
}
}
break;
case STARTED_STATE:
if (event==XMLStreamConstants.END_ELEMENT){
if (elementNameToTest.equals(reader.getName())){
currentState = ILLEGAL_STATE;
}else{
currentState = FINISHED_STATE;
}
}else if (event==XMLStreamConstants.START_ELEMENT){
QName name = reader.getName();
if (elementNameToTest.equals(name)){
currentState = START_ELEMENT_FOUND_STATE;
}
}
break;
case START_ELEMENT_FOUND_STATE:
if (event==XMLStreamConstants.CHARACTERS){
currentState = TEXT_FOUND_STATE;
}
break;
case TEXT_FOUND_STATE:
if (event==XMLStreamConstants.END_ELEMENT){
if (elementNameToTest.equals(reader.getName())){
currentState = END_ELEMENT_FOUND_STATE;
}else{
currentState = ILLEGAL_STATE;
}
}else if (event==XMLStreamConstants.CHARACTERS){
//another char event -
//so append it to the current text
}
break;
case NULLED_STATE:
//read upto the end and set the state to END_ELEMENT_FOUND_STATE
while (event!= XMLStreamConstants.END_ELEMENT){
event=reader.next();
}
currentState = END_ELEMENT_FOUND_STATE;
break;
case END_ELEMENT_FOUND_STATE:
if (event==XMLStreamConstants.START_ELEMENT ) {
//restart the parsing
if (elementNameToTest.equals(reader.getName())){
currentState = START_ELEMENT_FOUND_STATE;
}else{
currentState = FINISHED_STATE;
}
//another end element found after end-element
}else if (event==XMLStreamConstants.END_ELEMENT ) {
currentState = FINISHED_STATE;
//end document found
}
break;
default:
//characters found - if this is a characters event that was in the correct place then
//it would have been handled already. we need to check whether this is a ignorable
//whitespace and if not push the state machine to a illegal state.
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;
}
} else{
currentState = ILLEGAL_STATE;
}
}
}
}