KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > wsdl > symbolTable > SchemaUtils


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.apache.axis.wsdl.symbolTable;
17
18 import org.apache.axis.Constants;
19 import org.apache.axis.AxisProperties;
20 import org.apache.axis.utils.JavaUtils;
21 import org.w3c.dom.DOMException JavaDoc;
22 import org.w3c.dom.Element JavaDoc;
23 import org.w3c.dom.Node JavaDoc;
24 import org.w3c.dom.NodeList JavaDoc;
25
26 import javax.xml.namespace.QName JavaDoc;
27 import javax.xml.rpc.holders.BooleanHolder JavaDoc;
28 import javax.xml.rpc.holders.IntHolder JavaDoc;
29 import javax.xml.rpc.holders.BooleanHolder JavaDoc;
30 import javax.xml.rpc.holders.QNameHolder JavaDoc;
31 import java.util.Arrays JavaDoc;
32 import java.util.HashSet JavaDoc;
33 import java.util.Set JavaDoc;
34 import java.util.StringTokenizer JavaDoc;
35 import java.util.Vector JavaDoc;
36
37 /**
38  * This class contains static utility methods specifically for schema type queries.
39  *
40  * @author Rich Scheuerle (scheu@us.ibm.com)
41  */

42 public class SchemaUtils {
43
44     /** Field VALUE_QNAME */
45     static final QName JavaDoc VALUE_QNAME = Utils.findQName("", "_value");
46
47     /**
48      * This method checks mixed=true attribute is set either on
49      * complexType or complexContent element.
50      */

51     public static boolean isMixed(Node JavaDoc node) {
52         // Expecting a schema complexType
53
if (isXSDNode(node, "complexType")) {
54             String JavaDoc mixed = ((Element)node).getAttribute("mixed");
55             if (mixed != null && mixed.length() > 0) {
56                 return ("true".equalsIgnoreCase(mixed) ||
57                         "1".equals(mixed));
58             }
59             // Under the complexType there could be complexContent with
60
// mixed="true"
61
NodeList JavaDoc children = node.getChildNodes();
62
63             for (int j = 0; j < children.getLength(); j++) {
64                 Node JavaDoc kid = children.item(j);
65                 if (isXSDNode(kid, "complexContent")) {
66                     mixed = ((Element)kid).getAttribute("mixed");
67                     return ("true".equalsIgnoreCase(mixed) ||
68                             "1".equals(mixed));
69                 }
70             }
71         }
72         return false;
73     }
74
75     public static Node JavaDoc getUnionNode(Node JavaDoc node) {
76         // Expecting a schema complexType
77
if (isXSDNode(node, "simpleType")) {
78             // Under the simpleType there could be union
79
NodeList JavaDoc children = node.getChildNodes();
80             for (int j = 0; j < children.getLength(); j++) {
81                 Node JavaDoc kid = children.item(j);
82                 if (isXSDNode(kid, "union")) {
83                     return kid;
84                 }
85             }
86         }
87         return null;
88     }
89
90     public static Node JavaDoc getListNode(Node JavaDoc node) {
91         // Expecting a schema simpleType
92
if (isXSDNode(node, "simpleType")) {
93             // Under the simpleType there could be list
94
NodeList JavaDoc children = node.getChildNodes();
95             for (int j = 0; j < children.getLength(); j++) {
96                 Node JavaDoc kid = children.item(j);
97                 if (isXSDNode(kid, "list")) {
98                     return kid;
99                 }
100             }
101         }
102         return null;
103     }
104
105     public static boolean isSimpleTypeWithUnion(Node JavaDoc node) {
106         return (getUnionNode(node) != null);
107     }
108
109   /**
110    * This method checks out if the given node satisfies the 3rd condition
111    * of the "wrapper" style:
112    * such an element (a wrapper) must be of a complex type defined using the
113    * xsd:sequence compositor and containing only elements declarations.
114    * (excerpt from JAX-RPC spec 1.1 Maintenanace Review 2 Chapter 6 Section 4.1.)
115    *
116    * @param node
117    * @return
118    */

119   public static boolean isWrappedType(Node JavaDoc node) {
120
121     if (node == null) {
122       return false;
123     }
124
125     // If the node kind is an element, dive into it.
126
if (isXSDNode(node, "element")) {
127       NodeList JavaDoc children = node.getChildNodes();
128       boolean hasComplexType = false;
129       for (int j = 0; j < children.getLength(); j++) {
130         Node JavaDoc kid = children.item(j);
131         if (isXSDNode(kid, "complexType")) {
132           node = kid;
133           hasComplexType = true;
134           break;
135         }
136       }
137       if (!hasComplexType) {
138         return false;
139       }
140     }
141
142     // Expecting a schema complexType
143
if (isXSDNode(node, "complexType")) {
144       // Under the complexType there could be complexContent/simpleContent
145
// and extension elements if this is a derived type.
146
// A wrapper element must be complex-typed.
147

148       NodeList JavaDoc children = node.getChildNodes();
149
150       for (int j = 0; j < children.getLength(); j++) {
151         Node JavaDoc kid = children.item(j);
152
153         if (isXSDNode(kid, "complexContent")) {
154           return false;
155         } else if (isXSDNode(kid, "simpleContent")) {
156           return false;
157         }
158       }
159
160       // Under the complexType there may be choice, sequence, group and/or all nodes.
161
// (There may be other #text nodes, which we will ignore).
162
// The complex type of a wrapper element must have only sequence
163
// and again element declarations in the sequence.
164
children = node.getChildNodes();
165       int len = children.getLength();
166       for (int j = 0; j < len; j++) {
167           Node JavaDoc kid = children.item(j);
168           String JavaDoc localName = kid.getLocalName();
169           if (localName != null &&
170               Constants.isSchemaXSD(kid.getNamespaceURI())) {
171               if (localName.equals("sequence")) {
172                   Node JavaDoc sequenceNode = kid;
173                   NodeList JavaDoc sequenceChildren = sequenceNode.getChildNodes();
174                   int sequenceLen = sequenceChildren.getLength();
175                   for (int k = 0; k < sequenceLen; k++) {
176                       Node JavaDoc sequenceKid = sequenceChildren.item(k);
177                       String JavaDoc sequenceLocalName = sequenceKid.getLocalName();
178                       if (sequenceLocalName != null &&
179                           Constants.isSchemaXSD(sequenceKid.getNamespaceURI())) {
180                           // allow choice with element children
181
if (sequenceLocalName.equals("choice")) {
182                               Node JavaDoc choiceNode = sequenceKid;
183                               NodeList JavaDoc choiceChildren = choiceNode.getChildNodes();
184                               int choiceLen = choiceChildren.getLength();
185                               for (int l = 0; l < choiceLen; l++) {
186                                   Node JavaDoc choiceKid = choiceChildren.item(l);
187                                   String JavaDoc choiceLocalName = choiceKid.getLocalName();
188                                   if (choiceLocalName != null &&
189                                       Constants.isSchemaXSD(choiceKid.getNamespaceURI())) {
190                                       if (!choiceLocalName.equals("element")) {
191                                           return false;
192                                       }
193                                   }
194                               }
195                           }
196                           else
197                           if (!sequenceLocalName.equals("element")) {
198                               return false;
199                           }
200                       }
201                   }
202                   return true;
203               } else {
204                   return false;
205               }
206           }
207       }
208     }
209     // allows void type
210
return true;
211   }
212
213     /**
214      * If the specified node represents a supported JAX-RPC complexType or
215      * simpleType, a Vector is returned which contains ElementDecls for the
216      * child element names.
217      * If the element is a simpleType, an ElementDecls is built representing
218      * the restricted type with the special name "value".
219      * If the element is a complexType which has simpleContent, an ElementDecl
220      * is built representing the extended type with the special name "value".
221      * This method does not return attribute names and types
222      * (use the getContainedAttributeTypes)
223      * If the specified node is not a supported
224      * JAX-RPC complexType/simpleType/element null is returned.
225      *
226      * @param node
227      * @param symbolTable
228      * @return
229      */

230     public static Vector JavaDoc getContainedElementDeclarations(Node JavaDoc node,
231                                                          SymbolTable symbolTable) {
232
233         if (node == null) {
234             return null;
235         }
236
237         // If the node kind is an element, dive into it.
238
if (isXSDNode(node, "element")) {
239             NodeList JavaDoc children = node.getChildNodes();
240
241             for (int j = 0; j < children.getLength(); j++) {
242                 Node JavaDoc kid = children.item(j);
243
244                 if (isXSDNode(kid, "complexType")) {
245                     node = kid;
246
247                     break;
248                 }
249             }
250         }
251
252         // Expecting a schema complexType or simpleType
253
if (isXSDNode(node, "complexType")) {
254
255             // Under the complexType there could be complexContent/simpleContent
256
// and extension elements if this is a derived type. Skip over these.
257
NodeList JavaDoc children = node.getChildNodes();
258             Node JavaDoc complexContent = null;
259             Node JavaDoc simpleContent = null;
260             Node JavaDoc extension = null;
261
262             for (int j = 0; j < children.getLength(); j++) {
263                 Node JavaDoc kid = children.item(j);
264
265                 if (isXSDNode(kid, "complexContent")) {
266                     complexContent = kid;
267
268                     break; // REMIND: should this be here or on either branch?
269
} else if (isXSDNode(kid, "simpleContent")) {
270                     simpleContent = kid;
271                 }
272             }
273
274             if (complexContent != null) {
275                 children = complexContent.getChildNodes();
276
277                 for (int j = 0;
278                      (j < children.getLength()) && (extension == null);
279                      j++) {
280                     Node JavaDoc kid = children.item(j);
281
282                     if (isXSDNode(kid, "extension")
283                             || isXSDNode(kid, "restriction")) {
284                         extension = kid;
285                     }
286                 }
287             }
288
289             if (simpleContent != null) {
290                 children = simpleContent.getChildNodes();
291
292                 int len = children.getLength();
293                 for (int j = 0;
294                      (j < len) && (extension == null);
295                      j++) {
296                     Node JavaDoc kid = children.item(j);
297                     String JavaDoc localName = kid.getLocalName();
298
299                     if ((localName != null)
300                         && (localName.equals("extension") || localName.equals("restriction"))
301                         && Constants.isSchemaXSD(kid.getNamespaceURI())) {
302
303                         // get the type of the extension/restriction from the "base" attribute
304
QName JavaDoc extendsOrRestrictsType =
305                                 Utils.getTypeQName(children.item(j),
306                                         new BooleanHolder JavaDoc(), false);
307
308                         // Return an element declaration with a fixed name
309
// ("value") and the correct type.
310
Vector JavaDoc v = new Vector JavaDoc();
311                         ElementDecl elem = new ElementDecl(symbolTable.getTypeEntry(extendsOrRestrictsType, false), VALUE_QNAME);
312                         v.add(elem);
313
314                         return v;
315                     }
316                 }
317             }
318
319             if (extension != null) {
320                 node = extension; // Skip over complexContent and extension
321
}
322
323             // Under the complexType there may be choice, sequence, group and/or all nodes.
324
// (There may be other #text nodes, which we will ignore).
325
children = node.getChildNodes();
326
327             Vector JavaDoc v = new Vector JavaDoc();
328             int len = children.getLength();
329             for (int j = 0; j < len; j++) {
330                 Node JavaDoc kid = children.item(j);
331                 String JavaDoc localName = kid.getLocalName();
332                 if (localName != null &&
333                     Constants.isSchemaXSD(kid.getNamespaceURI())) {
334                     if (localName.equals("sequence")) {
335                         v.addAll(processSequenceNode(kid, symbolTable));
336                     } else if (localName.equals("all")) {
337                         v.addAll(processAllNode(kid, symbolTable));
338                     } else if (localName.equals("choice")) {
339                         v.addAll(processChoiceNode(kid, symbolTable));
340                     } else if (localName.equals("group")) {
341                         v.addAll(processGroupNode(kid, symbolTable));
342                     }
343                 }
344             }
345
346             return v;
347         } else if (isXSDNode(node, "group")) {
348             /*
349             * Does this else clause make any sense anymore if
350             * we're treating refs to xs:groups like a macro inclusion
351             * into the referencing type?
352             * Maybe this else clause should never be possible?
353             *
354             NodeList children = node.getChildNodes();
355             Vector v = new Vector();
356             int len = children.getLength();
357             for (int j = 0; j < len; j++) {
358                 Node kid = children.item(j);
359                 String localName = kid.getLocalName();
360                 if (localName != null &&
361                     Constants.isSchemaXSD(kid.getNamespaceURI())) {
362                     if (localName.equals("sequence")) {
363                         v.addAll(processSequenceNode(kid, symbolTable));
364                     } else if (localName.equals("all")) {
365                         v.addAll(processAllNode(kid, symbolTable));
366                     } else if (localName.equals("choice")) {
367                         v.addAll(processChoiceNode(kid, symbolTable));
368                     }
369                 }
370             }
371             return v;
372             */

373                 return null;
374         } else {
375
376             // This may be a simpleType, return the type with the name "value"
377
QName JavaDoc[] simpleQName = getContainedSimpleTypes(node);
378
379             if (simpleQName != null) {
380                 Vector JavaDoc v = null;
381
382                 for (int i = 0; i < simpleQName.length; i++) {
383
384                     Type simpleType = symbolTable.getType(simpleQName[i]);
385
386                     if (simpleType != null) {
387                         if (v == null) {
388                             v = new Vector JavaDoc();
389                         }
390
391                         QName JavaDoc qname = null;
392                         if (simpleQName.length > 1) {
393                             qname = new QName JavaDoc("", simpleQName[i].getLocalPart() + "Value");
394                         } else {
395                             qname = new QName JavaDoc("", "value");
396                         }
397
398                         v.add(new ElementDecl(simpleType, qname));
399                     }
400                 }
401
402                 return v;
403             }
404         }
405
406         return null;
407     }
408
409     /**
410      * Invoked by getContainedElementDeclarations to get the child element types
411      * and child element names underneath a Choice Node
412      *
413      * @param choiceNode
414      * @param symbolTable
415      * @return
416      */

417     private static Vector JavaDoc processChoiceNode(Node JavaDoc choiceNode,
418                                             SymbolTable symbolTable) {
419
420         Vector JavaDoc v = new Vector JavaDoc();
421         NodeList JavaDoc children = choiceNode.getChildNodes();
422         int len = children.getLength();
423         for (int j = 0; j < len; j++) {
424             Node JavaDoc kid = children.item(j);
425             String JavaDoc localName = kid.getLocalName();
426             if (localName != null &&
427                 Constants.isSchemaXSD(kid.getNamespaceURI())) {
428                 if (localName.equals("choice")) {
429                     v.addAll(processChoiceNode(kid, symbolTable));
430                 } else if (localName.equals("sequence")) {
431                     v.addAll(processSequenceNode(kid, symbolTable));
432                 } else if (localName.equals("group")) {
433                     v.addAll(processGroupNode(kid, symbolTable));
434                 } else if (localName.equals("element")) {
435                     ElementDecl elem = processChildElementNode(kid,
436                                                                symbolTable);
437
438                     if (elem != null) {
439                         // XXX: forces minOccurs="0" so that a null choice
440
// element can be serialized ok.
441
elem.setMinOccursIs0(true);
442
443                         v.add(elem);
444                     }
445                 } else if (localName.equals("any")) {
446                     // Represent this as an element named any of type any type.
447
// This will cause it to be serialized with the element
448
// serializer.
449
Type type = symbolTable.getType(Constants.XSD_ANY);
450                     ElementDecl elem = new ElementDecl(type,
451                             Utils.findQName("",
452                                     "any"));
453
454                     elem.setAnyElement(true);
455                     v.add(elem);
456                 }
457             }
458         }
459
460         return v;
461     }
462
463     /**
464      * Returns named child node.
465      *
466      * @param parentNode Parent node.
467      * @param name Element name of child node to return.
468      */

469     private static Node JavaDoc getChildByName(Node JavaDoc parentNode, String JavaDoc name) throws DOMException JavaDoc {
470         if (parentNode == null) return null;
471         NodeList JavaDoc children = parentNode.getChildNodes();
472         if (children != null) {
473             for (int i = 0; i < children.getLength(); i++) {
474                 Node JavaDoc child = children.item(i);
475                 if (child != null) {
476                     if (child.getNodeName() != null && name.equals(child.getNodeName())) {
477                         return child;
478                     }
479                 }
480             }
481         }
482         return null;
483     }
484
485     /**
486      * Returns all textual nodes of a subnode defined by a parent node
487      * and a path of element names to that subnode.
488      *
489      * @param root Parent node.
490      * @param path Path of element names to text of interest, delimited by "/".
491      */

492     public static String JavaDoc getTextByPath(Node JavaDoc root, String JavaDoc path) throws DOMException JavaDoc {
493         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(path, "/");
494         Node JavaDoc node = root;
495         while (st.hasMoreTokens()) {
496             String JavaDoc elementName = st.nextToken();
497             Node JavaDoc child = getChildByName(node, elementName);
498             if (child == null)
499                 throw new DOMException JavaDoc(DOMException.NOT_FOUND_ERR, "could not find " + elementName);
500             node = child;
501         }
502
503         // should have found the node
504
String JavaDoc text = "";
505         NodeList JavaDoc children = node.getChildNodes();
506         if (children != null) {
507             for (int i = 0; i < children.getLength(); i++) {
508                 Node JavaDoc child = children.item(i);
509                 if (child != null) {
510                     if (child.getNodeName() != null
511                             && (child.getNodeName().equals("#text")
512                             || child.getNodeName().equals("#cdata-section"))) {
513                         text += child.getNodeValue();
514                     }
515                 }
516             }
517         }
518         return text;
519     }
520
521     /**
522      * Returns the complete text of the child xsd:annotation/xsd:documentation
523      * element from the provided node. Only the first annotation element and
524      * the first documentation element in the annotation element will be used.
525      *
526      * @param typeNode Parent node.
527      */

528     public static String JavaDoc getAnnotationDocumentation(Node JavaDoc typeNode) {
529         Node JavaDoc annotationNode = typeNode.getFirstChild();
530         while (annotationNode != null) {
531             if (isXSDNode(annotationNode, "annotation")) {
532                 break;
533             }
534             annotationNode = annotationNode.getNextSibling();
535         }
536         Node JavaDoc documentationNode;
537         if (annotationNode != null) {
538             documentationNode = annotationNode.getFirstChild();
539             while (documentationNode != null) {
540                 if (isXSDNode(documentationNode, "documentation")) {
541                     break;
542                 }
543                 documentationNode = documentationNode.getNextSibling();
544             }
545         } else {
546             documentationNode = null;
547         }
548
549         // should have found the node if it exists
550
String JavaDoc text = "";
551         if (documentationNode != null) {
552             NodeList JavaDoc children = documentationNode.getChildNodes();
553             if (children != null) {
554                 for (int i = 0; i < children.getLength(); i++) {
555                     Node JavaDoc child = children.item(i);
556                     if (child != null) {
557                         if (child.getNodeName() != null
558                                 && (child.getNodeName().equals("#text")
559                                 || child.getNodeName().equals("#cdata-section"))) {
560                             text += child.getNodeValue();
561                         }
562                     }
563                 }
564             }
565         }
566         return text;
567     }
568
569     /**
570      * Invoked by getContainedElementDeclarations to get the child element types
571      * and child element names underneath a Sequence Node
572      *
573      * @param sequenceNode
574      * @param symbolTable
575      * @return
576      */

577     private static Vector JavaDoc processSequenceNode(Node JavaDoc sequenceNode,
578                                               SymbolTable symbolTable) {
579
580         Vector JavaDoc v = new Vector JavaDoc();
581         NodeList JavaDoc children = sequenceNode.getChildNodes();
582         int len = children.getLength();
583         for (int j = 0; j < len; j++) {
584             Node JavaDoc kid = children.item(j);
585             String JavaDoc localName = kid.getLocalName();
586
587             if (localName != null &&
588                 Constants.isSchemaXSD(kid.getNamespaceURI())) {
589                 if (localName.equals("choice")) {
590                     v.addAll(processChoiceNode(kid, symbolTable));
591                 } else if (localName.equals("sequence")) {
592                     v.addAll(processSequenceNode(kid, symbolTable));
593                 } else if (localName.equals("group")) {
594                     v.addAll(processGroupNode(kid, symbolTable));
595                 } else if (localName.equals("any")) {
596                     // Represent this as an element named any of type any type.
597
// This will cause it to be serialized with the element
598
// serializer.
599
Type type = symbolTable.getType(Constants.XSD_ANY);
600                     ElementDecl elem = new ElementDecl(type,
601                             Utils.findQName("",
602                                     "any"));
603
604                     elem.setAnyElement(true);
605                     v.add(elem);
606                 } else if (localName.equals("element")) {
607                     ElementDecl elem = processChildElementNode(kid,
608                                                                symbolTable);
609
610                     if (elem != null) {
611                         v.add(elem);
612                     }
613                 }
614             }
615         }
616
617         return v;
618     }
619
620     /**
621      * Invoked by getContainedElementDeclarations to get the child element types
622      * and child element names underneath a group node. If a ref attribute is
623      * specified, only the referenced group element is returned.
624      *
625      * @param groupNode
626      * @param symbolTable
627      * @return
628      */

629     private static Vector JavaDoc processGroupNode(Node JavaDoc groupNode,
630                                            SymbolTable symbolTable) {
631
632         Vector JavaDoc v = new Vector JavaDoc();
633         if (groupNode.getAttributes().getNamedItem("ref") == null) {
634             NodeList JavaDoc children = groupNode.getChildNodes();
635             int len = children.getLength();
636             for (int j = 0; j < len; j++) {
637                 Node JavaDoc kid = children.item(j);
638                 String JavaDoc localName = kid.getLocalName();
639                 if (localName != null &&
640                     Constants.isSchemaXSD(kid.getNamespaceURI())) {
641                     if (localName.equals("choice")) {
642                         v.addAll(processChoiceNode(kid, symbolTable));
643                     } else if (localName.equals("sequence")) {
644                         v.addAll(processSequenceNode(kid, symbolTable));
645                     } else if (localName.equals("all")) {
646                         v.addAll(processAllNode(kid, symbolTable));
647                     }
648                 }
649             }
650         } else {
651             QName JavaDoc nodeName = Utils.getNodeNameQName(groupNode);
652             QName JavaDoc nodeType = Utils.getTypeQName(groupNode, new BooleanHolder JavaDoc(), false);
653             // The value of the second argument is 'false' since global model group
654
// definitions are always represented by objects whose type is
655
// assignment compatible with 'org.apache.axis.wsdl.symbolTable.Type'.
656
Type type = (Type) symbolTable.getTypeEntry(nodeType, false);
657
658             if (type != null && type.getNode() != null) {
659                 //v.add(new ElementDecl(type, nodeName));
660
Node JavaDoc node = type.getNode();
661                 NodeList JavaDoc children = node.getChildNodes();
662                 for (int j = 0; j < children.getLength(); j++) {
663                     QName JavaDoc subNodeKind = Utils.getNodeQName(children.item(j));
664                     if ((subNodeKind != null)
665                         && Constants.isSchemaXSD(
666                             subNodeKind.getNamespaceURI())) {
667                         if (subNodeKind.getLocalPart().equals("sequence")) {
668                             v.addAll(processSequenceNode(children.item(j),
669                                  symbolTable));
670                         } else if (subNodeKind.getLocalPart().equals("all")) {
671                             v.addAll(processAllNode(children.item(j), symbolTable));
672                             } else if (subNodeKind.getLocalPart().equals("choice")) {
673                                 v.addAll(processChoiceNode(children.item(j),
674                                     symbolTable));
675                         }
676                     }
677                 }
678             }
679         }
680         return v;
681     }
682
683
684     /**
685      * Invoked by getContainedElementDeclarations to get the child element types
686      * and child element names underneath an all node.
687      *
688      * @param allNode
689      * @param symbolTable
690      * @return
691      */

692     private static Vector JavaDoc processAllNode(Node JavaDoc allNode,
693                                          SymbolTable symbolTable) {
694
695         Vector JavaDoc v = new Vector JavaDoc();
696         NodeList JavaDoc children = allNode.getChildNodes();
697
698         for (int j = 0; j < children.getLength(); j++) {
699             Node JavaDoc kid = children.item(j);
700
701             if (isXSDNode(kid, "element")) {
702                 ElementDecl elem = processChildElementNode(kid, symbolTable);
703
704                 if (elem != null) {
705                     v.add(elem);
706                 }
707             }
708         }
709
710         return v;
711     }
712
713     /**
714      * Invoked by getContainedElementDeclarations to get the child element type
715      * and child element name for a child element node.
716      * <p/>
717      * If the specified node represents a supported JAX-RPC child element,
718      * we return an ElementDecl containing the child element name and type.
719      *
720      * @param elementNode
721      * @param symbolTable
722      * @return
723      */

724     private static ElementDecl processChildElementNode(Node JavaDoc elementNode,
725                                                        SymbolTable symbolTable) {
726
727         // Get the name qnames.
728
QName JavaDoc nodeName = Utils.getNodeNameQName(elementNode);
729         BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
730         String JavaDoc comments = null;
731         comments = getAnnotationDocumentation(elementNode);
732
733         // The type qname is used to locate the TypeEntry, which is then
734
// used to retrieve the proper java name of the type.
735
QName JavaDoc nodeType = Utils.getTypeQName(elementNode, forElement, false);
736         TypeEntry type = symbolTable.getTypeEntry(nodeType,
737                 forElement.value);
738
739         // An element inside a complex type is either qualified or unqualified.
740
// If the ref= attribute is used, the name of the ref'd element is used
741
// (which must be a root element). If the ref= attribute is not
742
// used, the name of the element is unqualified.
743
if (!forElement.value) {
744
745             // check the Form (or elementFormDefault) attribute of this node to
746
// determine if it should be namespace quailfied or not.
747
String JavaDoc form = Utils.getAttribute(elementNode, "form");
748
749             if ((form != null) && form.equals("unqualified")) {
750
751                 // Unqualified nodeName
752
nodeName = Utils.findQName("", nodeName.getLocalPart());
753             } else if (form == null) {
754
755                 // check elementFormDefault on schema element
756
String JavaDoc def = Utils.getScopedAttribute(elementNode,
757                         "elementFormDefault");
758
759                 if ((def == null) || def.equals("unqualified")) {
760
761                     // Unqualified nodeName
762
nodeName = Utils.findQName("", nodeName.getLocalPart());
763                 }
764             }
765         }
766
767         if (type != null) {
768             ElementDecl elem = new ElementDecl(type, nodeName);
769             elem.setDocumentation(comments);
770             String JavaDoc minOccurs = Utils.getAttribute(elementNode,
771                     "minOccurs");
772
773             if ((minOccurs != null) && minOccurs.equals("0")) {
774                 elem.setMinOccursIs0(true);
775             }
776
777             String JavaDoc maxOccurs = Utils.getAttribute(elementNode, "maxOccurs");
778             if (maxOccurs != null) {
779                 if (maxOccurs.equals("unbounded")) {
780                     elem.setMaxOccursIsUnbounded(true);
781                 }
782                 else if(maxOccurs.equals("1")) {
783                     elem.setMaxOccursIsExactlyOne(true);
784                 }
785             }
786             else {
787                 elem.setMaxOccursIsExactlyOne(true);
788             }
789             elem.setNillable(
790                     JavaUtils.isTrueExplicitly(
791                             Utils.getAttribute(elementNode, "nillable")));
792
793             String JavaDoc useValue = Utils.getAttribute(elementNode, "use");
794
795             if (useValue != null) {
796                 elem.setOptional(useValue.equalsIgnoreCase("optional"));
797             }
798
799             return elem;
800         }
801
802         return null;
803     }
804
805     /**
806      * Returns the WSDL2Java QName for the anonymous type of the element
807      * or null.
808      *
809      * @param node
810      * @return
811      */

812     public static QName JavaDoc getElementAnonQName(Node JavaDoc node) {
813
814         if (isXSDNode(node, "element")) {
815             NodeList JavaDoc children = node.getChildNodes();
816
817             for (int j = 0; j < children.getLength(); j++) {
818                 Node JavaDoc kid = children.item(j);
819
820                 if (isXSDNode(kid, "complexType")
821                         || isXSDNode(kid, "simpleType")) {
822                     return Utils.getNodeNameQName(kid);
823                 }
824             }
825         }
826
827         return null;
828     }
829
830     /**
831      * Returns the WSDL2Java QName for the anonymous type of the attribute
832      * or null.
833      *
834      * @param node
835      * @return
836      */

837     public static QName JavaDoc getAttributeAnonQName(Node JavaDoc node) {
838
839         if (isXSDNode(node, "attribute")) {
840             NodeList JavaDoc children = node.getChildNodes();
841
842             for (int j = 0; j < children.getLength(); j++) {
843                 Node JavaDoc kid = children.item(j);
844
845                 if (isXSDNode(kid, "complexType")
846                         || isXSDNode(kid, "simpleType")) {
847                     return Utils.getNodeNameQName(kid);
848                 }
849             }
850         }
851
852         return null;
853     }
854
855     /**
856      * If the specified node is a simple type or contains simpleContent, return true
857      *
858      * @param node
859      * @return
860      */

861     public static boolean isSimpleTypeOrSimpleContent(Node JavaDoc node) {
862
863         if (node == null) {
864             return false;
865         }
866
867         // If the node kind is an element, dive into it.
868
if (isXSDNode(node, "element")) {
869             NodeList JavaDoc children = node.getChildNodes();
870
871             for (int j = 0; j < children.getLength(); j++) {
872                 Node JavaDoc kid = children.item(j);
873
874                 if (isXSDNode(kid, "complexType")) {
875                     node = kid;
876
877                     break;
878                 } else if (isXSDNode(kid, "simpleType")) {
879                     return true;
880                 }
881             }
882         }
883
884         // Expecting a schema complexType or simpleType
885
if (isXSDNode(node, "simpleType")) {
886             return true;
887         }
888
889         if (isXSDNode(node, "complexType")) {
890
891             // Under the complexType there could be complexContent/simpleContent
892
// and extension elements if this is a derived type. Skip over these.
893
NodeList JavaDoc children = node.getChildNodes();
894             Node JavaDoc complexContent = null;
895             Node JavaDoc simpleContent = null;
896
897             for (int j = 0; j < children.getLength(); j++) {
898                 Node JavaDoc kid = children.item(j);
899
900                 if (isXSDNode(kid, "complexContent")) {
901                     complexContent = kid;
902
903                     break;
904                 } else if (isXSDNode(kid, "simpleContent")) {
905                     simpleContent = kid;
906                 }
907             }
908
909             if (complexContent != null) {
910                 return false;
911             }
912
913             if (simpleContent != null) {
914                 return true;
915             }
916         }
917
918         return false;
919     }
920
921     /**
922      * Test whether <tt>node</tt> is not null, belongs to the XML
923      * Schema namespace, and has a localName that matches
924      * <tt>schemaLocalName</tt>
925      * <p/>
926      * This can be used to determine that a given Node defines a
927      * schema "complexType" "element" and so forth.
928      *
929      * @param node a <code>Node</code> value
930      * @param schemaLocalName a <code>String</code> value
931      * @return true if the node is matches the name in the schema namespace.
932      */

933     private static boolean isXSDNode(Node JavaDoc node, String JavaDoc schemaLocalName) {
934         if (node == null) {
935             return false;
936         }
937         String JavaDoc localName = node.getLocalName();
938         if (localName == null) {
939             return false;
940         }
941         return (localName.equals(schemaLocalName) &&
942                 Constants.isSchemaXSD(node.getNamespaceURI()));
943     }
944
945     /**
946      * Look for the base type of node iff node is a complex type that has been
947      * derived by restriction; otherwise return null.
948      *
949      * @param node
950      * @param symbolTable
951      * @return
952      */

953     public static TypeEntry getComplexElementRestrictionBase(Node JavaDoc node,
954                                                              SymbolTable symbolTable) {
955
956         if (node == null) {
957             return null;
958         }
959
960         // If the node kind is an element, dive into it.
961
if (isXSDNode(node, "element")) {
962             NodeList JavaDoc children = node.getChildNodes();
963             Node JavaDoc complexNode = null;
964
965             for (int j = 0;
966                  (j < children.getLength()) && (complexNode == null); j++) {
967                 if (isXSDNode(children.item(j), "complexType")) {
968                     complexNode = children.item(j);
969                     node = complexNode;
970                 }
971             }
972         }
973
974         // Expecting a schema complexType
975
if (isXSDNode(node, "complexType")) {
976
977             // Under the complexType there could be should be a complexContent &
978
// restriction elements if this is a derived type.
979
NodeList JavaDoc children = node.getChildNodes();
980             Node JavaDoc content = null;
981             Node JavaDoc restriction = null;
982
983             for (int j = 0; (j < children.getLength()) && (content == null);
984                  j++) {
985                 Node JavaDoc kid = children.item(j);
986
987                 if (isXSDNode(kid, "complexContent")) {
988                     content = kid;
989                 }
990             }
991
992             if (content != null) {
993                 children = content.getChildNodes();
994
995                 for (int j = 0;
996                      (j < children.getLength()) && (restriction == null);
997                      j++) {
998                     Node JavaDoc kid = children.item(j);
999
1000                    if (isXSDNode(kid, "restriction")) {
1001                        restriction = kid;
1002                    }
1003                }
1004            }
1005
1006            if (restriction == null) {
1007                return null;
1008            } else {
1009
1010                // Get the QName of the extension base
1011
QName JavaDoc restrictionType = Utils.getTypeQName(restriction,
1012                        new BooleanHolder JavaDoc(),
1013                        false);
1014
1015                if (restrictionType == null) {
1016                    return null;
1017                } else {
1018
1019                    // Return associated Type
1020
return symbolTable.getType(restrictionType);
1021                }
1022            }
1023        } else {
1024            return null;
1025        }
1026    }
1027
1028    /**
1029     * If the specified node represents a supported JAX-RPC complexType/element
1030     * which extends another complexType. The Type of the base is returned.
1031     *
1032     * @param node
1033     * @param symbolTable
1034     * @return
1035     */

1036    public static TypeEntry getComplexElementExtensionBase(Node JavaDoc node,
1037                                                           SymbolTable symbolTable) {
1038
1039        if (node == null) {
1040            return null;
1041        }
1042
1043        TypeEntry cached = (TypeEntry) symbolTable.node2ExtensionBase.get(node);
1044
1045        if (cached != null) {
1046            return cached; // cache hit
1047
}
1048
1049        // If the node kind is an element, dive into it.
1050
if (isXSDNode(node, "element")) {
1051            NodeList JavaDoc children = node.getChildNodes();
1052            Node JavaDoc complexNode = null;
1053
1054            for (int j = 0;
1055                 (j < children.getLength()) && (complexNode == null); j++) {
1056                if (isXSDNode(children.item(j), "complexType")) {
1057                    complexNode = children.item(j);
1058                    node = complexNode;
1059                }
1060            }
1061        }
1062
1063        // Expecting a schema complexType
1064
if (isXSDNode(node, "complexType")) {
1065
1066            // Under the complexType there could be should be a complexContent &
1067
// extension elements if this is a derived type.
1068
NodeList JavaDoc children = node.getChildNodes();
1069            Node JavaDoc content = null;
1070            Node JavaDoc extension = null;
1071
1072            for (int j = 0; (j < children.getLength()) && (content == null);
1073                 j++) {
1074                Node JavaDoc kid = children.item(j);
1075
1076                if (isXSDNode(kid, "complexContent")
1077                        || isXSDNode(kid, "simpleContent")) {
1078                    content = kid;
1079                }
1080            }
1081
1082            if (content != null) {
1083                children = content.getChildNodes();
1084
1085                for (int j = 0;
1086                     (j < children.getLength()) && (extension == null);
1087                     j++) {
1088                    Node JavaDoc kid = children.item(j);
1089
1090                    if (isXSDNode(kid, "extension")) {
1091                        extension = kid;
1092                    }
1093                }
1094            }
1095
1096            if (extension == null) {
1097                cached = null;
1098            } else {
1099
1100                // Get the QName of the extension base
1101
QName JavaDoc extendsType = Utils.getTypeQName(extension,
1102                        new BooleanHolder JavaDoc(),
1103                        false);
1104
1105                if (extendsType == null) {
1106                    cached = null;
1107                } else {
1108
1109                    // Return associated Type
1110
cached = symbolTable.getType(extendsType);
1111                }
1112            }
1113        }
1114
1115        symbolTable.node2ExtensionBase.put(node, cached);
1116
1117        return cached;
1118    }
1119
1120    /**
1121     * If the specified node represents a 'normal' non-enumeration simpleType,
1122     * the QName of the simpleType base is returned.
1123     *
1124     * @param node
1125     * @return
1126     */

1127    public static QName JavaDoc getSimpleTypeBase(Node JavaDoc node) {
1128
1129        QName JavaDoc[] qname = getContainedSimpleTypes(node);
1130
1131        if ((qname != null) && (qname.length > 0)) {
1132            return qname[0];
1133        }
1134
1135        return null;
1136    }
1137
1138    /**
1139     * Method getContainedSimpleTypes
1140     *
1141     * @param node
1142     * @return
1143     */

1144    public static QName JavaDoc[] getContainedSimpleTypes(Node JavaDoc node) {
1145
1146        QName JavaDoc[] baseQNames = null;
1147
1148        if (node == null) {
1149            return null;
1150        }
1151
1152        // If the node kind is an element, dive into it.
1153
if (isXSDNode(node, "element")) {
1154            NodeList JavaDoc children = node.getChildNodes();
1155
1156            for (int j = 0; j < children.getLength(); j++) {
1157                if (isXSDNode(children.item(j), "simpleType")) {
1158                    node = children.item(j);
1159
1160                    break;
1161                }
1162            }
1163        }
1164
1165        // Get the node kind, expecting a schema simpleType
1166
if (isXSDNode(node, "simpleType")) {
1167
1168            // Under the simpleType there should be a restriction.
1169
// (There may be other #text nodes, which we will ignore).
1170
NodeList JavaDoc children = node.getChildNodes();
1171            Node JavaDoc restrictionNode = null;
1172            Node JavaDoc unionNode = null;
1173
1174            for (int j = 0;
1175                 (j < children.getLength()) && (restrictionNode == null);
1176                 j++) {
1177                if (isXSDNode(children.item(j), "restriction")) {
1178                    restrictionNode = children.item(j);
1179                } else if (isXSDNode(children.item(j), "union")) {
1180                    unionNode = children.item(j);
1181                }
1182            }
1183
1184            // The restriction node indicates the type being restricted
1185
// (the base attribute contains this type).
1186
if (restrictionNode != null) {
1187                baseQNames = new QName JavaDoc[1];
1188                baseQNames[0] = Utils.getTypeQName(restrictionNode,
1189                        new BooleanHolder JavaDoc(), false);
1190            }
1191
1192            if (unionNode != null) {
1193                baseQNames = Utils.getMemberTypeQNames(unionNode);
1194            }
1195
1196            // Look for enumeration elements underneath the restriction node
1197
if ((baseQNames != null) && (restrictionNode != null)
1198                    && (unionNode != null)) {
1199                NodeList JavaDoc enums = restrictionNode.getChildNodes();
1200
1201                for (int i = 0; i < enums.getLength(); i++) {
1202                    if (isXSDNode(enums.item(i), "enumeration")) {
1203
1204                        // Found an enumeration, this isn't a
1205
// 'normal' simple type.
1206
return null;
1207                    }
1208                }
1209            }
1210        }
1211
1212        return baseQNames;
1213    }
1214
1215    /**
1216     * Returns the contained restriction or extension node underneath
1217     * the specified node. Returns null if not found
1218     *
1219     * @param node
1220     * @return
1221     */

1222    public static Node JavaDoc getRestrictionOrExtensionNode(Node JavaDoc node) {
1223
1224        Node JavaDoc re = null;
1225
1226        if (node == null) {
1227            return re;
1228        }
1229
1230        // If the node kind is an element, dive into it.
1231
if (isXSDNode(node, "element")) {
1232            NodeList JavaDoc children = node.getChildNodes();
1233
1234            for (int j = 0; j < children.getLength(); j++) {
1235                Node JavaDoc n = children.item(j);
1236
1237                if (isXSDNode(n, "simpleType") || isXSDNode(n, "complexType")
1238                        || isXSDNode(n, "simpleContent")) {
1239                    node = n;
1240
1241                    break;
1242                }
1243            }
1244        }
1245
1246        // Get the node kind, expecting a schema simpleType
1247
if (isXSDNode(node, "simpleType") || isXSDNode(node, "complexType")) {
1248
1249            // Under the complexType there could be a complexContent.
1250
NodeList JavaDoc children = node.getChildNodes();
1251            Node JavaDoc complexContent = null;
1252
1253            if (node.getLocalName().equals("complexType")) {
1254                for (int j = 0;
1255                     (j < children.getLength()) && (complexContent == null);
1256                     j++) {
1257                    Node JavaDoc kid = children.item(j);
1258
1259                    if (isXSDNode(kid, "complexContent")
1260                            || isXSDNode(kid, "simpleContent")) {
1261                        complexContent = kid;
1262                    }
1263                }
1264
1265                node = complexContent;
1266            }
1267
1268            // Now get the extension or restriction node
1269
if (node != null) {
1270                children = node.getChildNodes();
1271
1272                for (int j = 0; (j < children.getLength()) && (re == null);
1273                     j++) {
1274                    Node JavaDoc kid = children.item(j);
1275
1276                    if (isXSDNode(kid, "extension")
1277                            || isXSDNode(kid, "restriction")) {
1278                        re = kid;
1279                    }
1280                }
1281            }
1282        }
1283
1284        return re;
1285    }
1286
1287    /**
1288     * If the specified node represents an array encoding of one of the following
1289     * forms, then return the qname repesenting the element type of the array.
1290     *
1291     * @param node is the node
1292     * @param dims is the output value that contains the number of dimensions if return is not null
1293     * @param itemQName will end up containing the "inner" QName for a
1294     * wrapped literal array
1295     * @return QName or null
1296     */

1297    public static QName JavaDoc getArrayComponentQName(Node JavaDoc node,
1298                                               IntHolder JavaDoc dims,
1299                                               BooleanHolder JavaDoc underlTypeNillable,
1300                                               QNameHolder JavaDoc itemQName,
1301                                               SymbolTable symbolTable) {
1302
1303        dims.value = 1; // assume 1 dimension
1304
underlTypeNillable.value = false; // assume underlying type is not nillable
1305

1306        QName JavaDoc qName = getCollectionComponentQName(node, itemQName);
1307
1308        if (qName == null) {
1309            qName = getArrayComponentQName_JAXRPC(node, dims, underlTypeNillable, symbolTable);
1310        }
1311
1312        return qName;
1313    }
1314
1315    /**
1316     * If the specified node represents an element that references a collection
1317     * then return the qname repesenting the component of the collection.
1318     * <p/>
1319     * <xsd:element name="alias" type="xsd:string" maxOccurs="unbounded"/>
1320     * returns qname for"xsd:string"
1321     * <p/>
1322     * <xsd:complexType>
1323     * <xsd:sequence>
1324     * <xsd:element name="alias" type="xsd:string" maxOccurs="unbounded"/>
1325     * </xsd:sequence>
1326     * </xsd:complexType>
1327     * returns qname for"xsd:string"
1328     * <p/>
1329     * <xsd:element ref="alias" maxOccurs="unbounded"/>
1330     * returns qname for "alias"
1331     *
1332     * @param node is the Node
1333     * @return QName of the compoent of the collection
1334     */

1335    public static QName JavaDoc getCollectionComponentQName(Node JavaDoc node,
1336                                                    QNameHolder JavaDoc itemQName) {
1337        // If we're going to turn "wrapped" arrays into types such that
1338
// <complexType><sequence>
1339
// <element name="foo" type="xs:string" maxOccurs="unbounded"/>
1340
// </sequence></complexType>
1341
// becomes just "String []", we need to keep track of the inner
1342
// element name "foo" in metadata... This flag indicates whether to
1343
// do so.
1344
boolean storeComponentQName = false;
1345
1346        if (node == null) {
1347            return null;
1348        }
1349
1350        if (itemQName != null && isXSDNode(node, "complexType")) {
1351            // If this complexType is a sequence of exactly one element
1352
// we will continue processing below using that element, and
1353
// let the type checking logic determine if this is an array
1354
// or not.
1355
Node JavaDoc sequence = SchemaUtils.getChildByName(node, "sequence");
1356            if (sequence == null) {
1357                return null;
1358            }
1359            NodeList JavaDoc children = sequence.getChildNodes();
1360            Node JavaDoc element = null;
1361            for (int i = 0; i < children.getLength(); i++) {
1362                if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
1363                    if (element == null) {
1364                        element = children.item(i);
1365                    } else {
1366                        return null;
1367                    }
1368                }
1369            }
1370            if (element == null) {
1371                return null;
1372            }
1373
1374            // OK, exactly one element child of <sequence>,
1375
// continue the processing using that element ...
1376
node = element;
1377            storeComponentQName = true;
1378        }
1379
1380        // If the node kind is an element, dive to get its type.
1381
if (isXSDNode(node, "element")) {
1382
1383            // Compare the componentQName with the name of the
1384
// full name. If different, return componentQName
1385
BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
1386            QName JavaDoc componentTypeQName = Utils.getTypeQName(node,
1387                                                          forElement,
1388                                                          true);
1389
1390            if (componentTypeQName != null) {
1391                QName JavaDoc fullQName = Utils.getTypeQName(node, forElement, false);
1392
1393                if (!componentTypeQName.equals(fullQName)) {
1394                    if (storeComponentQName) {
1395                        String JavaDoc name = Utils.getAttribute(node, "name");
1396                        if (name != null) {
1397                            // check elementFormDefault on schema element
1398
String JavaDoc def = Utils.getScopedAttribute(node,
1399                                    "elementFormDefault");
1400                            String JavaDoc namespace = "";
1401                            if ((def != null) && def.equals("qualified")) {
1402                                 namespace = Utils.getScopedAttribute(node, "targetNamespace");
1403                            }
1404                            itemQName.value = new QName JavaDoc(namespace, name);
1405                        }
1406                    }
1407                    return componentTypeQName;
1408                }
1409            }
1410        }
1411
1412        return null;
1413    }
1414
1415    /**
1416     * If the specified node represents an array encoding of one of the following
1417     * forms, then return the qname repesenting the element type of the array.
1418     *
1419     * @param node is the node
1420     * @param dims is the output value that contains the number of dimensions if return is not null
1421     * @return QName or null
1422     * <p/>
1423     * JAX-RPC Style 2:
1424     * <xsd:complexType name="hobbyArray">
1425     * <xsd:complexContent>
1426     * <xsd:restriction base="soapenc:Array">
1427     * <xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
1428     * </xsd:restriction>
1429     * </xsd:complexContent>
1430     * </xsd:complexType>
1431     * <p/>
1432     * JAX-RPC Style 3:
1433     * <xsd:complexType name="petArray">
1434     * <xsd:complexContent>
1435     * <xsd:restriction base="soapenc:Array">
1436     * <xsd:sequence>
1437     * <xsd:element name="alias" type="xsd:string" maxOccurs="unbounded"/>
1438     * </xsd:sequence>
1439     * </xsd:restriction>
1440     * </xsd:complexContent>
1441     * </xsd:complexType>
1442     */

