/* # Licensed Materials - Property of IBM # Copyright IBM Corp. 2015 */ package com.ibm.streamsx.topology.internal.core; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import com.ibm.streamsx.topology.function.Function; import com.ibm.streamsx.topology.function.Supplier; import com.ibm.streamsx.topology.function.UnaryOperator; /** * Methods to determine the stream Java type from the logic type passed in. */ public class TypeDiscoverer { private static IllegalArgumentException nullTupleClass() { return new IllegalArgumentException("The tuple's class type must be known!"); } /** * */ public static Type determineStreamType(Function<?,?> function, Type tupleType) { if (tupleType != null) return tupleType; if (function instanceof UnaryOperator) return determineStreamTypeFromFunctionArg(UnaryOperator.class, 0, function); return determineStreamTypeFromFunctionArg(Function.class, 1, function); } public static Type determineStreamTypeFromFunctionArg(Class<?> objectInterface, int arg, Object function) { ParameterizedType pt = findParameterizedType(objectInterface, function); if (pt != null) { return pt.getActualTypeArguments()[arg]; } return null; } public static <T> Type determineStreamTypeNested(Class<?> objectInterface, int arg, Class<?> nestedInterface, Object function) { ParameterizedType pt = findParameterizedType(objectInterface, function); if (pt != null) { Type nestedArg = pt.getActualTypeArguments()[arg]; ParameterizedType nestedPt; if (nestedArg instanceof Class) nestedPt = findParameterizedType(nestedInterface, (Class<?>) nestedArg); else if (nestedArg instanceof ParameterizedType) nestedPt = (ParameterizedType) nestedArg; else return Object.class; if (nestedPt == null || !nestedInterface.equals(nestedPt.getRawType())) { return Object.class; } return nestedPt.getActualTypeArguments()[0]; } return Object.class; } public static Type determineStreamType(Supplier<?> function, Type tupleType) { if (tupleType != null) return tupleType; return determineStreamTypeFromFunctionArg(Supplier.class, 0, function); } private static ParameterizedType findParameterizedType(Class<?> functionInterface, Object function) { assert functionInterface.isInstance(function); Class<?> type = function.getClass(); return findParameterizedType(functionInterface, type); } private static ParameterizedType findParameterizedType(Class<?> functionInterface, Class<?> type) { assert functionInterface.isAssignableFrom(type); do { for (Type ty : type.getGenericInterfaces()) { if (ty instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType) ty; if (functionInterface.equals(pt.getRawType())) { return pt; } } } type = type.getSuperclass(); } while (!Object.class.equals(type)); return null; } public static String getTupleName(Type tupleType) { if (tupleType instanceof Class) return ((Class<?>) tupleType).getSimpleName(); return "Object"; } }