KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > tags > javascript > ScriptContainer


1 /*
2  * Copyright 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  * $Header:$
17  */

18 package org.apache.beehive.netui.tags.javascript;
19
20 import org.apache.beehive.netui.util.internal.InternalStringBuilder;
21
22 import org.apache.beehive.netui.tags.AbstractClassicTag;
23 import org.apache.beehive.netui.tags.TagConfig;
24 import org.apache.beehive.netui.tags.RequestUtils;
25 import org.apache.beehive.netui.tags.rendering.AbstractRenderAppender;
26 import org.apache.beehive.netui.tags.rendering.ScriptTag;
27 import org.apache.beehive.netui.tags.rendering.TagRenderingBase;
28 import org.apache.beehive.netui.tags.rendering.WriteRenderAppender;
29 import org.apache.beehive.netui.pageflow.scoping.ScopedRequest;
30 import org.apache.beehive.netui.pageflow.scoping.ScopedServletUtils;
31
32 import javax.servlet.http.HttpServletRequest JavaDoc;
33 import javax.servlet.jsp.JspException JavaDoc;
34 import javax.servlet.jsp.tagext.SimpleTagSupport JavaDoc;
35 import javax.servlet.jsp.tagext.Tag JavaDoc;
36 import javax.servlet.ServletRequest JavaDoc;
37 import java.util.ArrayList JavaDoc;
38 import java.util.HashMap JavaDoc;
39 import java.util.Iterator JavaDoc;
40
41 /**
42  * Acts as a container that will bundle up JavaScript created by other NetUI tags,
43  * and output it within a single <script> tag. This is especially needed for
44  * Portal web applications, because they often cannot rely on having
45  * <html> ... </html> tags to provide a default container. In a portlet,
46  * some JSP pages might be included into other JSP pages. Having redundant
47  * <html> ... </html> tags in the rendered portlet JSP can result in display
48  * problems for some browsers. However, omitting the <html> tag (and the
49  * container it provides) can result in cluttered code, especially where Javascript
50  * appears in the file. To solve this issue, Beehive provides the
51  * <netui:scriptContainer> tag.
52  *
53  * @jsptagref.tagdescription Acts as a container that will bundle up JavaScript created by other <netui...> tags,
54  * and outputs it within a single <script> tag. This is especially useful for
55  * Portal web applications, because they often cannot rely on having
56  * <html> ... </html> tags to provide a default container. In a Portlet,
57  * some JSP pages might be included in other JSP pages. Having redundant
58  * <html> ... </html> tags in the rendered Portlet JSP can result in display
59  * problems for some browsers. On the other hand, omitting the <html> tag (and the
60  * container it provides) can result in cluttered code, especially where JavaScript
61  * appears in the file. To solve this issue, Beehive provides the
62  * <netui:scriptContainer> tag.
63  *
64  * <p>The &lt;netui:scriptContainer> ... &lt;/netui:scriptContainer> tag set should
65  * enclose those &lt;netui:...> tags that you want included in the script container.
66  * The first &lt;netui:scriptContainer> tag should appear after the JSP's &lt;body> tag.
67  * The closing &lt;/netui:scriptContainer> tag should appear before the JSP's &lt;/body> tag.
68  * @example The &lt;netui:scriptContainer> ... &lt;/netui:scriptContainer tag set simply
69  * encloses other NetUI tags that you want to belong to that script container.
70  * The first &lt;netui:scriptContainer> tag should appear after the JSP's &lt;body> tag.
71  * The closing &lt;/netui:scriptContainer> tag should appear before the JSP's &lt;/body> tag.
72  * @netui:tag name="scriptContainer" description="ScriptContainers defines a container that will gather all of the JavaScript of their children and output it in a single &lt;script> tag. In addition, they providing scoping of tagIds."
73  */

