// Licensed to the Apache Software Foundation (ASF) under one or more contributor
// license agreements.  See the NOTICE.txt 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.oodt.commons.util;

import java.io.*;
import java.util.*;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import org.w3c.dom.*;
import org.xml.sax.*;

/** XML-RPC utilities.
 *
 * This class provides several XML-RPC utilities.
 *
 * @author Kelly
 */
public class XMLRPC {
	/** Build an XML-RPC method call.
	 *
	 * This may throw {@link IllegalArgumentException} if the <var>params</var>
	 * contains an object that's incompatible with XML-RPC.
	 *
	 * @param name Name of the method to call.
	 * @param params Parameters to pass to the call.
	 * @return An XML string encapsulationg the call.
	 * @throws DOMException If we can't construct the call.
	 */
	public static byte[] createMethodCall(String name, Collection params) throws DOMException {
		Document doc = XML.createDocument();
		Element methodCallElement = doc.createElement("methodCall");
		doc.appendChild(methodCallElement);
		XML.add(methodCallElement, "methodName", name);
		if (params != null && !params.isEmpty()) {
			Element paramsElement = doc.createElement("params");
			methodCallElement.appendChild(paramsElement);
			for (Iterator i = params.iterator(); i.hasNext();)
				paramsElement.appendChild(createValueElement(doc, i.next()));
		}
		return XML.serialize(doc).getBytes();
	}

	/** Create a &lt;value&gt; element for an XML-RPC method.
	 *
	 * This may throw {@link IllegalArgumentException} if the <var>value</var> is
	 * incompatible with XML-RPC.
	 *
	 * @param doc Owning document.
	 * @param value The value.
	 * @throws DOMException If we can't construct the &lt;value&gt;.
	 */
	private static Element createValueElement(Document doc, Object value) throws DOMException {
		if (value == null)
			throw new IllegalArgumentException("Nulls not supported in XML-RPC");
		Element valueElement = doc.createElement("value");
		if (value instanceof Integer || value instanceof Short) {
			XML.add(valueElement, "int", value.toString());
		} else if (value instanceof Boolean) {
			XML.add(valueElement, "boolean", ((Boolean) value).booleanValue()? "1" : "0");
		} else if (value instanceof String) {
			Element stringElement = doc.createElement("string");
			valueElement.appendChild(stringElement);
			stringElement.appendChild(doc.createCDATASection(value.toString()));
		} else if (value instanceof Float || value instanceof Double) {
			XML.add(valueElement, "double", value.toString());
		} else if (value instanceof Date) {
			XML.add(valueElement, "dateTime.iso8601", ISO8601_FORMAT.format((Date) value));
		} else if (value instanceof byte[]) {
			Element base64Element = doc.createElement("base64");
			valueElement.appendChild(base64Element);
			base64Element.appendChild(doc.createCDATASection(new String(Base64.encode((byte[])value))));
		} else if (value instanceof Map) {
			Element structElement = doc.createElement("struct");
			valueElement.appendChild(structElement);
			Map map = (Map) value;
			for (Iterator i = map.entrySet().iterator(); i.hasNext();) {
				Element memberElement = doc.createElement("member");
				valueElement.appendChild(memberElement);
				Map.Entry entry = (Map.Entry) i.next();
				if (!(entry.getKey() instanceof String))
					throw new IllegalArgumentException("Keys in maps for XML-RPC structs must be Strings");
				XML.add(memberElement, "name", entry.getKey().toString());
				memberElement.appendChild(createValueElement(doc, entry.getValue()));
			}
		} else if (value instanceof Collection) {
			Element arrayElement = doc.createElement("array");
			valueElement.appendChild(arrayElement);
			Element dataElement = doc.createElement("data");
			arrayElement.appendChild(dataElement);
			Collection collection = (Collection) value;
			for (Iterator i = collection.iterator(); i.hasNext();)
				dataElement.appendChild(createValueElement(doc, i.next()));
		} else throw new IllegalArgumentException(value.getClass().getName() + " not supported in XML-RPC");
		return valueElement;
	}

