| //TODO INCOMPLETE |
| |
| /* |
| * @author: ucla-cs |
| * |
| * Decodes CCN object into xml |
| */ |
| |
| var TextXMLDecoder = function TextXMLDecoder(){ |
| |
| this.reader = null; |
| |
| }; |
| |
| |
| exports.TextXMLDecoder = TextXMLDecoder; |
| |
| |
| exports.prototype.initializeDecoding = function(){ |
| try { |
| XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); |
| factory.setNamespaceAware(true); |
| _reader = factory.newPullParser(); |
| _reader.setInput(_istream, null); |
| } catch (XmlPullParserException e) { |
| throw new ContentDecodingException(e.getMessage(), e); |
| } |
| }; |
| |
| exports.prototype.readStartDocument = function(){ |
| try { |
| int event = _reader.getEventType(); |
| _reader.next(); |
| if (event != XmlPullParser.START_DOCUMENT) { |
| throw new ContentDecodingException("Expected start document, got: " + XmlPullParser.TYPES[event]); |
| } |
| } catch (XmlPullParserException e) { |
| throw new ContentDecodingException(e.getMessage(), e); |
| } catch (IOException e) { |
| throw new ContentDecodingException(e.getMessage(), e); |
| } |
| }; |
| |
| public void readEndDocument() throws ContentDecodingException { |
| int event; |
| try { |
| event = _reader.getEventType(); |
| } catch (XmlPullParserException e) { |
| throw new ContentDecodingException(e.getMessage(), e); |
| } |
| if (event != XmlPullParser.END_DOCUMENT) { |
| throw new ContentDecodingException("Expected end document, got: " + XmlPullParser.TYPES[event]); |
| } |
| }; |
| |
| exports.prototype.readStartElement = function(/*String*/ startTag, |
| TreeMap<String, String> attributes) throws ContentDecodingException { |
| |
| int event = readToNextTag(XmlPullParser.START_TAG); |
| if (event != XmlPullParser.START_TAG) { |
| throw new ContentDecodingException("Expected start element, got: " + XmlPullParser.TYPES[event]); |
| } |
| // Use getLocalPart to strip namespaces. |
| // Assumes we are working with a global default namespace of CCN. |
| if (!startTag.equals(_reader.getName())) { |
| // Coming back with namespace decoration doesn't match |
| throw new ContentDecodingException("Expected start element: " + startTag + " got: " + _reader.getName()); |
| } |
| if (null != attributes) { |
| // we might be expecting attributes |
| for (int i=0; i < _reader.getAttributeCount(); ++i) { |
| // may need fancier namespace handling. |
| attributes.put(_reader.getAttributeName(i), _reader.getAttributeValue(i)); |
| } |
| } |
| try { |
| _reader.next(); |
| } catch (XmlPullParserException e) { |
| throw new ContentDecodingException(e.getMessage()); |
| } catch (IOException e) { |
| throw new ContentDecodingException(e.getMessage()); |
| } |
| } |
| |
| public void readStartElement(long startTagLong, |
| TreeMap<String, String> attributes) throws ContentDecodingException { |
| |
| String startTag = tagToString(startTagLong); |
| |
| int event = readToNextTag(XmlPullParser.START_TAG); |
| if (event != XmlPullParser.START_TAG) { |
| throw new ContentDecodingException("Expected start element, got: " + XmlPullParser.TYPES[event]); |
| } |
| // Use getLocalPart to strip namespaces. |
| // Assumes we are working with a global default namespace of CCN. |
| if (!startTag.equals(_reader.getName())) { |
| // Coming back with namespace decoration doesn't match |
| throw new ContentDecodingException("Expected start element: " + startTag + " got: " + _reader.getName()); |
| } |
| if (null != attributes) { |
| // we might be expecting attributes |
| for (int i=0; i < _reader.getAttributeCount(); ++i) { |
| // may need fancier namespace handling. |
| attributes.put(_reader.getAttributeName(i), _reader.getAttributeValue(i)); |
| } |
| } |
| try { |
| _reader.next(); |
| } catch (XmlPullParserException e) { |
| throw new ContentDecodingException(e.getMessage()); |
| } catch (IOException e) { |
| throw new ContentDecodingException(e.getMessage()); |
| } |
| } |
| public String peekStartElementAsString() throws ContentDecodingException { |
| int event = readToNextTag(XmlPullParser.START_TAG); |
| if (event != XmlPullParser.START_TAG) { |
| return null; |
| } |
| return _reader.getName(); |
| } |
| |
| public Long peekStartElementAsLong() throws ContentDecodingException { |
| String strTag = peekStartElementAsString(); |
| if (null == strTag) { |
| return null; // e.g. hit an end tag... |
| } |
| return stringToTag(strTag); |
| } |
| |
| /** |
| * Helper method to decode text (UTF-8) and binary elements. Consumes the end element, |
| * behavior which other decoders are forced to match. |
| * @return the read data, as a String |
| * @throws ContentDecodingException if there is a problem decoding the data |
| */ |
| public String readUString() throws ContentDecodingException { |
| StringBuffer buf = new StringBuffer(); |
| try { |
| int event = _reader.getEventType();; |
| // Handles empty text element. |
| while (event == XmlPullParser.TEXT) { |
| buf.append(_reader.getText()); |
| event = _reader.next(); |
| } |
| if (event == XmlPullParser.START_TAG) { |
| throw new ContentDecodingException("readElementText expects start element to have been previously consumed, got: " + XmlPullParser.TYPES[event]); |
| } else if (event != XmlPullParser.END_TAG) { |
| throw new ContentDecodingException("Expected end of text element, got: " + XmlPullParser.TYPES[event]); |
| } |
| readEndElement(); |
| return buf.toString(); |
| } catch (XmlPullParserException e) { |
| throw new ContentDecodingException(e.getMessage(), e); |
| } catch (IOException e) { |
| throw new ContentDecodingException(e.getMessage(), e); |
| } |
| } |
| |
| public void readEndElement() throws ContentDecodingException { |
| int event = readToNextTag(XmlPullParser.END_TAG); |
| if (event != XmlPullParser.END_TAG) { |
| throw new ContentDecodingException("Expected end element, got: " + XmlPullParser.TYPES[event]); |
| } |
| try { |
| _reader.next(); |
| } catch (XmlPullParserException e) { |
| throw new ContentDecodingException(e.getMessage()); |
| } catch (IOException e) { |
| throw new ContentDecodingException(e.getMessage()); |
| } |
| } |
| |
| /** |
| * Read a BLOB. Consumes the end element, so force other versions |
| * to match. |
| */ |
| public byte [] readBlob() throws ContentDecodingException { |
| try { |
| String strElementText = readUString(); |
| // readEndElement(); // readElementText consumes end element |
| return TextXMLCodec.decodeBinaryElement(strElementText); |
| } catch (IOException e) { |
| throw new ContentDecodingException(e.getMessage(),e); |
| } |
| } |
| |
| public CCNTime readDateTime(String startTag) throws ContentDecodingException { |
| String strTimestamp = readUTF8Element(startTag); |
| CCNTime timestamp; |
| try { |
| timestamp = TextXMLCodec.parseDateTime(strTimestamp); |
| } catch (ParseException e) { |
| timestamp = null; |
| } |
| if (null == timestamp) { |
| throw new ContentDecodingException("Cannot parse timestamp: " + strTimestamp); |
| } |
| return timestamp; |
| } |
| |
| public CCNTime readDateTime(long startTag) throws ContentDecodingException { |
| String strTimestamp = readUTF8Element(startTag); |
| CCNTime timestamp; |
| try { |
| timestamp = TextXMLCodec.parseDateTime(strTimestamp); |
| } catch (ParseException e) { |
| timestamp = null; |
| } |
| if (null == timestamp) { |
| throw new ContentDecodingException("Cannot parse timestamp: " + strTimestamp); |
| } |
| return timestamp; |
| } |
| |
| private int readToNextTag(int type) throws ContentDecodingException { |
| int event; |
| try { |
| event = _reader.getEventType(); |
| if (event == type) |
| return event; |
| if (event == XmlPullParser.TEXT || event == XmlPullParser.COMMENT) |
| event = _reader.next(); |
| } catch (IOException e) { |
| throw new ContentDecodingException(e.getMessage(), e); |
| } catch (XmlPullParserException e) { |
| throw new ContentDecodingException(e.getMessage(), e); |
| } |
| return event; |
| } |
| |
| }; |