| /* |
| * 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 <class> " |
| */ |
| 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 <classes> " |
| */ |
| 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 |