KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis2 > om > impl > llom > OMElementImpl


1 /*
2 * Copyright 2004,2005 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.apache.axis2.om.impl.llom;
17
18 import org.apache.axis2.om.*;
19 import org.apache.axis2.om.impl.llom.serialize.StreamWriterToContentHandlerConverter;
20 import org.apache.axis2.om.impl.llom.traverse.OMChildrenIterator;
21 import org.apache.axis2.om.impl.llom.traverse.OMChildrenQNameIterator;
22 import org.apache.axis2.om.impl.llom.util.EmptyIterator;
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25
26 import javax.xml.namespace.QName JavaDoc;
27 import javax.xml.stream.XMLStreamException;
28 import javax.xml.stream.XMLStreamReader;
29 import java.util.HashMap JavaDoc;
30 import java.util.Iterator JavaDoc;
31
32 /**
33  * Class OMElementImpl
34  */

35 public class OMElementImpl extends OMNodeImpl
36         implements OMElement, OMConstants {
37
38     protected OMNamespace ns;
39
40     /**
41      * Field localName
42      */

43     protected String JavaDoc localName;
44     /**
45      * Field firstChild
46      */

47     protected OMNode firstChild;
48
49
50     /**
51      * Field namespaces
52      */

53     protected HashMap JavaDoc namespaces = null;
54
55     /**
56      * Field attributes
57      */

58     protected HashMap JavaDoc attributes = null;
59
60     /**
61      * Field log
62      */

63     private Log log = LogFactory.getLog(getClass());
64
65     /**
66      * Field noPrefixNamespaceCounter
67      */

68     protected int noPrefixNamespaceCounter = 0;
69     private OMNode lastChild;
70
71     /**
72      * Constructor OMElementImpl
73      *
74      * @param localName
75      * @param ns
76      * @param parent
77      * @param builder
78      */

79     public OMElementImpl(String JavaDoc localName, OMNamespace ns, OMContainer parent,
80                          OMXMLParserWrapper builder) {
81         super(parent);
82         this.localName = localName;
83         if (ns != null) {
84             setNamespace(handleNamespace(ns));
85         }
86         this.builder = builder;
87         firstChild = null;
88     }
89
90     /**
91      * @param parent
92      * @param parent
93      */

94     protected OMElementImpl(OMContainer parent) {
95         super(parent);
96         this.done = true;
97     }
98
99     /**
100      * Constructor OMElementImpl
101      *
102      * @param localName
103      * @param ns
104      */

105     public OMElementImpl(String JavaDoc localName, OMNamespace ns) {
106         super(null);
107         this.localName = localName;
108         this.done = true;
109         if (ns != null) {
110             setNamespace(handleNamespace(ns));
111         }
112     }
113
114     public OMElementImpl(String JavaDoc localName, OMNamespace ns, OMContainer parent) {
115         super(parent);
116         this.localName = localName;
117         this.done = true;
118         if (ns != null) {
119             setNamespace(handleNamespace(ns));
120         }
121     }
122
123     /**
124      * Here it is assumed that this QName passed, at least contains the localName for this element
125      *
126      * @param qname
127      * @param parent
128      * @throws OMException
129      */

130     public OMElementImpl(QName JavaDoc qname, OMContainer parent) throws OMException {
131         super(parent);
132         this.localName = qname.getLocalPart();
133         this.done = true;
134         handleNamespace(qname, parent);
135     }
136
137     /**
138      * Method handleNamespace
139      *
140      * @param qname
141      * @param parent
142      */

143     private void handleNamespace(QName JavaDoc qname, OMContainer parent) {
144         OMNamespace ns;
145
146         // first try to find a namespace from the scope
147
String JavaDoc namespaceURI = qname.getNamespaceURI();
148         if (!"".equals(namespaceURI)) {
149             ns = findNamespace(qname.getNamespaceURI(),
150                     qname.getPrefix());
151 // } else {
152
// if (parent != null) {
153
// ns = parent.getNamespace();
154
// } else {
155
// throw new OMException("Element can not be declared without a namespaceURI. Every Element should be namespace qualified");
156
// }
157
// }
158

159             /**
160              * What is left now is
161              * 1. nsURI = null & parent != null, but ns = null
162              * 2. nsURI != null, (parent doesn't have an ns with given URI), but ns = null
163              */

164             if ((ns == null) && !"".equals(namespaceURI)) {
165                 String JavaDoc prefix = qname.getPrefix();
166                 if (!"".equals(prefix)) {
167                     ns = declareNamespace(namespaceURI, prefix);
168                 } else {
169                     ns = declareNamespace(namespaceURI, getNextNamespacePrefix());
170                 }
171             }
172             if (ns != null) {
173                 this.setNamespace(ns);
174 // throw new OMException("Element can not be declared without a namespaceURI. Every Element should be namespace qualified");
175

176             }
177         }
178     }
179
180     /**
181      * Method handleNamespace
182      *
183      * @param ns
184      * @return
185      */

186     private OMNamespace handleNamespace(OMNamespace ns) {
187         OMNamespace namespace = findNamespace(ns.getName(),
188                 ns.getPrefix());
189         if (namespace == null) {
190             namespace = declareNamespace(ns);
191         }
192         return namespace;
193     }
194
195     /**
196      * This will add child to the element. One can decide whether he append the child or he adds to the
197      * front of the children list
198      *
199      * @param child
200      */

201     public void addChild(OMNode child) {
202         addChild((OMNodeImpl) child);
203     }
204
205     /**
206      * This will search for children with a given QName and will return an iterator to traverse through
207      * the OMNodes.
208      * This QName can contain any combination of prefix, localname and URI
209      *
210      * @param elementQName
211      * @return
212      * @throws org.apache.axis2.om.OMException
213      * @throws OMException
214      */

215     public Iterator getChildrenWithName(QName JavaDoc elementQName) throws OMException {
216         return new OMChildrenQNameIterator((OMNodeImpl) getFirstChild(),
217                 elementQName);
218     }
219
220     /**
221      * Method getFirstChildWithName
222      *
223      * @param elementQName
224      * @return
225      * @throws OMException
226      */

227     public OMElement getFirstChildWithName(QName JavaDoc elementQName) throws OMException {
228         OMChildrenQNameIterator omChildrenQNameIterator =
229                 new OMChildrenQNameIterator((OMNodeImpl) getFirstChild(),
230                         elementQName);
231         OMNode omNode = null;
232         if (omChildrenQNameIterator.hasNext()) {
233             omNode = (OMNode) omChildrenQNameIterator.next();
234         }
235
236         return ((omNode != null) && (OMNode.ELEMENT_NODE == omNode.getType())) ? (OMElement) omNode : null;
237
238     }
239
240     /**
241      * Method addChild
242      *
243      * @param child
244      */

245     private void addChild(OMNodeImpl child) {
246         if (firstChild == null) {
247             firstChild = child;
248             child.setPreviousSibling(null);
249         } else {
250             child.setPreviousSibling(lastChild);
251             lastChild.setNextSibling(child);
252         }
253         child.setNextSibling(null);
254         child.setParent(this);
255         lastChild = child;
256
257     }
258
259     /**
260      * This will give the next sibling. This can be an OMAttribute for OMAttribute or OMText or OMELement for others.
261      *
262      * @return
263      * @throws org.apache.axis2.om.OMException
264      * @throws OMException
265      */

266     public OMNode getNextSibling() throws OMException {
267         while (!done) {
268             builder.next();
269         }
270         return super.getNextSibling();
271     }
272
273     /**
274      * This returns a collection of this element.
275      * Children can be of types OMElement, OMText.
276      *
277      * @return
278      */

279     public Iterator getChildren() {
280         return new OMChildrenIterator(getFirstChild());
281     }
282
283     /**
284      * THis will create a namespace in the current element scope
285      *
286      * @param uri
287      * @param prefix
288      * @return
289      */

290     public OMNamespace declareNamespace(String JavaDoc uri, String JavaDoc prefix) {
291         OMNamespaceImpl ns = new OMNamespaceImpl(uri, prefix);
292         return declareNamespace(ns);
293     }
294
295
296     /**
297      * @param namespace
298      * @return
299      */

300     public OMNamespace declareNamespace(OMNamespace namespace) {
301         if (namespaces == null) {
302             this.namespaces = new HashMap JavaDoc(5);
303         }
304         namespaces.put(namespace.getPrefix(), namespace);
305         return namespace;
306     }
307
308     /**
309      * This will find a namespace with the given uri and prefix, in the scope of the docuemnt.
310      * This will start to find from the current element and goes up in the hiararchy until this finds one.
311      * If none is found, return null
312      *
313      * @param uri
314      * @param prefix
315      * @return
316      * @throws org.apache.axis2.om.OMException
317      * @throws OMException
318      */

319     public OMNamespace findNamespace(String JavaDoc uri, String JavaDoc prefix)
320             throws OMException {
321
322         // check in the current element
323
OMNamespace namespace = findDeclaredNamespace(uri, prefix);
324         if (namespace != null) {
325             return namespace;
326         }
327
328         // go up to check with ancestors
329
if (parent != null) {
330             //Comment by Jaya:
331
//For the OMDocument there won't be any explicit namespace
332
//declarations, so going up the parent chain till the document
333
//element should be enough.
334
//If at a later point community decides that some standard
335
//namespaces, like 'xml' which every XML w/ namespaces document
336
//is supposed to contain implicitly, should go into OMDocument then
337
//this 'if' block needs to be revisited.
338
if (parent instanceof OMElement) {
339                 return ((OMElementImpl) parent).findNamespace(uri, prefix);
340             }
341         }
342         return null;
343     }
344
345     /**
346      * This will ckeck for the namespace <B>only</B> in the current Element
347      * This can also be used to retrieve the prefix of a known namespace URI
348      *
349      * @param uri
350      * @param prefix
351      * @return
352      * @throws OMException
353      */

354     private OMNamespace findDeclaredNamespace(String JavaDoc uri, String JavaDoc prefix)
355             throws OMException {
356         if (namespaces == null) {
357             return null;
358         }
359         if (prefix == null || "".equals(prefix)) {
360             Iterator namespaceListIterator = namespaces.values().iterator();
361             while (namespaceListIterator.hasNext()) {
362                 OMNamespace omNamespace =
363                         (OMNamespace) namespaceListIterator.next();
364                 if (omNamespace.getName().equals(uri)) {
365                     return omNamespace;
366                 }
367             }
368             return null;
369         } else {
370             return (OMNamespace) namespaces.get(prefix);
371         }
372     }
373
374     /**
375      * Method getAllDeclaredNamespaces
376      *
377      * @return
378      */

379     public Iterator getAllDeclaredNamespaces() {
380         if (namespaces == null) {
381             return null;
382         }
383         return namespaces.values().iterator();
384     }
385
386     /**
387      * This will help to search for an attribute with a given QName within this Element
388      *
389      * @param qname
390      * @return
391      * @throws org.apache.axis2.om.OMException
392      * @throws OMException
393      */

394     public OMAttribute getFirstAttribute(QName JavaDoc qname) throws OMException {
395         if (attributes == null) {
396             return null;
397         }
398         return (OMAttribute) attributes.get(qname);
399     }
400
401     /**
402      * This will return a List of OMAttributes
403      *
404      * @return
405      */

406     public Iterator getAttributes() {
407         if (attributes == null) {
408             return new EmptyIterator();
409         }
410         return attributes.values().iterator();
411     }
412
413     public Iterator getAttributes(QName JavaDoc qname) {
414         //would there be multiple attributes with the same QName
415
return null; //ToDO
416
}
417
418     /**
419      * This will insert attribute to this element. Implementor can decide as to insert this
420      * in the front or at the end of set of attributes
421      *
422      * @param attr
423      * @return
424      */

425     public OMAttribute addAttribute(OMAttribute attr) {
426         if (attributes == null) {
427             this.attributes = new HashMap JavaDoc(5);
428         }
429         attributes.put(attr.getQName(), attr);
430         return attr;
431     }
432
433     /**
434      * Method removeAttribute
435      *
436      * @param attr
437      */

438     public void removeAttribute(OMAttribute attr) {
439         if (attributes != null) {
440             attributes.remove(attr.getQName());
441         }
442     }
443
444     /**
445      * Method addAttribute
446      *
447      * @param attributeName
448      * @param value
449      * @param ns
450      * @return
451      */

452     public OMAttribute addAttribute(String JavaDoc attributeName, String JavaDoc value,
453                                     OMNamespace ns) {
454         OMNamespace namespace = null;
455         if (ns != null) {
456             namespace = findNamespace(ns.getName(), ns.getPrefix());
457             if (namespace == null) {
458                 throw new OMException("Given OMNamespace(" + ns.getName() + ns.getPrefix()
459                         + ") for "
460                         + "this attribute is not declared in the scope of this element. First declare the namespace"
461                         + " and then use it with the attribute");
462             }
463         }
464         return addAttribute(new OMAttributeImpl(attributeName, ns, value));
465     }
466
467     /**
468      * Method setBuilder
469      *
470      * @param wrapper
471      */

472     public void setBuilder(OMXMLParserWrapper wrapper) {
473         this.builder = wrapper;
474     }
475
476     /**
477      * Method getBuilder
478      *
479      * @return
480      */

481     public OMXMLParserWrapper getBuilder() {
482         return builder;
483     }
484
485     /**
486      * This will force the parser to proceed, if parser has not yet finished with the XML input
487      */

488     public void buildNext() {
489         builder.next();
490     }
491
492     /**
493      * Method getFirstChild
494      *
495      * @return
496      */

497     public OMNode getFirstChild() {
498         while ((firstChild == null) && !done) {
499             buildNext();
500         }
501         return firstChild;
502     }
503
504     /**
505      * Method setFirstChild
506      *
507      * @param firstChild
508      */

509     public void setFirstChild(OMNode firstChild) {
510         this.firstChild = firstChild;
511     }
512
513     /**
514      * This will remove this information item and its children, from the model completely
515      *
516      * @throws org.apache.axis2.om.OMException
517      * @throws OMException
518      */

519     public OMNode detach() throws OMException {
520         if (!done) {
521             build();
522         } else {
523             super.detach();
524         }
525         return this;
526     }
527
528     /**
529      * Method isComplete
530      *
531      * @return
532      */

533     public boolean isComplete() {
534         return done;
535     }
536
537     /**
538      * This is to get the type of node, as this is the super class of all the nodes
539      *
540      * @return
541      * @throws org.apache.axis2.om.OMException
542      * @throws OMException
543      */

544     public int getType() throws OMException {
545         return OMNode.ELEMENT_NODE;
546     }
547
548     /**
549      * @return
550      * @see org.apache.axis2.om.OMElement#getXMLStreamReader()
551      */

552     public XMLStreamReader getXMLStreamReader() {
553         return getXMLStreamReader(true);
554     }
555
556     /**
557      * @return
558      * @see org.apache.axis2.om.OMElement#getXMLStreamReaderWithoutCaching()
559      */

560     public XMLStreamReader getXMLStreamReaderWithoutCaching() {
561         return getXMLStreamReader(false);
562     }
563
564     /**
565      * @param cache
566      * @return
567      */

568     private XMLStreamReader getXMLStreamReader(boolean cache) {
569         if ((builder == null) && !cache) {
570             throw new UnsupportedOperationException JavaDoc("This element was not created in a manner to be switched");
571         }
572         return new OMStAXWrapper(builder, this, cache);
573     }
574
575     /**
576      * Sets the text of the given element.
577      * caution - This method will wipe out all the text elements (and hence any
578      * moxed content) before setting the text
579      *
580      * @param text
581      */

582     public void setText(String JavaDoc text) {
583
584         OMNode child = this.getFirstChild();
585         while (child != null) {
586             if (child.getType() == OMNode.TEXT_NODE) {
587                 child.detach();
588             }
589             child = child.getNextSibling();
590         }
591
592         this.addChild(OMAbstractFactory.getOMFactory().createText(this, text));
593     }
594
595     /**
596      * select all the text children and concat them to a single string
597      *
598      * @return
599      */

600     public String JavaDoc getText() {
601         String JavaDoc childText = "";
602         OMNode child = this.getFirstChild();
603         OMText textNode = null;
604
605         while (child != null) {
606             if (child.getType() == OMNode.TEXT_NODE) {
607                 textNode = (OMText) child;
608                 if (textNode.getText() != null && !"".equals(textNode.getText().trim())) {
609                     childText += textNode.getText().trim();
610                 }
611             }
612             child = child.getNextSibling();
613         }
614
615         return childText;
616     }
617
618     /**
619      * Method serializeWithCache
620      *
621      * @param writer
622      * @throws XMLStreamException
623      */

624     public void serializeWithCache(OMOutput omOutput) throws XMLStreamException {
625         serialize(omOutput, true);
626     }
627
628     ///////////////////////////////////////////////////////////////////////////////////////////////
629
//////////////////////////////////////////////////////////////////////////////////////////////
630

631     protected void serialize(OMOutput omOutput, boolean cache) throws XMLStreamException {
632
633         // select the builder
634
short builderType = PULL_TYPE_BUILDER; // default is pull type
635
if (builder != null) {
636             builderType = this.builder.getBuilderType();
637         }
638         if ((builderType == PUSH_TYPE_BUILDER)
639                 && (builder.getRegisteredContentHandler() == null)) {
640             builder.registerExternalContentHandler(new StreamWriterToContentHandlerConverter(omOutput));
641         }
642
643
644         if (!cache) {
645             //No caching
646
if (this.firstChild != null) {
647                 OMSerializerUtil.serializeStartpart(this, omOutput);
648                 firstChild.serialize(omOutput);
649                 OMSerializerUtil.serializeEndpart(omOutput);
650             } else if (!this.done) {
651                 if (builderType == PULL_TYPE_BUILDER) {
652                     OMSerializerUtil.serializeByPullStream(this, omOutput);
653                 } else {
654                     OMSerializerUtil.serializeStartpart(this, omOutput);
655                     builder.setCache(cache);
656                     builder.next();
657                     OMSerializerUtil.serializeEndpart(omOutput);
658                 }
659             } else {
660                 OMSerializerUtil.serializeNormal(this, omOutput, cache);
661             }
662
663             //serilize siblings
664
if (this.nextSibling != null) {
665                 nextSibling.serialize(omOutput);
666             } else if (this.parent != null) {
667                 if (!this.parent.isComplete()) {
668                     builder.setCache(cache);
669                     builder.next();
670                 }
671             }
672         } else {
673             //Cached
674
OMSerializerUtil.serializeNormal(this, omOutput, cache);
675             // serialize the siblings
676
OMNode nextSibling = this.getNextSibling();
677             if (nextSibling != null) {
678                 nextSibling.serializeWithCache(omOutput);
679             }
680         }
681     }
682
683     ////////////////////////////////////////////////////////////////////////////////////////////////
684
////////////////////////////////////////////////////////////////////////////////////////////////
685

686     /**
687      * This was requested during the second Axis2 summit. When one call this method, this will
688      * serialize without building the object structure in the memory. Misuse of this method will
689      * cause loss of data.So its adviced to use populateYourSelf() method, before this,
690      * if you want to preserve data in the stream.
691      *
692      * @param omOutput
693      * @throws XMLStreamException
694      */

695     public void serialize(OMOutput omOutput) throws XMLStreamException {
696         this.serialize(omOutput, false);
697     }
698
699
700     /**
701      * Method getNextNamespacePrefix
702      *
703      * @return
704      */

705     private String JavaDoc getNextNamespacePrefix() {
706         return "ns" + ++noPrefixNamespaceCounter;
707     }
708
709     public OMElement getFirstElement() {
710         OMNode node = getFirstChild();
711         while (node != null) {
712             if (node.getType() == OMNode.ELEMENT_NODE) {
713                 return (OMElement) node;
714             } else {
715                 node = node.getNextSibling();
716             }
717         }
718         return null;
719     }
720
721 // /* (non-Javadoc)
722
// * @see org.apache.axis2.om.OMElement#getNextSiblingElement()
723
// */
724
// public OMElement getNextSiblingElement() throws OMException {
725
// OMNode node = getNextSibling();
726
// while(node != null){
727
// if(node.getType() == OMNode.ELEMENT_NODE){
728
// return (OMElement)node;
729
// }else{
730
// node = node.getNextSibling();
731
// }
732
// }
733
// return null;
734
// }
735

736
737     /**
738      * Method getLocalName
739      *
740      * @return
741      */

742     public String JavaDoc getLocalName() {
743         return localName;
744     }
745
746     /**
747      * Method setLocalName
748      *
749      * @param localName
750      */

751     public void setLocalName(String JavaDoc localName) {
752         this.localName = localName;
753     }
754
755     /**
756      * Method getNamespace
757      *
758      * @return
759      * @throws OMException
760      */

761     public OMNamespace getNamespace() throws OMException {
762 // if ((ns == null) && (parent != null)) {
763
// ns = parent.getNamespace();
764
// }
765
// if (ns == null) {
766
// throw new OMException("all elements in a soap message must be namespace qualified");
767
// }
768
return ns;
769     }
770
771
772     /**
773      * @param namespace
774      */

775     public void setNamespace(OMNamespace namespace) {
776         if (ns != null) {
777             OMNamespace ns = this.findNamespace(namespace.getName(), namespace.getPrefix());
778             if (ns == null) {
779                 ns = this.declareNamespace(namespace);
780             }
781         }
782         this.ns = namespace;
783     }
784
785     /**
786      * Method getQName
787      *
788      * @return
789      */

790     public QName JavaDoc getQName() {
791         QName JavaDoc qName = null;
792
793         if (ns != null) {
794             if (ns.getPrefix() != null) {
795                 qName = new QName JavaDoc(ns.getName(), localName, ns.getPrefix());
796             } else {
797                 qName = new QName JavaDoc(ns.getName(), localName);
798             }
799         } else {
800             qName = new QName JavaDoc(localName);
801         }
802         return qName;
803     }
804
805     /**
806      * Discard implementation for
807      *
808      * @throws OMException
809      */

810     public void discard() throws OMException {
811         if (done) {
812             this.detach();
813         } else {
814             builder.discard(this);
815         }
816     }
817 }
818
Popular Tags