/*******************************************************************************
 * Copyright (c) 2007, 2009 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * IBM Corporation - initial API and implementation
 * yyyymmdd bug      Email and other contact information
 * -------- -------- -----------------------------------------------------------
 * 20070413   176493 makandre@ca.ibm.com - Andrew Mak, WSE: Make message/transport stack pluggable
 * 20081020   251269 mahutch@ca.ibm.com - Mark Hutchinson, WSE Sends Wrong Namespace for child elements of the SOAP body
 * 20091104   294260 mahutch@ca.ibm.com - Mark Hutchinson, WSE source view missing some namespace prefixes in SOAP response message
 *******************************************************************************/
package org.eclipse.wst.ws.internal.explorer.platform.wsdl.transport;

import java.io.IOException;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.wsdl.Operation;
import javax.wsdl.Part;
import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.soap.SOAPBody;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.axis.Constants;
import org.eclipse.wst.ws.internal.explorer.platform.util.XMLUtils;
import org.eclipse.wst.ws.internal.explorer.platform.wsdl.util.SoapHelper;
import org.eclipse.wst.ws.internal.explorer.transport.IDeserializer;
import org.eclipse.wst.ws.internal.explorer.transport.ISOAPMessage;
import org.eclipse.wst.ws.internal.explorer.transport.ISerializer;
import org.eclipse.wst.ws.internal.explorer.transport.MessageContext;
import org.eclipse.wst.ws.internal.explorer.transport.TransportException;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * This class provides implementation for WSE default SOAP transport's ISerializer and IDeserializer.
 */
public class SOAPMessageProcessor implements ISerializer, IDeserializer {
	
	private static final String LITERAL = "literal";
	private static final String DEFAULT_SOAP_ENCODING = "UTF-8";	
	private static final String LINE_SEPARATOR = System.getProperties().getProperty("line.separator");
	
	/*
	 * Constructor.
	 */
	SOAPMessageProcessor() {}
	
	/*
	 * Join the encodingStyles into a space separated string
	 */
	private String joinEncodingStyles(List list) {
		
		if (list.isEmpty())
			return null;
		
		StringBuffer sb = new StringBuffer();
		
		Iterator iter = list.iterator();
		while (iter.hasNext())
			sb.append(" ").append(iter.next());
		
		return sb.substring(1).toString();
	}
	
	/*
	 * Retrieves the encoding information from the binding for the selected operation.
	 * This method is called only for RPC style bindings.  Two pieces of information are returned:  
	 * This method returns the encoding namespace in element [0] 
	 * If the use is encoded then the encoding style(s) is returned in element [1].  If the use is literal, 
	 * then element[1] is returned null.
	 */
	private String[] getEncodingInfo(MessageContext context) {
		
		String[] info = new String[] { null, null };
		
		Iterator iter = context.getBindingOperation().getBindingInput()
			.getExtensibilityElements().iterator();
				
		// look for the soapbind:body extensilibity element
		while (iter.hasNext()) {
			ExtensibilityElement e = (ExtensibilityElement) iter.next();			
			if (!(e instanceof SOAPBody))
				continue;
			
			SOAPBody soapBody = (SOAPBody) e;
			
			info[0] = soapBody.getNamespaceURI();
			// use="encoded"
			if (!LITERAL.equals(soapBody.getUse())) {
				info[1] = joinEncodingStyles(soapBody.getEncodingStyles());
			}
					
			break;
		}
		
		// namespace not specified on the soapbind:body element, use the definition's
		if (info[0] == null)
			info[0] = context.getDefinition().getTargetNamespace();
		
		return info;
	}
	
	/*
     * WS-I: In a rpc-literal SOAP binding, the serialized child element of the 
     * soap:Body element consists of a wrapper element, whose namespace is the value 
     * of the namespace attribute of the soapbind:body element and whose local name is 
     * either the name of the operation or the name of the operation suffixed 
     * with "Response". The namespace attribute is required, as opposed to being 
     * optional, to ensure that the children of the soap:Body element are namespace-
     * qualified.
     */
	private Element createRPCWrapper(Document document, MessageContext context, Hashtable namespaceTable) {
		
		String encodingNamespaceURI = getEncodingInfo(context)[0];
		
		return SoapHelper.createRPCWrapperElement(
				document, 
				namespaceTable, 
				encodingNamespaceURI, 
				context.getBindingOperation().getOperation().getName(),
				null);
	}
	
