/*
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 * 
 * Code generated by Microsoft (R) AutoRest Code Generator.
 * Changes may cause incorrect behavior and will be lost if the code is
 * regenerated.
 */

'use strict';

var util = require('util');
var msRest = require('ms-rest');
var msRestAzure = require('ms-rest-azure');
var WebResource = msRest.WebResource;

/**
 * @class
 * Job
 * __NOTE__: An instance of this class is automatically created for an
 * instance of the BatchServiceClient.
 * Initializes a new instance of the Job class.
 * @constructor
 *
 * @param {BatchServiceClient} client Reference to the service client.
 */
function Job(client) {
  this.client = client;
}

/**
 * Gets lifetime summary statistics for all of the jobs in the specified
 * account. Statistics are aggregated across all jobs that have ever existed
 * in the account, from account creation to the last update time of the
 * statistics.
 *
 * @param {object} [options] Optional Parameters.
 * 
 * @param {object} [options.jobGetAllJobsLifetimeStatisticsOptions] Additional
 * parameters for the operation
 * 
 * @param {number} [options.jobGetAllJobsLifetimeStatisticsOptions.timeout]
 * The maximum time that the server can spend processing the request, in
 * seconds. The default is 30 seconds.
 * 
 * @param {string}
 * [options.jobGetAllJobsLifetimeStatisticsOptions.clientRequestId] The
 * caller-generated request identity, in the form of a GUID with no
 * decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
 * 
 * @param {boolean}
 * [options.jobGetAllJobsLifetimeStatisticsOptions.returnClientRequestId]
 * Whether the server should return the client-request-id identifier in the
 * response.
 * 
 * @param {date} [options.jobGetAllJobsLifetimeStatisticsOptions.ocpDate] The
 * time the request was issued. If not specified, this header will be
 * automatically populated with the current system clock time.
 * 
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 * 
 * @param {function} callback
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object.
 *                      See {@link JobStatistics} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
Job.prototype.getAllJobsLifetimeStatistics = function (options, callback) {
  var client = this.client;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  var jobGetAllJobsLifetimeStatisticsOptions = (options && options.jobGetAllJobsLifetimeStatisticsOptions !== undefined) ? options.jobGetAllJobsLifetimeStatisticsOptions : undefined;
  // Validate
  try {
    if (this.client.apiVersion === null || this.client.apiVersion === undefined || typeof this.client.apiVersion.valueOf() !== 'string') {
      throw new Error('this.client.apiVersion cannot be null or undefined and it must be of type string.');
    }
    if (this.client.acceptLanguage !== null && this.client.acceptLanguage !== undefined && typeof this.client.acceptLanguage.valueOf() !== 'string') {
      throw new Error('this.client.acceptLanguage must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  var timeout;
  var clientRequestId;
  var returnClientRequestId;
  var ocpDate;
  try {
    if (jobGetAllJobsLifetimeStatisticsOptions !== null && jobGetAllJobsLifetimeStatisticsOptions !== undefined)
    {
      timeout = jobGetAllJobsLifetimeStatisticsOptions.timeout;
      if (timeout !== null && timeout !== undefined && typeof timeout !== 'number') {
        throw new Error('timeout must be of type number.');
      }
    }
    if (jobGetAllJobsLifetimeStatisticsOptions !== null && jobGetAllJobsLifetimeStatisticsOptions !== undefined)
    {
      clientRequestId = jobGetAllJobsLifetimeStatisticsOptions.clientRequestId;
      if (clientRequestId !== null && clientRequestId !== undefined && typeof clientRequestId.valueOf() !== 'string') {
        throw new Error('clientRequestId must be of type string.');
      }
    }
    if (jobGetAllJobsLifetimeStatisticsOptions !== null && jobGetAllJobsLifetimeStatisticsOptions !== undefined)
    {
      returnClientRequestId = jobGetAllJobsLifetimeStatisticsOptions.returnClientRequestId;
      if (returnClientRequestId !== null && returnClientRequestId !== undefined && typeof returnClientRequestId !== 'boolean') {
        throw new Error('returnClientRequestId must be of type boolean.');
      }
    }
    if (jobGetAllJobsLifetimeStatisticsOptions !== null && jobGetAllJobsLifetimeStatisticsOptions !== undefined)
    {
      ocpDate = jobGetAllJobsLifetimeStatisticsOptions.ocpDate;
      if (ocpDate && !(ocpDate instanceof Date || 
          (typeof ocpDate.valueOf() === 'string' && !isNaN(Date.parse(ocpDate))))) {
            throw new Error('ocpDate must be of type date.');
          }
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  var requestUrl = this.client.baseUri +
                   '//lifetimejobstats';
  var queryParameters = [];
  queryParameters.push('api-version=' + encodeURIComponent(this.client.apiVersion));
  if (timeout !== null && timeout !== undefined) {
    queryParameters.push('timeout=' + encodeURIComponent(timeout.toString()));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }
  // trim all duplicate forward slashes in the url
  var regex = /([^:]\/)\/+/gi;
  requestUrl = requestUrl.replace(regex, '$1');

  // Create HTTP transport objects
  var httpRequest = new WebResource();
  httpRequest.method = 'GET';
  httpRequest.headers = {};
  httpRequest.url = requestUrl;
  // Set Headers
  if (this.client.generateClientRequestId) {
      httpRequest.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
  }
  if (this.client.acceptLanguage !== undefined && this.client.acceptLanguage !== null) {
    httpRequest.headers['accept-language'] = this.client.acceptLanguage;
  }
  if (clientRequestId !== undefined && clientRequestId !== null) {
    httpRequest.headers['client-request-id'] = clientRequestId;
  }
  if (returnClientRequestId !== undefined && returnClientRequestId !== null) {
    httpRequest.headers['return-client-request-id'] = returnClientRequestId.toString();
  }
  if (ocpDate !== undefined && ocpDate !== null) {
    httpRequest.headers['ocp-date'] = ocpDate.toUTCString();
  }
  if(options) {
    for(var headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.headers['Content-Type'] = 'application/json; odata=minimalmetadata; charset=utf-8';
  httpRequest.body = null;
  // Send Request
  return client.pipeline(httpRequest, function (err, response, responseBody) {
    if (err) {
      return callback(err);
    }
    var statusCode = response.statusCode;
    if (statusCode !== 200) {
      var error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      var parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          if (parsedErrorResponse.error) parsedErrorResponse = parsedErrorResponse.error;
          if (parsedErrorResponse.code) error.code = parsedErrorResponse.code;
          if (parsedErrorResponse.message) error.message = parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          var resultMapper = new client.models['BatchError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = util.format('Error "%s" occurred in deserializing the responseBody ' + 
                         '- "%s" for the default response.', defaultError.message, responseBody);
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    var result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      var parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          var resultMapper = new client.models['JobStatistics']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        var deserializationError = new Error(util.format('Error "%s" occurred in deserializing the responseBody - "%s"', error, responseBody));
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
};

/**
 * Deletes a job.
 *
 * @param {string} jobId The id of the job to delete.
 * 
 * @param {object} [options] Optional Parameters.
 * 
 * @param {object} [options.jobDeleteMethodOptions] Additional parameters for
 * the operation
 * 
 * @param {number} [options.jobDeleteMethodOptions.timeout] The maximum time
 * that the server can spend processing the request, in seconds. The default
 * is 30 seconds.
 * 
 * @param {string} [options.jobDeleteMethodOptions.clientRequestId] The
 * caller-generated request identity, in the form of a GUID with no
 * decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
 * 
 * @param {boolean} [options.jobDeleteMethodOptions.returnClientRequestId]
 * Whether the server should return the client-request-id identifier in the
 * response.
 * 
 * @param {date} [options.jobDeleteMethodOptions.ocpDate] The time the request
 * was issued. If not specified, this header will be automatically populated
 * with the current system clock time.
 * 
 * @param {string} [options.jobDeleteMethodOptions.ifMatch] An ETag is
 * specified. Specify this header to perform the operation only if the
 * resource's ETag is an exact match as specified.
 * 
 * @param {string} [options.jobDeleteMethodOptions.ifNoneMatch] An ETag is
 * specified. Specify this header to perform the operation only if the
 * resource's ETag does not match the specified ETag.
 * 
 * @param {date} [options.jobDeleteMethodOptions.ifModifiedSince] Specify this
 * header to perform the operation only if the resource has been modified
 * since the specified date/time.
 * 
 * @param {date} [options.jobDeleteMethodOptions.ifUnmodifiedSince] Specify
 * this header to perform the operation only if the resource has not been
 * modified since the specified date/time.
 * 
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 * 
 * @param {function} callback
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {null} [result]   - The deserialized result object.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
Job.prototype.deleteMethod = function (jobId, options, callback) {
  var client = this.client;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  var jobDeleteMethodOptions = (options && options.jobDeleteMethodOptions !== undefined) ? options.jobDeleteMethodOptions : undefined;
  // Validate
  try {
    if (jobId === null || jobId === undefined || typeof jobId.valueOf() !== 'string') {
      throw new Error('jobId cannot be null or undefined and it must be of type string.');
    }
    if (this.client.apiVersion === null || this.client.apiVersion === undefined || typeof this.client.apiVersion.valueOf() !== 'string') {
      throw new Error('this.client.apiVersion cannot be null or undefined and it must be of type string.');
    }
    if (this.client.acceptLanguage !== null && this.client.acceptLanguage !== undefined && typeof this.client.acceptLanguage.valueOf() !== 'string') {
      throw new Error('this.client.acceptLanguage must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  var timeout;
  var clientRequestId;
  var returnClientRequestId;
  var ocpDate;
  var ifMatch;
  var ifNoneMatch;
  var ifModifiedSince;
  var ifUnmodifiedSince;
  try {
    if (jobDeleteMethodOptions !== null && jobDeleteMethodOptions !== undefined)
    {
      timeout = jobDeleteMethodOptions.timeout;
      if (timeout !== null && timeout !== undefined && typeof timeout !== 'number') {
        throw new Error('timeout must be of type number.');
      }
    }
    if (jobDeleteMethodOptions !== null && jobDeleteMethodOptions !== undefined)
    {
      clientRequestId = jobDeleteMethodOptions.clientRequestId;
      if (clientRequestId !== null && clientRequestId !== undefined && typeof clientRequestId.valueOf() !== 'string') {
        throw new Error('clientRequestId must be of type string.');
      }
    }
    if (jobDeleteMethodOptions !== null && jobDeleteMethodOptions !== undefined)
    {
      returnClientRequestId = jobDeleteMethodOptions.returnClientRequestId;
      if (returnClientRequestId !== null && returnClientRequestId !== undefined && typeof returnClientRequestId !== 'boolean') {
        throw new Error('returnClientRequestId must be of type boolean.');
      }
    }
    if (jobDeleteMethodOptions !== null && jobDeleteMethodOptions !== undefined)
    {
      ocpDate = jobDeleteMethodOptions.ocpDate;
      if (ocpDate && !(ocpDate instanceof Date || 
          (typeof ocpDate.valueOf() === 'string' && !isNaN(Date.parse(ocpDate))))) {
            throw new Error('ocpDate must be of type date.');
          }
    }
    if (jobDeleteMethodOptions !== null && jobDeleteMethodOptions !== undefined)
    {
      ifMatch = jobDeleteMethodOptions.ifMatch;
      if (ifMatch !== null && ifMatch !== undefined && typeof ifMatch.valueOf() !== 'string') {
        throw new Error('ifMatch must be of type string.');
      }
    }
    if (jobDeleteMethodOptions !== null && jobDeleteMethodOptions !== undefined)
    {
      ifNoneMatch = jobDeleteMethodOptions.ifNoneMatch;
      if (ifNoneMatch !== null && ifNoneMatch !== undefined && typeof ifNoneMatch.valueOf() !== 'string') {
        throw new Error('ifNoneMatch must be of type string.');
      }
    }
    if (jobDeleteMethodOptions !== null && jobDeleteMethodOptions !== undefined)
    {
      ifModifiedSince = jobDeleteMethodOptions.ifModifiedSince;
      if (ifModifiedSince && !(ifModifiedSince instanceof Date || 
          (typeof ifModifiedSince.valueOf() === 'string' && !isNaN(Date.parse(ifModifiedSince))))) {
            throw new Error('ifModifiedSince must be of type date.');
          }
    }
    if (jobDeleteMethodOptions !== null && jobDeleteMethodOptions !== undefined)
    {
      ifUnmodifiedSince = jobDeleteMethodOptions.ifUnmodifiedSince;
      if (ifUnmodifiedSince && !(ifUnmodifiedSince instanceof Date || 
          (typeof ifUnmodifiedSince.valueOf() === 'string' && !isNaN(Date.parse(ifUnmodifiedSince))))) {
            throw new Error('ifUnmodifiedSince must be of type date.');
          }
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  var requestUrl = this.client.baseUri +
                   '//jobs/{jobId}';
  requestUrl = requestUrl.replace('{jobId}', encodeURIComponent(jobId));
  var queryParameters = [];
  queryParameters.push('api-version=' + encodeURIComponent(this.client.apiVersion));
  if (timeout !== null && timeout !== undefined) {
    queryParameters.push('timeout=' + encodeURIComponent(timeout.toString()));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }
  // trim all duplicate forward slashes in the url
  var regex = /([^:]\/)\/+/gi;
  requestUrl = requestUrl.replace(regex, '$1');

  // Create HTTP transport objects
  var httpRequest = new WebResource();
  httpRequest.method = 'DELETE';
  httpRequest.headers = {};
  httpRequest.url = requestUrl;
  // Set Headers
  if (this.client.generateClientRequestId) {
      httpRequest.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
  }
  if (this.client.acceptLanguage !== undefined && this.client.acceptLanguage !== null) {
    httpRequest.headers['accept-language'] = this.client.acceptLanguage;
  }
  if (clientRequestId !== undefined && clientRequestId !== null) {
    httpRequest.headers['client-request-id'] = clientRequestId;
  }
  if (returnClientRequestId !== undefined && returnClientRequestId !== null) {
    httpRequest.headers['return-client-request-id'] = returnClientRequestId.toString();
  }
  if (ocpDate !== undefined && ocpDate !== null) {
    httpRequest.headers['ocp-date'] = ocpDate.toUTCString();
  }
  if (ifMatch !== undefined && ifMatch !== null) {
    httpRequest.headers['If-Match'] = ifMatch;
  }
  if (ifNoneMatch !== undefined && ifNoneMatch !== null) {
    httpRequest.headers['If-None-Match'] = ifNoneMatch;
  }
  if (ifModifiedSince !== undefined && ifModifiedSince !== null) {
    httpRequest.headers['If-Modified-Since'] = ifModifiedSince.toUTCString();
  }
  if (ifUnmodifiedSince !== undefined && ifUnmodifiedSince !== null) {
    httpRequest.headers['If-Unmodified-Since'] = ifUnmodifiedSince.toUTCString();
  }
  if(options) {
    for(var headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.headers['Content-Type'] = 'application/json; odata=minimalmetadata; charset=utf-8';
  httpRequest.body = null;
  // Send Request
  return client.pipeline(httpRequest, function (err, response, responseBody) {
    if (err) {
      return callback(err);
    }
    var statusCode = response.statusCode;
    if (statusCode !== 202) {
      var error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      var parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          if (parsedErrorResponse.error) parsedErrorResponse = parsedErrorResponse.error;
          if (parsedErrorResponse.code) error.code = parsedErrorResponse.code;
          if (parsedErrorResponse.message) error.message = parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          var resultMapper = new client.models['BatchError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = util.format('Error "%s" occurred in deserializing the responseBody ' + 
                         '- "%s" for the default response.', defaultError.message, responseBody);
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    var result = null;
    if (responseBody === '') responseBody = null;

    return callback(null, result, httpRequest, response);
  });
};

/**
 * Gets information about the specified job.
 *
 * @param {string} jobId The id of the job.
 * 
 * @param {object} [options] Optional Parameters.
 * 
 * @param {object} [options.jobGetOptions] Additional parameters for the
 * operation
 * 
 * @param {string} [options.jobGetOptions.select] An OData $select clause.
 * 
 * @param {string} [options.jobGetOptions.expand] An OData $expand clause.
 * 
 * @param {number} [options.jobGetOptions.timeout] The maximum time that the
 * server can spend processing the request, in seconds. The default is 30
 * seconds.
 * 
 * @param {string} [options.jobGetOptions.clientRequestId] The
 * caller-generated request identity, in the form of a GUID with no
 * decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
 * 
 * @param {boolean} [options.jobGetOptions.returnClientRequestId] Whether the
 * server should return the client-request-id identifier in the response.
 * 
 * @param {date} [options.jobGetOptions.ocpDate] The time the request was
 * issued. If not specified, this header will be automatically populated with
 * the current system clock time.
 * 
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 * 
 * @param {function} callback
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object.
 *                      See {@link CloudJob} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
Job.prototype.get = function (jobId, options, callback) {
  var client = this.client;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  var jobGetOptions = (options && options.jobGetOptions !== undefined) ? options.jobGetOptions : undefined;
  // Validate
  try {
    if (jobId === null || jobId === undefined || typeof jobId.valueOf() !== 'string') {
      throw new Error('jobId cannot be null or undefined and it must be of type string.');
    }
    if (this.client.apiVersion === null || this.client.apiVersion === undefined || typeof this.client.apiVersion.valueOf() !== 'string') {
      throw new Error('this.client.apiVersion cannot be null or undefined and it must be of type string.');
    }
    if (this.client.acceptLanguage !== null && this.client.acceptLanguage !== undefined && typeof this.client.acceptLanguage.valueOf() !== 'string') {
      throw new Error('this.client.acceptLanguage must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  var select;
  var expand;
  var timeout;
  var clientRequestId;
  var returnClientRequestId;
  var ocpDate;
  try {
    if (jobGetOptions !== null && jobGetOptions !== undefined)
    {
      select = jobGetOptions.select;
      if (select !== null && select !== undefined && typeof select.valueOf() !== 'string') {
        throw new Error('select must be of type string.');
      }
    }
    if (jobGetOptions !== null && jobGetOptions !== undefined)
    {
      expand = jobGetOptions.expand;
      if (expand !== null && expand !== undefined && typeof expand.valueOf() !== 'string') {
        throw new Error('expand must be of type string.');
      }
    }
    if (jobGetOptions !== null && jobGetOptions !== undefined)
    {
      timeout = jobGetOptions.timeout;
      if (timeout !== null && timeout !== undefined && typeof timeout !== 'number') {
        throw new Error('timeout must be of type number.');
      }
    }
    if (jobGetOptions !== null && jobGetOptions !== undefined)
    {
      clientRequestId = jobGetOptions.clientRequestId;
      if (clientRequestId !== null && clientRequestId !== undefined && typeof clientRequestId.valueOf() !== 'string') {
        throw new Error('clientRequestId must be of type string.');
      }
    }
    if (jobGetOptions !== null && jobGetOptions !== undefined)
    {
      returnClientRequestId = jobGetOptions.returnClientRequestId;
      if (returnClientRequestId !== null && returnClientRequestId !== undefined && typeof returnClientRequestId !== 'boolean') {
        throw new Error('returnClientRequestId must be of type boolean.');
      }
    }
    if (jobGetOptions !== null && jobGetOptions !== undefined)
    {
      ocpDate = jobGetOptions.ocpDate;
      if (ocpDate && !(ocpDate instanceof Date || 
          (typeof ocpDate.valueOf() === 'string' && !isNaN(Date.parse(ocpDate))))) {
            throw new Error('ocpDate must be of type date.');
          }
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  var requestUrl = this.client.baseUri +
                   '//jobs/{jobId}';
  requestUrl = requestUrl.replace('{jobId}', encodeURIComponent(jobId));
  var queryParameters = [];
  queryParameters.push('api-version=' + encodeURIComponent(this.client.apiVersion));
  if (select !== null && select !== undefined) {
    queryParameters.push('$select=' + encodeURIComponent(select));
  }
  if (expand !== null && expand !== undefined) {
    queryParameters.push('$expand=' + encodeURIComponent(expand));
  }
  if (timeout !== null && timeout !== undefined) {
    queryParameters.push('timeout=' + encodeURIComponent(timeout.toString()));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }
  // trim all duplicate forward slashes in the url
  var regex = /([^:]\/)\/+/gi;
  requestUrl = requestUrl.replace(regex, '$1');

  // Create HTTP transport objects
  var httpRequest = new WebResource();
  httpRequest.method = 'GET';
  httpRequest.headers = {};
  httpRequest.url = requestUrl;
  // Set Headers
  if (this.client.generateClientRequestId) {
      httpRequest.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
  }
  if (this.client.acceptLanguage !== undefined && this.client.acceptLanguage !== null) {
    httpRequest.headers['accept-language'] = this.client.acceptLanguage;
  }
  if (clientRequestId !== undefined && clientRequestId !== null) {
    httpRequest.headers['client-request-id'] = clientRequestId;
  }
  if (returnClientRequestId !== undefined && returnClientRequestId !== null) {
    httpRequest.headers['return-client-request-id'] = returnClientRequestId.toString();
  }
  if (ocpDate !== undefined && ocpDate !== null) {
    httpRequest.headers['ocp-date'] = ocpDate.toUTCString();
  }
  if(options) {
    for(var headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.headers['Content-Type'] = 'application/json; odata=minimalmetadata; charset=utf-8';
  httpRequest.body = null;
  // Send Request
  return client.pipeline(httpRequest, function (err, response, responseBody) {
    if (err) {
      return callback(err);
    }
    var statusCode = response.statusCode;
    if (statusCode !== 200) {
      var error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      var parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          if (parsedErrorResponse.error) parsedErrorResponse = parsedErrorResponse.error;
          if (parsedErrorResponse.code) error.code = parsedErrorResponse.code;
          if (parsedErrorResponse.message) error.message = parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          var resultMapper = new client.models['BatchError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = util.format('Error "%s" occurred in deserializing the responseBody ' + 
                         '- "%s" for the default response.', defaultError.message, responseBody);
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    var result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      var parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          var resultMapper = new client.models['CloudJob']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        var deserializationError = new Error(util.format('Error "%s" occurred in deserializing the responseBody - "%s"', error, responseBody));
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
};

/**
 * Updates the properties of a job.
 *
 * @param {string} jobId The id of the job whose properties you want to update.
 * 
 * @param {object} jobPatchParameter The parameters for the request.
 * 
 * @param {number} [jobPatchParameter.priority] The priority of the job.
 * Priority values can range from -1000 to 1000, with -1000 being the lowest
 * priority and 1000 being the highest priority. If omitted, the priority of
 * the job is left unchanged.
 * 
 * @param {object} [jobPatchParameter.constraints] The execution constraints
 * for the job. If omitted, the existing execution constraints are left
 * unchanged.
 * 
 * @param {moment.duration} [jobPatchParameter.constraints.maxWallClockTime]
 * The maximum elapsed time that the job may run, measured from the time the
 * job starts. If the job does not complete within the time limit, the Batch
 * service terminates it and any tasks that are still running.
 * 
 * @param {number} [jobPatchParameter.constraints.maxTaskRetryCount] The
 * maximum number of times each task may be retried. The Batch service
 * retries a task if its exit code is nonzero.
 * 
 * @param {object} [jobPatchParameter.poolInfo] The pool on which the Batch
 * service runs the job's tasks. If omitted, the job continues to run on its
 * current pool.
 * 
 * @param {string} [jobPatchParameter.poolInfo.poolId] The id of an existing
 * pool. All the tasks of the job will run on the specified pool. You must
 * specify either PoolId or AutoPoolSpecification, but not both.
 * 
 * @param {object} [jobPatchParameter.poolInfo.autoPoolSpecification]
 * Characteristics for a temporary 'auto pool'. The Batch service will create
 * this auto pool and run all of the tasks of the job on it, and will delete
 * the pool once the job has completed. You must specify either PoolId or
 * AutoPoolSpecification, but not both.
 * 
 * @param {string}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.autoPoolIdPrefix] A
 * prefix to be added to the unique identifier when a pool is automatically
 * created. The prefix can be up to 20 characters long.
 * 
 * @param {string}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.poolLifetimeOption] The
 * minimum lifetime of created auto pools, and how multiple jobs on a
 * schedule are assigned to pools. Possible values include: 'jobschedule',
 * 'job', 'unmapped'
 * 
 * @param {boolean}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.keepAlive] Whether to
 * keep an auto pool alive after its lifetime expires.
 * 
 * @param {object} [jobPatchParameter.poolInfo.autoPoolSpecification.pool] The
 * pool specification for the auto pool.
 * 
 * @param {string}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.displayName] The
 * display name for the pool.
 * 
 * @param {string}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.vmSize] The size of
 * the virtual machines in the pool. All virtual machines in a pool are the
 * same size.
 * 
 * @param {object}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.cloudServiceConfiguration]
 * The cloud service configuration for the pool. This property and
 * VirtualMachineConfiguration are mutually exclusive and one of the
 * properties must be specified.
 * 
 * @param {string}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.cloudServiceConfiguration.osFamily]
 * The Azure Guest OS family to be installed on the virtual machines in the
 * pool.
 * 
 * @param {string}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.cloudServiceConfiguration.targetOSVersion]
 * The Azure Guest OS version to be installed on the virtual machines in the
 * pool. The default value is * which specifies the latest operating system
 * version for the specified OS family.
 * 
 * @param {string}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.cloudServiceConfiguration.currentOSVersion]
 * The Azure Guest OS Version currently installed on the virtual machines in
 * the pool. This may differ from TargetOSVersion if the pool state is
 * Upgrading.
 * 
 * @param {object}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration]
 * The virtual machine configuration for the pool. This property and
 * CloudServiceConfiguration are mutually exclusive and one of the properties
 * must be specified.
 * 
 * @param {object}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.imageReference]
 * A reference to the Azure Virtual Machines Marketplace image to use.
 * 
 * @param {string}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.imageReference.publisher]
 * The publisher of the Azure Virtual Machines Marketplace image. For
 * example, Canonical or MicrosoftWindowsServer.
 * 
 * @param {string}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.imageReference.offer]
 * The offer type of the Azure Virtual Machines Marketplace image. For
 * example, UbuntuServer or WindowsServer.
 * 
 * @param {string}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.imageReference.sku]
 * The SKU of the Azure Virtual Machines Marketplace image. For example,
 * 14.04.0-LTS or 2012-R2-Datacenter.
 * 
 * @param {string}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.imageReference.version]
 * The version of the Azure Virtual Machines Marketplace image. A value of
 * 'latest' can be specified to select the latest version of an image. If
 * omitted, the default is 'latest'.
 * 
 * @param {string}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.nodeAgentSKUId]
 * The SKU of Batch Node Agent to be provisioned on the compute node. The
 * Batch node agent is a program that runs on each node in the pool, and
 * provides the command-and-control interface between the node and the Batch
 * service. There are different implementations of the node agent, known as
 * SKUs, for different operating systems.
 * 
 * @param {object}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.windowsConfiguration]
 * Windows operating system settings on the virtual machine. This property
 * must not be specified if the ImageReference property specifies a Linux OS
 * image.
 * 
 * @param {boolean}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.windowsConfiguration.enableAutomaticUpdates]
 * Whether automatic updates are enabled on the virtual machine. If omitted,
 * the default value is true.
 * 
 * @param {number}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.maxTasksPerNode]
 * The maximum number of tasks that can run concurrently on a single compute
 * node in the pool.
 * 
 * @param {object}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.taskSchedulingPolicy]
 * How tasks are distributed among compute nodes in the pool.
 * 
 * @param {string}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.taskSchedulingPolicy.nodeFillType]
 * How tasks should be distributed across compute nodes. Possible values
 * include: 'spread', 'pack', 'unmapped'
 * 
 * @param {moment.duration}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.resizeTimeout] The
 * timeout for allocation of compute nodes to the pool.
 * 
 * @param {number}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.targetDedicated]
 * The desired number of compute nodes in the pool.
 * 
 * @param {boolean}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.enableAutoScale]
 * Whether the pool size should automatically adjust over time.
 * 
 * @param {string}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.autoScaleFormula]
 * The formula for the desired number of compute nodes in the pool.
 * 
 * @param {moment.duration}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.autoScaleEvaluationInterval]
 * A time interval for the desired AutoScale evaluation period in the pool.
 * 
 * @param {boolean}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.enableInterNodeCommunication]
 * Whether the pool permits direct communication between nodes.
 * 
 * @param {object}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.startTask] A task
 * to run on each compute node as it joins the pool. The task runs when the
 * node is added to the pool or when the node is restarted.
 * 
 * @param {string}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.startTask.commandLine]
 * The command line of the start task.
 * 
 * @param {array}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.startTask.resourceFiles]
 * A list of files that the Batch service will download to the compute node
 * before running the command line.
 * 
 * @param {array}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.startTask.environmentSettings]
 * A list of environment variable settings for the start task.
 * 
 * @param {boolean}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.startTask.runElevated]
 * Whether to run the start task in elevated mode. The default value is false.
 * 
 * @param {number}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.startTask.maxTaskRetryCount]
 * The maximum number of times the task may be retried.
 * 
 * @param {boolean}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.startTask.waitForSuccess]
 * Whether the Batch service should wait for the start task to complete
 * successfully (that is, to exit with exit code 0) before scheduling any
 * tasks on the compute node.
 * 
 * @param {array}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.certificateReferences]
 * A list of certificates to be installed on each compute node in the pool.
 * 
 * @param {array}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.applicationPackageReferences]
 * The list of application packages to be installed on each compute node in
 * the pool.
 * 
 * @param {array}
 * [jobPatchParameter.poolInfo.autoPoolSpecification.pool.metadata] A list of
 * name-value pairs associated with the pool as metadata.
 * 
 * @param {array} [jobPatchParameter.metadata] A list of name-value pairs
 * associated with the job as metadata. If omitted, the existing job metadata
 * is left unchanged.
 * 
 * @param {object} [options] Optional Parameters.
 * 
 * @param {object} [options.jobPatchOptions] Additional parameters for the
 * operation
 * 
 * @param {number} [options.jobPatchOptions.timeout] The maximum time that the
 * server can spend processing the request, in seconds. The default is 30
 * seconds.
 * 
 * @param {string} [options.jobPatchOptions.clientRequestId] The
 * caller-generated request identity, in the form of a GUID with no
 * decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
 * 
 * @param {boolean} [options.jobPatchOptions.returnClientRequestId] Whether
 * the server should return the client-request-id identifier in the response.
 * 
 * @param {date} [options.jobPatchOptions.ocpDate] The time the request was
 * issued. If not specified, this header will be automatically populated with
 * the current system clock time.
 * 
 * @param {string} [options.jobPatchOptions.ifMatch] An ETag is specified.
 * Specify this header to perform the operation only if the resource's ETag
 * is an exact match as specified.
 * 
 * @param {string} [options.jobPatchOptions.ifNoneMatch] An ETag is specified.
 * Specify this header to perform the operation only if the resource's ETag
 * does not match the specified ETag.
 * 
 * @param {date} [options.jobPatchOptions.ifModifiedSince] Specify this header
 * to perform the operation only if the resource has been modified since the
 * specified date/time.
 * 
 * @param {date} [options.jobPatchOptions.ifUnmodifiedSince] Specify this
 * header to perform the operation only if the resource has not been modified
 * since the specified date/time.
 * 
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 * 
 * @param {function} callback
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {null} [result]   - The deserialized result object.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
Job.prototype.patch = function (jobId, jobPatchParameter, options, callback) {
  var client = this.client;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  var jobPatchOptions = (options && options.jobPatchOptions !== undefined) ? options.jobPatchOptions : undefined;
  // Validate
  try {
    if (jobId === null || jobId === undefined || typeof jobId.valueOf() !== 'string') {
      throw new Error('jobId cannot be null or undefined and it must be of type string.');
    }
    if (jobPatchParameter === null || jobPatchParameter === undefined) {
      throw new Error('jobPatchParameter cannot be null or undefined.');
    }
    if (this.client.apiVersion === null || this.client.apiVersion === undefined || typeof this.client.apiVersion.valueOf() !== 'string') {
      throw new Error('this.client.apiVersion cannot be null or undefined and it must be of type string.');
    }
    if (this.client.acceptLanguage !== null && this.client.acceptLanguage !== undefined && typeof this.client.acceptLanguage.valueOf() !== 'string') {
      throw new Error('this.client.acceptLanguage must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  var timeout;
  var clientRequestId;
  var returnClientRequestId;
  var ocpDate;
  var ifMatch;
  var ifNoneMatch;
  var ifModifiedSince;
  var ifUnmodifiedSince;
  try {
    if (jobPatchOptions !== null && jobPatchOptions !== undefined)
    {
      timeout = jobPatchOptions.timeout;
      if (timeout !== null && timeout !== undefined && typeof timeout !== 'number') {
        throw new Error('timeout must be of type number.');
      }
    }
    if (jobPatchOptions !== null && jobPatchOptions !== undefined)
    {
      clientRequestId = jobPatchOptions.clientRequestId;
      if (clientRequestId !== null && clientRequestId !== undefined && typeof clientRequestId.valueOf() !== 'string') {
        throw new Error('clientRequestId must be of type string.');
      }
    }
    if (jobPatchOptions !== null && jobPatchOptions !== undefined)
    {
      returnClientRequestId = jobPatchOptions.returnClientRequestId;
      if (returnClientRequestId !== null && returnClientRequestId !== undefined && typeof returnClientRequestId !== 'boolean') {
        throw new Error('returnClientRequestId must be of type boolean.');
      }
    }
    if (jobPatchOptions !== null && jobPatchOptions !== undefined)
    {
      ocpDate = jobPatchOptions.ocpDate;
      if (ocpDate && !(ocpDate instanceof Date || 
          (typeof ocpDate.valueOf() === 'string' && !isNaN(Date.parse(ocpDate))))) {
            throw new Error('ocpDate must be of type date.');
          }
    }
    if (jobPatchOptions !== null && jobPatchOptions !== undefined)
    {
      ifMatch = jobPatchOptions.ifMatch;
      if (ifMatch !== null && ifMatch !== undefined && typeof ifMatch.valueOf() !== 'string') {
        throw new Error('ifMatch must be of type string.');
      }
    }
    if (jobPatchOptions !== null && jobPatchOptions !== undefined)
    {
      ifNoneMatch = jobPatchOptions.ifNoneMatch;
      if (ifNoneMatch !== null && ifNoneMatch !== undefined && typeof ifNoneMatch.valueOf() !== 'string') {
        throw new Error('ifNoneMatch must be of type string.');
      }
    }
    if (jobPatchOptions !== null && jobPatchOptions !== undefined)
    {
      ifModifiedSince = jobPatchOptions.ifModifiedSince;
      if (ifModifiedSince && !(ifModifiedSince instanceof Date || 
          (typeof ifModifiedSince.valueOf() === 'string' && !isNaN(Date.parse(ifModifiedSince))))) {
            throw new Error('ifModifiedSince must be of type date.');
          }
    }
    if (jobPatchOptions !== null && jobPatchOptions !== undefined)
    {
      ifUnmodifiedSince = jobPatchOptions.ifUnmodifiedSince;
      if (ifUnmodifiedSince && !(ifUnmodifiedSince instanceof Date || 
          (typeof ifUnmodifiedSince.valueOf() === 'string' && !isNaN(Date.parse(ifUnmodifiedSince))))) {
            throw new Error('ifUnmodifiedSince must be of type date.');
          }
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  var requestUrl = this.client.baseUri +
                   '//jobs/{jobId}';
  requestUrl = requestUrl.replace('{jobId}', encodeURIComponent(jobId));
  var queryParameters = [];
  queryParameters.push('api-version=' + encodeURIComponent(this.client.apiVersion));
  if (timeout !== null && timeout !== undefined) {
    queryParameters.push('timeout=' + encodeURIComponent(timeout.toString()));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }
  // trim all duplicate forward slashes in the url
  var regex = /([^:]\/)\/+/gi;
  requestUrl = requestUrl.replace(regex, '$1');

  // Create HTTP transport objects
  var httpRequest = new WebResource();
  httpRequest.method = 'PATCH';
  httpRequest.headers = {};
  httpRequest.url = requestUrl;
  // Set Headers
  if (this.client.generateClientRequestId) {
      httpRequest.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
  }
  if (this.client.acceptLanguage !== undefined && this.client.acceptLanguage !== null) {
    httpRequest.headers['accept-language'] = this.client.acceptLanguage;
  }
  if (clientRequestId !== undefined && clientRequestId !== null) {
    httpRequest.headers['client-request-id'] = clientRequestId;
  }
  if (returnClientRequestId !== undefined && returnClientRequestId !== null) {
    httpRequest.headers['return-client-request-id'] = returnClientRequestId.toString();
  }
  if (ocpDate !== undefined && ocpDate !== null) {
    httpRequest.headers['ocp-date'] = ocpDate.toUTCString();
  }
  if (ifMatch !== undefined && ifMatch !== null) {
    httpRequest.headers['If-Match'] = ifMatch;
  }
  if (ifNoneMatch !== undefined && ifNoneMatch !== null) {
    httpRequest.headers['If-None-Match'] = ifNoneMatch;
  }
  if (ifModifiedSince !== undefined && ifModifiedSince !== null) {
    httpRequest.headers['If-Modified-Since'] = ifModifiedSince.toUTCString();
  }
  if (ifUnmodifiedSince !== undefined && ifUnmodifiedSince !== null) {
    httpRequest.headers['If-Unmodified-Since'] = ifUnmodifiedSince.toUTCString();
  }
  if(options) {
    for(var headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.headers['Content-Type'] = 'application/json; odata=minimalmetadata; charset=utf-8';
  // Serialize Request
  var requestContent = null;
  var requestModel = null;
  try {
    if (jobPatchParameter !== null && jobPatchParameter !== undefined) {
      var requestModelMapper = new client.models['JobPatchParameter']().mapper();
      requestModel = client.serialize(requestModelMapper, jobPatchParameter, 'jobPatchParameter');
      requestContent = JSON.stringify(requestModel);
    }
  } catch (error) {
    var serializationError = new Error(util.format('Error "%s" occurred in serializing the ' + 
        'payload - "%s"', error.message, util.inspect(jobPatchParameter, {depth: null})));
    return callback(serializationError);
  }
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, function (err, response, responseBody) {
    if (err) {
      return callback(err);
    }
    var statusCode = response.statusCode;
    if (statusCode !== 200) {
      var error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      var parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          if (parsedErrorResponse.error) parsedErrorResponse = parsedErrorResponse.error;
          if (parsedErrorResponse.code) error.code = parsedErrorResponse.code;
          if (parsedErrorResponse.message) error.message = parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          var resultMapper = new client.models['BatchError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = util.format('Error "%s" occurred in deserializing the responseBody ' + 
                         '- "%s" for the default response.', defaultError.message, responseBody);
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    var result = null;
    if (responseBody === '') responseBody = null;

    return callback(null, result, httpRequest, response);
  });
};

/**
 * Updates the properties of a job.
 *
 * @param {string} jobId The id of the job whose properties you want to update.
 * 
 * @param {object} jobUpdateParameter The parameters for the request.
 * 
 * @param {number} [jobUpdateParameter.priority] The priority of the job.
 * Priority values can range from -1000 to 1000, with -1000 being the lowest
 * priority and 1000 being the highest priority. If omitted, the priority of
 * the job is left unchanged.
 * 
 * @param {object} [jobUpdateParameter.constraints] The execution constraints
 * for the job. If omitted, the existing execution constraints are left
 * unchanged.
 * 
 * @param {moment.duration} [jobUpdateParameter.constraints.maxWallClockTime]
 * The maximum elapsed time that the job may run, measured from the time the
 * job starts. If the job does not complete within the time limit, the Batch
 * service terminates it and any tasks that are still running.
 * 
 * @param {number} [jobUpdateParameter.constraints.maxTaskRetryCount] The
 * maximum number of times each task may be retried. The Batch service
 * retries a task if its exit code is nonzero.
 * 
 * @param {object} [jobUpdateParameter.poolInfo] The pool on which the Batch
 * service runs the job's tasks. If omitted, the job continues to run on its
 * current pool.
 * 
 * @param {string} [jobUpdateParameter.poolInfo.poolId] The id of an existing
 * pool. All the tasks of the job will run on the specified pool. You must
 * specify either PoolId or AutoPoolSpecification, but not both.
 * 
 * @param {object} [jobUpdateParameter.poolInfo.autoPoolSpecification]
 * Characteristics for a temporary 'auto pool'. The Batch service will create
 * this auto pool and run all of the tasks of the job on it, and will delete
 * the pool once the job has completed. You must specify either PoolId or
 * AutoPoolSpecification, but not both.
 * 
 * @param {string}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.autoPoolIdPrefix] A
 * prefix to be added to the unique identifier when a pool is automatically
 * created. The prefix can be up to 20 characters long.
 * 
 * @param {string}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.poolLifetimeOption] The
 * minimum lifetime of created auto pools, and how multiple jobs on a
 * schedule are assigned to pools. Possible values include: 'jobschedule',
 * 'job', 'unmapped'
 * 
 * @param {boolean}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.keepAlive] Whether to
 * keep an auto pool alive after its lifetime expires.
 * 
 * @param {object} [jobUpdateParameter.poolInfo.autoPoolSpecification.pool]
 * The pool specification for the auto pool.
 * 
 * @param {string}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.displayName] The
 * display name for the pool.
 * 
 * @param {string}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.vmSize] The size
 * of the virtual machines in the pool. All virtual machines in a pool are
 * the same size.
 * 
 * @param {object}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.cloudServiceConfiguration]
 * The cloud service configuration for the pool. This property and
 * VirtualMachineConfiguration are mutually exclusive and one of the
 * properties must be specified.
 * 
 * @param {string}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.cloudServiceConfiguration.osFamily]
 * The Azure Guest OS family to be installed on the virtual machines in the
 * pool.
 * 
 * @param {string}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.cloudServiceConfiguration.targetOSVersion]
 * The Azure Guest OS version to be installed on the virtual machines in the
 * pool. The default value is * which specifies the latest operating system
 * version for the specified OS family.
 * 
 * @param {string}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.cloudServiceConfiguration.currentOSVersion]
 * The Azure Guest OS Version currently installed on the virtual machines in
 * the pool. This may differ from TargetOSVersion if the pool state is
 * Upgrading.
 * 
 * @param {object}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration]
 * The virtual machine configuration for the pool. This property and
 * CloudServiceConfiguration are mutually exclusive and one of the properties
 * must be specified.
 * 
 * @param {object}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.imageReference]
 * A reference to the Azure Virtual Machines Marketplace image to use.
 * 
 * @param {string}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.imageReference.publisher]
 * The publisher of the Azure Virtual Machines Marketplace image. For
 * example, Canonical or MicrosoftWindowsServer.
 * 
 * @param {string}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.imageReference.offer]
 * The offer type of the Azure Virtual Machines Marketplace image. For
 * example, UbuntuServer or WindowsServer.
 * 
 * @param {string}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.imageReference.sku]
 * The SKU of the Azure Virtual Machines Marketplace image. For example,
 * 14.04.0-LTS or 2012-R2-Datacenter.
 * 
 * @param {string}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.imageReference.version]
 * The version of the Azure Virtual Machines Marketplace image. A value of
 * 'latest' can be specified to select the latest version of an image. If
 * omitted, the default is 'latest'.
 * 
 * @param {string}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.nodeAgentSKUId]
 * The SKU of Batch Node Agent to be provisioned on the compute node. The
 * Batch node agent is a program that runs on each node in the pool, and
 * provides the command-and-control interface between the node and the Batch
 * service. There are different implementations of the node agent, known as
 * SKUs, for different operating systems.
 * 
 * @param {object}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.windowsConfiguration]
 * Windows operating system settings on the virtual machine. This property
 * must not be specified if the ImageReference property specifies a Linux OS
 * image.
 * 
 * @param {boolean}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.windowsConfiguration.enableAutomaticUpdates]
 * Whether automatic updates are enabled on the virtual machine. If omitted,
 * the default value is true.
 * 
 * @param {number}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.maxTasksPerNode]
 * The maximum number of tasks that can run concurrently on a single compute
 * node in the pool.
 * 
 * @param {object}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.taskSchedulingPolicy]
 * How tasks are distributed among compute nodes in the pool.
 * 
 * @param {string}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.taskSchedulingPolicy.nodeFillType]
 * How tasks should be distributed across compute nodes. Possible values
 * include: 'spread', 'pack', 'unmapped'
 * 
 * @param {moment.duration}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.resizeTimeout] The
 * timeout for allocation of compute nodes to the pool.
 * 
 * @param {number}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.targetDedicated]
 * The desired number of compute nodes in the pool.
 * 
 * @param {boolean}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.enableAutoScale]
 * Whether the pool size should automatically adjust over time.
 * 
 * @param {string}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.autoScaleFormula]
 * The formula for the desired number of compute nodes in the pool.
 * 
 * @param {moment.duration}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.autoScaleEvaluationInterval]
 * A time interval for the desired AutoScale evaluation period in the pool.
 * 
 * @param {boolean}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.enableInterNodeCommunication]
 * Whether the pool permits direct communication between nodes.
 * 
 * @param {object}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.startTask] A task
 * to run on each compute node as it joins the pool. The task runs when the
 * node is added to the pool or when the node is restarted.
 * 
 * @param {string}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.startTask.commandLine]
 * The command line of the start task.
 * 
 * @param {array}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.startTask.resourceFiles]
 * A list of files that the Batch service will download to the compute node
 * before running the command line.
 * 
 * @param {array}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.startTask.environmentSettings]
 * A list of environment variable settings for the start task.
 * 
 * @param {boolean}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.startTask.runElevated]
 * Whether to run the start task in elevated mode. The default value is false.
 * 
 * @param {number}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.startTask.maxTaskRetryCount]
 * The maximum number of times the task may be retried.
 * 
 * @param {boolean}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.startTask.waitForSuccess]
 * Whether the Batch service should wait for the start task to complete
 * successfully (that is, to exit with exit code 0) before scheduling any
 * tasks on the compute node.
 * 
 * @param {array}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.certificateReferences]
 * A list of certificates to be installed on each compute node in the pool.
 * 
 * @param {array}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.applicationPackageReferences]
 * The list of application packages to be installed on each compute node in
 * the pool.
 * 
 * @param {array}
 * [jobUpdateParameter.poolInfo.autoPoolSpecification.pool.metadata] A list
 * of name-value pairs associated with the pool as metadata.
 * 
 * @param {array} [jobUpdateParameter.metadata] A list of name-value pairs
 * associated with the job as metadata. If omitted, the existing job metadata
 * is left unchanged.
 * 
 * @param {object} [options] Optional Parameters.
 * 
 * @param {object} [options.jobUpdateOptions] Additional parameters for the
 * operation
 * 
 * @param {number} [options.jobUpdateOptions.timeout] The maximum time that
 * the server can spend processing the request, in seconds. The default is 30
 * seconds.
 * 
 * @param {string} [options.jobUpdateOptions.clientRequestId] The
 * caller-generated request identity, in the form of a GUID with no
 * decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
 * 
 * @param {boolean} [options.jobUpdateOptions.returnClientRequestId] Whether
 * the server should return the client-request-id identifier in the response.
 * 
 * @param {date} [options.jobUpdateOptions.ocpDate] The time the request was
 * issued. If not specified, this header will be automatically populated with
 * the current system clock time.
 * 
 * @param {string} [options.jobUpdateOptions.ifMatch] An ETag is specified.
 * Specify this header to perform the operation only if the resource's ETag
 * is an exact match as specified.
 * 
 * @param {string} [options.jobUpdateOptions.ifNoneMatch] An ETag is
 * specified. Specify this header to perform the operation only if the
 * resource's ETag does not match the specified ETag.
 * 
 * @param {date} [options.jobUpdateOptions.ifModifiedSince] Specify this
 * header to perform the operation only if the resource has been modified
 * since the specified date/time.
 * 
 * @param {date} [options.jobUpdateOptions.ifUnmodifiedSince] Specify this
 * header to perform the operation only if the resource has not been modified
 * since the specified date/time.
 * 
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 * 
 * @param {function} callback
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {null} [result]   - The deserialized result object.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
Job.prototype.update = function (jobId, jobUpdateParameter, options, callback) {
  var client = this.client;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  var jobUpdateOptions = (options && options.jobUpdateOptions !== undefined) ? options.jobUpdateOptions : undefined;
  // Validate
  try {
    if (jobId === null || jobId === undefined || typeof jobId.valueOf() !== 'string') {
      throw new Error('jobId cannot be null or undefined and it must be of type string.');
    }
    if (jobUpdateParameter === null || jobUpdateParameter === undefined) {
      throw new Error('jobUpdateParameter cannot be null or undefined.');
    }
    if (this.client.apiVersion === null || this.client.apiVersion === undefined || typeof this.client.apiVersion.valueOf() !== 'string') {
      throw new Error('this.client.apiVersion cannot be null or undefined and it must be of type string.');
    }
    if (this.client.acceptLanguage !== null && this.client.acceptLanguage !== undefined && typeof this.client.acceptLanguage.valueOf() !== 'string') {
      throw new Error('this.client.acceptLanguage must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  var timeout;
  var clientRequestId;
  var returnClientRequestId;
  var ocpDate;
  var ifMatch;
  var ifNoneMatch;
  var ifModifiedSince;
  var ifUnmodifiedSince;
  try {
    if (jobUpdateOptions !== null && jobUpdateOptions !== undefined)
    {
      timeout = jobUpdateOptions.timeout;
      if (timeout !== null && timeout !== undefined && typeof timeout !== 'number') {
        throw new Error('timeout must be of type number.');
      }
    }
    if (jobUpdateOptions !== null && jobUpdateOptions !== undefined)
    {
      clientRequestId = jobUpdateOptions.clientRequestId;
      if (clientRequestId !== null && clientRequestId !== undefined && typeof clientRequestId.valueOf() !== 'string') {
        throw new Error('clientRequestId must be of type string.');
      }
    }
    if (jobUpdateOptions !== null && jobUpdateOptions !== undefined)
    {
      returnClientRequestId = jobUpdateOptions.returnClientRequestId;
      if (returnClientRequestId !== null && returnClientRequestId !== undefined && typeof returnClientRequestId !== 'boolean') {
        throw new Error('returnClientRequestId must be of type boolean.');
      }
    }
    if (jobUpdateOptions !== null && jobUpdateOptions !== undefined)
    {
      ocpDate = jobUpdateOptions.ocpDate;
      if (ocpDate && !(ocpDate instanceof Date || 
          (typeof ocpDate.valueOf() === 'string' && !isNaN(Date.parse(ocpDate))))) {
            throw new Error('ocpDate must be of type date.');
          }
    }
    if (jobUpdateOptions !== null && jobUpdateOptions !== undefined)
    {
      ifMatch = jobUpdateOptions.ifMatch;
      if (ifMatch !== null && ifMatch !== undefined && typeof ifMatch.valueOf() !== 'string') {
        throw new Error('ifMatch must be of type string.');
      }
    }
    if (jobUpdateOptions !== null && jobUpdateOptions !== undefined)
    {
      ifNoneMatch = jobUpdateOptions.ifNoneMatch;
      if (ifNoneMatch !== null && ifNoneMatch !== undefined && typeof ifNoneMatch.valueOf() !== 'string') {
        throw new Error('ifNoneMatch must be of type string.');
      }
    }
    if (jobUpdateOptions !== null && jobUpdateOptions !== undefined)
    {
      ifModifiedSince = jobUpdateOptions.ifModifiedSince;
      if (ifModifiedSince && !(ifModifiedSince instanceof Date || 
          (typeof ifModifiedSince.valueOf() === 'string' && !isNaN(Date.parse(ifModifiedSince))))) {
            throw new Error('ifModifiedSince must be of type date.');
          }
    }
    if (jobUpdateOptions !== null && jobUpdateOptions !== undefined)
    {
      ifUnmodifiedSince = jobUpdateOptions.ifUnmodifiedSince;
      if (ifUnmodifiedSince && !(ifUnmodifiedSince instanceof Date || 
          (typeof ifUnmodifiedSince.valueOf() === 'string' && !isNaN(Date.parse(ifUnmodifiedSince))))) {
            throw new Error('ifUnmodifiedSince must be of type date.');
          }
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  var requestUrl = this.client.baseUri +
                   '//jobs/{jobId}';
  requestUrl = requestUrl.replace('{jobId}', encodeURIComponent(jobId));
  var queryParameters = [];
  queryParameters.push('api-version=' + encodeURIComponent(this.client.apiVersion));
  if (timeout !== null && timeout !== undefined) {
    queryParameters.push('timeout=' + encodeURIComponent(timeout.toString()));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }
  // trim all duplicate forward slashes in the url
  var regex = /([^:]\/)\/+/gi;
  requestUrl = requestUrl.replace(regex, '$1');

  // Create HTTP transport objects
  var httpRequest = new WebResource();
  httpRequest.method = 'PUT';
  httpRequest.headers = {};
  httpRequest.url = requestUrl;
  // Set Headers
  if (this.client.generateClientRequestId) {
      httpRequest.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
  }
  if (this.client.acceptLanguage !== undefined && this.client.acceptLanguage !== null) {
    httpRequest.headers['accept-language'] = this.client.acceptLanguage;
  }
  if (clientRequestId !== undefined && clientRequestId !== null) {
    httpRequest.headers['client-request-id'] = clientRequestId;
  }
  if (returnClientRequestId !== undefined && returnClientRequestId !== null) {
    httpRequest.headers['return-client-request-id'] = returnClientRequestId.toString();
  }
  if (ocpDate !== undefined && ocpDate !== null) {
    httpRequest.headers['ocp-date'] = ocpDate.toUTCString();
  }
  if (ifMatch !== undefined && ifMatch !== null) {
    httpRequest.headers['If-Match'] = ifMatch;
  }
  if (ifNoneMatch !== undefined && ifNoneMatch !== null) {
    httpRequest.headers['If-None-Match'] = ifNoneMatch;
  }
  if (ifModifiedSince !== undefined && ifModifiedSince !== null) {
    httpRequest.headers['If-Modified-Since'] = ifModifiedSince.toUTCString();
  }
  if (ifUnmodifiedSince !== undefined && ifUnmodifiedSince !== null) {
    httpRequest.headers['If-Unmodified-Since'] = ifUnmodifiedSince.toUTCString();
  }
  if(options) {
    for(var headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.headers['Content-Type'] = 'application/json; odata=minimalmetadata; charset=utf-8';
  // Serialize Request
  var requestContent = null;
  var requestModel = null;
  try {
    if (jobUpdateParameter !== null && jobUpdateParameter !== undefined) {
      var requestModelMapper = new client.models['JobUpdateParameter']().mapper();
      requestModel = client.serialize(requestModelMapper, jobUpdateParameter, 'jobUpdateParameter');
      requestContent = JSON.stringify(requestModel);
    }
  } catch (error) {
    var serializationError = new Error(util.format('Error "%s" occurred in serializing the ' + 
        'payload - "%s"', error.message, util.inspect(jobUpdateParameter, {depth: null})));
    return callback(serializationError);
  }
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, function (err, response, responseBody) {
    if (err) {
      return callback(err);
    }
    var statusCode = response.statusCode;
    if (statusCode !== 200) {
      var error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      var parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          if (parsedErrorResponse.error) parsedErrorResponse = parsedErrorResponse.error;
          if (parsedErrorResponse.code) error.code = parsedErrorResponse.code;
          if (parsedErrorResponse.message) error.message = parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          var resultMapper = new client.models['BatchError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = util.format('Error "%s" occurred in deserializing the responseBody ' + 
                         '- "%s" for the default response.', defaultError.message, responseBody);
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    var result = null;
    if (responseBody === '') responseBody = null;

    return callback(null, result, httpRequest, response);
  });
};

/**
 * Disables the specified job, preventing new tasks from running.
 *
 * @param {string} jobId The id of the job to disable.
 * 
 * @param {string} disableTasks What to do with active tasks associated with
 * the job. Possible values include: 'requeue', 'terminate', 'wait'
 * 
 * @param {object} [options] Optional Parameters.
 * 
 * @param {object} [options.jobDisableOptions] Additional parameters for the
 * operation
 * 
 * @param {number} [options.jobDisableOptions.timeout] The maximum time that
 * the server can spend processing the request, in seconds. The default is 30
 * seconds.
 * 
 * @param {string} [options.jobDisableOptions.clientRequestId] The
 * caller-generated request identity, in the form of a GUID with no
 * decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
 * 
 * @param {boolean} [options.jobDisableOptions.returnClientRequestId] Whether
 * the server should return the client-request-id identifier in the response.
 * 
 * @param {date} [options.jobDisableOptions.ocpDate] The time the request was
 * issued. If not specified, this header will be automatically populated with
 * the current system clock time.
 * 
 * @param {string} [options.jobDisableOptions.ifMatch] An ETag is specified.
 * Specify this header to perform the operation only if the resource's ETag
 * is an exact match as specified.
 * 
 * @param {string} [options.jobDisableOptions.ifNoneMatch] An ETag is
 * specified. Specify this header to perform the operation only if the
 * resource's ETag does not match the specified ETag.
 * 
 * @param {date} [options.jobDisableOptions.ifModifiedSince] Specify this
 * header to perform the operation only if the resource has been modified
 * since the specified date/time.
 * 
 * @param {date} [options.jobDisableOptions.ifUnmodifiedSince] Specify this
 * header to perform the operation only if the resource has not been modified
 * since the specified date/time.
 * 
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 * 
 * @param {function} callback
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {null} [result]   - The deserialized result object.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
Job.prototype.disable = function (jobId, disableTasks, options, callback) {
  var client = this.client;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  var jobDisableOptions = (options && options.jobDisableOptions !== undefined) ? options.jobDisableOptions : undefined;
  // Validate
  try {
    if (jobId === null || jobId === undefined || typeof jobId.valueOf() !== 'string') {
      throw new Error('jobId cannot be null or undefined and it must be of type string.');
    }
    if (this.client.apiVersion === null || this.client.apiVersion === undefined || typeof this.client.apiVersion.valueOf() !== 'string') {
      throw new Error('this.client.apiVersion cannot be null or undefined and it must be of type string.');
    }
    if (disableTasks) {
      var allowedValues = [ 'requeue', 'terminate', 'wait' ];
      if (!allowedValues.some( function(item) { return item === disableTasks; })) {
        throw new Error(disableTasks + ' is not a valid value. The valid values are: ' + allowedValues);
      }
    } else {
      throw new Error('disableTasks cannot be null or undefined.');
    }
    if (this.client.acceptLanguage !== null && this.client.acceptLanguage !== undefined && typeof this.client.acceptLanguage.valueOf() !== 'string') {
      throw new Error('this.client.acceptLanguage must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  var timeout;
  var clientRequestId;
  var returnClientRequestId;
  var ocpDate;
  var ifMatch;
  var ifNoneMatch;
  var ifModifiedSince;
  var ifUnmodifiedSince;
  var jobDisableParameter = new client.models['JobDisableParameter']();
  try {
    if (jobDisableOptions !== null && jobDisableOptions !== undefined)
    {
      timeout = jobDisableOptions.timeout;
      if (timeout !== null && timeout !== undefined && typeof timeout !== 'number') {
        throw new Error('timeout must be of type number.');
      }
    }
    if (jobDisableOptions !== null && jobDisableOptions !== undefined)
    {
      clientRequestId = jobDisableOptions.clientRequestId;
      if (clientRequestId !== null && clientRequestId !== undefined && typeof clientRequestId.valueOf() !== 'string') {
        throw new Error('clientRequestId must be of type string.');
      }
    }
    if (jobDisableOptions !== null && jobDisableOptions !== undefined)
    {
      returnClientRequestId = jobDisableOptions.returnClientRequestId;
      if (returnClientRequestId !== null && returnClientRequestId !== undefined && typeof returnClientRequestId !== 'boolean') {
        throw new Error('returnClientRequestId must be of type boolean.');
      }
    }
    if (jobDisableOptions !== null && jobDisableOptions !== undefined)
    {
      ocpDate = jobDisableOptions.ocpDate;
      if (ocpDate && !(ocpDate instanceof Date || 
          (typeof ocpDate.valueOf() === 'string' && !isNaN(Date.parse(ocpDate))))) {
            throw new Error('ocpDate must be of type date.');
          }
    }
    if (jobDisableOptions !== null && jobDisableOptions !== undefined)
    {
      ifMatch = jobDisableOptions.ifMatch;
      if (ifMatch !== null && ifMatch !== undefined && typeof ifMatch.valueOf() !== 'string') {
        throw new Error('ifMatch must be of type string.');
      }
    }
    if (jobDisableOptions !== null && jobDisableOptions !== undefined)
    {
      ifNoneMatch = jobDisableOptions.ifNoneMatch;
      if (ifNoneMatch !== null && ifNoneMatch !== undefined && typeof ifNoneMatch.valueOf() !== 'string') {
        throw new Error('ifNoneMatch must be of type string.');
      }
    }
    if (jobDisableOptions !== null && jobDisableOptions !== undefined)
    {
      ifModifiedSince = jobDisableOptions.ifModifiedSince;
      if (ifModifiedSince && !(ifModifiedSince instanceof Date || 
          (typeof ifModifiedSince.valueOf() === 'string' && !isNaN(Date.parse(ifModifiedSince))))) {
            throw new Error('ifModifiedSince must be of type date.');
          }
    }
    if (jobDisableOptions !== null && jobDisableOptions !== undefined)
    {
      ifUnmodifiedSince = jobDisableOptions.ifUnmodifiedSince;
      if (ifUnmodifiedSince && !(ifUnmodifiedSince instanceof Date || 
          (typeof ifUnmodifiedSince.valueOf() === 'string' && !isNaN(Date.parse(ifUnmodifiedSince))))) {
            throw new Error('ifUnmodifiedSince must be of type date.');
          }
    }
    if (disableTasks !== null && disableTasks !== undefined)
    {
      jobDisableParameter.disableTasks = disableTasks;
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  var requestUrl = this.client.baseUri +
                   '//jobs/{jobId}/disable';
  requestUrl = requestUrl.replace('{jobId}', encodeURIComponent(jobId));
  var queryParameters = [];
  queryParameters.push('api-version=' + encodeURIComponent(this.client.apiVersion));
  if (timeout !== null && timeout !== undefined) {
    queryParameters.push('timeout=' + encodeURIComponent(timeout.toString()));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }
  // trim all duplicate forward slashes in the url
  var regex = /([^:]\/)\/+/gi;
  requestUrl = requestUrl.replace(regex, '$1');

  // Create HTTP transport objects
  var httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.headers = {};
  httpRequest.url = requestUrl;
  // Set Headers
  if (this.client.generateClientRequestId) {
      httpRequest.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
  }
  if (this.client.acceptLanguage !== undefined && this.client.acceptLanguage !== null) {
    httpRequest.headers['accept-language'] = this.client.acceptLanguage;
  }
  if (clientRequestId !== undefined && clientRequestId !== null) {
    httpRequest.headers['client-request-id'] = clientRequestId;
  }
  if (returnClientRequestId !== undefined && returnClientRequestId !== null) {
    httpRequest.headers['return-client-request-id'] = returnClientRequestId.toString();
  }
  if (ocpDate !== undefined && ocpDate !== null) {
    httpRequest.headers['ocp-date'] = ocpDate.toUTCString();
  }
  if (ifMatch !== undefined && ifMatch !== null) {
    httpRequest.headers['If-Match'] = ifMatch;
  }
  if (ifNoneMatch !== undefined && ifNoneMatch !== null) {
    httpRequest.headers['If-None-Match'] = ifNoneMatch;
  }
  if (ifModifiedSince !== undefined && ifModifiedSince !== null) {
    httpRequest.headers['If-Modified-Since'] = ifModifiedSince.toUTCString();
  }
  if (ifUnmodifiedSince !== undefined && ifUnmodifiedSince !== null) {
    httpRequest.headers['If-Unmodified-Since'] = ifUnmodifiedSince.toUTCString();
  }
  if(options) {
    for(var headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.headers['Content-Type'] = 'application/json; odata=minimalmetadata; charset=utf-8';
  // Serialize Request
  var requestContent = null;
  var requestModel = null;
  try {
    if (jobDisableParameter !== null && jobDisableParameter !== undefined) {
      var requestModelMapper = new client.models['JobDisableParameter']().mapper();
      requestModel = client.serialize(requestModelMapper, jobDisableParameter, 'jobDisableParameter');
      requestContent = JSON.stringify(requestModel);
    }
  } catch (error) {
    var serializationError = new Error(util.format('Error "%s" occurred in serializing the ' + 
        'payload - "%s"', error.message, util.inspect(jobDisableParameter, {depth: null})));
    return callback(serializationError);
  }
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, function (err, response, responseBody) {
    if (err) {
      return callback(err);
    }
    var statusCode = response.statusCode;
    if (statusCode !== 202) {
      var error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      var parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          if (parsedErrorResponse.error) parsedErrorResponse = parsedErrorResponse.error;
          if (parsedErrorResponse.code) error.code = parsedErrorResponse.code;
          if (parsedErrorResponse.message) error.message = parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          var resultMapper = new client.models['BatchError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = util.format('Error "%s" occurred in deserializing the responseBody ' + 
                         '- "%s" for the default response.', defaultError.message, responseBody);
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    var result = null;
    if (responseBody === '') responseBody = null;

    return callback(null, result, httpRequest, response);
  });
};

/**
 * Enables the specified job, allowing new tasks to run.
 *
 * @param {string} jobId The id of the job to enable.
 * 
 * @param {object} [options] Optional Parameters.
 * 
 * @param {object} [options.jobEnableOptions] Additional parameters for the
 * operation
 * 
 * @param {number} [options.jobEnableOptions.timeout] The maximum time that
 * the server can spend processing the request, in seconds. The default is 30
 * seconds.
 * 
 * @param {string} [options.jobEnableOptions.clientRequestId] The
 * caller-generated request identity, in the form of a GUID with no
 * decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
 * 
 * @param {boolean} [options.jobEnableOptions.returnClientRequestId] Whether
 * the server should return the client-request-id identifier in the response.
 * 
 * @param {date} [options.jobEnableOptions.ocpDate] The time the request was
 * issued. If not specified, this header will be automatically populated with
 * the current system clock time.
 * 
 * @param {string} [options.jobEnableOptions.ifMatch] An ETag is specified.
 * Specify this header to perform the operation only if the resource's ETag
 * is an exact match as specified.
 * 
 * @param {string} [options.jobEnableOptions.ifNoneMatch] An ETag is
 * specified. Specify this header to perform the operation only if the
 * resource's ETag does not match the specified ETag.
 * 
 * @param {date} [options.jobEnableOptions.ifModifiedSince] Specify this
 * header to perform the operation only if the resource has been modified
 * since the specified date/time.
 * 
 * @param {date} [options.jobEnableOptions.ifUnmodifiedSince] Specify this
 * header to perform the operation only if the resource has not been modified
 * since the specified date/time.
 * 
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 * 
 * @param {function} callback
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {null} [result]   - The deserialized result object.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
Job.prototype.enable = function (jobId, options, callback) {
  var client = this.client;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  var jobEnableOptions = (options && options.jobEnableOptions !== undefined) ? options.jobEnableOptions : undefined;
  // Validate
  try {
    if (jobId === null || jobId === undefined || typeof jobId.valueOf() !== 'string') {
      throw new Error('jobId cannot be null or undefined and it must be of type string.');
    }
    if (this.client.apiVersion === null || this.client.apiVersion === undefined || typeof this.client.apiVersion.valueOf() !== 'string') {
      throw new Error('this.client.apiVersion cannot be null or undefined and it must be of type string.');
    }
    if (this.client.acceptLanguage !== null && this.client.acceptLanguage !== undefined && typeof this.client.acceptLanguage.valueOf() !== 'string') {
      throw new Error('this.client.acceptLanguage must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  var timeout;
  var clientRequestId;
  var returnClientRequestId;
  var ocpDate;
  var ifMatch;
  var ifNoneMatch;
  var ifModifiedSince;
  var ifUnmodifiedSince;
  try {
    if (jobEnableOptions !== null && jobEnableOptions !== undefined)
    {
      timeout = jobEnableOptions.timeout;
      if (timeout !== null && timeout !== undefined && typeof timeout !== 'number') {
        throw new Error('timeout must be of type number.');
      }
    }
    if (jobEnableOptions !== null && jobEnableOptions !== undefined)
    {
      clientRequestId = jobEnableOptions.clientRequestId;
      if (clientRequestId !== null && clientRequestId !== undefined && typeof clientRequestId.valueOf() !== 'string') {
        throw new Error('clientRequestId must be of type string.');
      }
    }
    if (jobEnableOptions !== null && jobEnableOptions !== undefined)
    {
      returnClientRequestId = jobEnableOptions.returnClientRequestId;
      if (returnClientRequestId !== null && returnClientRequestId !== undefined && typeof returnClientRequestId !== 'boolean') {
        throw new Error('returnClientRequestId must be of type boolean.');
      }
    }
    if (jobEnableOptions !== null && jobEnableOptions !== undefined)
    {
      ocpDate = jobEnableOptions.ocpDate;
      if (ocpDate && !(ocpDate instanceof Date || 
          (typeof ocpDate.valueOf() === 'string' && !isNaN(Date.parse(ocpDate))))) {
            throw new Error('ocpDate must be of type date.');
          }
    }
    if (jobEnableOptions !== null && jobEnableOptions !== undefined)
    {
      ifMatch = jobEnableOptions.ifMatch;
      if (ifMatch !== null && ifMatch !== undefined && typeof ifMatch.valueOf() !== 'string') {
        throw new Error('ifMatch must be of type string.');
      }
    }
    if (jobEnableOptions !== null && jobEnableOptions !== undefined)
    {
      ifNoneMatch = jobEnableOptions.ifNoneMatch;
      if (ifNoneMatch !== null && ifNoneMatch !== undefined && typeof ifNoneMatch.valueOf() !== 'string') {
        throw new Error('ifNoneMatch must be of type string.');
      }
    }
    if (jobEnableOptions !== null && jobEnableOptions !== undefined)
    {
      ifModifiedSince = jobEnableOptions.ifModifiedSince;
      if (ifModifiedSince && !(ifModifiedSince instanceof Date || 
          (typeof ifModifiedSince.valueOf() === 'string' && !isNaN(Date.parse(ifModifiedSince))))) {
            throw new Error('ifModifiedSince must be of type date.');
          }
    }
    if (jobEnableOptions !== null && jobEnableOptions !== undefined)
    {
      ifUnmodifiedSince = jobEnableOptions.ifUnmodifiedSince;
      if (ifUnmodifiedSince && !(ifUnmodifiedSince instanceof Date || 
          (typeof ifUnmodifiedSince.valueOf() === 'string' && !isNaN(Date.parse(ifUnmodifiedSince))))) {
            throw new Error('ifUnmodifiedSince must be of type date.');
          }
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  var requestUrl = this.client.baseUri +
                   '//jobs/{jobId}/enable';
  requestUrl = requestUrl.replace('{jobId}', encodeURIComponent(jobId));
  var queryParameters = [];
  queryParameters.push('api-version=' + encodeURIComponent(this.client.apiVersion));
  if (timeout !== null && timeout !== undefined) {
    queryParameters.push('timeout=' + encodeURIComponent(timeout.toString()));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }
  // trim all duplicate forward slashes in the url
  var regex = /([^:]\/)\/+/gi;
  requestUrl = requestUrl.replace(regex, '$1');

  // Create HTTP transport objects
  var httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.headers = {};
  httpRequest.url = requestUrl;
  // Set Headers
  if (this.client.generateClientRequestId) {
      httpRequest.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
  }
  if (this.client.acceptLanguage !== undefined && this.client.acceptLanguage !== null) {
    httpRequest.headers['accept-language'] = this.client.acceptLanguage;
  }
  if (clientRequestId !== undefined && clientRequestId !== null) {
    httpRequest.headers['client-request-id'] = clientRequestId;
  }
  if (returnClientRequestId !== undefined && returnClientRequestId !== null) {
    httpRequest.headers['return-client-request-id'] = returnClientRequestId.toString();
  }
  if (ocpDate !== undefined && ocpDate !== null) {
    httpRequest.headers['ocp-date'] = ocpDate.toUTCString();
  }
  if (ifMatch !== undefined && ifMatch !== null) {
    httpRequest.headers['If-Match'] = ifMatch;
  }
  if (ifNoneMatch !== undefined && ifNoneMatch !== null) {
    httpRequest.headers['If-None-Match'] = ifNoneMatch;
  }
  if (ifModifiedSince !== undefined && ifModifiedSince !== null) {
    httpRequest.headers['If-Modified-Since'] = ifModifiedSince.toUTCString();
  }
  if (ifUnmodifiedSince !== undefined && ifUnmodifiedSince !== null) {
    httpRequest.headers['If-Unmodified-Since'] = ifUnmodifiedSince.toUTCString();
  }
  if(options) {
    for(var headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.headers['Content-Type'] = 'application/json; odata=minimalmetadata; charset=utf-8';
  httpRequest.body = null;
  // Send Request
  return client.pipeline(httpRequest, function (err, response, responseBody) {
    if (err) {
      return callback(err);
    }
    var statusCode = response.statusCode;
    if (statusCode !== 202) {
      var error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      var parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          if (parsedErrorResponse.error) parsedErrorResponse = parsedErrorResponse.error;
          if (parsedErrorResponse.code) error.code = parsedErrorResponse.code;
          if (parsedErrorResponse.message) error.message = parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          var resultMapper = new client.models['BatchError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = util.format('Error "%s" occurred in deserializing the responseBody ' + 
                         '- "%s" for the default response.', defaultError.message, responseBody);
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    var result = null;
    if (responseBody === '') responseBody = null;

    return callback(null, result, httpRequest, response);
  });
};

/**
 * Terminates the specified job, marking it as completed.
 *
 * @param {string} jobId The id of the job to terminate.
 * 
 * @param {object} [options] Optional Parameters.
 * 
 * @param {string} [options.terminateReason] The text you want to appear as
 * the job's TerminateReason. The default is 'UserTerminate'.
 * 
 * @param {object} [options.jobTerminateOptions] Additional parameters for the
 * operation
 * 
 * @param {number} [options.jobTerminateOptions.timeout] The maximum time that
 * the server can spend processing the request, in seconds. The default is 30
 * seconds.
 * 
 * @param {string} [options.jobTerminateOptions.clientRequestId] The
 * caller-generated request identity, in the form of a GUID with no
 * decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
 * 
 * @param {boolean} [options.jobTerminateOptions.returnClientRequestId]
 * Whether the server should return the client-request-id identifier in the
 * response.
 * 
 * @param {date} [options.jobTerminateOptions.ocpDate] The time the request
 * was issued. If not specified, this header will be automatically populated
 * with the current system clock time.
 * 
 * @param {string} [options.jobTerminateOptions.ifMatch] An ETag is specified.
 * Specify this header to perform the operation only if the resource's ETag
 * is an exact match as specified.
 * 
 * @param {string} [options.jobTerminateOptions.ifNoneMatch] An ETag is
 * specified. Specify this header to perform the operation only if the
 * resource's ETag does not match the specified ETag.
 * 
 * @param {date} [options.jobTerminateOptions.ifModifiedSince] Specify this
 * header to perform the operation only if the resource has been modified
 * since the specified date/time.
 * 
 * @param {date} [options.jobTerminateOptions.ifUnmodifiedSince] Specify this
 * header to perform the operation only if the resource has not been modified
 * since the specified date/time.
 * 
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 * 
 * @param {function} callback
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {null} [result]   - The deserialized result object.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
Job.prototype.terminate = function (jobId, options, callback) {
  var client = this.client;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  var terminateReason = (options && options.terminateReason !== undefined) ? options.terminateReason : undefined;
  var jobTerminateOptions = (options && options.jobTerminateOptions !== undefined) ? options.jobTerminateOptions : undefined;
  // Validate
  try {
    if (jobId === null || jobId === undefined || typeof jobId.valueOf() !== 'string') {
      throw new Error('jobId cannot be null or undefined and it must be of type string.');
    }
    if (this.client.apiVersion === null || this.client.apiVersion === undefined || typeof this.client.apiVersion.valueOf() !== 'string') {
      throw new Error('this.client.apiVersion cannot be null or undefined and it must be of type string.');
    }
    if (terminateReason !== null && terminateReason !== undefined && typeof terminateReason.valueOf() !== 'string') {
      throw new Error('terminateReason must be of type string.');
    }
    if (this.client.acceptLanguage !== null && this.client.acceptLanguage !== undefined && typeof this.client.acceptLanguage.valueOf() !== 'string') {
      throw new Error('this.client.acceptLanguage must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  var timeout;
  var clientRequestId;
  var returnClientRequestId;
  var ocpDate;
  var ifMatch;
  var ifNoneMatch;
  var ifModifiedSince;
  var ifUnmodifiedSince;
  var jobTerminateParameter;
  try {
    if (jobTerminateOptions !== null && jobTerminateOptions !== undefined)
    {
      timeout = jobTerminateOptions.timeout;
      if (timeout !== null && timeout !== undefined && typeof timeout !== 'number') {
        throw new Error('timeout must be of type number.');
      }
    }
    if (jobTerminateOptions !== null && jobTerminateOptions !== undefined)
    {
      clientRequestId = jobTerminateOptions.clientRequestId;
      if (clientRequestId !== null && clientRequestId !== undefined && typeof clientRequestId.valueOf() !== 'string') {
        throw new Error('clientRequestId must be of type string.');
      }
    }
    if (jobTerminateOptions !== null && jobTerminateOptions !== undefined)
    {
      returnClientRequestId = jobTerminateOptions.returnClientRequestId;
      if (returnClientRequestId !== null && returnClientRequestId !== undefined && typeof returnClientRequestId !== 'boolean') {
        throw new Error('returnClientRequestId must be of type boolean.');
      }
    }
    if (jobTerminateOptions !== null && jobTerminateOptions !== undefined)
    {
      ocpDate = jobTerminateOptions.ocpDate;
      if (ocpDate && !(ocpDate instanceof Date || 
          (typeof ocpDate.valueOf() === 'string' && !isNaN(Date.parse(ocpDate))))) {
            throw new Error('ocpDate must be of type date.');
          }
    }
    if (jobTerminateOptions !== null && jobTerminateOptions !== undefined)
    {
      ifMatch = jobTerminateOptions.ifMatch;
      if (ifMatch !== null && ifMatch !== undefined && typeof ifMatch.valueOf() !== 'string') {
        throw new Error('ifMatch must be of type string.');
      }
    }
    if (jobTerminateOptions !== null && jobTerminateOptions !== undefined)
    {
      ifNoneMatch = jobTerminateOptions.ifNoneMatch;
      if (ifNoneMatch !== null && ifNoneMatch !== undefined && typeof ifNoneMatch.valueOf() !== 'string') {
        throw new Error('ifNoneMatch must be of type string.');
      }
    }
    if (jobTerminateOptions !== null && jobTerminateOptions !== undefined)
    {
      ifModifiedSince = jobTerminateOptions.ifModifiedSince;
      if (ifModifiedSince && !(ifModifiedSince instanceof Date || 
          (typeof ifModifiedSince.valueOf() === 'string' && !isNaN(Date.parse(ifModifiedSince))))) {
            throw new Error('ifModifiedSince must be of type date.');
          }
    }
    if (jobTerminateOptions !== null && jobTerminateOptions !== undefined)
    {
      ifUnmodifiedSince = jobTerminateOptions.ifUnmodifiedSince;
      if (ifUnmodifiedSince && !(ifUnmodifiedSince instanceof Date || 
          (typeof ifUnmodifiedSince.valueOf() === 'string' && !isNaN(Date.parse(ifUnmodifiedSince))))) {
            throw new Error('ifUnmodifiedSince must be of type date.');
          }
    }
    if (terminateReason !== null && terminateReason !== undefined)
    {
      jobTerminateParameter = new client.models['JobTerminateParameter']();
      jobTerminateParameter.terminateReason = terminateReason;
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  var requestUrl = this.client.baseUri +
                   '//jobs/{jobId}/terminate';
  requestUrl = requestUrl.replace('{jobId}', encodeURIComponent(jobId));
  var queryParameters = [];
  queryParameters.push('api-version=' + encodeURIComponent(this.client.apiVersion));
  if (timeout !== null && timeout !== undefined) {
    queryParameters.push('timeout=' + encodeURIComponent(timeout.toString()));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }
  // trim all duplicate forward slashes in the url
  var regex = /([^:]\/)\/+/gi;
  requestUrl = requestUrl.replace(regex, '$1');

  // Create HTTP transport objects
  var httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.headers = {};
  httpRequest.url = requestUrl;
  // Set Headers
  if (this.client.generateClientRequestId) {
      httpRequest.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
  }
  if (this.client.acceptLanguage !== undefined && this.client.acceptLanguage !== null) {
    httpRequest.headers['accept-language'] = this.client.acceptLanguage;
  }
  if (clientRequestId !== undefined && clientRequestId !== null) {
    httpRequest.headers['client-request-id'] = clientRequestId;
  }
  if (returnClientRequestId !== undefined && returnClientRequestId !== null) {
    httpRequest.headers['return-client-request-id'] = returnClientRequestId.toString();
  }
  if (ocpDate !== undefined && ocpDate !== null) {
    httpRequest.headers['ocp-date'] = ocpDate.toUTCString();
  }
  if (ifMatch !== undefined && ifMatch !== null) {
    httpRequest.headers['If-Match'] = ifMatch;
  }
  if (ifNoneMatch !== undefined && ifNoneMatch !== null) {
    httpRequest.headers['If-None-Match'] = ifNoneMatch;
  }
  if (ifModifiedSince !== undefined && ifModifiedSince !== null) {
    httpRequest.headers['If-Modified-Since'] = ifModifiedSince.toUTCString();
  }
  if (ifUnmodifiedSince !== undefined && ifUnmodifiedSince !== null) {
    httpRequest.headers['If-Unmodified-Since'] = ifUnmodifiedSince.toUTCString();
  }
  if(options) {
    for(var headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.headers['Content-Type'] = 'application/json; odata=minimalmetadata; charset=utf-8';
  // Serialize Request
  var requestContent = null;
  var requestModel = null;
  try {
    if (jobTerminateParameter !== null && jobTerminateParameter !== undefined) {
      var requestModelMapper = new client.models['JobTerminateParameter']().mapper();
      requestModel = client.serialize(requestModelMapper, jobTerminateParameter, 'jobTerminateParameter');
      requestContent = JSON.stringify(requestModel);
    }
  } catch (error) {
    var serializationError = new Error(util.format('Error "%s" occurred in serializing the ' + 
        'payload - "%s"', error.message, util.inspect(jobTerminateParameter, {depth: null})));
    return callback(serializationError);
  }
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, function (err, response, responseBody) {
    if (err) {
      return callback(err);
    }
    var statusCode = response.statusCode;
    if (statusCode !== 202) {
      var error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      var parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          if (parsedErrorResponse.error) parsedErrorResponse = parsedErrorResponse.error;
          if (parsedErrorResponse.code) error.code = parsedErrorResponse.code;
          if (parsedErrorResponse.message) error.message = parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          var resultMapper = new client.models['BatchError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = util.format('Error "%s" occurred in deserializing the responseBody ' + 
                         '- "%s" for the default response.', defaultError.message, responseBody);
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    var result = null;
    if (responseBody === '') responseBody = null;

    return callback(null, result, httpRequest, response);
  });
};

/**
 * Adds a job to the specified account.
 *
 * @param {object} job The job to be added.
 * 
 * @param {string} [job.id] A string that uniquely identifies the job within
 * the account. The id can contain any combination of alphanumeric characters
 * including hyphens and underscores, and cannot contain more than 64
 * characters. It is common to use a GUID for the id.
 * 
 * @param {string} [job.displayName] The display name for the job.
 * 
 * @param {number} [job.priority] The priority of the job. Priority values can
 * range from -1000 to 1000, with -1000 being the lowest priority and 1000
 * being the highest priority. The default value is 0.
 * 
 * @param {object} [job.constraints] The execution constraints for the job.
 * 
 * @param {moment.duration} [job.constraints.maxWallClockTime] The maximum
 * elapsed time that the job may run, measured from the time the job starts.
 * If the job does not complete within the time limit, the Batch service
 * terminates it and any tasks that are still running.
 * 
 * @param {number} [job.constraints.maxTaskRetryCount] The maximum number of
 * times each task may be retried. The Batch service retries a task if its
 * exit code is nonzero.
 * 
 * @param {object} [job.jobManagerTask] Details of a Job Manager task to be
 * launched when the job is started.
 * 
 * @param {string} [job.jobManagerTask.id] A string that uniquely identifies
 * the Job Manager task. A GUID is recommended.
 * 
 * @param {string} [job.jobManagerTask.displayName] The display name of the
 * Job Manager task.
 * 
 * @param {string} [job.jobManagerTask.commandLine] The command line of the
 * Job Manager task.
 * 
 * @param {array} [job.jobManagerTask.resourceFiles] A list of files that the
 * Batch service will download to the compute node before running the command
 * line.
 * 
 * @param {array} [job.jobManagerTask.environmentSettings] A list of
 * environment variable settings for the Job Manager task.
 * 
 * @param {object} [job.jobManagerTask.constraints] Constraints that apply to
 * the Job Manager task.
 * 
 * @param {boolean} [job.jobManagerTask.killJobOnCompletion] Whether
 * completion of the Job Manager task signifies completion of the entire job.
 * 
 * @param {boolean} [job.jobManagerTask.runElevated] Whether to run the Job
 * Manager task in elevated mode. The default value is false.
 * 
 * @param {boolean} [job.jobManagerTask.runExclusive] Whether the Job Manager
 * task requires exclusive use of the compute node where it runs. If true, no
 * other tasks will run on the same compute node for as long as the Job
 * Manager is running. If false, other tasks can run simultaneously with the
 * Job Manager on a compute node. (The Job Manager task counts normally
 * against the node’s concurrent task limit, so this is only relevant if the
 * node allows multiple concurrent tasks.)
 * 
 * @param {object} [job.jobPreparationTask] The Job Preparation task.
 * 
 * @param {string} [job.jobPreparationTask.id] A string that uniquely
 * identifies the job preparation task within the job. The id can contain any
 * combination of alphanumeric characters including hyphens and underscores
 * and cannot contain more than 64 characters.
 * 
 * @param {string} [job.jobPreparationTask.commandLine] The command line of
 * the Job Preparation task.
 * 
 * @param {array} [job.jobPreparationTask.resourceFiles] A list of files that
 * the Batch service will download to the compute node before running the
 * command line.
 * 
 * @param {array} [job.jobPreparationTask.environmentSettings] A list of
 * environment variable settings for the Job Preparation task.
 * 
 * @param {object} [job.jobPreparationTask.constraints] Constraints that apply
 * to the Job Preparation task.
 * 
 * @param {moment.duration}
 * [job.jobPreparationTask.constraints.maxWallClockTime] The maximum elapsed
 * time that the task may run, measured from the time the task starts. If the
 * task does not complete within the time limit, the Batch service terminates
 * it.
 * 
 * @param {moment.duration} [job.jobPreparationTask.constraints.retentionTime]
 * The minimum time to retain the working directory for the task on the
 * compute node where it ran, from the time it completes execution. After
 * this time, the Batch service may delete the working directory and all its
 * contents. The default is infinite.
 * 
 * @param {number} [job.jobPreparationTask.constraints.maxTaskRetryCount] The
 * maximum number of times the task may be retried. The Batch service retries
 * a task if its exit code is nonzero.
 * 
 * @param {boolean} [job.jobPreparationTask.waitForSuccess] Whether the Batch
 * service should wait for the Job Preparation task to complete successfully
 * before scheduling any other tasks of the job on the compute node.
 * 
 * @param {boolean} [job.jobPreparationTask.runElevated] Whether to run the
 * Job Preparation task in elevated mode. The default value is false.
 * 
 * @param {boolean} [job.jobPreparationTask.rerunOnNodeRebootAfterSuccess]
 * Whether the Batch service should rerun the Job Preparation task after a
 * compute node reboots. Note that the Job Preparation task should still be
 * written to be idempotent because it can be rerun if the compute node is
 * rebooted while Job Preparation task is still running. The default value is
 * true.
 * 
 * @param {object} [job.jobReleaseTask] The Job Release task.
 * 
 * @param {string} [job.jobReleaseTask.id] A string that uniquely identifies
 * the Job Release task within the job. The id can contain any combination of
 * alphanumeric characters including hyphens and underscores and cannot
 * contain more than 64 characters.
 * 
 * @param {string} [job.jobReleaseTask.commandLine] The command line of the
 * Job Release task.
 * 
 * @param {array} [job.jobReleaseTask.resourceFiles] A list of files that the
 * Batch service will download to the compute node before running the command
 * line.
 * 
 * @param {array} [job.jobReleaseTask.environmentSettings] A list of
 * environment variable settings for the Job Release task.
 * 
 * @param {moment.duration} [job.jobReleaseTask.maxWallClockTime] The maximum
 * elapsed time that the Job Release task may run on a given compute node,
 * measured from the time the task starts. If the task does not complete
 * within the time limit, the Batch service terminates it. The default value
 * is 15 minutes.
 * 
 * @param {moment.duration} [job.jobReleaseTask.retentionTime] The minimum
 * time to retain the working directory for the Job Release task on the
 * compute node. After this time, the Batch service may delete the working
 * directory and all its contents. The default is infinite.
 * 
 * @param {boolean} [job.jobReleaseTask.runElevated] Whether to run the Job
 * Release task in elevated mode. The default value is false.
 * 
 * @param {array} [job.commonEnvironmentSettings] The list of common
 * environment variable settings. These environment variables are set for all
 * tasks in the job (including the Job Manager, Job Preparation and Job
 * Release tasks).
 * 
 * @param {object} [job.poolInfo] The pool on which the Batch service runs the
 * job’s tasks.
 * 
 * @param {string} [job.poolInfo.poolId] The id of an existing pool. All the
 * tasks of the job will run on the specified pool. You must specify either
 * PoolId or AutoPoolSpecification, but not both.
 * 
 * @param {object} [job.poolInfo.autoPoolSpecification] Characteristics for a
 * temporary 'auto pool'. The Batch service will create this auto pool and
 * run all of the tasks of the job on it, and will delete the pool once the
 * job has completed. You must specify either PoolId or
 * AutoPoolSpecification, but not both.
 * 
 * @param {string} [job.poolInfo.autoPoolSpecification.autoPoolIdPrefix] A
 * prefix to be added to the unique identifier when a pool is automatically
 * created. The prefix can be up to 20 characters long.
 * 
 * @param {string} [job.poolInfo.autoPoolSpecification.poolLifetimeOption] The
 * minimum lifetime of created auto pools, and how multiple jobs on a
 * schedule are assigned to pools. Possible values include: 'jobschedule',
 * 'job', 'unmapped'
 * 
 * @param {boolean} [job.poolInfo.autoPoolSpecification.keepAlive] Whether to
 * keep an auto pool alive after its lifetime expires.
 * 
 * @param {object} [job.poolInfo.autoPoolSpecification.pool] The pool
 * specification for the auto pool.
 * 
 * @param {string} [job.poolInfo.autoPoolSpecification.pool.displayName] The
 * display name for the pool.
 * 
 * @param {string} [job.poolInfo.autoPoolSpecification.pool.vmSize] The size
 * of the virtual machines in the pool. All virtual machines in a pool are
 * the same size.
 * 
 * @param {object}
 * [job.poolInfo.autoPoolSpecification.pool.cloudServiceConfiguration] The
 * cloud service configuration for the pool. This property and
 * VirtualMachineConfiguration are mutually exclusive and one of the
 * properties must be specified.
 * 
 * @param {string}
 * [job.poolInfo.autoPoolSpecification.pool.cloudServiceConfiguration.osFamily]
 * The Azure Guest OS family to be installed on the virtual machines in the
 * pool.
 * 
 * @param {string}
 * [job.poolInfo.autoPoolSpecification.pool.cloudServiceConfiguration.targetOSVersion]
 * The Azure Guest OS version to be installed on the virtual machines in the
 * pool. The default value is * which specifies the latest operating system
 * version for the specified OS family.
 * 
 * @param {string}
 * [job.poolInfo.autoPoolSpecification.pool.cloudServiceConfiguration.currentOSVersion]
 * The Azure Guest OS Version currently installed on the virtual machines in
 * the pool. This may differ from TargetOSVersion if the pool state is
 * Upgrading.
 * 
 * @param {object}
 * [job.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration] The
 * virtual machine configuration for the pool. This property and
 * CloudServiceConfiguration are mutually exclusive and one of the properties
 * must be specified.
 * 
 * @param {object}
 * [job.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.imageReference]
 * A reference to the Azure Virtual Machines Marketplace image to use.
 * 
 * @param {string}
 * [job.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.imageReference.publisher]
 * The publisher of the Azure Virtual Machines Marketplace image. For
 * example, Canonical or MicrosoftWindowsServer.
 * 
 * @param {string}
 * [job.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.imageReference.offer]
 * The offer type of the Azure Virtual Machines Marketplace image. For
 * example, UbuntuServer or WindowsServer.
 * 
 * @param {string}
 * [job.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.imageReference.sku]
 * The SKU of the Azure Virtual Machines Marketplace image. For example,
 * 14.04.0-LTS or 2012-R2-Datacenter.
 * 
 * @param {string}
 * [job.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.imageReference.version]
 * The version of the Azure Virtual Machines Marketplace image. A value of
 * 'latest' can be specified to select the latest version of an image. If
 * omitted, the default is 'latest'.
 * 
 * @param {string}
 * [job.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.nodeAgentSKUId]
 * The SKU of Batch Node Agent to be provisioned on the compute node. The
 * Batch node agent is a program that runs on each node in the pool, and
 * provides the command-and-control interface between the node and the Batch
 * service. There are different implementations of the node agent, known as
 * SKUs, for different operating systems.
 * 
 * @param {object}
 * [job.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.windowsConfiguration]
 * Windows operating system settings on the virtual machine. This property
 * must not be specified if the ImageReference property specifies a Linux OS
 * image.
 * 
 * @param {boolean}
 * [job.poolInfo.autoPoolSpecification.pool.virtualMachineConfiguration.windowsConfiguration.enableAutomaticUpdates]
 * Whether automatic updates are enabled on the virtual machine. If omitted,
 * the default value is true.
 * 
 * @param {number} [job.poolInfo.autoPoolSpecification.pool.maxTasksPerNode]
 * The maximum number of tasks that can run concurrently on a single compute
 * node in the pool.
 * 
 * @param {object}
 * [job.poolInfo.autoPoolSpecification.pool.taskSchedulingPolicy] How tasks
 * are distributed among compute nodes in the pool.
 * 
 * @param {string}
 * [job.poolInfo.autoPoolSpecification.pool.taskSchedulingPolicy.nodeFillType]
 * How tasks should be distributed across compute nodes. Possible values
 * include: 'spread', 'pack', 'unmapped'
 * 
 * @param {moment.duration}
 * [job.poolInfo.autoPoolSpecification.pool.resizeTimeout] The timeout for
 * allocation of compute nodes to the pool.
 * 
 * @param {number} [job.poolInfo.autoPoolSpecification.pool.targetDedicated]
 * The desired number of compute nodes in the pool.
 * 
 * @param {boolean} [job.poolInfo.autoPoolSpecification.pool.enableAutoScale]
 * Whether the pool size should automatically adjust over time.
 * 
 * @param {string} [job.poolInfo.autoPoolSpecification.pool.autoScaleFormula]
 * The formula for the desired number of compute nodes in the pool.
 * 
 * @param {moment.duration}
 * [job.poolInfo.autoPoolSpecification.pool.autoScaleEvaluationInterval] A
 * time interval for the desired AutoScale evaluation period in the pool.
 * 
 * @param {boolean}
 * [job.poolInfo.autoPoolSpecification.pool.enableInterNodeCommunication]
 * Whether the pool permits direct communication between nodes.
 * 
 * @param {object} [job.poolInfo.autoPoolSpecification.pool.startTask] A task
 * to run on each compute node as it joins the pool. The task runs when the
 * node is added to the pool or when the node is restarted.
 * 
 * @param {string}
 * [job.poolInfo.autoPoolSpecification.pool.startTask.commandLine] The
 * command line of the start task.
 * 
 * @param {array}
 * [job.poolInfo.autoPoolSpecification.pool.startTask.resourceFiles] A list
 * of files that the Batch service will download to the compute node before
 * running the command line.
 * 
 * @param {array}
 * [job.poolInfo.autoPoolSpecification.pool.startTask.environmentSettings] A
 * list of environment variable settings for the start task.
 * 
 * @param {boolean}
 * [job.poolInfo.autoPoolSpecification.pool.startTask.runElevated] Whether to
 * run the start task in elevated mode. The default value is false.
 * 
 * @param {number}
 * [job.poolInfo.autoPoolSpecification.pool.startTask.maxTaskRetryCount] The
 * maximum number of times the task may be retried.
 * 
 * @param {boolean}
 * [job.poolInfo.autoPoolSpecification.pool.startTask.waitForSuccess] Whether
 * the Batch service should wait for the start task to complete successfully
 * (that is, to exit with exit code 0) before scheduling any tasks on the
 * compute node.
 * 
 * @param {array}
 * [job.poolInfo.autoPoolSpecification.pool.certificateReferences] A list of
 * certificates to be installed on each compute node in the pool.
 * 
 * @param {array}
 * [job.poolInfo.autoPoolSpecification.pool.applicationPackageReferences] The
 * list of application packages to be installed on each compute node in the
 * pool.
 * 
 * @param {array} [job.poolInfo.autoPoolSpecification.pool.metadata] A list of
 * name-value pairs associated with the pool as metadata.
 * 
 * @param {array} [job.metadata] A list of name-value pairs associated with
 * the job as metadata.
 * 
 * @param {boolean} [job.usesTaskDependencies] The flag that determines if
 * this job will use tasks with dependencies.
 * 
 * @param {object} [options] Optional Parameters.
 * 
 * @param {object} [options.jobAddOptions] Additional parameters for the
 * operation
 * 
 * @param {number} [options.jobAddOptions.timeout] The maximum time that the
 * server can spend processing the request, in seconds. The default is 30
 * seconds.
 * 
 * @param {string} [options.jobAddOptions.clientRequestId] The
 * caller-generated request identity, in the form of a GUID with no
 * decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
 * 
 * @param {boolean} [options.jobAddOptions.returnClientRequestId] Whether the
 * server should return the client-request-id identifier in the response.
 * 
 * @param {date} [options.jobAddOptions.ocpDate] The time the request was
 * issued. If not specified, this header will be automatically populated with
 * the current system clock time.
 * 
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 * 
 * @param {function} callback
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {null} [result]   - The deserialized result object.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
Job.prototype.add = function (job, options, callback) {
  var client = this.client;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  var jobAddOptions = (options && options.jobAddOptions !== undefined) ? options.jobAddOptions : undefined;
  // Validate
  try {
    if (job === null || job === undefined) {
      throw new Error('job cannot be null or undefined.');
    }
    if (this.client.apiVersion === null || this.client.apiVersion === undefined || typeof this.client.apiVersion.valueOf() !== 'string') {
      throw new Error('this.client.apiVersion cannot be null or undefined and it must be of type string.');
    }
    if (this.client.acceptLanguage !== null && this.client.acceptLanguage !== undefined && typeof this.client.acceptLanguage.valueOf() !== 'string') {
      throw new Error('this.client.acceptLanguage must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  var timeout;
  var clientRequestId;
  var returnClientRequestId;
  var ocpDate;
  try {
    if (jobAddOptions !== null && jobAddOptions !== undefined)
    {
      timeout = jobAddOptions.timeout;
      if (timeout !== null && timeout !== undefined && typeof timeout !== 'number') {
        throw new Error('timeout must be of type number.');
      }
    }
    if (jobAddOptions !== null && jobAddOptions !== undefined)
    {
      clientRequestId = jobAddOptions.clientRequestId;
      if (clientRequestId !== null && clientRequestId !== undefined && typeof clientRequestId.valueOf() !== 'string') {
        throw new Error('clientRequestId must be of type string.');
      }
    }
    if (jobAddOptions !== null && jobAddOptions !== undefined)
    {
      returnClientRequestId = jobAddOptions.returnClientRequestId;
      if (returnClientRequestId !== null && returnClientRequestId !== undefined && typeof returnClientRequestId !== 'boolean') {
        throw new Error('returnClientRequestId must be of type boolean.');
      }
    }
    if (jobAddOptions !== null && jobAddOptions !== undefined)
    {
      ocpDate = jobAddOptions.ocpDate;
      if (ocpDate && !(ocpDate instanceof Date || 
          (typeof ocpDate.valueOf() === 'string' && !isNaN(Date.parse(ocpDate))))) {
            throw new Error('ocpDate must be of type date.');
          }
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  var requestUrl = this.client.baseUri +
                   '//jobs';
  var queryParameters = [];
  queryParameters.push('api-version=' + encodeURIComponent(this.client.apiVersion));
  if (timeout !== null && timeout !== undefined) {
    queryParameters.push('timeout=' + encodeURIComponent(timeout.toString()));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }
  // trim all duplicate forward slashes in the url
  var regex = /([^:]\/)\/+/gi;
  requestUrl = requestUrl.replace(regex, '$1');

  // Create HTTP transport objects
  var httpRequest = new WebResource();
  httpRequest.method = 'POST';
  httpRequest.headers = {};
  httpRequest.url = requestUrl;
  // Set Headers
  if (this.client.generateClientRequestId) {
      httpRequest.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
  }
  if (this.client.acceptLanguage !== undefined && this.client.acceptLanguage !== null) {
    httpRequest.headers['accept-language'] = this.client.acceptLanguage;
  }
  if (clientRequestId !== undefined && clientRequestId !== null) {
    httpRequest.headers['client-request-id'] = clientRequestId;
  }
  if (returnClientRequestId !== undefined && returnClientRequestId !== null) {
    httpRequest.headers['return-client-request-id'] = returnClientRequestId.toString();
  }
  if (ocpDate !== undefined && ocpDate !== null) {
    httpRequest.headers['ocp-date'] = ocpDate.toUTCString();
  }
  if(options) {
    for(var headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.headers['Content-Type'] = 'application/json; odata=minimalmetadata; charset=utf-8';
  // Serialize Request
  var requestContent = null;
  var requestModel = null;
  try {
    if (job !== null && job !== undefined) {
      var requestModelMapper = new client.models['JobAddParameter']().mapper();
      requestModel = client.serialize(requestModelMapper, job, 'job');
      requestContent = JSON.stringify(requestModel);
    }
  } catch (error) {
    var serializationError = new Error(util.format('Error "%s" occurred in serializing the ' + 
        'payload - "%s"', error.message, util.inspect(job, {depth: null})));
    return callback(serializationError);
  }
  httpRequest.body = requestContent;
  // Send Request
  return client.pipeline(httpRequest, function (err, response, responseBody) {
    if (err) {
      return callback(err);
    }
    var statusCode = response.statusCode;
    if (statusCode !== 201) {
      var error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      var parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          if (parsedErrorResponse.error) parsedErrorResponse = parsedErrorResponse.error;
          if (parsedErrorResponse.code) error.code = parsedErrorResponse.code;
          if (parsedErrorResponse.message) error.message = parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          var resultMapper = new client.models['BatchError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = util.format('Error "%s" occurred in deserializing the responseBody ' + 
                         '- "%s" for the default response.', defaultError.message, responseBody);
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    var result = null;
    if (responseBody === '') responseBody = null;

    return callback(null, result, httpRequest, response);
  });
};

/**
 * Lists all of the jobs in the specified account.
 *
 * @param {object} [options] Optional Parameters.
 * 
 * @param {object} [options.jobListOptions] Additional parameters for the
 * operation
 * 
 * @param {string} [options.jobListOptions.filter] An OData $filter clause.
 * 
 * @param {string} [options.jobListOptions.select] An OData $select clause.
 * 
 * @param {string} [options.jobListOptions.expand] An OData $expand clause.
 * 
 * @param {number} [options.jobListOptions.maxResults] The maximum number of
 * items to return in the response.
 * 
 * @param {number} [options.jobListOptions.timeout] The maximum time that the
 * server can spend processing the request, in seconds. The default is 30
 * seconds.
 * 
 * @param {string} [options.jobListOptions.clientRequestId] The
 * caller-generated request identity, in the form of a GUID with no
 * decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
 * 
 * @param {boolean} [options.jobListOptions.returnClientRequestId] Whether the
 * server should return the client-request-id identifier in the response.
 * 
 * @param {date} [options.jobListOptions.ocpDate] The time the request was
 * issued. If not specified, this header will be automatically populated with
 * the current system clock time.
 * 
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 * 
 * @param {function} callback
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object.
 *                      See {@link CloudJobListResult} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
Job.prototype.list = function (options, callback) {
  var client = this.client;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  var jobListOptions = (options && options.jobListOptions !== undefined) ? options.jobListOptions : undefined;
  // Validate
  try {
    if (this.client.apiVersion === null || this.client.apiVersion === undefined || typeof this.client.apiVersion.valueOf() !== 'string') {
      throw new Error('this.client.apiVersion cannot be null or undefined and it must be of type string.');
    }
    if (this.client.acceptLanguage !== null && this.client.acceptLanguage !== undefined && typeof this.client.acceptLanguage.valueOf() !== 'string') {
      throw new Error('this.client.acceptLanguage must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  var filter;
  var select;
  var expand;
  var maxResults;
  var timeout;
  var clientRequestId;
  var returnClientRequestId;
  var ocpDate;
  try {
    if (jobListOptions !== null && jobListOptions !== undefined)
    {
      filter = jobListOptions.filter;
      if (filter !== null && filter !== undefined && typeof filter.valueOf() !== 'string') {
        throw new Error('filter must be of type string.');
      }
    }
    if (jobListOptions !== null && jobListOptions !== undefined)
    {
      select = jobListOptions.select;
      if (select !== null && select !== undefined && typeof select.valueOf() !== 'string') {
        throw new Error('select must be of type string.');
      }
    }
    if (jobListOptions !== null && jobListOptions !== undefined)
    {
      expand = jobListOptions.expand;
      if (expand !== null && expand !== undefined && typeof expand.valueOf() !== 'string') {
        throw new Error('expand must be of type string.');
      }
    }
    if (jobListOptions !== null && jobListOptions !== undefined)
    {
      maxResults = jobListOptions.maxResults;
      if (maxResults !== null && maxResults !== undefined && typeof maxResults !== 'number') {
        throw new Error('maxResults must be of type number.');
      }
    }
    if (jobListOptions !== null && jobListOptions !== undefined)
    {
      timeout = jobListOptions.timeout;
      if (timeout !== null && timeout !== undefined && typeof timeout !== 'number') {
        throw new Error('timeout must be of type number.');
      }
    }
    if (jobListOptions !== null && jobListOptions !== undefined)
    {
      clientRequestId = jobListOptions.clientRequestId;
      if (clientRequestId !== null && clientRequestId !== undefined && typeof clientRequestId.valueOf() !== 'string') {
        throw new Error('clientRequestId must be of type string.');
      }
    }
    if (jobListOptions !== null && jobListOptions !== undefined)
    {
      returnClientRequestId = jobListOptions.returnClientRequestId;
      if (returnClientRequestId !== null && returnClientRequestId !== undefined && typeof returnClientRequestId !== 'boolean') {
        throw new Error('returnClientRequestId must be of type boolean.');
      }
    }
    if (jobListOptions !== null && jobListOptions !== undefined)
    {
      ocpDate = jobListOptions.ocpDate;
      if (ocpDate && !(ocpDate instanceof Date || 
          (typeof ocpDate.valueOf() === 'string' && !isNaN(Date.parse(ocpDate))))) {
            throw new Error('ocpDate must be of type date.');
          }
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  var requestUrl = this.client.baseUri +
                   '//jobs';
  var queryParameters = [];
  queryParameters.push('api-version=' + encodeURIComponent(this.client.apiVersion));
  if (filter !== null && filter !== undefined) {
    queryParameters.push('$filter=' + encodeURIComponent(filter));
  }
  if (select !== null && select !== undefined) {
    queryParameters.push('$select=' + encodeURIComponent(select));
  }
  if (expand !== null && expand !== undefined) {
    queryParameters.push('$expand=' + encodeURIComponent(expand));
  }
  if (maxResults !== null && maxResults !== undefined) {
    queryParameters.push('maxresults=' + encodeURIComponent(maxResults.toString()));
  }
  if (timeout !== null && timeout !== undefined) {
    queryParameters.push('timeout=' + encodeURIComponent(timeout.toString()));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }
  // trim all duplicate forward slashes in the url
  var regex = /([^:]\/)\/+/gi;
  requestUrl = requestUrl.replace(regex, '$1');

  // Create HTTP transport objects
  var httpRequest = new WebResource();
  httpRequest.method = 'GET';
  httpRequest.headers = {};
  httpRequest.url = requestUrl;
  // Set Headers
  if (this.client.generateClientRequestId) {
      httpRequest.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
  }
  if (this.client.acceptLanguage !== undefined && this.client.acceptLanguage !== null) {
    httpRequest.headers['accept-language'] = this.client.acceptLanguage;
  }
  if (clientRequestId !== undefined && clientRequestId !== null) {
    httpRequest.headers['client-request-id'] = clientRequestId;
  }
  if (returnClientRequestId !== undefined && returnClientRequestId !== null) {
    httpRequest.headers['return-client-request-id'] = returnClientRequestId.toString();
  }
  if (ocpDate !== undefined && ocpDate !== null) {
    httpRequest.headers['ocp-date'] = ocpDate.toUTCString();
  }
  if(options) {
    for(var headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.headers['Content-Type'] = 'application/json; odata=minimalmetadata; charset=utf-8';
  httpRequest.body = null;
  // Send Request
  return client.pipeline(httpRequest, function (err, response, responseBody) {
    if (err) {
      return callback(err);
    }
    var statusCode = response.statusCode;
    if (statusCode !== 200) {
      var error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      var parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          if (parsedErrorResponse.error) parsedErrorResponse = parsedErrorResponse.error;
          if (parsedErrorResponse.code) error.code = parsedErrorResponse.code;
          if (parsedErrorResponse.message) error.message = parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          var resultMapper = new client.models['BatchError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = util.format('Error "%s" occurred in deserializing the responseBody ' + 
                         '- "%s" for the default response.', defaultError.message, responseBody);
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    var result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      var parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          var resultMapper = new client.models['CloudJobListResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        var deserializationError = new Error(util.format('Error "%s" occurred in deserializing the responseBody - "%s"', error, responseBody));
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
};

/**
 * Lists the jobs that have been created under the specified job schedule.
 *
 * @param {string} jobScheduleId The id of the job schedule from which you
 * want to get a list of jobs.
 * 
 * @param {object} [options] Optional Parameters.
 * 
 * @param {object} [options.jobListFromJobScheduleOptions] Additional
 * parameters for the operation
 * 
 * @param {string} [options.jobListFromJobScheduleOptions.filter] An OData
 * $filter clause.
 * 
 * @param {string} [options.jobListFromJobScheduleOptions.select] An OData
 * $select clause.
 * 
 * @param {string} [options.jobListFromJobScheduleOptions.expand] An OData
 * $expand clause.
 * 
 * @param {number} [options.jobListFromJobScheduleOptions.maxResults] The
 * maximum number of items to return in the response.
 * 
 * @param {number} [options.jobListFromJobScheduleOptions.timeout] The maximum
 * time that the server can spend processing the request, in seconds. The
 * default is 30 seconds.
 * 
 * @param {string} [options.jobListFromJobScheduleOptions.clientRequestId] The
 * caller-generated request identity, in the form of a GUID with no
 * decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
 * 
 * @param {boolean}
 * [options.jobListFromJobScheduleOptions.returnClientRequestId] Whether the
 * server should return the client-request-id identifier in the response.
 * 
 * @param {date} [options.jobListFromJobScheduleOptions.ocpDate] The time the
 * request was issued. If not specified, this header will be automatically
 * populated with the current system clock time.
 * 
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 * 
 * @param {function} callback
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object.
 *                      See {@link CloudJobListResult} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
Job.prototype.listFromJobSchedule = function (jobScheduleId, options, callback) {
  var client = this.client;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  var jobListFromJobScheduleOptions = (options && options.jobListFromJobScheduleOptions !== undefined) ? options.jobListFromJobScheduleOptions : undefined;
  // Validate
  try {
    if (jobScheduleId === null || jobScheduleId === undefined || typeof jobScheduleId.valueOf() !== 'string') {
      throw new Error('jobScheduleId cannot be null or undefined and it must be of type string.');
    }
    if (this.client.apiVersion === null || this.client.apiVersion === undefined || typeof this.client.apiVersion.valueOf() !== 'string') {
      throw new Error('this.client.apiVersion cannot be null or undefined and it must be of type string.');
    }
    if (this.client.acceptLanguage !== null && this.client.acceptLanguage !== undefined && typeof this.client.acceptLanguage.valueOf() !== 'string') {
      throw new Error('this.client.acceptLanguage must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  var filter;
  var select;
  var expand;
  var maxResults;
  var timeout;
  var clientRequestId;
  var returnClientRequestId;
  var ocpDate;
  try {
    if (jobListFromJobScheduleOptions !== null && jobListFromJobScheduleOptions !== undefined)
    {
      filter = jobListFromJobScheduleOptions.filter;
      if (filter !== null && filter !== undefined && typeof filter.valueOf() !== 'string') {
        throw new Error('filter must be of type string.');
      }
    }
    if (jobListFromJobScheduleOptions !== null && jobListFromJobScheduleOptions !== undefined)
    {
      select = jobListFromJobScheduleOptions.select;
      if (select !== null && select !== undefined && typeof select.valueOf() !== 'string') {
        throw new Error('select must be of type string.');
      }
    }
    if (jobListFromJobScheduleOptions !== null && jobListFromJobScheduleOptions !== undefined)
    {
      expand = jobListFromJobScheduleOptions.expand;
      if (expand !== null && expand !== undefined && typeof expand.valueOf() !== 'string') {
        throw new Error('expand must be of type string.');
      }
    }
    if (jobListFromJobScheduleOptions !== null && jobListFromJobScheduleOptions !== undefined)
    {
      maxResults = jobListFromJobScheduleOptions.maxResults;
      if (maxResults !== null && maxResults !== undefined && typeof maxResults !== 'number') {
        throw new Error('maxResults must be of type number.');
      }
    }
    if (jobListFromJobScheduleOptions !== null && jobListFromJobScheduleOptions !== undefined)
    {
      timeout = jobListFromJobScheduleOptions.timeout;
      if (timeout !== null && timeout !== undefined && typeof timeout !== 'number') {
        throw new Error('timeout must be of type number.');
      }
    }
    if (jobListFromJobScheduleOptions !== null && jobListFromJobScheduleOptions !== undefined)
    {
      clientRequestId = jobListFromJobScheduleOptions.clientRequestId;
      if (clientRequestId !== null && clientRequestId !== undefined && typeof clientRequestId.valueOf() !== 'string') {
        throw new Error('clientRequestId must be of type string.');
      }
    }
    if (jobListFromJobScheduleOptions !== null && jobListFromJobScheduleOptions !== undefined)
    {
      returnClientRequestId = jobListFromJobScheduleOptions.returnClientRequestId;
      if (returnClientRequestId !== null && returnClientRequestId !== undefined && typeof returnClientRequestId !== 'boolean') {
        throw new Error('returnClientRequestId must be of type boolean.');
      }
    }
    if (jobListFromJobScheduleOptions !== null && jobListFromJobScheduleOptions !== undefined)
    {
      ocpDate = jobListFromJobScheduleOptions.ocpDate;
      if (ocpDate && !(ocpDate instanceof Date || 
          (typeof ocpDate.valueOf() === 'string' && !isNaN(Date.parse(ocpDate))))) {
            throw new Error('ocpDate must be of type date.');
          }
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  var requestUrl = this.client.baseUri +
                   '//jobschedules/{jobScheduleId}/jobs';
  requestUrl = requestUrl.replace('{jobScheduleId}', encodeURIComponent(jobScheduleId));
  var queryParameters = [];
  queryParameters.push('api-version=' + encodeURIComponent(this.client.apiVersion));
  if (filter !== null && filter !== undefined) {
    queryParameters.push('$filter=' + encodeURIComponent(filter));
  }
  if (select !== null && select !== undefined) {
    queryParameters.push('$select=' + encodeURIComponent(select));
  }
  if (expand !== null && expand !== undefined) {
    queryParameters.push('$expand=' + encodeURIComponent(expand));
  }
  if (maxResults !== null && maxResults !== undefined) {
    queryParameters.push('maxresults=' + encodeURIComponent(maxResults.toString()));
  }
  if (timeout !== null && timeout !== undefined) {
    queryParameters.push('timeout=' + encodeURIComponent(timeout.toString()));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }
  // trim all duplicate forward slashes in the url
  var regex = /([^:]\/)\/+/gi;
  requestUrl = requestUrl.replace(regex, '$1');

  // Create HTTP transport objects
  var httpRequest = new WebResource();
  httpRequest.method = 'GET';
  httpRequest.headers = {};
  httpRequest.url = requestUrl;
  // Set Headers
  if (this.client.generateClientRequestId) {
      httpRequest.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
  }
  if (this.client.acceptLanguage !== undefined && this.client.acceptLanguage !== null) {
    httpRequest.headers['accept-language'] = this.client.acceptLanguage;
  }
  if (clientRequestId !== undefined && clientRequestId !== null) {
    httpRequest.headers['client-request-id'] = clientRequestId;
  }
  if (returnClientRequestId !== undefined && returnClientRequestId !== null) {
    httpRequest.headers['return-client-request-id'] = returnClientRequestId.toString();
  }
  if (ocpDate !== undefined && ocpDate !== null) {
    httpRequest.headers['ocp-date'] = ocpDate.toUTCString();
  }
  if(options) {
    for(var headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.headers['Content-Type'] = 'application/json; odata=minimalmetadata; charset=utf-8';
  httpRequest.body = null;
  // Send Request
  return client.pipeline(httpRequest, function (err, response, responseBody) {
    if (err) {
      return callback(err);
    }
    var statusCode = response.statusCode;
    if (statusCode !== 200) {
      var error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      var parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          if (parsedErrorResponse.error) parsedErrorResponse = parsedErrorResponse.error;
          if (parsedErrorResponse.code) error.code = parsedErrorResponse.code;
          if (parsedErrorResponse.message) error.message = parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          var resultMapper = new client.models['BatchError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = util.format('Error "%s" occurred in deserializing the responseBody ' + 
                         '- "%s" for the default response.', defaultError.message, responseBody);
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    var result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      var parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          var resultMapper = new client.models['CloudJobListResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        var deserializationError = new Error(util.format('Error "%s" occurred in deserializing the responseBody - "%s"', error, responseBody));
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
};

/**
 * Lists the execution status of the Job Preparation and Job Release task for
 * the specified job across the compute nodes where the job has run.
 *
 * @param {string} jobId The id of the job.
 * 
 * @param {object} [options] Optional Parameters.
 * 
 * @param {object} [options.jobListPreparationAndReleaseTaskStatusOptions]
 * Additional parameters for the operation
 * 
 * @param {string}
 * [options.jobListPreparationAndReleaseTaskStatusOptions.filter] An OData
 * $filter clause.
 * 
 * @param {string}
 * [options.jobListPreparationAndReleaseTaskStatusOptions.select] An OData
 * $select clause.
 * 
 * @param {number}
 * [options.jobListPreparationAndReleaseTaskStatusOptions.maxResults] The
 * maximum number of items to return in the response.
 * 
 * @param {number}
 * [options.jobListPreparationAndReleaseTaskStatusOptions.timeout] The
 * maximum time that the server can spend processing the request, in seconds.
 * The default is 30 seconds.
 * 
 * @param {string}
 * [options.jobListPreparationAndReleaseTaskStatusOptions.clientRequestId]
 * The caller-generated request identity, in the form of a GUID with no
 * decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
 * 
 * @param {boolean}
 * [options.jobListPreparationAndReleaseTaskStatusOptions.returnClientRequestId]
 * Whether the server should return the client-request-id identifier in the
 * response.
 * 
 * @param {date}
 * [options.jobListPreparationAndReleaseTaskStatusOptions.ocpDate] The time
 * the request was issued. If not specified, this header will be
 * automatically populated with the current system clock time.
 * 
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 * 
 * @param {function} callback
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object.
 *                      See {@link
 *                      CloudJobListPreparationAndReleaseTaskStatusResult}
 *                      for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
Job.prototype.listPreparationAndReleaseTaskStatus = function (jobId, options, callback) {
  var client = this.client;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  var jobListPreparationAndReleaseTaskStatusOptions = (options && options.jobListPreparationAndReleaseTaskStatusOptions !== undefined) ? options.jobListPreparationAndReleaseTaskStatusOptions : undefined;
  // Validate
  try {
    if (jobId === null || jobId === undefined || typeof jobId.valueOf() !== 'string') {
      throw new Error('jobId cannot be null or undefined and it must be of type string.');
    }
    if (this.client.apiVersion === null || this.client.apiVersion === undefined || typeof this.client.apiVersion.valueOf() !== 'string') {
      throw new Error('this.client.apiVersion cannot be null or undefined and it must be of type string.');
    }
    if (this.client.acceptLanguage !== null && this.client.acceptLanguage !== undefined && typeof this.client.acceptLanguage.valueOf() !== 'string') {
      throw new Error('this.client.acceptLanguage must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  var filter;
  var select;
  var maxResults;
  var timeout;
  var clientRequestId;
  var returnClientRequestId;
  var ocpDate;
  try {
    if (jobListPreparationAndReleaseTaskStatusOptions !== null && jobListPreparationAndReleaseTaskStatusOptions !== undefined)
    {
      filter = jobListPreparationAndReleaseTaskStatusOptions.filter;
      if (filter !== null && filter !== undefined && typeof filter.valueOf() !== 'string') {
        throw new Error('filter must be of type string.');
      }
    }
    if (jobListPreparationAndReleaseTaskStatusOptions !== null && jobListPreparationAndReleaseTaskStatusOptions !== undefined)
    {
      select = jobListPreparationAndReleaseTaskStatusOptions.select;
      if (select !== null && select !== undefined && typeof select.valueOf() !== 'string') {
        throw new Error('select must be of type string.');
      }
    }
    if (jobListPreparationAndReleaseTaskStatusOptions !== null && jobListPreparationAndReleaseTaskStatusOptions !== undefined)
    {
      maxResults = jobListPreparationAndReleaseTaskStatusOptions.maxResults;
      if (maxResults !== null && maxResults !== undefined && typeof maxResults !== 'number') {
        throw new Error('maxResults must be of type number.');
      }
    }
    if (jobListPreparationAndReleaseTaskStatusOptions !== null && jobListPreparationAndReleaseTaskStatusOptions !== undefined)
    {
      timeout = jobListPreparationAndReleaseTaskStatusOptions.timeout;
      if (timeout !== null && timeout !== undefined && typeof timeout !== 'number') {
        throw new Error('timeout must be of type number.');
      }
    }
    if (jobListPreparationAndReleaseTaskStatusOptions !== null && jobListPreparationAndReleaseTaskStatusOptions !== undefined)
    {
      clientRequestId = jobListPreparationAndReleaseTaskStatusOptions.clientRequestId;
      if (clientRequestId !== null && clientRequestId !== undefined && typeof clientRequestId.valueOf() !== 'string') {
        throw new Error('clientRequestId must be of type string.');
      }
    }
    if (jobListPreparationAndReleaseTaskStatusOptions !== null && jobListPreparationAndReleaseTaskStatusOptions !== undefined)
    {
      returnClientRequestId = jobListPreparationAndReleaseTaskStatusOptions.returnClientRequestId;
      if (returnClientRequestId !== null && returnClientRequestId !== undefined && typeof returnClientRequestId !== 'boolean') {
        throw new Error('returnClientRequestId must be of type boolean.');
      }
    }
    if (jobListPreparationAndReleaseTaskStatusOptions !== null && jobListPreparationAndReleaseTaskStatusOptions !== undefined)
    {
      ocpDate = jobListPreparationAndReleaseTaskStatusOptions.ocpDate;
      if (ocpDate && !(ocpDate instanceof Date || 
          (typeof ocpDate.valueOf() === 'string' && !isNaN(Date.parse(ocpDate))))) {
            throw new Error('ocpDate must be of type date.');
          }
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  var requestUrl = this.client.baseUri +
                   '//jobs/{jobId}/jobpreparationandreleasetaskstatus';
  requestUrl = requestUrl.replace('{jobId}', encodeURIComponent(jobId));
  var queryParameters = [];
  queryParameters.push('api-version=' + encodeURIComponent(this.client.apiVersion));
  if (filter !== null && filter !== undefined) {
    queryParameters.push('$filter=' + encodeURIComponent(filter));
  }
  if (select !== null && select !== undefined) {
    queryParameters.push('$select=' + encodeURIComponent(select));
  }
  if (maxResults !== null && maxResults !== undefined) {
    queryParameters.push('maxresults=' + encodeURIComponent(maxResults.toString()));
  }
  if (timeout !== null && timeout !== undefined) {
    queryParameters.push('timeout=' + encodeURIComponent(timeout.toString()));
  }
  if (queryParameters.length > 0) {
    requestUrl += '?' + queryParameters.join('&');
  }
  // trim all duplicate forward slashes in the url
  var regex = /([^:]\/)\/+/gi;
  requestUrl = requestUrl.replace(regex, '$1');

  // Create HTTP transport objects
  var httpRequest = new WebResource();
  httpRequest.method = 'GET';
  httpRequest.headers = {};
  httpRequest.url = requestUrl;
  // Set Headers
  if (this.client.generateClientRequestId) {
      httpRequest.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
  }
  if (this.client.acceptLanguage !== undefined && this.client.acceptLanguage !== null) {
    httpRequest.headers['accept-language'] = this.client.acceptLanguage;
  }
  if (clientRequestId !== undefined && clientRequestId !== null) {
    httpRequest.headers['client-request-id'] = clientRequestId;
  }
  if (returnClientRequestId !== undefined && returnClientRequestId !== null) {
    httpRequest.headers['return-client-request-id'] = returnClientRequestId.toString();
  }
  if (ocpDate !== undefined && ocpDate !== null) {
    httpRequest.headers['ocp-date'] = ocpDate.toUTCString();
  }
  if(options) {
    for(var headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.headers['Content-Type'] = 'application/json; odata=minimalmetadata; charset=utf-8';
  httpRequest.body = null;
  // Send Request
  return client.pipeline(httpRequest, function (err, response, responseBody) {
    if (err) {
      return callback(err);
    }
    var statusCode = response.statusCode;
    if (statusCode !== 200) {
      var error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      var parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          if (parsedErrorResponse.error) parsedErrorResponse = parsedErrorResponse.error;
          if (parsedErrorResponse.code) error.code = parsedErrorResponse.code;
          if (parsedErrorResponse.message) error.message = parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          var resultMapper = new client.models['BatchError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = util.format('Error "%s" occurred in deserializing the responseBody ' + 
                         '- "%s" for the default response.', defaultError.message, responseBody);
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    var result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      var parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          var resultMapper = new client.models['CloudJobListPreparationAndReleaseTaskStatusResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        var deserializationError = new Error(util.format('Error "%s" occurred in deserializing the responseBody - "%s"', error, responseBody));
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
};

/**
 * Lists all of the jobs in the specified account.
 *
 * @param {string} nextPageLink The NextLink from the previous successful call
 * to List operation.
 * 
 * @param {object} [options] Optional Parameters.
 * 
 * @param {object} [options.jobListNextOptions] Additional parameters for the
 * operation
 * 
 * @param {string} [options.jobListNextOptions.clientRequestId] The
 * caller-generated request identity, in the form of a GUID with no
 * decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
 * 
 * @param {boolean} [options.jobListNextOptions.returnClientRequestId] Whether
 * the server should return the client-request-id identifier in the response.
 * 
 * @param {date} [options.jobListNextOptions.ocpDate] The time the request was
 * issued. If not specified, this header will be automatically populated with
 * the current system clock time.
 * 
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 * 
 * @param {function} callback
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object.
 *                      See {@link CloudJobListResult} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
Job.prototype.listNext = function (nextPageLink, options, callback) {
  var client = this.client;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  var jobListNextOptions = (options && options.jobListNextOptions !== undefined) ? options.jobListNextOptions : undefined;
  // Validate
  try {
    if (nextPageLink === null || nextPageLink === undefined || typeof nextPageLink.valueOf() !== 'string') {
      throw new Error('nextPageLink cannot be null or undefined and it must be of type string.');
    }
    if (this.client.acceptLanguage !== null && this.client.acceptLanguage !== undefined && typeof this.client.acceptLanguage.valueOf() !== 'string') {
      throw new Error('this.client.acceptLanguage must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  var clientRequestId;
  var returnClientRequestId;
  var ocpDate;
  try {
    if (jobListNextOptions !== null && jobListNextOptions !== undefined)
    {
      clientRequestId = jobListNextOptions.clientRequestId;
      if (clientRequestId !== null && clientRequestId !== undefined && typeof clientRequestId.valueOf() !== 'string') {
        throw new Error('clientRequestId must be of type string.');
      }
    }
    if (jobListNextOptions !== null && jobListNextOptions !== undefined)
    {
      returnClientRequestId = jobListNextOptions.returnClientRequestId;
      if (returnClientRequestId !== null && returnClientRequestId !== undefined && typeof returnClientRequestId !== 'boolean') {
        throw new Error('returnClientRequestId must be of type boolean.');
      }
    }
    if (jobListNextOptions !== null && jobListNextOptions !== undefined)
    {
      ocpDate = jobListNextOptions.ocpDate;
      if (ocpDate && !(ocpDate instanceof Date || 
          (typeof ocpDate.valueOf() === 'string' && !isNaN(Date.parse(ocpDate))))) {
            throw new Error('ocpDate must be of type date.');
          }
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  var requestUrl = '{nextLink}';
  requestUrl = requestUrl.replace('{nextLink}', nextPageLink);
  // trim all duplicate forward slashes in the url
  var regex = /([^:]\/)\/+/gi;
  requestUrl = requestUrl.replace(regex, '$1');

  // Create HTTP transport objects
  var httpRequest = new WebResource();
  httpRequest.method = 'GET';
  httpRequest.headers = {};
  httpRequest.url = requestUrl;
  // Set Headers
  if (this.client.generateClientRequestId) {
      httpRequest.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
  }
  if (this.client.acceptLanguage !== undefined && this.client.acceptLanguage !== null) {
    httpRequest.headers['accept-language'] = this.client.acceptLanguage;
  }
  if (clientRequestId !== undefined && clientRequestId !== null) {
    httpRequest.headers['client-request-id'] = clientRequestId;
  }
  if (returnClientRequestId !== undefined && returnClientRequestId !== null) {
    httpRequest.headers['return-client-request-id'] = returnClientRequestId.toString();
  }
  if (ocpDate !== undefined && ocpDate !== null) {
    httpRequest.headers['ocp-date'] = ocpDate.toUTCString();
  }
  if(options) {
    for(var headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.headers['Content-Type'] = 'application/json; odata=minimalmetadata; charset=utf-8';
  httpRequest.body = null;
  // Send Request
  return client.pipeline(httpRequest, function (err, response, responseBody) {
    if (err) {
      return callback(err);
    }
    var statusCode = response.statusCode;
    if (statusCode !== 200) {
      var error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      var parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          if (parsedErrorResponse.error) parsedErrorResponse = parsedErrorResponse.error;
          if (parsedErrorResponse.code) error.code = parsedErrorResponse.code;
          if (parsedErrorResponse.message) error.message = parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          var resultMapper = new client.models['BatchError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = util.format('Error "%s" occurred in deserializing the responseBody ' + 
                         '- "%s" for the default response.', defaultError.message, responseBody);
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    var result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      var parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          var resultMapper = new client.models['CloudJobListResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        var deserializationError = new Error(util.format('Error "%s" occurred in deserializing the responseBody - "%s"', error, responseBody));
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
};

/**
 * Lists the jobs that have been created under the specified job schedule.
 *
 * @param {string} nextPageLink The NextLink from the previous successful call
 * to List operation.
 * 
 * @param {object} [options] Optional Parameters.
 * 
 * @param {object} [options.jobListFromJobScheduleNextOptions] Additional
 * parameters for the operation
 * 
 * @param {string} [options.jobListFromJobScheduleNextOptions.clientRequestId]
 * The caller-generated request identity, in the form of a GUID with no
 * decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
 * 
 * @param {boolean}
 * [options.jobListFromJobScheduleNextOptions.returnClientRequestId] Whether
 * the server should return the client-request-id identifier in the response.
 * 
 * @param {date} [options.jobListFromJobScheduleNextOptions.ocpDate] The time
 * the request was issued. If not specified, this header will be
 * automatically populated with the current system clock time.
 * 
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 * 
 * @param {function} callback
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object.
 *                      See {@link CloudJobListResult} for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
Job.prototype.listFromJobScheduleNext = function (nextPageLink, options, callback) {
  var client = this.client;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  var jobListFromJobScheduleNextOptions = (options && options.jobListFromJobScheduleNextOptions !== undefined) ? options.jobListFromJobScheduleNextOptions : undefined;
  // Validate
  try {
    if (nextPageLink === null || nextPageLink === undefined || typeof nextPageLink.valueOf() !== 'string') {
      throw new Error('nextPageLink cannot be null or undefined and it must be of type string.');
    }
    if (this.client.acceptLanguage !== null && this.client.acceptLanguage !== undefined && typeof this.client.acceptLanguage.valueOf() !== 'string') {
      throw new Error('this.client.acceptLanguage must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  var clientRequestId;
  var returnClientRequestId;
  var ocpDate;
  try {
    if (jobListFromJobScheduleNextOptions !== null && jobListFromJobScheduleNextOptions !== undefined)
    {
      clientRequestId = jobListFromJobScheduleNextOptions.clientRequestId;
      if (clientRequestId !== null && clientRequestId !== undefined && typeof clientRequestId.valueOf() !== 'string') {
        throw new Error('clientRequestId must be of type string.');
      }
    }
    if (jobListFromJobScheduleNextOptions !== null && jobListFromJobScheduleNextOptions !== undefined)
    {
      returnClientRequestId = jobListFromJobScheduleNextOptions.returnClientRequestId;
      if (returnClientRequestId !== null && returnClientRequestId !== undefined && typeof returnClientRequestId !== 'boolean') {
        throw new Error('returnClientRequestId must be of type boolean.');
      }
    }
    if (jobListFromJobScheduleNextOptions !== null && jobListFromJobScheduleNextOptions !== undefined)
    {
      ocpDate = jobListFromJobScheduleNextOptions.ocpDate;
      if (ocpDate && !(ocpDate instanceof Date || 
          (typeof ocpDate.valueOf() === 'string' && !isNaN(Date.parse(ocpDate))))) {
            throw new Error('ocpDate must be of type date.');
          }
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  var requestUrl = '{nextLink}';
  requestUrl = requestUrl.replace('{nextLink}', nextPageLink);
  // trim all duplicate forward slashes in the url
  var regex = /([^:]\/)\/+/gi;
  requestUrl = requestUrl.replace(regex, '$1');

  // Create HTTP transport objects
  var httpRequest = new WebResource();
  httpRequest.method = 'GET';
  httpRequest.headers = {};
  httpRequest.url = requestUrl;
  // Set Headers
  if (this.client.generateClientRequestId) {
      httpRequest.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
  }
  if (this.client.acceptLanguage !== undefined && this.client.acceptLanguage !== null) {
    httpRequest.headers['accept-language'] = this.client.acceptLanguage;
  }
  if (clientRequestId !== undefined && clientRequestId !== null) {
    httpRequest.headers['client-request-id'] = clientRequestId;
  }
  if (returnClientRequestId !== undefined && returnClientRequestId !== null) {
    httpRequest.headers['return-client-request-id'] = returnClientRequestId.toString();
  }
  if (ocpDate !== undefined && ocpDate !== null) {
    httpRequest.headers['ocp-date'] = ocpDate.toUTCString();
  }
  if(options) {
    for(var headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.headers['Content-Type'] = 'application/json; odata=minimalmetadata; charset=utf-8';
  httpRequest.body = null;
  // Send Request
  return client.pipeline(httpRequest, function (err, response, responseBody) {
    if (err) {
      return callback(err);
    }
    var statusCode = response.statusCode;
    if (statusCode !== 200) {
      var error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      var parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          if (parsedErrorResponse.error) parsedErrorResponse = parsedErrorResponse.error;
          if (parsedErrorResponse.code) error.code = parsedErrorResponse.code;
          if (parsedErrorResponse.message) error.message = parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          var resultMapper = new client.models['BatchError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = util.format('Error "%s" occurred in deserializing the responseBody ' + 
                         '- "%s" for the default response.', defaultError.message, responseBody);
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    var result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      var parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          var resultMapper = new client.models['CloudJobListResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        var deserializationError = new Error(util.format('Error "%s" occurred in deserializing the responseBody - "%s"', error, responseBody));
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
};

/**
 * Lists the execution status of the Job Preparation and Job Release task for
 * the specified job across the compute nodes where the job has run.
 *
 * @param {string} nextPageLink The NextLink from the previous successful call
 * to List operation.
 * 
 * @param {object} [options] Optional Parameters.
 * 
 * @param {object} [options.jobListPreparationAndReleaseTaskStatusNextOptions]
 * Additional parameters for the operation
 * 
 * @param {string}
 * [options.jobListPreparationAndReleaseTaskStatusNextOptions.clientRequestId]
 * The caller-generated request identity, in the form of a GUID with no
 * decoration such as curly braces, e.g. 9C4D50EE-2D56-4CD3-8152-34347DC9F2B0.
 * 
 * @param {boolean}
 * [options.jobListPreparationAndReleaseTaskStatusNextOptions.returnClientRequestId]
 * Whether the server should return the client-request-id identifier in the
 * response.
 * 
 * @param {date}
 * [options.jobListPreparationAndReleaseTaskStatusNextOptions.ocpDate] The
 * time the request was issued. If not specified, this header will be
 * automatically populated with the current system clock time.
 * 
 * @param {object} [options.customHeaders] Headers that will be added to the
 * request
 * 
 * @param {function} callback
 *
 * @returns {function} callback(err, result, request, response)
 *
 *                      {Error}  err        - The Error object if an error occurred, null otherwise.
 *
 *                      {object} [result]   - The deserialized result object.
 *                      See {@link
 *                      CloudJobListPreparationAndReleaseTaskStatusResult}
 *                      for more information.
 *
 *                      {object} [request]  - The HTTP Request object if an error did not occur.
 *
 *                      {stream} [response] - The HTTP Response stream if an error did not occur.
 */
