KickJava   Java API By Example, From Geeks To Geeks.

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


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

16 package org.apache.axis.wsdl.symbolTable;
17
18 import org.apache.axis.Constants;
19 import org.apache.axis.constants.Style;
20 import org.apache.axis.constants.Use;
21 import org.apache.axis.utils.Messages;
22 import org.apache.axis.utils.URLHashSet;
23 import org.apache.axis.utils.XMLUtils;
24 import org.w3c.dom.Document JavaDoc;
25 import org.w3c.dom.NamedNodeMap JavaDoc;
26 import org.w3c.dom.Node JavaDoc;
27 import org.w3c.dom.NodeList JavaDoc;
28 import org.xml.sax.SAXException JavaDoc;
29
30 import javax.wsdl.Binding;
31 import javax.wsdl.BindingFault;
32 import javax.wsdl.BindingInput;
33 import javax.wsdl.BindingOperation;
34 import javax.wsdl.BindingOutput;
35 import javax.wsdl.Definition;
36 import javax.wsdl.Fault;
37 import javax.wsdl.Import;
38 import javax.wsdl.Input;
39 import javax.wsdl.Message;
40 import javax.wsdl.Operation;
41 import javax.wsdl.Output;
42 import javax.wsdl.Part;
43 import javax.wsdl.Port;
44 import javax.wsdl.PortType;
45 import javax.wsdl.Service;
46 import javax.wsdl.WSDLException;
47 import javax.wsdl.extensions.ExtensibilityElement;
48 import javax.wsdl.extensions.UnknownExtensibilityElement;
49 import javax.wsdl.extensions.http.HTTPBinding;
50 import javax.wsdl.extensions.mime.MIMEContent;
51 import javax.wsdl.extensions.mime.MIMEMultipartRelated;
52 import javax.wsdl.extensions.mime.MIMEPart;
53 import javax.wsdl.extensions.soap.SOAPBinding;
54 import javax.wsdl.extensions.soap.SOAPBody;
55 import javax.wsdl.extensions.soap.SOAPFault;
56 import javax.wsdl.extensions.soap.SOAPHeader;
57 import javax.wsdl.extensions.soap.SOAPHeaderFault;
58 import javax.wsdl.factory.WSDLFactory;
59 import javax.wsdl.xml.WSDLReader;
60 import javax.xml.namespace.QName JavaDoc;
61 import javax.xml.parsers.ParserConfigurationException JavaDoc;
62 import javax.xml.rpc.holders.BooleanHolder JavaDoc;
63 import javax.xml.rpc.holders.IntHolder JavaDoc;
64 import javax.xml.rpc.holders.QNameHolder JavaDoc;
65 import java.io.File JavaDoc;
66 import java.io.IOException JavaDoc;
67 import java.net.MalformedURLException JavaDoc;
68 import java.net.URL JavaDoc;
69 import java.util.ArrayList JavaDoc;
70 import java.util.Collection JavaDoc;
71 import java.util.Collections JavaDoc;
72 import java.util.HashMap JavaDoc;
73 import java.util.HashSet JavaDoc;
74 import java.util.Iterator JavaDoc;
75 import java.util.List JavaDoc;
76 import java.util.Map JavaDoc;
77 import java.util.Set JavaDoc;
78 import java.util.Vector JavaDoc;
79
80 /**
81  * This class represents a table of all of the top-level symbols from a set of WSDL Definitions and
82  * DOM Documents: XML types; WSDL messages, portTypes, bindings, and services.
83  * <p/>
84  * This symbolTable contains entries of the form <key, value> where key is of type QName and value is
85  * of type Vector. The Vector's elements are all of the objects that have the given QName. This is
86  * necessary since names aren't unique among the WSDL types. message, portType, binding, service,
87  * could all have the same QName and are differentiated merely by type. SymbolTable contains
88  * type-specific getters to bypass the Vector layer:
89  * public PortTypeEntry getPortTypeEntry(QName name), etc.
90  */

