Package org.apache.axis.wsdl.fromJava

Source Code of org.apache.axis.wsdl.fromJava.Types

/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2001-2002 The Apache Software Foundation.  All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution,
*    if any, must include the following acknowledgment:
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowledgment may appear in the software itself,
*    if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Axis" and "Apache Software Foundation" must
*    not be used to endorse or promote products derived from this
*    software without prior written permission. For written
*    permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
*    nor may "Apache" appear in their name, without prior written
*    permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation.  For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/

package org.apache.axis.wsdl.fromJava;

import org.apache.axis.AxisFault;
import org.apache.axis.Constants;
import org.apache.axis.encoding.Serializer;
import org.apache.axis.encoding.SerializerFactory;
import org.apache.axis.encoding.SimpleType;
import org.apache.axis.encoding.TypeMapping;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.apache.axis.utils.JavaUtils;
import org.apache.axis.utils.XMLUtils;
import org.apache.axis.wsdl.symbolTable.BaseTypeMapping;
import org.apache.axis.wsdl.symbolTable.SymbolTable;
import org.apache.axis.wsdl.symbolTable.Type;
import org.apache.axis.wsdl.symbolTable.TypeEntry;

import org.apache.axis.components.logger.LogFactory;
import org.apache.commons.logging.Log;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;

import javax.wsdl.Definition;
import javax.wsdl.WSDLException;
import javax.xml.namespace.QName;
import javax.xml.rpc.holders.Holder;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;

/**
*
* <p>Description: </p> This class is used to recursively serializes a Java Class into
* an XML Schema representation.
*
* It has utility methods to create a schema node, assosiate namespaces to the various types
*
*
* @author unascribed
*/
public class Types {
    protected static Log log = LogFactory.getLog(Types.class.getName());

    Definition def;
    Namespaces namespaces = null;
    TypeMapping tm;
    TypeMapping defaultTM;
    String targetNamespace;
    Element wsdlTypesElem = null;
    HashMap schemaTypes = null;
    HashMap schemaElementNames = null;
    HashMap schemaUniqueElementNames = null;
    List stopClasses = null;
    List beanCompatErrs = new ArrayList();

    /**
     * This class serailizes a <code>Class</code> to XML Schema. The constructor
     * provides the context for the streamed node within the WSDL document
     * @param def WSDL Definition Element to declare namespaces
     * @param tm TypeMappingRegistry to handle known types
     * @param defaultTM default TM
     * @param namespaces user defined or autogenerated namespace and prefix maps
     * @param targetNamespace targetNamespace of the document
     */
    public Types(Definition def,
                 TypeMapping tm,
                 TypeMapping defaultTM,
                 Namespaces namespaces,
                 String targetNamespace,
                 List stopClasses) {
        this.def = def;
        createDocumentFragment();
        this.tm = tm;
        this.defaultTM = defaultTM;
        this.namespaces = namespaces;
        this.targetNamespace = targetNamespace;
        this.stopClasses = stopClasses;
        schemaElementNames = new HashMap();
        schemaUniqueElementNames = new HashMap();
        schemaTypes = new HashMap();
    }

