blob: 6af8be3a42a34cf689d3817fd1bf80b622628c61 [file] [log] [blame]
Meki Cherkaouif441d3a2012-04-22 15:17:52 -07001//TODO INCOMPLETE
2
3/*
4 * @author: ucla-cs
5 *
6 * Decodes CCN object into xml
7 */
8
9var TextXMLDecoder = function TextXMLDecoder(){
10
11 this.reader = null;
12
13};
14
15
16exports.TextXMLDecoder = TextXMLDecoder;
17
18
19exports.prototype.initializeDecoding = function(){
20 try {
21 XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
22 factory.setNamespaceAware(true);
23 _reader = factory.newPullParser();
24 _reader.setInput(_istream, null);
25 } catch (XmlPullParserException e) {
26 throw new ContentDecodingException(e.getMessage(), e);
27 }
28};
29
30exports.prototype.readStartDocument = function(){
31 try {
32 int event = _reader.getEventType();
33 _reader.next();
34 if (event != XmlPullParser.START_DOCUMENT) {
35 throw new ContentDecodingException("Expected start document, got: " + XmlPullParser.TYPES[event]);
36 }
37 } catch (XmlPullParserException e) {
38 throw new ContentDecodingException(e.getMessage(), e);
39 } catch (IOException e) {
40 throw new ContentDecodingException(e.getMessage(), e);
41 }
42};
43
44public void readEndDocument() throws ContentDecodingException {
45 int event;
46 try {
47 event = _reader.getEventType();
48 } catch (XmlPullParserException e) {
49 throw new ContentDecodingException(e.getMessage(), e);
50 }
51 if (event != XmlPullParser.END_DOCUMENT) {
52 throw new ContentDecodingException("Expected end document, got: " + XmlPullParser.TYPES[event]);
53 }
54};
55
56exports.prototype.readStartElement = function(/*String*/ startTag,
57 TreeMap<String, String> attributes) throws ContentDecodingException {
58
59 int event = readToNextTag(XmlPullParser.START_TAG);
60 if (event != XmlPullParser.START_TAG) {
61 throw new ContentDecodingException("Expected start element, got: " + XmlPullParser.TYPES[event]);
62 }
63 // Use getLocalPart to strip namespaces.
64 // Assumes we are working with a global default namespace of CCN.
65 if (!startTag.equals(_reader.getName())) {
66 // Coming back with namespace decoration doesn't match
67 throw new ContentDecodingException("Expected start element: " + startTag + " got: " + _reader.getName());
68 }
69 if (null != attributes) {
70 // we might be expecting attributes
71 for (int i=0; i < _reader.getAttributeCount(); ++i) {
72 // may need fancier namespace handling.
73 attributes.put(_reader.getAttributeName(i), _reader.getAttributeValue(i));
74 }
75 }
76 try {
77 _reader.next();
78 } catch (XmlPullParserException e) {
79 throw new ContentDecodingException(e.getMessage());
80 } catch (IOException e) {
81 throw new ContentDecodingException(e.getMessage());
82 }
83}
84
85 public void readStartElement(long startTagLong,
86 TreeMap<String, String> attributes) throws ContentDecodingException {
87
88 String startTag = tagToString(startTagLong);
89
90 int event = readToNextTag(XmlPullParser.START_TAG);
91 if (event != XmlPullParser.START_TAG) {
92 throw new ContentDecodingException("Expected start element, got: " + XmlPullParser.TYPES[event]);
93 }
94 // Use getLocalPart to strip namespaces.
95 // Assumes we are working with a global default namespace of CCN.
96 if (!startTag.equals(_reader.getName())) {
97 // Coming back with namespace decoration doesn't match
98 throw new ContentDecodingException("Expected start element: " + startTag + " got: " + _reader.getName());
99 }
100 if (null != attributes) {
101 // we might be expecting attributes
102 for (int i=0; i < _reader.getAttributeCount(); ++i) {
103 // may need fancier namespace handling.
104 attributes.put(_reader.getAttributeName(i), _reader.getAttributeValue(i));
105 }
106 }
107 try {
108 _reader.next();
109 } catch (XmlPullParserException e) {
110 throw new ContentDecodingException(e.getMessage());
111 } catch (IOException e) {
112 throw new ContentDecodingException(e.getMessage());
113 }
114 }
115 public String peekStartElementAsString() throws ContentDecodingException {
116 int event = readToNextTag(XmlPullParser.START_TAG);
117 if (event != XmlPullParser.START_TAG) {
118 return null;
119 }
120 return _reader.getName();
121 }
122
123 public Long peekStartElementAsLong() throws ContentDecodingException {
124 String strTag = peekStartElementAsString();
125 if (null == strTag) {
126 return null; // e.g. hit an end tag...
127 }
128 return stringToTag(strTag);
129 }
130
131 /**
132 * Helper method to decode text (UTF-8) and binary elements. Consumes the end element,
133 * behavior which other decoders are forced to match.
134 * @return the read data, as a String
135 * @throws ContentDecodingException if there is a problem decoding the data
136 */
137 public String readUString() throws ContentDecodingException {
138 StringBuffer buf = new StringBuffer();
139 try {
140 int event = _reader.getEventType();;
141 // Handles empty text element.
142 while (event == XmlPullParser.TEXT) {
143 buf.append(_reader.getText());
144 event = _reader.next();
145 }
146 if (event == XmlPullParser.START_TAG) {
147 throw new ContentDecodingException("readElementText expects start element to have been previously consumed, got: " + XmlPullParser.TYPES[event]);
148 } else if (event != XmlPullParser.END_TAG) {
149 throw new ContentDecodingException("Expected end of text element, got: " + XmlPullParser.TYPES[event]);
150 }
151 readEndElement();
152 return buf.toString();
153 } catch (XmlPullParserException e) {
154 throw new ContentDecodingException(e.getMessage(), e);
155 } catch (IOException e) {
156 throw new ContentDecodingException(e.getMessage(), e);
157 }
158 }
159
160 public void readEndElement() throws ContentDecodingException {
161 int event = readToNextTag(XmlPullParser.END_TAG);
162 if (event != XmlPullParser.END_TAG) {
163 throw new ContentDecodingException("Expected end element, got: " + XmlPullParser.TYPES[event]);
164 }
165 try {
166 _reader.next();
167 } catch (XmlPullParserException e) {
168 throw new ContentDecodingException(e.getMessage());
169 } catch (IOException e) {
170 throw new ContentDecodingException(e.getMessage());
171 }
172 }
173
174 /**
175 * Read a BLOB. Consumes the end element, so force other versions
176 * to match.
177 */
178 public byte [] readBlob() throws ContentDecodingException {
179 try {
180 String strElementText = readUString();
181 // readEndElement(); // readElementText consumes end element
182 return TextXMLCodec.decodeBinaryElement(strElementText);
183 } catch (IOException e) {
184 throw new ContentDecodingException(e.getMessage(),e);
185 }
186 }
187
188 public CCNTime readDateTime(String startTag) throws ContentDecodingException {
189 String strTimestamp = readUTF8Element(startTag);
190 CCNTime timestamp;
191 try {
192 timestamp = TextXMLCodec.parseDateTime(strTimestamp);
193 } catch (ParseException e) {
194 timestamp = null;
195 }
196 if (null == timestamp) {
197 throw new ContentDecodingException("Cannot parse timestamp: " + strTimestamp);
198 }
199 return timestamp;
200 }
201
202 public CCNTime readDateTime(long startTag) throws ContentDecodingException {
203 String strTimestamp = readUTF8Element(startTag);
204 CCNTime timestamp;
205 try {
206 timestamp = TextXMLCodec.parseDateTime(strTimestamp);
207 } catch (ParseException e) {
208 timestamp = null;
209 }
210 if (null == timestamp) {
211 throw new ContentDecodingException("Cannot parse timestamp: " + strTimestamp);
212 }
213 return timestamp;
214 }
215
216 private int readToNextTag(int type) throws ContentDecodingException {
217 int event;
218 try {
219 event = _reader.getEventType();
220 if (event == type)
221 return event;
222 if (event == XmlPullParser.TEXT || event == XmlPullParser.COMMENT)
223 event = _reader.next();
224 } catch (IOException e) {
225 throw new ContentDecodingException(e.getMessage(), e);
226 } catch (XmlPullParserException e) {
227 throw new ContentDecodingException(e.getMessage(), e);
228 }
229 return event;
230 }
231
232};