Package org.apache.axis2.description.java2wsdl

Source Code of org.apache.axis2.description.java2wsdl.DefaultSchemaGenerator

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.axis2.description.java2wsdl;

import org.apache.axis2.AxisFault;
import org.apache.axis2.deployment.util.BeanExcludeInfo;
import org.apache.axis2.deployment.util.Utils;
import org.apache.axis2.description.AxisMessage;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.WSDL2Constants;
import org.apache.axis2.description.java2wsdl.bytecode.MethodTable;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaCollection;
import org.apache.ws.commons.schema.XmlSchemaComplexContent;
import org.apache.ws.commons.schema.XmlSchemaComplexContentExtension;
import org.apache.ws.commons.schema.XmlSchemaComplexType;
import org.apache.ws.commons.schema.XmlSchemaElement;
import org.apache.ws.commons.schema.XmlSchemaForm;
import org.apache.ws.commons.schema.XmlSchemaImport;
import org.apache.ws.commons.schema.XmlSchemaObject;
import org.apache.ws.commons.schema.XmlSchemaSequence;
import org.apache.ws.commons.schema.utils.NamespaceMap;
import org.apache.ws.commons.schema.utils.NamespacePrefixList;
import org.codehaus.jam.JAnnotation;
import org.codehaus.jam.JClass;
import org.codehaus.jam.JComment;
import org.codehaus.jam.JField;
import org.codehaus.jam.JMethod;
import org.codehaus.jam.JPackage;
import org.codehaus.jam.JParameter;
import org.codehaus.jam.JProperty;
import org.codehaus.jam.JamClassIterator;
import org.codehaus.jam.JamService;
import org.codehaus.jam.JamServiceFactory;
import org.codehaus.jam.JamServiceParams;
import org.w3c.dom.Document;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

public class DefaultSchemaGenerator implements Java2WSDLConstants, SchemaGenerator {

    private static final Log log = LogFactory.getLog(DefaultSchemaGenerator.class);

    public static final String NAME_SPACE_PREFIX = "ax2";// axis2 name space

    private static int prefixCount = 1;

    protected Map targetNamespacePrefixMap = new Hashtable();

    protected Map schemaMap = new Hashtable();

    protected XmlSchemaCollection xmlSchemaCollection = new XmlSchemaCollection();


    protected ClassLoader classLoader;

    protected String className;

    protected TypeTable typeTable = new TypeTable();

    // to keep loadded method using JAM
    protected JMethod methods[];

    //to store byte code method using Axis 1.x codes
    protected MethodTable methodTable;

    protected String schemaTargetNameSpace;

    protected String schema_namespace_prefix;

    protected String attrFormDefault = null;

    protected String elementFormDefault = null;

    protected ArrayList excludeMethods = new ArrayList();

    protected ArrayList extraClasses = null;

    protected boolean useWSDLTypesNamespace = false;

    protected Map pkg2nsmap = null;

    protected NamespaceGenerator nsGen = null;

    protected String targetNamespace = null;
    //to keep the list of operation which uses MR other than RPC MR
    protected ArrayList nonRpcMethods = new ArrayList();

    protected Class serviceClass = null;
    protected AxisService service;
    // location of the custom schema , if any
    protected String customSchemaLocation;
    // location of the class name to package mapping file
    // File is simple file with qualifiedClassName:SchemaQName
    protected String mappingFileLocation;

    //To check whether we need to generate Schema element for Exception
    protected boolean generateBaseException ;

    public NamespaceGenerator getNsGen() throws Exception {
        if (nsGen == null) {
            nsGen = new DefaultNamespaceGenerator();
        }
        return nsGen;
    }

    public void setNsGen(NamespaceGenerator nsGen) {
        this.nsGen = nsGen;
    }

    public DefaultSchemaGenerator(ClassLoader loader, String className,
                                  String schematargetNamespace,
                                  String schematargetNamespacePrefix,
                                  AxisService service)
            throws Exception {
        this.classLoader = loader;
        this.className = className;
        this.service = service;

        serviceClass = Class.forName(className, true, loader);
        methodTable = new MethodTable(serviceClass);

        this.targetNamespace = Java2WSDLUtils.targetNamespaceFromClassName(
                className, loader, getNsGen()).toString();

        if (schematargetNamespace != null
                && schematargetNamespace.trim().length() != 0) {
            this.schemaTargetNameSpace = schematargetNamespace;
        } else {
            this.schemaTargetNameSpace =
                    Java2WSDLUtils.schemaNamespaceFromClassName(className, loader, getNsGen())
                            .toString();
        }

        if (schematargetNamespacePrefix != null
                && schematargetNamespacePrefix.trim().length() != 0) {
            this.schema_namespace_prefix = schematargetNamespacePrefix;
        } else {
            this.schema_namespace_prefix = SCHEMA_NAMESPACE_PRFIX;
        }
    }

