![JAR search and dependency download from the Maven repository](/logo.png)
org.apache.juneau.html.HtmlDocSerializer Maven / Gradle / Ivy
// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
// * to you 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 org.apache.juneau.html;
import static org.apache.juneau.collections.JsonMap.*;
import static org.apache.juneau.common.internal.ThrowableUtils.*;
import static org.apache.juneau.internal.CollectionUtils.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.nio.charset.*;
import java.util.*;
import java.util.function.*;
import java.util.regex.*;
import org.apache.juneau.*;
import org.apache.juneau.collections.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.svl.*;
import org.apache.juneau.utils.*;
import org.apache.juneau.xml.*;
/**
* Serializes POJOs to HTTP responses as HTML documents.
*
* Media types
*
* Handles Accept types: text/html
*
* Produces Content-Type types: text/html
*
*
Description
*
* Same as {@link HtmlSerializer}, except wraps the response in <html>
,
* <head>
, and <body>
tags so that it can be rendered in a browser.
*
*
* Configurable properties are typically specified via @HtmlDocConfig .
*
*
Example:
*
* @Rest (
* messages="nls/AddressBookResource" ,
* title="$L{title}" ,
* description="$L{description}"
* )
* @HtmlDocConfig (
* navlinks={
* "api: servlet:/api" ,
* "doc: doc"
* }
* )
* public class AddressBookResource extends BasicRestServlet {
*
*
*
* The $L{...} variable represent localized strings pulled from the resource bundle identified by the
* messages annotation.
*
These variables are replaced at runtime based on the HTTP request locale.
*
Several built-in runtime variable types are defined, and the API can be extended to include user-defined variables.
*
*
Notes:
* - This class is thread safe and reusable.
*
*
* See Also:
* - HTML Details
*
*/
public class HtmlDocSerializer extends HtmlStrippedDocSerializer {
//-------------------------------------------------------------------------------------------------------------------
// Static
//-------------------------------------------------------------------------------------------------------------------
private static final String[] EMPTY_ARRAY = {};
/** Default serializer, all default settings. */
public static final HtmlDocSerializer DEFAULT = new HtmlDocSerializer(create());
/**
* Creates a new builder for this object.
*
* @return A new builder.
*/
public static Builder create() {
return new Builder();
}
//-------------------------------------------------------------------------------------------------------------------
// Builder
//-------------------------------------------------------------------------------------------------------------------
/**
* Builder class.
*/
@FluentSetters
public static class Builder extends HtmlStrippedDocSerializer.Builder {
private static final Cache CACHE = Cache.of(HashKey.class, HtmlDocSerializer.class).build();
List aside, footer, head, header, nav, navlinks, script, style, stylesheet;
AsideFloat asideFloat;
String noResultsMessage;
boolean nowrap, resolveBodyVars;
Class extends HtmlDocTemplate> template;
List> widgets;
/**
* Constructor, default settings.
*/
protected Builder() {
produces("text/html");
accept("text/html");
asideFloat = AsideFloat.RIGHT;
noResultsMessage = "no results
";
template = BasicHtmlDocTemplate.class;
}
/**
* Copy constructor.
*
* @param copyFrom The bean to copy from.
*/
protected Builder(HtmlDocSerializer copyFrom) {
super(copyFrom);
aside = copy(copyFrom.aside);
footer = copy(copyFrom.footer);
head = copy(copyFrom.head);
header = copy(copyFrom.header);
nav = copy(copyFrom.nav);
navlinks = copy(copyFrom.navlinks);
script = copy(copyFrom.script);
style = copy(copyFrom.style);
stylesheet = copy(copyFrom.stylesheet);
asideFloat = copyFrom.asideFloat;
noResultsMessage = copyFrom.noResultsMessage;
nowrap = copyFrom.nowrap;
resolveBodyVars = copyFrom.resolveBodyVars;
template = copyFrom.template;
widgets = copy(copyFrom.widgets);
}
/**
* Copy constructor.
*
* @param copyFrom The builder to copy from.
*/
protected Builder(Builder copyFrom) {
super(copyFrom);
aside = copy(copyFrom.aside);
footer = copy(copyFrom.footer);
head = copy(copyFrom.head);
header = copy(copyFrom.header);
nav = copy(copyFrom.nav);
navlinks = copy(copyFrom.navlinks);
script = copy(copyFrom.script);
style = copy(copyFrom.style);
stylesheet = copy(copyFrom.stylesheet);
asideFloat = copyFrom.asideFloat;
noResultsMessage = copyFrom.noResultsMessage;
nowrap = copyFrom.nowrap;
resolveBodyVars = copyFrom.resolveBodyVars;
template = copyFrom.template;
widgets = copy(copyFrom.widgets);
}
@Override /* Context.Builder */
public Builder copy() {
return new Builder(this);
}
@Override /* Context.Builder */
public HtmlDocSerializer build() {
return cache(CACHE).build(HtmlDocSerializer.class);
}
@Override /* Context.Builder */
public HashKey hashKey() {
return HashKey.of(
super.hashKey(),
aside,
footer,
head,
header,
nav,
navlinks,
script,
style,
stylesheet,
asideFloat,
noResultsMessage,
nowrap,
resolveBodyVars,
template,
widgets
);
}
//-----------------------------------------------------------------------------------------------------------------
// Properties
//-----------------------------------------------------------------------------------------------------------------
/**
* Aside section contents.
*
*
* Allows you to specify the contents of the aside section on the HTML page.
* The aside section floats on the right of the page for providing content supporting the serialized content of
* the page.
*
*
* By default, the aside section is empty.
*
*
Example:
*
* WriterSerializer serializer = HtmlDocSerializer
* .create ()
* .aside(
* "<ul>" ,
* " <li>Item 1" ,
* " <li>Item 2" ,
* " <li>Item 3" ,
* "</ul>"
* )
* .build();
*
*
* Notes:
* -
* Format: HTML
*
-
* Supports SVL Variables
* (e.g.
"$L{my.localized.variable}" ).
* -
* A value of
"NONE" can be used to force no value.
* -
* The parent value can be included by adding the literal
"INHERIT" as a value.
* -
* Multiple values are combined with newlines into a single string.
*
-
* On methods, this value is inherited from the
@HtmlDocConfig annotation on the servlet/resource class.
* -
* On servlet/resource classes, this value is inherited from the
@HtmlDocConfig annotation on the
* parent class.
*
*
* @param value
* The new value for this property.
* @return This object.
*/
@FluentSetter
public Builder aside(String...value) {
aside = merge(aside, value);
return this;
}
/**
* Returns the list of aside section contents.
*
*
* Gives access to the inner list if you need to make more than simple additions via {@link #aside(String...)}.
*
* @return The list of aside section contents.
* @see #aside(String...)
*/
public List aside() {
if (aside == null)
aside = list();
return aside;
}
/**
* Float aside section contents.
*
*
* Allows you to position the aside contents of the page around the main contents.
*
*
* By default, the aside section is floated to the right.
*
*
Example:
*
* WriterSerializer serializer = HtmlDocSerializer
* .create ()
* .aside(
* "<ul>" ,
* " <li>Item 1" ,
* " <li>Item 2" ,
* " <li>Item 3" ,
* "</ul>"
* )
* .asideFloat(RIGHT )
* .build();
*
*
* @param value
* The new value for this property.
* @return This object.
*/
@FluentSetter
public Builder asideFloat(AsideFloat value) {
asideFloat = value;
return this;
}
/**
* Footer section contents.
*
*
* Allows you to specify the contents of the footer section on the HTML page.
*
*
* By default, the footer section is empty.
*
*
Example:
*
* WriterSerializer serializer = HtmlDocSerializer
* .create ()
* .footer(
* "<b>This interface is great!</b>"
* )
* .build();
*
*
* @param value
* The new value for this property.
* @return This object.
*/
@FluentSetter
public Builder footer(String...value) {
footer = merge(footer, value);
return this;
}
/**
* Returns the list of footer section contents.
*
*
* Gives access to the inner list if you need to make more than simple additions via {@link #footer(String...)}.
*
* @return The list of footer section contents.
* @see #footer(String...)
*/
public List footer() {
if (footer == null)
footer = list();
return footer;
}
/**
* Additional head section content.
*
*
* Adds the specified HTML content to the head section of the page.
*
*
Example:
*
* WriterSerializer serializer = HtmlDocSerializer
* .create ()
* .head(
* "<link rel='icon' href='$U{servlet:/htdocs/mypageicon.ico}'>"
* )
* .build();
*
*
* @param value
* The new value for this property.
* @return This object.
*/
@FluentSetter
public Builder head(String...value) {
head = merge(head, value);
return this;
}
/**
* Returns the list of head section contents.
*
*
* Gives access to the inner list if you need to make more than simple additions via {@link #head(String...)}.
*
* @return The list of head section contents.
* @see #head(String...)
*/
public List head() {
if (head == null)
head = list();
return head;
}
/**
* Header section contents.
*
*
* Allows you to override the contents of the header section on the HTML page.
* The header section normally contains the title and description at the top of the page.
*
*
Example:
*
* WriterSerializer serializer = HtmlDocSerializer
* .create ()
* .header(
* "<h1>My own header</h1>"
* )
* .build()
*
*
* @param value
* The new value for this property.
* @return This object.
*/
@FluentSetter
public Builder header(String...value) {
header = merge(header, value);
return this;
}
/**
* Returns the list of header section contents.
*
*
* Gives access to the inner list if you need to make more than simple additions via {@link #header(String...)}.
*
* @return The list of header section contents.
* @see #header(String...)
*/
public List header() {
if (header == null)
header = list();
return header;
}
/**
* Nav section contents.
*
*
* Allows you to override the contents of the nav section on the HTML page.
* The nav section normally contains the page links at the top of the page.
*
*
Example:
*
* WriterSerializer serializer = HtmlDocSerializer
* .create ()
* .nav(
* "<p class='special-navigation'>This is my special navigation content</p>"
* )
* .build()
*
*
*
* When this property is specified, the {@link Builder#navlinks(String...)} property is ignored.
*
* @param value
* The new value for this property.
* @return This object.
*/
@FluentSetter
public Builder nav(String...value) {
nav = merge(nav, value);
return this;
}
/**
* Returns the list of nav section contents.
*
*
* Gives access to the inner list if you need to make more than simple additions via {@link #nav(String...)}.
*
* @return The list of nav section contents.
* @see #nav(String...)
*/
public List nav() {
if (nav == null)
nav = list();
return nav;
}
/**
* Page navigation links.
*
*
* Adds a list of hyperlinks immediately under the title and description but above the content of the page.
*
*
* This can be used to provide convenient hyperlinks when viewing the REST interface from a browser.
*
*
* The value is an array of strings with two possible values:
*
* - A key-value pair representing a hyperlink label and href:
*
"google: http://google.com"
* - Arbitrary HTML.
*
*
*
* Relative URLs are considered relative to the servlet path.
* For example, if the servlet path is "http://localhost/myContext/myServlet" , and the
* URL is "foo" , the link becomes "http://localhost/myContext/myServlet/foo" .
* Absolute ("/myOtherContext/foo" ) and fully-qualified ("http://localhost2/foo" ) URLs
* can also be used in addition to various other protocols specified by {@link UriResolver} such as
* "servlet:/..." .
*
*
Example:
*
* WriterSerializer serializer = HtmlDocSerializer
* .create ()
* .navlinks(
* "api: servlet:/api" ,
* "stats: servlet:/stats" ,
* "doc: doc"
* )
* .build();
*
*
* @param value
* The new value for this property.
* @return This object.
*/
@FluentSetter
public Builder navlinks(String...value) {
navlinks = mergeNavLinks(navlinks, value);
return this;
}
/**
* Returns the list of navlinks section contents.
*
*
* Gives access to the inner list if you need to make more than simple additions via {@link #navlinks(String...)}.
*
* @return The list of navlinks section contents.
* @see #navlinks(String...)
*/
public List navlinks() {
if (navlinks == null)
navlinks = list();
return navlinks;
}
/**
* No-results message.
*
*
* Allows you to specify the string message used when trying to serialize an empty array or empty list.
*
*
Example:
*
* WriterSerializer serializer = HtmlDocSerializer
* .create ()
* .noResultsMessage("<b>This interface is great!</b>" )
* .build();
*
*
*
* A value of "NONE" can be used to represent no value to differentiate it from an empty string.
*
* @param value
* The new value for this property.
* @return This object.
*/
@FluentSetter
public Builder noResultsMessage(String value) {
noResultsMessage = value;
return this;
}
/**
* Prevent word wrap on page.
*
*
* Adds "* {white-space:nowrap}" to the CSS instructions on the page to prevent word wrapping.
*
* @return This object.
*/
@FluentSetter
public Builder nowrap() {
return nowrap(true);
}
/**
* Same as {@link #nowrap()} but allows you to explicitly specify the boolean value.
*
* @param value
* The new value for this property.
* @return This object.
* @see #nowrap()
*/
@FluentSetter
public Builder nowrap(boolean value) {
nowrap = value;
return this;
}
/**
* Resolve $ variables in serialized POJO.
*
* @return This object.
*/
@FluentSetter
public Builder resolveBodyVars() {
return resolveBodyVars(true);
}
/**
* Same as {@link #resolveBodyVars()} but allows you to explicitly specify the boolean value.
*
* @param value
* The new value for this property.
* @return This object.
* @see #nowrap()
*/
@FluentSetter
public Builder resolveBodyVars(boolean value) {
resolveBodyVars = value;
return this;
}
/**
* Adds the specified Javascript code to the HTML page.
*
*
* A shortcut on @Rest is also provided for this setting:
*
* WriterSerializer serializer = HtmlDocSerializer
* .create ()
* .script("alert('hello!');" )
* .build();
*
*
* @param value
* The value to add to this property.
* @return This object.
*/
@FluentSetter
public Builder script(String...value) {
script = merge(script, value);
return this;
}
/**
* Returns the list of page script contents.
*
*
* Gives access to the inner list if you need to make more than simple additions via {@link #script(String...)}.
*
* @return The list of page script contents.
* @see #script(String...)
*/
public List script() {
if (script == null)
script = list();
return script;
}
/**
* Adds the specified CSS instructions to the HTML page.
*
*
* WriterSerializer serializer = HtmlDocSerializer
* .create ()
* .style(
* "h3 { color: red; }" ,
* "h5 { font-weight: bold; }"
* )
* .build();
*
*
* @param value
* The value to add to this property.
* @return This object.
*/
@FluentSetter
public Builder style(String...value) {
style = merge(style, value);
return this;
}
/**
* Returns the list of page style contents.
*
*
* Gives access to the inner list if you need to make more than simple additions via {@link #style(String...)}.
*
* @return The list of page style contents.
* @see #style(String...)
*/
public List style() {
if (style == null)
style = list();
return style;
}
/**
* Adds to the list of stylesheet URLs.
*
*
* Note that this stylesheet is controlled by the @Rest .stylesheet()
annotation.
*
* @param value
* The value to add to this property.
* @return This object.
*/
@FluentSetter
public Builder stylesheet(String...value) {
stylesheet = merge(stylesheet, value);
return this;
}
/**
* Returns the list of stylesheet URLs.
*
*
* Gives access to the inner list if you need to make more than simple additions via {@link #stylesheet(String...)}.
*
* @return The list of stylesheet URLs.
* @see #stylesheet(String...)
*/
public List stylesheet() {
if (stylesheet == null)
stylesheet = list();
return stylesheet;
}
/**
* HTML document template.
*
*
* Specifies the template to use for serializing the page.
*
*
* By default, the {@link BasicHtmlDocTemplate} class is used to construct the contents of the HTML page, but
* can be overridden with your own custom implementation class.
*
*
Example:
*
* WriterSerializer serializer = HtmlDocSerializer
* .create ()
* .template(MySpecialDocTemplate.class )
* .build();
*
*
* @param value
* The new value for this property.
* @return This object.
*/
@FluentSetter
public Builder template(Class extends HtmlDocTemplate> value) {
template = value;
return this;
}
/**
* HTML Widgets.
*
*
* Defines widgets that can be used in conjunction with string variables of the form "$W{name}" to quickly
* generate arbitrary replacement text.
*
* Widgets resolve the following variables:
*
* "$W{name}" - Contents returned by {@link HtmlWidget#getHtml(VarResolverSession)}.
* "$W{name.script}" - Contents returned by {@link HtmlWidget#getScript(VarResolverSession)}.
*
The script contents are automatically inserted into the <head/script> section
* in the HTML page.
* "$W{name.style}" - Contents returned by {@link HtmlWidget#getStyle(VarResolverSession)}.
*
The styles contents are automatically inserted into the <head/style> section
* in the HTML page.
*
*
*
* The following examples shows how to associate a widget with a REST method and then have it rendered in the links
* and aside section of the page:
*
*
* WriterSerializer serializer = HtmlDocSerializer
* .create ()
* .widgets(
* MyWidget.class
* )
* .navlinks(
* "$W{MyWidget}"
* )
* .aside(
* "Check out this widget: $W{MyWidget}"
* )
* .build();
*
*
* Notes:
* -
* Widgets are inherited from super classes, but can be overridden by reusing the widget name.
*
*
* See Also:
* - Widgets
*
*
* @param values The values to add to this setting.
* @return This object.
*/
@FluentSetter
@SuppressWarnings("unchecked")
public Builder widgets(Class extends HtmlWidget>...values) {
addAll(widgets(), values);
return this;
}
/**
* Returns the list of page widgets.
*
*
* Gives access to the inner list if you need to make more than simple additions via {@link #widgets(Class...)}.
*
* @return The list of page widgets.
* @see #widgets(Class...)
*/
public List> widgets() {
if (widgets == null)
widgets = list();
return widgets;
}
//
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder annotations(Annotation...values) {
super.annotations(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder apply(AnnotationWorkList work) {
super.apply(work);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder applyAnnotations(java.lang.Class>...fromClasses) {
super.applyAnnotations(fromClasses);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder applyAnnotations(Method...fromMethods) {
super.applyAnnotations(fromMethods);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder cache(Cache value) {
super.cache(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder debug() {
super.debug();
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder debug(boolean value) {
super.debug(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder impl(Context value) {
super.impl(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder type(Class extends org.apache.juneau.Context> value) {
super.type(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanClassVisibility(Visibility value) {
super.beanClassVisibility(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanConstructorVisibility(Visibility value) {
super.beanConstructorVisibility(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanContext(BeanContext value) {
super.beanContext(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanContext(BeanContext.Builder value) {
super.beanContext(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanDictionary(java.lang.Class>...values) {
super.beanDictionary(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanFieldVisibility(Visibility value) {
super.beanFieldVisibility(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanInterceptor(Class> on, Class extends org.apache.juneau.swap.BeanInterceptor>> value) {
super.beanInterceptor(on, value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanMapPutReturnsOldValue() {
super.beanMapPutReturnsOldValue();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanMethodVisibility(Visibility value) {
super.beanMethodVisibility(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanProperties(Map values) {
super.beanProperties(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanProperties(Class> beanClass, String properties) {
super.beanProperties(beanClass, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanProperties(String beanClassName, String properties) {
super.beanProperties(beanClassName, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesExcludes(Map values) {
super.beanPropertiesExcludes(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesExcludes(Class> beanClass, String properties) {
super.beanPropertiesExcludes(beanClass, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesExcludes(String beanClassName, String properties) {
super.beanPropertiesExcludes(beanClassName, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesReadOnly(Map values) {
super.beanPropertiesReadOnly(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesReadOnly(Class> beanClass, String properties) {
super.beanPropertiesReadOnly(beanClass, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesReadOnly(String beanClassName, String properties) {
super.beanPropertiesReadOnly(beanClassName, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesWriteOnly(Map values) {
super.beanPropertiesWriteOnly(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesWriteOnly(Class> beanClass, String properties) {
super.beanPropertiesWriteOnly(beanClass, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beanPropertiesWriteOnly(String beanClassName, String properties) {
super.beanPropertiesWriteOnly(beanClassName, properties);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beansRequireDefaultConstructor() {
super.beansRequireDefaultConstructor();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beansRequireSerializable() {
super.beansRequireSerializable();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder beansRequireSettersForGetters() {
super.beansRequireSettersForGetters();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder dictionaryOn(Class> on, java.lang.Class>...values) {
super.dictionaryOn(on, values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder disableBeansRequireSomeProperties() {
super.disableBeansRequireSomeProperties();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder disableIgnoreMissingSetters() {
super.disableIgnoreMissingSetters();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder disableIgnoreTransientFields() {
super.disableIgnoreTransientFields();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder disableIgnoreUnknownNullBeanProperties() {
super.disableIgnoreUnknownNullBeanProperties();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder disableInterfaceProxies() {
super.disableInterfaceProxies();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder example(Class pojoClass, T o) {
super.example(pojoClass, o);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder example(Class pojoClass, String json) {
super.example(pojoClass, json);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder findFluentSetters() {
super.findFluentSetters();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder findFluentSetters(Class> on) {
super.findFluentSetters(on);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder ignoreInvocationExceptionsOnGetters() {
super.ignoreInvocationExceptionsOnGetters();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder ignoreInvocationExceptionsOnSetters() {
super.ignoreInvocationExceptionsOnSetters();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder ignoreUnknownBeanProperties() {
super.ignoreUnknownBeanProperties();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder ignoreUnknownEnumValues() {
super.ignoreUnknownEnumValues();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder implClass(Class> interfaceClass, Class> implClass) {
super.implClass(interfaceClass, implClass);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder implClasses(Map,Class>> values) {
super.implClasses(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder interfaceClass(Class> on, Class> value) {
super.interfaceClass(on, value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder interfaces(java.lang.Class>...value) {
super.interfaces(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder locale(Locale value) {
super.locale(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder mediaType(MediaType value) {
super.mediaType(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder notBeanClasses(java.lang.Class>...values) {
super.notBeanClasses(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder notBeanPackages(String...values) {
super.notBeanPackages(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder propertyNamer(Class extends org.apache.juneau.PropertyNamer> value) {
super.propertyNamer(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder propertyNamer(Class> on, Class extends org.apache.juneau.PropertyNamer> value) {
super.propertyNamer(on, value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder sortProperties() {
super.sortProperties();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder sortProperties(java.lang.Class>...on) {
super.sortProperties(on);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder stopClass(Class> on, Class> value) {
super.stopClass(on, value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder swap(Class normalClass, Class swappedClass, ThrowingFunction swapFunction) {
super.swap(normalClass, swappedClass, swapFunction);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder swap(Class normalClass, Class swappedClass, ThrowingFunction swapFunction, ThrowingFunction unswapFunction) {
super.swap(normalClass, swappedClass, swapFunction, unswapFunction);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder swaps(java.lang.Class>...values) {
super.swaps(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder timeZone(TimeZone value) {
super.timeZone(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder typeName(Class> on, String value) {
super.typeName(on, value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder typePropertyName(String value) {
super.typePropertyName(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder typePropertyName(Class> on, String value) {
super.typePropertyName(on, value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder useEnumNames() {
super.useEnumNames();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanContextable.Builder */
public Builder useJavaBeanIntrospector() {
super.useJavaBeanIntrospector();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */
public Builder detectRecursions() {
super.detectRecursions();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */
public Builder detectRecursions(boolean value) {
super.detectRecursions(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */
public Builder ignoreRecursions() {
super.ignoreRecursions();
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */
public Builder ignoreRecursions(boolean value) {
super.ignoreRecursions(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */
public Builder initialDepth(int value) {
super.initialDepth(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanTraverseContext.Builder */
public Builder maxDepth(int value) {
super.maxDepth(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder accept(String value) {
super.accept(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder addBeanTypes() {
super.addBeanTypes();
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder addBeanTypes(boolean value) {
super.addBeanTypes(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder addRootType() {
super.addRootType();
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder addRootType(boolean value) {
super.addRootType(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder keepNullProperties() {
super.keepNullProperties();
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder keepNullProperties(boolean value) {
super.keepNullProperties(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder listener(Class extends org.apache.juneau.serializer.SerializerListener> value) {
super.listener(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder produces(String value) {
super.produces(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder sortCollections() {
super.sortCollections();
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder sortCollections(boolean value) {
super.sortCollections(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder sortMaps() {
super.sortMaps();
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder sortMaps(boolean value) {
super.sortMaps(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder trimEmptyCollections() {
super.trimEmptyCollections();
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder trimEmptyCollections(boolean value) {
super.trimEmptyCollections(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder trimEmptyMaps() {
super.trimEmptyMaps();
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder trimEmptyMaps(boolean value) {
super.trimEmptyMaps(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder trimStrings() {
super.trimStrings();
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder trimStrings(boolean value) {
super.trimStrings(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder uriContext(UriContext value) {
super.uriContext(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder uriRelativity(UriRelativity value) {
super.uriRelativity(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.Serializer.Builder */
public Builder uriResolution(UriResolution value) {
super.uriResolution(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */
public Builder fileCharset(Charset value) {
super.fileCharset(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */
public Builder maxIndent(int value) {
super.maxIndent(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */
public Builder quoteChar(char value) {
super.quoteChar(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */
public Builder quoteCharOverride(char value) {
super.quoteCharOverride(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */
public Builder sq() {
super.sq();
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */
public Builder streamCharset(Charset value) {
super.streamCharset(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */
public Builder useWhitespace() {
super.useWhitespace();
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */
public Builder useWhitespace(boolean value) {
super.useWhitespace(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.serializer.WriterSerializer.Builder */
public Builder ws() {
super.ws();
return this;
}
@Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */
public Builder addBeanTypesXml() {
super.addBeanTypesXml();
return this;
}
@Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */
public Builder addBeanTypesXml(boolean value) {
super.addBeanTypesXml(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */
public Builder addNamespaceUrisToRoot() {
super.addNamespaceUrisToRoot();
return this;
}
@Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */
public Builder addNamespaceUrisToRoot(boolean value) {
super.addNamespaceUrisToRoot(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */
public Builder defaultNamespace(Namespace value) {
super.defaultNamespace(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */
public Builder disableAutoDetectNamespaces() {
super.disableAutoDetectNamespaces();
return this;
}
@Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */
public Builder disableAutoDetectNamespaces(boolean value) {
super.disableAutoDetectNamespaces(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */
public Builder enableNamespaces() {
super.enableNamespaces();
return this;
}
@Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */
public Builder enableNamespaces(boolean value) {
super.enableNamespaces(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */
public Builder namespaces(Namespace...values) {
super.namespaces(values);
return this;
}
@Override /* GENERATED - org.apache.juneau.xml.XmlSerializer.Builder */
public Builder ns() {
super.ns();
return this;
}
@Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */
public Builder addBeanTypesHtml() {
super.addBeanTypesHtml();
return this;
}
@Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */
public Builder addBeanTypesHtml(boolean value) {
super.addBeanTypesHtml(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */
public Builder addKeyValueTableHeaders() {
super.addKeyValueTableHeaders();
return this;
}
@Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */
public Builder addKeyValueTableHeaders(boolean value) {
super.addKeyValueTableHeaders(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */
public Builder disableDetectLabelParameters() {
super.disableDetectLabelParameters();
return this;
}
@Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */
public Builder disableDetectLabelParameters(boolean value) {
super.disableDetectLabelParameters(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */
public Builder disableDetectLinksInStrings() {
super.disableDetectLinksInStrings();
return this;
}
@Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */
public Builder disableDetectLinksInStrings(boolean value) {
super.disableDetectLinksInStrings(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */
public Builder labelParameter(String value) {
super.labelParameter(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.html.HtmlSerializer.Builder */
public Builder uriAnchorText(AnchorText value) {
super.uriAnchorText(value);
return this;
}
//
//-----------------------------------------------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------------------------------------------
private static List copy(List s) {
return s == null || s.isEmpty() ? null : copyOf(s);
}
private static List copy(T[] s) {
return s.length == 0 ? null : list(s);
}
private List merge(List old, String[] newValues) {
List x = list(newValues.length);
for (String s : newValues) {
if ("NONE".equals(s)) {
if (old != null)
old.clear();
} else if ("INHERIT".equals(s)) {
if (old != null)
x.addAll(old);
} else {
x.add(s);
}
}
return x;
}
private List mergeNavLinks(List old, String[] newValues) {
List x = list(newValues.length);
for (String s : newValues) {
if ("NONE".equals(s)) {
if (old != null)
old.clear();
} else if ("INHERIT".equals(s)) {
if (old != null)
x.addAll(old);
} else if (s.indexOf('[') != -1 && INDEXED_LINK_PATTERN.matcher(s).matches()) {
Matcher lm = INDEXED_LINK_PATTERN.matcher(s);
lm.matches();
String key = lm.group(1);
int index = Math.min(x.size(), Integer.parseInt(lm.group(2)));
String remainder = lm.group(3);
x.add(index, key.isEmpty() ? remainder : key + ":" + remainder);
} else {
x.add(s);
}
}
return x;
}
private static final Pattern INDEXED_LINK_PATTERN = Pattern.compile("(?s)(\\S*)\\[(\\d+)\\]\\:(.*)");
}
//-------------------------------------------------------------------------------------------------------------------
// Instance
//-------------------------------------------------------------------------------------------------------------------
final String[] style, stylesheet, script, navlinks, head, header, nav, aside, footer;
final AsideFloat asideFloat;
final String noResultsMessage;
final boolean nowrap, resolveBodyVars;
final Class extends HtmlDocTemplate> template;
final List> widgets;
private final HtmlWidgetMap widgetMap;
private final HtmlWidget[] widgetArray;
private final HtmlDocTemplate templateBean;
private volatile HtmlSchemaDocSerializer schemaSerializer;
/**
* Constructor.
*
* @param builder The builder for this object.
*/
public HtmlDocSerializer(Builder builder) {
super(builder);
style = builder.style != null ? toArray(builder.style) : EMPTY_ARRAY;
stylesheet = builder.stylesheet != null ? toArray(builder.stylesheet) : EMPTY_ARRAY;
script = builder.script != null ? toArray(builder.script) : EMPTY_ARRAY;
head = builder.head != null ? toArray(builder.head) : EMPTY_ARRAY;
header = builder.header != null ? toArray(builder.header) : EMPTY_ARRAY;
nav = builder.nav != null ? toArray(builder.nav) : EMPTY_ARRAY;
aside = builder.aside != null ? toArray(builder.aside) : EMPTY_ARRAY;
footer = builder.footer != null ? toArray(builder.footer) : EMPTY_ARRAY;
navlinks = builder.navlinks != null ? toArray(builder.navlinks) : EMPTY_ARRAY;
asideFloat = builder.asideFloat;
noResultsMessage = builder.noResultsMessage;
nowrap = builder.nowrap;
resolveBodyVars = builder.resolveBodyVars;
template = builder.template;
widgets = builder.widgets == null ? emptyList() : copyOf(builder.widgets);
templateBean = newInstance(template);
widgetMap = new HtmlWidgetMap();
widgets.stream().map(this::newInstance).forEach(x -> widgetMap.append(x));
widgetArray = array(widgetMap.values(), HtmlWidget.class);
}
@Override /* Context */
public Builder copy() {
return new Builder(this);
}
@Override /* Context */
public HtmlDocSerializerSession.Builder createSession() {
return HtmlDocSerializerSession.create(this);
}
@Override /* Context */
public HtmlDocSerializerSession getSession() {
return createSession().build();
}
@Override /* XmlSerializer */
public HtmlSerializer getSchemaSerializer() {
if (schemaSerializer == null)
schemaSerializer = HtmlSchemaDocSerializer.create().beanContext(getBeanContext()).build();
return schemaSerializer;
}
//-----------------------------------------------------------------------------------------------------------------
// Properties
//-----------------------------------------------------------------------------------------------------------------
/**
* Aside section contents.
*
* @see Builder#aside(String...)
* @return
* The overridden contents of the aside section on the HTML page.
*/
protected final String[] getAside() {
return aside;
}
/**
* Float side section contents.
*
* @see Builder#asideFloat(AsideFloat)
* @return
* How to float the aside contents on the page.
*/
protected final AsideFloat getAsideFloat() {
return asideFloat;
}
/**
* Footer section contents.
*
* @see Builder#footer(String...)
* @return
* The overridden contents of the footer section on the HTML page.
*/
protected final String[] getFooter() {
return footer;
}
/**
* Additional head section content.
*
* @see Builder#head(String...)
* @return
* HTML content to add to the head section of the HTML page.
*/
protected final String[] getHead() {
return head;
}
/**
* Header section contents.
*
* @see Builder#header(String...)
* @return
* The overridden contents of the header section on the HTML page.
*/
protected final String[] getHeader() {
return header;
}
/**
* Nav section contents.
*
* @see Builder#nav(String...)
* @return
* The overridden contents of the nav section on the HTML page.
*/
protected final String[] getNav() {
return nav;
}
/**
* Page navigation links.
*
* @see Builder#navlinks(String...)
* @return
* Navigation links to add to the HTML page.
*/
protected final String[] getNavlinks() {
return navlinks;
}
/**
* No-results message.
*
* @see Builder#noResultsMessage(String)
* @return
* The message used when serializing an empty array or empty list.
*/
protected final String getNoResultsMessage() {
return noResultsMessage;
}
/**
* Prevent word wrap on page.
*
* @see Builder#nowrap()
* @return
* true if "* {white-space:nowrap}" shoudl be added to the CSS instructions on the page to prevent word wrapping.
*/
protected final boolean isNowrap() {
return nowrap;
}
/**
* Javascript code.
*
* @see Builder#script(String...)
* @return
* Arbitrary Javascript to add to the HTML page.
*/
protected final String[] getScript() {
return script;
}
/**
* CSS style code.
*
* @see Builder#style(String...)
* @return
* The CSS instructions to add to the HTML page.
*/
protected final String[] getStyle() {
return style;
}
/**
* Stylesheet import URLs.
*
* @see Builder#stylesheet(String...)
* @return
* The link to the stylesheet of the HTML page.
*/
protected final String[] getStylesheet() {
return stylesheet;
}
/**
* HTML document template.
*
* @see Builder#template(Class)
* @return
* The template to use for serializing the page.
*/
protected final HtmlDocTemplate getTemplate() {
return templateBean;
}
/**
* HTML widgets.
*
* @see Builder#widgets(Class...)
* @return
* Widgets defined on this serializers.
*/
protected final HtmlWidgetMap getWidgets() {
return widgetMap;
}
/**
* Performs an action on all widgets defined on this serializer.
*
* @param action The action to perform.
* @return This object.
*/
protected final HtmlDocSerializer forEachWidget(Consumer action) {
for (HtmlWidget w : widgetArray)
action.accept(w);
return this;
}
//-----------------------------------------------------------------------------------------------------------------
// Other methods
//-----------------------------------------------------------------------------------------------------------------
private String[] toArray(List x) {
return x.toArray(new String[x.size()]);
}
private T newInstance(Class c) {
try {
return c.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw asRuntimeException(e);
}
}
@Override /* Context */
protected JsonMap properties() {
return filteredMap()
.append("header", header)
.append("nav", nav)
.append("navlinks", navlinks)
.append("aside", aside)
.append("asideFloat", asideFloat)
.append("footer", footer)
.append("style", style)
.append("head", head)
.append("stylesheet", stylesheet)
.append("nowrap", nowrap)
.append("template", template)
.append("noResultsMessage", noResultsMessage)
.append("widgets", widgets);
}
}