/// <summary>
 /// Performs validation and business logic checks on the UpdateStandardTermRequest values
 /// </summary>
 /// <param name="request"><see cref="UpdateStandardTermRequest">object</see></param>
 /// <exception cref="ArgumentNullException">Thrown when a required value is not set in the <see cref="UpdateStandardTermRequest">object</see></exception>
 /// <exception cref="ArgumentException">Thrown when there is a conflict between the values in the <see cref="UpdateStandardTermRequest">object</see></exception>
 /// <exception cref="ArgumentOutOfRangeException">Thrown when a value in the <see cref="UpdateStandardTermRequest">object</see> is invalid.</exception>
 private static void ValidateUpdateStandardTermRequest(UpdateStandardTermRequest request)
 {
     // Perform a Parameter Validation and Business Logic Check on the Request
     if (request.ClientString == null)
         throw new ArgumentNullException("The ClientString value is required.  Please correct and try the reqeust again.");
     else if (request.BillingClassificationType == null)
         throw new ArgumentNullException("The BillingClassificationType value is required.  Please correct and try the request again.");
     else if (request.TermId == null && request.TermSourcedId == null)
         throw new ArgumentNullException("Either a TermId or TermSourcedId value is required.  Please correct and try the request again.");
     else if (request.Name == null)
         throw new ArgumentNullException("The Name value is required.  Please correct and try the request again.");
     else if (request.DropAddPeriodStartDate != DateTime.MinValue && request.CourseActualStartDate != DateTime.MinValue)
     {
         if (request.DropAddPeriodStartDate == request.CourseActualStartDate)
             throw new ArgumentException("The DropAddPeriodStartDate value is set to the CourseActualStartDate.  This could cause downstream integration issues with the LearningStudio Enrollment API.  " +
                 "Best practice is to set the DropAddPeriodEndDate = CourseActualEndDate and set the DropAddPeriodStartDate = (CourseActualEndDate - 1 Day).  Please correct and try the request again.");
     }
     else if (request.TermId != null && request.TermSourcedId != null)
         throw new ArgumentException("The TermId and TermSourcedId values are mutually exclusive.  Only set one of the values for a given Term.  Please correct and try the request again.");
     else if (request.CourseActualEndDate != DateTime.MinValue && request.CourseActualStartDate != DateTime.MinValue)
     {
         if (request.CourseActualEndDate <= request.CourseActualStartDate)
             throw new ArgumentOutOfRangeException("The CourseActualStartDate must be before the CourseActualEndDate.  Please correct and try the request again.");
     }
     else if (request.DropAddPeriodEndDate != DateTime.MinValue && request.DropAddPeriodStartDate != DateTime.MinValue)
     {
         if (request.DropAddPeriodEndDate <= request.DropAddPeriodStartDate)
             throw new ArgumentOutOfRangeException("The DropAddPeriodStartDate must be before the DropAddPeriodEndDate.  Best practice is to set the DropAddPeriodEndDate = CourseActualEndDate and set the " +
                 "DropAddPeriodStartDate = (CourseActualEndDate - 1 Day).  Please correct and try the request again.");
     }
     else if (request.TermEndDate != DateTime.MinValue && request.TermStartDate != DateTime.MinValue)
     {
         if (request.TermEndDate <= request.TermStartDate)
             throw new ArgumentOutOfRangeException("The TermStartDate must be before the TermEndDate.  Please correct and try the request again.");
     }
     else if (request.RegistrationEndDate != DateTime.MinValue && request.RegistrationStartDate != DateTime.MinValue)
     {
         if (request.RegistrationEndDate <= request.RegistrationStartDate)
             throw new ArgumentOutOfRangeException("The RegistrationStartDate must be before the RegistrationEndDate.  Please correct and try the request again.");
     }
     else if (request.TermSourcedId != null)
     {
         if (!request.TermSourcedId.Contains(":"))
             throw new ArgumentOutOfRangeException("The TermSourcedId should have a format of \"{Source}:{Id}\".  Note the colon delimiter that seperates the two concatenated values.  " +
                 "In addition, please use your ClientString as the {Source} portion of this concatenated value.  Please correct and try the request again.");
     }
 }
        /// <summary>
        /// Creates the XML payload for the UpdateStandardTerm Term API Request
        /// </summary>
        /// <param name="request"><see cref="UpdateStandardTermRequest">object</see></param>
        /// <returns><see cref="API.StandardTermEx"/>object</returns>
        private API.StandardTermEx SetUpdateStandardTermRequest(UpdateStandardTermRequest request)
        {
            // Initialize and Set the UpdateStandardTermRequest
            API.StandardTermEx updateTerm = new API.StandardTermEx();
            updateTerm.ClientString = request.ClientString;
            updateTerm.BillingClassificationType = request.BillingClassificationType.ToString();
            updateTerm.Name = request.Name;
            updateTerm.TermTypeCode = API.TermType.Standard;

            // If specified update the Nodes the Term is associated with
            if (request.AssociatedEPOrganization != null)
                updateTerm.AssociatedEPOrganization = request.AssociatedEPOrganization;

            // If specified update the Course Dates
            if (request.CourseActualStartDate != null || request.CourseActualEndDate != null)
            {
                updateTerm.CourseActualTimeFrame = new API.TimeFrame();

                if (request.CourseActualStartDate != null)
                    updateTerm.CourseActualTimeFrame.StartDate = request.CourseActualStartDate;

                if (request.CourseActualEndDate != null)
                    updateTerm.CourseActualTimeFrame.EndDate = request.CourseActualEndDate;
            }

            // If specified update the Add Drop Dates
            if (request.DropAddPeriodStartDate != null || request.DropAddPeriodEndDate != null)
            {
                updateTerm.DropAddPeriodTimeFrame = new API.TimeFrame();

                if (request.DropAddPeriodStartDate != null)
                    updateTerm.DropAddPeriodTimeFrame.StartDate = request.DropAddPeriodStartDate;

                if (request.DropAddPeriodEndDate != null)
                    updateTerm.DropAddPeriodTimeFrame.EndDate = request.DropAddPeriodEndDate;
            }

            // If specified update the Term Dates
            if (request.TermStartDate != null || request.TermEndDate != null)
            {
                updateTerm.TermTimeFrame = new API.TimeFrame();

                if (request.TermStartDate != null)
                    updateTerm.TermTimeFrame.StartDate = request.TermStartDate;

                if (request.TermEndDate != null)
                    updateTerm.TermTimeFrame.EndDate = request.TermEndDate;
            }

            // If specified update the Registration Dates
            if (request.RegistrationStartDate != null || request.RegistrationEndDate != null)
            {
                updateTerm.RegistrationTimeFrame = new API.TimeFrame();

                if (request.RegistrationStartDate != null)
                    updateTerm.RegistrationTimeFrame.StartDate = request.RegistrationStartDate;

                if (request.RegistrationEndDate != null)
                    updateTerm.RegistrationTimeFrame.EndDate = request.RegistrationEndDate;
            }

            // If specified update the WithdrawPeriodEndsOn
            if (request.WithdrawPeriodEndsOn != null)
                updateTerm.WithdrawPeriodEndsOn = request.WithdrawPeriodEndsOn;

            // If specified update the Description
            if (request.Description != null)
                updateTerm.Description = request.Description;

            // Set the Term Identifier accordingly
            updateTerm.ID = new API.TermIdentifier();

            if (request.TermSourcedId != null)
            {
                updateTerm.ID.ID = request.TermSourcedId;
                updateTerm.ID.MappingType = API.MappedTermIDType.SourcedID;
            }
            else
            {
                updateTerm.ID.ID = request.TermId;
                updateTerm.ID.MappingType = API.MappedTermIDType.TermID;
            }

            return updateTerm;
        }
        /// <summary>
        /// Generates a UpdateStandardTerm Term API Request
        /// </summary>
        /// <param name="request"><see cref="UpdateStandardTermRequest">object</see></param>
        /// <returns><see cref="Response"/>object</returns>
        public Response UpdateStandardTerm(UpdateStandardTermRequest request)
        {
            API.StandardTermEx updateTerm = null;
            Response response = null;

            try
            {
                // Validate the Request Object
                ValidateUpdateStandardTermRequest(request);

                // Intialize and Set the CopyCourseContentRequest
                updateTerm = SetUpdateStandardTermRequest(request);

                // Build the Response object from the SOAP response
                response = ReadUpdateStandardTermResponse(updateTerm);
            }
            catch (Exception ex)
            {
                Logger.Error("Exception from UpdateStandardTerm: ", ex);
                throw;
            }
            finally
            {
                if (this.termAPI != null)
                    this.termAPI.Close();
            }

            return response;
        }