	/*
	 * Initializes the contents of new ISOAPMessage.
	 */
	void initMessage(ISOAPMessage message) throws TransportException {
	
		try {
			Document document = XMLUtils.createNewDocument(null);
			
			Hashtable namespaceTable = new Hashtable();
			SoapHelper.addDefaultSoapEnvelopeNamespaces(namespaceTable);
			
			message.setEnvelope(SoapHelper.createSoapEnvelopeElement(document, namespaceTable));
			message.setHeader(SoapHelper.createSoapHeaderElement(document));
			
			Element body = SoapHelper.createSoapBodyElement(document);
			if (!message.getMessageContext().isDocumentStyle()) {
				Element rpcWrapper = createRPCWrapper(document, message.getMessageContext(), namespaceTable);
				body.appendChild(rpcWrapper);
			}			
			message.setBody(body);			
			
			message.setNamespaceTable(namespaceTable);
		}
		catch (ParserConfigurationException e) {
			throw new TransportException(e);
		}		
	}
	
	/*
	 * Returns the first element with the given local name from the soap envelope namespace
	 * This method can be used on elements that are not namespace aware, but we have to give
	 * it a namespace table to look up prefixes.
	 */
	private Element getSOAPElement(Element root, String localName, Map namespaceTable) {
		String prefix = (String) namespaceTable.get(Constants.URI_SOAP11_ENV);
		if (prefix == null)
			return null;
		
		NodeList list = root.getElementsByTagName(prefix + ":" + localName);
		if (list.getLength() == 0)
			return null;
		
		return (Element) list.item(0);
	}
	
	/*
	 * Returns the first element with the given local name from the soap envelope namespace.
	 * This version assume the elements are namespace aware.
	 */
	private Element getSOAPElementNS(Element root, String localName) {
		NodeList list = root.getElementsByTagNameNS(Constants.URI_SOAP11_ENV, localName);
		if (list.getLength() == 0)
			return null;		
	
		return (Element) list.item(0);
	}
	
	/*
	 * Convert a NodeList to a vector of elements, nodes which are not elements are skipped.
	 */
	private Vector toElementVector(NodeList nodes) {
		
		Vector vector = new Vector();
		
		for (int i = 0; i < nodes.getLength(); i++) {
			Node node = nodes.item(i);
			if (node instanceof Element)
		    	vector.add(node);		    
		}
		
		return vector;	
	}
	
	/*
	 * Convert a NodeList to an array of elements, nodes which are not elements are skipped.
	 */
	private Element[] toElementArray(NodeList nodes) {
		Vector vector = toElementVector(nodes);
		Element[] elements = new Element[vector.size()];
		vector.copyInto(elements);
		return elements;
	}
	
	// Serialize ////////////////////////////////////////////////////////////////////////////////////////////////////////////	
	
	/*
	 * adds the encoding style attribute to the each element in the given array.
	 * noop if encodingStyle is null
	 */
	private void addEncodingStyle(Element[] elements, String encodingStyle) {
				
		// encodingStyle is non-null only if use="encoded"
		if (elements == null || encodingStyle == null)
			return;
		
		for (int i=0; i < elements.length; i++) {
	        if (elements[i] == null)
	        	continue;
	    	elements[i].setAttribute(
	    			Constants.NS_PREFIX_SOAP_ENV + ":" + Constants.ATTR_ENCODING_STYLE, encodingStyle);			
		}
	}
	
	/*
	 * Serialize an array of elements
	 */
	private String serializeElements(Element[] elements) {
	
		StringBuffer buffer = new StringBuffer();
		
		for (int i = 0; i < elements.length; i++) {
					
			String serializedFragment = XMLUtils.serialize(elements[i], true);
			if (serializedFragment == null) {
				// On Some JRE's (Sun java 5) elements with an attribute with the xsi
				// prefix do not serialize properly because the namespace can not
				// be found so the string returned comes back as null. To workaround
				// this problem try adding in the namespace declaration attribute
				// and retry the serialization (bug 144824)			 
				elements[i].setAttribute("xmlns:xsi", Constants.URI_2001_SCHEMA_XSI);
				serializedFragment = XMLUtils.serialize(elements[i], true);
			}
			
			buffer.append(serializedFragment);
			buffer.append(LINE_SEPARATOR);
		}
		
		return buffer.toString();
	}

