Class MarkupBuilder<T>

  • Type Parameters:
    T - This should always be parameterized with the exact same class that is extending the MarkupBuilder to support fluent style.
    Direct Known Subclasses:
    GeneratedHtmlBuilder

    public abstract class MarkupBuilder<T>
    extends java.lang.Object
    Fluent styled markup builder that writes to a Writer.

    Description

    Writes XML markup to a Writer. The Builder part of the name is somewhat misleading as this class does not store or keep track of all the markup objects created but rather writes using the writer as soon as it can. Thus the order of operations performed on this class is very important and should follow the order that you would write the markup.

    Usage

    You should not use this class directly but rather one of its subclasses that is parameterized with itself (see Extending). You generally define the markup you want to write using Java anonymous classes that extend either a MarkupBuilder or MarkupWriter. Markup builders write immediately to a writer where as a markup writer writes when told to. But again in both cases you generally define the markup with an anonymous class.

    For examples of use its best to see Html for an XHTML builder which will write XHTML markup immediatly or HtmlWriter which allows you to define XHTML markup then write it later.

    Markup writers are more useful for MVC frameworks and builders are more for convenience.

    Extending

    If you would you would like to make your own builder you should subclass this class or a subclass that has generic parameter (<T>).

    The custom builder should be parameterized to itself to support fluent style.

    Example:

    public class MyMarkup extends MarkupBuilder<MyMarkup> {
    
            public MyMarkup(Writer builder) {
                    super(builder);
            }
            protected MyMarkup getSelf() {
                    return this;
            }
            
            public MyMarkup myTag() {
                    return start("myTag");
            }
    }
     

    Composition

    Besides the extending method above you can achieve composition of markup builders by using MarkupWriter's instead. See MarkupWriter.

    See write(MarkupWriter...).

    Writing tags and attributes

    See start(String) and end() for writing tags. See attr(String...) for writting attributes.

    Variable expansion

    Simple named variable replacements are supported through the
    ${...}
    notation. See bind(String, Object), and text(String).

    Pretty Printing aka Indenting

    See #indent Indenter. For most cases you can use SimpleIndenter

    Namespaces

    You can either manually maintain namespaces and namespace prefixes by setting the correct attributes and then writing tags with the namespace prefix. Example: start("prefix:tagName"). Or you can use the namespace methods: ns(), ns(String), xmlns(String, String) The following Nested builders are very helpful for working with multiple XML schemas.

    Nested builders

    Nested builders are an easy way to allow different markup styles to coexist elegantly. An example might be HTML with in XSL. You would have an HTML builder nested inside the XSL builder.

    Example:

     new Xslt(writer) {{
            ns("xsl");
            template().match("stuff");
                    new Html(writer) {{
                            html().body().done();
                    }}
            done();
     }}
     
    See MarkupBuilder(MarkupBuilder).

    Thread safety

    This class and subclasses are not thread safe. One way to make a builder thread safe is to synchronize on the passed in writer:
     synchronize(writer) {
        new SomeBuilder(writer) {{ }}; 
     }
     

    Efficiency and Validation

    To keep the builder efficient and elegant there is very little XML validation. There is no guarantee that the markup generated will always be well formed. Generally Text will be escaped appropriately.

    For those seriously concerned with performance an appropriate implementation of Writer should be given to the builder.

    For example: In a single threaded environment where you are writing to memory Commons IO StringBuilderWriter is a good choice over StringWriter.

    On the other hand if you are writing very large XML document to a file or network socket PrintWriter is probably a better choice.

    See Also:
    MarkupBuilder.TagClosingPolicy, start(String, TagClosingPolicy), attr(String...), end(), done()
    • Field Detail

      • writer

        private java.io.Writer writer
      • attributes

        private java.util.Map<java.lang.String,​java.lang.String> attributes
      • bindings

        private java.util.Map<java.lang.String,​java.lang.Object> bindings
      • depth

        private int depth
      • namespacePrefix

        private java.lang.String namespacePrefix
      • previousIndenter

        private Indenter previousIndenter
      • indentOn

        protected static Indenter indentOn
        A default indenter that uses tabs.
      • indentOff

        protected static Indenter indentOff
        An indenter that turns off indenting.
      • indentSameLine

        protected static Indenter indentSameLine
        Indents by keeping a tag pair on the same line.
    • Constructor Detail

      • MarkupBuilder

        public MarkupBuilder​(java.io.Writer writer)
        Create a builder using the given writer.
        Parameters:
        writer - never null.
      • MarkupBuilder

        public MarkupBuilder​(MarkupBuilder<?> builder)
        Create a nested builder from given builder. Make sure done() is called when finished with the nested builder so that the parent builder can resume using the writer.
        Parameters:
        builder - parent builder, never null.
        See Also:
        done()
      • MarkupBuilder

        protected MarkupBuilder()
        Use for deferred writer. The writer should be set before the builder is used.
        See Also:
        setWriter(Writer), MarkupWriter
      • MarkupBuilder

        public MarkupBuilder​(MarkupBuilder<?> builder,
                             boolean nested)
        Create a nested builder from a builder or resume from a builder.
        Parameters:
        builder - never null.
        nested - true means nested, false means resuming.
    • Method Detail

      • getSelf

        protected abstract T getSelf()
        Needed for fluent style and Java parameterization limitations. Almost all public methods should return whatever this method returns.

        Most implementations only have to do:

         return this;
         
        Returns:
        the current builder which is usually this object.
      • ns

        public final T ns()
        Restores the current namespace prefix to whatever the surrounding tags prefix is. To set the namespace to the default namespace call:

        ns(null);

        Returns:
        maybe null.
        See Also:
        ns(String)
      • ns

        public final T ns​(java.lang.String prefix)
        Sets the current namespace prefix. If a tag is started when the prefix is set to a non-null non-empty string, the prefix will be added in front of the tag.

        Example:

         ns("html").div().end();
         
        Result:

         <html:div></html:div>
         
        Parameters:
        prefix - maybe null
        Returns:
        this, not null.
      • setWriter

        public final void setWriter​(java.io.Writer writer)
        Sets the writer after the builder has been created. Only useful with the empty constructor.
        Parameters:
        writer - never null
        Throws:
        java.lang.IllegalArgumentException - if the writer has already been set or the given writer is null.
      • setDepth

        public final void setDepth​(int depth)
        Sets the indent depth after the builder has been created. Only useful with the empty constructor.
        Parameters:
        depth - should greater than or equal 0
      • indent

        public T indent​(Indenter indenter)
        Sets the indenter.
        Parameters:
        indenter - if null reverts to the previous builder.
        Returns:
        the builder.
        See Also:
        indentOn, indentOff, indentSameLine
      • getAttributes

        private final java.util.Map<java.lang.String,​java.lang.String> getAttributes()
      • text

        public final T text​(java.lang.String text)
        Writes variable expanded escaped text inside a tag.
        Parameters:
        text - the text will be escaped and variables will be expanded.
        Returns:
        never null.
        See Also:
        raw(String), bind(String, Object)
      • raw

        public final T raw​(java.lang.String text)
        Write text with out escaping or variable expansion.
        Parameters:
        text -
        Returns:
        never null.
        See Also:
        raw(String, boolean)
      • raw

        public final T raw​(java.lang.String text,
                           boolean expand)
        Writes text with out escaping.
        Parameters:
        text -
        expand - true does variable expansion.
        Returns:
        never null.
      • bind

        public final T bind​(java.lang.String name,
                            java.lang.Object value)
        Binds a named variables to be used for expansion in attributes and text. Variables are represented with by ${...}.

        Example

         bind("name", "Ferris");
         text("${name}");
         

        Variables are expanded in order and can be referred in a later binding.

         bind("firstName", "Adam");
         bind("lastName", "Gent");
         bind("fullName", "${firstName} ${lastName}");
         
        Parameters:
        name - never null or empty.
        value - maybe null.
        Returns:
        never null.
      • unbind

        public final T unbind​(java.lang.String name)
        Removes a binding. There is no failure if the binding does not exist.
        Parameters:
        name - maybe null.
        Returns:
        never null.
        See Also:
        bind(String, Object)
      • bind

        public final T bind​(java.util.Collection<java.util.Map.Entry<java.lang.String,​java.lang.Object>> nvps)
        Convenience for bind(String, Object)
        Parameters:
        nvps - never null.
        Returns:
        never null.
      • start

        public final T start​(java.lang.String tag,
                             MarkupBuilder.TagClosingPolicy policy)
        Starts a tag but does not immediately write it till the next tag is started. The MarkupBuilder.TagClosingPolicy dictates whether or not the tag needs to be closed. Thus end() does not need to be called for all tags.
        Parameters:
        tag - never null or empty.
        policy - never null.
        Returns:
        never null.
        See Also:
        end()
      • attr

        public final T attr​(java.lang.String... attrs)
        Adds attributes to the last start tag. Attributes do not need an end() call.
        Parameters:
        attrs - name value pairs. Its invalid for an odd number of arguments.
        Returns:
        never null.
        Throws:
        java.lang.IllegalArgumentException - odd number of arguments.
      • xmlns

        public final T xmlns​(java.lang.String uri)
        Sets the default namespace on the last started tag.
        Parameters:
        uri - if null nothing will happen.
        Returns:
        this, never null.
        See Also:
        xmlns(String, String)
      • xmlns

        public final T xmlns​(java.lang.String uri,
                             java.lang.String prefix)
        Sets an XML namespace.
        Parameters:
        uri - if null nothing will happen.
        prefix - if null or blank will act like the default namespace and no prefix.
        Returns:
        this, never null.
      • end

        public final T end​(int i)
        Closes the inputed number of open tags.
        Parameters:
        i - less than zero will do nothing.
        Returns:
        never null.
        See Also:
        end()
      • endAll

        public final T endAll()
        Closes all open tags.
        Returns:
        never null.
        See Also:
        end()
      • done

        public final void done()
        Call when completely done with the builder. This is required for nested builders.

        If a builder is used again after done() is called an exception (usually IllegalArgumentException) will be thrown.

      • write

        public final T write​(MarkupWriter... writers)
        Writes immediately by passing the writer to each MarkupWriter in the order passed in.
        Parameters:
        writers - never null, null elements passed in are ignored.
        Returns:
        never null.
        Since:
        0.2.2
      • writeCurrentTag

        private void writeCurrentTag()
      • writeTag

        private void writeTag​(java.lang.String tag,
                              boolean close)
      • writeAttributes

        private void writeAttributes​(java.util.Map<java.lang.String,​java.lang.String> attrs)
      • writeAttr

        private void writeAttr​(java.lang.String name,
                               java.lang.String value)
      • q

        private java.lang.String q​(java.lang.String raw)
      • expand

        private java.lang.String expand​(java.lang.String text)
      • write

        private void write​(java.lang.String raw)
      • checkWriter

        private void checkWriter()
      • createMap

        private java.util.Map<java.lang.String,​java.lang.String> createMap()
      • escapeElementMarkup

        protected java.lang.String escapeElementMarkup​(java.lang.String raw)
        The strategy for escaping element markup. The default is escape for XML.
        Parameters:
        raw - maybe null.
        Returns:
        maybe null if null for input.
        See Also:
        text(String), escapeAttributeMarkup(String)
      • escapeAttributeMarkup

        protected java.lang.String escapeAttributeMarkup​(java.lang.String raw)
        The strategy for escaping attribute markup. The default escaping is XML. Entities will be used for white space characters: #xD, #xA, #x9

        CR, newline, and tab, respectively.

        Parameters:
        raw - maybe null.
        Returns:
        maybe null if null for input.