org.apache.axis.wsdl.toJava.JavaBeanHelperWriter Maven / Gradle / Ivy
/*
* Copyright 2001-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.axis.wsdl.toJava;
import org.apache.axis.utils.Messages;
import org.apache.axis.wsdl.symbolTable.ContainedAttribute;
import org.apache.axis.utils.JavaUtils;
import org.apache.axis.wsdl.symbolTable.DefinedElement;
import org.apache.axis.wsdl.symbolTable.DefinedType;
import org.apache.axis.wsdl.symbolTable.ElementDecl;
import org.apache.axis.wsdl.symbolTable.SchemaUtils;
import org.apache.axis.wsdl.symbolTable.TypeEntry;
import org.apache.axis.wsdl.symbolTable.CollectionTE;
import javax.xml.namespace.QName;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Vector;
import java.util.Set;
/**
* This is Wsdl2java's Helper Type Writer. It writes the .java file.
*/
public class JavaBeanHelperWriter extends JavaClassWriter {
/** Field type */
protected TypeEntry type;
/** Field elements */
protected Vector elements;
/** Field attributes */
protected Vector attributes;
/** Field extendType */
protected TypeEntry extendType;
/** Field wrapperPW */
protected PrintWriter wrapperPW = null;
/** Field elementMetaData */
protected Vector elementMetaData = null;
/** Field canSearchParents */
protected boolean canSearchParents;
/** Field reservedPropNames */
protected Set reservedPropNames;
/**
* Constructor.
*
* @param emitter
* @param type The type representing this class
* @param elements Vector containing the Type and name of each property
* @param extendType The type representing the extended class (or null)
* @param attributes Vector containing the attribute types and names
*/
protected JavaBeanHelperWriter(Emitter emitter, TypeEntry type,
Vector elements, TypeEntry extendType,
Vector attributes, Set reservedPropNames) {
super(emitter, type.getName() + "_Helper", "helper");
this.type = type;
this.elements = elements;
this.attributes = attributes;
this.extendType = extendType;
this.reservedPropNames = reservedPropNames;
// is this a complex type that is derived from other types
// by restriction? if so, set the policy of the generated
// TypeDescription to ignore metadata associated with
// superclasses, as restricted types are required to
// define their entire content model. Hence the type
// description associated with the current type provides
// all of the types (and only those types) allowed in
// the restricted derivation.
if ((null != extendType)
&& (null
!= SchemaUtils.getComplexElementRestrictionBase(
type.getNode(), emitter.getSymbolTable()))) {
this.canSearchParents = false;
} else {
this.canSearchParents = true;
}
} // ctor
/**
* The bean helper class may be its own class, or it may be
* embedded within the bean class. If it's embedded within the
* bean class, the JavaBeanWriter will set JavaBeanHelperWriter's
* PrintWriter to its own.
*
* @param pw
*/
protected void setPrintWriter(PrintWriter pw) {
this.wrapperPW = pw;
} // setPrintWriter
/**
* The default behaviour (of super.getPrintWriter) is, given the
* file name, create a PrintWriter for it. If the bean helper
* that this class is generating is embedded within a bean, then
* the PrintWriter returned by this method is the JavaBeanWriter's
* PrintWriter. Otherwise super.getPrintWriter is called.
*
* @param filename
* @return
* @throws IOException
*/
protected PrintWriter getPrintWriter(String filename) throws IOException {
return (wrapperPW == null)
? super.getPrintWriter(filename)
: wrapperPW;
} // getPrintWriter
/**
* Only register the filename if the bean helper is not wrapped
* within a bean.
*
* @param file
*/
protected void registerFile(String file) {
if (wrapperPW == null) {
super.registerFile(file);
}
} // registerFile
/**
* Return the string: "Generating ".
* only if we are going to generate a new file.
*
* @param file
* @return
*/
protected String verboseMessage(String file) {
if (wrapperPW == null) {
return super.verboseMessage(file);
} else {
return null;
}
} // verboseMessage
/**
* Only write the file header if the bean helper is not wrapped
* within a bean.
*
* @param pw
* @throws IOException
*/
protected void writeFileHeader(PrintWriter pw) throws IOException {
if (wrapperPW == null) {
super.writeFileHeader(pw);
}
} // writeFileHeader
/**
* Generate the file body for the bean helper.
*
* @param pw
* @throws IOException
*/
protected void writeFileBody(PrintWriter pw) throws IOException {
writeMetaData(pw);
writeSerializer(pw);
writeDeserializer(pw);
} // writeFileBody
/**
* Only write the file footer if the bean helper is not
* wrapped within a bean.
*
* @param pw
* @throws IOException
*/
protected void writeFileFooter(PrintWriter pw) throws IOException {
if (wrapperPW == null) {
super.writeFileFooter(pw);
}
} // writeFileFooter
/**
* Only close the PrintWriter if the PrintWriter belongs to
* this class. If the bean helper is embedded within a bean
* then the PrintWriter belongs to JavaBeanWriter and THAT
* class is responsible for closing the PrintWriter.
*
* @param pw
*/
protected void closePrintWriter(PrintWriter pw) {
// If the output of this writer is wrapped within
// another writer (JavaBeanWriter), then THAT
// writer will close the PrintWriter, not this one.
if (wrapperPW == null) {
pw.close();
}
} // closePrintWriter
/**
* write MetaData code
*
* @param pw
* @throws IOException
*/
protected void writeMetaData(PrintWriter pw) throws IOException {
// Collect elementMetaData
if (elements != null) {
for (int i = 0; i < elements.size(); i++) {
ElementDecl elem = (ElementDecl) elements.get(i);
// String elemName = elem.getName().getLocalPart();
// String javaName = Utils.xmlNameToJava(elemName);
// Changed the code to write meta data
// for all of the elements in order to
// support sequences. Defect 9060
// Meta data is needed if the default serializer
// action cannot map the javaName back to the
// element's qname. This occurs if:
// - the javaName and element name local part are different.
// - the javaName starts with uppercase char (this is a wierd
// case and we have several problems with the mapping rules.
// Seems best to gen meta data in this case.)
// - the element name is qualified (has a namespace uri)
// its also needed if:
// - the element has the minoccurs flag set
// if (!javaName.equals(elemName) ||
// Character.isUpperCase(javaName.charAt(0)) ||
// !elem.getName().getNamespaceURI().equals("") ||
// elem.getMinOccursIs0()) {
// If we did some mangling, make sure we'll write out the XML
// the correct way.
if (elementMetaData == null) {
elementMetaData = new Vector();
}
elementMetaData.add(elem);
// }
}
}
pw.println(" // " + Messages.getMessage("typeMeta"));
pw.println(
" private static org.apache.axis.description.TypeDesc typeDesc =");
pw.println(" new org.apache.axis.description.TypeDesc("
+ Utils.getJavaLocalName(type.getName()) + ".class, "
+ (this.canSearchParents
? "true"
: "false") + ");");
pw.println();
pw.println(" static {");
pw.println(" typeDesc.setXmlType("
+ Utils.getNewQName(type.getQName()) + ");");
// Add attribute and element field descriptors
if ((attributes != null) || (elementMetaData != null)) {
if (attributes != null) {
boolean wroteAttrDecl = false;
for (int i = 0; i < attributes.size(); i++) {
ContainedAttribute attr = (ContainedAttribute) attributes.get(i);
TypeEntry te = attr.getType();
QName attrName = attr.getQName();
String fieldName = getAsFieldName(attr.getName());
QName attrXmlType = te.getQName();
pw.print(" ");
if (!wroteAttrDecl) {
pw.print("org.apache.axis.description.AttributeDesc ");
wroteAttrDecl = true;
}
pw.println(
"attrField = new org.apache.axis.description.AttributeDesc();");
pw.println(" attrField.setFieldName(\"" + fieldName
+ "\");");
pw.println(" attrField.setXmlName("
+ Utils.getNewQNameWithLastLocalPart(attrName) + ");");
if (attrXmlType != null) {
pw.println(" attrField.setXmlType("
+ Utils.getNewQName(attrXmlType) + ");");
}
pw.println(" typeDesc.addFieldDesc(attrField);");
}
}
if (elementMetaData != null) {
boolean wroteElemDecl = false;
for (int i = 0; i < elementMetaData.size(); i++) {
ElementDecl elem =
(ElementDecl) elementMetaData.elementAt(i);
if (elem.getAnyElement()) {
continue;
}
String fieldName = getAsFieldName(elem.getName());
QName xmlName = elem.getQName();
// Some special handling for arrays.
TypeEntry elemType = elem.getType();
QName xmlType = null;
if ((elemType.getDimensions().length() > 1)
&& (elemType.getClass() == DefinedType.class)) {
// If we have a DefinedType with dimensions, it must
// be a SOAP array derived type. In this case, use
// the refType's QName for the metadata.
elemType = elemType.getRefType();
} else if (elemType.getClass() == DefinedElement.class
&& elemType.getRefType() != null) {
// If we have a DefinedElement which references other element
// (eg. )
// use the refType's QName for the metadata (which can be anonymous type.)
// see the schema of test/wsdl/axis2098
elemType = elemType.getRefType();
} else if (elemType.isSimpleType()
&& elemType.getRefType() != null) {
// see wsdl in AXIS-2138
elemType = elemType.getRefType();
} else {
// Otherwise, use the first non-Collection type we
// encounter up the ref chain.
while (elemType instanceof CollectionTE) {
elemType = elemType.getRefType();
}
}
xmlType = elemType.getQName();
pw.print(" ");
if (!wroteElemDecl) {
pw.print("org.apache.axis.description.ElementDesc ");
wroteElemDecl = true;
}
pw.println(
"elemField = new org.apache.axis.description.ElementDesc();");
pw.println(" elemField.setFieldName(\"" + fieldName
+ "\");");
pw.println(" elemField.setXmlName("
+ Utils.getNewQNameWithLastLocalPart(xmlName) + ");");
if (xmlType != null) {
pw.println(" elemField.setXmlType("
+ Utils.getNewQName(xmlType) + ");");
}
if (elem.getMinOccursIs0()) {
pw.println(" elemField.setMinOccurs(0);");
}
if (elem.getNillable()) {
pw.println(" elemField.setNillable(true);");
} else {
pw.println(" elemField.setNillable(false);");
}
if(elem.getMaxOccursIsUnbounded()) {
pw.println(" elemField.setMaxOccursUnbounded(true);");
}
QName itemQName = elem.getType().getItemQName();
if (itemQName != null) {
pw.println(" elemField.setItemQName(" +
Utils.getNewQName(itemQName) + ");");
}
pw.println(" typeDesc.addFieldDesc(elemField);");
}
}
}
pw.println(" }");
pw.println();
pw.println(" /**");
pw.println(" * " + Messages.getMessage("returnTypeMeta"));
pw.println(" */");
pw.println(
" public static org.apache.axis.description.TypeDesc getTypeDesc() {");
pw.println(" return typeDesc;");
pw.println(" }");
pw.println();
}
/**
* Utility function to get the bean property name (as will be returned
* by the Introspector) for a given field name. This just means
* we capitalize the first character if the second character is
* capitalized. Example: a field named "fOO" will turn into
* getter/setter methods "getFOO()/setFOO()". So when the Introspector
* looks at that bean, the property name will be "FOO", not "fOO" due
* to the rules in the JavaBeans spec. So this makes sure the
* metadata will match.
*
* The method also makes sure that the returned property name is not in
* the set of reserved properties as defined by {@link #reservedPropNames}.
*
* @param fieldName
* @return
*/
private String getAsFieldName(String fieldName) {
// If there's a second character, and it is uppercase, then the
// bean property name will have a capitalized first character
// (because setURL() maps to a property named "URL", not "uRL")
if ((fieldName.length() > 1)
&& Character.isUpperCase(fieldName.charAt(1))) {
fieldName = Utils.capitalizeFirstChar(fieldName);
}
// Make sure the property name is not reserved.
return JavaUtils.getUniqueValue(reservedPropNames, fieldName);
}
/**
* write Serializer getter code and pass in meta data to avoid
* undo introspection.
*
* @param pw
* @throws IOException
*/
protected void writeSerializer(PrintWriter pw) throws IOException {
String typeDesc = "typeDesc";
String ser = " org.apache.axis.encoding.ser.BeanSerializer";
if (type.isSimpleType()) {
ser = " org.apache.axis.encoding.ser.SimpleSerializer";
}
pw.println(" /**");
pw.println(" * Get Custom Serializer");
pw.println(" */");
pw.println(
" public static org.apache.axis.encoding.Serializer getSerializer(");
pw.println(" java.lang.String mechType, ");
pw.println(" java.lang.Class _javaType, ");
pw.println(" javax.xml.namespace.QName _xmlType) {");
pw.println(" return ");
pw.println(" new " + ser + "(");
pw.println(" _javaType, _xmlType, " + typeDesc + ");");
pw.println(" }");
pw.println();
}
/**
* write Deserializer getter code and pass in meta data to avoid
* undo introspection.
*
* @param pw
* @throws IOException
*/
protected void writeDeserializer(PrintWriter pw) throws IOException {
String typeDesc = "typeDesc";
String dser = " org.apache.axis.encoding.ser.BeanDeserializer";
if (type.isSimpleType()) {
dser = " org.apache.axis.encoding.ser.SimpleDeserializer";
}
pw.println(" /**");
pw.println(" * Get Custom Deserializer");
pw.println(" */");
pw.println(
" public static org.apache.axis.encoding.Deserializer getDeserializer(");
pw.println(" java.lang.String mechType, ");
pw.println(" java.lang.Class _javaType, ");
pw.println(" javax.xml.namespace.QName _xmlType) {");
pw.println(" return ");
pw.println(" new " + dser + "(");
pw.println(" _javaType, _xmlType, " + typeDesc + ");");
pw.println(" }");
pw.println();
}
} // class JavaBeanHelperWriter