	/*
	 * Determines if the given message is a request message using RPC style
	 */
	private boolean isRPCRequest(ISOAPMessage message) {
		return 
			!message.getMessageContext().isDocumentStyle() &&							// rpc style
			!Boolean.TRUE.equals(message.getProperty(SOAPTransport.PROP_READ_ONLY));	// not read-only
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.wst.ws.internal.explorer.transport.ISerializer#serialize(int, org.eclipse.wst.ws.internal.explorer.transport.ISOAPMessage)
	 */
	public String serialize(int part, ISOAPMessage message) throws TransportException {

		switch (part) {
			case ISOAPMessage.ENVELOPE:
				Element envelope = message.getEnvelope(true);
				
				if (isRPCRequest(message)) {					
					Element body = getSOAPElementNS(envelope, Constants.ELEM_BODY);
					if (body == null)
						body = getSOAPElement(envelope, Constants.ELEM_BODY, message.getNamespaceTable());
					
					if (body != null) {
						Element[] bodyContent = toElementArray(body.getFirstChild().getChildNodes());
						addEncodingStyle(bodyContent, getEncodingInfo(message.getMessageContext())[1]);
					}
				}
				
				String xml = XMLUtils.serialize(envelope, true);
				if (xml == null)
					xml = new String((byte[]) message.getProperty(SOAPTransport.PROP_RAW_BYTES));
				
				return xml;
				
			case ISOAPMessage.HEADER_CONTENT:
				return serializeElements(message.getHeaderContent());
				
			case ISOAPMessage.BODY_CONTENT:				
				Element[] bodyContent = message.getBodyContent();
				
				if (isRPCRequest(message))
					addEncodingStyle(bodyContent, getEncodingInfo(message.getMessageContext())[1]);
				
				return serializeElements(bodyContent);
		}
		
		return "";
	}
	
	// Deserialize //////////////////////////////////////////////////////////////////////////////////////////////////////////		
		
	/*
	 * Retrieve the soap header from the envelope and populate the given message
	 */
	private void processHeader(Element envelope, ISOAPMessage message) {
		
		Element header = getSOAPElementNS(envelope, Constants.ELEM_HEADER);
		if (header == null)
			return;
		
		message.setHeader(header);
		message.setHeaderContent(toElementArray(header.getChildNodes()));
	}
	
	/*
	 * HACK - The root element tag name of the instance document
	 * is ambiguous.  It lands on a very grey area between the SOAP
	 * spec and the WSDL spec.  The two specs do not explicitly define
	 * that the root element tag name must match the name of the
	 * WSDL part.  The hack is to treat elements with different tag names
	 * as instances of the WSDL part.
	 */
	private Element[] fixSOAPResponse(NodeList instanceList, MessageContext context) {
		
		Vector instanceVector = toElementVector(instanceList);		
		Element[] instanceDocuments = new Element[instanceVector.size()];
		
		Operation oper = context.getBindingOperation().getOperation();		
		Map partsMap = oper.getOutput().getMessage().getParts();
		
		if (partsMap.size() == 1) {
			Iterator it = partsMap.values().iterator();
			Part part = (Part) it.next();
			
			String fragName;
			if (part.getElementName() != null)
				fragName = part.getElementName().getLocalPart();
			else
				fragName = part.getName();
		    
		    for (int i = 0; i < instanceVector.size(); i++) {
		    	Element element = (Element) instanceVector.get(i);
		    	
		    	if (!element.getLocalName().equals(fragName)) {
		    		Document doc = element.getOwnerDocument();
		    		NodeList children = element.getChildNodes();
		    		NamedNodeMap attributes = element.getAttributes();
		    		element = doc.createElement(fragName);
		    		
		    		for (int j = 0; j < children.getLength(); j++) {
		    			if (children.item(j) != null) {
		    				element.appendChild(children.item(j));
				            // When you append a node from one element to another,
				            // the original element will lose its reference to this node,
				            // therefore, the size of the node list will decrease by 1.
				            j--;
		    			}
		    		}
		    		
		    		for (int j = 0; j < attributes.getLength(); j++) {
		    			Object attr = attributes.item(j);
		    			if (attr != null && (attr instanceof Attr)) {
		    				Attr attribute = (Attr)attr;
		    				element.setAttribute(attribute.getName(), attribute.getValue());
		    			}
		    		}
		    	}
		    	instanceDocuments[i] = element;
		    }
		}
		else
			instanceVector.copyInto(instanceDocuments);
		
		return instanceDocuments;
	}
	
	/*
	 * Retrieve the soap header from the envelope and populate the given message
	 */
	private void processBody(Element envelope, ISOAPMessage message) {
		
		Element body = getSOAPElementNS(envelope, Constants.ELEM_BODY);
		if (body == null)
			return;				
		
		message.setBody(body);
		
		// check for soap fault
		Element fault = getSOAPElementNS(body, Constants.ELEM_FAULT);
	    if (fault != null) {
	    	message.setFault(fault);
	    	return;
	    }
	        	        
	    NodeList instanceList;
	    
	    if (message.getMessageContext().isDocumentStyle())
	    	instanceList = body.getChildNodes();
	    else {
	        NodeList rpcWrapper = body.getElementsByTagNameNS("*", 
	        		message.getMessageContext().getBindingOperation().getOperation().getOutput().getMessage().getQName().getLocalPart());

	        /*
	        * HACK - Some of the web services out on the internet do not
	        * set their RPC wrapper properly.  It should be set to the output
	        * message name of the selected operation.  The hack is to
	        * assume the first element inside the body element is the
	        * RPC wrapper.
	        */
	        if (rpcWrapper.getLength() <= 0)
	        	rpcWrapper = body.getElementsByTagNameNS("*", "*");

	        if (rpcWrapper.getLength() > 0)
	        	instanceList = rpcWrapper.item(0).getChildNodes();
	        else
	        	return;
	    }
	    
	    message.setBodyContent(fixSOAPResponse(instanceList, message.getMessageContext()));
	}
	
	/*
	 * Deserialize the byte array into the given soap message.  The part parameters tells
	 * the method whether the input is the whole envelop or just the contents of the
	 * header or body. 
	 */
	void deserialize(int part, byte[] xml, ISOAPMessage message) throws		
		ParserConfigurationException,
		SAXException,
		IOException {
		
		Element root = XMLUtils.byteArrayToElement(xml, true);		
		
		switch (part) {
			case ISOAPMessage.ENVELOPE:				 
				message.setEnvelope(root);
				processHeader(root, message);
				processBody(root, message);
				break;
			case ISOAPMessage.HEADER_CONTENT:
				message.setHeaderContent(toElementArray(root.getChildNodes()));
				break;
			case ISOAPMessage.BODY_CONTENT:
				message.setBodyContent(toElementArray(root.getChildNodes()));
				break;
		}
	}
	
	/*
	 * Tack on a root element the string which represents a series of elements.
	 * This is needed to deserialize the string.
	 */
	private String addRootElement(String xml, Map namespaceTable) {
		StringBuffer sb = new StringBuffer();
	    sb.append("<root");
	    
	    Iterator iter = namespaceTable.keySet().iterator();
	    while (iter.hasNext()) {
	    	Object uri = iter.next();
	    	Object prefix = namespaceTable.get(uri);
	    	sb.append(" ").append("xmlns:").append(prefix).append("=\"").append(uri).append("\"");
	    }	    
	    
	    sb.append(">").append(xml).append("</root>");
	    return sb.toString();
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.wst.ws.internal.explorer.transport.IDeserializer#deserialize(int, java.lang.String, org.eclipse.wst.ws.internal.explorer.transport.ISOAPMessage)
	 */
	public void deserialize(int part, String xml, ISOAPMessage message) throws TransportException {
		
		if (part != ISOAPMessage.ENVELOPE)
			xml = addRootElement(xml, message.getNamespaceTable());
		
		try {
			deserialize(part, xml.getBytes(DEFAULT_SOAP_ENCODING), message);
		}
		catch (Exception e) {
			throw new TransportException(e);
		}
	}
}
