KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > wsdl > fromJava > Types


1 /*
2  * Copyright 2001-2002,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.fromJava;
17
18 import org.apache.axis.AxisFault;
19 import org.apache.axis.AxisProperties;
20 import org.apache.axis.Constants;
21 import org.apache.axis.InternalException;
22 import org.apache.axis.MessageContext;
23 import org.apache.axis.handlers.soap.SOAPService;
24 import org.apache.axis.components.logger.LogFactory;
25 import org.apache.axis.constants.Style;
26 import org.apache.axis.description.ServiceDesc;
27 import org.apache.axis.encoding.Serializer;
28 import org.apache.axis.encoding.SerializerFactory;
29 import org.apache.axis.encoding.SimpleType;
30 import org.apache.axis.encoding.TypeMapping;
31 import org.apache.axis.encoding.ser.BeanSerializerFactory;
32 import org.apache.axis.encoding.ser.EnumSerializerFactory;
33 import org.apache.axis.soap.SOAPConstants;
34 import org.apache.axis.utils.JavaUtils;
35 import org.apache.axis.utils.Messages;
36 import org.apache.axis.utils.XMLUtils;
37 import org.apache.axis.utils.StringUtils;
38 import org.apache.axis.wsdl.symbolTable.BaseTypeMapping;
39 import org.apache.axis.wsdl.symbolTable.SymbolTable;
40 import org.apache.axis.wsdl.symbolTable.TypeEntry;
41 import org.apache.commons.logging.Log;
42 import org.w3c.dom.Attr JavaDoc;
43 import org.w3c.dom.Document JavaDoc;
44 import org.w3c.dom.Element JavaDoc;
45 import org.w3c.dom.NamedNodeMap JavaDoc;
46 import org.w3c.dom.Node JavaDoc;
47 import org.w3c.dom.NodeList JavaDoc;
48 import org.xml.sax.SAXException JavaDoc;
49
50 import javax.wsdl.Definition;
51 import javax.wsdl.WSDLException;
52 import javax.xml.namespace.QName JavaDoc;
53 import javax.xml.parsers.ParserConfigurationException JavaDoc;
54 import javax.xml.rpc.holders.Holder JavaDoc;
55 import java.io.IOException JavaDoc;
56 import java.lang.reflect.Field JavaDoc;
57 import java.lang.reflect.Modifier JavaDoc;
58 import java.net.URL JavaDoc;
59 import java.util.ArrayList JavaDoc;
60 import java.util.HashMap JavaDoc;
61 import java.util.HashSet JavaDoc;
62 import java.util.Iterator JavaDoc;
63 import java.util.List JavaDoc;
64 import java.util.Map JavaDoc;
65 import java.util.Set JavaDoc;
66
67 /**
68  * <p>Description: </p> This class is used to recursively serializes a Java Class into
69  * an XML Schema representation.
70  * <p/>
71  * It has utility methods to create a schema node, assosiate namespaces to the various types
72  *
73  * @author unascribed
74  */

