Class MarkupBuilder<T>
- java.lang.Object
-
- com.googlecode.jatl.MarkupBuilder<T>
-
- Type Parameters:
T
- This should always be parameterized with the exact same class that is extending theMarkupBuilder
to support fluent style.
- Direct Known Subclasses:
GeneratedHtmlBuilder
public abstract class MarkupBuilder<T> extends java.lang.Object
Fluent styled markup builder that writes to aWriter
.Description
Writes XML markup to aWriter
. 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 aMarkupBuilder
orMarkupWriter
. 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 orHtmlWriter
which allows you to define XHTML markup then write it later.Markup writers
are more useful for MVC frameworks andbuilders
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. SeeMarkupWriter
.Writing tags and attributes
Seestart(String)
andend()
for writing tags. Seeattr(String...)
for writting attributes.Variable expansion
Simple named variable replacements are supported through the${...}
notation. Seebind(String, Object)
, andtext(String)
.Pretty Printing aka Indenting
See #indentIndenter
. For most cases you can useSimpleIndenter
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(); }}
SeeMarkupBuilder(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. GenerallyText
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.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private static class
MarkupBuilder.Tag
static class
MarkupBuilder.TagClosingPolicy
Policy for how tags should be closed.
-
Field Summary
Fields Modifier and Type Field Description private java.util.Map<java.lang.String,java.lang.String>
attributes
private java.util.Map<java.lang.String,java.lang.Object>
bindings
private int
depth
private Indenter
indenter
protected static Indenter
indentOff
An indenter that turns off indenting.protected static Indenter
indentOn
A default indenter that uses tabs.protected static Indenter
indentSameLine
Indents by keeping a tag pair on the same line.private java.lang.String
namespacePrefix
private MarkupBuilder<?>
previousBuilder
private Indenter
previousIndenter
private static java.lang.String
q
private java.util.Stack<MarkupBuilder.Tag>
tagStack
private java.io.Writer
writer
-
Constructor Summary
Constructors Modifier Constructor Description protected
MarkupBuilder()
Use for deferred writer.MarkupBuilder(MarkupBuilder<?> builder)
Create a nested builder from given builder.MarkupBuilder(MarkupBuilder<?> builder, boolean nested)
Create a nested builder from a builder or resume from a builder.MarkupBuilder(java.io.Writer writer)
Create a builder using the given writer.
-
Method Summary
All Methods Instance Methods Abstract Methods Concrete Methods Deprecated Methods Modifier and Type Method Description T
attr(java.lang.String... attrs)
Adds attributes to the laststart tag
.T
bind(java.lang.String name, java.lang.Object value)
Binds a named variables to be used for expansion inattributes
andtext
.T
bind(java.util.Collection<java.util.Map.Entry<java.lang.String,java.lang.Object>> nvps)
Convenience forbind(String, Object)
private void
checkWriter()
private java.util.Map<java.lang.String,java.lang.String>
createMap()
void
done()
Call when completely done with the builder.T
end()
Closes the laststart tag
.T
end(int i)
Closes the inputed number of open tags.T
endAll()
Closes all open tags.protected java.lang.String
escapeAttributeMarkup(java.lang.String raw)
The strategy for escaping attribute markup.protected java.lang.String
escapeElementMarkup(java.lang.String raw)
The strategy for escaping element markup.protected java.lang.String
escapeMarkup(java.lang.String raw)
Deprecated.Please useescapeElementMarkup(String)
andescapeAttributeMarkup(String)
private java.lang.String
expand(java.lang.String text)
private java.util.Map<java.lang.String,java.lang.String>
getAttributes()
protected abstract T
getSelf()
Needed for fluent style and Java parameterization limitations.T
indent(Indenter indenter)
Sets the indenter.T
ns()
Restores the current namespace prefix to whatever the surrounding tags prefix is.T
ns(java.lang.String prefix)
Sets the current namespace prefix.private java.lang.String
q(java.lang.String raw)
T
raw(java.lang.String text)
Write text with out escaping or variable expansion.T
raw(java.lang.String text, boolean expand)
Writes text with out escaping.void
setDepth(int depth)
Sets the indent depth after the builder has been created.void
setWriter(java.io.Writer writer)
Sets the writer after the builder has been created.T
start(java.lang.String tag)
Starts a tag using the default closing policyMarkupBuilder.TagClosingPolicy.NORMAL
.T
start(java.lang.String tag, MarkupBuilder.TagClosingPolicy policy)
Starts a tag but does not immediately write it till the next tag is started.T
text(java.lang.String text)
Writes variable expanded escaped text inside a tag.T
unbind(java.lang.String name)
Removes a binding.T
write(MarkupWriter... writers)
Writes immediately by passing the writer to eachMarkupWriter
in the order passed in.private void
write(java.lang.String raw)
private void
writeAttr(java.lang.String name, java.lang.String value)
private void
writeAttributes(java.util.Map<java.lang.String,java.lang.String> attrs)
private void
writeCurrentTag()
private void
writeEndTag(MarkupBuilder.Tag t)
private void
writeIndent(MarkupBuilder.Tag t, Indenter.TagIndentSpot spot)
private void
writeStartTag(MarkupBuilder.Tag t)
private void
writeTag(java.lang.String tag, boolean close)
T
xmlns(java.lang.String uri)
Sets the default namespace on the last started tag.T
xmlns(java.lang.String uri, java.lang.String prefix)
Sets an XML namespace.
-
-
-
Field Detail
-
tagStack
private java.util.Stack<MarkupBuilder.Tag> tagStack
-
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
-
previousBuilder
private MarkupBuilder<?> previousBuilder
-
depth
private int depth
-
namespacePrefix
private java.lang.String namespacePrefix
-
previousIndenter
private Indenter previousIndenter
-
indenter
private Indenter indenter
-
q
private static final java.lang.String q
- See Also:
- Constant Field Values
-
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
- nevernull
.
-
MarkupBuilder
public MarkupBuilder(MarkupBuilder<?> builder)
Create a nested builder from given builder. Make suredone()
is called when finished with the nested builder so that the parent builder can resume using the writer.- Parameters:
builder
- parent builder, nevernull
.- See Also:
done()
-
MarkupBuilder
protected MarkupBuilder()
Use for deferred writer. The writer should beset
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
- nevernull
.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
- maybenull
- 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
- nevernull
- 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 equal0
-
indent
public T indent(Indenter indenter)
Sets the indenter.- Parameters:
indenter
- ifnull
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 inattributes
andtext
. 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
- nevernull
or empty.value
- maybenull
.- 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
- maybenull
.- 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 forbind(String, Object)
- Parameters:
nvps
- nevernull
.- Returns:
- never
null
.
-
start
public final T start(java.lang.String tag)
Starts a tag using the default closing policyMarkupBuilder.TagClosingPolicy.NORMAL
.Equivalent to:
start("tag", TagClosingPolicy.NORMAL)
.- Parameters:
tag
-- Returns:
- this, never
null
. - See Also:
start(String, TagClosingPolicy)
-
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. TheMarkupBuilder.TagClosingPolicy
dictates whether or not the tag needs to beclosed
. Thusend()
does not need to be called for all tags.- Parameters:
tag
- nevernull
or empty.policy
- nevernull
.- Returns:
- never
null
. - See Also:
end()
-
attr
public final T attr(java.lang.String... attrs)
- 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
- ifnull
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
- ifnull
nothing will happen.prefix
- ifnull
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()
-
end
public final T end()
Closes the laststart tag
. This is equivalent to</tag> or <tag/> depending on the
MarkupBuilder.TagClosingPolicy
.- Returns:
- never
null
. - See Also:
start(String, TagClosingPolicy)
,endAll()
,done()
-
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 (usuallyIllegalArgumentException
) will be thrown.
-
write
public final T write(MarkupWriter... writers)
Writes immediately by passing the writer to eachMarkupWriter
in the order passed in.- Parameters:
writers
- nevernull
, null elements passed in are ignored.- Returns:
- never
null
. - Since:
- 0.2.2
-
writeCurrentTag
private void writeCurrentTag()
-
writeStartTag
private void writeStartTag(MarkupBuilder.Tag t)
-
writeTag
private void writeTag(java.lang.String tag, boolean close)
-
writeEndTag
private void writeEndTag(MarkupBuilder.Tag t)
-
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()
-
escapeMarkup
protected java.lang.String escapeMarkup(java.lang.String raw)
Deprecated.Please useescapeElementMarkup(String)
andescapeAttributeMarkup(String)
DEPRECATED.- Parameters:
raw
- maybenull
.- Returns:
- maybe
null
if null for input. - See Also:
text(String)
-
escapeElementMarkup
protected java.lang.String escapeElementMarkup(java.lang.String raw)
The strategy for escaping element markup. The default is escape for XML.- Parameters:
raw
- maybenull
.- 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
- maybenull
.- Returns:
- maybe
null
if null for input.
-
writeIndent
private void writeIndent(MarkupBuilder.Tag t, Indenter.TagIndentSpot spot)
-
-