	/** Parse an XML-RPC method response.
	 *
	 * @param response The response data.
	 * @return The value contained in the <var>response</var>.
	 * @throws XMLRPCFault If the <var>response</var> contained a fault.
	 */
	public static Object parseResponse(byte[] response) throws XMLRPCFault {
		try {
			DOMParser parser = XML.createDOMParser();
			parser.setFeature("http://xml.org/sax/features/validation", false);
			parser.parse(new InputSource(new ByteArrayInputStream(response)));
			Document doc = parser.getDocument();
			doc.normalize();
			XML.removeComments(doc);
			Element methodResponseElement = doc.getDocumentElement();
			if (!"methodResponse".equals(methodResponseElement.getNodeName()))
				throw new SAXException("Not a <methodResponse> document");
			Node child = methodResponseElement.getFirstChild();
			if ("params".equals(child.getNodeName())) {
				return parseValue(child.getFirstChild().getFirstChild());
			} else if ("fault".equals(child.getNodeName())) {
				try {
					Map map = (Map) parseValue(child.getFirstChild());
					throw new XMLRPCFault(((Integer) map.get("faultCode")).intValue(),
						(String) map.get("faultString"));
				} catch (ClassCastException ex) {
					throw new SAXException("XML-RPC <fault> invalid");
				}
			} else throw new SAXException("XML-RPC response does not contain <params> or <fault>");
		} catch (SAXException ex) {
			throw new IllegalArgumentException(ex.getMessage());
		} catch (IOException ex) {
			throw new RuntimeException("Unexpected I/O exception that shouldn't happen, but did: " + ex.getMessage());
		}
	}

	/** Parse an XML-RPC &lt;value&gt;.
	 *
	 * @param node The &lt;value&gt; node.
	 * @return The Java value of <var>node</var>.
	 */
	private static Object parseValue(Node node) {
		String n = node.getNodeName();
		if (!"value".equals(n)) throw new IllegalArgumentException("Expecting a <value>, not a <" + n + ">");
		Node t = node.getFirstChild();
		n = t.getNodeName();

		// Default if there's no nested element is a String.
		if (t.getNodeType() == Node.TEXT_NODE || t.getNodeType() == Node.CDATA_SECTION_NODE) {
			return t.getNodeValue();
		}

		// Figure out what the type is from the nested element.
		String txt = XML.unwrappedText(t);
		if ("i4".equals(n) || "int".equals(n)) {
			return new Integer(txt);
		} else if ("boolean".equals(n)) {
			if ("1".equals(txt))      return new Boolean(true);
			else if ("0".equals(txt)) return new Boolean(false);
			else throw new IllegalArgumentException(n + " does not contain a 0 or 1");
		} else if ("string".equals(n)) {
			return txt;
		} else if ("double".equals(n)) {
			return new Double(txt);
		} else if ("dateTime.iso8601".equals(n)) {
			try {
				return ISO8601_FORMAT.parse(txt);
			} catch (ParseException ex) {
				throw new IllegalArgumentException(n + " does not contain an ISO8601 format date/time");
			}
		} else if ("base64".equals(n)) {
			return Base64.decode(txt.getBytes());
		} else if ("struct".equals(n)) {
			Map m = new HashMap();
			NodeList memberNodes = t.getChildNodes();
			for (int i = 0; i < memberNodes.getLength(); ++i) {
				Node memberNode = memberNodes.item(i);
				if (!"member".equals(memberNode.getNodeName()))
					throw new IllegalArgumentException(n + " contains <" + memberNode.getNodeName()
						+ ">, not <member>");
				Node nameNode = memberNode.getFirstChild();
				if (nameNode == null || !"name".equals(nameNode.getNodeName()))
					throw new IllegalArgumentException("<member> missing <name> element");
				Node valueNode = nameNode.getNextSibling();
				if (valueNode == null || !"value".equals(valueNode.getNodeName()))
					throw new IllegalArgumentException("<member> missing <value> element");
				m.put(XML.unwrappedText(nameNode), parseValue(valueNode));
			}
			return m;
		} else if ("array".equals(n)) {
			Node dataNode = t.getFirstChild();
			if (dataNode == null || !"data".equals(dataNode.getNodeName()))
				throw new IllegalArgumentException("<array> missing <data> element");
			NodeList children = dataNode.getChildNodes();
			List x = new ArrayList(children.getLength());
			for (int i = 0; i < children.getLength(); ++i)
				x.add(parseValue(children.item(i)));
			return x;
		} else throw new IllegalArgumentException("Illegal type " + n + " in <value>");
	}

	/** Constructor that causes a runtime exception since this is a utility class.
	 */
	private XMLRPC() {
		throw new IllegalStateException("Do not construct XMLRPC objects");
	}

	/** ISO8601 date format for XML-RPC dates. */
	private static DateFormat ISO8601_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
}