Job.prototype.listPreparationAndReleaseTaskStatusNext = function (nextPageLink, options, callback) {
  var client = this.client;
  if(!callback && typeof options === 'function') {
    callback = options;
    options = null;
  }
  if (!callback) {
    throw new Error('callback cannot be null.');
  }
  var jobListPreparationAndReleaseTaskStatusNextOptions = (options && options.jobListPreparationAndReleaseTaskStatusNextOptions !== undefined) ? options.jobListPreparationAndReleaseTaskStatusNextOptions : undefined;
  // Validate
  try {
    if (nextPageLink === null || nextPageLink === undefined || typeof nextPageLink.valueOf() !== 'string') {
      throw new Error('nextPageLink cannot be null or undefined and it must be of type string.');
    }
    if (this.client.acceptLanguage !== null && this.client.acceptLanguage !== undefined && typeof this.client.acceptLanguage.valueOf() !== 'string') {
      throw new Error('this.client.acceptLanguage must be of type string.');
    }
  } catch (error) {
    return callback(error);
  }
  var clientRequestId;
  var returnClientRequestId;
  var ocpDate;
  try {
    if (jobListPreparationAndReleaseTaskStatusNextOptions !== null && jobListPreparationAndReleaseTaskStatusNextOptions !== undefined)
    {
      clientRequestId = jobListPreparationAndReleaseTaskStatusNextOptions.clientRequestId;
      if (clientRequestId !== null && clientRequestId !== undefined && typeof clientRequestId.valueOf() !== 'string') {
        throw new Error('clientRequestId must be of type string.');
      }
    }
    if (jobListPreparationAndReleaseTaskStatusNextOptions !== null && jobListPreparationAndReleaseTaskStatusNextOptions !== undefined)
    {
      returnClientRequestId = jobListPreparationAndReleaseTaskStatusNextOptions.returnClientRequestId;
      if (returnClientRequestId !== null && returnClientRequestId !== undefined && typeof returnClientRequestId !== 'boolean') {
        throw new Error('returnClientRequestId must be of type boolean.');
      }
    }
    if (jobListPreparationAndReleaseTaskStatusNextOptions !== null && jobListPreparationAndReleaseTaskStatusNextOptions !== undefined)
    {
      ocpDate = jobListPreparationAndReleaseTaskStatusNextOptions.ocpDate;
      if (ocpDate && !(ocpDate instanceof Date || 
          (typeof ocpDate.valueOf() === 'string' && !isNaN(Date.parse(ocpDate))))) {
            throw new Error('ocpDate must be of type date.');
          }
    }
  } catch (error) {
    return callback(error);
  }

  // Construct URL
  var requestUrl = '{nextLink}';
  requestUrl = requestUrl.replace('{nextLink}', nextPageLink);
  // trim all duplicate forward slashes in the url
  var regex = /([^:]\/)\/+/gi;
  requestUrl = requestUrl.replace(regex, '$1');

  // Create HTTP transport objects
  var httpRequest = new WebResource();
  httpRequest.method = 'GET';
  httpRequest.headers = {};
  httpRequest.url = requestUrl;
  // Set Headers
  if (this.client.generateClientRequestId) {
      httpRequest.headers['x-ms-client-request-id'] = msRestAzure.generateUuid();
  }
  if (this.client.acceptLanguage !== undefined && this.client.acceptLanguage !== null) {
    httpRequest.headers['accept-language'] = this.client.acceptLanguage;
  }
  if (clientRequestId !== undefined && clientRequestId !== null) {
    httpRequest.headers['client-request-id'] = clientRequestId;
  }
  if (returnClientRequestId !== undefined && returnClientRequestId !== null) {
    httpRequest.headers['return-client-request-id'] = returnClientRequestId.toString();
  }
  if (ocpDate !== undefined && ocpDate !== null) {
    httpRequest.headers['ocp-date'] = ocpDate.toUTCString();
  }
  if(options) {
    for(var headerName in options['customHeaders']) {
      if (options['customHeaders'].hasOwnProperty(headerName)) {
        httpRequest.headers[headerName] = options['customHeaders'][headerName];
      }
    }
  }
  httpRequest.headers['Content-Type'] = 'application/json; odata=minimalmetadata; charset=utf-8';
  httpRequest.body = null;
  // Send Request
  return client.pipeline(httpRequest, function (err, response, responseBody) {
    if (err) {
      return callback(err);
    }
    var statusCode = response.statusCode;
    if (statusCode !== 200) {
      var error = new Error(responseBody);
      error.statusCode = response.statusCode;
      error.request = msRest.stripRequest(httpRequest);
      error.response = msRest.stripResponse(response);
      if (responseBody === '') responseBody = null;
      var parsedErrorResponse;
      try {
        parsedErrorResponse = JSON.parse(responseBody);
        if (parsedErrorResponse) {
          if (parsedErrorResponse.error) parsedErrorResponse = parsedErrorResponse.error;
          if (parsedErrorResponse.code) error.code = parsedErrorResponse.code;
          if (parsedErrorResponse.message) error.message = parsedErrorResponse.message;
        }
        if (parsedErrorResponse !== null && parsedErrorResponse !== undefined) {
          var resultMapper = new client.models['BatchError']().mapper();
          error.body = client.deserialize(resultMapper, parsedErrorResponse, 'error.body');
        }
      } catch (defaultError) {
        error.message = util.format('Error "%s" occurred in deserializing the responseBody ' + 
                         '- "%s" for the default response.', defaultError.message, responseBody);
        return callback(error);
      }
      return callback(error);
    }
    // Create Result
    var result = null;
    if (responseBody === '') responseBody = null;
    // Deserialize Response
    if (statusCode === 200) {
      var parsedResponse = null;
      try {
        parsedResponse = JSON.parse(responseBody);
        result = JSON.parse(responseBody);
        if (parsedResponse !== null && parsedResponse !== undefined) {
          var resultMapper = new client.models['CloudJobListPreparationAndReleaseTaskStatusResult']().mapper();
          result = client.deserialize(resultMapper, parsedResponse, 'result');
        }
      } catch (error) {
        var deserializationError = new Error(util.format('Error "%s" occurred in deserializing the responseBody - "%s"', error, responseBody));
        deserializationError.request = msRest.stripRequest(httpRequest);
        deserializationError.response = msRest.stripResponse(response);
        return callback(deserializationError);
      }
    }

    return callback(null, result, httpRequest, response);
  });
};


module.exports = Job;
