summaryrefslogtreecommitdiffstats
path: root/xml/src/main/java/org/kxml2
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commitfdb2704414a9ed92394ada0d1395e4db86889465 (patch)
tree9b591a4a50054274a197f02b3ccb51313681879f /xml/src/main/java/org/kxml2
downloadlibcore-fdb2704414a9ed92394ada0d1395e4db86889465.zip
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.gz
libcore-fdb2704414a9ed92394ada0d1395e4db86889465.tar.bz2
Initial Contribution
Diffstat (limited to 'xml/src/main/java/org/kxml2')
-rw-r--r--xml/src/main/java/org/kxml2/io/KXmlParser.java1438
-rw-r--r--xml/src/main/java/org/kxml2/io/KXmlSerializer.java562
-rw-r--r--xml/src/main/java/org/kxml2/kdom/Document.java129
-rw-r--r--xml/src/main/java/org/kxml2/kdom/Element.java336
-rw-r--r--xml/src/main/java/org/kxml2/kdom/Node.java366
-rw-r--r--xml/src/main/java/org/kxml2/wap/Wbxml.java49
-rw-r--r--xml/src/main/java/org/kxml2/wap/WbxmlParser.java1050
-rw-r--r--xml/src/main/java/org/kxml2/wap/WbxmlSerializer.java418
-rw-r--r--xml/src/main/java/org/kxml2/wap/syncml/SyncML.java192
-rw-r--r--xml/src/main/java/org/kxml2/wap/wml/Wml.java233
-rw-r--r--xml/src/main/java/org/kxml2/wap/wv/WV.java593
11 files changed, 5366 insertions, 0 deletions
diff --git a/xml/src/main/java/org/kxml2/io/KXmlParser.java b/xml/src/main/java/org/kxml2/io/KXmlParser.java
new file mode 100644
index 0000000..8125745
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/io/KXmlParser.java
@@ -0,0 +1,1438 @@
+/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+// Contributors: Paul Hackenberger (unterminated entity handling in relaxed mode)
+
+package org.kxml2.io;
+
+import java.io.*;
+import java.util.*;
+
+import org.xmlpull.v1.*;
+
+/** A simple, pull based XML parser. This classe replaces the kXML 1
+ XmlParser class and the corresponding event classes. */
+
+public class KXmlParser implements XmlPullParser {
+
+ private Object location;
+ static final private String UNEXPECTED_EOF = "Unexpected EOF";
+ static final private String ILLEGAL_TYPE = "Wrong event type";
+ static final private int LEGACY = 999;
+ static final private int XML_DECL = 998;
+
+ // general
+
+ private String version;
+ private Boolean standalone;
+
+ private boolean processNsp;
+ private boolean relaxed;
+ private HashMap entityMap;
+ private int depth;
+ private String[] elementStack = new String[16];
+ private String[] nspStack = new String[8];
+ private int[] nspCounts = new int[4];
+
+ // source
+
+ private Reader reader;
+ private String encoding;
+ private char[] srcBuf;
+
+ private int srcPos;
+ private int srcCount;
+
+ private int line;
+ private int column;
+
+ // txtbuffer
+
+ private char[] txtBuf = new char[128];
+ private int txtPos;
+
+ // Event-related
+
+ private int type;
+ //private String text;
+ private boolean isWhitespace;
+ private String namespace;
+ private String prefix;
+ private String name;
+
+ private boolean degenerated;
+ private int attributeCount;
+ private String[] attributes = new String[16];
+ private int stackMismatch = 0;
+ private String error;
+
+ /**
+ * A separate peek buffer seems simpler than managing
+ * wrap around in the first level read buffer */
+
+ private int[] peek = new int[2];
+ private int peekCount;
+ private boolean wasCR;
+
+ private boolean unresolved;
+ private boolean token;
+
+ public KXmlParser() {
+// srcBuf = new char[Runtime.getRuntime().freeMemory() >= 1048576 ? 8192 : 128];
+
+ // XXX: We don't have a Runtime class at this time.
+ srcBuf = new char[8192];
+ }
+
+ private final boolean isProp(String n1, boolean prop, String n2) {
+ if (!n1.startsWith("http://xmlpull.org/v1/doc/"))
+ return false;
+ if (prop)
+ return n1.substring(42).equals(n2);
+ else
+ return n1.substring(40).equals(n2);
+ }
+
+ private final boolean adjustNsp() throws XmlPullParserException {
+
+ boolean any = false;
+
+ for (int i = 0; i < attributeCount << 2; i += 4) {
+ // * 4 - 4; i >= 0; i -= 4) {
+
+ String attrName = attributes[i + 2];
+ int cut = attrName.indexOf(':');
+ String prefix;
+
+ if (cut != -1) {
+ prefix = attrName.substring(0, cut);
+ attrName = attrName.substring(cut + 1);
+ }
+ else if (attrName.equals("xmlns")) {
+ prefix = attrName;
+ attrName = null;
+ }
+ else
+ continue;
+
+ if (!prefix.equals("xmlns")) {
+ any = true;
+ }
+ else {
+ int j = (nspCounts[depth]++) << 1;
+
+ nspStack = ensureCapacity(nspStack, j + 2);
+ nspStack[j] = attrName;
+ nspStack[j + 1] = attributes[i + 3];
+
+ if (attrName != null && attributes[i + 3].equals(""))
+ error("illegal empty namespace");
+
+ // prefixMap = new PrefixMap (prefixMap, attrName, attr.getValue ());
+
+ //System.out.println (prefixMap);
+
+ System.arraycopy(
+ attributes,
+ i + 4,
+ attributes,
+ i,
+ ((--attributeCount) << 2) - i);
+
+ i -= 4;
+ }
+ }
+
+ if (any) {
+ for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4) {
+
+ String attrName = attributes[i + 2];
+ int cut = attrName.indexOf(':');
+
+ if (cut == 0 && !relaxed)
+ throw new RuntimeException(
+ "illegal attribute name: " + attrName + " at " + this);
+
+ else if (cut != -1) {
+ String attrPrefix = attrName.substring(0, cut);
+
+ attrName = attrName.substring(cut + 1);
+
+ String attrNs = getNamespace(attrPrefix);
+
+ if (attrNs == null && !relaxed)
+ throw new RuntimeException(
+ "Undefined Prefix: " + attrPrefix + " in " + this);
+
+ attributes[i] = attrNs;
+ attributes[i + 1] = attrPrefix;
+ attributes[i + 2] = attrName;
+
+ /*
+ if (!relaxed) {
+ for (int j = (attributeCount << 2) - 4; j > i; j -= 4)
+ if (attrName.equals(attributes[j + 2])
+ && attrNs.equals(attributes[j]))
+ exception(
+ "Duplicate Attribute: {"
+ + attrNs
+ + "}"
+ + attrName);
+ }
+ */
+ }
+ }
+ }
+
+ int cut = name.indexOf(':');
+
+ if (cut == 0)
+ error("illegal tag name: " + name);
+
+ if (cut != -1) {
+ prefix = name.substring(0, cut);
+ name = name.substring(cut + 1);
+ }
+
+ this.namespace = getNamespace(prefix);
+
+ if (this.namespace == null) {
+ if (prefix != null)
+ error("undefined prefix: " + prefix);
+ this.namespace = NO_NAMESPACE;
+ }
+
+ return any;
+ }
+
+ private final String[] ensureCapacity(String[] arr, int required) {
+ if (arr.length >= required)
+ return arr;
+ String[] bigger = new String[required + 16];
+ System.arraycopy(arr, 0, bigger, 0, arr.length);
+ return bigger;
+ }
+
+ private final void error(String desc) throws XmlPullParserException {
+ if (relaxed) {
+ if (error == null)
+ error = "ERR: " + desc;
+ }
+ else
+ exception(desc);
+ }
+
+ private final void exception(String desc) throws XmlPullParserException {
+ throw new XmlPullParserException(
+ desc.length() < 100 ? desc : desc.substring(0, 100) + "\n",
+ this,
+ null);
+ }
+
+ /**
+ * common base for next and nextToken. Clears the state, except from
+ * txtPos and whitespace. Does not set the type variable */
+
+ private final void nextImpl() throws IOException, XmlPullParserException {
+
+ if (reader == null)
+ exception("No Input specified");
+
+ if (type == END_TAG)
+ depth--;
+
+ while (true) {
+ attributeCount = -1;
+
+ // degenerated needs to be handled before error because of possible
+ // processor expectations(!)
+
+ if (degenerated) {
+ degenerated = false;
+ type = END_TAG;
+ return;
+ }
+
+
+ if (error != null) {
+ for (int i = 0; i < error.length(); i++)
+ push(error.charAt(i));
+ // text = error;
+ error = null;
+ type = COMMENT;
+ return;
+ }
+
+
+ if (relaxed
+ && (stackMismatch > 0 || (peek(0) == -1 && depth > 0))) {
+ int sp = (depth - 1) << 2;
+ type = END_TAG;
+ namespace = elementStack[sp];
+ prefix = elementStack[sp + 1];
+ name = elementStack[sp + 2];
+ if (stackMismatch != 1)
+ error = "missing end tag /" + name + " inserted";
+ if (stackMismatch > 0)
+ stackMismatch--;
+ return;
+ }
+
+ prefix = null;
+ name = null;
+ namespace = null;
+ // text = null;
+
+ type = peekType();
+
+ switch (type) {
+
+ case ENTITY_REF :
+ pushEntity();
+ return;
+
+ case START_TAG :
+ parseStartTag(false);
+ return;
+
+ case END_TAG :
+ parseEndTag();
+ return;
+
+ case END_DOCUMENT :
+ return;
+
+ case TEXT :
+ pushText('<', !token);
+ if (depth == 0) {
+ if (isWhitespace)
+ type = IGNORABLE_WHITESPACE;
+ // make exception switchable for instances.chg... !!!!
+ // else
+ // exception ("text '"+getText ()+"' not allowed outside root element");
+ }
+ return;
+
+ default :
+ type = parseLegacy(token);
+ if (type != XML_DECL)
+ return;
+ }
+ }
+ }
+
+ private final int parseLegacy(boolean push)
+ throws IOException, XmlPullParserException {
+
+ String req = "";
+ int term;
+ int result;
+ int prev = 0;
+
+ read(); // <
+ int c = read();
+
+ if (c == '?') {
+ if ((peek(0) == 'x' || peek(0) == 'X')
+ && (peek(1) == 'm' || peek(1) == 'M')) {
+
+ if (push) {
+ push(peek(0));
+ push(peek(1));
+ }
+ read();
+ read();
+
+ if ((peek(0) == 'l' || peek(0) == 'L') && peek(1) <= ' ') {
+
+ if (line != 1 || column > 4)
+ error("PI must not start with xml");
+
+ parseStartTag(true);
+
+ if (attributeCount < 1 || !"version".equals(attributes[2]))
+ error("version expected");
+
+ version = attributes[3];
+
+ int pos = 1;
+
+ if (pos < attributeCount
+ && "encoding".equals(attributes[2 + 4])) {
+ encoding = attributes[3 + 4];
+ pos++;
+ }
+
+ if (pos < attributeCount
+ && "standalone".equals(attributes[4 * pos + 2])) {
+ String st = attributes[3 + 4 * pos];
+ if ("yes".equals(st))
+ standalone = new Boolean(true);
+ else if ("no".equals(st))
+ standalone = new Boolean(false);
+ else
+ error("illegal standalone value: " + st);
+ pos++;
+ }
+
+ if (pos != attributeCount)
+ error("illegal xmldecl");
+
+ isWhitespace = true;
+ txtPos = 0;
+
+ return XML_DECL;
+ }
+ }
+
+ /* int c0 = read ();
+ int c1 = read ();
+ int */
+
+ term = '?';
+ result = PROCESSING_INSTRUCTION;
+ }
+ else if (c == '!') {
+ if (peek(0) == '-') {
+ result = COMMENT;
+ req = "--";
+ term = '-';
+ }
+ else if (peek(0) == '[') {
+ result = CDSECT;
+ req = "[CDATA[";
+ term = ']';
+ push = true;
+ }
+ else {
+ result = DOCDECL;
+ req = "DOCTYPE";
+ term = -1;
+ }
+ }
+ else {
+ error("illegal: <" + c);
+ return COMMENT;
+ }
+
+ for (int i = 0; i < req.length(); i++)
+ read(req.charAt(i));
+
+ if (result == DOCDECL)
+ parseDoctype(push);
+ else {
+ while (true) {
+ c = read();
+ if (c == -1){
+ error(UNEXPECTED_EOF);
+ return COMMENT;
+ }
+
+ if (push)
+ push(c);
+
+ if ((term == '?' || c == term)
+ && peek(0) == term
+ && peek(1) == '>')
+ break;
+
+ prev = c;
+ }
+
+ if (term == '-' && prev == '-')
+ error("illegal comment delimiter: --->");
+
+ read();
+ read();
+
+ if (push && term != '?')
+ txtPos--;
+
+ }
+ return result;
+ }
+
+ /** precondition: &lt! consumed */
+
+ private final void parseDoctype(boolean push)
+ throws IOException, XmlPullParserException {
+
+ int nesting = 1;
+ boolean quoted = false;
+
+ // read();
+
+ while (true) {
+ int i = read();
+ switch (i) {
+
+ case -1 :
+ error(UNEXPECTED_EOF);
+ return;
+
+ case '\'' :
+ quoted = !quoted;
+ break;
+
+ case '<' :
+ if (!quoted)
+ nesting++;
+ break;
+
+ case '>' :
+ if (!quoted) {
+ if ((--nesting) == 0)
+ return;
+ }
+ break;
+ }
+ if (push)
+ push(i);
+ }
+ }
+
+ /* precondition: &lt;/ consumed */
+
+ private final void parseEndTag()
+ throws IOException, XmlPullParserException {
+
+ read(); // '<'
+ read(); // '/'
+ name = readName();
+ skip();
+ read('>');
+
+ int sp = (depth - 1) << 2;
+
+ if (depth == 0) {
+ error("element stack empty");
+ type = COMMENT;
+ return;
+ }
+
+ if (!name.equals(elementStack[sp + 3])) {
+ error("expected: /" + elementStack[sp + 3] + " read: " + name);
+
+ // become case insensitive in relaxed mode
+
+ int probe = sp;
+ while (probe >= 0 && !name.toLowerCase().equals(elementStack[probe + 3].toLowerCase())) {
+ stackMismatch++;
+ probe -= 4;
+ }
+
+ if (probe < 0) {
+ stackMismatch = 0;
+ // text = "unexpected end tag ignored";
+ type = COMMENT;
+ return;
+ }
+ }
+
+ namespace = elementStack[sp];
+ prefix = elementStack[sp + 1];
+ name = elementStack[sp + 2];
+ }
+
+ private final int peekType() throws IOException {
+ switch (peek(0)) {
+ case -1 :
+ return END_DOCUMENT;
+ case '&' :
+ return ENTITY_REF;
+ case '<' :
+ switch (peek(1)) {
+ case '/' :
+ return END_TAG;
+ case '?' :
+ case '!' :
+ return LEGACY;
+ default :
+ return START_TAG;
+ }
+ default :
+ return TEXT;
+ }
+ }
+
+ private final String get(int pos) {
+ return new String(txtBuf, pos, txtPos - pos);
+ }
+
+ /*
+ private final String pop (int pos) {
+ String result = new String (txtBuf, pos, txtPos - pos);
+ txtPos = pos;
+ return result;
+ }
+ */
+
+ private final void push(int c) {
+
+ isWhitespace &= c <= ' ';
+
+ if (txtPos == txtBuf.length) {
+ char[] bigger = new char[txtPos * 4 / 3 + 4];
+ System.arraycopy(txtBuf, 0, bigger, 0, txtPos);
+ txtBuf = bigger;
+ }
+
+ txtBuf[txtPos++] = (char) c;
+ }
+
+ /** Sets name and attributes */
+
+ private final void parseStartTag(boolean xmldecl)
+ throws IOException, XmlPullParserException {
+
+ if (!xmldecl)
+ read();
+ name = readName();
+ attributeCount = 0;
+
+ while (true) {
+ skip();
+
+ int c = peek(0);
+
+ if (xmldecl) {
+ if (c == '?') {
+ read();
+ read('>');
+ return;
+ }
+ }
+ else {
+ if (c == '/') {
+ degenerated = true;
+ read();
+ skip();
+ read('>');
+ break;
+ }
+
+ if (c == '>' && !xmldecl) {
+ read();
+ break;
+ }
+ }
+
+ if (c == -1) {
+ error(UNEXPECTED_EOF);
+ //type = COMMENT;
+ return;
+ }
+
+ String attrName = readName();
+
+ if (attrName.length() == 0) {
+ error("attr name expected");
+ //type = COMMENT;
+ break;
+ }
+
+ int i = (attributeCount++) << 2;
+
+ attributes = ensureCapacity(attributes, i + 4);
+
+ attributes[i++] = "";
+ attributes[i++] = null;
+ attributes[i++] = attrName;
+
+ skip();
+
+ if (peek(0) != '=') {
+ error("Attr.value missing f. "+attrName);
+ attributes[i] = "1";
+ }
+ else {
+ read('=');
+ skip();
+ int delimiter = peek(0);
+
+ if (delimiter != '\'' && delimiter != '"') {
+ error("attr value delimiter missing!");
+ delimiter = ' ';
+ }
+ else
+ read();
+
+ int p = txtPos;
+ pushText(delimiter, true);
+
+ attributes[i] = get(p);
+ txtPos = p;
+
+ if (delimiter != ' ')
+ read(); // skip endquote
+ }
+ }
+
+ int sp = depth++ << 2;
+
+ elementStack = ensureCapacity(elementStack, sp + 4);
+ elementStack[sp + 3] = name;
+
+ if (depth >= nspCounts.length) {
+ int[] bigger = new int[depth + 4];
+ System.arraycopy(nspCounts, 0, bigger, 0, nspCounts.length);
+ nspCounts = bigger;
+ }
+
+ nspCounts[depth] = nspCounts[depth - 1];
+
+ /*
+ if(!relaxed){
+ for (int i = attributeCount - 1; i > 0; i--) {
+ for (int j = 0; j < i; j++) {
+ if (getAttributeName(i).equals(getAttributeName(j)))
+ exception("Duplicate Attribute: " + getAttributeName(i));
+ }
+ }
+ }
+ */
+ if (processNsp)
+ adjustNsp();
+ else
+ namespace = "";
+
+ elementStack[sp] = namespace;
+ elementStack[sp + 1] = prefix;
+ elementStack[sp + 2] = name;
+ }
+
+ /**
+ * result: isWhitespace; if the setName parameter is set,
+ * the name of the entity is stored in "name" */
+
+ private final void pushEntity()
+ throws IOException, XmlPullParserException {
+
+ push(read()); // &
+
+
+ int pos = txtPos;
+
+ while (true) {
+ int c = read();
+ if (c == ';')
+ break;
+ if (c < 128
+ && (c < '0' || c > '9')
+ && (c < 'a' || c > 'z')
+ && (c < 'A' || c > 'Z')
+ && c != '_'
+ && c != '-'
+ && c != '#') {
+ if(!relaxed){
+ error("unterminated entity ref");
+ }
+ //; ends with:"+(char)c);
+ if (c != -1)
+ push(c);
+ return;
+ }
+
+ push(c);
+ }
+
+ String code = get(pos);
+ txtPos = pos - 1;
+ if (token && type == ENTITY_REF){
+ name = code;
+ }
+
+ if (code.charAt(0) == '#') {
+ int c =
+ (code.charAt(1) == 'x'
+ ? Integer.parseInt(code.substring(2), 16)
+ : Integer.parseInt(code.substring(1)));
+ push(c);
+ return;
+ }
+
+ String result = (String) entityMap.get(code);
+
+ unresolved = result == null;
+
+ if (unresolved) {
+ if (!token)
+ error("unresolved: &" + code + ";");
+ }
+ else {
+ for (int i = 0; i < result.length(); i++)
+ push(result.charAt(i));
+ }
+ }
+
+ /** types:
+ '<': parse to any token (for nextToken ())
+ '"': parse to quote
+ ' ': parse to whitespace or '>'
+ */
+
+ private final void pushText(int delimiter, boolean resolveEntities)
+ throws IOException, XmlPullParserException {
+
+ int next = peek(0);
+ int cbrCount = 0;
+
+ while (next != -1 && next != delimiter) { // covers eof, '<', '"'
+
+ if (delimiter == ' ')
+ if (next <= ' ' || next == '>')
+ break;
+
+ if (next == '&') {
+ if (!resolveEntities)
+ break;
+
+ pushEntity();
+ }
+ else if (next == '\n' && type == START_TAG) {
+ read();
+ push(' ');
+ }
+ else
+ push(read());
+
+ if (next == '>' && cbrCount >= 2 && delimiter != ']')
+ error("Illegal: ]]>");
+
+ if (next == ']')
+ cbrCount++;
+ else
+ cbrCount = 0;
+
+ next = peek(0);
+ }
+ }
+
+ private final void read(char c)
+ throws IOException, XmlPullParserException {
+ int a = read();
+ if (a != c)
+ error("expected: '" + c + "' actual: '" + ((char) a) + "'");
+ }
+
+ private final int read() throws IOException {
+ int result;
+
+ if (peekCount == 0)
+ result = peek(0);
+ else {
+ result = peek[0];
+ peek[0] = peek[1];
+ }
+ // else {
+ // result = peek[0];
+ // System.arraycopy (peek, 1, peek, 0, peekCount-1);
+ // }
+ peekCount--;
+
+ column++;
+
+ if (result == '\n') {
+
+ line++;
+ column = 1;
+ }
+
+ return result;
+ }
+
+ /** Does never read more than needed */
+
+ private final int peek(int pos) throws IOException {
+
+ while (pos >= peekCount) {
+
+ int nw;
+
+ if (srcBuf.length <= 1)
+ nw = reader.read();
+ else if (srcPos < srcCount)
+ nw = srcBuf[srcPos++];
+ else {
+ srcCount = reader.read(srcBuf, 0, srcBuf.length);
+ if (srcCount <= 0)
+ nw = -1;
+ else
+ nw = srcBuf[0];
+
+ srcPos = 1;
+ }
+
+ if (nw == '\r') {
+ wasCR = true;
+ peek[peekCount++] = '\n';
+ }
+ else {
+ if (nw == '\n') {
+ if (!wasCR)
+ peek[peekCount++] = '\n';
+ }
+ else
+ peek[peekCount++] = nw;
+
+ wasCR = false;
+ }
+ }
+
+ return peek[pos];
+ }
+
+ private final String readName()
+ throws IOException, XmlPullParserException {
+
+ int pos = txtPos;
+ int c = peek(0);
+ if ((c < 'a' || c > 'z')
+ && (c < 'A' || c > 'Z')
+ && c != '_'
+ && c != ':'
+ && c < 0x0c0
+ && !relaxed)
+ error("name expected");
+
+ do {
+ push(read());
+ c = peek(0);
+ }
+ while ((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || c == '_'
+ || c == '-'
+ || c == ':'
+ || c == '.'
+ || c >= 0x0b7);
+
+ String result = get(pos);
+ txtPos = pos;
+ return result;
+ }
+
+ private final void skip() throws IOException {
+
+ while (true) {
+ int c = peek(0);
+ if (c > ' ' || c == -1)
+ break;
+ read();
+ }
+ }
+
+ // public part starts here...
+
+ public void setInput(Reader reader) throws XmlPullParserException {
+ this.reader = reader;
+
+ line = 1;
+ column = 0;
+ type = START_DOCUMENT;
+ name = null;
+ namespace = null;
+ degenerated = false;
+ attributeCount = -1;
+ encoding = null;
+ version = null;
+ standalone = null;
+
+ if (reader == null)
+ return;
+
+ srcPos = 0;
+ srcCount = 0;
+ peekCount = 0;
+ depth = 0;
+
+ entityMap = new HashMap();
+ entityMap.put("amp", "&");
+ entityMap.put("apos", "'");
+ entityMap.put("gt", ">");
+ entityMap.put("lt", "<");
+ entityMap.put("quot", "\"");
+ }
+
+ public void setInput(InputStream is, String _enc)
+ throws XmlPullParserException {
+
+ srcPos = 0;
+ srcCount = 0;
+ String enc = _enc;
+
+ if (is == null)
+ throw new IllegalArgumentException();
+
+ try {
+
+ if (enc == null) {
+ // read four bytes
+
+ int chk = 0;
+
+ while (srcCount < 4) {
+ int i = is.read();
+ if (i == -1)
+ break;
+ chk = (chk << 8) | i;
+ srcBuf[srcCount++] = (char) i;
+ }
+
+ if (srcCount == 4) {
+ switch (chk) {
+ case 0x00000FEFF :
+ enc = "UTF-32BE";
+ srcCount = 0;
+ break;
+
+ case 0x0FFFE0000 :
+ enc = "UTF-32LE";
+ srcCount = 0;
+ break;
+
+ case 0x03c :
+ enc = "UTF-32BE";
+ srcBuf[0] = '<';
+ srcCount = 1;
+ break;
+
+ case 0x03c000000 :
+ enc = "UTF-32LE";
+ srcBuf[0] = '<';
+ srcCount = 1;
+ break;
+
+ case 0x0003c003f :
+ enc = "UTF-16BE";
+ srcBuf[0] = '<';
+ srcBuf[1] = '?';
+ srcCount = 2;
+ break;
+
+ case 0x03c003f00 :
+ enc = "UTF-16LE";
+ srcBuf[0] = '<';
+ srcBuf[1] = '?';
+ srcCount = 2;
+ break;
+
+ case 0x03c3f786d :
+ while (true) {
+ int i = is.read();
+ if (i == -1)
+ break;
+ srcBuf[srcCount++] = (char) i;
+ if (i == '>') {
+ String s = new String(srcBuf, 0, srcCount);
+ int i0 = s.indexOf("encoding");
+ if (i0 != -1) {
+ while (s.charAt(i0) != '"'
+ && s.charAt(i0) != '\'')
+ i0++;
+ char deli = s.charAt(i0++);
+ int i1 = s.indexOf(deli, i0);
+ enc = s.substring(i0, i1);
+ }
+ break;
+ }
+ }
+
+ default :
+ if ((chk & 0x0ffff0000) == 0x0FEFF0000) {
+ enc = "UTF-16BE";
+ srcBuf[0] =
+ (char) ((srcBuf[2] << 8) | srcBuf[3]);
+ srcCount = 1;
+ }
+ else if ((chk & 0x0ffff0000) == 0x0fffe0000) {
+ enc = "UTF-16LE";
+ srcBuf[0] =
+ (char) ((srcBuf[3] << 8) | srcBuf[2]);
+ srcCount = 1;
+ }
+ else if ((chk & 0x0ffffff00) == 0x0EFBBBF00) {
+ enc = "UTF-8";
+ srcBuf[0] = srcBuf[3];
+ srcCount = 1;
+ }
+ }
+ }
+ }
+
+ if (enc == null)
+ enc = "UTF-8";
+
+ int sc = srcCount;
+ setInput(new InputStreamReader(is, enc));
+ encoding = _enc;
+ srcCount = sc;
+ }
+ catch (Exception e) {
+ throw new XmlPullParserException(
+ "Invalid stream or encoding: " + e.toString(),
+ this,
+ e);
+ }
+ }
+
+ public boolean getFeature(String feature) {
+ if (XmlPullParser.FEATURE_PROCESS_NAMESPACES.equals(feature))
+ return processNsp;
+ else if (isProp(feature, false, "relaxed"))
+ return relaxed;
+ else
+ return false;
+ }
+
+ public String getInputEncoding() {
+ return encoding;
+ }
+
+ public void defineEntityReplacementText(String entity, String value)
+ throws XmlPullParserException {
+ if (entityMap == null)
+ throw new RuntimeException("entity replacement text must be defined after setInput!");
+ entityMap.put(entity, value);
+ }
+
+ public Object getProperty(String property) {
+ if (isProp(property, true, "xmldecl-version"))
+ return version;
+ if (isProp(property, true, "xmldecl-standalone"))
+ return standalone;
+ if (isProp(property, true, "location"))
+ return location != null ? location : reader.toString();
+ return null;
+ }
+
+ public int getNamespaceCount(int depth) {
+ if (depth > this.depth)
+ throw new IndexOutOfBoundsException();
+ return nspCounts[depth];
+ }
+
+ public String getNamespacePrefix(int pos) {
+ return nspStack[pos << 1];
+ }
+
+ public String getNamespaceUri(int pos) {
+ return nspStack[(pos << 1) + 1];
+ }
+
+ public String getNamespace(String prefix) {
+
+ if ("xml".equals(prefix))
+ return "http://www.w3.org/XML/1998/namespace";
+ if ("xmlns".equals(prefix))
+ return "http://www.w3.org/2000/xmlns/";
+
+ for (int i = (getNamespaceCount(depth) << 1) - 2; i >= 0; i -= 2) {
+ if (prefix == null) {
+ if (nspStack[i] == null)
+ return nspStack[i + 1];
+ }
+ else if (prefix.equals(nspStack[i]))
+ return nspStack[i + 1];
+ }
+ return null;
+ }
+
+ public int getDepth() {
+ return depth;
+ }
+
+ public String getPositionDescription() {
+
+ StringBuffer buf =
+ new StringBuffer(type < TYPES.length ? TYPES[type] : "unknown");
+ buf.append(' ');
+
+ if (type == START_TAG || type == END_TAG) {
+ if (degenerated)
+ buf.append("(empty) ");
+ buf.append('<');
+ if (type == END_TAG)
+ buf.append('/');
+
+ if (prefix != null)
+ buf.append("{" + namespace + "}" + prefix + ":");
+ buf.append(name);
+
+ int cnt = attributeCount << 2;
+ for (int i = 0; i < cnt; i += 4) {
+ buf.append(' ');
+ if (attributes[i + 1] != null)
+ buf.append(
+ "{" + attributes[i] + "}" + attributes[i + 1] + ":");
+ buf.append(attributes[i + 2] + "='" + attributes[i + 3] + "'");
+ }
+
+ buf.append('>');
+ }
+ else if (type == IGNORABLE_WHITESPACE);
+ else if (type != TEXT)
+ buf.append(getText());
+ else if (isWhitespace)
+ buf.append("(whitespace)");
+ else {
+ String text = getText();
+ if (text.length() > 16)
+ text = text.substring(0, 16) + "...";
+ buf.append(text);
+ }
+
+ buf.append("@"+line + ":" + column);
+ if(location != null){
+ buf.append(" in ");
+ buf.append(location);
+ }
+ else if(reader != null){
+ buf.append(" in ");
+ buf.append(reader.toString());
+ }
+ return buf.toString();
+ }
+
+ public int getLineNumber() {
+ return line;
+ }
+
+ public int getColumnNumber() {
+ return column;
+ }
+
+ public boolean isWhitespace() throws XmlPullParserException {
+ if (type != TEXT && type != IGNORABLE_WHITESPACE && type != CDSECT)
+ exception(ILLEGAL_TYPE);
+ return isWhitespace;
+ }
+
+ public String getText() {
+ return type < TEXT
+ || (type == ENTITY_REF && unresolved) ? null : get(0);
+ }
+
+ public char[] getTextCharacters(int[] poslen) {
+ if (type >= TEXT) {
+ if (type == ENTITY_REF) {
+ poslen[0] = 0;
+ poslen[1] = name.length();
+ return name.toCharArray();
+ }
+ poslen[0] = 0;
+ poslen[1] = txtPos;
+ return txtBuf;
+ }
+
+ poslen[0] = -1;
+ poslen[1] = -1;
+ return null;
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+
+ public boolean isEmptyElementTag() throws XmlPullParserException {
+ if (type != START_TAG)
+ exception(ILLEGAL_TYPE);
+ return degenerated;
+ }
+
+ public int getAttributeCount() {
+ return attributeCount;
+ }
+
+ public String getAttributeType(int index) {
+ return "CDATA";
+ }
+
+ public boolean isAttributeDefault(int index) {
+ return false;
+ }
+
+ public String getAttributeNamespace(int index) {
+ if (index >= attributeCount)
+ throw new IndexOutOfBoundsException();
+ return attributes[index << 2];
+ }
+
+ public String getAttributeName(int index) {
+ if (index >= attributeCount)
+ throw new IndexOutOfBoundsException();
+ return attributes[(index << 2) + 2];
+ }
+
+ public String getAttributePrefix(int index) {
+ if (index >= attributeCount)
+ throw new IndexOutOfBoundsException();
+ return attributes[(index << 2) + 1];
+ }
+
+ public String getAttributeValue(int index) {
+ if (index >= attributeCount)
+ throw new IndexOutOfBoundsException();
+ return attributes[(index << 2) + 3];
+ }
+
+ public String getAttributeValue(String namespace, String name) {
+
+ for (int i = (attributeCount << 2) - 4; i >= 0; i -= 4) {
+ if (attributes[i + 2].equals(name)
+ && (namespace == null || attributes[i].equals(namespace)))
+ return attributes[i + 3];
+ }
+
+ return null;
+ }
+
+ public int getEventType() throws XmlPullParserException {
+ return type;
+ }
+
+ public int next() throws XmlPullParserException, IOException {
+
+ txtPos = 0;
+ isWhitespace = true;
+ int minType = 9999;
+ token = false;
+
+ do {
+ nextImpl();
+ if (type < minType)
+ minType = type;
+ // if (curr <= TEXT) type = curr;
+ }
+ while (minType > ENTITY_REF // ignorable
+ || (minType >= TEXT && peekType() >= TEXT));
+
+ type = minType;
+ if (type > TEXT)
+ type = TEXT;
+
+ return type;
+ }
+
+ public int nextToken() throws XmlPullParserException, IOException {
+
+ isWhitespace = true;
+ txtPos = 0;
+
+ token = true;
+ nextImpl();
+ return type;
+ }
+
+ //
+ // utility methods to make XML parsing easier ...
+
+ public int nextTag() throws XmlPullParserException, IOException {
+
+ next();
+ if (type == TEXT && isWhitespace)
+ next();
+
+ if (type != END_TAG && type != START_TAG)
+ exception("unexpected type");
+
+ return type;
+ }
+
+ public void require(int type, String namespace, String name)
+ throws XmlPullParserException, IOException {
+
+ if (type != this.type
+ || (namespace != null && !namespace.equals(getNamespace()))
+ || (name != null && !name.equals(getName())))
+ exception(
+ "expected: " + TYPES[type] + " {" + namespace + "}" + name);
+ }
+
+ public String nextText() throws XmlPullParserException, IOException {
+ if (type != START_TAG)
+ exception("precondition: START_TAG");
+
+ next();
+
+ String result;
+
+ if (type == TEXT) {
+ result = getText();
+ next();
+ }
+ else
+ result = "";
+
+ if (type != END_TAG)
+ exception("END_TAG expected");
+
+ return result;
+ }
+
+ public void setFeature(String feature, boolean value)
+ throws XmlPullParserException {
+ if (XmlPullParser.FEATURE_PROCESS_NAMESPACES.equals(feature))
+ processNsp = value;
+ else if (isProp(feature, false, "relaxed"))
+ relaxed = value;
+ else
+ exception("unsupported feature: " + feature);
+ }
+
+ public void setProperty(String property, Object value)
+ throws XmlPullParserException {
+ if(isProp(property, true, "location"))
+ location = value;
+ else
+ throw new XmlPullParserException("unsupported property: " + property);
+ }
+
+ /**
+ * Skip sub tree that is currently porser positioned on.
+ * <br>NOTE: parser must be on START_TAG and when funtion returns
+ * parser will be positioned on corresponding END_TAG.
+ */
+
+ // Implementation copied from Alek's mail...
+
+ public void skipSubTree() throws XmlPullParserException, IOException {
+ require(START_TAG, null, null);
+ int level = 1;
+ while (level > 0) {
+ int eventType = next();
+ if (eventType == END_TAG) {
+ --level;
+ }
+ else if (eventType == START_TAG) {
+ ++level;
+ }
+ }
+ }
+}
diff --git a/xml/src/main/java/org/kxml2/io/KXmlSerializer.java b/xml/src/main/java/org/kxml2/io/KXmlSerializer.java
new file mode 100644
index 0000000..d63ed04
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/io/KXmlSerializer.java
@@ -0,0 +1,562 @@
+/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+
+package org.kxml2.io;
+
+import java.io.*;
+import org.xmlpull.v1.*;
+
+public class KXmlSerializer implements XmlSerializer {
+
+ // static final String UNDEFINED = ":";
+
+ // BEGIN android-added
+ /** size (in characters) for the write buffer */
+ private static final int WRITE_BUFFER_SIZE = 500;
+ // END android-added
+
+ // BEGIN android-changed
+ // (Guarantee that the writer is always buffered.)
+ private BufferedWriter writer;
+ // END android-changed
+
+ private boolean pending;
+ private int auto;
+ private int depth;
+
+ private String[] elementStack = new String[12];
+ //nsp/prefix/name
+ private int[] nspCounts = new int[4];
+ private String[] nspStack = new String[8];
+ //prefix/nsp; both empty are ""
+ private boolean[] indent = new boolean[4];
+ private boolean unicode;
+ private String encoding;
+
+ private final void check(boolean close) throws IOException {
+ if (!pending)
+ return;
+
+ depth++;
+ pending = false;
+
+ if (indent.length <= depth) {
+ boolean[] hlp = new boolean[depth + 4];
+ System.arraycopy(indent, 0, hlp, 0, depth);
+ indent = hlp;
+ }
+ indent[depth] = indent[depth - 1];
+
+ for (int i = nspCounts[depth - 1];
+ i < nspCounts[depth];
+ i++) {
+ writer.write(' ');
+ writer.write("xmlns");
+ if (!"".equals(nspStack[i * 2])) {
+ writer.write(':');
+ writer.write(nspStack[i * 2]);
+ }
+ else if ("".equals(getNamespace()) && !"".equals(nspStack[i * 2 + 1]))
+ throw new IllegalStateException("Cannot set default namespace for elements in no namespace");
+ writer.write("=\"");
+ writeEscaped(nspStack[i * 2 + 1], '"');
+ writer.write('"');
+ }
+
+ if (nspCounts.length <= depth + 1) {
+ int[] hlp = new int[depth + 8];
+ System.arraycopy(nspCounts, 0, hlp, 0, depth + 1);
+ nspCounts = hlp;
+ }
+
+ nspCounts[depth + 1] = nspCounts[depth];
+ // nspCounts[depth + 2] = nspCounts[depth];
+
+ writer.write(close ? " />" : ">");
+ }
+
+ private final void writeEscaped(String s, int quot)
+ throws IOException {
+
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ switch (c) {
+ case '\n':
+ case '\r':
+ case '\t':
+ if(quot == -1)
+ writer.write(c);
+ else
+ writer.write("&#"+((int) c)+';');
+ break;
+ case '&' :
+ writer.write("&amp;");
+ break;
+ case '>' :
+ writer.write("&gt;");
+ break;
+ case '<' :
+ writer.write("&lt;");
+ break;
+ case '"' :
+ case '\'' :
+ if (c == quot) {
+ writer.write(
+ c == '"' ? "&quot;" : "&apos;");
+ break;
+ }
+ default :
+ //if(c < ' ')
+ // throw new IllegalArgumentException("Illegal control code:"+((int) c));
+
+ if (c >= ' ' && c !='@' && (c < 127 || unicode))
+ writer.write(c);
+ else
+ writer.write("&#" + ((int) c) + ";");
+
+ }
+ }
+ }
+
+ /*
+ private final void writeIndent() throws IOException {
+ writer.write("\r\n");
+ for (int i = 0; i < depth; i++)
+ writer.write(' ');
+ }*/
+
+ public void docdecl(String dd) throws IOException {
+ writer.write("<!DOCTYPE");
+ writer.write(dd);
+ writer.write(">");
+ }
+
+ public void endDocument() throws IOException {
+ while (depth > 0) {
+ endTag(
+ elementStack[depth * 3 - 3],
+ elementStack[depth * 3 - 1]);
+ }
+ flush();
+ }
+
+ public void entityRef(String name) throws IOException {
+ check(false);
+ writer.write('&');
+ writer.write(name);
+ writer.write(';');
+ }
+
+ public boolean getFeature(String name) {
+ //return false;
+ return (
+ "http://xmlpull.org/v1/doc/features.html#indent-output"
+ .equals(
+ name))
+ ? indent[depth]
+ : false;
+ }
+
+ public String getPrefix(String namespace, boolean create) {
+ try {
+ return getPrefix(namespace, false, create);
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+
+ private final String getPrefix(
+ String namespace,
+ boolean includeDefault,
+ boolean create)
+ throws IOException {
+
+ for (int i = nspCounts[depth + 1] * 2 - 2;
+ i >= 0;
+ i -= 2) {
+ if (nspStack[i + 1].equals(namespace)
+ && (includeDefault || !nspStack[i].equals(""))) {
+ String cand = nspStack[i];
+ for (int j = i + 2;
+ j < nspCounts[depth + 1] * 2;
+ j++) {
+ if (nspStack[j].equals(cand)) {
+ cand = null;
+ break;
+ }
+ }
+ if (cand != null)
+ return cand;
+ }
+ }
+
+ if (!create)
+ return null;
+
+ String prefix;
+
+ if ("".equals(namespace))
+ prefix = "";
+ else {
+ do {
+ prefix = "n" + (auto++);
+ for (int i = nspCounts[depth + 1] * 2 - 2;
+ i >= 0;
+ i -= 2) {
+ if (prefix.equals(nspStack[i])) {
+ prefix = null;
+ break;
+ }
+ }
+ }
+ while (prefix == null);
+ }
+
+ boolean p = pending;
+ pending = false;
+ setPrefix(prefix, namespace);
+ pending = p;
+ return prefix;
+ }
+
+ public Object getProperty(String name) {
+ throw new RuntimeException("Unsupported property");
+ }
+
+ public void ignorableWhitespace(String s)
+ throws IOException {
+ text(s);
+ }
+
+ public void setFeature(String name, boolean value) {
+ if ("http://xmlpull.org/v1/doc/features.html#indent-output"
+ .equals(name)) {
+ indent[depth] = value;
+ }
+ else
+ throw new RuntimeException("Unsupported Feature");
+ }
+
+ public void setProperty(String name, Object value) {
+ throw new RuntimeException(
+ "Unsupported Property:" + value);
+ }
+
+ public void setPrefix(String prefix, String namespace)
+ throws IOException {
+
+ check(false);
+ if (prefix == null)
+ prefix = "";
+ if (namespace == null)
+ namespace = "";
+
+ String defined = getPrefix(namespace, true, false);
+
+ // boil out if already defined
+
+ if (prefix.equals(defined))
+ return;
+
+ int pos = (nspCounts[depth + 1]++) << 1;
+
+ if (nspStack.length < pos + 1) {
+ String[] hlp = new String[nspStack.length + 16];
+ System.arraycopy(nspStack, 0, hlp, 0, pos);
+ nspStack = hlp;
+ }
+
+ nspStack[pos++] = prefix;
+ nspStack[pos] = namespace;
+ }
+
+ public void setOutput(Writer writer) {
+ // BEGIN android-changed
+ // Guarantee that the writer is always buffered.
+ if (writer instanceof BufferedWriter) {
+ this.writer = (BufferedWriter) writer;
+ } else {
+ this.writer = new BufferedWriter(writer, WRITE_BUFFER_SIZE);
+ }
+ // END android-changed
+
+ // elementStack = new String[12]; //nsp/prefix/name
+ //nspCounts = new int[4];
+ //nspStack = new String[8]; //prefix/nsp
+ //indent = new boolean[4];
+
+ nspCounts[0] = 2;
+ nspCounts[1] = 2;
+ nspStack[0] = "";
+ nspStack[1] = "";
+ nspStack[2] = "xml";
+ nspStack[3] = "http://www.w3.org/XML/1998/namespace";
+ pending = false;
+ auto = 0;
+ depth = 0;
+
+ unicode = false;
+ }
+
+ public void setOutput(OutputStream os, String encoding)
+ throws IOException {
+ if (os == null)
+ throw new IllegalArgumentException();
+ setOutput(
+ encoding == null
+ ? new OutputStreamWriter(os)
+ : new OutputStreamWriter(os, encoding));
+ this.encoding = encoding;
+ if (encoding != null
+ && encoding.toLowerCase().startsWith("utf"))
+ unicode = true;
+ }
+
+ public void startDocument(
+ String encoding,
+ Boolean standalone)
+ throws IOException {
+ writer.write("<?xml version='1.0' ");
+
+ if (encoding != null) {
+ this.encoding = encoding;
+ if (encoding.toLowerCase().startsWith("utf"))
+ unicode = true;
+ }
+
+ if (this.encoding != null) {
+ writer.write("encoding='");
+ writer.write(this.encoding);
+ writer.write("' ");
+ }
+
+ if (standalone != null) {
+ writer.write("standalone='");
+ writer.write(
+ standalone.booleanValue() ? "yes" : "no");
+ writer.write("' ");
+ }
+ writer.write("?>");
+ }
+
+ public XmlSerializer startTag(String namespace, String name)
+ throws IOException {
+ check(false);
+
+ // if (namespace == null)
+ // namespace = "";
+
+ if (indent[depth]) {
+ writer.write("\r\n");
+ for (int i = 0; i < depth; i++)
+ writer.write(" ");
+ }
+
+ int esp = depth * 3;
+
+ if (elementStack.length < esp + 3) {
+ String[] hlp = new String[elementStack.length + 12];
+ System.arraycopy(elementStack, 0, hlp, 0, esp);
+ elementStack = hlp;
+ }
+
+ String prefix =
+ namespace == null
+ ? ""
+ : getPrefix(namespace, true, true);
+
+ if ("".equals(namespace)) {
+ for (int i = nspCounts[depth];
+ i < nspCounts[depth + 1];
+ i++) {
+ if ("".equals(nspStack[i * 2]) && !"".equals(nspStack[i * 2 + 1])) {
+ throw new IllegalStateException("Cannot set default namespace for elements in no namespace");
+ }
+ }
+ }
+
+ elementStack[esp++] = namespace;
+ elementStack[esp++] = prefix;
+ elementStack[esp] = name;
+
+ writer.write('<');
+ if (!"".equals(prefix)) {
+ writer.write(prefix);
+ writer.write(':');
+ }
+
+ writer.write(name);
+
+ pending = true;
+
+ return this;
+ }
+
+ public XmlSerializer attribute(
+ String namespace,
+ String name,
+ String value)
+ throws IOException {
+ if (!pending)
+ throw new IllegalStateException("illegal position for attribute");
+
+ // int cnt = nspCounts[depth];
+
+ if (namespace == null)
+ namespace = "";
+
+ // depth--;
+ // pending = false;
+
+ String prefix =
+ "".equals(namespace)
+ ? ""
+ : getPrefix(namespace, false, true);
+
+ // pending = true;
+ // depth++;
+
+ /* if (cnt != nspCounts[depth]) {
+ writer.write(' ');
+ writer.write("xmlns");
+ if (nspStack[cnt * 2] != null) {
+ writer.write(':');
+ writer.write(nspStack[cnt * 2]);
+ }
+ writer.write("=\"");
+ writeEscaped(nspStack[cnt * 2 + 1], '"');
+ writer.write('"');
+ }
+ */
+
+ writer.write(' ');
+ if (!"".equals(prefix)) {
+ writer.write(prefix);
+ writer.write(':');
+ }
+ writer.write(name);
+ writer.write('=');
+ char q = value.indexOf('"') == -1 ? '"' : '\'';
+ writer.write(q);
+ writeEscaped(value, q);
+ writer.write(q);
+
+ return this;
+ }
+
+ public void flush() throws IOException {
+ check(false);
+ writer.flush();
+ }
+ /*
+ public void close() throws IOException {
+ check();
+ writer.close();
+ }
+ */
+ public XmlSerializer endTag(String namespace, String name)
+ throws IOException {
+
+ if (!pending)
+ depth--;
+ // if (namespace == null)
+ // namespace = "";
+
+ if ((namespace == null
+ && elementStack[depth * 3] != null)
+ || (namespace != null
+ && !namespace.equals(elementStack[depth * 3]))
+ || !elementStack[depth * 3 + 2].equals(name))
+ throw new IllegalArgumentException("</{"+namespace+"}"+name+"> does not match start");
+
+ if (pending) {
+ check(true);
+ depth--;
+ }
+ else {
+ if (indent[depth + 1]) {
+ writer.write("\r\n");
+ for (int i = 0; i < depth; i++)
+ writer.write(" ");
+ }
+
+ writer.write("</");
+ String prefix = elementStack[depth * 3 + 1];
+ if (!"".equals(prefix)) {
+ writer.write(prefix);
+ writer.write(':');
+ }
+ writer.write(name);
+ writer.write('>');
+ }
+
+ nspCounts[depth + 1] = nspCounts[depth];
+ return this;
+ }
+
+ public String getNamespace() {
+ return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 3];
+ }
+
+ public String getName() {
+ return getDepth() == 0 ? null : elementStack[getDepth() * 3 - 1];
+ }
+
+ public int getDepth() {
+ return pending ? depth + 1 : depth;
+ }
+
+ public XmlSerializer text(String text) throws IOException {
+ check(false);
+ indent[depth] = false;
+ writeEscaped(text, -1);
+ return this;
+ }
+
+ public XmlSerializer text(char[] text, int start, int len)
+ throws IOException {
+ text(new String(text, start, len));
+ return this;
+ }
+
+ public void cdsect(String data) throws IOException {
+ check(false);
+ writer.write("<![CDATA[");
+ writer.write(data);
+ writer.write("]]>");
+ }
+
+ public void comment(String comment) throws IOException {
+ check(false);
+ writer.write("<!--");
+ writer.write(comment);
+ writer.write("-->");
+ }
+
+ public void processingInstruction(String pi)
+ throws IOException {
+ check(false);
+ writer.write("<?");
+ writer.write(pi);
+ writer.write("?>");
+ }
+}
diff --git a/xml/src/main/java/org/kxml2/kdom/Document.java b/xml/src/main/java/org/kxml2/kdom/Document.java
new file mode 100644
index 0000000..859334c
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/kdom/Document.java
@@ -0,0 +1,129 @@
+/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+
+package org.kxml2.kdom;
+
+import java.io.*;
+
+import org.xmlpull.v1.*;
+/** The document consists of some legacy events and a single root
+ element. This class basically adds some consistency checks to
+ Node. */
+
+public class Document extends Node {
+
+ protected int rootIndex = -1;
+ String encoding;
+ Boolean standalone;
+
+ /** returns "#document" */
+
+ public String getEncoding () {
+ return encoding;
+ }
+
+ public void setEncoding(String enc) {
+ this.encoding = enc;
+ }
+
+ public void setStandalone (Boolean standalone) {
+ this.standalone = standalone;
+ }
+
+ public Boolean getStandalone() {
+ return standalone;
+ }
+
+
+ public String getName() {
+ return "#document";
+ }
+
+ /** Adds a child at the given index position. Throws
+ an exception when a second root element is added */
+
+ public void addChild(int index, int type, Object child) {
+ if (type == ELEMENT) {
+ // if (rootIndex != -1)
+ // throw new RuntimeException("Only one document root element allowed");
+
+ rootIndex = index;
+ }
+ else if (rootIndex >= index)
+ rootIndex++;
+
+ super.addChild(index, type, child);
+ }
+
+ /** reads the document and checks if the last event
+ is END_DOCUMENT. If not, an exception is thrown.
+ The end event is consumed. For parsing partial
+ XML structures, consider using Node.parse (). */
+
+ public void parse(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+
+ parser.require(XmlPullParser.START_DOCUMENT, null, null);
+ parser.nextToken ();
+
+ encoding = parser.getInputEncoding();
+ standalone = (Boolean)parser.getProperty ("http://xmlpull.org/v1/doc/properties.html#xmldecl-standalone");
+
+ super.parse(parser);
+
+ if (parser.getEventType() != XmlPullParser.END_DOCUMENT)
+ throw new RuntimeException("Document end expected!");
+
+ }
+
+ public void removeChild(int index) {
+ if (index == rootIndex)
+ rootIndex = -1;
+ else if (index < rootIndex)
+ rootIndex--;
+
+ super.removeChild(index);
+ }
+
+ /** returns the root element of this document. */
+
+ public Element getRootElement() {
+ if (rootIndex == -1)
+ throw new RuntimeException("Document has no root element!");
+
+ return (Element) getChild(rootIndex);
+ }
+
+
+ /** Writes this node to the given XmlWriter. For node and document,
+ this method is identical to writeChildren, except that the
+ stream is flushed automatically. */
+
+ public void write(XmlSerializer writer)
+ throws IOException {
+
+ writer.startDocument(encoding, standalone);
+ writeChildren(writer);
+ writer.endDocument();
+ }
+
+
+} \ No newline at end of file
diff --git a/xml/src/main/java/org/kxml2/kdom/Element.java b/xml/src/main/java/org/kxml2/kdom/Element.java
new file mode 100644
index 0000000..61d5111
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/kdom/Element.java
@@ -0,0 +1,336 @@
+/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+package org.kxml2.kdom;
+
+import java.io.*;
+import java.util.*;
+
+import org.xmlpull.v1.*;
+
+/**
+ * In order to create an element, please use the createElement method
+ * instead of invoking the constructor directly. The right place to
+ * add user defined initialization code is the init method. */
+
+public class Element extends Node {
+
+ protected String namespace;
+ protected String name;
+ protected ArrayList attributes;
+ protected Node parent;
+ protected ArrayList prefixes;
+
+ public Element() {
+ }
+
+ /**
+ * called when all properties are set, but before children
+ * are parsed. Please do not use setParent for initialization
+ * code any longer. */
+
+ public void init() {
+ }
+
+
+
+
+ /**
+ * removes all children and attributes */
+
+ public void clear() {
+ attributes = null;
+ children = null;
+ }
+
+ /**
+ * Forwards creation request to parent if any, otherwise
+ * calls super.createElement. */
+
+ public Element createElement(
+ String namespace,
+ String name) {
+
+ return (this.parent == null)
+ ? super.createElement(namespace, name)
+ : this.parent.createElement(namespace, name);
+ }
+
+ /**
+ * Returns the number of attributes of this element. */
+
+ public int getAttributeCount() {
+ return attributes == null ? 0 : attributes.size();
+ }
+
+ public String getAttributeNamespace (int index) {
+ return ((String []) attributes.get(index)) [0];
+ }
+
+ public String getAttributeName (int index) {
+ return ((String []) attributes.get(index)) [1];
+ }
+
+
+ public String getAttributeValue (int index) {
+ return ((String []) attributes.get(index)) [2];
+ }
+
+
+ public String
+ getAttributeValue(String name)
+ {
+ return getAttributeValue(null, name);
+ }
+
+ public String getAttributeValue (String namespace, String name) {
+ for (int i = 0; i < getAttributeCount (); i++) {
+ if (name.equals (getAttributeName (i))
+ && (namespace == null || namespace.equals (getAttributeNamespace(i)))) {
+ return getAttributeValue (i);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the root node, determined by ascending to the
+ * all parents un of the root element. */
+
+ public Node getRoot() {
+
+ Element current = this;
+
+ while (current.parent != null) {
+ if (!(current.parent instanceof Element)) return current.parent;
+ current = (Element) current.parent;
+ }
+
+ return current;
+ }
+
+ /**
+ * returns the (local) name of the element */
+
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * returns the namespace of the element */
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+
+ /**
+ * returns the namespace for the given prefix */
+
+ public String getNamespaceUri (String prefix) {
+ int cnt = getNamespaceCount ();
+ for (int i = 0; i < cnt; i++) {
+ if (prefix == getNamespacePrefix (i) ||
+ (prefix != null && prefix.equals (getNamespacePrefix (i))))
+ return getNamespaceUri (i);
+ }
+ return parent instanceof Element ? ((Element) parent).getNamespaceUri (prefix) : null;
+ }
+
+
+ /**
+ * returns the number of declared namespaces, NOT including
+ * parent elements */
+
+ public int getNamespaceCount () {
+ return (prefixes == null ? 0 : prefixes.size ());
+ }
+
+
+ public String getNamespacePrefix (int i) {
+ return ((String []) prefixes.get(i)) [0];
+ }
+
+ public String getNamespaceUri (int i) {
+ return ((String []) prefixes.get(i)) [1];
+ }
+
+
+ /**
+ * Returns the parent node of this element */
+
+ public Node getParent() {
+ return parent;
+ }
+
+ /*
+ * Returns the parent element if available, null otherwise
+
+ public Element getParentElement() {
+ return (parent instanceof Element)
+ ? ((Element) parent)
+ : null;
+ }
+*/
+
+ /**
+ * Builds the child elements from the given Parser. By overwriting
+ * parse, an element can take complete control over parsing its
+ * subtree. */
+
+ public void parse(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+
+ for (int i = parser.getNamespaceCount (parser.getDepth () - 1);
+ i < parser.getNamespaceCount (parser.getDepth ()); i++) {
+ setPrefix (parser.getNamespacePrefix (i), parser.getNamespaceUri(i));
+ }
+
+
+ for (int i = 0; i < parser.getAttributeCount (); i++)
+ setAttribute (parser.getAttributeNamespace (i),
+// parser.getAttributePrefix (i),
+ parser.getAttributeName (i),
+ parser.getAttributeValue (i));
+
+
+ // if (prefixMap == null) throw new RuntimeException ("!!");
+
+ init();
+
+
+ if (parser.isEmptyElementTag())
+ parser.nextToken ();
+ else {
+ parser.nextToken ();
+ super.parse(parser);
+
+ if (getChildCount() == 0)
+ addChild(IGNORABLE_WHITESPACE, "");
+ }
+
+ parser.require(
+ XmlPullParser.END_TAG,
+ getNamespace(),
+ getName());
+
+ parser.nextToken ();
+ }
+
+
+ /**
+ * Sets the given attribute; a value of null removes the attribute */
+
+ public void setAttribute (String namespace, String name, String value) {
+ if (attributes == null)
+ attributes = new ArrayList();
+
+ if (namespace == null)
+ namespace = "";
+
+ for (int i = attributes.size()-1; i >=0; i--){
+ String[] attribut = (String[]) attributes.get(i);
+ if (attribut[0].equals(namespace) &&
+ attribut[1].equals(name)){
+
+ if (value == null) {
+ attributes.remove(i);
+ }
+ else {
+ attribut[2] = value;
+ }
+ return;
+ }
+ }
+
+ attributes.add(new String[] {namespace, name, value});
+ }
+
+
+ /**
+ * Sets the given prefix; a namespace value of null removess the
+ * prefix */
+
+ public void setPrefix (String prefix, String namespace) {
+ if (prefixes == null) prefixes = new ArrayList();
+ prefixes.add(new String [] {prefix, namespace});
+ }
+
+
+ /**
+ * sets the name of the element */
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * sets the namespace of the element. Please note: For no
+ * namespace, please use Xml.NO_NAMESPACE, null is not a legal
+ * value. Currently, null is converted to Xml.NO_NAMESPACE, but
+ * future versions may throw an exception. */
+
+ public void setNamespace(String namespace) {
+ if (namespace == null)
+ throw new NullPointerException ("Use \"\" for empty namespace");
+ this.namespace = namespace;
+ }
+
+ /**
+ * Sets the Parent of this element. Automatically called from the
+ * add method. Please use with care, you can simply
+ * create inconsitencies in the document tree structure using
+ * this method! */
+
+ protected void setParent(Node parent) {
+ this.parent = parent;
+ }
+
+
+ /**
+ * Writes this element and all children to the given XmlWriter. */
+
+ public void write(XmlSerializer writer)
+ throws IOException {
+
+ if (prefixes != null) {
+ for (int i = 0; i < prefixes.size(); i++) {
+ writer.setPrefix (getNamespacePrefix (i), getNamespaceUri (i));
+ }
+ }
+
+ writer.startTag(
+ getNamespace(),
+ getName());
+
+ int len = getAttributeCount();
+
+ for (int i = 0; i < len; i++) {
+ writer.attribute(
+ getAttributeNamespace(i),
+ getAttributeName(i),
+ getAttributeValue(i));
+ }
+
+ writeChildren(writer);
+
+ writer.endTag(getNamespace (), getName ());
+ }
+}
diff --git a/xml/src/main/java/org/kxml2/kdom/Node.java b/xml/src/main/java/org/kxml2/kdom/Node.java
new file mode 100644
index 0000000..4855893
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/kdom/Node.java
@@ -0,0 +1,366 @@
+/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+package org.kxml2.kdom;
+
+import java.util.*;
+import java.io.*;
+import org.xmlpull.v1.*;
+/** A common base class for Document and Element, also used for
+ storing XML fragments. */
+
+public class Node { //implements XmlIO{
+
+ public static final int DOCUMENT = 0;
+ public static final int ELEMENT = 2;
+ public static final int TEXT = 4;
+ public static final int CDSECT = 5;
+ public static final int ENTITY_REF = 6;
+ public static final int IGNORABLE_WHITESPACE = 7;
+ public static final int PROCESSING_INSTRUCTION = 8;
+ public static final int COMMENT = 9;
+ public static final int DOCDECL = 10;
+
+ protected ArrayList children;
+ protected StringBuffer types;
+
+ /** inserts the given child object of the given type at the
+ given index. */
+
+ public void addChild(int index, int type, Object child) {
+
+ if (child == null)
+ throw new NullPointerException();
+
+ if (children == null) {
+ children = new ArrayList();
+ types = new StringBuffer();
+ }
+
+ if (type == ELEMENT) {
+ if (!(child instanceof Element))
+ throw new RuntimeException("Element obj expected)");
+
+ ((Element) child).setParent(this);
+ }
+ else if (!(child instanceof String))
+ throw new RuntimeException("String expected");
+
+ children.add(index, child);
+ types.insert(index, (char) type);
+ }
+
+ /** convenience method for addChild (getChildCount (), child) */
+
+ public void addChild(int type, Object child) {
+ addChild(getChildCount(), type, child);
+ }
+
+ /** Builds a default element with the given properties. Elements
+ should always be created using this method instead of the
+ constructor in order to enable construction of specialized
+ subclasses by deriving custom Document classes. Please note:
+ For no namespace, please use Xml.NO_NAMESPACE, null is not a
+ legal value. Currently, null is converted to Xml.NO_NAMESPACE,
+ but future versions may throw an exception. */
+
+ public Element createElement(String namespace, String name) {
+
+ Element e = new Element();
+ e.namespace = namespace == null ? "" : namespace;
+ e.name = name;
+ return e;
+ }
+
+ /** Returns the child object at the given index. For child
+ elements, an Element object is returned. For all other child
+ types, a String is returned. */
+
+ public Object getChild(int index) {
+ return children.get(index);
+ }
+
+ /** Returns the number of child objects */
+
+ public int getChildCount() {
+ return children == null ? 0 : children.size();
+ }
+
+ /** returns the element at the given index. If the node at the
+ given index is a text node, null is returned */
+
+ public Element getElement(int index) {
+ Object child = getChild(index);
+ return (child instanceof Element) ? (Element) child : null;
+ }
+
+ /** Returns the element with the given namespace and name. If the
+ element is not found, or more than one matching elements are
+ found, an exception is thrown. */
+
+ public Element getElement(String namespace, String name) {
+
+ int i = indexOf(namespace, name, 0);
+ int j = indexOf(namespace, name, i + 1);
+
+ if (i == -1 || j != -1)
+ throw new RuntimeException(
+ "Element {"
+ + namespace
+ + "}"
+ + name
+ + (i == -1 ? " not found in " : " more than once in ")
+ + this);
+
+ return getElement(i);
+ }
+
+ /* returns "#document-fragment". For elements, the element name is returned
+
+ public String getName() {
+ return "#document-fragment";
+ }
+
+ /** Returns the namespace of the current element. For Node
+ and Document, Xml.NO_NAMESPACE is returned.
+
+ public String getNamespace() {
+ return "";
+ }
+
+ public int getNamespaceCount () {
+ return 0;
+ }
+
+ /** returns the text content if the element has text-only
+ content. Throws an exception for mixed content
+
+ public String getText() {
+
+ StringBuffer buf = new StringBuffer();
+ int len = getChildCount();
+
+ for (int i = 0; i < len; i++) {
+ if (isText(i))
+ buf.append(getText(i));
+ else if (getType(i) == ELEMENT)
+ throw new RuntimeException("not text-only content!");
+ }
+
+ return buf.toString();
+ }
+ */
+
+ /** Returns the text node with the given index or null if the node
+ with the given index is not a text node. */
+
+ public String getText(int index) {
+ return (isText(index)) ? (String) getChild(index) : null;
+ }
+
+ /** Returns the type of the child at the given index. Possible
+ types are ELEMENT, TEXT, COMMENT, and PROCESSING_INSTRUCTION */
+
+ public int getType(int index) {
+ return types.charAt(index);
+ }
+
+ /** Convenience method for indexOf (getNamespace (), name,
+ startIndex).
+
+ public int indexOf(String name, int startIndex) {
+ return indexOf(getNamespace(), name, startIndex);
+ }
+ */
+
+ /** Performs search for an element with the given namespace and
+ name, starting at the given start index. A null namespace
+ matches any namespace, please use Xml.NO_NAMESPACE for no
+ namespace). returns -1 if no matching element was found. */
+
+ public int indexOf(String namespace, String name, int startIndex) {
+
+ int len = getChildCount();
+
+ for (int i = startIndex; i < len; i++) {
+
+ Element child = getElement(i);
+
+ if (child != null
+ && name.equals(child.getName())
+ && (namespace == null || namespace.equals(child.getNamespace())))
+ return i;
+ }
+ return -1;
+ }
+
+ public boolean isText(int i) {
+ int t = getType(i);
+ return t == TEXT || t == IGNORABLE_WHITESPACE || t == CDSECT;
+ }
+
+ /** Recursively builds the child elements from the given parser
+ until an end tag or end document is found.
+ The end tag is not consumed. */
+
+ public void parse(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+
+ boolean leave = false;
+
+ do {
+ int type = parser.getEventType();
+
+ // System.out.println(parser.getPositionDescription());
+
+ switch (type) {
+
+ case XmlPullParser.START_TAG :
+ {
+ Element child =
+ createElement(
+ parser.getNamespace(),
+ parser.getName());
+ // child.setAttributes (event.getAttributes ());
+ addChild(ELEMENT, child);
+
+ // order is important here since
+ // setparent may perform some init code!
+
+ child.parse(parser);
+ break;
+ }
+
+ case XmlPullParser.END_DOCUMENT :
+ case XmlPullParser.END_TAG :
+ leave = true;
+ break;
+
+ default :
+ if (parser.getText() != null)
+ addChild(
+ type == XmlPullParser.ENTITY_REF ? TEXT : type,
+ parser.getText());
+ else if (
+ type == XmlPullParser.ENTITY_REF
+ && parser.getName() != null) {
+ addChild(ENTITY_REF, parser.getName());
+ }
+ parser.nextToken();
+ }
+ }
+ while (!leave);
+ }
+
+ /** Removes the child object at the given index */
+
+ public void removeChild(int idx) {
+ children.remove(idx);
+
+ /*** Modification by HHS - start ***/
+ // types.deleteCharAt (index);
+ /***/
+ int n = types.length() - 1;
+
+ for (int i = idx; i < n; i++)
+ types.setCharAt(i, types.charAt(i + 1));
+
+ types.setLength(n);
+
+ /*** Modification by HHS - end ***/
+ }
+
+ /* returns a valid XML representation of this Element including
+ attributes and children.
+ public String toString() {
+ try {
+ ByteArrayOutputStream bos =
+ new ByteArrayOutputStream();
+ XmlWriter xw =
+ new XmlWriter(new OutputStreamWriter(bos));
+ write(xw);
+ xw.close();
+ return new String(bos.toByteArray());
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+ */
+
+ /** Writes this node to the given XmlWriter. For node and document,
+ this method is identical to writeChildren, except that the
+ stream is flushed automatically. */
+
+ public void write(XmlSerializer writer) throws IOException {
+ writeChildren(writer);
+ writer.flush();
+ }
+
+ /** Writes the children of this node to the given XmlWriter. */
+
+ public void writeChildren(XmlSerializer writer) throws IOException {
+ if (children == null)
+ return;
+
+ int len = children.size();
+
+ for (int i = 0; i < len; i++) {
+ int type = getType(i);
+ Object child = children.get(i);
+ switch (type) {
+ case ELEMENT :
+ ((Element) child).write(writer);
+ break;
+
+ case TEXT :
+ writer.text((String) child);
+ break;
+
+ case IGNORABLE_WHITESPACE :
+ writer.ignorableWhitespace((String) child);
+ break;
+
+ case CDSECT :
+ writer.cdsect((String) child);
+ break;
+
+ case COMMENT :
+ writer.comment((String) child);
+ break;
+
+ case ENTITY_REF :
+ writer.entityRef((String) child);
+ break;
+
+ case PROCESSING_INSTRUCTION :
+ writer.processingInstruction((String) child);
+ break;
+
+ case DOCDECL :
+ writer.docdecl((String) child);
+ break;
+
+ default :
+ throw new RuntimeException("Illegal type: " + type);
+ }
+ }
+ }
+}
diff --git a/xml/src/main/java/org/kxml2/wap/Wbxml.java b/xml/src/main/java/org/kxml2/wap/Wbxml.java
new file mode 100644
index 0000000..5b0c2d3
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/wap/Wbxml.java
@@ -0,0 +1,49 @@
+/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+package org.kxml2.wap;
+
+
+/** contains the WBXML constants */
+
+
+public interface Wbxml {
+
+ static public final int SWITCH_PAGE = 0;
+ static public final int END = 1;
+ static public final int ENTITY = 2;
+ static public final int STR_I = 3;
+ static public final int LITERAL = 4;
+ static public final int EXT_I_0 = 0x40;
+ static public final int EXT_I_1 = 0x41;
+ static public final int EXT_I_2 = 0x42;
+ static public final int PI = 0x43;
+ static public final int LITERAL_C = 0x44;
+ static public final int EXT_T_0 = 0x80;
+ static public final int EXT_T_1 = 0x81;
+ static public final int EXT_T_2 = 0x82;
+ static public final int STR_T = 0x83;
+ static public final int LITERAL_A = 0x084;
+ static public final int EXT_0 = 0x0c0;
+ static public final int EXT_1 = 0x0c1;
+ static public final int EXT_2 = 0x0c2;
+ static public final int OPAQUE = 0x0c3;
+ static public final int LITERAL_AC = 0x0c4;
+}
diff --git a/xml/src/main/java/org/kxml2/wap/WbxmlParser.java b/xml/src/main/java/org/kxml2/wap/WbxmlParser.java
new file mode 100644
index 0000000..c3852eb
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/wap/WbxmlParser.java
@@ -0,0 +1,1050 @@
+/* Copyright (c) 2002,2003,2004 Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+// Contributors: Bjorn Aadland, Chris Bartley, Nicola Fankhauser,
+// Victor Havin, Christian Kurzke, Bogdan Onoiu,
+// Jain Sanjay, David Santoro.
+
+package org.kxml2.wap;
+
+import java.io.*;
+import java.util.Vector;
+import java.util.Hashtable;
+
+import org.xmlpull.v1.*;
+
+
+public class WbxmlParser implements XmlPullParser {
+
+ public static final int WAP_EXTENSION = 64;
+
+ static final private String UNEXPECTED_EOF =
+ "Unexpected EOF";
+ static final private String ILLEGAL_TYPE =
+ "Wrong event type";
+
+ private InputStream in;
+
+ private int TAG_TABLE = 0;
+ private int ATTR_START_TABLE = 1;
+ private int ATTR_VALUE_TABLE = 2;
+
+ private String[] attrStartTable;
+ private String[] attrValueTable;
+ private String[] tagTable;
+ private byte[] stringTable;
+ private Hashtable cacheStringTable = null;
+ private boolean processNsp;
+
+ private int depth;
+ private String[] elementStack = new String[16];
+ private String[] nspStack = new String[8];
+ private int[] nspCounts = new int[4];
+
+ private int attributeCount;
+ private String[] attributes = new String[16];
+ private int nextId = -2;
+
+ private Vector tables = new Vector();
+
+ int version;
+ int publicIdentifierId;
+ int charSet;
+
+ // StartTag current;
+ // ParseEvent next;
+
+ private String prefix;
+ private String namespace;
+ private String name;
+ private String text;
+ // private String encoding;
+ private Object wapExtensionData;
+ private int wapExtensionCode;
+
+ private int type;
+ private int codePage;
+
+ private boolean degenerated;
+ private boolean isWhitespace;
+ private String encoding = null;
+
+ public boolean getFeature(String feature) {
+ if (XmlPullParser
+ .FEATURE_PROCESS_NAMESPACES
+ .equals(feature))
+ return processNsp;
+ else
+ return false;
+ }
+
+ public String getInputEncoding() {
+ // should return someting depending on charSet here!!!!!
+ return encoding;
+ }
+
+ public void defineEntityReplacementText(
+ String entity,
+ String value)
+ throws XmlPullParserException {
+
+ // just ignore, has no effect
+ }
+
+ public Object getProperty(String property) {
+ return null;
+ }
+
+ public int getNamespaceCount(int depth) {
+ if (depth > this.depth)
+ throw new IndexOutOfBoundsException();
+ return nspCounts[depth];
+ }
+
+ public String getNamespacePrefix(int pos) {
+ return nspStack[pos << 1];
+ }
+
+ public String getNamespaceUri(int pos) {
+ return nspStack[(pos << 1) + 1];
+ }
+
+ public String getNamespace(String prefix) {
+
+ if ("xml".equals(prefix))
+ return "http://www.w3.org/XML/1998/namespace";
+ if ("xmlns".equals(prefix))
+ return "http://www.w3.org/2000/xmlns/";
+
+ for (int i = (getNamespaceCount(depth) << 1) - 2;
+ i >= 0;
+ i -= 2) {
+ if (prefix == null) {
+ if (nspStack[i] == null)
+ return nspStack[i + 1];
+ }
+ else if (prefix.equals(nspStack[i]))
+ return nspStack[i + 1];
+ }
+ return null;
+ }
+
+ public int getDepth() {
+ return depth;
+ }
+
+ public String getPositionDescription() {
+
+ StringBuffer buf =
+ new StringBuffer(
+ type < TYPES.length ? TYPES[type] : "unknown");
+ buf.append(' ');
+
+ if (type == START_TAG || type == END_TAG) {
+ if (degenerated)
+ buf.append("(empty) ");
+ buf.append('<');
+ if (type == END_TAG)
+ buf.append('/');
+
+ if (prefix != null)
+ buf.append("{" + namespace + "}" + prefix + ":");
+ buf.append(name);
+
+ int cnt = attributeCount << 2;
+ for (int i = 0; i < cnt; i += 4) {
+ buf.append(' ');
+ if (attributes[i + 1] != null)
+ buf.append(
+ "{"
+ + attributes[i]
+ + "}"
+ + attributes[i
+ + 1]
+ + ":");
+ buf.append(
+ attributes[i
+ + 2]
+ + "='"
+ + attributes[i
+ + 3]
+ + "'");
+ }
+
+ buf.append('>');
+ }
+ else if (type == IGNORABLE_WHITESPACE);
+ else if (type != TEXT)
+ buf.append(getText());
+ else if (isWhitespace)
+ buf.append("(whitespace)");
+ else {
+ String text = getText();
+ if (text.length() > 16)
+ text = text.substring(0, 16) + "...";
+ buf.append(text);
+ }
+
+ return buf.toString();
+ }
+
+ public int getLineNumber() {
+ return -1;
+ }
+
+ public int getColumnNumber() {
+ return -1;
+ }
+
+ public boolean isWhitespace()
+ throws XmlPullParserException {
+ if (type != TEXT
+ && type != IGNORABLE_WHITESPACE
+ && type != CDSECT)
+ exception(ILLEGAL_TYPE);
+ return isWhitespace;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public char[] getTextCharacters(int[] poslen) {
+ if (type >= TEXT) {
+ poslen[0] = 0;
+ poslen[1] = text.length();
+ char[] buf = new char[text.length()];
+ text.getChars(0, text.length(), buf, 0);
+ return buf;
+ }
+
+ poslen[0] = -1;
+ poslen[1] = -1;
+ return null;
+ }
+
+ public String getNamespace() {
+ return namespace;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPrefix() {
+ return prefix;
+ }
+
+ public boolean isEmptyElementTag()
+ throws XmlPullParserException {
+ if (type != START_TAG)
+ exception(ILLEGAL_TYPE);
+ return degenerated;
+ }
+
+ public int getAttributeCount() {
+ return attributeCount;
+ }
+
+ public String getAttributeType(int index) {
+ return "CDATA";
+ }
+
+ public boolean isAttributeDefault(int index) {
+ return false;
+ }
+
+ public String getAttributeNamespace(int index) {
+ if (index >= attributeCount)
+ throw new IndexOutOfBoundsException();
+ return attributes[index << 2];
+ }
+
+ public String getAttributeName(int index) {
+ if (index >= attributeCount)
+ throw new IndexOutOfBoundsException();
+ return attributes[(index << 2) + 2];
+ }
+
+ public String getAttributePrefix(int index) {
+ if (index >= attributeCount)
+ throw new IndexOutOfBoundsException();
+ return attributes[(index << 2) + 1];
+ }
+
+ public String getAttributeValue(int index) {
+ if (index >= attributeCount)
+ throw new IndexOutOfBoundsException();
+ return attributes[(index << 2) + 3];
+ }
+
+ public String getAttributeValue(
+ String namespace,
+ String name) {
+
+ for (int i = (attributeCount << 2) - 4;
+ i >= 0;
+ i -= 4) {
+ if (attributes[i + 2].equals(name)
+ && (namespace == null
+ || attributes[i].equals(namespace)))
+ return attributes[i + 3];
+ }
+
+ return null;
+ }
+
+ public int getEventType() throws XmlPullParserException {
+ return type;
+ }
+
+ public int next() throws XmlPullParserException, IOException {
+
+ isWhitespace = true;
+ int minType = 9999;
+
+ while (true) {
+
+ String save = text;
+
+ nextImpl();
+
+ if (type < minType)
+ minType = type;
+
+ if (minType > CDSECT) continue; // no "real" event so far
+
+ if (minType >= TEXT) { // text, see if accumulate
+
+ if (save != null) text = text == null ? save : save + text;
+
+ switch(peekId()) {
+ case Wbxml.ENTITY:
+ case Wbxml.STR_I:
+ case Wbxml.LITERAL:
+ case Wbxml.LITERAL_C:
+ case Wbxml.LITERAL_A:
+ case Wbxml.LITERAL_AC: continue;
+ }
+ }
+
+ break;
+ }
+
+ type = minType;
+
+ if (type > TEXT)
+ type = TEXT;
+
+ return type;
+ }
+
+
+ public int nextToken() throws XmlPullParserException, IOException {
+
+ isWhitespace = true;
+ nextImpl();
+ return type;
+ }
+
+
+
+ public int nextTag() throws XmlPullParserException, IOException {
+
+ next();
+ if (type == TEXT && isWhitespace)
+ next();
+
+ if (type != END_TAG && type != START_TAG)
+ exception("unexpected type");
+
+ return type;
+ }
+
+
+ public String nextText() throws XmlPullParserException, IOException {
+ if (type != START_TAG)
+ exception("precondition: START_TAG");
+
+ next();
+
+ String result;
+
+ if (type == TEXT) {
+ result = getText();
+ next();
+ }
+ else
+ result = "";
+
+ if (type != END_TAG)
+ exception("END_TAG expected");
+
+ return result;
+ }
+
+
+ public void require(int type, String namespace, String name)
+ throws XmlPullParserException, IOException {
+
+ if (type != this.type
+ || (namespace != null && !namespace.equals(getNamespace()))
+ || (name != null && !name.equals(getName())))
+ exception(
+ "expected: " + TYPES[type] + " {" + namespace + "}" + name);
+ }
+
+
+ public void setInput(Reader reader) throws XmlPullParserException {
+ exception("InputStream required");
+ }
+
+ public void setInput(InputStream in, String enc)
+ throws XmlPullParserException {
+
+ this.in = in;
+
+ try {
+ version = readByte();
+ publicIdentifierId = readInt();
+
+ if (publicIdentifierId == 0)
+ readInt();
+
+ int charset = readInt(); // skip charset
+
+ if (null == enc){
+ switch (charset){
+ case 4: encoding = "ISO-8859-1"; break;
+ case 106: encoding = "UTF-8"; break;
+ // add more if you need them
+ // http://www.iana.org/assignments/character-sets
+ // case MIBenum: encoding = Name break;
+ default: throw new UnsupportedEncodingException(""+charset);
+ }
+ }else{
+ encoding = enc;
+ }
+
+ int strTabSize = readInt();
+ stringTable = new byte[strTabSize];
+
+ int ok = 0;
+ while(ok < strTabSize){
+ int cnt = in.read(stringTable, ok, strTabSize - ok);
+ if(cnt <= 0) break;
+ ok += cnt;
+ }
+
+ selectPage(0, true);
+ selectPage(0, false);
+ }
+ catch (IOException e) {
+ exception("Illegal input format");
+ }
+ }
+
+ public void setFeature(String feature, boolean value)
+ throws XmlPullParserException {
+ if (XmlPullParser.FEATURE_PROCESS_NAMESPACES.equals(feature))
+ processNsp = value;
+ else
+ exception("unsupported feature: " + feature);
+ }
+
+ public void setProperty(String property, Object value)
+ throws XmlPullParserException {
+ throw new XmlPullParserException("unsupported property: " + property);
+ }
+
+ // ---------------------- private / internal methods
+
+ private final boolean adjustNsp()
+ throws XmlPullParserException {
+
+ boolean any = false;
+
+ for (int i = 0; i < attributeCount << 2; i += 4) {
+ // * 4 - 4; i >= 0; i -= 4) {
+
+ String attrName = attributes[i + 2];
+ int cut = attrName.indexOf(':');
+ String prefix;
+
+ if (cut != -1) {
+ prefix = attrName.substring(0, cut);
+ attrName = attrName.substring(cut + 1);
+ }
+ else if (attrName.equals("xmlns")) {
+ prefix = attrName;
+ attrName = null;
+ }
+ else
+ continue;
+
+ if (!prefix.equals("xmlns")) {
+ any = true;
+ }
+ else {
+ int j = (nspCounts[depth]++) << 1;
+
+ nspStack = ensureCapacity(nspStack, j + 2);
+ nspStack[j] = attrName;
+ nspStack[j + 1] = attributes[i + 3];
+
+ if (attrName != null
+ && attributes[i + 3].equals(""))
+ exception("illegal empty namespace");
+
+ // prefixMap = new PrefixMap (prefixMap, attrName, attr.getValue ());
+
+ //System.out.println (prefixMap);
+
+ System.arraycopy(
+ attributes,
+ i + 4,
+ attributes,
+ i,
+ ((--attributeCount) << 2) - i);
+
+ i -= 4;
+ }
+ }
+
+ if (any) {
+ for (int i = (attributeCount << 2) - 4;
+ i >= 0;
+ i -= 4) {
+
+ String attrName = attributes[i + 2];
+ int cut = attrName.indexOf(':');
+
+ if (cut == 0)
+ throw new RuntimeException(
+ "illegal attribute name: "
+ + attrName
+ + " at "
+ + this);
+
+ else if (cut != -1) {
+ String attrPrefix =
+ attrName.substring(0, cut);
+
+ attrName = attrName.substring(cut + 1);
+
+ String attrNs = getNamespace(attrPrefix);
+
+ if (attrNs == null)
+ throw new RuntimeException(
+ "Undefined Prefix: "
+ + attrPrefix
+ + " in "
+ + this);
+
+ attributes[i] = attrNs;
+ attributes[i + 1] = attrPrefix;
+ attributes[i + 2] = attrName;
+
+ for (int j = (attributeCount << 2) - 4;
+ j > i;
+ j -= 4)
+ if (attrName.equals(attributes[j + 2])
+ && attrNs.equals(attributes[j]))
+ exception(
+ "Duplicate Attribute: {"
+ + attrNs
+ + "}"
+ + attrName);
+ }
+ }
+ }
+
+ int cut = name.indexOf(':');
+
+ if (cut == 0)
+ exception("illegal tag name: " + name);
+ else if (cut != -1) {
+ prefix = name.substring(0, cut);
+ name = name.substring(cut + 1);
+ }
+
+ this.namespace = getNamespace(prefix);
+
+ if (this.namespace == null) {
+ if (prefix != null)
+ exception("undefined prefix: " + prefix);
+ this.namespace = NO_NAMESPACE;
+ }
+
+ return any;
+ }
+
+ private final void setTable(int page, int type, String[] table) {
+ if(stringTable != null){
+ throw new RuntimeException("setXxxTable must be called before setInput!");
+ }
+ while(tables.size() < 3*page +3){
+ tables.addElement(null);
+ }
+ tables.setElementAt(table, page*3+type);
+ }
+
+
+
+
+
+ private final void exception(String desc)
+ throws XmlPullParserException {
+ throw new XmlPullParserException(desc, this, null);
+ }
+
+
+ private void selectPage(int nr, boolean tags) throws XmlPullParserException{
+ if(tables.size() == 0 && nr == 0) return;
+
+ if(nr*3 > tables.size())
+ exception("Code Page "+nr+" undefined!");
+
+ if(tags)
+ tagTable = (String[]) tables.elementAt(nr * 3 + TAG_TABLE);
+ else {
+ attrStartTable = (String[]) tables.elementAt(nr * 3 + ATTR_START_TABLE);
+ attrValueTable = (String[]) tables.elementAt(nr * 3 + ATTR_VALUE_TABLE);
+ }
+ }
+
+ private final void nextImpl()
+ throws IOException, XmlPullParserException {
+
+ String s;
+
+ if (type == END_TAG) {
+ depth--;
+ }
+
+ if (degenerated) {
+ type = XmlPullParser.END_TAG;
+ degenerated = false;
+ return;
+ }
+
+ text = null;
+ prefix = null;
+ name = null;
+
+ int id = peekId ();
+ while(id == Wbxml.SWITCH_PAGE){
+ nextId = -2;
+ selectPage(readByte(), true);
+ id = peekId();
+ }
+ nextId = -2;
+
+ switch (id) {
+ case -1 :
+ type = XmlPullParser.END_DOCUMENT;
+ break;
+
+ case Wbxml.END :
+ {
+ int sp = (depth - 1) << 2;
+
+ type = END_TAG;
+ namespace = elementStack[sp];
+ prefix = elementStack[sp + 1];
+ name = elementStack[sp + 2];
+ }
+ break;
+
+ case Wbxml.ENTITY :
+ {
+ type = ENTITY_REF;
+ char c = (char) readInt();
+ text = "" + c;
+ name = "#" + ((int) c);
+ }
+
+ break;
+
+ case Wbxml.STR_I :
+ type = TEXT;
+ text = readStrI();
+ break;
+
+ case Wbxml.EXT_I_0 :
+ case Wbxml.EXT_I_1 :
+ case Wbxml.EXT_I_2 :
+ case Wbxml.EXT_T_0 :
+ case Wbxml.EXT_T_1 :
+ case Wbxml.EXT_T_2 :
+ case Wbxml.EXT_0 :
+ case Wbxml.EXT_1 :
+ case Wbxml.EXT_2 :
+ case Wbxml.OPAQUE :
+ parseWapExtension(id);
+ break;
+
+ case Wbxml.PI :
+ throw new RuntimeException("PI curr. not supp.");
+ // readPI;
+ // break;
+
+ case Wbxml.STR_T :
+ {
+ type = TEXT;
+ text = readStrT();
+ }
+ break;
+
+ default :
+ parseElement(id);
+ }
+ // }
+ // while (next == null);
+
+ // return next;
+ }
+
+
+
+ public void parseWapExtension(int id)
+ throws IOException, XmlPullParserException {
+
+ type = WAP_EXTENSION;
+ wapExtensionCode = id;
+
+ switch (id) {
+ case Wbxml.EXT_I_0 :
+ case Wbxml.EXT_I_1 :
+ case Wbxml.EXT_I_2 :
+ wapExtensionData = readStrI();
+ break;
+
+ case Wbxml.EXT_T_0 :
+ case Wbxml.EXT_T_1 :
+ case Wbxml.EXT_T_2 :
+ wapExtensionData = new Integer(readInt());
+ break;
+
+ case Wbxml.EXT_0 :
+ case Wbxml.EXT_1 :
+ case Wbxml.EXT_2 :
+ break;
+
+ case Wbxml.OPAQUE :
+ {
+ int len = readInt();
+ byte[] buf = new byte[len];
+
+ for (int i = 0;
+ i < len;
+ i++) // enhance with blockread!
+ buf[i] = (byte) readByte();
+
+ wapExtensionData = buf;
+ } // case OPAQUE
+ break;
+
+ default:
+ exception("illegal id: "+id);
+ } // SWITCH
+ }
+
+ public void readAttr() throws IOException, XmlPullParserException {
+
+ int id = readByte();
+ int i = 0;
+
+ while (id != 1) {
+
+ while(id == Wbxml.SWITCH_PAGE){
+ selectPage(readByte(), false);
+ id = readByte();
+ }
+
+ String name = resolveId(attrStartTable, id);
+ StringBuffer value;
+
+ int cut = name.indexOf('=');
+
+ if (cut == -1)
+ value = new StringBuffer();
+ else {
+ value =
+ new StringBuffer(name.substring(cut + 1));
+ name = name.substring(0, cut);
+ }
+
+ id = readByte();
+ while (id > 128
+ || id == Wbxml.SWITCH_PAGE
+ || id == Wbxml.ENTITY
+ || id == Wbxml.STR_I
+ || id == Wbxml.STR_T
+ || (id >= Wbxml.EXT_I_0 && id <= Wbxml.EXT_I_2)
+ || (id >= Wbxml.EXT_T_0 && id <= Wbxml.EXT_T_2)) {
+
+ switch (id) {
+ case Wbxml.SWITCH_PAGE :
+ selectPage(readByte(), false);
+ break;
+
+ case Wbxml.ENTITY :
+ value.append((char) readInt());
+ break;
+
+ case Wbxml.STR_I :
+ value.append(readStrI());
+ break;
+
+ case Wbxml.EXT_I_0 :
+ case Wbxml.EXT_I_1 :
+ case Wbxml.EXT_I_2 :
+ case Wbxml.EXT_T_0 :
+ case Wbxml.EXT_T_1 :
+ case Wbxml.EXT_T_2 :
+ case Wbxml.EXT_0 :
+ case Wbxml.EXT_1 :
+ case Wbxml.EXT_2 :
+ case Wbxml.OPAQUE :
+
+ throw new RuntimeException("wap extension in attr not supported yet");
+
+ /*
+ ParseEvent e = parseWapExtension(id);
+ if (!(e.getType() != Xml.TEXT
+ && e.getType() != Xml.WHITESPACE))
+ throw new RuntimeException("parse WapExtension must return Text Event in order to work inside Attributes!");
+
+ value.append(e.getText());
+
+ //value.append (handleExtension (id)); // skip EXT in ATTR
+ //break;
+ */
+
+ case Wbxml.STR_T :
+ value.append(readStrT());
+ break;
+
+ default :
+ value.append(
+ resolveId(attrValueTable, id));
+ }
+
+ id = readByte();
+ }
+
+ attributes = ensureCapacity(attributes, i + 4);
+
+ attributes[i++] = "";
+ attributes[i++] = null;
+ attributes[i++] = name;
+ attributes[i++] = value.toString();
+
+ attributeCount++;
+ }
+ }
+
+ private int peekId () throws IOException {
+ if (nextId == -2) {
+ nextId = in.read ();
+ }
+ return nextId;
+ }
+
+
+
+
+ String resolveId(String[] tab, int id) throws IOException {
+ int idx = (id & 0x07f) - 5;
+ if (idx == -1)
+ return readStrT();
+ if (idx < 0
+ || tab == null
+ || idx >= tab.length
+ || tab[idx] == null)
+ throw new IOException("id " + id + " undef.");
+
+ return tab[idx];
+ }
+
+ void parseElement(int id)
+ throws IOException, XmlPullParserException {
+
+ type = START_TAG;
+ name = resolveId(tagTable, id & 0x03f);
+
+ attributeCount = 0;
+ if ((id & 128) != 0) {
+ readAttr();
+ }
+
+ degenerated = (id & 64) == 0;
+
+ int sp = depth++ << 2;
+
+ // transfer to element stack
+
+ elementStack = ensureCapacity(elementStack, sp + 4);
+ elementStack[sp + 3] = name;
+
+ if (depth >= nspCounts.length) {
+ int[] bigger = new int[depth + 4];
+ System.arraycopy(nspCounts, 0, bigger, 0, nspCounts.length);
+ nspCounts = bigger;
+ }
+
+ nspCounts[depth] = nspCounts[depth - 1];
+
+ for (int i = attributeCount - 1; i > 0; i--) {
+ for (int j = 0; j < i; j++) {
+ if (getAttributeName(i)
+ .equals(getAttributeName(j)))
+ exception(
+ "Duplicate Attribute: "
+ + getAttributeName(i));
+ }
+ }
+
+ if (processNsp)
+ adjustNsp();
+ else
+ namespace = "";
+
+ elementStack[sp] = namespace;
+ elementStack[sp + 1] = prefix;
+ elementStack[sp + 2] = name;
+
+ }
+
+ private final String[] ensureCapacity(
+ String[] arr,
+ int required) {
+ if (arr.length >= required)
+ return arr;
+ String[] bigger = new String[required + 16];
+ System.arraycopy(arr, 0, bigger, 0, arr.length);
+ return bigger;
+ }
+
+ int readByte() throws IOException {
+ int i = in.read();
+ if (i == -1)
+ throw new IOException("Unexpected EOF");
+ return i;
+ }
+
+ int readInt() throws IOException {
+ int result = 0;
+ int i;
+
+ do {
+ i = readByte();
+ result = (result << 7) | (i & 0x7f);
+ }
+ while ((i & 0x80) != 0);
+
+ return result;
+ }
+
+ String readStrI() throws IOException {
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ boolean wsp = true;
+ while (true){
+ int i = in.read();
+ if (i == 0){
+ break;
+ }
+ if (i == -1){
+ throw new IOException(UNEXPECTED_EOF);
+ }
+ if (i > 32){
+ wsp = false;
+ }
+ buf.write(i);
+ }
+ isWhitespace = wsp;
+ String result = new String(buf.toByteArray(), encoding);
+ buf.close();
+ return result;
+ }
+
+ String readStrT() throws IOException {
+ int pos = readInt();
+ // As the main reason of stringTable is compression we build a cache of Strings
+ // stringTable is supposed to help create Strings from parts which means some cache hit rate
+ // This will help to minimize the Strings created when invoking readStrT() repeatedly
+ if (cacheStringTable == null){
+ //Lazy init if device is not using StringTable but inline 0x03 strings
+ cacheStringTable = new Hashtable();
+ }
+ String forReturn = (String) cacheStringTable.get(new Integer(pos));
+ if (forReturn == null){
+
+ int end = pos;
+ while(end < stringTable.length && stringTable[end] != '\0'){
+ end++;
+ }
+ forReturn = new String(stringTable, pos, end-pos, encoding);
+ cacheStringTable.put(new Integer(pos), forReturn);
+ }
+ return forReturn;
+ }
+
+ /**
+ * Sets the tag table for a given page.
+ * The first string in the array defines tag 5, the second tag 6 etc.
+ */
+
+ public void setTagTable(int page, String[] table) {
+ setTable(page, TAG_TABLE, table);
+
+ // this.tagTable = tagTable;
+ // if (page != 0)
+ // throw new RuntimeException("code pages curr. not supp.");
+ }
+
+ /** Sets the attribute start Table for a given page.
+ * The first string in the array defines attribute
+ * 5, the second attribute 6 etc. Please use the
+ * character '=' (without quote!) as delimiter
+ * between the attribute name and the (start of the) value
+ */
+
+ public void setAttrStartTable(
+ int page,
+ String[] table) {
+
+ setTable(page, ATTR_START_TABLE, table);
+ }
+
+ /** Sets the attribute value Table for a given page.
+ * The first string in the array defines attribute value 0x85,
+ * the second attribute value 0x86 etc.
+ */
+
+ public void setAttrValueTable(
+ int page,
+ String[] table) {
+
+ setTable(page, ATTR_VALUE_TABLE, table);
+ }
+
+}
diff --git a/xml/src/main/java/org/kxml2/wap/WbxmlSerializer.java b/xml/src/main/java/org/kxml2/wap/WbxmlSerializer.java
new file mode 100644
index 0000000..e4447b0
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/wap/WbxmlSerializer.java
@@ -0,0 +1,418 @@
+/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE. */
+
+//Contributors: Bogdan Onoiu (Genderal character encoding abstraction and UTF-8 Support)
+
+package org.kxml2.wap;
+
+import java.io.*;
+import java.util.*;
+
+import org.xmlpull.v1.*;
+
+// TODO: make some of the "direct" WBXML token writing methods public??
+
+/**
+ * A class for writing WBXML.
+ *
+ */
+
+
+
+public class WbxmlSerializer implements XmlSerializer {
+
+ Hashtable stringTable = new Hashtable();
+
+ OutputStream out;
+
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ ByteArrayOutputStream stringTableBuf = new ByteArrayOutputStream();
+
+ String pending;
+ int depth;
+ String name;
+ String namespace;
+ Vector attributes = new Vector();
+
+ Hashtable attrStartTable = new Hashtable();
+ Hashtable attrValueTable = new Hashtable();
+ Hashtable tagTable = new Hashtable();
+
+ private int attrPage;
+ private int tagPage;
+
+ private String encoding = null;
+
+
+ public XmlSerializer attribute(String namespace, String name, String value) {
+ attributes.addElement(name);
+ attributes.addElement(value);
+ return this;
+ }
+
+
+ public void cdsect (String cdsect) throws IOException{
+ text (cdsect);
+ }
+
+
+
+ /* silently ignore comment */
+
+ public void comment (String comment) {
+ }
+
+
+ public void docdecl (String docdecl) {
+ throw new RuntimeException ("Cannot write docdecl for WBXML");
+ }
+
+
+ public void entityRef (String er) {
+ throw new RuntimeException ("EntityReference not supported for WBXML");
+ }
+
+ public int getDepth() {
+ return depth;
+ }
+
+
+ public boolean getFeature (String name) {
+ return false;
+ }
+
+ public String getNamespace() {
+ throw new RuntimeException("NYI");
+ }
+
+ public String getName() {
+ throw new RuntimeException("NYI");
+ }
+
+ public String getPrefix(String nsp, boolean create) {
+ throw new RuntimeException ("NYI");
+ }
+
+
+ public Object getProperty (String name) {
+ return null;
+ }
+
+ public void ignorableWhitespace (String sp) {
+ }
+
+
+ public void endDocument() throws IOException {
+ writeInt(out, stringTableBuf.size());
+
+ // write StringTable
+
+ out.write(stringTableBuf.toByteArray());
+
+ // write buf
+
+ out.write(buf.toByteArray());
+
+ // ready!
+
+ out.flush();
+ }
+
+
+ /** ATTENTION: flush cannot work since Wbxml documents require
+ need buffering. Thus, this call does nothing. */
+
+ public void flush() {
+ }
+
+
+ public void checkPending(boolean degenerated) throws IOException {
+ if (pending == null)
+ return;
+
+ int len = attributes.size();
+
+ int[] idx = (int[]) tagTable.get(pending);
+
+ // if no entry in known table, then add as literal
+ if (idx == null) {
+ buf.write(
+ len == 0
+ ? (degenerated ? Wbxml.LITERAL : Wbxml.LITERAL_C)
+ : (degenerated ? Wbxml.LITERAL_A : Wbxml.LITERAL_AC));
+
+ writeStrT(pending);
+ }
+ else {
+ if(idx[0] != tagPage){
+ tagPage=idx[0];
+ buf.write(0);
+ buf.write(tagPage);
+ }
+
+ buf.write(
+ len == 0
+ ? (degenerated ? idx[1] : idx[1] | 64)
+ : (degenerated
+ ? idx[1] | 128
+ : idx[1] | 192));
+
+ }
+
+ for (int i = 0; i < len;) {
+ idx = (int[]) attrStartTable.get(attributes.elementAt(i));
+
+ if (idx == null) {
+ buf.write(Wbxml.LITERAL);
+ writeStrT((String) attributes.elementAt(i));
+ }
+ else {
+ if(idx[0] != attrPage){
+ attrPage = idx[1];
+ buf.write(0);
+ buf.write(attrPage);
+ }
+ buf.write(idx[1]);
+ }
+ idx = (int[]) attrValueTable.get(attributes.elementAt(++i));
+ if (idx == null) {
+ buf.write(Wbxml.STR_I);
+ writeStrI(buf, (String) attributes.elementAt(i));
+ }
+ else {
+ if(idx[0] != attrPage){
+ attrPage = idx[1];
+ buf.write(0);
+ buf.write(attrPage);
+ }
+ buf.write(idx[1]);
+ }
+ ++i;
+ }
+
+ if (len > 0)
+ buf.write(Wbxml.END);
+
+ pending = null;
+ attributes.removeAllElements();
+ }
+
+
+ public void processingInstruction(String pi) {
+ throw new RuntimeException ("PI NYI");
+ }
+
+
+ public void setFeature(String name, boolean value) {
+ throw new IllegalArgumentException ("unknown feature "+name);
+ }
+
+
+
+ public void setOutput (Writer writer) {
+ throw new RuntimeException ("Wbxml requires an OutputStream!");
+ }
+
+ public void setOutput (OutputStream out, String encoding) throws IOException {
+
+ if (encoding != null) throw new IllegalArgumentException ("encoding not yet supported for WBXML");
+
+ this.out = out;
+
+ buf = new ByteArrayOutputStream();
+ stringTableBuf = new ByteArrayOutputStream();
+
+ // ok, write header
+ }
+
+
+ public void setPrefix(String prefix, String nsp) {
+ throw new RuntimeException("NYI");
+ }
+
+ public void setProperty(String property, Object value) {
+ throw new IllegalArgumentException ("unknown property "+property);
+ }
+
+
+ public void startDocument(String s, Boolean b) throws IOException{
+ out.write(0x03); // version 1.3
+ // http://www.openmobilealliance.org/tech/omna/omna-wbxml-public-docid.htm
+ out.write(0x01); // unknown or missing public identifier
+
+ // default encoding is UTF-8
+ String[] encodings = { "UTF-8", "ISO-8859-1" };
+ if (s == null || s.toUpperCase().equals(encodings[0])){
+ encoding = encodings[0];
+ out.write(106);
+ }else if (true == s.toUpperCase().equals(encodings[1])){
+ encoding = encodings[1];
+ out.write(0x04);
+ }else{
+ throw new UnsupportedEncodingException(s);
+ }
+ }
+
+
+ public XmlSerializer startTag(String namespace, String name) throws IOException {
+
+ if (namespace != null && !"".equals(namespace))
+ throw new RuntimeException ("NSP NYI");
+
+ //current = new State(current, prefixMap, name);
+
+ checkPending(false);
+ pending = name;
+ depth++;
+
+ return this;
+ }
+
+ public XmlSerializer text(char[] chars, int start, int len) throws IOException {
+
+ checkPending(false);
+
+ buf.write(Wbxml.STR_I);
+ writeStrI(buf, new String(chars, start, len));
+
+ return this;
+ }
+
+ public XmlSerializer text(String text) throws IOException {
+
+ checkPending(false);
+
+ buf.write(Wbxml.STR_I);
+ writeStrI(buf, text);
+
+ return this;
+ }
+
+
+
+ public XmlSerializer endTag(String namespace, String name) throws IOException {
+
+ // current = current.prev;
+
+ if (pending != null)
+ checkPending(true);
+ else
+ buf.write(Wbxml.END);
+
+ depth--;
+
+ return this;
+ }
+
+ /** currently ignored! */
+
+ public void writeLegacy(int type, String data) {
+ }
+
+ // ------------- internal methods --------------------------
+
+ static void writeInt(OutputStream out, int i) throws IOException {
+ byte[] buf = new byte[5];
+ int idx = 0;
+
+ do {
+ buf[idx++] = (byte) (i & 0x7f);
+ i = i >> 7;
+ }
+ while (i != 0);
+
+ while (idx > 1) {
+ out.write(buf[--idx] | 0x80);
+ }
+ out.write(buf[0]);
+ }
+
+ static void writeStrI(OutputStream out, String s) throws IOException {
+ for (int i = 0; i < s.length(); i++) {
+ out.write((byte) s.charAt(i));
+ }
+ out.write(0);
+ }
+
+ void writeStrT(String s) throws IOException {
+
+ Integer idx = (Integer) stringTable.get(s);
+
+ if (idx == null) {
+ idx = new Integer(stringTableBuf.size());
+ stringTable.put(s, idx);
+ writeStrI(stringTableBuf, s);
+ stringTableBuf.flush();
+ }
+
+ writeInt(buf, idx.intValue());
+ }
+
+ /**
+ * Sets the tag table for a given page.
+ * The first string in the array defines tag 5, the second tag 6 etc.
+ */
+
+ public void setTagTable(int page, String[] tagTable) {
+ // clear entries in tagTable!
+ if (page != 0)
+ return;
+
+ for (int i = 0; i < tagTable.length; i++) {
+ if (tagTable[i] != null) {
+ Object idx = new int[]{page, i+5};
+ this.tagTable.put(tagTable[i], idx);
+ }
+ }
+ }
+
+ /**
+ * Sets the attribute start Table for a given page.
+ * The first string in the array defines attribute
+ * 5, the second attribute 6 etc.
+ * Please use the
+ * character '=' (without quote!) as delimiter
+ * between the attribute name and the (start of the) value
+ */
+ public void setAttrStartTable(int page, String[] attrStartTable) {
+
+ for (int i = 0; i < attrStartTable.length; i++) {
+ if (attrStartTable[i] != null) {
+ Object idx = new int[] {page, i + 5};
+ this.attrStartTable.put(attrStartTable[i], idx);
+ }
+ }
+ }
+
+ /**
+ * Sets the attribute value Table for a given page.
+ * The first string in the array defines attribute value 0x85,
+ * the second attribute value 0x86 etc.
+ */
+ public void setAttrValueTable(int page, String[] attrValueTable) {
+ // clear entries in this.table!
+ for (int i = 0; i < attrValueTable.length; i++) {
+ if (attrValueTable[i] != null) {
+ Object idx = new int[]{page, i + 0x085};
+ this.attrValueTable.put(attrValueTable[i], idx);
+ }
+ }
+ }
+}
diff --git a/xml/src/main/java/org/kxml2/wap/syncml/SyncML.java b/xml/src/main/java/org/kxml2/wap/syncml/SyncML.java
new file mode 100644
index 0000000..5ea8496
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/wap/syncml/SyncML.java
@@ -0,0 +1,192 @@
+package org.kxml2.wap.syncml;
+
+import org.kxml2.wap.*;
+
+public abstract class SyncML {
+
+
+ // SyncML-Common (-//SYNCML//DTD SyncML 1.2//EN and -//SYNCML//DTD MetInf 1.2//EN) support
+
+ public static WbxmlParser createParser() {
+ WbxmlParser p = new WbxmlParser();
+ p.setTagTable(0, TAG_TABLE_0);
+ p.setTagTable(1, TAG_TABLE_1);
+ return p;
+ }
+
+ public static WbxmlSerializer createSerializer() {
+ WbxmlSerializer s = new WbxmlSerializer();
+ s.setTagTable(0, TAG_TABLE_0);
+ s.setTagTable(1, TAG_TABLE_1);
+ return s;
+ }
+
+
+ // SyncML-Common + DMDDF (-//OMA//DTD-DM-DDF 1.2//EN) support
+
+ public static WbxmlParser createDMParser() {
+ WbxmlParser p = createParser();
+ p.setTagTable(2, TAG_TABLE_2_DM);
+ return p;
+ }
+
+ public static WbxmlSerializer createDMSerializer() {
+ WbxmlSerializer s = createSerializer();
+ s.setTagTable(2, TAG_TABLE_2_DM);
+ return s;
+ }
+
+ // Tables
+
+ public static final String [] TAG_TABLE_0 = {
+
+ // -//SYNCML//DTD SyncML 1.2//EN
+
+ "Add", // 0x05
+ "Alert", // 0x06
+ "Archive", // 0x07
+ "Atomic", // 0x08
+ "Chal", // 0x09
+ "Cmd", // 0x0a
+ "CmdID", // 0x0b
+ "CmdRef", // 0x0c
+ "Copy", // 0x0d
+ "Cred", // 0x0e
+ "Data", // 0x0f
+ "Delete", // 0x10
+ "Exec", // 0x11
+ "Final", // 0x12
+ "Get", // 0x13
+ "Item", // 0x14
+ "Lang", // 0x15
+ "LocName", // 0x16
+ "LocURI", // 0x17
+ "Map", // 0x18
+ "MapItem", // 0x19
+ "Meta", // 0x1a
+ "MsgID", // 0x1b
+ "MsgRef", // 0x1c
+ "NoResp", // 0x1d
+ "NoResults", // 0x1e
+ "Put", // 0x1f
+ "Replace", // 0x20
+ "RespURI", // 0x21
+ "Results", // 0x22
+ "Search", // 0x23
+ "Sequence", // 0x24
+ "SessionID", // 0x25
+ "SftDel", // 0x26
+ "Source", // 0x27
+ "SourceRef", // 0x28
+ "Status", // 0x29
+ "Sync", // 0x2a
+ "SyncBody", // 0x2b
+ "SyncHdr", // 0x2c
+ "SyncML", // 0x2d
+ "Target", // 0x2e
+ "TargetRef", // 0x2f
+ "Reserved for future use", // 0x30
+ "VerDTD", // 0x31
+ "VerProto", // 0x32
+ "NumberOfChanged",// 0x33
+ "MoreData", // 0x34
+ "Field", // 0x35
+ "Filter", // 0x36
+ "Record", // 0x37
+ "FilterType", // 0x38
+ "SourceParent", // 0x39
+ "TargetParent", // 0x3a
+ "Move", // 0x3b
+ "Correlator" // 0x3c
+ };
+
+ public static final String [] TAG_TABLE_1 = {
+
+ // -//SYNCML//DTD MetInf 1.2//EN
+
+ "Anchor", // 0x05
+ "EMI", // 0x06
+ "Format", // 0x07
+ "FreeID", // 0x08
+ "FreeMem", // 0x09
+ "Last", // 0x0a
+ "Mark", // 0x0b
+ "MaxMsgSize", // 0x0c
+ "Mem", // 0x0d
+ "MetInf", // 0x0e
+ "Next", // 0x0f
+ "NextNonce", // 0x10
+ "SharedMem", // 0x11
+ "Size", // 0x12
+ "Type", // 0x13
+ "Version", // 0x14
+ "MaxObjSize", // 0x15
+ "FieldLevel" // 0x16
+
+ };
+
+ public static final String [] TAG_TABLE_2_DM = {
+
+ // -//OMA//DTD-DM-DDF 1.2//EN
+
+ "AccessType", // 0x05
+ "ACL", // 0x06
+ "Add", // 0x07
+ "b64", // 0x08
+ "bin", // 0x09
+ "bool", // 0x0a
+ "chr", // 0x0b
+ "CaseSense", // 0x0c
+ "CIS", // 0x0d
+ "Copy", // 0x0e
+ "CS", // 0x0f
+ "date", // 0x10
+ "DDFName", // 0x11
+ "DefaultValue", // 0x12
+ "Delete", // 0x13
+ "Description", // 0x14
+ "DDFFormat", // 0x15
+ "DFProperties", // 0x16
+ "DFTitle", // 0x17
+ "DFType", // 0x18
+ "Dynamic", // 0x19
+ "Exec", // 0x1a
+ "float", // 0x1b
+ "Format", // 0x1c
+ "Get", // 0x1d
+ "int", // 0x1e
+ "Man", // 0x1f
+ "MgmtTree", // 0x20
+ "MIME", // 0x21
+ "Mod", // 0x22
+ "Name", // 0x23
+ "Node", // 0x24
+ "node", // 0x25
+ "NodeName", // 0x26
+ "null", // 0x27
+ "Occurence", // 0x28
+ "One", // 0x29
+ "OneOrMore", // 0x2a
+ "OneOrN", // 0x2b
+ "Path", // 0x2c
+ "Permanent", // 0x2d
+ "Replace", // 0x2e
+ "RTProperties", // 0x2f
+ "Scope", // 0x30
+ "Size", // 0x31
+ "time", // 0x32
+ "Title", // 0x33
+ "TStamp", // 0x34
+ "Type", // 0x35
+ "Value", // 0x36
+ "VerDTD", // 0x37
+ "VerNo", // 0x38
+ "xml", // 0x39
+ "ZeroOrMore", // 0x3a
+ "ZeroOrN", // 0x3b
+ "ZeroOrOne" // 0x3c
+
+ };
+
+}
+
diff --git a/xml/src/main/java/org/kxml2/wap/wml/Wml.java b/xml/src/main/java/org/kxml2/wap/wml/Wml.java
new file mode 100644
index 0000000..7e925d8
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/wap/wml/Wml.java
@@ -0,0 +1,233 @@
+package org.kxml2.wap.wml;
+
+import org.kxml2.wap.*;
+
+
+/** This class contains the wml coding tables for elements
+ * and attributes needed by the WmlParser.
+ */
+
+
+public abstract class Wml {
+
+ /** Creates a WbxmlParser with the WML code pages set */
+
+ public static WbxmlParser createParser() {
+ WbxmlParser p = new WbxmlParser();
+ p.setTagTable(0, TAG_TABLE);
+ p.setAttrStartTable(0, ATTR_START_TABLE);
+ p.setAttrValueTable(0, ATTR_VALUE_TABLE);
+ return p;
+ }
+
+ public static WbxmlSerializer createSerializer() {
+ WbxmlSerializer s = new WbxmlSerializer();
+ s.setTagTable(0, TAG_TABLE);
+ s.setAttrStartTable(0, ATTR_START_TABLE);
+ s.setAttrValueTable(0, ATTR_VALUE_TABLE);
+ return s;
+ }
+
+
+ public static final String [] TAG_TABLE = {
+
+ null, // 05
+ null, // 06
+ null, // 07
+ null, // 08
+ null, // 09
+ null, // 0A
+ null, // 0B
+ null, // 0C
+ null, // 0D
+ null, // 0E
+ null, // 0F
+
+ null, // 10
+ null, // 11
+ null, // 12
+ null, // 13
+ null, // 14
+ null, // 15
+ null, // 16
+ null, // 17
+ null, // 18
+ null, // 19
+ null, // 1A
+ null, // 1B
+ "a", // 1C
+ "td", // 1D
+ "tr", // 1E
+ "table", // 1F
+
+ "p", // 20
+ "postfield", // 21
+ "anchor", // 22
+ "access", // 23
+ "b", // 24
+ "big", // 25
+ "br", // 26
+ "card", // 27
+ "do", // 28
+ "em", // 29
+ "fieldset", // 2A
+ "go", // 2B
+ "head", // 2C
+ "i", // 2D
+ "img", // 2E
+ "input", // 2F
+
+ "meta", // 30
+ "noop", // 31
+ "prev", // 32
+ "onevent", // 33
+ "optgroup", // 34
+ "option", // 35
+ "refresh", // 36
+ "select", // 37
+ "small", // 38
+ "strong", // 39
+ null, // 3A
+ "template", // 3B
+ "timer", // 3C
+ "u", // 3D
+ "setvar", // 3E
+ "wml", // 3F
+ };
+
+
+ public static final String [] ATTR_START_TABLE = {
+ "accept-charset", // 05
+ "align=bottom", // 06
+ "align=center", // 07
+ "align=left", // 08
+ "align=middle", // 09
+ "align=right", // 0A
+ "align=top", // 0B
+ "alt", // 0C
+ "content", // 0D
+ null, // 0E
+ "domain", // 0F
+
+ "emptyok=false", // 10
+ "emptyok=true", // 11
+ "format", // 12
+ "height", // 13
+ "hspace", // 14
+ "ivalue", // 15
+ "iname", // 16
+ null, // 17
+ "label", // 18
+ "localsrc", // 19
+ "maxlength", // 1A
+ "method=get", // 1B
+ "method=post", // 1C
+ "mode=nowrap", // 1D
+ "mode=wrap", // 1E
+ "multiple=false", // 1F
+
+ "multiple=true", // 20
+ "name", // 21
+ "newcontext=false", // 22
+ "newcontext=true", // 23
+ "onpick", // 24
+ "onenterbackward", // 25
+ "onenterforward", // 26
+ "ontimer", // 27
+ "optimal=false", // 28
+ "optimal=true", // 29
+ "path", // 2A
+ null, // 2B
+ null, // 2C
+ null, // 2D
+ "scheme", // 2E
+ "sendreferer=false", // 2F
+
+ "sendreferer=true", // 30
+ "size", // 31
+ "src", // 32
+ "ordered=true", // 33
+ "ordered=false", // 34
+ "tabindex", // 35
+ "title", // 36
+ "type", // 37
+ "type=accept", // 38
+ "type=delete", // 39
+ "type=help", // 3A
+ "type=password", // 3B
+ "type=onpick", // 3C
+ "type=onenterbackward", // 3D
+ "type=onenterforward", // 3E
+ "type=ontimer", // 3F
+
+ null, // 40
+ null, // 41
+ null, // 42
+ null, // 43
+ null, // 44
+ "type=options", // 45
+ "type=prev", // 46
+ "type=reset", // 47
+ "type=text", // 48
+ "type=vnd.", // 49
+ "href", // 4A
+ "href=http://", // 4B
+ "href=https://", // 4C
+ "value", // 4D
+ "vspace", // 4E
+ "width", // 4F
+
+ "xml:lang", // 50
+ null, // 51
+ "align", // 52
+ "columns", // 53
+ "class", // 54
+ "id", // 55
+ "forua=false", // 56
+ "forua=true", // 57
+ "src=http://", // 58
+ "src=https://", // 59
+ "http-equiv", // 5A
+ "http-equiv=Content-Type", // 5B
+ "content=application/vnd.wap.wmlc;charset=", // 5C
+ "http-equiv=Expires", // 5D
+ null, // 5E
+ null, // 5F
+ };
+
+
+ public static final String [] ATTR_VALUE_TABLE = {
+ ".com/", // 85
+ ".edu/", // 86
+ ".net/", // 87
+ ".org/", // 88
+ "accept", // 89
+ "bottom", // 8A
+ "clear", // 8B
+ "delete", // 8C
+ "help", // 8D
+ "http://", // 8E
+ "http://www.", // 8F
+
+ "https://", // 90
+ "https://www.", // 91
+ null, // 92
+ "middle", // 93
+ "nowrap", // 94
+ "onpick", // 95
+ "onenterbackward", // 96
+ "onenterforward", // 97
+ "ontimer", // 98
+ "options", // 99
+ "password", // 9A
+ "reset", // 9B
+ null, // 9C
+ "text", // 9D
+ "top", // 9E
+ "unknown", // 9F
+
+ "wrap", // A0
+ "www.", // A1
+ };
+}
+
diff --git a/xml/src/main/java/org/kxml2/wap/wv/WV.java b/xml/src/main/java/org/kxml2/wap/wv/WV.java
new file mode 100644
index 0000000..e2afbfb
--- /dev/null
+++ b/xml/src/main/java/org/kxml2/wap/wv/WV.java
@@ -0,0 +1,593 @@
+package org.kxml2.wap.wv;
+
+import java.io.IOException;
+
+import org.kxml2.wap.*;
+
+/*
+
+ * WV.java
+
+ *
+
+ * Created on 25 September 2003, 10:40
+
+ */
+
+
+
+
+
+ /**
+ * Wireless Village CSP 1.1 ("OMA-WV-CSP-V1_1-20021001-A.pdf")
+ * Wireless Village CSP 1.2 ("OMA-IMPS-WV-CSP_WBXML-v1_2-20030221-C.PDF")
+ * There are some bugs in the 1.2 spec but this is Ok. 1.2 is candidate
+ *
+
+ * @author Bogdan Onoiu
+
+ */
+
+public abstract class WV {
+
+
+
+
+
+ public static WbxmlParser createParser () throws IOException {
+
+ WbxmlParser parser = new WbxmlParser();
+
+ parser.setTagTable (0, WV.tagTablePage0);
+ parser.setTagTable (1, WV.tagTablePage1);
+ parser.setTagTable (2, WV.tagTablePage2);
+ parser.setTagTable (3, WV.tagTablePage3);
+ parser.setTagTable (4, WV.tagTablePage4);
+ parser.setTagTable (5, WV.tagTablePage5);
+ parser.setTagTable (6, WV.tagTablePage6);
+ parser.setTagTable (7, WV.tagTablePage7);
+ parser.setTagTable (8, WV.tagTablePage8);
+ parser.setTagTable (9, WV.tagTablePage9);
+ parser.setTagTable (10, WV.tagTablePageA);
+
+ parser.setAttrStartTable (0, WV.attrStartTable);
+
+ parser.setAttrValueTable (0, WV.attrValueTable);
+
+ return parser;
+ }
+
+
+
+ public static final String [] tagTablePage0 = {
+ /* Common ... continue on Page 0x09 */
+ "Acceptance", //0x00, 0x05
+ "AddList", //0x00, 0x06
+ "AddNickList", //0x00, 0x07
+ "SName", //0x00, 0x08
+ "WV-CSP-Message", //0x00, 0x09
+ "ClientID", //0x00, 0x0A
+ "Code", //0x00, 0x0B
+ "ContactList", //0x00, 0x0C
+ "ContentData", //0x00, 0x0D
+ "ContentEncoding",//0x00, 0x0E
+ "ContentSize", //0x00, 0x0F
+ "ContentType", //0x00, 0x10
+ "DateTime", //0x00, 0x11
+ "Description", //0x00, 0x12
+ "DetailedResult", //0x00, 0x13
+ "EntityList", //0x00, 0x14
+ "Group", //0x00, 0x15
+ "GroupID", //0x00, 0x16
+ "GroupList", //0x00, 0x17
+ "InUse", //0x00, 0x18
+ "Logo", //0x00, 0x19
+ "MessageCount", //0x00, 0x1A
+ "MessageID", //0x00, 0x1B
+ "MessageURI", //0x00, 0x1C
+ "MSISDN", //0x00, 0x1D
+ "Name", //0x00, 0x1E
+ "NickList", //0x00, 0x1F
+ "NickName", //0x00, 0x20
+ "Poll", //0x00, 0x21
+ "Presence", //0x00, 0x22
+ "PresenceSubList",//0x00, 0x23
+ "PresenceValue", //0x00, 0x24
+ "Property", //0x00, 0x25
+ "Qualifier", //0x00, 0x26
+ "Recipient", //0x00, 0x27
+ "RemoveList", //0x00, 0x28
+ "RemoveNickList", //0x00, 0x29
+ "Result", //0x00, 0x2A
+ "ScreenName", //0x00, 0x2B
+ "Sender", //0x00, 0x2C
+ "Session", //0x00, 0x2D
+ "SessionDescriptor",//0x00, 0x2E
+ "SessionID", //0x00, 0x2F
+ "SessionType", //0x00, 0x30
+ "Status", //0x00, 0x31
+ "Transaction", //0x00, 0x32
+ "TransactionContent",//0x00, 0x33
+ "TransactionDescriptor",//0x00, 0x34
+ "TransactionID", //0x00, 0x35
+ "TransactionMode",//0x00, 0x36
+ "URL", //0x00, 0x37
+ "URLList", //0x00, 0x38
+ "User", //0x00, 0x39
+ "UserID", //0x00, 0x3A
+ "UserList", //0x00, 0x3B
+ "Validity", //0x00, 0x3C
+ "Value", //0x00, 0x3D
+ };
+
+ public static final String [] tagTablePage1 = {
+ /* Access ... continue on Page 0x0A */
+ "AllFunctions", // 0x01, 0x05
+ "AllFunctionsRequest", // 0x01, 0x06
+ "CancelInvite-Request", // 0x01, 0x07
+ "CancelInviteUser-Request", // 0x01, 0x08
+ "Capability", // 0x01, 0x09
+ "CapabilityList", // 0x01, 0x0A
+ "CapabilityRequest", // 0x01, 0x0B
+ "ClientCapability-Request", // 0x01, 0x0C
+ "ClientCapability-Response",// 0x01, 0x0D
+ "DigestBytes", // 0x01, 0x0E
+ "DigestSchema", // 0x01, 0x0F
+ "Disconnect", // 0x01, 0x10
+ "Functions", // 0x01, 0x11
+ "GetSPInfo-Request", // 0x01, 0x12
+ "GetSPInfo-Response", // 0x01, 0x13
+ "InviteID", // 0x01, 0x14
+ "InviteNote", // 0x01, 0x15
+ "Invite-Request", // 0x01, 0x16
+ "Invite-Response", // 0x01, 0x17
+ "InviteType", // 0x01, 0x18
+ "InviteUser-Request", // 0x01, 0x19
+ "InviteUser-Response", // 0x01, 0x1A
+ "KeepAlive-Request", // 0x01, 0x1B
+ "KeepAliveTime", // 0x01, 0x1C
+ "Login-Request", // 0x01, 0x1D
+ "Login-Response", // 0x01, 0x1E
+ "Logout-Request", // 0x01, 0x1F
+ "Nonce", // 0x01, 0x20
+ "Password", // 0x01, 0x21
+ "Polling-Request", // 0x01, 0x22
+ "ResponseNote", // 0x01, 0x23
+ "SearchElement", // 0x01, 0x24
+ "SearchFindings", // 0x01, 0x25
+ "SearchID", // 0x01, 0x26
+ "SearchIndex", // 0x01, 0x27
+ "SearchLimit", // 0x01, 0x28
+ "KeepAlive-Response", // 0x01, 0x29
+ "SearchPairList", // 0x01, 0x2A
+ "Search-Request", // 0x01, 0x2B
+ "Search-Response", // 0x01, 0x2C
+ "SearchResult", // 0x01, 0x2D
+ "Service-Request", // 0x01, 0x2E
+ "Service-Response", // 0x01, 0x2F
+ "SessionCookie", // 0x01, 0x30
+ "StopSearch-Request", // 0x01, 0x31
+ "TimeToLive", // 0x01, 0x32
+ "SearchString", // 0x01, 0x33
+ "CompletionFlag", // 0x01, 0x34
+ null, // 0x01, 0x35
+ "ReceiveList", // 0x01, 0x36 /* WV 1.2 */
+ "VerifyID-Request", // 0x01, 0x37 /* WV 1.2 */
+ "Extended-Request", // 0x01, 0x38 /* WV 1.2 */
+ "Extended-Response", // 0x01, 0x39 /* WV 1.2 */
+ "AgreedCapabilityList", // 0x01, 0x3A /* WV 1.2 */
+ "Extended-Data", // 0x01, 0x3B /* WV 1.2 */
+ "OtherServer", // 0x01, 0x3C /* WV 1.2 */
+ "PresenceAttributeNSName",//0x01, 0x3D /* WV 1.2 */
+ "SessionNSName", // 0x01, 0x3E /* WV 1.2 */
+ "TransactionNSName", // 0x01, 0x3F /* WV 1.2 */
+ };
+
+ public static final String [] tagTablePage2 = {
+ /* Service ... continue on Page 0x08 */
+ "ADDGM", // 0x02, 0x05
+ "AttListFunc", // 0x02, 0x06
+ "BLENT", // 0x02, 0x07
+ "CAAUT", // 0x02, 0x08
+ "CAINV", // 0x02, 0x09
+ "CALI", // 0x02, 0x0A
+ "CCLI", // 0x02, 0x0B
+ "ContListFunc", // 0x02, 0x0C
+ "CREAG", // 0x02, 0x0D
+ "DALI", // 0x02, 0x0E
+ "DCLI", // 0x02, 0x0F
+ "DELGR", // 0x02, 0x10
+ "FundamentalFeat",//0x02, 0x11
+ "FWMSG", // 0x02, 0x12
+ "GALS", // 0x02, 0x13
+ "GCLI", // 0x02, 0x14
+ "GETGM", // 0x02, 0x15
+ "GETGP", // 0x02, 0x16
+ "GETLM", // 0x02, 0x17
+ "GETM", // 0x02, 0x18
+ "GETPR", // 0x02, 0x19
+ "GETSPI", // 0x02, 0x1A
+ "GETWL", // 0x02, 0x1B
+ "GLBLU", // 0x02, 0x1C
+ "GRCHN", // 0x02, 0x1D
+ "GroupAuthFunc",// 0x02, 0x1E
+ "GroupFeat", // 0x02, 0x1F
+ "GroupMgmtFunc",// 0x02, 0x20
+ "GroupUseFunc", // 0x02, 0x21
+ "IMAuthFunc", // 0x02, 0x22
+ "IMFeat", // 0x02, 0x23
+ "IMReceiveFunc",// 0x02, 0x24
+ "IMSendFunc", // 0x02, 0x25
+ "INVIT", // 0x02, 0x26
+ "InviteFunc", // 0x02, 0x27
+ "MBRAC", // 0x02, 0x28
+ "MCLS", // 0x02, 0x29
+ "MDELIV", // 0x02, 0x2A
+ "NEWM", // 0x02, 0x2B
+ "NOTIF", // 0x02, 0x2C
+ "PresenceAuthFunc",//0x02, 0x2D
+ "PresenceDeliverFunc",//0x02, 0x2E
+ "PresenceFeat", // 0x02, 0x2F
+ "REACT", // 0x02, 0x30
+ "REJCM", // 0x02, 0x31
+ "REJEC", // 0x02, 0x32
+ "RMVGM", // 0x02, 0x33
+ "SearchFunc", // 0x02, 0x34
+ "ServiceFunc", // 0x02, 0x35
+ "SETD", // 0x02, 0x36
+ "SETGP", // 0x02, 0x37
+ "SRCH", // 0x02, 0x38
+ "STSRC", // 0x02, 0x39
+ "SUBGCN", // 0x02, 0x3A
+ "UPDPR", // 0x02, 0x3B
+ "WVCSPFeat", // 0x02, 0x3C
+ "MF", // 0x02, 0x3D /* WV 1.2 */
+ "MG", // 0x02, 0x3E /* WV 1.2 */
+ "MM" // 0x02, 0x3F /* WV 1.2 */
+ };
+
+ public static final String [] tagTablePage3 = {
+ /* Client Capability */
+ "AcceptedCharset", // 0x03, 0x05
+ "AcceptedContentLength", // 0x03, 0x06
+ "AcceptedContentType", // 0x03, 0x07
+ "AcceptedTransferEncoding", // 0x03, 0x08
+ "AnyContent", // 0x03, 0x09
+ "DefaultLanguage", // 0x03, 0x0A
+ "InitialDeliveryMethod", // 0x03, 0x0B
+ "MultiTrans", // 0x03, 0x0C
+ "ParserSize", // 0x03, 0x0D
+ "ServerPollMin", // 0x03, 0x0E
+ "SupportedBearer", // 0x03, 0x0F
+ "SupportedCIRMethod", // 0x03, 0x10
+ "TCPAddress", // 0x03, 0x11
+ "TCPPort", // 0x03, 0x12
+ "UDPPort" // 0x03, 0x13
+ };
+
+ public static final String [] tagTablePage4 = {
+ /* Presence Primitive */
+ "CancelAuth-Request", // 0x04, 0x05
+ "ContactListProperties", // 0x04, 0x06
+ "CreateAttributeList-Request", // 0x04, 0x07
+ "CreateList-Request", // 0x04, 0x08
+ "DefaultAttributeList", // 0x04, 0x09
+ "DefaultContactList", // 0x04, 0x0A
+ "DefaultList", // 0x04, 0x0B
+ "DeleteAttributeList-Request", // 0x04, 0x0C
+ "DeleteList-Request", // 0x04, 0x0D
+ "GetAttributeList-Request", // 0x04, 0x0E
+ "GetAttributeList-Response", // 0x04, 0x0F
+ "GetList-Request", // 0x04, 0x10
+ "GetList-Response", // 0x04, 0x11
+ "GetPresence-Request", // 0x04, 0x12
+ "GetPresence-Response", // 0x04, 0x13
+ "GetWatcherList-Request", // 0x04, 0x14
+ "GetWatcherList-Response", // 0x04, 0x15
+ "ListManage-Request", // 0x04, 0x16
+ "ListManage-Response", // 0x04, 0x17
+ "UnsubscribePresence-Request", // 0x04, 0x18
+ "PresenceAuth-Request", // 0x04, 0x19
+ "PresenceAuth-User", // 0x04, 0x1A
+ "PresenceNotification-Request", // 0x04, 0x1B
+ "UpdatePresence-Request", // 0x04, 0x1C
+ "SubscribePresence-Request", // 0x04, 0x1D
+ "Auto-Subscribe", // 0x04, 0x1E /* WV 1.2 */
+ "GetReactiveAuthStatus-Request",// 0x04, 0x1F /* WV 1.2 */
+ "GetReactiveAuthStatus-Response",// 0x04, 0x20 /* WV 1.2 */
+ };
+
+ public static final String [] tagTablePage5 = {
+ /* Presence Attribute */
+ "Accuracy", // 0x05, 0x05
+ "Address", // 0x05, 0x06
+ "AddrPref", // 0x05, 0x07
+ "Alias", // 0x05, 0x08
+ "Altitude", // 0x05, 0x09
+ "Building", // 0x05, 0x0A
+ "Caddr", // 0x05, 0x0B
+ "City", // 0x05, 0x0C
+ "ClientInfo", // 0x05, 0x0D
+ "ClientProducer", // 0x05, 0x0E
+ "ClientType", // 0x05, 0x0F
+ "ClientVersion", // 0x05, 0x10
+ "CommC", // 0x05, 0x11
+ "CommCap", // 0x05, 0x12
+ "ContactInfo", // 0x05, 0x13
+ "ContainedvCard", // 0x05, 0x14
+ "Country", // 0x05, 0x15
+ "Crossing1", // 0x05, 0x16
+ "Crossing2", // 0x05, 0x17
+ "DevManufacturer", // 0x05, 0x18
+ "DirectContent", // 0x05, 0x19
+ "FreeTextLocation", // 0x05, 0x1A
+ "GeoLocation", // 0x05, 0x1B
+ "Language", // 0x05, 0x1C
+ "Latitude", // 0x05, 0x1D
+ "Longitude", // 0x05, 0x1E
+ "Model", // 0x05, 0x1F
+ "NamedArea", // 0x05, 0x20
+ "OnlineStatus", // 0x05, 0x21
+ "PLMN", // 0x05, 0x22
+ "PrefC", // 0x05, 0x23
+ "PreferredContacts",// 0x05, 0x24
+ "PreferredLanguage",// 0x05, 0x25
+ "PreferredContent", // 0x05, 0x26
+ "PreferredvCard", // 0x05, 0x27
+ "Registration", // 0x05, 0x28
+ "StatusContent", // 0x05, 0x29
+ "StatusMood", // 0x05, 0x2A
+ "StatusText", // 0x05, 0x2B
+ "Street", // 0x05, 0x2C
+ "TimeZone", // 0x05, 0x2D
+ "UserAvailability", // 0x05, 0x2E
+ "Cap", // 0x05, 0x2F
+ "Cname", // 0x05, 0x30
+ "Contact", // 0x05, 0x31
+ "Cpriority", // 0x05, 0x32
+ "Cstatus", // 0x05, 0x33
+ "Note", // 0x05, 0x34 /* WV 1.2 */
+ "Zone", // 0x05, 0x35
+ null,
+ "Inf_link", // 0x05, 0x37 /* WV 1.2 */
+ "InfoLink", // 0x05, 0x38 /* WV 1.2 */
+ "Link", // 0x05, 0x39 /* WV 1.2 */
+ "Text", // 0x05, 0x3A /* WV 1.2 */
+ };
+
+ public static final String [] tagTablePage6 = {
+ /* Messaging */
+ "BlockList", // 0x06, 0x05
+// "BlockUser-Request", // 0x06, 0x06 //This is a bug in the spec
+ "BlockEntity-Request", // 0x06, 0x06
+ "DeliveryMethod", // 0x06, 0x07
+ "DeliveryReport", // 0x06, 0x08
+ "DeliveryReport-Request", // 0x06, 0x09
+ "ForwardMessage-Request", // 0x06, 0x0A
+ "GetBlockedList-Request", // 0x06, 0x0B
+ "GetBlockedList-Response", // 0x06, 0x0C
+ "GetMessageList-Request", // 0x06, 0x0D
+ "GetMessageList-Response", // 0x06, 0x0E
+ "GetMessage-Request", // 0x06, 0x0F
+ "GetMessage-Response", // 0x06, 0x10
+ "GrantList", // 0x06, 0x11
+ "MessageDelivered", // 0x06, 0x12
+ "MessageInfo", // 0x06, 0x13
+ "MessageNotification", // 0x06, 0x14
+ "NewMessage", // 0x06, 0x15
+ "RejectMessage-Request", // 0x06, 0x16
+ "SendMessage-Request", // 0x06, 0x17
+ "SendMessage-Response", // 0x06, 0x18
+ "SetDeliveryMethod-Request",// 0x06, 0x19
+ "DeliveryTime", // 0x06, 0x1A
+ };
+
+ public static final String [] tagTablePage7 = {
+ /* Group */
+ "AddGroupMembers-Request", // 0x07, 0x05
+ "Admin", // 0x07, 0x06
+ "CreateGroup-Request", // 0x07, 0x07
+ "DeleteGroup-Request", // 0x07, 0x08
+ "GetGroupMembers-Request", // 0x07, 0x09
+ "GetGroupMembers-Response", // 0x07, 0x0A
+ "GetGroupProps-Request", // 0x07, 0x0B
+ "GetGroupProps-Response", // 0x07, 0x0C
+ "GroupChangeNotice", // 0x07, 0x0D
+ "GroupProperties", // 0x07, 0x0E
+ "Joined", // 0x07, 0x0F
+ "JoinedRequest", // 0x07, 0x10
+ "JoinGroup-Request", // 0x07, 0x11
+ "JoinGroup-Response", // 0x07, 0x12
+ "LeaveGroup-Request", // 0x07, 0x13
+ "LeaveGroup-Response", // 0x07, 0x14
+ "Left", // 0x07, 0x15
+ "MemberAccess-Request", // 0x07, 0x16
+ "Mod", // 0x07, 0x17
+ "OwnProperties", // 0x07, 0x18
+ "RejectList-Request", // 0x07, 0x19
+ "RejectList-Response", // 0x07, 0x1A
+ "RemoveGroupMembers-Request",// 0x07, 0x1B
+ "SetGroupProps-Request", // 0x07, 0x1C
+ "SubscribeGroupNotice-Request", // 0x07, 0x1D
+ "SubscribeGroupNotice-Response",// 0x07, 0x1E
+ "Users", // 0x07, 0x1F
+ "WelcomeNote", // 0x07, 0x20
+ "JoinGroup", // 0x07, 0x21
+ "SubscribeNotification", // 0x07, 0x22
+ "SubscribeType", // 0x07, 0x23
+ "GetJoinedUsers-Request", // 0x07, 0x24 /* WV 1.2 */
+ "GetJoinedUsers-Response", // 0x07, 0x25 /* WV 1.2 */
+ "AdminMapList", // 0x07, 0x26 /* WV 1.2 */
+ "AdminMapping", // 0x07, 0x27 /* WV 1.2 */
+ "Mapping", // 0x07, 0x28 /* WV 1.2 */
+ "ModMapping", // 0x07, 0x29 /* WV 1.2 */
+ "UserMapList", // 0x07, 0x2A /* WV 1.2 */
+ "UserMapping", // 0x07, 0x2B /* WV 1.2 */
+ };
+
+ public static final String [] tagTablePage8 = {
+ /* Service ... continued */
+ "MP", // 0x08, 0x05 /* WV 1.2 */
+ "GETAUT", // 0x08, 0x06 /* WV 1.2 */
+ "GETJU", // 0x08, 0x07 /* WV 1.2 */
+ "VRID", // 0x08, 0x08 /* WV 1.2 */
+ "VerifyIDFunc", // 0x08, 0x09 /* WV 1.2 */
+ };
+
+ public static final String [] tagTablePage9 = {
+ /* Common ... continued */
+ "CIR", // 0x09, 0x05 /* WV 1.2 */
+ "Domain", // 0x09, 0x06 /* WV 1.2 */
+ "ExtBlock", // 0x09, 0x07 /* WV 1.2 */
+ "HistoryPeriod", // 0x09, 0x08 /* WV 1.2 */
+ "IDList", // 0x09, 0x09 /* WV 1.2 */
+ "MaxWatcherList", // 0x09, 0x0A /* WV 1.2 */
+ "ReactiveAuthState", // 0x09, 0x0B /* WV 1.2 */
+ "ReactiveAuthStatus", // 0x09, 0x0C /* WV 1.2 */
+ "ReactiveAuthStatusList", // 0x09, 0x0D /* WV 1.2 */
+ "Watcher", // 0x09, 0x0E /* WV 1.2 */
+ "WatcherStatus" // 0x09, 0x0F /* WV 1.2 */
+ };
+
+ public static final String [] tagTablePageA = {
+ /* Access ... continued */
+ "WV-CSP-NSDiscovery-Request", //0x0A, 0x05 /* WV 1.2 */
+ "WV-CSP-NSDiscovery-Response", //0x0A, 0x06 /* WV 1.2 */
+ "VersionList" //0x0A, 0x07 /* WV 1.2 */
+ };
+
+ public static final String [] attrStartTable = {
+ "xmlns=http://www.wireless-village.org/CSP",// 0x00, 0x05
+ "xmlns=http://www.wireless-village.org/PA", // 0x00, 0x06
+ "xmlns=http://www.wireless-village.org/TRC",// 0x00, 0x07
+ "xmlns=http://www.openmobilealliance.org/DTD/WV-CSP", // 0x00, 0x08
+ "xmlns=http://www.openmobilealliance.org/DTD/WV-PA", // 0x00, 0x09
+ "xmlns=http://www.openmobilealliance.org/DTD/WV-TRC", // 0x00, 0x0A
+ };
+
+ public static final String [] attrValueTable = {
+
+ "AccessType", // 0x00 /* Common value token */
+ "ActiveUsers", // 0x01 /* Common value token */
+ "Admin", // 0x02 /* Common value token */
+ "application/", // 0x03 /* Common value token */
+ "application/vnd.wap.mms-message", // 0x04 /* Common value token */
+ "application/x-sms", // 0x05 /* Common value token */
+ "AutoJoin", // 0x06 /* Common value token */
+ "BASE64", // 0x07 /* Common value token */
+ "Closed", // 0x08 /* Common value token */
+ "Default", // 0x09 /* Common value token */
+ "DisplayName", // 0x0a /* Common value token */
+ "F", // 0x0b /* Common value token */
+ "G", // 0x0c /* Common value token */
+ "GR", // 0x0d /* Common value token */
+ "http://", // 0x0e /* Common value token */
+ "https://", // 0x0f /* Common value token */
+ "image/", // 0x10 /* Common value token */
+ "Inband", // 0x11 /* Common value token */
+ "IM", // 0x12 /* Common value token */
+ "MaxActiveUsers", // 0x13 /* Common value token */
+ "Mod", // 0x14 /* Common value token */
+ "Name", // 0x15 /* Common value token */
+ "None", // 0x16 /* Common value token */
+ "N", // 0x17 /* Common value token */
+ "Open", // 0x18 /* Common value token */
+ "Outband", // 0x19 /* Common value token */
+ "PR", // 0x1a /* Common value token */
+ "Private", // 0x1b /* Common value token */
+ "PrivateMessaging", // 0x1c /* Common value token */
+ "PrivilegeLevel", // 0x1d /* Common value token */
+ "Public", // 0x1e /* Common value token */
+ "P", // 0x1f /* Common value token */
+ "Request", // 0x20 /* Common value token */
+ "Response", // 0x21 /* Common value token */
+ "Restricted", // 0x22 /* Common value token */
+ "ScreenName", // 0x23 /* Common value token */
+ "Searchable", // 0x24 /* Common value token */
+ "S", // 0x25 /* Common value token */
+ "SC", // 0x26 /* Common value token */
+ "text/", // 0x27 /* Common value token */
+ "text/plain", // 0x28 /* Common value token */
+ "text/x-vCalendar", // 0x29 /* Common value token */
+ "text/x-vCard", // 0x2a /* Common value token */
+ "Topic", // 0x2b /* Common value token */
+ "T", // 0x2c /* Common value token */
+ "Type", // 0x2d /* Common value token */
+ "U", // 0x2e /* Common value token */
+ "US", // 0x2f /* Common value token */
+ "www.wireless-village.org", // 0x30 /* Common value token */
+ "AutoDelete", // 0x31 /* Common value token */ /* WV 1.2 */
+ "GM", // 0x32 /* Common value token */ /* WV 1.2 */
+ "Validity", // 0x33 /* Common value token */ /* WV 1.2 */
+ "ShowID", // 0x34 /* Common value token */ /* WV 1.2 */
+ "GRANTED", // 0x35 /* Common value token */ /* WV 1.2 */
+ "PENDING", // 0x36 /* Common value token */ /* WV 1.2 */
+ null, // 0x37
+ null, // 0x38
+ null, // 0x39
+ null, // 0x3a
+ null, // 0x3b
+ null, // 0x3c
+ "GROUP_ID", // 0x3d /* Access value token */
+ "GROUP_NAME", // 0x3e /* Access value token */
+ "GROUP_TOPIC", // 0x3f /* Access value token */
+ "GROUP_USER_ID_JOINED", // 0x40 /* Access value token */
+ "GROUP_USER_ID_OWNER", // 0x41 /* Access value token */
+ "HTTP", // 0x42 /* Access value token */
+ "SMS", // 0x43 /* Access value token */
+ "STCP", // 0x44 /* Access value token */
+ "SUDP", // 0x45 /* Access value token */
+ "USER_ALIAS", // 0x46 /* Access value token */
+ "USER_EMAIL_ADDRESS", // 0x47 /* Access value token */
+ "USER_FIRST_NAME", // 0x48 /* Access value token */
+ "USER_ID", // 0x49 /* Access value token */
+ "USER_LAST_NAME", // 0x4a /* Access value token */
+ "USER_MOBILE_NUMBER", // 0x4b /* Access value token */
+ "USER_ONLINE_STATUS", // 0x4c /* Access value token */
+ "WAPSMS", // 0x4d /* Access value token */
+ "WAPUDP", // 0x4e /* Access value token */
+ "WSP", // 0x4f /* Access value token */
+ "GROUP_USER_ID_AUTOJOIN", // 0x50 /* Access value token */ /* WV 1.2 */
+ null, // 0x51
+ null, // 0x52
+ null, // 0x53
+ null, // 0x54
+ null, // 0x55
+ null, // 0x56
+ null, // 0x57
+ null, // 0x58
+ null, // 0x59
+ null, // 0x5a
+ "ANGRY", // 0x5b /* Presence value token */
+ "ANXIOUS", // 0x5c /* Presence value token */
+ "ASHAMED", // 0x5d /* Presence value token */
+ "AUDIO_CALL", // 0x5e /* Presence value token */
+ "AVAILABLE", // 0x5f /* Presence value token */
+ "BORED", // 0x60 /* Presence value token */
+ "CALL", // 0x61 /* Presence value token */
+ "CLI", // 0x62 /* Presence value token */
+ "COMPUTER", // 0x63 /* Presence value token */
+ "DISCREET", // 0x64 /* Presence value token */
+ "EMAIL", // 0x65 /* Presence value token */
+ "EXCITED", // 0x66 /* Presence value token */
+ "HAPPY", // 0x67 /* Presence value token */
+ "IM", // 0x68 /* Presence value token */
+ "IM_OFFLINE", // 0x69 /* Presence value token */
+ "IM_ONLINE", // 0x6a /* Presence value token */
+ "IN_LOVE", // 0x6b /* Presence value token */
+ "INVINCIBLE", // 0x6c /* Presence value token */
+ "JEALOUS", // 0x6d /* Presence value token */
+ "MMS", // 0x6e /* Presence value token */
+ "MOBILE_PHONE", // 0x6f /* Presence value token */
+ "NOT_AVAILABLE", // 0x70 /* Presence value token */
+ "OTHER", // 0x71 /* Presence value token */
+ "PDA", // 0x72 /* Presence value token */
+ "SAD", // 0x73 /* Presence value token */
+ "SLEEPY", // 0x74 /* Presence value token */
+ "SMS", // 0x75 /* Presence value token */
+ "VIDEO_CALL", // 0x76 /* Presence value token */
+ "VIDEO_STREAM", // 0x77 /* Presence value token */
+ };
+
+
+}