1 19 20 package org.netbeans.modules.xml.xdm.nodes; 21 import java.io.IOException ; 22 import java.util.ArrayList ; 23 import java.util.HashMap ; 24 import java.util.List ; 25 import java.util.Map ; 26 import javax.xml.XMLConstants ; 27 import org.netbeans.modules.xml.spi.dom.NodeListImpl; 28 import org.netbeans.modules.xml.xdm.XDMModel; 29 import org.netbeans.modules.xml.xdm.visitor.FlushVisitor; 30 import org.netbeans.modules.xml.xdm.visitor.Utils; 31 import org.netbeans.modules.xml.xdm.visitor.XMLNodeVisitor; 32 import org.w3c.dom.DOMException ; 33 import org.w3c.dom.NamedNodeMap ; 34 import org.w3c.dom.NodeList ; 35 36 55 public class Element extends NodeImpl implements Node, org.w3c.dom.Element { 56 57 58 Element() { 59 super(); 60 } 61 62 Element(String tagName) { 63 super(); 64 List <Token> tokens = getTokensForWrite(); 65 tokens.add(Token.create("<".concat(tagName), TokenType.TOKEN_ELEMENT_START_TAG)); 66 tokens.add(Token.create("/>", TokenType.TOKEN_ELEMENT_END_TAG)); 67 } 68 69 public short getNodeType() { 70 return Node.ELEMENT_NODE; 71 } 72 73 public String getNodeName() { 74 return getTagName(); 75 } 76 77 public void accept(XMLNodeVisitor visitor) { 78 visitor.visit(this); 79 } 80 81 public String getTagName() { 82 if(tagName == null){ 83 for(Token token : getTokens()) { 84 if(token.getType() == TokenType.TOKEN_ELEMENT_START_TAG) { 85 tagName = token.getValue().substring(1); 86 break; 87 } 88 } 89 } 90 return tagName; 91 } 92 93 public void setTagName(String tagName) { 94 assert tagName!= null && !"".equals(tagName); 95 checkNotInTree(); 96 this.tagName = tagName; 97 int tokenIndex = -1; 98 for(Token token : getTokens()) { 99 tokenIndex++; 100 if(token.getType() == TokenType.TOKEN_ELEMENT_START_TAG) { 101 String image; 102 String oldImage = token.getValue(); 103 if(oldImage.startsWith("</")) { 104 image = "</".concat(tagName); 105 } else { 106 image = "<".concat(tagName); 107 } 108 Token newToken = 109 Token.create(image,TokenType.TOKEN_ELEMENT_START_TAG); 110 getTokensForWrite().set(tokenIndex,newToken); 111 } 112 } 113 } 114 115 public String getPrefix() { 116 String qName = getTagName(); 117 if(qName != null){ 118 int idx = qName.indexOf(':'); 119 if(idx >0) return qName.substring(0,idx); 120 } 121 return null; 122 } 123 124 public void setPrefix(String prefix) { 125 String localName = getLocalName(); 126 if(prefix == null || prefix.equals("")) { 127 setTagName(localName); 128 } else { 129 setTagName(prefix.concat(":").concat(localName)); 130 } 131 } 132 133 public String getLocalName() { 134 String qName = getTagName(); 135 if(qName != null){ 136 int idx = qName.indexOf(':')+1; 137 if(idx >0) return qName.substring(idx); 138 } 139 return qName; 140 } 141 142 public void setLocalName(String localName) { 143 String prefix = getPrefix(); 144 if(prefix == null) { 145 setTagName(localName); 146 } else if(localName == null || localName.equals("")) { 147 setTagName(prefix); 148 } else { 149 setTagName(prefix.concat(":").concat(localName)); 150 } 151 } 152 153 void setTokens(List <Token> newTokens) { 154 tagName = null; 155 super.setTokens(newTokens); 156 } 157 158 164 public String getAttribute(String name) { 165 Attribute attribute = getAttributeNode(name); 166 return attribute!=null?attribute.getValue():null; 167 } 168 169 179 public Attribute getAttributeNode(String name) { 180 for(Attribute attr:getAttributesForRead()) { 181 if(name.equals(attr.getName())) 182 return attr; 183 } 184 return null; 185 } 186 187 197 public boolean hasAttribute(String name) { 198 return getAttributeNode(name)!=null; 199 } 200 201 217 public String getAttributeNS(String namespaceURI, String localName) { 218 Attribute attribute = getAttributeNodeNS(namespaceURI,localName); 219 return attribute!=null?attribute.getValue():null; 220 } 221 222 239 public Attribute getAttributeNodeNS(String namespaceURI, String localName) { 240 String prefix = lookupPrefix(namespaceURI); 241 String qualifiedName = localName; 242 if (prefix != null && !prefix.equals("")) qualifiedName = prefix+":"+localName; 243 return getAttributeNode(qualifiedName); 244 } 245 246 265 public boolean hasAttributeNS(String namespaceURI, String localName) { 266 return getAttributeNodeNS(namespaceURI,localName)!=null; 267 } 268 269 291 public void setAttribute(String name, String value) { 292 checkNotInTree(); 293 Attribute oldAttr = getAttributeNode(name); 294 if (oldAttr!=null) { 295 if(!oldAttr.isInTree()) { 296 oldAttr.setValue(value); 297 } else { 298 Attribute newAttr = (Attribute)oldAttr.clone(true,false,false); 299 newAttr.setValue(value); 300 int index = getAttributesForRead().indexOf(oldAttr); 301 getAttributesForWrite().set(index,newAttr); 302 } 303 } else { 304 Attribute attribute = new Attribute(name, value); 305 getAttributesForWrite().add(attribute); 306 } 307 } 308 309 329 public Attribute setAttributeNode(org.w3c.dom.Attr newAttr) { 330 checkNotInTree(); 331 if(newAttr instanceof Attribute) { 332 Attribute attribute = (Attribute)newAttr; 333 Attribute oldAttr = getAttributeNode(newAttr.getName()); 334 if (oldAttr==null) { 335 getAttributesForWrite().add(attribute); 336 return attribute; 337 } else { 338 int index = getAttributesForRead().indexOf(oldAttr); 339 return getAttributesForWrite().set(index,attribute); 340 } 341 } else { 342 throw new DOMException (DOMException.TYPE_MISMATCH_ERR,null); 343 } 344 } 345 346 361 public void removeAttribute(String name) { 362 Attribute attribute = getAttributeNode(name); 363 removeAttributeNode(attribute); 364 } 365 366 383 public Attribute removeAttributeNode(org.w3c.dom.Attr oldAttr) { 384 checkNotInTree(); 385 getAttributesForWrite().remove(oldAttr); 386 return (Attribute) oldAttr; 387 } 388 389 415 public org.w3c.dom.Attr setAttributeNodeNS(org.w3c.dom.Attr newAttr) { 416 return setAttributeNode(newAttr); 417 } 418 419 461 public void setAttributeNS(String namespaceURI, String qualifiedName, String value) { 462 checkNotInTree(); 464 Attribute oldAttr = getAttributeNodeNS(namespaceURI, qualifiedName); 465 if (oldAttr!=null) { 466 if(!oldAttr.isInTree()) { 467 oldAttr.setValue(value); 468 } else { 469 Attribute newAttr = (Attribute)oldAttr.clone(true,false,false); 470 newAttr.setValue(value); 471 int index = getAttributesForRead().indexOf(oldAttr); 472 getAttributesForWrite().set(index,newAttr); 473 } 474 } else { 475 String prefix = lookupPrefix(namespaceURI); 476 String name = qualifiedName; 477 if (prefix != null && !prefix.equals("")) name = prefix + ":" + qualifiedName; 478 Attribute attribute = new Attribute(name, value); 479 getAttributesForWrite().add(attribute); 480 } 481 } 482 483 507 public void removeAttributeNS(String namespaceURI, String localName) { 508 removeAttributeNode(getAttributeNodeNS(namespaceURI, localName)); 509 } 510 511 518 public org.w3c.dom.NodeList getElementsByTagName(String name) { 519 NodeList nl = getChildNodes(); 520 List <Element> l = new ArrayList <Element>(nl.getLength()); 521 boolean matchesAll = "*".equals(name); for (int i = 0; i < nl.getLength(); i++) { 523 org.w3c.dom.Node n = nl.item(i); 524 boolean matchesValue = 525 n instanceof Element && 526 (matchesAll || n.getNodeName().equals(name)); 527 if (matchesValue) { 528 l.add((Element)n); 529 } 530 } 531 return new NodeListImpl(l); 532 } 533 534 550 public org.w3c.dom.NodeList getElementsByTagNameNS(String namespaceURI, String localName) { 551 return null; 553 } 554 555 573 public void setIdAttributeNode(org.w3c.dom.Attr idAttr, boolean isId) { 574 } 576 577 597 public void setIdAttribute(String name, boolean isId) { 598 } 600 601 620 public void setIdAttributeNS(String namespaceURI, String localName, boolean isId) { 621 } 623 624 628 public org.w3c.dom.TypeInfo getSchemaTypeInfo() { 629 return null; 631 } 632 633 640 public void replaceAttribute(Attribute newAttr, Attribute oldAttr) { 641 checkNotInTree(); 642 List <Attribute> attributes = getAttributesForRead(); 643 int index = attributes.indexOf(oldAttr); 644 assert newAttr != null && index>-1; 645 newAttr.checkNotInTree(); 646 getAttributesForWrite().set(attributes.indexOf(oldAttr),newAttr); 647 } 648 649 657 public void addAttribute(Attribute newAttr, int index) { 658 checkNotInTree(); 659 assert newAttr != null; 660 newAttr.checkNotInTree(); 661 getAttributesForWrite().add(index,newAttr); 662 } 663 664 672 public void reorderAttribute(Attribute attr, int index) { 673 checkNotInTree(); 674 if (! attr.isInTree()) { 675 throw new IllegalArgumentException ("Node is not in tree"); 676 } 677 if (! getAttributesForWrite().remove(attr)) { 678 throw new IllegalArgumentException ("Node is not in children"); 679 } 680 getAttributesForWrite().add(index, attr); 681 } 682 683 688 public void reorderAttribute(int[] permutation) { 689 checkNotInTree(); 690 691 List <Attribute> attrs = new ArrayList <Attribute>(getAttributesForRead()); 692 if (permutation.length != attrs.size()) { 693 throw new IllegalArgumentException ( 694 "Permutation length: "+permutation.length+" " + 695 "is different than children size: "+attrs.size()); 696 } 697 698 for (int i = 0; i < attrs.size(); i++ ) { 699 Attribute child = attrs.get(i); 700 getAttributesForWrite().set(permutation[i], child); 701 } 702 } 703 704 710 public void appendAttribute(Attribute newAttr) { 711 checkNotInTree(); 712 assert newAttr != null; 713 newAttr.checkNotInTree(); 714 getAttributesForWrite().add(newAttr); 715 } 716 717 public Node appendChild(org.w3c.dom.Node node) { 718 boolean consolidateNamespace = 719 (getModel() == null || getModel().getStatus() != XDMModel.Status.PARSING); 720 return appendChild(node, consolidateNamespace); 721 } 722 723 public Node appendChild(org.w3c.dom.Node node, boolean consolidateNamespaces) { 724 boolean selfClosingElement = 725 getChildNodes().getLength() == 0 && 726 isStartTagSelfClosing(); 727 728 Node n = super.appendChild(node); 729 if (selfClosingElement) { 730 Token endToken = getEndToken(); 731 assert endToken != null; 732 733 List <Token> tokens = getTokensForWrite(); 734 735 int endPosition = tokens.indexOf(endToken); 737 assert endPosition != -1; 738 tokens.set(endPosition, 739 Token.create(">",TokenType.TOKEN_ELEMENT_END_TAG)); 740 741 tokens.add(Token.create("</"+getTagName(), 742 TokenType.TOKEN_ELEMENT_START_TAG)); 743 tokens.add(Token.create(">",TokenType.TOKEN_ELEMENT_END_TAG)); 744 } 745 if (n instanceof Element && consolidateNamespaces) { 746 consolidateNamespaces((Element)n); 747 } 748 return n; 749 } 750 751 public Node insertBefore(org.w3c.dom.Node newChild, org.w3c.dom.Node refChild) throws DOMException { 752 Node n = super.insertBefore(newChild, refChild); 753 if (n instanceof Element) { 754 if (getModel() == null || getModel().getStatus() != XDMModel.Status.PARSING) { 755 consolidateNamespaces((Element)n); 756 } 757 } 758 return n; 759 } 760 761 private Token getEndToken() { 762 Token endToken = null; 763 for (Token t: getTokens()) { 764 if (t.getType().equals(TokenType.TOKEN_ELEMENT_END_TAG)) { 765 endToken = t; 766 break; 767 } 768 } 769 return endToken; 770 } 771 772 private boolean isStartTagSelfClosing() { 773 boolean selfClosing = false; 774 for (Token t: getTokens()) { 775 if (t.getType().equals(TokenType.TOKEN_ELEMENT_END_TAG)) { 776 selfClosing = t.getValue().equals( 777 Token.create("/>",TokenType.TOKEN_ELEMENT_END_TAG) 778 .getValue()); 779 } 780 } 781 return selfClosing; 782 } 783 784 public String getXmlFragmentText() { 785 return new FlushVisitor().flush(getChildNodes()); 786 } 787 788 public void setXmlFragmentText(String text) throws IOException { 789 while(hasChildNodes()) { 790 removeChild(getFirstChild()); 791 } 792 NodeList children = Utils.parseFragment(text); 793 for (int i=0; i<children.getLength(); i++) { 794 appendChild(children.item(i)); 795 } 796 } 797 798 801 private void consolidateNamespaces(Element newChild) { 802 if (getModel() != null) return; 803 804 String parentNamespace = getNamespaceURI(); 806 if (parentNamespace != null && parentNamespace.equals(newChild.getNamespaceURI())) { 807 newChild.setPrefix(getPrefix()); 808 } 809 810 List attributes = newChild.getAttributesForRead(); 812 ArrayList <String > sparedPrefixes = new ArrayList <String >(); 813 for (int i=0; i<attributes.size(); i++) { 814 Attribute attr = (Attribute) attributes.get(i); 815 if (attr.isXmlnsAttribute()) { 817 continue; 818 } 819 String prefix = attr.getPrefix(); 821 if (prefix != null) { 822 String namespace = newChild.lookupNamespaceURI(prefix); 823 if (namespace == null) { continue; 825 } 826 String newPrefix = lookupPrefix(namespace); 827 if (newPrefix == null || newPrefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) { 828 sparedPrefixes.add(prefix); 829 } else if (! newPrefix.equals(prefix)) { 830 if (newChild.lookupNamespaceURI(newPrefix) != null) { 832 sparedPrefixes.add(prefix); 833 } else { 834 attr.setPrefix(newPrefix); 835 } 836 } 837 } 838 839 String value = attr.getValue().trim(); 841 String [] parts = value.split(":"); if (parts.length > 1) { 843 sparedPrefixes.add(parts[0]); 846 } 847 } 848 849 for (int i=0; i<attributes.size(); i++) { 851 Attribute attr = (Attribute) attributes.get(i); 852 if (! attr.isXmlnsAttribute()) continue; 853 854 String prefix = attr.getLocalName(); 855 if (sparedPrefixes.contains(prefix)) { 856 continue; 857 } 858 859 if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)) { 860 prefix = XMLConstants.DEFAULT_NS_PREFIX; 861 } 862 String namespace = attr.getValue(); 863 assert namespace != null; 864 865 String existingNS = lookupNamespaceURI(prefix); 866 String existingPrefix = lookupPrefix(namespace); 867 868 873 if (existingNS == null && existingPrefix == null) { newChild.removeAttributeNode(attr); 875 appendAttribute(attr); 876 } else if (namespace.equals(existingNS) && prefix.equals(existingPrefix)) { newChild.removeAttributeNode(attr); 879 } else if (existingPrefix != null) { newChild.removeAttributeNode(attr); } else { 883 } 885 } 886 } 887 888 public Element cloneNode(boolean deep, boolean cloneNamespacePrefix) { 889 Document root = isInTree() ? (Document) getOwnerDocument() : null; 890 Map <Integer ,String > allNamespaces = null; 891 if (root != null && cloneNamespacePrefix) { 892 allNamespaces = root.getNamespaceMap(); 893 } 894 Map <String ,String > clonePrefixes = new HashMap <String ,String >(); 895 Element clone = (Element) super.cloneNode(deep, allNamespaces, clonePrefixes); 896 for (Map.Entry e : clonePrefixes.entrySet()) { 897 String prefix = (String ) e.getKey(); 898 String attr = prefix.length() > 0 ? 899 XMLConstants.XMLNS_ATTRIBUTE+":"+prefix : 900 XMLConstants.XMLNS_ATTRIBUTE; 901 Attribute attrNode = new Attribute(attr, (String ) e.getValue()); 902 clone.setAttributeNode(attrNode); 903 } 904 return clone; 905 } 906 907 protected void cloneNamespacePrefix(Map <Integer ,String > allNS, Map <String ,String > prefixes) { 908 if (allNS == null) return; 909 910 String namespace = allNS.get(getId()); 911 if (namespace == null) return; 912 913 String prefix = getPrefix(); 914 if (prefix == null && getAttribute(XMLConstants.XMLNS_ATTRIBUTE) != null) { 915 prefix = XMLConstants.DEFAULT_NS_PREFIX; 916 } 917 if (prefix != null) { 918 prefixes.put(prefix, namespace); 919 } 920 } 921 922 private String tagName = null; 923 } 924 | Popular Tags |