001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Emil Ong
028: */
029:
030: package com.caucho.xml.saaj;
031:
032: import java.net.MalformedURLException;
033: import java.net.URL;
034: import java.util.*;
035:
036: import javax.xml.XMLConstants;
037: import javax.xml.namespace.*;
038: import javax.xml.soap.*;
039:
040: import org.w3c.dom.*;
041:
042: public class SOAPElementImpl extends SOAPNodeImpl implements
043: SOAPElement {
044: private static final Name ENCODING_STYLE_NAME = new NameImpl(
045: SOAPConstants.URI_NS_SOAP_1_1_ENVELOPE, "encodingStyle",
046: SOAPConstants.SOAP_ENV_PREFIX);
047:
048: protected SOAPAttrImpl _firstAttribute;
049: protected SOAPAttrImpl _lastAttribute;
050:
051: private String _encoding;
052: private HashMap<String, String> _namespaces = new HashMap<String, String>();
053:
054: SOAPElementImpl(SOAPFactory factory, NameImpl name, SOAPPart owner)
055: throws SOAPException {
056: super (factory, name, owner);
057: }
058:
059: SOAPElementImpl(SOAPFactory factory, NameImpl name)
060: throws SOAPException {
061: this (factory, name, null);
062: }
063:
064: SOAPElementImpl(SOAPFactory factory, Element element)
065: throws SOAPException {
066: this (factory, element, false);
067: }
068:
069: SOAPElementImpl(SOAPFactory factory, Element element,
070: boolean deepCopy) throws SOAPException {
071: this (factory, NameImpl.fromElement(element));
072:
073: if (deepCopy)
074: deepCopy(element);
075: else
076: copyElement(element, true);
077: }
078:
079: protected void setOwner(SOAPPart owner) {
080: _owner = owner;
081: }
082:
083: protected void copySOAPElement(SOAPElement source) {
084: try {
085: setEncodingStyle(source.getEncodingStyle());
086:
087: // ignore exception... if encoding style applies, it will be set
088: // and not if not
089: } catch (SOAPException e) {
090: } catch (IllegalArgumentException e) {
091: }
092:
093: if (source instanceof SOAPElementImpl) {
094: SOAPElementImpl sourceImpl = (SOAPElementImpl) source;
095:
096: _namespaces = (HashMap<String, String>) sourceImpl._namespaces
097: .clone();
098: _factory = sourceImpl._factory;
099:
100: copyElement(sourceImpl, false);
101: } else
102: copyElement(source, true);
103: }
104:
105: // do a shallow copy
106: protected void copyElement(Element source, boolean addNamespaces) {
107: _name = NameImpl.fromElement(source);
108:
109: for (org.w3c.dom.Node node = source.getFirstChild(); node != null; node = node
110: .getNextSibling())
111: appendChild(node);
112:
113: copyAttributesAndNamespaces(source, addNamespaces);
114:
115: // don't need to set parent because this element should be added
116: // as a child to another element. Ditto for siblings.
117: }
118:
119: protected void deepCopy(Element source) throws SOAPException {
120: _name = NameImpl.fromElement(source);
121:
122: for (org.w3c.dom.Node node = source.getFirstChild(); node != null; node = node
123: .getNextSibling()) {
124: if (node instanceof org.w3c.dom.CharacterData) {
125: addTextNode(((org.w3c.dom.CharacterData) node)
126: .getData());
127: } else if (node instanceof Element) {
128: Name name = NameImpl.fromNode(node);
129:
130: SOAPElementImpl child = (SOAPElementImpl) _factory
131: .createElement(name);
132: child.deepCopy((Element) node);
133:
134: addChildElement(child);
135: } else {
136: appendChild(node.cloneNode(true));
137: }
138: }
139:
140: copyAttributesAndNamespaces(source, true);
141:
142: // don't need to set parent because this element should be added
143: // as a child to another element. Ditto for siblings.
144: }
145:
146: private void copyAttributesAndNamespaces(Element source,
147: boolean addNamespaces) {
148: if (source instanceof SOAPElementImpl) {
149: // more efficient when we have an element
150: for (Attr attr = ((SOAPElementImpl) source)._firstAttribute; attr != null; attr = (Attr) attr
151: .getNextSibling()) {
152:
153: // Check if this is a namespace declaration.
154: if (addNamespaces
155: && XMLConstants.XMLNS_ATTRIBUTE_NS_URI
156: .equals(attr.getNamespaceURI()))
157: _namespaces.put(attr.getLocalName(), attr
158: .getValue());
159:
160: setAttributeNode(attr);
161: }
162: } else {
163: NamedNodeMap attributes = source.getAttributes();
164:
165: for (int i = 0; i < attributes.getLength(); i++) {
166: Attr attr = (Attr) attributes.item(i);
167: // Check if this is a namespace declaration.
168: if (addNamespaces
169: && XMLConstants.XMLNS_ATTRIBUTE_NS_URI
170: .equals(attr.getNamespaceURI()))
171: _namespaces.put(attr.getLocalName(), attr
172: .getValue());
173:
174: setAttributeNode(attr);
175: }
176: }
177: }
178:
179: public SOAPAttrImpl getFirstAttribute() {
180: return _firstAttribute;
181: }
182:
183: public SOAPAttrImpl getLastAttribute() {
184: return _lastAttribute;
185: }
186:
187: // javax.xml.soap.Element
188:
189: public SOAPElement addAttribute(Name name, String value)
190: throws SOAPException {
191: setAttribute(NameImpl.fromName(name), value);
192:
193: return this ;
194: }
195:
196: public SOAPElement addAttribute(QName qname, String value)
197: throws SOAPException {
198: setAttribute(NameImpl.fromQName(qname), value);
199:
200: return this ;
201: }
202:
203: public SOAPElement addChildElement(Name name) throws SOAPException {
204: SOAPElement child = _factory.createElement(name);
205:
206: appendChild(child);
207:
208: return child;
209: }
210:
211: public SOAPElement addChildElement(QName qname)
212: throws SOAPException {
213: return addChildElement((Name) NameImpl.fromQName(qname));
214: }
215:
216: public SOAPElement addChildElement(SOAPElement element)
217: throws SOAPException {
218: // to be overriden in certain elements (Header, Fault, Body)
219: appendChild(element);
220:
221: return element;
222: }
223:
224: public SOAPElement addChildElement(String localName)
225: throws SOAPException {
226: return addChildElement((Name) new NameImpl(localName));
227: }
228:
229: public SOAPElement addChildElement(String localName, String prefix)
230: throws SOAPException {
231: String uri = getNamespaceURI(prefix);
232:
233: if (uri == null)
234: throw new SOAPException("Undefined prefix: " + prefix);
235:
236: return addChildElement(localName, prefix, uri);
237: }
238:
239: public SOAPElement addChildElement(String localName, String prefix,
240: String uri) throws SOAPException {
241: return addChildElement((Name) new NameImpl(uri, localName,
242: prefix));
243: }
244:
245: public SOAPElement addNamespaceDeclaration(String prefix, String uri)
246: throws SOAPException {
247: _namespaces.put(prefix, uri);
248:
249: setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
250: XMLConstants.XMLNS_ATTRIBUTE + ':' + prefix, uri);
251:
252: return this ;
253: }
254:
255: public boolean removeNamespaceDeclaration(String prefix) {
256: if (_namespaces.remove(prefix) != null) {
257: removeAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
258: XMLConstants.XMLNS_ATTRIBUTE + ':' + prefix);
259: return true;
260: }
261:
262: return false;
263: }
264:
265: public SOAPElement addTextNode(String text) throws SOAPException {
266: appendChild(new TextImpl(_factory, text));
267:
268: return this ;
269: }
270:
271: public QName createQName(String localName, String prefix)
272: throws SOAPException {
273: String uri = getNamespaceURI(prefix);
274:
275: if (uri == null)
276: throw new SOAPException("Undefined prefix: " + prefix);
277:
278: return new NameImpl(uri, localName, prefix);
279: }
280:
281: public Iterator getAllAttributes() {
282: return new AttributeIterator(_firstAttribute);
283: }
284:
285: public Iterator getAllAttributesAsQNames() {
286: return new AttributeIterator(_firstAttribute);
287: }
288:
289: public String getAttributeValue(Name name) {
290: return getAttributeValue(NameImpl.toQName(name));
291: }
292:
293: public String getAttributeValue(QName qname) {
294: // DOM specifies that the default is "", while SAAJ says null
295:
296: Attr attr = null;
297:
298: if (qname.getNamespaceURI() != null)
299: attr = getAttributeNodeNS(qname.getNamespaceURI(), qname
300: .getLocalPart());
301: else
302: attr = getAttributeNode(qname.getLocalPart());
303:
304: if (attr == null)
305: return null;
306:
307: return attr.getValue();
308: }
309:
310: public Iterator getChildElements() {
311: return new NodeIterator();
312: }
313:
314: public Iterator getChildElements(Name name) {
315: return getChildElements(NameImpl.toQName(name));
316: }
317:
318: public Iterator getChildElements(QName qname) {
319: return new NodeIterator(qname);
320: }
321:
322: public Name getElementName() {
323: return _name;
324: }
325:
326: public QName getElementQName() {
327: return _name;
328: }
329:
330: public String getEncodingStyle() {
331: return getAttributeValue(ENCODING_STYLE_NAME);
332: }
333:
334: public void setEncodingStyle(String encodingStyle)
335: throws SOAPException {
336: // TCK required syntax check
337: try {
338: new URL(encodingStyle);
339: } catch (MalformedURLException e) {
340: throw new IllegalArgumentException(e);
341: }
342:
343: addAttribute(ENCODING_STYLE_NAME, encodingStyle);
344: }
345:
346: public Iterator getNamespacePrefixes() {
347: return _namespaces.keySet().iterator();
348: }
349:
350: public Iterator getVisibleNamespacePrefixes() {
351: // XXX parent
352:
353: return _namespaces.keySet().iterator();
354: }
355:
356: public String getNamespaceURI(String prefix) {
357: String uri = _namespaces.get(prefix);
358:
359: if (uri == null) {
360: if (prefix.equals(_name.getPrefix()))
361: return _name.getURI();
362:
363: if (getParentNode() != null)
364: return ((SOAPElement) getParentNode())
365: .getNamespaceURI(prefix);
366:
367: return null;
368: } else
369: return uri;
370: }
371:
372: public boolean removeAttribute(Name name) {
373: SOAPAttrImpl attr = null;
374:
375: if (name.getURI() != null)
376: attr = (SOAPAttrImpl) getAttributeNodeNS(name.getURI(),
377: name.getLocalName());
378: else
379: attr = (SOAPAttrImpl) getAttributeNode(name
380: .getQualifiedName());
381:
382: if (attr != null) {
383: attr.detachNode();
384: return true;
385: }
386:
387: return false;
388: }
389:
390: public boolean removeAttribute(QName qname) {
391: return removeAttribute((Name) NameImpl.fromQName(qname));
392: }
393:
394: public void removeContents() {
395: for (SOAPNodeImpl node = _firstChild; node != null;) {
396: SOAPNodeImpl current = node;
397:
398: node = current._next;
399:
400: current._parent = null;
401: current._next = null;
402: current._previous = null;
403: }
404:
405: _firstChild = null;
406: _lastChild = null;
407: }
408:
409: public SOAPElement setElementQName(QName newName)
410: throws SOAPException {
411: _name = NameImpl.fromQName(newName);
412:
413: return this ;
414: }
415:
416: // org.w3c.dom.Node
417:
418: public boolean hasAttributes() {
419: return _firstAttribute != null;
420: }
421:
422: public String getNodeName() {
423: return getTagName();
424: }
425:
426: public short getNodeType() {
427: return ELEMENT_NODE;
428: }
429:
430: public String getNodeValue() {
431: return null;
432: }
433:
434: public String lookupNamespaceURI(String prefix) {
435: return getNamespaceURI(prefix);
436: }
437:
438: public NamedNodeMap getAttributes() {
439: return new NamedNodeMapImpl(_firstAttribute);
440: }
441:
442: // org.w3c.dom.Element
443:
444: public String getAttribute(String name) {
445: for (Attr attr = _firstAttribute; attr != null; attr = (Attr) attr
446: .getNextSibling()) {
447: if (name.equals(attr.getName()))
448: return attr.getValue();
449: }
450:
451: return "";
452: }
453:
454: public String getAttributeNS(String namespaceURI, String localName) {
455: for (Attr attr = _firstAttribute; attr != null; attr = (Attr) attr
456: .getNextSibling()) {
457: if (localName.equals(attr.getLocalName())
458: && namespaceURI.equals(attr.getNamespaceURI()))
459: return attr.getValue();
460: }
461:
462: return "";
463: }
464:
465: public Attr getAttributeNode(String name) {
466: for (Attr attr = _firstAttribute; attr != null; attr = (Attr) attr
467: .getNextSibling()) {
468: if (name.equals(attr.getName()))
469: return attr;
470: }
471:
472: return null;
473: }
474:
475: public Attr getAttributeNodeNS(String namespaceURI, String localName) {
476: for (Attr attr = _firstAttribute; attr != null; attr = (Attr) attr
477: .getNextSibling()) {
478: if (localName.equals(attr.getLocalName())
479: && namespaceURI.equals(attr.getNamespaceURI()))
480: return attr;
481: }
482:
483: return null;
484: }
485:
486: public NodeList getElementsByTagName(String name) {
487: return new SelectiveNodeListImpl(name);
488: }
489:
490: public NodeList getElementsByTagNameNS(String namespaceURI,
491: String localName) {
492: return new SelectiveNodeListImpl(namespaceURI, localName);
493: }
494:
495: public TypeInfo getSchemaTypeInfo() {
496: return null;
497: }
498:
499: public String getTagName() {
500: return _name.getQualifiedName();
501: }
502:
503: public boolean hasAttribute(String name) {
504: return getAttributeNode(name) != null;
505: }
506:
507: public boolean hasAttributeNS(String namespaceURI, String localName) {
508: return getAttributeNodeNS(namespaceURI, localName) != null;
509: }
510:
511: public void removeAttribute(String name) {
512: SOAPAttrImpl attr = (SOAPAttrImpl) getAttributeNode(name);
513:
514: if (attr == null)
515: return;
516:
517: removeAttributeNode(attr);
518: }
519:
520: public void removeAttributeNS(String namespaceURI, String localName) {
521: SOAPAttrImpl attr = (SOAPAttrImpl) getAttributeNodeNS(
522: namespaceURI, localName);
523:
524: if (attr == null)
525: return;
526:
527: removeAttributeNode(attr);
528: }
529:
530: public Attr removeAttributeNode(Attr oldAttr) {
531: SOAPAttrImpl attr = (SOAPAttrImpl) oldAttr;
532:
533: if (attr._parent == this ) {
534: attr._parent = null;
535:
536: if (attr._previous != null)
537: attr._previous._next = attr._next;
538:
539: if (attr._next != null)
540: attr._next._previous = attr._previous;
541: }
542:
543: return attr;
544: }
545:
546: private void appendAttribute(SOAPAttrImpl attr) {
547: attr._parent = this ;
548:
549: if (_lastAttribute != null) {
550: _lastAttribute._next = attr;
551: attr._previous = _lastAttribute;
552: _lastAttribute = attr;
553: } else
554: _lastAttribute = _firstAttribute = attr;
555: }
556:
557: private void setAttribute(NameImpl name, String value) {
558: Attr attr = null;
559:
560: if (name.getURI() != null)
561: attr = getAttributeNodeNS(name.getURI(), name
562: .getLocalName());
563: else
564: attr = getAttributeNode(name.getLocalName());
565:
566: if (attr != null)
567: attr.setValue(value);
568: else
569: appendAttribute(new SOAPAttrImpl(_factory, name, value));
570: }
571:
572: public void setAttribute(String name, String value) {
573: Attr attr = getAttributeNode(name);
574:
575: if (attr != null)
576: attr.setValue(value);
577: else
578: appendAttribute(new SOAPAttrImpl(_factory, new NameImpl(
579: name), value));
580: }
581:
582: public Attr setAttributeNode(Attr newAttr) {
583: Attr attr = getAttributeNode(newAttr.getName());
584:
585: if (attr != null) {
586: attr.setValue(newAttr.getValue());
587: return attr;
588: } else if (newAttr instanceof SOAPAttrImpl) {
589: appendAttribute((SOAPAttrImpl) newAttr);
590: return newAttr;
591: } else {
592: SOAPAttrImpl soapAttr = new SOAPAttrImpl(_factory, NameImpl
593: .fromNode(newAttr));
594:
595: soapAttr.setValue(newAttr.getValue());
596:
597: appendAttribute(soapAttr);
598:
599: return soapAttr;
600: }
601: }
602:
603: public Attr setAttributeNodeNS(Attr newAttr) {
604: Attr attr = getAttributeNodeNS(newAttr.getNamespaceURI(),
605: newAttr.getName());
606:
607: if (attr != null) {
608: attr.setValue(newAttr.getValue());
609: return attr;
610: } else {
611: appendAttribute((SOAPAttrImpl) newAttr);
612: return newAttr;
613: }
614: }
615:
616: public void setAttributeNS(String namespaceURI,
617: String qualifiedName, String value) {
618: Attr attr = getAttributeNodeNS(namespaceURI, qualifiedName);
619:
620: if (attr != null)
621: attr.setValue(value);
622: else {
623: NameImpl name = NameImpl.fromQualifiedName(namespaceURI,
624: qualifiedName);
625: appendAttribute(new SOAPAttrImpl(_factory, name, value));
626: }
627: }
628:
629: public void setIdAttribute(String name, boolean isId) {
630: SOAPAttrImpl attr = (SOAPAttrImpl) getAttributeNode(name);
631:
632: if (attr != null)
633: attr.setIsId(isId);
634: }
635:
636: public void setIdAttributeNode(Attr attr, boolean isId) {
637: if (attr.getParentNode() != this )
638: throw new DOMException(DOMException.NOT_FOUND_ERR,
639: "Attribute does not belong to this element");
640:
641: ((SOAPAttrImpl) attr).setIsId(isId);
642: }
643:
644: public void setIdAttributeNS(String namespaceURI, String localName,
645: boolean isId) {
646: SOAPAttrImpl attr = (SOAPAttrImpl) getAttributeNodeNS(
647: namespaceURI, localName);
648:
649: if (attr != null)
650: attr.setIsId(isId);
651: }
652:
653: public String toString() {
654: return "SOAPElement(" + System.identityHashCode(this ) + ")["
655: + _name + "]";
656: }
657:
658: private static class AttributeIterator implements Iterator {
659: private SOAPAttrImpl _current;
660:
661: public AttributeIterator(SOAPAttrImpl first) {
662: _current = first;
663: }
664:
665: public boolean hasNext() {
666: return _current != null;
667: }
668:
669: public Object next() {
670: if (_current == null)
671: throw new NoSuchElementException();
672:
673: Name name = _current._name;
674:
675: _current = (SOAPAttrImpl) _current.getNextSibling();
676:
677: return name;
678: }
679:
680: public void remove() {
681: throw new UnsupportedOperationException();
682: }
683: }
684:
685: protected static class NamedNodeMapImpl implements NamedNodeMap {
686: private org.w3c.dom.Node _first;
687:
688: NamedNodeMapImpl(org.w3c.dom.Node first) {
689: _first = first;
690: }
691:
692: public int getLength() {
693: int length = 0;
694:
695: for (org.w3c.dom.Node node = _first; node != null; node = node
696: .getNextSibling())
697: length++;
698:
699: return length;
700: }
701:
702: public org.w3c.dom.Node getNamedItem(String name) {
703: for (org.w3c.dom.Node node = _first; node != null; node = node
704: .getNextSibling()) {
705: if (name.equals(node.getNodeName()))
706: return node;
707: }
708:
709: return null;
710: }
711:
712: public org.w3c.dom.Node getNamedItemNS(String namespaceURI,
713: String localName) {
714: for (org.w3c.dom.Node node = _first; node != null; node = node
715: .getNextSibling()) {
716: if (localName.equals(node.getLocalName())
717: && namespaceURI.equals(node.getNamespaceURI()))
718: return node;
719: }
720:
721: return null;
722: }
723:
724: public org.w3c.dom.Node item(int index) {
725: int i = 0;
726:
727: for (org.w3c.dom.Node node = _first; node != null; node = node
728: .getNextSibling()) {
729: if (i == index)
730: return node;
731:
732: i++;
733: }
734:
735: return null;
736: }
737:
738: public org.w3c.dom.Node removeNamedItem(String name) {
739: SOAPNodeImpl node = (SOAPNodeImpl) getNamedItem(name);
740:
741: node._parent = null;
742:
743: if (node._previous != null)
744: node._previous._next = node._next;
745:
746: if (node._next != null)
747: node._next._previous = node._previous;
748:
749: node._previous = null;
750: node._next = null;
751:
752: return node;
753: }
754:
755: public org.w3c.dom.Node removeNamedItemNS(String namespaceURI,
756: String localName) {
757: SOAPNodeImpl node = (SOAPNodeImpl) getNamedItemNS(
758: namespaceURI, localName);
759:
760: node._parent = null;
761:
762: if (node._previous != null)
763: node._previous._next = node._next;
764:
765: if (node._next != null)
766: node._next._previous = node._previous;
767:
768: node._previous = null;
769: node._next = null;
770:
771: return node;
772: }
773:
774: public org.w3c.dom.Node setNamedItem(org.w3c.dom.Node arg) {
775: org.w3c.dom.Node node = getNamedItem(arg.getNodeName());
776:
777: if (arg.getParentNode() != null)
778: return arg.getParentNode().replaceChild(arg, node);
779:
780: return null;
781: }
782:
783: public org.w3c.dom.Node setNamedItemNS(org.w3c.dom.Node arg) {
784: org.w3c.dom.Node node = getNamedItemNS(arg
785: .getNamespaceURI(), arg.getLocalName());
786:
787: if (arg.getParentNode() != null)
788: return arg.getParentNode().replaceChild(arg, node);
789:
790: return null;
791: }
792: }
793:
794: protected class NodeIterator implements Iterator {
795: private QName _name;
796: private SOAPNodeImpl _node;
797:
798: public NodeIterator(QName name) {
799: _name = name;
800:
801: if (_name == null)
802: _node = _firstChild;
803: else if (_name.getNamespaceURI() == null) {
804: for (_node = _firstChild; _node != null; _node = _node._next) {
805: if (_name.getLocalPart().equals(
806: _node.getLocalName()))
807: break;
808: }
809: } else {
810: for (_node = _firstChild; _node != null; _node = _node._next) {
811: if (_name.getNamespaceURI().equals(
812: _node.getNamespaceURI())
813: && _name.getLocalPart().equals(
814: _node.getLocalName()))
815: break;
816: }
817: }
818: }
819:
820: public NodeIterator() {
821: this (null);
822: }
823:
824: public boolean hasNext() {
825: return _node != null;
826: }
827:
828: public Object next() {
829: if (_node == null)
830: throw new NoSuchElementException();
831:
832: if (_name == null) {
833: SOAPNodeImpl next = _node;
834:
835: _node = _node._next;
836:
837: return next;
838: } else if (_name.getNamespaceURI() == null) {
839: SOAPNodeImpl next = _node;
840:
841: for (_node = _node._next; _node != null; _node = _node._next) {
842: if (_name.getLocalPart()
843: .equals(_node.getNodeName()))
844: break;
845: }
846:
847: return next;
848: } else {
849: SOAPNodeImpl next = _node;
850:
851: for (_node = _node._next; _node != null; _node = _node._next) {
852: if (_name.getLocalPart().equals(
853: _node.getLocalName())
854: && _name.getNamespaceURI().equals(
855: _node.getNamespaceURI()))
856: break;
857: }
858:
859: return next;
860: }
861: }
862:
863: public void remove() {
864: throw new UnsupportedOperationException();
865: }
866: }
867:
868: protected class SelectiveNodeListImpl implements NodeList {
869: private String _name;
870: private String _namespace;
871:
872: public SelectiveNodeListImpl(String namespace, String name) {
873: _namespace = namespace;
874: _name = name;
875: }
876:
877: public SelectiveNodeListImpl(String name) {
878: this (null, name);
879: }
880:
881: public int getLength() {
882: int length = 0;
883:
884: for (org.w3c.dom.Node node = _firstChild; node != null; node = node
885: .getNextSibling()) {
886: if (_namespace != null) {
887: if (_namespace.equals(node.getNamespaceURI())
888: && _name.equals(node.getLocalName()))
889: length++;
890: } else if (_name.equals(node.getNodeName()))
891: length++;
892: }
893:
894: return length;
895: }
896:
897: public org.w3c.dom.Node item(int i) {
898: int j = 0;
899:
900: for (org.w3c.dom.Node node = _firstChild; node != null; node = node
901: .getNextSibling()) {
902: if (i == j)
903: return node;
904:
905: if (_namespace != null) {
906: if (_namespace.equals(node.getNamespaceURI())
907: && _name.equals(node.getLocalName()))
908: j++;
909: } else if (_name.equals(node.getNodeName()))
910: j++;
911: }
912:
913: return null;
914: }
915: }
916:
917: }
|