Class MarkupBuilder<T>
- Type Parameters:
T- This should always be parameterized with the exact same class that is extending theMarkupBuilderto support fluent style.
- Direct Known Subclasses:
GeneratedHtmlBuilder
Writer.
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 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. SeeMarkupWriter. Writing tags and attributes
Seestart(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 #indentIndenter. 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. 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.
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static classstatic enumPolicy for how tags should be closed. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate intprivate Indenterprotected static IndenterAn indenter that turns off indenting.protected static IndenterA default indenter that uses tabs.protected static IndenterIndents by keeping a tag pair on the same line.private Stringprivate MarkupBuilder<?> private Indenterprivate static final Stringprivate Stack<MarkupBuilder.Tag> private Writer -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedUse 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(Writer writer) Create a builder using the given writer. -
Method Summary
Modifier and TypeMethodDescriptionfinal TAdds attributes to the laststart tag.final TBinds a named variables to be used for expansion inattributesandtext.final Tbind(Collection<Map.Entry<String, Object>> nvps) Convenience forbind(String, Object)private voidfinal voiddone()Call when completely done with the builder.final Tend()Closes the laststart tag.final Tend(int i) Closes the inputed number of open tags.final TendAll()Closes all open tags.protected StringThe strategy for escaping attribute markup.protected StringThe strategy for escaping element markup.protected StringescapeMarkup(String raw) Deprecated.private Stringprotected abstract TgetSelf()Needed for fluent style and Java parameterization limitations.Sets the indenter.final Tns()Restores the current namespace prefix to whatever the surrounding tags prefix is.final TSets the current namespace prefix.private Stringfinal TWrite text with out escaping or variable expansion.final TWrites text with out escaping.final voidsetDepth(int depth) Sets the indent depth after the builder has been created.final voidSets the writer after the builder has been created.final TStarts a tag using the default closing policyMarkupBuilder.TagClosingPolicy.NORMAL.final Tstart(String tag, MarkupBuilder.TagClosingPolicy policy) Starts a tag but does not immediately write it till the next tag is started.final TWrites variable expanded escaped text inside a tag.final TRemoves a binding.final Twrite(MarkupWriter... writers) Writes immediately by passing the writer to eachMarkupWriterin the order passed in.private voidprivate voidprivate voidwriteAttributes(Map<String, String> attrs) private voidprivate voidprivate voidprivate voidprivate voidfinal TSets the default namespace on the last started tag.final TSets an XML namespace.
-
Field Details
-
tagStack
-
writer
-
attributes
-
bindings
-
previousBuilder
-
depth
private int depth -
namespacePrefix
-
previousIndenter
-
indenter
-
q
- See Also:
-
indentOn
A default indenter that uses tabs. -
indentOff
An indenter that turns off indenting. -
indentSameLine
Indents by keeping a tag pair on the same line.
-
-
Constructor Details
-
MarkupBuilder
Create a builder using the given writer.- Parameters:
writer- nevernull.
-
MarkupBuilder
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:
-
MarkupBuilder
protected MarkupBuilder()Use for deferred writer. The writer should besetbefore the builder is used.- See Also:
-
MarkupBuilder
Create a nested builder from a builder or resume from a builder.- Parameters:
builder- nevernull.nested-truemeans nested,falsemeans resuming.
-
-
Method Details
-
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
thisobject.
-
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
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
Sets the writer after the builder has been created. Only useful with the empty constructor.- Parameters:
writer- nevernull- Throws:
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
-
getAttributes
-
text
-
raw
-
raw
-
bind
Binds a named variables to be used for expansion inattributesandtext. 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- nevernullor empty.value- maybenull.- Returns:
- never
null.
-
unbind
-
bind
Convenience forbind(String, Object)- Parameters:
nvps- nevernull.- Returns:
- never
null.
-
start
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
Starts a tag but does not immediately write it till the next tag is started. TheMarkupBuilder.TagClosingPolicydictates whether or not the tag needs to beclosed. Thusend()does not need to be called for all tags.- Parameters:
tag- nevernullor empty.policy- nevernull.- Returns:
- never
null. - See Also:
-
attr
- Parameters:
attrs- name value pairs. Its invalid for an odd number of arguments.- Returns:
- never
null. - Throws:
IllegalArgumentException- odd number of arguments.
-
xmlns
-
xmlns
-
end
Closes the inputed number of open tags.- Parameters:
i- less than zero will do nothing.- Returns:
- never
null. - See Also:
-
end
Closes the laststart tag. This is equivalent to</tag> or <tag/> depending on theMarkupBuilder.TagClosingPolicy.- Returns:
- never
null. - See Also:
-
endAll
-
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
Writes immediately by passing the writer to eachMarkupWriterin 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
-
writeTag
-
writeEndTag
-
writeAttributes
-
writeAttr
-
q
-
expand
-
write
-
checkWriter
private void checkWriter() -
createMap
-
escapeMarkup
Deprecated.Please useescapeElementMarkup(String)andescapeAttributeMarkup(String)DEPRECATED.- Parameters:
raw- maybenull.- Returns:
- maybe
nullif null for input. - See Also:
-
escapeElementMarkup
-
escapeAttributeMarkup
-
writeIndent
-
escapeElementMarkup(String)andescapeAttributeMarkup(String)