/// <summary>
        /// ctor
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="logPath">tracking file path </param>
        /// <param name="wfHost">Workflow service host name</param>
        /// <param name="wfPersistanceDb">connection string, where WF persistance happens</param>
        public XMLFileTrackingChannel(TrackingParameters parameters, string wfHost, string logPath, string wfPersistanceDb)
        {
            _parameters      = parameters;
            _wfPersistanceDb = wfPersistanceDb;
            _workflowID      = parameters.InstanceId.ToString();
            _logLocation     = logPath;
            _wfHost          = wfHost;

            if (!Directory.Exists(_logLocation))
            {
                Directory.CreateDirectory(_logLocation);
            }

            //Start- Save Wf definition
            if (_persistanceHelper == null)
            {
                _persistanceHelper = new XMLFilePersistence(
                    Path.Combine(_logLocation, _workflowID + "_def.xml"),
                    Path.Combine(_logLocation, _workflowID + ".xml"),
                    _wfPersistanceDb
                    );

                //We will save Wf definition, if wf is new or it has been updated
                if (_persistanceHelper.IsNewOrUpdatedWfDefinition(_parameters.RootActivity))
                {
                    DateTime wfCompilationTimestamp =
                        _persistanceHelper.GetWfCompilationTimestamp(_parameters.RootActivity);

                    ActivitySummary rootActivitySummary = BuildRootActivitySummary();
                    String          activityXml         = BuildActivityXml(rootActivitySummary, wfCompilationTimestamp);
                    _persistanceHelper.PersistWfDefinitionXml(activityXml);
                }
            }
            //End- Save Wf definition
        }
        /// <summary>
        /// Build an XML document containing the activities associated with a
        /// workflow instance.
        /// </summary>
        /// <param name="rootActivity">
        /// <see cref="ActivitySummary" /> representing the root activity of the
        /// workflow instance.
        /// </param>
        /// <param name="wfCompilationTimestamp">
        /// date/time when the WF definartion was last compiled
        /// </param>
        /// <returns>
        /// A String representing the XML document generated from the root activity.
        /// </returns>
        private static string BuildActivityXml(ActivitySummary rootActivity,
                                               DateTime wfCompilationTimestamp)
        {
            StringBuilder stringBuilder = new StringBuilder();

            using (XmlWriter xmlWriter = XmlWriter.Create(stringBuilder, CreateXmlWriterSettings()))
            {
                xmlWriter.WriteStartDocument();
                //xmlWriter.WriteStartElement("Activities");

                TraverseActivityTree(rootActivity, xmlWriter, wfCompilationTimestamp);

                //xmlWriter.WriteEndElement();
                xmlWriter.WriteEndDocument();
            }
            return(stringBuilder.ToString());
        }
        private static void TraverseActivityTree(ActivitySummary rootActivity,
                                                 XmlWriter xmlWriter,
                                                 DateTime?wfCompilationTimestamp)
        {
            xmlWriter.WriteStartElement("Activity");
            xmlWriter.WriteAttributeString("Type", rootActivity.Type.Name);
            xmlWriter.WriteAttributeString("QualifiedName", rootActivity.QualifiedName);

            if (wfCompilationTimestamp != null && wfCompilationTimestamp.HasValue)
            {
                xmlWriter.WriteAttributeString("WfCompliteTime", wfCompilationTimestamp.Value.ToString("MM-dd-yyyy hh:mm:ss tt")); //AM/PM
            }
            foreach (ActivitySummary activity in rootActivity.ChildActivities)
            {
                TraverseActivityTree(activity, xmlWriter, null);
            }
            xmlWriter.WriteEndElement();
        }
        /// <summary>
        /// Build a tree of activity summaries starting with the root activity
        /// of the workflow instance that this channel represents.
        /// </summary>
        /// <returns>
        /// <see cref="ActivitySummary" /> representing the root activity.
        /// </returns>
        private ActivitySummary BuildRootActivitySummary()
        {
            ActivitySummary rootActivitySummary = null;

            Dictionary <String, ActivitySummary> activitySummariesByQualifiedName = new Dictionary <String, ActivitySummary>();
            Queue <Activity> activityQueue = new Queue <Activity>();

            activityQueue.Enqueue(_parameters.RootActivity);

            while (activityQueue.Count > 0)
            {
                Activity        currentActivity        = activityQueue.Dequeue();
                ActivitySummary currentActivitySummary = new ActivitySummary(
                    currentActivity.GetType(), currentActivity.QualifiedName);

                if (currentActivity.Parent != null && activitySummariesByQualifiedName.ContainsKey(currentActivity.Parent.QualifiedName))
                {
                    ActivitySummary parentActivitySummary = activitySummariesByQualifiedName[currentActivity.Parent.QualifiedName];
                    currentActivitySummary.ParentActivity = parentActivitySummary;
                    parentActivitySummary.ChildActivities.Add(currentActivitySummary);
                }

                if (rootActivitySummary == null)
                {
                    rootActivitySummary = currentActivitySummary;
                }

                CompositeActivity parentActivity = currentActivity as CompositeActivity;

                if (parentActivity != null)
                {
                    activitySummariesByQualifiedName.Add(currentActivitySummary.QualifiedName, currentActivitySummary);
                    foreach (Activity childActivity in parentActivity.Activities)
                    {
                        if (childActivity.Enabled)
                        {
                            activityQueue.Enqueue(childActivity);
                        }
                    }
                }
            }

            return(rootActivitySummary);
        }