View Javadoc

    1   package org.apache.turbine.util.template;
    2
    3
    4   /*
    5    * Licensed to the Apache Software Foundation (ASF) under one
    6    * or more contributor license agreements.  See the NOTICE file
    7    * distributed with this work for additional information
    8    * regarding copyright ownership.  The ASF licenses this file
    9    * to you under the Apache License, Version 2.0 (the
    10   * "License"); you may not use this file except in compliance
    11   * with the License.  You may obtain a copy of the License at
    12   *
    13   *   http://www.apache.org/licenses/LICENSE-2.0
    14   *
    15   * Unless required by applicable law or agreed to in writing,
    16   * software distributed under the License is distributed on an
    17   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    18   * KIND, either express or implied.  See the License for the
    19   * specific language governing permissions and limitations
    20   * under the License.
    21   */
    22
    23
    24  import java.util.ArrayList;
    25  import java.util.LinkedHashMap;
    26  import java.util.List;
    27  import java.util.Map;
    28
    29  import org.apache.commons.lang.StringUtils;
    30  import org.apache.turbine.TurbineConstants;
    31  import org.apache.turbine.annotation.TurbineConfiguration;
    32  import org.apache.turbine.services.pull.ApplicationTool;
    33
    34  /**
    35   * Template context tool that can be used to set various attributes of a
    36   * HTML page.  This tool does not automatically make the changes in the HTML
    37   * page for you.  You must use this tool in your layout template to retrieve
    38   * the attributes.
    39   * <p>
    40   * The set/add methods are can be used from a screen template, action, screen
    41   * class, layour template, or anywhere else.  The get methods should be used in
    42   * your layout template(s) to construct the appropriate HTML tags.
    43   *<p>
    44   * Example usage of this tool to build the HEAD and BODY tags in your layout
    45   * templates:
    46   * <p>
    47   *  <code>
    48   *  ## Set defaults for all pages using this layout.  Anything set here can<br>
    49   *  ## be overridden in the screen template.<br>
    50   *  $page.setTitle("My default page title");<br>
    51   *  $page.setHttpEquiv("Content-Style-Type","text/css")<br>
    52   *  $page.addStyleSheet($content.getURI("myStyleSheet.css"))<br>
    53   *  $page.addScript($content.getURI("globalJavascriptCode.js"))<br>
    54   *  <br>
    55   *  ## build the HTML, HEAD, and BODY tags dynamically<br>
    56   *  &lt;html&gt;<br>
    57   *    &lt;head&gt;<br>
    58   *      #if( $page.Title != "" )<br>
    59   *      &lt;title&gt;$page.Title&lt;/title&gt;<br>
    60   *      #end<br>
    61   *      #foreach($metaTag in $page.MetaTags.keySet())<br>
    62   *      &lt;meta name="$metaTag" content="$page.MetaTags.get($metaTag)"&gt;<br>
    63   *      #end<br>
    64   *      #foreach($httpEquiv in $page.HttpEquivs.keySet())<br>
    65   *      &lt;meta http-equiv="$httpEquiv" content="$page.HttpEquivs.get($httpEquiv)"&gt;<br>
    66   *      #end<br>
    67   *      #foreach( $styleSheet in $page.StyleSheets )<br>
    68   *        &lt;link rel="stylesheet" href="$styleSheet.Url"<br>
    69   *          #if($styleSheet.Type != "" ) type="$styleSheet.Type" #end<br>
    70   *          #if($styleSheet.Media != "") media="$styleSheet.Media" #end<br>
    71   *          #if($styleSheet.Title != "") title="$styleSheet.Title" #end<br>
    72   *        &gt;<br>
    73   *      #end<br>
    74   *      #foreach( $script in $page.Scripts )<br>
    75   *        &lt;script type="text/javascript" src="$script" language="JavaScript"&gt;&lt;/script&gt;<br>
    76   *      #end<br>
    77   *    &lt;/head&gt;<br>
    78   *<br>
    79   *    ## Construct the body tag.  Iterate through the body attributes to build the opening tag<br>
    80   *    &lt;body<br>
    81   *      #foreach( $attributeName in $page.BodyAttributes.keySet() )<br>
    82   *        $attributeName = "$page.BodyAttributes.get($attributeName)"<br>
    83   *      #end<br>
    84   *     &gt;
    85   * </code>
    86   * <p>
    87   * Example usages of this tool in your screen templates:<br>
    88   *   <code>$page.addScript($content.getURI("myJavascript.js")<br>
    89   *   $page.setTitle("My page title")<br>
    90   *   $page.setHttpEquiv("refresh","5; URL=http://localhost/nextpage.html")</code>
    91   *
    92   * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
    93   * @author <a href="mailto:seade@backstagetech.com.au">Scott Eade</a>
    94   * @version $Id: HtmlPageAttributes.java 1725011 2016-01-16 17:38:47Z tv $
    95   */
    96  public class HtmlPageAttributes
    97          implements ApplicationTool
    98  {
    99      /** The title */
    100     private String title;
    101
    102     /** Body Attributes */
    103     private final Map<String, String> bodyAttributes = new LinkedHashMap<String, String>();
    104
    105     /** Script references */
    106     private final List<String> scripts = new ArrayList<String>();
    107
    108     /** External references */
    109     private final List<LinkTag> linkTags = new ArrayList<LinkTag>();
    110
    111     /** Inline styles */
    112     private final List<String> styles = new ArrayList<String>();
    113
    114     /** Meta tags for the HEAD */
    115     private final Map<String, String> metaTags = new LinkedHashMap<String, String>();
    116
    117     /** http-equiv tags */
    118     private final Map<String, String> httpEquivs = new LinkedHashMap<String, String>();
    119
    120     /** Doctype */
    121     private String doctype = null;
    122
    123     @TurbineConfiguration( TurbineConstants.DEFAULT_HTML_DOCTYPE_ROOT_ELEMENT_KEY )
    124     private String defaultHtmlDoctypeRootElement = TurbineConstants.DEFAULT_HTML_DOCTYPE_ROOT_ELEMENT_DEFAULT;
    125
    126     @TurbineConfiguration( TurbineConstants.DEFAULT_HTML_DOCTYPE_IDENTIFIER_KEY )
    127     private String defaultHtmlDoctypeIdentifier = TurbineConstants.DEFAULT_HTML_DOCTYPE_IDENTIFIER_DEFAULT;
    128
    129     @TurbineConfiguration( TurbineConstants.DEFAULT_HTML_DOCTYPE_URI_KEY )
    130     private String defaultHtmlDoctypeUri = TurbineConstants.DEFAULT_HTML_DOCTYPE_URI_DEFAULT;
    131
    132     /**
    133      * Construct a new instance
    134      */
    135     public HtmlPageAttributes()
    136     {
    137         init(null);
    138     }
    139
    140     /**
    141      * Initialize this instance.
    142      * (ApplicationTool method)
    143      *
    144      * @param data not used
    145      */
    146     @Override
    147     public void init(Object data)
    148     {
    149         this.title = null;
    150         this.bodyAttributes.clear();
    151         this.scripts.clear();
    152         this.linkTags.clear();
    153         this.styles.clear();
    154         this.metaTags.clear();
    155         this.httpEquivs.clear();
    156     }
    157
    158     /**
    159      * Refresh method - does nothing
    160      */
    161     @Override
    162     public void refresh()
    163     {
    164         // empty
    165     }
    166
    167     /**
    168      * Set the title in the page.  This returns an empty String so
    169      * that the template doesn't complain about getting a null return
    170      * value.  Subsequent calls to this method will replace the current
    171      * title.
    172      *
    173      * @param title A String with the title.
    174      * @return a <code>HtmlPageAttributes</code> (self).
    175      */
    176     public HtmlPageAttributes setTitle(String title)
    177     {
    178         this.title = title;
    179         return this;
    180     }
    181
    182     /**
    183      * Get the title in the page.  This returns an empty String if
    184      * empty so that the template doesn't complain about getting a null
    185      * return value.
    186      *
    187      * @return A String with the title.
    188      */
    189     public String getTitle()
    190     {
    191         if (StringUtils.isEmpty(this.title))
    192         {
    193             return "";
    194         }
    195         return title;
    196     }
    197
    198     /**
    199      * Adds an attribute to the BODY tag.
    200      *
    201      * @param name A String.
    202      * @param value A String.
    203      * @return a <code>HtmlPageAttributes</code> (self).
    204      */
    205     public HtmlPageAttributes addBodyAttribute(String name, String value)
    206     {
    207         this.bodyAttributes.put(name, value);
    208         return this;
    209     }
    210
    211     /**
    212      * Returns the map of body attributes
    213      *
    214      * @return the map
    215      */
    216     public Map<String, String> getBodyAttributes()
    217     {
    218         return this.bodyAttributes;
    219     }
    220
    221     /**
    222      * Adds a script reference
    223      *
    224      * @param scriptURL
    225      * @return a <code>HtmlPageAttributes</code> (self).
    226      */
    227     public HtmlPageAttributes addScript(String scriptURL)
    228     {
    229         this.scripts.add(scriptURL);
    230         return this;
    231     }
    232
    233     /**
    234      * Returns a collection of script URLs
    235      *
    236      * @return list of String objects containing URLs of javascript files
    237      * to include
    238      */
    239     public List<String> getScripts()
    240     {
    241         return this.scripts;
    242     }
    243
    244     /**
    245      * Adds a style sheet reference
    246      *
    247      * @param styleSheetURL URL of the style sheet
    248      * @return a <code>HtmlPageAttributes</code> (self).
    249      */
    250     public HtmlPageAttributes addStyleSheet(String styleSheetURL)
    251     {
    252         addStyleSheet(styleSheetURL, "screen", null, "text/css");
    253         return this;
    254     }
    255
    256     /**
    257      * Adds a style sheet reference
    258      *
    259      * @param styleSheetURL URL of the style sheet
    260      * @param media name of the media
    261      * @param title title of the stylesheet
    262      * @param type content type
    263      * @return a <code>HtmlPageAttributes</code> (self).
    264      */
    265     public HtmlPageAttributes addStyleSheet(String styleSheetURL,
    266                                             String media, String title, String type)
    267     {
    268         LinkTag ss = new LinkTag("stylesheet", styleSheetURL);
    269         ss.setMedia(media);
    270         ss.setTitle(title);
    271         ss.setType(type);
    272         this.linkTags.add(ss);
    273         return this;
    274     }
    275
    276     /**
    277      * Adds a generic external reference
    278      *
    279      * @param relation type of the reference (prev, next, first, last, top, etc.)
    280      * @param linkURL URL of the reference
    281      * @return a <code>HtmlPageAttributes</code> (self).
    282      */
    283     public HtmlPageAttributes addLink(String relation, String linkURL)
    284     {
    285         return addLink(relation, linkURL, null, null);
    286     }
    287
    288     /**
    289      * Adds a generic external reference
    290      *
    291      * @param relation type of the reference (prev, next, first, last, top, etc.)
    292      * @param linkURL URL of the reference
    293      * @param title title of the reference
    294      * @return a <code>HtmlPageAttributes</code> (self).
    295      */
    296     public HtmlPageAttributes addLink(String relation, String linkURL, String title)
    297     {
    298         return addLink(relation, linkURL, title, null);
    299     }
    300
    301     /**
    302      * Adds a generic external reference
    303      *
    304      * @param relation type of the reference (prev, next, first, last, top, etc.)
    305      * @param linkURL URL of the reference
    306      * @param title title of the reference
    307      * @param type content type
    308      * @return a <code>HtmlPageAttributes</code> (self).
    309      */
    310     public HtmlPageAttributes addLink(String relation, String linkURL, String title,
    311                                         String type)
    312     {
    313         LinkTag ss = new LinkTag(relation, linkURL);
    314         ss.setTitle(title);
    315         ss.setType(type);
    316         this.linkTags.add(ss);
    317         return this;
    318     }
    319
    320     /**
    321      * Returns a collection of link URLs
    322      *
    323      * @return list LinkTag objects (inner class)
    324      */
    325     public List<LinkTag> getLinks()
    326     {
    327         return this.linkTags;
    328     }
    329
    330     /**
    331      * Adds a STYLE element to the HEAD of the page with the provided content.
    332      *
    333      * @param styleText The contents of the <code>style</code> tag.
    334      * @return a <code>HtmlPageAttributes</code> (self).
    335      */
    336     public HtmlPageAttributes addStyle(String styleText)
    337     {
    338         this.styles.add(styleText);
    339         return this;
    340     }
    341
    342     /**
    343      * Returns a collection of styles
    344      *
    345      * @return list of String objects containing the contents of style tags
    346      */
    347     public List<String> getStyles()
    348     {
    349         return this.styles;
    350     }
    351
    352     /**
    353      * Set a keywords META tag in the HEAD of the page.
    354      *
    355      * @param keywords A String.
    356      * @return a <code>HtmlPageAttributes</code> (self).
    357      */
    358     public HtmlPageAttributes setKeywords(String keywords)
    359     {
    360         this.metaTags.put("keywords", keywords);
    361         return this;
    362     }
    363
    364     /**
    365      * Sets a HttpEquiv META tag in the HEAD of the page, usage:
    366      * <br><code>setHttpEquiv("refresh", "5; URL=http://localhost/nextpage.html")</code>
    367      * <br><code>setHttpEquiv("Expires", "Tue, 20 Aug 1996 14:25:27 GMT")</code>
    368      *
    369      * @param httpEquiv The value to use for the http-equiv attribute.
    370      * @param content   The text for the content attribute of the meta tag.
    371      * @return a <code>HtmlPageAttributes</code> (self).
    372      */
    373     public HtmlPageAttributes setHttpEquiv(String httpEquiv, String content)
    374     {
    375         this.httpEquivs.put(httpEquiv, content);
    376         return this;
    377     }
    378
    379     /**
    380      * Add a description META tag to the HEAD of the page.
    381      *
    382      * @param description A String.
    383      * @return a <code>HtmlPageAttributes</code> (self).
    384      */
    385     public HtmlPageAttributes setDescription(String description)
    386     {
    387         this.metaTags.put("description", description);
    388         return this;
    389     }
    390
    391     /**
    392      * Set the background image for the BODY tag.
    393      *
    394      * @param url A String.
    395      * @return a <code>HtmlPageAttributes</code> (self).
    396      */
    397     public HtmlPageAttributes setBackground(String url)
    398     {
    399         this.bodyAttributes.put("background", url);
    400         return this;
    401     }
    402
    403     /**
    404      * Set the background color for the BODY tag.  You can use either
    405      * color names or color values (e.g. "white" or "#ffffff" or
    406      * "ffffff").
    407      *
    408      * @param color A String.
    409      * @return a <code>HtmlPageAttributes</code> (self).
    410      */
    411     public HtmlPageAttributes setBgColor(String color)
    412     {
    413         this.bodyAttributes.put("BGCOLOR", color);
    414         return this;
    415     }
    416
    417     /**
    418      * Set the text color for the BODY tag.  You can use either color
    419      * names or color values (e.g. "white" or "#ffffff" or "ffffff").
    420      *
    421      * @param color A String.
    422      * @return a <code>HtmlPageAttributes</code> (self).
    423      */
    424     public HtmlPageAttributes setTextColor(String color)
    425     {
    426         this.bodyAttributes.put("TEXT", color);
    427         return this;
    428     }
    429
    430     /**
    431      * Set the link color for the BODY tag.  You can use either color
    432      * names or color values (e.g. "white" or "#ffffff" or "ffffff").
    433      *
    434      * @param color A String.
    435      * @return a <code>HtmlPageAttributes</code> (self).
    436      */
    437     public HtmlPageAttributes setLinkColor(String color)
    438     {
    439         this.bodyAttributes.put("LINK", color);
    440         return this;
    441     }
    442
    443     /**
    444      * Set the visited link color for the BODY tag.
    445      *
    446      * @param color A String.
    447      * @return a <code>HtmlPageAttributes</code> (self).
    448      */
    449     public HtmlPageAttributes setVlinkColor(String color)
    450     {
    451         this.bodyAttributes.put("VLINK", color);
    452         return this;
    453     }
    454
    455     /**
    456      * Set the active link color for the BODY tag.
    457      *
    458      * @param color A String.
    459      * @return a <code>HtmlPageAttributes</code> (self).
    460      */
    461     public HtmlPageAttributes setAlinkColor(String color)
    462     {
    463         this.bodyAttributes.put("ALINK", color);
    464         return this;
    465     }
    466
    467     /**
    468      * Gets the map of http equiv tags
    469      *
    470      * @return Map of http equiv names to the contents
    471      */
    472     public Map<String, String> getHttpEquivs()
    473     {
    474         return this.httpEquivs;
    475     }
    476
    477     /**
    478      * Gets the map of meta tags
    479      *
    480      * @return Map of http equiv names to the contents
    481      */
    482     public Map<String, String> getMetaTags()
    483     {
    484         return this.metaTags;
    485     }
    486
    487     /**
    488      * A dummy toString method that returns an empty string.
    489      *
    490      * @return An empty String ("").
    491      */
    492     @Override
    493     public String toString()
    494     {
    495         return "";
    496     }
    497
    498     /**
    499      * Helper class to hold data about a &lt;link ... /&gt; html header tag
    500      */
    501     public static class LinkTag
    502     {
    503         private String relation;
    504         private String url;
    505         private String title;
    506         private String media;
    507         private String type;
    508
    509         /**
    510          * Constructor requiring the URL and relation to be set
    511          *
    512          * @param relation Relation type the external link such as prev, next,
    513          *        stylesheet, shortcut icon
    514          * @param url URL of the external link
    515          */
    516         public LinkTag(String relation, String url)
    517         {
    518             setRelation(relation);
    519             setUrl(url);
    520         }
    521
    522         /**
    523          * Gets the content type of the style sheet
    524          *
    525          * @return content type
    526          */
    527         public String getType()
    528         {
    529             return (StringUtils.isEmpty(type) ? "" : type);
    530         }
    531
    532         /**
    533          * Sets the content type of the style sheet
    534          *
    535          * @param type content type
    536          */
    537         public void setType(String type)
    538         {
    539             this.type = type;
    540         }
    541
    542         /**
    543          * @return String representation of the URL
    544          */
    545         public String getUrl()
    546         {
    547             return url;
    548         }
    549
    550         /**
    551          * Sets the URL of the external style sheet
    552          *
    553          * @param url The URL of the stylesheet
    554          */
    555         private void setUrl(String url)
    556         {
    557             this.url = url;
    558         }
    559
    560         /**
    561          * Gets the title of the style sheet
    562          *
    563          * @return title
    564          */
    565         public String getTitle()
    566         {
    567             return (StringUtils.isEmpty(title) ? "" : title);
    568         }
    569
    570         /**
    571          * Sets the title of the stylesheet
    572          *
    573          * @param title
    574          */
    575         public void setTitle(String title)
    576         {
    577             this.title = title;
    578         }
    579
    580         /**
    581          * Gets the media for which the stylesheet should be applied.
    582          *
    583          * @return name of the media
    584          */
    585         public String getMedia()
    586         {
    587             return (StringUtils.isEmpty(media) ? "" : media);
    588         }
    589
    590         /**
    591          * Sets the media for which the stylesheet should be applied.
    592          *
    593          * @param media name of the media
    594          */
    595         public void setMedia(String media)
    596         {
    597             this.media = media;
    598         }
    599
    600         /**
    601          * Gets the relation type of the tag.
    602          *
    603          * @return name of the relation
    604          */
    605         public String getRelation()
    606         {
    607             return (StringUtils.isEmpty(relation) ? "" : relation);
    608         }
    609
    610         /**
    611          * Sets the relation type of the tag.
    612          *
    613          * @param relation name of the relation
    614          */
    615         public void setRelation(String relation)
    616         {
    617             this.relation = relation;
    618         }
    619     }
    620
    621     /**
    622      * Retrieve the default Doctype as configured by the
    623      * TurbineResources.peoperties
    624      * default.doctype.root.element, default.doctype.identifier and
    625      * default.doctype.url properties (defaults are "HTML",
    626      * "-//W3C//DTD HTML 4.01 Transitional//EN" and
    627      * "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd" respectively).
    628      *
    629      * @return the DOCTYPE tag constructed from the properties in
    630      * TurbineResources.properties.
    631      */
    632     public String getDefaultDoctype()
    633     {
    634         if (doctype == null)
    635         {
    636             String tag = defaultHtmlDoctypeRootElement;
    637
    638             if (StringUtils.isEmpty(tag))
    639             {
    640                 doctype = "";
    641             }
    642             else
    643             {
    644                 doctype = buildDoctype(tag, defaultHtmlDoctypeIdentifier, defaultHtmlDoctypeUri);
    645             }
    646         }
    647
    648         return doctype;
    649     }
    650
    651     /**
    652      * Build the doctype element.
    653      *
    654      * @param tag the tag whose DTD is being declared.
    655      * @param identifier the identifier for the doctype declaration.
    656      * @param uri the uri for the doctype declaration.
    657      * @return the doctype.
    658      */
    659     private String buildDoctype(String tag, String identifier, String uri)
    660     {
    661         StringBuilder doctypeBuf = new StringBuilder("<!DOCTYPE ");
    662         doctypeBuf.append(tag);
    663
    664         if (StringUtils.isNotEmpty(identifier))
    665         {
    666             doctypeBuf.append(" PUBLIC \"");
    667             doctypeBuf.append(identifier);
    668             doctypeBuf.append("\" \"");
    669         }
    670         else
    671         {
    672             doctypeBuf.append(" SYSTEM \"");
    673         }
    674
    675         doctypeBuf.append(uri);
    676         doctypeBuf.append("\">");
    677
    678         return doctypeBuf.toString();
    679     }
    680 }