    /**
     * Load the types from the input wsdl file.
     * @param inputWSDL file or URL
     */
    public void loadInputTypes(String inputWSDL)
        throws IOException, WSDLException
    {

        // Read the input wsdl file into a Document
        Document doc = XMLUtils.newDocument(inputWSDL);

        // Search for the 'types' element
        NodeList elements = doc.getChildNodes();
        if (elements.getLength() > 0 &&
            elements.item(0).getLocalName().equals("definitions")) {
            elements = elements.item(0).getChildNodes();
            for (int i=0;
                 i < elements.getLength() && wsdlTypesElem == null;
                 i++) {
                Node node = elements.item(i);
                if (node.getLocalName() != null &&
                    node.getLocalName().equals("types")) {
                    wsdlTypesElem = (Element) node;
                }
            }
        }

        // If types element not found, there is no need to continue.
        if (wsdlTypesElem == null) {
            return;
        }

        // Import the types element into the Types docHolder document
        wsdlTypesElem =
            (Element) docHolder.importNode(wsdlTypesElem, true);
        docHolder.appendChild(wsdlTypesElem);

        // Create a symbol table and populate it with the input wsdl document
        BaseTypeMapping btm =
            new BaseTypeMapping() {
                    public String getBaseName(QName qNameIn) {
                        QName qName = new QName(
                              qNameIn.getNamespaceURI(),                                
                              qNameIn.getLocalPart());
                        Class cls = defaultTM.getClassForQName(qName);
                        if (cls == null)
                            return null;
                        else
                            return JavaUtils.getTextClassName(cls.getName());
                    }
                };
        SymbolTable symbolTable = new SymbolTable(btm,
                                                  true, false, false, false);
        symbolTable.populate(null, doc);

        // Walk the type/element entries in the symbol table and
        // add each one to the list of processed types.  This prevents
        // the types from being duplicated.
        Vector v = symbolTable.getTypes();
        for (int i=0; i < v.size(); i++) {
            TypeEntry te = (TypeEntry) v.elementAt(i);
            if (te instanceof org.apache.axis.wsdl.symbolTable.Element) {
                addToElementsList(te.getQName());
            } else if (te instanceof Type) {
                addToTypesList(te.getQName(),
                               te.getQName().getLocalPart());
            }
        }

   
    }

    /**
     * Serialize the Class as XML schema to the document.
     * Create a types node for the WSDL if one doesn't exist
     * Create a schema node for the Class namespace, if one doesn't exist
     *
     * In case of a primitive type, no need to stream out anything, just return
     * the QName of the primitive type
     *
     * @param type <code>Class</code> to generate the XML Schema info for
     * @return the QName of the generated Schema type, null if void
     */
    public QName writePartType(Class type, QName qname) throws AxisFault {
        //patch by costin to fix an NPE; commented out till we find out what the problem is
        //if you get NullPointerExceptions in this class, turn it on and submit some
        //replicable test data to the Axis team via bugzilla
        /*
        if( type==null ) {
            return null;
        }
        */
        if (type.getName().equals("void")) {
          return null;
        }

        if (Holder.class.isAssignableFrom(type)) {
            type = JavaUtils.getHolderValueType(type);
        }

        if (qname == null) {
            qname = getTypeQName(type);
            if (qname == null) {
                throw new AxisFault("Type was " + type.getName()); // FIXME!
            }
        }

        /**
         * No need to do anything if this is a simple type (i.e. in the
         * xsd or soap-enc schemas already)
         */
        String nsURI = qname.getNamespaceURI();
        if (Constants.isSchemaXSD(nsURI) ||
                (Constants.isSOAP_ENC(nsURI) &&
                  !"Array".equals(qname.getLocalPart()))) {
            return qname;
        }

        if (wsdlTypesElem == null) {
            writeWsdlTypesElement();
        }
        // If writeTypeAsElement returns null, then
        // then no element was written due to problems.
        // return an anytype in such situations.
        qname = writeTypeAsElement(type, qname);
        if (qname == null) {
            qname = Constants.XSD_ANYTYPE;
        }
        return qname;
    }

    /**
     * Create a schema element for the given type
     * @param type the class type
     * @return the QName of the generated Element or null if no element written
     */
    private QName writeTypeAsElement(Class type, QName qName) throws AxisFault {
        if (qName == null ||
            Constants.equals(Constants.SOAP_ARRAY, qName)) {
            qName = getTypeQName(type);
        }
        QName typeQName = writeTypeNamespace(type, qName);
        String elementType = writeType(type, qName);
        if (elementType != null) {
            Element element = createElementDecl(qName, elementType, isNullable(type));
            if (element != null)
                writeSchemaElement(typeQName,element);
            return qName;
        }
        return null;
    }

    /**
     * write out the namespace declaration and return the type QName for the
     * given <code>Class</code>
     *
     * @param type input Class
     * @param qName qname of the Class
     * @return QName for the schema type representing the class
     */
    private QName writeTypeNamespace(Class type, QName qName) {
        if (qName == null) {
            qName = getTypeQName(type);
        }
        String pref = def.getPrefix(qName.getNamespaceURI());
        if (pref == null)
          def.addNamespace(namespaces.getCreatePrefix(qName.getNamespaceURI()),
                           qName.getNamespaceURI());
        return qName;
    }

