/*
 * 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.deployment;

import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.AddressingHelper;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.dataretrieval.DRConstants;
import org.apache.axis2.deployment.util.PhasesInfo;
import org.apache.axis2.deployment.util.Utils;
import org.apache.axis2.description.*;
import org.apache.axis2.description.java2wsdl.Java2WSDLConstants;
import org.apache.axis2.description.java2wsdl.TypeTable;
import org.apache.axis2.engine.MessageReceiver;
import org.apache.axis2.engine.ObjectSupplier;
import org.apache.axis2.engine.ServiceLifeCycle;
import org.apache.axis2.i18n.Messages;
import org.apache.axis2.util.Loader;
import org.apache.axis2.util.JavaUtils;
import org.apache.axis2.util.PolicyUtil;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.namespace.QName;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Builds a service description from OM
 */
public class ServiceBuilder extends DescriptionBuilder {
    private static final Log log = LogFactory.getLog(ServiceBuilder.class);
    private AxisService service;
    private Map<String,AxisService> wsdlServiceMap = new HashMap<String,AxisService>();

    public ServiceBuilder(ConfigurationContext configCtx, AxisService service) {
        this.service = service;
        this.configCtx = configCtx;
        this.axisConfig = this.configCtx.getAxisConfiguration();
    }

    public ServiceBuilder(InputStream serviceInputStream,
            ConfigurationContext configCtx, AxisService service) {
        super(serviceInputStream, configCtx);
        this.service = service;
    }

