KickJava   Java API By Example, From Geeks To Geeks.

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


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

55
56 package org.jboss.axis.wsdl.symbolTable;
57
58 import org.jboss.axis.Constants;
59 import org.jboss.axis.enums.Style;
60 import org.jboss.axis.enums.Use;
61 import org.jboss.axis.utils.LinkedHashMap;
62 import org.jboss.axis.utils.Messages;
63 import org.jboss.axis.utils.URLHashSet;
64 import org.jboss.axis.utils.XMLUtils;
65 import org.jboss.logging.Logger;
66 import org.w3c.dom.Document JavaDoc;
67 import org.w3c.dom.NamedNodeMap JavaDoc;
68 import org.w3c.dom.Node JavaDoc;
69 import org.w3c.dom.NodeList JavaDoc;
70 import org.xml.sax.SAXException JavaDoc;
71
72 import javax.wsdl.Binding;
73 import javax.wsdl.BindingFault;
74 import javax.wsdl.BindingInput;
75 import javax.wsdl.BindingOperation;
76 import javax.wsdl.BindingOutput;
77 import javax.wsdl.Definition;
78 import javax.wsdl.Fault;
79 import javax.wsdl.Import;
80 import javax.wsdl.Input;
81 import javax.wsdl.Message;
82 import javax.wsdl.Operation;
83 import javax.wsdl.Output;
84 import javax.wsdl.Part;
85 import javax.wsdl.Port;
86 import javax.wsdl.PortType;
87 import javax.wsdl.Service;
88 import javax.wsdl.WSDLException;
89 import javax.wsdl.extensions.UnknownExtensibilityElement;
90 import javax.wsdl.extensions.http.HTTPBinding;
91 import javax.wsdl.extensions.mime.MIMEContent;
92 import javax.wsdl.extensions.mime.MIMEMultipartRelated;
93 import javax.wsdl.extensions.mime.MIMEPart;
94 import javax.wsdl.extensions.soap.SOAPBinding;
95 import javax.wsdl.extensions.soap.SOAPBody;
96 import javax.wsdl.extensions.soap.SOAPFault;
97 import javax.wsdl.extensions.soap.SOAPHeader;
98 import javax.wsdl.extensions.soap.SOAPHeaderFault;
99 import javax.wsdl.factory.WSDLFactory;
100 import javax.wsdl.xml.WSDLReader;
101 import javax.xml.namespace.QName JavaDoc;
102 import javax.xml.parsers.ParserConfigurationException JavaDoc;
103 import javax.xml.rpc.holders.BooleanHolder JavaDoc;
104 import javax.xml.rpc.holders.IntHolder JavaDoc;
105 import java.io.File JavaDoc;
106 import java.io.IOException JavaDoc;
107 import java.net.MalformedURLException JavaDoc;
108 import java.net.URL JavaDoc;
109 import java.util.ArrayList JavaDoc;
110 import java.util.Collection JavaDoc;
111 import java.util.Collections JavaDoc;
112 import java.util.HashMap JavaDoc;
113 import java.util.HashSet JavaDoc;
114 import java.util.Iterator JavaDoc;
115 import java.util.List JavaDoc;
116 import java.util.Map JavaDoc;
117 import java.util.Vector JavaDoc;
118
119 /**
120  * This class represents a table of all of the top-level symbols from a set of WSDL Definitions and
121  * DOM Documents: XML types; WSDL messages, portTypes, bindings, and services.
122  * <p/>
123  * This symbolTable contains entries of the form <key, value> where key is of type QName and value is
124  * of type Vector. The Vector's elements are all of the objects that have the given QName. This is
125  * necessary since names aren't unique among the WSDL types. message, portType, binding, service,
126  * could all have the same QName and are differentiated merely by type. SymbolTable contains
127  * type-specific getters to bypass the Vector layer:
128  * public PortTypeEntry getPortTypeEntry(QName name), etc.
129  */

