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; | |
} | |
} | |
} |