    /**
     * Return the QName of the specified javaType
     * @param javaType input javaType Class
     * @return QName
     */
    public QName getTypeQName(Class javaType) {
        QName qName = null;

        // Use the typeMapping information to lookup the qName.
        QName dQName = null;
        if (defaultTM != null) {
            dQName = defaultTM.getTypeQName(javaType);
        }
        if (tm != null) {
            qName = tm.getTypeQName(javaType);
        }
        if (qName == null) {
            qName = dQName;
        } else if (qName != null && qName != dQName) {
            // If the TM and default TM resulted in different
            // names, choose qName unless it is a schema namespace.
            // (i.e. prefer soapenc primitives over schema primitives)
            if (Constants.isSchemaXSD(qName.getNamespaceURI())) {
                qName = dQName;
            }
        }

        // If the javaType is an array and the qName is
        // SOAP_ARRAY, construct the QName using the
        // QName of the component type
        if (javaType.isArray() &&
            qName != null &&
            Constants.equals(Constants.SOAP_ARRAY, qName)) {
            Class componentType = javaType.getComponentType();
            // If component namespace uri == targetNamespace
            // Construct ArrayOf<componentLocalPart>
            // Else
            // Construct ArrayOf_<componentPrefix>_<componentLocalPart>
            QName cqName = getTypeQName(componentType);
            if (targetNamespace.equals(cqName.getNamespaceURI())) {
                qName = new QName(
                        targetNamespace,
                        "ArrayOf" + cqName.getLocalPart());
            } else {
                String pre = namespaces.getCreatePrefix(cqName.getNamespaceURI());
                qName = new QName(
                        targetNamespace,
                        "ArrayOf_" + pre + "_" + cqName.getLocalPart());
            }
            return qName;
        }

        // If a qName was not found construct one using the
        // class name information.
        if (qName == null) {
            String pkg = getPackageNameFromFullName(javaType.getName());
            String lcl = getLocalNameFromFullName(javaType.getName());

            String ns = namespaces.getCreate(pkg);
            namespaces.getCreatePrefix(ns);
            String localPart = lcl.replace('$', '_');
            qName = new QName(ns, localPart);
        }

        return qName;
    }

    /**
     * Utility method to get the package name from a fully qualified java class name
     * @param full input class name
     * @return package name
     */
    public static String getPackageNameFromFullName(String full) {
        if (full.lastIndexOf('.') < 0)
            return "";
        else
            return full.substring(0, full.lastIndexOf('.'));
    }

    /**
     * Utility method to get the local class name from a fully qualified java class name
     * @param full input class name
     * @return package name
     */
    public static String getLocalNameFromFullName(String full) {
        if (full.lastIndexOf('.') < 0)
            return full;
        else
            return full.substring(full.lastIndexOf('.')+1);
    }

