/// <summary>
        /// Method intended to be called at the start of an orchestration to create a BAM process tracking activity.
        /// </summary>
        /// <param name="activatingMessage">
        /// The message that activates the orchestration instance.
        /// </param>
        /// <param name="processName">The name that will be used to qualify the new tracked process instance.</param>
        /// <returns>
        /// The <see cref="TrackingContext"/> that contains the BAM tracking activities identifiers for the current process.
        /// Notice that <see cref="TrackingContext.MessagingStepActivityId"/> will be filled with the tracking activity
        /// identifier of <paramref name="activatingMessage"/> if it exists.
        /// </returns>
        public static TrackingContext Initiate(XLANGMessage activatingMessage, string processName)
        {
            if (activatingMessage == null)
            {
                throw new ArgumentNullException(nameof(activatingMessage));
            }
            if (processName.IsNullOrEmpty())
            {
                throw new ArgumentNullException(nameof(processName));
            }

            var process = Initiate(
                Service.RootService.InstanceId,
                processName,
                activatingMessage.GetProperty(TrackingProperties.Value1),
                activatingMessage.GetProperty(TrackingProperties.Value2),
                activatingMessage.GetProperty(TrackingProperties.Value3));

            // link inbound activating messaging step to its process
            // only an orchestration can link an activating messaging step to its process
            // as ProcessActivityId is initialized *by* the orchestration's first step
            var messagingStep = new MessagingStep(activatingMessage);

            process.AddStep(messagingStep);

            // set up orchestration's tracking context
            return(new TrackingContext {
                ProcessActivityId = process.ActivityId,
                MessagingStepActivityId = messagingStep.ActivityId
            });
        }
 /// <summary>
 /// Returns the <see cref="TrackingContext"/> associated to the <paramref name="message"/>.
 /// </summary>
 /// <param name="message">
 /// Message whose associated <see cref="TrackingContext"/> will be returned.
 /// </param>
 /// <returns>
 /// The <see cref="TrackingContext"/> associated to the <paramref name="message"/>.
 /// </returns>
 public static TrackingContext GetTrackingContext(this XLANGMessage message)
 {
     if (message == null)
     {
         throw new ArgumentNullException(nameof(message));
     }
     return(new TrackingContext {
         ProcessActivityId = message.GetProperty(TrackingProperties.ProcessActivityId),
         ProcessingStepActivityId = message.GetProperty(TrackingProperties.ProcessingStepActivityId),
         MessagingStepActivityId = message.GetProperty(TrackingProperties.MessagingStepActivityId)
     });
 }
        /// <summary>
        /// Method intended to be called near the start of an orchestration after all of its activating parallel receives (<see
        /// cref="ParallelPreInitiate"/>) have completed, or failed, to create a BAM process tracking activity.
        /// </summary>
        /// <param name="keyMessage">
        /// The message that contains the key business values to be captured for tracking purposes.
        /// </param>
        /// <returns>
        /// The <see cref="TrackingContext"/> that contains the BAM tracking activities identifiers for the current process.
        /// Notice that, contrary to <see cref="Initiate(XLANGMessage)"/>, <see cref="TrackingContext.MessagingStepActivityId"/>
        /// will not be filled.
        /// </returns>
        /// <remarks>
        /// The BAM process tracking activity, whose parallel activating messages have already all been received (<see
        /// cref="ParallelPreInitiate"/>), will be created thereby providing the missing half of the process-to-activating
        /// messages associations. The name used for the process instance is the containing namespace of the calling
        /// orchestration.
        /// </remarks>
        public static TrackingContext ParallelInitiate(XLANGMessage keyMessage)
        {
            var process = Initiate(
                Service.RootService.InstanceId,
                Service.RootService.GetType().Namespace,
                keyMessage.GetProperty(TrackingProperties.Value1),
                keyMessage.GetProperty(TrackingProperties.Value2),
                keyMessage.GetProperty(TrackingProperties.Value3));

            // set up orchestration's tracking context
            return(new TrackingContext {
                ProcessActivityId = process.ActivityId
            });
        }
        /// <summary>
        /// Method intended to be called at the start of an orchestration to create a BAM process tracking activity.
        /// </summary>
        /// <param name="activatingMessage">
        /// The message that activates the orchestration instance.
        /// </param>
        /// <returns>
        /// The <see cref="TrackingContext"/> that contains the BAM tracking activities identifiers for the current process.
        /// Notice that <see cref="TrackingContext.MessagingStepActivityId">TrackingContext.MessagingStepActivityId</see> will be
        /// filled with the tracking activity identifier of <paramref name="activatingMessage"/> if it exists.
        /// </returns>
        /// <remarks>
        /// The name used for the process instance is automatically determined by the ambient message context property <see
        /// cref="TrackingProperties.ProcessName">TrackingProperties.ProcessName</see> should it be non null nor empty, or the
        /// containing namespace of the calling orchestration otherwise.
        /// </remarks>
        public static TrackingContext Initiate(XLANGMessage activatingMessage)
        {
            if (activatingMessage == null)
            {
                throw new ArgumentNullException(nameof(activatingMessage));
            }
            var processName = activatingMessage.GetProperty(TrackingProperties.ProcessName).IfNotNullOrWhiteSpace(p => p)
                              ?? Service.RootService.GetType().Namespace;

            return(Initiate(activatingMessage, processName));
        }
 /// <summary>
 /// Applies the XSL transformation provided by the <paramref name="message"/> context's <see
 /// cref="BizTalkFactoryProperties.MapTypeName">BizTalkFactoryProperties.MapTypeName</see> property to the specified
 /// <paramref name="message"/>.
 /// </summary>
 /// <param name="message">
 /// The <see cref="XLANGMessage"/> to be transformed.
 /// </param>
 /// <returns>
 /// The transformed message with the result in the first part (at index 0).
 /// </returns>
 /// <remarks>
 /// <para>
 /// This method assumes only the first part of a multi-part <paramref name="message"/> message has to be transformed and
 /// creates an output message with a single part named "Main".
 /// </para>
 /// <para>
 /// This method will throw if the map type to apply cannot be retrieved from the message context's <see
 /// cref="BizTalkFactoryProperties.MapTypeName">BizTalkFactoryProperties.MapTypeName</see> property.
 /// </para>
 /// </remarks>
 public static XLANGMessage Transform(XLANGMessage message)
 {
     return(Transform(message, Type.GetType(message.GetProperty(BizTalkFactoryProperties.MapTypeName), true)));
 }
 /// <summary>
 /// Applies the XSL transformation provided by the <paramref name="message"/> context's <see
 /// cref="BizTalkFactoryProperties.MapTypeName">BizTalkFactoryProperties.MapTypeName</see> property to the specified
 /// <paramref name="message"/>.
 /// </summary>
 /// <param name="message">
 /// The <see cref="XLANGMessage"/> to be transformed.
 /// </param>
 /// <param name="arguments">
 /// The arguments to pass to the XSL transformation.
 /// </param>
 /// <returns>
 /// The transformed message with the result in the first part (at index 0).
 /// </returns>
 /// <remarks>
 /// <para>
 /// This method assumes only the first part of a multi-part <paramref name="message"/> message has to be transformed and
 /// creates an output message with a single part named "Main".
 /// </para>
 /// <para>
 /// This method will throw if the map type to apply cannot be retrieved from the message context's <see
 /// cref="BizTalkFactoryProperties.MapTypeName">BizTalkFactoryProperties.MapTypeName</see> property.
 /// </para>
 /// </remarks>
 public static XLANGMessage Transform(XLANGMessage message, params XsltArgument[] arguments)
 {
     return(Transform(message, Type.GetType(message.GetProperty(BizTalkFactoryProperties.MapTypeName), true), arguments));
 }