1443    private static QName JavaDoc getArrayComponentQName_JAXRPC(Node JavaDoc node,
1444                                                       IntHolder JavaDoc dims,
1445                                                       BooleanHolder JavaDoc underlTypeNillable,
1446                                                       SymbolTable symbolTable)
1447    {
1448
1449        dims.value = 0; // Assume 0
1450
underlTypeNillable.value = false;
1451        if (node == null) {
1452            return null;
1453        }
1454
1455        // If the node kind is an element, dive into it.
1456
if (isXSDNode(node, "element")) {
1457            NodeList JavaDoc children = node.getChildNodes();
1458
1459            for (int j = 0; j < children.getLength(); j++) {
1460                Node JavaDoc kid = children.item(j);
1461
1462                if (isXSDNode(kid, "complexType")) {
1463                    node = kid;
1464
1465                    break;
1466                }
1467            }
1468        }
1469
1470        // Get the node kind, expecting a schema complexType
1471
if (isXSDNode(node, "complexType")) {
1472
1473            // Under the complexType there should be a complexContent.
1474
// (There may be other #text nodes, which we will ignore).
1475
NodeList JavaDoc children = node.getChildNodes();
1476            Node JavaDoc complexContentNode = null;
1477
1478            for (int j = 0; j < children.getLength(); j++) {
1479                Node JavaDoc kid = children.item(j);
1480
1481                if (isXSDNode(kid, "complexContent")
1482                        || isXSDNode(kid, "simpleContent")) {
1483                    complexContentNode = kid;
1484
1485                    break;
1486                }
1487            }
1488
1489            // Under the complexContent there should be a restriction.
1490
// (There may be other #text nodes, which we will ignore).
1491
Node JavaDoc restrictionNode = null;
1492
1493            if (complexContentNode != null) {
1494                children = complexContentNode.getChildNodes();
1495
1496                for (int j = 0; j < children.getLength(); j++) {
1497                    Node JavaDoc kid = children.item(j);
1498
1499                    if (isXSDNode(kid, "restriction")) {
1500                        restrictionNode = kid;
1501
1502                        break;
1503                    }
1504                }
1505            }
1506
1507            // The restriction node must have a base of soapenc:Array.
1508
QName JavaDoc baseType = null;
1509
1510            if (restrictionNode != null) {
1511                baseType = Utils.getTypeQName(restrictionNode,
1512                        new BooleanHolder JavaDoc(), false);
1513
1514                if (baseType != null) {
1515                    if (!baseType.getLocalPart().equals("Array") ||
1516                            !Constants.isSOAP_ENC(baseType.getNamespaceURI())) {
1517                        if (!symbolTable.arrayTypeQNames.contains(baseType)) {
1518                            baseType = null; // Did not find base=soapenc:Array
1519
}
1520                    }
1521                }
1522            }
1523
1524            // Under the restriction there should be an attribute OR a sequence/all group node.
1525
// (There may be other #text nodes, which we will ignore).
1526
Node JavaDoc groupNode = null;
1527            Node JavaDoc attributeNode = null;
1528
1529            if (baseType != null) {
1530                children = restrictionNode.getChildNodes();
1531
1532                for (int j = 0; (j < children.getLength())
1533                        && (groupNode == null)
1534                        && (attributeNode == null); j++) {
1535                    Node JavaDoc kid = children.item(j);
1536
1537                    if (isXSDNode(kid, "sequence") || isXSDNode(kid, "all")) {
1538                        groupNode = kid;
1539
1540                        if (groupNode.getChildNodes().getLength() == 0) {
1541
1542                            // This covers the rather odd but legal empty sequence.
1543
// <complexType name="ArrayOfString">
1544
// <complexContent>
1545
// <restriction base="soapenc:Array">
1546
// <sequence/>
1547
// <attribute ref="soapenc:arrayType" wsdl:arrayType="string[]"/>
1548
// </restriction>
1549
// </complexContent>
1550
// </complexType>
1551
groupNode = null;
1552                        }
1553                    }
1554
1555                    if (isXSDNode(kid, "attribute")) {
1556
1557                        // If the attribute node does not have ref="soapenc:arrayType"
1558
// then keep looking.
1559
BooleanHolder JavaDoc isRef = new BooleanHolder JavaDoc();
1560                        QName JavaDoc refQName = Utils.getTypeQName(kid, isRef,
1561                                false);
1562
1563                        if ((refQName != null) && isRef.value
1564                                && refQName.getLocalPart().equals("arrayType")
1565                                && Constants.isSOAP_ENC(
1566                                        refQName.getNamespaceURI())) {
1567                            attributeNode = kid;
1568                        }
1569                    }
1570                }
1571            }
1572
1573            // If there is an attribute node, look at wsdl:arrayType to get the element type
1574
if (attributeNode != null) {
1575                String JavaDoc wsdlArrayTypeValue = null;
1576                Vector JavaDoc attrs =
1577                        Utils.getAttributesWithLocalName(attributeNode,
1578                                "arrayType");
1579
1580                for (int i = 0;
1581                     (i < attrs.size()) && (wsdlArrayTypeValue == null);
1582                     i++) {
1583                    Node JavaDoc attrNode = (Node JavaDoc) attrs.elementAt(i);
1584                    String JavaDoc attrName = attrNode.getNodeName();
1585                    QName JavaDoc attrQName =
1586                            Utils.getQNameFromPrefixedName(attributeNode, attrName);
1587
1588                    if (Constants.isWSDL(attrQName.getNamespaceURI())) {
1589                        wsdlArrayTypeValue = attrNode.getNodeValue();
1590                    }
1591                }
1592
1593                // The value could have any number of [] or [,] on the end
1594
// Strip these off to get the prefixed name.
1595
// The convert the prefixed name into a qname.
1596
// Count the number of [ and , to get the dim information.
1597
if (wsdlArrayTypeValue != null) {
1598                    int i = wsdlArrayTypeValue.indexOf('[');
1599
1600                    if (i > 0) {
1601                        String JavaDoc prefixedName = wsdlArrayTypeValue.substring(0,
1602                                i);
1603                        String JavaDoc mangledString = wsdlArrayTypeValue.replace(',',
1604                                '[');
1605
1606                        dims.value = 0;
1607
1608                        int index = mangledString.indexOf('[');
1609
1610                        while (index > 0) {
1611                            dims.value++;
1612
1613                            index = mangledString.indexOf('[', index + 1);
1614                        }
1615
1616                        return Utils.getQNameFromPrefixedName(restrictionNode,
1617                                prefixedName);
1618                    }
1619                }
1620            } else if (groupNode != null) {
1621
1622                // Get the first element node under the group node.
1623
NodeList JavaDoc elements = groupNode.getChildNodes();
1624                Node JavaDoc elementNode = null;
1625
1626                for (int i = 0;
1627                     (i < elements.getLength()) && (elementNode == null);
1628                     i++) {
1629                    Node JavaDoc kid = elements.item(i);
1630
1631                    if (isXSDNode(kid, "element")) {
1632                        elementNode = elements.item(i);
1633
1634                        break;
1635                    }
1636                }
1637
1638                // The element node should have maxOccurs="unbounded" and
1639
// a type
1640
if (elementNode != null) {
1641
1642                    String JavaDoc underlTypeNillableValue = Utils.getAttribute(elementNode,
1643                        "nillable");
1644
1645                    if (underlTypeNillableValue != null
1646                            && underlTypeNillableValue.equals("true")) {
1647
1648                        underlTypeNillable.value = true;
1649                    }
1650
1651                    String JavaDoc maxOccursValue = Utils.getAttribute(elementNode,
1652                            "maxOccurs");
1653
1654                    if ((maxOccursValue != null)
1655                            && maxOccursValue.equalsIgnoreCase("unbounded")) {
1656
1657                        // Get the QName of the type without considering maxOccurs
1658
dims.value = 1;
1659
1660                        return Utils.getTypeQName(elementNode,
1661                                new BooleanHolder JavaDoc(), true);
1662                    }
1663                }
1664            }
1665        }
1666
1667        return null;
1668    }
1669
1670    /**
1671     * adds an attribute node's type and name to the vector
1672     * helper used by getContainedAttributeTypes
1673     *
1674     * @param v
1675     * @param child
1676     * @param symbolTable
1677     */

