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