    /**
     * Populates service from corresponding OM.
     * 
     * @param service_element
     *            an OMElement for the &lt;service&gt; tag
     * @return a filled-in AxisService, configured from the passed XML
     * @throws DeploymentException
     *             if there is a problem
     */
    public AxisService populateService(OMElement service_element)
            throws DeploymentException {
        try {
            // Determine whether service should be activated.
            String serviceActivate = service_element
                    .getAttributeValue(new QName(ATTRIBUTE_ACTIVATE));
            if (serviceActivate != null) {
                if ("true".equals(serviceActivate)) {
                    service.setActive(true);
                } else if ("false".equals(serviceActivate)) {
                    service.setActive(false);
                }
            }

            // Processing service level parameters
            OMAttribute serviceNameatt = service_element
                    .getAttribute(new QName(ATTRIBUTE_NAME));

            // If the service name is explicitly specified in the services.xml
            // then use that as the service name
            if (serviceNameatt != null) {
                if (!"".equals(serviceNameatt.getAttributeValue().trim())) {
                    AxisService wsdlService = wsdlServiceMap
                            .get(serviceNameatt.getAttributeValue());
                    if (wsdlService != null) {
                        wsdlService.setClassLoader(service.getClassLoader());
                        wsdlService.setParent(service.getAxisServiceGroup());
                        service = wsdlService;
                        service.setWsdlFound(true);
                        service.setCustomWsdl(true);
                    }
                    service.setName(serviceNameatt.getAttributeValue());
                    // To be on the safe side
                    if (service.getDocumentation() == null) {
                        service.setDocumentation(serviceNameatt
                                .getAttributeValue());
                    }
                }
            }

            Iterator<OMElement> itr = service_element.getChildrenWithName(new QName(
                    TAG_PARAMETER));
            processParameters(itr, service, service.getParent());

            Parameter childFirstClassLoading =
                    service.getParameter(Constants.Configuration.ENABLE_CHILD_FIRST_CLASS_LOADING);
            if (childFirstClassLoading != null) {
                ClassLoader cl = service.getClassLoader();
                if (cl instanceof DeploymentClassLoader) {
                    DeploymentClassLoader deploymentClassLoader = (DeploymentClassLoader) cl;
                    if (JavaUtils.isTrueExplicitly(childFirstClassLoading.getValue())){
                        deploymentClassLoader.setChildFirstClassLoading(true);
                    } else if (JavaUtils.isFalseExplicitly(childFirstClassLoading.getValue())){
                        deploymentClassLoader.setChildFirstClassLoading(false);
                    }
                }
            }

            // If multiple services in one service group have different values
            // for the PARENT_FIRST
            // parameter then the final value become the value specified by the
            // last service in the group
            // Parameter parameter =
            // service.getParameter(DeploymentClassLoader.PARENT_FIRST);
            // if (parameter !=null && "false".equals(parameter.getValue())) {
            // ClassLoader serviceClassLoader = service.getClassLoader();
            // ((DeploymentClassLoader)serviceClassLoader).setParentFirst(false);
            // }
            // process service description
            OMElement descriptionElement = service_element
                    .getFirstChildWithName(new QName(TAG_DESCRIPTION));
            if (descriptionElement == null) {
                descriptionElement = service_element.getFirstChildWithName(new QName(TAG_DESCRIPTION_ALT));
            }
            if (descriptionElement != null) {
                OMElement descriptionValue = descriptionElement
                        .getFirstElement();
                if (descriptionValue != null) {
                    service.setDocumentation(descriptionValue);
                } else {
                    service.setDocumentation(descriptionElement.getText());
                }
            } else {
                serviceNameatt = service_element.getAttribute(new QName(
                        ATTRIBUTE_NAME));

                if (serviceNameatt != null) {
                    if (!"".equals(serviceNameatt.getAttributeValue().trim())
                            && service.getDocumentation() == null) {
                        service.setDocumentation(serviceNameatt
                                .getAttributeValue());
                    }
                }
            }

            if (service.getParameter("ServiceClass") == null) {
                log.debug("The Service " + service.getName()
                        + " does not specify a Service Class");
            }

            // Process WS-Addressing flag attribute
            OMAttribute addressingRequiredatt = service_element
                    .getAttribute(new QName(ATTRIBUTE_WSADDRESSING));
            if (addressingRequiredatt != null) {
                String addressingRequiredString = addressingRequiredatt
                        .getAttributeValue();
                AddressingHelper.setAddressingRequirementParemeterValue(
                        service, addressingRequiredString);
            }

            // Setting service target namespace if any
            OMAttribute targetNameSpace = service_element
                    .getAttribute(new QName(TARGET_NAME_SPACE));

            if (targetNameSpace != null) {
                String nameSpeceVale = targetNameSpace.getAttributeValue();
                if (nameSpeceVale != null && !"".equals(nameSpeceVale)) {
                    service.setTargetNamespace(nameSpeceVale);
                }
            } else {
                if (service.getTargetNamespace() == null
                        || "".equals(service.getTargetNamespace())) {
                    service
                            .setTargetNamespace(Java2WSDLConstants.DEFAULT_TARGET_NAMESPACE);
                }
            }

            // Processing service lifecycle attribute
            OMAttribute serviceLifeCycleClass = service_element
                    .getAttribute(new QName(TAG_CLASS_NAME));
            if (serviceLifeCycleClass != null) {
                String className = serviceLifeCycleClass.getAttributeValue();
                loadServiceLifeCycleClass(className);
            }
            // Setting schema namespece if any
            OMElement schemaElement = service_element
                    .getFirstChildWithName(new QName(SCHEMA));
            if (schemaElement != null) {
                OMAttribute schemaNameSpace = schemaElement
                        .getAttribute(new QName(SCHEMA_NAME_SPACE));
                if (schemaNameSpace != null) {
                    String nameSpeceVale = schemaNameSpace.getAttributeValue();
                    if (nameSpeceVale != null && !"".equals(nameSpeceVale)) {
                        service.setSchemaTargetNamespace(nameSpeceVale);
                    }
                }
                OMAttribute elementFormDefault = schemaElement
                        .getAttribute(new QName(SCHEMA_ELEMENT_QUALIFIED));
                if (elementFormDefault != null) {
                    String value = elementFormDefault.getAttributeValue();
                    if ("true".equals(value)) {
                        service.setElementFormDefault(true);
                    } else if ("false".equals(value)) {
                        service.setElementFormDefault(false);
                    }
                }

                // package to namespace mapping. This will be an element that
                // maps pkg names to a namespace
                // when this is doing AxisService.getSchemaTargetNamespace will
                // be overridden
                // This will be <mapping/> with @namespace and @package
                Iterator<OMElement> mappingIterator = schemaElement
                        .getChildrenWithName(new QName(MAPPING));
                if (mappingIterator != null) {
                    Map<String,String> pkg2nsMap = new Hashtable<String,String>();
                    while (mappingIterator.hasNext()) {
                        OMElement mappingElement = mappingIterator.next();
                        OMAttribute namespaceAttribute = mappingElement
                                .getAttribute(new QName(ATTRIBUTE_NAMESPACE));
                        OMAttribute packageAttribute = mappingElement
                                .getAttribute(new QName(ATTRIBUTE_PACKAGE));
                        if (namespaceAttribute != null
                                && packageAttribute != null) {
                            String namespaceAttributeValue = namespaceAttribute
                                    .getAttributeValue();
                            String packageAttributeValue = packageAttribute
                                    .getAttributeValue();
                            if (namespaceAttributeValue != null
                                    && packageAttributeValue != null) {
                                pkg2nsMap.put(packageAttributeValue.trim(),
                                        namespaceAttributeValue.trim());
                            } else {
                                log
                                        .warn("Either value of @namespce or @packagename not available. Thus, generated will be selected.");
                            }
                        } else {
                            log
                                    .warn("Either @namespce or @packagename not available. Thus, generated will be selected.");
                        }
                    }
                    service.setP2nMap(pkg2nsMap);

                }

            }

            // processing Default Message receivers
            OMElement messageReceiver = service_element
                    .getFirstChildWithName(new QName(TAG_MESSAGE_RECEIVERS));
            if (messageReceiver != null) {
                HashMap<String,MessageReceiver> mrs = processMessageReceivers(service.getClassLoader(),
                        messageReceiver);
                for (Map.Entry<String,MessageReceiver> entry : mrs.entrySet()) {
                    service.addMessageReceiver(entry.getKey(), entry.getValue());
                }
            }

            // Removing exclude operations
            OMElement excludeOperations = service_element
                    .getFirstChildWithName(new QName(TAG_EXCLUDE_OPERATIONS));
            ArrayList<String> excludeops = null;
            if (excludeOperations != null) {
                excludeops = processExcludeOperations(excludeOperations);
            }
            if (excludeops == null) {
                excludeops = new ArrayList<String>();
            }
            Utils.addExcludeMethods(excludeops);

            // <schema targetNamespace="http://x.y.z"/>
            // setting the PolicyInclude
            // processing <wsp:Policy> .. </..> elements
            Iterator policyElements = PolicyUtil.getPolicyChildren(service_element);

            if (policyElements != null && policyElements.hasNext()) {
                processPolicyElements(policyElements, service.getPolicySubject());
            }

            // processing <wsp:PolicyReference> .. </..> elements
            Iterator policyRefElements = PolicyUtil.getPolicyRefChildren(service_element);

            if (policyRefElements != null && policyRefElements.hasNext()) {
                processPolicyRefElements(policyRefElements, service.getPolicySubject());
            }

            // processing service scope
            String sessionScope = service_element.getAttributeValue(new QName(
                    ATTRIBUTE_SCOPE));
            if (sessionScope != null) {
                service.setScope(sessionScope);
            }

            // processing service-wide modules which required to engage globally
            Iterator<OMElement> moduleRefs = service_element
                    .getChildrenWithName(new QName(TAG_MODULE));

            processModuleRefs(moduleRefs);

            // processing transports
            OMElement transports = service_element
                    .getFirstChildWithName(new QName(TAG_TRANSPORTS));
            if (transports != null) {
                Iterator<OMElement> transport_itr = transports
                        .getChildrenWithName(new QName(TAG_TRANSPORT));
                ArrayList<String> trs = new ArrayList<String>();
                while (transport_itr.hasNext()) {
                    OMElement trsEle = transport_itr.next();
                    String transportName = trsEle.getText().trim();
                    if (axisConfig.getTransportIn(transportName) == null) {
                        log.warn("Service [ " + service.getName()
                                + "] is trying to expose in a transport : "
                                + transportName
                                + " and which is not available in Axis2");
                    } else {
                        trs.add(transportName);
                    }
                }

                if(trs.isEmpty()){
                    throw new AxisFault("Service [" + service.getName()
                        + "] is trying expose in tranpsorts: "
                        + transports
                        + " and which is/are not available in Axis2");
                }
                service.setExposedTransports(trs);
            }
            // processing operations
            Iterator<OMElement> operationsIterator = service_element
                    .getChildrenWithName(new QName(TAG_OPERATION));
            ArrayList ops = processOperations(operationsIterator);

            for (int i = 0; i < ops.size(); i++) {
                AxisOperation operationDesc = (AxisOperation) ops.get(i);
                ArrayList wsamappings = operationDesc.getWSAMappingList();
                if (wsamappings == null) {
                    continue;
                }
                if (service.getOperation(operationDesc.getName()) == null) {
                    service.addOperation(operationDesc);
                }
                for (int j = 0; j < wsamappings.size(); j++) {
                    String mapping = (String) wsamappings.get(j);
                    if (mapping.length() > 0) {
                        service.mapActionToOperation(mapping, operationDesc);
                    }
                }
            }
            String objectSupplierValue = (String) service
                    .getParameterValue(TAG_OBJECT_SUPPLIER);
            if (objectSupplierValue != null) {
                loadObjectSupplierClass(objectSupplierValue);
            }
            // Set the default message receiver for the operations that were
            // not listed in the services.xml
            setDefaultMessageReceivers();
            Utils.processBeanPropertyExclude(service);
            if (!service.isUseUserWSDL()) {
                // Generating schema for the service if the impl class is Java
                if (!service.isWsdlFound()) {
                    // trying to generate WSDL for the service using JAM and
                    // Java reflection
                    try {
                        if (generateWsdl(service)) {
                            Utils.fillAxisService(service, axisConfig,
                                    excludeops, null);
                        } else {
                            ArrayList nonRpcOperations = getNonRPCMethods(service);
                            Utils.fillAxisService(service, axisConfig,
                                    excludeops, nonRpcOperations);
                        }
                    } catch (Exception e) {
                        throw new DeploymentException(Messages.getMessage(
                                "errorinschemagen", e.getMessage()), e);
                    }
                }
            }
            if (service.isCustomWsdl()) {
                OMElement mappingElement = service_element
                        .getFirstChildWithName(new QName(TAG_PACKAGE2QNAME));
                if (mappingElement != null) {
                    processTypeMappings(mappingElement);
                }
            }

            for (String opName : excludeops) {
                service.removeOperation(new QName(opName));
                service.addExcludeOperationName(opName);
            }

            // Need to call the same logic towice
            setDefaultMessageReceivers();
            Iterator<OMElement> moduleConfigs = service_element
                    .getChildrenWithName(new QName(TAG_MODULE_CONFIG));
            processServiceModuleConfig(moduleConfigs, service, service);

            // Loading Data Locator(s) configured
            OMElement dataLocatorElement = service_element
                    .getFirstChildWithName(new QName(
                            DRConstants.DATA_LOCATOR_ELEMENT));
            if (dataLocatorElement != null) {
                processDataLocatorConfig(dataLocatorElement, service);
            }

            processEndpoints(service);
            processPolicyAttachments(service_element, service);
            

        } catch (AxisFault axisFault) {
            throw new DeploymentException(axisFault);
        }

        startupServiceLifecycle();
        return service;
    }

    private void setDefaultMessageReceivers() {
        Iterator operations = service.getPublishedOperations().iterator();
        while (operations.hasNext()) {
            AxisOperation operation = (AxisOperation) operations.next();
            if (operation.getMessageReceiver() == null) {
                MessageReceiver messageReceiver = loadDefaultMessageReceiver(
                        operation.getMessageExchangePattern(), service);
                if (messageReceiver == null &&
                // we assume that if the MEP is ROBUST_IN_ONLY then the in-out
                        // MR can handle that
                        WSDL2Constants.MEP_URI_ROBUST_IN_ONLY.equals(operation
                                .getMessageExchangePattern())) {
                    messageReceiver = loadDefaultMessageReceiver(
                            WSDL2Constants.MEP_URI_IN_OUT, service);

                }
                operation.setMessageReceiver(messageReceiver);
            }
        }
    }

    private void loadObjectSupplierClass(String objectSupplierValue)
            throws AxisFault {
        try {
            ClassLoader loader = service.getClassLoader();
            Class objectSupplierImpl = Loader.loadClass(loader,
                    objectSupplierValue.trim());
            ObjectSupplier objectSupplier = (ObjectSupplier) objectSupplierImpl
                    .newInstance();
            service.setObjectSupplier(objectSupplier);
        } catch (Exception e) {
            throw AxisFault.makeFault(e);
        }
    }

    /**
     * Process the package name to QName mapping:
     * 
     * &lt;packageMapping&gt; &lt;mapping packageName="foo.bar"
     * qname="http://foo/bar/xsd"%gt; ...... ...... &lt;/packageMapping&gt;
     * 
     * @param packageMappingElement
     *            OMElement for the packageMappingElement
     */
    private void processTypeMappings(OMElement packageMappingElement) {
        Iterator<OMElement> elementItr = packageMappingElement
                .getChildrenWithName(new QName(TAG_MAPPING));
        TypeTable typeTable = service.getTypeTable();
        if (typeTable == null) {
            typeTable = new TypeTable();
        }
        while (elementItr.hasNext()) {
            OMElement mappingElement = elementItr.next();
            String packageName = mappingElement.getAttributeValue(new QName(
                    TAG_PACKAGE_NAME));
            String qName = mappingElement
                    .getAttributeValue(new QName(TAG_QNAME));
            if (packageName == null || qName == null) {
                continue;
            }
            Iterator keys = service.getNamespaceMap().keySet().iterator();
            while (keys.hasNext()) {
                String key = (String) keys.next();
                if (qName.equals(service.getNamespaceMap().get(key))) {
                    typeTable.addComplexSchema(packageName, new QName(qName,
                            packageName, key));
                }
            }
        }
        service.setTypeTable(typeTable);
    }