1678    private static void addAttributeToVector(Vector JavaDoc v, Node JavaDoc child,
1679                                             SymbolTable symbolTable) {
1680
1681        // Get the name and type qnames.
1682
// The type qname is used to locate the TypeEntry, which is then
1683
// used to retrieve the proper java name of the type.
1684
QName JavaDoc attributeName = Utils.getNodeNameQName(child);
1685        BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
1686        QName JavaDoc attributeType = Utils.getTypeQName(child, forElement,
1687                false);
1688
1689        // An attribute is either qualified or unqualified.
1690
// If the ref= attribute is used, the name of the ref'd element is used
1691
// (which must be a root element). If the ref= attribute is not
1692
// used, the name of the attribute is unqualified.
1693
if (!forElement.value) {
1694
1695            // check the Form (or attributeFormDefault) attribute of
1696
// this node to determine if it should be namespace
1697
// quailfied or not.
1698
String JavaDoc form = Utils.getAttribute(child, "form");
1699
1700            if ((form != null) && form.equals("unqualified")) {
1701
1702                // Unqualified nodeName
1703
attributeName = Utils.findQName("",
1704                        attributeName.getLocalPart());
1705            } else if (form == null) {
1706
1707                // check attributeFormDefault on schema element
1708
String JavaDoc def = Utils.getScopedAttribute(child,
1709                        "attributeFormDefault");
1710
1711                if ((def == null) || def.equals("unqualified")) {
1712
1713                    // Unqualified nodeName
1714
attributeName =
1715                            Utils.findQName("", attributeName.getLocalPart());
1716                }
1717            }
1718        } else {
1719            attributeName = attributeType;
1720        }
1721
1722        // Get the corresponding TypeEntry from the symbol table
1723
TypeEntry type = symbolTable.getTypeEntry(attributeType,
1724                forElement.value);
1725
1726        // Try to get the corresponding global attribute ElementEntry
1727
// from the symbol table.
1728
if (type instanceof org.apache.axis.wsdl.symbolTable.Element) {
1729                type = ((org.apache.axis.wsdl.symbolTable.Element) type).getRefType();
1730        }
1731
1732        // add type and name to vector, skip it if we couldn't parse it
1733
// XXX - this may need to be revisited.
1734
if ((type != null) && (attributeName != null)) {
1735            ContainedAttribute attr =
1736            new ContainedAttribute(type, attributeName);
1737
1738        String JavaDoc useValue = Utils.getAttribute(child, "use");
1739
1740        if (useValue != null) {
1741        attr.setOptional(useValue.equalsIgnoreCase("optional"));
1742        }
1743
1744            v.add(attr);
1745        }
1746    }
1747
1748    /**
1749     * adds an attribute to the vector
1750     * helper used by addAttributeGroupToVector
1751     *
1752     * @param v
1753     * @param symbolTable
1754     * @param type
1755     * @param name
1756     */

