// This file is part of TagSoup and is Copyright 2002-2008 by John Cowan. // // TagSoup is licensed under the Apache License, // Version 2.0. You may obtain a copy of this license at // http://www.apache.org/licenses/LICENSE-2.0 . You may also have // additional legal rights not granted by this license. // // TagSoup is distributed in the hope that it will be useful, but // unless required by applicable law or agreed to in writing, TagSoup // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS // OF ANY KIND, either express or implied; not even the implied warranty // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. package org.ccil.cowan.tagsoup; /** The internal representation of an actual element (not an element type). An Element has an element type, attributes, and a successor Element for use in constructing stacks and queues of Elements. @see ElementType @see AttributesImpl */ public class Element { private ElementType theType; // type of element private AttributesImpl theAtts; // attributes of element private Element theNext; // successor of element private boolean preclosed; // this element has been preclosed /** Return an Element from a specified ElementType. @param type The element type of the newly constructed element @param defaultAttributes True if default attributes are wanted */ public Element(ElementType type, boolean defaultAttributes) { theType = type; if (defaultAttributes) theAtts = new AttributesImpl(type.atts()); else theAtts = new AttributesImpl(); theNext = null; preclosed = false; } /** Return the element type. @return The element type. */ public ElementType type() { return theType; } /** Return the attributes as an AttributesImpl object. Returning an AttributesImpl makes the attributes mutable. @return The attributes @see AttributesImpl */ public AttributesImpl atts() { return theAtts; } /** Return the next element in an element stack or queue. @return The next element */ public Element next() { return theNext; } /** Change the next element in an element stack or queue. @param next The new next element */ public void setNext(Element next) { theNext = next; } /** Return the name of the element's type. Convenience method. @return The element type name */ public String name() { return theType.name(); } /** Return the namespace name of the element's type. Convenience method. @return The element type namespace name */ public String namespace() { return theType.namespace(); } /** Return the local name of the element's type. Convenience method. @return The element type local name */ public String localName() { return theType.localName(); } /** Return the content model vector of the element's type. Convenience method. @return The content model vector */ public int model() { return theType.model(); } /** Return the member-of vector of the element's type. Convenience method. @return The member-of vector */ public int memberOf() { return theType.memberOf(); } /** Return the flags vector of the element's type. Convenience method. @return The flags vector */ public int flags() { return theType.flags(); } /** Return the parent element type of the element's type. Convenience method. @return The parent element type */ public ElementType parent() { return theType.parent(); } /** Return true if the type of this element can contain the type of another element. Convenience method. @param other The other element */ public boolean canContain(Element other) { return theType.canContain(other.theType); } /** Set an attribute and its value into this element. @param name The attribute name (Qname) @param type The attribute type @param value The attribute value */ public void setAttribute(String name, String type, String value) { theType.setAttribute(theAtts, name, type, value); } /** Make this element anonymous. Remove any id or name attribute present in the element's attributes. */ public void anonymize() { for (int i = theAtts.getLength() - 1; i >= 0; i--) { if (theAtts.getType(i).equals("ID") || theAtts.getQName(i).equals("name")) { theAtts.removeAttribute(i); } } } /** Clean the attributes of this element. Attributes with null name (the name was ill-formed) or null value (the attribute was present in the element type but not in this actual element) are removed. */ public void clean() { for (int i = theAtts.getLength() - 1; i >= 0; i--) { String name = theAtts.getLocalName(i); if (theAtts.getValue(i) == null || name == null || name.length() == 0) { theAtts.removeAttribute(i); continue; } } } /** Force this element to preclosed status, meaning that an end-tag has been seen but the element cannot yet be closed for structural reasons. */ public void preclose() { preclosed = true; } /** Return true if this element has been preclosed. */ public boolean isPreclosed() { return preclosed; } }