View Javadoc

1   package org.codehaus.ivory.serialize;
2   
3   import java.lang.reflect.Modifier;
4   import java.util.List;
5   
6   import javax.xml.namespace.QName;
7   
8   import org.apache.axis.description.FieldDesc;
9   import org.apache.axis.description.TypeDesc;
10  import org.apache.axis.encoding.ser.BeanSerializer;
11  import org.apache.axis.utils.BeanPropertyDescriptor;
12  import org.apache.axis.wsdl.fromJava.Types;
13  import org.w3c.dom.Element;
14  
15  /***
16   * A BeanSerializer with metadata support.
17   * 
18   * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
19   * @since May 21, 2003
20   */
21  public class MetadataSerializer extends BeanSerializer
22  {
23      // Construct BeanSerializer for the indicated class/qname
24      public MetadataSerializer(Class javaType, QName xmlType)
25      {
26          this(javaType, xmlType, TypeDesc.getTypeDescForClass(javaType));
27      }
28  
29      // Construct BeanSerializer for the indicated class/qname
30      public MetadataSerializer(Class javaType, QName xmlType, TypeDesc typeDesc)
31      {
32          super(javaType, xmlType, typeDesc, null);
33  
34          if (typeDesc != null)
35          {
36              propertyDescriptor = typeDesc.getPropertyDescriptors();
37          }
38          else
39          {
40              propertyDescriptor = MetaBeanUtils.getPd(javaType, null);
41          }
42      }
43  
44      // Construct BeanSerializer for the indicated class/qname/propertyDesc
45      public MetadataSerializer(
46          Class javaType,
47          QName xmlType,
48          TypeDesc typeDesc,
49          BeanPropertyDescriptor[] propertyDescriptor)
50      {
51          super(javaType, xmlType, typeDesc, propertyDescriptor);
52      }
53  
54      /***
55       * Return XML schema for the specified type, suitable for insertion into
56       * the &lt;types&gt; element of a WSDL document, or underneath an
57       * &lt;element&gt; or &lt;attribute&gt; declaration.
58       *
59       * @param javaType the Java Class we're writing out schema for
60       * @param types the Java2WSDL Types object which holds the context
61       *              for the WSDL being generated.
62       * @return a type element containing a schema simpleType/complexType
63       * @see org.apache.axis.wsdl.fromJava.Types
64       */
65      /***
66       * Return XML schema for the specified type, suitable for insertion into
67       * the &lt;types&gt; element of a WSDL document, or underneath an
68       * &lt;element&gt; or &lt;attribute&gt; declaration.
69       *
70       * @param javaType the Java Class we're writing out schema for
71       * @param types the Java2WSDL Types object which holds the context
72       *              for the WSDL being generated.
73       * @return a type element containing a schema simpleType/complexType
74       * @see org.apache.axis.wsdl.fromJava.Types
75       */
76      public Element writeSchema(Class javaType, Types types) throws Exception {
77  
78          // ComplexType representation of bean class
79          Element complexType = types.createElement("complexType");
80  
81          // See if there is a super class, stop if we hit a stop class
82          Element e = null;
83          Class superClass = javaType.getSuperclass();
84          BeanPropertyDescriptor[] superPd = null;
85          List stopClasses = types.getStopClasses();
86          if (superClass != null &&
87                  superClass != java.lang.Object.class &&
88                  superClass != java.lang.Exception.class &&
89                  superClass != java.lang.Throwable.class &&
90                  superClass != java.rmi.RemoteException.class &&
91                  superClass != org.apache.axis.AxisFault.class &&
92                  (stopClasses == null ||
93                  !(stopClasses.contains(superClass.getName()))) ) {
94              // Write out the super class
95              String base = types.writeType(superClass);
96              Element complexContent = types.createElement("complexContent");
97              complexType.appendChild(complexContent);
98              Element extension = types.createElement("extension");
99              complexContent.appendChild(extension);
100             extension.setAttribute("base", base);
101             e = extension;
102             // Get the property descriptors for the super class
103             TypeDesc superTypeDesc = TypeDesc.getTypeDescForClass(superClass);
104             if (superTypeDesc != null) {
105                 superPd = superTypeDesc.getPropertyDescriptors();
106             } else {
107                 superPd = MetaBeanUtils.getPd(superClass, null);
108             }
109         } else {
110             e = complexType;
111         }
112 
113         // Add fields under sequence element.
114         // Note: In most situations it would be okay
115         // to put the fields under an all element.
116         // However it is illegal schema to put an
117         // element with minOccurs=0 or maxOccurs>1 underneath
118         // an all element.  This is the reason why a sequence
119         // element is used.
120         Element all = types.createElement("sequence");
121         e.appendChild(all);
122 
123         if (Modifier.isAbstract(javaType.getModifiers())) {
124             complexType.setAttribute("abstract", "true");
125         }
126 
127         // Serialize each property
128         for (int i=0; i<propertyDescriptor.length; i++) {
129             String propName = propertyDescriptor[i].getName();
130 
131             // Don't serializer properties named class
132             boolean writeProperty = true;
133             if (propName.equals("class")) {
134                 writeProperty = false;
135             }
136 
137             // Don't serialize the property if it is present
138             // in the super class property list
139             if (superPd != null && writeProperty) {
140                 for (int j=0; j<superPd.length && writeProperty; j++) {
141                     if (propName.equals(superPd[j].getName())) {
142                         writeProperty = false;
143                     }
144                 }
145             }
146             if (!writeProperty) {
147                 continue;
148             }
149 
150             Class fieldType = propertyDescriptor[i].getType();
151 
152             // If we have type metadata, check to see what we're doing
153             // with this field.  If it's an attribute, skip it.  If it's
154             // an element, use whatever qname is in there.  If we can't
155             // find any of this info, use the default.
156 
157             if (typeDesc != null) {
158                 FieldDesc field = typeDesc.getFieldByName(propName);
159 
160                 if (field != null) {
161                     QName qname = field.getXmlName();
162                     QName fieldXmlType = field.getXmlType();
163                     boolean isAnonymous = fieldXmlType != null && fieldXmlType.getLocalPart().startsWith(">");
164 
165                     if (qname != null) {
166                         // FIXME!
167                         // Check to see if this is in the right namespace -
168                         // if it's not, we need to use an <element ref="">
169                         // to represent it!!!
170 
171                         // Use the default...
172                         propName = qname.getLocalPart();
173                     }
174                     if (!field.isElement()) {
175                         writeAttribute(types,
176                                        propName,
177                                        fieldType,
178                                        fieldXmlType,
179                                        complexType);
180                     } else {
181                         writeField(types,
182                                    propName,
183                                    fieldXmlType,
184                                    fieldType,
185                                    propertyDescriptor[i].isIndexed(),
186                                    field.isMinOccursZero(),
187                                    all, isAnonymous);
188                     }
189                 } else {
190                     writeField(types,
191                                propName,
192                                null,
193                                fieldType,
194                                propertyDescriptor[i].isIndexed(), false, all, false);
195                 }
196             } else {
197                 writeField(types,
198                            propName,
199                            null,
200                            fieldType,
201                            propertyDescriptor[i].isIndexed(), false, all, false);
202             }
203         }
204 
205         // done
206         return complexType;
207     }
208 }