KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > uitags > tag > AbstractUiTag


1 package net.sf.uitags.tag;
2
3 import java.io.IOException JavaDoc;
4 import java.util.LinkedList JavaDoc;
5 import java.util.List JavaDoc;
6 import java.util.ListIterator JavaDoc;
7
8 import javax.servlet.jsp.JspException JavaDoc;
9 import javax.servlet.jsp.PageContext JavaDoc;
10 import javax.servlet.jsp.tagext.BodyTagSupport JavaDoc;
11
12 import net.sf.uitags.tagutil.validation.DeferredValidationException;
13
14 /**
15  * Parent of all tag handlers in uitags.
16  *
17  * @author jonni
18  */

19 public abstract class AbstractUiTag extends BodyTagSupport JavaDoc {
20   private static final String JavaDoc PARENT_LIST_KEY =
21       AbstractUiTag.class.getName() + "parentList";
22
23   private List JavaDoc visibleParentList;
24
25   public void setPageContext(PageContext JavaDoc pageContext) {
26     super.setPageContext(pageContext);
27
28     this.visibleParentList = (List JavaDoc) this.pageContext.getAttribute(
29         PARENT_LIST_KEY, PageContext.REQUEST_SCOPE);
30     if (this.visibleParentList == null) {
31       this.visibleParentList = new LinkedList JavaDoc();
32       this.pageContext.setAttribute(PARENT_LIST_KEY,
33           this.visibleParentList, PageContext.REQUEST_SCOPE);
34     }
35   }
36
37   /**
38    * Returns the tag name (the custom tag name used in JSP) of this tag handler.
39    *
40    * @return the tag name (the custom tag name used in JSP) of this tag handler
41    */

42   public String JavaDoc getTagName() {
43     return resolveTagNameForClass(this.getClass());
44   }
45
46   /**
47    * Given a tag handler <code>Class</code>, returns its <i>tag name</i>
48    * (the custom tag name used in JSP).
49    * This method assumes that tag handler classes are named according to its
50    * tag name, suffixed with the word "Tag".
51    *
52    * @param tagClass the tag handler class whose tag name is to be resolved
53    * @return the tag name. If the tag handler class name doesn't conform to
54    * the convention, returns the unqualified name of the supplied class.
55    */

56   private String JavaDoc resolveTagNameForClass(Class JavaDoc tagClass) {
57     String JavaDoc className = getUnqualifiedClassName(tagClass);
58     if (className.endsWith("Tag")) {
59       String JavaDoc firstCharInLowerCase = className.substring(0, 1).toLowerCase();
60       return firstCharInLowerCase + omitFirstCharAndLastThreeChars(className);
61     }
62
63     return className;
64   }
65
66   private String JavaDoc getUnqualifiedClassName(Class JavaDoc tagClass) {
67     String JavaDoc qualifiedClassName = tagClass.getName();
68     int cutOffPosition = qualifiedClassName.lastIndexOf('.');
69     return qualifiedClassName.substring(cutOffPosition + 1);
70   }
71
72   private String JavaDoc omitFirstCharAndLastThreeChars(String JavaDoc target) {
73     return target.substring(1, target.length() - 3);
74   }
75
76   /**
77    * Puts this tag handler into the request scope, allowing nested children tags
78    * to access it. This mechanism is used instead of the built-in
79    * <code>TagSupport.findAncestorWithClass()</code> to allow tags
80    * cooperate eventhough they are wrapped in different tag files.
81    * A side effect of this mechanism is that an instance of a tag cannot
82    * be nested under another instance of the same tag.
83    * <p>
84    * Typically a tag that wants to expose itself to the children calls
85    * this method in <code>doStartTag()</code>. The clean-up method
86    * ({@link #makeInvisibleFromChildren()}) is then called in
87    * <code>doEndTag()</code> (must not forget to call this clean-up method).
88    * Once the parent class has made itself visible to the children,
89    * the children can call {@link #findParent(Class)} to find the parent.
90    *
91    * @throws DeferredValidationException if the attribute already exists in
92    * the request scope, which almost always
93    * means that this tag has been nested
94    * under another instance of the same tag
95    */

96   protected final void makeVisibleToChildren() {
97     this.visibleParentList.add(this);
98   }
99
100   /**
101    * See {@link #makeVisibleToChildren()}.
102    */

103   protected final void makeInvisibleFromChildren() {
104     this.visibleParentList.remove(this);
105   }
106
107   /**
108    * See {@link #makeVisibleToChildren()}.
109    *
110    * @param tagClass the class of the parent tag handler to find
111    * @return the parent tag handler
112    * @throws DeferredValidationException if the parent tag handler was not found
113    */

114   protected final AbstractUiTag findParent(Class JavaDoc tagClass) {
115     // traverse in reverse direction because the closest parent is in the
116
// newest entry
117
int lastIndex = this.visibleParentList.size();
118     for (ListIterator JavaDoc iter = this.visibleParentList.listIterator(lastIndex);
119         iter.hasPrevious(); ) {
120       Object JavaDoc potentialParent = iter.previous();
121       if (tagClass.isInstance(potentialParent)) {
122         return (AbstractUiTag) potentialParent;
123       }
124     }
125
126     throw new DeferredValidationException("The parent tag '" +
127         resolveTagNameForClass(tagClass) + "' cannot be found.");
128   }
129
130   /**
131    * Convenience method for printing to the output stream that throws
132    * <code>JspException</code> instead of <code>IOException</code>.
133    *
134    * @param toPrint the value to print
135    * @throws JspException wrapping the original <code>IOException</code>
136    */

137   protected final void println(Object JavaDoc toPrint) throws JspException JavaDoc {
138     try {
139       this.pageContext.getOut().println(toPrint);
140     }
141     catch (IOException JavaDoc e) {
142       throw new JspException JavaDoc(e);
143     }
144   }
145 }
146
Popular Tags