blob: 69344f8a481549e948280e43526965f00ee2662d [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2007 The University of Manchester
*
* Modifications to the initial code base are copyright of their
* respective authors, or their employers as appropriate.
*
* 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
******************************************************************************/
package net.sf.taverna.wsdl.parser;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.namespace.QName;
/**
* Base class for all descriptors for type
*
*/
public class TypeDescriptor {
private String name;
private String type;
private boolean optional;
private boolean unbounded;
private QName qname;
private boolean nillable = false;
private String documentation;
public boolean isNillable() {
return nillable;
}
public QName getQname() {
if (qname != null)
return qname;
else {
return new QName("", type);
}
}
public void setQnameFromString(String qname) {
String[] split = qname.split("}");
if (split.length == 1) {
this.qname = new QName("", qname);
} else {
String uri = split[0];
uri = uri.replaceAll("\\{", "");
uri = uri.replaceAll("\\}", "");
this.qname = new QName(uri, split[1]);
}
}
public String getMimeType() {
return translateJavaType(determineClassType(this));
}
public void setQname(QName qname) {
this.qname = qname;
}
public String getNamespaceURI() {
return getQname().getNamespaceURI();
}
public String getName() {
return name;
}
public void setName(String name) {
int i;
if ((i = name.lastIndexOf('>')) != -1) {
this.name = name.substring(i + 1);
} else {
this.name = name;
}
}
/**
* @return the depth determined from the syntactic mime type of the original
* port. i.e text/plain = 0, l('text/plain') = 1, l(l('text/plain')) =
* 2, ... etc.
*/
public int getDepth() {
String syntacticType=getMimeType();
if (syntacticType == null) {
return 0;
} else {
return syntacticType.split("l\\(").length - 1;
}
}
public boolean isOptional() {
return optional;
}
public void setOptional(boolean optional) {
this.optional = optional;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public boolean isUnbounded() {
return unbounded;
}
public void setUnbounded(boolean unbounded) {
this.unbounded = unbounded;
}
@Override
public String toString() {
return name + ":" + type;
}
/**
* Translate a java type into a taverna type string
*/
public static String translateJavaType(Class<?> type) {
if (type.equals(String[].class)) {
return "l('text/plain')";
} else if (type.equals(org.w3c.dom.Element.class)) {
return "'text/xml'";
}
else if (type.equals(org.w3c.dom.Element[].class)) {
return "l('text/xml')";
} else if (type.equals(byte[].class)) {
return "'application/octet-stream'";
} else {
return "'text/plain'";
}
}
public static void retrieveSignature(List<TypeDescriptor> params, String[] names,
Class<?>[] types) {
for (int i = 0; i < names.length; i++) {
TypeDescriptor descriptor = params.get(i);
names[i] = descriptor.getName();
types[i]=determineClassType(descriptor);
}
}
private static Class<?> determineClassType(TypeDescriptor descriptor) {
String s = descriptor.getType().toLowerCase();
Class<?> type;
if (descriptor instanceof ArrayTypeDescriptor) {
if (((ArrayTypeDescriptor) descriptor).getElementType() instanceof BaseTypeDescriptor) {
type = String[].class;
} else if (((ArrayTypeDescriptor) descriptor).isUnbounded()) {
type = org.w3c.dom.Element[].class;
}
else {
type = org.w3c.dom.Element.class;
}
} else {
if ("string".equals(s)) {
type = String.class;
} else if ("double".equals(s) || "decimal".equals(s)) {
type = Double.TYPE;
} else if ("float".equals(s)) {
type = Float.TYPE;
} else if ("int".equals(s) || "integer".equals(s)) {
type = Integer.TYPE;
} else if ("boolean".equals(s)) {
type = Boolean.TYPE;
} else if ("base64binary".equals(s)) {
type = byte[].class;
} else {
//treat any other basetype as a String.
if (descriptor instanceof BaseTypeDescriptor) {
type=String.class;
}
else {
type = org.w3c.dom.Element.class;
}
}
}
return type;
}
/**
* Determines whether the descriptor describes a data structure that is
* cyclic, i.e. contains inner elements that contain references to outer
* elements, leading to a state of infinate recursion.
*
* @param descriptor
* @return
*/
public static boolean isCyclic(TypeDescriptor descriptor) {
boolean result = false;
if (!(descriptor instanceof BaseTypeDescriptor)) {
if (descriptor instanceof ComplexTypeDescriptor) {
result = testForCyclic((ComplexTypeDescriptor) descriptor,
new ArrayList<String>());
} else {
result = testForCyclic((ArrayTypeDescriptor) descriptor,
new ArrayList<String>());
}
}
return result;
}
@SuppressWarnings("unchecked")
private static boolean testForCyclic(ComplexTypeDescriptor descriptor,
List<String> parents) {
boolean result = false;
String descKey = descriptor.getQname().toString();
if (parents.contains(descKey))
result = true;
else {
parents.add(descKey);
List elements = descriptor.getElements();
for (Iterator iterator = elements.iterator(); iterator.hasNext();) {
TypeDescriptor elementDescriptor = (TypeDescriptor) iterator
.next();
if (elementDescriptor instanceof ComplexTypeDescriptor) {
result = testForCyclic(
(ComplexTypeDescriptor) elementDescriptor, parents);
} else if (elementDescriptor instanceof ArrayTypeDescriptor) {
result = testForCyclic(
(ArrayTypeDescriptor) elementDescriptor, parents);
}
if (result)
break;
}
parents.remove(descKey);
}
return result;
}
private static boolean testForCyclic(ArrayTypeDescriptor descriptor,
List<String> parents) {
boolean result = false;
String descKey = descriptor.getQname().toString();
if (parents.contains(descKey))
result = true;
else {
parents.add(descKey);
TypeDescriptor elementDescriptor = descriptor
.getElementType();
if (elementDescriptor instanceof ComplexTypeDescriptor) {
result = testForCyclic(
(ComplexTypeDescriptor) elementDescriptor, parents);
} else if (elementDescriptor instanceof ArrayTypeDescriptor) {
result = testForCyclic((ArrayTypeDescriptor) elementDescriptor,
parents);
}
parents.remove(descKey);
}
return result;
}
public void setNillable(boolean nillable) {
this.nillable = nillable;
}
public String getDocumentation() {
return documentation;
}
public void setDocumentation(String documentation) {
this.documentation = documentation;
}
}