001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */
019: package org.apache.axis2.databinding.utils;
020:
021: import javax.xml.namespace.QName;
022: import javax.xml.stream.XMLStreamConstants;
023: import javax.xml.stream.XMLStreamException;
024: import javax.xml.stream.XMLStreamReader;
025: import java.util.ArrayList;
026: import java.util.List;
027:
028: /** A state machine that reads arrays with simple content. returns a string array */
029: public class SimpleArrayReaderStateMachine implements States, Constants {
030:
031: private QName elementNameToTest = null;
032: private int currentState = INIT_STATE;
033: private boolean nillable = false;
034:
035: private boolean canbeAbsent = false;
036:
037: private List list = new ArrayList();
038:
039: /** @return an array of strings */
040: public String[] getTextArray() {
041: return (String[]) list.toArray(new String[list.size()]);
042: }
043:
044: public void setNillable() {
045: nillable = true;
046: }
047:
048: public boolean isCanbeAbsent() {
049: return canbeAbsent;
050: }
051:
052: public void setCanbeAbsent(boolean canbeAbsent) {
053: this .canbeAbsent = canbeAbsent;
054: }
055:
056: /**
057: * Resets the state machine. Once the reset is called the state machine is good enough for a
058: * fresh run
059: */
060: public void reset() {
061: elementNameToTest = null;
062: currentState = INIT_STATE;
063: nillable = false;
064: list = new ArrayList();
065: }
066:
067: public void setElementNameToTest(QName elementNameToTest) {
068: this .elementNameToTest = elementNameToTest;
069: }
070:
071: /**
072: * public read method - reads a given reader to extract the text value
073: *
074: * @param reader
075: */
076: public void read(XMLStreamReader reader) throws XMLStreamException {
077:
078: do {
079: updateState(reader);
080:
081: //test for the nillable attribute
082: if (currentState == START_ELEMENT_FOUND_STATE && nillable) {
083: if (TRUE.equals(reader.getAttributeValue(XSI_NAMESPACE,
084: NIL))) {
085: list.add(null);
086: //force the state to be null found
087: currentState = NULLED_STATE;
088: }
089: }
090:
091: if (currentState == TEXT_FOUND_STATE) {
092: //read the text value and store it in the list
093: list.add(reader.getText());
094: }
095: //increment the parser only if the state is
096: //not finished
097: if (currentState != FINISHED_STATE
098: && currentState != ILLEGAL_STATE) {
099: reader.next();
100: }
101:
102: } while (currentState != FINISHED_STATE
103: && currentState != ILLEGAL_STATE);
104:
105: if (currentState == ILLEGAL_STATE) {
106: throw new RuntimeException("Illegal state!");
107: }
108:
109: }
110:
111: private void updateState(XMLStreamReader reader)
112: throws XMLStreamException {
113: int event = reader.getEventType();
114:
115: switch (currentState) {
116:
117: case INIT_STATE:
118: if (event == XMLStreamConstants.START_DOCUMENT) {
119: currentState = STARTED_STATE;
120: } else if (event == XMLStreamConstants.START_ELEMENT) {
121: if (elementNameToTest.equals(reader.getName())) {
122: currentState = START_ELEMENT_FOUND_STATE;
123: } else {
124: //we found a start element that does not have
125: //the name of the element
126:
127: currentState = canbeAbsent ? FINISHED_STATE
128: : STARTED_STATE;
129: }
130: } else if (event == XMLStreamConstants.END_ELEMENT) {
131: // an end element is found at the init state
132: // we should break the process here ?
133: if (!elementNameToTest.equals(reader.getName())) {
134: currentState = FINISHED_STATE;
135: }
136: }
137: break;
138:
139: case STARTED_STATE:
140: if (event == XMLStreamConstants.END_ELEMENT) {
141: if (elementNameToTest.equals(reader.getName())) {
142: currentState = ILLEGAL_STATE;
143: } else {
144: currentState = FINISHED_STATE;
145: }
146: } else if (event == XMLStreamConstants.START_ELEMENT) {
147: QName name = reader.getName();
148: if (elementNameToTest.equals(name)) {
149: currentState = START_ELEMENT_FOUND_STATE;
150: }
151: }
152: break;
153:
154: case START_ELEMENT_FOUND_STATE:
155: if (event == XMLStreamConstants.CHARACTERS) {
156: currentState = TEXT_FOUND_STATE;
157: }
158: break;
159:
160: case TEXT_FOUND_STATE:
161: if (event == XMLStreamConstants.END_ELEMENT) {
162: if (elementNameToTest.equals(reader.getName())) {
163: currentState = END_ELEMENT_FOUND_STATE;
164: } else {
165: currentState = ILLEGAL_STATE;
166: }
167: } else if (event == XMLStreamConstants.CHARACTERS) {
168: //another char event -
169: //so append it to the current text
170: }
171: break;
172: case NULLED_STATE:
173: //read upto the end and set the state to END_ELEMENT_FOUND_STATE
174: while (event != XMLStreamConstants.END_ELEMENT) {
175: event = reader.next();
176: }
177: currentState = END_ELEMENT_FOUND_STATE;
178: break;
179: case END_ELEMENT_FOUND_STATE:
180: if (event == XMLStreamConstants.START_ELEMENT) {
181: //restart the parsing
182: if (elementNameToTest.equals(reader.getName())) {
183: currentState = START_ELEMENT_FOUND_STATE;
184: } else {
185: currentState = FINISHED_STATE;
186: }
187: //another end element found after end-element
188: } else if (event == XMLStreamConstants.END_ELEMENT) {
189: currentState = FINISHED_STATE;
190: //end document found
191: }
192: break;
193: default:
194:
195: //characters found - if this is a characters event that was in the correct place then
196: //it would have been handled already. we need to check whether this is a ignorable
197: //whitespace and if not push the state machine to a illegal state.
198: if (event == XMLStreamConstants.CHARACTERS) {
199: if (reader.getText().trim().length() == 0) {
200: //the text is empty - don't change the state
201: } else {
202: //we do NOT handle mixed content
203: currentState = ILLEGAL_STATE;
204: }
205:
206: } else {
207: currentState = ILLEGAL_STATE;
208: }
209:
210: }
211:
212: }
213:
214: }
|