Author: saces
Date: 2008-03-30 15:23:56 +0000 (Sun, 30 Mar 2008)
New Revision: 18860
Added:
trunk/plugins/ThawIndexBrowser/nanoxml/
trunk/plugins/ThawIndexBrowser/nanoxml/XMLElement.java
trunk/plugins/ThawIndexBrowser/nanoxml/XMLParseException.java
Modified:
trunk/plugins/ThawIndexBrowser/ThawIndexBrowser.java
Log:
switch parser to nanoxml
Modified: trunk/plugins/ThawIndexBrowser/ThawIndexBrowser.java
===================================================================
--- trunk/plugins/ThawIndexBrowser/ThawIndexBrowser.java 2008-03-30
14:12:01 UTC (rev 18859)
+++ trunk/plugins/ThawIndexBrowser/ThawIndexBrowser.java 2008-03-30
15:23:56 UTC (rev 18860)
@@ -1,14 +1,12 @@
package plugins.ThawIndexBrowser;
import java.io.IOException;
+import java.io.InputStreamReader;
import java.net.MalformedURLException;
+import java.util.Enumeration;
-import nu.xom.Builder;
-import nu.xom.Document;
-import nu.xom.Element;
-import nu.xom.Elements;
-import nu.xom.ParsingException;
-import nu.xom.ValidityException;
+import plugins.ThawIndexBrowser.nanoxml.XMLElement;
+import plugins.ThawIndexBrowser.nanoxml.XMLParseException;
import freenet.client.FetchException;
import freenet.client.FetchResult;
import freenet.client.HighLevelSimpleClient;
@@ -29,7 +27,7 @@
public class ThawIndexBrowser implements FredPlugin, FredPluginThreadless,
FredPluginHTTP {
- public static String SELF_URI =
"/plugins/plugins.ThawIndexBrowser.ThawIndexBrowser/";
+ public static String SELF_URI =
"/plugins/plugins.IndexBrowser.IndexBrowser/";
private PluginRespirator pr;
@@ -145,19 +143,19 @@
FetchResult content = client.fetch(uri, 90000);
String mime = content.getMimeType();
if (!"application/x-freenet-index".equals(mime)) {
- return makeErrorPage("Wrong mime type: " +
mime, "Expectedmime type \"application/x-freenet-index\", but found \""
+ return makeErrorPage("Wrong mime type: " +
mime, "Expected mime type \"application/x-freenet-index\", but found \""
+ mime + "\".");
}
// data here, parse xml
- Builder builder = new Builder();
+ XMLElement xmldoc = new XMLElement();
- Document doc =
builder.build(content.asBucket().getInputStream());
+ xmldoc.parseFromReader(new
InputStreamReader(content.asBucket().getInputStream()));
// now print the result...
- return printIndexPage(uri, doc, add);
+ return printIndexPage(uri, xmldoc, add);
} catch (MalformedURLException e) {
Logger.error(this, "Invalid URI: " + index, e);
@@ -180,12 +178,9 @@
} catch (IOException e) {
Logger.error(this, "IOError", e);
return makeErrorPage("IOError", "IOError while
processing " + index + ": " + e.getLocalizedMessage());
- } catch (ValidityException e) {
+ } catch (XMLParseException e) {
Logger.error(this, "DEBUG", e);
return makeErrorPage("Parser error", "Error while
processing " + index + ": " + e.getLocalizedMessage());
- } catch (ParsingException e) {
- Logger.error(this, "DEBUG", e);
- return makeErrorPage("Parser error", "Error while
processing " + index + ": " + e.getLocalizedMessage());
} catch (Exception e) {
Logger.error(this, "DEBUG", e);
return makeErrorPage("Error while processing " + index
+ ": " + e.getLocalizedMessage());
@@ -206,101 +201,134 @@
return browseBox;
}
- private String printIndexPage(FreenetURI uri, Document doc, boolean
add) {
+ private String printIndexPage(FreenetURI uri, XMLElement doc, boolean
add) {
HTMLNode pageNode = pm.getPageNode("Index Browser", null);
HTMLNode contentNode = pm.getContentNode(pageNode);
- Element root = doc.getRootElement();
- Element header = root.getFirstChildElement("header");
+ XMLElement root = doc;
HTMLNode titleBox = pm.getInfobox("Index: " + uri);
- Element titelelement = header.getFirstChildElement("title");
- if (titelelement != null) {
- titleBox.addChild("#", "Titel: \u00a0 " +
titelelement.getValue());
- titleBox.addChild("BR");
- }
+ HTMLNode indexBox = pm.getInfobox("Links:");
+ HTMLNode fileBox = pm.getInfobox("Files:");
- Element clientelement = header.getFirstChildElement("client");
- if (clientelement != null) {
- titleBox.addChild("#", "Client: \u00a0 " +
clientelement.getValue());
- titleBox.addChild("BR");
- }
+ HTMLNode table = new HTMLNode("table", "class", "requests");
+ HTMLNode headerRow = table.addChild("tr", "class",
"table-header");
+ headerRow.addChild("th");
+ headerRow.addChild("th", "Key/Name");
+ headerRow.addChild("th", "Mimetype");
+ headerRow.addChild("th", "Size");
- Element dateelement = header.getFirstChildElement("date");
- if (dateelement != null) {
- titleBox.addChild("#", "Date: \u00a0 " +
dateelement.getValue());
- titleBox.addChild("BR");
- }
+ boolean hasfiles = false;
- contentNode.addChild(titleBox);
-
- Element indizies = root.getFirstChildElement("indexes");
+ Enumeration rootchilds = root.enumerateChildren();
- if (indizies.getChildCount() > 0) {
- HTMLNode indexBox = pm.getInfobox("Links:");
- Elements es = indizies.getChildElements();
+ while (rootchilds.hasMoreElements()) {
+ XMLElement rc = (XMLElement) rootchilds.nextElement();
+ String name = rc.getName();
+ if ("header".equals(name)) {
+ Enumeration headerchilds =
rc.enumerateChildren();
+ String titel = null;
+ String clientname = null;
+ String date = null;
+ String category = null;
+ while (headerchilds.hasMoreElements()) {
+ XMLElement he = (XMLElement)
headerchilds.nextElement();
+ String hename = he.getName();
+ if ("title".equals(hename)) {
+ titel = he.getContent();
+ } else if ("client".equals(hename)) {
+ clientname = he.getContent();
+ } else if ("date".equals(hename)) {
+ date = he.getContent();
+ } else if ("category".equals(hename)) {
+ category = he.getContent();
+ } else {
+ Logger
+ .error(this,
"Unexpected xml element '" + hename + "' at line: " + rc.getLineNr(), new Error(
+
"DEBUG"));
+ }
+ }
- for (int i = 0; i < es.size(); i++) {
- Element e = es.get(i);
- indexBox.addChild(new HTMLNode("a", "href",
SELF_URI + "?key=" + e.getAttribute("key").getValue(), e.getAttribute(
- "key").getValue()));
- indexBox.addChild("BR");
- }
- contentNode.addChild(indexBox);
- }
+ if (titel != null) {
+ titleBox.addChild("#", "Titel: \u00a0 "
+ titel);
+ titleBox.addChild("BR");
+ }
+ if (clientname != null) {
+ titleBox.addChild("#", "Client: \u00a0
" + clientname);
+ titleBox.addChild("BR");
+ }
+ if (date != null) {
+ titleBox.addChild("#", "Date: \u00a0 "
+ date);
+ titleBox.addChild("BR");
+ }
+ if (category != null) {
+ titleBox.addChild("#", "Category:
\u00a0 " + category);
+ titleBox.addChild("BR");
+ }
- Element files = root.getFirstChildElement("files");
+ } else if ("indexes".equals(name)) {
+ Enumeration indexchilds =
rc.enumerateChildren();
+ while (indexchilds.hasMoreElements()) {
+ XMLElement ie = (XMLElement)
indexchilds.nextElement();
+ indexBox.addChild(new HTMLNode("a",
"href", SELF_URI + "?key=" + ie.getStringAttribute("key"), ie
+
.getStringAttribute("key")));
+ indexBox.addChild("BR");
+ }
- if (files.getChildCount() > 0) {
- HTMLNode fileBox = pm.getInfobox("Files:");
-
- HTMLNode table = new HTMLNode("table", "class",
"requests");
- HTMLNode headerRow = table.addChild("tr", "class",
"table-header");
- headerRow.addChild("th");
- headerRow.addChild("th", "Key/Name");
- headerRow.addChild("th", "Mimetype");
- headerRow.addChild("th", "Size");
-
- Elements es = files.getChildElements();
+ } else if ("files".equals(name)) {
+ Enumeration filechilds = rc.enumerateChildren();
+ hasfiles = rc.countChildren() > 0;
+ while (filechilds.hasMoreElements()) {
+ XMLElement fe = (XMLElement)
filechilds.nextElement();
+ HTMLNode fileRow = table.addChild("tr");
+ String s = fe.getStringAttribute("key");
+ String s1;
+ try {
+ FreenetURI u = new
FreenetURI(s);
+ if (add) {
+ try {
+
fcp.makePersistentGlobalRequest(u, null, "forever", "disk");
+ } catch
(NotAllowedException e1) {
+
Logger.error(this, "DEBUG", e1);
+ }
+ }
- for (int i = 0; i < es.size(); i++) {
- Element e = es.get(i);
- HTMLNode fileRow = table.addChild("tr");
- String s = e.getAttribute("key").getValue();
- String s1;
- try {
- FreenetURI u = new FreenetURI(s);
- if (add) {
- try {
-
fcp.makePersistentGlobalRequest(u, null, "forever", "disk");
- } catch (NotAllowedException
e1) {
- Logger.error(this,
"DEBUG", e1);
+ if (s.length() > 100) {
+ s1 = s.substring(0, 12);
+ s1 += "...";
+ s1 += s.substring(85);
+ // //s = s1;
+ } else {
+ s1 = s;
}
-
+
fileRow.addChild(createAddCell(s, uri.toString()));
+ fileRow.addChild(createCell(new
HTMLNode("a", "href", "/?key=" + s, s1)));
+ } catch (MalformedURLException e1) {
+ fileRow.addChild(new
HTMLNode("td"));
+ fileRow.addChild(createCell(new
HTMLNode("#", s)));
}
- if (s.length() > 100) {
- s1 = s.substring(0, 12);
- s1 += "...";
- s1 += s.substring(85);
- //s = s1;
- } else {
- s1 = s;
- }
- fileRow.addChild(createAddCell(s,
uri.toString()));
- fileRow.addChild(createCell(new
HTMLNode("a", "href", "/?key=" + s, s1)));
- } catch (MalformedURLException e1) {
- fileRow.addChild(new HTMLNode("td"));
- fileRow.addChild(createCell(new
HTMLNode("#", s)));
+
+ fileRow.addChild(createCell(new
HTMLNode("#", fe.getStringAttribute("mime"))));
+ fileRow.addChild(createCell(new
HTMLNode("#", fe.getStringAttribute("size"))));
+
}
+ HTMLNode allRow = table.addChild("tr");
+
allRow.addChild(createAddAllCell(uri.toString()));
+ fileBox.addChild(table);
- fileRow.addChild(createCell(new HTMLNode("#",
e.getAttribute("mime").getValue())));
- fileRow.addChild(createCell(new HTMLNode("#",
e.getAttribute("size").getValue())));
+ } else if ("comments".equals(name)) {
+
+ } else {
+ Logger.error(this, "Unexpected xml element '" +
name + "' at line: " + rc.getLineNr(), new Error("DEBUG"));
}
- HTMLNode fileRow = table.addChild("tr");
- fileRow.addChild(createAddAllCell(uri.toString()));
- fileBox.addChild(table);
+ }
+
+ contentNode.addChild(titleBox);
+ contentNode.addChild(indexBox);
+
+ if (hasfiles)
contentNode.addChild(fileBox);
- }
+
contentNode.addChild(createUriBox());
return pageNode.generate();
}
Added: trunk/plugins/ThawIndexBrowser/nanoxml/XMLElement.java
===================================================================
--- trunk/plugins/ThawIndexBrowser/nanoxml/XMLElement.java
(rev 0)
+++ trunk/plugins/ThawIndexBrowser/nanoxml/XMLElement.java 2008-03-30
15:23:56 UTC (rev 18860)
@@ -0,0 +1,2604 @@
+/* XMLElement.java
+ *
+ * $Revision: 1.4 $
+ * $Date: 2002/03/24 10:27:59 $
+ * $Name: RELEASE_2_2_1 $
+ *
+ * This file is part of NanoXML 2 Lite.
+ * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
+ *
+ * This software is provided 'as-is', without any express or implied warranty.
+ * In no event will the authors be held liable for any damages arising from the
+ * use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software in
+ * a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source distribution.
+ *****************************************************************************/
+/*
+ * Changes:
+ * - removed deprecaded functions
+ * - renames enum. its a reserved word.
+ * - renames to avoid "hiding" warnings.
+ */
+
+package plugins.ThawIndexBrowser.nanoxml;
+
+
+import java.io.ByteArrayOutputStream;
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.Writer;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+
+/**
+ * XMLElement is a representation of an XML object. The object is able to parse
+ * XML code.
+ * <P><DL>
+ * <DT><B>Parsing XML Data</B></DT>
+ * <DD>
+ * You can parse XML data using the following code:
+ * <UL><CODE>
+ * XMLElement xml = new XMLElement();<BR>
+ * FileReader reader = new FileReader("filename.xml");<BR>
+ * xml.parseFromReader(reader);
+ * </CODE></UL></DD></DL>
+ * <DL><DT><B>Retrieving Attributes</B></DT>
+ * <DD>
+ * You can enumerate the attributes of an element using the method
+ * {@link #enumerateAttributeNames() enumerateAttributeNames}.
+ * The attribute values can be retrieved using the method
+ * {@link #getStringAttribute(java.lang.String) getStringAttribute}.
+ * The following example shows how to list the attributes of an element:
+ * <UL><CODE>
+ * XMLElement element = ...;<BR>
+ * Enumeration enum = element.getAttributeNames();<BR>
+ * while (enum.hasMoreElements()) {<BR>
+ * String key = (String) enum.nextElement();<BR>
+ * String value = element.getStringAttribute(key);<BR>
+ * System.out.println(key + " = " + value);<BR>
+ * }
+ * </CODE></UL></DD></DL>
+ * <DL><DT><B>Retrieving Child Elements</B></DT>
+ * <DD>
+ * You can enumerate the children of an element using
+ * {@link #enumerateChildren() enumerateChildren}.
+ * The number of child elements can be retrieved using
+ * {@link #countChildren() countChildren}.
+ * </DD></DL>
+ * <DL><DT><B>Elements Containing Character Data</B></DT>
+ * <DD>
+ * If an elements contains character data, like in the following example:
+ * <UL><CODE>
+ * <title>The Title</title>
+ * </CODE></UL>
+ * you can retrieve that data using the method
+ * {@link #getContent() getContent}.
+ * </DD></DL>
+ * <DL><DT><B>Subclassing XMLElement</B></DT>
+ * <DD>
+ * When subclassing XMLElement, you need to override the method
+ * {@link #createAnotherElement() createAnotherElement}
+ * which has to return a new copy of the receiver.
+ * </DD></DL>
+ * <P>
+ *
+ * @see nanoxml.XMLParseException
+ *
+ * @author Marc De Scheemaecker
+ * <<A href="mailto:cyberelf at mac.com">cyberelf at mac.com</A>>
+ * @version $Name: RELEASE_2_2_1 $, $Revision: 1.4 $
+ */
+public class XMLElement
+{
+
+ /**
+ * Serialization serial version ID.
+ */
+ static final long serialVersionUID = 6685035139346394777L;
+
+
+ /**
+ * Major version of NanoXML. Classes with the same major and minor
+ * version are binary compatible. Classes with the same major version
+ * are source compatible. If the major version is different, you may
+ * need to modify the client source code.
+ *
+ * @see nanoxml.XMLElement#NANOXML_MINOR_VERSION
+ */
+ public static final int NANOXML_MAJOR_VERSION = 2;
+
+
+ /**
+ * Minor version of NanoXML. Classes with the same major and minor
+ * version are binary compatible. Classes with the same major version
+ * are source compatible. If the major version is different, you may
+ * need to modify the client source code.
+ *
+ * @see nanoxml.XMLElement#NANOXML_MAJOR_VERSION
+ */
+ public static final int NANOXML_MINOR_VERSION = 2;
+
+
+ /**
+ * The attributes given to the element.
+ *
+ * <dl><dt><b>Invariants:</b></dt><dd>
+ * <ul><li>The field can be empty.
+ * <li>The field is never <code>null</code>.
+ * <li>The keys and the values are strings.
+ * </ul></dd></dl>
+ */
+ private Hashtable attributes;
+
+
+ /**
+ * Child elements of the element.
+ *
+ * <dl><dt><b>Invariants:</b></dt><dd>
+ * <ul><li>The field can be empty.
+ * <li>The field is never <code>null</code>.
+ * <li>The elements are instances of <code>XMLElement</code>
+ * or a subclass of <code>XMLElement</code>.
+ * </ul></dd></dl>
+ */
+ private Vector children;
+
+
+ /**
+ * The name of the element.
+ *
+ * <dl><dt><b>Invariants:</b></dt><dd>
+ * <ul><li>The field is <code>null</code> iff the element is not
+ * initialized by either parse or setName.
+ * <li>If the field is not <code>null</code>, it's not empty.
+ * <li>If the field is not <code>null</code>, it contains a valid
+ * XML identifier.
+ * </ul></dd></dl>
+ */
+ private String name;
+
+
+ /**
+ * The #PCDATA content of the object.
+ *
+ * <dl><dt><b>Invariants:</b></dt><dd>
+ * <ul><li>The field is <code>null</code> iff the element is not a
+ * #PCDATA element.
+ * <li>The field can be any string, including the empty string.
+ * </ul></dd></dl>
+ */
+ private String contents;
+
+
+ /**
+ * Conversion table for &...; entities. The keys are the entity names
+ * without the & and ; delimiters.
+ *
+ * <dl><dt><b>Invariants:</b></dt><dd>
+ * <ul><li>The field is never <code>null</code>.
+ * <li>The field always contains the following associations:
+ * "lt" => "<", "gt" => ">",
+ * "quot" => "\"", "apos" => "'",
+ * "amp" => "&"
+ * <li>The keys are strings
+ * <li>The values are char arrays
+ * </ul></dd></dl>
+ */
+ private Hashtable entities;
+
+
+ /**
+ * The line number where the element starts.
+ *
+ * <dl><dt><b>Invariants:</b></dt><dd>
+ * <ul><li><code>lineNr >= 0</code>
+ * </ul></dd></dl>
+ */
+ private int lineNr;
+
+
+ /**
+ * <code>true</code> if the case of the element and attribute names
+ * are case insensitive.
+ */
+ private boolean ignoreCase;
+
+
+ /**
+ * <code>true</code> if the leading and trailing whitespace of #PCDATA
+ * sections have to be ignored.
+ */
+ private boolean ignoreWhitespace;
+
+
+ /**
+ * Character read too much.
+ * This character provides push-back functionality to the input reader
+ * without having to use a PushbackReader.
+ * If there is no such character, this field is '\0'.
+ */
+ private char charReadTooMuch;
+
+
+ /**
+ * The reader provided by the caller of the parse method.
+ *
+ * <dl><dt><b>Invariants:</b></dt><dd>
+ * <ul><li>The field is not <code>null</code> while the parse method
+ * is running.
+ * </ul></dd></dl>
+ */
+ private Reader reader;
+
+
+ /**
+ * The current line number in the source content.
+ *
+ * <dl><dt><b>Invariants:</b></dt><dd>
+ * <ul><li>parserLineNr > 0 while the parse method is running.
+ * </ul></dd></dl>
+ */
+ private int parserLineNr;
+
+
+ /**
+ * Creates and initializes a new XML element.
+ * Calling the construction is equivalent to:
+ * <ul><code>new XMLElement(new Hashtable(), false, true)
+ * </code></ul>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>countChildren() => 0
+ * <li>enumerateChildren() => empty enumeration
+ * <li>enumeratePropertyNames() => empty enumeration
+ * <li>getChildren() => empty vector
+ * <li>getContent() => ""
+ * <li>getLineNr() => 0
+ * <li>getName() => null
+ * </ul></dd></dl>
+ *
+ * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable)
+ * XMLElement(Hashtable)
+ * @see nanoxml.XMLElement#XMLElement(boolean)
+ * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable,boolean)
+ * XMLElement(Hashtable, boolean)
+ */
+ public XMLElement()
+ {
+ this(new Hashtable(), false, true, true);
+ }
+
+
+ /**
+ * Creates and initializes a new XML element.
+ * Calling the construction is equivalent to:
+ * <ul><code>new XMLElement(entities, false, true)
+ * </code></ul>
+ *
+ * @param entities
+ * The entity conversion table.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>entities != null</code>
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>countChildren() => 0
+ * <li>enumerateChildren() => empty enumeration
+ * <li>enumeratePropertyNames() => empty enumeration
+ * <li>getChildren() => empty vector
+ * <li>getContent() => ""
+ * <li>getLineNr() => 0
+ * <li>getName() => null
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#XMLElement()
+ * @see nanoxml.XMLElement#XMLElement(boolean)
+ * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable,boolean)
+ * XMLElement(Hashtable, boolean)
+ */
+ public XMLElement(Hashtable entities2)
+ {
+ this(entities2, false, true, true);
+ }
+
+
+ /**
+ * Creates and initializes a new XML element.
+ * Calling the construction is equivalent to:
+ * <ul><code>new XMLElement(new Hashtable(), skipLeadingWhitespace, true)
+ * </code></ul>
+ *
+ * @param skipLeadingWhitespace
+ * <code>true</code> if leading and trailing whitespace in PCDATA
+ * content has to be removed.
+ *
+ * </dl><dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>countChildren() => 0
+ * <li>enumerateChildren() => empty enumeration
+ * <li>enumeratePropertyNames() => empty enumeration
+ * <li>getChildren() => empty vector
+ * <li>getContent() => ""
+ * <li>getLineNr() => 0
+ * <li>getName() => null
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#XMLElement()
+ * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable)
+ * XMLElement(Hashtable)
+ * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable,boolean)
+ * XMLElement(Hashtable, boolean)
+ */
+ public XMLElement(boolean skipLeadingWhitespace)
+ {
+ this(new Hashtable(), skipLeadingWhitespace, true, true);
+ }
+
+
+ /**
+ * Creates and initializes a new XML element.
+ * Calling the construction is equivalent to:
+ * <ul><code>new XMLElement(entities, skipLeadingWhitespace, true)
+ * </code></ul>
+ *
+ * @param entities
+ * The entity conversion table.
+ * @param skipLeadingWhitespace
+ * <code>true</code> if leading and trailing whitespace in PCDATA
+ * content has to be removed.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>entities != null</code>
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>countChildren() => 0
+ * <li>enumerateChildren() => empty enumeration
+ * <li>enumeratePropertyNames() => empty enumeration
+ * <li>getChildren() => empty vector
+ * <li>getContent() => ""
+ * <li>getLineNr() => 0
+ * <li>getName() => null
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#XMLElement()
+ * @see nanoxml.XMLElement#XMLElement(boolean)
+ * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable)
+ * XMLElement(Hashtable)
+ */
+ public XMLElement(Hashtable entities2,
+ boolean skipLeadingWhitespace)
+ {
+ this(entities2, skipLeadingWhitespace, true, true);
+ }
+
+
+ /**
+ * Creates and initializes a new XML element.
+ *
+ * @param entities
+ * The entity conversion table.
+ * @param skipLeadingWhitespace
+ * <code>true</code> if leading and trailing whitespace in PCDATA
+ * content has to be removed.
+ * @param ignoreCase
+ * <code>true</code> if the case of element and attribute names have
+ * to be ignored.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>entities != null</code>
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>countChildren() => 0
+ * <li>enumerateChildren() => empty enumeration
+ * <li>enumeratePropertyNames() => empty enumeration
+ * <li>getChildren() => empty vector
+ * <li>getContent() => ""
+ * <li>getLineNr() => 0
+ * <li>getName() => null
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#XMLElement()
+ * @see nanoxml.XMLElement#XMLElement(boolean)
+ * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable)
+ * XMLElement(Hashtable)
+ * @see nanoxml.XMLElement#XMLElement(java.util.Hashtable,boolean)
+ * XMLElement(Hashtable, boolean)
+ */
+ public XMLElement(Hashtable entities2,
+ boolean skipLeadingWhitespace,
+ boolean ignoreCase2)
+ {
+ this(entities2, skipLeadingWhitespace, true, ignoreCase2);
+ }
+
+
+ /**
+ * Creates and initializes a new XML element.
+ * <P>
+ * This constructor should <I>only</I> be called from
+ * {@link #createAnotherElement() createAnotherElement}
+ * to create child elements.
+ *
+ * @param entities
+ * The entity conversion table.
+ * @param skipLeadingWhitespace
+ * <code>true</code> if leading and trailing whitespace in PCDATA
+ * content has to be removed.
+ * @param fillBasicConversionTable
+ * <code>true</code> if the basic entities need to be added to
+ * the entity list.
+ * @param ignoreCase
+ * <code>true</code> if the case of element and attribute names have
+ * to be ignored.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>entities != null</code>
+ * <li>if <code>fillBasicConversionTable == false</code>
+ * then <code>entities</code> contains at least the following
+ * entries: <code>amp</code>, <code>lt</code>, <code>gt</code>,
+ * <code>apos</code> and <code>quot</code>
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>countChildren() => 0
+ * <li>enumerateChildren() => empty enumeration
+ * <li>enumeratePropertyNames() => empty enumeration
+ * <li>getChildren() => empty vector
+ * <li>getContent() => ""
+ * <li>getLineNr() => 0
+ * <li>getName() => null
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#createAnotherElement()
+ */
+ protected XMLElement(Hashtable entities2,
+ boolean skipLeadingWhitespace,
+ boolean fillBasicConversionTable,
+ boolean ignoreCase2)
+ {
+ this.ignoreWhitespace = skipLeadingWhitespace;
+ this.ignoreCase = ignoreCase2;
+ this.name = null;
+ this.contents = "";
+ this.attributes = new Hashtable();
+ this.children = new Vector();
+ this.entities = entities2;
+ this.lineNr = 0;
+ Enumeration e = this.entities.keys();
+ while (e.hasMoreElements()) {
+ Object key = e.nextElement();
+ Object value = this.entities.get(key);
+ if (value instanceof String) {
+ value = ((String) value).toCharArray();
+ this.entities.put(key, value);
+ }
+ }
+ if (fillBasicConversionTable) {
+ this.entities.put("amp", new char[] { '&' });
+ this.entities.put("quot", new char[] { '"' });
+ this.entities.put("apos", new char[] { '\'' });
+ this.entities.put("lt", new char[] { '<' });
+ this.entities.put("gt", new char[] { '>' });
+ }
+ }
+
+
+ /**
+ * Adds a child element.
+ *
+ * @param child
+ * The child element to add.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>child != null</code>
+ * <li><code>child.getName() != null</code>
+ * <li><code>child</code> does not have a parent element
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>countChildren() => old.countChildren() + 1
+ * <li>enumerateChildren() => old.enumerateChildren() + child
+ * <li>getChildren() => old.enumerateChildren() + child
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#countChildren()
+ * @see nanoxml.XMLElement#enumerateChildren()
+ * @see nanoxml.XMLElement#getChildren()
+ * @see nanoxml.XMLElement#removeChild(nanoxml.XMLElement)
+ * removeChild(XMLElement)
+ */
+ public void addChild(XMLElement child)
+ {
+ this.children.addElement(child);
+ }
+
+
+ /**
+ * Adds or modifies an attribute.
+ *
+ * @param name
+ * The name of the attribute.
+ * @param value
+ * The value of the attribute.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * <li><code>value != null</code>
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>enumerateAttributeNames()
+ * => old.enumerateAttributeNames() + name
+ * <li>getAttribute(name) => value
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setDoubleAttribute(java.lang.String, double)
+ * setDoubleAttribute(String, double)
+ * @see nanoxml.XMLElement#setIntAttribute(java.lang.String, int)
+ * setIntAttribute(String, int)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#getAttribute(java.lang.String)
+ * getAttribute(String)
+ * @see nanoxml.XMLElement#getAttribute(java.lang.String, java.lang.Object)
+ * getAttribute(String, Object)
+ * @see nanoxml.XMLElement#getAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getAttribute(String, Hashtable, String, boolean)
+ * @see nanoxml.XMLElement#getStringAttribute(java.lang.String)
+ * getStringAttribute(String)
+ * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
+ * java.lang.String)
+ * getStringAttribute(String, String)
+ * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getStringAttribute(String, Hashtable, String, boolean)
+ */
+ public void setAttribute(String name,
+ Object value)
+ {
+ if (this.ignoreCase) {
+ name = name.toUpperCase();
+ }
+ this.attributes.put(name, value.toString());
+ }
+
+
+ /**
+ * Adds or modifies an attribute.
+ *
+ * @param name
+ * The name of the attribute.
+ * @param value
+ * The value of the attribute.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>enumerateAttributeNames()
+ * => old.enumerateAttributeNames() + name
+ * <li>getIntAttribute(name) => value
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setDoubleAttribute(java.lang.String, double)
+ * setDoubleAttribute(String, double)
+ * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
+ * setAttribute(String, Object)
+ * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
+ * removeAttribute(String)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#getIntAttribute(java.lang.String)
+ * getIntAttribute(String)
+ * @see nanoxml.XMLElement#getIntAttribute(java.lang.String, int)
+ * getIntAttribute(String, int)
+ * @see nanoxml.XMLElement#getIntAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getIntAttribute(String, Hashtable, String, boolean)
+ */
+ public void setIntAttribute(String name,
+ int value)
+ {
+ if (this.ignoreCase) {
+ name = name.toUpperCase();
+ }
+ this.attributes.put(name, Integer.toString(value));
+ }
+
+
+ /**
+ * Adds or modifies an attribute.
+ *
+ * @param name
+ * The name of the attribute.
+ * @param value
+ * The value of the attribute.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>enumerateAttributeNames()
+ * => old.enumerateAttributeNames() + name
+ * <li>getDoubleAttribute(name) => value
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setIntAttribute(java.lang.String, int)
+ * setIntAttribute(String, int)
+ * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
+ * setAttribute(String, Object)
+ * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
+ * removeAttribute(String)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String)
+ * getDoubleAttribute(String)
+ * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String, double)
+ * getDoubleAttribute(String, double)
+ * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getDoubleAttribute(String, Hashtable, String, boolean)
+ */
+ public void setDoubleAttribute(String name,
+ double value)
+ {
+ if (this.ignoreCase) {
+ name = name.toUpperCase();
+ }
+ this.attributes.put(name, Double.toString(value));
+ }
+
+
+ /**
+ * Returns the number of child elements of the element.
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li><code>result >= 0</code>
+ * </ul></dd></dl>
+ *
+ * @see nanoxml.XMLElement#addChild(nanoxml.XMLElement)
+ * addChild(XMLElement)
+ * @see nanoxml.XMLElement#enumerateChildren()
+ * @see nanoxml.XMLElement#getChildren()
+ * @see nanoxml.XMLElement#removeChild(nanoxml.XMLElement)
+ * removeChild(XMLElement)
+ */
+ public int countChildren()
+ {
+ return this.children.size();
+ }
+
+
+ /**
+ * Enumerates the attribute names.
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li><code>result != null</code>
+ * </ul></dd></dl>
+ *
+ * @see nanoxml.XMLElement#setDoubleAttribute(java.lang.String, double)
+ * setDoubleAttribute(String, double)
+ * @see nanoxml.XMLElement#setIntAttribute(java.lang.String, int)
+ * setIntAttribute(String, int)
+ * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
+ * setAttribute(String, Object)
+ * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
+ * removeAttribute(String)
+ * @see nanoxml.XMLElement#getAttribute(java.lang.String)
+ * getAttribute(String)
+ * @see nanoxml.XMLElement#getAttribute(java.lang.String, java.lang.Object)
+ * getAttribute(String, String)
+ * @see nanoxml.XMLElement#getAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getAttribute(String, Hashtable, String, boolean)
+ * @see nanoxml.XMLElement#getStringAttribute(java.lang.String)
+ * getStringAttribute(String)
+ * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
+ * java.lang.String)
+ * getStringAttribute(String, String)
+ * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getStringAttribute(String, Hashtable, String, boolean)
+ * @see nanoxml.XMLElement#getIntAttribute(java.lang.String)
+ * getIntAttribute(String)
+ * @see nanoxml.XMLElement#getIntAttribute(java.lang.String, int)
+ * getIntAttribute(String, int)
+ * @see nanoxml.XMLElement#getIntAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getIntAttribute(String, Hashtable, String, boolean)
+ * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String)
+ * getDoubleAttribute(String)
+ * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String, double)
+ * getDoubleAttribute(String, double)
+ * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getDoubleAttribute(String, Hashtable, String, boolean)
+ * @see nanoxml.XMLElement#getBooleanAttribute(java.lang.String,
+ * java.lang.String,
+ * java.lang.String, boolean)
+ * getBooleanAttribute(String, String, String, boolean)
+ */
+ public Enumeration enumerateAttributeNames()
+ {
+ return this.attributes.keys();
+ }
+
+
+ /**
+ * Enumerates the child elements.
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li><code>result != null</code>
+ * </ul></dd></dl>
+ *
+ * @see nanoxml.XMLElement#addChild(nanoxml.XMLElement)
+ * addChild(XMLElement)
+ * @see nanoxml.XMLElement#countChildren()
+ * @see nanoxml.XMLElement#getChildren()
+ * @see nanoxml.XMLElement#removeChild(nanoxml.XMLElement)
+ * removeChild(XMLElement)
+ */
+ public Enumeration enumerateChildren()
+ {
+ return this.children.elements();
+ }
+
+
+ /**
+ * Returns the child elements as a Vector. It is safe to modify this
+ * Vector.
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li><code>result != null</code>
+ * </ul></dd></dl>
+ *
+ * @see nanoxml.XMLElement#addChild(nanoxml.XMLElement)
+ * addChild(XMLElement)
+ * @see nanoxml.XMLElement#countChildren()
+ * @see nanoxml.XMLElement#enumerateChildren()
+ * @see nanoxml.XMLElement#removeChild(nanoxml.XMLElement)
+ * removeChild(XMLElement)
+ */
+ public Vector getChildren()
+ {
+ try {
+ return (Vector) this.children.clone();
+ } catch (Exception e) {
+ // this never happens, however, some Java compilers are so
+ // braindead that they require this exception clause
+ return null;
+ }
+ }
+
+
+ /**
+ * Returns the PCDATA content of the object. If there is no such content,
+ * <CODE>null</CODE> is returned.
+ *
+ * @see nanoxml.XMLElement#setContent(java.lang.String)
+ * setContent(String)
+ */
+ public String getContent()
+ {
+ return this.contents;
+ }
+
+
+ /**
+ * Returns the line nr in the source data on which the element is found.
+ * This method returns <code>0</code> there is no associated source data.
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li><code>result >= 0</code>
+ * </ul></dd></dl>
+ */
+ public int getLineNr()
+ {
+ return this.lineNr;
+ }
+
+
+ /**
+ * Returns an attribute of the element.
+ * If the attribute doesn't exist, <code>null</code> is returned.
+ *
+ * @param name The name of the attribute.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
+ * setAttribute(String, Object)
+ * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
+ * removeAttribute(String)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#getAttribute(java.lang.String, java.lang.Object)
+ * getAttribute(String, Object)
+ * @see nanoxml.XMLElement#getAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getAttribute(String, Hashtable, String, boolean)
+ */
+ public Object getAttribute(String name)
+ {
+ return this.getAttribute(name, null);
+ }
+
+
+ /**
+ * Returns an attribute of the element.
+ * If the attribute doesn't exist, <code>defaultValue</code> is returned.
+ *
+ * @param name The name of the attribute.
+ * @param defaultValue Key to use if the attribute is missing.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
+ * setAttribute(String, Object)
+ * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
+ * removeAttribute(String)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#getAttribute(java.lang.String)
+ * getAttribute(String)
+ * @see nanoxml.XMLElement#getAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getAttribute(String, Hashtable, String, boolean)
+ */
+ public Object getAttribute(String name,
+ Object defaultValue)
+ {
+ if (this.ignoreCase) {
+ name = name.toUpperCase();
+ }
+ Object value = this.attributes.get(name);
+ if (value == null) {
+ value = defaultValue;
+ }
+ return value;
+ }
+
+
+ /**
+ * Returns an attribute by looking up a key in a hashtable.
+ * If the attribute doesn't exist, the value corresponding to defaultKey
+ * is returned.
+ * <P>
+ * As an example, if valueSet contains the mapping <code>"one" =>
+ * "1"</code>
+ * and the element contains the attribute <code>attr="one"</code>, then
+ * <code>getAttribute("attr", mapping, defaultKey, false)</code> returns
+ * <code>"1"</code>.
+ *
+ * @param name
+ * The name of the attribute.
+ * @param valueSet
+ * Hashtable mapping keys to values.
+ * @param defaultKey
+ * Key to use if the attribute is missing.
+ * @param allowLiterals
+ * <code>true</code> if literals are valid.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * <li><code>valueSet</code> != null
+ * <li>the keys of <code>valueSet</code> are strings
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
+ * setAttribute(String, Object)
+ * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
+ * removeAttribute(String)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#getAttribute(java.lang.String)
+ * getAttribute(String)
+ * @see nanoxml.XMLElement#getAttribute(java.lang.String, java.lang.Object)
+ * getAttribute(String, Object)
+ */
+ public Object getAttribute(String name,
+ Hashtable valueSet,
+ String defaultKey,
+ boolean allowLiterals)
+ {
+ if (this.ignoreCase) {
+ name = name.toUpperCase();
+ }
+ Object key = this.attributes.get(name);
+ Object result;
+ if (key == null) {
+ key = defaultKey;
+ }
+ result = valueSet.get(key);
+ if (result == null) {
+ if (allowLiterals) {
+ result = key;
+ } else {
+ throw this.invalidValue(name, (String) key);
+ }
+ }
+ return result;
+ }
+
+
+ /**
+ * Returns an attribute of the element.
+ * If the attribute doesn't exist, <code>null</code> is returned.
+ *
+ * @param name The name of the attribute.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
+ * setAttribute(String, Object)
+ * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
+ * removeAttribute(String)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
+ * java.lang.String)
+ * getStringAttribute(String, String)
+ * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getStringAttribute(String, Hashtable, String, boolean)
+ */
+ public String getStringAttribute(String name)
+ {
+ return this.getStringAttribute(name, null);
+ }
+
+
+ /**
+ * Returns an attribute of the element.
+ * If the attribute doesn't exist, <code>defaultValue</code> is returned.
+ *
+ * @param name The name of the attribute.
+ * @param defaultValue Key to use if the attribute is missing.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
+ * setAttribute(String, Object)
+ * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
+ * removeAttribute(String)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#getStringAttribute(java.lang.String)
+ * getStringAttribute(String)
+ * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getStringAttribute(String, Hashtable, String, boolean)
+ */
+ public String getStringAttribute(String name,
+ String defaultValue)
+ {
+ return (String) this.getAttribute(name, defaultValue);
+ }
+
+
+ /**
+ * Returns an attribute by looking up a key in a hashtable.
+ * If the attribute doesn't exist, the value corresponding to defaultKey
+ * is returned.
+ * <P>
+ * As an example, if valueSet contains the mapping <code>"one" =>
+ * "1"</code>
+ * and the element contains the attribute <code>attr="one"</code>, then
+ * <code>getAttribute("attr", mapping, defaultKey, false)</code> returns
+ * <code>"1"</code>.
+ *
+ * @param name
+ * The name of the attribute.
+ * @param valueSet
+ * Hashtable mapping keys to values.
+ * @param defaultKey
+ * Key to use if the attribute is missing.
+ * @param allowLiterals
+ * <code>true</code> if literals are valid.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * <li><code>valueSet</code> != null
+ * <li>the keys of <code>valueSet</code> are strings
+ * <li>the values of <code>valueSet</code> are strings
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
+ * setAttribute(String, Object)
+ * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
+ * removeAttribute(String)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#getStringAttribute(java.lang.String)
+ * getStringAttribute(String)
+ * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
+ * java.lang.String)
+ * getStringAttribute(String, String)
+ */
+ public String getStringAttribute(String name,
+ Hashtable valueSet,
+ String defaultKey,
+ boolean allowLiterals)
+ {
+ return (String) this.getAttribute(name, valueSet, defaultKey,
+ allowLiterals);
+ }
+
+
+ /**
+ * Returns an attribute of the element.
+ * If the attribute doesn't exist, <code>0</code> is returned.
+ *
+ * @param name The name of the attribute.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setIntAttribute(java.lang.String, int)
+ * setIntAttribute(String, int)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#getIntAttribute(java.lang.String, int)
+ * getIntAttribute(String, int)
+ * @see nanoxml.XMLElement#getIntAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getIntAttribute(String, Hashtable, String, boolean)
+ */
+ public int getIntAttribute(String name)
+ {
+ return this.getIntAttribute(name, 0);
+ }
+
+
+ /**
+ * Returns an attribute of the element.
+ * If the attribute doesn't exist, <code>defaultValue</code> is returned.
+ *
+ * @param name The name of the attribute.
+ * @param defaultValue Key to use if the attribute is missing.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setIntAttribute(java.lang.String, int)
+ * setIntAttribute(String, int)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#getIntAttribute(java.lang.String)
+ * getIntAttribute(String)
+ * @see nanoxml.XMLElement#getIntAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getIntAttribute(String, Hashtable, String, boolean)
+ */
+ public int getIntAttribute(String name,
+ int defaultValue)
+ {
+ if (this.ignoreCase) {
+ name = name.toUpperCase();
+ }
+ String value = (String) this.attributes.get(name);
+ if (value == null) {
+ return defaultValue;
+ } else {
+ try {
+ return Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ throw this.invalidValue(name, value);
+ }
+ }
+ }
+
+
+ /**
+ * Returns an attribute by looking up a key in a hashtable.
+ * If the attribute doesn't exist, the value corresponding to defaultKey
+ * is returned.
+ * <P>
+ * As an example, if valueSet contains the mapping <code>"one" => 1</code>
+ * and the element contains the attribute <code>attr="one"</code>, then
+ * <code>getIntAttribute("attr", mapping, defaultKey, false)</code> returns
+ * <code>1</code>.
+ *
+ * @param name
+ * The name of the attribute.
+ * @param valueSet
+ * Hashtable mapping keys to values.
+ * @param defaultKey
+ * Key to use if the attribute is missing.
+ * @param allowLiteralNumbers
+ * <code>true</code> if literal numbers are valid.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * <li><code>valueSet</code> != null
+ * <li>the keys of <code>valueSet</code> are strings
+ * <li>the values of <code>valueSet</code> are Integer objects
+ * <li><code>defaultKey</code> is either <code>null</code>, a
+ * key in <code>valueSet</code> or an integer.
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setIntAttribute(java.lang.String, int)
+ * setIntAttribute(String, int)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#getIntAttribute(java.lang.String)
+ * getIntAttribute(String)
+ * @see nanoxml.XMLElement#getIntAttribute(java.lang.String, int)
+ * getIntAttribute(String, int)
+ */
+ public int getIntAttribute(String name,
+ Hashtable valueSet,
+ String defaultKey,
+ boolean allowLiteralNumbers)
+ {
+ if (this.ignoreCase) {
+ name = name.toUpperCase();
+ }
+ Object key = this.attributes.get(name);
+ Integer result;
+ if (key == null) {
+ key = defaultKey;
+ }
+ try {
+ result = (Integer) valueSet.get(key);
+ } catch (ClassCastException e) {
+ throw this.invalidValueSet(name);
+ }
+ if (result == null) {
+ if (! allowLiteralNumbers) {
+ throw this.invalidValue(name, (String) key);
+ }
+ try {
+ result = Integer.valueOf((String) key);
+ } catch (NumberFormatException e) {
+ throw this.invalidValue(name, (String) key);
+ }
+ }
+ return result.intValue();
+ }
+
+
+ /**
+ * Returns an attribute of the element.
+ * If the attribute doesn't exist, <code>0.0</code> is returned.
+ *
+ * @param name The name of the attribute.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setDoubleAttribute(java.lang.String, double)
+ * setDoubleAttribute(String, double)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String, double)
+ * getDoubleAttribute(String, double)
+ * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getDoubleAttribute(String, Hashtable, String, boolean)
+ */
+ public double getDoubleAttribute(String name)
+ {
+ return this.getDoubleAttribute(name, 0.);
+ }
+
+
+ /**
+ * Returns an attribute of the element.
+ * If the attribute doesn't exist, <code>defaultValue</code> is returned.
+ *
+ * @param name The name of the attribute.
+ * @param defaultValue Key to use if the attribute is missing.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setDoubleAttribute(java.lang.String, double)
+ * setDoubleAttribute(String, double)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String)
+ * getDoubleAttribute(String)
+ * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getDoubleAttribute(String, Hashtable, String, boolean)
+ */
+ public double getDoubleAttribute(String name,
+ double defaultValue)
+ {
+ if (this.ignoreCase) {
+ name = name.toUpperCase();
+ }
+ String value = (String) this.attributes.get(name);
+ if (value == null) {
+ return defaultValue;
+ } else {
+ try {
+ return Double.valueOf(value).doubleValue();
+ } catch (NumberFormatException e) {
+ throw this.invalidValue(name, value);
+ }
+ }
+ }
+
+
+ /**
+ * Returns an attribute by looking up a key in a hashtable.
+ * If the attribute doesn't exist, the value corresponding to defaultKey
+ * is returned.
+ * <P>
+ * As an example, if valueSet contains the mapping <code>"one" =>
+ * 1.0</code>
+ * and the element contains the attribute <code>attr="one"</code>, then
+ * <code>getDoubleAttribute("attr", mapping, defaultKey, false)</code>
+ * returns <code>1.0</code>.
+ *
+ * @param name
+ * The name of the attribute.
+ * @param valueSet
+ * Hashtable mapping keys to values.
+ * @param defaultKey
+ * Key to use if the attribute is missing.
+ * @param allowLiteralNumbers
+ * <code>true</code> if literal numbers are valid.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * <li><code>valueSet != null</code>
+ * <li>the keys of <code>valueSet</code> are strings
+ * <li>the values of <code>valueSet</code> are Double objects
+ * <li><code>defaultKey</code> is either <code>null</code>, a
+ * key in <code>valueSet</code> or a double.
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setDoubleAttribute(java.lang.String, double)
+ * setDoubleAttribute(String, double)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String)
+ * getDoubleAttribute(String)
+ * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String, double)
+ * getDoubleAttribute(String, double)
+ */
+ public double getDoubleAttribute(String name,
+ Hashtable valueSet,
+ String defaultKey,
+ boolean allowLiteralNumbers)
+ {
+ if (this.ignoreCase) {
+ name = name.toUpperCase();
+ }
+ Object key = this.attributes.get(name);
+ Double result;
+ if (key == null) {
+ key = defaultKey;
+ }
+ try {
+ result = (Double) valueSet.get(key);
+ } catch (ClassCastException e) {
+ throw this.invalidValueSet(name);
+ }
+ if (result == null) {
+ if (! allowLiteralNumbers) {
+ throw this.invalidValue(name, (String) key);
+ }
+ try {
+ result = Double.valueOf((String) key);
+ } catch (NumberFormatException e) {
+ throw this.invalidValue(name, (String) key);
+ }
+ }
+ return result.doubleValue();
+ }
+
+
+ /**
+ * Returns an attribute of the element.
+ * If the attribute doesn't exist, <code>defaultValue</code> is returned.
+ * If the value of the attribute is equal to <code>trueValue</code>,
+ * <code>true</code> is returned.
+ * If the value of the attribute is equal to <code>falseValue</code>,
+ * <code>false</code> is returned.
+ * If the value doesn't match <code>trueValue</code> or
+ * <code>falseValue</code>, an exception is thrown.
+ *
+ * @param name The name of the attribute.
+ * @param trueValue The value associated with <code>true</code>.
+ * @param falseValue The value associated with <code>true</code>.
+ * @param defaultValue Value to use if the attribute is missing.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * <li><code>trueValue</code> and <code>falseValue</code>
+ * are different strings.
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
+ * setAttribute(String, Object)
+ * @see nanoxml.XMLElement#removeAttribute(java.lang.String)
+ * removeAttribute(String)
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ */
+ public boolean getBooleanAttribute(String name,
+ String trueValue,
+ String falseValue,
+ boolean defaultValue)
+ {
+ if (this.ignoreCase) {
+ name = name.toUpperCase();
+ }
+ Object value = this.attributes.get(name);
+ if (value == null) {
+ return defaultValue;
+ } else if (value.equals(trueValue)) {
+ return true;
+ } else if (value.equals(falseValue)) {
+ return false;
+ } else {
+ throw this.invalidValue(name, (String) value);
+ }
+ }
+
+
+ /**
+ * Returns the name of the element.
+ *
+ * @see nanoxml.XMLElement#setName(java.lang.String) setName(String)
+ */
+ public String getName()
+ {
+ return this.name;
+ }
+
+
+ /**
+ * Reads one XML element from a java.io.Reader and parses it.
+ *
+ * @param reader
+ * The reader from which to retrieve the XML data.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>reader != null</code>
+ * <li><code>reader</code> is not closed
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>the state of the receiver is updated to reflect the XML element
+ * parsed from the reader
+ * <li>the reader points to the first character following the last
+ * '>' character of the XML element
+ * </ul></dd></dl><dl>
+ *
+ * @throws java.io.IOException
+ * If an error occured while reading the input.
+ * @throws nanoxml.XMLParseException
+ * If an error occured while parsing the read data.
+ */
+ public void parseFromReader(Reader reader)
+ throws IOException, XMLParseException
+ {
+ this.parseFromReader(reader, /*startingLineNr*/ 1);
+ }
+
+
+ /**
+ * Reads one XML element from a java.io.Reader and parses it.
+ *
+ * @param reader
+ * The reader from which to retrieve the XML data.
+ * @param startingLineNr
+ * The line number of the first line in the data.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>reader != null</code>
+ * <li><code>reader</code> is not closed
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>the state of the receiver is updated to reflect the XML element
+ * parsed from the reader
+ * <li>the reader points to the first character following the last
+ * '>' character of the XML element
+ * </ul></dd></dl><dl>
+ *
+ * @throws java.io.IOException
+ * If an error occured while reading the input.
+ * @throws nanoxml.XMLParseException
+ * If an error occured while parsing the read data.
+ */
+ public void parseFromReader(Reader reader2,
+ int startingLineNr)
+ throws IOException, XMLParseException
+ {
+ this.name = null;
+ this.contents = "";
+ this.attributes = new Hashtable();
+ this.children = new Vector();
+ this.charReadTooMuch = '\0';
+ this.reader = reader2;
+ this.parserLineNr = startingLineNr;
+
+ for (;;) {
+ char ch = this.scanWhitespace();
+
+ if (ch != '<') {
+ throw this.expectedInput("<");
+ }
+
+ ch = this.readChar();
+
+ if ((ch == '!') || (ch == '?')) {
+ this.skipSpecialTag(0);
+ } else {
+ this.unreadChar(ch);
+ this.scanElement(this);
+ return;
+ }
+ }
+ }
+
+
+ /**
+ * Reads one XML element from a String and parses it.
+ *
+ * @param reader
+ * The reader from which to retrieve the XML data.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>string != null</code>
+ * <li><code>string.length() > 0</code>
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>the state of the receiver is updated to reflect the XML element
+ * parsed from the reader
+ * </ul></dd></dl><dl>
+ *
+ * @throws nanoxml.XMLParseException
+ * If an error occured while parsing the string.
+ */
+ public void parseString(String string)
+ throws XMLParseException
+ {
+ try {
+ this.parseFromReader(new StringReader(string),
+ /*startingLineNr*/ 1);
+ } catch (IOException e) {
+ // Java exception handling suxx
+ }
+ }
+
+
+ /**
+ * Reads one XML element from a String and parses it.
+ *
+ * @param reader
+ * The reader from which to retrieve the XML data.
+ * @param offset
+ * The first character in <code>string</code> to scan.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>string != null</code>
+ * <li><code>offset < string.length()</code>
+ * <li><code>offset >= 0</code>
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>the state of the receiver is updated to reflect the XML element
+ * parsed from the reader
+ * </ul></dd></dl><dl>
+ *
+ * @throws nanoxml.XMLParseException
+ * If an error occured while parsing the string.
+ */
+ public void parseString(String string,
+ int offset)
+ throws XMLParseException
+ {
+ this.parseString(string.substring(offset));
+ }
+
+
+ /**
+ * Reads one XML element from a String and parses it.
+ *
+ * @param reader
+ * The reader from which to retrieve the XML data.
+ * @param offset
+ * The first character in <code>string</code> to scan.
+ * @param end
+ * The character where to stop scanning.
+ * This character is not scanned.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>string != null</code>
+ * <li><code>end <= string.length()</code>
+ * <li><code>offset < end</code>
+ * <li><code>offset >= 0</code>
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>the state of the receiver is updated to reflect the XML element
+ * parsed from the reader
+ * </ul></dd></dl><dl>
+ *
+ * @throws nanoxml.XMLParseException
+ * If an error occured while parsing the string.
+ */
+ public void parseString(String string,
+ int offset,
+ int end)
+ throws XMLParseException
+ {
+ this.parseString(string.substring(offset, end));
+ }
+
+
+ /**
+ * Reads one XML element from a String and parses it.
+ *
+ * @param reader
+ * The reader from which to retrieve the XML data.
+ * @param offset
+ * The first character in <code>string</code> to scan.
+ * @param end
+ * The character where to stop scanning.
+ * This character is not scanned.
+ * @param startingLineNr
+ * The line number of the first line in the data.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>string != null</code>
+ * <li><code>end <= string.length()</code>
+ * <li><code>offset < end</code>
+ * <li><code>offset >= 0</code>
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>the state of the receiver is updated to reflect the XML element
+ * parsed from the reader
+ * </ul></dd></dl><dl>
+ *
+ * @throws nanoxml.XMLParseException
+ * If an error occured while parsing the string.
+ */
+ public void parseString(String string,
+ int offset,
+ int end,
+ int startingLineNr)
+ throws XMLParseException
+ {
+ string = string.substring(offset, end);
+ try {
+ this.parseFromReader(new StringReader(string), startingLineNr);
+ } catch (IOException e) {
+ // Java exception handling suxx
+ }
+ }
+
+
+ /**
+ * Reads one XML element from a char array and parses it.
+ *
+ * @param reader
+ * The reader from which to retrieve the XML data.
+ * @param offset
+ * The first character in <code>string</code> to scan.
+ * @param end
+ * The character where to stop scanning.
+ * This character is not scanned.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>input != null</code>
+ * <li><code>end <= input.length</code>
+ * <li><code>offset < end</code>
+ * <li><code>offset >= 0</code>
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>the state of the receiver is updated to reflect the XML element
+ * parsed from the reader
+ * </ul></dd></dl><dl>
+ *
+ * @throws nanoxml.XMLParseException
+ * If an error occured while parsing the string.
+ */
+ public void parseCharArray(char[] input,
+ int offset,
+ int end)
+ throws XMLParseException
+ {
+ this.parseCharArray(input, offset, end, /*startingLineNr*/ 1);
+ }
+
+
+ /**
+ * Reads one XML element from a char array and parses it.
+ *
+ * @param reader
+ * The reader from which to retrieve the XML data.
+ * @param offset
+ * The first character in <code>string</code> to scan.
+ * @param end
+ * The character where to stop scanning.
+ * This character is not scanned.
+ * @param startingLineNr
+ * The line number of the first line in the data.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>input != null</code>
+ * <li><code>end <= input.length</code>
+ * <li><code>offset < end</code>
+ * <li><code>offset >= 0</code>
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>the state of the receiver is updated to reflect the XML element
+ * parsed from the reader
+ * </ul></dd></dl><dl>
+ *
+ * @throws nanoxml.XMLParseException
+ * If an error occured while parsing the string.
+ */
+ public void parseCharArray(char[] input,
+ int offset,
+ int end,
+ int startingLineNr)
+ throws XMLParseException
+ {
+ try {
+ Reader reader = new CharArrayReader(input, offset, end);
+ this.parseFromReader(reader, startingLineNr);
+ } catch (IOException e) {
+ // This exception will never happen.
+ }
+ }
+
+
+ /**
+ * Removes a child element.
+ *
+ * @param child
+ * The child element to remove.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>child != null</code>
+ * <li><code>child</code> is a child element of the receiver
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>countChildren() => old.countChildren() - 1
+ * <li>enumerateChildren() => old.enumerateChildren() - child
+ * <li>getChildren() => old.enumerateChildren() - child
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#addChild(nanoxml.XMLElement)
+ * addChild(XMLElement)
+ * @see nanoxml.XMLElement#countChildren()
+ * @see nanoxml.XMLElement#enumerateChildren()
+ * @see nanoxml.XMLElement#getChildren()
+ */
+ public void removeChild(XMLElement child)
+ {
+ this.children.removeElement(child);
+ }
+
+
+ /**
+ * Removes an attribute.
+ *
+ * @param name
+ * The name of the attribute.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>enumerateAttributeNames()
+ * => old.enumerateAttributeNames() - name
+ * <li>getAttribute(name) => <code>null</code>
+ * </ul></dd></dl><dl>
+ *
+ * @see nanoxml.XMLElement#enumerateAttributeNames()
+ * @see nanoxml.XMLElement#setDoubleAttribute(java.lang.String, double)
+ * setDoubleAttribute(String, double)
+ * @see nanoxml.XMLElement#setIntAttribute(java.lang.String, int)
+ * setIntAttribute(String, int)
+ * @see nanoxml.XMLElement#setAttribute(java.lang.String, java.lang.Object)
+ * setAttribute(String, Object)
+ * @see nanoxml.XMLElement#getAttribute(java.lang.String)
+ * getAttribute(String)
+ * @see nanoxml.XMLElement#getAttribute(java.lang.String, java.lang.Object)
+ * getAttribute(String, Object)
+ * @see nanoxml.XMLElement#getAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getAttribute(String, Hashtable, String, boolean)
+ * @see nanoxml.XMLElement#getStringAttribute(java.lang.String)
+ * getStringAttribute(String)
+ * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
+ * java.lang.String)
+ * getStringAttribute(String, String)
+ * @see nanoxml.XMLElement#getStringAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getStringAttribute(String, Hashtable, String, boolean)
+ * @see nanoxml.XMLElement#getIntAttribute(java.lang.String)
+ * getIntAttribute(String)
+ * @see nanoxml.XMLElement#getIntAttribute(java.lang.String, int)
+ * getIntAttribute(String, int)
+ * @see nanoxml.XMLElement#getIntAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getIntAttribute(String, Hashtable, String, boolean)
+ * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String)
+ * getDoubleAttribute(String)
+ * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String, double)
+ * getDoubleAttribute(String, double)
+ * @see nanoxml.XMLElement#getDoubleAttribute(java.lang.String,
+ * java.util.Hashtable,
+ * java.lang.String, boolean)
+ * getDoubleAttribute(String, Hashtable, String, boolean)
+ * @see nanoxml.XMLElement#getBooleanAttribute(java.lang.String,
+ * java.lang.String,
+ * java.lang.String, boolean)
+ * getBooleanAttribute(String, String, String, boolean)
+ */
+ public void removeAttribute(String name)
+ {
+ if (this.ignoreCase) {
+ name = name.toUpperCase();
+ }
+ this.attributes.remove(name);
+ }
+
+
+ /**
+ * Creates a new similar XML element.
+ * <P>
+ * You should override this method when subclassing XMLElement.
+ */
+ protected XMLElement createAnotherElement()
+ {
+ return new XMLElement(this.entities,
+ this.ignoreWhitespace,
+ false,
+ this.ignoreCase);
+ }
+
+
+ /**
+ * Changes the content string.
+ *
+ * @param content
+ * The new content string.
+ */
+ public void setContent(String content)
+ {
+ this.contents = content;
+ }
+
+
+ /**
+ * Changes the name of the element.
+ *
+ * @param name
+ * The new name.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name</code> is a valid XML identifier
+ * </ul></dd></dl>
+ *
+ * @see nanoxml.XMLElement#getName()
+ */
+ public void setName(String name2)
+ {
+ this.name = name2;
+ }
+
+
+ /**
+ * Writes the XML element to a string.
+ *
+ * @see nanoxml.XMLElement#write(java.io.Writer) write(Writer)
+ */
+ public String toString()
+ {
+ try {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ OutputStreamWriter writer = new OutputStreamWriter(out);
+ this.write(writer);
+ writer.flush();
+ return new String(out.toByteArray());
+ } catch (IOException e) {
+ // Java exception handling suxx
+ return super.toString();
+ }
+ }
+
+
+ /**
+ * Writes the XML element to a writer.
+ *
+ * @param writer
+ * The writer to write the XML data to.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>writer != null</code>
+ * <li><code>writer</code> is not closed
+ * </ul></dd></dl>
+ *
+ * @throws java.io.IOException
+ * If the data could not be written to the writer.
+ *
+ * @see nanoxml.XMLElement#toString()
+ */
+ public void write(Writer writer)
+ throws IOException
+ {
+ if (this.name == null) {
+ this.writeEncoded(writer, this.contents);
+ return;
+ }
+ writer.write('<');
+ writer.write(this.name);
+ if (! this.attributes.isEmpty()) {
+ Enumeration e = this.attributes.keys();
+ while (e.hasMoreElements()) {
+ writer.write(' ');
+ String key = (String) e.nextElement();
+ String value = (String) this.attributes.get(key);
+ writer.write(key);
+ writer.write('='); writer.write('"');
+ this.writeEncoded(writer, value);
+ writer.write('"');
+ }
+ }
+ if ((this.contents != null) && (this.contents.length() > 0)) {
+ writer.write('>');
+ this.writeEncoded(writer, this.contents);
+ writer.write('<'); writer.write('/');
+ writer.write(this.name);
+ writer.write('>');
+ } else if (this.children.isEmpty()) {
+ writer.write('/'); writer.write('>');
+ } else {
+ writer.write('>');
+ Enumeration e = this.enumerateChildren();
+ while (e.hasMoreElements()) {
+ XMLElement child = (XMLElement) e.nextElement();
+ child.write(writer);
+ }
+ writer.write('<'); writer.write('/');
+ writer.write(this.name);
+ writer.write('>');
+ }
+ }
+
+
+ /**
+ * Writes a string encoded to a writer.
+ *
+ * @param writer
+ * The writer to write the XML data to.
+ * @param str
+ * The string to write encoded.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>writer != null</code>
+ * <li><code>writer</code> is not closed
+ * <li><code>str != null</code>
+ * </ul></dd></dl>
+ */
+ protected void writeEncoded(Writer writer,
+ String str)
+ throws IOException
+ {
+ for (int i = 0; i < str.length(); i += 1) {
+ char ch = str.charAt(i);
+ switch (ch) {
+ case '<':
+ writer.write('&'); writer.write('l'); writer.write('t');
+ writer.write(';');
+ break;
+ case '>':
+ writer.write('&'); writer.write('g'); writer.write('t');
+ writer.write(';');
+ break;
+ case '&':
+ writer.write('&'); writer.write('a'); writer.write('m');
+ writer.write('p'); writer.write(';');
+ break;
+ case '"':
+ writer.write('&'); writer.write('q'); writer.write('u');
+ writer.write('o'); writer.write('t'); writer.write(';');
+ break;
+ case '\'':
+ writer.write('&'); writer.write('a'); writer.write('p');
+ writer.write('o'); writer.write('s'); writer.write(';');
+ break;
+ default:
+ int unicode = (int) ch;
+ if ((unicode < 32) || (unicode > 126)) {
+ writer.write('&'); writer.write('#');
+ writer.write('x');
+ writer.write(Integer.toString(unicode, 16));
+ writer.write(';');
+ } else {
+ writer.write(ch);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Scans an identifier from the current reader.
+ * The scanned identifier is appended to <code>result</code>.
+ *
+ * @param result
+ * The buffer in which the scanned identifier will be put.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>result != null</code>
+ * <li>The next character read from the reader is a valid first
+ * character of an XML identifier.
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>The next character read from the reader won't be an identifier
+ * character.
+ * </ul></dd></dl><dl>
+ */
+ protected void scanIdentifier(StringBuffer result)
+ throws IOException
+ {
+ for (;;) {
+ char ch = this.readChar();
+ if (((ch < 'A') || (ch > 'Z')) && ((ch < 'a') || (ch > 'z'))
+ && ((ch < '0') || (ch > '9')) && (ch != '_') && (ch != '.')
+ && (ch != ':') && (ch != '-') && (ch <= '\u007E')) {
+ this.unreadChar(ch);
+ return;
+ }
+ result.append(ch);
+ }
+ }
+
+
+ /**
+ * This method scans an identifier from the current reader.
+ *
+ * @return the next character following the whitespace.
+ */
+ protected char scanWhitespace()
+ throws IOException
+ {
+ for (;;) {
+ char ch = this.readChar();
+ switch (ch) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ break;
+ default:
+ return ch;
+ }
+ }
+ }
+
+
+ /**
+ * This method scans an identifier from the current reader.
+ * The scanned whitespace is appended to <code>result</code>.
+ *
+ * @return the next character following the whitespace.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>result != null</code>
+ * </ul></dd></dl>
+ */
+ protected char scanWhitespace(StringBuffer result)
+ throws IOException
+ {
+ for (;;) {
+ char ch = this.readChar();
+ switch (ch) {
+ case ' ':
+ case '\t':
+ case '\n':
+ result.append(ch);
+ case '\r':
+ break;
+ default:
+ return ch;
+ }
+ }
+ }
+
+
+ /**
+ * This method scans a delimited string from the current reader.
+ * The scanned string without delimiters is appended to
+ * <code>string</code>.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>string != null</code>
+ * <li>the next char read is the string delimiter
+ * </ul></dd></dl>
+ */
+ protected void scanString(StringBuffer string)
+ throws IOException
+ {
+ char delimiter = this.readChar();
+ if ((delimiter != '\'') && (delimiter != '"')) {
+ throw this.expectedInput("' or \"");
+ }
+ for (;;) {
+ char ch = this.readChar();
+ if (ch == delimiter) {
+ return;
+ } else if (ch == '&') {
+ this.resolveEntity(string);
+ } else {
+ string.append(ch);
+ }
+ }
+ }
+
+
+ /**
+ * Scans a #PCDATA element. CDATA sections and entities are resolved.
+ * The next < char is skipped.
+ * The scanned data is appended to <code>data</code>.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>data != null</code>
+ * </ul></dd></dl>
+ */
+ protected void scanPCData(StringBuffer data)
+ throws IOException
+ {
+ for (;;) {
+ char ch = this.readChar();
+ if (ch == '<') {
+ ch = this.readChar();
+ if (ch == '!') {
+ this.checkCDATA(data);
+ } else {
+ this.unreadChar(ch);
+ return;
+ }
+ } else if (ch == '&') {
+ this.resolveEntity(data);
+ } else {
+ data.append(ch);
+ }
+ }
+ }
+
+
+ /**
+ * Scans a special tag and if the tag is a CDATA section, append its
+ * content to <code>buf</code>.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>buf != null</code>
+ * <li>The first < has already been read.
+ * </ul></dd></dl>
+ */
+ protected boolean checkCDATA(StringBuffer buf)
+ throws IOException
+ {
+ char ch = this.readChar();
+ if (ch != '[') {
+ this.unreadChar(ch);
+ this.skipSpecialTag(0);
+ return false;
+ } else if (! this.checkLiteral("CDATA[")) {
+ this.skipSpecialTag(1); // one [ has already been read
+ return false;
+ } else {
+ int delimiterCharsSkipped = 0;
+ while (delimiterCharsSkipped < 3) {
+ ch = this.readChar();
+ switch (ch) {
+ case ']':
+ if (delimiterCharsSkipped < 2) {
+ delimiterCharsSkipped += 1;
+ } else {
+ buf.append(']');
+ buf.append(']');
+ delimiterCharsSkipped = 0;
+ }
+ break;
+ case '>':
+ if (delimiterCharsSkipped < 2) {
+ for (int i = 0; i < delimiterCharsSkipped; i++) {
+ buf.append(']');
+ }
+ delimiterCharsSkipped = 0;
+ buf.append('>');
+ } else {
+ delimiterCharsSkipped = 3;
+ }
+ break;
+ default:
+ for (int i = 0; i < delimiterCharsSkipped; i += 1) {
+ buf.append(']');
+ }
+ buf.append(ch);
+ delimiterCharsSkipped = 0;
+ }
+ }
+ return true;
+ }
+ }
+
+
+ /**
+ * Skips a comment.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li>The first <!-- has already been read.
+ * </ul></dd></dl>
+ */
+ protected void skipComment()
+ throws IOException
+ {
+ int dashesToRead = 2;
+ while (dashesToRead > 0) {
+ char ch = this.readChar();
+ if (ch == '-') {
+ dashesToRead -= 1;
+ } else {
+ dashesToRead = 2;
+ }
+ }
+ if (this.readChar() != '>') {
+ throw this.expectedInput(">");
+ }
+ }
+
+
+ /**
+ * Skips a special tag or comment.
+ *
+ * @param bracketLevel The number of open square brackets ([) that have
+ * already been read.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li>The first <! has already been read.
+ * <li><code>bracketLevel >= 0</code>
+ * </ul></dd></dl>
+ */
+ protected void skipSpecialTag(int bracketLevel)
+ throws IOException
+ {
+ int tagLevel = 1; // <
+ char stringDelimiter = '\0';
+ if (bracketLevel == 0) {
+ char ch = this.readChar();
+ if (ch == '[') {
+ bracketLevel += 1;
+ } else if (ch == '-') {
+ ch = this.readChar();
+ if (ch == '[') {
+ bracketLevel += 1;
+ } else if (ch == ']') {
+ bracketLevel -= 1;
+ } else if (ch == '-') {
+ this.skipComment();
+ return;
+ }
+ }
+ }
+ while (tagLevel > 0) {
+ char ch = this.readChar();
+ if (stringDelimiter == '\0') {
+ if ((ch == '"') || (ch == '\'')) {
+ stringDelimiter = ch;
+ } else if (bracketLevel <= 0) {
+ if (ch == '<') {
+ tagLevel += 1;
+ } else if (ch == '>') {
+ tagLevel -= 1;
+ }
+ }
+ if (ch == '[') {
+ bracketLevel += 1;
+ } else if (ch == ']') {
+ bracketLevel -= 1;
+ }
+ } else {
+ if (ch == stringDelimiter) {
+ stringDelimiter = '\0';
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Scans the data for literal text.
+ * Scanning stops when a character does not match or after the complete
+ * text has been checked, whichever comes first.
+ *
+ * @param literal the literal to check.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>literal != null</code>
+ * </ul></dd></dl>
+ */
+ protected boolean checkLiteral(String literal)
+ throws IOException
+ {
+ int length = literal.length();
+ for (int i = 0; i < length; i += 1) {
+ if (this.readChar() != literal.charAt(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ /**
+ * Reads a character from a reader.
+ */
+ protected char readChar()
+ throws IOException
+ {
+ if (this.charReadTooMuch != '\0') {
+ char ch = this.charReadTooMuch;
+ this.charReadTooMuch = '\0';
+ return ch;
+ } else {
+ int i = this.reader.read();
+ if (i < 0) {
+ throw this.unexpectedEndOfData();
+ } else if (i == 10) {
+ this.parserLineNr += 1;
+ return '\n';
+ } else {
+ return (char) i;
+ }
+ }
+ }
+
+
+ /**
+ * Scans an XML element.
+ *
+ * @param elt The element that will contain the result.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li>The first < has already been read.
+ * <li><code>elt != null</code>
+ * </ul></dd></dl>
+ */
+ protected void scanElement(XMLElement elt)
+ throws IOException
+ {
+ StringBuffer buf = new StringBuffer();
+ this.scanIdentifier(buf);
+ String name = buf.toString();
+ elt.setName(name);
+ char ch = this.scanWhitespace();
+ while ((ch != '>') && (ch != '/')) {
+ buf.setLength(0);
+ this.unreadChar(ch);
+ this.scanIdentifier(buf);
+ String key = buf.toString();
+ ch = this.scanWhitespace();
+ if (ch != '=') {
+ throw this.expectedInput("=");
+ }
+ this.unreadChar(this.scanWhitespace());
+ buf.setLength(0);
+ this.scanString(buf);
+ elt.setAttribute(key, buf);
+ ch = this.scanWhitespace();
+ }
+ if (ch == '/') {
+ ch = this.readChar();
+ if (ch != '>') {
+ throw this.expectedInput(">");
+ }
+ return;
+ }
+ buf.setLength(0);
+ ch = this.scanWhitespace(buf);
+ if (ch != '<') {
+ this.unreadChar(ch);
+ this.scanPCData(buf);
+ } else {
+ for (;;) {
+ ch = this.readChar();
+ if (ch == '!') {
+ if (this.checkCDATA(buf)) {
+ this.scanPCData(buf);
+ break;
+ } else {
+ ch = this.scanWhitespace(buf);
+ if (ch != '<') {
+ this.unreadChar(ch);
+ this.scanPCData(buf);
+ break;
+ }
+ }
+ } else {
+ if ((ch != '/') || this.ignoreWhitespace) {
+ buf.setLength(0);
+ }
+ if (ch == '/') {
+ this.unreadChar(ch);
+ }
+ break;
+ }
+ }
+ }
+ if (buf.length() == 0) {
+ while (ch != '/') {
+ if (ch == '!') {
+ ch = this.readChar();
+ if (ch != '-') {
+ throw this.expectedInput("Comment or Element");
+ }
+ ch = this.readChar();
+ if (ch != '-') {
+ throw this.expectedInput("Comment or Element");
+ }
+ this.skipComment();
+ } else {
+ this.unreadChar(ch);
+ XMLElement child = this.createAnotherElement();
+ this.scanElement(child);
+ elt.addChild(child);
+ }
+ ch = this.scanWhitespace();
+ if (ch != '<') {
+ throw this.expectedInput("<");
+ }
+ ch = this.readChar();
+ }
+ this.unreadChar(ch);
+ } else {
+ if (this.ignoreWhitespace) {
+ elt.setContent(buf.toString().trim());
+ } else {
+ elt.setContent(buf.toString());
+ }
+ }
+ ch = this.readChar();
+ if (ch != '/') {
+ throw this.expectedInput("/");
+ }
+ this.unreadChar(this.scanWhitespace());
+ if (! this.checkLiteral(name)) {
+ throw this.expectedInput(name);
+ }
+ if (this.scanWhitespace() != '>') {
+ throw this.expectedInput(">");
+ }
+ }
+
+
+ /**
+ * Resolves an entity. The name of the entity is read from the reader.
+ * The value of the entity is appended to <code>buf</code>.
+ *
+ * @param buf Where to put the entity value.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li>The first & has already been read.
+ * <li><code>buf != null</code>
+ * </ul></dd></dl>
+ */
+ protected void resolveEntity(StringBuffer buf)
+ throws IOException
+ {
+ char ch = '\0';
+ StringBuffer keyBuf = new StringBuffer();
+ for (;;) {
+ ch = this.readChar();
+ if (ch == ';') {
+ break;
+ }
+ keyBuf.append(ch);
+ }
+ String key = keyBuf.toString();
+ if (key.charAt(0) == '#') {
+ try {
+ if (key.charAt(1) == 'x') {
+ ch = (char) Integer.parseInt(key.substring(2), 16);
+ } else {
+ ch = (char) Integer.parseInt(key.substring(1), 10);
+ }
+ } catch (NumberFormatException e) {
+ throw this.unknownEntity(key);
+ }
+ buf.append(ch);
+ } else {
+ char[] value = (char[]) this.entities.get(key);
+ if (value == null) {
+ throw this.unknownEntity(key);
+ }
+ buf.append(value);
+ }
+ }
+
+
+ /**
+ * Pushes a character back to the read-back buffer.
+ *
+ * @param ch The character to push back.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li>The read-back buffer is empty.
+ * <li><code>ch != '\0'</code>
+ * </ul></dd></dl>
+ */
+ protected void unreadChar(char ch)
+ {
+ this.charReadTooMuch = ch;
+ }
+
+
+ /**
+ * Creates a parse exception for when an invalid valueset is given to
+ * a method.
+ *
+ * @param name The name of the entity.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * </ul></dd></dl>
+ */
+ protected XMLParseException invalidValueSet(String name)
+ {
+ String msg = "Invalid value set (entity name = \"" + name + "\")";
+ return new XMLParseException(this.getName(), this.parserLineNr, msg);
+ }
+
+
+ /**
+ * Creates a parse exception for when an invalid value is given to a
+ * method.
+ *
+ * @param name The name of the entity.
+ * @param value The value of the entity.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>value != null</code>
+ * </ul></dd></dl>
+ */
+ protected XMLParseException invalidValue(String name,
+ String value)
+ {
+ String msg = "Attribute \"" + name + "\" does not contain a valid "
+ + "value (\"" + value + "\")";
+ return new XMLParseException(this.getName(), this.parserLineNr, msg);
+ }
+
+
+ /**
+ * Creates a parse exception for when the end of the data input has been
+ * reached.
+ */
+ protected XMLParseException unexpectedEndOfData()
+ {
+ String msg = "Unexpected end of data reached";
+ return new XMLParseException(this.getName(), this.parserLineNr, msg);
+ }
+
+
+ /**
+ * Creates a parse exception for when a syntax error occured.
+ *
+ * @param context The context in which the error occured.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>context != null</code>
+ * <li><code>context.length() > 0</code>
+ * </ul></dd></dl>
+ */
+ protected XMLParseException syntaxError(String context)
+ {
+ String msg = "Syntax error while parsing " + context;
+ return new XMLParseException(this.getName(), this.parserLineNr, msg);
+ }
+
+
+ /**
+ * Creates a parse exception for when the next character read is not
+ * the character that was expected.
+ *
+ * @param charSet The set of characters (in human readable form) that was
+ * expected.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>charSet != null</code>
+ * <li><code>charSet.length() > 0</code>
+ * </ul></dd></dl>
+ */
+ protected XMLParseException expectedInput(String charSet)
+ {
+ String msg = "Expected: " + charSet;
+ return new XMLParseException(this.getName(), this.parserLineNr, msg);
+ }
+
+
+ /**
+ * Creates a parse exception for when an entity could not be resolved.
+ *
+ * @param name The name of the entity.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>name != null</code>
+ * <li><code>name.length() > 0</code>
+ * </ul></dd></dl>
+ */
+ protected XMLParseException unknownEntity(String name)
+ {
+ String msg = "Unknown or invalid entity: &" + name + ";";
+ return new XMLParseException(this.getName(), this.parserLineNr, msg);
+ }
+
+}
Added: trunk/plugins/ThawIndexBrowser/nanoxml/XMLParseException.java
===================================================================
--- trunk/plugins/ThawIndexBrowser/nanoxml/XMLParseException.java
(rev 0)
+++ trunk/plugins/ThawIndexBrowser/nanoxml/XMLParseException.java
2008-03-30 15:23:56 UTC (rev 18860)
@@ -0,0 +1,130 @@
+/* XMLParseException.java
+ *
+ * $Revision: 1.4 $
+ * $Date: 2002/03/24 10:27:59 $
+ * $Name: RELEASE_2_2_1 $
+ *
+ * This file is part of NanoXML 2 Lite.
+ * Copyright (C) 2000-2002 Marc De Scheemaecker, All Rights Reserved.
+ *
+ * This software is provided 'as-is', without any express or implied warranty.
+ * In no event will the authors be held liable for any damages arising from the
+ * use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software in
+ * a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source distribution.
+ *****************************************************************************/
+
+
+package plugins.ThawIndexBrowser.nanoxml;
+
+
+/**
+ * An XMLParseException is thrown when an error occures while parsing an XML
+ * string.
+ * <P>
+ * $Revision: 1.4 $<BR>
+ * $Date: 2002/03/24 10:27:59 $<P>
+ *
+ * @see nanoxml.XMLElement
+ *
+ * @author Marc De Scheemaecker
+ * @version $Name: RELEASE_2_2_1 $, $Revision: 1.4 $
+ */
+public class XMLParseException
+ extends RuntimeException
+{
+
+ /**
+ * Indicates that no line number has been associated with this exception.
+ */
+ public static final int NO_LINE = -1;
+
+
+ /**
+ * The line number in the source code where the error occurred, or
+ * <code>NO_LINE</code> if the line number is unknown.
+ *
+ * <dl><dt><b>Invariants:</b></dt><dd>
+ * <ul><li><code>lineNr > 0 || lineNr == NO_LINE</code>
+ * </ul></dd></dl>
+ */
+ private int lineNr;
+
+
+ /**
+ * Creates an exception.
+ *
+ * @param name The name of the element where the error is located.
+ * @param message A message describing what went wrong.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>message != null</code>
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>getLineNr() => NO_LINE
+ * </ul></dd></dl><dl>
+ */
+ public XMLParseException(String name,
+ String message)
+ {
+ super("XML Parse Exception during parsing of "
+ + ((name == null) ? "the XML definition"
+ : ("a " + name + " element"))
+ + ": " + message);
+ this.lineNr = XMLParseException.NO_LINE;
+ }
+
+
+ /**
+ * Creates an exception.
+ *
+ * @param name The name of the element where the error is located.
+ * @param lineNr The number of the line in the input.
+ * @param message A message describing what went wrong.
+ *
+ * </dl><dl><dt><b>Preconditions:</b></dt><dd>
+ * <ul><li><code>message != null</code>
+ * <li><code>lineNr > 0</code>
+ * </ul></dd></dl>
+ *
+ * <dl><dt><b>Postconditions:</b></dt><dd>
+ * <ul><li>getLineNr() => lineNr
+ * </ul></dd></dl><dl>
+ */
+ public XMLParseException(String name,
+ int lineNr,
+ String message)
+ {
+ super("XML Parse Exception during parsing of "
+ + ((name == null) ? "the XML definition"
+ : ("a " + name + " element"))
+ + " at line " + lineNr + ": " + message);
+ this.lineNr = lineNr;
+ }
+
+
+ /**
+ * Where the error occurred, or <code>NO_LINE</code> if the line number is
+ * unknown.
+ *
+ * @see nanoxml.XMLParseException#NO_LINE
+ */
+ public int getLineNr()
+ {
+ return this.lineNr;
+ }
+
+}