1757    private static void addAttributeToVector(Vector JavaDoc v, SymbolTable symbolTable,
1758                                             QName JavaDoc type, QName JavaDoc name) {
1759
1760        TypeEntry typeEnt = symbolTable.getTypeEntry(type, false);
1761
1762        if (typeEnt != null) // better not be null
1763
{
1764            v.add(new ContainedAttribute(typeEnt, name));
1765        }
1766    }
1767
1768    /**
1769     * adds each attribute group's attribute node to the vector
1770     * helper used by getContainedAttributeTypes
1771     *
1772     * @param v
1773     * @param attrGrpnode
1774     * @param symbolTable
1775     */

1776    private static void addAttributeGroupToVector(Vector JavaDoc v, Node JavaDoc attrGrpnode,
1777                                                  SymbolTable symbolTable) {
1778
1779        // get the type of the attributeGroup
1780
QName JavaDoc attributeGroupType = Utils.getTypeQName(attrGrpnode,
1781                new BooleanHolder JavaDoc(), false);
1782        TypeEntry type =
1783                symbolTable.getTypeEntry(attributeGroupType, false);
1784
1785        if (type != null) {
1786            if (type.getNode() != null) {
1787
1788                // for each attribute or attributeGroup defined in the attributeGroup...
1789
NodeList JavaDoc children = type.getNode().getChildNodes();
1790
1791                for (int j = 0; j < children.getLength(); j++) {
1792                    Node JavaDoc kid = children.item(j);
1793
1794                    if (isXSDNode(kid, "attribute")) {
1795                        addAttributeToVector(v, kid, symbolTable);
1796                    } else if (isXSDNode(kid, "attributeGroup")) {
1797                        addAttributeGroupToVector(v, kid, symbolTable);
1798                    }
1799                }
1800            } else if (type.isBaseType()) {
1801
1802                // soap/encoding is treated as a "known" schema
1803
// so let's act like we know it
1804
if (type.getQName().equals(Constants.SOAP_COMMON_ATTRS11)) {
1805
1806                    // 1.1 commonAttributes contains two attributes
1807
addAttributeToVector(v, symbolTable, Constants.XSD_ID,
1808                            new QName JavaDoc(Constants.URI_SOAP11_ENC,
1809                                    "id"));
1810                    addAttributeToVector(v, symbolTable, Constants.XSD_ANYURI,
1811                            new QName JavaDoc(Constants.URI_SOAP11_ENC,
1812                                    "href"));
1813                } else if (type.getQName().equals(
1814                        Constants.SOAP_COMMON_ATTRS12)) {
1815
1816                    // 1.2 commonAttributes contains one attribute
1817
addAttributeToVector(v, symbolTable, Constants.XSD_ID,
1818                            new QName JavaDoc(Constants.URI_SOAP12_ENC,
1819                                    "id"));
1820                } else if (type.getQName().equals(
1821                        Constants.SOAP_ARRAY_ATTRS11)) {
1822
1823                    // 1.1 arrayAttributes contains two attributes
1824
addAttributeToVector(v, symbolTable, Constants.XSD_STRING,
1825                            new QName JavaDoc(Constants.URI_SOAP12_ENC,
1826                                    "arrayType"));
1827                    addAttributeToVector(v, symbolTable, Constants.XSD_STRING,
1828                            new QName JavaDoc(Constants.URI_SOAP12_ENC,
1829                                    "offset"));
1830                } else if (type.getQName().equals(
1831                        Constants.SOAP_ARRAY_ATTRS12)) {
1832
1833                    // 1.2 arrayAttributes contains two attributes
1834
// the type of "arraySize" is really "2003soapenc:arraySize"
1835
// which is rather of a hairy beast that is not yet supported
1836
// in Axis, so let's just use string; nobody should care for
1837
// now because arraySize wasn't used at all up until this
1838
// bug 23145 was fixed, which had nothing to do, per se, with
1839
// adding support for arraySize
1840
addAttributeToVector(v, symbolTable, Constants.XSD_STRING,
1841                            new QName JavaDoc(Constants.URI_SOAP12_ENC,
1842                                    "arraySize"));
1843                    addAttributeToVector(v, symbolTable, Constants.XSD_QNAME,
1844                            new QName JavaDoc(Constants.URI_SOAP12_ENC,
1845                                    "itemType"));
1846                }
1847            }
1848        }
1849    }
1850
1851    /**
1852     * Return the attribute names and types if any in the node
1853     * The even indices are the attribute types (TypeEntry) and
1854     * the odd indices are the corresponding names (Strings).
1855     * <p/>
1856     * Example:
1857     * <complexType name="Person">
1858     * <sequence>
1859     * <element minOccurs="1" maxOccurs="1" name="Age" type="double" />
1860     * <element minOccurs="1" maxOccurs="1" name="ID" type="xsd:float" />
1861     * </sequence>
1862     * <attribute name="Name" type="string" />
1863     * <attribute name="Male" type="boolean" />
1864     * <attributeGroup ref="s0:MyAttrSet" />
1865     * </complexType>
1866     *
1867     * @param node
1868     * @param symbolTable
1869     * @return
1870     */