130 public class SymbolTable
131 {
132    private static final Logger log = Logger.getLogger(SymbolTable.class);
133
134    // Should the contents of imported files be added to the symbol table?
135
private boolean addImports;
136
137    // The actual symbol table. This symbolTable contains entries of the form
138
// <key, value> where key is of type QName and value is of type Vector. The
139
// Vector's elements are all of the objects that have the given QName. This
140
// is necessary since names aren't unique among the WSDL types. message,
141
// portType, binding, service, could all have the same QName and are
142
// differentiated merely by type. SymbolTable contains type-specific
143
// getters to bypass the Vector layer:
144
// public PortTypeEntry getPortTypeEntry(QName name), etc.
145

146    private HashMap symbolTable = new HashMap();
147
148    // a map of qnames -> Elements in the symbol table
149
private final Map elementTypeEntries = new HashMap();
150    // an unmodifiable wrapper so that we can share the index with others, safely
151
private final Map elementIndex = Collections.unmodifiableMap(elementTypeEntries);
152    // a map of qnames -> Types in the symbol table
153
private final Map typeTypeEntries = new HashMap();
154    // an unmodifiable wrapper so that we can share the index with others, safely
155
private final Map typeIndex = Collections.unmodifiableMap(typeTypeEntries);
156
157    /**
158     * cache of nodes -> base types for complexTypes. The cache is
159     * built on nodes because multiple TypeEntry objects may use the
160     * same node.
161     */

162    protected final Map node2ExtensionBase = new HashMap(); // allow friendly access
163

164    private boolean verbose;
165
166    private BaseTypeMapping btm = null;
167
168    // should we attempt to treat document/literal WSDL as "rpc-style"
169
private boolean nowrap;
170    // Did we encounter wraped mode WSDL
171
private boolean wrapped = false;
172
173    public static final String JavaDoc ANON_TOKEN = ">";
174
175    private Definition def = null;
176    private String JavaDoc wsdlURI = null;
177
178    /**
179     * Construct a symbol table with the given Namespaces.
180     */

181    public SymbolTable(BaseTypeMapping btm, boolean addImports,
182                       boolean verbose, boolean nowrap)
183    {
184       this.btm = btm;
185       this.addImports = addImports;
186       this.verbose = verbose;
187       this.nowrap = nowrap;
188    } // ctor
189

190    /**
191     * Get the raw symbol table HashMap.
192     */

193    public HashMap getHashMap()
194    {
195       return symbolTable;
196    } // getHashMap
197

198    /**
199     * Get the list of entries with the given QName. Since symbols can share QNames, this list is
200     * necessary. This list will not contain any more than one element of any given SymTabEntry.
201     */

202    public Vector JavaDoc getSymbols(QName JavaDoc qname)
203    {
204       return (Vector JavaDoc)symbolTable.get(qname);
205    } // get
206

207    /**
208     * Get the entry with the given QName of the given class. If it does not exist, return null.
209     */

210    public SymTabEntry get(QName JavaDoc qname, Class JavaDoc cls)
211    {
212       Vector JavaDoc v = (Vector JavaDoc)symbolTable.get(qname);
213       if (v == null)
214       {
215          return null;
216       }
217       else
218       {
219          for (int i = 0; i < v.size(); ++i)
220          {
221             SymTabEntry entry = (SymTabEntry)v.elementAt(i);
222             if (cls.isInstance(entry))
223             {
224                return entry;
225             }
226          }
227          return null;
228       }
229    } // get
230

231
232    /**
233     * Get the type entry for the given qname.
234     *
235     * @param qname
236     * @param wantElementType boolean that indicates type or element (for type= or ref=)
237     */

238    public TypeEntry getTypeEntry(QName JavaDoc qname, boolean wantElementType)
239    {
240       if (wantElementType)
241       {
242          return getElement(qname);
243       }
244       else
245          return getType(qname);
246    } // getTypeEntry
247

248    /**
249     * Get the Type TypeEntry with the given QName. If it doesn't
250     * exist, return null.
251     */

252    public Type getType(QName JavaDoc qname)
253    {
254       return (Type)typeTypeEntries.get(qname);
255    } // getType
256

257    /**
258     * Get the Element TypeEntry with the given QName. If it doesn't
259     * exist, return null.
260     */

261    public Element getElement(QName JavaDoc qname)
262    {
263       return (Element)elementTypeEntries.get(qname);
264    } // getElement
265

266    /**
267     * Get the MessageEntry with the given QName. If it doesn't exist, return null.
268     */

269    public MessageEntry getMessageEntry(QName JavaDoc qname)
270    {
271       return (MessageEntry)get(qname, MessageEntry.class);
272    } // getMessageEntry
273

274    /**
275     * Get the PortTypeEntry with the given QName. If it doesn't exist, return null.
276     */

277    public PortTypeEntry getPortTypeEntry(QName JavaDoc qname)
278    {
279       return (PortTypeEntry)get(qname, PortTypeEntry.class);
280    } // getPortTypeEntry
281

282    /**
283     * Get the BindingEntry with the given QName. If it doesn't exist, return null.
284     */

285    public BindingEntry getBindingEntry(QName JavaDoc qname)
286    {
287       return (BindingEntry)get(qname, BindingEntry.class);
288    } // getBindingEntry
289

290    /**
291     * Get the ServiceEntry with the given QName. If it doesn't exist, return null.
292     */

293    public ServiceEntry getServiceEntry(QName JavaDoc qname)
294    {
295       return (ServiceEntry)get(qname, ServiceEntry.class);
296    } // getServiceEntry
297

298    /**
299     * Get the list of all the XML schema types in the symbol table. In other words, all entries
300     * that are instances of TypeEntry.
301     *
302     * @deprecated use specialized get{Element,Type}Index() methods instead
303     */

304    public Vector JavaDoc getTypes()
305    {
306       Vector JavaDoc v = new Vector JavaDoc();
307       v.addAll(elementTypeEntries.values());
308       v.addAll(typeTypeEntries.values());
309       return v;
310    } // getTypes
311

312    /**
313     * Return an unmodifiable map of qnames -> Elements in the symbol
314     * table.
315     *
316     * @return an unmodifiable <code>Map</code> value
317     */

318    public Map getElementIndex()
319    {
320       return elementIndex;
321    }
322
323    /**
324     * Return an unmodifiable map of qnames -> Elements in the symbol
325     * table.
326     *
327     * @return an unmodifiable <code>Map</code> value
328     */

329    public Map getTypeIndex()
330    {
331       return typeIndex;
332    }
333
334    /**
335     * Return the count of TypeEntries in the symbol table.
336     *
337     * @return an <code>int</code> value
338     */

339    public int getTypeEntryCount()
340    {
341       return elementTypeEntries.size() + typeTypeEntries.size();
342    }
343
344    /**
345     * Get the Definition. The definition is null until
346     * populate is called.
347     */

348    public Definition getDefinition()
349    {
350       return def;
351    } // getDefinition
352

353    /**
354     * Get the WSDL URI. The WSDL URI is null until populate
355     * is called, and ONLY if a WSDL URI is provided.
356     */

357    public String JavaDoc getWSDLURI()
358    {
359       return wsdlURI;
360    } // getWSDLURI
361

362    /**
363     * Are we wrapping literal soap body elements.
364     */

365    public boolean isWrapped()
366    {
367       return wrapped;
368    }
369
370    /**
371     * Turn on/off element wrapping for literal soap body's.
372     */

373    public void setWrapped(boolean wrapped)
374    {
375       this.wrapped = wrapped;
376    }
377
378    /**
379     * Dump the contents of the symbol table. For debugging purposes only.
380     */

381    public void dump(java.io.PrintStream JavaDoc out)
382    {
383       out.println();
384       out.println(Messages.getMessage("symbolTable00"));
385       out.println("-----------------------");
386       Iterator JavaDoc it = symbolTable.values().iterator();
387       while (it.hasNext())
388       {
389          Vector JavaDoc v = (Vector JavaDoc)it.next();
390          for (int i = 0; i < v.size(); ++i)
391          {
392             out.println(v.elementAt(i).getClass().getName());
393             out.println(v.elementAt(i));
394          }
395       }
396       out.println("-----------------------");
397    } // dump
398

399
400    /**
401     * Call this method if you have a uri for the WSDL document
402     *
403     * @param uri wsdlURI the location of the WSDL file.
404     */

405
406    public void populate(String JavaDoc uri)
407            throws IOException JavaDoc, WSDLException,
408            SAXException JavaDoc, ParserConfigurationException JavaDoc
409    {
410       populate(uri, null, null);
411    } // populate
412

413    public void populate(String JavaDoc uri, String JavaDoc username, String JavaDoc password)
414            throws IOException JavaDoc, WSDLException,
415            SAXException JavaDoc, ParserConfigurationException JavaDoc
416    {
417       if (verbose)
418          System.out.println(Messages.getMessage("parsing00", uri));
419
420       Document JavaDoc doc = XMLUtils.newDocument(uri, username, password);
421       this.wsdlURI = uri;
422       try
423       {
424          File JavaDoc f = new File JavaDoc(uri);
425          if (f.exists())
426          {
427             uri = f.toURL().toString();
428          }
429       }
430       catch (Exception JavaDoc e)
431       {
432       }
433       populate(uri, doc);
434    } // populate
435

436    /**
437     * Call this method if your WSDL document has already been parsed as an XML DOM document.
438     *
439     * @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.
440     * @param doc doc This is the XML Document containing the WSDL.
441     */

442    public void populate(String JavaDoc context, Document JavaDoc doc)
443            throws IOException JavaDoc, SAXException JavaDoc, WSDLException,
444            ParserConfigurationException JavaDoc
445    {
446       WSDLReader reader = WSDLFactory.newInstance().newWSDLReader();
447       reader.setFeature("javax.wsdl.verbose", verbose);
448       this.def = reader.readWSDL(context, doc);
449
450       add(context, def, doc);
451    } // populate
452

453    /**
454     * Add the given Definition and Document information to the symbol table (including imported
455     * symbols), populating it with SymTabEntries for each of the top-level symbols. When the
456     * symbol table has been populated, iterate through it, setting the isReferenced flag
457     * appropriately for each entry.
458     */

459    protected void add(String JavaDoc context, Definition def, Document JavaDoc doc)
460            throws IOException JavaDoc, SAXException JavaDoc, WSDLException,
461            ParserConfigurationException JavaDoc
462    {
463       URL JavaDoc contextURL = context == null ? null : getURL(null, context);
464       populate(contextURL, def, doc, null);
465       checkForUndefined();
466       populateParameters();
467       setReferences(def, doc); // uses wrapped flag set in populateParameters
468
} // add
469

470    /**
471     * Scan the Definition for undefined objects and throw an error.
472     */

473    private void checkForUndefined(Definition def, String JavaDoc filename) throws IOException JavaDoc
474    {
475       if (def != null)
476       {
477          // Bindings
478
Iterator JavaDoc ib = def.getBindings().values().iterator();
479          while (ib.hasNext())
480          {
481             Binding binding = (Binding)ib.next();
482             if (binding.isUndefined())
483             {
484                if (filename == null)
485                {
486                   throw new IOException JavaDoc(Messages.getMessage("emitFailtUndefinedBinding01",
487                           binding.getQName().getLocalPart()));
488                }
489                else
490                {
491                   throw new IOException JavaDoc(Messages.getMessage("emitFailtUndefinedBinding02",
492                           binding.getQName().getLocalPart(), filename));
493                }
494             }
495          }
496
497          // portTypes
498
Iterator JavaDoc ip = def.getPortTypes().values().iterator();
499          while (ip.hasNext())
500          {
501             PortType portType = (PortType)ip.next();
502             if (portType.isUndefined())
503             {
504                if (filename == null)
505                {
506                   throw new IOException JavaDoc(Messages.getMessage("emitFailtUndefinedPort01",
507                           portType.getQName().getLocalPart()));
508                }
509                else
510                {
511                   throw new IOException JavaDoc(Messages.getMessage("emitFailtUndefinedPort02",
512                           portType.getQName().getLocalPart(), filename));
513                }
514             }
515          }
516
517 /* tomj: This is a bad idea, faults seem to be undefined
518 // RJB reply: this MUST be done for those systems that do something with
519 // messages. Perhaps we have to do an extra step for faults? I'll leave
520 // this commented for now, until someone uses this generator for something
521 // other than WSDL2Java.
522             // Messages
523             Iterator i = def.getMessages().values().iterator();
524             while (i.hasNext()) {
525                 Message message = (Message) i.next();
526                 if (message.isUndefined()) {
527                     throw new IOException(
528                             Messages.getMessage("emitFailtUndefinedMessage01",
529                                     message.getQName().getLocalPart()));
530                 }
531             }
532 */

533       }
534    }
535
536    /**
537     * Scan the symbol table for undefined types and throw an exception.
538     */

539    private void checkForUndefined() throws IOException JavaDoc
540    {
541       Iterator JavaDoc it = symbolTable.values().iterator();
542       while (it.hasNext())
543       {
544          Vector JavaDoc v = (Vector JavaDoc)it.next();
545          for (int i = 0; i < v.size(); ++i)
546          {
547             SymTabEntry entry = (SymTabEntry)v.get(i);
548
549             // Report undefined types
550
if (entry instanceof UndefinedType)
551             {
552                QName JavaDoc qn = entry.getQName();
553
554                // Special case dateTime/timeInstant that changed
555
// from version to version.
556
if ((qn.getLocalPart().equals("dateTime") &&
557                        !qn.getNamespaceURI().equals(Constants.URI_2001_SCHEMA_XSD)) ||
558                        (qn.getLocalPart().equals("timeInstant") &&
559                        qn.getNamespaceURI().equals(Constants.URI_2001_SCHEMA_XSD)))
560                {
561                   throw new IOException JavaDoc(Messages.getMessage("wrongNamespace00",
562                           qn.getLocalPart(),
563                           qn.getNamespaceURI()));
564                }
565
566                // Check for a undefined XSD Schema Type and throw
567
// an unsupported message instead of undefined
568
if (SchemaUtils.isSimpleSchemaType(entry.getQName()))
569                {
570                   throw new IOException JavaDoc(Messages.getMessage("unsupportedSchemaType00",
571                           qn.getLocalPart()));
572                }
573
574                // last case, its some other undefined thing
575
throw new IOException JavaDoc(Messages.getMessage("undefined00",
576                        entry.getQName().toString()));
577             } // if undefined
578
else if (entry instanceof UndefinedElement)
579             {
580                throw new IOException JavaDoc(Messages.getMessage("undefinedElem00",
581                        entry.getQName().toString()));
582             }
583          }
584       }
585    } // checkForUndefined
586

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

594    private URLHashSet importedFiles = new URLHashSet();
595
596    private void populate(URL JavaDoc context, Definition def, Document JavaDoc doc,
597                          String JavaDoc filename)
598            throws IOException JavaDoc, ParserConfigurationException JavaDoc,
599            SAXException JavaDoc, WSDLException
600    {
601       if (doc != null)
602       {
603          populateTypes(context, doc);
604
605          if (addImports)
606          {
607             // Add the symbols from any xsd:import'ed documents.
608
lookForImports(context, doc);
609          }
610       }
611       if (def != null)
612       {
613          checkForUndefined(def, filename);
614          if (addImports)
615          {
616             // Add the symbols from the wsdl:import'ed WSDL documents
617
Map imports = def.getImports();
618             Object JavaDoc[] importKeys = imports.keySet().toArray();
619             for (int i = 0; i < importKeys.length; ++i)
620             {
621                Vector JavaDoc v = (Vector JavaDoc)imports.get(importKeys[i]);
622                for (int j = 0; j < v.size(); ++j)
623                {
624                   Import imp = (Import)v.get(j);
625                   if (!importedFiles.contains(imp.getLocationURI()))
626                   {
627                      importedFiles.add(imp.getLocationURI());
628                      URL JavaDoc url = getURL(context, imp.getLocationURI());
629                      populate(url, imp.getDefinition(),
630                              XMLUtils.newDocument(url.toString()),
631                              url.toString());
632                   }
633                }
634             }
635          }
636          populateMessages(def);
637          populatePortTypes(def);
638          populateBindings(def);
639          populateServices(def);
640       }
641    } // populate
642

643    /**
644     * This is essentially a call to "new URL(contextURL, spec)" with extra handling in case spec is
645     * a file.
646     */

647    private static URL JavaDoc getURL(URL JavaDoc contextURL, String JavaDoc spec) throws IOException JavaDoc
648    {
649       // First, fix the slashes as windows filenames may have backslashes
650
// in them, but the URL class wont do the right thing when we later
651
// process this URL as the contextURL.
652
String JavaDoc path = spec.replace('\\', '/');
653
654       // See if we have a good URL.
655
URL JavaDoc url = null;
656       try
657       {
658          // first, try to treat spec as a full URL
659
url = new URL JavaDoc(contextURL, path);
660
661          // if we are deail with files in both cases, create a url
662
// by using the directory of the context URL.
663
if (contextURL != null &&
664                  url.getProtocol().equals("file") &&
665                  contextURL.getProtocol().equals("file"))
666          {
667             url = getFileURL(contextURL, path);
668          }
669       }
670       catch (MalformedURLException JavaDoc me)
671       {
672          // try treating is as a file pathname
673
url = getFileURL(contextURL, path);
674       }
675
676       // Everything is OK with this URL, although a file url constructed
677
// above may not exist. This will be caught later when the URL is
678
// accessed.
679
return url;
680    } // getURL
681

682    private static URL JavaDoc getFileURL(URL JavaDoc contextURL, String JavaDoc path)
683            throws IOException JavaDoc
684    {
685       if (contextURL != null)
686       {
687          // get the parent directory of the contextURL, and append
688
// the spec string to the end.
689
String JavaDoc contextFileName = contextURL.getFile();
690          URL JavaDoc parent = new File JavaDoc(contextFileName).getParentFile().toURL();
691          if (parent != null)
692          {
693             return new URL JavaDoc(parent, path);
694          }
695       }
696       return new URL JavaDoc("file", "", path);
697    } // getFileURL
698

699    /**
700     * Recursively find all xsd:import'ed objects and call populate for each one.
701     */

702    private void lookForImports(URL JavaDoc context, Node JavaDoc node)
703            throws IOException JavaDoc, ParserConfigurationException JavaDoc,
704            SAXException JavaDoc, WSDLException
705    {
706       NodeList JavaDoc children = node.getChildNodes();
707       for (int i = 0; i < children.getLength(); i++)
708       {
709          Node JavaDoc child = children.item(i);
710          if ("import".equals(child.getLocalName()))
711          {
712             NamedNodeMap JavaDoc attributes = child.getAttributes();
713             Node JavaDoc namespace = attributes.getNamedItem("namespace");
714             // skip XSD import of soap encoding
715
if (namespace != null &&
716                     isKnownNamespace(namespace.getNodeValue()))
717             {
718                continue;
719             }
720             Node JavaDoc importFile = attributes.getNamedItem("schemaLocation");
721             if (importFile != null)
722             {
723                URL JavaDoc url = getURL(context,
724                        importFile.getNodeValue());
725                if (!importedFiles.contains(url))
726                {
727                   importedFiles.add(url);
728                   String JavaDoc filename = url.toString();
729                   populate(url, null,
730                           XMLUtils.newDocument(filename), filename);
731                }
732             }
733          }
734          lookForImports(context, child);
735       }
736    } // lookForImports
737

738    /**
739     * Check if this is a known namespace (soap-enc or schema xsd or schema xsi or xml)
740     *
741     * @param namespace
742     * @return true if this is a know namespace.
743     */

744    public boolean isKnownNamespace(String JavaDoc namespace)
745    {
746       if (Constants.isSOAP_ENC(namespace))
747          return true;
748       if (Constants.isSchemaXSD(namespace))
749          return true;
750       if (Constants.isSchemaXSI(namespace))
751          return true;
752       if (namespace.equals(Constants.NS_URI_XML))
753          return true;
754       return false;
755    }
756
757    /**
758     * Populate the symbol table with all of the Types from the Document.
759     */

760    public void populateTypes(URL JavaDoc context, Document JavaDoc doc)
761            throws IOException JavaDoc, SAXException JavaDoc, WSDLException,
762            ParserConfigurationException JavaDoc
763    {
764       addTypes(context, doc, ABOVE_SCHEMA_LEVEL);
765    } // populateTypes
766

767    /**
768     * Utility method which walks the Document and creates Type objects for
769     * each complexType, simpleType, or element referenced or defined.
770     * <p/>
771     * What goes into the symbol table? In general, only the top-level types
772     * (ie., those just below
773     * the schema tag). But base types and references can
774     * appear below the top level. So anything
775     * at the top level is added to the symbol table,
776     * plus non-Element types (ie, base and refd)
777     * that appear deep within other types.
778     */

779    private static final int ABOVE_SCHEMA_LEVEL = -1;
780    private static final int SCHEMA_LEVEL = 0;
781
782    private void addTypes(URL JavaDoc context, Node JavaDoc node, int level)
783            throws IOException JavaDoc, ParserConfigurationException JavaDoc,
784            WSDLException, SAXException JavaDoc
785    {
786       if (node == null)
787       {
788          return;
789       }
790       // Get the kind of node (complexType, wsdl:part, etc.)
791
QName JavaDoc nodeKind = Utils.getNodeQName(node);
792
793       if (nodeKind != null)
794       {
795          String JavaDoc localPart = nodeKind.getLocalPart();
796          boolean isXSD = Constants.isSchemaXSD(nodeKind.getNamespaceURI());
797          if ((isXSD && localPart.equals("complexType") ||
798                  localPart.equals("simpleType")))
799          {
800
801             // If an extension or restriction is present,
802
// create a type for the reference
803
Node JavaDoc re = SchemaUtils.getRestrictionOrExtensionNode(node);
804             if (re != null &&
805                     Utils.getAttribute(re, "base") != null)
806             {
807                createTypeFromRef(re);
808             }
809
810             // This is a definition of a complex type.
811
// Create a Type.
812
createTypeFromDef(node, false, false);
813          }
814          else if (isXSD && localPart.equals("element"))
815          {
816             // Create a type entry for the referenced type
817
createTypeFromRef(node);
818
819             // If an extension or restriction is present,
820
// create a type for the reference
821
Node JavaDoc re = SchemaUtils.getRestrictionOrExtensionNode(node);
822             if (re != null &&
823                     Utils.getAttribute(re, "base") != null)
824             {
825                createTypeFromRef(re);
826             }
827
828             // Create a type representing an element. (This may
829
// seem like overkill, but is necessary to support ref=
830
// and element=.
831
createTypeFromDef(node, true, level > SCHEMA_LEVEL);
832          }
833          else if (isXSD && localPart.equals("attribute"))
834          {
835             // Create a type entry for the referenced type
836
BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
837             QName JavaDoc refQName = Utils.getTypeQName(node, forElement, false);
838
839             if (refQName != null && !forElement.value)
840             {
841                createTypeFromRef(node);
842
843                // Get the symbol table entry and make sure it is a simple
844
// type
845
if (refQName != null)
846                {
847                   TypeEntry refType = getTypeEntry(refQName, false);
848                   if (refType != null &&
849                           refType instanceof Undefined)
850                   {
851                      // Don't know what the type is.
852
// It better be simple so set it as simple
853
refType.setSimpleType(true);
854                   }
855                   else if (refType == null ||
856                           (!(refType instanceof BaseType) &&
857                           !refType.isSimpleType()))
858                   {
859                      // Problem if not simple
860
throw new IOException JavaDoc(Messages.getMessage("AttrNotSimpleType01",
861                              refQName.toString()));
862                   }
863                }
864             }
865          }
866          else if (isXSD && localPart.equals("any"))
867          {
868             // Map xsd:any element to special xsd:any "type"
869
if (getType(Constants.XSD_ANY) == null)
870             {
871                Type type = new BaseType(Constants.XSD_ANY);
872                symbolTablePut(type);
873             }
874          }
875          else if (localPart.equals("part") &&
876                  Constants.isWSDL(nodeKind.getNamespaceURI()))
877          {
878
879             // This is a wsdl part. Create an TypeEntry representing the reference
880
createTypeFromRef(node);
881          }
882          else if (isXSD && localPart.equals("include"))
883          {
884             String JavaDoc includeName = Utils.getAttribute(node, "schemaLocation");
885             if (includeName != null)
886             {
887                URL JavaDoc url = getURL(context, includeName);
888                Document JavaDoc includeDoc = XMLUtils.newDocument(url.toString());
889                // Vidyanand : Fix for Bug #15124
890
org.w3c.dom.Element JavaDoc schemaEl = includeDoc.getDocumentElement();
891                if (!schemaEl.hasAttribute("targetNamespace"))
892                {
893                   org.w3c.dom.Element JavaDoc parentSchemaEl = (org.w3c.dom.Element JavaDoc)node.getParentNode();
894                   if (parentSchemaEl.hasAttribute("targetNamespace"))
895                   {
896                      // we need to set two things in here
897
// 1. targetNamespace
898
// 2. setup the xmlns=<targetNamespace> attribute
899
String JavaDoc tns = parentSchemaEl.getAttribute("targetNamespace");
900                      schemaEl.setAttribute("targetNamespace", tns);
901                      schemaEl.setAttribute("xmlns", tns);
902                   }
903                }
904                populate(url, null, includeDoc, url.toString());
905             }
906          }
907       }
908
909       if (level == ABOVE_SCHEMA_LEVEL)
910       {
911          if (nodeKind != null && nodeKind.getLocalPart().equals("schema"))
912          {
913             level = SCHEMA_LEVEL;
914          }
915       }
916       else
917       {
918          ++level;
919       }
920
921       // Recurse through children nodes
922
NodeList JavaDoc children = node.getChildNodes();
923       for (int i = 0; i < children.getLength(); i++)
924       {
925          addTypes(context, children.item(i), level);
926       }
927    } // addTypes
928

929    /**
930     * Create a TypeEntry from the indicated node, which defines a type
931     * that represents a complexType, simpleType or element (for ref=).
932     */

933    private void createTypeFromDef(Node JavaDoc node, boolean isElement,
934                                   boolean belowSchemaLevel) throws IOException JavaDoc
935    {
936       // Get the QName of the node's name attribute value
937
QName JavaDoc qName = Utils.getNodeNameQName(node);
938       if (qName != null)
939       {
940
941          // If the qname is already registered as a base type,
942
// don't create a defining type/element.
943
if (!isElement && btm.getBaseName(qName) != null)
944          {
945             return;
946          }
947
948          // If the node has a type or ref attribute, get the
949
// qname representing the type
950
BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
951          QName JavaDoc refQName = Utils.getTypeQName(node, forElement, false);
952
953          if (refQName != null)
954          {
955             // Error check - bug 12362
956
if (qName.getLocalPart().length() == 0)
957             {
958                String JavaDoc name = Utils.getAttribute(node, "name");
959                if (name == null)
960                {
961                   name = "unknown";
962                }
963                throw new IOException JavaDoc(Messages.getMessage("emptyref00", name));
964             }
965
966             // Now get the TypeEntry
967
TypeEntry refType = getTypeEntry(refQName, forElement.value);
968             if (!belowSchemaLevel)
969             {
970                if (refType == null)
971                {
972                   throw new IOException JavaDoc(Messages.getMessage("absentRef00", refQName.toString(), qName.toString()));
973                }
974                symbolTablePut(new DefinedElement(qName, refType, node, ""));
975             }
976          }
977          else
978          {
979             // Flow to here indicates no type= or ref= attribute.
980

981             // See if this is an array or simple type definition.
982
IntHolder JavaDoc numDims = new IntHolder JavaDoc();
983             numDims.value = 0;
984             QName JavaDoc arrayEQName = SchemaUtils.getArrayComponentQName(node, numDims);
985
986             if (arrayEQName != null)
987             {
988                // Get the TypeEntry for the array element type
989
refQName = arrayEQName;
990                TypeEntry refType = getTypeEntry(refQName, false);
991                if (refType == null)
992                {
993                   // Not defined yet, add one
994
String JavaDoc baseName = btm.getBaseName(refQName);
995                   if (baseName != null)
996                      refType = new BaseType(refQName);
997                   else
998                      refType = new UndefinedType(refQName);
999                   symbolTablePut(refType);
1000               }
1001
1002               // Create a defined type or element that references refType
1003
String JavaDoc dims = "";
1004               while (numDims.value > 0)
1005               {
1006                  dims += "[]";
1007                  numDims.value--;
1008               }
1009
1010               TypeEntry defType = null;
1011               if (isElement)
1012               {
1013                  if (!belowSchemaLevel)
1014                  {
1015                     defType = new DefinedElement(qName, refType, node, dims);
1016                  }
1017               }
1018               else
1019               {
1020                  defType = new DefinedType(qName, refType, node, dims);
1021               }
1022               if (defType != null)
1023               {
1024                  symbolTablePut(defType);
1025               }
1026            }
1027            else
1028            {
1029
1030               // Create a TypeEntry representing this type/element
1031
String JavaDoc baseName = btm.getBaseName(qName);
1032               if (baseName != null)
1033               {
1034                  symbolTablePut(new BaseType(qName));
1035               }
1036               else
1037               {
1038
1039                  // Create a type entry, set whether it should
1040
// be mapped as a simple type, and put it in the
1041
// symbol table.
1042
TypeEntry te = null;
1043                  if (!isElement)
1044                  {
1045                     te = new DefinedType(qName, node);
1046
1047                     // check if we are an anonymous type underneath
1048
// an element. If so, we point the refType of the
1049
// element to us (the real type).
1050
if (qName.getLocalPart().indexOf(ANON_TOKEN) >= 0)
1051                     {
1052                        Node JavaDoc parent = node.getParentNode();
1053                        QName JavaDoc parentQName = Utils.getNodeNameQName(parent);
1054                        TypeEntry parentType = getElement(parentQName);
1055                        if (parentType != null)
1056                        {
1057                           parentType.setRefType(te);
1058                        }
1059                     }
1060
1061                  }
1062                  else
1063                  {
1064                     if (!belowSchemaLevel)
1065                     {
1066                        te = new DefinedElement(qName, node);
1067                     }
1068                  }
1069                  if (te != null)
1070                  {
1071                     if (SchemaUtils.isSimpleTypeOrSimpleContent(node))
1072                     {
1073                        te.setSimpleType(true);
1074                     }
1075                     symbolTablePut(te);
1076                  }
1077               }
1078            }
1079         }
1080      }
1081   } // createTypeFromDef
1082

1083   /**
1084    * Node may contain a reference (via type=, ref=, or element= attributes) to
1085    * another type. Create a Type object representing this referenced type.
1086    */

1087   private void createTypeFromRef(Node JavaDoc node) throws IOException JavaDoc
1088   {
1089      // Get the QName of the node's type attribute value
1090
BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
1091      QName JavaDoc qName = Utils.getTypeQName(node, forElement, false);
1092      if (qName != null)
1093      {
1094         // Error check - bug 12362
1095
if (qName.getLocalPart().length() == 0)
1096         {
1097            String JavaDoc name = Utils.getAttribute(node, "name");
1098            if (name == null)
1099            {
1100               name = "unknown";
1101            }
1102            throw new IOException JavaDoc(Messages.getMessage("emptyref00", name));
1103         }
1104
1105         // Get Type or Element depending on whether type attr was used.
1106
TypeEntry type = getTypeEntry(qName, forElement.value);
1107
1108         // A symbol table entry is created if the TypeEntry is not found
1109
if (type == null)
1110         {
1111            // See if this is a special QName for collections
1112
if (qName.getLocalPart().indexOf("[") > 0)
1113            {
1114               QName JavaDoc containedQName = Utils.getTypeQName(node, forElement, true);
1115               TypeEntry containedTE = getTypeEntry(containedQName, forElement.value);
1116               if (!forElement.value)
1117               {
1118                  // Case of type and maxOccurs
1119
if (containedTE == null)
1120                  {
1121                     // Collection Element Type not defined yet, add one.
1122
String JavaDoc baseName = btm.getBaseName(containedQName);
1123                     if (baseName != null)
1124                     {
1125                        containedTE = new BaseType(containedQName);
1126                     }
1127                     else
1128                     {
1129                        containedTE = new UndefinedType(containedQName);
1130                     }
1131                     symbolTablePut(containedTE);
1132                  }
1133                  symbolTablePut(new CollectionType(qName, containedTE, node, "[]"));
1134               }
1135               else
1136               {
1137                  // Case of ref and maxOccurs
1138
if (containedTE == null)
1139                  {
1140                     containedTE = new UndefinedElement(containedQName);
1141                     symbolTablePut(containedTE);
1142                  }
1143                  symbolTablePut(new CollectionElement(qName, containedTE, node, "[]"));
1144               }
1145            }
1146            else
1147            {
1148               // Add a BaseType or Undefined Type/Element
1149
String JavaDoc baseName = btm.getBaseName(qName);
1150               if (baseName != null)
1151                  symbolTablePut(new BaseType(qName));
1152               else if (forElement.value == false)
1153                  symbolTablePut(new UndefinedType(qName));
1154               else
1155                  symbolTablePut(new UndefinedElement(qName));
1156            }
1157         }
1158      }
1159   } // createTypeFromRef
1160

1161   /**
1162    * Populate the symbol table with all of the MessageEntry's from the Definition.
1163    */

1164   private void populateMessages(Definition def) throws IOException JavaDoc
1165   {
1166      Iterator JavaDoc i = def.getMessages().values().iterator();
1167      while (i.hasNext())
1168      {
1169         Message message = (Message)i.next();
1170         MessageEntry mEntry = new MessageEntry(message);
1171         symbolTablePut(mEntry);
1172      }
1173   } // populateMessages
1174

1175   /**
1176    * ensures that a message in a <code>&lt;input&gt;</code>, <code>&lt;output&gt;</code>,
1177    * or <code>&lt;fault&gt;</fault> element in an <code>&lt;operation&gt;</code>
1178    * element is valid. In particular, ensures that
1179    * <ol>
1180    * <li>an attribute <code>message</code> is present (according to the
1181    * XML Schema for WSDL 1.1 <code>message</code> is <strong>required</strong>
1182    * <p/>
1183    * <li>the value of attribute <code>message</code> (a QName) refers to
1184    * an already defined message
1185    * </ol>
1186    * <p/>
1187    * <strong>Note</strong>: this method should throw a <code>javax.wsdl.WSDLException</code> rather than
1188    * a <code>java.io.IOException</code>
1189    *
1190    * @param message the message object
1191    * @throws IOException thrown, if the message is not valid
1192    */

1193   protected void ensureOperationMessageValid(Message message) throws IOException JavaDoc
1194   {
1195
1196      // make sure the message is not null (i.e. there is an
1197
// attribute 'message ')
1198
//
1199
if (message == null)
1200      {
1201         throw new IOException JavaDoc("<input>,<output>, or <fault> in <operation ..> without attribute 'message' found. Attribute 'message' is required.");
1202      }
1203
1204      // make sure the value of the attribute refers to an
1205
// already defined message
1206
//
1207
if (message.isUndefined())
1208      {
1209         throw new IOException JavaDoc("<input ..>, <output ..> or <fault ..> in <portType> with undefined message found. message name is '"
1210                 + message.getQName().toString()
1211                 + "'");
1212      }
1213   }
1214
1215
1216   /**
1217    * ensures that an an element <code>&lt;operation&gt;</code> within
1218    * an element <code>&lt;portType&gt;<code> is valid. Throws an exception
1219    * if the operation is not valid.
1220    * <p/>
1221    * <strong>Note</strong>: this method should throw a <code>javax.wsdl.WSDLException</code>
1222    * rather than a <code>java.io.IOException</code>
1223    *
1224    * @param operation the operation element
1225    * @throws IOException thrown, if the element is not valid.
1226    * @throws IllegalArgumentException thrown, if operation is null
1227    */

1228   protected void ensureOperationValid(Operation operation) throws IOException JavaDoc
1229   {
1230
1231      if (operation == null)
1232      {
1233         throw new IllegalArgumentException JavaDoc("parameter 'operation' must not be null");
1234      }
1235
1236      Input input = operation.getInput();
1237      if (input != null)
1238      {
1239         ensureOperationMessageValid(input.getMessage());
1240      }
1241
1242      Output output = operation.getOutput();
1243      if (output != null)
1244      {
1245         ensureOperationMessageValid(output.getMessage());
1246      }
1247
1248      Map faults = operation.getFaults();
1249      if (faults != null)
1250      {
1251         Iterator JavaDoc it = faults.values().iterator();
1252         while (it.hasNext())
1253         {
1254            ensureOperationMessageValid(((Fault)it.next()).getMessage());
1255         }
1256      }
1257   }
1258
1259   /**
1260    * ensures that an an element <code>&lt;portType&gt;</code>
1261    * is valid. Throws an exception if the portType is not valid.
1262    * <p/>
1263    * <strong>Note</strong>: this method should throw a <code>javax.wsdl.WSDLException</code>
1264    * rather than a <code>java.io.IOException</code>
1265    *
1266    * @param portType the portType element
1267    * @throws IOException thrown, if the element is not valid.
1268    * @throws IllegalArgumentException thrown, if operation is null
1269    */

1270
1271   protected void ensureOperationsOfPortTypeValid(PortType portType) throws IOException JavaDoc
1272   {
1273      if (portType == null)
1274         throw new IllegalArgumentException JavaDoc("parameter 'portType' must not be null");
1275
1276      List JavaDoc operations = portType.getOperations();
1277
1278      // no operations defined ? -> valid according to the WSDL 1.1 schema
1279
//
1280
if (operations == null || operations.size() == 0) return;
1281
1282      // check operations defined in this portType
1283
//
1284
Iterator JavaDoc it = operations.iterator();
1285      while (it.hasNext())
1286      {
1287         Operation operation = (Operation)it.next();
1288         ensureOperationValid(operation);
1289      }
1290   }
1291
1292   /**
1293    * Populate the symbol table with all of the PortTypeEntry's from the Definition.
1294    */

1295   private void populatePortTypes(Definition def) throws IOException JavaDoc
1296   {
1297      Iterator JavaDoc i = def.getPortTypes().values().iterator();
1298      while (i.hasNext())
1299      {
1300         PortType portType = (PortType)i.next();
1301
1302
1303         // If the portType is undefined, then we're parsing a Definition
1304
// that didn't contain a portType, merely a binding that referred
1305
// to a non-existent port type. Don't bother with it.
1306
if (!portType.isUndefined())
1307         {
1308            ensureOperationsOfPortTypeValid(portType);
1309            PortTypeEntry ptEntry = new PortTypeEntry(portType);
1310            symbolTablePut(ptEntry);
1311         }
1312      }
1313   } // populatePortTypes
1314

1315
1316   /**
1317    * Create the parameters and store them in the bindingEntry.
1318    */

1319   private void populateParameters() throws IOException JavaDoc
1320   {
1321      Iterator JavaDoc it = symbolTable.values().iterator();
1322      while (it.hasNext())
1323      {
1324         Vector JavaDoc v = (Vector JavaDoc)it.next();
1325         for (int i = 0; i < v.size(); ++i)
1326         {
1327            if (v.get(i) instanceof BindingEntry)
1328            {
1329               BindingEntry bEntry = (BindingEntry)v.get(i);
1330               // Skip non-soap bindings
1331
if (bEntry.getBindingType() != BindingEntry.TYPE_SOAP)
1332                  continue;
1333
1334               Binding binding = bEntry.getBinding();
1335               Collection JavaDoc bindOperations = bEntry.getOperations();
1336               PortType portType = binding.getPortType();
1337
1338               LinkedHashMap parameters = new LinkedHashMap();
1339               Iterator JavaDoc operations = portType.getOperations().iterator();
1340
1341               // get parameters
1342
while (operations.hasNext())
1343               {
1344                  Operation operation = (Operation)operations.next();
1345
1346                  // See if the PortType operation has a corresponding
1347
// Binding operation and report an error if it doesn't.
1348
if (!bindOperations.contains(operation))
1349                  {
1350                     throw new IOException JavaDoc(Messages.getMessage("emitFailNoMatchingBindOperation01",
1351                             operation.getName(),
1352                             portType.getQName().getLocalPart()));
1353                  }
1354
1355                  String JavaDoc namespace = portType.getQName().getNamespaceURI();
1356                  Parameters parms = getOperationParameters(operation,
1357                          namespace,
1358                          bEntry);
1359                  parameters.put(operation, parms);
1360               }
1361               bEntry.setParameters(parameters);
1362            }
1363         }
1364      }
1365   } // populateParameters
1366

1367   /**
1368    * For the given operation, this method returns the parameter info conveniently collated.
1369    * There is a bit of processing that is needed to write the interface, stub, and skeleton.
1370    * Rather than do that processing 3 times, it is done once, here, and stored in the
1371    * Parameters object.
1372    */

1373   public Parameters getOperationParameters(Operation operation,
1374                                            String JavaDoc namespace,
1375                                            BindingEntry bindingEntry) throws IOException JavaDoc
1376   {
1377      Parameters parameters = new Parameters();
1378
1379      // The input and output Vectors of Parameters
1380
Vector JavaDoc inputs = new Vector JavaDoc();
1381      Vector JavaDoc outputs = new Vector JavaDoc();
1382
1383      List JavaDoc parameterOrder = operation.getParameterOrdering();
1384
1385      // Handle parameterOrder="", which is techinically illegal
1386
if (parameterOrder != null && parameterOrder.isEmpty())
1387      {
1388         parameterOrder = null;
1389      }
1390
1391      // All input parts MUST be in the parameterOrder list. It is an error otherwise.
1392
if (parameterOrder != null)
1393      {
1394         Input input = operation.getInput();
1395         if (input != null)
1396         {
1397            Message inputMsg = input.getMessage();
1398            Map allInputs = inputMsg.getParts();
1399            Collection JavaDoc orderedInputs = inputMsg.getOrderedParts(parameterOrder);
1400            if (allInputs.size() != orderedInputs.size())
1401            {
1402               throw new IOException JavaDoc(Messages.getMessage("emitFail00", operation.getName()));
1403            }
1404         }
1405      }
1406
1407      boolean literalInput = false;
1408      boolean literalOutput = false;
1409      if (bindingEntry != null)
1410      {
1411         literalInput = (bindingEntry.getInputBodyType(operation) == Use.LITERAL);
1412         literalOutput = (bindingEntry.getOutputBodyType(operation) == Use.LITERAL);
1413      }
1414
1415      // Collect all the input parameters
1416
Input input = operation.getInput();
1417      if (input != null && input.getMessage() != null)
1418      {
1419         getParametersFromParts(inputs,
1420                 input.getMessage().getOrderedParts(null),
1421                 literalInput,
1422                 operation.getName(),
1423                 bindingEntry);
1424      }
1425
1426      // Collect all the output parameters
1427
Output output = operation.getOutput();
1428      if (output != null && output.getMessage() != null)
1429      {
1430         getParametersFromParts(outputs,
1431                 output.getMessage().getOrderedParts(null),
1432                 literalOutput,
1433                 operation.getName(),
1434                 bindingEntry);
1435      }
1436
1437      if (parameterOrder != null)
1438      {
1439         // Construct a list of the parameters in the parameterOrder list, determining the
1440
// mode of each parameter and preserving the parameterOrder list.
1441
for (int i = 0; i < parameterOrder.size(); ++i)
1442         {
1443            String JavaDoc name = (String JavaDoc)parameterOrder.get(i);
1444
1445            // index in the inputs Vector of the given name, -1 if it doesn't exist.
1446
int index = getPartIndex(name, inputs);
1447
1448            // index in the outputs Vector of the given name, -1 if it doesn't exist.
1449
int outdex = getPartIndex(name, outputs);
1450
1451            if (index >= 0)
1452            {
1453               // The mode of this parameter is either in or inout
1454
addInishParm(inputs, outputs, index, outdex, parameters, true);
1455            }
1456            else if (outdex >= 0)
1457            {
1458               addOutParm(outputs, outdex, parameters, true);
1459            }
1460            else
1461            {
1462               System.err.println(Messages.getMessage("noPart00", name));
1463            }
1464         }
1465      }
1466
1467      // Some special case logic for JAX-RPC, but also to make things
1468
// nicer for the user.
1469
// If we have a single input and output with the same name
1470
// instead of: void echo(StringHolder inout)
1471
// Do this: string echo(string in)
1472
if (wrapped && inputs.size() == 1 && outputs.size() == 1 &&
1473              ((Parameter)inputs.get(0)).getName().equals(((Parameter)outputs.get(0)).getName()))
1474      {
1475         // add the input and make sure its a IN not an INOUT
1476
addInishParm(inputs, null, 0, -1, parameters, false);
1477      }
1478      else
1479      {
1480         // Get the mode info about those parts that aren't in the
1481
// parameterOrder list. Since they're not in the parameterOrder list,
1482
// the order is, first all in (and inout) parameters, then all out
1483
// parameters, in the order they appear in the messages.
1484
for (int i = 0; i < inputs.size(); i++)
1485         {
1486            Parameter p = (Parameter)inputs.get(i);
1487            int outdex = getPartIndex(p.getName(), outputs);
1488            addInishParm(inputs, outputs, i, outdex, parameters, false);
1489         }
1490      }
1491
1492      // Now that the remaining in and inout parameters are collected,
1493
// determine the status of outputs. If there is only 1, then it
1494
// is the return value. If there are more than 1, then they are
1495
// out parameters.
1496
if (outputs.size() == 1)
1497      {
1498         parameters.returnParam = (Parameter)outputs.get(0);
1499         parameters.returnParam.setMode(Parameter.OUT);
1500         if (parameters.returnParam.getType() instanceof DefinedElement)
1501         {
1502            parameters.returnParam.setQName(parameters.returnParam.getType()
1503                    .getQName());
1504         }
1505         ++parameters.outputs;
1506      }
1507      else
1508      {
1509         for (int i = 0; i < outputs.size(); i++)
1510         {
1511            addOutParm(outputs, i, parameters, false);
1512         }
1513      }
1514      parameters.faults = operation.getFaults();
1515
1516      // before we return the paramters,
1517
// make sure we dont have a duplicate name
1518
Vector JavaDoc used = new Vector JavaDoc(parameters.list.size());
1519      Iterator JavaDoc i = parameters.list.iterator();
1520      while (i.hasNext())
1521      {
1522         Parameter parameter = (Parameter)i.next();
1523         int count = 2;
1524         while (used.contains(parameter.getName()))
1525         {
1526            // duplicate, add a suffix and try again
1527
parameter.setName(parameter.getName() + Integer.toString(count++));
1528         }
1529         used.add(parameter.getName());
1530      }
1531
1532      return parameters;
1533   } // parameters
1534

1535   // True if the paramter is already in the given list
1536
private boolean isInParameterList(Vector JavaDoc params, String JavaDoc partName)
1537   {
1538      for (int i = 0; i < params.size(); i++)
1539      {
1540         Parameter parameter = (Parameter)params.get(i);
1541         if (partName.equals(parameter.getName()))
1542            return true;
1543      }
1544      return false;
1545   }
1546
1547   /**
1548    * Return the index of the given name in the given Vector, -1 if it doesn't exist.
1549    */

1550   private int getPartIndex(String JavaDoc name, Vector JavaDoc v)
1551   {
1552      for (int i = 0; i < v.size(); i++)
1553      {
1554         if (name.equals(((Parameter)v.get(i)).getName()))
1555         {
1556            return i;
1557         }
1558      }
1559      return -1;
1560   } // getPartIndex
1561

1562   /**
1563    * Add an in or inout parameter to the parameters object.
1564    */

1565   private void addInishParm(Vector JavaDoc inputs,
1566                             Vector JavaDoc outputs,
1567                             int index,
1568                             int outdex,
1569                             Parameters parameters,
1570                             boolean trimInput)
1571   {
1572      Parameter p = (Parameter)inputs.get(index);
1573      // If this is an element, we want the XML to reflect the element name
1574
// not the part name. Same check is made in addOutParam below.
1575
if (p.getType() instanceof DefinedElement)
1576      {
1577         DefinedElement de = (DefinedElement)p.getType();
1578         p.setQName(de.getQName());
1579      }
1580      // If this is a collection we want the XML to reflect the type in
1581
// the collection, not foo[unbounded].
1582
// Same check is made in addOutParam below.
1583
if (p.getType() instanceof CollectionElement)
1584      {
1585         p.setQName(p.getType().getRefType().getQName());
1586      }
1587
1588      // Should we remove the given parameter type/name entries from the Vector?
1589
if (trimInput)
1590      {
1591         inputs.remove(index);
1592      }
1593
1594      // At this point we know the name and type of the parameter, and that it's at least an
1595
// in parameter. Now check to see whether it's also in the outputs Vector. If it is,
1596
// then it's an inout parameter.
1597
if (outdex >= 0)
1598      {
1599         Parameter outParam = (Parameter)outputs.get(outdex);
1600         if (p.getType().equals(outParam.getType()))
1601         {
1602            outputs.remove(outdex);
1603            p.setMode(Parameter.INOUT);
1604            ++parameters.inouts;
1605         }
1606         else
1607         {
1608            // If we're here, we have both an input and an output
1609
// part with the same name but different types.... guess
1610
// it's not really an inout....
1611
//
1612
//throw new IOException(Messages.getMessage("differentTypes00",
1613
// new String[] { p.getName(),
1614
// p.getType().getQName().toString(),
1615
// outParam.getType().getQName().toString()
1616
// }
1617
//));
1618

1619            // There is some controversy about this, and the specs are
1620
// a bit vague about what should happen if the types don't
1621
// agree. Throwing an error is not correct with document/lit
1622
// operations, as part names get resused (i.e. "body").
1623
// See WSDL 1.1 section 2.4.6,
1624
// WSDL 1.2 working draft 9 July 2002 section 2.3.1
1625
++parameters.inputs;
1626         }
1627      }
1628      else
1629      {
1630         ++parameters.inputs;
1631      }
1632
1633      parameters.list.add(p);
1634   } // addInishParm
1635

1636   /**
1637    * Add an output parameter to the parameters object.
1638    */

1639   private void addOutParm(Vector JavaDoc outputs,
1640                           int outdex,
1641                           Parameters parameters,
1642                           boolean trim)
1643   {
1644      Parameter p = (Parameter)outputs.get(outdex);
1645
1646      // If this is an element, we want the XML to reflect the element name
1647
// not the part name. Same check is made in addInishParam above.
1648
if (p.getType() instanceof DefinedElement)
1649      {
1650         DefinedElement de = (DefinedElement)p.getType();
1651         p.setQName(de.getQName());
1652      }
1653      // If this is a collection we want the XML to reflect the type in
1654
// the collection, not foo[unbounded].
1655
// Same check is made in addInishParam above.
1656
if (p.getType() instanceof CollectionElement)
1657      {
1658         p.setQName(p.getType().getRefType().getQName());
1659      }
1660
1661      if (trim)
1662      {
1663         outputs.remove(outdex);
1664      }
1665
1666      p.setMode(Parameter.OUT);
1667      ++parameters.outputs;
1668
1669      parameters.list.add(p);
1670   } // addOutParm
1671

1672   /**
1673    * This method returns a vector containing Parameters which represent
1674    * each Part (shouldn't we call these "Parts" or something?)
1675    */

1676   public void getParametersFromParts(Vector JavaDoc v,
1677                                      Collection JavaDoc parts,
1678                                      boolean literal,
1679                                      String JavaDoc opName,
1680                                      BindingEntry bindingEntry)
1681           throws IOException JavaDoc
1682   {
1683
1684      // HACK ALERT! This whole method is waaaay too complex.
1685
// It needs rewriting (for instance, we sometimes new up
1686
// a Parameter, then ignore it in favor of another we new up.)
1687

1688      // Determine if there's only one element. For wrapped
1689
// style, we normally only have 1 part which is an
1690
// element. But with MIME we could have any number of
1691
// types along with that single element. As long as
1692
// there's only ONE element, and it's the same name as
1693
// the operation, we can unwrap it.
1694
int numberOfElements = 0;
1695      boolean possiblyWrapped = false;
1696      Iterator JavaDoc i = parts.iterator();
1697      while (i.hasNext())
1698      {
1699         Part part = (Part)i.next();
1700         if (part.getElementName() != null)
1701         {
1702            ++numberOfElements;
1703            if (part.getElementName().getLocalPart().equals(opName))
1704            {
1705               possiblyWrapped = true;
1706            }
1707         }
1708      }
1709
1710      // Hack alert - Try to sense "wrapped" document literal mode
1711
// if we haven't been told not to.
1712
// Criteria:
1713
// - If there is a single element part,
1714
// - That part is an element
1715
// - That element has the same name as the operation
1716
// - That element has no attributes (check done below)
1717
if (!nowrap &&
1718              literal &&
1719              numberOfElements == 1 &&
1720              possiblyWrapped)
1721      {
1722         wrapped = true;
1723      }
1724
1725      i = parts.iterator();
1726      while (i.hasNext())
1727      {
1728         Parameter param = new Parameter();
1729         Part part = (Part)i.next();
1730         QName JavaDoc elementName = part.getElementName();
1731         QName JavaDoc typeName = part.getTypeName();
1732         String JavaDoc partName = part.getName();
1733
1734         // We're either:
1735
// 1. encoded
1736
// 2. literal & not wrapped.
1737
if (!literal || !wrapped || elementName == null)
1738         {
1739
1740            param.setName(partName);
1741
1742            // Add this type or element name
1743
if (typeName != null)
1744            {
1745               param.setType(getType(typeName));
1746            }
1747            else if (elementName != null)
1748            {
1749               // Just an FYI: The WSDL spec says that for use=encoded
1750
// that parts reference an abstract type using the type attr
1751
// but we kinda do the right thing here, so let it go.
1752
// if (!literal)
1753
// error...
1754
param.setType(getElement(elementName));
1755            }
1756            else
1757            {
1758               // no type or element
1759
throw new IOException JavaDoc(Messages.getMessage("noTypeOrElement00",
1760                       new String JavaDoc[]{partName,
1761                                    opName}));
1762            }
1763            setMIMEInfo(param, bindingEntry == null ? null :
1764                    bindingEntry.getMIMEInfo(opName, partName));
1765            if (bindingEntry != null &&
1766                    bindingEntry.isInHeaderPart(opName, partName))
1767            {
1768               param.setInHeader(true);
1769            }
1770            if (bindingEntry != null &&
1771                    bindingEntry.isOutHeaderPart(opName, partName))
1772            {
1773               param.setOutHeader(true);
1774            }
1775
1776            v.add(param);
1777
1778            continue; // next part
1779
}
1780
1781         // flow to here means wrapped literal !
1782

1783         // See if we can map all the XML types to java(?) types
1784
// if we can, we use these as the types
1785
Node JavaDoc node = null;
1786         if (typeName != null && bindingEntry.getMIMETypes().size() == 0)
1787         {
1788            // Since we can't (yet?) make the Axis engine generate the right
1789
// XML for literal parts that specify the type attribute,
1790
// (unless they're MIME types) abort processing with an
1791
// error if we encounter this case
1792
//
1793
// node = getTypeEntry(typeName, false).getNode();
1794
String JavaDoc bindingName =
1795                    bindingEntry == null ? "unknown" : bindingEntry.getBinding().getQName().toString();
1796            throw new IOException JavaDoc(Messages.getMessage("literalTypePart00",
1797                    new String JavaDoc[]{partName,
1798                                 opName,
1799                                 bindingName}));
1800         }
1801
1802         // Get the node which corresponds to the type entry for this
1803
// element. i.e.:
1804
// <part name="part" element="foo:bar"/>
1805
// ...
1806
// <schema targetNamespace="foo">
1807
// <element name="bar"...> <--- This one
1808
node = getTypeEntry(elementName, true).getNode();
1809
1810         // Check if this element is of the form:
1811
// <element name="foo" type="tns:foo_type"/>
1812
BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
1813         QName JavaDoc type = Utils.getTypeQName(node, forElement, false);
1814         if (type != null && !forElement.value)
1815         {
1816            // If in fact we have such a type, go get the node that
1817
// corresponds to THAT definition.
1818
node = getTypeEntry(type, false).getNode();
1819         }
1820
1821         Vector JavaDoc vTypes = null;
1822         // If we have nothing at this point, we're in trouble.
1823
if (node == null)
1824         {
1825            if (bindingEntry.isInHeaderPart(opName, partName))
1826            {
1827               wrapped = false;
1828            }
1829            else
1830            {
1831               /*
1832               throw new IOException(
1833                   Messages.getMessage("badTypeNode",
1834                                        new String[] {
1835                                            partName,
1836                                            opName,
1837                                            elementName.toString()}));
1838               */

1839            }
1840         }
1841         else
1842         {
1843            // check for attributes
1844
Vector JavaDoc vAttrs = SchemaUtils.getContainedAttributeTypes(node, this);
1845            if (vAttrs != null)
1846            {
1847               // can't do wrapped mode
1848
wrapped = false;
1849            }
1850
1851            // Get the nested type entries.
1852
// TODO - If we are unable to represent any of the types in the
1853
// element, we need to use SOAPElement/SOAPBodyElement.
1854
// I don't believe getContainedElementDecl does the right thing yet.
1855
vTypes = SchemaUtils.getContainedElementDeclarations(node, this);
1856         }
1857         // IF we got the type entries and we didn't find attributes
1858
// THEN use the things in this element as the parameters
1859
if (vTypes != null && wrapped)
1860         {
1861            // add the elements in this list
1862
for (int j = 0; j < vTypes.size(); j++)
1863            {
1864               ElementDecl elem = (ElementDecl)vTypes.elementAt(j);
1865               Parameter p = new Parameter();
1866               p.setQName(elem.getName());
1867               p.setType(elem.getType());
1868               setMIMEInfo(p, bindingEntry == null ? null :
1869                       bindingEntry.getMIMEInfo(opName, partName));
1870               if (bindingEntry.isInHeaderPart(opName, partName))
1871               {
1872                  p.setInHeader(true);
1873               }
1874               if (bindingEntry.isOutHeaderPart(opName, partName))
1875               {
1876                  p.setOutHeader(true);
1877               }
1878               v.add(p);
1879            }
1880         }
1881         else
1882         {
1883            // - we were unable to get the types OR
1884
// - we found attributes
1885
// so we can't use wrapped mode.
1886
param.setName(partName);
1887
1888            if (typeName != null)
1889            {
1890               param.setType(getType(typeName));
1891            }
1892            else if (elementName != null)
1893            {
1894               param.setType(getElement(elementName));
1895            }
1896            setMIMEInfo(param, bindingEntry == null ? null :
1897                    bindingEntry.getMIMEInfo(opName, partName));
1898            if (bindingEntry.isInHeaderPart(opName, partName))
1899            {
1900               param.setInHeader(true);
1901            }
1902            if (bindingEntry.isOutHeaderPart(opName, partName))
1903            {
1904               param.setOutHeader(true);
1905            }
1906
1907            v.add(param);
1908         }
1909      } // while
1910

1911   } // getParametersFromParts
1912

1913   /**
1914    * Set the MIME type. This can be determine in one of two ways:
1915    * 1. From WSDL 1.1 MIME constructs on the binding (passed in);
1916    * 2. From AXIS-specific xml MIME types.
1917    */

1918   private void setMIMEInfo(Parameter p, MimeInfo mimeInfo)
1919   {
1920      // If there is no binding MIME construct (ie., the mimeType parameter is
1921
// null), then get the MIME type from the AXIS-specific xml MIME type.
1922
if (mimeInfo == null)
1923      {
1924         QName JavaDoc mimeQName = p.getType().getQName();
1925         if (mimeQName.getNamespaceURI().equals(Constants.NS_URI_XMLSOAP))
1926         {
1927            if (Constants.MIME_IMAGE.equals(mimeQName))
1928            {
1929               mimeInfo = new MimeInfo("image/jpeg", "");
1930            }
1931            else if (Constants.MIME_PLAINTEXT.equals(mimeQName))
1932            {
1933               mimeInfo = new MimeInfo("text/plain", "");
1934            }
1935            else if (Constants.MIME_MULTIPART.equals(mimeQName))
1936            {
1937               mimeInfo = new MimeInfo("multipart/related", "");
1938            }
1939            else if (Constants.MIME_SOURCE.equals(mimeQName))
1940            {
1941               mimeInfo = new MimeInfo("text/xml", "");
1942            }
1943            else if (Constants.MIME_OCTETSTREAM.equals(mimeQName))
1944            {
1945               mimeInfo = new MimeInfo("application/octetstream", "");
1946            }
1947         }
1948      }
1949      p.setMIMEInfo(mimeInfo);
1950   } // setMIMEType
1951

1952   /**
1953    * Populate the symbol table with all of the BindingEntry's from the Definition.
1954    */

1955   private void populateBindings(Definition def) throws IOException JavaDoc
1956   {
1957      Iterator JavaDoc i = def.getBindings().values().iterator();
1958      while (i.hasNext())
1959      {
1960         Binding binding = (Binding)i.next();
1961
1962         BindingEntry bEntry = new BindingEntry(binding);
1963         symbolTablePut(bEntry);
1964
1965         Iterator JavaDoc extensibilityElementsIterator = binding.getExtensibilityElements().iterator();
1966         while (extensibilityElementsIterator.hasNext())
1967         {
1968            Object JavaDoc obj = extensibilityElementsIterator.next();
1969            if (obj instanceof SOAPBinding)
1970            {
1971               bEntry.setBindingType(BindingEntry.TYPE_SOAP);
1972               SOAPBinding sb = (SOAPBinding)obj;
1973               String JavaDoc style = sb.getStyle();
1974               if ("rpc".equalsIgnoreCase(style))
1975               {
1976                  bEntry.setBindingStyle(Style.RPC);
1977               }
1978            }
1979            else if (obj instanceof HTTPBinding)
1980            {
1981               HTTPBinding hb = (HTTPBinding)obj;
1982               if (hb.getVerb().equalsIgnoreCase("post"))
1983               {
1984                  bEntry.setBindingType(BindingEntry.TYPE_HTTP_POST);
1985               }
1986               else
1987               {
1988                  bEntry.setBindingType(BindingEntry.TYPE_HTTP_GET);
1989               }
1990            }
1991            else if (obj instanceof UnknownExtensibilityElement)
1992            {
1993               //TODO: After WSDL4J supports soap12, change this code
1994
UnknownExtensibilityElement unkElement = (UnknownExtensibilityElement)obj;
1995               QName JavaDoc name = unkElement.getElementType();
1996               if (name.getNamespaceURI().equals(Constants.URI_WSDL12_SOAP) &&
1997                       name.getLocalPart().equals("binding"))
1998               {
1999                  bEntry.setBindingType(BindingEntry.TYPE_SOAP);
2000                  String JavaDoc style = unkElement.getElement().getAttribute("style");
2001                  if ("rpc".equalsIgnoreCase(style))
2002                  {
2003                     bEntry.setBindingStyle(Style.RPC);
2004                  }
2005               }
2006            }
2007         }
2008
2009         // Step through the binding operations, setting the following as appropriate:
2010
// - hasLiteral
2011
// - body types
2012
// - mimeTypes
2013
// - headers
2014
HashMap attributes = new HashMap();
2015         List JavaDoc bindList = binding.getBindingOperations();
2016         HashMap faultMap = new HashMap(); // name to SOAPFault from WSDL4J
2017
for (Iterator JavaDoc opIterator = bindList.iterator(); opIterator.hasNext();)
2018         {
2019            BindingOperation bindOp = (BindingOperation)opIterator.next();
2020            Operation operation = bindOp.getOperation();
2021            BindingInput bindingInput = bindOp.getBindingInput();
2022            BindingOutput bindingOutput = bindOp.getBindingOutput();
2023            String JavaDoc opName = bindOp.getName();
2024
2025            // First, make sure the binding operation matches a portType operation
2026
String JavaDoc inputName = bindingInput == null ? null :
2027                    bindingInput.getName();
2028            String JavaDoc outputName = bindingOutput == null ? null :
2029                    bindingOutput.getName();
2030            if (binding.getPortType().getOperation(opName, inputName, outputName) == null)
2031            {
2032               throw new IOException JavaDoc(Messages.getMessage("unmatchedOp",
2033                       new String JavaDoc[]{opName, inputName, outputName}));
2034            }
2035
2036            ArrayList JavaDoc faults = new ArrayList JavaDoc();
2037
2038            // input
2039
if (bindingInput != null)
2040            {
2041               if (bindingInput.getExtensibilityElements() != null)
2042               {
2043                  Iterator JavaDoc inIter = bindingInput.
2044                          getExtensibilityElements().iterator();
2045                  fillInBindingInfo(bEntry, operation, inIter, faults,
2046                          true);
2047               }
2048            }
2049
2050            // output
2051
if (bindingOutput != null)
2052            {
2053               if (bindingOutput.getExtensibilityElements() != null)
2054               {
2055                  Iterator JavaDoc outIter = bindingOutput.
2056                          getExtensibilityElements().iterator();
2057                  fillInBindingInfo(bEntry, operation, outIter, faults,
2058                          false);
2059               }
2060            }
2061
2062            // faults
2063
faultsFromSOAPFault(binding, bindOp, operation, faults);
2064
2065            // Add this fault name and info to the map
2066
faultMap.put(bindOp, faults);
2067
2068            Use inputBodyType = bEntry.getInputBodyType(operation);
2069            Use outputBodyType = bEntry.getOutputBodyType(operation);
2070
2071            // Associate the portType operation that goes with this binding
2072
// with the body types.
2073
attributes.put(bindOp.getOperation(),
2074                    new BindingEntry.OperationAttr(inputBodyType, outputBodyType, faultMap));
2075
2076            // If the input or output body uses literal, flag the binding as using literal.
2077
// NOTE: should I include faultBodyType in this check?
2078
if (inputBodyType == Use.LITERAL ||
2079                    outputBodyType == Use.LITERAL)
2080            {
2081               bEntry.setHasLiteral(true);
2082            }
2083            bEntry.setFaultBodyTypeMap(operation, faultMap);
2084         } // binding operations
2085

2086         bEntry.setFaults(faultMap);
2087      }
2088   } // populateBindings
2089

2090   /**
2091    * Fill in some binding information: bodyType, mimeType, header info.
2092    */

2093   private void fillInBindingInfo(BindingEntry bEntry, Operation operation,
2094                                  Iterator JavaDoc it, ArrayList JavaDoc faults, boolean input) throws IOException JavaDoc
2095   {
2096      for (; it.hasNext();)
2097      {
2098         Object JavaDoc obj = it.next();
2099         if (obj instanceof SOAPBody)
2100         {
2101            setBodyType(((SOAPBody)obj).getUse(), bEntry, operation,
2102                    input);
2103         }
2104         else if (obj instanceof SOAPHeader)
2105         {
2106            SOAPHeader header = (SOAPHeader)obj;
2107            setBodyType(header.getUse(), bEntry, operation, input);
2108
2109            // Note, this only works for explicit headers - those whose
2110
// parts come from messages used in the portType's operation
2111
// input/output clauses - it does not work for implicit
2112
// headers - those whose parts come from messages not used in
2113
// the portType's operation's input/output clauses. I don't
2114
// know what we're supposed to emit for implicit headers.
2115
bEntry.setHeaderPart(operation.getName(), header.getPart(), header,
2116                    input ? BindingEntry.IN_HEADER : BindingEntry.OUT_HEADER);
2117
2118            // Add any soap:headerFault info to the faults array
2119
Iterator JavaDoc headerFaults = header.getSOAPHeaderFaults().iterator();
2120            while (headerFaults.hasNext())
2121            {
2122               SOAPHeaderFault headerFault =
2123                       (SOAPHeaderFault)headerFaults.next();
2124               faults.add(new FaultInfo(headerFault, this));
2125            }
2126         }
2127         else if (obj instanceof MIMEMultipartRelated)
2128         {
2129            bEntry.setBodyType(operation,
2130                    addMIMETypes(bEntry, (MIMEMultipartRelated)obj,
2131                            operation), input);
2132         }
2133         else if (obj instanceof UnknownExtensibilityElement)
2134         {
2135            UnknownExtensibilityElement unkElement = (UnknownExtensibilityElement)obj;
2136            QName JavaDoc name = unkElement.getElementType();
2137            if (name.getNamespaceURI().equals(Constants.URI_DIME_WSDL) &&
2138                    name.getLocalPart().equals("message"))
2139            {
2140               fillInDIMEInformation(unkElement, input, operation, bEntry);
2141            }
2142            //TODO: After WSDL4J supports soap12, change this code
2143
if (name.getNamespaceURI().equals(Constants.URI_WSDL12_SOAP) &&
2144                    name.getLocalPart().equals("body"))
2145            {
2146               setBodyType(unkElement.getElement().getAttribute("use"), bEntry, operation,
2147                       input);
2148            }
2149            //TODO: After WSDL4J supports soap12, change this code
2150
if (name.getNamespaceURI().equals(Constants.URI_WSDL12_SOAP) &&
2151                    name.getLocalPart().equals("header"))
2152            {
2153               setBodyType(unkElement.getElement().getAttribute("use"), bEntry, operation, input);
2154
2155               // Note, this only works for explicit headers - those whose
2156
// parts come from messages used in the portType's operation
2157
// input/output clauses - it does not work for implicit
2158
// headers - those whose parts come from messages not used in
2159
// the portType's operation's input/output clauses. I don't
2160
// know what we're supposed to emit for implicit headers.
2161
String JavaDoc partName = unkElement.getElement().getAttribute("part");
2162               bEntry.setHeaderPart(operation.getName(), partName, null,
2163                       input ? BindingEntry.IN_HEADER : BindingEntry.OUT_HEADER);
2164
2165               // Add any soap12:headerFault info to the faults array
2166
NodeList JavaDoc headerFaults = unkElement.getElement().getChildNodes();
2167               for (int i = 0; i < headerFaults.getLength(); i++)
2168               {
2169                  String JavaDoc faultMessage = unkElement.getElement().getAttribute("message");
2170                  String JavaDoc faultPart = unkElement.getElement().getAttribute("part");
2171                  String JavaDoc faultUse = unkElement.getElement().getAttribute("use");
2172                  String JavaDoc faultNamespaceURI = unkElement.getElement().getAttribute("namespace");
2173                  QName JavaDoc faultMessageQName = null;
2174                  int sep = faultMessage.indexOf(':');
2175                  if (sep == -1)
2176                  {
2177                     faultMessageQName = new QName JavaDoc(faultMessage);
2178                  }
2179                  else
2180                  {
2181                     faultMessageQName = new QName JavaDoc(faultMessage.substring(0, sep), faultMessage.substring(sep + 1));
2182                  }
2183                  faults.add(new FaultInfo(faultMessageQName, faultPart, faultUse, faultNamespaceURI, this));
2184               }
2185            }
2186         }
2187      }
2188   } // fillInBindingInfo
2189

2190   /**
2191    * Fill in DIME information
2192    *
2193    * @param unkElement
2194    * @param input
2195    * @param operation
2196    * @param bEntry
2197    */

2198   private void fillInDIMEInformation(UnknownExtensibilityElement unkElement, boolean input, Operation operation, BindingEntry bEntry)
2199   {
2200      String JavaDoc layout = unkElement.getElement().getAttribute("layout");
2201      // TODO: what to do with layout info?
2202
if (layout.equals(Constants.URI_DIME_CLOSED_LAYOUT))
2203      {
2204      }
2205      else if (layout.equals(Constants.URI_DIME_OPEN_LAYOUT))
2206      {
2207      }
2208      Map parts = null;
2209      if (input)
2210      {
2211         parts = operation.getInput().getMessage().getParts();
2212      }
2213      else
2214      {
2215         parts = operation.getOutput().getMessage().getParts();
2216      }
2217      if (parts != null)
2218      {
2219         Iterator JavaDoc iterator = parts.values().iterator();
2220         while (iterator.hasNext())
2221         {
2222            Part part = (Part)iterator.next();
2223            if (part != null)
2224            {
2225               String JavaDoc dims = "";
2226               org.w3c.dom.Element JavaDoc element = null;
2227               if (part.getTypeName() != null)
2228               {
2229                  TypeEntry partType = getType(part.getTypeName());
2230                  if (partType.getDimensions().length() > 0)
2231                  {
2232                     dims = partType.getDimensions();
2233                     partType = partType.getRefType();
2234                  }
2235                  element = (org.w3c.dom.Element JavaDoc)partType.getNode();
2236               }
2237               else if (part.getElementName() != null)
2238               {
2239                  TypeEntry partElement = getElement(part.getElementName()).getRefType();
2240                  element = (org.w3c.dom.Element JavaDoc)partElement.getNode();
2241                  QName JavaDoc name = getInnerCollectionComponentQName(element);
2242                  if (name != null)
2243                  {
2244                     dims += "[]";
2245                     partElement = getType(name);
2246                     element = (org.w3c.dom.Element JavaDoc)partElement.getNode();
2247                  }
2248                  else
2249                  {
2250                     name = getInnerTypeQName(element);
2251                     if (name != null)
2252                     {
2253                        partElement = getType(name);
2254                        element = (org.w3c.dom.Element JavaDoc)partElement.getNode();
2255                     }
2256                  }
2257               }
2258               if (element != null)
2259               {
2260                  org.w3c.dom.Element JavaDoc e = (org.w3c.dom.Element JavaDoc)XMLUtils.findNode(element, new QName JavaDoc(Constants.URI_DIME_CONTENT, "mediaType"));
2261                  if (e != null)
2262                  {
2263                     String JavaDoc value = e.getAttribute("value");
2264                     bEntry.setOperationDIME(operation.getName());
2265                     bEntry.setMIMEInfo(operation.getName(), part.getName(), value, dims);
2266                  }
2267               }
2268            }
2269         }
2270      }
2271   }
2272
2273   /**
2274    * Get the faults from the soap:fault clause.
2275    */

2276   private void faultsFromSOAPFault(Binding binding, BindingOperation bindOp,
2277                                    Operation operation, ArrayList JavaDoc faults) throws IOException JavaDoc
2278   {
2279      Iterator JavaDoc faultMapIter = bindOp.getBindingFaults().values().iterator();
2280      for (; faultMapIter.hasNext();)
2281      {
2282         BindingFault bFault = (BindingFault)faultMapIter.next();
2283
2284         // Set default entry for this fault
2285
String JavaDoc faultName = bFault.getName();
2286
2287         // Check to make sure this fault is named
2288
if (faultName == null || faultName.length() == 0)
2289         {
2290            throw new IOException JavaDoc(Messages.getMessage("unNamedFault00",
2291                    bindOp.getName(),
2292                    binding.getQName().toString()));
2293         }
2294
2295         boolean foundSOAPFault = false;
2296         String JavaDoc soapFaultUse = "";
2297         String JavaDoc soapFaultNamespace = "";
2298
2299         Iterator JavaDoc faultIter = bFault.getExtensibilityElements().iterator();
2300         for (; faultIter.hasNext();)
2301         {
2302            Object JavaDoc obj = faultIter.next();
2303            if (obj instanceof SOAPFault)
2304            {
2305               foundSOAPFault = true;
2306               soapFaultUse = ((SOAPFault)obj).getUse();
2307               soapFaultNamespace = ((SOAPFault)obj).getNamespaceURI();
2308               break;
2309            }
2310            else if (obj instanceof UnknownExtensibilityElement)
2311            {
2312               //TODO: After WSDL4J supports soap12, change this code
2313
UnknownExtensibilityElement unkElement = (UnknownExtensibilityElement)obj;
2314               QName JavaDoc name = unkElement.getElementType();
2315               if (name.getNamespaceURI().equals(Constants.URI_WSDL12_SOAP) &&
2316                       name.getLocalPart().equals("fault"))
2317               {
2318                  if (unkElement.getElement().getAttribute("use") != null)
2319                  {
2320                     soapFaultUse = unkElement.getElement().getAttribute("use");
2321                  }
2322                  if (unkElement.getElement().getAttribute("namespace") != null)
2323                  {
2324                     soapFaultNamespace = unkElement.getElement().getAttribute("namespace");
2325                  }
2326               }
2327            }
2328         }
2329
2330         // Check to make sure we have a soap:fault element
2331
if (!foundSOAPFault)
2332         {
2333            throw new IOException JavaDoc(Messages.getMessage("missingSoapFault00",
2334                    faultName,
2335                    bindOp.getName(),
2336                    binding.getQName().toString()));
2337         }
2338
2339         // TODO error checking:
2340
// if use=literal, no use of namespace on the soap:fault
2341
// if use=encoded, no use of element on the part
2342

2343         // Check this fault to make sure it matches the one
2344
// in the matching portType Operation
2345
Fault opFault = operation.getFault(bFault.getName());
2346         if (opFault == null)
2347         {
2348            throw new IOException JavaDoc(Messages.getMessage("noPortTypeFault",
2349                    new String JavaDoc[]{bFault.getName(),
2350                                 bindOp.getName(),
2351                                 binding.getQName().toString()}));
2352         }
2353         // put the updated entry back in the map
2354
faults.add(new FaultInfo(opFault,
2355                 Use.getUse(soapFaultUse),
2356                 soapFaultNamespace,
2357                 this));
2358      }
2359   } // faultsFromSOAPFault
2360

2361   /**
2362    * Set the body type.
2363    */

2364   private void setBodyType(String JavaDoc use, BindingEntry bEntry,
2365                            Operation operation, boolean input)
2366   {
2367      if (use == null)
2368      {
2369         use = "literal"; // set by default
2370
}
2371      if (use.equalsIgnoreCase("literal"))
2372      {
2373         bEntry.setBodyType(operation, Use.LITERAL,
2374                 input);
2375      }
2376   } // setBodyType
2377

2378   /**
2379    * Add the parts that are really MIME types as MIME types.
2380    * A side effect is to return the body Type of the given
2381    * MIMEMultipartRelated object.
2382    */

2383   private Use addMIMETypes(BindingEntry bEntry, MIMEMultipartRelated mpr,
2384                            Operation op) throws IOException JavaDoc
2385   {
2386      Use bodyType = Use.ENCODED;
2387      List JavaDoc parts = mpr.getMIMEParts();
2388      Iterator JavaDoc i = parts.iterator();
2389      while (i.hasNext())
2390      {
2391         MIMEPart part = (MIMEPart)i.next();
2392         List JavaDoc elems = part.getExtensibilityElements();
2393         Iterator JavaDoc j = elems.iterator();
2394         while (j.hasNext())
2395         {
2396            Object JavaDoc obj = j.next();
2397            if (obj instanceof MIMEContent)
2398            {
2399               MIMEContent content = (MIMEContent)obj;
2400               TypeEntry typeEntry = findPart(op, content.getPart());
2401               String JavaDoc dims = typeEntry.getDimensions();
2402               if (dims.length() <= 0 && typeEntry.getRefType() != null)
2403               {
2404                  Node JavaDoc node = typeEntry.getRefType().getNode();
2405                  if (getInnerCollectionComponentQName(node) != null)
2406                     dims += "[]";
2407               }
2408               String JavaDoc type = content.getType();
2409               if (type == null || type.length() == 0)
2410                  type = "text/plain";
2411               bEntry.setMIMEInfo(op.getName(), content.getPart(), type, dims);
2412            }
2413            else if (obj instanceof SOAPBody)
2414            {
2415               String JavaDoc use = ((SOAPBody)obj).getUse();
2416               if (use == null)
2417               {
2418                  use = "literal";
2419               }
2420               if (use.equalsIgnoreCase("literal"))
2421               {
2422                  bodyType = Use.LITERAL;
2423               }
2424            }
2425            else if (obj instanceof UnknownExtensibilityElement)
2426            {
2427               //TODO: After WSDL4J supports soap12, change this code
2428
UnknownExtensibilityElement unkElement = (UnknownExtensibilityElement)obj;
2429               QName JavaDoc name = unkElement.getElementType();
2430               if (name.getNamespaceURI().equals(Constants.URI_WSDL12_SOAP) &&
2431                       name.getLocalPart().equals("body"))
2432               {
2433                  String JavaDoc use = unkElement.getElement().getAttribute("use");
2434                  if (use == null)
2435                  {
2436                     use = "literal";
2437                  }
2438                  if (use.equalsIgnoreCase("literal"))
2439                  {
2440                     bodyType = Use.LITERAL;
2441                  }
2442               }
2443            }
2444         }
2445      }
2446      return bodyType;
2447   } // addMIMETypes
2448

2449   private TypeEntry findPart(Operation operation, String JavaDoc partName)
2450   {
2451      Map parts = operation.getInput().getMessage().getParts();
2452      Iterator JavaDoc iterator = parts.values().iterator();
2453      TypeEntry part = findPart(iterator, partName);
2454
2455      if (part == null)
2456      {
2457         parts = operation.getOutput().getMessage().getParts();
2458         iterator = parts.values().iterator();
2459         part = findPart(iterator, partName);
2460      }
2461      return part;
2462   }
2463
2464   private TypeEntry findPart(Iterator JavaDoc iterator, String JavaDoc partName)
2465   {
2466      while (iterator.hasNext())
2467      {
2468         Part part = (Part)iterator.next();
2469         if (part != null)
2470         {
2471            String JavaDoc typeName = part.getName();
2472            if (partName.equals(typeName))
2473            {
2474               if (part.getTypeName() != null)
2475               {
2476                  return getType(part.getTypeName());
2477               }
2478               else if (part.getElementName() != null)
2479               {
2480                  return getElement(part.getElementName());
2481               }
2482            }
2483         }
2484      }
2485      return null;
2486   }
2487
2488   /**
2489    * Populate the symbol table with all of the ServiceEntry's from the Definition.
2490    */

2491   private void populateServices(Definition def) throws IOException JavaDoc
2492   {
2493      Iterator JavaDoc i = def.getServices().values().iterator();
2494      while (i.hasNext())
2495      {
2496         Service service = (Service)i.next();
2497
2498         // do a bit of name validation
2499
if (service.getQName() == null ||
2500                 service.getQName().getLocalPart() == null ||
2501                 service.getQName().getLocalPart().equals(""))
2502         {
2503            throw new IOException JavaDoc(Messages.getMessage("BadServiceName00"));
2504         }
2505
2506         ServiceEntry sEntry = new ServiceEntry(service);
2507         symbolTablePut(sEntry);
2508         populatePorts(service.getPorts());
2509      }
2510   } // populateServices
2511

2512
2513   /**
2514    * populates the symbol table with port elements defined within a &lt;service&gt;
2515    * element.
2516    *
2517    * @param ports a map of name->port pairs (i.e. what is returned by service.getPorts()
2518    * @throws IOException thrown, if an IO or WSDL error is detected
2519    * @see javax.wsdl.Service#getPorts()
2520    * @see javax.wsdl.Port
2521    */

2522   private void populatePorts(Map ports) throws IOException JavaDoc
2523   {
2524      if (ports == null) return;
2525      Iterator JavaDoc it = ports.values().iterator();
2526      while (it.hasNext())
2527      {
2528
2529         Port port = (Port)it.next();
2530         String JavaDoc portName = port.getName();
2531         Binding portBinding = port.getBinding();
2532
2533         // make sure there is a port name. The 'name' attribute for WSDL ports is
2534
// mandatory
2535
//
2536
if (portName == null)
2537         {
2538            //REMIND: should rather be a javax.wsdl.WSDLException ?
2539
throw new IOException JavaDoc(Messages.getMessage("missingPortNameException"));
2540         }
2541
2542         // make sure there is a binding for the port. The 'binding' attribute for
2543
// WSDL ports is mandatory
2544
//
2545
if (portBinding == null)
2546         {
2547            //REMIND: should rather be a javax.wsdl.WSDLException ?
2548
throw new IOException JavaDoc(Messages.getMessage("missingBindingException"));
2549         }
2550
2551         // make sure the port name is unique among all port names defined in this
2552
// WSDL document.
2553
//
2554
// NOTE: there's a flaw in com.ibm.wsdl.xml.WSDLReaderImpl#parsePort() and
2555
// com.ibm.wsdl.xml.WSDLReaderImpl#addPort(). These methods do not enforce
2556
// the port name exists and is unique. Actually, if two port definitions with
2557
// the same name exist within the same service element, only *one* port
2558
// element is present after parsing and the following exception is not thrown.
2559
//
2560
// If two ports with the same name exist in different service elements,
2561
// the exception below is thrown. This is conformant to the WSDL 1.1 spec (sec 2.6)
2562
// , which states: "The name attribute provides a unique name among all ports
2563
// defined within in the enclosing WSDL document."
2564
//
2565
//
2566
if (existsPortWithName(new QName JavaDoc(portName)))
2567         {
2568            //REMIND: should rather be a javax.wsdl.WSDLException ?
2569
throw new IOException JavaDoc(Messages.getMessage("twoPortsWithSameName", portName));
2570         }
2571         PortEntry portEntry = new PortEntry(port);
2572         symbolTablePut(portEntry);
2573      }
2574   }
2575
2576   /**
2577    * Set each SymTabEntry's isReferenced flag. The default is false. If no other symbol
2578    * references this symbol, then leave it false, otherwise set it to true.
2579    * (An exception to the rule is that derived types are set as referenced if
2580    * their base type is referenced. This is necessary to support generation and
2581    * registration of derived types.)
2582    */

2583   private void setReferences(Definition def, Document JavaDoc doc)
2584   {
2585      Map stuff = def.getServices();
2586      if (stuff.isEmpty())
2587      {
2588         stuff = def.getBindings();
2589         if (stuff.isEmpty())
2590         {
2591            stuff = def.getPortTypes();
2592            if (stuff.isEmpty())
2593            {
2594               stuff = def.getMessages();
2595               if (stuff.isEmpty())
2596               {
2597                  for (Iterator JavaDoc i = elementTypeEntries.values().iterator();
2598                       i.hasNext();)
2599                  {
2600                     setTypeReferences((TypeEntry)i.next(), doc, false);
2601                  }
2602                  for (Iterator JavaDoc i = typeTypeEntries.values().iterator();
2603                       i.hasNext();)
2604                  {
2605                     setTypeReferences((TypeEntry)i.next(), doc, false);
2606                  }
2607               }
2608               else
2609               {
2610                  Iterator JavaDoc i = stuff.values().iterator();
2611                  while (i.hasNext())
2612                  {
2613                     Message message = (Message)i.next();
2614                     MessageEntry mEntry =
2615                             getMessageEntry(message.getQName());
2616                     setMessageReferences(mEntry, def, doc, false);
2617                  }
2618               }
2619            }
2620            else
2621            {
2622               Iterator JavaDoc i = stuff.values().iterator();
2623               while (i.hasNext())
2624               {
2625                  PortType portType = (PortType)i.next();
2626                  PortTypeEntry ptEntry =
2627                          getPortTypeEntry(portType.getQName());
2628                  setPortTypeReferences(ptEntry, null, def, doc);
2629               }
2630            }
2631         }
2632         else
2633         {
2634            Iterator JavaDoc i = stuff.values().iterator();
2635            while (i.hasNext())
2636            {
2637               Binding binding = (Binding)i.next();
2638               BindingEntry bEntry = getBindingEntry(binding.getQName());
2639               setBindingReferences(bEntry, def, doc);
2640            }
2641         }
2642      }
2643      else
2644      {
2645         Iterator JavaDoc i = stuff.values().iterator();
2646         while (i.hasNext())
2647         {
2648            Service service = (Service)i.next();
2649            ServiceEntry sEntry = getServiceEntry(service.getQName());
2650            setServiceReferences(sEntry, def, doc);
2651         }
2652      }
2653   } // setReferences
2654

2655   /**
2656    * Set the isReferenced flag to true on the given TypeEntry and all
2657    * SymTabEntries that it refers to.
2658    */

2659   private void setTypeReferences(TypeEntry entry, Document JavaDoc doc,
2660                                  boolean literal)
2661   {
2662
2663      // Check to see if already processed.
2664
if ((entry.isReferenced() && !literal) ||
2665              (entry.isOnlyLiteralReferenced() && literal))
2666      {
2667         return;
2668      }
2669
2670      if (wrapped)
2671      {
2672         // If this type is ONLY referenced from a literal usage in a binding,
2673
// then isOnlyLiteralReferenced should return true.
2674
if (!entry.isReferenced() && literal)
2675         {
2676            entry.setOnlyLiteralReference(true);
2677         }
2678         // If this type was previously only referenced as a literal type,
2679
// but now it is referenced in a non-literal manner, turn off the
2680
// onlyLiteralReference flag.
2681
else if (entry.isOnlyLiteralReferenced() && !literal)
2682         {
2683            entry.setOnlyLiteralReference(false);
2684         }
2685      }
2686
2687
2688      // If we don't want to emit stuff from imported files, only set the
2689
// isReferenced flag if this entry exists in the immediate WSDL file.
2690
Node JavaDoc node = entry.getNode();
2691      if (addImports || node == null || node.getOwnerDocument() == doc)
2692      {
2693         entry.setIsReferenced(true);
2694         if (entry instanceof DefinedElement)
2695         {
2696            BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
2697            QName JavaDoc referentName = Utils.getTypeQName(node, forElement, false);
2698            if (referentName != null)
2699            {
2700               TypeEntry referent = getTypeEntry(referentName, forElement.value);
2701               if (referent != null)
2702               {
2703                  setTypeReferences(referent, doc, literal);
2704               }
2705            }
2706            // If the Defined Element has an anonymous type,
2707
// process it with the current literal flag setting.
2708
QName JavaDoc anonQName = SchemaUtils.getElementAnonQName(entry.getNode());
2709            if (anonQName != null)
2710            {
2711               TypeEntry anonType = getType(anonQName);
2712               if (anonType != null)
2713               {
2714                  setTypeReferences(anonType, doc, literal);
2715                  return;
2716               }
2717            }
2718         }
2719      }
2720
2721      HashSet nestedTypes = Utils.getNestedTypes(entry, this, true);
2722      Iterator JavaDoc it = nestedTypes.iterator();
2723      while (it.hasNext())
2724      {
2725         TypeEntry nestedType = (TypeEntry)it.next();
2726         if (!nestedType.isReferenced())
2727         {
2728            //setTypeReferences(nestedType, doc, literal);
2729
if (nestedType != entry)
2730               setTypeReferences(nestedType, doc, false);
2731         }
2732      }
2733   } // setTypeReferences
2734

2735   /**
2736    * Set the isReferenced flag to true on the given MessageEntry and all
2737    * SymTabEntries that it refers to.
2738    */

2739   private void setMessageReferences(MessageEntry entry, Definition def, Document JavaDoc doc, boolean literal)
2740   {
2741      // If we don't want to emit stuff from imported files, only set the
2742
// isReferenced flag if this entry exists in the immediate WSDL file.
2743
Message message = entry.getMessage();
2744      if (addImports)
2745      {
2746         entry.setIsReferenced(true);
2747      }
2748      else
2749      {
2750         // NOTE: I thought I could have simply done:
2751
// if (def.getMessage(message.getQName()) != null)
2752
// but that method traces through all imported messages.
2753
Map messages = def.getMessages();
2754         if (messages.containsValue(message))
2755         {
2756            entry.setIsReferenced(true);
2757         }
2758      }
2759
2760      // Set all the message's types
2761
Iterator JavaDoc parts = message.getParts().values().iterator();
2762      while (parts.hasNext())
2763      {
2764         Part part = (Part)parts.next();
2765         TypeEntry type = getType(part.getTypeName());
2766         if (type != null)
2767         {
2768            setTypeReferences(type, doc, literal);
2769         }
2770         type = getElement(part.getElementName());
2771         if (type != null)
2772         {
2773            setTypeReferences(type, doc, literal);
2774            TypeEntry refType = type.getRefType();
2775            if (refType != null)
2776            {
2777               setTypeReferences(refType, doc, literal);
2778            }
2779         }
2780      }
2781   } // setMessageReference
2782

2783   /**
2784    * Set the isReferenced flag to true on the given PortTypeEntry and all
2785    * SymTabEntries that it refers to.
2786    */

2787   private void setPortTypeReferences(PortTypeEntry entry, BindingEntry bEntry,
2788                                      Definition def, Document JavaDoc doc)
2789   {
2790      // If we don't want to emit stuff from imported files, only set the
2791
// isReferenced flag if this entry exists in the immediate WSDL file.
2792
PortType portType = entry.getPortType();
2793      if (addImports)
2794      {
2795         entry.setIsReferenced(true);
2796      }
2797      else
2798      {
2799         // NOTE: I thought I could have simply done:
2800
// if (def.getPortType(portType.getQName()) != null)
2801
// but that method traces through all imported portTypes.
2802
Map portTypes = def.getPortTypes();
2803         if (portTypes.containsValue(portType))
2804         {
2805            entry.setIsReferenced(true);
2806         }
2807      }
2808
2809      // Set all the portType's messages
2810
Iterator JavaDoc operations = portType.getOperations().iterator();
2811
2812      // For each operation, query its input, output, and fault messages
2813
while (operations.hasNext())
2814      {
2815         Operation operation = (Operation)operations.next();
2816
2817         Input input = operation.getInput();
2818         Output output = operation.getOutput();
2819
2820         // Find out if this reference is a literal reference or not.
2821
boolean literalInput = false;
2822         boolean literalOutput = false;
2823         if (bEntry != null)
2824         {
2825            literalInput = bEntry.getInputBodyType(operation) ==
2826                    Use.LITERAL;
2827            literalOutput = bEntry.getOutputBodyType(operation) ==
2828                    Use.LITERAL;
2829         }
2830
2831         // Query the input message
2832
if (input != null)
2833         {
2834            Message message = input.getMessage();
2835            if (message != null)
2836            {
2837               MessageEntry mEntry = getMessageEntry(message.getQName());
2838               if (mEntry != null)
2839               {
2840                  setMessageReferences(mEntry, def, doc, literalInput);
2841               }
2842            }
2843         }
2844
2845         // Query the output message
2846
if (output != null)
2847         {
2848            Message message = output.getMessage();
2849            if (message != null)
2850            {
2851               MessageEntry mEntry = getMessageEntry(message.getQName());
2852               if (mEntry != null)
2853               {
2854                  setMessageReferences(mEntry, def, doc, literalOutput);
2855               }
2856            }
2857         }
2858
2859         // Query the fault messages
2860
Iterator JavaDoc faults =
2861                 operation.getFaults().values().iterator();
2862         while (faults.hasNext())
2863         {
2864            Message message = ((Fault)faults.next()).getMessage();
2865            if (message != null)
2866            {
2867               MessageEntry mEntry = getMessageEntry(message.getQName());
2868               if (mEntry != null)
2869               {
2870                  setMessageReferences(mEntry, def, doc, false);
2871               }
2872            }
2873         }
2874      }
2875   } // setPortTypeReferences
2876

2877   /**
2878    * Set the isReferenced flag to true on the given BindingEntry and all
2879    * SymTabEntries that it refers to ONLY if this binding is a SOAP binding.
2880    */

2881   private void setBindingReferences(BindingEntry entry, Definition def, Document JavaDoc doc)
2882   {
2883
2884      if (entry.getBindingType() == BindingEntry.TYPE_SOAP)
2885      {
2886         // If we don't want to emit stuff from imported files, only set the
2887
// isReferenced flag if this entry exists in the immediate WSDL file.
2888
Binding binding = entry.getBinding();
2889         if (addImports)
2890         {
2891            entry.setIsReferenced(true);
2892         }
2893         else
2894         {
2895            // NOTE: I thought I could have simply done:
2896
// if (def.getBindng(binding.getQName()) != null)
2897
// but that method traces through all imported bindings.
2898
Map bindings = def.getBindings();
2899            if (bindings.containsValue(binding))
2900            {
2901               entry.setIsReferenced(true);
2902            }
2903         }
2904
2905         // Set all the binding's portTypes
2906
PortType portType = binding.getPortType();
2907         PortTypeEntry ptEntry = getPortTypeEntry(portType.getQName());
2908         if (ptEntry != null)
2909         {
2910            setPortTypeReferences(ptEntry, entry, def, doc);
2911         }
2912      }
2913   } // setBindingReferences
2914

2915   /**
2916    * Set the isReferenced flag to true on the given ServiceEntry and all
2917    * SymTabEntries that it refers to.
2918    */

2919   private void setServiceReferences(ServiceEntry entry, Definition def, Document JavaDoc doc)
2920   {
2921      // If we don't want to emit stuff from imported files, only set the
2922
// isReferenced flag if this entry exists in the immediate WSDL file.
2923
Service service = entry.getService();
2924      if (addImports)
2925      {
2926         entry.setIsReferenced(true);
2927      }
2928      else
2929      {
2930         // NOTE: I thought I could have simply done:
2931
// if (def.getService(service.getQName()) != null)
2932
// but that method traces through all imported services.
2933
Map services = def.getServices();
2934         if (services.containsValue(service))
2935         {
2936            entry.setIsReferenced(true);
2937         }
2938      }
2939
2940      // Set all the service's bindings
2941
Iterator JavaDoc ports = service.getPorts().values().iterator();
2942      while (ports.hasNext())
2943      {
2944         Port port = (Port)ports.next();
2945         Binding binding = port.getBinding();
2946         if (binding != null)
2947         {
2948            BindingEntry bEntry = getBindingEntry(binding.getQName());
2949            if (bEntry != null)
2950            {
2951               setBindingReferences(bEntry, def, doc);
2952            }
2953         }
2954      }
2955   } // setServiceReferences
2956

2957   /**
2958    * Put the given SymTabEntry into the symbol table, if appropriate.
2959    */

2960   private void symbolTablePut(SymTabEntry entry) throws IOException JavaDoc
2961   {
2962      QName JavaDoc name = entry.getQName();
2963      if (get(name, entry.getClass()) == null)
2964      {
2965         // An entry of the given qname of the given type doesn't exist yet.
2966
if (entry instanceof Type &&
2967                 get(name, UndefinedType.class) != null)
2968         {
2969
2970            // A undefined type exists in the symbol table, which means
2971
// that the type is used, but we don't yet have a definition for
2972
// the type. Now we DO have a definition for the type, so
2973
// replace the existing undefined type with the real type.
2974

2975            if (((TypeEntry)get(name, UndefinedType.class)).isSimpleType() &&
2976                    !((TypeEntry)entry).isSimpleType())
2977            {
2978               // Problem if the undefined type was used in a
2979
// simple type context.
2980
throw new IOException JavaDoc(Messages.getMessage("AttrNotSimpleType01",
2981                       name.toString()));
2982
2983            }
2984            Vector JavaDoc v = (Vector JavaDoc)symbolTable.get(name);
2985            for (int i = 0; i < v.size(); ++i)
2986            {
2987               Object JavaDoc oldEntry = v.elementAt(i);
2988               if (oldEntry instanceof UndefinedType)
2989               {
2990
2991                  // Replace it in the symbol table
2992
v.setElementAt(entry, i);
2993
2994                  // Replace it in the types index
2995
typeTypeEntries.put(name, entry);
2996
2997                  // Update all of the entries that refer to the unknown type
2998
((UndefinedType)oldEntry).update((Type)entry);
2999               }
3000            }
3001         }
3002         else if (entry instanceof Element &&
3003                 get(name, UndefinedElement.class) != null)
3004         {
3005            // A undefined element exists in the symbol table, which means
3006
// that the element is used, but we don't yet have a definition for
3007
// the element. Now we DO have a definition for the element, so
3008
// replace the existing undefined element with the real element.
3009
Vector JavaDoc v = (Vector JavaDoc)symbolTable.get(name);
3010            for (int i = 0; i < v.size(); ++i)
3011            {
3012               Object JavaDoc oldEntry = v.elementAt(i);
3013               if (oldEntry instanceof UndefinedElement)
3014               {
3015
3016                  // Replace it in the symbol table
3017
v.setElementAt(entry, i);
3018
3019                  // Replace it in the elements index
3020
elementTypeEntries.put(name, entry);
3021
3022                  // Update all of the entries that refer to the unknown type
3023
((Undefined)oldEntry).update((Element)entry);
3024               }
3025            }
3026         }
3027         else
3028         {
3029            // Add this entry to the symbol table
3030
Vector JavaDoc v = (Vector JavaDoc)symbolTable.get(name);
3031            if (v == null)
3032            {
3033               v = new Vector JavaDoc();
3034               symbolTable.put(name, v);
3035            }
3036            v.add(entry);
3037            // add TypeEntries to specialized indices for
3038
// fast lookups during reference resolution.
3039
if (entry instanceof Element)
3040            {
3041               elementTypeEntries.put(name, entry);
3042            }
3043            else if (entry instanceof Type)
3044            {
3045               typeTypeEntries.put(name, entry);
3046            }
3047         }
3048      }
3049      else
3050      {
3051         System.out.println(Messages.getMessage("alreadyExists00", "" + name));
3052      }
3053   } // symbolTablePut
3054

3055
3056   /**
3057    * checks whether there exists a WSDL port with a given name in the current
3058    * symbol table
3059    *
3060    * @param name the QName of the port. Note: only the local part of the qname is relevant,
3061    * since port names are not qualified with a namespace. They are of type nmtoken in WSDL 1.1
3062    * and of type ncname in WSDL 1.2
3063    * @return true, if there is a port element with the specified name; false, otherwise
3064    */

3065   protected boolean existsPortWithName(QName JavaDoc name)
3066   {
3067      Vector JavaDoc v = (Vector JavaDoc)symbolTable.get(name);
3068      if (v == null) return false;
3069      Iterator JavaDoc it = v.iterator();
3070      while (it.hasNext())
3071      {
3072         Object JavaDoc o = it.next();
3073         if (o instanceof PortEntry) return true;
3074      }
3075      return false;
3076   }
3077
3078
3079   private static QName JavaDoc getInnerCollectionComponentQName(Node JavaDoc node)
3080   {
3081      if (node == null)
3082      {
3083         return null;
3084      }
3085
3086      QName JavaDoc name = SchemaUtils.getCollectionComponentQName(node);
3087      if (name != null)
3088         return name;
3089
3090      // Dive into the node if necessary
3091
NodeList JavaDoc children = node.getChildNodes();
3092      for (int i = 0; i < children.getLength(); i++)
3093      {
3094         name = getInnerCollectionComponentQName(children.item(i));
3095         if (name != null)
3096            return name;
3097      }
3098      return null;
3099   }
3100
3101   private static QName JavaDoc getInnerTypeQName(Node JavaDoc node)
3102   {
3103      if (node == null)
3104      {
3105         return null;
3106      }
3107
3108      BooleanHolder JavaDoc forElement = new BooleanHolder JavaDoc();
3109      QName JavaDoc name = Utils.getTypeQName(node, forElement, true);
3110      if (name != null)
3111         return name;
3112
3113      // Dive into the node if necessary
3114
NodeList JavaDoc children = node.getChildNodes();
3115      for (int i = 0; i < children.getLength(); i++)
3116      {
3117         name = getInnerTypeQName(children.item(i));
3118         if (name != null)
3119            return name;
3120      }
3121      return null;
3122   }
3123
3124} // class SymbolTable
3125
Popular Tags