/* jshint latedef:false */
/* jshint forin:false */
/* jshint noempty:false */

// 
// Copyright (c) Microsoft and contributors.  All rights reserved.
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//   http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// 
// See the License for the specific language governing permissions and
// limitations under the License.
// 

// Warning: This code was generated by a tool.
// 
// Changes to this file may cause incorrect behavior and will be lost if the
// code is regenerated.

'use strict';

var util = require('util');
var azureCommon = require('azure-common');
var xml = azureCommon.xml2js;
var js2xml = azureCommon.js2xml;
var Service = azureCommon.Service;
var WebResource = azureCommon.WebResource;

var StorageManagementClient = ( /** @lends StorageManagementClient */ function() {
  /**
   * @class
   * The Service Management API provides programmatic access to much of the
   * functionality available through the Management Portal. The Service
   * Management API is a REST API. All API operations are performed over SSL
   * and are mutually authenticated using X.509 v3 certificates.  (see
   * http://msdn.microsoft.com/en-us/library/windowsazure/ee460799.aspx for
   * more information)
   * Initializes a new instance of the StorageManagementClient class.
   * @constructor
   * 
   * @param {SubscriptionCloudCredentials} credentials Gets subscription
   * credentials which uniquely identify Microsoft Azure subscription. The
   * subscription ID forms part of the URI for every service call.
   * 
   * @param {string} [credentials.subscriptionId]
   * 
   * @param {string} [baseUri] Gets the URI used as the base for all cloud
   * service requests.
   * 
   * @param {Array} filters
   */
  function StorageManagementClient(credentials, baseUri, filters) {
    if (credentials === null || credentials === undefined) {
      throw new Error('credentials cannot be null.');
    }
    
    StorageManagementClient['super_'].call(this, credentials, filters);
    
    this.credentials = credentials;
    this.baseUri = baseUri;
    if (this.baseUri === null || this.baseUri === undefined) {
      this.baseUri = 'https://management.core.windows.net';
    }
    if (this.apiVersion === null || this.apiVersion === undefined) {
      this.apiVersion = '2016-03-01';
    }
    if (this.longRunningOperationInitialTimeout === null || this.longRunningOperationInitialTimeout === undefined) {
      this.longRunningOperationInitialTimeout = -1;
    }
    if (this.longRunningOperationRetryTimeout === null || this.longRunningOperationRetryTimeout === undefined) {
      this.longRunningOperationRetryTimeout = -1;
    }
    /**
     * Provides an instance of the
     * [StorageAccountOperations](-StorageAccountOperations.html) object.
     * @type {object}
     */
    this.storageAccounts = new StorageAccountOperations(this);
  }
  
  util.inherits(StorageManagementClient, Service);
  
  /**
   * The Get Operation Status operation returns the status of the specified
   * operation. After calling an asynchronous operation, you can call Get
   * Operation Status to determine whether the operation has succeeded,
   * failed, or is still in progress.  (see
   * http://msdn.microsoft.com/en-us/library/windowsazure/ee460783.aspx for
   * more information)
   * 
   * @param {string} requestId The request ID for the request you wish to
   * track. The request ID is returned in the x-ms-request-id response header
   * for every request.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageManagementClient.prototype.getOperationStatus = function(requestId, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    // Validate
    if (requestId === null || requestId === undefined) {
      return callback(new Error('requestId cannot be null.'));
    }
    
    // Tracing
    
    // Construct URL
    var url2 = '';
    url2 = url2 + '/';
    if (this.credentials.subscriptionId !== null && this.credentials.subscriptionId !== undefined) {
      url2 = url2 + encodeURIComponent(this.credentials.subscriptionId);
    }
    url2 = url2 + '/operations/';
    url2 = url2 + encodeURIComponent(requestId);
    var baseUrl = this.baseUri;
    // Trim '/' character from the end of baseUrl and beginning of url.
    if (baseUrl[baseUrl.length - 1] === '/') {
      baseUrl = baseUrl.substring(0, (baseUrl.length - 1) + 0);
    }
    if (url2[0] === '/') {
      url2 = url2.substring(1);
    }
    url2 = baseUrl + '/' + url2;
    url2 = url2.replace(' ', '%20');
    
    // Create HTTP transport objects
    var httpRequest = new WebResource();
    httpRequest.method = 'GET';
    httpRequest.headers = {};
    httpRequest.url = url2;
    
    // Set Headers
    httpRequest.headers['x-ms-version'] = '2016-03-01';
    
    // Send Request
    return this.pipeline(httpRequest, function (err, response, body) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var statusCode = response.statusCode;
      if (statusCode !== 200) {
        var error = new Error(body);
        error.statusCode = response.statusCode;
        return callback(error);
      }
      
      // Create Result
      var result = null;
      // Deserialize Response
      if (statusCode === 200) {
        var responseContent = body;
        result = {};
        var options = {};
        options.trim = false;
        options.strict = false;
        xml.parseString(responseContent, options, function (err2, responseDoc) {
          if (err2 !== null && err2 !== undefined) {
            return callback(err2);
          }
          
          var operationElement = js2xml.getElement(responseDoc, responseDoc, 'OPERATION', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
          if (operationElement !== null && operationElement !== undefined) {
            var idElement = js2xml.getElement(responseDoc, operationElement, 'ID', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
            if (idElement !== null && idElement !== undefined) {
              var idInstance = idElement;
              result.id = idInstance;
            }
            
            var statusElement = js2xml.getElement(responseDoc, operationElement, 'STATUS', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
            if (statusElement !== null && statusElement !== undefined && statusElement.length !== 0) {
              var statusInstance = statusElement;
              result.status = statusInstance;
            }
            
            var httpStatusCodeElement = js2xml.getElement(responseDoc, operationElement, 'HTTPSTATUSCODE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
            if (httpStatusCodeElement !== null && httpStatusCodeElement !== undefined && httpStatusCodeElement.length !== 0) {
              var httpStatusCodeInstance = httpStatusCodeElement;
              result.httpStatusCode = httpStatusCodeInstance;
            }
            
            var errorElement = js2xml.getElement(responseDoc, operationElement, 'ERROR', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
            if (errorElement !== null && errorElement !== undefined) {
              var errorInstance = {};
              result.error = errorInstance;
              
              var codeElement = js2xml.getElement(responseDoc, errorElement, 'CODE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (codeElement !== null && codeElement !== undefined) {
                var codeInstance = codeElement;
                errorInstance.code = codeInstance;
              }
              
              var messageElement = js2xml.getElement(responseDoc, errorElement, 'MESSAGE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (messageElement !== null && messageElement !== undefined) {
                var messageInstance = messageElement;
                errorInstance.message = messageInstance;
              }
            }
          }
          
        });
      }
      result.statusCode = statusCode;
      result.requestId = response.headers['x-ms-request-id'];
      
      return callback(null, result);
    });
  };
  
  return StorageManagementClient;
})();
exports.StorageManagementClient = StorageManagementClient;

var StorageAccountOperations = ( /** @lends StorageAccountOperations */ function() {
  /**
   * @class
   * The Service Management API includes operations for managing the storage
   * accounts beneath your subscription.  (see
   * http://msdn.microsoft.com/en-us/library/windowsazure/ee460790.aspx for
   * more information)
   * __NOTE__: An instance of this class is automatically created for an
   * instance of the [StorageManagementClient] {@link
   * StorageManagementClient~StorageManagementClient}.
   * See [storageAccounts] {@link
   * StorageManagementClient~StorageManagementClient#storageAccounts}.
   * Initializes a new instance of the StorageAccountOperations class.
   * @constructor
   * 
   * @param {StorageManagementClient} client Reference to the service client.
   */
  function StorageAccountOperations(client) {
    this.client = client;
  }
  
  /**
   * Abort storage account migration api validates and aborts the given storage
   * account for IaaS Classic to ARM migration.
   * 
   * @param {string} storageAccountName Name of storage account to be migrated.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.abortMigration = function(storageAccountName, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    var client2 = this.client;
    
    return client2.storageAccounts.beginAbortMigration(storageAccountName, function (err, result) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var delayInSeconds = 30;
      if (client2.longRunningOperationInitialTimeout >= 0) {
        delayInSeconds = client2.longRunningOperationInitialTimeout;
      }
      
      var pollOperation = function () {
        setTimeout(function () {
          return client2.getOperationStatus(result.requestId, function (err2, result2) {
            if (err2 !== null && err2 !== undefined) {
              return callback(err2);
            } else {
              if (result2.status !== 'InProgress') {
                if (result2.status !== 'Succeeded') {
                  if (result2.error !== null && result2.error !== undefined) {
                    var ex = new Error(result2.error.code + ' : ' + result2.error.message);
                    ex.error = new Error();
                    ex.error.code = result2.error.code;
                    ex.error.message = result2.error.message;
                    return callback(ex);
                  } else {
                    var ex = new Error('');
                    return callback(ex);
                  }
                }
                
                return callback(null, result2);
              } else {
                delayInSeconds = 30;
                if (client2.longRunningOperationRetryTimeout >= 0) {
                  delayInSeconds = client2.longRunningOperationRetryTimeout;
                }
                pollOperation();
              }
            }
          });
        }, delayInSeconds * 1000);
      };
      
      pollOperation();
    });
  };
  
  /**
   * Abort storage account migration api validates and aborts the given storage
   * account for IaaS Classic to ARM migration.
   * 
   * @param {string} storageAccountName Name of storage account to be migrated.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.beginAbortMigration = function(storageAccountName, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    // Validate
    if (storageAccountName === null || storageAccountName === undefined) {
      return callback(new Error('storageAccountName cannot be null.'));
    }
    
    // Tracing
    
    // Construct URL
    var url2 = '';
    url2 = url2 + '/';
    if (this.client.credentials.subscriptionId !== null && this.client.credentials.subscriptionId !== undefined) {
      url2 = url2 + encodeURIComponent(this.client.credentials.subscriptionId);
    }
    url2 = url2 + '/services/storageservices/';
    url2 = url2 + encodeURIComponent(storageAccountName);
    url2 = url2 + '/migration';
    var queryParameters = [];
    queryParameters.push('comp=abort');
    if (queryParameters.length > 0) {
      url2 = url2 + '?' + queryParameters.join('&');
    }
    var baseUrl = this.client.baseUri;
    // Trim '/' character from the end of baseUrl and beginning of url.
    if (baseUrl[baseUrl.length - 1] === '/') {
      baseUrl = baseUrl.substring(0, (baseUrl.length - 1) + 0);
    }
    if (url2[0] === '/') {
      url2 = url2.substring(1);
    }
    url2 = baseUrl + '/' + url2;
    url2 = url2.replace(' ', '%20');
    
    // Create HTTP transport objects
    var httpRequest = new WebResource();
    httpRequest.method = 'POST';
    httpRequest.headers = {};
    httpRequest.url = url2;
    
    // Set Headers
    httpRequest.headers['x-ms-version'] = '2016-03-01';
    
    // Send Request
    return this.client.pipeline(httpRequest, function (err, response, body) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var statusCode = response.statusCode;
      if (statusCode !== 202) {
        var error = new Error(body);
        error.statusCode = response.statusCode;
        return callback(error);
      }
      
      // Create Result
      var result = null;
      // Deserialize Response
      result = {};
      result.statusCode = statusCode;
      result.requestId = response.headers['x-ms-request-id'];
      
      return callback(null, result);
    });
  };
  
  /**
   * Commit storage account migration api validates and commits the given
   * storage account for IaaS Classic to ARM migration.
   * 
   * @param {string} storageAccountName Name of storage account to be migrated.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.beginCommitMigration = function(storageAccountName, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    // Validate
    if (storageAccountName === null || storageAccountName === undefined) {
      return callback(new Error('storageAccountName cannot be null.'));
    }
    
    // Tracing
    
    // Construct URL
    var url2 = '';
    url2 = url2 + '/';
    if (this.client.credentials.subscriptionId !== null && this.client.credentials.subscriptionId !== undefined) {
      url2 = url2 + encodeURIComponent(this.client.credentials.subscriptionId);
    }
    url2 = url2 + '/services/storageservices/';
    url2 = url2 + encodeURIComponent(storageAccountName);
    url2 = url2 + '/migration';
    var queryParameters = [];
    queryParameters.push('comp=commit');
    if (queryParameters.length > 0) {
      url2 = url2 + '?' + queryParameters.join('&');
    }
    var baseUrl = this.client.baseUri;
    // Trim '/' character from the end of baseUrl and beginning of url.
    if (baseUrl[baseUrl.length - 1] === '/') {
      baseUrl = baseUrl.substring(0, (baseUrl.length - 1) + 0);
    }
    if (url2[0] === '/') {
      url2 = url2.substring(1);
    }
    url2 = baseUrl + '/' + url2;
    url2 = url2.replace(' ', '%20');
    
    // Create HTTP transport objects
    var httpRequest = new WebResource();
    httpRequest.method = 'POST';
    httpRequest.headers = {};
    httpRequest.url = url2;
    
    // Set Headers
    httpRequest.headers['x-ms-version'] = '2016-03-01';
    
    // Send Request
    return this.client.pipeline(httpRequest, function (err, response, body) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var statusCode = response.statusCode;
      if (statusCode !== 202) {
        var error = new Error(body);
        error.statusCode = response.statusCode;
        return callback(error);
      }
      
      // Create Result
      var result = null;
      // Deserialize Response
      result = {};
      result.statusCode = statusCode;
      result.requestId = response.headers['x-ms-request-id'];
      
      return callback(null, result);
    });
  };
  
  /**
   * The Begin Creating Storage Account operation creates a new storage account
   * in Azure.  (see
   * http://msdn.microsoft.com/en-us/library/windowsazure/hh264518.aspx for
   * more information)
   * 
   * @param {StorageAccountCreateParameters} parameters Parameters supplied to
   * the Begin Creating Storage Account operation.
   * 
   * @param {string} parameters.name A name for the storage account, unique
   * within Azure. Storage account names must be between 3 and 24 characters
   * in length, and must use numbers and lower-case letters only. This name is
   * the DNS prefix name and can be used to access blobs, queues, and tables
   * in the storage account. For example:
   * http://ServiceName.blob.core.windows.net/mycontainer/.
   * 
   * @param {string} [parameters.description] A description for the storage
   * account. The description may be up to 1024 characters in length.
   * 
   * @param {string} parameters.label A name for the storage account, specified
   * as abase64-encoded string. The name may be up to 100 characters in
   * length. The name can be used identify the storage account for your
   * tracking purposes.
   * 
   * @param {string} [parameters.affinityGroup] The name of an existing
   * affinity group in the specified subscription. Required if Location is not
   * specified. You can include either a Location or AffinityGroup element in
   * the request body, but not both. To list available affinity groups, use
   * the List Affinity Groups operation.
   * 
   * @param {string} [parameters.location] The location where the storage
   * account is created. Required if AffinityGroup is not specified. You can
   * include either a Location or AffinityGroup element in the request body,
   * but not both. To list available locations, use the List Locations
   * operation.
   * 
   * @param {object} [parameters.extendedProperties] Represents the name of an
   * extended storage account property. Each extended property must have a
   * defined name and a value. You can have a maximum of 50 extended property
   * name/value pairs. The maximum length of the Name element is 64
   * characters, only alphanumeric characters and underscores are valid in the
   * Name, and the name must start with a letter. Attempting to use other
   * characters, starting the Name with a non-letter character, or entering a
   * name that is identical to that of another extended property owned by the
   * same storage account will result in a status code 400 (Bad Request)
   * error. Each extended property value has a maximum length of 255
   * characters.
   * 
   * @param {string} [parameters.accountType] Specifies whether the account
   * supports locally-redundant storage, geo-redundant storage, zone-redundant
   * storage, or read access geo-redundant storage. Possible values
   * are:'Standard_LRS', 'Standard_ZRS', 'Standard_GRS', and 'Standard_RAGRS'.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.beginCreating = function(parameters, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    // Validate
    if (parameters === null || parameters === undefined) {
      return callback(new Error('parameters cannot be null.'));
    }
    if (parameters.description !== null && parameters.description !== undefined && parameters.description.length > 1024) {
      return callback(new Error('parameters.description is outside the valid range.'));
    }
    if (parameters.label === null || parameters.label === undefined) {
      return callback(new Error('parameters.label cannot be null.'));
    }
    if (parameters.label.length > 100) {
      return callback(new Error('parameters.label is outside the valid range.'));
    }
    if (parameters.name === null || parameters.name === undefined) {
      return callback(new Error('parameters.name cannot be null.'));
    }
    if (parameters.name.length < 3) {
      return callback(new Error('parameters.name is outside the valid range.'));
    }
    if (parameters.name.length > 24) {
      return callback(new Error('parameters.name is outside the valid range.'));
    }
    for (var loweredIndex1 = 0; loweredIndex1 < parameters.name.length; loweredIndex1 = loweredIndex1 + 1) {
      var nameChar = parameters.name[loweredIndex1];
      if (nameChar === nameChar.toLowerCase() === false && isNaN(parseInt(nameChar, 10)) === false === false) {
        return callback(new Error('parameters.name is outside the valid range.'));
      }
    }
    // TODO: Validate parameters.name is a valid DNS name.
    
    // Tracing
    
    // Construct URL
    var url2 = '';
    url2 = url2 + '/';
    if (this.client.credentials.subscriptionId !== null && this.client.credentials.subscriptionId !== undefined) {
      url2 = url2 + encodeURIComponent(this.client.credentials.subscriptionId);
    }
    url2 = url2 + '/services/storageservices';
    var baseUrl = this.client.baseUri;
    // Trim '/' character from the end of baseUrl and beginning of url.
    if (baseUrl[baseUrl.length - 1] === '/') {
      baseUrl = baseUrl.substring(0, (baseUrl.length - 1) + 0);
    }
    if (url2[0] === '/') {
      url2 = url2.substring(1);
    }
    url2 = baseUrl + '/' + url2;
    url2 = url2.replace(' ', '%20');
    
    // Create HTTP transport objects
    var httpRequest = new WebResource();
    httpRequest.method = 'POST';
    httpRequest.headers = {};
    httpRequest.url = url2;
    
    // Set Headers
    httpRequest.headers['Content-Type'] = 'application/xml';
    httpRequest.headers['x-ms-version'] = '2016-03-01';
    
    // Serialize Request
    var requestContent = null;
    var requestDoc = {};
    
    var createStorageServiceInputElement = js2xml.createElement('CreateStorageServiceInput', 'http://schemas.microsoft.com/windowsazure');
    js2xml.addChildElement(requestDoc, createStorageServiceInputElement);
    
    var serviceNameElement = js2xml.createElement('ServiceName', 'http://schemas.microsoft.com/windowsazure');
    js2xml.setElementValue(serviceNameElement, parameters.name);
    js2xml.addChildElement(createStorageServiceInputElement, serviceNameElement);
    
    if (parameters.description !== null && parameters.description !== undefined) {
      var descriptionElement = js2xml.createElement('Description', 'http://schemas.microsoft.com/windowsazure');
      js2xml.setElementValue(descriptionElement, parameters.description);
      js2xml.addChildElement(createStorageServiceInputElement, descriptionElement);
    }
    else if (parameters.description !== undefined) {
      var emptyElement = js2xml.createElement('Description', 'http://schemas.microsoft.com/windowsazure');
      var nilAttribute = js2xml.createAttribute('nil', 'http://www.w3.org/2001/XMLSchema-instance');
      js2xml.setAttributeValue(nilAttribute, 'true');
      js2xml.addAttribute(emptyElement, nilAttribute);
      js2xml.addChildElement(createStorageServiceInputElement, emptyElement);
    }
    
    var labelElement = js2xml.createElement('Label', 'http://schemas.microsoft.com/windowsazure');
    js2xml.setElementValue(labelElement, new Buffer(parameters.label).toString('base64'));
    js2xml.addChildElement(createStorageServiceInputElement, labelElement);
    
    if (parameters.affinityGroup !== null && parameters.affinityGroup !== undefined) {
      var affinityGroupElement = js2xml.createElement('AffinityGroup', 'http://schemas.microsoft.com/windowsazure');
      js2xml.setElementValue(affinityGroupElement, parameters.affinityGroup);
      js2xml.addChildElement(createStorageServiceInputElement, affinityGroupElement);
    }
    
    if (parameters.location !== null && parameters.location !== undefined) {
      var locationElement = js2xml.createElement('Location', 'http://schemas.microsoft.com/windowsazure');
      js2xml.setElementValue(locationElement, parameters.location);
      js2xml.addChildElement(createStorageServiceInputElement, locationElement);
    }
    
    if (parameters.extendedProperties !== null && parameters.extendedProperties !== undefined) {
      var extendedPropertiesDictionaryElement = js2xml.createElement('ExtendedProperties', 'http://schemas.microsoft.com/windowsazure');
      for (var extendedPropertiesKey in parameters.extendedProperties) {
        var extendedPropertiesValue = parameters.extendedProperties[extendedPropertiesKey];
        var extendedPropertiesElement = js2xml.createElement('ExtendedProperty', 'http://schemas.microsoft.com/windowsazure');
        js2xml.addChildElement(extendedPropertiesDictionaryElement, extendedPropertiesElement);
        
        var extendedPropertiesKeyElement = js2xml.createElement('Name', 'http://schemas.microsoft.com/windowsazure');
        js2xml.setElementValue(extendedPropertiesKeyElement, extendedPropertiesKey);
        js2xml.addChildElement(extendedPropertiesElement, extendedPropertiesKeyElement);
        
        var extendedPropertiesValueElement = js2xml.createElement('Value', 'http://schemas.microsoft.com/windowsazure');
        js2xml.setElementValue(extendedPropertiesValueElement, extendedPropertiesValue);
        js2xml.addChildElement(extendedPropertiesElement, extendedPropertiesValueElement);
      }
      js2xml.addChildElement(createStorageServiceInputElement, extendedPropertiesDictionaryElement);
    }
    
    if (parameters.accountType !== null && parameters.accountType !== undefined) {
      var accountTypeElement = js2xml.createElement('AccountType', 'http://schemas.microsoft.com/windowsazure');
      js2xml.setElementValue(accountTypeElement, parameters.accountType);
      js2xml.addChildElement(createStorageServiceInputElement, accountTypeElement);
    }
    
    requestContent = js2xml.serializeDocument(requestDoc);
    httpRequest.body = requestContent;
    httpRequest.headers['Content-Length'] = Buffer.isBuffer(requestContent) ? requestContent.length : Buffer.byteLength(requestContent, 'UTF8');
    // Send Request
    return this.client.pipeline(httpRequest, function (err, response, body) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var statusCode = response.statusCode;
      if (statusCode !== 202) {
        var error = new Error(body);
        error.statusCode = response.statusCode;
        return callback(error);
      }
      
      // Create Result
      var result = null;
      // Deserialize Response
      result = {};
      result.statusCode = statusCode;
      result.requestId = response.headers['x-ms-request-id'];
      
      return callback(null, result);
    });
  };
  
  /**
   * Prepare storage account migration api validates and prepares the given
   * storage account for IaaS Classic to ARM migration.
   * 
   * @param {string} storageAccountName Name of storage account to be migrated.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.beginPrepareMigration = function(storageAccountName, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    // Validate
    if (storageAccountName === null || storageAccountName === undefined) {
      return callback(new Error('storageAccountName cannot be null.'));
    }
    
    // Tracing
    
    // Construct URL
    var url2 = '';
    url2 = url2 + '/';
    if (this.client.credentials.subscriptionId !== null && this.client.credentials.subscriptionId !== undefined) {
      url2 = url2 + encodeURIComponent(this.client.credentials.subscriptionId);
    }
    url2 = url2 + '/services/storageservices/';
    url2 = url2 + encodeURIComponent(storageAccountName);
    url2 = url2 + '/migration';
    var queryParameters = [];
    queryParameters.push('comp=prepare');
    if (queryParameters.length > 0) {
      url2 = url2 + '?' + queryParameters.join('&');
    }
    var baseUrl = this.client.baseUri;
    // Trim '/' character from the end of baseUrl and beginning of url.
    if (baseUrl[baseUrl.length - 1] === '/') {
      baseUrl = baseUrl.substring(0, (baseUrl.length - 1) + 0);
    }
    if (url2[0] === '/') {
      url2 = url2.substring(1);
    }
    url2 = baseUrl + '/' + url2;
    url2 = url2.replace(' ', '%20');
    
    // Create HTTP transport objects
    var httpRequest = new WebResource();
    httpRequest.method = 'POST';
    httpRequest.headers = {};
    httpRequest.url = url2;
    
    // Set Headers
    httpRequest.headers['x-ms-version'] = '2016-03-01';
    
    // Send Request
    return this.client.pipeline(httpRequest, function (err, response, body) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var statusCode = response.statusCode;
      if (statusCode !== 202) {
        var error = new Error(body);
        error.statusCode = response.statusCode;
        return callback(error);
      }
      
      // Create Result
      var result = null;
      // Deserialize Response
      result = {};
      result.statusCode = statusCode;
      result.requestId = response.headers['x-ms-request-id'];
      
      return callback(null, result);
    });
  };
  
  /**
   * The Check Name Availability operation checks if a storage account name is
   * available for use in Azure.  (see
   * http://msdn.microsoft.com/en-us/library/windowsazure/jj154125.aspx for
   * more information)
   * 
   * @param {string} accountName The desired storage account name to check for
   * availability.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.checkNameAvailability = function(accountName, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    // Validate
    if (accountName === null || accountName === undefined) {
      return callback(new Error('accountName cannot be null.'));
    }
    
    // Tracing
    
    // Construct URL
    var url2 = '';
    url2 = url2 + '/';
    if (this.client.credentials.subscriptionId !== null && this.client.credentials.subscriptionId !== undefined) {
      url2 = url2 + encodeURIComponent(this.client.credentials.subscriptionId);
    }
    url2 = url2 + '/services/storageservices/operations/isavailable/';
    url2 = url2 + encodeURIComponent(accountName);
    var baseUrl = this.client.baseUri;
    // Trim '/' character from the end of baseUrl and beginning of url.
    if (baseUrl[baseUrl.length - 1] === '/') {
      baseUrl = baseUrl.substring(0, (baseUrl.length - 1) + 0);
    }
    if (url2[0] === '/') {
      url2 = url2.substring(1);
    }
    url2 = baseUrl + '/' + url2;
    url2 = url2.replace(' ', '%20');
    
    // Create HTTP transport objects
    var httpRequest = new WebResource();
    httpRequest.method = 'GET';
    httpRequest.headers = {};
    httpRequest.url = url2;
    
    // Set Headers
    httpRequest.headers['x-ms-version'] = '2016-03-01';
    
    // Send Request
    return this.client.pipeline(httpRequest, function (err, response, body) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var statusCode = response.statusCode;
      if (statusCode !== 200) {
        var error = new Error(body);
        error.statusCode = response.statusCode;
        return callback(error);
      }
      
      // Create Result
      var result = null;
      // Deserialize Response
      if (statusCode === 200) {
        var responseContent = body;
        result = {};
        var options = {};
        options.trim = false;
        options.strict = false;
        xml.parseString(responseContent, options, function (err2, responseDoc) {
          if (err2 !== null && err2 !== undefined) {
            return callback(err2);
          }
          
          var availabilityResponseElement = js2xml.getElement(responseDoc, responseDoc, 'AVAILABILITYRESPONSE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
          if (availabilityResponseElement !== null && availabilityResponseElement !== undefined) {
            var resultElement = js2xml.getElement(responseDoc, availabilityResponseElement, 'RESULT', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
            if (resultElement !== null && resultElement !== undefined && resultElement.length !== 0) {
              var resultInstance = resultElement === 'true';
              result.isAvailable = resultInstance;
            }
            
            var reasonElement = js2xml.getElement(responseDoc, availabilityResponseElement, 'REASON', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
            if (reasonElement !== null && reasonElement !== undefined) {
              var isNil = false;
              var nilAttribute = js2xml.getAttribute(responseDoc, reasonElement, 'NIL', 'HTTP://WWW.W3.ORG/2001/XMLSCHEMA-INSTANCE');
              if (nilAttribute !== null && nilAttribute !== undefined) {
                isNil = nilAttribute === 'true';
              }
              if (isNil === false) {
                var reasonInstance = reasonElement;
                result.reason = reasonInstance;
              }
            }
          }
          
        });
      }
      result.statusCode = statusCode;
      result.requestId = response.headers['x-ms-request-id'];
      
      return callback(null, result);
    });
  };
  
  /**
   * Commit storage account migration api validates and commits the given
   * storage account for IaaS Classic to ARM migration.
   * 
   * @param {string} storageAccountName Name of storage account to be migrated.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.commitMigration = function(storageAccountName, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    var client2 = this.client;
    
    return client2.storageAccounts.beginCommitMigration(storageAccountName, function (err, result) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var delayInSeconds = 30;
      if (client2.longRunningOperationInitialTimeout >= 0) {
        delayInSeconds = client2.longRunningOperationInitialTimeout;
      }
      
      var pollOperation = function () {
        setTimeout(function () {
          return client2.getOperationStatus(result.requestId, function (err2, result2) {
            if (err2 !== null && err2 !== undefined) {
              return callback(err2);
            } else {
              if (result2.status !== 'InProgress') {
                if (result2.status !== 'Succeeded') {
                  if (result2.error !== null && result2.error !== undefined) {
                    var ex = new Error(result2.error.code + ' : ' + result2.error.message);
                    ex.error = new Error();
                    ex.error.code = result2.error.code;
                    ex.error.message = result2.error.message;
                    return callback(ex);
                  } else {
                    var ex = new Error('');
                    return callback(ex);
                  }
                }
                
                return callback(null, result2);
              } else {
                delayInSeconds = 30;
                if (client2.longRunningOperationRetryTimeout >= 0) {
                  delayInSeconds = client2.longRunningOperationRetryTimeout;
                }
                pollOperation();
              }
            }
          });
        }, delayInSeconds * 1000);
      };
      
      pollOperation();
    });
  };
  
  /**
   * The Create Storage Account operation creates a new storage account in
   * Azure.  (see
   * http://msdn.microsoft.com/en-us/library/windowsazure/hh264518.aspx for
   * more information)
   * 
   * @param {StorageAccountCreateParameters} parameters Parameters supplied to
   * the Create Storage Account operation.
   * 
   * @param {string} parameters.name A name for the storage account, unique
   * within Azure. Storage account names must be between 3 and 24 characters
   * in length, and must use numbers and lower-case letters only. This name is
   * the DNS prefix name and can be used to access blobs, queues, and tables
   * in the storage account. For example:
   * http://ServiceName.blob.core.windows.net/mycontainer/.
   * 
   * @param {string} [parameters.description] A description for the storage
   * account. The description may be up to 1024 characters in length.
   * 
   * @param {string} parameters.label A name for the storage account, specified
   * as abase64-encoded string. The name may be up to 100 characters in
   * length. The name can be used identify the storage account for your
   * tracking purposes.
   * 
   * @param {string} [parameters.affinityGroup] The name of an existing
   * affinity group in the specified subscription. Required if Location is not
   * specified. You can include either a Location or AffinityGroup element in
   * the request body, but not both. To list available affinity groups, use
   * the List Affinity Groups operation.
   * 
   * @param {string} [parameters.location] The location where the storage
   * account is created. Required if AffinityGroup is not specified. You can
   * include either a Location or AffinityGroup element in the request body,
   * but not both. To list available locations, use the List Locations
   * operation.
   * 
   * @param {object} [parameters.extendedProperties] Represents the name of an
   * extended storage account property. Each extended property must have a
   * defined name and a value. You can have a maximum of 50 extended property
   * name/value pairs. The maximum length of the Name element is 64
   * characters, only alphanumeric characters and underscores are valid in the
   * Name, and the name must start with a letter. Attempting to use other
   * characters, starting the Name with a non-letter character, or entering a
   * name that is identical to that of another extended property owned by the
   * same storage account will result in a status code 400 (Bad Request)
   * error. Each extended property value has a maximum length of 255
   * characters.
   * 
   * @param {string} [parameters.accountType] Specifies whether the account
   * supports locally-redundant storage, geo-redundant storage, zone-redundant
   * storage, or read access geo-redundant storage. Possible values
   * are:'Standard_LRS', 'Standard_ZRS', 'Standard_GRS', and 'Standard_RAGRS'.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.create = function(parameters, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    var client2 = this.client;
    
    return client2.storageAccounts.beginCreating(parameters, function (err, result) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var delayInSeconds = 30;
      if (client2.longRunningOperationInitialTimeout >= 0) {
        delayInSeconds = client2.longRunningOperationInitialTimeout;
      }
      
      var pollOperation = function () {
        setTimeout(function () {
          return client2.getOperationStatus(result.requestId, function (err2, result2) {
            if (err2 !== null && err2 !== undefined) {
              return callback(err2);
            } else {
              if (result2.status !== 'InProgress') {
                if (result2.status !== 'Succeeded') {
                  if (result2.error !== null && result2.error !== undefined) {
                    var ex = new Error(result2.error.code + ' : ' + result2.error.message);
                    ex.error = new Error();
                    ex.error.code = result2.error.code;
                    ex.error.message = result2.error.message;
                    return callback(ex);
                  } else {
                    var ex = new Error('');
                    return callback(ex);
                  }
                }
                
                return callback(null, result2);
              } else {
                delayInSeconds = 30;
                if (client2.longRunningOperationRetryTimeout >= 0) {
                  delayInSeconds = client2.longRunningOperationRetryTimeout;
                }
                pollOperation();
              }
            }
          });
        }, delayInSeconds * 1000);
      };
      
      pollOperation();
    });
  };
  
  /**
   * The Delete Storage Account operation deletes the specified storage account
   * from Azure.  (see
   * http://msdn.microsoft.com/en-us/library/windowsazure/hh264517.aspx for
   * more information)
   * 
   * @param {string} accountName The name of the storage account to be deleted.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.deleteMethod = function(accountName, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    // Validate
    if (accountName === null || accountName === undefined) {
      return callback(new Error('accountName cannot be null.'));
    }
    
    // Tracing
    
    // Construct URL
    var url2 = '';
    url2 = url2 + '/';
    if (this.client.credentials.subscriptionId !== null && this.client.credentials.subscriptionId !== undefined) {
      url2 = url2 + encodeURIComponent(this.client.credentials.subscriptionId);
    }
    url2 = url2 + '/services/storageservices/';
    url2 = url2 + encodeURIComponent(accountName);
    var baseUrl = this.client.baseUri;
    // Trim '/' character from the end of baseUrl and beginning of url.
    if (baseUrl[baseUrl.length - 1] === '/') {
      baseUrl = baseUrl.substring(0, (baseUrl.length - 1) + 0);
    }
    if (url2[0] === '/') {
      url2 = url2.substring(1);
    }
    url2 = baseUrl + '/' + url2;
    url2 = url2.replace(' ', '%20');
    
    // Create HTTP transport objects
    var httpRequest = new WebResource();
    httpRequest.method = 'DELETE';
    httpRequest.headers = {};
    httpRequest.url = url2;
    
    // Set Headers
    httpRequest.headers['x-ms-version'] = '2016-03-01';
    
    // Send Request
    return this.client.pipeline(httpRequest, function (err, response, body) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var statusCode = response.statusCode;
      if (statusCode !== 200) {
        var error = new Error(body);
        error.statusCode = response.statusCode;
        return callback(error);
      }
      
      // Create Result
      var result = null;
      // Deserialize Response
      result = {};
      result.statusCode = statusCode;
      result.requestId = response.headers['x-ms-request-id'];
      
      return callback(null, result);
    });
  };
  
  /**
   * The Get Storage Account Properties operation returns system properties for
   * the specified storage account.  (see
   * http://msdn.microsoft.com/en-us/library/windowsazure/ee460802.aspx for
   * more information)
   * 
   * @param {string} accountName Name of the storage account to get properties
   * for.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.get = function(accountName, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    // Validate
    if (accountName === null || accountName === undefined) {
      return callback(new Error('accountName cannot be null.'));
    }
    
    // Tracing
    
    // Construct URL
    var url2 = '';
    url2 = url2 + '/';
    if (this.client.credentials.subscriptionId !== null && this.client.credentials.subscriptionId !== undefined) {
      url2 = url2 + encodeURIComponent(this.client.credentials.subscriptionId);
    }
    url2 = url2 + '/services/storageservices/';
    url2 = url2 + encodeURIComponent(accountName);
    var baseUrl = this.client.baseUri;
    // Trim '/' character from the end of baseUrl and beginning of url.
    if (baseUrl[baseUrl.length - 1] === '/') {
      baseUrl = baseUrl.substring(0, (baseUrl.length - 1) + 0);
    }
    if (url2[0] === '/') {
      url2 = url2.substring(1);
    }
    url2 = baseUrl + '/' + url2;
    url2 = url2.replace(' ', '%20');
    
    // Create HTTP transport objects
    var httpRequest = new WebResource();
    httpRequest.method = 'GET';
    httpRequest.headers = {};
    httpRequest.url = url2;
    
    // Set Headers
    httpRequest.headers['x-ms-version'] = '2016-03-01';
    
    // Send Request
    return this.client.pipeline(httpRequest, function (err, response, body) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var statusCode = response.statusCode;
      if (statusCode !== 200) {
        var error = new Error(body);
        error.statusCode = response.statusCode;
        return callback(error);
      }
      
      // Create Result
      var result = null;
      // Deserialize Response
      if (statusCode === 200) {
        var responseContent = body;
        result = {};
        var options = {};
        options.trim = false;
        options.strict = false;
        xml.parseString(responseContent, options, function (err2, responseDoc) {
          if (err2 !== null && err2 !== undefined) {
            return callback(err2);
          }
          
          var storageServiceElement = js2xml.getElement(responseDoc, responseDoc, 'STORAGESERVICE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
          if (storageServiceElement !== null && storageServiceElement !== undefined) {
            var storageServiceInstance = { extendedProperties: {} };
            result.storageAccount = storageServiceInstance;
            
            var urlElement = js2xml.getElement(responseDoc, storageServiceElement, 'URL', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
            if (urlElement !== null && urlElement !== undefined) {
              var urlInstance = urlElement;
              storageServiceInstance.uri = urlInstance;
            }
            
            var serviceNameElement = js2xml.getElement(responseDoc, storageServiceElement, 'SERVICENAME', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
            if (serviceNameElement !== null && serviceNameElement !== undefined) {
              var serviceNameInstance = serviceNameElement;
              storageServiceInstance.name = serviceNameInstance;
            }
            
            var storageServicePropertiesElement = js2xml.getElement(responseDoc, storageServiceElement, 'STORAGESERVICEPROPERTIES', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
            if (storageServicePropertiesElement !== null && storageServicePropertiesElement !== undefined) {
              var storageServicePropertiesInstance = { endpoints: [] };
              storageServiceInstance.properties = storageServicePropertiesInstance;
              
              var descriptionElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'DESCRIPTION', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (descriptionElement !== null && descriptionElement !== undefined) {
                var isNil = false;
                var nilAttribute = js2xml.getAttribute(responseDoc, descriptionElement, 'NIL', 'HTTP://WWW.W3.ORG/2001/XMLSCHEMA-INSTANCE');
                if (nilAttribute !== null && nilAttribute !== undefined) {
                  isNil = nilAttribute === 'true';
                }
                if (isNil === false) {
                  var descriptionInstance = descriptionElement;
                  storageServicePropertiesInstance.description = descriptionInstance;
                }
              }
              
              var affinityGroupElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'AFFINITYGROUP', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (affinityGroupElement !== null && affinityGroupElement !== undefined) {
                var affinityGroupInstance = affinityGroupElement;
                storageServicePropertiesInstance.affinityGroup = affinityGroupInstance;
              }
              
              var locationElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'LOCATION', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (locationElement !== null && locationElement !== undefined) {
                var locationInstance = locationElement;
                storageServicePropertiesInstance.location = locationInstance;
              }
              
              var labelElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'LABEL', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (labelElement !== null && labelElement !== undefined) {
                var labelInstance = new Buffer(labelElement, 'base64').toString('utf8');
                storageServicePropertiesInstance.label = labelInstance;
              }
              
              var statusElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'STATUS', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (statusElement !== null && statusElement !== undefined && statusElement.length !== 0) {
                var statusInstance = statusElement;
                storageServicePropertiesInstance.status = statusInstance;
              }
              
              var endpointsSequenceElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'ENDPOINTS', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (endpointsSequenceElement !== null && endpointsSequenceElement !== undefined) {
                for (var loweredIndex1 = 0; loweredIndex1 < js2xml.getElements(responseDoc, endpointsSequenceElement, 'ENDPOINT', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE').length; loweredIndex1 = loweredIndex1 + 1) {
                  var endpointsElement = js2xml.getElements(responseDoc, endpointsSequenceElement, 'ENDPOINT', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE')[loweredIndex1];
                  storageServicePropertiesInstance.endpoints.push(endpointsElement);
                }
              }
              
              var geoPrimaryRegionElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'GEOPRIMARYREGION', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (geoPrimaryRegionElement !== null && geoPrimaryRegionElement !== undefined) {
                var geoPrimaryRegionInstance = geoPrimaryRegionElement;
                storageServicePropertiesInstance.geoPrimaryRegion = geoPrimaryRegionInstance;
              }
              
              var statusOfPrimaryElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'STATUSOFPRIMARY', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (statusOfPrimaryElement !== null && statusOfPrimaryElement !== undefined && statusOfPrimaryElement.length !== 0) {
                var statusOfPrimaryInstance = statusOfPrimaryElement;
                storageServicePropertiesInstance.statusOfGeoPrimaryRegion = statusOfPrimaryInstance;
              }
              
              var lastGeoFailoverTimeElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'LASTGEOFAILOVERTIME', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (lastGeoFailoverTimeElement !== null && lastGeoFailoverTimeElement !== undefined && lastGeoFailoverTimeElement.length !== 0) {
                var lastGeoFailoverTimeInstance = new Date(lastGeoFailoverTimeElement);
                storageServicePropertiesInstance.lastGeoFailoverTime = lastGeoFailoverTimeInstance;
              }
              
              var geoSecondaryRegionElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'GEOSECONDARYREGION', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (geoSecondaryRegionElement !== null && geoSecondaryRegionElement !== undefined) {
                var geoSecondaryRegionInstance = geoSecondaryRegionElement;
                storageServicePropertiesInstance.geoSecondaryRegion = geoSecondaryRegionInstance;
              }
              
              var statusOfSecondaryElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'STATUSOFSECONDARY', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (statusOfSecondaryElement !== null && statusOfSecondaryElement !== undefined && statusOfSecondaryElement.length !== 0) {
                var statusOfSecondaryInstance = statusOfSecondaryElement;
                storageServicePropertiesInstance.statusOfGeoSecondaryRegion = statusOfSecondaryInstance;
              }
              
              var accountTypeElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'ACCOUNTTYPE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (accountTypeElement !== null && accountTypeElement !== undefined) {
                var accountTypeInstance = accountTypeElement;
                storageServicePropertiesInstance.accountType = accountTypeInstance;
              }
            }
            
            var extendedPropertiesSequenceElement = js2xml.getElement(responseDoc, storageServiceElement, 'EXTENDEDPROPERTIES', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
            if (extendedPropertiesSequenceElement !== null && extendedPropertiesSequenceElement !== undefined) {
              for (var loweredIndex2 = 0; loweredIndex2 < js2xml.getElements(responseDoc, extendedPropertiesSequenceElement, 'EXTENDEDPROPERTY', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE').length; loweredIndex2 = loweredIndex2 + 1) {
                var extendedPropertiesElement = js2xml.getElements(responseDoc, extendedPropertiesSequenceElement, 'EXTENDEDPROPERTY', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE')[loweredIndex2];
                var extendedPropertiesKey = js2xml.getElement(responseDoc, extendedPropertiesElement, 'NAME', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                var extendedPropertiesValue = js2xml.getElement(responseDoc, extendedPropertiesElement, 'VALUE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                storageServiceInstance.extendedProperties[extendedPropertiesKey] = extendedPropertiesValue;
              }
            }
            
            var migrationStateElement = js2xml.getElement(responseDoc, storageServiceElement, 'MIGRATIONSTATE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
            if (migrationStateElement !== null && migrationStateElement !== undefined) {
              var migrationStateInstance = migrationStateElement;
              storageServiceInstance.migrationState = migrationStateInstance;
            }
          }
          
        });
      }
      result.statusCode = statusCode;
      result.requestId = response.headers['x-ms-request-id'];
      
      return callback(null, result);
    });
  };
  
  /**
   * The Get Storage Keys operation returns the primary and secondary access
   * keys for the specified storage account.  (see
   * http://msdn.microsoft.com/en-us/library/windowsazure/ee460785.aspx for
   * more information)
   * 
   * @param {string} accountName The name of the desired storage account.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.getKeys = function(accountName, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    // Validate
    if (accountName === null || accountName === undefined) {
      return callback(new Error('accountName cannot be null.'));
    }
    
    // Tracing
    
    // Construct URL
    var url2 = '';
    url2 = url2 + '/';
    if (this.client.credentials.subscriptionId !== null && this.client.credentials.subscriptionId !== undefined) {
      url2 = url2 + encodeURIComponent(this.client.credentials.subscriptionId);
    }
    url2 = url2 + '/services/storageservices/';
    url2 = url2 + encodeURIComponent(accountName);
    url2 = url2 + '/keys';
    var baseUrl = this.client.baseUri;
    // Trim '/' character from the end of baseUrl and beginning of url.
    if (baseUrl[baseUrl.length - 1] === '/') {
      baseUrl = baseUrl.substring(0, (baseUrl.length - 1) + 0);
    }
    if (url2[0] === '/') {
      url2 = url2.substring(1);
    }
    url2 = baseUrl + '/' + url2;
    url2 = url2.replace(' ', '%20');
    
    // Create HTTP transport objects
    var httpRequest = new WebResource();
    httpRequest.method = 'GET';
    httpRequest.headers = {};
    httpRequest.url = url2;
    
    // Set Headers
    httpRequest.headers['x-ms-version'] = '2016-03-01';
    
    // Send Request
    return this.client.pipeline(httpRequest, function (err, response, body) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var statusCode = response.statusCode;
      if (statusCode !== 200) {
        var error = new Error(body);
        error.statusCode = response.statusCode;
        return callback(error);
      }
      
      // Create Result
      var result = null;
      // Deserialize Response
      if (statusCode === 200) {
        var responseContent = body;
        result = {};
        var options = {};
        options.trim = false;
        options.strict = false;
        xml.parseString(responseContent, options, function (err2, responseDoc) {
          if (err2 !== null && err2 !== undefined) {
            return callback(err2);
          }
          
          var storageServiceElement = js2xml.getElement(responseDoc, responseDoc, 'STORAGESERVICE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
          if (storageServiceElement !== null && storageServiceElement !== undefined) {
            var urlElement = js2xml.getElement(responseDoc, storageServiceElement, 'URL', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
            if (urlElement !== null && urlElement !== undefined) {
              var urlInstance = urlElement;
              result.uri = urlInstance;
            }
            
            var storageServiceKeysElement = js2xml.getElement(responseDoc, storageServiceElement, 'STORAGESERVICEKEYS', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
            if (storageServiceKeysElement !== null && storageServiceKeysElement !== undefined) {
              var primaryElement = js2xml.getElement(responseDoc, storageServiceKeysElement, 'PRIMARY', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (primaryElement !== null && primaryElement !== undefined) {
                var primaryInstance = primaryElement;
                result.primaryKey = primaryInstance;
              }
              
              var secondaryElement = js2xml.getElement(responseDoc, storageServiceKeysElement, 'SECONDARY', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (secondaryElement !== null && secondaryElement !== undefined) {
                var secondaryInstance = secondaryElement;
                result.secondaryKey = secondaryInstance;
              }
            }
          }
          
        });
      }
      result.statusCode = statusCode;
      result.requestId = response.headers['x-ms-request-id'];
      
      return callback(null, result);
    });
  };
  
  /**
   * The List Storage Accounts operation lists the storage accounts available
   * under the current subscription.  (see
   * http://msdn.microsoft.com/en-us/library/windowsazure/ee460787.aspx for
   * more information)
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.list = function(callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    // Validate
    
    // Tracing
    
    // Construct URL
    var url2 = '';
    url2 = url2 + '/';
    if (this.client.credentials.subscriptionId !== null && this.client.credentials.subscriptionId !== undefined) {
      url2 = url2 + encodeURIComponent(this.client.credentials.subscriptionId);
    }
    url2 = url2 + '/services/storageservices';
    var baseUrl = this.client.baseUri;
    // Trim '/' character from the end of baseUrl and beginning of url.
    if (baseUrl[baseUrl.length - 1] === '/') {
      baseUrl = baseUrl.substring(0, (baseUrl.length - 1) + 0);
    }
    if (url2[0] === '/') {
      url2 = url2.substring(1);
    }
    url2 = baseUrl + '/' + url2;
    url2 = url2.replace(' ', '%20');
    
    // Create HTTP transport objects
    var httpRequest = new WebResource();
    httpRequest.method = 'GET';
    httpRequest.headers = {};
    httpRequest.url = url2;
    
    // Set Headers
    httpRequest.headers['x-ms-version'] = '2016-03-01';
    
    // Send Request
    return this.client.pipeline(httpRequest, function (err, response, body) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var statusCode = response.statusCode;
      if (statusCode !== 200) {
        var error = new Error(body);
        error.statusCode = response.statusCode;
        return callback(error);
      }
      
      // Create Result
      var result = null;
      // Deserialize Response
      if (statusCode === 200) {
        var responseContent = body;
        result = { storageAccounts: [] };
        var options = {};
        options.trim = false;
        options.strict = false;
        xml.parseString(responseContent, options, function (err2, responseDoc) {
          if (err2 !== null && err2 !== undefined) {
            return callback(err2);
          }
          
          var storageServicesSequenceElement = js2xml.getElement(responseDoc, responseDoc, 'STORAGESERVICES', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
          if (storageServicesSequenceElement !== null && storageServicesSequenceElement !== undefined) {
            for (var loweredIndex1 = 0; loweredIndex1 < js2xml.getElements(responseDoc, storageServicesSequenceElement, 'STORAGESERVICE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE').length; loweredIndex1 = loweredIndex1 + 1) {
              var storageServicesElement = js2xml.getElements(responseDoc, storageServicesSequenceElement, 'STORAGESERVICE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE')[loweredIndex1];
              var storageServiceInstance = { extendedProperties: {} };
              result.storageAccounts.push(storageServiceInstance);
              
              var urlElement = js2xml.getElement(responseDoc, storageServicesElement, 'URL', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (urlElement !== null && urlElement !== undefined) {
                var urlInstance = urlElement;
                storageServiceInstance.uri = urlInstance;
              }
              
              var serviceNameElement = js2xml.getElement(responseDoc, storageServicesElement, 'SERVICENAME', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (serviceNameElement !== null && serviceNameElement !== undefined) {
                var serviceNameInstance = serviceNameElement;
                storageServiceInstance.name = serviceNameInstance;
              }
              
              var storageServicePropertiesElement = js2xml.getElement(responseDoc, storageServicesElement, 'STORAGESERVICEPROPERTIES', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (storageServicePropertiesElement !== null && storageServicePropertiesElement !== undefined) {
                var storageServicePropertiesInstance = { endpoints: [] };
                storageServiceInstance.properties = storageServicePropertiesInstance;
                
                var descriptionElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'DESCRIPTION', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                if (descriptionElement !== null && descriptionElement !== undefined) {
                  var isNil = false;
                  var nilAttribute = js2xml.getAttribute(responseDoc, descriptionElement, 'NIL', 'HTTP://WWW.W3.ORG/2001/XMLSCHEMA-INSTANCE');
                  if (nilAttribute !== null && nilAttribute !== undefined) {
                    isNil = nilAttribute === 'true';
                  }
                  if (isNil === false) {
                    var descriptionInstance = descriptionElement;
                    storageServicePropertiesInstance.description = descriptionInstance;
                  }
                }
                
                var affinityGroupElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'AFFINITYGROUP', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                if (affinityGroupElement !== null && affinityGroupElement !== undefined) {
                  var affinityGroupInstance = affinityGroupElement;
                  storageServicePropertiesInstance.affinityGroup = affinityGroupInstance;
                }
                
                var locationElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'LOCATION', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                if (locationElement !== null && locationElement !== undefined) {
                  var locationInstance = locationElement;
                  storageServicePropertiesInstance.location = locationInstance;
                }
                
                var labelElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'LABEL', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                if (labelElement !== null && labelElement !== undefined) {
                  var labelInstance = new Buffer(labelElement, 'base64').toString('utf8');
                  storageServicePropertiesInstance.label = labelInstance;
                }
                
                var statusElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'STATUS', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                if (statusElement !== null && statusElement !== undefined && statusElement.length !== 0) {
                  var statusInstance = statusElement;
                  storageServicePropertiesInstance.status = statusInstance;
                }
                
                var endpointsSequenceElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'ENDPOINTS', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                if (endpointsSequenceElement !== null && endpointsSequenceElement !== undefined) {
                  for (var loweredIndex2 = 0; loweredIndex2 < js2xml.getElements(responseDoc, endpointsSequenceElement, 'ENDPOINT', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE').length; loweredIndex2 = loweredIndex2 + 1) {
                    var endpointsElement = js2xml.getElements(responseDoc, endpointsSequenceElement, 'ENDPOINT', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE')[loweredIndex2];
                    storageServicePropertiesInstance.endpoints.push(endpointsElement);
                  }
                }
                
                var geoPrimaryRegionElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'GEOPRIMARYREGION', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                if (geoPrimaryRegionElement !== null && geoPrimaryRegionElement !== undefined) {
                  var geoPrimaryRegionInstance = geoPrimaryRegionElement;
                  storageServicePropertiesInstance.geoPrimaryRegion = geoPrimaryRegionInstance;
                }
                
                var statusOfPrimaryElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'STATUSOFPRIMARY', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                if (statusOfPrimaryElement !== null && statusOfPrimaryElement !== undefined && statusOfPrimaryElement.length !== 0) {
                  var statusOfPrimaryInstance = statusOfPrimaryElement;
                  storageServicePropertiesInstance.statusOfGeoPrimaryRegion = statusOfPrimaryInstance;
                }
                
                var lastGeoFailoverTimeElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'LASTGEOFAILOVERTIME', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                if (lastGeoFailoverTimeElement !== null && lastGeoFailoverTimeElement !== undefined && lastGeoFailoverTimeElement.length !== 0) {
                  var lastGeoFailoverTimeInstance = new Date(lastGeoFailoverTimeElement);
                  storageServicePropertiesInstance.lastGeoFailoverTime = lastGeoFailoverTimeInstance;
                }
                
                var geoSecondaryRegionElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'GEOSECONDARYREGION', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                if (geoSecondaryRegionElement !== null && geoSecondaryRegionElement !== undefined) {
                  var geoSecondaryRegionInstance = geoSecondaryRegionElement;
                  storageServicePropertiesInstance.geoSecondaryRegion = geoSecondaryRegionInstance;
                }
                
                var statusOfSecondaryElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'STATUSOFSECONDARY', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                if (statusOfSecondaryElement !== null && statusOfSecondaryElement !== undefined && statusOfSecondaryElement.length !== 0) {
                  var statusOfSecondaryInstance = statusOfSecondaryElement;
                  storageServicePropertiesInstance.statusOfGeoSecondaryRegion = statusOfSecondaryInstance;
                }
                
                var accountTypeElement = js2xml.getElement(responseDoc, storageServicePropertiesElement, 'ACCOUNTTYPE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                if (accountTypeElement !== null && accountTypeElement !== undefined) {
                  var accountTypeInstance = accountTypeElement;
                  storageServicePropertiesInstance.accountType = accountTypeInstance;
                }
              }
              
              var extendedPropertiesSequenceElement = js2xml.getElement(responseDoc, storageServicesElement, 'EXTENDEDPROPERTIES', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (extendedPropertiesSequenceElement !== null && extendedPropertiesSequenceElement !== undefined) {
                for (var loweredIndex3 = 0; loweredIndex3 < js2xml.getElements(responseDoc, extendedPropertiesSequenceElement, 'EXTENDEDPROPERTY', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE').length; loweredIndex3 = loweredIndex3 + 1) {
                  var extendedPropertiesElement = js2xml.getElements(responseDoc, extendedPropertiesSequenceElement, 'EXTENDEDPROPERTY', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE')[loweredIndex3];
                  var extendedPropertiesKey = js2xml.getElement(responseDoc, extendedPropertiesElement, 'NAME', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                  var extendedPropertiesValue = js2xml.getElement(responseDoc, extendedPropertiesElement, 'VALUE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
                  storageServiceInstance.extendedProperties[extendedPropertiesKey] = extendedPropertiesValue;
                }
              }
              
              var migrationStateElement = js2xml.getElement(responseDoc, storageServicesElement, 'MIGRATIONSTATE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (migrationStateElement !== null && migrationStateElement !== undefined) {
                var migrationStateInstance = migrationStateElement;
                storageServiceInstance.migrationState = migrationStateInstance;
              }
            }
          }
          
        });
      }
      result.statusCode = statusCode;
      result.requestId = response.headers['x-ms-request-id'];
      
      return callback(null, result);
    });
  };
  
  /**
   * Prepare storage account migration api validates and prepares the given
   * storage account for IaaS Classic to ARM migration.
   * 
   * @param {string} storageAccountName Name of storage account to be migrated.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.prepareMigration = function(storageAccountName, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    var client2 = this.client;
    
    return client2.storageAccounts.beginPrepareMigration(storageAccountName, function (err, result) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var delayInSeconds = 30;
      if (client2.longRunningOperationInitialTimeout >= 0) {
        delayInSeconds = client2.longRunningOperationInitialTimeout;
      }
      
      var pollOperation = function () {
        setTimeout(function () {
          return client2.getOperationStatus(result.requestId, function (err2, result2) {
            if (err2 !== null && err2 !== undefined) {
              return callback(err2);
            } else {
              if (result2.status !== 'InProgress') {
                if (result2.status !== 'Succeeded') {
                  if (result2.error !== null && result2.error !== undefined) {
                    var ex = new Error(result2.error.code + ' : ' + result2.error.message);
                    ex.error = new Error();
                    ex.error.code = result2.error.code;
                    ex.error.message = result2.error.message;
                    return callback(ex);
                  } else {
                    var ex = new Error('');
                    return callback(ex);
                  }
                }
                
                return callback(null, result2);
              } else {
                delayInSeconds = 30;
                if (client2.longRunningOperationRetryTimeout >= 0) {
                  delayInSeconds = client2.longRunningOperationRetryTimeout;
                }
                pollOperation();
              }
            }
          });
        }, delayInSeconds * 1000);
      };
      
      pollOperation();
    });
  };
  
  /**
   * The Regenerate Keys operation regenerates the primary or secondary access
   * key for the specified storage account.  (see
   * http://msdn.microsoft.com/en-us/library/windowsazure/ee460795.aspx for
   * more information)
   * 
   * @param {StorageAccountRegenerateKeysParameters} parameters Parameters
   * supplied to the Regenerate Keys operation.
   * 
   * @param {string} parameters.name The name of the desired storage account.
   * 
   * @param {StorageKeyType} parameters.keyType Specifies which key to
   * regenerate.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.regenerateKeys = function(parameters, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    // Validate
    if (parameters === null || parameters === undefined) {
      return callback(new Error('parameters cannot be null.'));
    }
    if (parameters.keyType === null || parameters.keyType === undefined) {
      return callback(new Error('parameters.keyType cannot be null.'));
    }
    if (parameters.name === null || parameters.name === undefined) {
      return callback(new Error('parameters.name cannot be null.'));
    }
    
    // Tracing
    
    // Construct URL
    var url2 = '';
    url2 = url2 + '/';
    if (this.client.credentials.subscriptionId !== null && this.client.credentials.subscriptionId !== undefined) {
      url2 = url2 + encodeURIComponent(this.client.credentials.subscriptionId);
    }
    url2 = url2 + '/services/storageservices/';
    url2 = url2 + encodeURIComponent(parameters.name);
    url2 = url2 + '/keys';
    var queryParameters = [];
    queryParameters.push('action=regenerate');
    if (queryParameters.length > 0) {
      url2 = url2 + '?' + queryParameters.join('&');
    }
    var baseUrl = this.client.baseUri;
    // Trim '/' character from the end of baseUrl and beginning of url.
    if (baseUrl[baseUrl.length - 1] === '/') {
      baseUrl = baseUrl.substring(0, (baseUrl.length - 1) + 0);
    }
    if (url2[0] === '/') {
      url2 = url2.substring(1);
    }
    url2 = baseUrl + '/' + url2;
    url2 = url2.replace(' ', '%20');
    
    // Create HTTP transport objects
    var httpRequest = new WebResource();
    httpRequest.method = 'POST';
    httpRequest.headers = {};
    httpRequest.url = url2;
    
    // Set Headers
    httpRequest.headers['Content-Type'] = 'application/xml';
    httpRequest.headers['x-ms-version'] = '2016-03-01';
    
    // Serialize Request
    var requestContent = null;
    var requestDoc = {};
    
    var regenerateKeysElement = js2xml.createElement('RegenerateKeys', 'http://schemas.microsoft.com/windowsazure');
    js2xml.addChildElement(requestDoc, regenerateKeysElement);
    
    var keyTypeElement = js2xml.createElement('KeyType', 'http://schemas.microsoft.com/windowsazure');
    js2xml.setElementValue(keyTypeElement, parameters.keyType !== null && parameters.keyType !== undefined ? parameters.keyType.toString() : 'Primary');
    js2xml.addChildElement(regenerateKeysElement, keyTypeElement);
    
    requestContent = js2xml.serializeDocument(requestDoc);
    httpRequest.body = requestContent;
    httpRequest.headers['Content-Length'] = Buffer.isBuffer(requestContent) ? requestContent.length : Buffer.byteLength(requestContent, 'UTF8');
    // Send Request
    return this.client.pipeline(httpRequest, function (err, response, body) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var statusCode = response.statusCode;
      if (statusCode !== 200) {
        var error = new Error(body);
        error.statusCode = response.statusCode;
        return callback(error);
      }
      
      // Create Result
      var result = null;
      // Deserialize Response
      if (statusCode === 200) {
        var responseContent = body;
        result = {};
        var options = {};
        options.trim = false;
        options.strict = false;
        xml.parseString(responseContent, options, function (err2, responseDoc) {
          if (err2 !== null && err2 !== undefined) {
            return callback(err2);
          }
          
          var storageServiceElement = js2xml.getElement(responseDoc, responseDoc, 'STORAGESERVICE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
          if (storageServiceElement !== null && storageServiceElement !== undefined) {
            var urlElement = js2xml.getElement(responseDoc, storageServiceElement, 'URL', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
            if (urlElement !== null && urlElement !== undefined) {
              var urlInstance = urlElement;
              result.uri = urlInstance;
            }
            
            var storageServiceKeysElement = js2xml.getElement(responseDoc, storageServiceElement, 'STORAGESERVICEKEYS', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
            if (storageServiceKeysElement !== null && storageServiceKeysElement !== undefined) {
              var primaryElement = js2xml.getElement(responseDoc, storageServiceKeysElement, 'PRIMARY', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (primaryElement !== null && primaryElement !== undefined) {
                var primaryInstance = primaryElement;
                result.primaryKey = primaryInstance;
              }
              
              var secondaryElement = js2xml.getElement(responseDoc, storageServiceKeysElement, 'SECONDARY', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (secondaryElement !== null && secondaryElement !== undefined) {
                var secondaryInstance = secondaryElement;
                result.secondaryKey = secondaryInstance;
              }
            }
          }
          
        });
      }
      result.statusCode = statusCode;
      result.requestId = response.headers['x-ms-request-id'];
      
      return callback(null, result);
    });
  };
  
  /**
   * The Update Storage Account operation updates the label and the
   * description, and enables or disables the geo-replication status for a
   * storage account in Azure.  (see
   * http://msdn.microsoft.com/en-us/library/windowsazure/hh264516.aspx for
   * more information)
   * 
   * @param {string} accountName Name of the storage account to update.
   * 
   * @param {StorageAccountUpdateParameters} parameters Parameters supplied to
   * the Update Storage Account operation.
   * 
   * @param {string} [parameters.description]
   * 
   * @param {string} [parameters.label] A name for the storage account,
   * base64-encoded. The name may be up to 100 characters in length. The name
   * can be used identify the storage account for your tracking purposes.
   * 
   * @param {object} [parameters.extendedProperties] Represents the name of an
   * extended storage account property. Each extended property must have a
   * defined name and a value. You can have a maximum of 50 extended property
   * name/value pairs. The maximum length of the Name element is 64
   * characters, only alphanumeric characters and underscores are valid in the
   * Name, and the name must start with a letter. Attempting to use other
   * characters, starting the Name with a non-letter character, or entering a
   * name that is identical to that of another extended property owned by the
   * same storage account will result in a status code 400 (Bad Request)
   * error. Each extended property value has a maximum length of 255
   * characters. You can delete an extended property by setting the value to
   * NULL.
   * 
   * @param {string} [parameters.accountType] Specifies whether the account
   * supports locally-redundant storage, geo-redundant storage, zone-redundant
   * storage, or read access geo-redundant storage. Possible values
   * are:'Standard_LRS', 'Standard_ZRS', 'Standard_GRS', and 'Standard_RAGRS'.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.update = function(accountName, parameters, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    // Validate
    if (accountName === null || accountName === undefined) {
      return callback(new Error('accountName cannot be null.'));
    }
    if (accountName.length < 3) {
      return callback(new Error('accountName is outside the valid range.'));
    }
    if (accountName.length > 24) {
      return callback(new Error('accountName is outside the valid range.'));
    }
    for (var loweredIndex1 = 0; loweredIndex1 < accountName.length; loweredIndex1 = loweredIndex1 + 1) {
      var accountNameChar = accountName[loweredIndex1];
      if (accountNameChar === accountNameChar.toLowerCase() === false && isNaN(parseInt(accountNameChar, 10)) === false === false) {
        return callback(new Error('accountName is outside the valid range.'));
      }
    }
    // TODO: Validate accountName is a valid DNS name.
    if (parameters === null || parameters === undefined) {
      return callback(new Error('parameters cannot be null.'));
    }
    if (parameters.description !== null && parameters.description !== undefined && parameters.description.length > 1024) {
      return callback(new Error('parameters.description is outside the valid range.'));
    }
    
    // Tracing
    
    // Construct URL
    var url2 = '';
    url2 = url2 + '/';
    if (this.client.credentials.subscriptionId !== null && this.client.credentials.subscriptionId !== undefined) {
      url2 = url2 + encodeURIComponent(this.client.credentials.subscriptionId);
    }
    url2 = url2 + '/services/storageservices/';
    url2 = url2 + encodeURIComponent(accountName);
    var baseUrl = this.client.baseUri;
    // Trim '/' character from the end of baseUrl and beginning of url.
    if (baseUrl[baseUrl.length - 1] === '/') {
      baseUrl = baseUrl.substring(0, (baseUrl.length - 1) + 0);
    }
    if (url2[0] === '/') {
      url2 = url2.substring(1);
    }
    url2 = baseUrl + '/' + url2;
    url2 = url2.replace(' ', '%20');
    
    // Create HTTP transport objects
    var httpRequest = new WebResource();
    httpRequest.method = 'PUT';
    httpRequest.headers = {};
    httpRequest.url = url2;
    
    // Set Headers
    httpRequest.headers['Content-Type'] = 'application/xml';
    httpRequest.headers['x-ms-version'] = '2016-03-01';
    
    // Serialize Request
    var requestContent = null;
    var requestDoc = {};
    
    var updateStorageServiceInputElement = js2xml.createElement('UpdateStorageServiceInput', 'http://schemas.microsoft.com/windowsazure');
    js2xml.addChildElement(requestDoc, updateStorageServiceInputElement);
    
    if (parameters.description !== null && parameters.description !== undefined) {
      var descriptionElement = js2xml.createElement('Description', 'http://schemas.microsoft.com/windowsazure');
      js2xml.setElementValue(descriptionElement, parameters.description);
      js2xml.addChildElement(updateStorageServiceInputElement, descriptionElement);
    }
    else if (parameters.description !== undefined) {
      var emptyElement = js2xml.createElement('Description', 'http://schemas.microsoft.com/windowsazure');
      var nilAttribute = js2xml.createAttribute('nil', 'http://www.w3.org/2001/XMLSchema-instance');
      js2xml.setAttributeValue(nilAttribute, 'true');
      js2xml.addAttribute(emptyElement, nilAttribute);
      js2xml.addChildElement(updateStorageServiceInputElement, emptyElement);
    }
    
    if (parameters.label !== null && parameters.label !== undefined) {
      var labelElement = js2xml.createElement('Label', 'http://schemas.microsoft.com/windowsazure');
      js2xml.setElementValue(labelElement, new Buffer(parameters.label).toString('base64'));
      js2xml.addChildElement(updateStorageServiceInputElement, labelElement);
    }
    
    if (parameters.extendedProperties !== null && parameters.extendedProperties !== undefined) {
      var extendedPropertiesDictionaryElement = js2xml.createElement('ExtendedProperties', 'http://schemas.microsoft.com/windowsazure');
      for (var extendedPropertiesKey in parameters.extendedProperties) {
        var extendedPropertiesValue = parameters.extendedProperties[extendedPropertiesKey];
        var extendedPropertiesElement = js2xml.createElement('ExtendedProperty', 'http://schemas.microsoft.com/windowsazure');
        js2xml.addChildElement(extendedPropertiesDictionaryElement, extendedPropertiesElement);
        
        var extendedPropertiesKeyElement = js2xml.createElement('Name', 'http://schemas.microsoft.com/windowsazure');
        js2xml.setElementValue(extendedPropertiesKeyElement, extendedPropertiesKey);
        js2xml.addChildElement(extendedPropertiesElement, extendedPropertiesKeyElement);
        
        var extendedPropertiesValueElement = js2xml.createElement('Value', 'http://schemas.microsoft.com/windowsazure');
        js2xml.setElementValue(extendedPropertiesValueElement, extendedPropertiesValue);
        js2xml.addChildElement(extendedPropertiesElement, extendedPropertiesValueElement);
      }
      js2xml.addChildElement(updateStorageServiceInputElement, extendedPropertiesDictionaryElement);
    }
    
    if (parameters.accountType !== null && parameters.accountType !== undefined) {
      var accountTypeElement = js2xml.createElement('AccountType', 'http://schemas.microsoft.com/windowsazure');
      js2xml.setElementValue(accountTypeElement, parameters.accountType);
      js2xml.addChildElement(updateStorageServiceInputElement, accountTypeElement);
    }
    
    requestContent = js2xml.serializeDocument(requestDoc);
    httpRequest.body = requestContent;
    httpRequest.headers['Content-Length'] = Buffer.isBuffer(requestContent) ? requestContent.length : Buffer.byteLength(requestContent, 'UTF8');
    // Send Request
    return this.client.pipeline(httpRequest, function (err, response, body) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var statusCode = response.statusCode;
      if (statusCode !== 200) {
        var error = new Error(body);
        error.statusCode = response.statusCode;
        return callback(error);
      }
      
      // Create Result
      var result = null;
      // Deserialize Response
      result = {};
      result.statusCode = statusCode;
      result.requestId = response.headers['x-ms-request-id'];
      
      return callback(null, result);
    });
  };
  
  /**
   * Validate storage account migration api validates the given storage account
   * for IaaS Classic to ARM migration.
   * 
   * @param {string} storageAccountName Name of storage account to be migrated.
   * 
   * @param {function} callback
   * 
   * @returns {Stream} The response stream.
   */
  StorageAccountOperations.prototype.validateMigration = function(storageAccountName, callback) {
    if (callback === null || callback === undefined) {
      throw new Error('callback cannot be null.');
    }
    // Validate
    if (storageAccountName === null || storageAccountName === undefined) {
      return callback(new Error('storageAccountName cannot be null.'));
    }
    
    // Tracing
    
    // Construct URL
    var url2 = '';
    url2 = url2 + '/';
    if (this.client.credentials.subscriptionId !== null && this.client.credentials.subscriptionId !== undefined) {
      url2 = url2 + encodeURIComponent(this.client.credentials.subscriptionId);
    }
    url2 = url2 + '/services/storageservices/';
    url2 = url2 + encodeURIComponent(storageAccountName);
    url2 = url2 + '/migration';
    var queryParameters = [];
    queryParameters.push('comp=validate');
    if (queryParameters.length > 0) {
      url2 = url2 + '?' + queryParameters.join('&');
    }
    var baseUrl = this.client.baseUri;
    // Trim '/' character from the end of baseUrl and beginning of url.
    if (baseUrl[baseUrl.length - 1] === '/') {
      baseUrl = baseUrl.substring(0, (baseUrl.length - 1) + 0);
    }
    if (url2[0] === '/') {
      url2 = url2.substring(1);
    }
    url2 = baseUrl + '/' + url2;
    url2 = url2.replace(' ', '%20');
    
    // Create HTTP transport objects
    var httpRequest = new WebResource();
    httpRequest.method = 'POST';
    httpRequest.headers = {};
    httpRequest.url = url2;
    
    // Set Headers
    httpRequest.headers['x-ms-version'] = '2016-03-01';
    
    // Send Request
    return this.client.pipeline(httpRequest, function (err, response, body) {
      if (err !== null && err !== undefined) {
        return callback(err);
      }
      var statusCode = response.statusCode;
      if (statusCode !== 200) {
        var error = new Error(body);
        error.statusCode = response.statusCode;
        return callback(error);
      }
      
      // Create Result
      var result = null;
      // Deserialize Response
      if (statusCode === 200) {
        var responseContent = body;
        result = { validateStorageMessages: [] };
        var options = {};
        options.trim = false;
        options.strict = false;
        xml.parseString(responseContent, options, function (err2, responseDoc) {
          if (err2 !== null && err2 !== undefined) {
            return callback(err2);
          }
          
          var validationMessagesSequenceElement = js2xml.getElement(responseDoc, responseDoc, 'VALIDATIONMESSAGES', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
          if (validationMessagesSequenceElement !== null && validationMessagesSequenceElement !== undefined) {
            for (var loweredIndex1 = 0; loweredIndex1 < js2xml.getElements(responseDoc, validationMessagesSequenceElement, 'VALIDATIONMESSAGE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE').length; loweredIndex1 = loweredIndex1 + 1) {
              var validationMessagesElement = js2xml.getElements(responseDoc, validationMessagesSequenceElement, 'VALIDATIONMESSAGE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE')[loweredIndex1];
              var validationMessageInstance = {};
              result.validateStorageMessages.push(validationMessageInstance);
              
              var resourceTypeElement = js2xml.getElement(responseDoc, validationMessagesElement, 'RESOURCETYPE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (resourceTypeElement !== null && resourceTypeElement !== undefined) {
                var resourceTypeInstance = resourceTypeElement;
                validationMessageInstance.resourceType = resourceTypeInstance;
              }
              
              var resourceNameElement = js2xml.getElement(responseDoc, validationMessagesElement, 'RESOURCENAME', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (resourceNameElement !== null && resourceNameElement !== undefined) {
                var resourceNameInstance = resourceNameElement;
                validationMessageInstance.resourceName = resourceNameInstance;
              }
              
              var categoryElement = js2xml.getElement(responseDoc, validationMessagesElement, 'CATEGORY', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (categoryElement !== null && categoryElement !== undefined) {
                var categoryInstance = categoryElement;
                validationMessageInstance.category = categoryInstance;
              }
              
              var messageElement = js2xml.getElement(responseDoc, validationMessagesElement, 'MESSAGE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (messageElement !== null && messageElement !== undefined) {
                var messageInstance = messageElement;
                validationMessageInstance.message = messageInstance;
              }
              
              var virtualMachineElement = js2xml.getElement(responseDoc, validationMessagesElement, 'VIRTUALMACHINE', 'HTTP://SCHEMAS.MICROSOFT.COM/WINDOWSAZURE');
              if (virtualMachineElement !== null && virtualMachineElement !== undefined) {
                var virtualMachineInstance = virtualMachineElement;
                validationMessageInstance.virtualMachineName = virtualMachineInstance;
              }
            }
          }
          
        });
      }
      result.statusCode = statusCode;
      result.requestId = response.headers['x-ms-request-id'];
      
      return callback(null, result);
    });
  };
  
  return StorageAccountOperations;
})();
