1 20 package org.enhydra.barracuda.core.comp.renderer; 21 22 import java.util.*; 23 import org.w3c.dom.*; 24 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 36 public class TemplateHelper { 37 38 protected static final Logger logger = Logger.getLogger(TemplateHelper.class.getName()); 39 40 final String 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 56 public void render(BTemplate comp, TemplateView view, ViewContext vc) throws RenderException { 57 74 btemplate = (BTemplate) comp; 76 Node node = view.getNode(); 77 Node origNode = node; 78 Node origParent = origNode.getParentNode(); 79 Node newNode = null; 80 81 if (comp.isStepChild()) { 88 newNode = getNode(node, view, vc, 0); 90 if (newNode!=null) node = newNode; 91 } 92 93 if (!comp.isStepChild()) { 98 while (node.hasChildNodes()) { 100 node.removeChild(node.getFirstChild()); 101 } 102 103 Node masterTemplate = view.getMasterTemplate(); 106 copyChildNodes(masterTemplate, node, view, vc, 0); 107 } 108 109 if (newNode!=null) { 112 origNode.getParentNode().replaceChild(newNode, origNode); 114 } 115 } 117 118 121 protected void copyChildNodes(Node templateNode, Node targetNode, TemplateView view, ViewContext vc, int depth) throws RenderException { 122 123 Node child = templateNode.getFirstChild(); 125 Node newChild = null; 126 while (child!=null) { 127 newChild = getNode(child, view, vc, depth+1); 129 130 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 if (itcontext.endNode!=null) child = itcontext.endNode; 142 else child = child.getNextSibling(); 143 continue; 144 } 145 } 146 147 if (newChild!=null) { 149 masterRenderer.addChildToParent(targetNode, newChild); 152 } 153 154 child = child.getNextSibling(); 156 } 157 } 158 159 162 protected Node getNode(Node templateNode, TemplateView view, ViewContext vc, int depth) throws RenderException { 163 vc.putState(ViewContext.TEMPLATE_NODE, templateNode); 165 166 167 if (logger.isDebugEnabled()) logger.debug("Checking for directives"); 187 List dirList = null; 188 189 String origClassAttr = null; 191 String newClassAttr = null; 192 Map attrMap = new HashMap(); 193 boolean idMatchesDirectives = false; 194 if (templateNode instanceof Element) { 195 Element el = (Element) templateNode; 196 197 if (logger.isDebugEnabled()) logger.debug("Looking for directives based on id attribute"); 199 String 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 if (logger.isDebugEnabled()) logger.debug("Looking for directives based on class attribute"); 209 origClassAttr = el.getAttribute(view.getDirAttrName()); 210 if (origClassAttr!=null) { 211 StringBuffer sbNewClassAttr = new StringBuffer (origClassAttr.length()); 212 StringTokenizer st = new StringTokenizer(origClassAttr, " "); 213 while (st.hasMoreTokens()) { 214 String 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 Node newNode = null; 230 boolean processedDir = false; 231 if (dirList!=null && dirList.size()>0) { 232 233 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 if (logger.isDebugEnabled()) logger.debug("Processing directives"); 257 Iterator itDir = dirList.iterator(); 259 TemplateModel tm = null; 260 while (itDir.hasNext()) try { 261 TemplateDirective td = (TemplateDirective) itDir.next(); 262 263 String cmd = td.getCommand(); 264 String model = td.getModelName(); 265 String key = td.getKeyName(); 266 String data = td.getKeyData(); 267 tm = btemplate.getModel(model); 268 269 Object item = null; 270 if (logger.isDebugEnabled()) logger.debug("Next dir-->"+td); 271 272 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 (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 if (cmd.equals(TemplateDirective.GET_DATA)) { 293 if (logger.isDebugEnabled()) logger.debug("GET_DATA"); 294 295 if (itStack!=null) { 298 IteratorContext itcontext = (IteratorContext) itStack.peek(); 299 if (itcontext.EOF) return null; 300 } 301 302 item = tm.getItem(td); if (item!=null) { 306 if (item instanceof BComponent) { 308 if (logger.isDebugEnabled()) logger.debug("Getting BComponent item: "+item+"..."); 310 BComponent bcomp = (BComponent) item; 311 312 boolean defaultNodeCreatedViews = false; 316 if (!bcomp.hasViews() || bcomp.getViews().size()<1) { FormatType ft = vc.getViewCapabilities().getFormatType(); 320 Document doc = vc.getElementFactory().getDocument(); 321 322 try { 323 Renderer r = bcomp.getRenderer(ft.getDOMClass()); 326 327 newNode = r.createDefaultNode(doc, bcomp, vc); 330 if (bcomp.hasViews()) defaultNodeCreatedViews = true; 332 else bcomp.addTempView(new DefaultView(newNode)); 333 334 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 } else { newNode = ((View) bcomp.getViews().get(0)).getNode(); 350 } 351 352 btemplate.addStepChild(bcomp); 361 362 if (!(bcomp instanceof BTemplate) && 369 !(bcomp instanceof BTable) && 370 !(bcomp instanceof BList) && 371 !(defaultNodeCreatedViews) && (newNode!=null && newNode.hasChildNodes())) { 373 374 395 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(); } 418 } 420 422 } else if (item instanceof Node) { 424 if (logger.isDebugEnabled()) logger.debug("Getting Node item: "+item+"..."); 425 newNode = (Node) item; 426 427 428 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(); } 462 464 } else { 466 if (logger.isDebugEnabled()) logger.debug("Getting String item: "+item+"..."); 467 newNode = templateNode.cloneNode(true); 468 String s = item.toString(); 469 BText textComp = new BText(s); 470 textComp.setView(new DefaultView(newNode)); 471 btemplate.addStepChild(textComp); 472 473 484 } 485 } else { 487 496 if (logger.isDebugEnabled()) logger.debug("Null value returned; skipping this directive"); 497 return null; 498 } 500 processedDir = true; 501 502 } else if (cmd.equals(TemplateDirective.SET_ATTR)) { 504 if (logger.isDebugEnabled()) logger.debug("SET_ATTR"); 505 506 if (itStack!=null) { 509 IteratorContext itcontext = (IteratorContext) itStack.peek(); 510 if (itcontext.EOF) return null; 511 } 512 513 item = tm.getItem(td); String curAttr = (String ) attrMap.get(data); 522 String 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 527 } else if (cmd.equals(TemplateDirective.DISCARD)) { 529 if (logger.isDebugEnabled()) logger.debug("DISCARD"); 530 531 return null; 533 534 } else if (cmd.equals(TemplateDirective.ITERATE_START)) { 536 if (logger.isDebugEnabled()) logger.debug("ITERATE_START"); 537 538 if (tm==null || !(tm instanceof IterativeModel)) continue; 540 IterativeModel itm = (IterativeModel) tm; 541 542 if (itStack==null) itStack = new Stack(); 544 545 IteratorContext itcontext = null; 549 if (!itStack.empty()) itcontext = (IteratorContext) itStack.peek(); 550 if (itcontext!=null && itcontext.startNode==templateNode && itcontext.startTd.equals(td)) continue; 553 itcontext = new IteratorContext(itm, templateNode, td); itStack.push(itcontext); 558 559 itm.preIterate(); 561 562 } else if (cmd.equals(TemplateDirective.ITERATE_NEXT)) { 564 if (logger.isDebugEnabled()) logger.debug("ITERATE_NEXT"); 565 566 if (itStack==null) continue; 568 569 IteratorContext itcontext = (IteratorContext) itStack.peek(); 572 if (itcontext==null) continue; 573 574 if (itcontext.itm.hasNext()) itcontext.itm.loadNext(); 576 else { 577 itcontext.EOF = true; 578 return null; 579 } 580 581 } else if (cmd.equals(TemplateDirective.ITERATE_END)) { 583 if (logger.isDebugEnabled()) logger.debug("ITERATE_END"); 584 585 if (itStack==null || itStack.empty()) continue; 587 588 IteratorContext itcontext = (IteratorContext) itStack.peek(); 591 592 if (!itcontext.startTd.getModelName().equals(model)) continue; 596 if (itcontext.EOF) { 598 itcontext.itm.postIterate(); 599 itStack.pop(); 600 if (itStack.empty()) itStack = null; 601 602 } else { 604 itcontext.NEXTLOOP = true; 605 itcontext.SKIP_TO_NEXT = true; 606 itcontext.endNode = templateNode; 607 608 return null; 611 } 612 } 613 } finally { 614 if (tm!=null) tm.setViewContext(null); 615 } 616 } 617 618 if (!processedDir) { 619 if (logger.isDebugEnabled()) logger.debug("Default Processing"); 622 newNode = templateNode.cloneNode(false); 623 copyChildNodes(templateNode, newNode, view, vc, depth+1); 624 } 625 626 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 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 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 key = (String ) it.next(); 648 String attr = (String ) attrMap.get(key); 649 if (logger.isDebugEnabled()) logger.debug("attr: "+key+"="+attr); 650 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; boolean SKIP_TO_NEXT = false; 669 boolean NEXTLOOP = false; 670 boolean EOF = false; 671 672 public IteratorContext(IterativeModel iitm, Node istartNode, TemplateDirective istartTd) { itm = iitm; 675 startNode = istartNode; 676 endNode = null; 677 startTd = istartTd; } 681 } 682 683 } 684 | Popular Tags |