91 public class SymbolTable {
92
93     // used to cache dervied types
94
protected HashMap JavaDoc derivedTypes = new HashMap JavaDoc();
95
96     // Should the contents of imported files be added to the symbol table?
97

98     /** Field addImports */
99     private boolean addImports;
100
101     // The actual symbol table. This symbolTable contains entries of the form
102
// <key, value> where key is of type QName and value is of type Vector. The
103
// Vector's elements are all of the objects that have the given QName. This
104
// is necessary since names aren't unique among the WSDL types. message,
105
// portType, binding, service, could all have the same QName and are
106
// differentiated merely by type. SymbolTable contains type-specific
107
// getters to bypass the Vector layer:
108
// public PortTypeEntry getPortTypeEntry(QName name), etc.
109

110     /** Field symbolTable */
111     private HashMap JavaDoc symbolTable = new HashMap JavaDoc();
112
113     // a map of qnames -> Elements in the symbol table
114

115     /** Field elementTypeEntries */
116     private final Map JavaDoc elementTypeEntries = new HashMap JavaDoc();
117
118     // an unmodifiable wrapper so that we can share the index with others, safely
119

120     /** Field elementIndex */
121     private final Map JavaDoc elementIndex =
122             Collections.unmodifiableMap(elementTypeEntries);
123
124     // a map of qnames -> Types in the symbol table
125

126     /** Field typeTypeEntries */
127     private final Map JavaDoc typeTypeEntries = new HashMap JavaDoc();
128
129     // an unmodifiable wrapper so that we can share the index with others, safely
130

131     /** Field typeIndex */
132     private final Map JavaDoc typeIndex = Collections.unmodifiableMap(typeTypeEntries);
133
134     /**
135      * cache of nodes -> base types for complexTypes. The cache is
136      * built on nodes because multiple TypeEntry objects may use the
137      * same node.
138      */

139     protected final Map JavaDoc node2ExtensionBase =
140             new HashMap JavaDoc(); // allow friendly access
141

142     /** Field verbose */
143     private boolean verbose;
144
145     /** Field quiet */
146     protected boolean quiet;
147
148     /** Field btm */
149     private BaseTypeMapping btm = null;
150
151     // should we attempt to treat document/literal WSDL as "rpc-style"
152

153     /** Field nowrap */
154     private boolean nowrap;
155
156     // Did we encounter wraped mode WSDL
157

158     /** Field wrapped */
159     private boolean wrapped = false;
160
161     /** Field ANON_TOKEN */
162     public static final String JavaDoc ANON_TOKEN = ">";
163
164     /** Field def */
165     private Definition def = null;
166
167     /** Field wsdlURI */
168     private String JavaDoc wsdlURI = null;
169
170     /** If this is false, we will "unwrap" literal arrays, generating a plan "String[]" instead
171      * of "ArrayOfString" when encountering an element containing a single maxOccurs="unbounded"
172      * inner element.
173      */

174     private boolean wrapArrays;
175
176     Set arrayTypeQNames = new HashSet();
177
178     /** Field elementFormDefaults */
179     private final Map JavaDoc elementFormDefaults = new HashMap JavaDoc();
180     /**
181      * Construct a symbol table with the given Namespaces.
182      *
183      * @param btm
184      * @param addImports
185      * @param verbose
186      * @param nowrap
187      */

188     public SymbolTable(BaseTypeMapping btm, boolean addImports,
189                        boolean verbose, boolean nowrap) {
190
191         this.btm = btm;
192         this.addImports = addImports;
193         this.verbose = verbose;
194         this.nowrap = nowrap;
195     } // ctor
196

197     /**
198      * Method isQuiet
199      *
200      * @return
201      */

202     public boolean isQuiet() {
203         return quiet;
204     }
205
206     /**
207      * Method setQuiet
208      *
209      * @param quiet
210      */

211     public void setQuiet(boolean quiet) {
212         this.quiet = quiet;
213     }
214
215     /**
216      * Get the raw symbol table HashMap.
217      *
218      * @return
219      */

220     public HashMap JavaDoc getHashMap() {
221         return symbolTable;
222     } // getHashMap
223

224     /**
225      * Get the list of entries with the given QName. Since symbols can share QNames, this list is
226      * necessary. This list will not contain any more than one element of any given SymTabEntry.
227      *
228      * @param qname
229      * @return
230      */

231     public Vector JavaDoc getSymbols(QName JavaDoc qname) {
232         return (Vector JavaDoc) symbolTable.get(qname);
233     } // get
234

235     /**
236      * Get the entry with the given QName of the given class. If it does not exist, return null.
237      *
238      * @param qname
239      * @param cls
240      * @return
241      */

242     public SymTabEntry get(QName JavaDoc qname, Class JavaDoc cls) {
243
244         Vector JavaDoc v = (Vector JavaDoc) symbolTable.get(qname);
245
246         if (v == null) {
247             return null;
248         } else {
249             for (int i = 0; i < v.size(); ++i) {
250                 SymTabEntry entry = (SymTabEntry) v.elementAt(i);
251
252                 if (cls.isInstance(entry)) {
253                     return entry;
254                 }
255             }
256
257             return null;
258         }
259     } // get
260

261     /**
262      * Get the type entry for the given qname.
263      *
264      * @param qname
265      * @param wantElementType boolean that indicates type or element (for type= or ref=)
266      * @return
267      */

268     public TypeEntry getTypeEntry(QName JavaDoc qname, boolean wantElementType) {
269
270         if (wantElementType) {
271             return getElement(qname);
272         } else {
273             return getType(qname);
274         }
275     } // getTypeEntry
276

277     /**
278      * Get the Type TypeEntry with the given QName. If it doesn't
279      * exist, return null.
280      *
281      * @param qname
282      * @return
283      */

284     public Type getType(QName JavaDoc qname) {
285         return (Type) typeTypeEntries.get(qname);
286     } // getType
287

288     /**
289      * Get the Element TypeEntry with the given QName. If it doesn't
290      * exist, return null.
291      *
292      * @param qname
293      * @return
294      */

295     public Element getElement(QName JavaDoc qname) {
296         return (Element) elementTypeEntries.get(qname);
297     } // getElement
298

299     /**
300      * Get the MessageEntry with the given QName. If it doesn't exist, return null.
301      *
302      * @param qname
303      * @return
304      */

305     public MessageEntry getMessageEntry(QName JavaDoc qname) {
306         return (MessageEntry) get(qname, MessageEntry.class);
307     } // getMessageEntry
308

309     /**
310      * Get the PortTypeEntry with the given QName. If it doesn't exist, return null.
311      *
312      * @param qname
313      * @return
314      */

315     public PortTypeEntry getPortTypeEntry(QName JavaDoc qname) {
316         return (PortTypeEntry) get(qname, PortTypeEntry.class);
317     } // getPortTypeEntry
318

319     /**
320      * Get the BindingEntry with the given QName. If it doesn't exist, return null.
321      *
322      * @param qname
323      * @return
324      */

325     public BindingEntry getBindingEntry(QName JavaDoc qname) {
326         return (BindingEntry) get(qname, BindingEntry.class);
327     } // getBindingEntry
328

329     /**
330      * Get the ServiceEntry with the given QName. If it doesn't exist, return null.
331      *
332      * @param qname
333      * @return
334      */

335     public ServiceEntry getServiceEntry(QName JavaDoc qname) {
336         return (ServiceEntry) get(qname, ServiceEntry.class);
337     } // getServiceEntry
338

339     /**
340      * Get the list of all the XML schema types in the symbol table. In other words, all entries
341      * that are instances of TypeEntry.
342      *
343      * @return
344      * @deprecated use specialized get{Element,Type}Index() methods instead
345      */

346     public Vector JavaDoc getTypes() {
347
348         Vector JavaDoc v = new Vector JavaDoc();
349
350         v.addAll(elementTypeEntries.values());
351         v.addAll(typeTypeEntries.values());
352
353         return v;
354     } // getTypes
355

356     /**
357      * Return an unmodifiable map of qnames -> Elements in the symbol
358      * table.
359      *
360      * @return an unmodifiable <code>Map</code> value
361      */

362     public Map JavaDoc getElementIndex() {
363         return elementIndex;
364     }
365
366     /**
367      * Return an unmodifiable map of qnames -> Elements in the symbol
368      * table.
369      *
370      * @return an unmodifiable <code>Map</code> value
371      */

372     public Map JavaDoc getTypeIndex() {
373         return typeIndex;
374     }
375
376     /**
377      * Return the count of TypeEntries in the symbol table.
378      *
379      * @return an <code>int</code> value
380      */

381     public int getTypeEntryCount() {
382         return elementTypeEntries.size() + typeTypeEntries.size();
383     }
384
385     /**
386      * Get the Definition. The definition is null until
387      * populate is called.
388      *
389      * @return
390      */

391     public Definition getDefinition() {
392         return def;
393     } // getDefinition
394

395     /**
396      * Get the WSDL URI. The WSDL URI is null until populate
397      * is called, and ONLY if a WSDL URI is provided.
398      *
399      * @return
400      */

401     public String JavaDoc getWSDLURI() {
402         return wsdlURI;
403     } // getWSDLURI
404

405     /**
406      * Are we wrapping literal soap body elements.
407      *
408      * @return
409      */

410     public boolean isWrapped() {
411         return wrapped;
412     }
413
414     /**
415      * Turn on/off element wrapping for literal soap body's.
416      *
417      * @param wrapped
418      */

419     public void setWrapped(boolean wrapped) {
420         this.wrapped = wrapped;
421     }
422
423     /**
424      * Dump the contents of the symbol table. For debugging purposes only.
425      *
426      * @param out
427      */

428     public void dump(java.io.PrintStream JavaDoc out) {
429
430         out.println();
431         out.println(Messages.getMessage("symbolTable00"));
432         out.println("-----------------------");
433
434         Iterator JavaDoc it = symbolTable.values().iterator();
435
436         while (it.hasNext()) {
437             Vector JavaDoc v = (Vector JavaDoc) it.next();
438
439             for (int i = 0; i < v.size(); ++i) {
440                 out.println(v.elementAt(i).getClass().getName());
441                 out.println(v.elementAt(i));
442             }
443         }
444
445         out.println("-----------------------");
446     } // dump
447

448     /**
449      * Call this method if you have a uri for the WSDL document
450      *
451      * @param uri wsdlURI the location of the WSDL file.
452      * @throws IOException
453      * @throws WSDLException
454      * @throws SAXException
455      * @throws ParserConfigurationException
456      */

457     public void populate(String JavaDoc uri)
458             throws IOException JavaDoc, WSDLException, SAXException JavaDoc,
459             ParserConfigurationException JavaDoc {
460         populate(uri, null, null);
461     } // populate
462

463     /**
464      * Method populate
465      *
466      * @param uri
467      * @param username
468      * @param password
469      * @throws IOException
470      * @throws WSDLException
471      * @throws SAXException
472      * @throws ParserConfigurationException
473      */

474     public void populate(String JavaDoc uri, String JavaDoc username, String JavaDoc password)
475             throws IOException JavaDoc, WSDLException, SAXException JavaDoc,
476             ParserConfigurationException JavaDoc {
477
478         if (verbose) {
479             System.out.println(Messages.getMessage("parsing00", uri));
480         }
481
482         Document JavaDoc doc = XMLUtils.newDocument(uri, username, password);
483
484         this.wsdlURI = uri;
485
486         try {
487             File JavaDoc f = new File JavaDoc(uri);
488
489             if (f.exists()) {
490                 uri = f.toURL().toString();
491             }
492         } catch (Exception JavaDoc e) {
493         }
494
495         populate(uri, doc);
496     } // populate
497

498     /**
499      * Call this method if your WSDL document has already been parsed as an XML DOM document.
500      *
501      * @param context context This is directory context for the Document. If the Document were from file "/x/y/z.wsdl" then the context could be "/x/y" (even "/x/y/z.wsdl" would work). If context is null, then the context becomes the current directory.
502      * @param doc doc This is the XML Document containing the WSDL.
503      * @throws IOException
504      * @throws SAXException
505      * @throws WSDLException
506      * @throws ParserConfigurationException
507      */

508     public void populate(String JavaDoc context, Document JavaDoc doc)
509             throws IOException JavaDoc, SAXException JavaDoc, WSDLException,
510             ParserConfigurationException JavaDoc {
511
512         WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
513
514         reader.setFeature("javax.wsdl.verbose", verbose);
515
516         this.def = reader.readWSDL(context, doc);
517
518         add(context, def, doc);
519     } // populate
520

521     /**
522      * Add the given Definition and Document information to the symbol table (including imported
523      * symbols), populating it with SymTabEntries for each of the top-level symbols. When the
524      * symbol table has been populated, iterate through it, setting the isReferenced flag
525      * appropriately for each entry.
526      *
527      * @param context
528      * @param def
529      * @param doc
530      * @throws IOException
531      * @throws SAXException
532      * @throws WSDLException
533      * @throws ParserConfigurationException
534      */

535     protected void add(String JavaDoc context, Definition def, Document JavaDoc doc)
536             throws IOException JavaDoc, SAXException JavaDoc, WSDLException,
537             ParserConfigurationException JavaDoc {
538
539         URL JavaDoc contextURL = (context == null)
540                 ? null
541                 : getURL(null, context);
542
543         populate(contextURL, def, doc, null);
544         processTypes();
545         checkForUndefined();
546         populateParameters();
547         setReferences(def, doc); // uses wrapped flag set in populateParameters
548
} // add
549

550     /**
551      * Scan the Definition for undefined objects and throw an error.
552      *
553      * @param def
554      * @param filename
555      * @throws IOException
556      */

557     private void checkForUndefined(Definition def, String JavaDoc filename)
558             throws IOException JavaDoc {
559
560         if (def != null) {
561
562             // Bindings
563
Iterator JavaDoc ib = def.getBindings().values().iterator();
564
565             while (ib.hasNext()) {
566                 Binding binding = (Binding) ib.next();
567
568                 if (binding.isUndefined()) {
569                     if (filename == null) {
570                         throw new IOException JavaDoc(
571                                 Messages.getMessage(
572                                         "emitFailtUndefinedBinding01",
573                                         binding.getQName().getLocalPart()));
574                     } else {
575                         throw new IOException JavaDoc(
576                                 Messages.getMessage(
577                                         "emitFailtUndefinedBinding02",
578                                         binding.getQName().getLocalPart(), filename));
579                     }
580                 }
581             }
582
583             // portTypes
584
Iterator JavaDoc ip = def.getPortTypes().values().iterator();
585
586             while (ip.hasNext()) {
587                 PortType portType = (PortType) ip.next();
588
589                 if (portType.isUndefined()) {
590                     if (filename == null) {
591                         throw new IOException JavaDoc(
592                                 Messages.getMessage(
593                                         "emitFailtUndefinedPort01",
594                                         portType.getQName().getLocalPart()));
595                     } else {
596                         throw new IOException JavaDoc(
597                                 Messages.getMessage(
598                                         "emitFailtUndefinedPort02",
599                                         portType.getQName().getLocalPart(), filename));
600                     }
601                 }
602             }
603
604             /*
605              * tomj: This is a bad idea, faults seem to be undefined
606              * / RJB reply: this MUST be done for those systems that do something with
607              * / messages. Perhaps we have to do an extra step for faults? I'll leave
608              * / this commented for now, until someone uses this generator for something
609              * / other than WSDL2Java.
610              * // Messages
611              * Iterator i = def.getMessages().values().iterator();
612              * while (i.hasNext()) {
613              * Message message = (Message) i.next();
614              * if (message.isUndefined()) {
615              * throw new IOException(
616              * Messages.getMessage("emitFailtUndefinedMessage01",
617              * message.getQName().getLocalPart()));
618              * }
619              * }
620              */

621         }
622     }
623
624     /**
625      * Scan the symbol table for undefined types and throw an exception.
626      *
627      * @throws IOException
628      */

629     private void checkForUndefined() throws IOException JavaDoc {
630
631         Iterator JavaDoc it = symbolTable.values().iterator();
632
633         while (it.hasNext()) {
634             Vector JavaDoc v = (Vector JavaDoc) it.next();
635
636             for (int i = 0; i < v.size(); ++i) {
637                 SymTabEntry entry = (SymTabEntry) v.get(i);
638
639                 // Report undefined types
640
if (entry instanceof UndefinedType) {
641                     QName JavaDoc qn = entry.getQName();
642
643                     // Special case dateTime/timeInstant that changed
644
// from version to version.
645
if ((qn.getLocalPart().equals(
646                             "dateTime") && !qn.getNamespaceURI().equals(
647                                     Constants.URI_2001_SCHEMA_XSD)) || (qn.getLocalPart().equals(
648                                             "timeInstant") && qn.getNamespaceURI().equals(
649                                                     Constants.URI_2001_SCHEMA_XSD))) {
650                         throw new IOException JavaDoc(
651                                 Messages.getMessage(
652                                         "wrongNamespace00", qn.getLocalPart(),
653                                         qn.getNamespaceURI()));
654                     }
655
656                     // Check for a undefined XSD Schema Type and throw
657
// an unsupported message instead of undefined
658
if (SchemaUtils.isSimpleSchemaType(qn)) {
659                         throw new IOException JavaDoc(
660                                 Messages.getMessage(
661                                         "unsupportedSchemaType00", qn.getLocalPart()));
662                     }
663
664                     // last case, its some other undefined thing
665
throw new IOException JavaDoc(
666                             Messages.getMessage(
667                                     "undefined00", qn.toString()));
668                 } // if undefined
669
else if (entry instanceof UndefinedElement) {
670                     throw new IOException JavaDoc(
671                             Messages.getMessage(
672                                     "undefinedElem00", entry.getQName().toString()));
673                 }
674             }
675         }
676     } // checkForUndefined
677

678     /**
679      * Add the given Definition and Document information to the symbol table (including imported
680      * symbols), populating it with SymTabEntries for each of the top-level symbols.
681      * NOTE: filename is used only by checkForUndefined so that it can report which WSDL file
682      * has the problem. If we're on the primary WSDL file, then we don't know the name and
683      * filename will be null. But we know the names of all imported files.
684      */

685     private URLHashSet importedFiles = new URLHashSet();
686
687     /**
688      * Method populate
689      *
690      * @param context
691      * @param def
692      * @param doc
693      * @param filename
694      * @throws IOException
695      * @throws ParserConfigurationException
696      * @throws SAXException
697      * @throws WSDLException
698      */

699     private void populate(
700             URL JavaDoc context, Definition def, Document JavaDoc doc, String JavaDoc filename)
701             throws IOException JavaDoc, ParserConfigurationException JavaDoc, SAXException JavaDoc,
702             WSDLException {
703
704         if (doc != null) {
705             populateTypes(context, doc);
706
707             if (addImports) {
708
709                 // Add the symbols from any xsd:import'ed documents.
710
lookForImports(context, doc);
711             }
712         }
713
714         if (def != null) {
715             checkForUndefined(def, filename);
716
717             if (addImports) {
718
719                 // Add the symbols from the wsdl:import'ed WSDL documents
720
Map JavaDoc imports = def.getImports();
721                 Object JavaDoc[] importKeys = imports.keySet().toArray();
722
723                 for (int i = 0; i < importKeys.length; ++i) {
724                     Vector JavaDoc v = (Vector JavaDoc) imports.get(importKeys[i]);
725
726                     for (int j = 0; j < v.size(); ++j) {
727                         Import imp = (Import) v.get(j);
728
729                         if (!importedFiles.contains(imp.getLocationURI())) {
730                             importedFiles.add(imp.getLocationURI());
731
732                             URL JavaDoc url = getURL(context, imp.getLocationURI());
733
734                             populate(url, imp.getDefinition(),
735                                     XMLUtils.newDocument(url.toString()),
736                                     url.toString());
737                         }
738                     }
739                 }
740             }
741
742             populateMessages(def);
743             populatePortTypes(def);
744             populateBindings(def);
745             populateServices(def);
746         }
747     } // populate
748

749     /**
750      * This is essentially a call to "new URL(contextURL, spec)" with extra handling in case spec is
751      * a file.
752      *
753      * @param contextURL
754      * @param spec
755      * @return
756      * @throws IOException
757      */

758     private static URL JavaDoc getURL(URL JavaDoc contextURL, String JavaDoc spec) throws IOException JavaDoc {
759
760         // First, fix the slashes as windows filenames may have backslashes
761
// in them, but the URL class wont do the right thing when we later
762
// process this URL as the contextURL.
763
String JavaDoc path = spec.replace('\\', '/');
764
765         // See if we have a good URL.
766
URL JavaDoc url = null;
767
768         try {
769
770             // first, try to treat spec as a full URL
771
url = new URL JavaDoc(contextURL, path);
772
773             // if we are deail with files in both cases, create a url
774
// by using the directory of the context URL.
775
if ((contextURL != null) && url.getProtocol().equals("file")
776                     && contextURL.getProtocol().equals("file")) {
777                 url = getFileURL(contextURL, path);
778             }
779         } catch (MalformedURLException JavaDoc me) {
780
781             // try treating is as a file pathname
782
url = getFileURL(contextURL, path);
783         }
784
785         // Everything is OK with this URL, although a file url constructed
786
// above may not exist. This will be caught later when the URL is
787
// accessed.
788
return url;
789     } // getURL
790

791     /**
792      * Method getFileURL
793      *
794      * @param contextURL
795      * @param path
796      * @return
797      * @throws IOException
798      */

799     private static URL JavaDoc getFileURL(URL JavaDoc contextURL, String JavaDoc path)
800             throws IOException JavaDoc {
801
802         if (contextURL != null) {
803
804             // get the parent directory of the contextURL, and append
805
// the spec string to the end.
806
String JavaDoc contextFileName = contextURL.getFile();
807             URL JavaDoc parent = null;
808             File JavaDoc parentFile = new File JavaDoc(contextFileName).getParentFile();
809             if ( parentFile != null ) {
810                 parent = parentFile.toURL();
811             }
812             if (parent != null) {
813                 return new URL JavaDoc(parent, path);
814             }
815         }
816
817         return new URL JavaDoc("file", "", path);
818     } // getFileURL
819

820     /**
821      * Recursively find all xsd:import'ed objects and call populate for each one.
822      *
823      * @param context
824      * @param node
825      * @throws IOException
826      * @throws ParserConfigurationException
827      * @throws SAXException
828      * @throws WSDLException
829      */

830     private void lookForImports(URL JavaDoc context, Node JavaDoc node)
831             throws IOException JavaDoc, ParserConfigurationException JavaDoc, SAXException JavaDoc,
832             WSDLException {
833
834         NodeList JavaDoc children = node.getChildNodes();
835
836         for (int i = 0; i < children.getLength(); i++) {
837             Node JavaDoc child = children.item(i);
838
839             if ("import".equals(child.getLocalName())) {
840                 NamedNodeMap JavaDoc attributes = child.getAttributes();
841                 Node JavaDoc namespace = attributes.getNamedItem("namespace");
842
843                 // skip XSD import of soap encoding
844
if ((namespace != null)
845                         && isKnownNamespace(namespace.getNodeValue())) {
846                     continue;
847                 }
848
849                 Node JavaDoc importFile = attributes.getNamedItem("schemaLocation");
850
851                 if (importFile != null) {
852                     URL JavaDoc url = getURL(context, importFile.getNodeValue());
853
854                     if (!importedFiles.contains(url)) {
855                         importedFiles.add(url);
856
857                         String JavaDoc filename = url.toString();
858
859                         populate(url, null, XMLUtils.newDocument(filename),
860                                 filename);
861                     }
862                 }
863             }
864
865             lookForImports(context, child);
866         }
867     } // lookForImports
868

869     /**
870      * Check if this is a known namespace (soap-enc or schema xsd or schema xsi or xml)
871      *
872      * @param namespace
873      * @return true if this is a know namespace.
874      */

875     public boolean isKnownNamespace(String JavaDoc namespace) {
876
877         if (Constants.isSOAP_ENC(namespace)) {
878             return true;
879         }
880
881         if (Constants.isSchemaXSD(namespace)) {
882             return true;
883         }
884
885         if (Constants.isSchemaXSI(namespace)) {
886             return true;
887         }
888
889         if (namespace.equals(Constants.NS_URI_XML)) {
890             return true;
891         }
892
893         return false;
894     }
895
896     /**
897      * Populate the symbol table with all of the Types from the Document.
898      *
899      * @param context
900      * @param doc
901      * @throws IOException
902      * @throws SAXException
903      * @throws WSDLException
904      * @throws ParserConfigurationException
905      */

906     public void populateTypes(URL JavaDoc context, Document JavaDoc doc)
907             throws IOException JavaDoc, SAXException JavaDoc, WSDLException,
908             ParserConfigurationException JavaDoc {
909         addTypes(context, doc, ABOVE_SCHEMA_LEVEL);
910     } // populateTypes
911

912     /**
913      * Utility method which walks the Document and creates Type objects for
914      * each complexType, simpleType, attributeGroup or element referenced or defined.
915      * <p/>
916      * What goes into the symbol table? In general, only the top-level types
917      * (ie., those just below
918      * the schema tag). But base types and references can
919      * appear below the top level. So anything
920      * at the top level is added to the symbol table,
921      * plus non-Element types (ie, base and refd)
922      * that appear deep within other types.
923      */

924     private static final int ABOVE_SCHEMA_LEVEL = -1;
925
926     /** Field SCHEMA_LEVEL */
927     private static final int SCHEMA_LEVEL = 0;
928
929     /**
930      * Method addTypes
931      *
932      * @param context
933      * @param node
934      * @param level
935      * @throws IOException
936      * @throws ParserConfigurationException
937      * @throws WSDLException
938      * @throws SAXException
939      */

940     private void addTypes(URL JavaDoc context, Node JavaDoc node, int level)
941             throws IOException JavaDoc, ParserConfigurationException JavaDoc, WSDLException,
942             SAXException JavaDoc {
943
944         if (node == null) {
945             return;
946         }
947
948         // Get the kind of node (complexType, wsdl:part, etc.)
949
String JavaDoc localPart = node.getLocalName();
950
951         if (localPart != null) {
952             boolean isXSD =
953                     Constants.isSchemaXSD(node.getNamespaceURI());
954
955             if (((isXSD && localPart.equals("complexType"))
956                     || localPart.equals("simpleType"))) {
957
958                 // If an extension or restriction is present,
959
// create a type for the reference
960
Node JavaDoc re = SchemaUtils.getRestrictionOrExtensionNode(node);
961
962                 if ((re != null) && (Utils.getAttribute(re, "base") != null)) {
963                     createTypeFromRef(re);
964                 }
965
966                 Node JavaDoc list = SchemaUtils.getListNode(node);
967                 if (list != null && Utils.getAttribute(list,"itemType") != null) {
968                     createTypeFromRef(list);
969                 }
970
971                 Node JavaDoc union = SchemaUtils.getUnionNode(node);
972                 if (union != null) {
973                     QName JavaDoc [] memberTypes = Utils.getMemberTypeQNames(union);
974                     if (memberTypes != null) {
975                         for (int i=0;i<memberTypes.length;i++) {
976                             if (SchemaUtils.isSimpleSchemaType(memberTypes[i]) &&
977                                 getType(memberTypes[i]) == null) {
978                                 symbolTablePut(new BaseType(memberTypes[i]));
979                             }
980                         }
981                     }
982                 }
983
984                 // This is a definition of a complex type.
985
// Create a Type.
986
createTypeFromDef(node, false, false);
987             } else if (isXSD && localPart.equals("element")) {
988
989                 // Create a type entry for the referenced type
990
createTypeFromRef(node);
991
992                 // If an extension or restriction is present,
993
// create a type for the reference
994
Node JavaDoc re = SchemaUtils.getRestrictionOrExtensionNode(node);
995
996                 if ((re != null) && (Utils.getAttribute(re, "base") != null)) {
997                     createTypeFromRef(re);
998                 }
999
1000                // Create a type representing an element. (This may
1001
// seem like overkill, but is necessary to support ref=
1002
// and element=.
1003
createTypeFromDef(node, true, level > SCHEMA_LEVEL);
1004            } else if (isXSD && localPart.equals("attributeGroup")) {
1005
1006                // bug 23145: support attributeGroup (Brook Richan)
1007
// Create a type entry for the referenced type
1008
createTypeFromRef(node);
1009
1010                // Create a type representing an attributeGroup.
1011
createTypeFromDef(node, false, level > SCHEMA_LEVEL);
1012            } else if (isXSD && localPart.equals("group")) {
1013                // Create a type entry for the referenced type
1014
createTypeFromRef(node);
1015                // Create a type representing an group
1016
createTypeFromDef(node, false, level > SCHEMA_LEVEL);
1017            } else if (isXSD && localPart.equals("attribute")) {
1018
1019                // Create a type entry for the referenced type
1020
BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
1021                QName JavaDoc refQName = Utils.getTypeQName(node, forElement,
1022                        false);
1023
1024                if ((refQName != null) && !forElement.value) {
1025                    createTypeFromRef(node);
1026
1027                    // Get the symbol table entry and make sure it is a simple
1028
// type
1029
if (refQName != null) {
1030                        TypeEntry refType = getTypeEntry(refQName, false);
1031
1032                        if ((refType != null)
1033                                && (refType instanceof Undefined)) {
1034
1035                            // Don't know what the type is.
1036
// It better be simple so set it as simple
1037
refType.setSimpleType(true);
1038                        } else if ((refType == null)
1039                                || (!(refType instanceof BaseType)
1040                                && !refType.isSimpleType())) {
1041
1042                            // Problem if not simple
1043
throw new IOException JavaDoc(
1044                                    Messages.getMessage(
1045                                            "AttrNotSimpleType01",
1046                                            refQName.toString()));
1047                        }
1048                    }
1049                }
1050                createTypeFromDef(node, true, level > SCHEMA_LEVEL);
1051            } else if (isXSD && localPart.equals("any")) {
1052
1053                // Map xsd:any element to special xsd:any "type"
1054
if (getType(Constants.XSD_ANY) == null) {
1055                    Type type = new BaseType(Constants.XSD_ANY);
1056
1057                    symbolTablePut(type);
1058                }
1059            } else if (localPart.equals("part")
1060                    && Constants.isWSDL(node.getNamespaceURI())) {
1061
1062                // This is a wsdl part. Create an TypeEntry representing the reference
1063
createTypeFromRef(node);
1064            } else if (isXSD && localPart.equals("include")) {
1065                String JavaDoc includeName = Utils.getAttribute(node, "schemaLocation");
1066
1067                if (includeName != null) {
1068                    URL JavaDoc url = getURL(context, includeName);
1069                    Document JavaDoc includeDoc = XMLUtils.newDocument(url.toString());
1070
1071                    // Vidyanand : Fix for Bug #15124
1072
org.w3c.dom.Element JavaDoc schemaEl =
1073                            includeDoc.getDocumentElement();
1074
1075                    if (!schemaEl.hasAttribute("targetNamespace")) {
1076                        org.w3c.dom.Element JavaDoc parentSchemaEl =
1077                                (org.w3c.dom.Element JavaDoc) node.getParentNode();
1078
1079                        if (parentSchemaEl.hasAttribute("targetNamespace")) {
1080
1081                            // we need to set two things in here
1082
// 1. targetNamespace
1083
// 2. setup the xmlns=<targetNamespace> attribute
1084
String JavaDoc tns =
1085                                    parentSchemaEl.getAttribute("targetNamespace");
1086
1087                            schemaEl.setAttribute("targetNamespace", tns);
1088                            schemaEl.setAttribute("xmlns", tns);
1089                        }
1090                    }
1091
1092                    populate(url, null, includeDoc, url.toString());
1093                }
1094            }
1095        }
1096
1097        if (level == ABOVE_SCHEMA_LEVEL) {
1098            if ((localPart != null)
1099                && localPart.equals("schema")) {
1100                level = SCHEMA_LEVEL;
1101                String JavaDoc targetNamespace = ((org.w3c.dom.Element JavaDoc) node).getAttribute("targetNamespace");
1102                String JavaDoc elementFormDefault = ((org.w3c.dom.Element JavaDoc) node).getAttribute("elementFormDefault");
1103                if (targetNamespace != null && targetNamespace.length() > 0) {
1104                    elementFormDefault = (elementFormDefault == null || elementFormDefault.length() == 0) ?
1105                            "unqualified" : elementFormDefault;
1106                    if(elementFormDefaults.get(targetNamespace)==null) {
1107                        elementFormDefaults.put(targetNamespace, elementFormDefault);
1108                    }
1109                }
1110            }
1111        } else {
1112            ++level;
1113        }
1114
1115        // Recurse through children nodes
1116
NodeList JavaDoc children = node.getChildNodes();
1117
1118        for (int i = 0; i < children.getLength(); i++) {
1119            addTypes(context, children.item(i), level);
1120        }
1121    } // addTypes
1122

1123    /**
1124     * Create a TypeEntry from the indicated node, which defines a type
1125     * that represents a complexType, simpleType or element (for ref=).
1126     *
1127     * @param node
1128     * @param isElement
1129     * @param belowSchemaLevel
1130     * @throws IOException
1131     */

1132    private void createTypeFromDef(
1133            Node JavaDoc node, boolean isElement, boolean belowSchemaLevel)
1134            throws IOException JavaDoc {
1135
1136        // Get the QName of the node's name attribute value
1137
QName JavaDoc qName = Utils.getNodeNameQName(node);
1138
1139        if (qName != null) {
1140
1141            // If the qname is already registered as a base type,
1142
// don't create a defining type/element.
1143
if (!isElement && (btm.getBaseName(qName) != null)) {
1144                return;
1145            }
1146
1147            // If the node has a type or ref attribute, get the
1148
// qname representing the type
1149
BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
1150            QName JavaDoc refQName = Utils.getTypeQName(node, forElement,
1151                    false);
1152
1153            if (refQName != null) {
1154
1155                // Error check - bug 12362
1156
if (qName.getLocalPart().length() == 0) {
1157                    String JavaDoc name = Utils.getAttribute(node, "name");
1158
1159                    if (name == null) {
1160                        name = "unknown";
1161                    }
1162
1163                    throw new IOException JavaDoc(Messages.getMessage("emptyref00",
1164                            name));
1165                }
1166
1167                // Now get the TypeEntry
1168
TypeEntry refType = getTypeEntry(refQName, forElement.value);
1169
1170                if (!belowSchemaLevel) {
1171                    if (refType == null) {
1172                        throw new IOException JavaDoc(
1173                                Messages.getMessage(
1174                                        "absentRef00", refQName.toString(),
1175                                        qName.toString()));
1176                    }
1177
1178                    symbolTablePut(new DefinedElement(qName, refType, node,
1179                            ""));
1180                }
1181            } else {
1182
1183                // Flow to here indicates no type= or ref= attribute.
1184
// See if this is an array or simple type definition.
1185
IntHolder JavaDoc numDims = new IntHolder JavaDoc();
1186                BooleanHolder JavaDoc underlTypeNillable = new BooleanHolder JavaDoc();
1187
1188                // If we're supposed to unwrap arrays, supply someplace to put the "inner" QName
1189
// so we can propagate it into the appropriate metadata container.
1190
QNameHolder JavaDoc itemQName = wrapArrays ? null : new QNameHolder JavaDoc();
1191
1192                numDims.value = 0;
1193
1194                QName JavaDoc arrayEQName =
1195                        SchemaUtils.getArrayComponentQName(node,
1196                                                           numDims,
1197                                                           underlTypeNillable,
1198                                                           itemQName,
1199                                                           this);
1200
1201                if (arrayEQName != null) {
1202
1203                    // Get the TypeEntry for the array element type
1204
refQName = arrayEQName;
1205
1206                    TypeEntry refType = getTypeEntry(refQName, false);
1207
1208                    if (refType == null) {
1209// arrayTypeQNames.add(refQName);
1210

1211                        // Not defined yet, add one
1212
String JavaDoc baseName = btm.getBaseName(refQName);
1213
1214                        if (baseName != null) {
1215                            refType = new BaseType(refQName);
1216                        } else {
1217                            refType = new UndefinedType(refQName);
1218                        }
1219
1220                        symbolTablePut(refType);
1221                    }
1222
1223                    // Create a defined type or element that references refType
1224
String JavaDoc dims = "";
1225
1226                    while (numDims.value > 0) {
1227                        dims += "[]";
1228
1229                        numDims.value--;
1230                    }
1231
1232                    TypeEntry defType = null;
1233
1234                    if (isElement) {
1235                        if (!belowSchemaLevel) {
1236                            defType =
1237                               new DefinedElement(qName, refType, node, dims);
1238                            // Save component type for ArraySerializer
1239
defType.setComponentType(arrayEQName);
1240                            if (itemQName != null)
1241                                defType.setItemQName(itemQName.value);
1242                        }
1243                    } else {
1244                        defType = new DefinedType(qName, refType, node, dims);
1245                        // Save component type for ArraySerializer
1246
defType.setComponentType(arrayEQName);
1247                        defType.setUnderlTypeNillable(underlTypeNillable.value);
1248                        if (itemQName != null)
1249                            defType.setItemQName(itemQName.value);
1250                    }
1251
1252                    if (defType != null) {
1253                        symbolTablePut(defType);
1254                    }
1255                } else {
1256
1257                    // Create a TypeEntry representing this type/element
1258
String JavaDoc baseName = btm.getBaseName(qName);
1259
1260                    if (baseName != null) {
1261                        symbolTablePut(new BaseType(qName));
1262                    } else {
1263
1264                        // Create a type entry, set whether it should
1265
// be mapped as a simple type, and put it in the
1266
// symbol table.
1267
TypeEntry te = null;
1268                        TypeEntry parentType = null;
1269
1270                        if (!isElement) {
1271                            te = new DefinedType(qName, node);
1272
1273                            // check if we are an anonymous type underneath
1274
// an element. If so, we point the refType of the
1275
// element to us (the real type).
1276
if (qName.getLocalPart().indexOf(ANON_TOKEN) >= 0) {
1277                                Node JavaDoc parent = node.getParentNode();
1278                                QName JavaDoc parentQName =
1279                                        Utils.getNodeNameQName(parent);
1280                                parentType = getElement(parentQName);
1281                            }
1282                        } else {
1283                            if (!belowSchemaLevel) {
1284                                te = new DefinedElement(qName, node);
1285                            }
1286                        }
1287
1288                        if (te != null) {
1289                            if (SchemaUtils.isSimpleTypeOrSimpleContent(node)) {
1290                                te.setSimpleType(true);
1291                            }
1292                            te = (TypeEntry)symbolTablePut(te);
1293
1294                            if (parentType != null) {
1295                                parentType.setRefType(te);
1296                            }
1297                        }
1298                    }
1299                }
1300            }
1301        }
1302    } // createTypeFromDef
1303

1304    /**
1305     * Node may contain a reference (via type=, ref=, or element= attributes) to
1306     * another type. Create a Type object representing this referenced type.
1307     *
1308     * @param node
1309     * @throws IOException
1310     */

1311    private void createTypeFromRef(Node JavaDoc node) throws IOException JavaDoc {
1312
1313        // Get the QName of the node's type attribute value
1314
BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
1315        QName JavaDoc qName = Utils.getTypeQName(node, forElement, false);
1316
1317        if (qName == null || (Constants.isSchemaXSD(qName.getNamespaceURI()) &&
1318                qName.getLocalPart().equals("simpleRestrictionModel"))) {
1319            return;
1320        }
1321
1322        // Error check - bug 12362
1323
if (qName.getLocalPart().length() == 0) {
1324            String JavaDoc name = Utils.getAttribute(node, "name");
1325
1326            if (name == null) {
1327                name = "unknown";
1328            }
1329
1330            throw new IOException JavaDoc(Messages.getMessage("emptyref00", name));
1331        }
1332
1333        // Get Type or Element depending on whether type attr was used.
1334
TypeEntry type = getTypeEntry(qName, forElement.value);
1335
1336        // A symbol table entry is created if the TypeEntry is not found
1337
if (type == null) {
1338
1339            // See if this is a special QName for collections
1340
if (qName.getLocalPart().indexOf("[") > 0) {
1341                QName JavaDoc containedQName = Utils.getTypeQName(node,
1342                        forElement, true);
1343                TypeEntry containedTE = getTypeEntry(containedQName,
1344                        forElement.value);
1345
1346                if (!forElement.value) {
1347
1348                    // Case of type and maxOccurs
1349
if (containedTE == null) {
1350
1351                        // Collection Element Type not defined yet, add one.
1352
String JavaDoc baseName = btm.getBaseName(containedQName);
1353
1354                        if (baseName != null) {
1355                            containedTE = new BaseType(containedQName);
1356                        } else {
1357                            containedTE = new UndefinedType(containedQName);
1358                        }
1359
1360                        symbolTablePut(containedTE);
1361                    }
1362                    symbolTablePut(new CollectionType(qName, containedTE,
1363                            node, "[]"));
1364                } else {
1365
1366                    // Case of ref and maxOccurs
1367
if (containedTE == null) {
1368                        containedTE = new UndefinedElement(containedQName);
1369
1370                        symbolTablePut(containedTE);
1371                    }
1372
1373                    symbolTablePut(new CollectionElement(qName,
1374                            containedTE, node,
1375                            "[]"));
1376                }
1377            } else {
1378
1379                // Add a BaseType or Undefined Type/Element
1380
String JavaDoc baseName = btm.getBaseName(qName);
1381
1382                if (baseName != null) {
1383                    symbolTablePut(new BaseType(qName));
1384
1385                    // bugzilla 23145: handle attribute groups
1386
// soap/encoding is treated as a "known" schema
1387
// so now let's act like we know it
1388
} else if (qName.equals(Constants.SOAP_COMMON_ATTRS11)) {
1389                    symbolTablePut(new BaseType(qName));
1390
1391                    // the 1.1 commonAttributes type contains two attributes
1392
// make sure those attributes' types are in the symbol table
1393
// attribute name = "id" type = "xsd:ID"
1394
if (getTypeEntry(Constants.XSD_ID, false) == null) {
1395                        symbolTablePut(new BaseType(Constants.XSD_ID));
1396                    }
1397
1398                    // attribute name = "href" type = "xsd:anyURI"
1399
if (getTypeEntry(Constants.XSD_ANYURI, false) == null) {
1400                        symbolTablePut(new BaseType(Constants.XSD_ANYURI));
1401                    }
1402                } else if (qName.equals(Constants.SOAP_COMMON_ATTRS12)) {
1403                    symbolTablePut(new BaseType(qName));
1404
1405                    // the 1.2 commonAttributes type contains one attribute
1406
// make sure the attribute's type is in the symbol table
1407
// attribute name = "id" type = "xsd:ID"
1408
if (getTypeEntry(Constants.XSD_ID, false) == null) {
1409                        symbolTablePut(new BaseType(Constants.XSD_ID));
1410                    }
1411                } else if (qName.equals(Constants.SOAP_ARRAY_ATTRS11)) {
1412                    symbolTablePut(new BaseType(qName));
1413
1414                    // the 1.1 arrayAttributes type contains two attributes
1415
// make sure the attributes' types are in the symbol table
1416
// attribute name = "arrayType" type = "xsd:string"
1417
if (getTypeEntry(Constants.XSD_STRING, false) == null) {
1418                        symbolTablePut(new BaseType(Constants.XSD_STRING));
1419                    }
1420
1421                    // attribute name = "offset" type = "soapenc:arrayCoordinate"
1422
// which is really an xsd:string
1423
} else if (qName.equals(Constants.SOAP_ARRAY_ATTRS12)) {
1424                    symbolTablePut(new BaseType(qName));
1425
1426                    // the 1.2 arrayAttributes type contains two attributes
1427
// make sure the attributes' types are in the symbol table
1428
// attribute name = "arraySize" type = "2003soapenc:arraySize"
1429
// which is really a hairy beast that is not
1430
// supported, yet; so let's just use string
1431
if (getTypeEntry(Constants.XSD_STRING, false) == null) {
1432                        symbolTablePut(new BaseType(Constants.XSD_STRING));
1433                    }
1434
1435                    // attribute name = "itemType" type = "xsd:QName"
1436
if (getTypeEntry(Constants.XSD_QNAME, false) == null) {
1437                        symbolTablePut(new BaseType(Constants.XSD_QNAME));
1438                    }
1439                } else if (forElement.value == false) {
1440                    symbolTablePut(new UndefinedType(qName));
1441                } else {
1442                    symbolTablePut(new UndefinedElement(qName));
1443                }
1444            }
1445        }
1446    } // createTypeFromRef
1447

1448    /**
1449     * Populate the symbol table with all of the MessageEntry's from the Definition.
1450     *
1451     * @param def
1452     * @throws IOException
1453     */

1454    private void populateMessages(Definition def) throws IOException JavaDoc {
1455
1456        Iterator JavaDoc i = def.getMessages().values().iterator();
1457
1458        while (i.hasNext()) {
1459            Message message = (Message) i.next();
1460            MessageEntry mEntry = new MessageEntry(message);
1461
1462            symbolTablePut(mEntry);
1463        }
1464    } // populateMessages
1465

1466    /**
1467     * ensures that a message in a <code>&lt;input&gt;</code>, <code>&lt;output&gt;</code>,
1468     * or <code>&lt;fault&gt;</fault> element in an <code>&lt;operation&gt;</code>
1469     * element is valid. In particular, ensures that
1470     * <ol>
1471     * <li>an attribute <code>message</code> is present (according to the
1472     * XML Schema for WSDL 1.1 <code>message</code> is <strong>required</strong>
1473     * <p/>
1474     * <li>the value of attribute <code>message</code> (a QName) refers to
1475     * an already defined message
1476     * </ol>
1477     * <p/>
1478     * <strong>Note</strong>: this method should throw a <code>javax.wsdl.WSDLException</code> rather than
1479     * a <code>java.io.IOException</code>
1480     *
1481     * @param message the message object
1482     * @throws IOException thrown, if the message is not valid
1483     */

1484    protected void ensureOperationMessageValid(Message message)
1485            throws IOException JavaDoc {
1486
1487        // make sure the message is not null (i.e. there is an
1488
// attribute 'message ')
1489
//
1490
if (message == null) {
1491            throw new IOException JavaDoc(
1492                    "<input>,<output>, or <fault> in <operation ..> without attribute 'message' found. Attribute 'message' is required.");
1493        }
1494
1495        // make sure the value of the attribute refers to an
1496
// already defined message
1497
//
1498
if (message.isUndefined()) {
1499            throw new IOException JavaDoc(
1500                    "<input ..>, <output ..> or <fault ..> in <portType> with undefined message found. message name is '"
1501                    + message.getQName().toString() + "'");
1502        }
1503    }
1504
1505    /**
1506     * ensures that an an element <code>&lt;operation&gt;</code> within
1507     * an element <code>&lt;portType&gt;<code> is valid. Throws an exception
1508     * if the operation is not valid.
1509     * <p/>
1510     * <strong>Note</strong>: this method should throw a <code>javax.wsdl.WSDLException</code>
1511     * rather than a <code>java.io.IOException</code>
1512     *
1513     * @param operation the operation element
1514     * @throws IOException thrown, if the element is not valid.
1515     * @throws IllegalArgumentException thrown, if operation is null
1516     */

1517    protected void ensureOperationValid(Operation operation)
1518            throws IOException JavaDoc {
1519
1520        if (operation == null) {
1521            throw new IllegalArgumentException JavaDoc(
1522                    "parameter 'operation' must not be null");
1523        }
1524
1525        Input input = operation.getInput();
1526        Message message;
1527        
1528        if (input != null) {
1529            message = input.getMessage();
1530            if (message == null) {
1531                throw new IOException JavaDoc(
1532                        "No 'message' attribute in <input> for operation '" +
1533                        operation.getName() + "'");
1534            }
1535            ensureOperationMessageValid(message);
1536        }
1537
1538        Output output = operation.getOutput();
1539
1540        if (output != null) {
1541            message = output.getMessage();
1542            if (message == null) {
1543                throw new IOException JavaDoc(
1544                        "No 'message' attribute in <output> for operation '" +
1545                        operation.getName() + "'");
1546            }
1547            ensureOperationMessageValid(output.getMessage());
1548        }
1549
1550        Map JavaDoc faults = operation.getFaults();
1551
1552        if (faults != null) {
1553            Iterator JavaDoc it = faults.values().iterator();
1554
1555            while (it.hasNext()) {
1556                Fault fault = (Fault)it.next();
1557                message = fault.getMessage();
1558                if (message == null) {
1559                    throw new IOException JavaDoc(
1560                            "No 'message' attribute in <fault> named '" +
1561                            fault.getName() + "' for operation '" +
1562                            operation.getName() + "'");
1563                }
1564                ensureOperationMessageValid(message);
1565            }
1566        }
1567    }
1568
1569    /**
1570     * ensures that an an element <code>&lt;portType&gt;</code>
1571     * is valid. Throws an exception if the portType is not valid.
1572     * <p/>
1573     * <strong>Note</strong>: this method should throw a <code>javax.wsdl.WSDLException</code>
1574     * rather than a <code>java.io.IOException</code>
1575     *
1576     * @param portType the portType element
1577     * @throws IOException thrown, if the element is not valid.
1578     * @throws IllegalArgumentException thrown, if operation is null
1579     */

1580    protected void ensureOperationsOfPortTypeValid(PortType portType)
1581            throws IOException JavaDoc {
1582
1583        if (portType == null) {
1584            throw new IllegalArgumentException JavaDoc(
1585                    "parameter 'portType' must not be null");
1586        }
1587
1588        List JavaDoc operations = portType.getOperations();
1589
1590        // no operations defined ? -> valid according to the WSDL 1.1 schema
1591
//
1592
if ((operations == null) || (operations.size() == 0)) {
1593            return;
1594        }
1595
1596        // check operations defined in this portType
1597
//
1598
Iterator JavaDoc it = operations.iterator();
1599
1600        while (it.hasNext()) {
1601            Operation operation = (Operation) it.next();
1602
1603            ensureOperationValid(operation);
1604        }
1605    }
1606
1607    /**
1608     * Populate the symbol table with all of the PortTypeEntry's from the Definition.
1609     *
1610     * @param def
1611     * @throws IOException
1612     */

1613    private void populatePortTypes(Definition def) throws IOException JavaDoc {
1614
1615        Iterator JavaDoc i = def.getPortTypes().values().iterator();
1616
1617        while (i.hasNext()) {
1618            PortType portType = (PortType) i.next();
1619
1620            // If the portType is undefined, then we're parsing a Definition
1621
// that didn't contain a portType, merely a binding that referred
1622
// to a non-existent port type. Don't bother with it.
1623
if (!portType.isUndefined()) {
1624                ensureOperationsOfPortTypeValid(portType);
1625
1626                PortTypeEntry ptEntry = new PortTypeEntry(portType);
1627
1628                symbolTablePut(ptEntry);
1629            }
1630        }
1631    } // populatePortTypes
1632

1633    /**
1634     * Create the parameters and store them in the bindingEntry.
1635     *
1636     * @throws IOException
1637     */

1638    private void populateParameters() throws IOException JavaDoc {
1639
1640        Iterator JavaDoc it = symbolTable.values().iterator();
1641
1642        while (it.hasNext()) {
1643            Vector JavaDoc v = (Vector JavaDoc) it.next();
1644
1645            for (int i = 0; i < v.size(); ++i) {
1646                if (v.get(i) instanceof BindingEntry) {
1647                    BindingEntry bEntry = (BindingEntry) v.get(i);
1648
1649                    // Skip non-soap bindings
1650
if (bEntry.getBindingType() != BindingEntry.TYPE_SOAP) {
1651                        continue;
1652                    }
1653
1654                    Binding binding = bEntry.getBinding();
1655                    Collection JavaDoc bindOperations = bEntry.getOperations();
1656                    PortType portType = binding.getPortType();
1657                    HashMap JavaDoc parameters = new HashMap JavaDoc();
1658                    Iterator JavaDoc operations =
1659                            portType.getOperations().iterator();
1660
1661                    // get parameters
1662
while (operations.hasNext()) {
1663                        Operation operation = (Operation) operations.next();
1664
1665                        // See if the PortType operation has a corresponding
1666
// Binding operation and report an error if it doesn't.
1667
if (!bindOperations.contains(operation)) {
1668                            throw new IOException JavaDoc(
1669                                    Messages.getMessage(
1670                                            "emitFailNoMatchingBindOperation01",
1671                                            operation.getName(),
1672                                            portType.getQName().getLocalPart()));
1673                        }
1674
1675                        String JavaDoc namespace =
1676                                portType.getQName().getNamespaceURI();
1677                        Parameters parms = getOperationParameters(operation,
1678                                namespace, bEntry);
1679                        parameters.put(operation, parms);
1680                    }
1681
1682                    bEntry.setParameters(parameters);
1683                }
1684            }
1685        }
1686    } // populateParameters
1687

1688    /**
1689     * For the given operation, this method returns the parameter info conveniently collated.
1690     * There is a bit of processing that is needed to write the interface, stub, and skeleton.
1691     * Rather than do that processing 3 times, it is done once, here, and stored in the
1692     * Parameters object.
1693     *
1694     * @param operation
1695     * @param namespace
1696     * @param bindingEntry
1697     * @return
1698     * @throws IOException
1699     */

1700    public Parameters getOperationParameters(
1701            Operation operation, String JavaDoc namespace, BindingEntry bindingEntry)
1702            throws IOException JavaDoc {
1703
1704        Parameters parameters = new Parameters();
1705
1706        // The input and output Vectors of Parameters
1707
Vector JavaDoc inputs = new Vector JavaDoc();
1708        Vector JavaDoc outputs = new Vector JavaDoc();
1709        List JavaDoc parameterOrder = operation.getParameterOrdering();
1710
1711        // Handle parameterOrder="", which is techinically illegal
1712
if ((parameterOrder != null) && parameterOrder.isEmpty()) {
1713            parameterOrder = null;
1714        }
1715
1716        Input input = operation.getInput();
1717        Output output = operation.getOutput();
1718        
1719        parameters.mep = operation.getStyle();
1720        
1721        // All input parts MUST be in the parameterOrder list. It is an error otherwise.
1722
if (parameterOrder != null && !wrapped) {
1723            if (input != null) {
1724                Message inputMsg = input.getMessage();
1725                Map JavaDoc allInputs = inputMsg.getParts();
1726                Collection JavaDoc orderedInputs =
1727                        inputMsg.getOrderedParts(parameterOrder);
1728
1729                if (allInputs.size() != orderedInputs.size()) {
1730                    throw new IOException JavaDoc(
1731                            Messages.getMessage("emitFail00", operation.getName()));
1732                }
1733            }
1734        }
1735
1736        boolean literalInput = false;
1737        boolean literalOutput = false;
1738
1739        if (bindingEntry != null) {
1740            literalInput = (bindingEntry.getInputBodyType(operation)
1741                    == Use.LITERAL);
1742            literalOutput = (bindingEntry.getOutputBodyType(operation)
1743                    == Use.LITERAL);
1744        }
1745
1746        // Collect all the input parameters
1747
if ((input != null) && (input.getMessage() != null)) {
1748            getParametersFromParts(inputs,
1749                    input.getMessage().getOrderedParts(null),
1750                    literalInput, operation.getName(),
1751                    bindingEntry);
1752        }
1753
1754        // Collect all the output parameters
1755
if ((output != null) && (output.getMessage() != null)) {
1756            getParametersFromParts(outputs,
1757                    output.getMessage().getOrderedParts(null),
1758                    literalOutput, operation.getName(),
1759                    bindingEntry);
1760        }
1761
1762        if (parameterOrder != null && !wrapped) {
1763
1764            // Construct a list of the parameters in the parameterOrder list, determining the
1765
// mode of each parameter and preserving the parameterOrder list.
1766
for (int i = 0; i < parameterOrder.size(); ++i) {
1767                String JavaDoc name = (String JavaDoc) parameterOrder.get(i);
1768
1769                // index in the inputs Vector of the given name, -1 if it doesn't exist.
1770
int index = getPartIndex(name, inputs);
1771
1772                // index in the outputs Vector of the given name, -1 if it doesn't exist.
1773
int outdex = getPartIndex(name, outputs);
1774
1775                if (index >= 0) {
1776
1777                    // The mode of this parameter is either in or inout
1778
addInishParm(inputs, outputs, index, outdex, parameters,
1779                            true);
1780                } else if (outdex >= 0) {
1781                    addOutParm(outputs, outdex, parameters, true);
1782                } else {
1783                    System.err.println(Messages.getMessage("noPart00", name));
1784                }
1785            }
1786        }
1787
1788        // Some special case logic for JAX-RPC, but also to make things
1789
// nicer for the user.
1790
// If we have a single input and output with the same name
1791
// instead of: void echo(StringHolder inout)
1792
// Do this: string echo(string in)
1793
if (wrapped && (inputs.size() == 1) && (outputs.size() == 1)
1794                &&
1795                Utils.getLastLocalPart(((Parameter) inputs.get(0)).getName()).equals(
1796                Utils.getLastLocalPart(((Parameter) outputs.get(0)).getName()))
1797                ) {
1798
1799            // add the input and make sure its a IN not an INOUT
1800
addInishParm(inputs, null, 0, -1, parameters, false);
1801        } else {
1802
1803            // Get the mode info about those parts that aren't in the
1804
// parameterOrder list. Since they're not in the parameterOrder list,
1805
// the order is, first all in (and inout) parameters, then all out
1806
// parameters, in the order they appear in the messages.
1807
for (int i = 0; i < inputs.size(); i++) {
1808                Parameter p = (Parameter) inputs.get(i);
1809                int outdex = getPartIndex(p.getName(), outputs);
1810
1811                addInishParm(inputs, outputs, i, outdex, parameters, false);
1812            }
1813        }
1814
1815        // Now that the remaining in and inout parameters are collected,
1816
// determine the status of outputs. If there is only 1, then it
1817
// is the return value. If there are more than 1, then they are
1818
// out parameters.
1819
if (outputs.size() == 1) {
1820            parameters.returnParam = (Parameter) outputs.get(0);
1821
1822            parameters.returnParam.setMode(Parameter.OUT);
1823
1824            if (parameters.returnParam.getType() instanceof DefinedElement) {
1825                parameters.returnParam.setQName(
1826                        parameters.returnParam.getType().getQName());
1827            }
1828
1829            ++parameters.outputs;
1830        } else {
1831            for (int i = 0; i < outputs.size(); i++) {
1832                addOutParm(outputs, i, parameters, false);
1833            }
1834        }
1835
1836        parameters.faults = operation.getFaults();
1837
1838        // before we return the paramters,
1839
// make sure we dont have a duplicate name
1840
Vector JavaDoc used = new Vector JavaDoc(parameters.list.size());
1841        Iterator JavaDoc i = parameters.list.iterator();
1842
1843        while (i.hasNext()) {
1844            Parameter parameter = (Parameter) i.next();
1845            int count = 2;
1846
1847            while (used.contains(parameter.getName())) {
1848
1849                // duplicate, add a suffix and try again
1850
parameter.setName(parameter.getName()
1851                        + Integer.toString(count++));
1852            }
1853
1854            used.add(parameter.getName());
1855        }
1856
1857        return parameters;
1858    } // parameters
1859

1860    /**
1861     * Return the index of the given name in the given Vector, -1 if it doesn't exist.
1862     *
1863     * @param name
1864     * @param v
1865     * @return
1866     */

1867    private int getPartIndex(String JavaDoc name, Vector JavaDoc v) {
1868        name = Utils.getLastLocalPart(name);
1869        for (int i = 0; i < v.size(); i++) {
1870            String JavaDoc paramName = ((Parameter) v.get(i)).getName();
1871            paramName = Utils.getLastLocalPart(paramName);
1872            if (name.equals(paramName)) {
1873                return i;
1874            }
1875        }
1876
1877        return -1;
1878    } // getPartIndex
1879

1880    /**
1881     * Add an in or inout parameter to the parameters object.
1882     *
1883     * @param inputs
1884     * @param outputs
1885     * @param index
1886     * @param outdex
1887     * @param parameters
1888     * @param trimInput
1889     */

1890    private void addInishParm(Vector JavaDoc inputs, Vector JavaDoc outputs, int index,
1891                              int outdex, Parameters parameters,
1892                              boolean trimInput) {
1893
1894        Parameter p = (Parameter) inputs.get(index);
1895
1896        // If this is an element, we want the XML to reflect the element name
1897
// not the part name. Same check is made in addOutParam below.
1898
if (p.getType() instanceof DefinedElement) {
1899            DefinedElement de = (DefinedElement) p.getType();
1900
1901            p.setQName(de.getQName());
1902        }
1903
1904        // If this is a collection we want the XML to reflect the type in
1905
// the collection, not foo[unbounded].
1906
// Same check is made in addOutParam below.
1907
if (p.getType() instanceof CollectionElement) {
1908            p.setQName(p.getType().getRefType().getQName());
1909        }
1910
1911        // Should we remove the given parameter type/name entries from the Vector?
1912
if (trimInput) {
1913            inputs.remove(index);
1914        }
1915
1916        // At this point we know the name and type of the parameter, and that it's at least an
1917
// in parameter. Now check to see whether it's also in the outputs Vector. If it is,
1918
// then it's an inout parameter.
1919
if (outdex >= 0) {
1920            Parameter outParam = (Parameter) outputs.get(outdex);
1921
1922            TypeEntry paramEntry = p.getType();
1923            TypeEntry outParamEntry = outParam.getType();
1924// String paramLastLocalPart = Utils.getLastLocalPart(paramEntry.getQName().getLocalPart());
1925
// String outParamLastLocalPart = Utils.getLastLocalPart(outParamEntry.getQName().getLocalPart());
1926
if (paramEntry.equals(outParamEntry)) {
1927                outputs.remove(outdex);
1928                p.setMode(Parameter.INOUT);
1929
1930                ++parameters.inouts;
1931            }
1932            /*
1933            else if (paramLastLocalPart.equals(outParamLastLocalPart)) {
1934                outputs.remove(outdex);
1935                p.setMode(Parameter.INOUT);
1936
1937                ++parameters.inouts;
1938                if (paramEntry.isBaseType()) {
1939                    if (paramEntry.getBaseType().equals(outParamEntry.getBaseType())) {
1940                        outputs.remove(outdex);
1941                        p.setMode(Parameter.INOUT);
1942
1943                        ++parameters.inouts;
1944                    }
1945                }
1946                else if (paramEntry.getRefType() != null) {
1947                    if (paramEntry.getRefType().equals(outParamEntry.getRefType())) {
1948                        outputs.remove(outdex);
1949                        p.setMode(Parameter.INOUT);
1950
1951                        ++parameters.inouts;
1952                    }
1953                }
1954                else {
1955                    ++parameters.inputs;
1956                }
1957            }
1958        */

1959            else {
1960                
1961                // If we're here, we have both an input and an output
1962
// part with the same name but different types.... guess
1963
// it's not really an inout....
1964
//
1965
// throw new IOException(Messages.getMessage("differentTypes00",
1966
// new String[] { p.getName(),
1967
// p.getType().getQName().toString(),
1968
// outParam.getType().getQName().toString()
1969
// }
1970
// ));
1971
// There is some controversy about this, and the specs are
1972
// a bit vague about what should happen if the types don't
1973
// agree. Throwing an error is not correct with document/lit
1974
// operations, as part names get resused (i.e. "body").
1975
// See WSDL 1.1 section 2.4.6,
1976
// WSDL 1.2 working draft 9 July 2002 section 2.3.1
1977
++parameters.inputs;
1978            }
1979        } else {
1980            ++parameters.inputs;
1981        }
1982
1983        parameters.list.add(p);
1984    } // addInishParm
1985

1986    /**
1987     * Add an output parameter to the parameters object.
1988     *
1989     * @param outputs
1990     * @param outdex
1991     * @param parameters
1992     * @param trim
1993     */

1994    private void addOutParm(Vector JavaDoc outputs, int outdex, Parameters parameters,
1995                            boolean trim) {
1996
1997        Parameter p = (Parameter) outputs.get(outdex);
1998
1999        // If this is an element, we want the XML to reflect the element name
2000
// not the part name. Same check is made in addInishParam above.
2001
if (p.getType() instanceof DefinedElement) {
2002            DefinedElement de = (DefinedElement) p.getType();
2003
2004            p.setQName(de.getQName());
2005        }
2006
2007        // If this is a collection we want the XML to reflect the type in
2008
// the collection, not foo[unbounded].
2009
// Same check is made in addInishParam above.
2010
if (p.getType() instanceof CollectionElement) {
2011            p.setQName(p.getType().getRefType().getQName());
2012        }
2013
2014        if (trim) {
2015            outputs.remove(outdex);
2016        }
2017
2018        p.setMode(Parameter.OUT);
2019
2020        ++parameters.outputs;
2021
2022        parameters.list.add(p);
2023    } // addOutParm
2024

2025    /**
2026     * This method returns a vector containing Parameters which represent
2027     * each Part (shouldn't we call these "Parts" or something?)
2028     *
2029     * This routine does the wrapped doc/lit processing.
2030     * It is also used for generating Faults, and this really confuses things
2031     * but we need to do the same processing for the fault messages.
2032     *
2033     * This whole method is waaaay too complex.
2034     * It needs rewriting (for instance, we sometimes new up
2035     * a Parameter, then ignore it in favor of another we new up.)
2036     *
2037     * @param v The output vector of parameters
2038     * @param parts The parts of the message
2039     * @param literal Are we in a literal operation (or fault)?
2040     * @param opName The operation (or fault) name
2041     * @param bindingEntry The binding for this operation - can be NULL if we are looking at a fault
2042     * @throws IOException when encountering an error in the WSDL
2043     */

2044    public void getParametersFromParts(Vector JavaDoc v,
2045                                       Collection JavaDoc parts,
2046                                       boolean literal,
2047                                       String JavaDoc opName,
2048                                       BindingEntry bindingEntry)
2049            throws IOException JavaDoc {
2050
2051        // Determine if there's only one element. For wrapped
2052
// style, we normally only have 1 part which is an
2053
// element. But with MIME we could have any number of
2054
// types along with that single element. As long as
2055
// there's only ONE element, and it's the same name as
2056
// the operation, we can unwrap it.
2057
int numberOfElements = 0;
2058        boolean possiblyWrapped = false;
2059        Iterator JavaDoc i = parts.iterator();
2060
2061        while (i.hasNext()) {
2062            Part part = (Part) i.next();
2063
2064            if (part.getElementName() != null) {
2065                ++numberOfElements;
2066
2067                if (part.getElementName().getLocalPart().equals(opName)) {
2068                    possiblyWrapped = true;
2069                }
2070            }
2071        }
2072
2073        // Try to sense "wrapped" document literal mode
2074
// if we haven't been told not to.
2075
// Criteria:
2076
// - If there is a single element part,
2077
// - That part is an element
2078
// - That element has the same name as the operation
2079
// - That element has no attributes (check done below)
2080

2081        if (!nowrap && literal && (numberOfElements == 1) && possiblyWrapped) {
2082            wrapped = true;
2083        }
2084
2085        i = parts.iterator();
2086
2087        while (i.hasNext()) {
2088            Parameter param = new Parameter();
2089            Part part = (Part) i.next();
2090            QName JavaDoc elementName = part.getElementName();
2091            QName JavaDoc typeName = part.getTypeName();
2092            String JavaDoc partName = part.getName();
2093
2094            // if we are either:
2095
// 1. encoded
2096
// 2. literal & not wrapped.
2097
if (!literal || !wrapped || (elementName == null)) {
2098                param.setName(partName);
2099
2100                // Add this type or element name
2101
if (typeName != null) {
2102                    param.setType(getType(typeName));
2103                } else if (elementName != null) {
2104
2105                    // Just an FYI: The WSDL spec says that for use=encoded
2106
// that parts reference an abstract type using the type attr
2107
// but we kinda do the right thing here, so let it go.
2108
// if (!literal)
2109
// error...
2110
param.setType(getElement(elementName));
2111                } else {
2112
2113                    // no type or element
2114
throw new IOException JavaDoc(
2115                            Messages.getMessage(
2116                                    "noTypeOrElement00", new String JavaDoc[]{partName,
2117                                                                      opName}));
2118                }
2119
2120                fillParamInfo(param, bindingEntry, opName, partName);
2121                v.add(param);
2122
2123                continue; // next part
2124
}
2125
2126            // flow to here means wrapped literal !
2127
// See if we can map all the XML types to java(?) types
2128
// if we can, we use these as the types
2129
Node JavaDoc node = null;
2130            TypeEntry typeEntry = null;
2131
2132            if ((typeName != null)
2133                    && (bindingEntry == null || bindingEntry.getMIMETypes().size() == 0)) {
2134
2135                // Since we can't (yet?) make the Axis engine generate the right
2136
// XML for literal parts that specify the type attribute,
2137
// (unless they're MIME types) abort processing with an
2138
// error if we encounter this case
2139
//
2140
// node = getTypeEntry(typeName, false).getNode();
2141
String JavaDoc bindingName = (bindingEntry == null)
2142                        ? "unknown"
2143                        : bindingEntry.getBinding().getQName().toString();
2144
2145                throw new IOException JavaDoc(Messages.getMessage("literalTypePart00",
2146                        new String JavaDoc[]{
2147                            partName,
2148                            opName,
2149                            bindingName}));
2150            }
2151
2152            // Get the node which corresponds to the type entry for this
2153
// element. i.e.:
2154
// <part name="part" element="foo:bar"/>
2155
// ...
2156
// <schema targetNamespace="foo">
2157
// <element name="bar"...> <--- This one
2158
typeEntry = getTypeEntry(elementName, true);
2159            node = typeEntry.getNode();
2160
2161            // Check if this element is of the form:
2162
// <element name="foo" type="tns:foo_type"/>
2163
BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
2164            QName JavaDoc type = Utils.getTypeQName(node, forElement,
2165                    false);
2166            if ((type != null) && !forElement.value) {
2167
2168                // If in fact we have such a type, go get the node that
2169
// corresponds to THAT definition.
2170
typeEntry = getTypeEntry(type, false);
2171                node = typeEntry.getNode();
2172            }
2173
2174            Vector JavaDoc vTypes = null;
2175            
2176            // If we have nothing at this point, we're in trouble.
2177
if (node == null) {
2178              // If node is null, that means the element in question has no type declaration,
2179
// therefore is not a wrapper element.
2180
wrapped = false;
2181            } else {
2182
2183                // check for attributes
2184
if (typeEntry.getContainedAttributes() != null) {
2185                    // can't do wrapped mode
2186
wrapped = false;
2187                }
2188                
2189                if (!SchemaUtils.isWrappedType(node)) {
2190                    // mark the type entry as not just literal referenced
2191
// This doesn't work, but it may help in the future.
2192
// The problem is "wrapped" is a symbol table wide flag,
2193
// which means if one operation breaks the rules
2194
// implemented in isWrappedType(), then everything goes bad
2195
// For example, see bug Axis-1900.
2196
typeEntry.setOnlyLiteralReference(false);
2197                    wrapped = false;
2198                }
2199
2200                // Get the nested type entries.
2201
// TODO - If we are unable to represent any of the types in the
2202
// element, we need to use SOAPElement/SOAPBodyElement.
2203
// I don't believe getContainedElementDecl does the right thing yet.
2204
vTypes = typeEntry.getContainedElements();
2205            }
2206
2207            // IF we got the type entries and we didn't find attributes
2208
// THEN use the things in this element as the parameters
2209
if ((vTypes != null) && wrapped) {
2210
2211                // add the elements in this list
2212
for (int j = 0; j < vTypes.size(); j++) {
2213                    ElementDecl elem = (ElementDecl) vTypes.elementAt(j);
2214                    Parameter p = new Parameter();
2215
2216                    p.setQName(elem.getQName());
2217                    // If the parameter is a anonymous complex type, the parameter
2218
// name should just be the name of the element, not >foo>element
2219
String JavaDoc paramName = p.getName();
2220                    final int gt = paramName.lastIndexOf(ANON_TOKEN);
2221                    if (gt != 1) {
2222                        paramName = paramName.substring(gt+1);
2223                    }
2224                    p.setName(paramName);
2225                    p.setType(elem.getType());
2226                    p.setOmittable(elem.getMinOccursIs0());
2227                    fillParamInfo(p, bindingEntry, opName, partName);
2228                    v.add(p);
2229                }
2230            } else {
2231
2232                // - we were unable to get the types OR
2233
// - we found attributes
2234
// so we can't use wrapped mode.
2235
param.setName(partName);
2236
2237                if (typeName != null) {
2238                    param.setType(getType(typeName));
2239                } else if (elementName != null) {
2240                    param.setType(getElement(elementName));
2241                }
2242
2243                fillParamInfo(param, bindingEntry, opName, partName);
2244                v.add(param);
2245            }
2246        } // while
2247
} // getParametersFromParts
2248

2249    /**
2250     * Set the header information for this paramter
2251     *
2252     * @param param Parameter to modify
2253     * @param bindingEntry Binding info for this operation/parameter
2254     * @param opName the operation we are processing
2255     * @param partName the part we are processing
2256     */

2257    private void fillParamInfo(Parameter param, BindingEntry bindingEntry,
2258                               String JavaDoc opName, String JavaDoc partName) {
2259
2260        // If we don't have a binding, can't do anything
2261
if (bindingEntry == null)
2262            return;
2263
2264        setMIMEInfo(param, bindingEntry.getMIMEInfo(opName, partName));
2265
2266        boolean isHeader = false;
2267
2268        // Is this parameter in an Input header?
2269
if (bindingEntry.isInHeaderPart(opName, partName)) {
2270            isHeader = true;
2271            param.setInHeader(true);
2272        }
2273
2274        // Is this parameter in an Output header?
2275
if (bindingEntry.isOutHeaderPart(opName, partName)) {
2276            isHeader = true;
2277            param.setOutHeader(true);
2278        }
2279
2280        // If this parameter is part of a header, find the binding operation
2281
// that we are processing and get the QName of the parameter.
2282
if (isHeader && (bindingEntry.getBinding() != null)) {
2283            List JavaDoc list = bindingEntry.getBinding().getBindingOperations();
2284
2285            for (int i = 0; (list != null) && (i < list.size()); i++) {
2286                BindingOperation operation = (BindingOperation) list.get(i);
2287
2288                if (operation.getName().equals(opName)) {
2289                    if (param.isInHeader()) {
2290                        QName JavaDoc qName = getBindedParameterName(
2291                                operation.getBindingInput().getExtensibilityElements(),
2292                                param);
2293
2294                        if(qName!= null) {
2295                            param.setQName(qName);
2296                        }
2297                    } else if (param.isOutHeader()) {
2298                        QName JavaDoc qName = getBindedParameterName(
2299                                operation.getBindingOutput().getExtensibilityElements(),
2300                                param);
2301
2302                        if(qName!= null) {
2303                            param.setQName(qName);
2304                        }
2305                    }
2306                }
2307            }
2308        }
2309    }
2310
2311    /**
2312     * Method getBindedParameterName
2313     *
2314     * @param elements
2315     * @param p
2316     * @return
2317     */

2318    private QName JavaDoc getBindedParameterName(List JavaDoc elements, Parameter p) {
2319
2320        // If the parameter can either be in the message header or in the
2321
// message body.
2322
// When it is in the header, there may be a SOAPHeader (soap:header)
2323
// with its part name. The namespace used is the one of the soap:header.
2324
// When it is in the body, if there is a SOAPBody with its part name,
2325
// the namespace used is the one of this soap:body.
2326
//
2327
// If the parameter is in the body and there is a soap:body with no parts,
2328
// its namespace is used for the parameter.
2329
QName JavaDoc paramName = null;
2330        String JavaDoc defaultNamespace = null;
2331        String JavaDoc parameterPartName = p.getName();
2332
2333        for (Iterator JavaDoc k = elements.iterator(); k.hasNext();) {
2334            ExtensibilityElement element = (ExtensibilityElement) k.next();
2335
2336            if (element instanceof SOAPBody) {
2337                SOAPBody bodyElement = (SOAPBody) element;
2338                List JavaDoc parts = bodyElement.getParts();
2339
2340                if ((parts == null) || (parts.size() == 0)) {
2341                    defaultNamespace = bodyElement.getNamespaceURI();
2342                } else {
2343                    boolean found = false;
2344
2345                    for (Iterator JavaDoc l = parts.iterator(); l.hasNext();) {
2346                        Object JavaDoc o = l.next();
2347
2348                        if(o instanceof String JavaDoc) {
2349                            if (parameterPartName.equals((String JavaDoc)o)) {
2350                                paramName =
2351                                        new QName JavaDoc(bodyElement.getNamespaceURI(),
2352                                                parameterPartName);
2353                                found = true;
2354                                break;
2355                            }
2356                        }
2357                    }
2358
2359                    if (found) {
2360                        break;
2361                    }
2362                }
2363            } else if (element instanceof SOAPHeader) {
2364                SOAPHeader headerElement = (SOAPHeader) element;
2365                String JavaDoc part = headerElement.getPart();
2366
2367                if (parameterPartName.equals(part)) {
2368                    paramName = new QName JavaDoc(headerElement.getNamespaceURI(),
2369                            parameterPartName);
2370                    break;
2371                }
2372            }
2373        }
2374
2375        if ((paramName == null) && (!p.isInHeader()) && (!p.isOutHeader())) {
2376            if (defaultNamespace != null) {
2377                paramName = new QName JavaDoc(defaultNamespace, parameterPartName);
2378            } else {
2379                paramName = p.getQName();
2380            }
2381        }
2382
2383        return paramName;
2384    }
2385
2386    /**
2387     * Set the MIME type. This can be determine in one of two ways:
2388     * 1. From WSDL 1.1 MIME constructs on the binding (passed in);
2389     * 2. From AXIS-specific xml MIME types.
2390     *
2391     * @param p
2392     * @param mimeInfo
2393     */

2394    private void setMIMEInfo(Parameter p, MimeInfo mimeInfo) {
2395
2396        // If there is no binding MIME construct (ie., the mimeType parameter is
2397
// null), then get the MIME type from the AXIS-specific xml MIME type.
2398
if (mimeInfo == null && p.getType() != null) {
2399            QName JavaDoc mimeQName = p.getType().getQName();
2400
2401            if (mimeQName.getNamespaceURI().equals(Constants.NS_URI_XMLSOAP)) {
2402                if (Constants.MIME_IMAGE.equals(mimeQName)) {
2403                    mimeInfo = new MimeInfo("image/jpeg", "");
2404                } else if (Constants.MIME_PLAINTEXT.equals(mimeQName)) {
2405                    mimeInfo = new MimeInfo("text/plain", "");
2406                } else if (Constants.MIME_MULTIPART.equals(mimeQName)) {
2407                    mimeInfo = new MimeInfo("multipart/related", "");
2408                } else if (Constants.MIME_SOURCE.equals(mimeQName)) {
2409                    mimeInfo = new MimeInfo("text/xml", "");
2410                } else if (Constants.MIME_OCTETSTREAM.equals(mimeQName)) {
2411                    mimeInfo = new MimeInfo("application/octet-stream", "");
2412                }
2413            }
2414        }
2415
2416        p.setMIMEInfo(mimeInfo);
2417    } // setMIMEType
2418

2419    /**
2420     * Populate the symbol table with all of the BindingEntry's from the Definition.
2421     *
2422     * @param def
2423     * @throws IOException
2424     */

2425    private void populateBindings(Definition def) throws IOException JavaDoc {
2426
2427        Iterator JavaDoc i = def.getBindings().values().iterator();
2428
2429        while (i.hasNext()) {
2430            Binding binding = (Binding) i.next();
2431            BindingEntry bEntry = new BindingEntry(binding);
2432
2433            symbolTablePut(bEntry);
2434
2435            Iterator JavaDoc extensibilityElementsIterator =
2436                    binding.getExtensibilityElements().iterator();
2437
2438            while (extensibilityElementsIterator.hasNext()) {
2439                Object JavaDoc obj = extensibilityElementsIterator.next();
2440
2441                if (obj instanceof SOAPBinding) {
2442                    bEntry.setBindingType(BindingEntry.TYPE_SOAP);
2443
2444                    SOAPBinding sb = (SOAPBinding) obj;
2445                    String JavaDoc style = sb.getStyle();
2446
2447                    if ("rpc".equalsIgnoreCase(style)) {
2448                        bEntry.setBindingStyle(Style.RPC);
2449                    }
2450                } else if (obj instanceof HTTPBinding) {
2451                    HTTPBinding hb = (HTTPBinding) obj;
2452
2453                    if (hb.getVerb().equalsIgnoreCase("post")) {
2454                        bEntry.setBindingType(BindingEntry.TYPE_HTTP_POST);
2455                    } else {
2456                        bEntry.setBindingType(BindingEntry.TYPE_HTTP_GET);
2457                    }
2458                } else if (obj instanceof UnknownExtensibilityElement) {
2459
2460                    // TODO: After WSDL4J supports soap12, change this code
2461
UnknownExtensibilityElement unkElement =
2462                            (UnknownExtensibilityElement) obj;
2463                    QName JavaDoc name =
2464                            unkElement.getElementType();
2465
2466                    if (name.getNamespaceURI().equals(Constants.URI_WSDL12_SOAP)
2467                            && name.getLocalPart().equals("binding")) {
2468                        bEntry.setBindingType(BindingEntry.TYPE_SOAP);
2469
2470                        String JavaDoc style =
2471                                unkElement.getElement().getAttribute("style");
2472
2473                        if ("rpc".equalsIgnoreCase(style)) {
2474                            bEntry.setBindingStyle(Style.RPC);
2475                        }
2476                    }
2477                }
2478            }
2479
2480            // Step through the binding operations, setting the following as appropriate:
2481
// - hasLiteral
2482
// - body types
2483
// - mimeTypes
2484
// - headers
2485
HashMap JavaDoc attributes = new HashMap JavaDoc();
2486            List JavaDoc bindList = binding.getBindingOperations();
2487            HashMap JavaDoc faultMap = new HashMap JavaDoc(); // name to SOAPFault from WSDL4J
2488

2489            for (Iterator JavaDoc opIterator = bindList.iterator();
2490                 opIterator.hasNext();) {
2491                BindingOperation bindOp =
2492                        (BindingOperation) opIterator.next();
2493                Operation operation = bindOp.getOperation();
2494                BindingInput bindingInput = bindOp.getBindingInput();
2495                BindingOutput bindingOutput = bindOp.getBindingOutput();
2496                String JavaDoc opName = bindOp.getName();
2497
2498                // First, make sure the binding operation matches a portType operation
2499
String JavaDoc inputName = (bindingInput == null)
2500                        ? null
2501                        : bindingInput.getName();
2502                String JavaDoc outputName = (bindingOutput == null)
2503                        ? null
2504                        : bindingOutput.getName();
2505
2506                if (binding.getPortType().getOperation(
2507                        opName, inputName, outputName) == null) {
2508                    throw new IOException JavaDoc(Messages.getMessage("unmatchedOp",
2509                            new String JavaDoc[]{
2510                                opName,
2511                                inputName,
2512                                outputName}));
2513                }
2514
2515                ArrayList JavaDoc faults = new ArrayList JavaDoc();
2516
2517                // input
2518
if (bindingInput != null) {
2519                    if (bindingInput.getExtensibilityElements() != null) {
2520                        Iterator JavaDoc inIter =
2521                                bindingInput.getExtensibilityElements().iterator();
2522
2523                        fillInBindingInfo(bEntry, operation, inIter, faults,
2524                                true);
2525                    }
2526                }
2527
2528                // output
2529
if (bindingOutput != null) {
2530                    if (bindingOutput.getExtensibilityElements() != null) {
2531                        Iterator JavaDoc outIter =
2532                                bindingOutput.getExtensibilityElements().iterator();
2533
2534                        fillInBindingInfo(bEntry, operation, outIter, faults,
2535                                false);
2536                    }
2537                }
2538
2539                // faults
2540
faultsFromSOAPFault(binding, bindOp, operation, faults);
2541
2542                // Add this fault name and info to the map
2543
faultMap.put(bindOp, faults);
2544
2545                Use inputBodyType = bEntry.getInputBodyType(operation);
2546                Use outputBodyType = bEntry.getOutputBodyType(operation);
2547
2548                // Associate the portType operation that goes with this binding
2549
// with the body types.
2550
attributes.put(bindOp.getOperation(),
2551                        new BindingEntry.OperationAttr(inputBodyType,
2552                                outputBodyType, faultMap));
2553
2554                // If the input or output body uses literal, flag the binding as using literal.
2555
// NOTE: should I include faultBodyType in this check?
2556
if ((inputBodyType == Use.LITERAL)
2557                        || (outputBodyType == Use.LITERAL)) {
2558                    bEntry.setHasLiteral(true);
2559                }
2560
2561                bEntry.setFaultBodyTypeMap(operation, faultMap);
2562            } // binding operations
2563

2564            bEntry.setFaults(faultMap);
2565        }
2566    } // populateBindings
2567

2568    /**
2569     * Fill in some binding information: bodyType, mimeType, header info.
2570     *
2571     * @param bEntry
2572     * @param operation
2573     * @param it
2574     * @param faults
2575     * @param input
2576     * @throws IOException
2577     */

2578    private void fillInBindingInfo(
2579            BindingEntry bEntry, Operation operation, Iterator JavaDoc it, ArrayList JavaDoc faults, boolean input)
2580            throws IOException JavaDoc {
2581
2582        for (; it.hasNext();) {
2583            Object JavaDoc obj = it.next();
2584
2585            if (obj instanceof SOAPBody) {
2586                setBodyType(((SOAPBody) obj).getUse(), bEntry, operation,
2587                        input);
2588            } else if (obj instanceof SOAPHeader) {
2589                SOAPHeader header = (SOAPHeader) obj;
2590
2591                setBodyType(header.getUse(), bEntry, operation, input);
2592
2593                // Note, this only works for explicit headers - those whose
2594
// parts come from messages used in the portType's operation
2595
// input/output clauses - it does not work for implicit
2596
// headers - those whose parts come from messages not used in
2597
// the portType's operation's input/output clauses. I don't
2598
// know what we're supposed to emit for implicit headers.
2599
bEntry.setHeaderPart(operation.getName(), header.getPart(),
2600                        input
2601                        ? BindingEntry.IN_HEADER
2602                        : BindingEntry.OUT_HEADER);
2603
2604                // Add any soap:headerFault info to the faults array
2605
Iterator JavaDoc headerFaults = header.getSOAPHeaderFaults().iterator();
2606
2607                while (headerFaults.hasNext()) {
2608                    SOAPHeaderFault headerFault =
2609                            (SOAPHeaderFault) headerFaults.next();
2610
2611                    faults.add(new FaultInfo(headerFault, this));
2612                }
2613            } else if (obj instanceof MIMEMultipartRelated) {
2614                bEntry.setBodyType(
2615                        operation,
2616                        addMIMETypes(
2617                                bEntry, (MIMEMultipartRelated) obj, operation), input);
2618            } else if (obj instanceof UnknownExtensibilityElement) {
2619                UnknownExtensibilityElement unkElement =
2620                        (UnknownExtensibilityElement) obj;
2621                QName JavaDoc name =
2622                        unkElement.getElementType();
2623
2624                if (name.getNamespaceURI().equals(Constants.URI_DIME_WSDL)
2625                        && name.getLocalPart().equals("message")) {
2626                    fillInDIMEInformation(unkElement, input, operation, bEntry);
2627                }
2628
2629                // TODO: After WSDL4J supports soap12, change this code
2630
if (name.getNamespaceURI().equals(Constants.URI_WSDL12_SOAP)
2631                        && name.getLocalPart().equals("body")) {
2632                    setBodyType(unkElement.getElement().getAttribute("use"),
2633                            bEntry, operation, input);
2634                }
2635
2636                // TODO: After WSDL4J supports soap12, change this code
2637
if (name.getNamespaceURI().equals(Constants.URI_WSDL12_SOAP)
2638                        && name.getLocalPart().equals("header")) {
2639                    setBodyType(unkElement.getElement().getAttribute("use"),
2640                            bEntry, operation, input);
2641
2642                    // Note, this only works for explicit headers - those whose
2643
// parts come from messages used in the portType's operation
2644
// input/output clauses - it does not work for implicit
2645
// headers - those whose parts come from messages not used in
2646
// the portType's operation's input/output clauses. I don't
2647
// know what we're supposed to emit for implicit headers.
2648
bEntry.setHeaderPart(
2649                            operation.getName(),
2650                            unkElement.getElement().getAttribute("part"), input
2651                            ? BindingEntry.IN_HEADER
2652                            : BindingEntry.OUT_HEADER);
2653
2654                    // Add any soap12:headerFault info to the faults array
2655
NodeList JavaDoc headerFaults =
2656                            unkElement.getElement().getChildNodes();
2657
2658                    for (int i = 0; i < headerFaults.getLength(); i++) {
2659                        String JavaDoc faultMessage =
2660                                unkElement.getElement().getAttribute("message");
2661                        String JavaDoc faultPart =
2662                                unkElement.getElement().getAttribute("part");
2663                        String JavaDoc faultUse =
2664                                unkElement.getElement().getAttribute("use");
2665                        String JavaDoc faultNamespaceURI =
2666                                unkElement.getElement().getAttribute("namespace");
2667                        QName JavaDoc faultMessageQName = null;
2668                        int sep = faultMessage.indexOf(':');
2669
2670                        if (sep == -1) {
2671                            faultMessageQName = new QName JavaDoc(faultMessage);
2672                        } else {
2673                            faultMessageQName =
2674                                    new QName JavaDoc(faultMessage.substring(0, sep),
2675                                            faultMessage.substring(sep + 1));
2676                        }
2677
2678                        faults.add(new FaultInfo(faultMessageQName, faultPart,
2679                                faultUse, faultNamespaceURI,
2680                                this));
2681                    }
2682                }
2683            }
2684        }
2685    } // fillInBindingInfo
2686

2687    /**
2688     * Fill in DIME information
2689     *
2690     * @param unkElement
2691     * @param input
2692     * @param operation
2693     * @param bEntry
2694     */

2695    private void fillInDIMEInformation(UnknownExtensibilityElement unkElement,
2696                                       boolean input, Operation operation,
2697                                       BindingEntry bEntry) {
2698
2699        String JavaDoc layout = unkElement.getElement().getAttribute("layout");
2700
2701        // TODO: what to do with layout info?
2702
if (layout.equals(Constants.URI_DIME_CLOSED_LAYOUT)) {
2703        } else if (layout.equals(Constants.URI_DIME_OPEN_LAYOUT)) {
2704        }
2705
2706        Map JavaDoc parts = null;
2707
2708        if (input) {
2709            parts = operation.getInput().getMessage().getParts();
2710        } else {
2711            parts = operation.getOutput().getMessage().getParts();
2712        }
2713
2714        if (parts != null) {
2715            Iterator JavaDoc iterator = parts.values().iterator();
2716
2717            while (iterator.hasNext()) {
2718                Part part = (Part) iterator.next();
2719
2720                if (part != null) {
2721                    String JavaDoc dims = "";
2722                    org.w3c.dom.Element JavaDoc element = null;
2723
2724                    if (part.getTypeName() != null) {
2725                        TypeEntry partType = getType(part.getTypeName());
2726
2727                        if (partType.getDimensions().length() > 0) {
2728                            dims = partType.getDimensions();
2729                            partType = partType.getRefType();
2730                        }
2731
2732                        element = (org.w3c.dom.Element JavaDoc) partType.getNode();
2733                    } else if (part.getElementName() != null) {
2734                        TypeEntry partElement =
2735                                getElement(part.getElementName()).getRefType();
2736
2737                        element = (org.w3c.dom.Element JavaDoc) partElement.getNode();
2738
2739                        QName JavaDoc name = getInnerCollectionComponentQName(element);
2740
2741                        if (name != null) {
2742                            dims += "[]";
2743                            partElement = getType(name);
2744                            element =
2745                                    (org.w3c.dom.Element JavaDoc) partElement.getNode();
2746                        } else {
2747                            name = getInnerTypeQName(element);
2748
2749                            if (name != null) {
2750                                partElement = getType(name);
2751                                element =
2752                                        (org.w3c.dom.Element JavaDoc) partElement.getNode();
2753                            }
2754                        }
2755                    }
2756
2757                    if (element != null) {
2758                        org.w3c.dom.Element JavaDoc e =
2759                                (org.w3c.dom.Element JavaDoc) XMLUtils.findNode(
2760                                        element,
2761                                        new QName JavaDoc(
2762                                                Constants.URI_DIME_CONTENT, "mediaType"));
2763
2764                        if (e != null) {
2765                            String JavaDoc value = e.getAttribute("value");
2766
2767                            bEntry.setOperationDIME(operation.getName());
2768                            bEntry.setMIMEInfo(operation.getName(),
2769                                    part.getName(), value, dims);
2770                        }
2771                    }
2772                }
2773            }
2774        }
2775    }
2776
2777    /**
2778     * Get the faults from the soap:fault clause.
2779     *
2780     * @param binding
2781     * @param bindOp
2782     * @param operation
2783     * @param faults
2784     * @throws IOException
2785     */

2786    private void faultsFromSOAPFault(
2787            Binding binding, BindingOperation bindOp, Operation operation, ArrayList JavaDoc faults)
2788            throws IOException JavaDoc {
2789
2790        Iterator JavaDoc faultMapIter = bindOp.getBindingFaults().values().iterator();
2791
2792        for (; faultMapIter.hasNext();) {
2793            BindingFault bFault = (BindingFault) faultMapIter.next();
2794
2795            // Set default entry for this fault
2796
String JavaDoc faultName = bFault.getName();
2797
2798            // Check to make sure this fault is named
2799
if ((faultName == null) || (faultName.length() == 0)) {
2800                throw new IOException JavaDoc(
2801                        Messages.getMessage(
2802                                "unNamedFault00", bindOp.getName(),
2803                                binding.getQName().toString()));
2804            }
2805
2806            boolean foundSOAPFault = false;
2807            String JavaDoc soapFaultUse = "";
2808            String JavaDoc soapFaultNamespace = "";
2809            Iterator JavaDoc faultIter =
2810                    bFault.getExtensibilityElements().iterator();
2811
2812            for (; faultIter.hasNext();) {
2813                Object JavaDoc obj = faultIter.next();
2814
2815                if (obj instanceof SOAPFault) {
2816                    foundSOAPFault = true;
2817                    soapFaultUse = ((SOAPFault) obj).getUse();
2818                    soapFaultNamespace = ((SOAPFault) obj).getNamespaceURI();
2819
2820                    break;
2821                } else if (obj instanceof UnknownExtensibilityElement) {
2822
2823                    // TODO: After WSDL4J supports soap12, change this code
2824
UnknownExtensibilityElement unkElement =
2825                            (UnknownExtensibilityElement) obj;
2826                    QName JavaDoc name =
2827                            unkElement.getElementType();
2828
2829                    if (name.getNamespaceURI().equals(Constants.URI_WSDL12_SOAP)
2830                            && name.getLocalPart().equals("fault")) {
2831                        if (unkElement.getElement().getAttribute("use")
2832                                != null) {
2833                            soapFaultUse =
2834                                    unkElement.getElement().getAttribute("use");
2835                        }
2836
2837                        if (unkElement.getElement().getAttribute("namespace")
2838                                != null) {
2839                            soapFaultNamespace =
2840                                    unkElement.getElement().getAttribute(
2841                                            "namespace");
2842                        }
2843                    }
2844                }
2845            }
2846
2847            // Check to make sure we have a soap:fault element
2848
if (!foundSOAPFault) {
2849                throw new IOException JavaDoc(
2850                        Messages.getMessage(
2851                                "missingSoapFault00", faultName, bindOp.getName(),
2852                                binding.getQName().toString()));
2853            }
2854
2855            // TODO error checking:
2856
// if use=literal, no use of namespace on the soap:fault
2857
// if use=encoded, no use of element on the part
2858
// Check this fault to make sure it matches the one
2859
// in the matching portType Operation
2860
Fault opFault = operation.getFault(bFault.getName());
2861
2862            if (opFault == null) {
2863                throw new IOException JavaDoc(Messages.getMessage("noPortTypeFault",
2864                        new String JavaDoc[]{
2865                            bFault.getName(),
2866                            bindOp.getName(),
2867                            binding.getQName().toString()}));
2868            }
2869
2870            // put the updated entry back in the map
2871
faults.add(new FaultInfo(opFault, Use.getUse(soapFaultUse),
2872                    soapFaultNamespace, this));
2873        }
2874    } // faultsFromSOAPFault
2875

2876    /**
2877     * Set the body type.
2878     *
2879     * @param use
2880     * @param bEntry
2881     * @param operation
2882     * @param input
2883     */

2884    private void setBodyType(String JavaDoc use,
2885                             BindingEntry bEntry,
2886                             Operation operation,
2887                             boolean input)
2888    {
2889
2890        if (use == null) {
2891            // Deprecated
2892
// throw new IOException(Messages.getMessage("noUse",
2893
// operation.getName()));
2894
// for WS-I BP 1.0 R2707.
2895
// Set default of use to literal.
2896
use = "literal";
2897        }
2898
2899        if (use.equalsIgnoreCase("literal")) {
2900            bEntry.setBodyType(operation, Use.LITERAL, input);
2901        }
2902    } // setBodyType
2903

2904    /**
2905     * Add the parts that are really MIME types as MIME types.
2906     * A side effect is to return the body Type of the given
2907     * MIMEMultipartRelated object.
2908     *
2909     * @param bEntry
2910     * @param mpr
2911     * @param op
2912     * @return
2913     * @throws IOException
2914     */

2915    private Use addMIMETypes(
2916            BindingEntry bEntry, MIMEMultipartRelated mpr, Operation op)
2917            throws IOException JavaDoc {
2918
2919        Use bodyType = Use.ENCODED;
2920        List JavaDoc parts = mpr.getMIMEParts();
2921        Iterator JavaDoc i = parts.iterator();
2922
2923        while (i.hasNext()) {
2924            MIMEPart part = (MIMEPart) i.next();
2925            List JavaDoc elems = part.getExtensibilityElements();
2926            Iterator JavaDoc j = elems.iterator();
2927
2928            while (j.hasNext()) {
2929                Object JavaDoc obj = j.next();
2930
2931                if (obj instanceof MIMEContent) {
2932                    MIMEContent content = (MIMEContent) obj;
2933                    TypeEntry typeEntry = findPart(op, content.getPart());
2934                    if (typeEntry == null) {
2935                        throw new RuntimeException JavaDoc(Messages.getMessage("cannotFindPartForOperation00", content.getPart(),
2936                                op.getName(), content.getType()));
2937                    }
2938                    String JavaDoc dims = typeEntry.getDimensions();
2939
2940                    if ((dims.length() <= 0)
2941                            && (typeEntry.getRefType() != null)) {
2942                        Node JavaDoc node = typeEntry.getRefType().getNode();
2943
2944                        if (getInnerCollectionComponentQName(node) != null) {
2945                            dims += "[]";
2946                        }
2947                    }
2948
2949                    String JavaDoc type = content.getType();
2950
2951                    if ((type == null) || (type.length() == 0)) {
2952                        type = "text/plain";
2953                    }
2954
2955                    bEntry.setMIMEInfo(op.getName(), content.getPart(), type,
2956                            dims);
2957                } else if (obj instanceof SOAPBody) {
2958                    String JavaDoc use = ((SOAPBody) obj).getUse();
2959
2960                    if (use == null) {
2961                        throw new IOException JavaDoc(
2962                                Messages.getMessage("noUse", op.getName()));
2963                    }
2964
2965                    if (use.equalsIgnoreCase("literal")) {
2966                        bodyType = Use.LITERAL;
2967                    }
2968                } else if (obj instanceof UnknownExtensibilityElement) {
2969
2970                    // TODO: After WSDL4J supports soap12, change this code
2971
UnknownExtensibilityElement unkElement =
2972                            (UnknownExtensibilityElement) obj;
2973                    QName JavaDoc name =
2974                            unkElement.getElementType();
2975
2976                    if (name.getNamespaceURI().equals(Constants.URI_WSDL12_SOAP)
2977                            && name.getLocalPart().equals("body")) {
2978                        String JavaDoc use =
2979                                unkElement.getElement().getAttribute("use");
2980
2981                        if (use == null) {
2982                            throw new IOException JavaDoc(
2983                                    Messages.getMessage("noUse", op.getName()));
2984                        }
2985
2986                        if (use.equalsIgnoreCase("literal")) {
2987                            bodyType = Use.LITERAL;
2988                        }
2989                    }
2990                }
2991            }
2992        }
2993
2994        return bodyType;
2995    } // addMIMETypes
2996

2997    /**
2998     * Method findPart
2999     *
3000     * @param operation
3001     * @param partName
3002     * @return
3003     */

3004    private TypeEntry findPart(Operation operation, String JavaDoc partName) {
3005
3006        Map JavaDoc parts = operation.getInput().getMessage().getParts();
3007        Iterator JavaDoc iterator = parts.values().iterator();
3008        TypeEntry part = findPart(iterator, partName);
3009
3010        if (part == null) {
3011            parts = operation.getOutput().getMessage().getParts();
3012            iterator = parts.values().iterator();
3013            part = findPart(iterator, partName);
3014        }
3015
3016        return part;
3017    }
3018
3019    /**
3020     * Method findPart
3021     *
3022     * @param iterator
3023     * @param partName
3024     * @return
3025     */

3026    private TypeEntry findPart(Iterator JavaDoc iterator, String JavaDoc partName) {
3027
3028        while (iterator.hasNext()) {
3029            Part part = (Part) iterator.next();
3030
3031            if (part != null) {
3032                String JavaDoc typeName = part.getName();
3033
3034                if (partName.equals(typeName)) {
3035                    if (part.getTypeName() != null) {
3036                        return getType(part.getTypeName());
3037                    } else if (part.getElementName() != null) {
3038                        return getElement(part.getElementName());
3039                    }
3040                }
3041            }
3042        }
3043
3044        return null;
3045    }
3046
3047    /**
3048     * Populate the symbol table with all of the ServiceEntry's from the Definition.
3049     *
3050     * @param def
3051     * @throws IOException
3052     */

3053    private void populateServices(Definition def) throws IOException JavaDoc {
3054
3055        Iterator JavaDoc i = def.getServices().values().iterator();
3056
3057        while (i.hasNext()) {
3058            Service service = (Service) i.next();
3059
3060            // do a bit of name validation
3061
if ((service.getQName() == null)
3062                    || (service.getQName().getLocalPart() == null)
3063                    || service.getQName().getLocalPart().equals("")) {
3064                throw new IOException JavaDoc(Messages.getMessage("BadServiceName00"));
3065            }
3066
3067            ServiceEntry sEntry = new ServiceEntry(service);
3068
3069            symbolTablePut(sEntry);
3070            populatePorts(service.getPorts());
3071        }
3072    } // populateServices
3073

3074    /**
3075     * populates the symbol table with port elements defined within a &lt;service&gt;
3076     * element.
3077     *
3078     * @param ports a map of name->port pairs (i.e. what is returned by service.getPorts()
3079     * @throws IOException thrown, if an IO or WSDL error is detected
3080     * @see javax.wsdl.Service#getPorts()
3081     * @see javax.wsdl.Port
3082     */

3083    private void populatePorts(Map JavaDoc ports) throws IOException JavaDoc {
3084
3085        if (ports == null) {
3086            return;
3087        }
3088
3089        Iterator JavaDoc it = ports.values().iterator();
3090
3091        while (it.hasNext()) {
3092            Port port = (Port) it.next();
3093            String JavaDoc portName = port.getName();
3094            Binding portBinding = port.getBinding();
3095
3096            // make sure there is a port name. The 'name' attribute for WSDL ports is
3097
// mandatory
3098
//
3099
if (portName == null) {
3100
3101                // REMIND: should rather be a javax.wsdl.WSDLException ?
3102
throw new IOException JavaDoc(
3103                        Messages.getMessage("missingPortNameException"));
3104            }
3105
3106            // make sure there is a binding for the port. The 'binding' attribute for
3107
// WSDL ports is mandatory
3108
//
3109
if (portBinding == null) {
3110
3111                // REMIND: should rather be a javax.wsdl.WSDLException ?
3112
throw new IOException JavaDoc(
3113                        Messages.getMessage("missingBindingException"));
3114            }
3115
3116            // make sure the port name is unique among all port names defined in this
3117
// WSDL document.
3118
//
3119
// NOTE: there's a flaw in com.ibm.wsdl.xml.WSDLReaderImpl#parsePort() and
3120
// com.ibm.wsdl.xml.WSDLReaderImpl#addPort(). These methods do not enforce
3121
// the port name exists and is unique. Actually, if two port definitions with
3122
// the same name exist within the same service element, only *one* port
3123
// element is present after parsing and the following exception is not thrown.
3124
//
3125
// If two ports with the same name exist in different service elements,
3126
// the exception below is thrown. This is conformant to the WSDL 1.1 spec (sec 2.6)
3127
// , which states: "The name attribute provides a unique name among all ports
3128
// defined within in the enclosing WSDL document."
3129
//
3130
//
3131
if (existsPortWithName(new QName JavaDoc(portName))) {
3132
3133                // REMIND: should rather be a javax.wsdl.WSDLException ?
3134
throw new IOException JavaDoc(
3135                        Messages.getMessage("twoPortsWithSameName", portName));
3136            }
3137
3138            PortEntry portEntry = new PortEntry(port);
3139
3140            symbolTablePut(portEntry);
3141        }
3142    }
3143
3144    /**
3145     * Set each SymTabEntry's isReferenced flag. The default is false. If no other symbol
3146     * references this symbol, then leave it false, otherwise set it to true.
3147     * (An exception to the rule is that derived types are set as referenced if
3148     * their base type is referenced. This is necessary to support generation and
3149     * registration of derived types.)
3150     *
3151     * @param def
3152     * @param doc
3153     */

3154    private void setReferences(Definition def, Document JavaDoc doc) {
3155
3156        Map JavaDoc stuff = def.getServices();
3157
3158        if (stuff.isEmpty()) {
3159            stuff = def.getBindings();
3160
3161            if (stuff.isEmpty()) {
3162                stuff = def.getPortTypes();
3163
3164                if (stuff.isEmpty()) {
3165                    stuff = def.getMessages();
3166
3167                    if (stuff.isEmpty()) {
3168                        for (Iterator JavaDoc i = elementTypeEntries.values().iterator();
3169                             i.hasNext();) {
3170                            setTypeReferences((TypeEntry) i.next(), doc, false);
3171                        }
3172
3173                        for (Iterator JavaDoc i = typeTypeEntries.values().iterator();
3174                             i.hasNext();) {
3175                            setTypeReferences((TypeEntry) i.next(), doc, false);
3176                        }
3177                    } else {
3178                        Iterator JavaDoc i = stuff.values().iterator();
3179
3180                        while (i.hasNext()) {
3181                            Message message = (Message) i.next();
3182                            MessageEntry mEntry =
3183                                    getMessageEntry(message.getQName());
3184
3185                            setMessageReferences(mEntry, def, doc, false);
3186                        }
3187                    }
3188                } else {
3189                    Iterator JavaDoc i = stuff.values().iterator();
3190
3191                    while (i.hasNext()) {
3192                        PortType portType = (PortType) i.next();
3193                        PortTypeEntry ptEntry =
3194                                getPortTypeEntry(portType.getQName());
3195
3196                        setPortTypeReferences(ptEntry, null, def, doc);
3197                    }
3198                }
3199            } else {
3200                Iterator JavaDoc i = stuff.values().iterator();
3201
3202                while (i.hasNext()) {
3203                    Binding binding = (Binding) i.next();
3204                    BindingEntry bEntry = getBindingEntry(binding.getQName());
3205
3206                    setBindingReferences(bEntry, def, doc);
3207                }
3208            }
3209        } else {
3210            Iterator JavaDoc i = stuff.values().iterator();
3211
3212            while (i.hasNext()) {
3213                Service service = (Service) i.next();
3214                ServiceEntry sEntry = getServiceEntry(service.getQName());
3215
3216                setServiceReferences(sEntry, def, doc);
3217            }
3218        }
3219    } // setReferences
3220

3221    /**
3222     * Set the isReferenced flag to true on the given TypeEntry and all
3223     * SymTabEntries that it refers to.
3224     *
3225     * @param entry
3226     * @param doc
3227     * @param literal
3228     */

3229    private void setTypeReferences(TypeEntry entry, Document JavaDoc doc,
3230                                   boolean literal) {
3231
3232        // Check to see if already processed.
3233
if ((entry.isReferenced() && !literal)
3234                || (entry.isOnlyLiteralReferenced() && literal)) {
3235            return;
3236        }
3237
3238        if (wrapped) {
3239
3240            // If this type is ONLY referenced from a literal usage in a binding,
3241
// then isOnlyLiteralReferenced should return true.
3242
if (!entry.isReferenced() && literal) {
3243                entry.setOnlyLiteralReference(true);
3244            }
3245
3246            // If this type was previously only referenced as a literal type,
3247
// but now it is referenced in a non-literal manner, turn off the
3248
// onlyLiteralReference flag.
3249
else if (entry.isOnlyLiteralReferenced() && !literal) {
3250                entry.setOnlyLiteralReference(false);
3251            }
3252        }
3253
3254        // If we don't want to emit stuff from imported files, only set the
3255
// isReferenced flag if this entry exists in the immediate WSDL file.
3256
Node JavaDoc node = entry.getNode();
3257
3258        if (addImports || (node == null) || (node.getOwnerDocument() == doc)) {
3259            entry.setIsReferenced(true);
3260
3261            if (entry instanceof DefinedElement) {
3262                BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
3263                QName JavaDoc referentName = Utils.getTypeQName(node,
3264                        forElement, false);
3265
3266                if (referentName != null) {
3267                    TypeEntry referent = getTypeEntry(referentName,
3268                            forElement.value);
3269
3270                    if (referent != null) {
3271                        setTypeReferences(referent, doc, literal);
3272                    }
3273                }
3274
3275                // If the Defined Element has an anonymous type,
3276
// process it with the current literal flag setting.
3277
QName JavaDoc anonQName =
3278                        SchemaUtils.getElementAnonQName(entry.getNode());
3279
3280                if (anonQName != null) {
3281                    TypeEntry anonType = getType(anonQName);
3282
3283                    if (anonType != null) {
3284                        setTypeReferences(anonType, doc, literal);
3285
3286                        return;
3287                    }
3288                }
3289            }
3290        }
3291
3292        HashSet nestedTypes = entry.getNestedTypes(this, true);
3293        Iterator JavaDoc it = nestedTypes.iterator();
3294
3295        while (it.hasNext()) {
3296            TypeEntry nestedType = (TypeEntry) it.next();
3297            TypeEntry refType = entry.getRefType();
3298
3299            if (nestedType == null) {
3300                continue;
3301            }
3302
3303            // If this entry has a referenced type that isn't
3304
// the same as the nested type
3305
// AND the OnlyLiteral reference switch is on
3306
// THEN turn the OnlyLiteral reference switch off.
3307
// If only someone had put a comment here saying why we do this...
3308
if ((refType != null)
3309                    && !refType.equals(nestedType)
3310                    && nestedType.isOnlyLiteralReferenced()) {
3311                nestedType.setOnlyLiteralReference(false);
3312            }
3313
3314            if (!nestedType.isReferenced()) {
3315
3316                // setTypeReferences(nestedType, doc, literal);
3317
if (nestedType != entry) {
3318                    setTypeReferences(nestedType, doc, false);
3319                }
3320            }
3321        }
3322    } // setTypeReferences
3323

3324    /**
3325     * Set the isReferenced flag to true on the given MessageEntry and all
3326     * SymTabEntries that it refers to.
3327     *
3328     * @param entry
3329     * @param def
3330     * @param doc
3331     * @param literal
3332     */

3333    private void setMessageReferences(MessageEntry entry, Definition def,
3334                                      Document JavaDoc doc, boolean literal) {
3335
3336        // If we don't want to emit stuff from imported files, only set the
3337
// isReferenced flag if this entry exists in the immediate WSDL file.
3338
Message message = entry.getMessage();
3339
3340        if (addImports) {
3341            entry.setIsReferenced(true);
3342        } else {
3343
3344            // NOTE: I thought I could have simply done:
3345
// if (def.getMessage(message.getQName()) != null)
3346
// but that method traces through all imported messages.
3347
Map JavaDoc messages = def.getMessages();
3348
3349            if (messages.containsValue(message)) {
3350                entry.setIsReferenced(true);
3351            }
3352        }
3353
3354        // Set all the message's types
3355
Iterator JavaDoc parts = message.getParts().values().iterator();
3356
3357        while (parts.hasNext()) {
3358            Part part = (Part) parts.next();
3359            TypeEntry type = getType(part.getTypeName());
3360
3361            if (type != null) {
3362                setTypeReferences(type, doc, literal);
3363            }
3364
3365            type = getElement(part.getElementName());
3366
3367            if (type != null) {
3368                setTypeReferences(type, doc, literal);
3369
3370                TypeEntry refType = type.getRefType();
3371
3372                if (refType != null) {
3373                    setTypeReferences(refType, doc, literal);
3374                }
3375            }
3376        }
3377    } // setMessageReference
3378

3379    /**
3380     * Set the isReferenced flag to true on the given PortTypeEntry and all
3381     * SymTabEntries that it refers to.
3382     *
3383     * @param entry
3384     * @param bEntry
3385     * @param def
3386     * @param doc
3387     */

3388    private void setPortTypeReferences(PortTypeEntry entry,
3389                                       BindingEntry bEntry, Definition def,
3390                                       Document JavaDoc doc) {
3391
3392        // If we don't want to emit stuff from imported files, only set the
3393
// isReferenced flag if this entry exists in the immediate WSDL file.
3394
PortType portType = entry.getPortType();
3395
3396        if (addImports) {
3397            entry.setIsReferenced(true);
3398        } else {
3399
3400            // NOTE: I thought I could have simply done:
3401
// if (def.getPortType(portType.getQName()) != null)
3402
// but that method traces through all imported portTypes.
3403
Map JavaDoc portTypes = def.getPortTypes();
3404
3405            if (portTypes.containsValue(portType)) {
3406                entry.setIsReferenced(true);
3407            }
3408        }
3409
3410        // Set all the portType's messages
3411
Iterator JavaDoc operations = portType.getOperations().iterator();
3412
3413        // For each operation, query its input, output, and fault messages
3414
while (operations.hasNext()) {
3415            Operation operation = (Operation) operations.next();
3416            Input input = operation.getInput();
3417            Output output = operation.getOutput();
3418
3419            // Find out if this reference is a literal reference or not.
3420
boolean literalInput = false;
3421            boolean literalOutput = false;
3422
3423            if (bEntry != null) {
3424                literalInput = bEntry.getInputBodyType(operation)
3425                        == Use.LITERAL;
3426                literalOutput = bEntry.getOutputBodyType(operation)
3427                        == Use.LITERAL;
3428            }
3429
3430            // Query the input message
3431
if (input != null) {
3432                Message message = input.getMessage();
3433
3434                if (message != null) {
3435                    MessageEntry mEntry = getMessageEntry(message.getQName());
3436
3437                    if (mEntry != null) {
3438                        setMessageReferences(mEntry, def, doc, literalInput);
3439                    }
3440                }
3441            }
3442
3443            // Query the output message
3444
if (output != null) {
3445                Message message = output.getMessage();
3446
3447                if (message != null) {
3448                    MessageEntry mEntry = getMessageEntry(message.getQName());
3449
3450                    if (mEntry != null) {
3451                        setMessageReferences(mEntry, def, doc, literalOutput);
3452                    }
3453                }
3454            }
3455
3456            // Query the fault messages
3457
Iterator JavaDoc faults = operation.getFaults().values().iterator();
3458
3459            while (faults.hasNext()) {
3460                Message message = ((Fault) faults.next()).getMessage();
3461
3462                if (message != null) {
3463                    MessageEntry mEntry = getMessageEntry(message.getQName());
3464
3465                    if (mEntry != null) {
3466                        setMessageReferences(mEntry, def, doc, false);
3467                    }
3468                }
3469            }
3470        }
3471    } // setPortTypeReferences
3472

3473    /**
3474     * Set the isReferenced flag to true on the given BindingEntry and all
3475     * SymTabEntries that it refers to ONLY if this binding is a SOAP binding.
3476     *
3477     * @param entry
3478     * @param def
3479     * @param doc
3480     */

3481    private void setBindingReferences(BindingEntry entry, Definition def,
3482                                      Document JavaDoc doc) {
3483
3484        if (entry.getBindingType() == BindingEntry.TYPE_SOAP) {
3485
3486            // If we don't want to emit stuff from imported files, only set the
3487
// isReferenced flag if this entry exists in the immediate WSDL file.
3488
Binding binding = entry.getBinding();
3489
3490            if (addImports) {
3491                entry.setIsReferenced(true);
3492            } else {
3493
3494                // NOTE: I thought I could have simply done:
3495
// if (def.getBindng(binding.getQName()) != null)
3496
// but that method traces through all imported bindings.
3497
Map JavaDoc bindings = def.getBindings();
3498
3499                if (bindings.containsValue(binding)) {
3500                    entry.setIsReferenced(true);
3501                }
3502            }
3503
3504            // Set all the binding's portTypes
3505
PortType portType = binding.getPortType();
3506            PortTypeEntry ptEntry = getPortTypeEntry(portType.getQName());
3507
3508            if (ptEntry != null) {
3509                setPortTypeReferences(ptEntry, entry, def, doc);
3510            }
3511        }
3512    } // setBindingReferences
3513

3514    /**
3515     * Set the isReferenced flag to true on the given ServiceEntry and all
3516     * SymTabEntries that it refers to.
3517     *
3518     * @param entry
3519     * @param def
3520     * @param doc
3521     */

3522    private void setServiceReferences(ServiceEntry entry, Definition def,
3523                                      Document JavaDoc doc) {
3524
3525        // If we don't want to emit stuff from imported files, only set the
3526
// isReferenced flag if this entry exists in the immediate WSDL file.
3527
Service service = entry.getService();
3528
3529        if (addImports) {
3530            entry.setIsReferenced(true);
3531        } else {
3532
3533            // NOTE: I thought I could have simply done:
3534
// if (def.getService(service.getQName()) != null)
3535
// but that method traces through all imported services.
3536
Map JavaDoc services = def.getServices();
3537
3538            if (services.containsValue(service)) {
3539                entry.setIsReferenced(true);
3540            }
3541        }
3542
3543        // Set all the service's bindings
3544
Iterator JavaDoc ports = service.getPorts().values().iterator();
3545
3546        while (ports.hasNext()) {
3547            Port port = (Port) ports.next();
3548            Binding binding = port.getBinding();
3549
3550            if (binding != null) {
3551                BindingEntry bEntry = getBindingEntry(binding.getQName());
3552
3553                if (bEntry != null) {
3554                    setBindingReferences(bEntry, def, doc);
3555                }
3556            }
3557        }
3558    } // setServiceReferences
3559

3560    /**
3561     * Put the given SymTabEntry into the symbol table, if appropriate.
3562     *
3563     * @param entry
3564     * @throws IOException
3565     */

3566    private SymTabEntry symbolTablePut(SymTabEntry entry) throws IOException JavaDoc {
3567
3568        QName JavaDoc name = entry.getQName();
3569
3570        SymTabEntry e = get(name, entry.getClass());
3571
3572        if (e == null) {
3573            e = entry;
3574
3575            // An entry of the given qname of the given type doesn't exist yet.
3576
if ((entry instanceof Type)
3577                    && (get(name, UndefinedType.class) != null)) {
3578
3579                // A undefined type exists in the symbol table, which means
3580
// that the type is used, but we don't yet have a definition for
3581
// the type. Now we DO have a definition for the type, so
3582
// replace the existing undefined type with the real type.
3583
if (((TypeEntry) get(name, UndefinedType.class)).isSimpleType()
3584                        && !((TypeEntry) entry).isSimpleType()) {
3585
3586                    // Problem if the undefined type was used in a
3587
// simple type context.
3588
throw new IOException JavaDoc(
3589                            Messages.getMessage(
3590                                    "AttrNotSimpleType01", name.toString()));
3591                }
3592
3593                Vector JavaDoc v = (Vector JavaDoc) symbolTable.get(name);
3594
3595                for (int i = 0; i < v.size(); ++i) {
3596                    Object JavaDoc oldEntry = v.elementAt(i);
3597
3598                    if (oldEntry instanceof UndefinedType) {
3599
3600                        // Replace it in the symbol table
3601
v.setElementAt(entry, i);
3602
3603                        // Replace it in the types index
3604
typeTypeEntries.put(name, entry);
3605
3606                        // Update all of the entries that refer to the unknown type
3607
((UndefinedType) oldEntry).update((Type) entry);
3608                    }
3609                }
3610            } else if ((entry instanceof Element)
3611                    && (get(name, UndefinedElement.class) != null)) {
3612
3613                // A undefined element exists in the symbol table, which means
3614
// that the element is used, but we don't yet have a definition for
3615
// the element. Now we DO have a definition for the element, so
3616
// replace the existing undefined element with the real element.
3617
Vector JavaDoc v = (Vector JavaDoc) symbolTable.get(name);
3618
3619                for (int i = 0; i < v.size(); ++i) {
3620                    Object JavaDoc oldEntry = v.elementAt(i);
3621
3622                    if (oldEntry instanceof UndefinedElement) {
3623
3624                        // Replace it in the symbol table
3625
v.setElementAt(entry, i);
3626
3627                        // Replace it in the elements index
3628
elementTypeEntries.put(name, entry);
3629
3630                        // Update all of the entries that refer to the unknown type
3631
((Undefined) oldEntry).update((Element) entry);
3632                    }
3633                }
3634            } else {
3635
3636                // Add this entry to the symbol table
3637
Vector JavaDoc v = (Vector JavaDoc) symbolTable.get(name);
3638
3639                if (v == null) {
3640                    v = new Vector JavaDoc();
3641
3642                    symbolTable.put(name, v);
3643                }
3644
3645                v.add(entry);
3646
3647                // add TypeEntries to specialized indices for
3648
// fast lookups during reference resolution.
3649
if (entry instanceof Element) {
3650                    elementTypeEntries.put(name, entry);
3651                } else if (entry instanceof Type) {
3652                    typeTypeEntries.put(name, entry);
3653                }
3654            }
3655        } else {
3656            if (!quiet) {
3657                System.out.println(Messages.getMessage("alreadyExists00",
3658                                                       "" + name));
3659            }
3660        }
3661
3662        return e;
3663    } // symbolTablePut
3664

3665    /**
3666     * checks whether there exists a WSDL port with a given name in the current
3667     * symbol table
3668     *
3669     * @param name the QName of the port. Note: only the local part of the qname is relevant,
3670     * since port names are not qualified with a namespace. They are of type nmtoken in WSDL 1.1
3671     * and of type ncname in WSDL 1.2
3672     * @return true, if there is a port element with the specified name; false, otherwise
3673     */

3674    protected boolean existsPortWithName(QName JavaDoc name) {
3675
3676        Vector JavaDoc v = (Vector JavaDoc) symbolTable.get(name);
3677
3678        if (v == null) {
3679            return false;
3680        }
3681
3682        Iterator JavaDoc it = v.iterator();
3683
3684        while (it.hasNext()) {
3685            Object JavaDoc o = it.next();
3686
3687            if (o instanceof PortEntry) {
3688                return true;
3689            }
3690        }
3691
3692        return false;
3693    }
3694
3695    /**
3696     * Method getInnerCollectionComponentQName
3697     *
3698     * @param node
3699     * @return
3700     */

3701    private static QName JavaDoc getInnerCollectionComponentQName(Node JavaDoc node) {
3702
3703        if (node == null) {
3704            return null;
3705        }
3706
3707        QName JavaDoc name = SchemaUtils.getCollectionComponentQName(node, new QNameHolder JavaDoc());
3708
3709        if (name != null) {
3710            return name;
3711        }
3712
3713        // Dive into the node if necessary
3714
NodeList JavaDoc children = node.getChildNodes();
3715
3716        for (int i = 0; i < children.getLength(); i++) {
3717            name = getInnerCollectionComponentQName(children.item(i));
3718
3719            if (name != null) {
3720                return name;
3721            }
3722        }
3723
3724        return null;
3725    }
3726
3727    /**
3728     * Method getInnerTypeQName
3729     *
3730     * @param node
3731     * @return
3732     */

3733    private static QName JavaDoc getInnerTypeQName(Node JavaDoc node) {
3734
3735        if (node == null) {
3736            return null;
3737        }
3738
3739        BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
3740        QName JavaDoc name = Utils.getTypeQName(node, forElement, true);
3741
3742        if (name != null) {
3743            return name;
3744        }
3745
3746        // Dive into the node if necessary
3747
NodeList JavaDoc children = node.getChildNodes();
3748
3749        for (int i = 0; i < children.getLength(); i++) {
3750            name = getInnerTypeQName(children.item(i));
3751
3752            if (name != null) {
3753                return name;
3754            }
3755        }
3756
3757        return null;
3758    }
3759    
3760    protected void processTypes() {
3761        for (Iterator JavaDoc i = typeTypeEntries.values().iterator(); i.hasNext(); ) {
3762            Type type = (Type) i.next();
3763            Node JavaDoc node = type.getNode();
3764            
3765            // Process the attributes
3766
Vector JavaDoc attributes =
3767                    SchemaUtils.getContainedAttributeTypes(node, this);
3768
3769            if (attributes != null) {
3770                type.setContainedAttributes(attributes);
3771            }
3772
3773            // Process the elements
3774
Vector JavaDoc elements =
3775                    SchemaUtils.getContainedElementDeclarations(node, this);
3776
3777            if (elements != null) {
3778                type.setContainedElements(elements);
3779            }
3780        }
3781    }
3782    
3783    public List JavaDoc getMessageEntries() {
3784        List JavaDoc messageEntries = new ArrayList JavaDoc();
3785        Iterator JavaDoc iter = symbolTable.values().iterator();
3786        while (iter.hasNext()) {
3787            Vector JavaDoc v = (Vector JavaDoc)iter.next();
3788            for (int i = 0; i < v.size(); ++i) {
3789                SymTabEntry entry = (SymTabEntry)v.elementAt(i);
3790                if (entry instanceof MessageEntry) {
3791                    messageEntries.add(entry);
3792                }
3793            }
3794        }
3795
3796        return messageEntries;
3797    }
3798
3799    public void setWrapArrays(boolean wrapArrays) {
3800        this.wrapArrays = wrapArrays;
3801    }
3802
3803    public Map JavaDoc getElementFormDefaults() {
3804        return elementFormDefaults;
3805    }
3806}
3807
Popular Tags