    //This will locad the custom schema file and add that into the schema map
    private void loadCustomSchemaFile(){
      if (customSchemaLocation != null) {
          try {
              DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
              documentBuilderFactory.setNamespaceAware(true);
              Document doc = documentBuilderFactory.newDocumentBuilder().parse(new File(customSchemaLocation));
              XmlSchema schema = xmlSchemaCollection.read(doc,null);
              schemaMap.put(schema.getTargetNamespace() ,schema);
          } catch (Exception e) {
              log.info(e.getMessage());
          }
      }
    }

    /**This will load the mapping file and update the Typetable with the Class name and the Qname
     * Mapping file look like
     * org.foo.bar.FooException|http://www.abc.com/soaframework/common/types|ErrorMessage
     */
    private void loadMappingFile(){
        if(mappingFileLocation != null){
            File file = new File(mappingFileLocation);
            BufferedReader input = null;
        try {
            input = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
            String line;
            while ((line = input.readLine()) != null) {
                line = line.trim();
                if (line.length() > 0 && line.charAt(0)!='#') {
                    String values [] = line.split("\\|");
                    if (values != null && values.length >2) {
                        typeTable.addComplexSchema(values[0],new QName(values[1] , values[2]));
                    }
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (input != null) {
                    input.close();
                }
            }
            catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        }
    }


    /**
     * Generates schema for all the parameters in method. First generates schema for all different
     * parameter type and later refers to them.
     *
     * @return Returns XmlSchema.
     * @throws Exception
     */
    public Collection generateSchema() throws Exception {
        loadCustomSchemaFile();
        loadMappingFile();
        JamServiceFactory factory = JamServiceFactory.getInstance();
        JamServiceParams jam_service_parms = factory.createServiceParams();
        //setting the classLoder
        //it can posible to add the classLoader as well
        jam_service_parms.addClassLoader(classLoader);
        jam_service_parms.includeClass(className);

        for (int count = 0; count < getExtraClasses().size(); ++count) {
            jam_service_parms.includeClass((String) getExtraClasses().get(count));
        }
        JamService jamService = factory.createService(jam_service_parms);
        QName extraSchemaTypeName;
        JamClassIterator jClassIter = jamService.getClasses();
        //all most all the time the ittr will have only one class in it
        while (jClassIter.hasNext()) {
            JClass jclass = (JClass) jClassIter.next();
            if (getActualQualifiedName(jclass).equals(className)) {
                /**
                 * Schema genertaion done in two stage 1. Load all the methods and
                 * create type for methods parameters (if the parameters are Bean
                 * then it will create Complex types foer those , and if the
                 * parameters are simple type which decribe in SimpleTypeTable
                 * nothing will happen) 2. In the next stage for all the methods
                 * messages and port types will be creteated
                 */
                JAnnotation annotation = jclass.getAnnotation(AnnotationConstants.WEB_SERVICE);
                JComment comment = jclass.getComment();
                if (comment !=null) {
                    System.out.println(comment.getText());
                }
                if (annotation != null) {
                    String tns =
                            annotation.getValue(AnnotationConstants.TARGETNAMESPACE).asString();
                    if (tns != null && !"".equals(tns)) {
                        targetNamespace = tns;
                        schemaTargetNameSpace = tns;
                    }
                        service.setName(Utils.getAnnotatedServiceName(serviceClass,annotation));
                }
                methods = processMethods(jclass.getDeclaredMethods());

            } else {
                //generate the schema type for extra classes
                extraSchemaTypeName = typeTable.getSimpleSchemaTypeName(getQualifiedName(jclass));
                if (extraSchemaTypeName == null) {
                    generateSchema(jclass);
                }
            }
        }
        return schemaMap.values();
    }

    protected JMethod[] processMethods(JMethod[] declaredMethods) throws Exception {
        ArrayList list = new ArrayList();
        //short the elements in the array
        Arrays.sort(declaredMethods);

        // since we do not support overload
        HashMap uniqueMethods = new HashMap();
        XmlSchemaComplexType methodSchemaType;
        XmlSchemaSequence sequence = null;

        for (int i = 0; i < declaredMethods.length; i++) {
            JMethod jMethod = declaredMethods[i];
            JAnnotation methodAnnon = jMethod.getAnnotation(AnnotationConstants.WEB_METHOD);
            if (methodAnnon != null) {
                if (methodAnnon.getValue(AnnotationConstants.EXCLUDE).asBoolean()) {
                    continue;
                }
            }
            String methodName = getSimpleName(jMethod);
            // no need to think abt this method , since that is system
            // config method
            if (excludeMethods.contains(methodName)) {
                continue;
            }

            if (uniqueMethods.get(methodName) != null) {
                log.warn("We don't support method overloading. Ignoring [" +
                        jMethod.getQualifiedName() + "]");
                continue;
            }

            if (!jMethod.isPublic()) {
                // no need to generate Schema for non public methods
                continue;
            }
            boolean addToService = false;
            AxisOperation axisOperation = service.getOperation(new QName(methodName));
            if (axisOperation == null) {
                axisOperation = Utils.getAxisOperationForJmethod(jMethod);
                if (WSDL2Constants.MEP_URI_ROBUST_IN_ONLY.equals(
                        axisOperation.getMessageExchangePattern())){
                    AxisMessage outMessage = axisOperation.getMessage(
                            WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
                    if (outMessage !=null ){
                        outMessage.setName(methodName + RESPONSE);
                    }
                }
                addToService = true;
            }
            // Maintain a list of methods we actually work with
            list.add(jMethod);

            processException(jMethod,axisOperation);
            uniqueMethods.put(methodName, jMethod);
            JParameter[] paras = jMethod.getParameters();
            String parameterNames[] = null;
            AxisMessage inMessage = axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
            if (inMessage != null) {
                inMessage.setName(methodName + Java2WSDLConstants.MESSAGE_SUFFIX);
            }
            if (paras.length > 0) {
                parameterNames = methodTable.getParameterNames(methodName);
                sequence = new XmlSchemaSequence();

                methodSchemaType = createSchemaTypeForMethodPart(methodName);
                methodSchemaType.setParticle(sequence);
                inMessage.setElementQName(typeTable.getQNamefortheType(methodName));
                service.addMessageElementQNameToOperationMapping(methodSchemaType.getQName(),
                        axisOperation);
            }

            for (int j = 0; j < paras.length; j++) {
                JParameter methodParameter = paras[j];
                String parameterName = null;
                JAnnotation paramterAnnon =
                        methodParameter.getAnnotation(AnnotationConstants.WEB_PARAM);
                if (paramterAnnon != null) {
                    parameterName =
                            paramterAnnon.getValue(AnnotationConstants.NAME).asString();
                }
                if (parameterName == null || "".equals(parameterName)) {
                    parameterName = (parameterNames != null && parameterNames[j] != null) ?
                            parameterNames[j] : getSimpleName(methodParameter);
                }
                JClass paraType = methodParameter.getType();
                if (nonRpcMethods.contains(getSimpleName(jMethod))) {
                    generateSchemaForType(sequence, null, getSimpleName(jMethod));
                    break;
                } else {
                    generateSchemaForType(sequence, paraType, parameterName);
                }
            }
            // for its return type
            JClass returnType = jMethod.getReturnType();

            if (!returnType.isVoidType()) {
                String partQname = methodName + RESPONSE;
                methodSchemaType =
                        createSchemaTypeForMethodPart(partQname);
                sequence = new XmlSchemaSequence();
                methodSchemaType.setParticle(sequence);
                JAnnotation returnAnnon =
                        jMethod.getAnnotation(AnnotationConstants.WEB_RESULT);
                String returnName = "return";
                if (returnAnnon != null) {
                    returnName = returnAnnon.getValue(AnnotationConstants.NAME).asString();
                    if (returnName != null && !"".equals(returnName)) {
                        returnName = "return";
                    }
                }
                if (nonRpcMethods.contains(getSimpleName(jMethod))) {
                    generateSchemaForType(sequence, null, returnName);
                } else {
                    generateSchemaForType(sequence, returnType, returnName);
                }
                AxisMessage outMessage = axisOperation.getMessage(
                        WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
                outMessage.setElementQName(typeTable.getQNamefortheType(partQname));
                outMessage.setName(partQname);
                service.addMessageElementQNameToOperationMapping(methodSchemaType.getQName(),
                        axisOperation);
            }
            if (addToService) {
                service.addOperation(axisOperation);
            }
        }
        return (JMethod[]) list.toArray(new JMethod[list.size()]);
    }

    /**
     *  This method will generate Schema element for all the excetion types in a given JMethod
     *  - No matter what it will generate Schema element for java.lang.Exception so that for other
     *    exception which extend java.lang.Excetion can use as the base class type
     */
    protected void processException(JMethod jMethod,
                                    AxisOperation axisOperation) throws Exception {
        XmlSchemaComplexType methodSchemaType;
        XmlSchemaSequence sequence;
        if (jMethod.getExceptionTypes().length > 0) {
            if (!generateBaseException) {
                if (typeTable.getComplexSchemaType(Exception.class.getName()) !=null) {

                } else {
                    sequence = new XmlSchemaSequence();
                    XmlSchema xmlSchema = getXmlSchema(schemaTargetNameSpace);
                    QName elementName = new QName(schemaTargetNameSpace,
                            "Exception",
                            schema_namespace_prefix);
                    XmlSchemaComplexType complexType = new XmlSchemaComplexType(xmlSchema);
                    complexType.setName("Exception");
                    xmlSchema.getItems().add(complexType);
                    xmlSchema.getElements().add(elementName, complexType);
                    typeTable.addComplexSchema(Exception.class.getName(), elementName);
                    QName schemaTypeName = TypeTable.ANY_TYPE;
                    addContentToMethodSchemaType(sequence,
                            schemaTypeName,
                            "Exception",
                            false);
                    complexType.setParticle(sequence);
                }
                generateBaseException = true;
            }
            JClass[] extypes = jMethod.getExceptionTypes();
            for (int j = 0; j < extypes.length; j++) {
                JClass extype = extypes[j];
                if (AxisFault.class.getName().equals(extype.getQualifiedName())) {
                    continue;
                }
                String partQname = extype.getSimpleName();
                methodSchemaType = createSchemaTypeForFault(partQname);
                QName elementName =
                        new QName(this.schemaTargetNameSpace, partQname, this.schema_namespace_prefix);
                sequence = new XmlSchemaSequence();
                if (Exception.class.getName().equals(extype.getQualifiedName())) {
                    QName schemaTypeName = typeTable.getComplexSchemaType(Exception.class.getName());
                    addContentToMethodSchemaType(sequence,
                            schemaTypeName,
                            partQname,
                            false);
                    methodSchemaType.setParticle(sequence);
                    typeTable.addComplexSchema(Exception.class.getPackage().getName(),
                            methodSchemaType.getQName());
                    String schemaNamespace = resolveSchemaNamespace(Exception.class.getPackage().getName());
                    addImport(getXmlSchema(schemaTargetNameSpace),schemaTypeName );
                } else {
                    generateSchemaForType(sequence, extype, extype.getSimpleName());
                    methodSchemaType.setParticle(sequence);
                }

                typeTable.addComplexSchema(partQname,elementName);

                if (AxisFault.class.getName().equals(extype.getQualifiedName())) {
                    continue;
                }
                AxisMessage faultMessage = new AxisMessage();
                faultMessage.setName(extype.getSimpleName());
                faultMessage.setElementQName(typeTable.getQNamefortheType(partQname));
                axisOperation.setFaultMessages(faultMessage);
            }
        }
    }

    /**
     * JAM converts the first letter of a field into uppercase, so field "foo" would end up
     * called "Foo".  This method corrects that problem.
     *
     * @param wrongName
     * @return the right name, using english as the locale for case conversion
     */
    public static String getCorrectName(String wrongName) {
        if (wrongName.length() > 1) {
            return wrongName.substring(0, 1).toLowerCase(Locale.ENGLISH)
                    + wrongName.substring(1, wrongName.length());
        } else {
            return wrongName.substring(0, 1).toLowerCase(Locale.ENGLISH);
        }
    }

    /**
     * Generate schema construct for given type
     * @param javaType : Class to whcih need to generate Schema
     * @return : Generated QName
     */
    private QName generateSchema(JClass javaType) throws Exception {
        String name = getQualifiedName(javaType);
        QName schemaTypeName = typeTable.getComplexSchemaType(name);
        if (schemaTypeName == null) {
            String simpleName = getSimpleName(javaType);

            String packageName = getQualifiedName(javaType.getContainingPackage());
            String targetNameSpace = resolveSchemaNamespace(packageName);

            XmlSchema xmlSchema = getXmlSchema(targetNameSpace);
            String targetNamespacePrefix = (String) targetNamespacePrefixMap.get(targetNameSpace);
            if (targetNamespacePrefix == null) {
                targetNamespacePrefix = generatePrefix();
                targetNamespacePrefixMap.put(targetNameSpace, targetNamespacePrefix);
            }

            XmlSchemaComplexType complexType = new XmlSchemaComplexType(xmlSchema);
            XmlSchemaSequence sequence = new XmlSchemaSequence();
            XmlSchemaComplexContentExtension complexExtension =
                    new XmlSchemaComplexContentExtension();

            XmlSchemaElement eltOuter = new XmlSchemaElement();
            schemaTypeName = new QName(targetNameSpace, simpleName, targetNamespacePrefix);
            eltOuter.setName(simpleName);
            eltOuter.setQName(schemaTypeName);

            JClass sup = javaType.getSuperclass();

            if ((sup != null) && !("java.lang.Object".compareTo(sup.getQualifiedName()) == 0) &&
                    !("org.apache.axis2".compareTo(sup.getContainingPackage().getQualifiedName()) == 0)
                    &&!("java.util".compareTo(sup.getContainingPackage().getQualifiedName()) == 0)) {
                String superClassName = sup.getQualifiedName();
                String superclassname = getSimpleName(sup);
                String tgtNamespace;
                String tgtNamespacepfx;
                QName qName = typeTable.getSimpleSchemaTypeName(superClassName);
                if (qName != null) {
                    tgtNamespace = qName.getNamespaceURI();
                    tgtNamespacepfx = qName.getPrefix();
                } else {
                    tgtNamespace =
                            resolveSchemaNamespace(sup.getContainingPackage().getQualifiedName());
                    tgtNamespacepfx = (String) targetNamespacePrefixMap.get(tgtNamespace);
                    QName superClassQname = generateSchema(sup);
                    if(superClassQname!=null){
                        tgtNamespacepfx = superClassQname.getPrefix();
                        tgtNamespace = superClassQname.getNamespaceURI();
                    }
                }

                if (tgtNamespacepfx == null) {
                    tgtNamespacepfx = generatePrefix();
                    targetNamespacePrefixMap.put(tgtNamespace, tgtNamespacepfx);
                }
                //if the parent class package name is differ from the child
                if (!((NamespaceMap) xmlSchema.getNamespaceContext()).values().
                        contains(tgtNamespace)) {
                    XmlSchemaImport importElement = new XmlSchemaImport();
                    importElement.setNamespace(tgtNamespace);
                    xmlSchema.getItems().add(importElement);
                    ((NamespaceMap) xmlSchema.getNamespaceContext()).
                            put(generatePrefix(),tgtNamespace);
                }

                QName basetype = new QName(tgtNamespace, superclassname, tgtNamespacepfx);


                complexExtension.setBaseTypeName(basetype);
                complexExtension.setParticle(sequence);

                XmlSchemaComplexContent contentModel = new XmlSchemaComplexContent();

                contentModel.setContent(complexExtension);

                complexType.setContentModel(contentModel);

            } else {
                complexType.setParticle(sequence);
            }

            complexType.setName(simpleName);

//            xmlSchema.getItems().add(eltOuter);
            xmlSchema.getElements().add(schemaTypeName, eltOuter);
            eltOuter.setSchemaTypeName(complexType.getQName());

            xmlSchema.getItems().add(complexType);
            xmlSchema.getSchemaTypes().add(schemaTypeName, complexType);

            // adding this type to the table
            typeTable.addComplexSchema(name, eltOuter.getQName());
            // adding this type's package to the table, to support inheritance.
            typeTable.addComplexSchema(javaType.getContainingPackage().getQualifiedName(),
                    eltOuter.getQName());


            Set propertiesSet = new HashSet();
            Set propertiesNames = new HashSet();

            JProperty[] tempProperties = javaType.getDeclaredProperties();
            BeanExcludeInfo beanExcludeInfo = null;
            if (service.getExcludeInfo() !=null) {
                beanExcludeInfo = service.getExcludeInfo().getBeanExcludeInfoForClass(
                        javaType.getQualifiedName());
            }
            for (int i = 0; i < tempProperties.length; i++) {
                JProperty tempProperty = tempProperties[i];
                String propertyName = getCorrectName(tempProperty.getSimpleName());
                if ((beanExcludeInfo == null) || !beanExcludeInfo.isExcludedProperty(propertyName)){
                    propertiesSet.add(tempProperty);
                }
            }

            JProperty[] properties = (JProperty[]) propertiesSet.toArray(new JProperty[0]);
            Arrays.sort(properties);
            for (int i = 0; i < properties.length; i++) {
                JProperty property = properties[i];
                boolean isArryType = property.getType().isArrayType();

                String propname = getCorrectName(property.getSimpleName());

                propertiesNames.add(propname);

                this.generateSchemaforFieldsandProperties(xmlSchema, sequence, property.getType(),
                        propname, isArryType);

            }

            JField[] tempFields = javaType.getDeclaredFields();
            HashMap FieldMap = new HashMap();


            for (int i = 0; i < tempFields.length; i++) {
                // create a element for the field only if it is public
                // and there is no property with the same name
                if (tempFields[i].isPublic()) {
                    if (tempFields[i].isStatic()){
//                        We do not need to expose static fields
                        continue;
                    }
                    String propertyName = getCorrectName(tempFields[i].getSimpleName());
                    if ((beanExcludeInfo == null) || !beanExcludeInfo.isExcludedProperty(propertyName)) {
                        // skip field with same name as a property
                        if (!propertiesNames.contains(tempFields[i].getSimpleName())) {

                            FieldMap.put(tempFields[i].getSimpleName(), tempFields[i]);
                        }
                    }
                   
                }

            }

            // remove fields from super classes patch for defect Annogen-21
            // getDeclaredFields is incorrectly returning fields of super classes as well
            // getDeclaredProperties used earlier works correctly
            JClass supr = javaType.getSuperclass();
            while (supr != null && supr.getQualifiedName().compareTo("java.lang.Object") != 0) {
                JField[] suprFields = supr.getFields();
                for (int i = 0; i < suprFields.length; i++) {
                    FieldMap.remove(suprFields[i].getSimpleName());
                }
                supr = supr.getSuperclass();
            }
            // end patch for Annogen -21

            JField[] froperties = (JField[]) FieldMap.values().toArray(new JField[0]);
            Arrays.sort(froperties);

            for (int i = 0; i < froperties.length; i++) {
                JField field = froperties[i];
                boolean isArryType = field.getType().isArrayType();

                this.generateSchemaforFieldsandProperties(xmlSchema, sequence, field.getType(),
                        field.getSimpleName(), isArryType);
            }


        }
        return schemaTypeName;
    }


    // moved code common to Fields & properties out of above method
    protected void generateSchemaforFieldsandProperties(XmlSchema xmlSchema,
                                                        XmlSchemaSequence sequence, JClass type,
                                                        String name, boolean isArryType)
            throws Exception {

        String propertyName;

        if (isArryType) {
            propertyName = getQualifiedName(type.getArrayComponentType());
        } else
            propertyName = getQualifiedName(type);

        if (isArryType && "byte".equals(propertyName)) {
            propertyName = "base64Binary";
        }
        if (isDataHandler(type)) {
            propertyName = "base64Binary";
        }

        if (typeTable.isSimpleType(propertyName)) {
            XmlSchemaElement elt1 = new XmlSchemaElement();
            elt1.setName(name);
            elt1.setSchemaTypeName(typeTable.getSimpleSchemaTypeName(propertyName));
            sequence.getItems().add(elt1);

            if (isArryType && (!propertyName.equals("base64Binary"))) {
                elt1.setMaxOccurs(Long.MAX_VALUE);
            }
            elt1.setMinOccurs(0);
            if (!type.isPrimitiveType()) {
                elt1.setNillable(true);
            }
        } else {
            if (isArryType) {
                generateSchema(type.getArrayComponentType());
            } else {
                generateSchema(type);
            }
            XmlSchemaElement elt1 = new XmlSchemaElement();
            elt1.setName(name);
            elt1.setSchemaTypeName(typeTable.getComplexSchemaType(propertyName));
            sequence.getItems().add(elt1);
            if (isArryType) {
                elt1.setMaxOccurs(Long.MAX_VALUE);
            }
            elt1.setMinOccurs(0);
            elt1.setNillable(true);

            if (!((NamespaceMap) xmlSchema.getNamespaceContext()).values().
                    contains(typeTable.getComplexSchemaType(propertyName).getNamespaceURI())) {
                XmlSchemaImport importElement = new XmlSchemaImport();
                importElement.setNamespace(
                        typeTable.getComplexSchemaType(propertyName).getNamespaceURI());
                xmlSchema.getItems().add(importElement);
                ((NamespaceMap) xmlSchema.getNamespaceContext()).
                        put(generatePrefix(),
                                typeTable.getComplexSchemaType(propertyName).getNamespaceURI());
            }
        }


    }


    private QName generateSchemaForType(XmlSchemaSequence sequence, JClass type, String partName)
            throws Exception {

        boolean isArrayType = false;
        if (type != null) {
            isArrayType = type.isArrayType();
        }
        if (isArrayType) {
            type = type.getArrayComponentType();
        }
        if (AxisFault.class.getName().equals(type)) {
            return null;
        }
        String classTypeName;
        if (type == null) {
            classTypeName = "java.lang.Object";
        } else {
            classTypeName = getQualifiedName(type);
        }
        if (isArrayType && "byte".equals(classTypeName)) {
            classTypeName = "base64Binary";
            isArrayType = false;
        }

        if (isDataHandler(type)) {
            classTypeName = "base64Binary";
        }
        QName schemaTypeName = typeTable.getSimpleSchemaTypeName(classTypeName);
        if (schemaTypeName == null) {
            schemaTypeName = generateSchema(type);
            addContentToMethodSchemaType(sequence,
                    schemaTypeName,
                    partName,
                    isArrayType);
            String schemaNamespace;
            schemaNamespace = resolveSchemaNamespace(getQualifiedName(type.getContainingPackage()));
            addImport(getXmlSchema(schemaNamespace), schemaTypeName);

        } else {
            addContentToMethodSchemaType(sequence,
                    schemaTypeName,
                    partName,
                    isArrayType);
        }
        addImport(getXmlSchema(schemaTargetNameSpace), schemaTypeName);
        return schemaTypeName;
    }

    protected boolean isDataHandler(JClass clazz){
        if(clazz == null ){
            return false;
        }
        String classType = clazz.getQualifiedName();
        if("java.lang.Object".equals(classType)){
            return false;
        }
        if ("javax.activation.DataHandler".equals(classType)) {
            return true;
        } else {
            JClass supuerClass = clazz.getSuperclass();
            if (supuerClass != null) {
                return isDataHandler(supuerClass);
            } else {
                return false;
            }
        }
    }

    protected void addContentToMethodSchemaType(XmlSchemaSequence sequence,
                                                QName schemaTypeName,
                                                String paraName,
                                                boolean isArray) {
        XmlSchemaElement elt1 = new XmlSchemaElement();
        elt1.setName(paraName);
        elt1.setSchemaTypeName(schemaTypeName);
        if (sequence != null) {
            sequence.getItems().add(elt1);
        }

        if (isArray) {
            elt1.setMaxOccurs(Long.MAX_VALUE);
        }
        elt1.setMinOccurs(0);
        if (!("int".equals(schemaTypeName.getLocalPart()) ||
                "double".equals(schemaTypeName.getLocalPart()) ||
                "long".equals(schemaTypeName.getLocalPart()) ||
                "boolean".equals(schemaTypeName.getLocalPart()) ||
                "short".equals(schemaTypeName.getLocalPart()) ||
                "float".equals(schemaTypeName.getLocalPart()) )) {
            elt1.setNillable(true);
        }
    }

    private XmlSchemaComplexType createSchemaTypeForMethodPart(String localPartName) {
        XmlSchema xmlSchema = getXmlSchema(schemaTargetNameSpace);
        QName elementName =
                new QName(this.schemaTargetNameSpace, localPartName, this.schema_namespace_prefix);

        XmlSchemaComplexType complexType = getComplexTypeForElement(xmlSchema, elementName);
        if (complexType == null) {
            complexType = new XmlSchemaComplexType(xmlSchema);

            XmlSchemaElement globalElement = new XmlSchemaElement();
            globalElement.setSchemaType(complexType);
            globalElement.setName(localPartName);
            globalElement.setQName(elementName);
            xmlSchema.getItems().add(globalElement);
            xmlSchema.getElements().add(elementName, globalElement);
        }
        typeTable.addComplexSchema(localPartName, elementName);

        return complexType;
    }

    private XmlSchemaComplexType createSchemaTypeForFault(String localPartName) {
        XmlSchema xmlSchema = getXmlSchema(schemaTargetNameSpace);
        QName elementName =
                new QName(this.schemaTargetNameSpace, localPartName, this.schema_namespace_prefix);

        XmlSchemaComplexType complexType = getComplexTypeForElement(xmlSchema, elementName);
        if (complexType == null) {
            complexType = new XmlSchemaComplexType(xmlSchema);

            XmlSchemaElement globalElement = new XmlSchemaElement();
            globalElement.setSchemaType(complexType);
            globalElement.setName(localPartName);
            globalElement.setQName(elementName);
            xmlSchema.getItems().add(globalElement);
            xmlSchema.getElements().add(elementName, globalElement);
        }
        return complexType;
    }

    protected XmlSchemaComplexType getComplexTypeForElement(XmlSchema xmlSchema, QName name) {
        Iterator iterator = xmlSchema.getItems().getIterator();
        while (iterator.hasNext()) {
            XmlSchemaObject object = (XmlSchemaObject) iterator.next();
            if (object instanceof XmlSchemaElement && ((XmlSchemaElement) object).getQName().equals(name)) {
                return (XmlSchemaComplexType) ((XmlSchemaElement) object).getSchemaType();
            }
        }
        return null;
    }

    protected XmlSchema getXmlSchema(String targetNamespace) {
        XmlSchema xmlSchema;

        if ((xmlSchema = (XmlSchema) schemaMap.get(targetNamespace)) == null) {
            String targetNamespacePrefix;

            if (targetNamespace.equals(schemaTargetNameSpace) &&
                    schema_namespace_prefix != null) {
                targetNamespacePrefix = schema_namespace_prefix;
            } else {
                targetNamespacePrefix = generatePrefix();
            }


            xmlSchema = new XmlSchema(targetNamespace, xmlSchemaCollection);
            xmlSchema.setAttributeFormDefault(getAttrFormDefaultSetting());
            xmlSchema.setElementFormDefault(getElementFormDefaultSetting());


            targetNamespacePrefixMap.put(targetNamespace, targetNamespacePrefix);
            schemaMap.put(targetNamespace, xmlSchema);

            NamespaceMap prefixmap = new NamespaceMap();
            prefixmap.put(DEFAULT_SCHEMA_NAMESPACE_PREFIX, URI_2001_SCHEMA_XSD);
            prefixmap.put(targetNamespacePrefix, targetNamespace);
            xmlSchema.setNamespaceContext(prefixmap);
        }
        return xmlSchema;
    }


    public TypeTable getTypeTable() {
        return typeTable;
    }

    public JMethod[] getMethods() {
        return methods;
    }

    protected String generatePrefix() {
        return NAME_SPACE_PREFIX + prefixCount++;
    }

    public void setExcludeMethods(ArrayList excludeMethods) {
        if (excludeMethods == null) excludeMethods = new ArrayList();
        this.excludeMethods = excludeMethods;
    }

    public String getSchemaTargetNameSpace() {
        return schemaTargetNameSpace;
    }

    protected void addImport(XmlSchema xmlSchema, QName schemaTypeName) {
        NamespacePrefixList map = xmlSchema.getNamespaceContext();
        if (map == null ||
                ((map instanceof NamespaceMap) && ((NamespaceMap) map).values() == null) ||
                schemaTypeName == null){
            return;
        }
        if (map instanceof NamespaceMap && !((NamespaceMap) map).values().
                contains(schemaTypeName.getNamespaceURI())) {
            XmlSchemaImport importElement = new XmlSchemaImport();
            importElement.setNamespace(schemaTypeName.getNamespaceURI());
            xmlSchema.getItems().add(importElement);
            ((NamespaceMap) xmlSchema.getNamespaceContext()).
                    put(generatePrefix(), schemaTypeName.getNamespaceURI());
        }
    }

    public String getAttrFormDefault() {
        return attrFormDefault;
    }

    public void setAttrFormDefault(String attrFormDefault) {
        this.attrFormDefault = attrFormDefault;
    }

    public String getElementFormDefault() {
        return elementFormDefault;
    }

    public void setElementFormDefault(String elementFormDefault) {
        this.elementFormDefault = elementFormDefault;
    }

    protected XmlSchemaForm getAttrFormDefaultSetting() {
        if (FORM_DEFAULT_UNQUALIFIED.equals(getAttrFormDefault())) {
            return new XmlSchemaForm(XmlSchemaForm.UNQUALIFIED);
        } else {
            return new XmlSchemaForm(XmlSchemaForm.QUALIFIED);
        }
    }

    protected XmlSchemaForm getElementFormDefaultSetting() {
        if (FORM_DEFAULT_UNQUALIFIED.equals(getElementFormDefault())) {
            return new XmlSchemaForm(XmlSchemaForm.UNQUALIFIED);
        } else {
            return new XmlSchemaForm(XmlSchemaForm.QUALIFIED);
        }
    }

    public ArrayList getExtraClasses() {
        if (extraClasses == null) {
            extraClasses = new ArrayList();
        }
        return extraClasses;
    }

    public void setExtraClasses(ArrayList extraClasses) {
        this.extraClasses = extraClasses;
    }

    protected String resolveSchemaNamespace(String packageName) throws Exception {
        //if all types must go into the wsdl types schema namespace
        if (useWSDLTypesNamespace) {
            //return schemaTargetNameSpace;
            return (String) pkg2nsmap.get("all");
        } else {
            if (pkg2nsmap != null && !pkg2nsmap.isEmpty()) {
                //if types should go into namespaces that are mapped against the package name for the type
                if (pkg2nsmap.get(packageName) != null) {
                    //return that mapping
                    return (String) pkg2nsmap.get(packageName);
                } else {
                    return getNsGen().schemaNamespaceFromPackageName(packageName).toString();
                }
            } else {
                // if  pkg2nsmap is null and if not default schema ns found for the custom bean
                return getNsGen().schemaNamespaceFromPackageName(packageName).toString();
            }
        }
    }

    public boolean isUseWSDLTypesNamespace() {
        return useWSDLTypesNamespace;
    }

    public void setUseWSDLTypesNamespace(boolean useWSDLTypesNamespace) {
        this.useWSDLTypesNamespace = useWSDLTypesNamespace;
    }

    public Map getPkg2nsmap() {
        return pkg2nsmap;
    }

    public void setPkg2nsmap(Map pkg2nsmap) {
        this.pkg2nsmap = pkg2nsmap;
    }

    public String getTargetNamespace() {
        return targetNamespace;
    }

    protected String getSimpleName(JMethod method) {
       return Utils.getSimpleName(method);
    }

    protected String getSimpleName(JClass type) {
        String name = type.getSimpleName();
        if (name.indexOf("$")>0){
           name = name.replace('$','_');
        }
        return name;
    }

    protected String getSimpleName(JProperty peroperty) {
        return peroperty.getSimpleName();
    }

    protected String getSimpleName(JParameter parameter) {
        return parameter.getSimpleName();
    }

    protected String getQualifiedName(JMethod method) {
        return method.getQualifiedName();
    }

    protected String getActualQualifiedName(JClass type ) {
        return type.getQualifiedName();
    }
    protected String getQualifiedName(JClass type) {
        String name = type.getQualifiedName();
        if (name.indexOf("$")>0){
           name = name.replace('$','_');
        }
        return name;
    }

    protected String getQualifiedName(JProperty peroperty) {
        return peroperty.getQualifiedName();
    }

    protected String getQualifiedName(JParameter parameter) {
        return parameter.getQualifiedName();
    }

    protected String getQualifiedName(JPackage packagez) {
        return packagez.getQualifiedName();
    }

    public void setNonRpcMethods(ArrayList nonRpcMethods) {
        if (nonRpcMethods != null) {
            this.nonRpcMethods = nonRpcMethods;
        }
    }

    public void setAxisService(AxisService service) {
        this.service = service;
    }


    public String getCustomSchemaLocation() {
        return customSchemaLocation;
    }

    public void setCustomSchemaLocation(String customSchemaLocation) {
        this.customSchemaLocation = customSchemaLocation;
    }

    public String getMappingFileLocation() {
        return mappingFileLocation;
    }

    public void setMappingFileLocation(String mappingFileLocation) {
        this.mappingFileLocation = mappingFileLocation;
    }
}
TOP

Related Classes of org.apache.axis2.description.java2wsdl.DefaultSchemaGenerator

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.