    /**
     * Write out the given Element into the appropriate schema node.
     * If need be create the schema node as well
     *
     * @param qName qName to get the namespace of the schema node
     * @param element the Element to append to the Schema node
     */
    public void writeSchemaElement(QName qName, Element element) {
        if (wsdlTypesElem == null) {
            try {
                writeWsdlTypesElement();
            } catch (Exception e) {
                log.error(e);
                return;
            }
        }
        Element schemaElem = null;
        NodeList nl = wsdlTypesElem.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++ ) {
            NamedNodeMap attrs = nl.item(i).getAttributes();
            if (attrs != null) {
                for (int n = 0; n < attrs.getLength(); n++) {
                    Attr a = (Attr)attrs.item(n);
                    if (a.getName().equals("targetNamespace") &&
                        a.getValue().equals(qName.getNamespaceURI()))
                        schemaElem = (Element)nl.item(i);
                }
            }
        }
        if (schemaElem == null) {
            schemaElem = docHolder.createElement("schema");
            wsdlTypesElem.appendChild(schemaElem);
            schemaElem.setAttribute("xmlns", Constants.URI_DEFAULT_SCHEMA_XSD);
            schemaElem.setAttribute("targetNamespace", qName.getNamespaceURI());

            // Add SOAP-ENC namespace import
            Element importElem = docHolder.createElement("import");
            schemaElem.appendChild(importElem);
            importElem.setAttribute("namespace", Constants.URI_DEFAULT_SOAP_ENC);
        }
        schemaElem.appendChild(element);
    }

    /**
     * Get the Types element for the WSDL document. If not present, create one
     */
    private void writeWsdlTypesElement() {
        if (wsdlTypesElem == null) {
            // Create a <wsdl:types> element corresponding to the wsdl namespaces.
            wsdlTypesElem =
                    docHolder.createElementNS(Constants.NS_URI_WSDL11, "types");
            wsdlTypesElem.setPrefix(Constants.NS_PREFIX_WSDL);
        }
    }

    /**
     * Write a schema representation for the given <code>Class</code>. Recurse
     * through all the public fields as well as fields represented by java
     * bean compliant accessor methods.
     *
     * Then return the qualified string representation of the generated type
     *
     * @param type Class for which to generate schema
     * @return a prefixed string for the schema type
     */
    public String writeType(Class type) throws AxisFault {
        return writeType(type, null);
    }

    /**
     * Write a schema representation for the given <code>Class</code>. Recurse
     * through all the public fields as well as fields represented by java
     * bean compliant accessor methods.
     *
     * Then return the qualified string representation of the generated type
     *
     * @param type Class for which to generate schema
     * @param qName of the type to write
     * @return a prefixed string for the schema type
     */
    public String writeType(Class type, QName qName) throws AxisFault {
        // Get a corresponding QName if one is not provided
        if (qName == null ||
            Constants.equals(Constants.SOAP_ARRAY, qName)) {
            qName = getTypeQName(type);
        }

        // Quick return if schema type
        if (Constants.isSchemaXSD(qName.getNamespaceURI())) {
            return Constants.NS_PREFIX_SCHEMA_XSD + ":" +
                    qName.getLocalPart();
        } else if (Constants.isSOAP_ENC(qName.getNamespaceURI()) &&
                      !"Array".equals(qName.getLocalPart())) {
            return Constants.NS_PREFIX_SOAP_ENC + ":" +
                    qName.getLocalPart();
        }

        // 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 no factory is found, use the BeanSerializerFactory
        // if applicable, otherwise issue errors and treat as an anyType
        if (factory == null) {
            if (isBeanCompatible(type, true)) {
                factory = new BeanSerializerFactory(type, qName);
            } else {
                return null; // Don't return an element name
            }
        }

        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
        writeTypeNamespace(type, qName);

        // If an array the component type should be processed first
        String componentTypeName = null;
        Class componentType = null;
        if (type.isArray()) {
            String dimString = "[]";
            componentType = type.getComponentType();
            if (componentType.isArray()) {
                while (componentType.isArray()) {
                    dimString += "[]";
                    componentType = componentType.getComponentType();
                }
            }
            componentTypeName = writeType(componentType, null) + dimString;
        }

        String soapTypeName = qName.getLocalPart();
        String prefix = namespaces.getCreatePrefix(qName.getNamespaceURI());
        String prefixedName = prefix+":"+soapTypeName;

        // If processed before, or this is a known namespace, return
        if (!addToTypesList(qName, soapTypeName))
          return prefixedName;

        if (type.isArray()) {
            // ComplexType representation of array
            Element complexType = docHolder.createElement("complexType");
            writeSchemaElement(qName, complexType);
            complexType.setAttribute("name", soapTypeName);

            Element complexContent = docHolder.createElement("complexContent");
            complexType.appendChild(complexContent);

            Element restriction = docHolder.createElement("restriction");
            complexContent.appendChild(restriction);
            restriction.setAttribute("base",
                                     Constants.NS_PREFIX_SOAP_ENC + ":Array");

            Element attribute = docHolder.createElement("attribute");
            restriction.appendChild(attribute);
            attribute.setAttribute("ref",
                                   Constants.NS_PREFIX_SOAP_ENC +":arrayType");
            attribute.setAttribute(Constants.NS_PREFIX_WSDL +":arrayType",
                                   componentTypeName );
        } else {
            try {
                if (isEnumClass(type)) {
                    writeEnumType(qName, type);
                } else {
                    ser.writeSchema(this);
                }
            } catch (Exception e) {
                throw new AxisFault(JavaUtils.getMessage("writeSchemaProblem00", type.getName()), e);
            }
        }
        return prefixedName;
    }

    /**
     * Returns true if indicated type matches the JAX-RPC enumeration class.
     * Note: supports JSR 101 version 0.6 Public Draft
     */
    public static boolean isEnumClass(Class cls) {
        try {
            java.lang.reflect.Method m  = cls.getMethod("getValue", null);
            java.lang.reflect.Method m2 = cls.getMethod("toString", null);
            if (m != null && m2 != null) {
                java.lang.reflect.Method m3 =
                    cls.getDeclaredMethod("fromString",
                                          new Class[] {java.lang.String.class});
                java.lang.reflect.Method m4 =
                    cls.getDeclaredMethod("fromValue",
                                          new Class[] {m.getReturnType()});

                if (m3 != null &&
                    Modifier.isStatic(m3.getModifiers()) &&
                    Modifier.isPublic(m3.getModifiers()) &&
                    m4 != null &&
                    Modifier.isStatic(m4.getModifiers()) &&
                    Modifier.isPublic(m4.getModifiers())) {
                    // Return false if there is a setValue member method
                    try {
                        if (cls.getMethod("setValue",
                                          new Class[] {m.getReturnType()}) == null)
                            return true;
                        return false;
                    } catch (java.lang.NoSuchMethodException e) {
                        return true;
                    }
                }
            }
        } catch (java.lang.NoSuchMethodException e) {}
        return false;
    }

    /**
     * Write Enumeration Complex Type
     * (Only supports enumeration classes of string types)
     * @param qName QName of type.
     * @param cls class of type
     */
    private void writeEnumType(QName qName, Class cls)
        throws NoSuchMethodException, IllegalAccessException, AxisFault  {
        if (!isEnumClass(cls))
            return;
        // Get the base type of the enum class
        java.lang.reflect.Method m  = cls.getMethod("getValue", null);
        Class base = m.getReturnType();

        // Create simpleType, restriction elements
        Element simpleType = docHolder.createElement("simpleType");
        writeSchemaElement(qName, simpleType);
        simpleType.setAttribute("name", qName.getLocalPart());
        Element restriction = docHolder.createElement("restriction");
        simpleType.appendChild(restriction);
        String baseType = writeType(base, null);
        restriction.setAttribute("base", baseType);

        // Create an enumeration using the field values
        Field[] fields= cls.getDeclaredFields();
        for (int i=0; i < fields.length; i++) {
            Field field = fields[i];
            int mod = field.getModifiers();

            // Inspect each public static final field of the same type
            // as the base
            if (Modifier.isPublic(mod) &&
                Modifier.isStatic(mod) &&
                Modifier.isFinal(mod) &&
                field.getType() == base) {
                // Create an enumeration using the value specified
                Element enumeration = docHolder.createElement("enumeration");
                enumeration.setAttribute("value", field.get(null).toString());
                restriction.appendChild(enumeration);

            }
        }

    }

    /**
     * Create Element
     * @param qName the namespace of the created element
     * @param elementType schema type representation of the element
     * @param nullable nillable attribute of the element
     * @return the created Element
     */
    private Element createElementDecl(QName qName,
                                      String elementType,
                                      boolean nullable) {
        if (!addToElementsList(qName))
            return null;

        Element element = docHolder.createElement("element");

        //Generate an element name that matches the type.

        element.setAttribute("name", qName.getLocalPart());
        if (nullable)
            element.setAttribute("nillable", "true");
        element.setAttribute("type", elementType);
        return element;
    }

    /**
     * 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
     */
    public Element createElement(String elementName,
                                 String elementType,
                                 boolean nullable,
                                 boolean omittable,
                                 Document docHolder) {
        Element element = docHolder.createElement("element");
        element.setAttribute("name", elementName);
        if (nullable)
            element.setAttribute("nillable", "true");
        if (omittable) {
            element.setAttribute("minOccurs", "0");
            element.setAttribute("maxOccurs", "1");
        }
        element.setAttribute("type", elementType);
        return element;
    }


    /**
     * Create Attribute 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
     */
    public Element createAttributeElement(String elementName,
                                  String elementType,
                                  boolean nullable,
                                  Document docHolder) {
        Element element = docHolder.createElement("attribute");
        element.setAttribute("name", elementName);
        if (nullable)
            element.setAttribute("nillable", "true");
        element.setAttribute("type", elementType);
        return element;
    }

    /**
     * Is the given class one of the simple types?  In other words,
     * do we have a mapping for this type which is in the xsd or
     * soap-enc namespaces?
     *
     * @param type input Class
     * @return true if the type is a simple type
     */
    boolean isSimpleType(Class type) {
        QName qname = tm.getTypeQName(type);
        if (qname == null)
            return false// No mapping

        String nsURI = qname.getNamespaceURI();
        return (Constants.isSchemaXSD(nsURI) ||
                Constants.isSOAP_ENC(nsURI));
    }

    /**
     * Is the given class acceptable as an attribute
     * @param type input Class
     * @return true if the type is a simple, enum type or extends SimpleType
     */
    public boolean isAcceptableAsAttribute(Class type) {
        return isSimpleType(type) ||
            isEnumClass(type) ||
            implementsSimpleType(type);
    }

    /**
     * Does the class implement SimpleType
     * @param type input Class
     * @return true if the type implements SimpleType
     */
    boolean implementsSimpleType(Class type) {
        Class[] impls = type.getInterfaces();
        for(int i=0; i<impls.length; i++) {
            if (impls[i] == SimpleType.class) {
                return true;
            }
        }
        return false;
    }
    /**
     * Generates a unique element name for a given namespace of the form
     * el0, el1 ....
     *
     * @param qName the namespace for the generated element
     * @return elementname
     */