1871    public static Vector JavaDoc getContainedAttributeTypes(Node JavaDoc node,
1872                                                    SymbolTable symbolTable) {
1873
1874        Vector JavaDoc v = null; // return value
1875

1876        if (node == null) {
1877            return null;
1878        }
1879
1880        // Check for SimpleContent
1881
// If the node kind is an element, dive into it.
1882
if (isXSDNode(node, "element")) {
1883            NodeList JavaDoc children = node.getChildNodes();
1884            int len = children.getLength();
1885            for (int j = 0; j < len; j++) {
1886                Node JavaDoc kid = children.item(j);
1887
1888                if (isXSDNode(kid, "complexType")) {
1889                    node = kid;
1890
1891                    break;
1892                }
1893            }
1894        }
1895
1896        // Expecting a schema complexType
1897
if (isXSDNode(node, "complexType")) {
1898
1899            // Under the complexType there could be complexContent/simpleContent
1900
// and extension elements if this is a derived type. Skip over these.
1901
NodeList JavaDoc children = node.getChildNodes();
1902            Node JavaDoc content = null;
1903            int len = children.getLength();
1904            for (int j = 0; j < len; j++) {
1905                Node JavaDoc kid = children.item(j);
1906
1907                if (isXSDNode(kid, "complexContent")
1908                        || isXSDNode(kid, "simpleContent")) {
1909                    content = kid;
1910
1911                    break;
1912                }
1913            }
1914
1915            // Check for extensions or restrictions
1916
if (content != null) {
1917                children = content.getChildNodes();
1918                len = children.getLength();
1919                for (int j = 0; j < len; j++) {
1920                    Node JavaDoc kid = children.item(j);
1921
1922                    if (isXSDNode(kid, "extension")
1923                            || isXSDNode(kid, "restriction")) {
1924                        node = kid;
1925
1926                        break;
1927                    }
1928                }
1929            }
1930
1931            // examine children of the node for <attribute> elements
1932
children = node.getChildNodes();
1933            len = children.getLength();
1934            for (int i = 0; i < len; i++) {
1935                Node JavaDoc child = children.item(i);
1936
1937                if (isXSDNode(child, "attributeGroup")) {
1938                    if (v == null) {
1939                        v = new Vector JavaDoc();
1940                    }
1941                    addAttributeGroupToVector(v, child, symbolTable);
1942                } else if (isXSDNode(child, "anyAttribute")) {
1943                    // do nothing right now
1944
if (v == null) {
1945                        v = new Vector JavaDoc();
1946                    }
1947                } else if (isXSDNode(child, "attribute")) {
1948                    // we have an attribute
1949
if (v == null) {
1950                        v = new Vector JavaDoc();
1951                    }
1952                    addAttributeToVector(v, child, symbolTable);
1953                }
1954            }
1955        }
1956
1957        return v;
1958    }
1959
1960    // list of all of the XSD types in Schema 2001
1961