75 public class Types {
76
77     /** Field log */
78     protected static Log log = LogFactory.getLog(Types.class.getName());
79
80     /** Field def */
81     Definition def;
82
83     /** Field namespaces */
84     Namespaces namespaces = null;
85
86     /** Field tm */
87     TypeMapping tm;
88
89     /** Field defaultTM */
90     TypeMapping defaultTM;
91
92     /** Field targetNamespace */
93     String JavaDoc targetNamespace;
94
95     /** Field wsdlTypesElem */
96     Element JavaDoc wsdlTypesElem = null;
97
98     /** Field schemaTypes */
99     HashMap JavaDoc schemaTypes = null;
100
101     /** Field schemaElementNames */
102     HashMap JavaDoc schemaElementNames = null;
103
104     /** Field schemaUniqueElementNames */
105     HashMap JavaDoc schemaUniqueElementNames = null;
106
107     /** Field wrapperMap */
108     HashMap JavaDoc wrapperMap = new HashMap JavaDoc();
109
110     /** Field stopClasses */
111     List JavaDoc stopClasses = null;
112
113     /** Field beanCompatErrs */
114     List JavaDoc beanCompatErrs = new ArrayList JavaDoc();
115
116     /** Field serviceDesc */
117     private ServiceDesc serviceDesc = null;
118
119     /** Keep track of the element QNames we've written to avoid dups */
120     private Set JavaDoc writtenElementQNames = new HashSet JavaDoc();
121
122     /** Which types have we already written? */
123     Class JavaDoc [] mappedTypes = null;
124
125     /** The java to wsdl emitter */
126     Emitter emitter = null;
127
128     public static boolean isArray(Class JavaDoc clazz)
129     {
130         return clazz.isArray() || java.util.Collection JavaDoc.class.isAssignableFrom(clazz);
131     }
132
133     private static Class JavaDoc getComponentType(Class JavaDoc clazz)
134     {
135         if (clazz.isArray())
136         {
137             return clazz.getComponentType();
138         }
139         else if (java.util.Collection JavaDoc.class.isAssignableFrom(clazz))
140         {
141             return Object JavaDoc.class;
142         }
143         else
144         {
145             return null;
146         }
147     }
148
149     /**
150      * This class serailizes a <code>Class</code> to XML Schema. The constructor
151      * provides the context for the streamed node within the WSDL document
152      *
153      * @param def WSDL Definition Element to declare namespaces
154      * @param tm TypeMappingRegistry to handle known types
155      * @param defaultTM default TM
156      * @param namespaces user defined or autogenerated namespace and prefix maps
157      * @param targetNamespace targetNamespace of the document
158      * @param stopClasses
159      * @param serviceDesc
160      */

161     public Types(Definition def, TypeMapping tm, TypeMapping defaultTM,
162                  Namespaces namespaces, String JavaDoc targetNamespace,
163                  List JavaDoc stopClasses, ServiceDesc serviceDesc) {
164
165         this.def = def;
166         this.serviceDesc = serviceDesc;
167
168         createDocumentFragment();
169
170         this.tm = tm;
171         this.defaultTM = defaultTM;
172
173         mappedTypes = tm.getAllClasses();
174
175         this.namespaces = namespaces;
176         this.targetNamespace = targetNamespace;
177         this.stopClasses = stopClasses;
178         schemaElementNames = new HashMap JavaDoc();
179         schemaUniqueElementNames = new HashMap JavaDoc();
180         schemaTypes = new HashMap JavaDoc();
181     }
182
183     /**
184      * This class serailizes a <code>Class</code> to XML Schema. The constructor
185      * provides the context for the streamed node within the WSDL document
186      *
187      * @param def WSDL Definition Element to declare namespaces
188      * @param tm TypeMappingRegistry to handle known types
189      * @param defaultTM default TM
190      * @param namespaces user defined or autogenerated namespace and prefix maps
191      * @param targetNamespace targetNamespace of the document
192      * @param stopClasses
193      * @param serviceDesc
194      * @param emitter Java2Wsdl emitter
195      */

196     public Types(Definition def, TypeMapping tm, TypeMapping defaultTM,
197                  Namespaces namespaces, String JavaDoc targetNamespace,
198                  List JavaDoc stopClasses, ServiceDesc serviceDesc, Emitter emitter) {
199         this(def, tm, defaultTM, namespaces, targetNamespace, stopClasses, serviceDesc);
200         this.emitter = emitter;
201     }
202
203     /**
204      * Return the namespaces object for the current context
205      *
206      * @return
207      */

208     public Namespaces getNamespaces() {
209         return namespaces;
210     }
211
212     /**
213      * Loads the types from the input schema file.
214      *
215      * @param inputSchema file or URL
216      * @throws IOException
217      * @throws WSDLException
218      * @throws SAXException
219      * @throws ParserConfigurationException
220      */

221     public void loadInputSchema(String JavaDoc inputSchema)
222             throws IOException JavaDoc, WSDLException, SAXException JavaDoc,
223             ParserConfigurationException JavaDoc {
224
225         // Read the input wsdl file into a Document
226
Document JavaDoc doc = XMLUtils.newDocument(inputSchema);
227
228         // Ensure that the root element is xsd:schema
229
Element JavaDoc root = doc.getDocumentElement();
230
231         if (root.getLocalName().equals("schema")
232                 && Constants.isSchemaXSD(root.getNamespaceURI())) {
233             Node JavaDoc schema = docHolder.importNode(root, true);
234
235             if (null == wsdlTypesElem) {
236                 writeWsdlTypesElement();
237             }
238
239             wsdlTypesElem.appendChild(schema);
240
241             // Create a symbol table and populate it with the input types
242
BaseTypeMapping btm = new BaseTypeMapping() {
243
244                 public String JavaDoc getBaseName(QName JavaDoc qNameIn) {
245
246                     QName JavaDoc qName = new QName JavaDoc(qNameIn.getNamespaceURI(),
247                             qNameIn.getLocalPart());
248                     Class JavaDoc cls = defaultTM.getClassForQName(qName);
249
250                     if (cls == null) {
251                         return null;
252                     } else {
253                         return JavaUtils.getTextClassName(cls.getName());
254                     }
255                 }
256             };
257             SymbolTable symbolTable = new SymbolTable(btm, true, false, false);
258
259             symbolTable.populateTypes(new URL JavaDoc(inputSchema), doc);
260             processSymTabEntries(symbolTable);
261         } else {
262
263             // If not, we'll just bail out... perhaps we should log a warning
264
// or throw an exception?
265
;
266         }
267     }
268
269     /**
270      * Walk the type/element entries in the symbol table and
271      * add each one to the list of processed types. This prevents
272      * the types from being duplicated.
273      *
274      * @param symbolTable
275      */

276     private void processSymTabEntries(SymbolTable symbolTable) {
277
278         Iterator JavaDoc iterator = symbolTable.getElementIndex().entrySet().iterator();
279
280         while (iterator.hasNext()) {
281             Map.Entry JavaDoc me = (Map.Entry JavaDoc) iterator.next();
282             QName JavaDoc name = (QName JavaDoc) me.getKey();
283             TypeEntry te = (TypeEntry) me.getValue();
284             String JavaDoc prefix = XMLUtils.getPrefix(name.getNamespaceURI(),
285                     te.getNode());
286
287             if (!((null == prefix) || "".equals(prefix))) {
288                 namespaces.putPrefix(name.getNamespaceURI(), prefix);
289                 def.addNamespace(prefix, name.getNamespaceURI());
290             }
291
292             addToElementsList(name);
293         }
294
295         iterator = symbolTable.getTypeIndex().entrySet().iterator();
296
297         while (iterator.hasNext()) {
298             Map.Entry JavaDoc me = (Map.Entry JavaDoc) iterator.next();
299             QName JavaDoc name = (QName JavaDoc) me.getKey();
300             TypeEntry te = (TypeEntry) me.getValue();
301             String JavaDoc prefix = XMLUtils.getPrefix(name.getNamespaceURI(),
302                     te.getNode());
303
304             if (!((null == prefix) || "".equals(prefix))) {
305                 namespaces.putPrefix(name.getNamespaceURI(), prefix);
306                 def.addNamespace(prefix, name.getNamespaceURI());
307             }
308
309             addToTypesList(name);
310         }
311     }
312
313     /**
314      * Load the types from the input wsdl file.
315      *
316      * @param inputWSDL file or URL
317      * @throws IOException
318      * @throws WSDLException
319      * @throws SAXException
320      * @throws ParserConfigurationException
321      */

322     public void loadInputTypes(String JavaDoc inputWSDL)
323             throws IOException JavaDoc, WSDLException, SAXException JavaDoc,
324             ParserConfigurationException JavaDoc {
325
326         // Read the input wsdl file into a Document
327
Document JavaDoc doc = XMLUtils.newDocument(inputWSDL);
328
329         // Search for the 'types' element
330
NodeList JavaDoc elements = doc.getChildNodes();
331
332         if ((elements.getLength() > 0)
333                 && elements.item(0).getLocalName().equals("definitions")) {
334             elements = elements.item(0).getChildNodes();
335
336             for (int i = 0;
337                  (i < elements.getLength()) && (wsdlTypesElem == null);
338                  i++) {
339                 Node JavaDoc node = elements.item(i);
340
341                 if ((node.getLocalName() != null)
342                         && node.getLocalName().equals("types")) {
343                     wsdlTypesElem = (Element JavaDoc) node;
344                 }
345             }
346         }
347
348         // If types element not found, there is no need to continue.
349
if (wsdlTypesElem == null) {
350             return;
351         }
352
353         // Import the types element into the Types docHolder document
354
wsdlTypesElem = (Element JavaDoc) docHolder.importNode(wsdlTypesElem, true);
355
356         docHolder.appendChild(wsdlTypesElem);
357
358         // Create a symbol table and populate it with the input wsdl document
359
BaseTypeMapping btm = new BaseTypeMapping() {
360
361             public String JavaDoc getBaseName(QName JavaDoc qNameIn) {
362
363                 QName JavaDoc qName = new QName JavaDoc(qNameIn.getNamespaceURI(),
364                         qNameIn.getLocalPart());
365                 Class JavaDoc cls = tm.getClassForQName(qName);
366
367                 if (cls == null) {
368                     return null;
369                 } else {
370                     return JavaUtils.getTextClassName(cls.getName());
371                 }
372             }
373         };
374         SymbolTable symbolTable = new SymbolTable(btm, true, false, false);
375
376         symbolTable.populate(null, doc);
377         processSymTabEntries(symbolTable);
378     }
379
380     /**
381      * Write out a type referenced by a part type attribute.
382      *
383      * @param type <code>Class</code> to generate the XML Schema info for
384      * @param qname <code>QName</code> of the type. If null, qname is
385      * defaulted from the class.
386      * @return the QName of the generated Schema type, null if void,
387      * if the Class type cannot be converted to a schema type
388      * then xsd:anytype is returned.
389      * @throws AxisFault
390      */

391     public QName JavaDoc writeTypeForPart(Class JavaDoc type, QName JavaDoc qname) throws AxisFault {
392
393         // patch by costin to fix an NPE; commented out till we find out what the problem is
394
// if you get NullPointerExceptions in this class, turn it on and submit some
395
// replicable test data to the Axis team via bugzilla
396

397         /*
398         * if( type==null ) {
399         * return null;
400         * }
401         */

402         if (type.getName().equals("void")) {
403             return null;
404         }
405
406         if (Holder JavaDoc.class.isAssignableFrom(type)) {
407             type = JavaUtils.getHolderValueType(type);
408         }
409
410         // Get the qname
411
if ((qname == null)
412                 || (Constants.isSOAP_ENC(qname.getNamespaceURI())
413                 && "Array".equals(qname.getLocalPart()))) {
414             qname = getTypeQName(type);
415
416             if (qname == null) {
417                 throw new AxisFault("Class:" + type.getName());
418             }
419         }
420
421         if (!makeTypeElement(type, qname, null)) {
422             qname = Constants.XSD_ANYTYPE;
423         }
424
425         return qname;
426     }
427
428     /**
429      * Write out a type (and its subtypes) referenced by a part type attribute.
430      *
431      * @param type <code>Class</code> to generate the XML Schema info for
432      * @param qname <code>QName</code> of the type. If null, qname is
433      * defaulted from the class.
434      * @return the QName of the generated Schema type, null if void,
435      * if the Class type cannot be converted to a schema type
436      * then xsd:anytype is returned.
437      */

438     public QName JavaDoc writeTypeAndSubTypeForPart(Class JavaDoc type, QName JavaDoc qname)
439             throws AxisFault {
440
441         // Write out type in parameter
442
QName JavaDoc qNameRet = writeTypeForPart(type, qname);
443
444         // If mappedTypesexists
445
// Will write subTypes of the type in parameters
446
if (mappedTypes != null) {
447             for (int i = 0; i < mappedTypes.length; i++) {
448                 Class JavaDoc tempMappedType = mappedTypes[i];
449                 QName JavaDoc name;
450
451                 // If tempMappedType is subtype of the "type" parameter
452
// and type is not Object (Object superclass of all Java class...)
453
// write the subtype
454
if (tempMappedType != null &&
455                         type != Object JavaDoc.class &&
456                         tempMappedType != type &&
457                         type.isAssignableFrom(tempMappedType)) {
458                     name = tm.getTypeQName(tempMappedType);
459                     if (!isAnonymousType(name)) {
460                         writeTypeForPart(tempMappedType, name);
461                     }
462
463                     // Only do each one once. This is OK to do because each
464
// Types instance is for generating a single WSDL.
465
mappedTypes[i] = null;
466                 }
467             }
468         } //if (mappedTyped != null) {
469

470         return qNameRet;
471     }
472
473     /**
474      * Write out an element referenced by a part element attribute.
475      *
476      * @param type <code>Class</code> to generate the XML Schema info for
477      * @param qname <code>QName</code> of the element. If null, qname is
478      * defaulted from the class.
479      * @return the QName of the generated Schema type, null if no element
480      * @throws AxisFault
481      */

482     public QName JavaDoc writeElementForPart(Class JavaDoc type, QName JavaDoc qname) throws AxisFault {
483
484         // patch by costin to fix an NPE; commented out till we find out what the problem is
485
// if you get NullPointerExceptions in this class, turn it on and submit some
486
// replicable test data to the Axis team via bugzilla
487

488         /*
489         * if( type==null ) {
490         * return null;
491         * }
492         */

493         if (type.getName().equals("void")) {
494             return null;
495         }
496
497         if (Holder JavaDoc.class.isAssignableFrom(type)) {
498             type = JavaUtils.getHolderValueType(type);
499         }
500
501         // Get the qname
502
if ((qname == null)
503                 || (Constants.isSOAP_ENC(qname.getNamespaceURI())
504                 && "Array".equals(qname.getLocalPart()))) {
505             qname = getTypeQName(type);
506
507             if (qname == null) {
508                 throw new AxisFault("Class:" + type.getName());
509             }
510         }
511
512         // Return null it a simple type (not an element)
513
String JavaDoc nsURI = qname.getNamespaceURI();
514
515         if (Constants.isSchemaXSD(nsURI)
516                 || (Constants.isSOAP_ENC(nsURI)
517                 && !"Array".equals(qname.getLocalPart()))) {
518             return null;
519         }
520
521         // Make sure a types section is present
522
if (wsdlTypesElem == null) {
523             writeWsdlTypesElement();
524         }
525
526         // Write Element, if problems occur return null.
527
if (writeTypeAsElement(type, qname) == null) {
528             qname = null;
529         }
530
531         return qname;
532     }
533
534     /**
535      * Write the element definition for a WRAPPED operation. This will
536      * write out any necessary namespace/schema declarations, an an element
537      * definition with an internal (anonymous) complexType. The name of the
538      * element will be *foo*Request or *foo*Response depending on whether the
539      * request boolean is true. If the operation contains parameters, then
540      * we also generate a &gt;sequence&lt; node underneath the complexType,
541      * and return it for later use by writeWrappedParameter() below.
542      *
543      * @param qname the desired element QName
544      * @param request true if we're writing the request wrapper, false if
545      * writing the response.
546      * @param hasParams true if there are parameters, and thus a sequence
547      * node is needed
548      * @return a DOM Element for the sequence, inside which we'll write the
549      * parameters as elements, or null if there are no parameters
550      * @throws AxisFault
551      */

552     public Element JavaDoc writeWrapperElement(
553             QName JavaDoc qname, boolean request, boolean hasParams) throws AxisFault {
554
555         // Make sure a types section is present
556
if (wsdlTypesElem == null) {
557             writeWsdlTypesElement();
558         }
559
560         // Write the namespace definition for the wrapper
561
writeTypeNamespace(qname.getNamespaceURI());
562
563         // Create an <element> for the wrapper
564
Element JavaDoc wrapperElement = docHolder.createElement("element");
565
566         writeSchemaElementDecl(qname, wrapperElement);
567         wrapperElement.setAttribute("name", qname.getLocalPart());
568
569         // Create an anonymous <complexType> for the wrapper
570
Element JavaDoc complexType = docHolder.createElement("complexType");
571
572         wrapperElement.appendChild(complexType);
573
574         // If we have parameters in the operation, create a <sequence>
575
// under the complexType and return it.
576
if (hasParams) {
577             Element JavaDoc sequence = docHolder.createElement("sequence");
578
579             complexType.appendChild(sequence);
580
581             return sequence;
582         }
583
584         return null;
585     }
586
587
588     /**
589      * Write a parameter (a sub-element) into a sequence generated by
590      * writeWrapperElement() above.
591      *
592      * @param sequence the &lt;sequence&gt; in which we're writing
593      * @param name is the name of an element to add to the wrapper element.
594      * @param type is the QName of the type of the element.
595      * @param javaType
596      * @throws AxisFault
597      */

598     public void writeWrappedParameter(
599             Element JavaDoc sequence, String JavaDoc name, QName JavaDoc type, Class JavaDoc javaType)
600             throws AxisFault {
601
602         if (javaType == void.class) {
603             return;
604         }
605
606         // JAX-RPC 1.1 says that byte[] should always be a Base64Binary
607
// This (rather strange) hack will ensure that we don't map it
608
// in to an maxoccurs=unbounded array.
609
if (javaType.isArray() && !javaType.equals(byte[].class)) {
610             type = writeTypeForPart(javaType.getComponentType(), null);
611         } else {
612             type = writeTypeForPart(javaType, type);
613         }
614
615         if (type == null) {
616             // TODO: throw an Exception!!
617
return;
618         }
619
620         Element JavaDoc childElem;
621
622         if (isAnonymousType(type)) {
623             childElem = createElementWithAnonymousType(name, javaType, false,
624                     docHolder);
625         } else {
626
627             // Create the child <element> and add it to the wrapper <sequence>
628
childElem = docHolder.createElement("element");
629
630             childElem.setAttribute("name", name);
631
632             String JavaDoc prefix =
633                     namespaces.getCreatePrefix(type.getNamespaceURI());
634             String JavaDoc prefixedName = prefix + ":" + type.getLocalPart();
635
636             childElem.setAttribute("type", prefixedName);
637
638             // JAX-RPC 1.1 says that byte[] should always be a Base64Binary
639
// This (rather strange) hack will ensure that we don't map it
640
// in to an maxoccurs=unbounded array.
641
if (javaType.isArray() && !javaType.equals(byte[].class)) {
642                 childElem.setAttribute("maxOccurs", "unbounded");
643             }
644         }
645
646         sequence.appendChild(childElem);
647     }
648
649     /**
650      * Method isAnonymousType
651      *
652      * @param type
653      * @return
654      */

655     private boolean isAnonymousType(QName JavaDoc type) {
656         return type.getLocalPart().indexOf(SymbolTable.ANON_TOKEN) != -1;
657     }
658
659     /**
660      * Create a schema element for the given type
661      *
662      * @param type the class type
663      * @param qName
664      * @return the QName of the generated Element or problems occur
665      * @throws AxisFault
666      */

667     private QName JavaDoc writeTypeAsElement(Class JavaDoc type, QName JavaDoc qName) throws AxisFault {
668
669         if ((qName == null) || Constants.equals(Constants.SOAP_ARRAY, qName)) {
670             qName = getTypeQName(type);
671         }
672
673         writeTypeNamespace(type, qName);
674         String JavaDoc elementType = writeType(type, qName);
675
676         if (elementType != null) {
677
678             // Element element = createElementDecl(qName.getLocalPart(), type, qName, isNullable(type), false);
679
// if (element != null)
680
// writeSchemaElement(typeQName,element);
681
return qName;
682         }
683
684         return null;
685     }
686
687     /**
688      * write out the namespace declaration and return the type QName for the
689      * given <code>Class</code>
690      *
691      * @param type input Class
692      * @param qName qname of the Class
693      * @return QName for the schema type representing the class
694      */

695     private QName JavaDoc writeTypeNamespace(Class JavaDoc type, QName JavaDoc qName) {
696
697         if (qName == null) {
698             qName = getTypeQName(type);
699         }
700
701         writeTypeNamespace(qName.getNamespaceURI());
702
703         return qName;
704     }
705
706     /**
707      * write out the namespace declaration.
708      *
709      * @param namespaceURI qname of the type
710      */

711     private void writeTypeNamespace(String JavaDoc namespaceURI) {
712
713         if ((namespaceURI != null) && !namespaceURI.equals("")) {
714             String JavaDoc pref = def.getPrefix(namespaceURI);
715
716             if (pref == null) {
717                 def.addNamespace(namespaces.getCreatePrefix(namespaceURI),
718                         namespaceURI);
719             }
720         }
721     }
722
723     /**
724      * Return the QName of the specified javaType
725      *
726      * @param javaType input javaType Class
727      * @return QName
728      */

729     public QName JavaDoc getTypeQName(Class JavaDoc javaType) {
730         QName JavaDoc qName = null;
731
732         // Use the typeMapping information to lookup the qName.
733
qName = tm.getTypeQName(javaType);
734
735         // If the javaType is an array and the qName is
736
// SOAP_ARRAY, construct the QName using the
737
// QName of the component type
738
if (isArray(javaType) &&
739                 Constants.equals(Constants.SOAP_ARRAY, qName)) {
740             Class JavaDoc componentType = getComponentType(javaType);
741
742             // For WS-I BP compliance, we can't use "ArrayOf" as a type prefix
743
// instead use "MyArrayOf" (gag)
744
String JavaDoc arrayTypePrefix = "ArrayOf";
745
746             boolean isWSICompliant = JavaUtils.isTrue(
747                     AxisProperties.getProperty(Constants.WSIBP11_COMPAT_PROPERTY));
748             if (isWSICompliant) {
749                 arrayTypePrefix = "MyArrayOf";
750             }
751
752             // If component namespace uri == targetNamespace
753
// Construct ArrayOf<componentLocalPart>
754
// Else
755
// Construct ArrayOf_<componentPrefix>_<componentLocalPart>
756
QName JavaDoc cqName = getTypeQName(componentType);
757
758             if (targetNamespace.equals(cqName.getNamespaceURI())) {
759                 qName = new QName JavaDoc(targetNamespace,
760                         arrayTypePrefix + cqName.getLocalPart());
761             } else {
762                 String JavaDoc pre =
763                         namespaces.getCreatePrefix(cqName.getNamespaceURI());
764
765                 qName = new QName JavaDoc(targetNamespace,
766                         arrayTypePrefix + "_" + pre + "_"
767                         + cqName.getLocalPart());
768             }
769
770             return qName;
771         }
772
773         // If a qName was not found construct one using the
774
// class name information.
775
if (qName == null) {
776             String JavaDoc pkg = getPackageNameFromFullName(javaType.getName());
777             String JavaDoc lcl = getLocalNameFromFullName(javaType.getName());
778             String JavaDoc ns = namespaces.getCreate(pkg);
779
780             namespaces.getCreatePrefix(ns);
781
782             String JavaDoc localPart = lcl.replace('$', '_');
783
784             qName = new QName JavaDoc(ns, localPart);
785         }
786
787         return qName;
788     }
789
790     /**
791      * Return a string suitable for representing a given QName in the context
792      * of this WSDL document. If the namespace of the QName is not yet
793      * registered, we will register it up in the Definitions.
794      *
795      * @param qname a QName (typically a type)
796      * @return a String containing a standard "ns:localPart" rep of the QName
797      */

798     public String JavaDoc getQNameString(QName JavaDoc qname) {
799
800         String JavaDoc prefix = namespaces.getCreatePrefix(qname.getNamespaceURI());
801
802         return prefix + ":" + qname.getLocalPart();
803     }
804
805     /**
806      * Utility method to get the package name from a fully qualified java class name
807      *
808      * @param full input class name
809      * @return package name
810      */

811     public static String JavaDoc getPackageNameFromFullName(String JavaDoc full) {
812
813         if (full.lastIndexOf('.') < 0) {
814             return "";
815         } else {
816             return full.substring(0, full.lastIndexOf('.'));
817         }
818     }
819
820     /**
821      * Utility method to get the local class name from a fully qualified java class name
822      *
823      * @param full input class name
824      * @return package name
825      */

826     public static String JavaDoc getLocalNameFromFullName(String JavaDoc full) {
827
828         String JavaDoc end = "";
829
830         if (full.startsWith("[L")) {
831             end = "[]";
832             full = full.substring(3, full.length() - 1);
833         }
834
835         if (full.lastIndexOf('.') < 0) {
836             return full + end;
837         } else {
838             return full.substring(full.lastIndexOf('.') + 1) + end;
839         }
840     }
841
842     /**
843      * Method writeSchemaTypeDecl
844      *
845      * @param qname
846      * @param element
847      * @throws AxisFault
848      */

849     public void writeSchemaTypeDecl(QName JavaDoc qname, Element JavaDoc element)
850             throws AxisFault {
851         writeSchemaElement(qname.getNamespaceURI(), element);
852     }
853
854     /**
855      * Method writeSchemaElementDecl
856      *
857      * @param qname
858      * @param element
859      * @throws AxisFault
860      */

861     public void writeSchemaElementDecl(QName JavaDoc qname, Element JavaDoc element)
862             throws AxisFault {
863
864         if (writtenElementQNames.contains(qname)) {
865             throw new AxisFault(
866                     Constants.FAULT_SERVER_GENERAL,
867                     Messages.getMessage(
868                             "duplicateSchemaElement", qname.toString()), null, null);
869         }
870
871         writeSchemaElement(qname.getNamespaceURI(), element);
872         writtenElementQNames.add(qname);
873     }
874
875     /**
876      * @deprecated
877      * Please use writeSchemaElement(String namespaceURI, Element element)
878      *
879      * @param qName qName to get the namespace of the schema node
880      * @param element the Element to append to the Schema node
881      * @throws AxisFault
882      */

883     public void writeSchemaElement(QName JavaDoc qName, Element JavaDoc element)
884             throws AxisFault {
885         writeSchemaElement(qName.getNamespaceURI(), element);
886     }
887
888     /**
889      * Write out the given Element into the appropriate schema node.
890      * If need be create the schema node as well
891      *
892      * @param namespaceURI namespace this node should get dropped into
893      * @param element the Element to append to the Schema node
894      * @throws AxisFault
895      */

896     public void writeSchemaElement(String JavaDoc namespaceURI, Element JavaDoc element)
897             throws AxisFault {
898
899         if (wsdlTypesElem == null) {
900             try {
901                 writeWsdlTypesElement();
902             } catch (Exception JavaDoc e) {
903                 log.error(e);
904
905                 return;
906             }
907         }
908
909         if ((namespaceURI == null) || namespaceURI.equals("")) {
910             throw new AxisFault(
911                     Constants.FAULT_SERVER_GENERAL,
912                     Messages.getMessage("noNamespace00", namespaceURI), null, null);
913         }
914
915         Element JavaDoc schemaElem = null;
916         NodeList JavaDoc nl = wsdlTypesElem.getChildNodes();
917
918         for (int i = 0; i < nl.getLength(); i++) {
919             NamedNodeMap JavaDoc attrs = nl.item(i).getAttributes();
920
921             if (attrs != null) {
922                 for (int n = 0; n < attrs.getLength(); n++) {
923                     Attr JavaDoc a = (Attr JavaDoc) attrs.item(n);
924
925                     if (a.getName().equals("targetNamespace")
926                             && a.getValue().equals(namespaceURI)) {
927                         schemaElem = (Element JavaDoc) nl.item(i);
928                     }
929                 }
930             }
931         }
932
933         if (schemaElem == null) {
934             schemaElem = docHolder.createElement("schema");
935
936             wsdlTypesElem.appendChild(schemaElem);
937             schemaElem.setAttribute("xmlns", Constants.URI_DEFAULT_SCHEMA_XSD);
938             schemaElem.setAttribute("targetNamespace", namespaceURI);
939
940             // Add SOAP-ENC namespace import if necessary
941
if (serviceDesc.getStyle() == Style.RPC) {
942                 Element JavaDoc importElem = docHolder.createElement("import");
943
944                 schemaElem.appendChild(importElem);
945                 importElem.setAttribute("namespace",
946                         Constants.URI_DEFAULT_SOAP_ENC);
947             }
948
949             SOAPService service = null;
950             if(MessageContext.getCurrentContext() != null) {
951                 service = MessageContext.getCurrentContext().getService();
952             }
953             if(service != null && isPresent((String JavaDoc) service.getOption("schemaQualified"), namespaceURI)){
954                 schemaElem.setAttribute("elementFormDefault", "qualified");
955             } else if(service != null && isPresent((String JavaDoc) service.getOption("schemaUnqualified"), namespaceURI)){
956                 // DO nothing..default is unqualified.
957
} else if ((serviceDesc.getStyle() == Style.DOCUMENT)
958                     || (serviceDesc.getStyle() == Style.WRAPPED)) {
959                 schemaElem.setAttribute("elementFormDefault", "qualified");
960             }
961
962             writeTypeNamespace(namespaceURI);
963         }
964
965         schemaElem.appendChild(element);
966     }
967
968     /**
969      * check if the namespace is present in the list.
970      * @param list
971      * @param namespace
972      * @return
973      */

974     private boolean isPresent(String JavaDoc list, String JavaDoc namespace) {
975         if(list == null || list.length()==0)
976                 return false;
977         String JavaDoc[] array = StringUtils.split(list,',');
978         for(int i=0;i<array.length;i++){
979             if(array[i].equals(namespace))
980                 return true;
981         }
982         return false;
983     }
984
985     /**
986      * Get the Types element for the WSDL document. If not present, create one
987      */

988     private void writeWsdlTypesElement() {
989
990         if (wsdlTypesElem == null) {
991
992             // Create a <wsdl:types> element corresponding to the wsdl namespaces.
993
wsdlTypesElem = docHolder.createElementNS(Constants.NS_URI_WSDL11,
994                     "types");
995
996             wsdlTypesElem.setPrefix(Constants.NS_PREFIX_WSDL);
997         }
998     }
999
1000    /**
1001     * Write a schema representation for the given <code>Class</code>. Recurse
1002     * through all the public fields as well as fields represented by java
1003     * bean compliant accessor methods.
1004     * <p/>
1005     * Then return the qualified string representation of the generated type
1006     *
1007     * @param type Class for which to generate schema
1008     * @return a prefixed string for the schema type
1009     * @throws AxisFault
1010     */

1011    public String JavaDoc writeType(Class JavaDoc type) throws AxisFault {
1012        return writeType(type, null);
1013    }
1014
1015    /**
1016     * Write a schema representation for the given <code>Class</code>. Recurse
1017     * through all the public fields as well as fields represented by java
1018     * bean compliant accessor methods.
1019     * <p/>
1020     * Then return the qualified string representation of the generated type
1021     *
1022     * @param type Class for which to generate schema
1023     * @param qName of the type to write
1024     * @return a prefixed string for the schema type or null if problems occur
1025     * @throws AxisFault
1026     */

1027    public String JavaDoc writeType(Class JavaDoc type, QName JavaDoc qName) throws AxisFault {
1028
1029        // Get a corresponding QName if one is not provided
1030
if ((qName == null) || Constants.equals(Constants.SOAP_ARRAY, qName)) {
1031            qName = getTypeQName(type);
1032        }
1033
1034        if (!makeTypeElement(type, qName, null)) {
1035            return null;
1036        }
1037
1038        return getQNameString(qName);
1039    }
1040
1041    /**
1042     * Method createArrayElement
1043     *
1044     * @param componentTypeName
1045     * @return
1046     */

1047    public Element JavaDoc createArrayElement(String JavaDoc componentTypeName) {
1048
1049        SOAPConstants constants;
1050        MessageContext mc = MessageContext.getCurrentContext();
1051        if(mc==null||mc.getSOAPConstants()==null){
1052            constants = SOAPConstants.SOAP11_CONSTANTS;
1053        } else {
1054            constants = mc.getSOAPConstants();
1055        }
1056        String JavaDoc prefix = namespaces.getCreatePrefix(constants.getEncodingURI());
1057        // ComplexType representation of array
1058
Element JavaDoc complexType = docHolder.createElement("complexType");
1059        Element JavaDoc complexContent = docHolder.createElement("complexContent");
1060
1061        complexType.appendChild(complexContent);
1062
1063        Element JavaDoc restriction = docHolder.createElement("restriction");
1064
1065        complexContent.appendChild(restriction);
1066        restriction.setAttribute("base",
1067                prefix + ":Array");
1068
1069        Element JavaDoc attribute = docHolder.createElement("attribute");
1070
1071        restriction.appendChild(attribute);
1072
1073        attribute.setAttribute("ref",
1074                prefix + ":arrayType");
1075
1076        prefix = namespaces.getCreatePrefix(Constants.NS_URI_WSDL11);
1077        attribute.setAttribute(prefix + ":arrayType",
1078                componentTypeName);
1079
1080        return complexType;
1081    }
1082
1083    /**
1084     * Create an array which is a wrapper type for "item" elements
1085     * of a component type. This is basically the unencoded parallel to
1086     * a SOAP-encoded array.
1087     *
1088     * @param componentType
1089     * @param itemName the QName of the inner element (right now we only use the localPart)
1090     * @return
1091     */

1092    public Element JavaDoc createLiteralArrayElement(String JavaDoc componentType,
1093                                             QName JavaDoc itemName) {
1094        String JavaDoc itemLocalName = "item";
1095        if (itemName != null) {
1096            itemLocalName = itemName.getLocalPart();
1097        }
1098
1099        Element JavaDoc complexType = docHolder.createElement("complexType");
1100        Element JavaDoc sequence = docHolder.createElement("sequence");
1101
1102        complexType.appendChild(sequence);
1103
1104        Element JavaDoc elem = docHolder.createElement("element");
1105        elem.setAttribute("name", itemLocalName);
1106        elem.setAttribute("type", componentType);
1107        elem.setAttribute("minOccurs", "0");
1108        elem.setAttribute("maxOccurs", "unbounded");
1109
1110        sequence.appendChild(elem);
1111
1112        return complexType;
1113    }
1114
1115    /**
1116     * Returns true if indicated type matches the JAX-RPC enumeration class.
1117     * Note: supports JSR 101 version 0.6 Public Draft
1118     *
1119     * @param cls
1120     * @return
1121     */

1122    public static boolean isEnumClass(Class JavaDoc cls) {
1123
1124        try {
1125            java.lang.reflect.Method JavaDoc m = cls.getMethod("getValue", null);
1126            java.lang.reflect.Method JavaDoc m2 = cls.getMethod("toString", null);
1127
1128            if ((m != null) && (m2 != null)) {
1129                java.lang.reflect.Method JavaDoc m3 =
1130                        cls.getDeclaredMethod("fromString",
1131                                new Class JavaDoc[]{
1132                                    java.lang.String JavaDoc.class});
1133                java.lang.reflect.Method JavaDoc m4 = cls.getDeclaredMethod("fromValue",
1134                        new Class JavaDoc[]{
1135                            m.getReturnType()});
1136
1137                if ((m3 != null) && Modifier.isStatic(m3.getModifiers())
1138                        && Modifier.isPublic(m3.getModifiers()) && (m4 != null)
1139                        && Modifier.isStatic(m4.getModifiers())
1140                        && Modifier.isPublic(m4.getModifiers())) {
1141
1142                    // Return false if there is a setValue member method
1143
try {
1144                        if (cls.getMethod("setValue", new Class JavaDoc[]{
1145                            m.getReturnType()}) == null) {
1146                            return true;
1147                        }
1148
1149                        return false;
1150                    } catch (java.lang.NoSuchMethodException JavaDoc e) {
1151                        return true;
1152                    }
1153                }
1154            }
1155        } catch (java.lang.NoSuchMethodException JavaDoc e) {
1156        }
1157
1158        return false;
1159    }
1160
1161    /**
1162     * Write Enumeration Complex Type
1163     * (Only supports enumeration classes of string types)
1164     *
1165     * @param qName QName of type.
1166     * @param cls class of type
1167     * @return
1168     * @throws NoSuchMethodException
1169     * @throws IllegalAccessException
1170     * @throws AxisFault
1171     */

1172    public Element JavaDoc writeEnumType(QName JavaDoc qName, Class JavaDoc cls)
1173            throws NoSuchMethodException JavaDoc, IllegalAccessException JavaDoc, AxisFault {
1174
1175        if (!isEnumClass(cls)) {
1176            return null;
1177        }
1178
1179        // Get the base type of the enum class
1180
java.lang.reflect.Method JavaDoc m = cls.getMethod("getValue", null);
1181        Class JavaDoc base = m.getReturnType();
1182
1183        // Create simpleType, restriction elements
1184
Element JavaDoc simpleType = docHolder.createElement("simpleType");
1185
1186        simpleType.setAttribute("name", qName.getLocalPart());
1187
1188        Element JavaDoc restriction = docHolder.createElement("restriction");
1189
1190        simpleType.appendChild(restriction);
1191
1192        String JavaDoc baseType = writeType(base, null);
1193
1194        restriction.setAttribute("base", baseType);
1195
1196        // Create an enumeration using the field values
1197
Field JavaDoc[] fields = cls.getDeclaredFields();
1198
1199        for (int i = 0; i < fields.length; i++) {
1200            Field JavaDoc field = fields[i];
1201            int mod = field.getModifiers();
1202
1203            // Inspect each public static final field of the same type
1204
// as the base
1205
if (Modifier.isPublic(mod) && Modifier.isStatic(mod)
1206                    && Modifier.isFinal(mod) && (field.getType() == base)) {
1207
1208                // Create an enumeration using the value specified
1209
Element JavaDoc enumeration = docHolder.createElement("enumeration");
1210
1211                enumeration.setAttribute("value", field.get(null).toString());
1212                restriction.appendChild(enumeration);
1213            }
1214        }
1215
1216        return simpleType;
1217    }
1218
1219    /**
1220     * Create a top-level element declaration in our generated schema
1221     *
1222     * @param qname
1223     * @param javaType
1224     * @param typeQName
1225     * @param nillable nillable attribute of the element
1226     * @param itemQName
1227     * @throws AxisFault
1228     */

1229    public void writeElementDecl(QName JavaDoc qname,
1230                                 Class JavaDoc javaType,
1231                                 QName JavaDoc typeQName,
1232                                 boolean nillable,
1233                                 QName JavaDoc itemQName)
1234            throws AxisFault {
1235
1236        if (writtenElementQNames.contains(qname)) {
1237            return;
1238        }
1239
1240        String JavaDoc name = qname.getLocalPart();
1241
1242        Element JavaDoc element = docHolder.createElement("element");
1243
1244        // Generate an element name that matches the type.
1245
element.setAttribute("name", name);
1246
1247        if (nillable) {
1248            element.setAttribute("nillable", "true");
1249        }
1250
1251        /*
1252         * These are not legal on top-level elements!
1253         * (feel free to delete this block after say Oct 2005)
1254        if (omittable) {
1255            element.setAttribute("minOccurs", "0");
1256            element.setAttribute("maxOccurs", "1");
1257        }
1258
1259        if (javaType.isArray()) {
1260            element.setAttribute("maxOccurs", "unbounded");
1261        }
1262        */

1263
1264        if (javaType.isArray()) {
1265            // TODO : Should check to see if this array type is specifically mapped
1266
String JavaDoc componentType = writeType(javaType.getComponentType());
1267            Element JavaDoc complexType = createLiteralArrayElement(componentType,
1268                                                            itemQName);
1269            element.appendChild(complexType);
1270        } else {
1271            // Write the type for this element, handling anonymous or named
1272
// types appropriately.
1273
makeTypeElement(javaType, typeQName, element);
1274        }
1275
1276        writeSchemaElementDecl(qname, element);
1277    }
1278
1279    /**
1280     * Create Element with a given name and type
1281     *
1282     * @param elementName the name of the created element
1283     * @param elementType schema type representation of the element
1284     * @param nullable nullable attribute of the element
1285     * @param omittable
1286     * @param docHolder
1287     * @return the created Element
1288     */

1289    public Element JavaDoc createElement(String JavaDoc elementName, String JavaDoc elementType,
1290                                 boolean nullable, boolean omittable,
1291                                 Document JavaDoc docHolder) {
1292
1293        Element JavaDoc element = docHolder.createElement("element");
1294
1295        element.setAttribute("name", elementName);
1296
1297        if (nullable) {
1298            element.setAttribute("nillable", "true");
1299        }
1300
1301        if (omittable) {
1302            element.setAttribute("minOccurs", "0");
1303            element.setAttribute("maxOccurs", "1");
1304        }
1305
1306        if (elementType != null) {
1307            element.setAttribute("type", elementType);
1308        }
1309
1310        return element;
1311    }
1312
1313    /**
1314     * Create Attribute Element with a given name and type
1315     *
1316     * @param elementName the name of the created element
1317     * @param javaType
1318     * @param xmlType
1319     * @param nullable nullable attribute of the element
1320     * @param docHolder
1321     * @return the created Element
1322     * @throws AxisFault
1323     */

1324    public Element JavaDoc createAttributeElement(
1325            String JavaDoc elementName, Class JavaDoc javaType, QName JavaDoc xmlType, boolean nullable, Document JavaDoc docHolder)
1326            throws AxisFault {
1327
1328        Element JavaDoc element = docHolder.createElement("attribute");
1329
1330        element.setAttribute("name", elementName);
1331
1332        if (nullable) {
1333            element.setAttribute("nillable", "true");
1334        }
1335
1336        makeTypeElement(javaType, xmlType, element);
1337
1338        return element;
1339    }
1340
1341    /**
1342     * Is the given class one of the simple types? In other words,
1343     * do we have a mapping for this type which is in the xsd or
1344     * soap-enc namespaces?
1345     *
1346     * @param type input Class
1347     * @return true if the type is a simple type
1348     */

1349    boolean isSimpleType(Class JavaDoc type) {
1350
1351        QName JavaDoc qname = tm.getTypeQName(type);
1352
1353        if (qname == null) {
1354            return false; // No mapping
1355
}
1356
1357        String JavaDoc nsURI = qname.getNamespaceURI();
1358
1359        return (Constants.isSchemaXSD(nsURI) || Constants.isSOAP_ENC(nsURI));
1360    }
1361
1362    /**
1363     * Is the given class acceptable as an attribute
1364     *
1365     * @param type input Class
1366     * @return true if the type is a simple, enum type or extends SimpleType
1367     */

1368    public boolean isAcceptableAsAttribute(Class JavaDoc type) {
1369        return isSimpleType(type) || isEnumClass(type)
1370                || implementsSimpleType(type);
1371    }
1372
1373    /**
1374     * Does the class implement SimpleType
1375     *
1376     * @param type input Class
1377     * @return true if the type implements SimpleType
1378     */

1379    boolean implementsSimpleType(Class JavaDoc type) {
1380
1381        Class JavaDoc[] impls = type.getInterfaces();
1382
1383        for (int i = 0; i < impls.length; i++) {
1384            if (impls[i] == SimpleType.class) {
1385                return true;
1386            }
1387        }
1388
1389        return false;
1390    }
1391
1392    /**
1393     * Generates a unique element name for a given namespace of the form
1394     * el0, el1 ....
1395     *
1396     * @param qName the namespace for the generated element
1397     * @return elementname
1398     */

1399
1400    // *** NOT USED? ***
1401
//
1402
// private String generateUniqueElementName(QName qName) {
1403
// Integer count = (Integer)schemaUniqueElementNames.get(qName.getNamespaceURI());
1404
// if (count == null)
1405
// count = new Integer(0);
1406
// else
1407
// count = new Integer(count.intValue() + 1);
1408
// schemaUniqueElementNames.put(qName.getNamespaceURI(), count);
1409
// return "el" + count.intValue();
1410
// }
1411

1412    /**
1413     * Add the type to an ArrayList and return true if the Schema node
1414     * needs to be generated
1415     * If the type already exists, just return false to indicate that the type is already
1416     * generated in a previous iteration
1417     *
1418     * @param qName of the type.
1419     * @return if the type is added returns true,
1420     * else if the type is already present returns false
1421     */

1422    private boolean addToTypesList(QName JavaDoc qName) {
1423
1424        boolean added = false;
1425        String JavaDoc namespaceURI = qName.getNamespaceURI();
1426        ArrayList JavaDoc types = (ArrayList JavaDoc) schemaTypes.get(namespaceURI);
1427
1428        // Quick return if schema type (will never add these ourselves)
1429
if (Constants.isSchemaXSD(namespaceURI)
1430                || (Constants.isSOAP_ENC(namespaceURI)
1431                && !"Array".equals(qName.getLocalPart()))) {
1432
1433            // Make sure we do have the namespace declared, though...
1434
writeTypeNamespace(namespaceURI);
1435
1436            return false;
1437        }
1438
1439        if (types == null) {
1440            types = new ArrayList JavaDoc();
1441
1442            types.add(qName.getLocalPart());
1443
1444            writeTypeNamespace(namespaceURI);
1445            schemaTypes.put(namespaceURI, types);
1446
1447            added = true;
1448        } else {
1449            if (!types.contains(qName.getLocalPart())) {
1450                types.add(qName.getLocalPart());
1451
1452                added = true;
1453            }
1454        }
1455
1456        // If addded, look at the namespace uri to see if the schema element should be
1457
// generated.
1458
if (added) {
1459            String JavaDoc prefix = namespaces.getCreatePrefix(namespaceURI);
1460
1461            if (prefix.equals(Constants.NS_PREFIX_SOAP_ENV)
1462                    || prefix.equals(Constants.NS_PREFIX_SOAP_ENC)
1463                    || prefix.equals(Constants.NS_PREFIX_SCHEMA_XSD)
1464                    || prefix.equals(Constants.NS_PREFIX_WSDL)
1465                    || prefix.equals(Constants.NS_PREFIX_WSDL_SOAP)) {
1466                return false;
1467            } else {
1468                return true;
1469            }
1470        }
1471
1472        return false;
1473    }
1474
1475    /**
1476     * Add the element to an ArrayList and return true if the Schema element
1477     * needs to be generated
1478     * If the element already exists, just return false to indicate that the type is already
1479     * generated in a previous iteration
1480     *
1481     * @param qName the name space of the element
1482     * @return if the type is added returns true, else if the type is already present returns false
1483     */

1484    private boolean addToElementsList(QName JavaDoc qName) {
1485
1486        if (qName == null) {
1487            return false;
1488        }
1489
1490        boolean added = false;
1491        ArrayList JavaDoc elements =
1492                (ArrayList JavaDoc) schemaElementNames.get(qName.getNamespaceURI());
1493
1494        if (elements == null) {
1495            elements = new ArrayList JavaDoc();
1496
1497            elements.add(qName.getLocalPart());
1498            schemaElementNames.put(qName.getNamespaceURI(), elements);
1499
1500            added = true;
1501        } else {
1502            if (!elements.contains(qName.getLocalPart())) {
1503                elements.add(qName.getLocalPart());
1504
1505                added = true;
1506            }
1507        }
1508
1509        return added;
1510    }
1511
1512    /**
1513     * Determines if the field is nullable. All non-primitives are nillable.
1514     *
1515     * @param type input Class
1516     * @return true if nullable
1517     */

1518    public static boolean isNullable(Class JavaDoc type) {
1519        if (type.isPrimitive()) {
1520            return false;
1521        } else {
1522            return true;
1523        }
1524    }
1525
1526    /**
1527     * todo ravi: Get rid of Doccument fragment and import node stuuf,
1528     * once I have a handle on the wsdl4j mechanism to get at types.
1529     * <p/>
1530     * Switch over notes: remove docHolder, docFragment in favor of wsdl4j Types
1531     * <p/>
1532     * DocumentFragment docFragment;
1533     * <p/>
1534     * DocumentFragment docFragment;
1535     * <p/>
1536     * DocumentFragment docFragment;
1537     * <p/>
1538     * DocumentFragment docFragment;
1539     */

1540
1541    // DocumentFragment docFragment;
1542
Document JavaDoc docHolder;
1543
1544    /**
1545     * Method createDocumentFragment
1546     */

1547    private void createDocumentFragment() {
1548
1549        try {
1550            this.docHolder = XMLUtils.newDocument();
1551        } catch (ParserConfigurationException JavaDoc e) {
1552
1553            // This should not occur
1554
throw new InternalException(e);
1555        }
1556    }
1557
1558    /**
1559     * Method updateNamespaces
1560     */

1561    public void updateNamespaces() {
1562
1563        Namespaces namespaces = getNamespaces();
1564        Iterator JavaDoc nspIterator = namespaces.getNamespaces();
1565
1566        while (nspIterator.hasNext()) {
1567            String JavaDoc nsp = (String JavaDoc) nspIterator.next();
1568            String JavaDoc pref = def.getPrefix(nsp);
1569
1570            if (pref == null) {
1571                def.addNamespace(namespaces.getCreatePrefix(nsp), nsp);
1572            }
1573        }
1574    }
1575
1576    /**
1577     * Inserts the type fragment into the given wsdl document and ensures
1578     * that definitions from each embedded schema are allowed to reference
1579     * schema components from the other sibling schemas.
1580     * @param doc
1581     */

1582    public void insertTypesFragment(Document JavaDoc doc) {
1583
1584        updateNamespaces();
1585
1586        if (wsdlTypesElem == null)
1587            return;
1588
1589        // Make sure that definitions from each embedded schema are allowed
1590
// to reference schema components from the other sibling schemas.
1591
Element JavaDoc schemaElem = null;
1592        String JavaDoc tns = null;
1593        NodeList JavaDoc nl = wsdlTypesElem.getChildNodes();
1594        for (int i = 0; i < nl.getLength(); i++) {
1595            NamedNodeMap JavaDoc attrs = nl.item(i).getAttributes();
1596            if (attrs == null) continue; // Should never happen.
1597
for (int n = 0; n < attrs.getLength(); n++) {
1598                Attr JavaDoc a = (Attr JavaDoc) attrs.item(n);
1599                if (a.getName().equals("targetNamespace")) {
1600                    tns = a.getValue();
1601                    schemaElem = (Element JavaDoc) nl.item(i);
1602                    break;
1603                }
1604            }
1605
1606            // Ignore what appears to be a not namespace-qualified
1607
// schema definition.
1608
if (tns != null && !"".equals(tns.trim())) {
1609                // By now we know that an import element might be necessary
1610
// for some sibling schemas. However, in the absence of
1611
// a symbol table proper, the best we can do is add one
1612
// for each sibling schema.
1613
Iterator JavaDoc it = schemaTypes.keySet().iterator();
1614                String JavaDoc otherTns;
1615                Element JavaDoc importElem;
1616                while (it.hasNext()) {
1617                    if (!tns.equals(otherTns = (String JavaDoc) it.next())) {
1618                        importElem = docHolder.createElement("import");
1619                        importElem.setAttribute("namespace", otherTns);
1620                        schemaElem.insertBefore(importElem,
1621                                schemaElem.getFirstChild());
1622                    }
1623                }
1624            }
1625            schemaElem = null;
1626            tns = null;
1627        }
1628
1629        // Import the wsdlTypesElement into the doc.
1630
org.w3c.dom.Node JavaDoc node = doc.importNode(wsdlTypesElem, true);
1631        // Insert the imported element at the beginning of the document
1632
doc.getDocumentElement().
1633                insertBefore(node,
1634                        doc.getDocumentElement().getFirstChild());
1635    }
1636
1637    /**
1638     * Return the list of classes that we should not emit WSDL for.
1639     *
1640     * @return
1641     */

1642    public List JavaDoc getStopClasses() {
1643        return stopClasses;
1644    }
1645
1646    /**
1647     * Create a DOM Element in this context
1648     *
1649     * @param elementName
1650     * @return
1651     */

1652    public Element JavaDoc createElement(String JavaDoc elementName) {
1653        return docHolder.createElement(elementName);
1654    }
1655
1656    /**
1657     * isBeanCompatible
1658     *
1659     * @param javaType Class
1660     * @param issueErrors if true, issue messages if not compatible
1661     * Returns true if it appears that this class is a bean and
1662     * can be mapped to a complexType
1663     * @return
1664     */

1665    protected boolean isBeanCompatible(Class JavaDoc javaType, boolean issueErrors) {
1666
1667        // Must be a non-primitive and non array
1668
if (javaType.isArray() || javaType.isPrimitive()) {
1669            if (issueErrors && !beanCompatErrs.contains(javaType)) {
1670                log.warn(Messages.getMessage("beanCompatType00",
1671                        javaType.getName()));
1672                beanCompatErrs.add(javaType);
1673            }
1674
1675            return false;
1676        }
1677
1678        // Anything in the java or javax package that
1679
// does not have a defined mapping is excluded.
1680
if (javaType.getName().startsWith("java.")
1681                || javaType.getName().startsWith("javax.")) {
1682            if (issueErrors && !beanCompatErrs.contains(javaType)) {
1683                log.warn(Messages.getMessage("beanCompatPkg00",
1684                        javaType.getName()));
1685                beanCompatErrs.add(javaType);
1686            }
1687
1688            return false;
1689        }
1690
1691        // Return true if appears to be an enum class
1692
if (JavaUtils.isEnumClass(javaType)) {
1693            return true;
1694        }
1695
1696        // Must have a default public constructor if not
1697
// Throwable
1698
if (!java.lang.Throwable JavaDoc.class.isAssignableFrom(javaType)) {
1699            try {
1700                javaType.getConstructor(new Class JavaDoc[]{
1701                });
1702            } catch (java.lang.NoSuchMethodException JavaDoc e) {
1703                if (issueErrors && !beanCompatErrs.contains(javaType)) {
1704                    log.warn(Messages.getMessage("beanCompatConstructor00",
1705                            javaType.getName()));
1706                    beanCompatErrs.add(javaType);
1707                }
1708
1709                return false;
1710            }
1711        }
1712
1713        // Make sure superclass is compatible
1714
Class JavaDoc superClass = javaType.getSuperclass();
1715
1716        if ((superClass != null) && (superClass != java.lang.Object JavaDoc.class)
1717                && (superClass != java.lang.Exception JavaDoc.class)
1718                && (superClass != java.lang.Throwable JavaDoc.class)
1719                && (superClass != java.rmi.RemoteException JavaDoc.class)
1720                && (superClass != org.apache.axis.AxisFault.class)
1721                && ((stopClasses == null)
1722                || !(stopClasses.contains(superClass.getName())))) {
1723            if (!isBeanCompatible(superClass, false)) {
1724                if (issueErrors && !beanCompatErrs.contains(javaType)) {
1725                    log.warn(Messages.getMessage("beanCompatExtends00",
1726                            javaType.getName(),
1727                            superClass.getName(),
1728                            javaType.getName()));
1729                    beanCompatErrs.add(javaType);
1730                }
1731
1732                return false;
1733            }
1734        }
1735
1736        return true;
1737    }
1738
1739    /**
1740     * Write an &lt;element&gt; with an anonymous internal ComplexType
1741     *
1742     * @param elementName
1743     * @param fieldType
1744     * @param omittable
1745     * @param ownerDocument
1746     * @return
1747     * @throws AxisFault
1748     */

1749    public Element JavaDoc createElementWithAnonymousType(String JavaDoc elementName,
1750                                                  Class JavaDoc fieldType,
1751                                                  boolean omittable,
1752                                                  Document JavaDoc ownerDocument)
1753            throws AxisFault {
1754
1755        Element JavaDoc element = docHolder.createElement("element");
1756
1757        element.setAttribute("name", elementName);
1758
1759        if (isNullable(fieldType)) {
1760            element.setAttribute("nillable", "true");
1761        }
1762
1763        if (omittable) {
1764            element.setAttribute("minOccurs", "0");
1765            element.setAttribute("maxOccurs", "1");
1766        }
1767
1768        makeTypeElement(fieldType, null, element);
1769
1770        return element;
1771    }
1772
1773    /**
1774     * Create a schema type element (either simpleType or complexType) for
1775     * the particular type/qName combination. If the type is named, we
1776     * handle inserting the new type into the appropriate &lt;schema&gt;
1777     * in the WSDL types section. If the type is anonymous, we append the
1778     * definition underneath the Element which was passed as the container
1779     * (typically a field of a higher-level type or a parameter in a wrapped
1780     * operation).
1781     *
1782     * @param type Java type to write
1783     * @param qName the desired type QName
1784     * @param containingElement a schema element ("element" or "attribute")
1785     * which should either receive a type="" attribute decoration
1786     * (for named types) or a child element defining an anonymous
1787     * type
1788     * @return true if the type was already present or was added, false if there was a problem
1789     * @throws AxisFault
1790     */

1791    private boolean makeTypeElement(Class JavaDoc type,
1792                                    QName JavaDoc qName,
1793                                    Element JavaDoc containingElement)
1794            throws AxisFault {
1795
1796        // Get a corresponding QName if one is not provided
1797
if ((qName == null) || Constants.equals(Constants.SOAP_ARRAY, qName)) {
1798            qName = getTypeQName(type);
1799        }
1800
1801        boolean anonymous = isAnonymousType(qName);
1802
1803        // Can't have an anonymous type outside of a containing element
1804
if (anonymous && (containingElement == null)) {
1805            throw new AxisFault(
1806                    Messages.getMessage(
1807                            "noContainerForAnonymousType", qName.toString()));
1808        }
1809
1810        // If we've already got this type (because it's a native type or
1811
// because we've already written it), just add the type="" attribute
1812
// (if appropriate) and return.
1813
if (!addToTypesList(qName) && !anonymous) {
1814            if (containingElement != null) {
1815                containingElement.setAttribute("type", getQNameString(qName));
1816            }
1817
1818            return true;
1819        }
1820
1821        // look up the serializer in the TypeMappingRegistry
1822
SerializerFactory factory;
1823        factory = (SerializerFactory) tm.getSerializer(type, qName);
1824
1825        // If no factory is found, use the BeanSerializerFactory
1826
// if applicable, otherwise issue errors and treat as an anyType
1827
if (factory == null) {
1828            if (isEnumClass(type)) {
1829                factory = new EnumSerializerFactory(type, qName);
1830            } else if (isBeanCompatible(type, true)) {
1831                factory = new BeanSerializerFactory(type, qName);
1832            } else {
1833                return false;
1834            }
1835        }
1836
1837        // factory is not null
1838
Serializer ser = (Serializer) factory.getSerializerAs(Constants.AXIS_SAX);
1839
1840        // if we can't get a serializer, that is bad.
1841
if (ser == null) {
1842            throw new AxisFault(Messages.getMessage("NoSerializer00",
1843                    type.getName()));
1844        }
1845
1846        Element JavaDoc typeEl;
1847
1848        try {
1849            typeEl = ser.writeSchema(type, this);
1850        } catch (Exception JavaDoc e) {
1851            throw AxisFault.makeFault(e);
1852        }
1853
1854        // If this is an anonymous type, just make the type element a child
1855
// of containingElement. If not, set the "type" attribute of
1856
// containingElement to the right QName, and make sure the type is
1857
// correctly written into the appropriate <schema> element.
1858
if (anonymous) {
1859            if (typeEl == null) {
1860                containingElement.setAttribute("type", getQNameString(getTypeQName(type)));
1861            } else {
1862                containingElement.appendChild(typeEl);
1863            }
1864        } else {
1865            if (typeEl != null) {
1866                typeEl.setAttribute("name", qName.getLocalPart());
1867
1868                // Write the type in the appropriate <schema>
1869
writeSchemaTypeDecl(qName, typeEl);
1870            }
1871
1872            if (containingElement != null) {
1873                containingElement.setAttribute("type", getQNameString(qName));
1874            }
1875        }
1876
1877        // store the mapping of type qname and its correspoding java type
1878
if (emitter != null) {
1879            emitter.getQName2ClassMap().put(qName, type);
1880        }
1881
1882        return true;
1883    }
1884
1885    /**
1886     * return the service description
1887     * @return
1888     */

1889    public ServiceDesc getServiceDesc() {
1890        return serviceDesc;
1891    }
1892}
1893
Popular Tags