Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/axis/wsdl/symbolTable/TypeEntry.java


1   /*
2    * Copyright 2001-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.axis.wsdl.symbolTable;
17  
18  import org.apache.axis.utils.Messages;
19  import org.w3c.dom.Node;
20  
21  import javax.xml.namespace.QName;
22  import java.io.IOException;
23  import java.io.Serializable;
24  import java.util.HashSet;
25  import java.util.Vector;
26  
27  /**
28   * This class represents a wsdl types entry that is supported by the WSDL2Java emitter.
29   * A TypeEntry has a QName representing its XML name and a name, which in the
30   * WSDL2Java back end is its full java name.  The TypeEntry may also have a Node,
31   * which locates the definition of the emit type in the xml.
32   * A TypeEntry object extends SymTabEntry and is built by the SymbolTable class for
33   * each supported root complexType, simpleType, and elements that are
34   * defined or encountered.
35   * <p/>
36   * SymTabEntry
37   * |
38   * TypeEntry
39   * /           \
40   * Type                Element
41   * |                     |
42   * (BaseType,                    (DefinedElement,
43   * CollectionType                CollectionElement,
44   * DefinedType,                  UndefinedElement)
45   * UndefinedType)
46   * <p/>
47   * UndefinedType and UndefinedElement are placeholders when the real type or element
48   * is not encountered yet.  Both of these implement the Undefined interface.
49   * <p/>
50   * A TypeEntry whose java (or other language) name depends on an Undefined type, will
51   * have its name initialization deferred until the Undefined type is replaced with
52   * a defined type.  The updateUndefined() method is invoked by the UndefinedDelegate to
53   * update the information.
54   * <p/>
55   * Each TypeEntry whose language name depends on another TypeEntry will have the refType
56   * field set.  For example:
57   * <element name="foo" type="bar" />
58   * The TypeEntry for "foo" will have a refType set to the TypeEntry of "bar".
59   * <p/>
60   * Another Example:
61   * <xsd:complexType name="hobbyArray">
62   * <xsd:complexContent>
63   * <xsd:restriction base="soapenc:Array">
64   * <xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
65   * </xsd:restriction>
66   * </xsd:complexContent>
67   * </xsd:complexType>
68   * The TypeEntry for "hobbyArray" will have a refType that locates the TypeEntry for xsd:string
69   * and the dims field will be "[]"
70   * 
71   * @author Rich Scheuerle  (scheu@us.ibm.com)
72   */
73  public abstract class TypeEntry extends SymTabEntry implements Serializable {
74  
75      /** Field node */
76      protected Node node;                               // Node
77  
78      /** Field refType */
79      protected TypeEntry refType;                       // Some TypeEntries refer to other types.
80  
81      /** Field dims */
82      protected String dims = "";                        // If refType is an element, dims indicates
83  
84                                                         // the array dims (for example "[]").
85  
86      protected boolean underlTypeNillable = false;      // if this is an array, underlTypeNillable indicates 
87                                                         // whether the underlying type of the array is nillable.
88  
89      protected QName componentType = null;              // If this is an array, the component type
90  
91      /** If this TypeEntry represents an array with elements inside a "wrapper"
92       * this field can optionally change the inner QName (default is <item>).
93       */
94      protected QName itemQName = null;
95  
96      /** Field undefined */
97      protected boolean undefined;                       // If refType is an Undefined type
98  
99      // (or has a refType that is Undefined)
100     // then the undefined flag is set.
101     // The name cannot be determined
102     // until the Undefined type is found.
103 
104     /** Field isBaseType */
105     protected boolean isBaseType;                      // Indicates if represented by a
106 
107     // primitive or util class
108 
109     /** Field isSimpleType */
110     protected boolean isSimpleType =
111             false;                                         // Indicates if this type is a simple type
112 
113     /** Field onlyLiteralReference */
114     protected boolean onlyLiteralReference = false;    // Indicates
115     
116     /** Field types */
117     protected HashSet types = null;
118     
119     /** contained elements in the schema's type definition */
120     protected Vector containedElements;
121 
122     /** contained attributes in the schema's type definition */
123     protected Vector containedAttributes;
124 
125     // whether this type is only referenced
126     // via a binding's literal use.
127 
128     /**
129      * Create a TypeEntry object for an xml construct that references another type.
130      * Defer processing until refType is known.
131      * 
132      * @param pqName  
133      * @param refType 
134      * @param pNode   
135      * @param dims    
136      */
137     protected TypeEntry(QName pqName, TypeEntry refType, Node pNode,
138                         String dims) {
139 
140         super(pqName);
141 
142         node = pNode;
143         this.undefined = refType.undefined;
144         this.refType = refType;
145 
146         if (dims == null) {
147             dims = "";
148         }
149 
150         this.dims = dims;
151 
152         if (refType.undefined) {
153 
154             // Need to defer processing until known.
155             TypeEntry uType = refType;
156 
157             while (!(uType instanceof Undefined)) {
158                 uType = uType.refType;
159             }
160 
161             ((Undefined) uType).register(this);
162         } else {
163             isBaseType = (refType.isBaseType && refType.dims.equals("")
164                     && dims.equals(""));
165         }
166     }
167 
168     /**
169      * Create a TypeEntry object for an xml construct that is not a base type
170      * 
171      * @param pqName 
172      * @param pNode  
173      */
174     protected TypeEntry(QName pqName, Node pNode) {
175 
176         super(pqName);
177 
178         node = pNode;
179         refType = null;
180         undefined = false;
181         dims = "";
182         isBaseType = false;
183     }
184 
185     /**
186      * Create a TypeEntry object for an xml construct name that represents a base type
187      * 
188      * @param pqName 
189      */
190     protected TypeEntry(QName pqName) {
191 
192         super(pqName);
193 
194         node = null;
195         undefined = false;
196         dims = "";
197         isBaseType = true;
198     }
199 
200     /**
201      * Query the node for this type.
202      * 
203      * @return 
204      */
205     public Node getNode() {
206         return node;
207     }
208 
209     /**
210      * Returns the Base Type Name.
211      * For example if the Type represents a schema integer, "int" is returned.
212      * If this is a user defined type, null is returned.
213      * 
214      * @return 
215      */
216     public String getBaseType() {
217 
218         if (isBaseType) {
219             return name;
220         } else {
221             return null;
222         }
223     }
224 
225     /**
226      * Method isBaseType
227      * 
228      * @return 
229      */
230     public boolean isBaseType() {
231         return isBaseType;
232     }
233 
234     /**
235      * Method setBaseType
236      * 
237      * @param baseType 
238      */
239     public void setBaseType(boolean baseType) {
240         isBaseType = baseType;
241     }
242     
243     /**
244      * Method isSimpleType
245      * 
246      * @return 
247      */
248     public boolean isSimpleType() {
249         return isSimpleType;
250     }
251 
252     /**
253      * Method setSimpleType
254      * 
255      * @param simpleType 
256      */
257     public void setSimpleType(boolean simpleType) {
258         isSimpleType = simpleType;
259     }
260 
261     /**
262      * Is this type references ONLY as a literal type?  If a binding's
263      * message's soapBody says:  use="literal", then a type is referenced
264      * literally.  Note that that type's contained types (ie., an address
265      * contains a phone#) are not referenced literally.  Since a type
266      * that is ONLY referenced as a literal may cause a generator to act
267      * differently (like WSDL2Java), this extra reference distinction is
268      * needed.
269      * 
270      * @return 
271      */
272     public boolean isOnlyLiteralReferenced() {
273         return onlyLiteralReference;
274     }    // isOnlyLiteralReferenced
275 
276     /**
277      * Set the isOnlyLiteralReference flag.
278      * 
279      * @param set 
280      */
281     public void setOnlyLiteralReference(boolean set) {
282         onlyLiteralReference = set;
283     }    // setOnlyLiteralRefeerence
284 
285     /**
286      * getUndefinedTypeRef returns the Undefined TypeEntry that this entry depends on or NULL.
287      * 
288      * @return 
289      */
290     protected TypeEntry getUndefinedTypeRef() {
291 
292         if (this instanceof Undefined) {
293             return this;
294         }
295 
296         if (undefined && (refType != null)) {
297             if (refType.undefined) {
298                 TypeEntry uType = refType;
299 
300                 while (!(uType instanceof Undefined)) {
301                     uType = uType.refType;
302                 }
303 
304                 return uType;
305             }
306         }
307 
308         return null;
309     }
310 
311     /**
312      * UpdateUndefined is called when the ref TypeEntry is finally known.
313      * 
314      * @param oldRef The TypeEntry representing the Undefined TypeEntry
315      * @param newRef The replacement TypeEntry
316      * @return true if TypeEntry is changed in any way.
317      * @throws IOException 
318      */
319     protected boolean updateUndefined(TypeEntry oldRef, TypeEntry newRef)
320             throws IOException {
321 
322         boolean changedState = false;
323 
324         // Replace refType with the new one if applicable
325         if (refType == oldRef) {
326             refType = newRef;
327             changedState = true;
328 
329             // Detect a loop
330             TypeEntry te = refType;
331 
332             while ((te != null) && (te != this)) {
333                 te = te.refType;
334             }
335 
336             if (te == this) {
337 
338                 // Detected a loop.
339                 undefined = false;
340                 isBaseType = false;
341                 node = null;
342 
343                 throw new IOException(
344                         Messages.getMessage(
345                                 "undefinedloop00", getQName().toString()));
346             }
347         }
348 
349         // Update information if refType is now defined
350         if ((refType != null) && undefined && (refType.undefined == false)) {
351             undefined = false;
352             changedState = true;
353             isBaseType = (refType.isBaseType && refType.dims.equals("")
354                     && dims.equals(""));
355         }
356 
357         return changedState;
358     }
359 
360     /**
361      * If this type references another type, return that type, otherwise return null.
362      * 
363      * @return 
364      */
365     public TypeEntry getRefType() {
366         return refType;
367     }    // getRefType
368 
369     /**
370      * Method setRefType
371      * 
372      * @param refType 
373      */
374     public void setRefType(TypeEntry refType) {
375         this.refType = refType;
376     }
377 
378     /**
379      * Return the dimensions of this type, which can be 0 or more "[]".
380      * 
381      * @return 
382      */
383     public String getDimensions() {
384         return dims;
385     }    // getDimensions
386 
387     /**
388      * Return whether the underlying type is nillable if this is an array type.
389      * @return true if it is an array and nillable
390      */
391     public boolean getUnderlTypeNillable() {
392       // refType could refer to array with underlying nillable
393       // type - set the underlTypeNillable to true if this is 
394       // the case.
395         if (!underlTypeNillable 
396             && !getDimensions().equals("")
397             && refType != null) {
398             underlTypeNillable = refType.getUnderlTypeNillable();
399       }
400       return underlTypeNillable;
401     }
402 
403     /**
404      * Set the boolean indicating whether underlying type of array is nillable.
405      */
406     public void setUnderlTypeNillable(boolean underlTypeNillable) {
407         this.underlTypeNillable = underlTypeNillable;
408     }
409 
410     /**
411      * Return the QName of the component if this is an array type
412      * @return QName of array elements or null
413      */
414     public QName getComponentType()
415     {
416         return componentType;
417     }
418 
419     /**
420      * Set the QName of the component if this is an array type
421      */ 
422     public void setComponentType(QName componentType)
423     {
424         this.componentType = componentType;
425     }
426 
427     public QName getItemQName() {
428         return itemQName;
429     }
430 
431     public void setItemQName(QName itemQName) {
432         this.itemQName = itemQName;
433     }
434 
435     /**
436      * Get string representation.
437      * 
438      * @return 
439      */
440     public String toString() {
441         return toString("");
442     }
443 
444     /**
445      * Get string representation with indentation
446      * 
447      * @param indent 
448      * @return 
449      */
450     protected String toString(String indent) {
451 
452         String refString = indent + "RefType:       null \n";
453 
454         if (refType != null) {
455             refString = indent + "RefType:\n" + refType.toString(indent + "  ")
456                     + "\n";
457         }
458 
459         return super.toString(indent) 
460                 + indent + "Class:         " + this.getClass().getName() + "\n" 
461                 + indent + "Base?:         " + isBaseType + "\n" 
462                 + indent + "Undefined?:    " + undefined + "\n" 
463                 + indent + "isSimpleType?  " + isSimpleType + "\n"
464                 + indent + "Node:          " + getNode() + "\n" 
465                 + indent + "Dims:          " + dims + "\n"              
466                 + indent + "isOnlyLiteralReferenced: " + onlyLiteralReference + "\n"
467                 + refString;
468     }
469 
470     /**
471      * This method returns a set of all the nested types.
472      * Nested types are types declared within this TypeEntry (or descendents)
473      * plus any extended types and the extended type nested types
474      * The elements of the returned HashSet are Types.
475      * 
476      * @param symbolTable is the symbolTable
477      * @param derivedFlag should be set if all dependendent derived types should also be
478      *                    returned.
479      * @return 
480      */
481     public HashSet getNestedTypes(SymbolTable symbolTable,
482                                          boolean derivedFlag) {
483         if( types == null) {
484             types = Utils.getNestedTypes(this, symbolTable, derivedFlag);
485         }
486         return types;
487     }    // getNestedTypes
488 
489     /**
490      * @return Returns the containedAttributes.
491      */
492     public Vector getContainedAttributes() {
493         return containedAttributes;
494     }
495     /**
496      * @param containedAttributes The containedAttributes to set.
497      */
498     public void setContainedAttributes(Vector containedAttributes) {
499         this.containedAttributes = containedAttributes;
500     }
501     /**
502      * @return Returns the containedElements.
503      */
504     public Vector getContainedElements() {
505         return containedElements;
506     }
507     /**
508      * @param containedElements The containedElements to set.
509      */
510     public void setContainedElements(Vector containedElements) {
511         this.containedElements = containedElements;
512     }
513 }