KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > axis > message > SOAPElementAxisImpl


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.jboss.axis.message;
17
18 // $Id: SOAPElementAxisImpl.java,v 1.1.2.6 2005/06/16 12:23:38 tdiesler Exp $
19

20 import org.jboss.axis.AxisFault;
21 import org.jboss.axis.Constants;
22 import org.jboss.axis.MessageContext;
23 import org.jboss.axis.MessagePart;
24 import org.jboss.axis.encoding.DeserializationContext;
25 import org.jboss.axis.encoding.DeserializationContextImpl;
26 import org.jboss.axis.encoding.Deserializer;
27 import org.jboss.axis.encoding.SerializationContext;
28 import org.jboss.axis.encoding.SerializationContextImpl;
29 import org.jboss.axis.enums.Style;
30 import org.jboss.axis.soap.SOAPConstants;
31 import org.jboss.axis.utils.Mapping;
32 import org.jboss.axis.utils.Messages;
33 import org.jboss.axis.utils.XMLUtils;
34 import org.jboss.logging.Logger;
35 import org.w3c.dom.Attr JavaDoc;
36 import org.w3c.dom.DOMException JavaDoc;
37 import org.w3c.dom.Document JavaDoc;
38 import org.w3c.dom.Element JavaDoc;
39 import org.w3c.dom.NamedNodeMap JavaDoc;
40 import org.w3c.dom.Node JavaDoc;
41 import org.w3c.dom.NodeList JavaDoc;
42 import org.w3c.dom.Text JavaDoc;
43 import org.xml.sax.Attributes JavaDoc;
44 import org.xml.sax.ContentHandler JavaDoc;
45 import org.xml.sax.InputSource JavaDoc;
46 import org.xml.sax.SAXException JavaDoc;
47 import org.xml.sax.helpers.AttributesImpl JavaDoc;
48
49 import javax.xml.namespace.QName JavaDoc;
50 import javax.xml.rpc.JAXRPCException JavaDoc;
51 import javax.xml.rpc.encoding.TypeMapping JavaDoc;
52 import javax.xml.soap.Name JavaDoc;
53 import javax.xml.soap.SOAPElement JavaDoc;
54 import javax.xml.soap.SOAPException JavaDoc;
55 import java.io.PrintWriter JavaDoc;
56 import java.io.Reader JavaDoc;
57 import java.io.StringReader JavaDoc;
58 import java.io.StringWriter JavaDoc;
59 import java.util.ArrayList JavaDoc;
60 import java.util.Collections JavaDoc;
61 import java.util.Iterator JavaDoc;
62 import java.util.List JavaDoc;
63 import java.util.Vector JavaDoc;
64
65 /**
66  * SOAPElementImpl is the base type of nodes of the SOAP message parse tree.
67  */

