/* Given a service URL, a set of input parameters and a set of expected Output          */
        /* this method calls each operation from the service with the provided input parameters */
        /* matches the obtained outputs with the outputs provided and declares the result of the*/
        /* operation which is then returned.                                                    */
        /* Note that the output parameters need to be provided as an XML string because the     */
        /* deserialization cannot take care of deserializing complex objects to perform the     */
        /* comparison.                                                                          */
        public InvokeResult InvokeWebServiceOperationsGroup(string url, string[] inputParams,
                                                            string[] expectedOutputParams)
        {
            try
            {
                /* Extract the service and the method info from the service */
                Type         serviceType;
                MethodInfo[] methodsInfo;

                /* Extract web service methods */
                GetWebServiceMethods(url, out methodsInfo, out serviceType);

                /* If either of the methods info or the service type weren't obtained, return */
                if (methodsInfo == null || serviceType == null)
                {
                    return(null);
                }

                List <MethodInfo> methodsToInvoke = new List <MethodInfo>();
                int inputParametersRequired       = 0;

                /* Create a list of methods to be invoked */
                foreach (MethodInfo method in methodsInfo)
                {
                    if (method.Name == "Discover")
                    {
                        break;
                    }

                    methodsToInvoke.Add(method);
                    inputParametersRequired += method.GetParameters().Length;
                }

                /* If the number of output parameters passed don't match with the number of */
                /* methods to be invoked, return */
                if (methodsToInvoke.Count != expectedOutputParams.Length)
                {
                    return(null);
                }

                /* The provided input parameters are not sufficient to make all invocations */
                if (inputParametersRequired != inputParams.Length)
                {
                    return(null);
                }

                InvokeResult invokeResults = new InvokeResult(expectedOutputParams.Length);

                int j = 0;
                int k = 0;
                foreach (MethodInfo methodToInvoke in methodsToInvoke)
                {
                    ParameterInfo[] invokeMethodParameters      = methodToInvoke.GetParameters();
                    string[]        invokeMethodInputParameters = new string[invokeMethodParameters.Length];

                    /* The total number of input parameters provided should be equal to the summation */
                    /* of the total number of input parameters provided for each method. If not, there*/
                    /* has been some error in parsing the input parameters and an error has to be     */
                    /* returned. If this case is hit, it is a bug and will need to be debugged.       */
                    if (j >= inputParams.Length)
                    {
                        return(null);
                    }

                    for (int i = 0; i < invokeMethodInputParameters.Length; i++)
                    {
                        invokeMethodInputParameters[i] = inputParams[j];
                        j++;
                    }

                    /* Invoke web service method */
                    ReturnData responseData = InvokeWebServiceMethod(serviceType, methodToInvoke,
                                                                     invokeMethodInputParameters);

                    /* Check if the returned data matches with that provided */
                    if (compareXmlStrings(responseData.objectXML, expectedOutputParams[k]) == false)
                    {
                        invokeResults.InvokeStatus[k] = false;
                    }
                    else
                    {
                        invokeResults.InvokeStatus[k] = true;
                    }

                    invokeResults.MethodName[k] = methodToInvoke.Name;

                    k++;
                }

                return(invokeResults);
            }
            catch (Exception ec)
            {
                throw new FaultException(ec.Message);
            }
        }
        /* Given a service URL, a set of input parameters and a set of expected Output          */
        /* this method calls each operation from the service with the provided input parameters */
        /* matches the obtained outputs with the outputs provided and declares the result of the*/
        /* operation which is then returned.                                                    */
        /* Note that the output parameters need to be provided as an XML string because the     */
        /* deserialization cannot take care of deserializing complex objects to perform the     */
        /* comparison.                                                                          */
        public InvokeResult InvokeWebServiceOperationsGroup(string url, string[] inputParams, 
                                                            string[] expectedOutputParams)
        {
            try
            {
                /* Extract the service and the method info from the service */
                Type serviceType;
                MethodInfo[] methodsInfo;

                /* Extract web service methods */
                GetWebServiceMethods(url, out methodsInfo, out serviceType);

                /* If either of the methods info or the service type weren't obtained, return */
                if (methodsInfo == null || serviceType == null)
                    return null;

                List<MethodInfo> methodsToInvoke = new List<MethodInfo>();
                int inputParametersRequired = 0;

                /* Create a list of methods to be invoked */
                foreach (MethodInfo method in methodsInfo)
                {
                    if (method.Name == "Discover")
                        break;

                    methodsToInvoke.Add(method);
                    inputParametersRequired += method.GetParameters().Length;
                }

                /* If the number of output parameters passed don't match with the number of */
                /* methods to be invoked, return */
                if (methodsToInvoke.Count != expectedOutputParams.Length)
                    return null;

                /* The provided input parameters are not sufficient to make all invocations */
                if (inputParametersRequired != inputParams.Length)
                    return null;

                InvokeResult invokeResults = new InvokeResult(expectedOutputParams.Length);

                int j = 0;
                int k = 0;
                foreach (MethodInfo methodToInvoke in methodsToInvoke)
                {
                    ParameterInfo[] invokeMethodParameters = methodToInvoke.GetParameters();
                    string[] invokeMethodInputParameters = new string[invokeMethodParameters.Length];

                    /* The total number of input parameters provided should be equal to the summation */
                    /* of the total number of input parameters provided for each method. If not, there*/
                    /* has been some error in parsing the input parameters and an error has to be     */
                    /* returned. If this case is hit, it is a bug and will need to be debugged.       */
                    if (j >= inputParams.Length)
                        return null;

                    for (int i = 0; i < invokeMethodInputParameters.Length; i++)
                    {
                        invokeMethodInputParameters[i] = inputParams[j];
                        j++;
                    }

                    /* Invoke web service method */
                    ReturnData responseData = InvokeWebServiceMethod(serviceType, methodToInvoke,
                                                                     invokeMethodInputParameters);

                    /* Check if the returned data matches with that provided */
                    if (compareXmlStrings(responseData.objectXML, expectedOutputParams[k]) == false)
                        invokeResults.InvokeStatus[k] = false;
                    else
                        invokeResults.InvokeStatus[k] = true;

                    invokeResults.MethodName[k] = methodToInvoke.Name;

                    k++;
                }

                return invokeResults;
            }
            catch(Exception ec)
            {
                throw new FaultException(ec.Message);
            }
        }