/// <summary>
        /// Method that waits for a jobDetails to complete.
        /// </summary>
        /// <param name="client">The Hadoop client to use.</param>
        /// <param name="jobId">The id of the job to wait for.</param>
        /// <param name="duration">The duration to wait before timing out.</param>
        /// <param name="cancellationToken">
        /// The Cancellation Token for the request.
        /// </param>
        /// <returns>An awaitable task that represents the action.</returns>
        public static async Task<JobDetails> WaitForJobCompletionAsync(
            this IJobSubmissionClient client, string jobId, TimeSpan duration, CancellationToken cancellationToken)
        {
            client.ArgumentNotNull("client");
            jobId.ArgumentNotNull("jobId");
            JobDetails jobDetailsResults = new JobDetails() { JobId = jobId, StatusCode = JobStatusCode.Unknown };
            var pollingInterval = GetPollingInterval();
            var startTime = DateTime.UtcNow;
            var endTime = DateTime.UtcNow;

            while (jobDetailsResults.IsNotNull() && ((endTime = DateTime.UtcNow) - startTime) < duration &&
                   !(jobDetailsResults.StatusCode == JobStatusCode.Completed || jobDetailsResults.StatusCode == JobStatusCode.Failed ||
                     jobDetailsResults.StatusCode == JobStatusCode.Canceled))
            {
                client.HandleClusterWaitNotifyEvent(jobDetailsResults);
                if (jobDetailsResults.StatusCode == JobStatusCode.Completed || jobDetailsResults.StatusCode == JobStatusCode.Failed)
                {
                    break;
                }
                Thread.Sleep(pollingInterval);
                jobDetailsResults = await GetJobWithRetry(client, jobId, cancellationToken);
            }

            if (jobDetailsResults.StatusCode != JobStatusCode.Completed && jobDetailsResults.StatusCode != JobStatusCode.Failed &&
                jobDetailsResults.StatusCode != JobStatusCode.Canceled && (endTime - startTime) >= duration)
            {
                throw new TimeoutException(string.Format(CultureInfo.InvariantCulture, "The requested task failed to complete in the allotted time ({0}).", duration));
            }

            return jobDetailsResults;
        }
        /// <summary>
        /// Method that waits for a jobDetails to complete.
        /// </summary>
        /// <param name="client">The Hadoop client to use.</param>
        /// <param name="job">The jobDetails to wait for.</param>
        /// <param name="duration">The duration to wait before timing out.</param>
        /// <param name="cancellationToken">
        /// The Cancellation Token for the request.
        /// </param>
        /// <returns>An awaitable task that represents the action.</returns>
        public static async Task<JobDetails> WaitForJobCompletionAsync(
            this IJobSubmissionClient client, JobCreationResults job, TimeSpan duration, CancellationToken cancellationToken)
        {
            client.ArgumentNotNull("client");
            job.ArgumentNotNull("jobDetails");

            return await client.WaitForJobCompletionAsync(job.JobId, duration, cancellationToken);
        }
        /// <summary>
        /// Extracts the name of the property inside the lambdaexpression
        /// - UnaryExpression: Expression{Func{Warrior, object}} unaryObject = w => w.ID; --> ID
        /// - MemberExpression: Expression{Func{Warrior, int}} memberInt = w => w.ID; --> ID
        /// - BinaryExpression: Expression{Func{Warrior, bool}} binaryInt = w => w.ID == 1; --> ID (Takes the left side and casts to MemberExpression)
        /// - BinaryExpression: Expression{Func{Warrior, bool}} binaryInt = w => 1 == w.ID; --> ID (Takes the right side and casts to MemberExpression)
        /// - Compiled Expression: Expression{Func{int}} binaryInt = () => 5; --> 5
        /// - ToString: Expression{Func{Warrior, bool}} binaryInt = w => 1 == 1; --> w => True
        /// </summary>
        /// <param name="propertyExpression"></param>
        /// <returns></returns>
        public static string TryExtractPropertyName(this LambdaExpression propertyExpression)
        {
            propertyExpression.ArgumentNotNull("propertyExpression");

            var memberExpression = propertyExpression.Body as MemberExpression;
            if (memberExpression == null)
            {
                // try get the member from the operand of the unaryexpression
                var unary = propertyExpression.Body as UnaryExpression;
                if (unary != null)
                    memberExpression = unary.Operand as MemberExpression;

                if (memberExpression == null)
                {
                    var binary = propertyExpression.Body as BinaryExpression;
                    if (binary != null)
                    {
                        memberExpression = binary.Left as MemberExpression;
                        if (memberExpression == null)
                            memberExpression = binary.Right as MemberExpression;
                    }
                }

                if (memberExpression == null)
                {
                    LogDelegate.TraceLine("## PersistenceMap - Property is not a MemberAccessExpression: {0}", propertyExpression.ToString());

                    try
                    {
                        return propertyExpression.Compile().DynamicInvoke().ToString();
                    }
                    catch (Exception e)
                    {
                        LogDelegate.TraceLine(e.Message);
                        return propertyExpression.ToString();
                    }
                }
            }

            var propertyInfo = memberExpression.Member as PropertyInfo;
            if (propertyInfo == null)
            {
                LogDelegate.TraceLine(string.Format("## PersistenceMap - Property {0} is not a PropertyInfo", memberExpression.Member));
                return memberExpression.Member.ToString();
            }

            if (propertyInfo.GetGetMethod(true).IsStatic)
            {
                LogDelegate.TraceLine(string.Format("## PersistenceMap - Property {0} is static", memberExpression.Member.Name));
                return memberExpression.Member.Name;
            }

            return memberExpression.Member.Name;
        }
 internal static string GetCleartextPassword(this PSCredential credentials)
 {
     credentials.ArgumentNotNull("credentials");
     return GetCleartextFromSecureString(credentials.Password);
 }
        /// <summary>
        /// Extracts the type of the property inside the lambdaexpression or of the return value
        /// - UnaryExpression: Expression{Func{Warrior, object}} unaryObject = w => w.ID; --> int
        /// - MemberExpression: Expression{Func{Warrior, int}} memberInt = w => w.ID; --> int
        /// - BinaryExpression: Expression{Func{Warrior, bool}} binaryInt = w => w.ID == 1; --> int (Takes the left side and casts to MemberExpression)
        /// - BinaryExpression: Expression{Func{Warrior, bool}} binaryInt = w => 1 == w.ID; --> int (Takes the right side and casts to MemberExpression)
        /// - Compiled Expression: Expression{Func{int}} binaryInt = () => 5; --> int
        /// - Compiled Expression: Expression{Func{Warrior, bool}} binaryInt = w => 1 == 1; --> bool
        /// </summary>
        /// <param name="propertyExpression"></param>
        /// <returns></returns>
        public static Type TryExtractPropertyType(this LambdaExpression propertyExpression)
        {
            propertyExpression.ArgumentNotNull("propertyExpression");

            var memberExpression = propertyExpression.Body as MemberExpression;
            if (memberExpression == null)
            {
                // try get the member from the operand of the unaryexpression
                var unary = propertyExpression.Body as UnaryExpression;
                if (unary != null)
                    memberExpression = unary.Operand as MemberExpression;

                if (memberExpression == null)
                {
                    var binary = propertyExpression.Body as BinaryExpression;
                    if (binary != null)
                    {
                        memberExpression = binary.Left as MemberExpression;
                        if (memberExpression == null)
                        {
                            memberExpression = binary.Right as MemberExpression;
                        }
                    }
                }

                if (memberExpression == null)
                {
                    try
                    {
                        return propertyExpression.Compile().DynamicInvoke().GetType();
                    }
                    catch (Exception e)
                    {
                        LogDelegate.TraceLine(e.Message);
                        return propertyExpression.Body.Type;
                    }
                }
            }

            return memberExpression.Type;
        }