// 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 com.onegravity.rteditor.converter.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 <tt>id</tt> or <tt>name</tt>
* 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;
}
}