1962    /** Field schemaTypes[] */
1963    private static String JavaDoc schemaTypes[] = {
1964        "string", "normalizedString", "token", "byte", "unsignedByte",
1965        "base64Binary", "hexBinary", "integer", "positiveInteger",
1966        "negativeInteger", "nonNegativeInteger", "nonPositiveInteger", "int",
1967        "unsignedInt", "long", "unsignedLong", "short", "unsignedShort",
1968        "decimal", "float", "double", "boolean", "time", "dateTime", "duration",
1969        "date", "gMonth", "gYear", "gYearMonth", "gDay", "gMonthDay", "Name",
1970        "QName", "NCName", "anyURI", "language", "ID", "IDREF", "IDREFS",
1971        "ENTITY", "ENTITIES", "NOTATION", "NMTOKEN", "NMTOKENS",
1972        "anySimpleType"
1973    };
1974
1975    /** Field schemaTypeSet */
1976    private static final Set JavaDoc schemaTypeSet =
1977            new HashSet JavaDoc(Arrays.asList(schemaTypes));
1978
1979    /**
1980     * Determine if a string is a simple XML Schema type
1981     *
1982     * @param s
1983     * @return
1984     */

1985    private static boolean isSimpleSchemaType(String JavaDoc s) {
1986
1987        if (s == null) {
1988            return false;
1989        }
1990
1991        return schemaTypeSet.contains(s);
1992    }
1993
1994    /**
1995     * Determine if a QName is a simple XML Schema type
1996     *
1997     * @param qname
1998     * @return
1999     */

