com.google.sites.liberation.util.XmlElement.java Source code

Java tutorial

Introduction

Here is the source code for com.google.sites.liberation.util.XmlElement.java

Source

/*
 * Copyright (C) 2009 Google Inc.
 *
 * 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 com.google.sites.liberation.util;

import com.google.gdata.util.common.base.Pair;
import com.google.gdata.util.common.base.Preconditions;

import org.apache.commons.lang.StringEscapeUtils;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * A very simple implementation of an xml element to aid
 * in generating well formed xhtml pages.
 * 
 * @author bsimon@google.com (Benjamin Simon)
 */
public class XmlElement {

    private final String elementType;
    private final List<Pair<Object, ChildType>> children;
    private final Map<String, String> attributes;

    private static enum ChildType {
        ELEMENT, TEXT, XML
    }

    /**
     * Creates a new {@code XmlElement} of the given type.
     * 
     * @param elementType tag name of this element
     */
    public XmlElement(String elementType) {
        Preconditions.checkNotNull(elementType);
        this.elementType = elementType;
        children = new LinkedList<Pair<Object, ChildType>>();
        attributes = new TreeMap<String, String>();
    }

    /**
     * Adds a child XmlElement to this one.
     * 
     * <p>Children appear in the order in which they are added in the xml output.
     * </p>
     */
    public XmlElement addElement(XmlElement child) {
        Preconditions.checkNotNull(child);
        children.add(new Pair<Object, ChildType>(child, ChildType.ELEMENT));
        return this;
    }

    /**
     * Adds a plain text child to this element. The String given is
     * automatically converted to xml-safe characters.
     * 
     * <p>Children appear in the order in which they are added in the xml output.
     * </p>
     */
    public XmlElement addText(String text) {
        Preconditions.checkNotNull(text);
        children.add(new Pair<Object, ChildType>(StringEscapeUtils.escapeXml(text), ChildType.TEXT));
        return this;
    }

    /**
     * Adds a string of xml as a child to this element. 
     * 
     * <p>Unlike addText(String), the string provided will not be escaped. If the 
     * given String is not well formed, then this element may not be well formed.
     * </p>
     */
    public XmlElement addXml(String xml) {
        Preconditions.checkNotNull(xml);
        children.add(new Pair<Object, ChildType>(xml, ChildType.XML));
        return this;
    }

    /**
     * Sets the attribute with the given name to the given value.
     * 
     * <p>Attributes appear alphabetically by name in the xml output.</p>
     */
    public XmlElement setAttribute(String name, String value) {
        Preconditions.checkNotNull(name, "name");
        Preconditions.checkNotNull(value, "value");
        attributes.put(name, StringEscapeUtils.escapeXml(value));
        return this;
    }

    /**
     * Appends this XmlElement (and any children) to an Appendable.
     */
    public void appendTo(Appendable a) throws IOException {
        a.append('<').append(elementType);
        for (Map.Entry<String, String> attribute : attributes.entrySet()) {
            a.append(' ').append(attribute.getKey()).append("=\"").append(attribute.getValue()).append("\"");
        }
        if (children.isEmpty()) {
            a.append(" />");
        } else {
            a.append(">");
            for (Pair<Object, ChildType> pair : children) {
                Object child = pair.getFirst();
                ChildType type = pair.getSecond();
                if (type == ChildType.ELEMENT) {
                    ((XmlElement) child).appendTo(a);
                } else {
                    a.append((String) child);
                }
            }
            a.append("</").append(elementType).append('>');
        }
    }

    /**
     * Returns the String of xml corresponding to this XmlElement.
     */
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        try {
            appendTo(builder);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return builder.toString();
    }

    @Override
    public boolean equals(Object other) {
        if (other instanceof XmlElement) {
            return toString().equals(other.toString());
        }
        return false;
    }
}