74 public class ScriptContainer extends AbstractClassicTag
75         implements IScriptReporter
76 {
77     public final static String JavaDoc SCOPE_ID = "netui:scopeId";
78
79     private String JavaDoc _idScope = null;
80     private ArrayList JavaDoc/*<String>*/ _funcBlocks;
81     private ArrayList JavaDoc/*<String>*/ _codeBefore;
82     private ArrayList JavaDoc/*<String>*/ _codeAfter;
83     private HashMap JavaDoc/*<String, String>*/ _idMap;
84     private HashMap JavaDoc/*<String, String>*/ _idToNameMap;
85     private boolean _genScope = false;
86     private boolean _writeScript = false;
87     private boolean _writeId = false;
88
89     /**
90      * Returns the name of the Tag.
91      */

92     public String JavaDoc getTagName()
93     {
94         return "ScriptContainer";
95     }
96
97     /////////////////////////// ScriptReporter Interface ////////////////////////////
98

99     /**
100      * This method will add Script as a function.
101      * @param placement
102      * @param script the text of the function. This value must not be null.
103      */

104     public void addScriptFunction(ScriptPlacement placement, String JavaDoc script)
105     {
106         assert (script != null) : "The paramter 'script' must not be null";
107         IScriptReporter sr = getParentScriptReporter();
108         if (sr != null) {
109             sr.addScriptFunction(placement, script);
110             return;
111         }
112
113         // get the list of function blocks and add this script to it.
114
if (placement == null || placement == ScriptPlacement.PLACE_INFRAMEWORK) {
115             if (_funcBlocks == null) {
116                 _funcBlocks = new ArrayList JavaDoc/*<String>*/();
117             }
118             assert (_funcBlocks != null) : "_funcBlocks should not be null";
119             _funcBlocks.add(script);
120         }
121         else if (placement == ScriptPlacement.PLACE_BEFORE) {
122             if (_codeBefore == null)
123                 _codeBefore = new ArrayList JavaDoc/*<String>*/();
124             _codeBefore.add(script);
125         }
126         else if (placement == ScriptPlacement.PLACE_AFTER) {
127             if (_codeAfter == null)
128                 _codeAfter = new ArrayList JavaDoc/*<String>*/();
129             _codeAfter.add(script);
130         }
131         else {
132             assert(false) : "unsupported placement:" + placement;
133         }
134     }
135
136     /**
137      * Adds a tagID and tagName to the Html's getId javascript function.
138      * @param tagId the id of a child tag.
139      * @param tagName the name of a child tag.
140      */

141     public void addLegacyTagIdMappings(String JavaDoc tagId, String JavaDoc tagName)
142     {
143         assert (tagId != null) : "The parameter 'tagId' must not be null";
144         assert (tagName != null) : "The parameter 'tagName' must not be null";
145
146         if (_idMap == null) {
147             _idMap = new HashMap JavaDoc/*<String, String>*/();
148         }
149
150         assert (_idMap != null) : "_idMap should not be null";
151         _idMap.put(tagId, tagName);
152     }
153
154     /**
155      * This will add the mapping between the tagId and the real name to the NameMap hashmap.
156      * @param tagId
157      * @param realId
158      * @param realName
159      */

160     public void addTagIdMappings(String JavaDoc tagId, String JavaDoc realId, String JavaDoc realName)
161     {
162         assert (tagId != null) : "The parameter 'tagId' must not be null";
163         assert (realId != null) : "The parameter 'realId' must not be null";
164
165         _writeId = true;
166
167         if (realName != null) {
168             if (_idToNameMap == null)
169                 _idToNameMap = new HashMap JavaDoc/*<String, String>*/();
170             _idToNameMap.put(tagId, realName);
171         }
172     }
173
174     /**
175      * This method will output all of the Script associated with the script reporter.
176      * @param sb The script is written into the provided InternalStringBuilder. This value must not be null.
177      */

178     public void writeScript(AbstractRenderAppender sb)
179     {
180         assert(sb != null) : "The paramter 'sb' must not be null;";
181         if (_writeScript)
182             return;
183
184         _writeScript = true;
185         IScriptReporter sr = getParentScriptReporter();
186         if (sr != null) {
187             sr.writeScript(sb);
188             return;
189         }
190
191         writeBeforeBlocks(sb);
192         writeFrameworkScript(sb);
193         writeAfterBlocks(sb);
194     }
195
196     /////////////////////////// Attributes ////////////////////////////
197

198     /**
199      * Set the idScope associated with the code methods
200      * @jsptagref.attributedescription The id that is associated with the script methods.
201      * @jsptagref.databindable false
202      * @jsptagref.attributesyntaxvalue <i>string_scopeId</i>
203      * @netui:attribute required="false" rtexprvalue="true"
204      * description="The id that is associated with the script methods."
205      */

206     public void setIdScope(String JavaDoc idScope)
207     {
208         _idScope = idScope;
209     }
210
211     /**
212      * return the scopeId associated with the ScriptContainer
213      */

214     public String JavaDoc getIdScope()
215     {
216         return _idScope;
217
218     }
219
220     /**
221      * If true generate a scope id for this script container. If this is set to true
222      * and a scopeId is also set, the scopeId set will be written.
223      * @jsptagref.attributedescription Automatically generate a scopeId for this script container.
224      * @jsptagref.databindable true
225      * @jsptagref.attributesyntaxvalue <i>string_generateScopeId</i>
226      * @netui:attribute required="false" rtexprvalue="true"
227      * description="Automatically generate a ScopeId."
228      */

229     public void setGenerateIdScope(boolean genScopeValue)
230     {
231         _genScope = genScopeValue;
232     }
233     ///////////////////////////////// Tag Methods ////////////////////////////////////////
234

235     public int doStartTag()
236             throws JspException JavaDoc
237     {
238         String JavaDoc scope = getRealIdScope();
239         pushIdScope();
240
241         WriteRenderAppender writer = new WriteRenderAppender(pageContext);
242         writeBeforeBlocks(writer);
243
244         // if there is a scopeId, then we need to create a div to contains everything
245
if (_idScope != null) {
246             write("<div");
247             write(" netui:idScope=\"");
248             write(scope);
249             write("\" ");
250             write(">");
251         }
252
253         return EVAL_BODY_INCLUDE;
254     }
255
256     /**
257      * Write out the body content and report any errors that occured.
258      * @throws JspException if a JSP exception has occurred
259      */

260     public int doEndTag()
261             throws JspException JavaDoc
262     {
263
264         popIdScope();
265
266         // writeout the script.
267
WriteRenderAppender writer = new WriteRenderAppender(pageContext);
268
269         // if we wrote out the scopeId then we end it.
270
if (_idScope != null) {
271             writer.append("</div>");
272         }
273
274         writeFrameworkScript(writer);
275         writeAfterBlocks(writer);
276         localRelease();
277         return EVAL_PAGE;
278     }
279
280     /////////////////////////////////// Protected Support ////////////////////////////////////
281

282     protected void pushIdScope()
283     {
284         if (_idScope != null) {
285             HttpServletRequest JavaDoc req = (HttpServletRequest JavaDoc) pageContext.getRequest();
286             ArrayList JavaDoc/*<String>*/ list = (ArrayList JavaDoc/*<String>*/) RequestUtils.getOuterAttribute(req,SCOPE_ID);
287             if (list == null) {
288                 list = new ArrayList JavaDoc/*<String>*/();
289                 RequestUtils.setOuterAttribute(req,SCOPE_ID,list);
290             }
291             list.add(_idScope);
292
293         }
294     }
295
296     protected void popIdScope()
297     {
298         if (_idScope != null) {
299             HttpServletRequest JavaDoc req = (HttpServletRequest JavaDoc) pageContext.getRequest();
300             ArrayList JavaDoc/*<String>*/ list = (ArrayList JavaDoc/*<String>*/) RequestUtils.getOuterAttribute(req,SCOPE_ID);
301             assert(list != null);
302             list.remove(list.size() -1);
303         }
304     }
305
306     /**
307      * This method will return the real scope id for the script container.
308      * @return String
309      */

310     protected String JavaDoc getRealIdScope()
311     {
312         ServletRequest JavaDoc request = pageContext.getRequest();
313         
314         // default to the set idScope.
315
String JavaDoc idScope = _idScope;
316
317         // if there isn't a set idScope and generate scope is on, generate the scope id.
318
if (_idScope == null && _genScope) {
319             int id = getNextId(request);
320             idScope = "n" + Integer.toString(id);
321             _idScope = idScope;
322         }
323         
324         // if there's still no idScope and we're in a ScopedRequest, use the scope-key from the request.
325
if (_idScope == null) {
326             ScopedRequest scopedRequest = ScopedServletUtils.unwrapRequest(request);
327             if (scopedRequest != null) {
328                 _idScope = scopedRequest.getScopeKey().toString();
329                 idScope = _idScope;
330             }
331         }
332         
333         return idScope;
334     }
335
336     protected void writeBeforeBlocks(AbstractRenderAppender sb)
337     {
338         if (_codeBefore == null || _codeBefore.size() == 0)
339             return;
340
341         InternalStringBuilder s = new InternalStringBuilder(256);
342         for (Iterator JavaDoc i = _codeBefore.iterator(); i.hasNext();)
343         {
344             String JavaDoc code = ( String JavaDoc ) i.next();
345             s.append(code);
346             s.append("\n");
347         }
348         ScriptRequestState.writeScriptBlock(pageContext.getRequest(), sb, s.toString());
349
350     }
351
352     protected void writeAfterBlocks(AbstractRenderAppender sb)
353     {
354         if (_codeAfter == null || _codeAfter.size() == 0)
355             return;
356
357         InternalStringBuilder s = new InternalStringBuilder(256);
358         for (Iterator JavaDoc i = _codeAfter.iterator(); i.hasNext();)
359         {
360             String JavaDoc code = ( String JavaDoc ) i.next();
361             s.append(code);
362             s.append("\n");
363         }
364         ScriptRequestState.writeScriptBlock(pageContext.getRequest(), sb, s.toString());
365     }
366
367     /**
368      * This will write the script block.
369      */

370     protected void writeFrameworkScript(AbstractRenderAppender sb)
371     {
372         boolean script = false;
373         ScriptRequestState jsu = ScriptRequestState.getScriptRequestState((HttpServletRequest JavaDoc) pageContext.getRequest());
374
375         boolean writeLegacy = false;
376         boolean writeName = false;
377         String JavaDoc val;
378
379         // if we are writing out legacy JavaScript support output the idMap
380
if (TagConfig.isLegacyJavaScript()) {
381             val = processIdMap(_idMap, "idMappingEntry", _idScope);
382             if (val != null) {
383                 writeIdMap(this, "idMappingTable", val);
384                 writeLegacy = true;
385             }
386         }
387
388         // if we are writing out default JavaScript support we create the name map
389
if (TagConfig.isDefaultJavaScript()) {
390             String JavaDoc idScope = getJavaScriptId();
391             if (idScope.equals(""))
392                 idScope = null;
393             val = processIdMap(_idToNameMap, "tagIdNameMappingEntry", idScope);
394             if (val != null) {
395                 writeIdMap(this, "tagIdNameMappingTable", val);
396                 writeName = true;
397             }
398         }
399
400         if (writeLegacy || _writeId || writeName)
401             jsu.writeNetuiNameFunctions(this, writeLegacy, _writeId, writeName);
402
403         ScriptTag.State state = null;
404         ScriptTag br = null;
405         if (_funcBlocks != null && _funcBlocks.size() > 0) {
406             if (!script) {
407                 state = new ScriptTag.State();
408                 state.suppressComments = false;
409                 br = (ScriptTag) TagRenderingBase.Factory.getRendering(TagRenderingBase.SCRIPT_TAG, pageContext.getRequest());
410                 br.doStartTag(sb, state);
411                 script = true;
412             }
413             String JavaDoc s = ScriptRequestState.getString("functionComment", null);
414             sb.append(s);
415             int cnt = _funcBlocks.size();
416             for (int i = 0; i < cnt; i++) {
417                 sb.append((String JavaDoc)_funcBlocks.get(i));
418                 if (i != cnt - 1) {
419                     sb.append("\n");
420                 }
421             }
422         }
423
424         if (script) {
425             assert(br != null);
426             br.doEndTag(sb, false);
427         }
428     }
429
430     /////////////////////////////////// Private Support ////////////////////////////////////
431

432     /**
433      * @param scriptRepoter
434      * @param mapObj
435      * @param entries
436      * @return
437      */

438     private String JavaDoc writeIdMap(IScriptReporter scriptRepoter, String JavaDoc mapObj, String JavaDoc entries)
439     {
440         String JavaDoc s = ScriptRequestState.getString(mapObj, new Object JavaDoc[]{entries});
441         if (scriptRepoter != null) {
442             scriptRepoter.addScriptFunction(null, s);
443             return null;
444         }
445         return s;
446     }
447
448
449     private String JavaDoc getJavaScriptId()
450     {
451         String JavaDoc idScope = "";
452         Tag tag = this;
453         while (tag != null) {
454             if (tag instanceof ScriptContainer) {
455                 String JavaDoc sid = ((ScriptContainer) tag).getIdScope();
456                 if (sid != null) {
457                     idScope = sid + "_" + idScope;
458                 }
459             }
460             tag = tag.getParent();
461         }
462         return idScope;
463     }
464
465     private String JavaDoc processIdMap(HashMap JavaDoc/*<String, String>*/ map, String JavaDoc mapEntry, String JavaDoc idScope)
466     {
467         // if no map or empty then return
468
if (map == null || map.size() == 0)
469             return null;
470
471         InternalStringBuilder results = new InternalStringBuilder(128);
472         Iterator JavaDoc/*<String>*/ ids = map.keySet().iterator();
473         while (ids.hasNext()) {
474             String JavaDoc id = (String JavaDoc) ids.next();
475             String JavaDoc value = (String JavaDoc) map.get(id);
476             if (idScope != null)
477                 id = idScope + "__" + id;
478             String JavaDoc entry = ScriptRequestState.getString(mapEntry, new Object JavaDoc[]{id, value});
479             results.append(entry);
480         }
481         return results.toString();
482     }
483
484     /////////////////////////////////// Local Release ////////////////////////////////////
485
private IScriptReporter getParentScriptReporter()
486     {
487         Tag parent = getParent();
488         if (parent == null)
489             return null;
490         IScriptReporter sr = (IScriptReporter) SimpleTagSupport.findAncestorWithClass(parent, IScriptReporter.class);
491         return sr;
492     }
493
494     /**
495      * Release any acquired resources.
496      */

497     protected void localRelease()
498     {
499         super.localRelease();
500
501         _idScope = null;
502         _writeScript = false;
503         _genScope = false;
504         _writeId = false;
505
506         if (_funcBlocks != null)
507             _funcBlocks.clear();
508         if (_codeBefore != null)
509             _codeBefore.clear();
510         if (_codeAfter != null)
511             _codeAfter.clear();
512
513         if (_idMap != null)
514             _idMap.clear();
515         if (_idToNameMap != null)
516             _idToNameMap.clear();
517     }
518
519 }
520
Popular Tags