1 20 package org.enhydra.barracuda.core.comp; 21 22 import java.io.*; 23 import java.util.*; 24 import org.w3c.dom.*; 25 import org.w3c.dom.html.*; 26 27 import org.apache.log4j.*; 28 29 import org.enhydra.barracuda.core.util.dom.*; 30 import org.enhydra.barracuda.core.view.*; 31 import org.enhydra.barracuda.core.comp.renderer.*; 32 import org.enhydra.barracuda.plankton.*; 33 import org.enhydra.barracuda.plankton.data.*; 34 35 39 public abstract class AbstractBComponent implements BContainer, StateMap { 40 41 protected static final Logger logger = Logger.getLogger(AbstractBComponent.class.getName()); 43 44 private static byte[] sep = System.getProperty("line.separator").getBytes(); 46 private static Map rfCompMap = new HashMap(); 47 49 protected BContainer parent = null; 51 protected List children = new ArrayList(); 52 protected List stepChildren = null; 53 protected boolean isStepChild = false; 54 protected List views = new ArrayList(); 55 protected List tempViews = null; 56 protected Object dvc = null; 58 protected boolean validated = false; 59 protected StateMap statemap = new DefaultStateMap(); 60 61 62 public abstract void setName(String iname); 64 public abstract String getName(); 65 public abstract void setVisible(boolean val); 66 public abstract void setVisible(boolean val, boolean recurse); 67 public abstract boolean isVisible(); 68 public abstract void setEnabled(boolean val); 69 public abstract void setEnabled(boolean val, boolean recurse); 70 public abstract boolean isEnabled(); 71 public abstract void setView(View view); 72 public abstract void addView(View view); 73 public abstract boolean removeView(View view); 74 public abstract void removeAllViews(); 75 public abstract List getViews(); 76 public abstract void setAttr(Object attr, Object val); 77 public abstract Object getAttr(Object attr); 78 public abstract Map getAttrMap(); 79 public abstract void render(ViewContext vc) throws RenderException; 80 public abstract boolean supports(ViewContext vc); 81 82 87 public void setDefaultViewContext(ViewContext idvc) { 88 dvc = idvc; 89 } 90 91 96 public ViewContext getDefaultViewContext() { 97 return (ViewContext) dvc; 98 } 99 100 public AbstractBComponent getRootComponent() { 101 if (parent!=null && parent instanceof AbstractBComponent) { 102 return ((AbstractBComponent) parent).getRootComponent(); 103 } else { 104 return this; 105 } 106 } 107 108 109 118 public static void installRendererFactory(RendererFactory rf, Class compCl, Class domCl) { 119 if (logger.isInfoEnabled()) logger.info("Installing renderer factory for comp:"+compCl+" for dom:"+domCl); 120 synchronized (rfCompMap) { 121 Map rfDomMap = (Map) rfCompMap.get(compCl); 122 if (rfDomMap==null) { 123 rfDomMap = new HashMap(); 124 rfCompMap.put(compCl, rfDomMap); 126 } 127 synchronized (rfDomMap) { 128 rfDomMap.put(domCl, rf); 129 } 130 } 131 } 132 133 138 public Renderer getRenderer(View view) throws NoSuitableRendererException { 139 Node node = view.getNode(); 140 Class domCl = node.getClass(); 141 return getRenderer(domCl); 142 } 143 144 public Renderer getRenderer(Class domCl) throws NoSuitableRendererException { 145 Class cl = this.getClass(); 146 boolean registered = true; 147 if (logger.isInfoEnabled()) logger.info("Looking up renderer factory for comp:"+cl+" for dom:"+domCl); 148 149 Map rfDomMap = (Map) rfCompMap.get(cl); 151 if (rfDomMap==null) { 153 List list = Classes.getAllInterfaces(domCl); 154 Iterator it = list.iterator(); 155 while (it.hasNext()) { 156 Class clint = (Class ) it.next(); 157 if (logger.isDebugEnabled()) logger.debug("Looking for comp map interfaces:"+clint); 158 rfDomMap = (Map) rfCompMap.get(clint); 159 if (rfDomMap!=null) break; 160 } 161 registered = false; 162 } 163 if (rfDomMap==null) { 165 if (logger.isDebugEnabled()) logger.debug("Looking for comp map superclass:"+cl.getSuperclass()); 166 rfDomMap = findComponentMap(cl.getSuperclass()); 167 } 168 if (rfDomMap==null) throw new NoSuitableRendererException("No renderer available for this component:"+cl); 169 170 RendererFactory rf = (RendererFactory) rfDomMap.get(domCl); 172 if (rf==null) { 174 List list = Classes.getAllInterfaces(domCl); 175 Iterator it = list.iterator(); 176 while (it.hasNext()) { 177 Class clint = (Class ) it.next(); 178 if (logger.isDebugEnabled()) logger.debug("Looking for dom map interfaces:"+clint); 179 rf = (RendererFactory) rfDomMap.get(clint); 180 if (rf!=null) break; 181 } 182 registered = false; 183 } 184 if (rf==null) { 186 if (logger.isDebugEnabled()) logger.debug("Looking for dom map superclass:"+domCl.getSuperclass()); 187 rf = findRendererFactory(domCl.getSuperclass(), rfDomMap); 188 } 189 if (rf==null) throw new NoSuitableRendererException("No renderer available for this markup:"+domCl); 190 191 if (!registered) installRendererFactory(rf, cl, domCl); 194 195 return rf.getInstance(); 197 } 198 199 203 protected Map findComponentMap(Class cl) { 204 Map rfDomMap = (Map) rfCompMap.get(cl); 205 if (rfDomMap==null && cl.getSuperclass()!=null) { 206 rfDomMap = findComponentMap(cl.getSuperclass()); 207 } 208 return rfDomMap; 209 } 210 211 215 protected RendererFactory findRendererFactory(Class cl, Map domMap) { 216 RendererFactory rf = (RendererFactory) domMap.get(cl); 217 if (rf==null && cl.getSuperclass()!=null) { 218 rf = findRendererFactory(cl.getSuperclass(), domMap); 219 } 220 return rf; 221 } 222 223 230 public void initCycle() { 231 233 if (children==null) children = new ArrayList(); 235 Iterator it = children.iterator(); 236 while (it.hasNext()) { 237 Object child = it.next(); 238 if (child instanceof AbstractBComponent) ((AbstractBComponent) child).initCycle(); 239 } 240 } 241 242 246 public void destroyCycle() { 247 if (children!=null) { Iterator it = children.iterator(); 250 while (it.hasNext()) { 251 Object child = it.next(); 252 if (child instanceof AbstractBComponent) ((AbstractBComponent) child).destroyCycle(); 253 } 254 } 255 256 parent = null; 258 children = null; 259 views = null; 260 statemap = null; } 262 263 264 265 266 272 public void setParent(BContainer iparent) { 273 parent = iparent; 274 } 275 276 281 public BContainer getParent() { 282 return parent; 283 } 284 285 290 public void addChild(BContainer child) { 291 if ((child==null) || 293 (children!=null && children.contains(child))) return; 294 299 if (logger.isDebugEnabled()) logger.debug(this.toRef()+": adding "+child); 300 if (children==null) children = new ArrayList(); 302 children.add(child); 303 child.setParent(this); 304 invalidate(); 305 } 306 307 312 public BContainer getChild(int index) { 313 if (logger.isDebugEnabled()) logger.debug(this.toRef()+": getting idx:"+index); 314 return (BContainer) children.get(index); 315 } 316 317 323 public BContainer removeChild(BContainer child) { 324 if (child==null) return null; 325 if (logger.isDebugEnabled()) logger.debug(this.toRef()+": removing "+child); 326 return removeChild(children.indexOf(child)); 327 } 328 329 335 public BContainer removeChild(int index) { 336 if (index<0) return null; 337 if (logger.isDebugEnabled()) logger.debug(this.toRef()+": removing idx:"+index); 338 BContainer child = (BContainer) children.remove(index); 339 child.setParent(null); 340 invalidate(); 341 return child; 342 } 343 344 347 public void removeAll() { 348 if (logger.isDebugEnabled()) logger.debug(this.toRef()+": removing all children"); 349 if (children!=null) children.clear(); 350 invalidate(); 351 } 352 353 358 public boolean hasChildren() { 359 return (children!=null && children.size()>0); 360 } 361 362 368 public List getChildren() { 369 return new ArrayList(children); 370 } 371 372 377 public boolean isStepChild() { 378 return isStepChild; 379 } 380 381 387 public void addStepChild(BContainer child) { 388 addStepChild(child, false); 389 } 390 391 399 public void addStepChild(BContainer child, boolean inheritParentAttrs) { 400 if ((child==null) || 402 (stepChildren!=null && stepChildren.contains(child)) || 403 (children!=null && children.contains(child))) return; 404 if (logger.isDebugEnabled()) logger.debug(this.toRef()+": adding stepchild "+child); 405 this.addChild(child); 406 if (stepChildren==null) stepChildren = new ArrayList(); 407 stepChildren.add(child); 408 409 if (child instanceof BComponent) { 415 BComponent chComp = (BComponent) child; 416 chComp.isStepChild = true; 417 if (inheritParentAttrs) { 418 chComp.setVisible(this.isVisible()); 419 chComp.setEnabled(this.isEnabled()); 420 } 421 } 422 424 if (inheritParentAttrs && child instanceof BComponent) { 428 BComponent bchild = (BComponent) child; 429 if (!bchild.hasViews()) { 430 Iterator it = getViews().iterator(); 431 while (it.hasNext()) { 432 View v = (View) it.next(); 433 bchild.addView(v); 434 if (logger.isDebugEnabled()) logger.debug(this.toRef()+": adding view to stepchild "+child); 435 } 436 if (tempViews!=null) { 437 it = tempViews.iterator(); 438 while (it.hasNext()) { 439 View v = (View) it.next(); 440 bchild.addTempView(v); 441 if (logger.isDebugEnabled()) logger.debug(this.toRef()+": adding tempview to stepchild "+child); 442 } 443 } 444 } 445 } 446 } 447 448 451 public void removeAllStepChildren() { 452 if (logger.isDebugEnabled()) logger.debug(this.toRef()+": removing stepchildren"); 453 if (stepChildren!=null) { 454 Iterator it = stepChildren.iterator(); 455 while (it.hasNext()) { 456 BContainer tempChild = (BContainer) it.next(); 457 if (logger.isDebugEnabled()) logger.debug(this.toRef()+": removing stepchild "+tempChild); 458 459 if (tempChild instanceof BComponent) { 469 ((BComponent) tempChild).destroyCycle(); 470 } 471 472 this.removeChild(tempChild); 477 } 478 } 479 stepChildren = null; 480 } 481 482 488 public void addTempView(View tview) { 489 if ((tview==null) || 491 (tempViews!=null && tempViews.contains(tview)) || 492 (views!=null && views.contains(tview))) return; 493 if (logger.isDebugEnabled()) logger.debug(this.toRef()+": adding tempview "+tview); 494 if (tempViews==null) tempViews = new ArrayList(); 495 tempViews.add(tview); 496 497 if (stepChildren!=null) { 503 Iterator it = stepChildren.iterator(); 504 while (it.hasNext()) { 505 BComponent tempChild = (BComponent) it.next(); 506 if (!tempChild.hasViews()) { 507 if (logger.isDebugEnabled()) logger.debug(this.toRef()+": adding tempview to stepchild"); 508 tempChild.addTempView(tview); 509 } 510 } 511 } 512 } 513 514 519 public boolean hasViews() { 520 return ((views!=null && views.size()>0) || 521 (tempViews!=null && tempViews.size()>0)); 522 } 523 524 531 public void invalidate() { 532 if (validated) { 533 validated = false; 534 if (getParent()!=null) getParent().invalidate(); 535 } 536 } 537 538 545 public void validate() { 546 validated = false; 547 Iterator it = children.iterator(); 548 while (it.hasNext()) { 549 BContainer child = (BContainer) it.next(); 550 child.validate(); 551 } 552 } 553 554 555 556 563 public void putState(Object key, Object val) { 564 statemap.putState(key,val); 565 } 566 567 573 public Object getState(Object key) { 574 return statemap.getState(key); 575 } 576 577 583 public Object removeState(Object key) { 584 return statemap.removeState(key); 585 } 586 587 592 public List getStateKeys() { 593 return statemap.getStateKeys(); 594 } 595 596 601 public Map getStateValues() { 602 return statemap.getStateValues(); 603 } 604 605 609 public void clearState() { 610 statemap.clearState(); 611 } 612 613 614 620 public String toRef() { 621 return "[@"+Integer.toHexString(this.hashCode())+"]"; 624 } 625 626 631 public String toString() { 632 return toString(getDefaultViewContext()); 633 } 634 635 642 public String toString(ViewContext vc) { 643 if (vc==null) { 644 String sname = getName(); 645 if (sname==null) sname = this.getClass().getName(); 646 int lpos = sname.lastIndexOf("."); 647 if (lpos>-1) sname = sname.substring(lpos); 648 return sname+" (@"+Integer.toHexString(this.hashCode())+")"; 649 } 650 651 FormatType ft = vc.getViewCapabilities().getFormatType(); 653 Document doc = vc.getElementFactory().getDocument(); 654 655 List linkViews = this.getViews(); 658 this.removeAllViews(); 659 660 try { 661 Renderer r = this.getRenderer(ft.getDOMClass()); 664 665 673 Node n = r.createDefaultNode(doc, (BComponent) this, vc); 683 if (!this.hasViews()) this.addTempView(new DefaultView(n)); 685 687 this.invalidate(); 689 690 this.render(vc); 692 693 StringWriter sw = new StringWriter(200); 695 DefaultDOMWriter ddw = new DefaultDOMWriter(); 696 ddw.write(n, sw); 697 String linkStr = sw.toString(); 698 String endln = System.getProperty("line.separator"); 699 if (linkStr.endsWith(endln)) linkStr = linkStr.substring(0,linkStr.length()-endln.length()); 700 return linkStr; 701 702 } catch (Exception e) { 703 return ("Err building component markup string: "+e); 704 } finally { 705 if (linkViews!=null) { 708 Iterator it = linkViews.iterator(); 709 while (it.hasNext()) { 710 this.addView((View) it.next()); 711 if (validated) this.invalidate(); 712 } 713 } 714 } 715 } 716 717 public void printStackTrace(int depth, Logger logger) { 718 printStackTrace(depth, logger, null); 719 } 720 721 public void printStackTrace(int depth, OutputStream out) { 722 printStackTrace(depth, null, out); 723 } 724 725 729 protected void printStackTrace(int depth, Logger logger, OutputStream out) { 730 if (depth<0) depth = 0; 731 if (depth>25) depth = 25; 732 String spaces = " "; 733 String inset = spaces.substring(0,depth*3); 734 735 boolean stepchild = (parent!=null && 736 ((AbstractBComponent) parent).stepChildren!=null && 737 ((AbstractBComponent) parent).stepChildren.contains(this)); 738 print(logger, out, inset+this.getClass().getName() + "@" + Integer.toHexString(this.hashCode()) + (stepchild ? " (stepchild)" : "")); 739 740 print(logger, out, inset+" children: "+(children==null ? "null" : "")); 742 int cntr = -1; 743 if (children!=null) { 744 Iterator it = children.iterator(); 745 while (it.hasNext()) { 746 BContainer cont = (BContainer) it.next(); 747 if (cont instanceof BComponent) { 748 print(logger, out, inset+" ["+(++cntr)+"]:"); 749 ((BComponent) cont).printStackTrace(depth+2, logger, out); 750 } else { 751 print(logger, out, inset+" ["+(++cntr)+"]"+cont.getClass().getName()+" (details unknown)"); 752 } 753 } 754 } 755 print(logger, out, inset+" /end children"); 756 757 print(logger, out, inset+"/end @" + Integer.toHexString(this.hashCode())); 758 } 759 760 private static void print(Logger logger, OutputStream out, String s) { 761 if (logger!=null) { 762 logger.debug(s); 763 } else if (out!=null) { 764 try { 765 out.write(s.getBytes()); 766 out.write(sep); 767 } catch (IOException ioe) {} 768 } 769 } 770 771 772 } | Popular Tags |