1 21 24 package org.lobobrowser.html.domimpl; 25 26 import java.net.MalformedURLException ; 27 import java.net.URL ; 28 import java.util.*; 29 import java.util.logging.*; 30 31 import org.lobobrowser.html.*; 32 import org.lobobrowser.html.style.*; 33 import org.lobobrowser.js.*; 34 import org.lobobrowser.util.*; 35 import org.w3c.dom.*; 36 37 public abstract class NodeImpl extends AbstractScriptableDelegate implements Node, ModelNode { 38 private static final NodeImpl[] EMPTY_ARRAY = new NodeImpl[0]; 39 private static final RenderState INVALID_RENDER_STATE = new StyleSheetRenderState(null, null); 40 protected static final Logger logger = Logger.getLogger(NodeImpl.class.getName()); 41 protected UINode uiNode; 42 protected ArrayList nodeList; 43 protected volatile Document document; 44 45 50 protected volatile Object treeLock = this; 51 52 public NodeImpl() { 53 super(); 54 } 55 56 public void setUINode(UINode uiNode) { 57 this.uiNode = uiNode; 59 } 60 61 public UINode getUINode() { 62 return this.uiNode; 64 } 65 66 70 public UINode findUINode() { 71 UINode uiNode = this.uiNode; 73 if(uiNode != null) { 74 return uiNode; 75 } 76 NodeImpl parentNode = (NodeImpl) this.getParentNode(); 77 return parentNode == null ? null : parentNode.findUINode(); 78 } 79 80 public Node appendChild(Node newChild) 87 throws DOMException { 88 synchronized(this.treeLock) { 89 ArrayList nl = this.nodeList; 90 if(nl == null) { 91 nl = new ArrayList(3); 92 this.nodeList = nl; 93 } 94 nl.add(newChild); 95 if(newChild instanceof NodeImpl) { 96 ((NodeImpl) newChild).setParentImpl(this); 97 } 98 } 99 100 if(!this.notificationsSuspended) { 101 this.informInvalid(); 102 } 103 return newChild; 104 } 105 106 protected void removeAllChildren() { 107 synchronized(this.treeLock) { 108 this.removeAllChildrenImpl(); 109 } 110 } 111 112 protected void removeAllChildrenImpl() { 113 synchronized(this.treeLock) { 114 ArrayList nl = this.nodeList; 115 if(nl != null) { 116 nl.clear(); 117 } 119 } 120 if(!this.notificationsSuspended) { 121 this.informInvalid(); 122 } 123 } 124 125 protected NodeList getNodeList(NodeFilter filter) { 126 Collection collection = new ArrayList(); 127 synchronized(this.treeLock) { 128 this.appendChildrenToCollectionImpl(filter, collection); 129 } 130 return new NodeListImpl(collection); 131 } 132 133 public NodeImpl[] getChildrenArray() { 134 ArrayList nl = this.nodeList; 135 synchronized(this.treeLock) { 136 return nl == null ? null : (NodeImpl[]) nl.toArray(NodeImpl.EMPTY_ARRAY); 137 } 138 } 139 140 int getChildCount() { 141 ArrayList nl = this.nodeList; 142 synchronized(this.treeLock) { 143 return nl == null ? 0 : nl.size(); 144 } 145 } 146 147 private ChildHTMLCollection childrenCollection; 148 public ChildHTMLCollection getChildren() { 149 synchronized(this) { 151 ChildHTMLCollection collection = this.childrenCollection; 152 if(collection == null) { 153 collection = new ChildHTMLCollection(this); 154 this.childrenCollection = collection; 155 } 156 return collection; 157 } 158 } 159 160 164 public ArrayList getDescendents(NodeFilter filter) { 165 ArrayList al = new ArrayList(); 166 synchronized(this.treeLock) { 167 this.extractDescendentsArrayImpl(filter, al); 168 } 169 return al; 170 } 171 172 178 private void extractDescendentsArrayImpl(NodeFilter filter, ArrayList al) { 179 ArrayList nl = this.nodeList; 180 if(nl != null) { 181 Iterator i = nl.iterator(); 182 while(i.hasNext()) { 183 NodeImpl n = (NodeImpl) i.next(); 184 if(filter.accept(n)) { 185 al.add(n); 186 } 187 else if(n.getNodeType() == Node.ELEMENT_NODE) { 188 n.extractDescendentsArrayImpl(filter, al); 189 } 190 } 191 } 192 } 193 194 private void appendChildrenToCollectionImpl(NodeFilter filter, Collection collection) { 195 ArrayList nl = this.nodeList; 196 if(nl != null) { 197 Iterator i = nl.iterator(); 198 while(i.hasNext()) { 199 NodeImpl node = (NodeImpl) i.next(); 200 if(filter.accept(node)) { 201 collection.add(node); 202 } 203 node.appendChildrenToCollectionImpl(filter, collection); 204 } 205 } 206 } 207 208 212 protected abstract Node createSimilarNode(); 213 214 public Node cloneNode(boolean deep) { 215 try { 216 Node newNode = this.createSimilarNode(); 217 NodeList children = this.getChildNodes(); 218 int length = children.getLength(); 219 for(int i = 0; i < length; i++) { 220 Node child = (Node) children.item(i); 221 Node newChild = deep ? child.cloneNode(deep) : child; 222 newNode.appendChild(newChild); 223 } 224 if(newNode instanceof Element) { 225 Element elem = (Element) newNode; 226 NamedNodeMap nnmap = this.getAttributes(); 227 if(nnmap != null) { 228 int nnlength = nnmap.getLength(); 229 for(int i = 0; i < nnlength; i++) { 230 Attr attr = (Attr) nnmap.item(i); 231 elem.setAttributeNode((Attr) attr.cloneNode(true)); 232 } 233 } 234 } 235 return newNode; 236 } catch(Exception err) { 237 throw new IllegalStateException (err.getMessage()); 238 } 239 } 240 241 private int getNodeIndex() { 242 NodeImpl parent = (NodeImpl) this.getParentNode(); 243 return parent == null ? -1 : parent.getChildIndex(this); 244 } 245 246 int getChildIndex(Node child) { 247 synchronized(this.treeLock) { 248 ArrayList nl = this.nodeList; 249 return nl == null ? -1 : nl.indexOf(child); 250 } 251 } 252 253 Node getChildAtIndex(int index) { 254 synchronized(this.treeLock) { 255 ArrayList nl = this.nodeList; 256 try { 257 return nl == null ? null : (Node) nl.get(index); 258 } catch(IndexOutOfBoundsException iob) { 259 this.warn("getChildAtIndex(): Bad index=" + index + " for node=" + this + "."); 260 return null; 261 } 262 } 263 } 264 265 private boolean isAncestorOf(Node other) { 266 NodeImpl parent = (NodeImpl) other.getParentNode(); 267 if(parent == this) { 268 return true; 269 } 270 else if(parent == null) { 271 return false; 272 } 273 else { 274 return this.isAncestorOf(parent); 275 } 276 } 277 278 public short compareDocumentPosition(Node other) 279 throws DOMException { 280 Node parent = this.getParentNode(); 281 if(!(other instanceof NodeImpl)) { 282 throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Unknwon node implementation"); 283 } 284 if(parent != null && parent == other.getParentNode()) { 285 int thisIndex = this.getNodeIndex(); 286 int otherIndex = ((NodeImpl) other).getNodeIndex(); 287 if(thisIndex == -1 || otherIndex == -1) { 288 return Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; 289 } 290 if(thisIndex < otherIndex) { 291 return Node.DOCUMENT_POSITION_FOLLOWING; 292 } 293 else { 294 return Node.DOCUMENT_POSITION_PRECEDING; 295 } 296 } 297 else if(this.isAncestorOf(other)) { 298 return Node.DOCUMENT_POSITION_CONTAINED_BY; 299 } 300 else if(((NodeImpl) other).isAncestorOf(this)) { 301 return Node.DOCUMENT_POSITION_CONTAINS; 302 } 303 else { 304 return Node.DOCUMENT_POSITION_DISCONNECTED; 305 } 306 } 307 308 public NamedNodeMap getAttributes() { 309 return null; 310 } 311 312 public Document getOwnerDocument() { 313 return this.document; 314 } 315 316 void setOwnerDocument(Document value) { 317 this.document = value; 318 this.treeLock = value == null ? this : (Object ) value; 319 } 320 321 void setOwnerDocument(Document value, boolean deep) { 322 this.document = value; 323 this.treeLock = value == null ? this : (Object ) value; 324 if(deep) { 325 synchronized(this.treeLock) { 326 ArrayList nl = this.nodeList; 327 if(nl != null) { 328 Iterator i = nl.iterator(); 329 while(i.hasNext()) { 330 NodeImpl child = (NodeImpl) i.next(); 331 child.setOwnerDocument(value, deep); 332 } 333 } 334 } 335 } 336 } 337 338 void visitImpl(NodeVisitor visitor) { 339 try { 340 visitor.visit(this); 341 } catch(SkipVisitorException sve) { 342 return; 343 } catch(StopVisitorException sve) { 344 throw sve; 345 } 346 ArrayList nl = this.nodeList; 347 if(nl != null) { 348 Iterator i = nl.iterator(); 349 while(i.hasNext()) { 350 NodeImpl child = (NodeImpl) i.next(); 351 try { 352 child.visit(visitor); 354 } catch(StopVisitorException sve) { 355 throw sve; 356 } 357 } 358 } 359 } 360 361 void visit(NodeVisitor visitor) { 362 synchronized(this.treeLock) { 363 this.visitImpl(visitor); 364 } 365 } 366 367 public Node insertBefore(Node newChild, Node refChild) 368 throws DOMException { 369 synchronized(this.treeLock) { 370 ArrayList nl = this.nodeList; 371 int idx = nl == null ? -1 : nl.indexOf(refChild); 372 if(idx == -1) { 373 throw new DOMException(DOMException.NOT_FOUND_ERR, "refChild not found"); 374 } 375 nl.add(idx, newChild); 376 if(newChild instanceof NodeImpl) { 377 ((NodeImpl) newChild).setParentImpl(this); 378 } 379 } 380 if(!this.notificationsSuspended) { 381 this.informInvalid(); 382 } 383 return newChild; 384 } 385 386 protected Node insertAt(Node newChild, int idx) 387 throws DOMException { 388 synchronized(this.treeLock) { 389 ArrayList nl = this.nodeList; 390 if(nl == null) { 391 nl = new ArrayList(); 392 this.nodeList = nl; 393 } 394 nl.add(idx, newChild); 395 if(newChild instanceof NodeImpl) { 396 ((NodeImpl) newChild).setParentImpl(this); 397 } 398 } 399 if(!this.notificationsSuspended) { 400 this.informInvalid(); 401 } 402 return newChild; 403 } 404 405 public Node replaceChild(Node newChild, Node oldChild) 406 throws DOMException { 407 synchronized(this.treeLock) { 408 ArrayList nl = this.nodeList; 409 int idx = nl == null ? -1 : nl.indexOf(oldChild); 410 if(idx == -1) { 411 throw new DOMException(DOMException.NOT_FOUND_ERR, "oldChild not found"); 412 } 413 nl.set(idx, newChild); 414 } 415 if(!this.notificationsSuspended) { 416 this.informInvalid(); 417 } 418 return newChild; 419 } 420 421 public Node removeChild(Node oldChild) 422 throws DOMException { 423 synchronized(this.treeLock) { 424 ArrayList nl = this.nodeList; 425 if(nl == null || !nl.remove(oldChild)) { 426 throw new DOMException(DOMException.NOT_FOUND_ERR, "oldChild not found"); 427 } 428 } 429 if(!this.notificationsSuspended) { 430 this.informInvalid(); 431 } 432 return oldChild; 433 } 434 435 public Node removeChildAt(int index) 436 throws DOMException { 437 try { 438 synchronized(this.treeLock) { 439 ArrayList nl = this.nodeList; 440 if(nl == null) { 441 throw new DOMException(DOMException.INDEX_SIZE_ERR, "Empty list of children"); 442 } 443 Node n = (Node) nl.remove(index); 444 if (n == null) { 445 throw new DOMException(DOMException.INDEX_SIZE_ERR, "No node with that index"); 446 } 447 return n; 448 } 449 } finally { 450 if(!this.notificationsSuspended) { 451 this.informInvalid(); 452 } 453 } 454 } 455 456 public boolean hasChildNodes() { 457 synchronized(this.treeLock) { 458 ArrayList nl = this.nodeList; 459 return nl != null && !nl.isEmpty(); 460 } 461 } 462 463 public String getBaseURI() { 464 Document document = this.document; 465 return document == null ? null : document.getBaseURI(); 466 } 467 468 public NodeList getChildNodes() { 469 synchronized(this.treeLock) { 470 ArrayList nl = this.nodeList; 471 return new NodeListImpl(nl == null ? Collections.EMPTY_LIST : nl); 472 } 473 } 474 475 public Node getFirstChild() { 476 synchronized(this.treeLock) { 477 ArrayList nl = this.nodeList; 478 try { 479 return nl == null ? null : (Node) nl.get(0); 480 } catch(IndexOutOfBoundsException iob) { 481 return null; 482 } 483 } 484 } 485 486 public Node getLastChild() { 487 synchronized(this.treeLock) { 488 ArrayList nl = this.nodeList; 489 try { 490 return nl == null ? null : (Node) nl.get(nl.size() - 1); 491 } catch(IndexOutOfBoundsException iob) { 492 return null; 493 } 494 } 495 } 496 497 private Node getPreviousTo(Node node) { 498 synchronized(this.treeLock) { 499 ArrayList nl = this.nodeList; 500 int idx = nl == null ? -1 : nl.indexOf(node); 501 if(idx == -1) { 502 throw new DOMException(DOMException.NOT_FOUND_ERR, "node not found"); 503 } 504 try { 505 return (Node) nl.get(idx-1); 506 } catch(IndexOutOfBoundsException iob) { 507 return null; 508 } 509 } 510 } 511 512 private Node getNextTo(Node node) { 513 synchronized(this.treeLock) { 514 ArrayList nl = this.nodeList; 515 int idx = nl == null ? -1 : nl.indexOf(node); 516 if(idx == -1) { 517 throw new DOMException(DOMException.NOT_FOUND_ERR, "node not found"); 518 } 519 try { 520 return (Node) nl.get(idx+1); 521 } catch(IndexOutOfBoundsException iob) { 522 return null; 523 } 524 } 525 } 526 527 public Node getPreviousSibling() { 528 NodeImpl parent = (NodeImpl) this.getParentNode(); 529 return parent == null ? null : parent.getPreviousTo(this); 530 } 531 532 public Node getNextSibling() { 533 NodeImpl parent = (NodeImpl) this.getParentNode(); 534 return parent == null ? null : parent.getNextTo(this); 535 } 536 537 public Object getFeature(String feature, String version) { 538 return null; 540 } 541 542 private Map userData; 543 private List userDataHandlers; 545 protected volatile boolean notificationsSuspended = false; 546 547 public Object setUserData(String key, Object data, 548 UserDataHandler handler) { 549 if(org.lobobrowser.html.parser.HtmlParser.MODIFYING_KEY.equals(key)) { 550 boolean ns = (Boolean.TRUE == data); 551 this.notificationsSuspended = ns; 552 if(!ns) { 553 this.informNodeLoaded(); 554 } 555 } 556 synchronized(this) { 557 if(handler != null) { 558 if(this.userDataHandlers == null) { 559 this.userDataHandlers = new LinkedList(); 560 } 561 this.userDataHandlers.add(handler); 562 } 563 Map userData = this.userData; 564 if(userData == null) { 565 userData = new HashMap(); 566 this.userData = userData; 567 } 568 return userData.put(key, data); 569 } 570 } 571 572 public Object getUserData(String key) { 573 synchronized(this) { 574 Map ud = this.userData; 575 return ud == null ? null : ud.get(key); 576 } 577 } 578 579 public abstract String getLocalName(); 580 581 public boolean hasAttributes() { 582 return false; 583 } 584 585 public String getNamespaceURI() { 586 return null; 587 } 588 589 public abstract String getNodeName(); 590 591 public abstract String getNodeValue() throws DOMException; 592 593 private volatile String prefix; 594 595 public String getPrefix() { 596 return this.prefix; 597 } 598 599 public void setPrefix(String prefix) throws DOMException { 600 this.prefix = prefix; 601 } 602 603 public abstract void setNodeValue(String nodeValue) throws DOMException; 604 605 public abstract short getNodeType(); 606 607 611 public String getTextContent() throws DOMException { 612 StringBuffer sb = new StringBuffer (); 613 synchronized(this.treeLock) { 614 ArrayList nl = this.nodeList; 615 if(nl != null) { 616 Iterator i = nl.iterator(); 617 while(i.hasNext()) { 618 Node node = (Node) i.next(); 619 short type = node.getNodeType(); 620 switch(type) { 621 case Node.CDATA_SECTION_NODE: 622 case Node.TEXT_NODE: 623 case Node.ELEMENT_NODE: 624 String textContent = node.getTextContent(); 625 if(textContent != null) { 626 sb.append(textContent); 627 } 628 break; 629 default: 630 break; 631 } 632 } 633 } 634 } 635 return sb.toString(); 636 } 637 638 public void setTextContent(String textContent) throws DOMException { 639 synchronized(this.treeLock) { 640 this.removeChildrenImpl(new TextFilter()); 641 if(textContent != null && !"".equals(textContent)) { 642 TextImpl t = new TextImpl(textContent); 643 t.setOwnerDocument(this.document); 644 t.setParentImpl(this); 645 ArrayList nl = this.nodeList; 646 if(nl == null) { 647 nl = new ArrayList(); 648 this.nodeList = nl; 649 } 650 nl.add(t); 651 } 652 } 653 if(!this.notificationsSuspended) { 654 this.informInvalid(); 655 } 656 } 657 658 protected void removeChildren(NodeFilter filter) { 659 synchronized(this.treeLock) { 660 this.removeChildrenImpl(filter); 661 } 662 if(!this.notificationsSuspended) { 663 this.informInvalid(); 664 } 665 } 666 667 protected void removeChildrenImpl(NodeFilter filter) { 668 ArrayList nl = this.nodeList; 669 if(nl != null) { 670 int len = nl.size(); 671 for(int i = len; --i >= 0;) { 672 Node node = (Node) nl.get(i); 673 if(filter.accept(node)) { 674 nl.remove(i); 675 } 676 } 677 } 678 } 679 680 public Node insertAfter(Node newChild, Node refChild) { 681 synchronized(this.treeLock) { 682 ArrayList nl = this.nodeList; 683 int idx = nl == null ? -1 : nl.indexOf(refChild); 684 if(idx == -1) { 685 throw new DOMException(DOMException.NOT_FOUND_ERR, "refChild not found"); 686 } 687 nl.add(idx+1, newChild); 688 if(newChild instanceof NodeImpl) { 689 ((NodeImpl) newChild).setParentImpl(this); 690 } 691 } 692 if(!this.notificationsSuspended) { 693 this.informInvalid(); 694 } 695 return newChild; 696 } 697 698 public Text replaceAdjacentTextNodes(Text node, String textContent) { 699 try { 700 synchronized(this.treeLock) { 701 ArrayList nl = this.nodeList; 702 if(nl == null) { 703 throw new DOMException(DOMException.NOT_FOUND_ERR, "Node not a child"); 704 } 705 int idx = nl.indexOf(node); 706 if(idx == -1) { 707 throw new DOMException(DOMException.NOT_FOUND_ERR, "Node not a child"); 708 } 709 int firstIdx = idx; 710 List toDelete = new LinkedList(); 711 for(int adjIdx = idx; --adjIdx >= 0;) { 712 Object child = this.nodeList.get(adjIdx); 713 if(child instanceof Text) { 714 firstIdx = adjIdx; 715 toDelete.add(child); 716 } 717 } 718 int length = this.nodeList.size(); 719 for(int adjIdx = idx; ++adjIdx < length;) { 720 Object child = this.nodeList.get(adjIdx); 721 if(child instanceof Text) { 722 toDelete.add(child); 723 } 724 } 725 this.nodeList.removeAll(toDelete); 726 TextImpl textNode = new TextImpl(textContent); 727 textNode.setOwnerDocument(this.document); 728 textNode.setParentImpl(this); 729 this.nodeList.add(firstIdx, textNode); 730 return textNode; 731 } 732 } finally { 733 if(!this.notificationsSuspended) { 734 this.informInvalid(); 735 } 736 } 737 } 738 739 public Text replaceAdjacentTextNodes(Text node) { 740 try { 741 synchronized(this.treeLock) { 742 ArrayList nl = this.nodeList; 743 if(nl == null) { 744 throw new DOMException(DOMException.NOT_FOUND_ERR, "Node not a child"); 745 } 746 int idx = nl.indexOf(node); 747 if(idx == -1) { 748 throw new DOMException(DOMException.NOT_FOUND_ERR, "Node not a child"); 749 } 750 StringBuffer textBuffer = new StringBuffer (); 751 int firstIdx = idx; 752 List toDelete = new LinkedList(); 753 for(int adjIdx = idx; --adjIdx >= 0;) { 754 Object child = this.nodeList.get(adjIdx); 755 if(child instanceof Text) { 756 firstIdx = adjIdx; 757 toDelete.add(child); 758 textBuffer.append(((Text) child).getNodeValue()); 759 } 760 } 761 int length = this.nodeList.size(); 762 for(int adjIdx = idx; ++adjIdx < length;) { 763 Object child = this.nodeList.get(adjIdx); 764 if(child instanceof Text) { 765 toDelete.add(child); 766 textBuffer.append(((Text) child).getNodeValue()); 767 } 768 } 769 this.nodeList.removeAll(toDelete); 770 TextImpl textNode = new TextImpl(textBuffer.toString()); 771 textNode.setOwnerDocument(this.document); 772 textNode.setParentImpl(this); 773 this.nodeList.add(firstIdx, textNode); 774 return textNode; 775 } 776 } finally { 777 if(!this.notificationsSuspended) { 778 this.informInvalid(); 779 } 780 } 781 } 782 783 protected volatile Node parentNode; 784 785 public Node getParentNode() { 786 return this.parentNode; 788 } 789 790 public boolean isSameNode(Node other) { 791 return this == other; 792 } 793 794 public boolean isSupported(String feature, String version) { 795 return ("HTML".equals(feature) && version.compareTo("4.01") <= 0); 796 } 797 798 public String lookupNamespaceURI(String prefix) { 799 return null; 800 } 801 802 public boolean equalAttributes(Node arg) { 803 return false; 804 } 805 806 public boolean isEqualNode(Node arg) { 807 return arg instanceof NodeImpl && 808 this.getNodeType() == arg.getNodeType() && 809 Objects.equals(this.getNodeName(), arg.getNodeName()) && 810 Objects.equals(this.getNodeValue(), arg.getNodeValue()) && 811 Objects.equals(this.getLocalName(), arg.getLocalName()) && 812 Objects.equals(this.nodeList, ((NodeImpl) arg).nodeList) && 813 this.equalAttributes(arg); 814 } 815 816 public boolean isDefaultNamespace(String namespaceURI) { 817 return namespaceURI == null; 818 } 819 820 public String lookupPrefix(String namespaceURI) { 821 return null; 822 } 823 824 public void normalize() { 825 synchronized(this.treeLock) { 826 ArrayList nl = this.nodeList; 827 if(nl != null) { 828 Iterator i = nl.iterator(); 829 List textNodes = new LinkedList(); 830 boolean prevText = false; 831 while(i.hasNext()) { 832 Node child = (Node) i.next(); 833 if(child.getNodeType() == Node.TEXT_NODE) { 834 if(!prevText) { 835 prevText = true; 836 textNodes.add(child); 837 } 838 } 839 else { 840 prevText = false; 841 } 842 } 843 i = textNodes.iterator(); 844 while(i.hasNext()) { 845 Text text = (Text) i.next(); 846 this.replaceAdjacentTextNodes(text); 847 } 848 } 849 } 850 if(!this.notificationsSuspended) { 851 this.informInvalid(); 852 } 853 } 854 855 public String toString() { 856 return this.getNodeName(); 857 } 858 859 public UserAgentContext getUserAgentContext() { 860 Object doc = this.document; 861 if(doc instanceof HTMLDocumentImpl) { 862 return ((HTMLDocumentImpl) doc).getUserAgentContext(); 863 } 864 else { 865 return null; 866 } 867 } 868 869 public HtmlRendererContext getHtmlRendererContext() { 870 Object doc = this.document; 871 if(doc instanceof HTMLDocumentImpl) { 872 return ((HTMLDocumentImpl) doc).getHtmlRendererContext(); 873 } 874 else { 875 return null; 876 } 877 } 878 879 final void setParentImpl(Node parent) { 880 this.parentNode = parent; 882 } 883 884 886 889 public float getAlignmentX() { 890 return 0.5f; 892 } 893 894 897 public float getAlignmentY() { 898 return 0.5f; 899 } 900 901 904 public URL getFullURL(String spec) throws MalformedURLException { 905 Object doc = this.document; 906 if(doc instanceof HTMLDocumentImpl) { 907 return ((HTMLDocumentImpl) doc).getFullURL(spec); 908 } 909 else { 910 return new java.net.URL (spec); 911 } 912 } 913 914 public URL getDocumentURL() { 915 Object doc = this.document; 916 if(doc instanceof HTMLDocumentImpl) { 917 return ((HTMLDocumentImpl) doc).getDocumentURL(); 918 } 919 else { 920 return null; 921 } 922 } 923 924 927 public Object getDocumentItem(String name) { 928 org.w3c.dom.Document document = this.document; 929 return document == null ? null : document.getUserData(name); 930 } 931 932 935 public void setDocumentItem(String name, Object value) { 936 org.w3c.dom.Document document = this.document; 937 if(document == null) { 938 return; 939 } 940 document.setUserData(name, value, null); 941 } 942 943 946 public final boolean isEqualOrDescendentOf(ModelNode otherContext) { 947 if(otherContext == this) { 948 return true; 949 } 950 Object parent = this.getParentNode(); 951 if(parent instanceof HTMLElementImpl) { 952 return ((HTMLElementImpl) parent).isEqualOrDescendentOf(otherContext); 953 } 954 else { 955 return false; 956 } 957 } 958 959 public final ModelNode getParentModelNode() { 960 return (ModelNode) this.parentNode; 961 } 962 963 public void warn(String message, Throwable err) { 964 logger.log(Level.WARNING, message, err); 965 } 966 967 public void warn(String message) { 968 logger.log(Level.WARNING, message); 969 } 970 971 public void informSizeInvalid() { 972 HTMLDocumentImpl doc = (HTMLDocumentImpl) this.document; 973 if(doc != null) { 974 doc.sizeInvalidated(this); 975 } 976 } 977 978 public void informLookInvalid() { 979 this.forgetRenderState(); 980 HTMLDocumentImpl doc = (HTMLDocumentImpl) this.document; 981 if(doc != null) { 982 doc.lookInvalidated(this); 983 } 984 } 985 986 public void informPositionInvalid() { 987 HTMLDocumentImpl doc = (HTMLDocumentImpl) this.document; 988 if(doc != null) { 989 doc.positionInParentInvalidated(this); 990 } 991 } 992 993 public void informInvalid() { 994 this.forgetRenderState(); 996 HTMLDocumentImpl doc = (HTMLDocumentImpl) this.document; 997 if(doc != null) { 998 doc.invalidated(this); 999 } 1000 } 1001 1002 protected void informNodeLoaded() { 1003 this.forgetRenderState(); 1005 HTMLDocumentImpl doc = (HTMLDocumentImpl) this.document; 1006 if(doc != null) { 1007 doc.nodeLoaded(this); 1008 } 1009 } 1010 1011 protected void informExternalScriptLoading() { 1012 this.forgetRenderState(); 1014 HTMLDocumentImpl doc = (HTMLDocumentImpl) this.document; 1015 if(doc != null) { 1016 doc.externalScriptLoading(this); 1017 } 1018 } 1019 1020 public void informLayoutInvalid() { 1021 this.forgetRenderState(); 1023 HTMLDocumentImpl doc = (HTMLDocumentImpl) this.document; 1024 if(doc != null) { 1025 doc.invalidated(this); 1026 } 1027 } 1028 1029 private RenderState renderState = INVALID_RENDER_STATE; 1030 1031 public RenderState getRenderState() { 1032 RenderState rs; 1035 synchronized(this.treeLock) { 1036 rs = this.renderState; 1037 if(rs != INVALID_RENDER_STATE) { 1038 return rs; 1039 } 1040 Object parent = this.parentNode; 1041 if(parent != null || this instanceof Document) { 1042 RenderState prs = this.getParentRenderState(parent); 1043 rs = this.createRenderState(prs); 1044 this.renderState = rs; 1045 return rs; 1046 } 1047 else { 1048 return null; 1051 } 1052 } 1053 } 1054 1055 protected final RenderState getParentRenderState(Object parent) { 1056 if(parent instanceof NodeImpl) { 1057 return ((NodeImpl) parent).getRenderState(); 1058 } 1059 else { 1060 return null; 1061 } 1062 } 1063 1064 protected RenderState createRenderState(RenderState prevRenderState) { 1065 return prevRenderState; 1066 } 1067 1068 protected void forgetRenderState() { 1069 synchronized(this.treeLock) { 1070 if(this.renderState != INVALID_RENDER_STATE) { 1071 this.renderState = INVALID_RENDER_STATE; 1072 java.util.ArrayList nl = this.nodeList; 1075 if(nl != null) { 1076 Iterator i = nl.iterator(); 1077 while(i.hasNext()) { 1078 ((NodeImpl) i.next()).forgetRenderState(); 1079 } 1080 } 1081 } 1082 } 1083 } 1084 1085} 1086 | Popular Tags |