2000    public static boolean isSimpleSchemaType(QName JavaDoc qname) {
2001
2002        if ((qname == null) || !Constants.isSchemaXSD(qname.getNamespaceURI())) {
2003            return false;
2004        }
2005
2006        return isSimpleSchemaType(qname.getLocalPart());
2007    }
2008
2009    /**
2010     * Returns the base type of a given type with its symbol table.
2011     * This logic is extracted from JavaTypeWriter's constructor() method
2012     * for reusing.
2013     *
2014     * @param type
2015     * @param symbolTable
2016     * @return
2017     */

2018    public static TypeEntry getBaseType(TypeEntry type, SymbolTable symbolTable) {
2019        Node JavaDoc node = type.getNode();
2020        TypeEntry base = getComplexElementExtensionBase(
2021                node, symbolTable);
2022        if (base == null) {
2023            base = getComplexElementRestrictionBase(node, symbolTable);
2024        }
2025
2026        if (base == null) {
2027            QName JavaDoc baseQName = getSimpleTypeBase(node);
2028            if (baseQName != null) {
2029                base = symbolTable.getType(baseQName);
2030            }
2031        }
2032        return base;
2033    }
2034
2035    /**
2036     * Returns whether the specified node represents a <xsd:simpleType>
2037     * with a nested <xsd:list itemType="...">.
2038     * @param node
2039     * @return
2040     */

2041    public static boolean isListWithItemType(Node JavaDoc node) {
2042
2043        return getListItemType(node) != null;
2044    }
2045
2046    /**
2047     * Returns the value of itemType attribute of <xsd:list> in <xsd:simpleType>
2048     * @param node
2049     * @return
2050     */

2051    public static QName JavaDoc getListItemType(Node JavaDoc node) {
2052
2053        if (node == null) {
2054            return null;
2055        }
2056
2057        // If the node kind is an element, dive into it.
2058
if (isXSDNode(node, "element")) {
2059            NodeList JavaDoc children = node.getChildNodes();
2060            for (int j = 0; j < children.getLength(); j++) {
2061                if (isXSDNode(children.item(j), "simpleType")) {
2062                    node = children.item(j);
2063                    break;
2064                }
2065            }
2066        }
2067        // Get the node kind, expecting a schema simpleType
2068
if (isXSDNode(node, "simpleType")) {
2069            NodeList JavaDoc children = node.getChildNodes();
2070            for (int j = 0; j < children.getLength(); j++) {
2071                if (isXSDNode(children.item(j), "list")) {
2072                    Node JavaDoc listNode = children.item(j);
2073                    org.w3c.dom.Element JavaDoc listElement =
2074                    (org.w3c.dom.Element JavaDoc) listNode;
2075                    String JavaDoc type = listElement.getAttribute("itemType");
2076                    if (type.equals("")) {
2077                        Node JavaDoc localType = null;
2078                        children = listNode.getChildNodes();
2079                        for (j = 0; j < children.getLength() && localType == null; j++) {
2080                            if (isXSDNode(children.item(j), "simpleType")) {
2081                                localType = children.item(j);
2082                            }
2083                        }
2084                        if (localType != null) {
2085                            return getSimpleTypeBase(localType);
2086                        }
2087                        return null;
2088                    }
2089                    //int colonIndex = type.lastIndexOf(":");
2090
//if (colonIndex > 0) {
2091
//type = type.substring(colonIndex + 1);
2092
//}
2093
//return new QName(Constants.URI_2001_SCHEMA_XSD, type + "[]");
2094
return Utils.getQNameFromPrefixedName(node, type);
2095                }
2096            }
2097        }
2098        return null;
2099    }
2100}
2101
Popular Tags