All Downloads are FREE. Search and download functionalities are using the official Maven repository.

info.bliki.wiki.tags.util.WikiTagNode Maven / Gradle / Ivy

The newest version!
package info.bliki.wiki.tags.util;

import java.util.ArrayList;
import java.util.List;

/**
 * WikiTagNode represents a generic tag. If no scanner is registered for a given
 * tag name, this is what you get. This is also the base class for all tags
 * created by the parser.
 */
public class WikiTagNode extends AbstractNode {
    /**
     *
     */
    private static final long serialVersionUID = -5135255005207719745L;

    /**
     * An empty set of tag names.
     */
    private final static String[] NONE = new String[0];

    /**
     * The tag attributes. Objects of type {@link Attribute}. The first element is
     * the tag name, subsequent elements being either whitespace or real
     * attributes.
     */
    protected List mAttributes;

    /**
     * Create an empty tag.
     */
    public WikiTagNode() {
        this(-1, -1, new ArrayList());
    }

    /**
     * Create a tag with the location and attributes provided
     *
     * @param page
     *          The page this tag was read from.
     * @param start
     *          The starting offset of this node within the page.
     * @param end
     *          The ending offset of this node within the page.
     * @param attributes
     *          The list of attributes that were parsed in this tag.
     * @see Attribute
     */
    public WikiTagNode(int start, int end, ArrayList attributes) {
        super(start, end);

        mAttributes = attributes;
        if ((null == mAttributes) || (0 == mAttributes.size())) {
            String[] names;

            names = getIds();
            if ((null != names) && (0 != names.length))
                setTagName(names[0]);
            else
                setTagName(""); // make sure it's not null
        } else {
            setTagName(((Attribute) mAttributes.get(0)).getName());
        }
    }

    /**
     * Returns the value of an attribute.
     *
     * @param name
     *          Name of attribute, case insensitive.
     * @return The value associated with the attribute or null if it does not
     *         exist, or is a stand-alone or
     */
    public String getAttribute(String name) {
        Attribute attribute;
        String ret;

        ret = null;

        attribute = getAttributeEx(name);
        if (null != attribute)
            ret = attribute.getValue();

        return (ret);
    }

    /**
     * Set attribute with given key, value pair. Figures out a quote character to
     * use if necessary.
     *
     * @param key
     *          The name of the attribute.
     * @param value
     *          The value of the attribute.
     */
    public void setAttribute(String key, String value) {
        char ch;
        boolean needed;
        boolean singleq;
        boolean doubleq;
        // String ref;
        // StringBuffer buffer;
        char quote;
        Attribute attribute;

        // first determine if there's whitespace in the value
        // and while we'return at it find a suitable quote character
        needed = false;
        singleq = true;
        doubleq = true;
        if (null != value)
            for (int i = 0; i < value.length(); i++) {
                ch = value.charAt(i);
                if (Character.isWhitespace(ch))
                    needed = true;
                else if ('\'' == ch)
                    singleq = false;
                else if ('"' == ch)
                    doubleq = false;
            }

        // now apply quoting
        if (needed) {
            if (doubleq)
                quote = '"';
            else if (singleq)
                quote = '\'';
            else {
                // uh-oh, we need to convert some quotes into character
                // references
                // convert all double quotes into "
                quote = '"';
                // ref = """; // Translate.encode (quote);
                // JDK 1.4: value = value.replaceAll ("\"", ref);
                value = value.replaceAll("\"", """);
                // value = StringUtils.replace(value, "\"", """);

                // buffer = new StringBuffer(value.length() * 5);
                // for (int i = 0; i < value.length(); i++) {
                // ch = value.charAt(i);
                // if (quote == ch)
                // buffer.append(ref);
                // else
                // buffer.append(ch);
                // }
                // value = buffer.toString();
            }
        } else
            quote = 0;
        attribute = getAttributeEx(key);
        if (null != attribute) { // see if we can splice it in rather than
            // replace it
            attribute.setValue(value);
            if (0 != quote)
                attribute.setQuote(quote);
        } else
            setAttribute(key, value, quote);
    }

    /**
     * Remove the attribute with the given key, if it exists.
     *
     * @param key
     *          The name of the attribute.
     */
    public void removeAttribute(String key) {
        Attribute attribute;

        attribute = getAttributeEx(key);
        if (null != attribute)
            getAttributesEx().remove(attribute);
    }

    /**
     * Set attribute with given key, value pair where the value is quoted by
     * quote.
     *
     * @param key
     *          The name of the attribute.
     * @param value
     *          The value of the attribute.
     * @param quote
     *          The quote character to be used around value. If zero, it is an
     *          unquoted value.
     */
    public void setAttribute(String key, String value, char quote) {
        setAttribute(new NodeAttribute(key, value, quote));
    }

