diff options
Diffstat (limited to 'sax/java/android/sax/Element.java')
-rw-r--r-- | sax/java/android/sax/Element.java | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/sax/java/android/sax/Element.java b/sax/java/android/sax/Element.java new file mode 100644 index 0000000..8c8334c --- /dev/null +++ b/sax/java/android/sax/Element.java @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.sax; + +import org.xml.sax.Locator; +import org.xml.sax.SAXParseException; + +import java.util.ArrayList; + +import android.util.Log; + +/** + * An XML element. Provides access to child elements and hooks to listen + * for events related to this element. + * + * @see RootElement + */ +public class Element { + + final String uri; + final String localName; + final int depth; + final Element parent; + + Children children; + ArrayList<Element> requiredChilden; + + boolean visited; + + StartElementListener startElementListener; + EndElementListener endElementListener; + EndTextElementListener endTextElementListener; + + Element(Element parent, String uri, String localName, int depth) { + this.parent = parent; + this.uri = uri; + this.localName = localName; + this.depth = depth; + } + + /** + * Gets the child element with the given name. Uses an empty string as the + * namespace. + */ + public Element getChild(String localName) { + return getChild("", localName); + } + + /** + * Gets the child element with the given name. + */ + public Element getChild(String uri, String localName) { + if (endTextElementListener != null) { + throw new IllegalStateException("This element already has an end" + + " text element listener. It cannot have children."); + } + + if (children == null) { + children = new Children(); + } + + return children.getOrCreate(this, uri, localName); + } + + /** + * Gets the child element with the given name. Uses an empty string as the + * namespace. We will throw a {@link org.xml.sax.SAXException} at parsing + * time if the specified child is missing. This helps you ensure that your + * listeners are called. + */ + public Element requireChild(String localName) { + return requireChild("", localName); + } + + /** + * Gets the child element with the given name. We will throw a + * {@link org.xml.sax.SAXException} at parsing time if the specified child + * is missing. This helps you ensure that your listeners are called. + */ + public Element requireChild(String uri, String localName) { + Element child = getChild(uri, localName); + + if (requiredChilden == null) { + requiredChilden = new ArrayList<Element>(); + requiredChilden.add(child); + } else { + if (!requiredChilden.contains(child)) { + requiredChilden.add(child); + } + } + + return child; + } + + /** + * Sets start and end element listeners at the same time. + */ + public void setElementListener(ElementListener elementListener) { + setStartElementListener(elementListener); + setEndElementListener(elementListener); + } + + /** + * Sets start and end text element listeners at the same time. + */ + public void setTextElementListener(TextElementListener elementListener) { + setStartElementListener(elementListener); + setEndTextElementListener(elementListener); + } + + /** + * Sets a listener for the start of this element. + */ + public void setStartElementListener( + StartElementListener startElementListener) { + if (this.startElementListener != null) { + throw new IllegalStateException( + "Start element listener has already been set."); + } + this.startElementListener = startElementListener; + } + + /** + * Sets a listener for the end of this element. + */ + public void setEndElementListener(EndElementListener endElementListener) { + if (this.endElementListener != null) { + throw new IllegalStateException( + "End element listener has already been set."); + } + this.endElementListener = endElementListener; + } + + /** + * Sets a listener for the end of this text element. + */ + public void setEndTextElementListener( + EndTextElementListener endTextElementListener) { + if (this.endTextElementListener != null) { + throw new IllegalStateException( + "End text element listener has already been set."); + } + + if (children != null) { + throw new IllegalStateException("This element already has children." + + " It cannot have an end text element listener."); + } + + this.endTextElementListener = endTextElementListener; + } + + @Override + public String toString() { + return toString(uri, localName); + } + + static String toString(String uri, String localName) { + return "'" + (uri.equals("") ? localName : uri + ":" + localName) + "'"; + } + + /** + * Clears flags on required children. + */ + void resetRequiredChildren() { + ArrayList<Element> requiredChildren = this.requiredChilden; + if (requiredChildren != null) { + for (int i = requiredChildren.size() - 1; i >= 0; i--) { + requiredChildren.get(i).visited = false; + } + } + } + + /** + * Throws an exception if a required child was not present. + */ + void checkRequiredChildren(Locator locator) throws SAXParseException { + ArrayList<Element> requiredChildren = this.requiredChilden; + if (requiredChildren != null) { + for (int i = requiredChildren.size() - 1; i >= 0; i--) { + Element child = requiredChildren.get(i); + if (!child.visited) { + throw new BadXmlException( + "Element named " + this + " is missing required" + + " child element named " + + child + ".", locator); + } + } + } + } +} |