All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.juneau.html.HtmlSerializer Maven / Gradle / Ivy

There is a newer version: 9.0.1
Show newest version
// ***************************************************************************************************************************
// * 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 java.util.*;

import org.apache.juneau.*;
import org.apache.juneau.html.annotation.*;
import org.apache.juneau.serializer.*;
import org.apache.juneau.xml.*;

/**
 * Serializes POJO models to HTML.
 *
 * 
Media types
* * Handles Accept types: text/html *

* Produces Content-Type types: text/html * *

Description
* * The conversion is as follows... *
    *
  • * {@link Map Maps} (e.g. {@link HashMap}, {@link TreeMap}) and beans are converted to HTML tables with * 'key' and 'value' columns. *
  • * {@link Collection Collections} (e.g. {@link HashSet}, {@link LinkedList}) and Java arrays are converted * to HTML ordered lists. *
  • * {@code Collections} of {@code Maps} and beans are converted to HTML tables with keys as headers. *
  • * Everything else is converted to text. *
* *

* This serializer provides several serialization options. Typically, one of the predefined DEFAULT * serializers will be sufficient. * However, custom serializers can be constructed to fine-tune behavior. * *

* The {@link HtmlLink} annotation can be used on beans to add hyperlinks to the output. * *

Behavior-specific subclasses
* * The following direct subclasses are provided for convenience: *
    *
  • * {@link Sq} - Default serializer, single quotes. *
  • * {@link SqReadable} - Default serializer, single quotes, whitespace added. *
* *
Example:
*

* // Use one of the default serializers to serialize a POJO * String html = HtmlSerializer.DEFAULT.serialize(someObject); * * // Create a custom serializer that doesn't use whitespace and newlines * HtmlSerializer serializer = new HtmlSerializerBuider().ws().build(); * * // Same as above, except uses cloning * HtmlSerializer serializer = HtmlSerializer.DEFAULT.builder().ws().build(); * * // Serialize POJOs to HTML * * // Produces: * // <ul><li>1<li>2<li>3</ul> * List l = new ObjectList(1, 2, 3); * String html = HtmlSerializer.DEFAULT.serialize(l); * * // Produces: * // <table> * // <tr><th>firstName</th><th>lastName</th></tr> * // <tr><td>Bob</td><td>Costas</td></tr> * // <tr><td>Billy</td><td>TheKid</td></tr> * // <tr><td>Barney</td><td>Miller</td></tr> * // </table> * l = new ObjectList(); * l.add(new ObjectMap("{firstName:'Bob',lastName:'Costas'}")); * l.add(new ObjectMap("{firstName:'Billy',lastName:'TheKid'}")); * l.add(new ObjectMap("{firstName:'Barney',lastName:'Miller'}")); * String html = HtmlSerializer.DEFAULT.serialize(l); * * // Produces: * // <table> * // <tr><th>key</th><th>value</th></tr> * // <tr><td>foo</td><td>bar</td></tr> * // <tr><td>baz</td><td>123</td></tr> * // </table> * Map m = new ObjectMap("{foo:'bar',baz:123}"); * String html = HtmlSerializer.DEFAULT.serialize(m); * * // HTML elements can be nested arbitrarily deep * // Produces: * // <table> * // <tr><th>key</th><th>value</th></tr> * // <tr><td>foo</td><td>bar</td></tr> * // <tr><td>baz</td><td>123</td></tr> * // <tr><td>someNumbers</td><td><ul><li>1<li>2<li>3</ul></td></tr> * // <tr><td>someSubMap</td><td> * // <table> * // <tr><th>key</th><th>value</th></tr> * // <tr><td>a</td><td>b</td></tr> * // </table> * // </td></tr> * // </table> * Map m = new ObjectMap("{foo:'bar',baz:123}"); * m.put("someNumbers", new ObjectList(1, 2, 3)); * m.put("someSubMap", new ObjectMap("{a:'b'}")); * String html = HtmlSerializer.DEFAULT.serialize(m); *

*/ public class HtmlSerializer extends XmlSerializer { //------------------------------------------------------------------------------------------------------------------- // Configurable properties //------------------------------------------------------------------------------------------------------------------- private static final String PREFIX = "HtmlSerializer."; /** * Configuration property: Add "_type" properties when needed. * *
Property:
*
    *
  • Name: "HtmlSerializer.addBeanTypes.b" *
  • Data type: Boolean *
  • Default: false *
  • Session property: false *
  • Methods: *
      *
    • {@link HtmlSerializerBuilder#addBeanTypes(boolean)} *
    *
* *
Description:
*

* If true, then "_type" properties will be added to beans if their type cannot be inferred * through reflection. * *

* When present, this value overrides the {@link #SERIALIZER_addBeanTypes} setting and is * provided to customize the behavior of specific serializers in a {@link SerializerGroup}. */ public static final String HTML_addBeanTypes = PREFIX + "addBeanTypes.b"; /** * Configuration property: Add key/value headers on bean/map tables. * *

Property:
*
    *
  • Name: "HtmlSerializer.addKeyValueTableHeaders.b" *
  • Data type: Boolean *
  • Default: false *
  • Session property: false *
  • Annotations: *
      *
    • {@link Html#noTableHeaders()} *
    *
  • Methods: *
      *
    • {@link HtmlSerializerBuilder#addKeyValueTableHeaders(boolean)} *
    • {@link HtmlSerializerBuilder#addKeyValueTableHeaders()} *
    *
* *

* When enabled, key and value column headers are added to tables. * *

Example:
*

* // Our bean class. * public class MyBean { * public String f1 = "foo"; * public String f2 = "bar"; * } * * // Serializer without headers. * WriterSerializer s1 = HtmlSerializer.DEFAULT; * * // Serializer with headers. * WriterSerializer s2 = HtmlSerializer * .create() * .addKeyValueTableHeaders() * .build(); * * String withoutHeaders = s1.serialize(new MyBean()); * String withHeaders = s2.serialize(new MyBean()); *

* *

* The following shows the difference between the two generated outputs: * *

* * * * * * * * *
withoutHeaderswithHeaders
* * * *
f1foo
f2bar
*
* * * * *
keyvalue
f1foo
f2bar
*
*/ public static final String HTML_addKeyValueTableHeaders = PREFIX + "addKeyValueTableHeaders.b"; /** * Configuration property: Look for URLs in {@link String Strings}. * *
Property:
*
    *
  • Name: "HtmlSerializer.detectLinksInStrings.b" *
  • Data type: Boolean *
  • Default: true *
  • Session property: false *
  • Methods: *
      *
    • {@link HtmlSerializerBuilder#detectLinksInStrings(boolean)} *
    *
* *
Description:
*

* If a string looks like a URL (i.e. starts with "http://" or "https://", then treat it like a URL * and make it into a hyperlink based on the rules specified by {@link #HTML_uriAnchorText}. * *

Example:
*

* // Our bean class with a property containing what looks like a URL. * public class MyBean { * public String f1 = "http://www.apache.org"; * } * * // Serializer with link detection. * WriterSerializer s1 = HtmlSerializer * .create() * .addKeyValueTableHeaders() * .build(); * * // Serializer without link detection. * WriterSerializer s2 = HtmlSerializer * .create() * .addKeyValueTableHeaders() * .detectLinksInStrings(false) * .build(); * * String withLinks = s1.serialize(new MyBean()); * String withoutLinks = s2.serialize(new MyBean()); *

* *

* The following shows the difference between the two generated outputs: * *

* * * * * * * * *
withLinkswithoutLinks
* * * *
keyvalue
f1http://www.apache.org
*
* * * *
keyvalue
f1http://www.apache.org
*
*/ public static final String HTML_detectLinksInStrings = PREFIX + "detectLinksInStrings.b"; /** * Configuration property: Link label parameter name. * *
Property:
*
    *
  • Name: "HtmlSerializer.labelParameter.s" *
  • Data type: String *
  • Default: "label" *
  • Session property: false *
  • Methods: *
      *
    • {@link HtmlSerializerBuilder#labelParameter(String)} *
    *
* *

* The parameter name to look for when resolving link labels via {@link #HTML_detectLabelParameters}. * *

See Also:
*
    *
  • {@link #HTML_detectLabelParameters} *
*/ public static final String HTML_labelParameter = PREFIX + "labelParameter.s"; /** * Configuration property: Look for link labels in URIs. * *
Property:
*
    *
  • Name: "HtmlSerializer.detectLabelParameters.b" *
  • Data type: Boolean *
  • Default: true *
  • Session property: false *
  • Methods: *
      *
    • {@link HtmlSerializerBuilder#detectLabelParameters(boolean)} *
    *
* *
Description:
*

* If the URL has a label parameter (e.g. "?label=foobar"), then use that as the anchor text of the link. * *

* The parameter name can be changed via the {@link #HTML_labelParameter} property. * *

Example:
*

* // Our bean class with a property containing what looks like a URL. * public class MyBean { * public URI f1 = URI.create("http://www.apache.org?label=Apache%20Foundation"); * } * * // Serializer with label detection. * WriterSerializer s1 = HtmlSerializer * .create() * .addKeyValueTableHeaders() * .build(); * * // Serializer without label detection. * WriterSerializer s2 = HtmlSerializer * .create() * .addKeyValueTableHeaders() * .lookForLabelParameters(false) * .build(); * * String withLabels = s1.serialize(new MyBean()); * String withoutLabels = s2.serialize(new MyBean()); *

* *

* The following shows the difference between the two generated outputs. *
Note that they're both hyperlinks, but the anchor text differs: * *

* * * * * * * * *
withLabelswithoutLabels
* * * *
keyvalue
f1Apache Foundation
*
* * * *
keyvalue
f1http://www.apache.org?label=Apache%20Foundation
*
*/ public static final String HTML_detectLabelParameters = PREFIX + "detectLabelParameters.b"; /** * Configuration property: Anchor text source. * *
Property:
*
    *
  • Name: "HtmlSerializer.uriAnchorText.s" *
  • Data type: String ({@link AnchorText}) *
  • Default: "TO_STRING" *
  • Session property: false *
  • Annotations: *
      *
    • {@link Html#anchorText()} *
    *
  • Methods: *
      *
    • {@link HtmlSerializerBuilder#uriAnchorText(AnchorText)} *
    • {@link HtmlSerializerBuilder#uriAnchorText(String)} *
    *
* *
Description:
*

* When creating anchor tags (e.g. <a href='...' * >text</a>) in HTML, this setting defines what to set the inner text to. * *

* The possible values are: *

    *
  • {@link AnchorText} *
      *
    • {@link AnchorText#TO_STRING TO_STRING} (default) - Set to whatever is returned by {@link #toString()} on the object. *
      *
      Example:
      *

      * // Our bean class with a URI property. * public class MyBean { * public URI f1 = URI.create("http://www.apache.org?foo=bar#myAnchor"); * } * * // Serializer with TO_STRING anchor text. * WriterSerializer s1 = HtmlSerializer.create().anchorText(TO_STRING).build(); * * // Produces: <a href='http://www.apache.org?foo=bar#myAnchor'>http://www.apache.org?foo=bar#myAnchor</a> * String html = s1.serialize(new MyBean()); *

      *
    • {@link AnchorText#PROPERTY_NAME PROPERTY_NAME} - Set to the bean property name. *
      *
      Example:
      *

      * // Our bean class with a URI property. * public class MyBean { * public URI f1 = URI.create("http://www.apache.org?foo=bar#myAnchor"); * } * * // Serializer with PROPERTY_NAME anchor text. * WriterSerializer s1 = HtmlSerializer.create().anchorText(PROPERTY_NAME).build(); * * // Produces: <a href='http://www.apache.org?foo=bar#myAnchor'>f1</a> * String html = s1.serialize(new MyBean()); *

      *
    • {@link AnchorText#URI URI} - Set to the URI value. *
      *
      Example:
      *

      * // Our bean class with a URI property. * public class MyBean { * public URI f1 = URI.create("http://www.apache.org?foo=bar#myAnchor"); * } * * // Serializer with URI anchor text. * WriterSerializer s1 = HtmlSerializer.create().anchorText(URI).build(); * * // Produces: <a href='http://www.apache.org?foo=bar#myAnchor'>http://www.apache.org?foo=bar</a> * String html = s1.serialize(new MyBean()); *

      *
    • {@link AnchorText#LAST_TOKEN LAST_TOKEN} - Set to the last token of the URI value. *
      *
      Example:
      *

      * // Our bean class with a URI property. * public class MyBean { * public URI f1 = URI.create("http://www.apache.org/foo/bar?baz=qux#myAnchor"); * } * * // Serializer with LAST_TOKEN anchor text. * WriterSerializer s1 = HtmlSerializer.create().anchorText(LAST_TOKEN).build(); * * // Produces: <a href='http://www.apache.org/foo/bar?baz=qux#myAnchor'>bar</a> * String html = s1.serialize(new MyBean()); *

      *
    • {@link AnchorText#URI_ANCHOR URI_ANCHOR} - Set to the anchor of the URL. *
      *
      Example:
      *

      * // Our bean class with a URI property. * public class MyBean { * public URI f1 = URI.create("http://www.apache.org/foo/bar?baz=qux#myAnchor"); * } * * // Serializer with URI_ANCHOR anchor text. * WriterSerializer s1 = HtmlSerializer.create().anchorText(URI_ANCHOR).build(); * * // Produces: <a href='http://www.apache.org/foo/bar?baz=qux#myAnchor'>myAnchor</a> * String html = s1.serialize(new MyBean()); *

      *
    • {@link AnchorText#CONTEXT_RELATIVE CONTEXT_RELATIVE} - Same as {@link AnchorText#TO_STRING TO_STRING} but assumes it's a context-relative path. *
      *
      Example:
      *

      * // Our bean class with a URI property. * public class MyBean { * public URI f1 = URI.create("bar/baz"); * } * * // Serializer with CONTEXT_RELATIVE anchor text. * WriterSerializer s1 = HtmlSerializer * .create() * .anchorText(CONTEXT_RELATIVE) * .uriResolution(ROOT_RELATIVE) * .uriRelativity(RESOURCE) * .uriContext("{authority:'http://localhost:10000',contextRoot:'/myContext',servletPath:'/myServlet',pathInfo:'/foo'}") * .build(); * * // Produces: <a href='/myContext/myServlet/bar/baz'>myServlet/bar/baz</a> * String html = s1.serialize(new MyBean()); *

      *
    • {@link AnchorText#SERVLET_RELATIVE SERVLET_RELATIVE} - Same as {@link AnchorText#TO_STRING TO_STRING} but assumes it's a servlet-relative path. *
      *
      Example:
      *

      * // Our bean class with a URI property. * public class MyBean { * public URI f1 = URI.create("bar/baz"); * } * * // Serializer with SERVLET_RELATIVE anchor text. * WriterSerializer s1 = HtmlSerializer * .create() * .anchorText(SERVLET_RELATIVE) * .uriResolution(ROOT_RELATIVE) * .uriRelativity(RESOURCE) * .uriContext("{authority:'http://localhost:10000',contextRoot:'/myContext',servletPath:'/myServlet',pathInfo:'/foo'}") * .build(); * * // Produces: <a href='/myContext/myServlet/bar/baz'>bar/baz</a> * String html = s1.serialize(new MyBean()); *

      *
    • {@link AnchorText#PATH_RELATIVE PATH_RELATIVE} - Same as {@link AnchorText#TO_STRING TO_STRING} but assumes it's a path-relative path. *
      *
      Example:
      *

      * // Our bean class with a URI property. * public class MyBean { * public URI f1 = URI.create("bar/baz"); * } * * // Serializer with PATH_RELATIVE anchor text. * WriterSerializer s1 = HtmlSerializer * .create() * .anchorText(PATH_RELATIVE) * .uriResolution(ROOT_RELATIVE) * .uriRelativity(PATH_INFO) * .uriContext("{authority:'http://localhost:10000',contextRoot:'/myContext',servletPath:'/myServlet',pathInfo:'/foo'}") * .build(); * * // Produces: <a href='/myContext/myServlet/foo/bar/baz'>bar/baz</a> * String html = s1.serialize(new MyBean()); *

      *
    *
*/ public static final String HTML_uriAnchorText = PREFIX + "uriAnchorText.s"; //------------------------------------------------------------------------------------------------------------------- // Predefined instances //------------------------------------------------------------------------------------------------------------------- /** Default serializer, all default settings. */ public static final HtmlSerializer DEFAULT = new HtmlSerializer(PropertyStore.DEFAULT); /** Default serializer, single quotes. */ public static final HtmlSerializer DEFAULT_SQ = new HtmlSerializer.Sq(PropertyStore.DEFAULT); /** Default serializer, single quotes, whitespace added. */ public static final HtmlSerializer DEFAULT_SQ_READABLE = new HtmlSerializer.SqReadable(PropertyStore.DEFAULT); //------------------------------------------------------------------------------------------------------------------- // Predefined subclasses //------------------------------------------------------------------------------------------------------------------- /** Default serializer, single quotes. */ public static class Sq extends HtmlSerializer { /** * Constructor. * * @param ps The property store containing all the settings for this object. */ public Sq(PropertyStore ps) { super( ps.builder() .set(WSERIALIZER_quoteChar, '\'') .build() ); } } /** Default serializer, single quotes, whitespace added. */ public static class SqReadable extends HtmlSerializer { /** * Constructor. * * @param ps The property store containing all the settings for this object. */ public SqReadable(PropertyStore ps) { super( ps.builder() .set(WSERIALIZER_quoteChar, '\'') .set(SERIALIZER_useWhitespace, true) .build() ); } } //------------------------------------------------------------------------------------------------------------------- // Instance //------------------------------------------------------------------------------------------------------------------- private final AnchorText uriAnchorText; private final boolean lookForLabelParameters, detectLinksInStrings, addKeyValueTableHeaders, addBeanTypes; private final String labelParameter; private volatile HtmlSchemaSerializer schemaSerializer; /** * Constructor. * * @param ps * The property store containing all the settings for this object. */ public HtmlSerializer(PropertyStore ps) { this(ps, "text/html", null); } /** * Constructor. * * @param ps * The property store containing all the settings for this object. * @param produces * The media type that this serializer produces. * @param accept * The accept media types that the serializer can handle. *

* Can contain meta-characters per the media-type specification of * {@doc RFC2616.section14.1} *

* If empty, then assumes the only media type supported is produces. *

* For example, if this serializer produces "application/json" but should handle media types of * "application/json" and "text/json", then the arguments should be: *

* super(ps, "application/json", "application/json,text/json"); *

*
...or... *

* super(ps, "application/json", "*​/json"); *

*

* The accept value can also contain q-values. */ public HtmlSerializer(PropertyStore ps, String produces, String accept) { super(ps, produces, accept); uriAnchorText = getProperty(HTML_uriAnchorText, AnchorText.class, AnchorText.TO_STRING); lookForLabelParameters = getBooleanProperty(HTML_detectLabelParameters, true); detectLinksInStrings = getBooleanProperty(HTML_detectLinksInStrings, true); labelParameter = getStringProperty(HTML_labelParameter, "label"); addKeyValueTableHeaders = getBooleanProperty(HTML_addKeyValueTableHeaders, false); addBeanTypes = getBooleanProperty(HTML_addBeanTypes, getBooleanProperty(SERIALIZER_addBeanTypes, false)); } @Override /* Context */ public HtmlSerializerBuilder builder() { return new HtmlSerializerBuilder(getPropertyStore()); } /** * Instantiates a new clean-slate {@link HtmlSerializerBuilder} object. * *

* This is equivalent to simply calling new HtmlSerializerBuilder(). * *

* Note that this method creates a builder initialized to all default settings, whereas {@link #builder()} copies * the settings of the object called on. * * @return A new {@link HtmlSerializerBuilder} object. */ public static HtmlSerializerBuilder create() { return new HtmlSerializerBuilder(); } @Override /* Serializer */ public WriterSerializerSession createSession(SerializerSessionArgs args) { return new HtmlSerializerSession(this, args); } @Override /* XmlSerializer */ public HtmlSerializer getSchemaSerializer() { if (schemaSerializer == null) schemaSerializer = builder().build(HtmlSchemaSerializer.class); return schemaSerializer; } //----------------------------------------------------------------------------------------------------------------- // Properties //----------------------------------------------------------------------------------------------------------------- /** * Configuration property: Look for link labels in URIs. * * @see #HTML_detectLabelParameters * @return * true if we should look for URL label parameters (e.g. "?label=foobar"). */ protected final boolean isLookForLabelParameters() { return lookForLabelParameters; } /** * Configuration property: Look for URLs in {@link String Strings}. * * @see #HTML_detectLinksInStrings * @return * true if we should automatically convert strings to URLs if they look like a URL. */ protected final boolean isDetectLinksInStrings() { return detectLinksInStrings; } /** * Configuration property: Add key/value headers on bean/map tables. * * @see #HTML_addKeyValueTableHeaders * @return * true if key and value column headers are added to tables. */ protected final boolean isAddKeyValueTableHeaders() { return addKeyValueTableHeaders; } /** * Configuration property: Add "_type" properties when needed. * * @see #HTML_addBeanTypes * @return * true if "_type" properties will be added to beans if their type cannot be inferred * through reflection. */ @Override protected final boolean isAddBeanTypes() { return addBeanTypes; } /** * Configuration property: Link label parameter name. * * @see #HTML_labelParameter * @return * The parameter name to look for when resolving link labels via {@link #HTML_detectLabelParameters}. */ protected final String getLabelParameter() { return labelParameter; } /** * Configuration property: Anchor text source. * * @see #HTML_uriAnchorText * @return * When creating anchor tags (e.g. <a href='...' * >text</a>) in HTML, this setting defines what to set the inner text to. */ protected final AnchorText getUriAnchorText() { return uriAnchorText; } @Override /* Context */ public ObjectMap asMap() { return super.asMap() .append("HtmlSerializer", new ObjectMap() .append("uriAnchorText", uriAnchorText) .append("lookForLabelParameters", lookForLabelParameters) .append("detectLinksInStrings", detectLinksInStrings) .append("labelParameter", labelParameter) .append("addKeyValueTableHeaders", addKeyValueTableHeaders) .append("addBeanTypes", addBeanTypes) ); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy