KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2001-2003 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Axis" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation. For more
52  * information on the Apache Software Foundation, please see
53  * <http://www.apache.org/>.
54  */

55 package org.jboss.axis.wsdl.symbolTable;
56
57 import org.jboss.axis.Constants;
58 import org.w3c.dom.Node JavaDoc;
59 import org.w3c.dom.NodeList JavaDoc;
60
61 import javax.xml.namespace.QName JavaDoc;
62 import javax.xml.rpc.holders.BooleanHolder JavaDoc;
63 import javax.xml.rpc.holders.IntHolder JavaDoc;
64 import java.util.Arrays JavaDoc;
65 import java.util.HashSet JavaDoc;
66 import java.util.Set JavaDoc;
67 import java.util.Vector JavaDoc;
68
69 /**
70  * This class contains static utility methods specifically for schema type queries.
71  *
72  * @author Rich Scheuerle (scheu@us.ibm.com)
73  */

74 public class SchemaUtils
75 {
76
77    static final QName JavaDoc VALUE_QNAME = Utils.findQName("", "value");
78
79    /**
80     * If the specified node represents a supported JAX-RPC complexType or
81     * simpleType, a Vector is returned which contains ElementDecls for the
82     * child element names.
83     * If the element is a simpleType, an ElementDecls is built representing
84     * the restricted type with the special name "value".
85     * If the element is a complexType which has simpleContent, an ElementDecl
86     * is built representing the extended type with the special name "value".
87     * This method does not return attribute names and types
88     * (use the getContainedAttributeTypes)
89     * If the specified node is not a supported
90     * JAX-RPC complexType/simpleType/element null is returned.
91     */

92    public static Vector JavaDoc getContainedElementDeclarations(Node JavaDoc node, SymbolTable symbolTable)
93    {
94       if (node == null)
95       {
96          return null;
97       }
98
99       // If the node kind is an element, dive into it.
100
if (isXSDNode(node, "element"))
101       {
102          NodeList JavaDoc children = node.getChildNodes();
103          for (int j = 0; j < children.getLength(); j++)
104          {
105             Node JavaDoc kid = children.item(j);
106             if (isXSDNode(kid, "complexType"))
107             {
108                node = kid;
109                break;
110             }
111          }
112       }
113
114       // Expecting a schema complexType or simpleType
115
if (isXSDNode(node, "complexType"))
116       {
117          // Under the complexType there could be complexContent/simpleContent
118
// and extension elements if this is a derived type. Skip over these.
119
NodeList JavaDoc children = node.getChildNodes();
120          Node JavaDoc complexContent = null;
121          Node JavaDoc simpleContent = null;
122          Node JavaDoc extension = null;
123          for (int j = 0; j < children.getLength(); j++)
124          {
125             Node JavaDoc kid = children.item(j);
126             if (isXSDNode(kid, "complexContent"))
127             {
128                complexContent = kid;
129                break; // REMIND: should this be here or on either branch?
130
}
131             else if (isXSDNode(kid, "simpleContent"))
132             {
133                simpleContent = kid;
134             }
135          }
136          if (complexContent != null)
137          {
138             children = complexContent.getChildNodes();
139             for (int j = 0; j < children.getLength() && extension == null; j++)
140             {
141                Node JavaDoc kid = children.item(j);
142                if (isXSDNode(kid, "extension"))
143                {
144                   extension = kid;
145                }
146             }
147          }
148          if (simpleContent != null)
149          {
150             children = simpleContent.getChildNodes();
151             for (int j = 0; j < children.getLength() && extension == null; j++)
152             {
153                QName JavaDoc extensionOrRestrictionKind = Utils.getNodeQName(children.item(j));
154                if (extensionOrRestrictionKind != null &&
155                        (extensionOrRestrictionKind.getLocalPart().equals("extension") ||
156                        extensionOrRestrictionKind.getLocalPart().equals("restriction")) &&
157                        Constants.isSchemaXSD(extensionOrRestrictionKind.getNamespaceURI()))
158                {
159
160                   // get the type of the extension/restriction from the "base" attribute
161
QName JavaDoc extendsOrRestrictsType =
162                           Utils.getTypeQName(children.item(j), new BooleanHolder JavaDoc(), false);
163
164                   // Return an element declaration with a fixed name
165
// ("value") and the correct type.
166
Vector JavaDoc v = new Vector JavaDoc();
167                   ElementDecl elem = new ElementDecl();
168                   elem.setType(symbolTable.getTypeEntry(extendsOrRestrictsType, false));
169                   elem.setName(VALUE_QNAME);
170                   v.add(elem);
171                   return v;
172                }
173             }
174          }
175
176          if (extension != null)
177          {
178             node = extension; // Skip over complexContent and extension
179
}
180
181          // Under the complexType there may be choice, sequence, group and/or all nodes.
182
// (There may be other #text nodes, which we will ignore).
183
children = node.getChildNodes();
184          Vector JavaDoc v = new Vector JavaDoc();
185          for (int j = 0; j < children.getLength(); j++)
186          {
187             QName JavaDoc subNodeKind = Utils.getNodeQName(children.item(j));
188             if (subNodeKind != null &&
189                     Constants.isSchemaXSD(subNodeKind.getNamespaceURI()))
190             {
191                if (subNodeKind.getLocalPart().equals("sequence"))
192                {
193                   v.addAll(processSequenceNode(children.item(j), symbolTable));
194                }
195                else if (subNodeKind.getLocalPart().equals("all"))
196                {
197                   v.addAll(processAllNode(children.item(j), symbolTable));
198                }
199                else if (subNodeKind.getLocalPart().equals("choice"))
200                {
201                   v.addAll(processChoiceNode(children.item(j), symbolTable));
202                }
203                else if (subNodeKind.getLocalPart().equals("group"))
204                {
205                   v.addAll(processGroupNode(children.item(j), symbolTable));
206                }
207             }
208          }
209          return v;
210       }
211       else
212       {
213          // This may be a simpleType, return the type with the name "value"
214
QName JavaDoc simpleQName = getSimpleTypeBase(node);
215          if (simpleQName != null)
216          {
217             TypeEntry simpleType = symbolTable.getType(simpleQName);
218             if (simpleType != null)
219             {
220                Vector JavaDoc v = new Vector JavaDoc();
221                ElementDecl elem = new ElementDecl();
222                elem.setType(simpleType);
223                elem.setName(new javax.xml.namespace.QName JavaDoc("", "value"));
224                v.add(elem);
225                return v;
226             }
227          }
228       }
229       return null;
230    }
231
232    /**
233     * Invoked by getContainedElementDeclarations to get the child element types
234     * and child element names underneath a Choice Node
235     */

236    private static Vector JavaDoc processChoiceNode(Node JavaDoc choiceNode,
237                                            SymbolTable symbolTable)
238    {
239       Vector JavaDoc v = new Vector JavaDoc();
240       NodeList JavaDoc children = choiceNode.getChildNodes();
241       for (int j = 0; j < children.getLength(); j++)
242       {
243          QName JavaDoc subNodeKind = Utils.getNodeQName(children.item(j));
244          if (subNodeKind != null &&
245                  Constants.isSchemaXSD(subNodeKind.getNamespaceURI()))
246          {
247             if (subNodeKind.getLocalPart().equals("choice"))
248             {
249                v.addAll(processChoiceNode(children.item(j), symbolTable));
250             }
251             else if (subNodeKind.getLocalPart().equals("sequence"))
252             {
253                v.addAll(processSequenceNode(children.item(j), symbolTable));
254             }
255             else if (subNodeKind.getLocalPart().equals("group"))
256             {
257                v.addAll(processGroupNode(children.item(j), symbolTable));
258             }
259             else if (subNodeKind.getLocalPart().equals("element"))
260             {
261                ElementDecl elem =
262                        processChildElementNode(children.item(j),
263                                symbolTable);
264                if (elem != null)
265                   v.add(elem);
266             }
267          }
268       }
269       return v;
270    }
271
272    /**
273     * Invoked by getContainedElementDeclarations to get the child element types
274     * and child element names underneath a Sequence Node
275     */

276    private static Vector JavaDoc processSequenceNode(Node JavaDoc sequenceNode,
277                                              SymbolTable symbolTable)
278    {
279       Vector JavaDoc v = new Vector JavaDoc();
280       NodeList JavaDoc children = sequenceNode.getChildNodes();
281       for (int j = 0; j < children.getLength(); j++)
282       {
283          QName JavaDoc subNodeKind = Utils.getNodeQName(children.item(j));
284          if (subNodeKind != null &&
285                  Constants.isSchemaXSD(subNodeKind.getNamespaceURI()))
286          {
287             if (subNodeKind.getLocalPart().equals("choice"))
288             {
289                v.addAll(processChoiceNode(children.item(j), symbolTable));
290             }
291             else if (subNodeKind.getLocalPart().equals("sequence"))
292             {
293                v.addAll(processSequenceNode(children.item(j), symbolTable));
294             }
295             else if (subNodeKind.getLocalPart().equals("group"))
296             {
297                v.addAll(processGroupNode(children.item(j), symbolTable));
298             }
299             else if (subNodeKind.getLocalPart().equals("any"))
300             {
301                // Represent this as an element named any of type any type.
302
// This will cause it to be serialized with the element
303
// serializer.
304
TypeEntry type = symbolTable.getType(Constants.XSD_ANY);
305                ElementDecl elem =
306                        new ElementDecl(type, Utils.findQName("", "any"));
307                elem.setAnyElement(true);
308                v.add(elem);
309             }
310             else if (subNodeKind.getLocalPart().equals("element"))
311             {
312                ElementDecl elem =
313                        processChildElementNode(children.item(j),
314                                symbolTable);
315                if (elem != null)
316                   v.add(elem);
317             }
318          }
319       }
320       return v;
321    }
322
323    /**
324     * Invoked by getContainedElementDeclarations to get the child element types
325     * and child element names underneath a group node.
326     * (Currently the code only supports a defined group it does not
327     * support a group that references a previously defined group)
328     */

329    private static Vector JavaDoc processGroupNode(Node JavaDoc groupNode, SymbolTable symbolTable)
330    {
331       Vector JavaDoc v = new Vector JavaDoc();
332       NodeList JavaDoc children = groupNode.getChildNodes();
333       for (int j = 0; j < children.getLength(); j++)
334       {
335          QName JavaDoc subNodeKind = Utils.getNodeQName(children.item(j));
336          if (subNodeKind != null &&
337                  Constants.isSchemaXSD(subNodeKind.getNamespaceURI()))
338          {
339             if (subNodeKind.getLocalPart().equals("choice"))
340             {
341                v.addAll(processChoiceNode(children.item(j), symbolTable));
342             }
343             else if (subNodeKind.getLocalPart().equals("sequence"))
344             {
345                v.addAll(processSequenceNode(children.item(j), symbolTable));
346             }
347             else if (subNodeKind.getLocalPart().equals("all"))
348             {
349                v.addAll(processAllNode(children.item(j), symbolTable));
350             }
351          }
352       }
353       return v;
354    }
355
356    /**
357     * Invoked by getContainedElementDeclarations to get the child element types
358     * and child element names underneath an all node.
359     */

360    private static Vector JavaDoc processAllNode(Node JavaDoc allNode, SymbolTable symbolTable)
361    {
362       Vector JavaDoc v = new Vector JavaDoc();
363       NodeList JavaDoc children = allNode.getChildNodes();
364       for (int j = 0; j < children.getLength(); j++)
365       {
366          Node JavaDoc kid = children.item(j);
367          if (isXSDNode(kid, "element"))
368          {
369             ElementDecl elem = processChildElementNode(kid, symbolTable);
370             if (elem != null)
371             {
372                v.add(elem);
373             }
374          }
375       }
376       return v;
377    }
378
379
380    /**
381     * Invoked by getContainedElementDeclarations to get the child element type
382     * and child element name for a child element node.
383     * <p/>
384     * If the specified node represents a supported JAX-RPC child element,
385     * we return an ElementDecl containing the child element name and type.
386     */

387    private static ElementDecl processChildElementNode(Node JavaDoc elementNode,
388                                                       SymbolTable symbolTable)
389    {
390       // Get the name qnames.
391
QName JavaDoc nodeName = Utils.getNodeNameQName(elementNode);
392       BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
393
394       // The type qname is used to locate the TypeEntry, which is then
395
// used to retrieve the proper java name of the type.
396
QName JavaDoc nodeType = Utils.getTypeQName(elementNode, forElement, false);
397
398       TypeEntry type = symbolTable.getTypeEntry(nodeType, forElement.value);
399
400       // An element inside a complex type is either qualified or unqualified.
401
// If the ref= attribute is used, the name of the ref'd element is used
402
// (which must be a root element). If the ref= attribute is not
403
// used, the name of the element is unqualified.
404

405       if (!forElement.value)
406       {
407          // check the Form (or elementFormDefault) attribute of this node to
408
// determine if it should be namespace quailfied or not.
409
String JavaDoc form = Utils.getAttribute(elementNode, "form");
410          if (form != null && form.equals("unqualified"))
411          {
412             // Unqualified nodeName
413
nodeName = Utils.findQName("", nodeName.getLocalPart());
414          }
415          else if (form == null)
416          {
417             // check elementForDefault on schema element
418
String JavaDoc def = Utils.getScopedAttribute(elementNode,
419                     "elementFormDefault");
420             if (def == null || def.equals("unqualified"))
421             {
422                // Unqualified nodeName
423
nodeName = Utils.findQName("", nodeName.getLocalPart());
424             }
425          }
426       }
427
428       if (type != null)
429       {
430          ElementDecl elem = new ElementDecl(type, nodeName);
431          String JavaDoc minOccurs = Utils.getAttribute(elementNode, "minOccurs");
432          if (minOccurs != null && minOccurs.equals("0"))
433          {
434             elem.setMinOccursIs0(true);
435          }
436          return elem;
437       }
438
439       return null;
440    }
441
442    /**
443     * Returns the WSDL2Java QName for the anonymous type of the element
444     * or null.
445     */

446    public static QName JavaDoc getElementAnonQName(Node JavaDoc node)
447    {
448       if (isXSDNode(node, "element"))
449       {
450          NodeList JavaDoc children = node.getChildNodes();
451          for (int j = 0; j < children.getLength(); j++)
452          {
453             Node JavaDoc kid = children.item(j);
454             if (isXSDNode(kid, "complexType") || isXSDNode(kid, "simpleType"))
455             {
456                return Utils.getNodeNameQName(kid);
457             }
458          }
459       }
460       return null;
461    }
462
463    /**
464     * Returns the WSDL2Java QName for the anonymous type of the attribute
465     * or null.
466     */

467    public static QName JavaDoc getAttributeAnonQName(Node JavaDoc node)
468    {
469       if (isXSDNode(node, "attribute"))
470       {
471          NodeList JavaDoc children = node.getChildNodes();
472          for (int j = 0; j < children.getLength(); j++)
473          {
474             Node JavaDoc kid = children.item(j);
475             if (isXSDNode(kid, "complexType") || isXSDNode(kid, "simpleType"))
476             {
477                return Utils.getNodeNameQName(kid);
478             }
479          }
480       }
481       return null;
482    }
483
484    /**
485     * If the specified node is a simple type or contains simpleContent, return true
486     */

487    public static boolean isSimpleTypeOrSimpleContent(Node JavaDoc node)
488    {
489       if (node == null)
490       {
491          return false;
492       }
493
494       // If the node kind is an element, dive into it.
495
if (isXSDNode(node, "element"))
496       {
497          NodeList JavaDoc children = node.getChildNodes();
498          for (int j = 0; j < children.getLength(); j++)
499          {
500             Node JavaDoc kid = children.item(j);
501             if (isXSDNode(kid, "complexType"))
502             {
503                node = kid;
504                break;
505             }
506             else if (isXSDNode(kid, "simpleType"))
507             {
508                return true;
509             }
510          }
511       }
512
513       // Expecting a schema complexType or simpleType
514
if (isXSDNode(node, "simpleType"))
515       {
516          return true;
517       }
518
519       if (isXSDNode(node, "complexType"))
520       {
521          // Under the complexType there could be complexContent/simpleContent
522
// and extension elements if this is a derived type. Skip over these.
523
NodeList JavaDoc children = node.getChildNodes();
524          Node JavaDoc complexContent = null;
525          Node JavaDoc simpleContent = null;
526          for (int j = 0; j < children.getLength(); j++)
527          {
528             Node JavaDoc kid = children.item(j);
529             if (isXSDNode(kid, "complexContent"))
530             {
531                complexContent = kid;
532                break;
533             }
534             else if (isXSDNode(kid, "simpleContent"))
535             {
536                simpleContent = kid;
537             }
538          }
539          if (complexContent != null)
540          {
541             return false;
542          }
543          if (simpleContent != null)
544          {
545             return true;
546          }
547       }
548       return false;
549    }
550
551    /**
552     * Test whether <tt>node</tt> is not null, belongs to the XML
553     * Schema namespace, and has a localName that matches
554     * <tt>schemaLocalName</tt>
555     * <p/>
556     * This can be used to determine that a given Node defines a
557     * schema "complexType" "element" and so forth.
558     *
559     * @param node a <code>Node</code> value
560     * @param schemaLocalName a <code>String</code> value
561     * @return true if the node is matches the name in the schema namespace.
562     */

563    private static boolean isXSDNode(Node JavaDoc node, String JavaDoc schemaLocalName)
564    {
565       if ((node != null) && Constants.isSchemaXSD(node.getNamespaceURI()))
566       {
567          String JavaDoc localName = node.getLocalName();
568          return ((localName != null) && localName.equals(schemaLocalName));
569       }
570       return false;
571    }
572
573    /**
574     * If the specified node represents a supported JAX-RPC complexType/element
575     * which extends another complexType. The Type of the base is returned.
576     */

577    public static TypeEntry getComplexElementExtensionBase(Node JavaDoc node, SymbolTable symbolTable)
578    {
579       if (node == null)
580       {
581          return null;
582       }
583
584       TypeEntry cached = (TypeEntry)symbolTable.node2ExtensionBase.get(node);
585       if (cached != null)
586       {
587          return cached; // cache hit
588
}
589
590       // If the node kind is an element, dive into it.
591
if (isXSDNode(node, "element"))
592       {
593          NodeList JavaDoc children = node.getChildNodes();
594          Node JavaDoc complexNode = null;
595          for (int j = 0; j < children.getLength() && complexNode == null; j++)
596          {
597             if (isXSDNode(children.item(j), "complexType"))
598             {
599                complexNode = children.item(j);
600                node = complexNode;
601             }
602          }
603       }
604
605       // Expecting a schema complexType
606
if (isXSDNode(node, "complexType"))
607       {
608
609          // Under the complexType there could be should be a complexContent &
610
// extension elements if this is a derived type.
611
NodeList JavaDoc children = node.getChildNodes();
612          Node JavaDoc content = null;
613          Node JavaDoc extension = null;
614          for (int j = 0; j < children.getLength() && content == null; j++)
615          {
616             Node JavaDoc kid = children.item(j);
617             if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent"))
618             {
619                content = kid;
620             }
621          }
622          if (content != null)
623          {
624             children = content.getChildNodes();
625             for (int j = 0; j < children.getLength() && extension == null; j++)
626             {
627                Node JavaDoc kid = children.item(j);
628                if (isXSDNode(kid, "extension"))
629                {
630                   extension = kid;
631                }
632             }
633          }
634          if (extension == null)
635          {
636             cached = null;
637          }
638          else
639          {
640             // Get the QName of the extension base
641
QName JavaDoc extendsType = Utils.getTypeQName(extension, new BooleanHolder JavaDoc(), false);
642             if (extendsType == null)
643             {
644                cached = null;
645             }
646             else
647             {
648                // Return associated Type
649
cached = symbolTable.getType(extendsType);
650             }
651          }
652       }
653       symbolTable.node2ExtensionBase.put(node, cached);
654       return cached;
655    }
656
657    /**
658     * If the specified node represents a 'normal' non-enumeration simpleType,
659     * the QName of the simpleType base is returned.
660     */

661    public static QName JavaDoc getSimpleTypeBase(Node JavaDoc node)
662    {
663       QName JavaDoc baseQName = null;
664
665       if (node == null)
666       {
667          return null;
668       }
669
670       // If the node kind is an element, dive into it.
671
QName JavaDoc nodeKind = Utils.getNodeQName(node);
672       if (isXSDNode(node, "element"))
673       {
674          NodeList JavaDoc children = node.getChildNodes();
675          for (int j = 0; j < children.getLength(); j++)
676          {
677             if (isXSDNode(children.item(j), "simpleType"))
678             {
679                node = children.item(j);
680                break;
681             }
682          }
683       }
684       // Get the node kind, expecting a schema simpleType
685
if (isXSDNode(node, "simpleType"))
686       {
687          // Under the simpleType there should be a restriction.
688
// (There may be other #text nodes, which we will ignore).
689
NodeList JavaDoc children = node.getChildNodes();
690          Node JavaDoc restrictionNode = null;
691          for (int j = 0; j < children.getLength() && restrictionNode == null; j++)
692          {
693             if (isXSDNode(children.item(j), "restriction"))
694             {
695                restrictionNode = children.item(j);
696             }
697          }
698
699          // The restriction node indicates the type being restricted
700
// (the base attribute contains this type).
701

702          if (restrictionNode != null)
703          {
704             baseQName = Utils.getTypeQName(restrictionNode, new BooleanHolder JavaDoc(), false);
705          }
706
707          // Look for enumeration elements underneath the restriction node
708
if (baseQName != null && restrictionNode != null)
709          {
710             NodeList JavaDoc enums = restrictionNode.getChildNodes();
711             for (int i = 0; i < enums.getLength(); i++)
712             {
713                if (isXSDNode(enums.item(i), "enumeration"))
714                {
715                   // Found an enumeration, this isn't a
716
// 'normal' simple type.
717
return null;
718                }
719             }
720          }
721       }
722       return baseQName;
723    }
724
725    /**
726     * Returns the contained restriction or extension node underneath
727     * the specified node. Returns null if not found
728     */

729    public static Node JavaDoc getRestrictionOrExtensionNode(Node JavaDoc node)
730    {
731       Node JavaDoc re = null;
732       if (node == null)
733       {
734          return re;
735       }
736
737       // If the node kind is an element, dive into it.
738
if (isXSDNode(node, "element"))
739       {
740          NodeList JavaDoc children = node.getChildNodes();
741          Node JavaDoc node2 = null;
742          for (int j = 0; j < children.getLength(); j++)
743          {
744             Node JavaDoc n = children.item(j);
745             if (isXSDNode(n, "simpleType") || isXSDNode(n, "complexType") || isXSDNode(n, "simpleContent"))
746             {
747                node = n;
748                break;
749             }
750          }
751       }
752       // Get the node kind, expecting a schema simpleType
753
if (isXSDNode(node, "simpleType") || isXSDNode(node, "complexType"))
754       {
755          // Under the complexType there could be a complexContent.
756
NodeList JavaDoc children = node.getChildNodes();
757          Node JavaDoc complexContent = null;
758          if (node.getLocalName().equals("complexType"))
759          {
760             for (int j = 0; j < children.getLength() && complexContent == null; j++)
761             {
762                Node JavaDoc kid = children.item(j);
763                if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent"))
764                {
765                   complexContent = kid;
766                }
767             }
768             node = complexContent;
769          }
770          // Now get the extension or restriction node
771
if (node != null)
772          {
773             children = node.getChildNodes();
774             for (int j = 0; j < children.getLength() && re == null; j++)
775             {
776                Node JavaDoc kid = children.item(j);
777                if (isXSDNode(kid, "extension") || isXSDNode(kid, "restriction"))
778                {
779                   re = kid;
780                }
781             }
782          }
783       }
784
785       return re;
786    }
787
788    /**
789     * If the specified node represents an array encoding of one of the following
790     * forms, then return the qname repesenting the element type of the array.
791     *
792     * @param node is the node
793     * @param dims is the output value that contains the number of dimensions if return is not null
794     * @return QName or null
795     */

796    public static QName JavaDoc getArrayComponentQName(Node JavaDoc node, IntHolder JavaDoc dims)
797    {
798       dims.value = 1; // assume 1 dimension
799
QName JavaDoc qName = getCollectionComponentQName(node);
800       if (qName == null)
801       {
802          qName = getArrayComponentQName_JAXRPC(node, dims);
803       }
804       return qName;
805    }
806
807    /**
808     * If the specified node represents an element that references a collection
809     * then return the qname repesenting the component of the collection.
810     * <p/>
811     * <xsd:element name="alias" type="xsd:string" maxOccurs="unbounded"/>
812     * returns qname for"xsd:string"
813     * <xsd:element ref="alias" maxOccurs="unbounded"/>
814     * returns qname for "alias"
815     *
816     * @param node is the Node
817     * @return QName of the compoent of the collection
818     */

819    public static QName JavaDoc getCollectionComponentQName(Node JavaDoc node)
820    {
821       if (node == null)
822       {
823          return null;
824       }
825
826       // If the node kind is an element, dive get its type.
827
if (isXSDNode(node, "element"))
828       {
829          // Compare the componentQName with the name of the
830
// full name. If different, return componentQName
831
BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
832          QName JavaDoc componentQName = Utils.getTypeQName(node, forElement, true);
833          if (componentQName != null)
834          {
835             QName JavaDoc fullQName = Utils.getTypeQName(node, forElement, false);
836             if (!componentQName.equals(fullQName))
837             {
838                return componentQName;
839             }
840          }
841       }
842       return null;
843    }
844
845    /**
846     * If the specified node represents an array encoding of one of the following
847     * forms, then return the qname repesenting the element type of the array.
848     *
849     * @param node is the node
850     * @param dims is the output value that contains the number of dimensions if return is not null
851     * @return QName or null
852     * <p/>
853     * JAX-RPC Style 2:
854     * <xsd:complexType name="hobbyArray">
855     * <xsd:complexContent>
856     * <xsd:restriction base="soapenc:Array">
857     * <xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
858     * </xsd:restriction>
859     * </xsd:complexContent>
860     * </xsd:complexType>
861     * <p/>
862     * JAX-RPC Style 3:
863     * <xsd:complexType name="petArray">
864     * <xsd:complexContent>
865     * <xsd:restriction base="soapenc:Array">
866     * <xsd:sequence>
867     * <xsd:element name="alias" type="xsd:string" maxOccurs="unbounded"/>
868     * </xsd:sequence>
869     * </xsd:restriction>
870     * </xsd:complexContent>
871     * </xsd:complexType>
872     */

873    private static QName JavaDoc getArrayComponentQName_JAXRPC(Node JavaDoc node, IntHolder JavaDoc dims)
874    {
875       dims.value = 0; // Assume 0
876
if (node == null)
877       {
878          return null;
879       }
880
881       // If the node kind is an element, dive into it.
882
if (isXSDNode(node, "element"))
883       {
884          NodeList JavaDoc children = node.getChildNodes();
885          for (int j = 0; j < children.getLength(); j++)
886          {
887             Node JavaDoc kid = children.item(j);
888             if (isXSDNode(kid, "complexType"))
889             {
890                node = kid;
891                break;
892             }
893          }
894       }
895
896       // Get the node kind, expecting a schema complexType
897
if (isXSDNode(node, "complexType"))
898       {
899          // Under the complexType there should be a complexContent.
900
// (There may be other #text nodes, which we will ignore).
901
NodeList JavaDoc children = node.getChildNodes();
902          Node JavaDoc complexContentNode = null;
903          for (int j = 0; j < children.getLength(); j++)
904          {
905             Node JavaDoc kid = children.item(j);
906             if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent"))
907             {
908                complexContentNode = kid;
909                break;
910             }
911          }
912
913          // Under the complexContent there should be a restriction.
914
// (There may be other #text nodes, which we will ignore).
915
Node JavaDoc restrictionNode = null;
916          if (complexContentNode != null)
917          {
918             children = complexContentNode.getChildNodes();
919             for (int j = 0; j < children.getLength(); j++)
920             {
921                Node JavaDoc kid = children.item(j);
922                if (isXSDNode(kid, "restriction"))
923                {
924                   restrictionNode = kid;
925                   break;
926                }
927             }
928          }
929
930          // The restriction node must have a base of soapenc:Array.
931
QName JavaDoc baseType = null;
932          if (restrictionNode != null)
933          {
934             baseType = Utils.getTypeQName(restrictionNode, new BooleanHolder JavaDoc(), false);
935             if (baseType != null &&
936                     baseType.getLocalPart().equals("Array") &&
937                     Constants.isSOAP_ENC(baseType.getNamespaceURI()))
938                ; // Okay
939
else
940                baseType = null; // Did not find base=soapenc:Array
941
}
942
943
944          // Under the restriction there should be an attribute OR a sequence/all group node.
945
// (There may be other #text nodes, which we will ignore).
946
Node JavaDoc groupNode = null;
947          Node JavaDoc attributeNode = null;
948          if (baseType != null)
949          {
950             children = restrictionNode.getChildNodes();
951             for (int j = 0;
952                  j < children.getLength() && groupNode == null && attributeNode == null;
953                  j++)
954             {
955                Node JavaDoc kid = children.item(j);
956                if (isXSDNode(kid, "sequence") || isXSDNode(kid, "all"))
957                {
958                   groupNode = kid;
959                   if (groupNode.getChildNodes().getLength() == 0)
960                   {
961                      // This covers the rather odd but legal empty sequence.
962
// <complexType name="ArrayOfString">
963
// <complexContent>
964
// <restriction base="soapenc:Array">
965
// <sequence/>
966
// <attribute ref="soapenc:arrayType" wsdl:arrayType="string[]"/>
967
// </restriction>
968
// </complexContent>
969
// </complexType>
970
groupNode = null;
971                   }
972                }
973                if (isXSDNode(kid, "attribute"))
974                {
975                   // If the attribute node does not have ref="soapenc:arrayType"
976
// then keep looking.
977
BooleanHolder JavaDoc isRef = new BooleanHolder JavaDoc();
978                   QName JavaDoc refQName = Utils.getTypeQName(kid, isRef, false);
979                   if (refQName != null &&
980                           isRef.value &&
981                           refQName.getLocalPart().equals("arrayType") &&
982                           Constants.isSOAP_ENC(refQName.getNamespaceURI()))
983                   {
984                      attributeNode = kid;
985                   }
986                }
987             }
988          }
989
990          // If there is an attribute node, look at wsdl:arrayType to get the element type
991
if (attributeNode != null)
992          {
993             String JavaDoc wsdlArrayTypeValue = null;
994             Vector JavaDoc attrs = Utils.getAttributesWithLocalName(attributeNode, "arrayType");
995             for (int i = 0; i < attrs.size() && wsdlArrayTypeValue == null; i++)
996             {
997                Node JavaDoc attrNode = (Node JavaDoc)attrs.elementAt(i);
998                String JavaDoc attrName = attrNode.getNodeName();
999                QName JavaDoc attrQName = Utils.getQNameFromPrefixedName(attributeNode, attrName);
1000               if (Constants.isWSDL(attrQName.getNamespaceURI()))
1001               {
1002                  wsdlArrayTypeValue = attrNode.getNodeValue();
1003               }
1004            }
1005
1006            // The value could have any number of [] or [,] on the end
1007
// Strip these off to get the prefixed name.
1008
// The convert the prefixed name into a qname.
1009
// Count the number of [ and , to get the dim information.
1010
if (wsdlArrayTypeValue != null)
1011            {
1012               int i = wsdlArrayTypeValue.indexOf('[');
1013               if (i > 0)
1014               {
1015                  String JavaDoc prefixedName = wsdlArrayTypeValue.substring(0, i);
1016                  String JavaDoc mangledString = wsdlArrayTypeValue.replace(',', '[');
1017                  dims.value = 0;
1018                  int index = mangledString.indexOf('[');
1019                  while (index > 0)
1020                  {
1021                     dims.value++;
1022                     index = mangledString.indexOf('[', index + 1);
1023                  }
1024
1025                  return Utils.getQNameFromPrefixedName(restrictionNode, prefixedName);
1026               }
1027            }
1028         }
1029         else if (groupNode != null)
1030         {
1031
1032            // Get the first element node under the group node.
1033
NodeList JavaDoc elements = groupNode.getChildNodes();
1034            Node JavaDoc elementNode = null;
1035            for (int i = 0; i < elements.getLength() && elementNode == null; i++)
1036            {
1037               Node JavaDoc kid = elements.item(i);
1038               if (isXSDNode(kid, "element"))
1039               {
1040                  elementNode = elements.item(i);
1041                  break;
1042               }
1043            }
1044
1045            // The element node should have maxOccurs="unbounded" and
1046
// a type
1047
if (elementNode != null)
1048            {
1049               String JavaDoc maxOccursValue = Utils.getAttribute(elementNode, "maxOccurs");
1050               if (maxOccursValue != null &&
1051                       maxOccursValue.equalsIgnoreCase("unbounded"))
1052               {
1053                  // Get the QName of the type without considering maxOccurs
1054
dims.value = 1;
1055                  return Utils.getTypeQName(elementNode, new BooleanHolder JavaDoc(), true);
1056               }
1057            }
1058         }
1059
1060      }
1061      return null;
1062   }
1063
1064   /**
1065    * Return the attribute names and types if any in the node
1066    * The even indices are the element types (TypeEntry) and
1067    * the odd indices are the corresponding names (Strings).
1068    * <p/>
1069    * Example:
1070    * <complexType name="Person">
1071    * <sequence>
1072    * <element minOccurs="1" maxOccurs="1" name="Age" type="double" />
1073    * <element minOccurs="1" maxOccurs="1" name="ID" type="xsd:float" />
1074    * </sequence>
1075    * <attribute name="Name" type="string" />
1076    * <attribute name="Male" type="boolean" />
1077    * </complexType>
1078    */

1079   public static Vector JavaDoc getContainedAttributeTypes(Node JavaDoc node,
1080                                                   SymbolTable symbolTable)
1081   {
1082      Vector JavaDoc v = null; // return value
1083

1084      if (node == null)
1085      {
1086         return null;
1087      }
1088      // Check for SimpleContent
1089
// If the node kind is an element, dive into it.
1090
if (isXSDNode(node, "element"))
1091      {
1092         NodeList JavaDoc children = node.getChildNodes();
1093         for (int j = 0; j < children.getLength(); j++)
1094         {
1095            Node JavaDoc kid = children.item(j);
1096            if (isXSDNode(kid, "complexType"))
1097            {
1098               node = kid;
1099               break;
1100            }
1101         }
1102      }
1103
1104      // Expecting a schema complexType
1105
if (isXSDNode(node, "complexType"))
1106      {
1107         // Under the complexType there could be complexContent/simpleContent
1108
// and extension elements if this is a derived type. Skip over these.
1109
NodeList JavaDoc children = node.getChildNodes();
1110         Node JavaDoc content = null;
1111         for (int j = 0; j < children.getLength(); j++)
1112         {
1113            Node JavaDoc kid = children.item(j);
1114            if (isXSDNode(kid, "complexContent") || isXSDNode(kid, "simpleContent"))
1115            {
1116               content = kid;
1117               break;
1118            }
1119         }
1120         // Check for extensions
1121
if (content != null)
1122         {
1123            children = content.getChildNodes();
1124            for (int j = 0; j < children.getLength(); j++)
1125            {
1126               Node JavaDoc kid = children.item(j);
1127               if (isXSDNode(kid, "extension"))
1128               {
1129                  node = kid;
1130                  break;
1131               }
1132            }
1133         }
1134
1135         // examine children of the node for <attribute> elements
1136
children = node.getChildNodes();
1137         for (int i = 0; i < children.getLength(); i++)
1138         {
1139            Node JavaDoc child = children.item(i);
1140            if (!isXSDNode(child, "attribute"))
1141            {
1142               continue;
1143            }
1144
1145            // we have an attribute node
1146
if (v == null)
1147               v = new Vector JavaDoc();
1148
1149            // Get the name and type qnames.
1150
// The type qname is used to locate the TypeEntry, which is then
1151
// used to retrieve the proper java name of the type.
1152
QName JavaDoc attributeName = Utils.getNodeNameQName(child);
1153            BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
1154            QName JavaDoc attributeType = Utils.getTypeQName(child, forElement, false);
1155
1156            // An attribute is either qualified or unqualified.
1157
// If the ref= attribute is used, the name of the ref'd element is used
1158
// (which must be a root element). If the ref= attribute is not
1159
// used, the name of the attribute is unqualified.
1160
if (!forElement.value)
1161            {
1162               // check the Form (or attributeFormDefault) attribute of
1163
// this node to determine if it should be namespace
1164
// quailfied or not.
1165
String JavaDoc form = Utils.getAttribute(child, "form");
1166               if (form != null && form.equals("unqualified"))
1167               {
1168                  // Unqualified nodeName
1169
attributeName = Utils.findQName("", attributeName.getLocalPart());
1170               }
1171               else if (form == null)
1172               {
1173                  // check attributeFormDefault on schema element
1174
String JavaDoc def = Utils.getScopedAttribute(child,
1175                          "attributeFormDefault");
1176                  if (def == null || def.equals("unqualified"))
1177                  {
1178                     // Unqualified nodeName
1179
attributeName = Utils.findQName("", attributeName.getLocalPart());
1180                  }
1181               }
1182            }
1183            else
1184            {
1185               attributeName = attributeType;
1186            }
1187
1188            // Get the corresponding TypeEntry from the symbol table
1189
TypeEntry type = symbolTable.getTypeEntry(attributeType,
1190                    forElement.value);
1191
1192            // add type and name to vector, skip it if we couldn't parse it
1193
// XXX - this may need to be revisited.
1194
if (type != null && attributeName != null)
1195            {
1196               v.add(type);
1197               v.add(attributeName);
1198            }
1199         }
1200      }
1201      return v;
1202   }
1203
1204   // list of all of the XSD types in Schema 2001
1205
private static String JavaDoc schemaTypes[] = {
1206      "string",
1207      "normalizedString",
1208      "token",
1209      "byte",
1210      "unsignedByte",
1211      "base64Binary",
1212      "hexBinary",
1213      "integer",
1214      "positiveInteger",
1215      "negativeInteger",
1216      "nonNegativeInteger",
1217      "nonPositiveInteger",
1218      "int",
1219      "unsignedInt",
1220      "long",
1221      "unsignedLong",
1222      "short",
1223      "unsignedShort",
1224      "decimal",
1225      "float",
1226      "double",
1227      "boolean",
1228      "time",
1229      "dateTime",
1230      "duration",
1231      "date",
1232      "gMonth",
1233      "gYear",
1234      "gYearMonth",
1235      "gDay",
1236      "gMonthDay",
1237      "Name",
1238      "QName",
1239      "NCName",
1240      "anyURI",
1241      "language",
1242      "ID",
1243      "IDREF",
1244      "IDREFS",
1245      "ENTITY",
1246      "ENTITIES",
1247      "NOTATION",
1248      "NMTOKEN",
1249      "NMTOKENS"
1250   };
1251
1252   private static final Set JavaDoc schemaTypeSet = new HashSet JavaDoc(Arrays.asList(schemaTypes));
1253
1254   /**
1255    * Determine if a string is a simple XML Schema type
1256    */

1257   private static boolean isSimpleSchemaType(String JavaDoc s)
1258   {
1259      if (s == null)
1260         return false;
1261
1262      return schemaTypeSet.contains(s);
1263   }
1264
1265   /**
1266    * Determine if a QName is a simple XML Schema type
1267    */

1268   public static boolean isSimpleSchemaType(QName JavaDoc qname)
1269   {
1270      if (qname == null ||
1271              !Constants.isSchemaXSD(qname.getNamespaceURI()))
1272      {
1273         return false;
1274      }
1275      return isSimpleSchemaType(qname.getLocalPart());
1276   }
1277}
1278
Popular Tags