1 package org.codehaus.xfire.aegis.stax;
2
3 import java.io.InputStream;
4
5 import javax.xml.namespace.QName;
6 import javax.xml.stream.XMLInputFactory;
7 import javax.xml.stream.XMLStreamException;
8 import javax.xml.stream.XMLStreamReader;
9
10 import org.codehaus.xfire.XFireRuntimeException;
11 import org.codehaus.xfire.aegis.AbstractMessageReader;
12 import org.codehaus.xfire.aegis.MessageReader;
13 import org.codehaus.xfire.util.DepthXMLStreamReader;
14
15 /***
16 * Reads literal encoded messages.
17 *
18 * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
19 */
20 public class ElementReader
21 extends AbstractMessageReader
22 implements MessageReader
23 {
24 private DepthXMLStreamReader root;
25 private StringBuffer value;
26 private String localName;
27 private QName name;
28 private boolean hasCheckedChildren = false;
29 private boolean hasChildren = false;
30 private boolean hasFoundText = false;
31 private String namespace;
32 private int depth;
33 private int currentAttribute = 0;
34
35 /***
36 * Expects the XMLStreamReader in the START_DOCUMENT event.
37 * @param root
38 */
39 public ElementReader(DepthXMLStreamReader root)
40 {
41 this.root = root;
42 this.localName = root.getLocalName();
43 this.name = root.getName();
44 this.namespace = root.getNamespaceURI();
45
46 depth = root.getDepth();
47 }
48
49 public ElementReader(XMLStreamReader reader)
50 {
51 this.root = new DepthXMLStreamReader(reader);
52 this.localName = root.getLocalName();
53 this.name = root.getName();
54 this.namespace = root.getNamespaceURI();
55
56 depth = root.getDepth();
57 }
58
59 /***
60 * @param resourceAsStream
61 * @throws XMLStreamException
62 */
63 public ElementReader(InputStream is)
64 throws XMLStreamException
65 {
66 XMLInputFactory factory = XMLInputFactory.newInstance();
67 XMLStreamReader xmlReader = factory.createXMLStreamReader(is);
68
69 while ( xmlReader.getEventType() != XMLStreamReader.START_ELEMENT )
70 xmlReader.next();
71
72 this.root = new DepthXMLStreamReader(xmlReader);
73 this.localName = root.getLocalName();
74 this.name = root.getName();
75 this.namespace = root.getNamespaceURI();
76
77 depth = root.getDepth();
78 }
79
80 /***
81 * @see org.codehaus.xfire.aegis.MessageReader#getValue()
82 */
83 public String getValue()
84 {
85 while( !hasFoundText && checkHasMoreChildReaders() )
86 {
87 }
88
89 if (value == null)
90 return null;
91
92 return value.toString().trim();
93 }
94
95 public String getValue( String ns, String attr )
96 {
97 return root.getAttributeValue(ns, attr);
98 }
99
100 public boolean hasMoreElementReaders()
101 {
102
103
104 if ( !hasCheckedChildren )
105 checkHasMoreChildReaders();
106
107 return hasChildren;
108 }
109
110 private boolean checkHasMoreChildReaders()
111 {
112 try
113 {
114 int event = root.getEventType();
115 while ( true )
116 {
117 switch( event )
118 {
119 case XMLStreamReader.START_ELEMENT:
120 if ( root.getDepth() > depth )
121 {
122 hasCheckedChildren = true;
123 hasChildren = true;
124 return true;
125 }
126 break;
127 case XMLStreamReader.END_ELEMENT:
128 if ( root.getDepth() <= depth )
129 {
130 hasCheckedChildren = true;
131 hasChildren = false;
132 root.next();
133 return false;
134 }
135 break;
136 case XMLStreamReader.CHARACTERS:
137 if (value == null)
138 value = new StringBuffer();
139
140 value.append(root.getText());
141 hasFoundText = true;
142 break;
143 case XMLStreamReader.END_DOCUMENT:
144
145 hasCheckedChildren = true;
146 hasChildren = false;
147 return false;
148 default:
149 break;
150 }
151 event = root.next();
152 }
153 }
154 catch (XMLStreamException e)
155 {
156 throw new XFireRuntimeException("Error parsing document.", e);
157 }
158 }
159
160 public MessageReader getNextElementReader()
161 {
162 if ( !hasCheckedChildren )
163 checkHasMoreChildReaders();
164
165 if ( !hasChildren )
166 return null;
167
168 hasCheckedChildren = false;
169
170 return new ElementReader( root );
171 }
172
173 public QName getName()
174 {
175 return name;
176 }
177
178 public String getLocalName()
179 {
180 return localName;
181 }
182
183 public String getNamespace()
184 {
185 return namespace;
186 }
187
188 public XMLStreamReader getXMLStreamReader()
189 {
190 return root;
191 }
192
193 public boolean hasMoreAttributeReaders()
194 {
195 return currentAttribute < root.getAttributeCount();
196 }
197
198 public MessageReader getNextAttributeReader()
199 {
200 MessageReader reader = new AttributeReader(root.getAttributeName(currentAttribute),
201 root.getAttributeValue(currentAttribute));
202 currentAttribute++;
203
204 return reader;
205 }
206 }