    /**
     * Returns the attribute with the given name.
     *
     * @param name
     *          Name of attribute, case insensitive.
     * @return The attribute or null if it does not exist.
     */
    public NodeAttribute getAttributeEx(String name) {
        List attributes;
        int size;
        NodeAttribute attribute;
        String string;
        NodeAttribute ret;

        ret = null;

        attributes = getAttributesEx();
        if (null != attributes) {
            size = attributes.size();
            for (int i = 0; i < size; i++) {
                attribute = attributes.get(i);
                string = attribute.getName();
                if ((null != string) && name.equalsIgnoreCase(string)) {
                    ret = attribute;
                    i = size; // exit fast
                }
            }
        }

        return ret;
    }

    /**
     * Set an attribute.
     *
     * @param attribute
     *          The attribute to set.
     * @see #setAttribute(Attribute)
     */
    public void setAttributeEx(NodeAttribute attribute) {
        setAttribute(attribute);
    }

    /**
     * Set an attribute. This replaces an attribute of the same name. To set the
     * zeroth attribute (the tag name), use setTagName().
     *
     * @param attribute
     *          The attribute to set.
     */
    public void setAttribute(NodeAttribute attribute) {
        boolean replaced;
        List attributes;
        int length;
        String name;
        Attribute test;
        String test_name;

        replaced = false;
        attributes = getAttributesEx();
        length = attributes.size();
        if (0 < length) {
            name = attribute.getName();
            for (int i = 1; i < attributes.size(); i++) {
                test = attributes.get(i);
                test_name = test.getName();
                if (null != test_name)
                    if (test_name.equalsIgnoreCase(name)) {
                        attributes.set(i, attribute);
                        replaced = true;
                    }
            }
        }
        if (!replaced) {
            // add whitespace between attributes
            if ((0 != length) && !(attributes.get(length - 1)).isWhitespace())
                attributes.add(new NodeAttribute(" "));
            attributes.add(attribute);
        }
    }

    /**
     * Gets the attributes in the tag.
     *
     * @return Returns the list of {@link Attribute Attributes} in the tag. The
     *         first element is the tag name, subsequent elements being either
     *         whitespace or real attributes.
     */
    public List getAttributesEx() {
        return (mAttributes);
    }

