%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
org.apache.commons.jelly.TagSupport |
|
|
1 | /* |
|
2 | * Copyright 2002,2004 The Apache Software Foundation. |
|
3 | * |
|
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
|
5 | * you may not use this file except in compliance with the License. |
|
6 | * You may obtain a copy of the License at |
|
7 | * |
|
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
9 | * |
|
10 | * Unless required by applicable law or agreed to in writing, software |
|
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
13 | * See the License for the specific language governing permissions and |
|
14 | * limitations under the License. |
|
15 | */ |
|
16 | package org.apache.commons.jelly; |
|
17 | ||
18 | import java.io.StringWriter; |
|
19 | import java.util.Arrays; |
|
20 | import java.util.Collection; |
|
21 | import java.util.Iterator; |
|
22 | ||
23 | import org.apache.commons.jelly.util.TagUtils; |
|
24 | ||
25 | /** <p><code>TagSupport</code> an abstract base class which is useful to |
|
26 | * inherit from if developing your own tag.</p> |
|
27 | * |
|
28 | * @author <a href="mailto:jstrachan@apache.org">James Strachan</a> |
|
29 | * @version $Revision: 155420 $ |
|
30 | */ |
|
31 | ||
32 | public abstract class TagSupport implements Tag { |
|
33 | ||
34 | /** the parent of this tag */ |
|
35 | protected Tag parent; |
|
36 | ||
37 | /** the body of the tag */ |
|
38 | protected Script body; |
|
39 | /** The current context */ |
|
40 | ||
41 | protected Boolean shouldTrim; |
|
42 | protected boolean hasTrimmed; |
|
43 | ||
44 | protected JellyContext context; |
|
45 | ||
46 | /** whether xml text should be escaped */ |
|
47 | 10309 | private boolean escapeText = true; |
48 | ||
49 | /** |
|
50 | * Searches up the parent hierarchy from the given tag |
|
51 | * for a Tag of the given type |
|
52 | * |
|
53 | * @param from the tag to start searching from |
|
54 | * @param tagClass the type of the tag to find |
|
55 | * @return the tag of the given type or null if it could not be found |
|
56 | */ |
|
57 | public static Tag findAncestorWithClass(Tag from, Class tagClass) { |
|
58 | // we could implement this as |
|
59 | // return findAncestorWithClass(from,Collections.singleton(tagClass)); |
|
60 | // but this is so simple let's save the object creation for now |
|
61 | 3120 | while (from != null) { |
62 | 2899 | if (tagClass.isInstance(from)) { |
63 | 2444 | return from; |
64 | } |
|
65 | 455 | from = from.getParent(); |
66 | 455 | } |
67 | 221 | return null; |
68 | } |
|
69 | ||
70 | /** |
|
71 | * Searches up the parent hierarchy from the given tag |
|
72 | * for a Tag matching one or more of given types. |
|
73 | * |
|
74 | * @param from the tag to start searching from |
|
75 | * @param tagClasses a Collection of Class types that might match |
|
76 | * @return the tag of the given type or null if it could not be found |
|
77 | */ |
|
78 | public static Tag findAncestorWithClass(Tag from, Collection tagClasses) { |
|
79 | 0 | while (from != null) { |
80 | 0 | for(Iterator iter = tagClasses.iterator();iter.hasNext();) { |
81 | 0 | Class klass = (Class)(iter.next()); |
82 | 0 | if (klass.isInstance(from)) { |
83 | 0 | return from; |
84 | } |
|
85 | 0 | } |
86 | 0 | from = from.getParent(); |
87 | 0 | } |
88 | 0 | return null; |
89 | } |
|
90 | ||
91 | /** |
|
92 | * Searches up the parent hierarchy from the given tag |
|
93 | * for a Tag matching one or more of given types. |
|
94 | * |
|
95 | * @param from the tag to start searching from |
|
96 | * @param tagClasses an array of types that might match |
|
97 | * @return the tag of the given type or null if it could not be found |
|
98 | * @see #findAncestorWithClass(Tag,Collection) |
|
99 | */ |
|
100 | public static Tag findAncestorWithClass(Tag from, Class[] tagClasses) { |
|
101 | 0 | return findAncestorWithClass(from,Arrays.asList(tagClasses)); |
102 | } |
|
103 | ||
104 | 10309 | public TagSupport() { |
105 | 10309 | } |
106 | ||
107 | 0 | public TagSupport(boolean shouldTrim) { |
108 | 0 | setTrim( shouldTrim ); |
109 | 0 | } |
110 | ||
111 | /** |
|
112 | * Sets whether whitespace inside this tag should be trimmed or not. |
|
113 | * Defaults to true so whitespace is trimmed |
|
114 | */ |
|
115 | public void setTrim(boolean shouldTrim) { |
|
116 | 65 | if ( shouldTrim ) { |
117 | 39 | this.shouldTrim = Boolean.TRUE; |
118 | 39 | } |
119 | else { |
|
120 | 26 | this.shouldTrim = Boolean.FALSE; |
121 | } |
|
122 | 65 | } |
123 | ||
124 | public boolean isTrim() { |
|
125 | 9230 | if ( this.shouldTrim == null ) { |
126 | 6487 | Tag parent = getParent(); |
127 | 6487 | if ( parent == null ) { |
128 | 2392 | return true; |
129 | } |
|
130 | else { |
|
131 | 4095 | if ( parent instanceof TagSupport ) { |
132 | 4095 | TagSupport parentSupport = (TagSupport) parent; |
133 | ||
134 | 4095 | this.shouldTrim = ( parentSupport.isTrim() ? Boolean.TRUE : Boolean.FALSE ); |
135 | 4095 | } |
136 | else { |
|
137 | 0 | this.shouldTrim = Boolean.TRUE; |
138 | } |
|
139 | } |
|
140 | } |
|
141 | ||
142 | 6838 | return this.shouldTrim.booleanValue(); |
143 | } |
|
144 | ||
145 | /** @return the parent of this tag */ |
|
146 | public Tag getParent() { |
|
147 | 9607 | return parent; |
148 | } |
|
149 | ||
150 | /** Sets the parent of this tag */ |
|
151 | public void setParent(Tag parent) { |
|
152 | 9854 | this.parent = parent; |
153 | 9854 | } |
154 | ||
155 | /** @return the body of the tag */ |
|
156 | public Script getBody() { |
|
157 | 6890 | if (! hasTrimmed) { |
158 | 5135 | hasTrimmed = true; |
159 | 5135 | if (isTrim()) { |
160 | 5109 | trimBody(); |
161 | } |
|
162 | } |
|
163 | 6890 | return body; |
164 | } |
|
165 | ||
166 | /** Sets the body of the tag */ |
|
167 | public void setBody(Script body) { |
|
168 | 9854 | this.body = body; |
169 | 9854 | this.hasTrimmed = false; |
170 | 9854 | } |
171 | ||
172 | /** @return the context in which the tag will be run */ |
|
173 | public JellyContext getContext() { |
|
174 | 91 | return context; |
175 | } |
|
176 | ||
177 | /** Sets the context in which the tag will be run */ |
|
178 | public void setContext(JellyContext context) throws JellyTagException { |
|
179 | 12571 | this.context = context; |
180 | 12571 | } |
181 | ||
182 | /** |
|
183 | * Invokes the body of this tag using the given output |
|
184 | */ |
|
185 | public void invokeBody(XMLOutput output) throws JellyTagException { |
|
186 | 6617 | getBody().run(context, output); |
187 | 6071 | } |
188 | ||
189 | // Implementation methods |
|
190 | //------------------------------------------------------------------------- |
|
191 | /** |
|
192 | * Searches up the parent hierarchy for a Tag of the given type. |
|
193 | * @return the tag of the given type or null if it could not be found |
|
194 | */ |
|
195 | protected Tag findAncestorWithClass(Class parentClass) { |
|
196 | 2665 | return findAncestorWithClass(getParent(), parentClass); |
197 | } |
|
198 | ||
199 | /** |
|
200 | * Searches up the parent hierarchy for a Tag of one of the given types. |
|
201 | * @return the tag of the given type or null if it could not be found |
|
202 | * @see #findAncestorWithClass(Collection) |
|
203 | */ |
|
204 | protected Tag findAncestorWithClass(Class[] parentClasses) { |
|
205 | 0 | return findAncestorWithClass(getParent(),parentClasses); |
206 | } |
|
207 | ||
208 | /** |
|
209 | * Searches up the parent hierarchy for a Tag of one of the given types. |
|
210 | * @return the tag of the given type or null if it could not be found |
|
211 | */ |
|
212 | protected Tag findAncestorWithClass(Collection parentClasses) { |
|
213 | 0 | return findAncestorWithClass(getParent(),parentClasses); |
214 | } |
|
215 | ||
216 | /** |
|
217 | * Executes the body of the tag and returns the result as a String. |
|
218 | * |
|
219 | * @return the text evaluation of the body |
|
220 | */ |
|
221 | protected String getBodyText() throws JellyTagException { |
|
222 | 416 | return getBodyText(escapeText); |
223 | } |
|
224 | ||
225 | /** |
|
226 | * Executes the body of the tag and returns the result as a String. |
|
227 | * |
|
228 | * @param shouldEscape Signal if the text should be escaped. |
|
229 | * |
|
230 | * @return the text evaluation of the body |
|
231 | */ |
|
232 | protected String getBodyText(boolean shouldEscape) throws JellyTagException { |
|
233 | 572 | StringWriter writer = new StringWriter(); |
234 | 572 | invokeBody(XMLOutput.createXMLOutput(writer, shouldEscape)); |
235 | 572 | return writer.toString(); |
236 | } |
|
237 | ||
238 | ||
239 | /** |
|
240 | * Find all text nodes inside the top level of this body and |
|
241 | * if they are just whitespace then remove them |
|
242 | */ |
|
243 | protected void trimBody() { |
|
244 | 5109 | TagUtils.trimScript(body); |
245 | 5109 | } |
246 | ||
247 | /** |
|
248 | * Returns whether the body of this tag will be escaped or not. |
|
249 | */ |
|
250 | public boolean isEscapeText() { |
|
251 | 78 | return escapeText; |
252 | } |
|
253 | ||
254 | /** |
|
255 | * Sets whether the body of the tag should be escaped as text (so that < and > are |
|
256 | * escaped as &lt; and &gt;), which is the default or leave the text as XML. |
|
257 | */ |
|
258 | public void setEscapeText(boolean escapeText) { |
|
259 | 26 | this.escapeText = escapeText; |
260 | 26 | } |
261 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |