/*
 * 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 HashMap<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 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) {
				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 mappingIterator = schemaElement
						.getChildrenWithName(new QName(MAPPING));
				if (mappingIterator != null) {
					Map<String,String> pkg2nsMap = new Hashtable<String,String>();
					while (mappingIterator.hasNext()) {
						OMElement mappingElement = (OMElement) 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 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 transport_itr = transports
						.getChildrenWithName(new QName(TAG_TRANSPORT));
				ArrayList<String> trs = new ArrayList<String>();
				while (transport_itr.hasNext()) {
					OMElement trsEle = (OMElement) 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 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 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 elementItr = packageMappingElement
				.getChildrenWithName(new QName(TAG_MAPPING));
		TypeTable typeTable = service.getTypeTable();
		if (typeTable == null) {
			typeTable = new TypeTable();
		}
		while (elementItr.hasNext()) {
			OMElement mappingElement = (OMElement) 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 excludeOp_itr = excludeOperations
				.getChildrenWithName(new QName(TAG_OPERATION));
		while (excludeOp_itr.hasNext()) {
			OMElement opName = (OMElement) 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 parameters = messageElement.getChildrenWithName(new QName(
					TAG_PARAMETER));

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

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

			// processing <wsp:PolicyReference> .. </..> elements
			Iterator 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 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 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 modules = operation.getChildrenWithName(new QName(
					TAG_MODULE));

			processOperationModuleRefs(modules, op_descrip);

			// processing Messages
			Iterator 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 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 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 iterator = dataLocatorElement.getChildrenWithName(new QName(
				DRConstants.DIALECT_LOCATOR_ELEMENT));

		while (iterator.hasNext()) {
			OMElement locatorElement = (OMElement) 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(HashMap<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);
        }
    }
}