    /**
     * Return the name of this tag.
     * 

* * Note: This value is converted to uppercase and does not * begin with "/" if it is an end tag. Nor does it end with * a slash in the case of an XML type tag. * To get at the original text of the tag name use * {@link #getRawTagName getRawTagName()}. * The conversion to uppercase is performed with an ENGLISH locale. * * * @return The tag name. */ public String getTagName() { String ret; ret = getRawTagName(); if (null != ret) { ret = ret.toLowerCase(); if (ret.startsWith("/")) ret = ret.substring(1); if (ret.endsWith("/")) ret = ret.substring(0, ret.length() - 1); } return (ret); } /** * Return the name of this tag. * * @return The tag name or null if this tag contains nothing or only * whitespace. */ public String getRawTagName() { List attributes; String ret; ret = null; attributes = getAttributesEx(); if (0 != attributes.size()) ret = attributes.get(0).getName(); return (ret); } /** * Set the name of this tag. This creates or replaces the first attribute of * the tag (the zeroth element of the attribute vector). * * @param name * The tag name. */ public void setTagName(String name) { NodeAttribute attribute; List attributes; Attribute zeroth; attribute = new NodeAttribute(name, null, (char) 0); attributes = getAttributesEx(); if (null == attributes) { attributes = new ArrayList<>(); setAttributesEx(attributes); } if (0 == attributes.size()) // nothing added yet attributes.add(attribute); else { zeroth = attributes.get(0); // check for attribute that looks like a name if ((null == zeroth.getValue()) && (0 == zeroth.getQuote())) attributes.set(0, attribute); else attributes.add(0, attribute); } } /** * Return the text contained in this tag. * * @return The complete contents of the tag (within the angle brackets). */ @Override public String getText() { String ret; ret = toHtml(); ret = ret.substring(1, ret.length() - 1); return (ret); } /** * Sets the attributes. NOTE: Values of the extended hashtable are two element * arrays of String, with the first element being the original name (not * uppercased), and the second element being the value. * * @param attribs * The attribute collection to set. */ public void setAttributesEx(List attribs) { mAttributes = attribs; } /** * Sets the nodeBegin. * * @param tagBegin * The nodeBegin to set */ public void setTagBegin(int tagBegin) { nodeBegin = tagBegin; } /** * Gets the nodeBegin. * * @return The nodeBegin value. */ public int getTagBegin() { return (nodeBegin); } /** * Sets the nodeEnd. * * @param tagEnd * The nodeEnd to set */ public void setTagEnd(int tagEnd) { nodeEnd = tagEnd; } /** * Gets the nodeEnd. * * @return The nodeEnd value. */ public int getTagEnd() { return (nodeEnd); } /** * Get the plain text from this node. * * @return An empty string (tag contents do not display in a browser). If you * want this tags HTML equivalent, use {@link #toHtml toHtml()}. */ @Override public String toPlainTextString() { return (""); } /** * Render the tag as HTML. A call to a tag's toHtml() method will * render it in HTML. * * @param verbatim * If true return as close to the original page text as * possible. * @return The tag as an HTML fragment. * @see org.htmlparser.Node#toHtml() */ @Override public String toHtml(boolean verbatim) { int length; int size; List attributes; NodeAttribute attribute; StringBuilder ret; length = 2; attributes = getAttributesEx(); size = attributes.size(); for (int i = 0; i < size; i++) { attribute = attributes.get(i); length += attribute.getLength(); } ret = new StringBuilder(length); ret.append("<"); for (int i = 0; i < size; i++) { attribute = attributes.get(i); attribute.toString(ret); if (i < size - 1) { ret.append(" "); } } ret.append(">"); return (ret.toString()); } /** * Is this an empty xml tag of the form <tag/>. * * @return true if the last character of the last attribute is a '/'. */ public boolean isEmptyXmlTag() { List attributes; int size; Attribute attribute; String name; int length; boolean ret; ret = false; attributes = getAttributesEx(); size = attributes.size(); if (0 < size) { attribute = attributes.get(size - 1); name = attribute.getName(); if (null != name) { length = name.length(); ret = name.charAt(length - 1) == '/'; } } return (ret); } /** * Set this tag to be an empty xml node, or not. Adds or removes an ending * slash on the tag. * * @param emptyXmlTag * If true, ensures there is an ending slash in the node, i.e. * <tag/>, otherwise removes it. */ public void setEmptyXmlTag(boolean emptyXmlTag) { List attributes; int size; NodeAttribute attribute; String name; String value; int length; attributes = getAttributesEx(); size = attributes.size(); if (0 < size) { attribute = attributes.get(size - 1); name = attribute.getName(); if (null != name) { length = name.length(); value = attribute.getValue(); if (null == value) if (name.charAt(length - 1) == '/') { // already exists, remove if requested if (!emptyXmlTag) if (1 == length) attributes.remove(size - 1); else { // this shouldn't happen, but covers the case // where no whitespace separates the slash // from the previous attribute name = name.substring(0, length - 1); attribute = new NodeAttribute(name, null); attributes.remove(size - 1); attributes.add(attribute); } } else { // ends with attribute, add whitespace + slash if // requested if (emptyXmlTag) { attribute = new NodeAttribute(" "); attributes.add(attribute); attribute = new NodeAttribute("/", null); attributes.add(attribute); } } else { // some valued attribute, add whitespace + slash if // requested if (emptyXmlTag) { attribute = new NodeAttribute(" "); attributes.add(attribute); attribute = new NodeAttribute("/", null); attributes.add(attribute); } } } else { // ends with whitespace, add if requested if (emptyXmlTag) { attribute = new NodeAttribute("/", null); attributes.add(attribute); } } } else // nothing there, add if requested if (emptyXmlTag) { attribute = new NodeAttribute("/", null); attributes.add(attribute); } } /** * Predicate to determine if this tag is an end tag (i.e. </HTML>). * * @return true if this tag is an end tag. */ public boolean isEndTag() { String raw; raw = getRawTagName(); return ((null != raw) && ((0 != raw.length()) && ('/' == raw.charAt(0)))); } /** * Return the set of names handled by this tag. Since this a a generic tag, it * has no ids. * * @return The names to be matched that create tags of this type. */ public String[] getIds() { return (NONE); } /** * Return the set of tag names that cause this tag to finish. These are the * normal (non end tags) that if encountered while scanning (a composite tag) * will cause the generation of a virtual tag. Since this a a non-composite * tag, the default is no enders. * * @return The names of following tags that stop further scanning. */ public String[] getEnders() { return (NONE); } /** * Return the set of end tag names that cause this tag to finish. These are * the end tags that if encountered while scanning (a composite tag) will * cause the generation of a virtual tag. Since this a a non-composite tag, it * has no end tag enders. * * @return The names of following end tags that stop further scanning. */ public String[] getEndTagEnders() { return (NONE); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy