KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > barracuda > core > comp > renderer > TemplateHelper


1 /*
2  * Copyright (C) 2003 Christian Cryder [christianc@granitepeaks.com]
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * $Id: TemplateHelper.java,v 1.35 2004/02/01 05:16:27 christianc Exp $
19  */

20 package org.enhydra.barracuda.core.comp.renderer;
21
22 import java.util.*;
23 import org.w3c.dom.*;
24 //import org.w3c.dom.html.*;
25

26 import org.apache.log4j.*;
27
28 import org.enhydra.barracuda.plankton.*;
29 import org.enhydra.barracuda.core.comp.*;
30 import org.enhydra.barracuda.core.util.dom.*;
31 import org.enhydra.barracuda.core.view.*;
32
33 /**
34  * Provide a default encapsulation of the template rendering stuff.
35  */

36 public class TemplateHelper {
37
38     protected static final Logger logger = Logger.getLogger(TemplateHelper.class.getName());
39
40     final String JavaDoc s = "";
41
42     protected Renderer masterRenderer = null;
43     protected BTemplate btemplate = null;
44     protected Stack itStack = null;
45
46     static boolean showDebug = false;
47
48     public TemplateHelper(Renderer imasterRenderer) {
49         masterRenderer = imasterRenderer;
50     }
51
52     /**
53      * This renders a BTemplate component into the specified TemplateView,
54      * for the given ViewCOntext
55      */

56     public void render(BTemplate comp, TemplateView view, ViewContext vc) throws RenderException {
57         //csc_091401.1_start - the purpose of this mod is to make it possible to process
58
//directives in the root node of the template view. We can only do this for
59
//BTemplates that are step children because in this case they will only be rendered
60
//once and thus its not a big deal to go replacing the root node
61
/*
62         //start by removing all the children from the target node
63         btemplate = (BTemplate) comp;
64         Node node = view.getNode();
65         while (node.hasChildNodes()) {
66             node.removeChild(node.getFirstChild());
67         }
68         
69         //now we're going to iterate through the master template and
70         //add children back in, applying template directives as we go
71         Node masterTemplate = view.getMasterTemplate();
72         copyChildNodes(masterTemplate, node, view, vc, 0);
73 */

74         //get a reference to the template and the root node
75
btemplate = (BTemplate) comp;
76         Node node = view.getNode();
77         Node origNode = node;
78         Node origParent = origNode.getParentNode();
79         Node newNode = null;
80     
81         //if we're dealing with a step child, we know that this component/view will only be
82
//rendered once. As such, we can actually replace the node that the component is
83
//bound to with one that's been parsed for directives (allowing us to effectively
84
//parse the root node for directives as well). We can't do this with permanent views
85
//since the component has established a view on the node so we can't just go changing
86
//that node
87
if (comp.isStepChild()) {
88 //System.out.println ("processing stepchild @"+Integer.toHexString(comp.hashCode()));
89
newNode = getNode(node, view, vc, 0);
90             if (newNode!=null) node = newNode;
91         }
92         
93         //now, if we're NOT dealing with a step child, go ahead and do this. If
94
//we ARE dealing with a step child, we want to skip this step (or else it'll
95
//end up processing parts of the template twice)
96
if (!comp.isStepChild()) { //csc_032202.1 - added
97

98             //start by removing all the children from the target node
99
while (node.hasChildNodes()) {
100                 node.removeChild(node.getFirstChild());
101             }
102             
103             //now iterate through the master template and add children back in,
104
//applying template directives as we go.
105
Node masterTemplate = view.getMasterTemplate();
106             copyChildNodes(masterTemplate, node, view, vc, 0);
107         }
108         
109         //now, if we actually are using newNode, then we need to replace the
110
//origNode with it once we're done
111
if (newNode!=null) {
112 //System.out.println ("or:"+origNode+" p1:"+origParent+" p2:"+origNode.getParentNode()+" nn:"+newNode);
113
origNode.getParentNode().replaceChild(newNode, origNode);
114         }
115         //csc_091401.1_end
116
}
117
118     /**
119      * Copy nodes from the template to the target
120      */

121     protected void copyChildNodes(Node templateNode, Node targetNode, TemplateView view, ViewContext vc, int depth) throws RenderException {
122
123         //iterate through all the template node's children, copying them across
124
Node child = templateNode.getFirstChild();
125         Node newChild = null;
126         while (child!=null) {
127             //get the new child
128
newChild = getNode(child, view, vc, depth+1);
129             
130             //if we're iterating and we need to loop, reset to the starting
131
//point for the current iteration loop
132
if (itStack!=null) {
133                 IteratorContext itcontext = (IteratorContext) itStack.peek();
134                 if (itcontext.NEXTLOOP) {
135                     child = itcontext.startNode;
136                     itcontext.NEXTLOOP = false;
137                     continue;
138                 } else if (itcontext.EOF) {
139                     //Only set it equal to the endNode if the endNode is not null;
140
//otherwise, set it equal to the next sibling.
141
if (itcontext.endNode!=null) child = itcontext.endNode;
142                     else child = child.getNextSibling();
143                     continue;
144                 }
145             }
146             
147             //add the newchild in
148
if (newChild!=null) {
149 //if (newChild instanceof Element) System.out.println("Adding newChild:"+newChild+"("+((Element) newChild).getAttribute("name")+")"+" to parent");
150
//else System.out.println("Adding newChild:"+newChild+" to parent");
151
masterRenderer.addChildToParent(targetNode, newChild);
152             }
153     
154             //get the next child
155
child = child.getNextSibling();
156         }
157     }
158
159     /**
160      * Given the specified templateNode, return the new Node to be rendered into the view
161      */

162     protected Node getNode(Node templateNode, TemplateView view, ViewContext vc, int depth) throws RenderException {
163         //put the template node into the view context
164
vc.putState(ViewContext.TEMPLATE_NODE, templateNode);
165
166
167         //now start by getting the directives for the current node.
168
//
169
//When we look for directives, we do so by looking first to see if the
170
//previous node was a processing instruction that contained directives.
171
//This is how you would use directives in XML, since the DTD probably
172
//wouldn't support them in the class attribute.
173
//
174
//Now, once we have checked there, see if the view contains any directive
175
//lists associated witha particular node. If you are a developer who
176
//doesn't want directives embedded in *ML, or if the *ML won't allow for it,
177
//this is how you provide for them--by passing in a map to the view which
178
//can be used to xref ids to dir lists.
179
//
180
//finally, look to see if there are any directives directly associated
181
//with the class attribute in the *ML. If there are, add them to the
182
//list.
183
//
184
//When we're all done, we will have a list consisting of all the directives
185
//associated witha given node...
186
if (logger.isDebugEnabled()) logger.debug("Checking for directives");
187         List dirList = null;
188
189         //...now look in the attributes
190
String JavaDoc origClassAttr = null;
191         String JavaDoc newClassAttr = null;
192         Map attrMap = new HashMap();
193         boolean idMatchesDirectives = false;
194         if (templateNode instanceof Element) {
195             Element el = (Element) templateNode;
196
197             //...look for directives based on id attribute
198
if (logger.isDebugEnabled()) logger.debug("Looking for directives based on id attribute");
199             String JavaDoc idName = el.getAttribute(view.getIDAttrName());
200             if (idName!=null && idName.trim().length()>0 && view.getDirIDMap()!=null) {
201                 if (dirList==null) dirList = new ArrayList();
202                 List tlist = view.lookupDirsByID(idName);
203                 if (tlist!=null) dirList.addAll(tlist);
204                 if (dirList.size()>0) idMatchesDirectives = true;
205             }
206
207             //...look for directives in the class attribute
208
if (logger.isDebugEnabled()) logger.debug("Looking for directives based on class attribute");
209             origClassAttr = el.getAttribute(view.getDirAttrName());
210             if (origClassAttr!=null) {
211                 StringBuffer JavaDoc sbNewClassAttr = new StringBuffer JavaDoc(origClassAttr.length());
212                 StringTokenizer st = new StringTokenizer(origClassAttr, " ");
213                 while (st.hasMoreTokens()) {
214                     String JavaDoc s = st.nextToken();
215                     TemplateDirective td = view.lookupDir(s);
216                     if (td!=null) {
217                         if (dirList==null) dirList = new ArrayList(1);
218                         dirList.add(td);
219                     } else {
220                         sbNewClassAttr.append(s+" ");
221                     }
222                 }
223                 newClassAttr = sbNewClassAttr.toString().trim();
224             }
225         }
226
227
228         //next, process any directives
229
Node newNode = null;
230         boolean processedDir = false;
231         if (dirList!=null && dirList.size()>0) {
232
233             //csc_050702.1 - first and foremost, see if we are in the middle of an iteration. If so,
234
//see if we need to SKIP_TO_NEXT. If so, run through the list of directives and strip out
235
//any that occur up to and including the Iterate_Start directive. Then clear the SKIP_TO_NEXT
236
//flag in the iterator context. What this should effectively do is allow us to nest start
237
//iterator directives within the same node
238
if (itStack!=null) {
239                 IteratorContext itcontext = (IteratorContext) itStack.peek();
240                 if (itcontext.SKIP_TO_NEXT) {
241                     Iterator itDir = dirList.iterator();
242                     while (itDir.hasNext()) {
243                         TemplateDirective td = (TemplateDirective) itDir.next();
244                         if (td.equals(itcontext.startTd)) {
245                             itDir.remove();
246                             break;
247                         } else {
248                             itDir.remove();
249                         }
250                     }
251                     itcontext.SKIP_TO_NEXT = false;
252                 }
253             }
254
255             //iterate through all directives.
256
if (logger.isDebugEnabled()) logger.debug("Processing directives");
257 //System.out.println("Processing directive list");
258
Iterator itDir = dirList.iterator();
259             TemplateModel tm = null;
260             while (itDir.hasNext()) try {
261                 TemplateDirective td = (TemplateDirective) itDir.next();
262
263                 String JavaDoc cmd = td.getCommand();
264                 String JavaDoc model = td.getModelName();
265                 String JavaDoc key = td.getKeyName();
266                 String JavaDoc data = td.getKeyData();
267                 tm = btemplate.getModel(model);
268
269                 Object JavaDoc item = null;
270                 if (logger.isDebugEnabled()) logger.debug("Next dir-->"+td);
271
272                 // If tm is null, that means we couldn't find a TemplateModel by the
273
// requested name. In that case, we'll just log a warning and skip
274
// this directive. - Submitted by Jeff French 7/17/2001
275
if (tm==null && !cmd.equals(TemplateDirective.DISCARD)) {
276                     logger.warn("Cannot find a model named "+model+". Skipping directive "+td);
277                     continue;
278                 }
279                 
280                 //if the directive is aimed at a specific model, let the model
281
//know about it. If this directive gets vetoed, no further
282
//directives will get processed and the entire node will get
283
//skipped
284
if (tm!=null) {
285                     if (logger.isInfoEnabled()) logger.info("Notifying model "+model+" of directive "+td);
286                     tm.setViewContext(vc);
287                     boolean ok = tm.processDirective(td);
288                     if (!ok) return null;
289                 }
290
291                 //Dir::Get_Data
292
if (cmd.equals(TemplateDirective.GET_DATA)) {
293                     if (logger.isDebugEnabled()) logger.debug("GET_DATA");
294
295                     //make sure that if we're in the middle of an iteration we still have data
296
//available. If not, don't return this node!
297
if (itStack!=null) {
298                         IteratorContext itcontext = (IteratorContext) itStack.peek();
299                         if (itcontext.EOF) return null;
300                     }
301
302                     //get the item and process accordingly
303
//csc_030603.2 item = tm.getItem(key);
304
item = tm.getItem(td); //csc_030603.2
305
if (item!=null) {
306                         //..BComponent
307
if (item instanceof BComponent) {
308                             //add in the Node for the first view
309
if (logger.isDebugEnabled()) logger.debug("Getting BComponent item: "+item+"...");
310                             BComponent bcomp = (BComponent) item;
311
312                             //this is not really the right way to do this, but its a
313
//quick fix that will work for now. See csc for details...
314
boolean defaultNodeCreatedViews = false; //csc_110501.1
315

316                             //if the component needs a default view create one for it...
317
if (!bcomp.hasViews() || bcomp.getViews().size()<1) { //jrk_040702.2
318
//get the format type and the doc from the view context
319
FormatType ft = vc.getViewCapabilities().getFormatType();
320                                 Document doc = vc.getElementFactory().getDocument();
321
322                                 try {
323                                     //get the appropriate renderer by looking up the
324
//DOM class associated with the given format type
325
Renderer r = bcomp.getRenderer(ft.getDOMClass());
326
327                                     //ask the renderer to create the default Node
328
newNode = r.createDefaultNode(doc, bcomp, vc); //csc_110501.1
329

330                                     //if the component still needs a default view create one for it...
331
if (bcomp.hasViews()) defaultNodeCreatedViews = true;
332                                     else bcomp.addTempView(new DefaultView(newNode));
333
334                                     //finally, invalidate the component to ensure redraw
335
bcomp.invalidate();
336                                     
337                                 } catch (RenderException e) {
338                                     logger.warn("Unable to create default view:", e);
339                                 } catch (DOMException e) {
340                                     logger.warn("Unable to create default view:", e);
341                                 }
342                                 
343                             //if the component being returned is already bound to views,
344
//just add in the nodes that back the views
345
} else { //csc_110501.1
346
//hmmm...I'm not sure if it would make sense to return components from a template model
347
//that had more than one view. Probably not; in case someone tries it, it won't work
348
//since we only handle the first one here...
349
newNode = ((View) bcomp.getViews().get(0)).getNode();
350                             }
351
352                             //now add the comp as a temporary child (by doing this, we ensure that
353
//the child will get rendered as well. After rendering, we'll remove
354
//the child from the hierarchy, so as to return to our original state)
355
//
356
//(Note that we DON'T have these step children inherit the parent
357
//settings...this is because the model will be returning distinct
358
//components whose visibility/enabled status should NOT be the same as
359
//that of the master template)
360
btemplate.addStepChild(bcomp);
361
362                             //csc_091301.2_start - added
363
//if the component returned is NOT an instance of BTemplate,
364
//BTable, or BList, then check to see if it has any non-text
365
//children. If so, automatically create BTemplate components
366
//to parse them as well (thereby catching any nested directives
367
//they might also contain...)
368
if (!(bcomp instanceof BTemplate) &&
369                                 !(bcomp instanceof BTable) &&
370                                 !(bcomp instanceof BList) &&
371                                 !(defaultNodeCreatedViews) && //csc_110501.1
372
(newNode!=null && newNode.hasChildNodes())) {
373
374 //csc_112102.1_start
375
//ok, so the problem with this approach is that while immediately rendering the
376
//btChild here does solved the nested iterative directive problem (making sure they all
377
//get called in the current iteration, rather than later as was happening when we were
378
//simply adding to btemplate as a step child), it inadvertantly SKIPS directives that
379
//are in the DOM layer that is immediately below newNode
380
/*
381                                 Node chNode = newNode.getFirstChild();
382                                 while (chNode!=null) {
383                                     if (chNode instanceof Element) {
384                                         TemplateView tv = (TemplateView) view.clone();
385                                         tv.setNode(chNode);
386                                         BTemplate btChild = new BTemplate();
387                                         btChild.setView(tv);
388                                         btChild.addModels(btemplate.getModels());
389 // btemplate.addStepChild(btChild); //csc_111902.1 - roll back changes that got added in csc_100802.1 - these changes where not processing nested directives correctly (the test case was failing too...not sure how I missed that originally)
390                                         btChild.render(vc);
391                                     }
392                                     chNode = chNode.getNextSibling();
393                                 }
394 */

395 //The solution then, is to run through all the child elements; if any of them
396
//actually implement element, then create one BTemplate and bind it to newNode
397
//(rather than each individual child node as we were doing before), and THEN
398
//render immediately. Voila! All is well...whew! This was a bugger to find.
399
Node chNode = newNode.getFirstChild();
400                                 boolean hasElements = false;
401                                 while (chNode!=null) {
402                                     if (chNode instanceof Element) {
403                                         hasElements = true;
404                                         break;
405                                     }
406                                     chNode = chNode.getNextSibling();
407                                 }
408
409                                 if (hasElements) {
410                                     TemplateView tv = (TemplateView) view.clone();
411                                     tv.setNode(newNode);
412                                     BTemplate broot = new BTemplate();
413                                     broot.setView(tv);
414                                     broot.addModels(btemplate.getModels());
415                                     broot.render(vc);
416                                     broot.destroyCycle(); //saw_121102.1 - we must call this so that the BTemplate can be gc'd
417
}
418 //csc_112102.1_end
419
}
420                             //csc_091301.2_end
421

422                         //..Nodes
423
} else if (item instanceof Node) {
424                             if (logger.isDebugEnabled()) logger.debug("Getting Node item: "+item+"...");
425                             newNode = (Node) item;
426
427
428 //csc_112102.1_start - same explanation as above
429
/*
430                             //csc_091301.2_start - added
431                             //when we get a node back, automatically create a BTemplate
432                             //component to parse it as well (using the same models as the
433                             //current template component)
434                             TemplateView tv = (TemplateView) view.clone();
435                             tv.setNode(newNode);
436                             BTemplate btChild = new BTemplate();
437                             btChild.setView(tv);
438                             btChild.addModels(btemplate.getModels());
439 // btemplate.addStepChild(btChild); //csc_111902.1 - roll back changes that got added in csc_100802.1 - these changes where not processing nested directives correctly (the test case was failing too...not sure how I missed that originally)
440                             btChild.render(vc);
441                             //csc_091301.2_end
442 */

443                             Node chNode = newNode.getFirstChild();
444                             boolean hasElements = false;
445                             while (chNode!=null) {
446                                 if (chNode instanceof Element) {
447                                     hasElements = true;
448                                     break;
449                                 }
450                                 chNode = chNode.getNextSibling();
451                             }
452
453                             if (hasElements) {
454                                 TemplateView tv = (TemplateView) view.clone();
455                                 tv.setNode(newNode);
456                                 BTemplate broot = new BTemplate();
457                                 broot.setView(tv);
458                                 broot.addModels(btemplate.getModels());
459                                 broot.render(vc);
460                                 broot.destroyCycle(); //saw_121102.1 - we must call this so that the BTemplate can be gc'd
461
}
462 //csc_112102.1_end
463

464                         //..Strings
465
} else {
466                             if (logger.isDebugEnabled()) logger.debug("Getting String item: "+item+"...");
467                             newNode = templateNode.cloneNode(true);
468                             String JavaDoc s = item.toString();
469                             BText textComp = new BText(s);
470                             textComp.setView(new DefaultView(newNode));
471                             btemplate.addStepChild(textComp);
472                             
473                             //TODO: if the String value contains any directives, create a
474
//BTemplate component to process them as well...this is
475
//actually not at all trivial, because by this point the dom
476
//structure (if there even was one) has been flattened...even
477
//if we can tell there's a directive embedded in the text, its
478
//not clear to me how we'd process it, since the structure is
479
//flat. We could conceivably try break the string up and reconstruct
480
//DOM pieces, but I suspect this would be very difficult to do
481
//with any reliability...hmm. More thought needed before we bite
482
//this one off to do.
483

484                         }
485                     //..skip this directive
486
} else {
487                         //csc_091301.1_start - change the meaning of a null item to
488
//indicate that the node should be skipped
489
/*
490                         if (logger.isDebugEnabled()) logger.debug("Undefined key.");
491                         newNode = templateNode.cloneNode(true);
492                         String s = model+"."+key+" "+AbstractTemplateModel.UNDEFINED;
493                         BText textComp = new BText(s, new DefaultView(newNode));
494                         btemplate.addStepChild(textComp);
495 */

496                         if (logger.isDebugEnabled()) logger.debug("Null value returned; skipping this directive");
497                         return null;
498                         //csc_091301.1_end
499
}
500                     processedDir = true;
501                     
502                 //Dir::Set_Attr
503
} else if (cmd.equals(TemplateDirective.SET_ATTR)) {
504                     if (logger.isDebugEnabled()) logger.debug("SET_ATTR");
505                 
506                     //make sure that if we're in the middle of an iteration we still have data
507
//available. If not, don't return this node!
508
if (itStack!=null) {
509                         IteratorContext itcontext = (IteratorContext) itStack.peek();
510                         if (itcontext.EOF) return null;
511                     }
512
513                     //get the item, convert it to a String and add it to the attr map
514
//csc_030603.2 item = tm.getItem(key);
515
item = tm.getItem(td); //csc_030603.2
516
//csc_112103_1_start
517
//the purpose behind this fix is so that multiple Set_Attr directives in the same node
518
//won't stomp on each other
519
// if (item!=null) attrMap.put(data, item.toString());
520
// else attrMap.put(data, null);
521
String JavaDoc curAttr = (String JavaDoc) attrMap.get(data);
522                     String JavaDoc newAttr = (item!=null ? item.toString() : null);
523                     if (curAttr==null) attrMap.put(data, newAttr);
524                     else if (newAttr!=null) attrMap.put(data, curAttr+" "+newAttr);
525 //csc_112103_1_end
526

527                 //Dir::Discard
528
} else if (cmd.equals(TemplateDirective.DISCARD)) {
529                     if (logger.isDebugEnabled()) logger.debug("DISCARD");
530                     
531                     //cause the node to be discarded by returning null immediately
532
return null;
533                 
534                 //Dir::Iterate_Start
535
} else if (cmd.equals(TemplateDirective.ITERATE_START)) {
536                     if (logger.isDebugEnabled()) logger.debug("ITERATE_START");
537                 
538                     //make sure the model supports iteration
539
if (tm==null || !(tm instanceof IterativeModel)) continue;
540                     IterativeModel itm = (IterativeModel) tm;
541                     
542                     //create the iterator stack if necessary
543
if (itStack==null) itStack = new Stack();
544                     
545                     //see if the IteratorContext on the stack has the same starting node
546
//as this one...if so, we've already processed this directive so just
547
//continue
548
IteratorContext itcontext = null;
549                     if (!itStack.empty()) itcontext = (IteratorContext) itStack.peek();
550 //csc_050702.1 if (itcontext!=null && itcontext.startNode==templateNode) continue;
551
if (itcontext!=null && itcontext.startNode==templateNode && itcontext.startTd.equals(td)) continue; //csc_050702.1
552

553                     //if not, this is a brand new iteration. Create an iteration
554
//context and add it to the stack
555
//csc_050702.1 itcontext = new IteratorContext(itm, templateNode);
556
itcontext = new IteratorContext(itm, templateNode, td); //csc_050702.1
557
itStack.push(itcontext);
558                     
559                     //notify the IterativeModel to prepare for iteration
560
itm.preIterate();
561                 
562                 //Dir::Iterate_Next
563
} else if (cmd.equals(TemplateDirective.ITERATE_NEXT)) {
564                     if (logger.isDebugEnabled()) logger.debug("ITERATE_NEXT");
565                 
566                     //if itStack is null something is wrong...just continue
567
if (itStack==null) continue;
568
569                     //peek on the stack and get the iteration context. If there is no context,
570
//something's wrong so just continue
571
IteratorContext itcontext = (IteratorContext) itStack.peek();
572                     if (itcontext==null) continue;
573                     
574                     //move the iterator forward. If we're out of records, return immediately
575
if (itcontext.itm.hasNext()) itcontext.itm.loadNext();
576                     else {
577                         itcontext.EOF = true;
578                         return null;
579                     }
580                 
581                 //Dir::Iterate_End
582
} else if (cmd.equals(TemplateDirective.ITERATE_END)) {
583                     if (logger.isDebugEnabled()) logger.debug("ITERATE_END");
584             
585                     //if the stack is null something is wrong...just continue
586
if (itStack==null || itStack.empty()) continue;
587             
588                     //pop the current iteration context back off and give the model
589
//a chance to clean up after iteration
590
IteratorContext itcontext = (IteratorContext) itStack.peek();
591                     
592                     //if we hit and end directive that is not for the current context,
593
//just ignore it
594
if (!itcontext.startTd.getModelName().equals(model)) continue; //csc_050702.1
595

596                     //see if we're at the end of the iteration
597
if (itcontext.EOF) {
598                         itcontext.itm.postIterate();
599                         itStack.pop();
600                         if (itStack.empty()) itStack = null;
601                         
602                     //otherwise, just nextloop
603
} else {
604                         itcontext.NEXTLOOP = true;
605                         itcontext.SKIP_TO_NEXT = true;
606                         itcontext.endNode = templateNode;
607                         
608                         //return immediately since we don't want to add this node
609
//in, instead we want to loop back up to the top of the iterator
610
return null;
611                     }
612                 }
613             } finally {
614                 if (tm!=null) tm.setViewContext(null);
615             }
616         }
617         
618         if (!processedDir) {
619             //if there aren't any, shallow copy and continue and then
620
//copy in child nodes
621
if (logger.isDebugEnabled()) logger.debug("Default Processing");
622             newNode = templateNode.cloneNode(false);
623             copyChildNodes(templateNode, newNode, view, vc, depth+1);
624         }
625         
626         //adjust the outgoing class attributes on the node
627
if (origClassAttr!=null && !(origClassAttr.equals(newClassAttr))) {
628             if (logger.isDebugEnabled()) logger.debug("Adjusting class attributes on new node");
629             Element elNew = (Element) newNode;
630             if (newClassAttr!=null && newClassAttr.length()>0) elNew.setAttribute(view.getDirAttrName(), newClassAttr);
631             else elNew.removeAttribute(view.getDirAttrName());
632         }
633
634         //adjust the outgoing id attributes on the node
635
if (idMatchesDirectives) {
636             if (logger.isDebugEnabled()) logger.debug("Adjusting id attributes on new node");
637             Element elNew = (Element) newNode;
638             elNew.removeAttribute(view.getIDAttrName());
639         }
640
641         //set any attributes that were set through directives
642
if (attrMap.size()>0) {
643             if (logger.isDebugEnabled()) logger.debug("Setting attributes resulting from directives");
644             Iterator it = attrMap.keySet().iterator();
645             Element elNew = (Element) newNode;
646             while (it.hasNext()) {
647                 String JavaDoc key = (String JavaDoc) it.next();
648                 String JavaDoc attr = (String JavaDoc) attrMap.get(key);
649                 if (logger.isDebugEnabled()) logger.debug("attr: "+key+"="+attr);
650                 //don't just passively set non-null values; also actively remove
651
//null values.
652
if (attr!=null) elNew.setAttribute(key, attr);
653                 else elNew.removeAttribute(key);
654             }
655         }
656         
657         return newNode;
658     }
659     
660
661
662     class IteratorContext {
663     
664         IterativeModel itm = null;
665         Node startNode = null;
666         Node endNode = null;
667         TemplateDirective startTd = null; //csc_050702.1
668
boolean SKIP_TO_NEXT = false;
669         boolean NEXTLOOP = false;
670         boolean EOF = false;
671     
672 //csc_050702.1 public IteratorContext(IterativeModel iitm, Node istartNode) {
673
public IteratorContext(IterativeModel iitm, Node istartNode, TemplateDirective istartTd) { //csc_050702.1
674
itm = iitm;
675             startNode = istartNode;
676             endNode = null;
677             startTd = istartTd; //csc_050702.1
678
//csc_050702.1 EOF = false;
679
//csc_050702.1 NEXTLOOP = false;
680
}
681     }
682     
683 }
684
Popular Tags