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