/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE 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.tuscany.sca.databinding.util;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.tuscany.sca.interfacedef.DataType;
import org.apache.tuscany.sca.interfacedef.Interface;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.interfacedef.util.WrapperInfo;
/**
*
* @version $Rev$ $Date$
*/
public final class DataTypeHelper {
private DataTypeHelper() {
}
/**
* Find all classes referenced by this data type though java generics
* @param d
* @return
*/
public static Set<Class<?>> findClasses(DataType d) {
Set<Class<?>> classes = new HashSet<Class<?>>();
Set<Type> visited = new HashSet<Type>();
findClasses(d, classes, visited);
return classes;
}
private static void findClasses(DataType d, Set<Class<?>> classes, Set<Type> visited) {
if (d == null) {
return;
}
classes.add(d.getPhysical());
if (d.getPhysical() != d.getGenericType()) {
findClasses(d.getGenericType(), classes, visited);
}
}
/**
* Find referenced classes in the generic type
* @param type
* @param classSet
* @param visited
*/
private static void findClasses(Type type, Set<Class<?>> classSet, Set<Type> visited) {
if (visited.contains(type) || type == null) {
return;
}
visited.add(type);
if (type instanceof Class) {
Class<?> cls = (Class<?>)type;
if (!cls.isInterface()) {
classSet.add(cls);
}
return;
} else if (type instanceof ParameterizedType) {
ParameterizedType pType = (ParameterizedType)type;
findClasses(pType.getRawType(), classSet, visited);
for (Type t : pType.getActualTypeArguments()) {
findClasses(t, classSet, visited);
}
} else if (type instanceof TypeVariable) {
TypeVariable<?> tv = (TypeVariable<?>)type;
for (Type t : tv.getBounds()) {
findClasses(t, classSet, visited);
}
} else if (type instanceof GenericArrayType) {
GenericArrayType gType = (GenericArrayType)type;
findClasses(gType, classSet, visited);
} else if (type instanceof WildcardType) {
WildcardType wType = (WildcardType)type;
for (Type t : wType.getLowerBounds()) {
findClasses(t, classSet, visited);
}
for (Type t : wType.getUpperBounds()) {
findClasses(t, classSet, visited);
}
}
}
/**
* Get all the data types in the interface
* @param intf The interface
* @param useWrapper Use wrapper classes?
* @return A list of DataTypes
*/
public static List<DataType> getDataTypes(Interface intf, boolean useWrapper) {
List<DataType> dataTypes = new ArrayList<DataType>();
for (Operation op : intf.getOperations()) {
getDataTypes(dataTypes, op, useWrapper);
}
return dataTypes;
}
/**
* Get all the data types in the operation
* @param op The operation
* @param useWrapper Use wrapper classes?
* @return A list of DataTypes
*/
public static List<DataType> getDataTypes(Operation op, boolean useWrapper) {
List<DataType> dataTypes = new ArrayList<DataType>();
getDataTypes(dataTypes, op, useWrapper);
return dataTypes;
}
private static void getDataTypes(List<DataType> dataTypes, Operation op, boolean useWrapper) {
WrapperInfo wrapper = op.getWrapper();
if (useWrapper && wrapper != null) {
DataType dt1 = wrapper.getInputWrapperType();
if (dt1 != null) {
dataTypes.add(dt1);
}
DataType dt2 = wrapper.getOutputWrapperType();
if (dt2 != null) {
dataTypes.add(dt2);
}
}
// FIXME: [rfeng] We may need to find the referenced classes in the child types
// else
{
for (DataType dt1 : op.getInputType().getLogical()) {
dataTypes.add(dt1);
}
DataType dt2 = op.getOutputType();
if (dt2 != null) {
dataTypes.add(dt2);
}
}
for (DataType<DataType> dt3 : op.getFaultTypes()) {
DataType dt4 = dt3.getLogical();
if (dt4 != null) {
dataTypes.add(dt4);
}
}
}
}