blob: 26cf30e99fc37f3ca530e563ebe6d2424db21054 [file] [log] [blame]
/*
* 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.Constants;
import org.apache.axis.utils.JavaUtils;
import org.apache.axis.utils.Messages;
import org.apache.axis.wsdl.symbolTable.ContainedAttribute;
import org.apache.axis.wsdl.symbolTable.ElementDecl;
import org.apache.axis.wsdl.symbolTable.SchemaUtils;
import org.apache.axis.wsdl.symbolTable.TypeEntry;
import org.w3c.dom.DOMException;
import org.w3c.dom.Node;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;
/**
* This is Wsdl2java's Complex Type Writer. It writes the <typeName>.java file.
*/
public class JavaBeanWriter extends JavaClassWriter {
/** Field type */
private TypeEntry type;
/** Field elements */
private Vector elements;
/** Field attributes */
private Vector attributes;
/** Field extendType */
private TypeEntry extendType;
/** Field helper */
protected JavaBeanHelperWriter helper;
/** Field names */
protected Vector names = new Vector(); // even indices: types, odd: vars
/** Field simpleValueTypes */
protected ArrayList simpleValueTypes =
new ArrayList(); // name of type of simple value
/** Field enumerationTypes */
protected Set enumerationTypes = new HashSet(); // name of enumerated types
/** Field pw */
protected PrintWriter pw;
// The following fields can be set by extended classes
// to control processing
/** Field enableDefaultConstructor */
protected boolean enableDefaultConstructor = true;
/** Field enableFullConstructor */
protected boolean enableFullConstructor = false;
/** Field enableSimpleConstructors */
protected boolean enableSimpleConstructors = false;
/** Field enableToString */
protected boolean enableToString = false;
/** Field enableSetters */
protected boolean enableSetters = true;
/** Field enableGetters */
protected boolean enableGetters = true;
/** Field enableEquals */
protected boolean enableEquals = true;
/** Field enableHashCode */
protected boolean enableHashCode = true;
/** Field enableMemberFields */
protected boolean enableMemberFields = true;
/** Field isAny */
protected boolean isAny = false;
/** Field isMixed */
protected boolean isMixed = false;
/** Field parentIsAny */
protected boolean parentIsAny = false;
/** Field parentIsMixed */
protected boolean parentIsMixed = false;
/**
* 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
* @param helper Helper class writer
*/
protected JavaBeanWriter(Emitter emitter, TypeEntry type, Vector elements,
TypeEntry extendType, Vector attributes,
JavaWriter helper) {
super(emitter, type.getName(), "complexType");
this.type = type;
this.elements = elements;
this.attributes = attributes;
this.extendType = extendType;
this.helper = (JavaBeanHelperWriter) helper;
if (type.isSimpleType()) {
enableSimpleConstructors = true;
enableToString = true;
} else {
// is this a complex type that is derived from other types
// by restriction? if so, do not emit instance variables
// or accessor/mutator pairs as those are inherited from
// the super type, which must be non-null.
if (null != extendType) {
if (null != SchemaUtils.getComplexElementRestrictionBase(
type.getNode(), emitter.getSymbolTable())) {
enableMemberFields = false;
enableGetters = false;
enableSetters = false;
enableEquals = false;
enableHashCode = false;
} else {
// derived by extension.
// Write full constructor, so that instance variables
// in super class are intialized.
enableFullConstructor = true;
}
}
}
preprocess();
} // ctor
/**
* Write a common header, including the package name, the class
* declaration, and the opening curly brace.
* Prints javadoc from WSDL documentation. (Cannot pull up, type DOM not avail)
*/
protected void writeFileHeader(PrintWriter pw) throws IOException {
writeHeaderComments(pw);
writePackage(pw);
try
{
String comments = SchemaUtils.getAnnotationDocumentation(type.getNode());
comments = getJavadocDescriptionPart(comments, false);
if (comments != null && comments.trim().length() > 0)
{
pw.println();
pw.println("/**");
pw.println(comments);
pw.println(" */");
}
}
catch (DOMException e)
{
// no comment
}
// print class declaration
pw.println(getClassModifiers() + getClassText() + getClassName() + ' ' + getExtendsText() + getImplementsText() + "{");
} // writeFileHeader
/**
* Generate the binding for the given complex type.
*
* @param pw
* @throws IOException
*/
protected void writeFileBody(PrintWriter pw) throws IOException {
this.pw = pw;
// Populate Names Vector with the names and types of the members.
// The write methods use the names vector whenever they need to get
// a member name or type. Moved to implements callback in order
// to set any interface
// preprocess();
// Write Member Fields
if (enableMemberFields) {
writeMemberFields();
}
// Write the default constructor
if (enableDefaultConstructor) {
writeDefaultConstructor();
}
// Write Full Constructor
if (enableFullConstructor) {
writeFullConstructor();
}
// Write SimpleConstructors
if (enableSimpleConstructors) {
writeSimpleConstructors();
}
if(!enableFullConstructor && !enableSimpleConstructors && enableMemberFields) {
writeMinimalConstructor();
}
// Write ToString method
if (enableToString) {
writeToStringMethod();
}
// Write accessor methods
writeAccessMethods();
// Write general purpose equals and hashCode methods
if (enableEquals) {
writeEqualsMethod();
}
if (enableHashCode) {
writeHashCodeMethod();
}
// Write the meta data into a Helper class or
// embed it in the bean class
if (!emitter.isHelperWanted()) {
// Write the helper info into the bean class
helper.setPrintWriter(pw);
}
helper.generate();
} // writeFileBody
/**
* Builds the names String vector.
* The even indices are the java class names of the
* member fields. The odd indices are the member variable
* names.
* Also sets the simpleValueType variable to the
* java class name of the simple value if this bean represents
* a simple type
*/
protected void preprocess() {
// Add element names
if (elements != null) {
// Check the inheritance chain for xs:any and xs:mixed
TypeEntry parent = extendType;
while ((!parentIsAny || !parentIsMixed) && parent != null) {
if (SchemaUtils.isMixed(parent.getNode())) {
parentIsMixed = true;
}
Vector hisElements = parent.getContainedElements();
for (int i = 0; hisElements != null && i < hisElements.size(); i++) {
ElementDecl elem = (ElementDecl) hisElements.get(i);
if (elem.getAnyElement()) {
parentIsAny = true;
}
}
parent =
SchemaUtils.getComplexElementExtensionBase(parent.getNode(),
emitter.getSymbolTable());
}
for (int i = 0; i < elements.size(); i++) {
ElementDecl elem = (ElementDecl) elements.get(i);
String typeName = elem.getType().getName();
String variableName = null;
if (elem.getAnyElement()) {
if (!parentIsAny && !parentIsMixed) {
typeName = "org.apache.axis.message.MessageElement []";
variableName = Constants.ANYCONTENT;
}
isAny = true;
} else {
variableName = elem.getName();
typeName = processTypeName(elem, typeName);
}
if (variableName == null) {
continue;
}
// Make sure the property name is not reserved.
variableName = JavaUtils.getUniqueValue(
helper.reservedPropNames, variableName);
names.add(typeName);
names.add(variableName);
if (type.isSimpleType()
&& (variableName.endsWith("Value")
|| variableName.equals("_value"))) {
simpleValueTypes.add(typeName);
}
// bug 19069: need to generate code that access member variables that
// are enum types through the class interface, not the constructor
// this util method returns non-null if the type at node is an enum
if (null != Utils.getEnumerationBaseAndValues(
elem.getType().getNode(), emitter.getSymbolTable())) {
enumerationTypes.add(typeName);
}
}
}
if (enableMemberFields && SchemaUtils.isMixed(type.getNode())) {
isMixed = true;
if (!isAny && !parentIsAny && !parentIsMixed) {
names.add("org.apache.axis.message.MessageElement []");
names.add(Constants.ANYCONTENT);
}
}
// Add attribute names
if (attributes != null) {
for (int i = 0; i < attributes.size(); i++) {
ContainedAttribute attr = (ContainedAttribute) attributes.get(i);
String typeName = attr.getType().getName();
String variableName = getAttributeName(attr);
// TODO - What about MinOccurs and Nillable?
// Do they make sense here?
if (attr.getOptional()) {
typeName = Utils.getWrapperType(typeName);
}
// Make sure the property name is not reserved.
variableName = JavaUtils.getUniqueValue(
helper.reservedPropNames, variableName);
names.add(typeName);
names.add(variableName);
if (type.isSimpleType()
&& (variableName.endsWith("Value")
|| variableName.equals("_value"))) {
simpleValueTypes.add(typeName);
}
// bug 19069: need to generate code that access member variables that
// are enum types through the class interface, not the constructor
// this util method returns non-null if the type at node is an enum
if (null != Utils.getEnumerationBaseAndValues(attr.getType().getNode(),
emitter.getSymbolTable())) {
enumerationTypes.add(typeName);
}
}
}
if ((extendType != null) && extendType.getDimensions().equals("[]")) {
String typeName = extendType.getName();
String elemName = extendType.getQName().getLocalPart();
String variableName = JavaUtils.xmlNameToJava(elemName);
names.add(typeName);
names.add(variableName);
}
if((extendType != null) && (Utils.getEnumerationBaseAndValues(
extendType.getNode(), emitter.getSymbolTable()) != null)){
enableDefaultConstructor = false;
}
// Check for duplicate names and make them unique
// Start at index 2 and go by twos
for (int i = 1; i < names.size(); i +=2)
{
int suffix = 2; // the number we append to the name
String s = (String) names.elementAt(i);
if (i < names.size() - 2)
{
int dup = names.indexOf(s, i+1);
while (dup > 0)
{
// duplicate name, tack a number on the end
names.set(dup, names.get(dup) + Integer.toString(suffix));
suffix++;
// get out if we don't have more
if (i >= names.size() - 2)
break;
dup = names.indexOf(s, dup+1);
}
}
}
}
/**
* generate a name for the attribute
* @param attr
* @return name
*/
private String getAttributeName(ContainedAttribute attr) {
String variableName = attr.getName();
if (variableName == null) {
variableName = Utils.getLastLocalPart(attr.getQName().getLocalPart());
}
return variableName;
}
/**
* Check if we need to use the wrapper type or MessageElement
*
* @param elem
* @param typeName
* @return type name
*/
private String processTypeName(ElementDecl elem, String typeName) {
if (elem.getAnyElement()) {
typeName = "org.apache.axis.message.MessageElement []";
} else if (elem.getType().getUnderlTypeNillable()
|| (elem.getNillable() && elem.getMaxOccursIsUnbounded())) {
/*
* Soapenc arrays with nillable underlying type or
* nillable="true" maxOccurs="unbounded" elements
* should be mapped to a wrapper type.
*/
typeName = Utils.getWrapperType(elem.getType());
} else if (elem.getMinOccursIs0() && elem.getMaxOccursIsExactlyOne()
|| elem.getNillable() || elem.getOptional()) {
/*
* Quote from JAX-RPC 1.1, Section 4.2.1:
* There are a number of cases in which a built-in simple
* XML data type must be mapped to the corresponding Java
* wrapper class for the Java primitive type:
* * an element declaration with the nillable attribute
* set to true;
* * an element declaration with the minOccurs attribute
* set to 0 (zero) and the maxOccurs attribute set
* to 1 (one) or absent;
* * an attribute declaration with the use attribute set
* to optional or absent and carrying neither
* the default nor the fixed attribute;
*/
typeName = Utils.getWrapperType(typeName);
}
return typeName;
}
/**
* Returns the class name that should be used to serialize and
* deserialize this binary element
*/
protected String getBinaryTypeEncoderName(String elementName)
{
TypeEntry type = getElementDecl(elementName);
if (type != null)
{
String typeName = type.getQName().getLocalPart();
if (typeName.equals("base64Binary"))
return "org.apache.axis.encoding.Base64";
if (typeName.equals("hexBinary"))
return "org.apache.axis.types.HexBinary";
throw new java.lang.RuntimeException("Unknown binary type " +
typeName + " for element " + elementName);
}
throw new java.lang.RuntimeException("Unknown element " + elementName);
}
/**
* Returns the TypeEntry of the given element
*/
protected TypeEntry getElementDecl(String elementName)
{
if (elements != null) {
for (int i = 0; i < elements.size(); i++) {
ElementDecl elem = (ElementDecl) elements.get(i);
String variableName;
if (elem.getAnyElement()) {
variableName = Constants.ANYCONTENT;
} else {
variableName = elem.getName();
}
if (variableName.equals(elementName))
return elem.getType();
}
}
return null;
}
/**
* Returns the appropriate extends text
*
* @return "" or "abstract "
*/
protected String getClassModifiers() {
Node node = type.getNode();
if (node != null) {
if (JavaUtils.isTrueExplicitly(Utils.getAttribute(node,
"abstract"))) {
return super.getClassModifiers() + "abstract ";
}
}
return super.getClassModifiers();
} // getClassModifiers
/**
* Returns the appropriate extends text
*
* @return "" or " extends &lt;class&gt; "
*/
protected String getExtendsText() {
// See if this class extends another class
String extendsText = "";
if ((extendType != null) && !isUnion()
&& (!type.isSimpleType() || !extendType.isBaseType())
&& (extendType.getDimensions().length() == 0)) {
extendsText = " extends " + extendType.getName() + " ";
}
return extendsText;
}
/**
* Returns the appropriate implements text
*
* @return " implements &lt;classes&gt; "
*/
protected String getImplementsText() {
// See if this class extends another class
String implementsText = " implements java.io.Serializable";
if (type.isSimpleType() &&
(isUnion() || extendType == null || extendType.isBaseType()))
{
implementsText += ", org.apache.axis.encoding.SimpleType";
}
if (isAny) {
implementsText += ", org.apache.axis.encoding.AnyContentType";
}
if (isMixed) {
implementsText += ", org.apache.axis.encoding.MixedContentType";
}
implementsText += " ";
return implementsText;
}
/**
* Writes the member fields.
*/
protected void writeMemberFields() {
// Define the member element of the bean
if (isUnion()) {
pw.println(" private java.lang.String _value;");
return;
}
for (int i = 0; i < names.size(); i += 2) {
// get comments for this field
String comments = "";
if (elements != null)
{
if (elements != null && i < (elements.size()*2))
{
ElementDecl elem = (ElementDecl)elements.get(i/2);
comments = elem.getDocumentation();
}
}
String typeName = (String) names.get(i);
String variable = (String) names.get(i + 1);
// Declare the bean element
if (comments != null && comments.trim().length() > 0)
{
String flatComments = getJavadocDescriptionPart(comments, true).substring(7);
// it will be flat if it fits on one line
pw.println(" /* " + flatComments.trim() + " */");
}
pw.print(" private " + typeName + " " + variable + ";");
// label the attribute fields.
if ((elements == null) || (i >= (elements.size() * 2))) {
pw.println(" // attribute");
} else {
pw.println();
}
pw.println();
}
}
/**
* Writes the default constructor.
*/
protected void writeDefaultConstructor() {
// Define the default constructor
pw.println(" public " + className + "() {");
pw.println(" }");
pw.println();
}
/**
* Write a constructor containing the fields in this class.
* Will not write a construtor with more than 254 arguments as
* the Java compiler will choke.
*/
protected void writeMinimalConstructor() {
if (isUnion() || names.size() == 0 || names.size() > 254) {
return;
}
pw.println(" public " + className + "(");
for (int i = 0; i < names.size(); i += 2) {
String typeName = (String) names.get(i);
String variable = (String) names.get(i + 1);
pw.print(" " + typeName + " "
+ variable);
if (i >= names.size() - 2) {
pw.println(") {");
} else {
pw.println(",");
}
}
for (int i = 0; i < names.size(); i += 2) {
String variable = (String) names.get(i + 1);
pw.println(" this." + variable + " = " + variable + ";");
if (i >= names.size() - 2) {
break;
}
}
pw.println(" }");
pw.println();
}
/**
* Writes the full constructor.
* Note that this class is not recommended for
* JSR 101 compliant beans, but is provided for
* extended classes which may wish to generate a full
* constructor.
*/
protected void writeFullConstructor() {
if (type.isSimpleType()) {
return;
}
// The constructor needs to consider all extended types
Vector extendList = new Vector();
extendList.add(type);
TypeEntry parent = extendType;
while (parent != null) {
if (parent.isSimpleType())
return;
extendList.add(parent);
parent =
SchemaUtils.getComplexElementExtensionBase(parent.getNode(),
emitter.getSymbolTable());
}
// Now generate a list of names and types starting with
// the oldest parent. (Attrs are considered before elements).
Vector paramTypes = new Vector();
Vector paramNames = new Vector();
boolean gotAny = false;
for (int i = extendList.size() - 1; i >= 0; i--) {
TypeEntry te = (TypeEntry) extendList.elementAt(i);
// The names of the inherited parms are mangled
// in case they interfere with local parms.
String mangle = "";
if (i > 0) {
mangle = "_"
+ JavaUtils.xmlNameToJava(te.getQName().getLocalPart())
+ "_";
}
// Process the attributes
Vector attributes = te.getContainedAttributes();
if (attributes != null) {
for (int j = 0; j < attributes.size(); j += 1) {
ContainedAttribute attr = (ContainedAttribute) attributes.get(j);
String name = getAttributeName(attr);
String typeName = attr.getType().getName();
// TODO - What about MinOccurs and Nillable?
// Do they make sense here?
if (attr.getOptional()) {
typeName = Utils.getWrapperType(typeName);
}
paramTypes.add(typeName);
paramNames.add(JavaUtils.getUniqueValue(
helper.reservedPropNames, name));
}
}
// Process the elements
Vector elements = te.getContainedElements();
if (elements != null) {
for (int j = 0; j < elements.size(); j++) {
ElementDecl elem = (ElementDecl) elements.get(j);
if (elem.getAnyElement()) {
if (!gotAny) {
gotAny = true;
paramTypes.add("org.apache.axis.message.MessageElement []");
paramNames.add(Constants.ANYCONTENT);
}
} else {
paramTypes.add(processTypeName(elem,elem.getType().getName()));
String name = elem.getName() == null ? ("param" + i) : elem.getName();
paramNames.add(JavaUtils.getUniqueValue(
helper.reservedPropNames, name));
}
}
}
}
if (isMixed && !isAny && !parentIsAny && !parentIsMixed) {
paramTypes.add("org.apache.axis.message.MessageElement []");
paramNames.add(Constants.ANYCONTENT);
}
// Set the index where the local params start
int localParams = paramTypes.size() - names.size() / 2;
// Now write the constructor signature
if (paramTypes.size() > 0 && paramTypes.size() < 255) {
// Prevent name clash between local parameters and the
// parameters for the super class
if(localParams > 0) {
for (int j = 0; j < localParams; j++) {
String name = (String) paramNames.elementAt(j);
if(paramNames.indexOf(name, localParams)!=-1){
paramNames.set(j, "_" + name);
}
}
}
pw.println(" public " + className + "(");
for (int i = 0; i < paramTypes.size(); i++) {
pw.print(" " + paramTypes.elementAt(i) + " "
+ paramNames.elementAt(i));
if ((i + 1) < paramTypes.size()) {
pw.println(",");
} else {
pw.println(") {");
}
}
// Call the extended constructor to set inherited fields
if ((extendType != null) && (localParams > 0)) {
pw.println(" super(");
for (int j = 0; j < localParams; j++) {
pw.print(" " + paramNames.elementAt(j));
if ((j + 1) < localParams) {
pw.println(",");
} else {
pw.println(");");
}
}
}
// Set local fields directly
for (int j = localParams; j < paramNames.size(); j++) {
pw.println(" this." + paramNames.elementAt(j) + " = "
+ paramNames.elementAt(j) + ";");
}
pw.println(" }");
pw.println();
}
}
/**
* Writes the constructors for SimpleTypes.
* Writes a constructor accepting a string and
* a constructor accepting the simple java type.
*/
protected void writeSimpleConstructors() {
// If this is a simple type,need to emit a string
// constructor and a value construtor.
if (!type.isSimpleType())
return;
pw.println(" // " + Messages.getMessage("needStringCtor"));
// Simple types without simpleValueTypes are derived classes.
// Inherit the simple constructor.
if (simpleValueTypes.size() == 0)
{
if (extendType != null)
{
// Find the java type of the most base type.
TypeEntry baseType = type;
while (true)
{
TypeEntry superType = SchemaUtils.getBaseType(
baseType, emitter.getSymbolTable());
if (superType == null)
break;
else
baseType = superType;
}
String baseJavaType = baseType.getName();
pw.println(" public " + className + "("
+ baseJavaType + " _value) {");
pw.println(" super(_value);");
pw.println(" }");
pw.println();
}
}
else if (isUnion() || simpleValueTypes.get(0).equals("java.lang.String")) {
pw.println(" public " + className
+ "(java.lang.String _value) {");
pw.println(" this._value = _value;");
pw.println(" }");
int i = 0;
for (Iterator iterator = simpleValueTypes.iterator();
iterator.hasNext();) {
String typeName = (String) iterator.next();
if (typeName.equals("java.lang.String")) {
i += 2;
continue;
}
String capName = "_value";
if (isUnion()) {
// names and simpleValueTypes should match as
// union is over simple types
String name = (String) names.get(i + 1);
capName = Utils.capitalizeFirstChar(name);
}
pw.println(" public " + className + "(" + typeName
+ " _value) {");
pw.println(" set" + capName + "(_value);");
pw.println(" }");
pw.println();
i += 2;
}
} else if (simpleValueTypes.size() == 1) {
pw.println(" public " + className + "("
+ simpleValueTypes.get(0) + " _value) {");
pw.println(" this._value = _value;");
pw.println(" }");
pw.println(" public " + className
+ "(java.lang.String _value) {");
writeSimpleTypeGetter((String) simpleValueTypes.get(0), null,
"this._value =");
pw.println(" }");
pw.println();
}
}
/**
* Method writeSimpleTypeGetter
*
* @param simpleValueType
* @param name
* @param returnString
*/
protected void writeSimpleTypeGetter(String simpleValueType, String name,
String returnString) {
// Make sure we wrap base types with its Object type
String wrapper = JavaUtils.getWrapper(simpleValueType);
if (wrapper != null) {
pw.println(" " + returnString + " new " + wrapper
+ "(_value)." + simpleValueType + "Value();");
} else {
if (simpleValueType.equals("byte[]")) {
String encoder = getBinaryTypeEncoderName ("_value");
pw.println(" " + returnString
+ " " + encoder + ".decode(_value);");
} else if (simpleValueType.equals("org.apache.axis.types.URI")) {
pw.println(" try {");
pw.println(" " + returnString
+ " new org.apache.axis.types.URI(_value);");
pw.println(" }");
pw.println(
" catch (org.apache.axis.types.URI.MalformedURIException mue) {");
pw.println(
" throw new java.lang.RuntimeException(mue.toString());");
pw.println(" }");
} else if (simpleValueType.equals("java.util.Date")) {
pw.println(" try {");
pw.println(
" " + returnString
+ " (java.text.DateFormat.getDateTimeInstance()).parse(_value);");
pw.println(" }");
pw.println(" catch (java.text.ParseException e){");
pw.println(
" throw new java.lang.RuntimeException(e.toString());");
pw.println(" }");
} else if (simpleValueType.equals("java.util.Calendar")) {
pw.println(" java.util.Calendar cal =");
pw.println(
" (java.util.Calendar) new org.apache.axis.encoding.ser.CalendarDeserializer(");
pw.println(
" java.lang.String.class, org.apache.axis.Constants.XSD_STRING).makeValue(_value);");
pw.println(" " + returnString + " cal;");
} else if (enumerationTypes.contains(simpleValueType)) {
// we're generating code that will obtain a reference to an enumeration: use the
// class forString interface, not the constructor. Bug 19069
pw.println(" " + returnString + " " + simpleValueType
+ ".fromString(_value);");
} else {
pw.println(" " + returnString + " new "
+ simpleValueType + "(_value);");
}
}
}
/**
* Method isUnion
*
* @return
*/
private boolean isUnion() {
return this.simpleValueTypes.size() > 1;
}
/**
* Writes the toString method
* Currently the toString method is only written for
* simpleTypes.
*/
protected void writeToStringMethod() {
// If this is a simple type, emit a toString
if (simpleValueTypes.size() == 0) {
return;
}
pw.println(" // " + Messages.getMessage("needToString"));
pw.println(" public java.lang.String toString() {");
if (isUnion() || simpleValueTypes.get(0).equals("java.lang.String")) {
pw.println(" return _value;");
} else {
String wrapper =
JavaUtils.getWrapper((String) simpleValueTypes.get(0));
if (wrapper != null) {
pw.println(" return new " + wrapper
+ "(_value).toString();");
} else {
String simpleValueType0 = (String)simpleValueTypes.get(0);
if (simpleValueType0.equals("byte[]")) {
String encoder = getBinaryTypeEncoderName ("_value");
pw.println(
" return _value == null ? null : " +
encoder + ".encode(_value);");
} else if (simpleValueType0.equals("java.util.Calendar")) {
pw.println(
" return _value == null ? null : new org.apache.axis.encoding.ser.CalendarSerializer().getValueAsString(_value, null);");
} else {
pw.println(
" return _value == null ? null : _value.toString();");
}
}
}
pw.println(" }");
pw.println();
}
/**
* Method writeSimpleTypeSetter
*
* @param simpleValueType
*/
protected void writeSimpleTypeSetter(String simpleValueType) {
String wrapper = JavaUtils.getWrapper(simpleValueType);
if (wrapper != null) {
pw.println(" this._value = new " + wrapper
+ "(_value).toString();");
} else {
if (simpleValueType.equals("byte[]")) {
String encoder = getBinaryTypeEncoderName ("_value");
pw.println(
" this._value = _value == null ? null : " +
encoder + ".encode(_value);");
} else if (simpleValueType.equals("java.util.Calendar")) {
pw.println(
" this._value = _value == null ? null : new org.apache.axis.encoding.ser.CalendarSerializer().getValueAsString(_value, null);");
} else {
pw.println(
" this._value = _value == null ? null : _value.toString();");
}
}
}
/**
* Writes the setter and getter methods
*/
protected void writeAccessMethods() {
int j = 0;
// Define getters and setters for the bean elements
for (int i = 0; i < names.size(); i += 2, j++) {
String typeName = (String) names.get(i);
String name = (String) names.get(i + 1);
String capName = Utils.capitalizeFirstChar(name);
String documentation = "";
if (elements != null)
{
if (elements != null && i < (elements.size()*2))
{
ElementDecl elem = (ElementDecl)elements.get(i/2);
documentation = elem.getDocumentation();
}
}
String get = "get";
if (typeName.equals("boolean")) {
get = "is";
}
String comment = getJavadocDescriptionPart(documentation, true);
if (comment.length() > 3) {
// remove the " *" at the front of the first line
comment = comment.substring(2);
}
if (enableGetters) {
try {
pw.println();
pw.println(" /**");
pw.println(" * Gets the " + name + " value for this " + getClassName() + ".");
pw.println(" * ");
pw.println(" * @return " + name + comment);
pw.println(" */");
} catch (DOMException e) {
// no comment
}
pw.println(" public " + typeName + " " + get + capName
+ "() {");
if (isUnion()) {
writeSimpleTypeGetter(typeName, name, "return");
} else {
pw.println(" return " + name + ";");
}
pw.println(" }");
pw.println();
}
if (enableSetters) {
try
{
String nm = (isUnion()) ? "_value" : name;
pw.println();
pw.println(" /**");
pw.println(" * Sets the " + nm + " value for this " + getClassName() + ".");
pw.println(" * ");
pw.println(" * @param " + nm + comment);
pw.println(" */");
}
catch (DOMException e)
{
// no comment
}
if (isUnion()) {
pw.println(" public void set" + capName + "(" + typeName
+ " _value) {");
writeSimpleTypeSetter(typeName);
} else {
pw.println(" public void set" + capName + "(" + typeName
+ " " + name + ") {");
pw.println(" this." + name + " = " + name + ";");
}
pw.println(" }");
pw.println();
}
// If this is a special collection type, insert extra
// java code so that the serializer/deserializer can recognize
// the class. This is not JAX-RPC, and will be replaced with
// compliant code when JAX-RPC determines how to deal with this case.
// These signatures comply with Bean Indexed Properties which seems
// 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 ((elements != null) && (j < elements.size())) {
ElementDecl elem = (ElementDecl) elements.get(j);
if (elem.getType().getQName().getLocalPart().indexOf("[") > 0) {
String compName =
typeName.substring(0, typeName.lastIndexOf("["));
if (enableGetters) {
pw.println(" public " + compName + " " + get
+ capName + "(int i) {");
pw.println(" return this." + name + "[i];");
pw.println(" }");
pw.println();
}
if (enableSetters) {
pw.println(" public void set" + capName + "(int i, "
+ compName + " _value) {");
// According to the section 7.2 of the JavaBeans
// specification, the indexed setter should not
// establish or grow the array. Thus the following
// code is not generated for compliance purposes.
/*
* int bracketIndex = typeName.indexOf("[");
* String newingName = typeName.substring(0, bracketIndex + 1);
* String newingSuffix = typeName.substring(bracketIndex + 1);
*
* pw.println(" if (this." + name + " == null ||");
* pw.println(" this." + name + ".length <= i) {");
* pw.println(" " + typeName + " a = new " +
* newingName + "i + 1" + newingSuffix + ";");
* pw.println(" if (this." + name + " != null) {");
* pw.println(" for(int j = 0; j < this." + name +
* ".length; j++)");
* pw.println(" a[j] = this." + name + "[j];");
* pw.println(" }");
* pw.println(" this." + name + " = a;");
* pw.println(" }");
*/
pw.println(" this." + name + "[i] = _value;");
pw.println(" }");
pw.println();
}
}
}
}
}
/**
* Writes a general purpose equals method
*/
protected void writeEqualsMethod() {
// The __equalsCalc field and synchronized method are necessary
// in case the object has direct or indirect references to itself.
pw.println(" private java.lang.Object __equalsCalc = null;");
pw.println(
" public synchronized boolean equals(java.lang.Object obj) {");
// First do the general comparison checks
pw.println(" if (!(obj instanceof " + className
+ ")) return false;");
pw.println(" " + className + " other = (" + className
+ ") obj;");
pw.println(" if (this == obj) return true;");
// Have we been here before ? return true if yes otherwise false
pw.println(" if (__equalsCalc != null) {");
pw.println(" return (__equalsCalc == obj);");
pw.println(" }");
pw.println(" __equalsCalc = obj;");
// Before checking the elements, check equality of the super class
String truth = "true";
if ((extendType != null) &&
(!type.isSimpleType() || simpleValueTypes.size() == 0))
{
truth = "super.equals(obj)";
}
pw.println(" boolean _equals;");
if (names.size() == 0) {
pw.println(" _equals = " + truth + ";");
} else if (isUnion()) {
pw.println(" _equals = " + truth + " && "
+ " this.toString().equals(obj.toString());");
} else {
pw.println(" _equals = " + truth + " && ");
for (int i = 0; i < names.size(); i += 2) {
String variableType = (String) names.get(i);
String variable = (String) names.get(i + 1);
String get = "get";
if (variableType.equals("boolean")) {
get = "is";
}
if (variableType.equals("int") || variableType.equals("long")
|| variableType.equals("short")
|| variableType.equals("float")
|| variableType.equals("double")
|| variableType.equals("boolean")
|| variableType.equals("byte")) {
pw.print(" this." + variable + " == other."
+ get + Utils.capitalizeFirstChar(variable)
+ "()");
} else if (variableType.indexOf("[") >= 0) {
// Use java.util.Arrays.equals to compare arrays.
pw.println(" ((this." + variable
+ "==null && other." + get
+ Utils.capitalizeFirstChar(variable)
+ "()==null) || ");
pw.println(" (this." + variable + "!=null &&");
pw.print(" java.util.Arrays.equals(this."
+ variable + ", other." + get
+ Utils.capitalizeFirstChar(variable) + "())))");
} else {
pw.println(" ((this." + variable
+ "==null && other." + get
+ Utils.capitalizeFirstChar(variable)
+ "()==null) || ");
pw.println(" (this." + variable + "!=null &&");
pw.print(" this." + variable
+ ".equals(other." + get
+ Utils.capitalizeFirstChar(variable) + "())))");
}
if (i == (names.size() - 2)) {
pw.println(";");
} else {
pw.println(" &&");
}
}
}
pw.println(" __equalsCalc = null;");
pw.println(" return _equals;");
pw.println(" }");
pw.println("");
}
/**
* Writes a general purpose hashCode method.
*/
protected void writeHashCodeMethod() {
// The __hashCodeCalc field and synchronized method are necessary
// in case the object has direct or indirect references to itself.
pw.println(" private boolean __hashCodeCalc = false;");
pw.println(" public synchronized int hashCode() {");
pw.println(" if (__hashCodeCalc) {");
pw.println(" return 0;");
pw.println(" }");
pw.println(" __hashCodeCalc = true;");
// Get the hashCode of the super class
String start = "1";
if ((extendType != null) && !type.isSimpleType()) {
start = "super.hashCode()";
}
pw.println(" int _hashCode = " + start + ";");
if (isUnion()) {
pw.println(" if (this._value != null) {");
pw.println(" _hashCode += this._value.hashCode();");
pw.println(" }");
}
for (int i = 0; !isUnion() && (i < names.size()); i += 2) {
String variableType = (String) names.get(i);
String variable = (String) names.get(i + 1);
String get = "get";
if (variableType.equals("boolean")) {
get = "is";
}
if (variableType.equals("int") || variableType.equals("short")
|| variableType.equals("byte")) {
pw.println(" _hashCode += " + get
+ Utils.capitalizeFirstChar(variable) + "();");
} else if (variableType.equals("boolean")) {
pw.println(" _hashCode += (" + get
+ Utils.capitalizeFirstChar(variable)
+ "() ? Boolean.TRUE : Boolean.FALSE).hashCode();");
} else if (variableType.equals("long")) {
pw.println(" _hashCode += new Long(" + get
+ Utils.capitalizeFirstChar(variable)
+ "()).hashCode();");
} else if (variableType.equals("float")) {
pw.println(" _hashCode += new Float(" + get
+ Utils.capitalizeFirstChar(variable)
+ "()).hashCode();");
} else if (variableType.equals("double")) {
pw.println(" _hashCode += new Double(" + get
+ Utils.capitalizeFirstChar(variable)
+ "()).hashCode();");
} else if (variableType.indexOf("[") >= 0) {
// The hashCode calculation for arrays is complicated.
// Wish there was a hashCode method in java.utils.Arrays !
// Get the hashCode for each element of the array which is not an array.
pw.println(" if (" + get
+ Utils.capitalizeFirstChar(variable)
+ "() != null) {");
pw.println(" for (int i=0;");
pw.println(
" i<java.lang.reflect.Array.getLength("
+ get + Utils.capitalizeFirstChar(variable) + "());");
pw.println(" i++) {");
pw.println(
" java.lang.Object obj = java.lang.reflect.Array.get("
+ get + Utils.capitalizeFirstChar(variable) + "(), i);");
pw.println(" if (obj != null &&");
pw.println(" !obj.getClass().isArray()) {");
pw.println(" _hashCode += obj.hashCode();");
pw.println(" }");
pw.println(" }");
pw.println(" }");
} else {
pw.println(" if (" + get
+ Utils.capitalizeFirstChar(variable)
+ "() != null) {");
pw.println(" _hashCode += " + get
+ Utils.capitalizeFirstChar(variable)
+ "().hashCode();");
pw.println(" }");
}
}
// Reset the __hashCodeCalc variable and return
pw.println(" __hashCodeCalc = false;");
pw.println(" return _hashCode;");
pw.println(" }");
pw.println("");
}
/** Generate a java source file and/or helper source file.
* If the emitter works in deploy mode and the class already exists, only the helper is generated.
* Otherwise, the java bean and helper source are generated.
*/
public void generate() throws IOException {
String fqcn = getPackage() + "." + getClassName();
if (emitter.isDeploy() && emitter.doesExist(fqcn)) {
if (emitter.isHelperWanted()) {
helper.generate();
}
} else {
super.generate();
}
}
} // class JavaBeanWriter