// *** NOT USED? ***
//
//    private String generateUniqueElementName(QName qName) {
//      Integer count = (Integer)schemaUniqueElementNames.get(qName.getNamespaceURI());
//      if (count == null)
//        count = new Integer(0);
//      else
//        count = new Integer(count.intValue() + 1);
//      schemaUniqueElementNames.put(qName.getNamespaceURI(), count);
//      return "el" + count.intValue();
//    }

    /**
     * Add the type to an ArrayList and return true if the Schema node
     * needs to be generated
     * If the type already exists, just return false to indicate that the type is already
     * generated in a previous iteration
     *
     * @param qName the name space of the type
     * @param typeName the name of the type
     * @return if the type is added returns true, else if the type is already present returns false
     */
    private boolean addToTypesList (QName qName, String typeName) {
        boolean added = false;
        ArrayList types = (ArrayList)schemaTypes.get(qName.getNamespaceURI());
        if (types == null) {
            types = new ArrayList();
            types.add(typeName);
            schemaTypes.put(qName.getNamespaceURI(), types);
            added = true;
        }
        else {
            if (!types.contains(typeName)) {
               types.add(typeName);
               added = true;
            }
        }

        // If addded, look at the namespace uri to see if the schema element should be
        // generated.
        if (added) {
            String prefix = namespaces.getCreatePrefix(qName.getNamespaceURI());
            if (prefix.equals(Constants.NS_PREFIX_SOAP_ENV) ||
                prefix.equals(Constants.NS_PREFIX_SOAP_ENC) ||
                prefix.equals(Constants.NS_PREFIX_SCHEMA_XSD) ||
                prefix.equals(Constants.NS_PREFIX_WSDL) ||
                prefix.equals(Constants.NS_PREFIX_WSDL_SOAP))
                return false;
            else
                return true;
        }
        return false;
    }

    /**
     * Add the element to an ArrayList and return true if the Schema element
     * needs to be generated
     * If the element already exists, just return false to indicate that the type is already
     * generated in a previous iteration
     *
     * @param qName the name space of the element
     * @return if the type is added returns true, else if the type is already present returns false
     */
    private boolean addToElementsList (QName qName) {
        if (qName == null) {
            return false;
        }

        boolean added = false;
        ArrayList elements = (ArrayList)schemaElementNames.get(qName.getNamespaceURI());
        if (elements == null) {
            elements = new ArrayList();
            elements.add(qName.getLocalPart());
            schemaElementNames.put(qName.getNamespaceURI(), elements);
            added = true;
        }
        else {
            if (!elements.contains(qName.getLocalPart())) {
               elements.add(qName.getLocalPart());
               added = true;
            }
        }
        return added;
    }


    /**
     * Determines if the field is nullable. All non-primitives except
     * for byte[] are nillable.
     *
     * @param type input Class
     * @return true if nullable
     */
    public boolean isNullable(Class type) {
        if (type.isPrimitive() ||
            (type.isArray() && type.getComponentType() == byte.class))
            return false;
        else
            return true;
    }


    /** todo ravi: Get rid of Doccument fragment and import node stuuf,
     *  once I have a handle on the wsdl4j mechanism to get at types.
     *
     *  Switch over notes: remove docHolder, docFragment in favor of wsdl4j Types
     */
    //DocumentFragment docFragment;
    Document docHolder;

    private void createDocumentFragment () {
        this.docHolder = XMLUtils.newDocument();
    }

    /**
     * Inserts the type fragment into the given wsdl document
     * @param doc
     */
    public void insertTypesFragment(Document doc) {

        if (wsdlTypesElem != null) {
            // Import the wsdlTypesElement into the doc.
            org.w3c.dom.Node node = doc.importNode(wsdlTypesElem, true);
            // Insert the imported element at the beginning of the document
            doc.getDocumentElement().
                insertBefore(node,
                             doc.getDocumentElement().getFirstChild());
        }
    }

    /**
     * Return the list of classes that we should not emit WSDL for.
     */
    public List getStopClasses() {
        return stopClasses;
    }

    /**
     * Create a DOM Element in this context
     */
    public Element createElement(String elementName)
    {
        return docHolder.createElement(elementName);
    }
   
    /**
     * isBeanCompatible
     * @param javaType Class
     * @param issueErrors if true, issue messages if not compatible
     * Returns true if it appears that this class is a bean and
     * can be mapped to a complexType
     */
    protected boolean isBeanCompatible(Class javaType,
                                       boolean issueErrors) {

        // Must be a non-primitive and non array
        if (javaType.isArray() ||
            javaType.isPrimitive()) {
            if (issueErrors &&
                !beanCompatErrs.contains(javaType)) {
                log.error(JavaUtils.getMessage("beanCompatType00",
                                               javaType.getName()));
                beanCompatErrs.add(javaType);
            }
            return false;
        }
       
        // Anything in the java or javax package that
        // does not have a defined mapping is excluded.
        if (javaType.getName().startsWith("java.") ||
            javaType.getName().startsWith("javax.")) {
            if (issueErrors &&
                !beanCompatErrs.contains(javaType)) {
                log.error(JavaUtils.getMessage("beanCompatPkg00",
                                               javaType.getName()));
                beanCompatErrs.add(javaType);
            }
            return false;
        }

        // Return true if appears to be an enum class
        if (JavaUtils.isEnumClass(javaType)) {
            return true;
        }
        // Must have a default public constructor if not
        // Throwable
        if (!java.lang.Throwable.class.isAssignableFrom(javaType)) {
            try {
                javaType.getConstructor(new Class[] {});
            } catch (java.lang.NoSuchMethodException e) {
                if (issueErrors &&
                    !beanCompatErrs.contains(javaType)) {
                    log.error(JavaUtils.getMessage("beanCompatConstructor00",
                                                   javaType.getName()));
                    beanCompatErrs.add(javaType);
                }
                return false;
            }
        }

        // Make sure superclass is compatible
        Class superClass = javaType.getSuperclass();
        if (superClass != null &&
            superClass != java.lang.Object.class &&
            superClass != java.lang.Exception.class &&
            superClass != java.lang.Throwable.class &&
            superClass != java.rmi.RemoteException.class &&
            superClass != org.apache.axis.AxisFault.class &&
            (stopClasses == null ||
             !(stopClasses.contains(superClass.getName()))) ) {

            if (!isBeanCompatible(superClass, false)) {

                if (issueErrors &&
                    !beanCompatErrs.contains(javaType)) {
                    log.error(JavaUtils.getMessage("beanCompatExtends00",
                                                   javaType.getName(),
                                                   superClass.getName(),
                                                    javaType.getName()));
                    beanCompatErrs.add(javaType);
                }
                return false;
            }
        }
        return true;
    }
   
}
TOP

Related Classes of org.apache.axis.wsdl.fromJava.Types

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.