private List getOperations()

in modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java [208:365]


    private <T> List<Operation> getOperations(Class<T> clazz,
                                              boolean remotable,
                                              String ns) throws InvalidInterfaceException {

        Set<Type> genericInterfaces = new HashSet<Type>();
        collectGenericInterfaces(clazz, genericInterfaces);
        Map<String, Type> typeBindings = new HashMap<String, Type>();
        for (Type genericInterface : genericInterfaces) {
            if (genericInterface instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType)genericInterface;
                TypeVariable<?>[] typeVariables = ((Class<?>)parameterizedType.getRawType()).getTypeParameters();
                Type[] typeArguments = parameterizedType.getActualTypeArguments();
                for (int i = 0; i < typeArguments.length; i++) {
                    typeBindings.put(typeVariables[i].getName(), typeArguments[i]);
                }
            }
        }
        
        boolean isAsyncService = clazz.isAnnotationPresent(AsyncInvocation.class);

        Method[] methods = clazz.getMethods();
        List<Operation> operations = new ArrayList<Operation>(methods.length);
        Set<String> names = remotable ? new HashSet<String>() : null;
        for (Method method : methods) {
            boolean hasMultipleOutputs = false;
            if (method.getDeclaringClass() == Object.class) {
                // Skip the methods on the Object.class
                continue;
            }
            String name = method.getName();

            Class<?> lastParameter = method.getParameterTypes().length > 0 ? method.getParameterTypes()[method.getParameterTypes().length-1] : null;
            boolean isAsyncMethod = isAsyncService && name.endsWith("Async") && lastParameter != null && ResponseDispatch.class.equals(lastParameter);

            if (isAsyncMethod) {
                name = name.substring(0, name.length()-5);
            }

            if (remotable && names.contains(name)) {
                throw new OverloadedOperationException(method);
            }
            if (remotable && !jaxwsAsyncMethod(method)) {
                names.add(name);
            }

            Class<?>[] parameterTypes = getActualTypes(method.getGenericParameterTypes(), method.getParameterTypes(), typeBindings, isAsyncMethod);

            Class<?> returnType;
            if (isAsyncMethod) {
                ParameterizedType t = (ParameterizedType)method.getGenericParameterTypes()[method.getGenericParameterTypes().length-1];
                returnType = (Class<?>)t.getActualTypeArguments()[0];
            } else {
                returnType = getActualType(method.getGenericReturnType(), method.getReturnType(), typeBindings);
            }

            Class<?>[] faultTypes =
                getActualTypes(method.getGenericExceptionTypes(), method.getExceptionTypes(), typeBindings, false);
            Class<?>[] allOutputTypes = getOutputTypes(returnType, parameterTypes);

            // For async server interfaces, faults are described using the @AsyncFaults annotation
            if( method.isAnnotationPresent(AsyncFault.class) ) {
                faultTypes = readAsyncFaultTypes( method );
            } // end if 

            boolean nonBlocking = method.isAnnotationPresent(OneWay.class);
            if (nonBlocking) {
                if (!(returnType == void.class)) {
                    throw new InvalidOperationException(
                                                        "Method should return 'void' when declared with an @OneWay annotation. " + method,
                                                        method);
                }
                if (!(faultTypes.length == 0)) {
                    throw new InvalidOperationException(
                                                        "Method should not declare exceptions with an @OneWay annotation. " + method,
                                                        method);
                }
            }

            JavaOperation operation = new JavaOperationImpl();
            operation.setName(name);

            // Given details of Holder mapping, it's easier to handle output first.                
            List<DataType> outputDataTypes = new ArrayList<DataType>();
            XMLType xmlReturnType = new XMLType(new QName(ns, "return"), null);            
            DataType<XMLType> returnDataType = null;
            if (returnType == void.class) {
                operation.setReturnTypeVoid(true);
            } else {
                if (isAsyncMethod) {
                    returnDataType = new DataTypeImpl<XMLType>(UNKNOWN_DATABINDING, returnType, returnType, xmlReturnType);
                } else {
                    returnDataType = new DataTypeImpl<XMLType>(UNKNOWN_DATABINDING, returnType, method.getGenericReturnType(), xmlReturnType);
                }
                 operation.setReturnTypeVoid(false);
                 outputDataTypes.add(returnDataType);
            }

            // Handle Input Types
            List<DataType> paramDataTypes = new ArrayList<DataType>(parameterTypes.length);
            Type[] genericParamTypes = method.getGenericParameterTypes();
            for (int i = 0; i < parameterTypes.length; i++) {
                Class<?> paramType = parameterTypes[i];
                XMLType xmlParamType = new XMLType(new QName(ns, "arg" + i), null);                            

                DataTypeImpl<XMLType> xmlDataType = new DataTypeImpl<XMLType>(
                    UNKNOWN_DATABINDING, paramType, genericParamTypes[i],xmlParamType);
                ParameterMode mode = ParameterMode.IN;
                // Holder pattern. Physical types of Holder<T> classes are updated to <T> to aid in transformations.
                if ( Holder.class == paramType) {
                    hasMultipleOutputs = true;
                    Type firstActual = getFirstActualType( genericParamTypes[ i ] );
                    if ( firstActual != null ) {
                        xmlDataType.setPhysical( (Class<?>)firstActual );
                        mode = ParameterMode.INOUT;
                    } 
                    outputDataTypes.add(xmlDataType);
                }
                paramDataTypes.add( xmlDataType);
                operation.getParameterModes().add(mode);
            }

            // Fault types                                                          
            List<DataType> faultDataTypes = new ArrayList<DataType>(faultTypes.length);
            Type[] genericFaultTypes = method.getGenericExceptionTypes();
            if( method.isAnnotationPresent(AsyncFault.class) ) {
                genericFaultTypes = readAsyncGenericFaultTypes( method );
            } // end if
            for (int i = 0; i < faultTypes.length; i++) {
                Class<?> faultType = faultTypes[i];
                // Only add checked exceptions
                // JAXWS Specification v2.1 section 3.7 says RemoteException should not be mapped
                if (Exception.class.isAssignableFrom(faultType) && (!RuntimeException.class.isAssignableFrom(faultType))
                    && (!RemoteException.class.isAssignableFrom(faultType))) {
                    XMLType xmlFaultType = new XMLType(new QName(ns, faultType.getSimpleName()), null);
                    DataType<XMLType> faultDataType =
                        new DataTypeImpl<XMLType>(UNKNOWN_DATABINDING, faultType, genericFaultTypes[i], xmlFaultType);
                    faultDataTypes.add(new DataTypeImpl<DataType>(UNKNOWN_DATABINDING, faultType, genericFaultTypes[i],
                        faultDataType));
                }
            }

            DataType<List<DataType>> inputType =
                new DataTypeImpl<List<DataType>>(IDL_INPUT, Object[].class, paramDataTypes);
            DataType<List<DataType>> outputType = 
                new DataTypeImpl<List<DataType>>(IDL_OUTPUT, Object[].class, outputDataTypes);

            operation.setOutputType(outputType);

            operation.setInputType(inputType);                     
            operation.setFaultTypes(faultDataTypes);
            operation.setNonBlocking(nonBlocking);
            operation.setJavaMethod(method);
            operation.setHasArrayWrappedOutput(hasMultipleOutputs); 
            operation.setAsyncServer(isAsyncMethod);
            operations.add(operation);
        }
        return operations;
    }