68 public class SOAPElementAxisImpl extends SOAPElementImpl implements SOAPElement JavaDoc, Cloneable JavaDoc
69 {
70    private static Logger log = Logger.getLogger(SOAPElementAxisImpl.class.getName());
71
72    protected String JavaDoc name;
73    protected String JavaDoc prefix;
74    protected String JavaDoc namespaceURI;
75    protected transient Attributes JavaDoc attributes = NullAttributes.singleton;
76    protected String JavaDoc id;
77    protected String JavaDoc href;
78    protected boolean _isRoot = true;
79    protected SOAPEnvelopeAxisImpl message;
80
81    protected transient DeserializationContext context;
82
83    protected transient QName JavaDoc typeQName;
84
85    protected Vector JavaDoc qNameAttrs;
86
87    // Some message representations - as recorded SAX events...
88
protected transient SAX2EventRecorder recorder;
89    protected int startEventIndex;
90    protected int startContentsIndex;
91    protected int endEventIndex = -1;
92
93    // ...or as DOM
94
protected Element JavaDoc elementRep;
95
96    private SOAPElementAxisImpl parent;
97
98    public ArrayList JavaDoc namespaces;
99
100    /**
101     * Our encoding style, if any
102     */

103    protected String JavaDoc encodingStyle;
104
105    /**
106     * Object value, possibly supplied by subclass
107     */

108    protected Object JavaDoc objectValue;
109
110    // The children of this MessageElement
111
private ChildElementList children = new ChildElementList();
112
113    protected MessagePart soapPart;
114
115    // Set this flag to prevent clients from modifying this element
116
// eg. ws4ee handlers are not allowed to change the name of every element in the response
117
// TDI 15-Jun-2004
118
private boolean immutable;
119
120    /**
121     * No-arg constructor for building messages?
122     */

123    public SOAPElementAxisImpl()
124    {
125       super("unqualified-element");
126    }
127
128    public SOAPElementAxisImpl(String JavaDoc localPart)
129    {
130       super(localPart);
131       namespaceURI = "";
132       name = localPart;
133    }
134
135    public SOAPElementAxisImpl(String JavaDoc namespace, String JavaDoc localPart)
136    {
137       super(localPart, null, namespace);
138       namespaceURI = namespace;
139       name = localPart;
140    }
141
142    public SOAPElementAxisImpl(String JavaDoc localPart, String JavaDoc prefix, String JavaDoc namespace)
143    {
144       super(localPart, prefix, namespace);
145       this.namespaceURI = namespace;
146       this.name = localPart;
147       this.prefix = prefix;
148       if (prefix != null && prefix.length() > 0)
149          addMapping(new Mapping(namespace, prefix));
150    }
151
152    public SOAPElementAxisImpl(Name JavaDoc eltName)
153    {
154       super(eltName);
155       this.namespaceURI = eltName.getURI();
156       this.name = eltName.getLocalName();
157       this.prefix = eltName.getPrefix();
158       if (prefix != null && prefix.length() > 0)
159          addMapping(new Mapping(namespaceURI, prefix));
160    }
161
162    public SOAPElementAxisImpl(String JavaDoc namespace, String JavaDoc localPart, Object JavaDoc value)
163    {
164       super(localPart, "", namespace);
165       this.namespaceURI = namespace;
166       this.name = localPart;
167       objectValue = value;
168    }
169
170    public SOAPElementAxisImpl(QName JavaDoc name, Object JavaDoc value)
171    {
172       super(name.getLocalPart(), name.getPrefix(), name.getNamespaceURI());
173       this.namespaceURI = name.getNamespaceURI();
174       this.prefix = name.getPrefix();
175       this.name = name.getLocalPart();
176       objectValue = value;
177    }
178
179    public SOAPElementAxisImpl(Element JavaDoc elem)
180    {
181       super(elem);
182       namespaceURI = elem.getNamespaceURI();
183       prefix = elem.getPrefix();
184       name = elem.getLocalName();
185       elementRep = elem;
186    }
187
188    public SOAPElementAxisImpl(String JavaDoc namespace, String JavaDoc localPart, String JavaDoc prefix, Attributes JavaDoc attributes, DeserializationContext context)
189            throws AxisFault
190    {
191
192       super(localPart, prefix, namespace);
193       this.namespaceURI = namespace;
194       this.name = localPart;
195       this.prefix = prefix;
196
197       if (log.isDebugEnabled())
198       {
199          log.debug(Messages.getMessage("newElem00", super.toString(),
200                  "{" + prefix + "}" + localPart));
201          for (int i = 0; attributes != null && i < attributes.getLength(); i++)
202          {
203             log.debug(" " + attributes.getQName(i) + " = '" + attributes.getValue(i) + "'");
204          }
205       }
206
207       this.context = context;
208       this.startEventIndex = context.getStartOfMappingsPos();
209
210       setNSMappings(context.getCurrentNSMappings());
211
212       this.recorder = context.getRecorder();
213
214       if (attributes != null && attributes.getLength() > 0)
215       {
216          this.attributes = attributes;
217
218          typeQName = context.getTypeFromAttributes(namespace,
219                  localPart,
220                  attributes);
221
222          String JavaDoc rootVal = attributes.getValue(Constants.URI_DEFAULT_SOAP_ENC, Constants.ATTR_ROOT);
223          if (rootVal != null)
224             _isRoot = rootVal.equals("1");
225
226          id = attributes.getValue(Constants.ATTR_ID);
227          // Register this ID with the context.....
228
if (id != null)
229          {
230             context.registerElementByID(id, this);
231             if (recorder == null)
232             {
233                recorder = new SAX2EventRecorder();
234                context.setRecorder(recorder);
235             }
236          }
237
238          // Set the encoding style to the attribute value. If null,
239
// we just automatically use our parent's (see getEncodingStyle)
240
MessageContext mc = context.getMessageContext();
241          SOAPConstants sc = (mc != null) ?
242                  mc.getSOAPConstants() :
243                  SOAPConstants.SOAP11_CONSTANTS;
244
245          href = attributes.getValue(sc.getAttrHref());
246
247          // If there's an arrayType attribute, we can pretty well guess that we're an Array???
248
if (attributes.getValue(Constants.URI_DEFAULT_SOAP_ENC, Constants.ATTR_ARRAY_TYPE) != null)
249             typeQName = Constants.SOAP_ARRAY;
250
251
252          encodingStyle =
253                  attributes.getValue(sc.getEncodingURI(),
254                          Constants.ATTR_ENCODING_STYLE);
255
256          // if no-encoding style was defined, we don't define as well
257
if (Constants.URI_SOAP12_NOENC.equals(encodingStyle))
258             encodingStyle = null;
259
260          // If we have an encoding style, and are not a MESSAGE style
261
// operation (in other words - we're going to do some data
262
// binding), AND we're SOAP 1.2, check the encoding style against
263
// the ones we've got type mappings registered for. If it isn't
264
// registered, throw a DataEncodingUnknown fault as per the
265
// SOAP 1.2 spec.
266
if (encodingStyle != null &&
267                  sc.equals(SOAPConstants.SOAP12_CONSTANTS) &&
268                  (mc.getOperationStyle() != Style.MESSAGE))
269          {
270             TypeMapping JavaDoc tm = mc.getTypeMappingRegistry().
271                     getTypeMapping(encodingStyle);
272             if (tm == null ||
273                     (tm.equals(mc.getTypeMappingRegistry().
274                     getDefaultTypeMapping())))
275             {
276                AxisFault badEncodingFault = new AxisFault(Constants.FAULT_SOAP12_DATAENCODINGUNKNOWN,
277                        "bad encoding style", null, null);
278                throw badEncodingFault;
279             }
280          }
281
282       }
283    }
284
285    /**
286     * !!! TODO : Make sure this handles multiple targets
287     */

288    Deserializer fixupDeserializer;
289
290    public void setFixupDeserializer(Deserializer dser)
291    {
292       // !!! Merge targets here if already set?
293
fixupDeserializer = dser;
294    }
295
296    public Deserializer getFixupDeserializer()
297    {
298       return fixupDeserializer;
299    }
300
301    public void setEndIndex(int endIndex)
302    {
303       endEventIndex = endIndex;
304       //context.setRecorder(null);
305
}
306
307    /**
308     * For ws4ee we should explicitly turn replay of the SAX events of.
309     * This is a bad performance hit, but better than a inconsistent soap tree
310     * [tdi 05-June-2004]
311     */

312    private boolean isDirty;
313
314    public boolean isDirty()
315    {
316       return isDirty;
317       //return true;
318
}
319
320    public void setDirty(boolean dirty)
321    {
322       isDirty = dirty;
323    }
324
325    public boolean isRoot()
326    {
327       return _isRoot;
328    }
329
330    public String JavaDoc getID()
331    {
332       return id;
333    }
334
335    public String JavaDoc getHref()
336    {
337       return href;
338    }
339
340    public Attributes JavaDoc getAttributesEx()
341    {
342       return attributes;
343    }
344
345    public Node JavaDoc getFirstChild()
346    {
347       if (children != null && !children.isEmpty())
348       {
349          return (Node JavaDoc)children.get(0);
350       }
351       else
352       {
353          return null;
354       }
355    }
356
357    public Node JavaDoc getLastChild()
358    {
359       List JavaDoc children = getChildren();
360       if (children != null)
361          return (Node JavaDoc)children.get(children.size() - 1);
362       else
363          return null;
364    }
365
366    public Node JavaDoc getNextSibling()
367    {
368       SOAPElement JavaDoc parent = getParentElement();
369       if (parent == null)
370       {
371          return null;
372       }
373       Iterator JavaDoc iter = parent.getChildElements();
374       Node JavaDoc nextSibling = null;
375       while (iter.hasNext())
376       {
377          if (iter.next().equals(this))
378          {
379             if (iter.hasNext())
380             {
381                return (Node JavaDoc)iter.next();
382             }
383             else
384             {
385                return null;
386             }
387          }
388       }
389       return nextSibling; // should be null.
390
}
391
392    public Node JavaDoc getParentNode()
393    {
394       return parent;
395    }
396
397    public Node JavaDoc getPreviousSibling()
398    {
399       SOAPElement JavaDoc parent = getParentElement();
400       Iterator JavaDoc iter = parent.getChildElements();
401       Node JavaDoc previousSibling = null;
402       while (iter.hasNext())
403       {
404          if (iter.next().equals(this))
405          {
406             return previousSibling;
407          }
408       }
409       return previousSibling; // should be null.
410
}
411
412    public Node JavaDoc cloneNode(boolean deep)
413    {
414       try
415       {
416          SOAPElementAxisImpl clonedSelf = (SOAPElementAxisImpl)this.clonning();
417
418          if (deep == true)
419          {
420             if (children != null)
421             {
422                for (int i = 0; i < children.size(); i++)
423                {
424                   SOAPElementAxisImpl child = (SOAPElementAxisImpl)children.get(i);
425                   if (child != null)
426                   { // why child can be null?
427
SOAPElementAxisImpl clonedChild = (SOAPElementAxisImpl)child.cloneNode(deep); // deep == true
428
clonedChild.setParent(clonedSelf);
429                      clonedChild.setOwnerDocument(soapPart);
430                   }
431                }
432             }
433          }
434          return clonedSelf;
435       }
436       catch (Exception JavaDoc e)
437       {
438          return null;
439       }
440    }
441
442    /**
443     * protected clone method (not public)
444     * <p/>
445     * copied status
446     * -------------------
447     * protected String name ; Y
448     * protected String prefix ; Y
449     * protected String namespaceURI ; Y
450     * protected transient Attributes attributes Y
451     * protected String id; Y?
452     * protected String href; Y?
453     * protected boolean _isRoot = true; Y?
454     * protected SOAPEnvelope message = null; N?
455     * protected boolean _isDirty = false; Y?
456     * protected transient DeserializationContext context; Y?
457     * protected transient QName typeQName = null; Y?
458     * protected Vector qNameAttrs = null; Y?
459     * protected transient SAX2EventRecorder recorder = null; N?
460     * protected int startEventIndex = 0; N?
461     * protected int startContentsIndex = 0; N?
462     * protected int endEventIndex = -1; N?
463     * protected Element elementRep = null; N?
464     * protected MessageElement parent = null; N
465     * public ArrayList namespaces = null; Y
466     * protected String encodingStyle = null; N?
467     * private Object objectValue = null; N?
468     *
469     * @return
470     * @throws CloneNotSupportedException
471     */

472    protected Object JavaDoc clonning() throws CloneNotSupportedException JavaDoc
473    {
474       try
475       {
476          SOAPElementAxisImpl clonedME = null;
477          clonedME = (SOAPElementAxisImpl)this.clone();
478
479          clonedME.setName(name);
480          clonedME.setNamespaceURI(namespaceURI);
481          clonedME.setPrefix(prefix);
482
483          // new AttributesImpl will copy all data not set referencing only
484
clonedME.setAllAttributes(new AttributesImpl JavaDoc(attributes));
485          // clonedME.addNamespaceDeclaration((namespaces.clone()); // cannot do this. since we cannot access the namepace arraylist
486

487          clonedME.namespaces = new ArrayList JavaDoc();
488          if (namespaces != null)
489          {
490             for (int i = 0; i < namespaces.size(); i++)
491             {
492                // jeus.util.Logger.directLog( " Debug : namspace.size() = " + namespaces.size());
493
Mapping namespace = (Mapping)namespaces.get(i);
494                clonedME.addNamespaceDeclaration(namespace.getPrefix(), namespace.getNamespaceURI()); // why exception here!!
495
}
496          }
497          // clear reference to old children
498
clonedME.detachAllChildren();
499
500          // clear parents relationship to old parent
501
clonedME.setParent(null);
502          // clonedME.setObjectValue(objectValue); // how to copy this???
503
clonedME.setDirty(isDirty());
504          if (encodingStyle != null)
505          {
506             clonedME.setEncodingStyle(new String JavaDoc(encodingStyle));
507          }
508          clonedME.setRecorder(recorder);
509          return clonedME;
510       }
511       catch (Exception JavaDoc ex)
512       {
513          return null;
514       }
515    }
516
517    // called in MESerialaizationContext
518
public void setAllAttributes(Attributes JavaDoc attrs)
519    {
520       attributes = attrs;
521    }
522
523    public void detachAllChildren()
524    {
525       children.clear();
526    }
527
528    public NodeList JavaDoc getChildNodes()
529    {
530       NodeListImpl nodeList = new NodeListImpl();
531       for (int i = 0; i < children.size(); i++)
532       {
533          Node JavaDoc node = (Node JavaDoc)children.get(i);
534          nodeList.addNode(node);
535       }
536       return nodeList;
537    }
538
539    public boolean isSupported(String JavaDoc feature, String JavaDoc version)
540    {
541       return false; //TODO: Fix this for SAAJ 1.2 Implementation
542
}
543
544    public Node JavaDoc appendChild(Node JavaDoc newChild) throws DOMException JavaDoc
545    {
546       super.appendChild(newChild);
547       children.add(newChild);
548       return newChild;
549    }
550
551    /**
552     * Note that this method will log a error and no-op if there is
553     * a value (set using setObjectValue) in the MessageElement.
554     */

555    public void addChild(SOAPElementAxisImpl el) throws SOAPException JavaDoc
556    {
557
558       assertImmutable();
559
560       el.parent = this;
561       children.add(el);
562    }
563
564    /**
565     * Throws an JAXRPCException if an attempt is made to modifty this immutable element while
566     * RPCProcessing is going on.
567     */

568    private void assertImmutable()
569    {
570       SOAPEnvelopeAxisImpl env = getSOAPEnvelope();
571       if (env != null && env.isProcessingRPCInvocation() && immutable)
572          throw new JAXRPCException JavaDoc("Cannot modify an immutable element");
573    }
574
575    public Node JavaDoc removeChild(Node JavaDoc oldChild) throws DOMException JavaDoc
576    {
577
578       int position = children.indexOf(oldChild);
579       if (position < 0)
580          throw new DOMException JavaDoc(DOMException.NOT_FOUND_ERR, "MessageElement Not found");
581
582       // Remove all occurrences in case it has been added multiple times.
583
Iterator JavaDoc it = children.iterator();
584       while (it.hasNext())
585       {
586          Node JavaDoc node = (Node JavaDoc)it.next();
587          if (node.equals(oldChild))
588          {
589             log.debug("Remove child node: " + node.getNodeName());
590             it.remove();
591          }
592       }
593
594       setDirty(true);
595       return oldChild;
596    }
597
598    public Node JavaDoc insertBefore(Node JavaDoc newChild, Node JavaDoc refChild) throws DOMException JavaDoc
599    {
600       int position = children.indexOf(refChild);
601       if (position < 0) position = 0;
602       children.add(position, newChild);
603       setDirty(true);
604       return newChild;
605    }
606
607    public Node JavaDoc replaceChild(Node JavaDoc newChild, Node JavaDoc oldChild) throws DOMException JavaDoc
608    {
609       int position = children.indexOf(oldChild);
610       if (position < 0)
611          throw new DOMException JavaDoc(DOMException.NOT_FOUND_ERR, "MessageElement Not found");
612
613       children.remove(position);
614       children.add(position, newChild);
615       setDirty(true);
616       return oldChild;
617    }
618
619    /**
620     * Obtain an Attributes collection consisting of all attributes
621     * for this MessageElement, including namespace declarations.
622     *
623     * @return Attributes collection
624     */

625    public Attributes JavaDoc getCompleteAttributes()
626    {
627       if (namespaces == null)
628          return attributes;
629
630       AttributesImpl JavaDoc attrs = null;
631       if (attributes == NullAttributes.singleton)
632          attrs = new AttributesImpl JavaDoc();
633       else
634          attrs = new AttributesImpl JavaDoc(attributes);
635
636       for (Iterator JavaDoc iterator = namespaces.iterator(); iterator.hasNext();)
637       {
638          Mapping mapping = (Mapping)iterator.next();
639          String JavaDoc prefix = mapping.getPrefix();
640          String JavaDoc nsURI = mapping.getNamespaceURI();
641          attrs.addAttribute(Constants.NS_URI_XMLNS, prefix,
642                  "xmlns:" + prefix, nsURI, "CDATA");
643       }
644       return attrs;
645    }
646
647    public String JavaDoc getName()
648    {
649       return (name);
650    }
651
652    public void setName(String JavaDoc name)
653    {
654       this.name = name;
655    }
656
657    public QName JavaDoc getQName()
658    {
659       return new QName JavaDoc(namespaceURI, name);
660    }
661
662    public void setQName(QName JavaDoc qName)
663    {
664       this.name = qName.getLocalPart();
665       this.namespaceURI = qName.getNamespaceURI();
666    }
667
668    public String JavaDoc getPrefix()
669    {
670       return (prefix);
671    }
672
673    public void setPrefix(String JavaDoc prefix)
674    {
675       this.prefix = prefix;
676    }
677
678    public Document JavaDoc getOwnerDocument()
679    {
680       return soapPart;
681    }
682
683    public NamedNodeMap JavaDoc getAttributes()
684    {
685       // make first it is editable.
686
makeAttributesEditable();
687       return convertAttrSAXtoDOM();
688    }
689
690    /**
691     * [todo] In order to be compatible SAAJ Spec(ver 1.2),
692     * The internal representation of Attributes cannot help being changed
693     * It is because Attribute is not immutible Type, so if we keep out value and
694     * just return it in another form, the application may chnae it, which we cannot
695     * detect without some kind back track method (call back notifying the chnage.)
696     * I am not sure which approach is better.
697     */

698
699    private NamedNodeMap JavaDoc convertAttrSAXtoDOM()
700    {
701       try
702       {
703          org.w3c.dom.Document JavaDoc doc = org.jboss.axis.utils.XMLUtils.newDocument();
704
705          AttributesImpl JavaDoc saxAttrs = (AttributesImpl JavaDoc)attributes;
706          NamedNodeMap JavaDoc domAttributes = new NamedNodeMapImpl();
707          for (int i = 0; i < saxAttrs.getLength(); i++)
708          {
709             String JavaDoc uri = saxAttrs.getURI(i);
710             String JavaDoc qname = saxAttrs.getQName(i);
711             String JavaDoc value = saxAttrs.getValue(i);
712
713             if (uri != null && uri.trim().length() > 0)
714             {
715                // filterring out the tricky method to differentiate the null namespace
716
// -ware case
717
if (uri.equals("intentionalNullURI"))
718                {
719                   uri = null;
720                }
721                
722                if (uri.equals(Constants.NS_URI_XMLNS) && qname.startsWith("xmlns:") == false)
723                   qname = "xmlns:" + qname;
724
725                if (uri.equals(Constants.URI_DEFAULT_SCHEMA_XSI) && qname.startsWith("xsi:") == false)
726                   qname = "xsi:" + qname;
727
728                Attr JavaDoc attr = doc.createAttributeNS(uri, qname);
729                attr.setValue(value);
730                domAttributes.setNamedItemNS(attr);
731             }
732             else
733             {
734
735                Attr JavaDoc attr = doc.createAttribute(qname);
736                attr.setValue(value);
737                domAttributes.setNamedItem(attr);
738             }
739          }
740          return domAttributes;
741
742       }
743       catch (Exception JavaDoc ex)
744       {
745          log.error("Cannot convert SAX to DOM attributes", ex);
746          return null;
747       }
748
749    }
750
751    public short getNodeType()
752    {
753       if (false)
754       {
755          return DOCUMENT_FRAGMENT_NODE;
756       }
757       else if (false)
758       {
759          return Node.ELEMENT_NODE;
760       }
761       else
762       { // most often but we cannot give prioeity now
763
return Node.ELEMENT_NODE;
764       }
765    }
766
767    public void normalize()
768    {
769       //TODO: Fix this for SAAJ 1.2 Implementation
770
}
771
772    public boolean hasAttributes()
773    {
774       return attributes.getLength() > 0;
775    }
776
777    public boolean hasChildNodes()
778    {
779       return children.size() > 0;
780    }
781
782    public String JavaDoc getLocalName()
783    {
784       return name;
785    }
786
787    public String JavaDoc getNamespaceURI()
788    {
789       return (namespaceURI);
790    }
791
792    public String JavaDoc getNodeValue() throws DOMException JavaDoc
793    {
794       throw new DOMException JavaDoc(DOMException.NO_DATA_ALLOWED_ERR,
795               "Cannot use TextNode.get in " + this);
796    }
797
798    public void setNamespaceURI(String JavaDoc nsURI)
799    {
800       namespaceURI = nsURI;
801    }
802
803    public QName JavaDoc getType()
804    {
805       // Try to get the type from our target if we're a reference...
806
if (typeQName == null && href != null && context != null)
807       {
808          SOAPElementAxisImpl referent = context.getElementByID(href);
809          if (referent != null)
810          {
811             typeQName = referent.getType();
812          }
813       }
814       return typeQName;
815    }
816
817    public void setType(QName JavaDoc qname)
818    {
819       typeQName = qname;
820    }
821
822    public SAX2EventRecorder getRecorder()
823    {
824       return recorder;
825    }
826
827    public void setRecorder(SAX2EventRecorder rec)
828    {
829       recorder = rec;
830    }
831
832    /**
833     * Get the encoding style. If ours is null, walk up the hierarchy
834     * and use our parent's. Default if we're the root is "".
835     *
836     * @return the currently in-scope encoding style
837     */

838    public String JavaDoc getEncodingStyle()
839    {
840       if (encodingStyle == null)
841       {
842          if (parent == null)
843             return "";
844          return parent.getEncodingStyle();
845       }
846       return encodingStyle;
847    }
848
849    public void removeContents()
850    {
851       // unlink
852
if (children != null)
853       {
854          for (int i = 0; i < children.size(); i++)
855          {
856             try
857             {
858                ((SOAPElementAxisImpl)children.get(i)).setParent(null);
859             }
860             catch (Exception JavaDoc e)
861             {
862             }
863          }
864          // empty the collection
865
children.clear();
866       }
867    }
868
869    public Iterator JavaDoc getVisibleNamespacePrefixes()
870    {
871       Vector JavaDoc prefixes = new Vector JavaDoc();
872
873       // Add all parents namespace definitions
874
if (parent != null)
875       {
87