/*
 * Copyright (C) 2003 The University of Manchester 
 *
 * Modifications to the initial code base are copyright of their
 * respective authors, or their employers as appropriate.  Authorship
 * of the modifications may be determined from the ChangeLog placed at
 * the end of this file.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA.
 *
 ****************************************************************
 * Source code information
 * -----------------------
 * Filename           $RCSfile: XMLOutputSplitter.java,v $
 * Revision           $Revision: 1.2 $
 * Release status     $State: Exp $
 * Last modified on   $Date: 2008/08/08 10:28:07 $
 *               by   $Author: stain $
 * Created on 16-May-2006
 *****************************************************************/
package net.sf.taverna.wsdl.xmlsplitter;

import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.taverna.wsdl.parser.ArrayTypeDescriptor;
import net.sf.taverna.wsdl.parser.BaseTypeDescriptor;
import net.sf.taverna.wsdl.parser.ComplexTypeDescriptor;
import net.sf.taverna.wsdl.parser.TypeDescriptor;

import org.apache.axis.encoding.Base64;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

public class XMLOutputSplitter {

	private TypeDescriptor typeDescriptor;
	private String[] outputNames;
	private String[] inputNames;
	private String[] outputTypes;

	public XMLOutputSplitter(TypeDescriptor typeDescriptor,
			String[] outputNames, String[] outputTypes,String[] inputNames) {
		this.typeDescriptor = typeDescriptor;
		this.outputNames = outputNames;
		this.inputNames = inputNames;
		this.outputTypes = outputTypes;
	}

	@SuppressWarnings("unchecked")
	public Map<String, Object> execute(Map<String, String> inputMap)
			throws XMLSplitterExecutionException {

		Map<String, Object> result = new HashMap<String, Object>();
		List<String> outputNameList = Arrays.asList(outputNames);

		String xml = inputMap.get(inputNames[0]);
		try {
			Document doc = new SAXBuilder().build(new StringReader(xml));
			List<Element> children = doc.getRootElement().getChildren();
			if (typeDescriptor instanceof ArrayTypeDescriptor) {
				if (outputNames.length > 1)
					throw new XMLSplitterExecutionException(
							"Unexpected, multiple output names for ArrayType");
				executeForArrayType(result, children);
			} else {
				executeForComplexType(result, outputNameList, children, doc.getRootElement().getAttributes());
			}

			// populate missing outputs with empty strings for basic types,
			// empty elements for complex/array types.
			for (int i = 0; i < outputNames.length; i++) {
				if (result.get(outputNames[i]) == null) {
					if (outputTypes[i].equals("'text/xml'")) {
						result
								.put(outputNames[i], "<" + outputNames[i]
										+ " />");
					} else if (outputTypes[i].startsWith("l('")) {
						result.put(outputNames[i], new ArrayList<Object>());
					} else {
						result.put(outputNames[i], "");
					}

				}
			}
		} catch (JDOMException e) {
			throw new XMLSplitterExecutionException("Unable to parse XML: " + xml, e);
		} catch (IOException e) {
			throw new XMLSplitterExecutionException("IOException parsing XML: " + xml,
					e);
		}

		return result;
	}

	private void executeForArrayType(Map<String, Object> result,
			List<Element> children) {
		ArrayTypeDescriptor arrayDescriptor = (ArrayTypeDescriptor) typeDescriptor;
		List<String> values = new ArrayList<String>();
		XMLOutputter outputter = new XMLOutputter();

		boolean isInnerBaseType = arrayDescriptor.getElementType() instanceof BaseTypeDescriptor;
		if (isInnerBaseType) {
			values = extractBaseTypeArrayFromChildren(children);
		} else {
			for (Element child : children) {
				values.add(outputter.outputString(child));
			}
		}
		result.put(outputNames[0], values);
	}

	@SuppressWarnings({ "unchecked" })
	private void executeForComplexType(Map<String, Object> result,
			List<String> outputNameList, List<Element> children, List<Attribute> list)
			throws IOException {               

		XMLOutputter outputter = new XMLOutputter();
		for (Element child : children) {
			
			if (outputNameList.contains(child.getName())) {
				int i = outputNameList.indexOf(child.getName());
				TypeDescriptor descriptorForChild = ((ComplexTypeDescriptor) typeDescriptor)
						.elementForName(outputNames[i]);
				if (outputTypes[i].startsWith("l(")
						&& descriptorForChild instanceof ArrayTypeDescriptor
						&& !((ArrayTypeDescriptor) descriptorForChild)
								.isWrapped()) {
					boolean isXMLContent = outputTypes[i].contains("text/xml");
					result.put(child.getName(), extractDataListFromChildList(
							children, isXMLContent));
                    break;
				} else {
					if (outputTypes[i].equals("'text/xml'")
							|| outputTypes[i].equals("l('text/xml')")) {
						String xmlText = outputter.outputString(child);
						result.put(child.getName(), xmlText);
					} else if (outputTypes[i]
							.equals("'application/octet-stream'")) { // base64Binary
						
						byte[] data = Base64.decode(child
								.getText());
						result.put(child.getName(), data);
					} else if (outputTypes[i].equals("l('text/plain')")) { // an
																			// inner
																			// element
																			// containing
																			// a
																			// list
						result.put(child.getName(),
								extractBaseTypeArrayFromChildren(child
										.getChildren()));
					} else {
						result.put(child.getName(), child.getText());
					}
				}
			}
		}
		for (Attribute attribute : list) {
			if (outputNameList.contains("1" + attribute.getName())) {
				result.put("1" + attribute.getName(), attribute.getValue());
			} else if (outputNameList.contains(attribute.getName())) {
				result.put(attribute.getName(), attribute.getValue());
			}
		}
	}

	private List<String> extractDataListFromChildList(List<Element> children,
			boolean isXMLContent) {
		List<String> result = new ArrayList<String>();
		XMLOutputter outputter = new XMLOutputter();
		for (Element child : children) {
			if (!isXMLContent) {
				result.add(child.getTextTrim());
			} else {
				result.add(outputter.outputString(child));
			}
		}
		return result;
	}

	private List<String> extractBaseTypeArrayFromChildren(List<Element> children) {
		List<String> result = new ArrayList<String>();
		for (Element child : children) {
			result.add(child.getTextTrim());
		}
		return result;
	}

}
