tomj 02/02/21 10:51:24
Modified: java/test/wsdl Wsdl2javaTestSuite.xml
java/src/org/apache/axis/wsdl/fromJava Types.java
java/src/org/apache/axis/wsdl/toJava SymbolTable.java
SchemaUtils.java JavaTypeWriter.java
JavaComplexTypeWriter.java
java/src/org/apache/axis/utils resources.properties
java/src/org/apache/axis/encoding/ser BeanSerializer.java
Log:
Support for <attribute> WSDL (required for interop tests).
WSDL2Java will generate bean fields for XML element attributes if specified
in the WSDL. It wil also generate a getAttributeElements() static function in
the bean that the bean serializer/deserializer uses. (The modifications to the
serialization code have already been committed.)
Sample:
public class AccessPoint implements java.io.Serializable {
private String element;
private String myAttribute; // attribute
...
public static java.util.Vector getAttributeElements() {
java.util.Vector v = new java.util.Vector();
v.add("myAttribute");
return v;
}
}
Java2WSDL will generate <attribute> in the type schema for beans that have
the getAttributeElements() method to id which fields should be attributes.
This involved moving the WSDL type generation for beans out of Java2WSDL
and in to the serializer itself.
TBD:
- we do not handle all forms of attributes and the UDDI WSDL in our test
suite is commented out (this WSDL uses LOTS of attributes).
- The generation of type Schema should live in the serializers for all types.
Currently only Map and Bean have this code.
- For command line Java2WSDL, type serializers are generally not registered,
so we default to the BeanSerializer for everything that isn't built in.
Revision Changes Path
1.77 +2 -0 xml-axis/java/test/wsdl/Wsdl2javaTestSuite.xml
Index: Wsdl2javaTestSuite.xml
===================================================================
RCS file: /home/cvs/xml-axis/java/test/wsdl/Wsdl2javaTestSuite.xml,v
retrieving revision 1.76
retrieving revision 1.77
diff -u -r1.76 -r1.77
--- Wsdl2javaTestSuite.xml 20 Feb 2002 20:41:14 -0000 1.76
+++ Wsdl2javaTestSuite.xml 21 Feb 2002 18:51:23 -0000 1.77
@@ -565,6 +565,7 @@
</wsdl2java>
<!-- UDDI 1.0 WSDL's -->
+<!-- tomj: turn these off while attribute processing is in flux
<wsdl2java url="http://www.uddi.org/wsdl/inquire_v1.wsdl"
output="build/work"
testcase="no"
@@ -585,6 +586,7 @@
<mapping namespace="urn:uddi-org:api" package="org.uddi.api"/>
<mapping namespace="urn:uddi-org:publication"
package="org.uddi.publication"/>
</wsdl2java>
+-->
<!-- XMethods Delayed Quote Service from
http://www.xmethods.net/detail.html?id=2 -->
<wsdl2java
url="http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl"
1.16 +43 -86 xml-axis/java/src/org/apache/axis/wsdl/fromJava/Types.java
Index: Types.java
===================================================================
RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/fromJava/Types.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- Types.java 8 Feb 2002 16:52:12 -0000 1.15
+++ Types.java 21 Feb 2002 18:51:23 -0000 1.16
@@ -57,10 +57,13 @@
package org.apache.axis.wsdl.fromJava;
import org.apache.axis.Constants;
+import org.apache.axis.AxisFault;
import org.apache.axis.encoding.TypeMapping;
import org.apache.axis.encoding.Serializer;
import org.apache.axis.encoding.SerializerFactory;
+import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.apache.axis.utils.XMLUtils;
+import org.apache.axis.utils.JavaUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
@@ -338,14 +341,7 @@
* @throws Exception
*/
public String writeType(Class type) throws Exception {
- Serializer ser = null;
- if (tm != null) {
- SerializerFactory factory = (SerializerFactory)tm.getSerializer(type);
- if (factory != null) {
- ser = (Serializer)factory.getSerializerAs(Constants.AXIS_SAX);
- }
- }
-
+
// Quick return if schema type
if (isSimpleSchemaType(type))
return Constants.NSPREFIX_SCHEMA_XSD + ":" +
@@ -354,7 +350,27 @@
return Constants.NSPREFIX_SOAP_ENC + ":" +
getTypeQName(type).getLocalPart();
- // Write the namespace
+ // look up the serializer in the TypeMappingRegistry
+ Serializer ser = null;
+ SerializerFactory factory = null;
+ if (tm != null) {
+ factory = (SerializerFactory)tm.getSerializer(type);
+ } else {
+ factory = (SerializerFactory)defaultTM.getSerializer(type);
+ }
+ if (factory == null) {
+ factory = new BeanSerializerFactory(type, getTypeQName(type));
+ }
+ if (factory != null) {
+ ser = (Serializer)factory.getSerializerAs(Constants.AXIS_SAX);
+ }
+
+ // if we can't get a serializer, that is bad.
+ if (ser == null)
+ throw new AxisFault(
+ JavaUtils.getMessage("NoSerializer00", type.getName()));
+
+ // Write the namespace
QName qName = writeTypeNamespace(type);
// If an array the component type should be processed first
@@ -397,10 +413,7 @@
if (isEnumClass(type)) {
writeEnumType(qName, type);
} else {
- if (ser != null)
- ser.writeSchema(this);
- else
- writeBeanClassType(qName, type);
+ ser.writeSchema(this);
}
}
return prefixedName;
@@ -508,83 +521,13 @@
}
/**
- * Write Bean Class Complex Type
- * @param qname QName of type.
- * @param type class of type
- */
- public void writeBeanClassType(javax.wsdl.QName qName, Class cls)
- throws Exception {
- // ComplexType representation of bean class
- Element complexType = docHolder.createElement("complexType");
- writeSchemaElement(qName, complexType);
- complexType.setAttribute("name", qName.getLocalPart());
-
- // See if there is a super class, stop if we hit a stop class
- Element e = null;
- Class superClass = cls.getSuperclass();
- if (superClass != null &&
- superClass != java.lang.Object.class &&
- (stopClasses == null ||
!stopClasses.contains(superClass.getName()))) {
- // Write out the super class
- String base = writeType(superClass);
- Element complexContent = docHolder.createElement("complexContent");
- complexType.appendChild(complexContent);
- Element extension = docHolder.createElement("extension");
- complexContent.appendChild(extension);
- extension.setAttribute("base", base);
- e = extension;
- } else {
- e = complexType;
- }
-
- // Add fields under all element
- Element all = docHolder.createElement("all");
- e.appendChild(all);
-
- // Build a ClassRep that represents the bean class. This
- // allows users to provide their own field mapping.
- ClassRep clsRep = beanBuilder.build(cls);
-
- // Write out fields
- Vector fields = clsRep.getFields();
- for (int i=0; i < fields.size(); i++) {
- FieldRep field = (FieldRep) fields.elementAt(i);
-
- writeField(field.getName(), field.getType(), field.getIndexed(), all);
- }
- }
-
- /**
- * write a schema representation of the given Class field and append it to the
where Node * recurse on complex types
- * @param fieldName name of the field
- * @param fieldType type of the field
- * @param isUnbounded causes maxOccurs="unbounded" if set
- * @param where location for the generated schema node
- * @throws Exception
- */
- private void writeField(String fieldName,
- Class fieldType,
- boolean isUnbounded,
- Element where) throws Exception {
- String elementType = writeType(fieldType);
- Element elem = createElement(fieldName,
- elementType,
- isNullable(fieldType),
- where.getOwnerDocument());
- if (isUnbounded) {
- elem.setAttribute("maxOccurs", "unbounded");
- }
- where.appendChild(elem);
- }
-
- /**
* Create Element with a given name and type
* @param elementName the name of the created element
* @param elementType schema type representation of the element
* @param nullable nullable attribute of the element
* @return the created Element
*/
- private Element createElement(String elementName,
+ public Element createElement(String elementName,
String elementType,
boolean nullable,
Document docHolder) {
@@ -612,7 +555,7 @@
* @param type input Class
* @return true if the type is a simple schema type
*/
- boolean isSimpleSchemaType(Class type) {
+ public boolean isSimpleSchemaType(Class type) {
return (type == java.lang.String.class ||
type == java.lang.Boolean.TYPE ||
type == java.lang.Byte.TYPE ||
@@ -752,7 +695,7 @@
* @param type input Class
* @return true if nullable
*/
- private boolean isNullable(Class type) {
+ public boolean isNullable(Class type) {
if (type.isPrimitive() ||
(type.isArray() && type.getComponentType() == byte.class))
return false;
@@ -783,6 +726,20 @@
doc.importNode(wsdlTypesElem, true),
doc.getDocumentElement().getFirstChild());
}
+ }
+
+ /**
+ * Return the list of classes that we should not emit WSDL for.
+ */
+ public Vector getStopClasses() {
+ return stopClasses;
+ }
+
+ /**
+ * Return the class rep that allows users to build their own beans
+ */
+ public BuilderBeanClassRep getBeanBuilder() {
+ return beanBuilder;
}
/**
1.34 +19 -0 xml-axis/java/src/org/apache/axis/wsdl/toJava/SymbolTable.java
Index: SymbolTable.java
===================================================================
RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/SymbolTable.java,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -r1.33 -r1.34
--- SymbolTable.java 19 Feb 2002 20:55:00 -0000 1.33
+++ SymbolTable.java 21 Feb 2002 18:51:23 -0000 1.34
@@ -566,6 +566,25 @@
Constants.isSchemaXSD(nodeKind.getNamespaceURI())) {
// we can no longer do .NET stuff and treat document as rpc style
this.dotNet = false;
+ // Create symbol table entry for attribute type
+ QName refQName = Utils.getNodeTypeRefQName(node, "type");
+ if (refQName == null) {
+ TypeEntry refType = getTypeEntry(refQName, false);
+ if (refType != null) {
+ // Not defined yet, add one
+ String baseName = btm.getBaseName(refQName);
+ if (baseName != null) {
+ BaseType bt = new BaseType(refQName);
+ bt.setIsReferenced(true);
+ symbolTablePut(bt);
+ }
+ else {
+ throw new IOException(
+ "Attribute type is not simple:" +
refQName.toString());
+ }
+ }
+ }
+
}
}
1.10 +53 -0 xml-axis/java/src/org/apache/axis/wsdl/toJava/SchemaUtils.java
Index: SchemaUtils.java
===================================================================
RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/SchemaUtils.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- SchemaUtils.java 15 Feb 2002 23:02:19 -0000 1.9
+++ SchemaUtils.java 21 Feb 2002 18:51:23 -0000 1.10
@@ -852,5 +852,58 @@
return null;
}
+ /**
+ * Return the attribute names and types if any in the node
+ * The even indices are the element types (TypeEntry) and
+ * the odd indices are the corresponding names (Strings).
+ *
+ * Example:
+ * <complexType name="Person">
+ * <sequence>
+ * <element minOccurs="1" maxOccurs="1" name="Age" type="double" />
+ * <element minOccurs="1" maxOccurs="1" name="ID" type="xsd:float" />
+ * </sequence>
+ * <attribute name="Name" type="string" />
+ * <attribute name="Male" type="boolean" />
+ * </complexType>
+ *
+ */
+ public static Vector getComplexElementAttributes(Node node,
+ SymbolTable symbolTable)
+ {
+ Vector v = null; // return value
+
+ if (node == null) {
+ return null;
+ }
+
+ // examine children of the node for <attribute> elements
+ NodeList children = node.getChildNodes();
+ for (int i = 0; i < children.getLength(); i++) {
+ Node child = children.item(i);
+ QName nodeKind = Utils.getNodeQName(child);
+ if (nodeKind == null ||
+ ! nodeKind.getLocalPart().equals("attribute"))
+ continue;
+
+ // we have an attribute node
+ if (v == null)
+ v = new Vector();
+
+ // type
+ QName typeAttr = Utils.getNodeTypeRefQName(child, "type");
+ TypeEntry type = symbolTable.getTypeEntry(typeAttr, false);
+ // name
+ QName name = Utils.getNodeNameQName(child);
+ // add type and name to vector, skip it if we couldn't parse it
+ // XXX - this may need to be revisited.
+ if (type != null && name != null) {
+ v.add(type);
+ v.add(name.getLocalPart());
+ }
+ }
+
+ return v;
+ }
}
1.5 +9 -3
xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaTypeWriter.java
Index: JavaTypeWriter.java
===================================================================
RCS file:
/home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaTypeWriter.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- JavaTypeWriter.java 23 Jan 2002 17:53:05 -0000 1.4
+++ JavaTypeWriter.java 21 Feb 2002 18:51:23 -0000 1.5
@@ -94,9 +94,15 @@
Vector v = SchemaUtils.getComplexElementTypesAndNames(
node, symbolTable);
if (v != null) {
- typeWriter = new JavaComplexTypeWriter(emitter, type, v,
- SchemaUtils.getComplexElementExtensionBase(
- node, symbolTable));
+ typeWriter = new
+ JavaComplexTypeWriter(emitter,
+ type,
+ v,
+
SchemaUtils.getComplexElementExtensionBase(
+ node, symbolTable),
+
SchemaUtils.getComplexElementAttributes(
+ node,
+ symbolTable));
}
else {
v = SchemaUtils.getEnumerationBaseAndValues(
1.7 +37 -3
xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaComplexTypeWriter.java
Index: JavaComplexTypeWriter.java
===================================================================
RCS file:
/home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaComplexTypeWriter.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- JavaComplexTypeWriter.java 5 Feb 2002 21:53:49 -0000 1.6
+++ JavaComplexTypeWriter.java 21 Feb 2002 18:51:23 -0000 1.7
@@ -70,6 +70,7 @@
public class JavaComplexTypeWriter extends JavaWriter {
private TypeEntry type;
private Vector elements;
+ private Vector attributes;
private TypeEntry extendType;
/**
@@ -81,11 +82,16 @@
*/
protected JavaComplexTypeWriter(
Emitter emitter,
- TypeEntry type, Vector elements, TypeEntry extendType) {
+ TypeEntry type,
+ Vector elements,
+ TypeEntry extendType,
+ Vector attributes)
+ {
super(emitter, type, "", "java",
JavaUtils.getMessage("genType00"), "complexType");
this.type = type;
this.elements = elements;
+ this.attributes = attributes;
this.extendType = extendType;
} // ctor
@@ -109,12 +115,25 @@
names.add(((TypeEntry) elements.get(i)).getName());
names.add( Utils.xmlNameToJava((String) elements.get(i + 1)));
}
+ // add the attributes to the names list (which will be bean elements too)
+ if (attributes != null) {
+ for (int i=0; i < attributes.size(); i+=2) {
+ names.add(((TypeEntry) attributes.get(i)).getName());
+ names.add( Utils.xmlNameToJava((String) attributes.get(i + 1)));
+ }
+ }
+
pw.println("public class " + className + extendsText + " implements
java.io.Serializable {");
for (int i = 0; i < names.size(); i += 2) {
String variable = (String) names.get(i + 1);
- pw.println(" private " + names.get(i) + " " + variable + ";");
+ pw.print(" private " + names.get(i) + " " + variable + ";");
+ // label the attribute fields.
+ if (i >= elements.size())
+ pw.println(" // attribute");
+ else
+ pw.println();
}
pw.println();
@@ -163,7 +182,8 @@
// like the reasonable approach to take for collection types.
// (It may be more efficient to handle this with an ArrayList...but
// for the initial support it was easier to use an actual array.)
- if
(((TypeEntry)elements.elementAt(i)).getQName().getLocalPart().indexOf("[")>0) {
+ if (i < elements.size() &&
+
((TypeEntry)elements.elementAt(i)).getQName().getLocalPart().indexOf("[")>0) {
String compName = typeName.substring(0, typeName.lastIndexOf("["));
@@ -191,6 +211,20 @@
pw.println();
}
}
+
+ // if we have attributes, create metadata function which returns the
+ // list of properties that are attributes instead of elements
+ if (attributes != null) {
+ pw.println(" public static java.util.Vector getAttributeElements()
{");
+ pw.println(" java.util.Vector v = new java.util.Vector();");
+ for (int i=0; i < attributes.size(); i+=2) {
+ pw.println(" v.add(\"" + Utils.xmlNameToJava((String)
attributes.get(i + 1)) + "\");");
+ }
+ pw.println(" return v;");
+ pw.println(" }");
+ pw.println();
+ }
+
pw.println("}");
pw.close();
} // writeOperation
1.57 +2 -1 xml-axis/java/src/org/apache/axis/utils/resources.properties
Index: resources.properties
===================================================================
RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/utils/resources.properties,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -r1.56 -r1.57
--- resources.properties 20 Feb 2002 17:17:35 -0000 1.56
+++ resources.properties 21 Feb 2002 18:51:23 -0000 1.57
@@ -643,7 +643,8 @@
literalTypePart00=Error: Message part {0} of operation or fault {1} is specified as
a type and the soap:body use of binding "{2}" is literal. This WSDL is not currently
supported.
BadServiceName00=Error: Empty or missing service name
-AttrNotSimpleType00=Attribute {0} is of type {1}, which is not a simple type
+AttrNotSimpleType00=Bean attribute {0} is of type {1}, which is not a simple type
+NoSerializer00=Unable to find serializer for type {0}
optionTypeMapping00=indicate 1.1 or 1.2. The default is 1.2 (SOAP 1.2 JAX-RPC
compliant)
1.6 +105 -1
xml-axis/java/src/org/apache/axis/encoding/ser/BeanSerializer.java
Index: BeanSerializer.java
===================================================================
RCS file:
/home/cvs/xml-axis/java/src/org/apache/axis/encoding/ser/BeanSerializer.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- BeanSerializer.java 19 Feb 2002 20:50:46 -0000 1.5
+++ BeanSerializer.java 21 Feb 2002 18:51:23 -0000 1.6
@@ -71,6 +71,8 @@
import org.apache.axis.encoding.DeserializationContext;
import org.apache.axis.encoding.DeserializerImpl;
import org.apache.axis.InternalException;
+import org.apache.axis.AxisFault;
+import org.apache.axis.utils.JavaUtils;
import org.apache.axis.wsdl.fromJava.ClassRep;
import org.apache.axis.wsdl.fromJava.FieldRep;
import org.apache.axis.wsdl.fromJava.Types;
@@ -289,8 +291,110 @@
* @see org.apache.axis.wsdl.fromJava.Types
*/
public boolean writeSchema(Types types) throws Exception {
- types.writeBeanClassType(types.getWsdlQName(xmlType), javaType);
+
+ javax.wsdl.QName qName = types.getWsdlQName(xmlType);
+
+ // ComplexType representation of bean class
+ Element complexType = types.createElement("complexType");
+ types.writeSchemaElement(qName, complexType);
+ complexType.setAttribute("name", qName.getLocalPart());
+
+ // See if there is a super class, stop if we hit a stop class
+ Element e = null;
+ Class superClass = javaType.getSuperclass();
+ Vector stopClasses = types.getStopClasses();
+ if (superClass != null &&
+ superClass != java.lang.Object.class &&
+ (stopClasses == null ||
+ !(stopClasses.contains(superClass.getName()))) ) {
+ // Write out the super class
+ String base = types.writeType(superClass);
+ Element complexContent = types.createElement("complexContent");
+ complexType.appendChild(complexContent);
+ Element extension = types.createElement("extension");
+ complexContent.appendChild(extension);
+ extension.setAttribute("base", base);
+ e = extension;
+ } else {
+ e = complexType;
+ }
+
+ // Add fields under all element
+ Element all = types.createElement("all");
+ e.appendChild(all);
+
+ // Build a ClassRep that represents the bean class. This
+ // allows users to provide their own field mapping.
+ ClassRep clsRep = types.getBeanBuilder().build(javaType);
+
+ // Write out fields
+ Vector fields = clsRep.getFields();
+ for (int i=0; i < fields.size(); i++) {
+ FieldRep field = (FieldRep) fields.elementAt(i);
+
+ // if bean fields are attributes, write attribute element
+ if (beanAttributeNames.contains(field.getName()))
+ writeAttribute(types, field.getName(),
+ field.getType(),
+ complexType);
+ else
+ writeField(types, field.getName(),
+ field.getType(),
+ field.getIndexed(),
+ all);
+ }
+ // done
return true;
+ }
+
+ /**
+ * write a schema representation of the given Class field and append it to
+ * the where Node, recurse on complex types
+ * @param fieldName name of the field
+ * @param fieldType type of the field
+ * @param isUnbounded causes maxOccurs="unbounded" if set
+ * @param where location for the generated schema node
+ * @throws Exception
+ */
+ private void writeField(Types types, String fieldName,
+ Class fieldType,
+ boolean isUnbounded,
+ Element where) throws Exception {
+ String elementType = types.writeType(fieldType);
+ Element elem = types.createElement(fieldName,
+ elementType,
+ types.isNullable(fieldType),
+ where.getOwnerDocument());
+ if (isUnbounded) {
+ elem.setAttribute("maxOccurs", "unbounded");
+ }
+ where.appendChild(elem);
+ }
+
+ /**
+ * write aa attribute element and append it to the 'where' Node
+ * @param fieldName name of the field
+ * @param fieldType type of the field
+ * @param where location for the generated schema node
+ * @throws Exception
+ */
+ private void writeAttribute(Types types,
+ String fieldName,
+ Class fieldType,
+ Element where) throws Exception {
+
+ // Attribute must be a simple type.
+ if (!types.isSimpleSchemaType(fieldType))
+ throw new AxisFault(JavaUtils.getMessage("AttrNotSimpleType00",
+ fieldName,
+ fieldType.getName()));
+
+ String elementType = types.writeType(fieldType);
+ Element elem = types.createElement(fieldName,
+ elementType,
+ false,
+ where.getOwnerDocument());
+ where.appendChild(elem);
}
/**