/// <summary>
        /// Processes a trace file and generates the test code.
        /// </summary>
        /// <param name="scenarioName">The name to be given to the scenario, used for namespace and class names.</param>
        /// <param name="traceFileName">The file containing the trace to be processed.</param>
        /// <param name="timedCommentsFile">The stream representing the file of timed comments, <c>null</c> if there is no timed comments file.</param>
        /// <param name="configuration">The configuration guiding the generation process.</param>
        /// <param name="mainFileName">The name of the main unit test file to be generated.</param>
        /// <param name="stubFileName">The name of the file to be generated containing the stubs.</param>
        /// <returns>Collection of paths to assemblies containing the proxies.</returns>
        public Collection <string> ProcessTraceFile(string scenarioName, string traceFileName, Stream timedCommentsFile, WcfUnitConfiguration configuration, string mainFileName, string stubFileName)
        {
            Trace.WriteLine(string.Format(CultureInfo.InvariantCulture, "Starting to process the trace file"));
            if (configuration == null)
            {
                throw new ArgumentNullException("configuration");
            }

            this.proxyAssemblies = new Collection <Assembly>();
            string[] assemblies = new string[configuration.assembly.Length];
            for (int i = 0; i < configuration.assembly.Length; i++)
            {
                assemblies[i] = configuration.assembly[i].fileName;
            }

            string[] actions = null;
            if (configuration.soapActions.soapAction != null)
            {
                actions = new string[configuration.soapActions.soapAction.Length];
                for (int i = 0; i < configuration.soapActions.soapAction.Length; i++)
                {
                    actions[i] = configuration.soapActions.soapAction[i].action;
                }
            }

            TimingsFile timings = null;

            if (timedCommentsFile != null)
            {
                timings = new TimingsFile(timedCommentsFile);
            }

            ProxyManager pm = new ProxyManager(assemblies);

            pm.TypeResolved += new EventHandler <ProxyAssemblyEventArgs>(this.TypeResolvedHandler);
            UnitTestGenerator tg = new UnitTestGenerator(scenarioName, scenarioName, scenarioName + "Tests", configuration.testMethodMode, configuration.operationTimerMode);

            Stream traceFile = null;

            try
            {
                traceFile = Parser.OpenTraceFile(traceFileName);
                int count = 0;
                using (Parser p = Parser.CreateParser(configuration.parser, traceFile, traceFileName, configuration.clientTrace, configuration.serviceTrace, configuration.soapActions.soapActionMode, actions))
                {
                    traceFile = null;
                    Deserializer  d = new Deserializer();
                    ParsedMessage parsedMessage;
                    TimedComment  timedComment         = null;
                    DateTime      lastMessageTimeStamp = DateTime.MinValue;

                    if (timings != null)
                    {
                        timedComment = timings.NextTimedComment();
                    }

                    while ((parsedMessage = p.ReadNextRequest()) != null)
                    {
                        string comment = parsedMessage.Timestamp.ToString(CultureInfo.CurrentCulture);

                        if (timings != null)
                        {
                            // loop in case more than one timed comment between the same two messages, must get last one.
                            while (timedComment != null && timedComment.Timestamp > lastMessageTimeStamp && timedComment.Timestamp <= parsedMessage.Timestamp.ToUniversalTime())
                            {
                                comment      = string.Format(CultureInfo.CurrentCulture, "{0} {1}", timedComment.Timestamp, timedComment.Comment);
                                timedComment = timings.NextTimedComment();
                            }
                        }

                        lastMessageTimeStamp = parsedMessage.Timestamp.ToUniversalTime();

                        MethodInfo contractMethod = pm.GetContractMethod(parsedMessage.SoapAction);
                        if (contractMethod == null)
                        {
                            Console.WriteLine(string.Format(CultureInfo.CurrentCulture, Messages.Processor_MethodNotFound, parsedMessage.SoapAction));
                            continue;
                        }

                        CallParameterInfo[] parameters  = d.DeserializeInputParameters(parsedMessage.Message, contractMethod);
                        MethodInfo          proxyMethod = pm.GetProxyMethod(contractMethod);
                        tg.GenerateServiceCall(proxyMethod, contractMethod, parameters, comment);
                        count++;
                    }
                }

                if (count <= 0)
                {
                    throw new UserException(Messages.NoDataInTraceFile);
                }

                tg.WriteCode(mainFileName, stubFileName);
            }
            finally
            {
                if (traceFile != null)
                {
                    traceFile.Dispose();
                }
            }

            Collection <string> ans = new Collection <string>();

            foreach (Assembly a in this.proxyAssemblies)
            {
                ans.Add(a.Location);
            }

            return(ans);
        }