    private void loadServiceLifeCycleClass(String className)
            throws DeploymentException {
        if (className != null) {
            try {
                ClassLoader loader = service.getClassLoader();
                Class serviceLifeCycleClassImpl = Loader.loadClass(loader,
                        className);
                ServiceLifeCycle serviceLifeCycle =
                        (ServiceLifeCycle) serviceLifeCycleClassImpl.newInstance();
                service.setServiceLifeCycle(serviceLifeCycle);
            } catch (Exception e) {
                throw new DeploymentException(e.getMessage(), e);
            }
        }
    }

    private boolean generateWsdl(AxisService axisService) {
        Iterator operatins = axisService.getOperations();
        if (operatins.hasNext()) {
            while (operatins.hasNext()) {
                AxisOperation axisOperation = (AxisOperation) operatins.next();

                if (axisOperation.isControlOperation()) {
                    continue;
                }

                if (axisOperation.getMessageReceiver() == null) {
                    continue;
                }
                String messageReceiverClass = axisOperation
                        .getMessageReceiver().getClass().getName();
                if (!("org.apache.axis2.rpc.receivers.RPCMessageReceiver"
                        .equals(messageReceiverClass)
                        || "org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"
                                .equals(messageReceiverClass)
                        || "org.apache.axis2.rpc.receivers.RPCInOutAsyncMessageReceiver"
                                .equals(messageReceiverClass) || "org.apache.axis2.jaxws.server.JAXWSMessageReceiver"
                        .equals(messageReceiverClass))) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * To get the methods which do not use RPC* MessageReceivers
     * 
     * @param axisService
     *            the AxisService to search
     * @return an ArrayList of the LOCAL PARTS of the QNames of any non-RPC
     *         operations TODO: Why not just return the AxisOperations
     *         themselves??
     */
    private ArrayList<String> getNonRPCMethods(AxisService axisService) {
        ArrayList<String> excludeOperations = new ArrayList<String>();
        Iterator<AxisOperation> operatins = axisService.getOperations();
        if (operatins.hasNext()) {
            while (operatins.hasNext()) {
                AxisOperation axisOperation = operatins.next();
                if (axisOperation.getMessageReceiver() == null) {
                    continue;
                }
                String messageReceiverClass = axisOperation
                        .getMessageReceiver().getClass().getName();
                if (!("org.apache.axis2.rpc.receivers.RPCMessageReceiver"
                        .equals(messageReceiverClass)
                        || "org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"
                                .equals(messageReceiverClass)
                        || "org.apache.axis2.rpc.receivers.RPCInOutAsyncMessageReceiver"
                                .equals(messageReceiverClass) || "org.apache.axis2.jaxws.server.JAXWSMessageReceiver"
                        .equals(messageReceiverClass))) {
                    excludeOperations.add(axisOperation.getName()
                            .getLocalPart());
                }
            }
        }
        return excludeOperations;
    }

    /**
     * Process &lt;excludeOperation&gt; element in services.xml. Each operation
     * referenced will be removed from the AxisService.
     * 
     * @param excludeOperations
     *            the &lt;excludeOperations&gt; element from services.xml
     * @return an ArrayList of the String contents of the &lt;operation&gt;
     *         elements
     */
    private ArrayList<String> processExcludeOperations(OMElement excludeOperations) {
        ArrayList<String> exOps = new ArrayList<String>();
        Iterator<OMElement> excludeOp_itr = excludeOperations
                .getChildrenWithName(new QName(TAG_OPERATION));
        while (excludeOp_itr.hasNext()) {
            OMElement opName = excludeOp_itr.next();
            exOps.add(opName.getText().trim());
        }
        return exOps;
    }

    private void processMessages(Iterator messages, AxisOperation operation)
            throws DeploymentException {
        while (messages.hasNext()) {
            OMElement messageElement = (OMElement) messages.next();
            OMAttribute label = messageElement
                    .getAttribute(new QName(TAG_LABEL));

            if (label == null) {
                throw new DeploymentException(Messages
                        .getMessage("messagelabelcannotfound"));
            }

            AxisMessage message = operation.getMessage(label
                    .getAttributeValue());

            Iterator<OMElement> parameters = messageElement.getChildrenWithName(new QName(
                    TAG_PARAMETER));

            // processing <wsp:Policy> .. </..> elements
            Iterator<OMElement> policyElements = PolicyUtil.getPolicyChildren(messageElement);

            if (policyElements != null) {
                processPolicyElements(policyElements, message.getPolicySubject());
            }

            // processing <wsp:PolicyReference> .. </..> elements
            Iterator<OMElement> policyRefElements = PolicyUtil.getPolicyRefChildren(messageElement);

            if (policyRefElements != null) {
                processPolicyRefElements(policyRefElements, message.getPolicySubject());
            }

            processParameters(parameters, message, operation);

        }
    }

    /**
     * Gets the list of modules that is required to be engaged globally.
     * 
     * @param moduleRefs
     *            <code>java.util.Iterator</code>
     * @throws DeploymentException
     *             <code>DeploymentException</code>
     */
    protected void processModuleRefs(Iterator moduleRefs)
            throws DeploymentException {
//        try {
            while (moduleRefs.hasNext()) {
                OMElement moduleref = (OMElement) moduleRefs.next();
                OMAttribute moduleRefAttribute = moduleref
                        .getAttribute(new QName(TAG_REFERENCE));

                if (moduleRefAttribute != null) {
                    String refName = moduleRefAttribute.getAttributeValue();
                    service.addModuleref(refName);
//                    if (axisConfig.getModule(refName) == null) {
//                        throw new DeploymentException(Messages.getMessage(
//                                DeploymentErrorMsgs.MODULE_NOT_FOUND, refName));
//                    } else {
//                        service.addModuleref(refName);
//                    }
                }
            }
//        } catch (AxisFault axisFault) {
//            throw new DeploymentException(axisFault);
//        }
    }

    protected void processOperationModuleConfig(Iterator moduleConfigs,
            ParameterInclude parent, AxisOperation operation)
            throws DeploymentException {
        while (moduleConfigs.hasNext()) {
            OMElement moduleConfig = (OMElement) moduleConfigs.next();
            OMAttribute moduleName_att = moduleConfig.getAttribute(new QName(
                    ATTRIBUTE_NAME));

            if (moduleName_att == null) {
                throw new DeploymentException(Messages
                        .getMessage(DeploymentErrorMsgs.INVALID_MODULE_CONFIG));
            } else {
                String module = moduleName_att.getAttributeValue();
                ModuleConfiguration moduleConfiguration = new ModuleConfiguration(
                        module, parent);
                Iterator<OMElement> parameters = moduleConfig
                        .getChildrenWithName(new QName(TAG_PARAMETER));

                processParameters(parameters, moduleConfiguration, parent);
                operation.addModuleConfig(moduleConfiguration);
            }
        }
    }

    private ArrayList<AxisOperation> processOperations(Iterator operationsIterator)
            throws AxisFault {
        ArrayList<AxisOperation> operations = new ArrayList<AxisOperation>();
        while (operationsIterator.hasNext()) {
            OMElement operation = (OMElement) operationsIterator.next();
            // getting operation name
            OMAttribute op_name_att = operation.getAttribute(new QName(
                    ATTRIBUTE_NAME));
            if (op_name_att == null) {
                throw new DeploymentException(Messages.getMessage(Messages
                        .getMessage(DeploymentErrorMsgs.INVALID_OP,
                                "operation name missing")));
            }

            // setting the MEP of the operation
            OMAttribute op_mep_att = operation.getAttribute(new QName(TAG_MEP));
            String mepurl = null;

            if (op_mep_att != null) {
                mepurl = op_mep_att.getAttributeValue();
            }

            String opname = op_name_att.getAttributeValue();
            AxisOperation op_descrip = null;

            // getting the namesapce from the attribute.
            OMAttribute operationNamespace = operation.getAttribute(new QName(
                    ATTRIBUTE_NAMESPACE));
            if (operationNamespace != null) {
                String namespace = operationNamespace.getAttributeValue();
                op_descrip = service.getOperation(new QName(namespace, opname));
            }
            if (op_descrip == null) {
                op_descrip = service.getOperation(new QName(opname));
            }

            if (op_descrip == null) {
                op_descrip = service.getOperation(new QName(service
                        .getTargetNamespace(), opname));
            }
            if (op_descrip == null) {
                if (mepurl == null) {
                    // assumed MEP is in-out
                    op_descrip = new InOutAxisOperation();
                    op_descrip.setParent(service);

                } else {
                    op_descrip = AxisOperationFactory
                            .getOperationDescription(mepurl);
                }
                op_descrip.setName(new QName(opname));
                String MEP = op_descrip.getMessageExchangePattern();
                if (WSDL2Constants.MEP_URI_IN_ONLY.equals(MEP)
                        || WSDL2Constants.MEP_URI_IN_OPTIONAL_OUT.equals(MEP)
                        || WSDL2Constants.MEP_URI_OUT_OPTIONAL_IN.equals(MEP)
                        || WSDL2Constants.MEP_URI_ROBUST_OUT_ONLY.equals(MEP)
                        || WSDL2Constants.MEP_URI_ROBUST_IN_ONLY.equals(MEP)
                        || WSDL2Constants.MEP_URI_IN_OUT.equals(MEP)) {
                    AxisMessage inaxisMessage = op_descrip
                            .getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
                    if (inaxisMessage != null) {
                        inaxisMessage.setName(opname
                                + Java2WSDLConstants.MESSAGE_SUFFIX);
                    }
                }

                if (WSDL2Constants.MEP_URI_OUT_ONLY.equals(MEP)
                        || WSDL2Constants.MEP_URI_OUT_OPTIONAL_IN.equals(MEP)
                        || WSDL2Constants.MEP_URI_IN_OPTIONAL_OUT.equals(MEP)
                        || WSDL2Constants.MEP_URI_ROBUST_OUT_ONLY.equals(MEP)
                        || WSDL2Constants.MEP_URI_IN_OUT.equals(MEP)) {
                    AxisMessage outAxisMessage = op_descrip
                            .getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
                    if (outAxisMessage != null) {
                        outAxisMessage.setName(opname
                                + Java2WSDLConstants.RESPONSE);
                    }
                }
            }

            // setting the PolicyInclude

            // processing <wsp:Policy> .. </..> elements
            Iterator policyElements = PolicyUtil.getPolicyChildren(operation);

            if (policyElements != null && policyElements.hasNext()) {
                processPolicyElements(policyElements, op_descrip.getPolicySubject());
            }

            // processing <wsp:PolicyReference> .. </..> elements
            Iterator policyRefElements = PolicyUtil.getPolicyRefChildren(operation);

            if (policyRefElements != null && policyRefElements.hasNext()) {
                processPolicyRefElements(policyRefElements, op_descrip.getPolicySubject());
            }

            // Operation Parameters
            Iterator<OMElement> parameters = operation.getChildrenWithName(new QName(
                    TAG_PARAMETER));
            processParameters(parameters, op_descrip, service);
            // To process wsamapping;
            processActionMappings(operation, op_descrip);

            // loading the message receivers
            OMElement receiverElement = operation
                    .getFirstChildWithName(new QName(TAG_MESSAGE_RECEIVER));

            if (receiverElement != null) {
                MessageReceiver messageReceiver = loadMessageReceiver(service
                        .getClassLoader(), receiverElement);

                op_descrip.setMessageReceiver(messageReceiver);
            } else {
                // setting default message receiver
                MessageReceiver msgReceiver = loadDefaultMessageReceiver(
                        op_descrip.getMessageExchangePattern(), service);
                op_descrip.setMessageReceiver(msgReceiver);
            }

            // Process Module Refs
            Iterator<OMElement> modules = operation.getChildrenWithName(new QName(
                    TAG_MODULE));

            processOperationModuleRefs(modules, op_descrip);

            // processing Messages
            Iterator<OMElement> messages = operation.getChildrenWithName(new QName(
                    TAG_MESSAGE));

            processMessages(messages, op_descrip);

            // setting Operation phase
            if (axisConfig != null) {
                PhasesInfo info = axisConfig.getPhasesInfo();

                info.setOperationPhases(op_descrip);
            }
            Iterator<OMElement> moduleConfigs = operation.getChildrenWithName(new QName(
                    TAG_MODULE_CONFIG));
            processOperationModuleConfig(moduleConfigs, op_descrip, op_descrip);
            // adding the operation
            operations.add(op_descrip);
        }
        return operations;
    }

    protected void processServiceModuleConfig(Iterator moduleConfigs,
            ParameterInclude parent, AxisService service)
            throws DeploymentException {
        while (moduleConfigs.hasNext()) {
            OMElement moduleConfig = (OMElement) moduleConfigs.next();
            OMAttribute moduleName_att = moduleConfig.getAttribute(new QName(
                    ATTRIBUTE_NAME));

            if (moduleName_att == null) {
                throw new DeploymentException(Messages
                        .getMessage(DeploymentErrorMsgs.INVALID_MODULE_CONFIG));
            } else {
                String module = moduleName_att.getAttributeValue();
                ModuleConfiguration moduleConfiguration = new ModuleConfiguration(
                        module, parent);
                Iterator<OMElement> parameters = moduleConfig
                        .getChildrenWithName(new QName(TAG_PARAMETER));

                processParameters(parameters, moduleConfiguration, parent);
                service.addModuleConfig(moduleConfiguration);
            }
        }
    }

    /*
     * process data locator configuration for data retrieval.
     */
    private void processDataLocatorConfig(OMElement dataLocatorElement,
            AxisService service) {
        OMAttribute serviceOverallDataLocatorclass = dataLocatorElement
                .getAttribute(new QName(DRConstants.CLASS_ATTRIBUTE));
        if (serviceOverallDataLocatorclass != null) {
            String className = serviceOverallDataLocatorclass
                    .getAttributeValue();
            service.addDataLocatorClassNames(DRConstants.SERVICE_LEVEL,
                    className);
        }
        Iterator<OMElement> iterator = dataLocatorElement.getChildrenWithName(new QName(
                DRConstants.DIALECT_LOCATOR_ELEMENT));

        while (iterator.hasNext()) {
            OMElement locatorElement = iterator.next();
            OMAttribute dialect = locatorElement.getAttribute(new QName(
                    DRConstants.DIALECT_ATTRIBUTE));
            OMAttribute dialectclass = locatorElement.getAttribute(new QName(
                    DRConstants.CLASS_ATTRIBUTE));
            service.addDataLocatorClassNames(dialect.getAttributeValue(),
                    dialectclass.getAttributeValue());

        }

    }

    public void setWsdlServiceMap(Map<String,AxisService> wsdlServiceMap) {
        this.wsdlServiceMap = wsdlServiceMap;
    }

    private void processEndpoints(AxisService axisService) throws AxisFault {
        String endpointName = axisService.getEndpointName();
        if (endpointName == null || endpointName.length() == 0) {
            Utils.addEndpointsToService(axisService, service.getAxisConfiguration());
        }
    }
    
    private void processPolicyAttachments(OMElement serviceElement,
                                          AxisService service) throws DeploymentException {
        List<OMElement> attachmentElements = new ArrayList<OMElement>();
        for (Iterator it = serviceElement.getChildElements(); it.hasNext(); ) {
            OMElement elem = (OMElement)it.next();
            if (org.apache.neethi.Constants.isPolicyNS(elem.getNamespaceURI()) &&
                    elem.getLocalName().equals(TAG_POLICY_ATTACHMENT)) {
                attachmentElements.add(elem);
            }
        }
        try {
            Utils.processPolicyAttachments(attachmentElements.iterator(), service);
        } catch (Exception e) {
            throw new DeploymentException(e);
        }
    }

    private void startupServiceLifecycle() {
        if (service.getServiceLifeCycle() != null) {
            service.getServiceLifeCycle().startUp(configCtx, service);
        }
    }
}
