blob: 4ad5061c1ddd02338aef0e640006aa5928f3f1ce [file] [log] [blame]
/*
* 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;
}
}