/*******************************************************************************
 * Copyright 2008-2010 Amazon.com, Inc. or its affiliates. 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. A copy of the License is located at
 *
 * http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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.
 * *****************************************************************************
 *    __  _    _  ___
 *   (  )( \/\/ )/ __)
 *   /__\ \    / \__ \
 *  (_)(_) \/\/  (___/
 *
 *  AWS SDK for .NET
 *  API Version: 2009-11-30
 */

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.XPath;
using System.Xml.Xsl;

using Amazon.EC2.Model;
using Amazon.EC2.Util;

using Amazon.Util;

namespace Amazon.EC2
{
    /// <summary>
    /// AmazonEC2Client is an implementation of AmazonEC2
    /// The Amazon Elastic Compute Cloud (Amazon EC2) web service provides you with
    /// the ability to execute your applications in Amazon's computing environment.
    /// To use Amazon EC2 you simply:
    /// 1. Create an Amazon Machine Image (AMI) containing all your software, including
    /// your operating system and associated configuration settings, applications,
    /// libraries, etc. Think of this as zipping up the contents of your hard drive. We
    /// provide all the necessary tools to create and package your AMI.
    /// 2. Upload this AMI to the Amazon S3 (Amazon Simple Storage Service) service. This
    /// gives us reliable, secure access to your AMI.
    /// 3. Register your AMI with Amazon EC2. This allows us to verify that your AMI has
    /// been uploaded correctly and to allocate a unique identifier for it.
    /// 4. Use this AMI ID and the Amazon EC2 web service APIs to run, monitor, and
    /// terminate as many instances of this AMI as required.
    /// You can also skip the first three steps and choose to launch an AMI that is
    /// provided by Amazon or shared by another user.
    /// While instances are running, you are billed for the computing and network
    /// resources that they consume.
    /// You can also skip the first three steps and choose to launch an AMI that is
    /// provided by Amazon or shared by another user.
    /// While instances are running, you are billed for the computing and network
    /// resources that they consume.
    /// </summary>
    public class AmazonEC2Client : AmazonEC2
    {
        private string awsAccessKeyId;
        private SecureString awsSecretAccessKey;
        private AmazonEC2Config config;
        private bool disposed;

        #region Dispose Pattern Implementation

        /// <summary>
        /// Implements the Dispose pattern for the AmazonEC2Client
        /// </summary>
        /// <param name="fDisposing">Whether this object is being disposed via a call to Dispose
        /// or garbage collected.</param>
        protected virtual void Dispose(bool fDisposing)
        {
            if (!this.disposed)
            {
                if (fDisposing)
                {
                    //Remove Unmanaged Resources
                    // I.O.W. remove resources that have to be explicitly
                    // "Dispose"d or Closed
                    if (awsSecretAccessKey != null)
                    {
                        awsSecretAccessKey.Dispose();
                        awsSecretAccessKey = null;
                    }
                }
                this.disposed = true;
            }
        }

        /// <summary>
        /// Disposes of all managed and unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// The destructor for the client class.
        /// </summary>
        ~AmazonEC2Client()
        {
            this.Dispose(false);
        }

        #endregion

        /// <summary>
        /// Constructs AmazonEC2Client with AWS Access Key ID and AWS Secret Key
        /// </summary>
        /// <param name="awsAccessKeyId">AWS Access Key ID</param>
        /// <param name="awsSecretAccessKey">AWS Secret Access Key</param>
        public AmazonEC2Client(string awsAccessKeyId, string awsSecretAccessKey)
            : this(awsAccessKeyId, awsSecretAccessKey, new AmazonEC2Config())
        {
        }

        /// <summary>
        /// Constructs AmazonEC2Client with AWS Access Key ID, AWS Secret Key and an
        /// AmazonEC2 Configuration object
        /// </summary>
        /// <param name="awsAccessKeyId">AWS Access Key ID</param>
        /// <param name="awsSecretAccessKey">AWS Secret Access Key</param>
        /// <param name="config">The AmazonEC2 Configuration Object</param>
        public AmazonEC2Client(string awsAccessKeyId, string awsSecretAccessKey, AmazonEC2Config config)
        {
            if (awsSecretAccessKey != null)
            {
                this.awsSecretAccessKey = new SecureString();
                foreach (char ch in awsSecretAccessKey.ToCharArray())
                {
                    this.awsSecretAccessKey.AppendChar(ch);
                }
                this.awsSecretAccessKey.MakeReadOnly();
            }
            this.awsAccessKeyId = awsAccessKeyId;
            this.config = config;
            ServicePointManager.Expect100Continue = false;
            ServicePointManager.UseNagleAlgorithm = false;
        }

        /// <summary>
        /// Constructs an AmazonEC2Client with AWS Access Key ID, AWS Secret Key and an
        /// AmazonEC2 Configuration object
        /// </summary>
        /// <param name="awsAccessKeyId">AWS Access Key ID</param>
        /// <param name="awsSecretAccessKey">AWS Secret Access Key as a SecureString</param>
        /// <param name="config">The AmazonEC2 Configuration Object</param>
        public AmazonEC2Client(string awsAccessKeyId, SecureString awsSecretAccessKey, AmazonEC2Config config)
        {
            this.awsAccessKeyId = awsAccessKeyId;
            this.awsSecretAccessKey = awsSecretAccessKey;
            this.config = config;
            ServicePointManager.Expect100Continue = false;
            ServicePointManager.UseNagleAlgorithm = false;
        }

        #region Public API

        /// <summary>
        /// Allocate Address
        /// </summary>
        /// <param name="request">Allocate Address  request</param>
        /// <returns>Allocate Address  Response from the service</returns>
        /// <remarks>
        /// The AllocateAddress operation acquires an elastic IP address for use with your
        /// account.
        /// </remarks>
        public AllocateAddressResponse AllocateAddress(AllocateAddressRequest request)
        {
            return Invoke<AllocateAddressResponse>(ConvertAllocateAddress(request));
        }

        /// <summary>
        /// Associate Address
        /// </summary>
        /// <param name="request">Associate Address  request</param>
        /// <returns>Associate Address  Response from the service</returns>
        /// <remarks>
        /// The AssociateAddress operation associates an elastic IP address with an
        /// instance.
        /// If the IP address is currently assigned to another instance, the IP address is
        /// assigned to the new instance. This is an idempotent operation. If you enter it
        /// more than once, Amazon EC2 does not return an error.
        /// </remarks>
        public AssociateAddressResponse AssociateAddress(AssociateAddressRequest request)
        {
            return Invoke<AssociateAddressResponse>(ConvertAssociateAddress(request));
        }

        /// <summary>
        /// Attach Volume
        /// </summary>
        /// <param name="request">Attach Volume  request</param>
        /// <returns>Attach Volume  Response from the service</returns>
        /// <remarks>
        /// Attach a previously created volume to a running instance.
        /// </remarks>
        public AttachVolumeResponse AttachVolume(AttachVolumeRequest request)
        {
            return Invoke<AttachVolumeResponse>(ConvertAttachVolume(request));
        }

        /// <summary>
        /// Authorize Security Group Ingress
        /// </summary>
        /// <param name="request">Authorize Security Group Ingress  request</param>
        /// <returns>Authorize Security Group Ingress  Response from the service</returns>
        /// <remarks>
        /// The AuthorizeSecurityGroupIngress operation adds permissions to a security
        /// group.
        /// Permissions are specified by the IP protocol (TCP, UDP or ICMP), the source of
        /// the request (by IP range or an Amazon EC2 user-group pair), the source and
        /// destination port ranges (for TCP and UDP), and the ICMP codes and types (for
        /// ICMP). When authorizing ICMP, -1 can be used as a wildcard in the type and code
        /// fields.
        /// Permission changes are propagated to instances within the security group as
        /// quickly as possible. However, depending on the number of instances, a small
        /// delay might occur.
        /// When authorizing a user/group pair permission, GroupName,
        /// SourceSecurityGroupName and SourceSecurityGroupOwnerId must be specified. When
        /// authorizing a CIDR IP permission, GroupName, IpProtocol, FromPort, ToPort and
        /// CidrIp must be specified. Mixing these two types of parameters is not allowed.
        /// </remarks>
        public AuthorizeSecurityGroupIngressResponse AuthorizeSecurityGroupIngress(AuthorizeSecurityGroupIngressRequest request)
        {
            return Invoke<AuthorizeSecurityGroupIngressResponse>(ConvertAuthorizeSecurityGroupIngress(request));
        }

        /// <summary>
        /// Bundle Instance
        /// </summary>
        /// <param name="request">Bundle Instance  request</param>
        /// <returns>Bundle Instance  Response from the service</returns>
        /// <remarks>
        /// The BundleInstance operation request that an instance is bundled the next time it boots.
        /// The bundling process creates a new image from a running instance and stores
        /// the AMI data in S3. Once bundled, the image must be registered in the normal
        /// way using the RegisterImage API.
        /// </remarks>
        public BundleInstanceResponse BundleInstance(BundleInstanceRequest request)
        {
            S3Storage s3 = request.Storage.S3;
            // Check to see if S3 upload policy was set on request.
            // If not, generate. Set expiration to 24 hours.
            if (!s3.IsSetUploadPolicy())
            {
                s3.AWSAccessKeyId = this.awsAccessKeyId;
                S3UploadPolicy policy = new S3UploadPolicy(
                    this.awsAccessKeyId,
                    this.awsSecretAccessKey,
                    s3.Bucket,
                    s3.Prefix,
                    1440
                    );
                s3.UploadPolicy = policy.PolicyString;
                s3.UploadPolicySignature = policy.PolicySignature;
            }
            return Invoke<BundleInstanceResponse>(ConvertBundleInstance(request));
        }

        /// <summary>
        /// Cancel Bundle Task
        /// </summary>
        /// <param name="request">Cancel Bundle Task  request</param>
        /// <returns>Cancel Bundle Task  Response from the service</returns>
        /// <remarks>
        /// CancelBundleTask operation cancels a pending or
        /// in-progress bundling task. This is an asynchronous
        /// call and it make take a while for the task to be cancelled.
        /// If a task is cancelled while it is storing items,
        /// there may be parts of the incomplete AMI stored in S3.
        /// It is up to the caller to clean up these parts from S3.
        /// </remarks>
        public CancelBundleTaskResponse CancelBundleTask(CancelBundleTaskRequest request)
        {
            return Invoke<CancelBundleTaskResponse>(ConvertCancelBundleTask(request));
        }

        /// <summary>
        /// Confirm Product Instance
        /// </summary>
        /// <param name="request">Confirm Product Instance  request</param>
        /// <returns>Confirm Product Instance  Response from the service</returns>
        /// <remarks>
        /// The ConfirmProductInstance operation returns true if the specified product code
        /// is attached to the specified instance. The operation returns false if the
        /// product code is not attached to the instance.
        /// The ConfirmProductInstance operation can only be executed by the owner of the
        /// AMI. This feature is useful when an AMI owner is providing support and wants to
        /// verify whether a user's instance is eligible.
        /// </remarks>
        public ConfirmProductInstanceResponse ConfirmProductInstance(ConfirmProductInstanceRequest request)
        {
            return Invoke<ConfirmProductInstanceResponse>(ConvertConfirmProductInstance(request));
        }

        /// <summary>
        /// Create Image
        /// </summary>
        /// <param name="request">Create Image  request</param>
        /// <returns>Create Image  Response from the service</returns>
        /// <remarks>
        /// Creates an AMI that uses an Amazon EBS root device from a "running" or "stopped" instance.
        /// AMIs that use an Amazon EBS root device boot faster than AMIs that use instance stores. They can be
        /// up to 1 TiB in size, use storage that persists on instance failure, and can be stopped and started.
        /// </remarks>
        public CreateImageResponse CreateImage(CreateImageRequest request)
        {
            return Invoke<CreateImageResponse>(ConvertCreateImage(request));
        }

        /// <summary>
        /// Create Key Pair
        /// </summary>
        /// <param name="request">Create Key Pair  request</param>
        /// <returns>Create Key Pair  Response from the service</returns>
        /// <remarks>
        /// The CreateKeyPair operation creates a new 2048 bit RSA key pair and returns a
        /// unique ID that can be used to reference this key pair when launching new
        /// instances. For more information, see RunInstances.
        /// </remarks>
        public CreateKeyPairResponse CreateKeyPair(CreateKeyPairRequest request)
        {
            return Invoke<CreateKeyPairResponse>(ConvertCreateKeyPair(request));
        }

        /// <summary>
        /// Create Security Group
        /// </summary>
        /// <param name="request">Create Security Group  request</param>
        /// <returns>Create Security Group  Response from the service</returns>
        /// <remarks>
        /// The CreateSecurityGroup operation creates a new security group.
        /// Every instance is launched in a security group. If no security group is
        /// specified during launch, the instances are launched in the default security
        /// group. Instances within the same security group have unrestricted network
        /// access to each other. Instances will reject network access attempts from other
        /// instances in a different security group. As the owner of instances you can
        /// grant or revoke specific permissions using the AuthorizeSecurityGroupIngress
        /// and RevokeSecurityGroupIngress operations.
        /// </remarks>
        public CreateSecurityGroupResponse CreateSecurityGroup(CreateSecurityGroupRequest request)
        {
            return Invoke<CreateSecurityGroupResponse>(ConvertCreateSecurityGroup(request));
        }

        /// <summary>
        /// Create Snapshot
        /// </summary>
        /// <param name="request">Create Snapshot  request</param>
        /// <returns>Create Snapshot  Response from the service</returns>
        /// <remarks>
        /// Create a snapshot of the volume identified by volume ID. A volume does not have to be detached
        /// at the time the snapshot is taken.
        /// Important Note:
        /// Snapshot creation requires that the system is in a consistent state.
        /// For instance, this means that if taking a snapshot of a database, the tables must
        /// be read-only locked to ensure that the snapshot will not contain a corrupted
        /// version of the database.  Therefore, be careful when using this API to ensure that
        /// the system remains in the consistent state until the create snapshot status
        /// has returned.
        /// </remarks>
        public CreateSnapshotResponse CreateSnapshot(CreateSnapshotRequest request)
        {
            return Invoke<CreateSnapshotResponse>(ConvertCreateSnapshot(request));
        }

        /// <summary>
        /// Create Volume
        /// </summary>
        /// <param name="request">Create Volume  request</param>
        /// <returns>Create Volume  Response from the service</returns>
        /// <remarks>
        /// Initializes an empty volume of a given size
        /// </remarks>
        public CreateVolumeResponse CreateVolume(CreateVolumeRequest request)
        {
            return Invoke<CreateVolumeResponse>(ConvertCreateVolume(request));
        }

        /// <summary>
        /// Delete Key Pair
        /// </summary>
        /// <param name="request">Delete Key Pair  request</param>
        /// <returns>Delete Key Pair  Response from the service</returns>
        /// <remarks>
        /// The DeleteKeyPair operation deletes a key pair.
        /// </remarks>
        public DeleteKeyPairResponse DeleteKeyPair(DeleteKeyPairRequest request)
        {
            return Invoke<DeleteKeyPairResponse>(ConvertDeleteKeyPair(request));
        }

        /// <summary>
        /// Delete Security Group
        /// </summary>
        /// <param name="request">Delete Security Group  request</param>
        /// <returns>Delete Security Group  Response from the service</returns>
        /// <remarks>
        /// The DeleteSecurityGroup operation deletes a security group.
        /// Note:
        /// If you attempt to delete a security group that contains instances, a fault is
        /// returned.
        /// If you attempt to delete a security group that is referenced by another
        /// security group, a fault is returned. For example, if security group B has a
        /// rule that allows access from security group A, security group A cannot be
        /// deleted until the allow rule is removed.
        /// </remarks>
        public DeleteSecurityGroupResponse DeleteSecurityGroup(DeleteSecurityGroupRequest request)
        {
            return Invoke<DeleteSecurityGroupResponse>(ConvertDeleteSecurityGroup(request));
        }

        /// <summary>
        /// Delete Snapshot
        /// </summary>
        /// <param name="request">Delete Snapshot  request</param>
        /// <returns>Delete Snapshot  Response from the service</returns>
        /// <remarks>
        /// Deletes the snapshot identitied by snapshotId.
        /// </remarks>
        public DeleteSnapshotResponse DeleteSnapshot(DeleteSnapshotRequest request)
        {
            return Invoke<DeleteSnapshotResponse>(ConvertDeleteSnapshot(request));
        }

        /// <summary>
        /// Delete Volume
        /// </summary>
        /// <param name="request">Delete Volume  request</param>
        /// <returns>Delete Volume  Response from the service</returns>
        /// <remarks>
        /// Deletes a  previously created volume. Once successfully deleted, a new volume  can be created with the same name.
        /// </remarks>
        public DeleteVolumeResponse DeleteVolume(DeleteVolumeRequest request)
        {
            return Invoke<DeleteVolumeResponse>(ConvertDeleteVolume(request));
        }

        /// <summary>
        /// Deregister Image
        /// </summary>
        /// <param name="request">Deregister Image  request</param>
        /// <returns>Deregister Image  Response from the service</returns>
        /// <remarks>
        /// The DeregisterImage operation deregisters an AMI. Once deregistered, instances
        /// of the AMI can no longer be launched.
        /// </remarks>
        public DeregisterImageResponse DeregisterImage(DeregisterImageRequest request)
        {
            return Invoke<DeregisterImageResponse>(ConvertDeregisterImage(request));
        }

        /// <summary>
        /// Describe Addresses
        /// </summary>
        /// <param name="request">Describe Addresses  request</param>
        /// <returns>Describe Addresses  Response from the service</returns>
        /// <remarks>
        /// The DescribeAddresses operation lists elastic IP addresses assigned to your
        /// account.
        /// </remarks>
        public DescribeAddressesResponse DescribeAddresses(DescribeAddressesRequest request)
        {
            return Invoke<DescribeAddressesResponse>(ConvertDescribeAddresses(request));
        }

        /// <summary>
        /// Describe Availability Zones
        /// </summary>
        /// <param name="request">Describe Availability Zones  request</param>
        /// <returns>Describe Availability Zones  Response from the service</returns>
        /// <remarks>
        /// The DescribeAvailabilityZones operation describes availability zones that are
        /// currently available to the account and their states.
        /// Availability zones are not the same across accounts. The availability zone
        /// us-east-1a for account A is not necessarily the same as us-east-1a for account
        /// B. Zone assignments are mapped independently for each account.
        /// </remarks>
        public DescribeAvailabilityZonesResponse DescribeAvailabilityZones(DescribeAvailabilityZonesRequest request)
        {
            return Invoke<DescribeAvailabilityZonesResponse>(ConvertDescribeAvailabilityZones(request));
        }

        /// <summary>
        /// Describe Bundle Tasks
        /// </summary>
        /// <param name="request">Describe Bundle Tasks  request</param>
        /// <returns>Describe Bundle Tasks  Response from the service</returns>
        /// <remarks>
        /// The DescribeBundleTasks operation describes in-progress
        /// and recent bundle tasks. Complete and failed tasks are
        /// removed from the list a short time after completion.
        /// If no bundle ids are given, all bundle tasks are returned.
        /// </remarks>
        public DescribeBundleTasksResponse DescribeBundleTasks(DescribeBundleTasksRequest request)
        {
            return Invoke<DescribeBundleTasksResponse>(ConvertDescribeBundleTasks(request));
        }

        /// <summary>
        /// Describe Snapshot Attribute
        /// </summary>
        /// <param name="request">Describe Snapshot Attribute  request</param>
        /// <returns>Describe Snapshot Attribute  Response from the service</returns>
        /// <remarks>
        /// Returns information about an attribute of a snapshot.
        /// Only one attribute can be specified per call.
        /// </remarks>
        public DescribeSnapshotAttributeResponse DescribeSnapshotAttribute(DescribeSnapshotAttributeRequest request)
        {
            return Invoke<DescribeSnapshotAttributeResponse>(ConvertDescribeSnapshotAttribute(request));
        }

        /// <summary>
        /// Describe Image Attribute
        /// </summary>
        /// <param name="request">Describe Image Attribute  request</param>
        /// <returns>Describe Image Attribute  Response from the service</returns>
        /// <remarks>
        /// The DescribeImageAttribute operation returns information about an attribute of
        /// an AMI. Only one attribute can be specified per call.
        /// </remarks>
        public DescribeImageAttributeResponse DescribeImageAttribute(DescribeImageAttributeRequest request)
        {
            return Invoke<DescribeImageAttributeResponse>(ConvertDescribeImageAttribute(request));
        }

        /// <summary>
        /// Describe Images
        /// </summary>
        /// <param name="request">Describe Images  request</param>
        /// <returns>Describe Images  Response from the service</returns>
        /// <remarks>
        /// The DescribeImages operation returns information about AMIs, AKIs, and ARIs
        /// available to the user. Information returned includes image type, product codes,
        /// architecture, and kernel and RAM disk IDs. Images available to the user include
        /// public images available for any user to launch, private images owned by the
        /// user making the request, and private images owned by other users for which the
        /// user has explicit launch permissions.
        /// Launch permissions fall into three categories:
        /// Public:
        /// The owner of the AMI granted launch permissions for the AMI to the all group.
        /// All users have launch permissions for these AMIs.
        /// Explicit:
        /// The owner of the AMI granted launch permissions to a specific user.
        /// Implicit:
        /// A user has implicit launch permissions for all AMIs he or she owns.
        /// The list of AMIs returned can be modified by specifying AMI IDs, AMI owners, or
        /// users with launch permissions. If no options are specified, Amazon EC2 returns
        /// all AMIs for which the user has launch permissions.
        /// If you specify one or more AMI IDs, only AMIs that have the specified IDs are
        /// returned. If you specify an invalid AMI ID, a fault is returned. If you specify
        /// an AMI ID for which you do not have access, it will not be included in the
        /// returned results.
        /// If you specify one or more AMI owners, only AMIs from the specified owners and
        /// for which you have access are returned. The results can include the account IDs
        /// of the specified owners, amazon for AMIs owned by Amazon or self for AMIs that
        /// you own.
        /// If you specify a list of executable users, only users that have launch
        /// permissions for the AMIs are returned. You can specify account IDs (if you own
        /// the AMI(s)), self for AMIs for which you own or have explicit permissions, or
        /// all for public AMIs.
        /// Note:
        /// Deregistered images are included in the returned results for an unspecified
        /// interval after deregistration.
        /// </remarks>
        public DescribeImagesResponse DescribeImages(DescribeImagesRequest request)
        {
            return Invoke<DescribeImagesResponse>(ConvertDescribeImages(request));
        }

        /// <summary>
        /// Describe Instances
        /// </summary>
        /// <param name="request">Describe Instances  request</param>
        /// <returns>Describe Instances  Response from the service</returns>
        /// <remarks>
        /// The DescribeInstances operation returns information about instances that you
        /// own.
        /// If you specify one or more instance IDs, Amazon EC2 returns information for
        /// those instances. If you do not specify instance IDs, Amazon EC2 returns
        /// information for all relevant instances. If you specify an invalid instance ID,
        /// a fault is returned. If you specify an instance that you do not own, it will
        /// not be included in the returned results.
        /// Recently terminated instances might appear in the returned results. This
        /// interval is usually less than one hour.
        /// </remarks>
        public DescribeInstancesResponse DescribeInstances(DescribeInstancesRequest request)
        {
            return Invoke<DescribeInstancesResponse>(ConvertDescribeInstances(request));
        }

        /// <summary>
        /// Describe Regions
        /// </summary>
        /// <param name="request">Describe Regions  request</param>
        /// <returns>Describe Regions  Response from the service</returns>
        /// <remarks>
        /// The DescribeRegions operation describes regions zones that are currently available to the account.
        /// </remarks>
        public DescribeRegionsResponse DescribeRegions(DescribeRegionsRequest request)
        {
            return Invoke<DescribeRegionsResponse>(ConvertDescribeRegions(request));
        }

        /// <summary>
        /// Describe Reserved Instances
        /// </summary>
        /// <param name="request">Describe Reserved Instances  request</param>
        /// <returns>Describe Reserved Instances  Response from the service</returns>
        /// <remarks>
        /// The DescribeReservedInstances operation describes Reserved Instances that were purchased for use with your account.
        /// </remarks>
        public DescribeReservedInstancesResponse DescribeReservedInstances(DescribeReservedInstancesRequest request)
        {
            return Invoke<DescribeReservedInstancesResponse>(ConvertDescribeReservedInstances(request));
        }

        /// <summary>
        /// Describe Reserved Instances Offerings
        /// </summary>
        /// <param name="request">Describe Reserved Instances Offerings  request</param>
        /// <returns>Describe Reserved Instances Offerings  Response from the service</returns>
        /// <remarks>
        /// The DescribeReservedInstancesOfferings operation describes Reserved
        /// Instance offerings that are available for purchase. With Amazon EC2
        /// Reserved Instances, you purchase the right to launch Amazon EC2 instances
        /// for a period of time (without getting insufficient capacity errors) and
        /// pay a lower usage rate for the actual time used.
        /// </remarks>
        public DescribeReservedInstancesOfferingsResponse DescribeReservedInstancesOfferings(DescribeReservedInstancesOfferingsRequest request)
        {
            return Invoke<DescribeReservedInstancesOfferingsResponse>(ConvertDescribeReservedInstancesOfferings(request));
        }

        /// <summary>
        /// Describe Key Pairs
        /// </summary>
        /// <param name="request">Describe Key Pairs  request</param>
        /// <returns>Describe Key Pairs  Response from the service</returns>
        /// <remarks>
        /// The DescribeKeyPairs operation returns information about key pairs available to
        /// you. If you specify key pairs, information about those key pairs is returned.
        /// Otherwise, information for all registered key pairs is returned.
        /// </remarks>
        public DescribeKeyPairsResponse DescribeKeyPairs(DescribeKeyPairsRequest request)
        {
            return Invoke<DescribeKeyPairsResponse>(ConvertDescribeKeyPairs(request));
        }

        /// <summary>
        /// Describe Security Groups
        /// </summary>
        /// <param name="request">Describe Security Groups  request</param>
        /// <returns>Describe Security Groups  Response from the service</returns>
        /// <remarks>
        /// The DescribeSecurityGroups operation returns information about security groups
        /// that you own.
        /// If you specify security group names, information about those security group is
        /// returned. Otherwise, information for all security group is returned. If you
        /// specify a group that does not exist, a fault is returned.
        /// </remarks>
        public DescribeSecurityGroupsResponse DescribeSecurityGroups(DescribeSecurityGroupsRequest request)
        {
            return Invoke<DescribeSecurityGroupsResponse>(ConvertDescribeSecurityGroups(request));
        }

        /// <summary>
        /// Describe Snapshots
        /// </summary>
        /// <param name="request">Describe Snapshots  request</param>
        /// <returns>Describe Snapshots  Response from the service</returns>
        /// <remarks>
        /// Describes the indicated snapshots, or in lieu of that, all snapshots owned by the caller.
        /// </remarks>
        public DescribeSnapshotsResponse DescribeSnapshots(DescribeSnapshotsRequest request)
        {
            return Invoke<DescribeSnapshotsResponse>(ConvertDescribeSnapshots(request));
        }

        /// <summary>
        /// Describe Volumes
        /// </summary>
        /// <param name="request">Describe Volumes  request</param>
        /// <returns>Describe Volumes  Response from the service</returns>
        /// <remarks>
        /// Describes the status of the indicated or, in lieu of any specified,  all volumes belonging to the caller.
        /// Volumes that have been deleted are not described.
        /// </remarks>
        public DescribeVolumesResponse DescribeVolumes(DescribeVolumesRequest request)
        {
            return Invoke<DescribeVolumesResponse>(ConvertDescribeVolumes(request));
        }

        /// <summary>
        /// Detach Volume
        /// </summary>
        /// <param name="request">Detach Volume  request</param>
        /// <returns>Detach Volume  Response from the service</returns>
        /// <remarks>
        /// Detach a previously attached volume from a running instance.
        /// </remarks>
        public DetachVolumeResponse DetachVolume(DetachVolumeRequest request)
        {
            return Invoke<DetachVolumeResponse>(ConvertDetachVolume(request));
        }

        /// <summary>
        /// Disassociate Address
        /// </summary>
        /// <param name="request">Disassociate Address  request</param>
        /// <returns>Disassociate Address  Response from the service</returns>
        /// <remarks>
        /// The DisassociateAddress operation disassociates the specified elastic IP
        /// address from the instance to which it is assigned. This is an idempotent
        /// operation. If you enter it more than once, Amazon EC2 does not return an error.
        /// </remarks>
        public DisassociateAddressResponse DisassociateAddress(DisassociateAddressRequest request)
        {
            return Invoke<DisassociateAddressResponse>(ConvertDisassociateAddress(request));
        }

        /// <summary>
        /// Get Password Data
        /// </summary>
        /// <param name="request">Get Password Data  request</param>
        /// <returns>Get Password Data  Response from the service</returns>
        /// <remarks>
        /// Retrieves the encrypted administrator password for the instances running Windows.
        /// </remarks>
        public GetPasswordDataResponse GetPasswordData(GetPasswordDataRequest request)
        {
            return Invoke<GetPasswordDataResponse>(ConvertGetPasswordData(request));
        }

        /// <summary>
        /// Get Console Output
        /// </summary>
        /// <param name="request">Get Console Output  request</param>
        /// <returns>Get Console Output  Response from the service</returns>
        /// <remarks>
        /// The GetConsoleOutput operation retrieves console output for the specified
        /// instance.
        /// Instance console output is buffered and posted shortly after instance boot,
        /// reboot, and termination. Amazon EC2 preserves the most recent 64 KB output
        /// which will be available for at least one hour after the most recent post.
        /// </remarks>
        public GetConsoleOutputResponse GetConsoleOutput(GetConsoleOutputRequest request)
        {
            return Invoke<GetConsoleOutputResponse>(ConvertGetConsoleOutput(request));
        }

        /// <summary>
        /// Modify Snapshot Attribute
        /// </summary>
        /// <param name="request">Modify Snapshot Attribute  request</param>
        /// <returns>Modify Snapshot Attribute  Response from the service</returns>
        /// <remarks>
        /// Adds or remove permission settings for the specified snapshot.
        /// </remarks>
        public ModifySnapshotAttributeResponse ModifySnapshotAttribute(ModifySnapshotAttributeRequest request)
        {
            return Invoke<ModifySnapshotAttributeResponse>(ConvertModifySnapshotAttribute(request));
        }

        /// <summary>
        /// Modify Image Attribute
        /// </summary>
        /// <param name="request">Modify Image Attribute  request</param>
        /// <returns>Modify Image Attribute  Response from the service</returns>
        /// <remarks>
        /// The ModifyImageAttribute operation modifies an attribute of an AMI.
        /// </remarks>
        public ModifyImageAttributeResponse ModifyImageAttribute(ModifyImageAttributeRequest request)
        {
            return Invoke<ModifyImageAttributeResponse>(ConvertModifyImageAttribute(request));
        }

        /// <summary>
        /// Purchase Reserved Instances Offering
        /// </summary>
        /// <param name="request">Purchase Reserved Instances Offering  request</param>
        /// <returns>Purchase Reserved Instances Offering  Response from the service</returns>
        /// <remarks>
        /// The PurchaseReservedInstancesOffering operation purchases a
        /// Reserved Instance for use with your account. With Amazon EC2
        /// Reserved Instances, you purchase the right to launch Amazon EC2
        /// instances for a period of time (without getting insufficient
        /// capacity errors) and pay a lower usage rate for the
        /// actual time used.
        /// </remarks>
        public PurchaseReservedInstancesOfferingResponse PurchaseReservedInstancesOffering(PurchaseReservedInstancesOfferingRequest request)
        {
            return Invoke<PurchaseReservedInstancesOfferingResponse>(ConvertPurchaseReservedInstancesOffering(request));
        }

        /// <summary>
        /// Reboot Instances
        /// </summary>
        /// <param name="request">Reboot Instances  request</param>
        /// <returns>Reboot Instances  Response from the service</returns>
        /// <remarks>
        /// The RebootInstances operation requests a reboot of one or more instances. This
        /// operation is asynchronous; it only queues a request to reboot the specified
        /// instance(s). The operation will succeed if the instances are valid and belong
        /// to the user. Requests to reboot terminated instances are ignored.
        /// </remarks>
        public RebootInstancesResponse RebootInstances(RebootInstancesRequest request)
        {
            return Invoke<RebootInstancesResponse>(ConvertRebootInstances(request));
        }

        /// <summary>
        /// Register Image
        /// </summary>
        /// <param name="request">Register Image  request</param>
        /// <returns>Register Image  Response from the service</returns>
        /// <remarks>
        /// The RegisterImage operation registers an AMI with Amazon EC2. Images must be
        /// registered before they can be launched. For more information, see RunInstances.
        /// Each AMI is associated with an unique ID which is provided by the Amazon EC2
        /// service through the RegisterImage operation. During registration, Amazon EC2
        /// retrieves the specified image manifest from Amazon S3 and verifies that the
        /// image is owned by the user registering the image.
        /// The image manifest is retrieved once and stored within the Amazon EC2. Any
        /// modifications to an image in Amazon S3 invalidates this registration. If you
        /// make changes to an image, deregister the previous image and register the new
        /// image. For more information, see DeregisterImage.
        /// </remarks>
        public RegisterImageResponse RegisterImage(RegisterImageRequest request)
        {
            return Invoke<RegisterImageResponse>(ConvertRegisterImage(request));
        }

        /// <summary>
        /// Release Address
        /// </summary>
        /// <param name="request">Release Address  request</param>
        /// <returns>Release Address  Response from the service</returns>
        /// <remarks>
        /// The ReleaseAddress operation releases an elastic IP address associated with
        /// your account.
        /// Note:
        /// Releasing an IP address automatically disassociates it from any instance with
        /// which it is associated. For more information, see DisassociateAddress.
        /// Important:
        /// After releasing an elastic IP address, it is released to the IP address pool
        /// and might no longer be available to your account. Make sure to update your DNS
        /// records and any servers or devices that communicate with the address.
        /// If you run this operation on an elastic IP address that is already released,
        /// the address might be assigned to another account which will cause Amazon EC2 to
        /// return an error.
        /// </remarks>
        public ReleaseAddressResponse ReleaseAddress(ReleaseAddressRequest request)
        {
            return Invoke<ReleaseAddressResponse>(ConvertReleaseAddress(request));
        }

        /// <summary>
        /// Reset Snapshot Attribute
        /// </summary>
        /// <param name="request">Reset Snapshot Attribute  request</param>
        /// <returns>Reset Snapshot Attribute  Response from the service</returns>
        /// <remarks>
        /// Resets permission settings for the specified snapshot.
        /// </remarks>
        public ResetSnapshotAttributeResponse ResetSnapshotAttribute(ResetSnapshotAttributeRequest request)
        {
            return Invoke<ResetSnapshotAttributeResponse>(ConvertResetSnapshotAttribute(request));
        }

        /// <summary>
        /// Reset Image Attribute
        /// </summary>
        /// <param name="request">Reset Image Attribute  request</param>
        /// <returns>Reset Image Attribute  Response from the service</returns>
        /// <remarks>
        /// The ResetImageAttribute operation resets an attribute of an AMI to its default
        /// value.
        /// Note:
        /// The productCodes attribute cannot be reset.
        /// </remarks>
        public ResetImageAttributeResponse ResetImageAttribute(ResetImageAttributeRequest request)
        {
            return Invoke<ResetImageAttributeResponse>(ConvertResetImageAttribute(request));
        }

        /// <summary>
        /// Revoke Security Group Ingress
        /// </summary>
        /// <param name="request">Revoke Security Group Ingress  request</param>
        /// <returns>Revoke Security Group Ingress  Response from the service</returns>
        /// <remarks>
        /// The RevokeSecurityGroupIngress operation revokes permissions from a security
        /// group. The permissions used to revoke must be specified using the same values
        /// used to grant the permissions.
        /// Permissions are specified by IP protocol (TCP, UDP, or ICMP), the source of the
        /// request (by IP range or an Amazon EC2 user-group pair), the source and
        /// destination port ranges (for TCP and UDP), and the ICMP codes and types (for
        /// ICMP).
        /// Permission changes are quickly propagated to instances within the security
        /// group. However, depending on the number of instances in the group, a small
        /// delay is might occur, .
        /// When revoking a user/group pair permission, GroupName, SourceSecurityGroupName
        /// and SourceSecurityGroupOwnerId must be specified. When authorizing a CIDR IP
        /// permission, GroupName, IpProtocol, FromPort, ToPort and CidrIp must be
        /// specified. Mixing these two types of parameters is not allowed.
        /// </remarks>
        public RevokeSecurityGroupIngressResponse RevokeSecurityGroupIngress(RevokeSecurityGroupIngressRequest request)
        {
            return Invoke<RevokeSecurityGroupIngressResponse>(ConvertRevokeSecurityGroupIngress(request));
        }

        /// <summary>
        /// Run Instances
        /// </summary>
        /// <param name="request">Run Instances  request</param>
        /// <returns>Run Instances  Response from the service</returns>
        /// <remarks>
        /// The RunInstances operation launches a specified number of instances.
        /// If Amazon EC2 cannot launch the minimum number AMIs you request, no instances
        /// launch. If there is insufficient capacity to launch the maximum number of AMIs
        /// you request, Amazon EC2 launches as many as possible to satisfy the requested
        /// maximum values.
        /// Every instance is launched in a security group. If you do not specify a
        /// security group at launch, the instances start in your default security group.
        /// For more information on creating security groups, see CreateSecurityGroup.
        /// An optional instance type can be specified. For information about instance
        /// types, see Instance Types.
        /// You can provide an optional key pair ID for each image in the launch request
        /// (for more information, see CreateKeyPair). All instances that are created from
        /// images that use this key pair will have access to the associated public key at
        /// boot. You can use this key to provide secure access to an instance of an image
        /// on a per-instance basis. Amazon EC2 public images use this feature to provide
        /// secure access without passwords.
        /// Important:
        /// Launching public images without a key pair ID will leave them inaccessible.
        /// The public key material is made available to the instance at boot time by
        /// placing it in the openssh_id.pub file on a logical device that is exposed to
        /// the instance as /dev/sda2 (the ephemeral store). The format of this file is
        /// suitable for use as an entry within ~/.ssh/authorized_keys (the OpenSSH
        /// format). This can be done at boot (e.g., as part of rc.local) allowing for
        /// secure access without passwords.
        /// Optional user data can be provided in the launch request. All instances that
        /// collectively comprise the launch request have access to this data For more
        /// information, see Instance Metadata.
        /// Note:
        /// If any of the AMIs have a product code attached for which the user has not
        /// subscribed, the RunInstances call will fail.
        /// Important:
        /// We strongly recommend using the 2.6.18 Xen stock kernel with the c1.medium and
        /// c1.xlarge instances. Although the default Amazon EC2 kernels will work, the new
        /// kernels provide greater stability and performance for these instance types. For
        /// more information about kernels, see Kernels, RAM Disks, and Block Device
        /// Mappings.
        /// </remarks>
        public RunInstancesResponse RunInstances(RunInstancesRequest request)
        {
            return Invoke<RunInstancesResponse>(ConvertRunInstances(request));
        }

        /// <summary>
        /// Stop Instances
        /// </summary>
        /// <param name="request">Stop Instances  request</param>
        /// <returns>Stop Instances  Response from the service</returns>
        /// <remarks>
        /// Stops an instance that uses an Amazon EBS volume as its root device.
        /// Instances that use Amazon EBS volumes as their root devices can be quickly stopped and started.
        /// When an instance is stopped, the compute resources are released and you are not billed for hourly
        /// instance usage. However, your root partition Amazon EBS volume remains, continues to persist your
        /// data, and you are charged for Amazon EBS volume usage. You can restart your instance at any time.
        /// </remarks>
        public StopInstancesResponse StopInstances(StopInstancesRequest request)
        {
            return Invoke<StopInstancesResponse>(ConvertStopInstances(request));
        }

        /// <summary>
        /// Start Instances
        /// </summary>
        /// <param name="request">Start Instances  request</param>
        /// <returns>Start Instances  Response from the service</returns>
        /// <remarks>
        /// Starts an instance that uses an Amazon EBS volume as its root device.
        /// Instances that use Amazon EBS volumes as their root devices can be quickly stopped and started.
        /// When an instance is stopped, the compute resources are released and you are not billed for hourly
        /// instance usage. However, your root partition Amazon EBS volume remains, continues to persist your
        /// data, and you are charged for Amazon EBS volume usage. You can restart your instance at any time.
        /// </remarks>
        public StartInstancesResponse StartInstances(StartInstancesRequest request)
        {
            return Invoke<StartInstancesResponse>(ConvertStartInstances(request));
        }

        /// <summary>
        /// Modify Instance Attribute
        /// </summary>
        /// <param name="request">Modify Instance Attribute  request</param>
        /// <returns>Modify Instance Attribute  Response from the service</returns>
        /// <remarks>
        /// Modifies an attribute of an instance.
        /// </remarks>
        public ModifyInstanceAttributeResponse ModifyInstanceAttribute(ModifyInstanceAttributeRequest request)
        {
            return Invoke<ModifyInstanceAttributeResponse>(ConvertModifyInstanceAttribute(request));
        }

        /// <summary>
        /// Reset Instance Attribute
        /// </summary>
        /// <param name="request">Reset Instance Attribute  request</param>
        /// <returns>Reset Instance Attribute  Response from the service</returns>
        /// <remarks>
        /// Resets an attribute of an instance to its default value.
        /// </remarks>
        public ResetInstanceAttributeResponse ResetInstanceAttribute(ResetInstanceAttributeRequest request)
        {
            return Invoke<ResetInstanceAttributeResponse>(ConvertResetInstanceAttribute(request));
        }

        /// <summary>
        /// Describe Instance Attribute
        /// </summary>
        /// <param name="request">Describe Instance Attribute  request</param>
        /// <returns>Describe Instance Attribute  Response from the service</returns>
        /// <remarks>
        /// Returns information about an attribute of an instance. Only one attribute can be specified per call.
        /// </remarks>
        public DescribeInstanceAttributeResponse DescribeInstanceAttribute(DescribeInstanceAttributeRequest request)
        {
            return Invoke<DescribeInstanceAttributeResponse>(ConvertDescribeInstanceAttribute(request));
        }

        /// <summary>
        /// Terminate Instances
        /// </summary>
        /// <param name="request">Terminate Instances  request</param>
        /// <returns>Terminate Instances  Response from the service</returns>
        /// <remarks>
        /// The TerminateInstances operation shuts down one or more instances. This
        /// operation is idempotent; if you terminate an instance more than once, each call
        /// will succeed.
        /// Terminated instances will remain visible after termination (approximately one
        /// hour).
        /// </remarks>
        public TerminateInstancesResponse TerminateInstances(TerminateInstancesRequest request)
        {
            return Invoke<TerminateInstancesResponse>(ConvertTerminateInstances(request));
        }

        /// <summary>
        /// Monitor Instances
        /// </summary>
        /// <param name="request">Monitor Instances  request</param>
        /// <returns>Monitor Instances  Response from the service</returns>
        /// <remarks>
        /// Enables monitoring for a running instance.
        /// </remarks>
        public MonitorInstancesResponse MonitorInstances(MonitorInstancesRequest request)
        {
            return Invoke<MonitorInstancesResponse>(ConvertMonitorInstances(request));
        }

        /// <summary>
        /// Unmonitor Instances
        /// </summary>
        /// <param name="request">Unmonitor Instances  request</param>
        /// <returns>Unmonitor Instances  Response from the service</returns>
        /// <remarks>
        /// Disables monitoring for a running instance.
        /// </remarks>
        public UnmonitorInstancesResponse UnmonitorInstances(UnmonitorInstancesRequest request)
        {
            return Invoke<UnmonitorInstancesResponse>(ConvertUnmonitorInstances(request));
        }

        /// <summary>
        /// Describe Vpn Connections
        /// </summary>
        /// <param name="request">Describe Vpn Connections  request</param>
        /// <returns>Describe Vpn Connections  Response from the service</returns>
        /// <remarks>
        /// Gives you information about your VPN connections.
        /// Important -
        /// We strongly recommend you use HTTPS when calling this operation because the
        /// response contains sensitive cryptographic information for configuring your customer gateway.
        /// You can filter the results to return information only about VPN connections
        /// that match criteria you specify. For example, you could ask to get information
        /// about a particular VPN connection (or all) only if the VPN's state is pending
        /// or available. You can specify multiple filters (e.g., the VPN connection is
        /// associated with a particular VPN gateway, and the gateway's state is
        /// pending or available). The result includes information for a particular
        /// VPN connection only if the VPN connection matches all your filters.
        /// If there's no match, no special message is returned; the response is
        /// simply empty.
        /// </remarks>
        public DescribeVpnConnectionsResponse DescribeVpnConnections(DescribeVpnConnectionsRequest request)
        {
            return Invoke<DescribeVpnConnectionsResponse>(ConvertDescribeVpnConnections(request));
        }

        /// <summary>
        /// Describe Subnets
        /// </summary>
        /// <param name="request">Describe Subnets  request</param>
        /// <returns>Describe Subnets  Response from the service</returns>
        /// <remarks>
        /// Gives you information about your subnets. You can filter the results to
        /// return information only about subnets that match criteria you specify.
        /// For example, you could ask to get information about a particular subnet
        /// (or all) only if the subnet's state is available. You can specify multiple
        /// filters (e.g., the subnet is in a particular VPC, and the subnet's state is
        /// available). The result includes information for a particular subnet only
        /// if the subnet matches all your filters. If there's no match, no special
        /// message is returned; the response is simply empty. The following table
        /// shows the available filters.
        /// </remarks>
        public DescribeSubnetsResponse DescribeSubnets(DescribeSubnetsRequest request)
        {
            return Invoke<DescribeSubnetsResponse>(ConvertDescribeSubnets(request));
        }

        /// <summary>
        /// Detach Vpn Gateway
        /// </summary>
        /// <param name="request">Detach Vpn Gateway  request</param>
        /// <returns>Detach Vpn Gateway  Response from the service</returns>
        /// <remarks>
        /// Detaches a VPN gateway from a VPC. You do this if you're planning to
        /// turn off the VPC and not use it anymore. You can confirm a VPN gateway
        /// has been completely detached from a VPC by describing the VPN gateway
        /// (any attachments to the VPN gateway are also described).
        /// You must wait for the attachment's state to switch to detached before you can
        /// delete the VPC or attach a different VPC to the VPN gateway.
        /// </remarks>
        public DetachVpnGatewayResponse DetachVpnGateway(DetachVpnGatewayRequest request)
        {
            return Invoke<DetachVpnGatewayResponse>(ConvertDetachVpnGateway(request));
        }

        /// <summary>
        /// Describe Vpcs
        /// </summary>
        /// <param name="request">Describe Vpcs  request</param>
        /// <returns>Describe Vpcs  Response from the service</returns>
        /// <remarks>
        /// Gives you information about your VPCs. You can filter the results to return
        /// information only about VPCs that match criteria you specify. For example,
        /// you could ask to get information about a particular VPC or VPCs (or all your VPCs)
        /// only if the VPC's state is available. You can specify multiple filters (e.g.,
        /// the VPC uses one of several sets of DHCP options, and the VPC's state is available).
        /// The result includes information for a particular VPC only if the VPC
        /// matches all your filters. If there's no match, no special message is
        /// returned; the response is simply empty.
        /// </remarks>
        public DescribeVpcsResponse DescribeVpcs(DescribeVpcsRequest request)
        {
            return Invoke<DescribeVpcsResponse>(ConvertDescribeVpcs(request));
        }

        /// <summary>
        /// Delete Customer Gateway
        /// </summary>
        /// <param name="request">Delete Customer Gateway  request</param>
        /// <returns>Delete Customer Gateway  Response from the service</returns>
        /// <remarks>
        /// Deletes a customer gateway. You must delete the VPN connection before
        /// deleting the customer gateway.
        /// AWS might delete any customer gateway if you leave it inactive for an extended
        /// period of time (inactive means that there's no VPN connection in use with the
        /// customer gateway).
        /// </remarks>
        public DeleteCustomerGatewayResponse DeleteCustomerGateway(DeleteCustomerGatewayRequest request)
        {
            return Invoke<DeleteCustomerGatewayResponse>(ConvertDeleteCustomerGateway(request));
        }

        /// <summary>
        /// Attach Vpn Gateway
        /// </summary>
        /// <param name="request">Attach Vpn Gateway  request</param>
        /// <returns>Attach Vpn Gateway  Response from the service</returns>
        /// <remarks>
        /// Attaches a VPN gateway to a VPC. This is the last step required to get your
        /// VPC fully connected to your data center before launching instances in it.
        /// For more information, go to Process for Using Amazon VPC in the Amazon Virtual
        /// Private Cloud Developer Guide.
        /// </remarks>
        public AttachVpnGatewayResponse AttachVpnGateway(AttachVpnGatewayRequest request)
        {
            return Invoke<AttachVpnGatewayResponse>(ConvertAttachVpnGateway(request));
        }

        /// <summary>
        /// Delete Dhcp Options
        /// </summary>
        /// <param name="request">Delete Dhcp Options  request</param>
        /// <returns>Delete Dhcp Options  Response from the service</returns>
        /// <remarks>
        /// Deletes a set of DHCP options that you specify. Amazon VPC returns an error if the
        /// set of options you specify is currently associated with a VPC. You can disassociate
        /// the set of options by associating either a new set of options or the default options with the VPC.
        /// </remarks>
        public DeleteDhcpOptionsResponse DeleteDhcpOptions(DeleteDhcpOptionsRequest request)
        {
            return Invoke<DeleteDhcpOptionsResponse>(ConvertDeleteDhcpOptions(request));
        }

        /// <summary>
        /// Delete Subnet
        /// </summary>
        /// <param name="request">Delete Subnet  request</param>
        /// <returns>Delete Subnet  Response from the service</returns>
        /// <remarks>
        /// Deletes a subnet from a VPC. You must terminate all running instances in the
        /// subnet before deleting it, otherwise Amazon VPC returns an error.
        /// AWS might delete any subnet if you leave it inactive for an extended period
        /// of time (inactive means that there are no running Amazon EC2 instances in the subnet).
        /// </remarks>
        public DeleteSubnetResponse DeleteSubnet(DeleteSubnetRequest request)
        {
            return Invoke<DeleteSubnetResponse>(ConvertDeleteSubnet(request));
        }

        /// <summary>
        /// Create Vpc
        /// </summary>
        /// <param name="request">Create Vpc  request</param>
        /// <returns>Create Vpc  Response from the service</returns>
        /// <remarks>
        /// Creates a VPC with the CIDR block you specify. The smallest VPC you can create
        /// uses a /28 netmask (16 IP addresses), and the largest uses a /18 netmask
        /// (16,384 IP addresses). To help you decide how big to make your VPC, go
        /// to the topic about creating VPCs  in the Amazon Virtual Private Cloud
        /// Developer Guide.
        /// By default, each instance you launch in the VPC has the default DHCP options
        /// (the standard EC2 host name, no domain name, no DNS server, no NTP server, and
        /// no NetBIOS server or node type).
        /// AWS might delete any VPC that you create with this operation if you leave it inactive
        /// for an extended period of time (inactive means that there are no running Amazon EC2
        /// instances in the VPC).
        /// </remarks>
        public CreateVpcResponse CreateVpc(CreateVpcRequest request)
        {
            return Invoke<CreateVpcResponse>(ConvertCreateVpc(request));
        }

        /// <summary>
        /// Create Customer Gateway
        /// </summary>
        /// <param name="request">Create Customer Gateway  request</param>
        /// <returns>Create Customer Gateway  Response from the service</returns>
        /// <remarks>
        /// Provides information to AWS about your customer gateway device.
        /// The customer gateway is the appliance at your end of the VPN connection
        /// (compared to the VPN gateway, which is the device at the AWS side of the VPN
        /// connection). AWS might delete any customer gateway that you create with this
        /// operation if you leave it inactive for an extended period of time (inactive means
        /// that there's no VPN connection in use with the customer gateway).
        /// You must provide the Internet-routable IP address of the customer gateway's external
        /// interface. The IP address must be static and can't be behind a device performing
        /// network address translation (NAT).
        /// You must also provide the device's Border Gateway Protocol (BGP) Autonomous
        /// System Number (ASN). You can use an existing ASN assigned to your network.
        /// If you don't have an ASN already, you can use a private ASN (in the 64512 - 65534 range).
        /// For more information about ASNs, go to the Wikipedia article -
        /// http://en.wikipedia.org/wiki/Autonomous_system_%28Internet%29.
        /// </remarks>
        public CreateCustomerGatewayResponse CreateCustomerGateway(CreateCustomerGatewayRequest request)
        {
            return Invoke<CreateCustomerGatewayResponse>(ConvertCreateCustomerGateway(request));
        }

        /// <summary>
        /// Create Vpn Gateway
        /// </summary>
        /// <param name="request">Create Vpn Gateway  request</param>
        /// <returns>Create Vpn Gateway  Response from the service</returns>
        /// <remarks>
        /// Creates a new VPN gateway. A VPN gateway is the VPC-side endpoint for
        /// your VPN connection. You can create a VPN gateway before creating the VPC
        /// itself. AWS might delete any VPN gateway that you create with this operation
        /// if you leave it inactive for an extended period of time (inactive means
        /// that there's no VPN connection in use with the VPN gateway).
        /// </remarks>
        public CreateVpnGatewayResponse CreateVpnGateway(CreateVpnGatewayRequest request)
        {
            return Invoke<CreateVpnGatewayResponse>(ConvertCreateVpnGateway(request));
        }

        /// <summary>
        /// Delete Vpc
        /// </summary>
        /// <param name="request">Delete Vpc  request</param>
        /// <returns>Delete Vpc  Response from the service</returns>
        /// <remarks>
        /// Deletes a VPC. You must terminate all running instances and delete all
        /// subnets before deleting the VPC, otherwise Amazon VPC returns an error.
        /// AWS might delete any VPC if you leave it inactive for an extended period of time
        /// (inactive means that there are no running Amazon EC2 instances in the VPC).
        /// </remarks>
        public DeleteVpcResponse DeleteVpc(DeleteVpcRequest request)
        {
            return Invoke<DeleteVpcResponse>(ConvertDeleteVpc(request));
        }

        /// <summary>
        /// Associate Dhcp Options
        /// </summary>
        /// <param name="request">Associate Dhcp Options  request</param>
        /// <returns>Associate Dhcp Options  Response from the service</returns>
        /// <remarks>
        /// Associates a set of DHCP options (that you've previously created) with the specified VPC.
        /// Or, associates the default DHCP options with the VPC. The default set consists of the standard
        /// EC2 host name, no domain name, no DNS server, no NTP server, and no NetBIOS server or node type.
        /// After you associate the options with the VPC, any existing instances and all new instances
        /// that you launch in that VPC use the options. For more information about the supported DHCP
        /// options and using them with Amazon VPC, go to Using DHCP Options in the Amazon Virtual
        /// Private Cloud Developer Guide.
        /// </remarks>
        public AssociateDhcpOptionsResponse AssociateDhcpOptions(AssociateDhcpOptionsRequest request)
        {
            return Invoke<AssociateDhcpOptionsResponse>(ConvertAssociateDhcpOptions(request));
        }

        /// <summary>
        /// Describe Vpn Gateways
        /// </summary>
        /// <param name="request">Describe Vpn Gateways  request</param>
        /// <returns>Describe Vpn Gateways  Response from the service</returns>
        /// <remarks>
        /// Gives you information about your VPN gateways. You can filter the results to return
        /// information only about VPN gateways that match criteria you specify. For example,
        /// you could ask to get information about a particular VPN gateway (or all) only if the
        /// gateway's state is pending or available. You can specify multiple filters (e.g., the
        /// VPN gateway is in a particular Availability Zone and the gateway's state is pending or
        /// available). The result includes information for a particular VPN gateway only if the
        /// gateway matches all your filters. If there's no match, no special message is returned;
        /// the response is simply empty.
        /// </remarks>
        public DescribeVpnGatewaysResponse DescribeVpnGateways(DescribeVpnGatewaysRequest request)
        {
            return Invoke<DescribeVpnGatewaysResponse>(ConvertDescribeVpnGateways(request));
        }

        /// <summary>
        /// Create Subnet
        /// </summary>
        /// <param name="request">Create Subnet  request</param>
        /// <returns>Create Subnet  Response from the service</returns>
        /// <remarks>
        /// Creates a subnet in an existing VPC. You can create up to 20 subnets in a VPC.
        /// If you add more than one subnet to a VPC, they're set up in a star topology with
        /// a logical router in the middle. If you feel you need more than 20 subnets, you can
        /// request more by going to http://aws.amazon.com/contact-us/vpc-request/.
        /// When you create each subnet, you provide the VPC ID and the CIDR block you
        /// want for the subnet. Once you create a subnet, you can't change its CIDR block.
        /// The subnet's CIDR block can be the same as the VPC's CIDR block (assuming you
        /// want only a single subnet in the VPC), or a subset of the VPC's CIDR block.
        /// If you create more than one subnet in a VPC, the subnets' CIDR blocks must not overlap.
        /// The smallest subnet (and VPC) you can create uses a /28 netmask (16 IP addresses),
        /// and the largest uses a /18 netmask (16,384 IP addresses).
        /// Important -
        /// AWS reserves both the first four and the last IP address in each subnet's CIDR block.
        /// They're not available for use.
        /// AWS might delete any subnet you create with this operation if you leave it inactive
        /// for an extended period of time (inactive means that there are no running Amazon EC2
        /// instances in the subnet).
        /// </remarks>
        public CreateSubnetResponse CreateSubnet(CreateSubnetRequest request)
        {
            return Invoke<CreateSubnetResponse>(ConvertCreateSubnet(request));
        }

        /// <summary>
        /// Delete Vpn Connection
        /// </summary>
        /// <param name="request">Delete Vpn Connection  request</param>
        /// <returns>Delete Vpn Connection  Response from the service</returns>
        /// <remarks>
        /// Deletes a VPN connection. Use this if you want to delete a VPC and
        /// all its associated components. Another reason to use this operation
        /// is if you believe the tunnel credentials for your VPN connection have
        /// been compromised. In that situation, you can delete the VPN connection
        /// and create a new one that has new keys, without needing to delete the
        /// VPC or VPN gateway. If you create a new VPN connection, you must
        /// reconfigure the customer gateway using the new configuration
        /// information returned with the new VPN connection ID.
        /// If you're deleting the VPC and all its associated parts, we recommend you
        /// detach the VPN gateway from the VPC and delete the VPC before deleting
        /// the VPN connection.
        /// </remarks>
        public DeleteVpnConnectionResponse DeleteVpnConnection(DeleteVpnConnectionRequest request)
        {
            return Invoke<DeleteVpnConnectionResponse>(ConvertDeleteVpnConnection(request));
        }

        /// <summary>
        /// Delete Vpn Gateway
        /// </summary>
        /// <param name="request">Delete Vpn Gateway  request</param>
        /// <returns>Delete Vpn Gateway  Response from the service</returns>
        /// <remarks>
        /// Deletes a VPN gateway. Use this when you want to delete a VPC and all
        /// its associated components because you no longer need them. We recommend
        /// that before you delete a VPN gateway, you detach it from the VPC and
        /// delete the VPN connection. Note that you don't need to delete the VPN
        /// gateway if you just want to delete and re-create the VPN connection
        /// between your VPC and data center.
        /// AWS might delete any VPN gateway if you leave it inactive for an extended period of time
        /// (inactive means that there's no VPN connection in use with the VPN gateway).
        /// </remarks>
        public DeleteVpnGatewayResponse DeleteVpnGateway(DeleteVpnGatewayRequest request)
        {
            return Invoke<DeleteVpnGatewayResponse>(ConvertDeleteVpnGateway(request));
        }

        /// <summary>
        /// Describe Customer Gateways
        /// </summary>
        /// <param name="request">Describe Customer Gateways  request</param>
        /// <returns>Describe Customer Gateways  Response from the service</returns>
        /// <remarks>
        /// Gives you information about your customer gateways. You can filter the results to return
        /// information only about customer gateways that match criteria you specify. For example,
        /// you could ask to get information about a particular customer gateway (or all) only if
        /// the gateway's state is pending or available. You can specify multiple filters (e.g.,
        /// the customer gateway has a particular IP address for the Internet-routable external
        /// interface, and the gateway's state is pending or available). The result includes
        /// information for a particular customer gateway only if the gateway matches all  your
        /// filters. If there's no match, no special message is returned; the response is simply empty.
        /// </remarks>
        public DescribeCustomerGatewaysResponse DescribeCustomerGateways(DescribeCustomerGatewaysRequest request)
        {
            return Invoke<DescribeCustomerGatewaysResponse>(ConvertDescribeCustomerGateways(request));
        }

        /// <summary>
        /// Create Vpn Connection
        /// </summary>
        /// <param name="request">Create Vpn Connection  request</param>
        /// <returns>Create Vpn Connection  Response from the service</returns>
        /// <remarks>
        /// Creates a new VPN connection between an existing VPN gateway and customer
        /// gateway. The only supported connection type is ipsec.1.
        /// The response includes information that you need to configure your customer gateway,
        /// in XML format. We recommend you use the command line version of this operation
        /// (ec2-create-vpn-connection), which lets you get the configuration information
        /// formatted in a friendlier way. For information about the command, go to
        /// ec2-create-vpn-connection in the Amazon Virtual Private Cloud Command Line Reference.
        /// Important -
        /// We strongly recommend you use HTTPS when calling this operation because
        /// the response contains sensitive cryptographic information for configuring
        /// your customer gateway.
        /// If you decide to shut down your VPN connection for any reason and then create a new
        /// one, you must re-configure your customer gateway with the new information
        /// returned from this call.
        /// </remarks>
        public CreateVpnConnectionResponse CreateVpnConnection(CreateVpnConnectionRequest request)
        {
            return Invoke<CreateVpnConnectionResponse>(ConvertCreateVpnConnection(request));
        }

        /// <summary>
        /// Describe Dhcp Options
        /// </summary>
        /// <param name="request">Describe Dhcp Options  request</param>
        /// <returns>Describe Dhcp Options  Response from the service</returns>
        /// <remarks>
        /// Gives you information about one or more sets of DHCP options. You can specify
        /// one or more DHCP options set IDs, or no IDs (to describe all your sets of DHCP options).
        /// The returned information consists of:
        /// - The DHCP options set ID
        /// - The options
        /// </remarks>
        public DescribeDhcpOptionsResponse DescribeDhcpOptions(DescribeDhcpOptionsRequest request)
        {
            return Invoke<DescribeDhcpOptionsResponse>(ConvertDescribeDhcpOptions(request));
        }

        /// <summary>
        /// Create Dhcp Options
        /// </summary>
        /// <param name="request">Create Dhcp Options  request</param>
        /// <returns>Create Dhcp Options  Response from the service</returns>
        /// <remarks>
        /// Creates a set of DHCP options that you can then associate with one or more VPCs,
        /// causing all existing and new instances that you launch in those VPCs to use the
        /// set of DHCP options. The following table lists the individual DHCP options you can
        /// specify. For more information about the options, go to RFC 2132 - http://www.ietf.org/rfc/rfc2132.txt
        /// </remarks>
        public CreateDhcpOptionsResponse CreateDhcpOptions(CreateDhcpOptionsRequest request)
        {
            return Invoke<CreateDhcpOptionsResponse>(ConvertCreateDhcpOptions(request));
        }

        /// <summary>
        /// Request Spot Instances
        /// </summary>
        /// <param name="request">Request Spot Instances  request</param>
        /// <returns>Request Spot Instances  Response from the service</returns>
        /// <remarks>
        /// Creates a Spot Instance request. Spot Instances are instances that automatically launch when your
        /// request price exceeds the Spot Price that Amazon EC2 periodically calculates.
        /// </remarks>
        public RequestSpotInstancesResponse RequestSpotInstances(RequestSpotInstancesRequest request)
        {
            return Invoke<RequestSpotInstancesResponse>(ConvertRequestSpotInstances(request));
        }

        /// <summary>
        /// Describe Spot Instance Requests
        /// </summary>
        /// <param name="request">Describe Spot Instance Requests  request</param>
        /// <returns>Describe Spot Instance Requests  Response from the service</returns>
        /// <remarks>
        /// Describes Spot Instance requests. Spot Instances are instances that automatically launch when your
        /// request price exceeds the Spot Price that Amazon EC2 periodically calculates.
        /// </remarks>
        public DescribeSpotInstanceRequestsResponse DescribeSpotInstanceRequests(DescribeSpotInstanceRequestsRequest request)
        {
            return Invoke<DescribeSpotInstanceRequestsResponse>(ConvertDescribeSpotInstanceRequests(request));
        }

        /// <summary>
        /// Cancel Spot Instance Requests
        /// </summary>
        /// <param name="request">Cancel Spot Instance Requests  request</param>
        /// <returns>Cancel Spot Instance Requests  Response from the service</returns>
        /// <remarks>
        /// Cancels Spot Instance requests. Spot Instances are instances that automatically launch when your
        /// request price exceeds the Spot Price that Amazon EC2 periodically calculates.
        /// </remarks>
        public CancelSpotInstanceRequestsResponse CancelSpotInstanceRequests(CancelSpotInstanceRequestsRequest request)
        {
            return Invoke<CancelSpotInstanceRequestsResponse>(ConvertCancelSpotInstanceRequests(request));
        }

        /// <summary>
        /// Describe Spot Price History
        /// </summary>
        /// <param name="request">Describe Spot Price History  request</param>
        /// <returns>Describe Spot Price History  Response from the service</returns>
        /// <remarks>
        /// Describes historical pricing for Spot Instances. Spot Instances are instances that automatically launch
        /// when your request price exceeds the Spot Price that Amazon EC2 periodically calculates.
        /// </remarks>
        public DescribeSpotPriceHistoryResponse DescribeSpotPriceHistory(DescribeSpotPriceHistoryRequest request)
        {
            return Invoke<DescribeSpotPriceHistoryResponse>(ConvertDescribeSpotPriceHistory(request));
        }

        /// <summary>
        /// Create Spot Datafeed Subscription
        /// </summary>
        /// <param name="request">Create Spot Datafeed Subscription  request</param>
        /// <returns>Create Spot Datafeed Subscription  Response from the service</returns>
        /// <remarks>
        /// Creates the data feed for Spot Instances, enabling you to view Spot Instance usage logs. You can
        /// create one data feed per account.
        /// </remarks>
        public CreateSpotDatafeedSubscriptionResponse CreateSpotDatafeedSubscription(CreateSpotDatafeedSubscriptionRequest request)
        {
            return Invoke<CreateSpotDatafeedSubscriptionResponse>(ConvertCreateSpotDatafeedSubscription(request));
        }

        /// <summary>
        /// Describe Spot Datafeed Subscription
        /// </summary>
        /// <param name="request">Describe Spot Datafeed Subscription  request</param>
        /// <returns>Describe Spot Datafeed Subscription  Response from the service</returns>
        /// <remarks>
        /// Describes the data feed for Spot Instances.
        /// </remarks>
        public DescribeSpotDatafeedSubscriptionResponse DescribeSpotDatafeedSubscription(DescribeSpotDatafeedSubscriptionRequest request)
        {
            return Invoke<DescribeSpotDatafeedSubscriptionResponse>(ConvertDescribeSpotDatafeedSubscription(request));
        }

        /// <summary>
        /// Delete Spot Datafeed Subscription
        /// </summary>
        /// <param name="request">Delete Spot Datafeed Subscription  request</param>
        /// <returns>Delete Spot Datafeed Subscription  Response from the service</returns>
        /// <remarks>
        /// Deletes the data feed for Spot Instances.
        /// </remarks>
        public DeleteSpotDatafeedSubscriptionResponse DeleteSpotDatafeedSubscription(DeleteSpotDatafeedSubscriptionRequest request)
        {
            return Invoke<DeleteSpotDatafeedSubscriptionResponse>(ConvertDeleteSpotDatafeedSubscription(request));
        }

        #endregion

        #region Private API

        /**
         * Configure HttpClient with set of defaults as well as configuration
         * from AmazonEC2Config instance
         */
        private static HttpWebRequest ConfigureWebRequest(int contentLength, AmazonEC2Config config)
        {
            HttpWebRequest request = WebRequest.Create(config.ServiceURL) as HttpWebRequest;

            if (config.IsSetProxyHost())
            {
                request.Proxy = new WebProxy(config.ProxyHost, config.ProxyPort);
            }
            request.UserAgent = config.UserAgent;
            request.Method = "POST";
            request.Timeout = 50000;
            request.ContentType = AWSSDKUtils.UrlEncodedContent;
            request.ContentLength = contentLength;

            return request;
        }

        /**
         * Invoke request and return response
         */
        private T Invoke<T>(IDictionary<string, string> parameters)
        {
            string actionName = parameters["Action"];
            T response = default(T);
            string responseBody = null;
            HttpStatusCode statusCode = default(HttpStatusCode);

            /* Add required request parameters */
            AddRequiredParameters(parameters);

            string queryString = GetParametersAsString(parameters);

            byte[] requestData = Encoding.UTF8.GetBytes(queryString);
            bool shouldRetry = true;
            int retries = 0;
            do
            {
                HttpWebRequest request = ConfigureWebRequest(requestData.Length, config);
                /* Submit the request and read response body */
                try
                {
                    using (Stream requestStream = request.GetRequestStream())
                    {
                        requestStream.Write(requestData, 0, requestData.Length);
                    }
                    using (HttpWebResponse httpResponse = request.GetResponse() as HttpWebResponse)
                    {
                        statusCode = httpResponse.StatusCode;
                        using (StreamReader reader = new StreamReader(httpResponse.GetResponseStream(), Encoding.UTF8))
                        {
                            responseBody = reader.ReadToEnd();
                        }
                    }

                    /* Perform response transformation */
                    if (responseBody != null &&
                        responseBody.Trim().EndsWith(String.Concat(actionName, "Response>")))
                    {
                        responseBody = Transform(responseBody, actionName, this.GetType());
                    }

                    /* Attempt to deserialize response into <Action> Response type */
                    XmlSerializer serializer = new XmlSerializer(typeof(T));
                    using (XmlTextReader sr = new XmlTextReader(new StringReader(responseBody)))
                    {
                        response = (T)serializer.Deserialize(sr);
                    }
                    shouldRetry = false;
                }
                /* Web exception is thrown on unsucessful responses */
                catch (WebException we)
                {
                    shouldRetry = false;
                    using (HttpWebResponse httpErrorResponse = (HttpWebResponse)we.Response as HttpWebResponse)
                    {
                        if (httpErrorResponse == null)
                        {
                            // Abort the unsuccessful request
                            request.Abort();
                            throw new AmazonEC2Exception(we);
                        }
                        statusCode = httpErrorResponse.StatusCode;
                        using (StreamReader reader = new StreamReader(httpErrorResponse.GetResponseStream(), Encoding.UTF8))
                        {
                            responseBody = reader.ReadToEnd();
                        }

                        // Abort the unsuccessful request
                        request.Abort();
                    }

                    if (statusCode == HttpStatusCode.InternalServerError || statusCode == HttpStatusCode.ServiceUnavailable)
                    {
                        shouldRetry = true;
                        PauseOnRetry(++retries, config.MaxErrorRetry, statusCode);
                    }
                    else
                    {
                        /* Attempt to deserialize response into ErrorResponse type */
                        try
                        {
                            using (XmlTextReader sr = new XmlTextReader(new StringReader(responseBody)))
                            {
                                XmlSerializer serializer = new XmlSerializer(typeof(ErrorResponse));
                                ErrorResponse errorResponse = (ErrorResponse) serializer.Deserialize(sr);
                                Error error = errorResponse.Error[0];

                                /* Throw formatted exception with information available from the error response */
                                throw new AmazonEC2Exception(
                                    error.Message,
                                    statusCode,
                                    error.Code,
                                    error.Type,
                                    errorResponse.RequestId,
                                    errorResponse.ToXML()
                                    );
                            }
                        }
                        /* Rethrow on deserializer error */
                        catch (Exception e)
                        {
                            if (e is AmazonEC2Exception)
                            {
                                throw;
                            }
                            else
                            {
                                AmazonEC2Exception se = ReportAnyErrors(responseBody, statusCode);
                                throw se;
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    // Abort the unsuccessful request
                    request.Abort();
                    throw;
                }
            } while (shouldRetry);

            return response;
        }

        /**
         * Look for additional error strings in the response and return formatted exception
         */
        private static AmazonEC2Exception ReportAnyErrors(string responseBody, HttpStatusCode status)
        {
            AmazonEC2Exception ex = null;

            if (responseBody != null && responseBody.StartsWith("<"))
            {
                Match errorMatcherOne = Regex.Match(
                    responseBody,
                    "<RequestId>(.*)</RequestId>.*<Error><Code>(.*)</Code><Message>(.*)</Message></Error>.*(<Error>)?",
                    RegexOptions.Multiline
                    );
                Match errorMatcherTwo = Regex.Match(
                    responseBody,
                    "<Error><Code>(.*)</Code><Message>(.*)</Message></Error>.*(<Error>)?.*<RequestID>(.*)</RequestID>",
                    RegexOptions.Multiline
                    );

                if (errorMatcherOne.Success)
                {
                    string requestId = errorMatcherOne.Groups[1].Value;
                    string code = errorMatcherOne.Groups[2].Value;
                    string message = errorMatcherOne.Groups[3].Value;

                    ex = new AmazonEC2Exception(message, status, code, "Unknown", requestId, responseBody);
                }
                else if (errorMatcherTwo.Success)
                {
                    string code = errorMatcherTwo.Groups[1].Value;
                    string message = errorMatcherTwo.Groups[2].Value;
                    string requestId = errorMatcherTwo.Groups[4].Value;

                    ex = new AmazonEC2Exception(message, status, code, "Unknown", requestId, responseBody);
                }
                else
                {
                    ex = new AmazonEC2Exception("Internal Error", status);
                }
            }
            else
            {
                ex = new AmazonEC2Exception("Internal Error", status);
            }
            return ex;
        }

        /**
         * Exponential sleep on failed request
         */
        private static void PauseOnRetry(int retries, int maxRetries, HttpStatusCode status)
        {
            if (retries <= maxRetries)
            {
                int delay = (int)Math.Pow(4, retries) * 100;
                System.Threading.Thread.Sleep(delay);
            }
            else
            {
                throw new AmazonEC2Exception("Maximum number of retry attempts reached : " + (retries - 1), status);
            }
        }

        /**
         * Add authentication related and version parameters
         */
        private void AddRequiredParameters(IDictionary<string, string> parameters)
        {
            if (String.IsNullOrEmpty(this.awsAccessKeyId))
            {
                throw new AmazonEC2Exception("The AWS Access Key ID cannot be NULL or a Zero length string");
            }
            parameters.Add("AWSAccessKeyId", this.awsAccessKeyId);
            parameters.Add("Timestamp", S3UploadPolicy.GetFormattedTimestamp(0));
            parameters.Add("Version", config.ServiceVersion);
            parameters.Add("SignatureVersion", config.SignatureVersion);
            parameters.Add("Signature", SignParameters(parameters, this.awsSecretAccessKey, config));
        }

        /**
         * Convert Dictionary of paremeters to Url encoded query string
         */
        private static string GetParametersAsString(IDictionary<string, string> parameters)
        {
            StringBuilder data = new StringBuilder(512);
            foreach (string key in (IEnumerable<string>)parameters.Keys)
            {
                string value = parameters[key];
                if (value != null)
                {
                    data.Append(key);
                    data.Append('=');
                    data.Append(AWSSDKUtils.UrlEncode(value, false));
                    data.Append('&');
                }
            }
            string result = data.ToString();
            return result.Remove(result.Length - 1);
        }

        /**
         * Computes RFC 2104-compliant HMAC signature for request parameters
         * Implements AWS Signature, as per following spec:
         *
         * If Signature Version is 0, it signs concatenated Action and Timestamp
         *
         * If Signature Version is 1, it performs the following:
         *
         * Sorts all  parameters (including SignatureVersion and excluding Signature,
         * the value of which is being created), ignoring case.
         *
         * Iterate over the sorted list and append the parameter name (in original case)
         * and then its value. It will not URL-encode the parameter values before
         * constructing this string. There are no separators.
         *
         * If Signature Version is 2, string to sign is based on following:
         *
         *    1. The HTTP Request Method followed by an ASCII newline (%0A)
         *    2. The HTTP Host header in the form of lowercase host, followed by an ASCII newline.
         *    3. The URL encoded HTTP absolute path component of the URI
         *       (up to but not including the query string parameters);
         *       if this is empty use a forward '/'. This parameter is followed by an ASCII newline.
         *    4. The concatenation of all query string components (names and values)
         *       as UTF-8 characters which are URL encoded as per RFC 3986
         *       (hex characters MUST be uppercase), sorted using lexicographic byte ordering.
         *       Parameter names are separated from their values by the '=' character
         *       (ASCII character 61), even if the value is empty.
         *       Pairs of parameter and values are separated by the ampersand character (ASCII code 38).
         *
         */
        private static string SignParameters(IDictionary<string, string> parameters, SecureString key, AmazonEC2Config config)
        {
            string signatureVersion = parameters["SignatureVersion"];

            KeyedHashAlgorithm algorithm = new HMACSHA1();

            string stringToSign = null;
            if ("2".Equals(signatureVersion))
            {
                string signatureMethod = config.SignatureMethod;
                algorithm = KeyedHashAlgorithm.Create(signatureMethod.ToUpper());
                parameters.Add("SignatureMethod", signatureMethod);
                stringToSign = CalculateStringToSignV2(parameters, config);
            }
            else
            {
                throw new AmazonEC2Exception("Invalid Signature Version specified");
            }

            return S3UploadPolicy.Sign(stringToSign, key, algorithm);
        }

        private static string CalculateStringToSignV2(IDictionary<string, string> parameters, AmazonEC2Config config)
        {
            StringBuilder data = new StringBuilder(512);
            IDictionary<string, string> sorted =
                  new SortedDictionary<string, string>(parameters, StringComparer.Ordinal);
            data.Append("POST");
            data.Append("\n");
            Uri endpoint = new Uri(config.ServiceURL.ToLower());

            data.Append(endpoint.Host);
            data.Append("\n");
            string uri = endpoint.AbsolutePath;
            if (uri == null || uri.Length == 0)
            {
                uri = "/";
            }

            data.Append(AWSSDKUtils.UrlEncode(uri, true));
            data.Append("\n");
            foreach (KeyValuePair<string, string> pair in sorted)
            {
                if (pair.Value != null)
                {
                    data.Append(AWSSDKUtils.UrlEncode(pair.Key, false));
                    data.Append("=");
                    data.Append(AWSSDKUtils.UrlEncode(pair.Value, false));
                    data.Append("&");
                }
            }

            string result = data.ToString();
            return result.Remove(result.Length - 1);
        }

        /**
         * Convert AllocateAddressRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertAllocateAddress(AllocateAddressRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "AllocateAddress");

            return parameters;
        }

        /**
         * Convert AttachVpnGatewayRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertAttachVpnGateway(AttachVpnGatewayRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "AttachVpnGateway");
            if (request.IsSetVpnGatewayId())
            {
                parameters.Add("VpnGatewayId", request.VpnGatewayId);
            }
            if (request.IsSetVpcId())
            {
                parameters.Add("VpcId", request.VpcId);
            }

            return parameters;
        }

        /**
         * Convert AssociateDhcpOptionsRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertAssociateDhcpOptions(AssociateDhcpOptionsRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "AssociateDhcpOptions");
            if (request.IsSetDhcpOptionsId())
            {
                parameters.Add("DhcpOptionsId", request.DhcpOptionsId);
            }
            if (request.IsSetVpcId())
            {
                parameters.Add("VpcId", request.VpcId);
            }

            return parameters;
        }

        /**
         * Convert AssociateAddressRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertAssociateAddress(AssociateAddressRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "AssociateAddress");
            if (request.IsSetInstanceId())
            {
                parameters.Add("InstanceId", request.InstanceId);
            }
            if (request.IsSetPublicIp())
            {
                parameters.Add("PublicIp", request.PublicIp);
            }

            return parameters;
        }

        /**
         * Convert AuthorizeSecurityGroupIngressRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertAuthorizeSecurityGroupIngress(AuthorizeSecurityGroupIngressRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "AuthorizeSecurityGroupIngress");
            if (request.IsSetUserId())
            {
                parameters.Add("UserId", request.UserId);
            }
            if (request.IsSetGroupName())
            {
                parameters.Add("GroupName", request.GroupName);
            }
            if (request.IsSetSourceSecurityGroupName())
            {
                parameters.Add("SourceSecurityGroupName", request.SourceSecurityGroupName);
            }
            if (request.IsSetSourceSecurityGroupOwnerId())
            {
                parameters.Add("SourceSecurityGroupOwnerId", request.SourceSecurityGroupOwnerId);
            }
            if (request.IsSetIpProtocol())
            {
                parameters.Add("IpProtocol", request.IpProtocol);
            }
            if (request.IsSetFromPort())
            {
                parameters.Add("FromPort", (request.FromPort + ""));
            }
            if (request.IsSetToPort())
            {
                parameters.Add("ToPort", (request.ToPort + ""));
            }
            if (request.IsSetCidrIp())
            {
                parameters.Add("CidrIp", request.CidrIp);
            }

            return parameters;
        }

        /**
         * Convert BundleInstanceRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertBundleInstance(BundleInstanceRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "BundleInstance");
            if (request.IsSetInstanceId())
            {
                parameters.Add("InstanceId", request.InstanceId);
            }
            if (request.IsSetStorage())
            {
                Storage  bundleInstanceRequestStorage = request.Storage;
                if (bundleInstanceRequestStorage.IsSetS3())
                {
                    S3Storage  storageS3 = bundleInstanceRequestStorage.S3;
                    if (storageS3.IsSetBucket())
                    {
                        parameters.Add("Storage" + "." + "S3" + "." + "Bucket", storageS3.Bucket);
                    }
                    if (storageS3.IsSetPrefix())
                    {
                        parameters.Add("Storage" + "." + "S3" + "." + "Prefix", storageS3.Prefix);
                    }
                    if (storageS3.IsSetAWSAccessKeyId())
                    {
                        parameters.Add("Storage" + "." + "S3" + "." + "AWSAccessKeyId", storageS3.AWSAccessKeyId);
                    }
                    if (storageS3.IsSetUploadPolicy())
                    {
                        parameters.Add("Storage" + "." + "S3" + "." + "UploadPolicy", storageS3.UploadPolicy);
                    }
                    if (storageS3.IsSetUploadPolicySignature())
                    {
                        parameters.Add("Storage" + "." + "S3" + "." + "UploadPolicySignature", storageS3.UploadPolicySignature);
                    }
                }
            }

            return parameters;
        }

        /**
         * Convert CancelBundleTaskRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertCancelBundleTask(CancelBundleTaskRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "CancelBundleTask");
            if (request.IsSetBundleId())
            {
                parameters.Add("BundleId", request.BundleId);
            }

            return parameters;
        }

        /**
         * Convert ConfirmProductInstanceRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertConfirmProductInstance(ConfirmProductInstanceRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "ConfirmProductInstance");
            if (request.IsSetProductCode())
            {
                parameters.Add("ProductCode", request.ProductCode);
            }
            if (request.IsSetInstanceId())
            {
                parameters.Add("InstanceId", request.InstanceId);
            }

            return parameters;
        }

        /**
         * Convert CreateImageRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertCreateImage(CreateImageRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "CreateImage");
            if (request.IsSetInstanceId())
            {
                parameters.Add("InstanceId", request.InstanceId);
            }
            if (request.IsSetName())
            {
                parameters.Add("Name", request.Name);
            }
            if (request.IsSetDescription())
            {
                parameters.Add("Description", request.Description);
            }
            if (request.IsSetNoReboot())
            {
                parameters.Add("NoReboot", (request.NoReboot + "").ToLower());
            }

            return parameters;
        }

        /**
         * Convert CreateKeyPairRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertCreateKeyPair(CreateKeyPairRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "CreateKeyPair");
            if (request.IsSetKeyName())
            {
                parameters.Add("KeyName", request.KeyName);
            }

            return parameters;
        }

        /**
         * Convert CreateSubnetRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertCreateSubnet(CreateSubnetRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "CreateSubnet");
            if (request.IsSetVpcId())
            {
                parameters.Add("VpcId", request.VpcId);
            }
            if (request.IsSetCidrBlock())
            {
                parameters.Add("CidrBlock", request.CidrBlock);
            }
            if (request.IsSetAvailabilityZone())
            {
                parameters.Add("AvailabilityZone", request.AvailabilityZone);
            }

            return parameters;
        }

        /**
         * Convert CreateVpnConnectionRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertCreateVpnConnection(CreateVpnConnectionRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "CreateVpnConnection");
            if (request.IsSetType())
            {
                parameters.Add("Type", request.Type);
            }
            if (request.IsSetCustomerGatewayId())
            {
                parameters.Add("CustomerGatewayId", request.CustomerGatewayId);
            }
            if (request.IsSetVpnGatewayId())
            {
                parameters.Add("VpnGatewayId", request.VpnGatewayId);
            }

            return parameters;
        }

        /**
         * Convert CreateVpnGatewayRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertCreateVpnGateway(CreateVpnGatewayRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "CreateVpnGateway");
            if (request.IsSetType())
            {
                parameters.Add("Type", request.Type);
            }
            if (request.IsSetAvailabilityZone())
            {
                parameters.Add("AvailabilityZone", request.AvailabilityZone);
            }

            return parameters;
        }

        /**
         * Convert CreateDhcpOptionsRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertCreateDhcpOptions(CreateDhcpOptionsRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "CreateDhcpOptions");
            List<DhcpConfiguration> createDhcpOptionsRequestDhcpConfigurationList = request.DhcpConfiguration;
            int createDhcpOptionsRequestDhcpConfigurationListIndex = 1;
            foreach (DhcpConfiguration createDhcpOptionsRequestDhcpConfiguration in createDhcpOptionsRequestDhcpConfigurationList)
            {
                if (createDhcpOptionsRequestDhcpConfiguration.IsSetKey())
                {
                    parameters.Add("DhcpConfiguration" + "."  + createDhcpOptionsRequestDhcpConfigurationListIndex + "." + "Key", createDhcpOptionsRequestDhcpConfiguration.Key);
                }
                List<string> dhcpConfigurationValueList  =  createDhcpOptionsRequestDhcpConfiguration.Value;
                int dhcpConfigurationValueListIndex = 1;
                foreach  (string dhcpConfigurationValue in dhcpConfigurationValueList)
                {
                    parameters.Add("DhcpConfiguration" + "."  + createDhcpOptionsRequestDhcpConfigurationListIndex + "." + "Value" + "."  + dhcpConfigurationValueListIndex, dhcpConfigurationValue);
                    dhcpConfigurationValueListIndex++;
                }

                createDhcpOptionsRequestDhcpConfigurationListIndex++;
            }

            return parameters;
        }

        /**
         * Convert CreateVpcRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertCreateVpc(CreateVpcRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "CreateVpc");
            if (request.IsSetCidrBlock())
            {
                parameters.Add("CidrBlock", request.CidrBlock);
            }

            return parameters;
        }

        /**
         * Convert CreateCustomerGatewayRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertCreateCustomerGateway(CreateCustomerGatewayRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "CreateCustomerGateway");
            if (request.IsSetType())
            {
                parameters.Add("Type", request.Type);
            }
            if (request.IsSetIpAddress())
            {
                parameters.Add("IpAddress", request.IpAddress);
            }
            if (request.IsSetBgpAsn())
            {
                parameters.Add("BgpAsn", (request.BgpAsn + ""));
            }

            return parameters;
        }

        /**
         * Convert CreateSecurityGroupRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertCreateSecurityGroup(CreateSecurityGroupRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "CreateSecurityGroup");
            if (request.IsSetGroupName())
            {
                parameters.Add("GroupName", request.GroupName);
            }
            if (request.IsSetGroupDescription())
            {
                parameters.Add("GroupDescription", request.GroupDescription);
            }

            return parameters;
        }

        /**
         * Convert DeleteKeyPairRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDeleteKeyPair(DeleteKeyPairRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DeleteKeyPair");
            if (request.IsSetKeyName())
            {
                parameters.Add("KeyName", request.KeyName);
            }

            return parameters;
        }

        /**
         * Convert DeleteVpcRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDeleteVpc(DeleteVpcRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DeleteVpc");
            if (request.IsSetVpcId())
            {
                parameters.Add("VpcId", request.VpcId);
            }

            return parameters;
        }

        /**
         * Convert DeleteVpnGatewayRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDeleteVpnGateway(DeleteVpnGatewayRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DeleteVpnGateway");
            if (request.IsSetVpnGatewayId())
            {
                parameters.Add("VpnGatewayId", request.VpnGatewayId);
            }

            return parameters;
        }

        /**
         * Convert DeleteVpnConnectionRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDeleteVpnConnection(DeleteVpnConnectionRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DeleteVpnConnection");
            if (request.IsSetVpnConnectionId())
            {
                parameters.Add("VpnConnectionId", request.VpnConnectionId);
            }

            return parameters;
        }

        /**
         * Convert DeleteDhcpOptionsRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDeleteDhcpOptions(DeleteDhcpOptionsRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DeleteDhcpOptions");
            if (request.IsSetDhcpOptionsId())
            {
                parameters.Add("DhcpOptionsId", request.DhcpOptionsId);
            }

            return parameters;
        }

        /**
         * Convert DeleteCustomerGatewayRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDeleteCustomerGateway(DeleteCustomerGatewayRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DeleteCustomerGateway");
            if (request.IsSetCustomerGatewayId())
            {
                parameters.Add("CustomerGatewayId", request.CustomerGatewayId);
            }

            return parameters;
        }

        /**
         * Convert DeleteSecurityGroupRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDeleteSecurityGroup(DeleteSecurityGroupRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DeleteSecurityGroup");
            if (request.IsSetGroupName())
            {
                parameters.Add("GroupName", request.GroupName);
            }

            return parameters;
        }

        /**
         * Convert DeleteSubnetRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDeleteSubnet(DeleteSubnetRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DeleteSubnet");
            if (request.IsSetSubnetId())
            {
                parameters.Add("SubnetId", request.SubnetId);
            }

            return parameters;
        }

        /**
         * Convert DescribeVpcsRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeVpcs(DescribeVpcsRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeVpcs");
            List<string> describeVpcsRequestVpcIdList  =  request.VpcId;
            int describeVpcsRequestVpcIdListIndex = 1;
            foreach  (string describeVpcsRequestVpcId in describeVpcsRequestVpcIdList)
            {
                parameters.Add("VpcId" + "."  + describeVpcsRequestVpcIdListIndex, describeVpcsRequestVpcId);
                describeVpcsRequestVpcIdListIndex++;
            }
            List<Filter> describeVpcsRequestFilterList = request.Filter;
            int describeVpcsRequestFilterListIndex = 1;
            foreach (Filter describeVpcsRequestFilter in describeVpcsRequestFilterList)
            {
                if (describeVpcsRequestFilter.IsSetName())
                {
                    parameters.Add("Filter" + "."  + describeVpcsRequestFilterListIndex + "." + "Name", describeVpcsRequestFilter.Name);
                }
                List<string> filterValueList  =  describeVpcsRequestFilter.Value;
                int filterValueListIndex = 1;
                foreach  (string filterValue in filterValueList)
                {
                    parameters.Add("Filter" + "."  + describeVpcsRequestFilterListIndex + "." + "Value" + "."  + filterValueListIndex, filterValue);
                    filterValueListIndex++;
                }

                describeVpcsRequestFilterListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DescribeVpnGatewaysRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeVpnGateways(DescribeVpnGatewaysRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeVpnGateways");
            List<string> describeVpnGatewaysRequestVpnGatewayIdList  =  request.VpnGatewayId;
            int describeVpnGatewaysRequestVpnGatewayIdListIndex = 1;
            foreach  (string describeVpnGatewaysRequestVpnGatewayId in describeVpnGatewaysRequestVpnGatewayIdList)
            {
                parameters.Add("VpnGatewayId" + "."  + describeVpnGatewaysRequestVpnGatewayIdListIndex, describeVpnGatewaysRequestVpnGatewayId);
                describeVpnGatewaysRequestVpnGatewayIdListIndex++;
            }
            List<Filter> describeVpnGatewaysRequestFilterList = request.Filter;
            int describeVpnGatewaysRequestFilterListIndex = 1;
            foreach (Filter describeVpnGatewaysRequestFilter in describeVpnGatewaysRequestFilterList)
            {
                if (describeVpnGatewaysRequestFilter.IsSetName())
                {
                    parameters.Add("Filter" + "."  + describeVpnGatewaysRequestFilterListIndex + "." + "Name", describeVpnGatewaysRequestFilter.Name);
                }
                List<string> filterValueList  =  describeVpnGatewaysRequestFilter.Value;
                int filterValueListIndex = 1;
                foreach  (string filterValue in filterValueList)
                {
                    parameters.Add("Filter" + "."  + describeVpnGatewaysRequestFilterListIndex + "." + "Value" + "."  + filterValueListIndex, filterValue);
                    filterValueListIndex++;
                }

                describeVpnGatewaysRequestFilterListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DescribeDhcpOptionsRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeDhcpOptions(DescribeDhcpOptionsRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeDhcpOptions");
            List<string> describeDhcpOptionsRequestDhcpOptionsIdList  =  request.DhcpOptionsId;
            int describeDhcpOptionsRequestDhcpOptionsIdListIndex = 1;
            foreach  (string describeDhcpOptionsRequestDhcpOptionsId in describeDhcpOptionsRequestDhcpOptionsIdList)
            {
                parameters.Add("DhcpOptionsId" + "."  + describeDhcpOptionsRequestDhcpOptionsIdListIndex, describeDhcpOptionsRequestDhcpOptionsId);
                describeDhcpOptionsRequestDhcpOptionsIdListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DescribeVpnConnectionsRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeVpnConnections(DescribeVpnConnectionsRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeVpnConnections");
            List<string> describeVpnConnectionsRequestVpnConnectionIdList  =  request.VpnConnectionId;
            int describeVpnConnectionsRequestVpnConnectionIdListIndex = 1;
            foreach  (string describeVpnConnectionsRequestVpnConnectionId in describeVpnConnectionsRequestVpnConnectionIdList)
            {
                parameters.Add("VpnConnectionId" + "."  + describeVpnConnectionsRequestVpnConnectionIdListIndex, describeVpnConnectionsRequestVpnConnectionId);
                describeVpnConnectionsRequestVpnConnectionIdListIndex++;
            }
            List<Filter> describeVpnConnectionsRequestFilterList = request.Filter;
            int describeVpnConnectionsRequestFilterListIndex = 1;
            foreach (Filter describeVpnConnectionsRequestFilter in describeVpnConnectionsRequestFilterList)
            {
                if (describeVpnConnectionsRequestFilter.IsSetName())
                {
                    parameters.Add("Filter" + "."  + describeVpnConnectionsRequestFilterListIndex + "." + "Name", describeVpnConnectionsRequestFilter.Name);
                }
                List<string> filterValueList  =  describeVpnConnectionsRequestFilter.Value;
                int filterValueListIndex = 1;
                foreach  (string filterValue in filterValueList)
                {
                    parameters.Add("Filter" + "."  + describeVpnConnectionsRequestFilterListIndex + "." + "Value" + "."  + filterValueListIndex, filterValue);
                    filterValueListIndex++;
                }

                describeVpnConnectionsRequestFilterListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DescribeCustomerGatewaysRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeCustomerGateways(DescribeCustomerGatewaysRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeCustomerGateways");
            List<string> describeCustomerGatewaysRequestCustomerGatewayIdList  =  request.CustomerGatewayId;
            int describeCustomerGatewaysRequestCustomerGatewayIdListIndex = 1;
            foreach  (string describeCustomerGatewaysRequestCustomerGatewayId in describeCustomerGatewaysRequestCustomerGatewayIdList)
            {
                parameters.Add("CustomerGatewayId" + "."  + describeCustomerGatewaysRequestCustomerGatewayIdListIndex, describeCustomerGatewaysRequestCustomerGatewayId);
                describeCustomerGatewaysRequestCustomerGatewayIdListIndex++;
            }
            List<Filter> describeCustomerGatewaysRequestFilterList = request.Filter;
            int describeCustomerGatewaysRequestFilterListIndex = 1;
            foreach (Filter describeCustomerGatewaysRequestFilter in describeCustomerGatewaysRequestFilterList)
            {
                if (describeCustomerGatewaysRequestFilter.IsSetName())
                {
                    parameters.Add("Filter" + "."  + describeCustomerGatewaysRequestFilterListIndex + "." + "Name", describeCustomerGatewaysRequestFilter.Name);
                }
                List<string> filterValueList  =  describeCustomerGatewaysRequestFilter.Value;
                int filterValueListIndex = 1;
                foreach  (string filterValue in filterValueList)
                {
                    parameters.Add("Filter" + "."  + describeCustomerGatewaysRequestFilterListIndex + "." + "Value" + "."  + filterValueListIndex, filterValue);
                    filterValueListIndex++;
                }

                describeCustomerGatewaysRequestFilterListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DescribeReservedInstancesOfferingsRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeReservedInstancesOfferings(DescribeReservedInstancesOfferingsRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeReservedInstancesOfferings");
            List<string> describeReservedInstancesOfferingsRequestReservedInstancesIdList  =  request.ReservedInstancesId;
            int describeReservedInstancesOfferingsRequestReservedInstancesIdListIndex = 1;
            foreach  (string describeReservedInstancesOfferingsRequestReservedInstancesId in describeReservedInstancesOfferingsRequestReservedInstancesIdList)
            {
                parameters.Add("ReservedInstancesId" + "."  + describeReservedInstancesOfferingsRequestReservedInstancesIdListIndex, describeReservedInstancesOfferingsRequestReservedInstancesId);
                describeReservedInstancesOfferingsRequestReservedInstancesIdListIndex++;
            }
            if (request.IsSetInstanceType())
            {
                parameters.Add("InstanceType", request.InstanceType);
            }
            if (request.IsSetAvailabilityZone())
            {
                parameters.Add("AvailabilityZone", request.AvailabilityZone);
            }
            if (request.IsSetProductDescription())
            {
                parameters.Add("ProductDescription", request.ProductDescription);
            }

            return parameters;
        }

        /**
         * Convert DescribeReservedInstancesRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeReservedInstances(DescribeReservedInstancesRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeReservedInstances");
            List<string> describeReservedInstancesRequestReservedInstancesIdList  =  request.ReservedInstancesId;
            int describeReservedInstancesRequestReservedInstancesIdListIndex = 1;
            foreach  (string describeReservedInstancesRequestReservedInstancesId in describeReservedInstancesRequestReservedInstancesIdList)
            {
                parameters.Add("ReservedInstancesId" + "."  + describeReservedInstancesRequestReservedInstancesIdListIndex, describeReservedInstancesRequestReservedInstancesId);
                describeReservedInstancesRequestReservedInstancesIdListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DescribeSubnetsRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeSubnets(DescribeSubnetsRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeSubnets");
            List<string> describeSubnetsRequestSubnetIdList  =  request.SubnetId;
            int describeSubnetsRequestSubnetIdListIndex = 1;
            foreach  (string describeSubnetsRequestSubnetId in describeSubnetsRequestSubnetIdList)
            {
                parameters.Add("SubnetId" + "."  + describeSubnetsRequestSubnetIdListIndex, describeSubnetsRequestSubnetId);
                describeSubnetsRequestSubnetIdListIndex++;
            }
            List<Filter> describeSubnetsRequestFilterList = request.Filter;
            int describeSubnetsRequestFilterListIndex = 1;
            foreach (Filter describeSubnetsRequestFilter in describeSubnetsRequestFilterList)
            {
                if (describeSubnetsRequestFilter.IsSetName())
                {
                    parameters.Add("Filter" + "."  + describeSubnetsRequestFilterListIndex + "." + "Name", describeSubnetsRequestFilter.Name);
                }
                List<string> filterValueList  =  describeSubnetsRequestFilter.Value;
                int filterValueListIndex = 1;
                foreach  (string filterValue in filterValueList)
                {
                    parameters.Add("Filter" + "."  + describeSubnetsRequestFilterListIndex + "." + "Value" + "."  + filterValueListIndex, filterValue);
                    filterValueListIndex++;
                }

                describeSubnetsRequestFilterListIndex++;
            }

            return parameters;
        }

        /**
         * Convert PurchaseReservedInstancesOfferingRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertPurchaseReservedInstancesOffering(PurchaseReservedInstancesOfferingRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "PurchaseReservedInstancesOffering");
            if (request.IsSetReservedInstancesOfferingId())
            {
                parameters.Add("ReservedInstancesOfferingId", request.ReservedInstancesOfferingId);
            }
            if (request.IsSetInstanceCount())
            {
                parameters.Add("InstanceCount", request.InstanceCount);
            }

            return parameters;
        }

        /**
         * Convert DeregisterImageRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDeregisterImage(DeregisterImageRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DeregisterImage");
            if (request.IsSetImageId())
            {
                parameters.Add("ImageId", request.ImageId);
            }

            return parameters;
        }

        /**
         * Convert DescribeAddressesRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeAddresses(DescribeAddressesRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeAddresses");
            List<string> describeAddressesRequestPublicIpList  =  request.PublicIp;
            int describeAddressesRequestPublicIpListIndex = 1;
            foreach  (string describeAddressesRequestPublicIp in describeAddressesRequestPublicIpList)
            {
                parameters.Add("PublicIp" + "."  + describeAddressesRequestPublicIpListIndex, describeAddressesRequestPublicIp);
                describeAddressesRequestPublicIpListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DescribeAvailabilityZonesRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeAvailabilityZones(DescribeAvailabilityZonesRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeAvailabilityZones");
            List<string> describeAvailabilityZonesRequestZoneNameList  =  request.ZoneName;
            int describeAvailabilityZonesRequestZoneNameListIndex = 1;
            foreach  (string describeAvailabilityZonesRequestZoneName in describeAvailabilityZonesRequestZoneNameList)
            {
                parameters.Add("ZoneName" + "."  + describeAvailabilityZonesRequestZoneNameListIndex, describeAvailabilityZonesRequestZoneName);
                describeAvailabilityZonesRequestZoneNameListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DescribeBundleTasksRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeBundleTasks(DescribeBundleTasksRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeBundleTasks");
            List<string> describeBundleTasksRequestBundleIdList  =  request.BundleId;
            int describeBundleTasksRequestBundleIdListIndex = 1;
            foreach  (string describeBundleTasksRequestBundleId in describeBundleTasksRequestBundleIdList)
            {
                parameters.Add("BundleId" + "."  + describeBundleTasksRequestBundleIdListIndex, describeBundleTasksRequestBundleId);
                describeBundleTasksRequestBundleIdListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DescribeImageAttributeRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeImageAttribute(DescribeImageAttributeRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeImageAttribute");
            if (request.IsSetImageId())
            {
                parameters.Add("ImageId", request.ImageId);
            }
            if (request.IsSetAttribute())
            {
                parameters.Add("Attribute", request.Attribute);
            }

            return parameters;
        }

        /**
         * Convert DescribeInstanceAttributeRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeInstanceAttribute(DescribeInstanceAttributeRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeInstanceAttribute");
            if (request.IsSetInstanceId())
            {
                parameters.Add("InstanceId", request.InstanceId);
            }
            if (request.IsSetAttribute())
            {
                parameters.Add("Attribute", request.Attribute);
            }

            return parameters;
        }

        /**
         * Convert DescribeSnapshotAttributeRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeSnapshotAttribute(DescribeSnapshotAttributeRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeSnapshotAttribute");
            if (request.IsSetSnapshotId())
            {
                parameters.Add("SnapshotId", request.SnapshotId);
            }
            if (request.IsSetAttribute())
            {
                parameters.Add("Attribute", request.Attribute);
            }

            return parameters;
        }

        /**
         * Convert DescribeImagesRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeImages(DescribeImagesRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeImages");
            List<string> describeImagesRequestImageIdList  =  request.ImageId;
            int describeImagesRequestImageIdListIndex = 1;
            foreach  (string describeImagesRequestImageId in describeImagesRequestImageIdList)
            {
                parameters.Add("ImageId" + "."  + describeImagesRequestImageIdListIndex, describeImagesRequestImageId);
                describeImagesRequestImageIdListIndex++;
            }
            List<string> describeImagesRequestOwnerList  =  request.Owner;
            int describeImagesRequestOwnerListIndex = 1;
            foreach  (string describeImagesRequestOwner in describeImagesRequestOwnerList)
            {
                parameters.Add("Owner" + "."  + describeImagesRequestOwnerListIndex, describeImagesRequestOwner);
                describeImagesRequestOwnerListIndex++;
            }
            List<string> describeImagesRequestExecutableByList  =  request.ExecutableBy;
            int describeImagesRequestExecutableByListIndex = 1;
            foreach  (string describeImagesRequestExecutableBy in describeImagesRequestExecutableByList)
            {
                parameters.Add("ExecutableBy" + "."  + describeImagesRequestExecutableByListIndex, describeImagesRequestExecutableBy);
                describeImagesRequestExecutableByListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DescribeInstancesRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeInstances(DescribeInstancesRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeInstances");
            List<string> describeInstancesRequestInstanceIdList  =  request.InstanceId;
            int describeInstancesRequestInstanceIdListIndex = 1;
            foreach  (string describeInstancesRequestInstanceId in describeInstancesRequestInstanceIdList)
            {
                parameters.Add("InstanceId" + "."  + describeInstancesRequestInstanceIdListIndex, describeInstancesRequestInstanceId);
                describeInstancesRequestInstanceIdListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DescribeKeyPairsRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeKeyPairs(DescribeKeyPairsRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeKeyPairs");
            List<string> describeKeyPairsRequestKeyNameList  =  request.KeyName;
            int describeKeyPairsRequestKeyNameListIndex = 1;
            foreach  (string describeKeyPairsRequestKeyName in describeKeyPairsRequestKeyNameList)
            {
                parameters.Add("KeyName" + "."  + describeKeyPairsRequestKeyNameListIndex, describeKeyPairsRequestKeyName);
                describeKeyPairsRequestKeyNameListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DescribeSecurityGroupsRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeSecurityGroups(DescribeSecurityGroupsRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeSecurityGroups");
            List<string> describeSecurityGroupsRequestGroupNameList  =  request.GroupName;
            int describeSecurityGroupsRequestGroupNameListIndex = 1;
            foreach  (string describeSecurityGroupsRequestGroupName in describeSecurityGroupsRequestGroupNameList)
            {
                parameters.Add("GroupName" + "."  + describeSecurityGroupsRequestGroupNameListIndex, describeSecurityGroupsRequestGroupName);
                describeSecurityGroupsRequestGroupNameListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DisassociateAddressRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDisassociateAddress(DisassociateAddressRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DisassociateAddress");
            if (request.IsSetPublicIp())
            {
                parameters.Add("PublicIp", request.PublicIp);
            }

            return parameters;
        }

        /**
         * Convert GetConsoleOutputRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertGetConsoleOutput(GetConsoleOutputRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "GetConsoleOutput");
            if (request.IsSetInstanceId())
            {
                parameters.Add("InstanceId", request.InstanceId);
            }

            return parameters;
        }

        /**
         * Convert GetPasswordDataRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertGetPasswordData(GetPasswordDataRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "GetPasswordData");
            if (request.IsSetInstanceId())
            {
                parameters.Add("InstanceId", request.InstanceId);
            }

            return parameters;
        }

        /**
         * Convert ModifyImageAttributeRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertModifyImageAttribute(ModifyImageAttributeRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "ModifyImageAttribute");
            if (request.IsSetImageId())
            {
                parameters.Add("ImageId", request.ImageId);
            }
            if (request.IsSetAttribute())
            {
                parameters.Add("Attribute", request.Attribute);
            }
            if (request.IsSetOperationType())
            {
                parameters.Add("OperationType", request.OperationType);
            }
            List<string> modifyImageAttributeRequestUserIdList  =  request.UserId;
            int modifyImageAttributeRequestUserIdListIndex = 1;
            foreach  (string modifyImageAttributeRequestUserId in modifyImageAttributeRequestUserIdList)
            {
                parameters.Add("UserId" + "."  + modifyImageAttributeRequestUserIdListIndex, modifyImageAttributeRequestUserId);
                modifyImageAttributeRequestUserIdListIndex++;
            }
            List<string> modifyImageAttributeRequestUserGroupList  =  request.UserGroup;
            int modifyImageAttributeRequestUserGroupListIndex = 1;
            foreach  (string modifyImageAttributeRequestUserGroup in modifyImageAttributeRequestUserGroupList)
            {
                parameters.Add("UserGroup" + "."  + modifyImageAttributeRequestUserGroupListIndex, modifyImageAttributeRequestUserGroup);
                modifyImageAttributeRequestUserGroupListIndex++;
            }
            List<string> modifyImageAttributeRequestProductCodeList  =  request.ProductCode;
            int modifyImageAttributeRequestProductCodeListIndex = 1;
            foreach  (string modifyImageAttributeRequestProductCode in modifyImageAttributeRequestProductCodeList)
            {
                parameters.Add("ProductCode" + "."  + modifyImageAttributeRequestProductCodeListIndex, modifyImageAttributeRequestProductCode);
                modifyImageAttributeRequestProductCodeListIndex++;
            }
            if (request.IsSetDescription())
            {
                parameters.Add("Description", request.Description);
            }

            return parameters;
        }

        /**
         * Convert ModifyInstanceAttributeRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertModifyInstanceAttribute(ModifyInstanceAttributeRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "ModifyInstanceAttribute");
            if (request.IsSetInstanceId())
            {
                parameters.Add("InstanceId", request.InstanceId);
            }
            if (request.IsSetAttribute())
            {
                parameters.Add("Attribute", request.Attribute);
            }
            if (request.IsSetValue())
            {
                parameters.Add("Value", request.Value);
            }
            List<InstanceBlockDeviceMappingParameter> modifyInstanceAttributeRequestBlockDeviceMappingList = request.BlockDeviceMapping;
            int modifyInstanceAttributeRequestBlockDeviceMappingListIndex = 1;
            foreach (InstanceBlockDeviceMappingParameter modifyInstanceAttributeRequestBlockDeviceMapping in modifyInstanceAttributeRequestBlockDeviceMappingList)
            {
                if (modifyInstanceAttributeRequestBlockDeviceMapping.IsSetDeviceName())
                {
                    parameters.Add("BlockDeviceMapping" + "."  + modifyInstanceAttributeRequestBlockDeviceMappingListIndex + "." + "DeviceName", modifyInstanceAttributeRequestBlockDeviceMapping.DeviceName);
                }
                if (modifyInstanceAttributeRequestBlockDeviceMapping.IsSetVirtualName())
                {
                    parameters.Add("BlockDeviceMapping" + "."  + modifyInstanceAttributeRequestBlockDeviceMappingListIndex + "." + "VirtualName", modifyInstanceAttributeRequestBlockDeviceMapping.VirtualName);
                }
                if (modifyInstanceAttributeRequestBlockDeviceMapping.IsSetEbs())
                {
                    InstanceEbsBlockDeviceParameter  blockDeviceMappingEbs = modifyInstanceAttributeRequestBlockDeviceMapping.Ebs;
                    if (blockDeviceMappingEbs.IsSetVolumeId())
                    {
                        parameters.Add("BlockDeviceMapping" + "."  + modifyInstanceAttributeRequestBlockDeviceMappingListIndex + "." + "Ebs" + "." + "VolumeId", blockDeviceMappingEbs.VolumeId);
                    }
                    if (blockDeviceMappingEbs.IsSetDeleteOnTermination())
                    {
                        parameters.Add("BlockDeviceMapping" + "."  + modifyInstanceAttributeRequestBlockDeviceMappingListIndex + "." + "Ebs" + "." + "DeleteOnTermination", (blockDeviceMappingEbs.DeleteOnTermination + "").ToLower());
                    }
                }
                if (modifyInstanceAttributeRequestBlockDeviceMapping.IsSetNoDevice())
                {
                    parameters.Add("BlockDeviceMapping" + "."  + modifyInstanceAttributeRequestBlockDeviceMappingListIndex + "." + "NoDevice", modifyInstanceAttributeRequestBlockDeviceMapping.NoDevice);
                }

                modifyInstanceAttributeRequestBlockDeviceMappingListIndex++;
            }

            return parameters;
        }

        /**
         * Convert ModifySnapshotAttributeRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertModifySnapshotAttribute(ModifySnapshotAttributeRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "ModifySnapshotAttribute");
            if (request.IsSetSnapshotId())
            {
                parameters.Add("SnapshotId", request.SnapshotId);
            }
            if (request.IsSetAttribute())
            {
                parameters.Add("Attribute", request.Attribute);
            }
            if (request.IsSetOperationType())
            {
                parameters.Add("OperationType", request.OperationType);
            }
            List<string> modifySnapshotAttributeRequestUserIdList  =  request.UserId;
            int modifySnapshotAttributeRequestUserIdListIndex = 1;
            foreach  (string modifySnapshotAttributeRequestUserId in modifySnapshotAttributeRequestUserIdList)
            {
                parameters.Add("UserId" + "."  + modifySnapshotAttributeRequestUserIdListIndex, modifySnapshotAttributeRequestUserId);
                modifySnapshotAttributeRequestUserIdListIndex++;
            }
            List<string> modifySnapshotAttributeRequestUserGroupList  =  request.UserGroup;
            int modifySnapshotAttributeRequestUserGroupListIndex = 1;
            foreach  (string modifySnapshotAttributeRequestUserGroup in modifySnapshotAttributeRequestUserGroupList)
            {
                parameters.Add("UserGroup" + "."  + modifySnapshotAttributeRequestUserGroupListIndex, modifySnapshotAttributeRequestUserGroup);
                modifySnapshotAttributeRequestUserGroupListIndex++;
            }

            return parameters;
        }

        /**
         * Convert MonitorInstancesRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertMonitorInstances(MonitorInstancesRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "MonitorInstances");
            List<string> monitorInstancesRequestInstanceIdList  =  request.InstanceId;
            int monitorInstancesRequestInstanceIdListIndex = 1;
            foreach  (string monitorInstancesRequestInstanceId in monitorInstancesRequestInstanceIdList)
            {
                parameters.Add("InstanceId" + "."  + monitorInstancesRequestInstanceIdListIndex, monitorInstancesRequestInstanceId);
                monitorInstancesRequestInstanceIdListIndex++;
            }

            return parameters;
        }

        /**
         * Convert UnmonitorInstancesRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertUnmonitorInstances(UnmonitorInstancesRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "UnmonitorInstances");
            List<string> unmonitorInstancesRequestInstanceIdList  =  request.InstanceId;
            int unmonitorInstancesRequestInstanceIdListIndex = 1;
            foreach  (string unmonitorInstancesRequestInstanceId in unmonitorInstancesRequestInstanceIdList)
            {
                parameters.Add("InstanceId" + "."  + unmonitorInstancesRequestInstanceIdListIndex, unmonitorInstancesRequestInstanceId);
                unmonitorInstancesRequestInstanceIdListIndex++;
            }

            return parameters;
        }

        /**
         * Convert RebootInstancesRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertRebootInstances(RebootInstancesRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "RebootInstances");
            List<string> rebootInstancesRequestInstanceIdList  =  request.InstanceId;
            int rebootInstancesRequestInstanceIdListIndex = 1;
            foreach  (string rebootInstancesRequestInstanceId in rebootInstancesRequestInstanceIdList)
            {
                parameters.Add("InstanceId" + "."  + rebootInstancesRequestInstanceIdListIndex, rebootInstancesRequestInstanceId);
                rebootInstancesRequestInstanceIdListIndex++;
            }

            return parameters;
        }

        /**
         * Convert RegisterImageRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertRegisterImage(RegisterImageRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "RegisterImage");
            if (request.IsSetImageLocation())
            {
                parameters.Add("ImageLocation", request.ImageLocation);
            }
            if (request.IsSetName())
            {
                parameters.Add("Name", request.Name);
            }
            if (request.IsSetDescription())
            {
                parameters.Add("Description", request.Description);
            }
            if (request.IsSetArchitecture())
            {
                parameters.Add("Architecture", request.Architecture);
            }
            if (request.IsSetKernelId())
            {
                parameters.Add("KernelId", request.KernelId);
            }
            if (request.IsSetRamdiskId())
            {
                parameters.Add("RamdiskId", request.RamdiskId);
            }
            if (request.IsSetRootDeviceName())
            {
                parameters.Add("RootDeviceName", request.RootDeviceName);
            }
            List<BlockDeviceMapping> registerImageRequestBlockDeviceMappingList = request.BlockDeviceMapping;
            int registerImageRequestBlockDeviceMappingListIndex = 1;
            foreach (BlockDeviceMapping registerImageRequestBlockDeviceMapping in registerImageRequestBlockDeviceMappingList)
            {
                if (registerImageRequestBlockDeviceMapping.IsSetDeviceName())
                {
                    parameters.Add("BlockDeviceMapping" + "."  + registerImageRequestBlockDeviceMappingListIndex + "." + "DeviceName", registerImageRequestBlockDeviceMapping.DeviceName);
                }
                if (registerImageRequestBlockDeviceMapping.IsSetVirtualName())
                {
                    parameters.Add("BlockDeviceMapping" + "."  + registerImageRequestBlockDeviceMappingListIndex + "." + "VirtualName", registerImageRequestBlockDeviceMapping.VirtualName);
                }
                if (registerImageRequestBlockDeviceMapping.IsSetEbs())
                {
                    EbsBlockDevice  blockDeviceMappingEbs = registerImageRequestBlockDeviceMapping.Ebs;
                    if (blockDeviceMappingEbs.IsSetSnapshotId())
                    {
                        parameters.Add("BlockDeviceMapping" + "."  + registerImageRequestBlockDeviceMappingListIndex + "." + "Ebs" + "." + "SnapshotId", blockDeviceMappingEbs.SnapshotId);
                    }
                    if (blockDeviceMappingEbs.IsSetVolumeSize())
                    {
                        parameters.Add("BlockDeviceMapping" + "."  + registerImageRequestBlockDeviceMappingListIndex + "." + "Ebs" + "." + "VolumeSize", (blockDeviceMappingEbs.VolumeSize + ""));
                    }
                    if (blockDeviceMappingEbs.IsSetDeleteOnTermination())
                    {
                        parameters.Add("BlockDeviceMapping" + "."  + registerImageRequestBlockDeviceMappingListIndex + "." + "Ebs" + "." + "DeleteOnTermination", (blockDeviceMappingEbs.DeleteOnTermination + "").ToLower());
                    }
                }
                if (registerImageRequestBlockDeviceMapping.IsSetNoDevice())
                {
                    parameters.Add("BlockDeviceMapping" + "."  + registerImageRequestBlockDeviceMappingListIndex + "." + "NoDevice", registerImageRequestBlockDeviceMapping.NoDevice);
                }

                registerImageRequestBlockDeviceMappingListIndex++;
            }

            return parameters;
        }

        /**
         * Convert ReleaseAddressRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertReleaseAddress(ReleaseAddressRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "ReleaseAddress");
            if (request.IsSetPublicIp())
            {
                parameters.Add("PublicIp", request.PublicIp);
            }

            return parameters;
        }

        /**
         * Convert ResetImageAttributeRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertResetImageAttribute(ResetImageAttributeRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "ResetImageAttribute");
            if (request.IsSetImageId())
            {
                parameters.Add("ImageId", request.ImageId);
            }
            if (request.IsSetAttribute())
            {
                parameters.Add("Attribute", request.Attribute);
            }

            return parameters;
        }

        /**
         * Convert ResetInstanceAttributeRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertResetInstanceAttribute(ResetInstanceAttributeRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "ResetInstanceAttribute");
            if (request.IsSetInstanceId())
            {
                parameters.Add("InstanceId", request.InstanceId);
            }
            if (request.IsSetAttribute())
            {
                parameters.Add("Attribute", request.Attribute);
            }

            return parameters;
        }

        /**
         * Convert ResetSnapshotAttributeRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertResetSnapshotAttribute(ResetSnapshotAttributeRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "ResetSnapshotAttribute");
            if (request.IsSetSnapshotId())
            {
                parameters.Add("SnapshotId", request.SnapshotId);
            }
            if (request.IsSetAttribute())
            {
                parameters.Add("Attribute", request.Attribute);
            }

            return parameters;
        }

        /**
         * Convert RevokeSecurityGroupIngressRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertRevokeSecurityGroupIngress(RevokeSecurityGroupIngressRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "RevokeSecurityGroupIngress");
            if (request.IsSetUserId())
            {
                parameters.Add("UserId", request.UserId);
            }
            if (request.IsSetGroupName())
            {
                parameters.Add("GroupName", request.GroupName);
            }
            if (request.IsSetSourceSecurityGroupName())
            {
                parameters.Add("SourceSecurityGroupName", request.SourceSecurityGroupName);
            }
            if (request.IsSetSourceSecurityGroupOwnerId())
            {
                parameters.Add("SourceSecurityGroupOwnerId", request.SourceSecurityGroupOwnerId);
            }
            if (request.IsSetIpProtocol())
            {
                parameters.Add("IpProtocol", request.IpProtocol);
            }
            if (request.IsSetFromPort())
            {
                parameters.Add("FromPort", (request.FromPort + ""));
            }
            if (request.IsSetToPort())
            {
                parameters.Add("ToPort", (request.ToPort + ""));
            }
            if (request.IsSetCidrIp())
            {
                parameters.Add("CidrIp", request.CidrIp);
            }

            return parameters;
        }

        /**
         * Convert RunInstancesRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertRunInstances(RunInstancesRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "RunInstances");
            if (request.IsSetImageId())
            {
                parameters.Add("ImageId", request.ImageId);
            }
            if (request.IsSetMinCount())
            {
                parameters.Add("MinCount", (request.MinCount + ""));
            }
            if (request.IsSetMaxCount())
            {
                parameters.Add("MaxCount", (request.MaxCount + ""));
            }
            if (request.IsSetKeyName())
            {
                parameters.Add("KeyName", request.KeyName);
            }
            List<string> runInstancesRequestSecurityGroupList  =  request.SecurityGroup;
            int runInstancesRequestSecurityGroupListIndex = 1;
            foreach  (string runInstancesRequestSecurityGroup in runInstancesRequestSecurityGroupList)
            {
                parameters.Add("SecurityGroup" + "."  + runInstancesRequestSecurityGroupListIndex, runInstancesRequestSecurityGroup);
                runInstancesRequestSecurityGroupListIndex++;
            }
            if (request.IsSetUserData())
            {
                parameters.Add("UserData", request.UserData);
            }
            if (request.IsSetInstanceType())
            {
                parameters.Add("InstanceType", request.InstanceType);
            }
            if (request.IsSetPlacement())
            {
                Placement  runInstancesRequestPlacement = request.Placement;
                if (runInstancesRequestPlacement.IsSetAvailabilityZone())
                {
                    parameters.Add("Placement" + "." + "AvailabilityZone", runInstancesRequestPlacement.AvailabilityZone);
                }
            }
            if (request.IsSetKernelId())
            {
                parameters.Add("KernelId", request.KernelId);
            }
            if (request.IsSetRamdiskId())
            {
                parameters.Add("RamdiskId", request.RamdiskId);
            }
            List<BlockDeviceMapping> runInstancesRequestBlockDeviceMappingList = request.BlockDeviceMapping;
            int runInstancesRequestBlockDeviceMappingListIndex = 1;
            foreach (BlockDeviceMapping runInstancesRequestBlockDeviceMapping in runInstancesRequestBlockDeviceMappingList)
            {
                if (runInstancesRequestBlockDeviceMapping.IsSetDeviceName())
                {
                    parameters.Add("BlockDeviceMapping" + "."  + runInstancesRequestBlockDeviceMappingListIndex + "." + "DeviceName", runInstancesRequestBlockDeviceMapping.DeviceName);
                }
                if (runInstancesRequestBlockDeviceMapping.IsSetVirtualName())
                {
                    parameters.Add("BlockDeviceMapping" + "."  + runInstancesRequestBlockDeviceMappingListIndex + "." + "VirtualName", runInstancesRequestBlockDeviceMapping.VirtualName);
                }
                if (runInstancesRequestBlockDeviceMapping.IsSetEbs())
                {
                    EbsBlockDevice  blockDeviceMappingEbs = runInstancesRequestBlockDeviceMapping.Ebs;
                    if (blockDeviceMappingEbs.IsSetSnapshotId())
                    {
                        parameters.Add("BlockDeviceMapping" + "."  + runInstancesRequestBlockDeviceMappingListIndex + "." + "Ebs" + "." + "SnapshotId", blockDeviceMappingEbs.SnapshotId);
                    }
                    if (blockDeviceMappingEbs.IsSetVolumeSize())
                    {
                        parameters.Add("BlockDeviceMapping" + "."  + runInstancesRequestBlockDeviceMappingListIndex + "." + "Ebs" + "." + "VolumeSize", (blockDeviceMappingEbs.VolumeSize + ""));
                    }
                    if (blockDeviceMappingEbs.IsSetDeleteOnTermination())
                    {
                        parameters.Add("BlockDeviceMapping" + "."  + runInstancesRequestBlockDeviceMappingListIndex + "." + "Ebs" + "." + "DeleteOnTermination", (blockDeviceMappingEbs.DeleteOnTermination + "").ToLower());
                    }
                }
                if (runInstancesRequestBlockDeviceMapping.IsSetNoDevice())
                {
                    parameters.Add("BlockDeviceMapping" + "."  + runInstancesRequestBlockDeviceMappingListIndex + "." + "NoDevice", runInstancesRequestBlockDeviceMapping.NoDevice);
                }

                runInstancesRequestBlockDeviceMappingListIndex++;
            }
            if (request.IsSetMonitoring())
            {
                MonitoringSpecification  runInstancesRequestMonitoring = request.Monitoring;
                if (runInstancesRequestMonitoring.IsSetEnabled())
                {
                    parameters.Add("Monitoring" + "." + "Enabled", (runInstancesRequestMonitoring.Enabled + "").ToLower());
                }
            }
            if (request.IsSetSubnetId())
            {
                parameters.Add("SubnetId", request.SubnetId);
            }
            if (request.IsSetAdditionalInfo())
            {
                parameters.Add("AdditionalInfo", request.AdditionalInfo);
            }
            if (request.IsSetDisableApiTermination())
            {
                parameters.Add("DisableApiTermination", (request.DisableApiTermination + "").ToLower());
            }
            if (request.IsSetInstanceInitiatedShutdownBehavior())
            {
                parameters.Add("InstanceInitiatedShutdownBehavior", request.InstanceInitiatedShutdownBehavior);
            }

            return parameters;
        }

        /**
         * Convert StopInstancesRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertStopInstances(StopInstancesRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "StopInstances");
            List<string> stopInstancesRequestInstanceIdList  =  request.InstanceId;
            int stopInstancesRequestInstanceIdListIndex = 1;
            foreach  (string stopInstancesRequestInstanceId in stopInstancesRequestInstanceIdList)
            {
                parameters.Add("InstanceId" + "."  + stopInstancesRequestInstanceIdListIndex, stopInstancesRequestInstanceId);
                stopInstancesRequestInstanceIdListIndex++;
            }
            if (request.IsSetForce())
            {
                parameters.Add("Force", (request.Force + "").ToLower());
            }

            return parameters;
        }

        /**
         * Convert StartInstancesRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertStartInstances(StartInstancesRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "StartInstances");
            List<string> startInstancesRequestInstanceIdList  =  request.InstanceId;
            int startInstancesRequestInstanceIdListIndex = 1;
            foreach  (string startInstancesRequestInstanceId in startInstancesRequestInstanceIdList)
            {
                parameters.Add("InstanceId" + "."  + startInstancesRequestInstanceIdListIndex, startInstancesRequestInstanceId);
                startInstancesRequestInstanceIdListIndex++;
            }

            return parameters;
        }

        /**
         * Convert TerminateInstancesRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertTerminateInstances(TerminateInstancesRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "TerminateInstances");
            List<string> terminateInstancesRequestInstanceIdList  =  request.InstanceId;
            int terminateInstancesRequestInstanceIdListIndex = 1;
            foreach  (string terminateInstancesRequestInstanceId in terminateInstancesRequestInstanceIdList)
            {
                parameters.Add("InstanceId" + "."  + terminateInstancesRequestInstanceIdListIndex, terminateInstancesRequestInstanceId);
                terminateInstancesRequestInstanceIdListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DeleteVolumeRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDeleteVolume(DeleteVolumeRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DeleteVolume");
            if (request.IsSetVolumeId())
            {
                parameters.Add("VolumeId", request.VolumeId);
            }

            return parameters;
        }

        /**
         * Convert CreateVolumeRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertCreateVolume(CreateVolumeRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "CreateVolume");
            if (request.IsSetSize())
            {
                parameters.Add("Size", request.Size);
            }
            if (request.IsSetSnapshotId())
            {
                parameters.Add("SnapshotId", request.SnapshotId);
            }
            if (request.IsSetAvailabilityZone())
            {
                parameters.Add("AvailabilityZone", request.AvailabilityZone);
            }

            return parameters;
        }

        /**
         * Convert DescribeVolumesRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeVolumes(DescribeVolumesRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeVolumes");
            List<string> describeVolumesRequestVolumeIdList  =  request.VolumeId;
            int describeVolumesRequestVolumeIdListIndex = 1;
            foreach  (string describeVolumesRequestVolumeId in describeVolumesRequestVolumeIdList)
            {
                parameters.Add("VolumeId" + "."  + describeVolumesRequestVolumeIdListIndex, describeVolumesRequestVolumeId);
                describeVolumesRequestVolumeIdListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DetachVolumeRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDetachVolume(DetachVolumeRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DetachVolume");
            if (request.IsSetVolumeId())
            {
                parameters.Add("VolumeId", request.VolumeId);
            }
            if (request.IsSetInstanceId())
            {
                parameters.Add("InstanceId", request.InstanceId);
            }
            if (request.IsSetDevice())
            {
                parameters.Add("Device", request.Device);
            }
            if (request.IsSetForce())
            {
                parameters.Add("Force", (request.Force + "").ToLower());
            }

            return parameters;
        }

        /**
         * Convert DetachVpnGatewayRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDetachVpnGateway(DetachVpnGatewayRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DetachVpnGateway");
            if (request.IsSetVpnGatewayId())
            {
                parameters.Add("VpnGatewayId", request.VpnGatewayId);
            }
            if (request.IsSetVpcId())
            {
                parameters.Add("VpcId", request.VpcId);
            }

            return parameters;
        }

        /**
         * Convert DescribeSnapshotsRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeSnapshots(DescribeSnapshotsRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeSnapshots");
            List<string> describeSnapshotsRequestSnapshotIdList  =  request.SnapshotId;
            int describeSnapshotsRequestSnapshotIdListIndex = 1;
            foreach  (string describeSnapshotsRequestSnapshotId in describeSnapshotsRequestSnapshotIdList)
            {
                parameters.Add("SnapshotId" + "."  + describeSnapshotsRequestSnapshotIdListIndex, describeSnapshotsRequestSnapshotId);
                describeSnapshotsRequestSnapshotIdListIndex++;
            }
            if (request.IsSetOwner())
            {
                parameters.Add("Owner", request.Owner);
            }
            if (request.IsSetRestorableBy())
            {
                parameters.Add("RestorableBy", request.RestorableBy);
            }

            return parameters;
        }

        /**
         * Convert DeleteSnapshotRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDeleteSnapshot(DeleteSnapshotRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DeleteSnapshot");
            if (request.IsSetSnapshotId())
            {
                parameters.Add("SnapshotId", request.SnapshotId);
            }

            return parameters;
        }

        /**
         * Convert CreateSnapshotRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertCreateSnapshot(CreateSnapshotRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "CreateSnapshot");
            if (request.IsSetVolumeId())
            {
                parameters.Add("VolumeId", request.VolumeId);
            }
            if (request.IsSetDescription())
            {
                parameters.Add("Description", request.Description);
            }

            return parameters;
        }

        /**
         * Convert AttachVolumeRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertAttachVolume(AttachVolumeRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "AttachVolume");
            if (request.IsSetVolumeId())
            {
                parameters.Add("VolumeId", request.VolumeId);
            }
            if (request.IsSetInstanceId())
            {
                parameters.Add("InstanceId", request.InstanceId);
            }
            if (request.IsSetDevice())
            {
                parameters.Add("Device", request.Device);
            }

            return parameters;
        }

        /**
         * Convert DescribeRegionsRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeRegions(DescribeRegionsRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeRegions");
            List<string> describeRegionsRequestRegionNameList  =  request.RegionName;
            int describeRegionsRequestRegionNameListIndex = 1;
            foreach  (string describeRegionsRequestRegionName in describeRegionsRequestRegionNameList)
            {
                parameters.Add("RegionName" + "."  + describeRegionsRequestRegionNameListIndex, describeRegionsRequestRegionName);
                describeRegionsRequestRegionNameListIndex++;
            }

            return parameters;
        }

        /**
         * Convert RequestSpotInstancesRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertRequestSpotInstances(RequestSpotInstancesRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "RequestSpotInstances");
            if (request.IsSetSpotPrice())
            {
                parameters.Add("SpotPrice", request.SpotPrice);
            }
            if (request.IsSetInstanceCount())
            {
                parameters.Add("InstanceCount", (request.InstanceCount + ""));
            }
            if (request.IsSetType())
            {
                parameters.Add("Type", request.Type);
            }
            if (request.IsSetValidFrom())
            {
                parameters.Add("ValidFrom", request.ValidFrom);
            }
            if (request.IsSetValidUntil())
            {
                parameters.Add("ValidUntil", request.ValidUntil);
            }
            if (request.IsSetLaunchGroup())
            {
                parameters.Add("LaunchGroup", request.LaunchGroup);
            }
            if (request.IsSetAvailabilityZoneGroup())
            {
                parameters.Add("AvailabilityZoneGroup", request.AvailabilityZoneGroup);
            }
            if (request.IsSetLaunchSpecification())
            {
                LaunchSpecification  requestSpotInstancesRequestLaunchSpecification = request.LaunchSpecification;
                if (requestSpotInstancesRequestLaunchSpecification.IsSetImageId())
                {
                    parameters.Add("LaunchSpecification" + "." + "ImageId", requestSpotInstancesRequestLaunchSpecification.ImageId);
                }
                if (requestSpotInstancesRequestLaunchSpecification.IsSetKeyName())
                {
                    parameters.Add("LaunchSpecification" + "." + "KeyName", requestSpotInstancesRequestLaunchSpecification.KeyName);
                }
                List<string> launchSpecificationSecurityGroupList  =  requestSpotInstancesRequestLaunchSpecification.SecurityGroup;
                int launchSpecificationSecurityGroupListIndex = 1;
                foreach  (string launchSpecificationSecurityGroup in launchSpecificationSecurityGroupList)
                {
                    parameters.Add("LaunchSpecification" + "." + "SecurityGroup" + "."  + launchSpecificationSecurityGroupListIndex, launchSpecificationSecurityGroup);
                    launchSpecificationSecurityGroupListIndex++;
                }
                if (requestSpotInstancesRequestLaunchSpecification.IsSetUserData())
                {
                    parameters.Add("LaunchSpecification" + "." + "UserData", requestSpotInstancesRequestLaunchSpecification.UserData);
                }
                if (requestSpotInstancesRequestLaunchSpecification.IsSetAddressingType())
                {
                    parameters.Add("LaunchSpecification" + "." + "AddressingType", requestSpotInstancesRequestLaunchSpecification.AddressingType);
                }
                if (requestSpotInstancesRequestLaunchSpecification.IsSetInstanceType())
                {
                    parameters.Add("LaunchSpecification" + "." + "InstanceType", requestSpotInstancesRequestLaunchSpecification.InstanceType);
                }
                if (requestSpotInstancesRequestLaunchSpecification.IsSetPlacement())
                {
                    Placement  launchSpecificationPlacement = requestSpotInstancesRequestLaunchSpecification.Placement;
                    if (launchSpecificationPlacement.IsSetAvailabilityZone())
                    {
                        parameters.Add("LaunchSpecification" + "." + "Placement" + "." + "AvailabilityZone", launchSpecificationPlacement.AvailabilityZone);
                    }
                }
                if (requestSpotInstancesRequestLaunchSpecification.IsSetKernelId())
                {
                    parameters.Add("LaunchSpecification" + "." + "KernelId", requestSpotInstancesRequestLaunchSpecification.KernelId);
                }
                if (requestSpotInstancesRequestLaunchSpecification.IsSetRamdiskId())
                {
                    parameters.Add("LaunchSpecification" + "." + "RamdiskId", requestSpotInstancesRequestLaunchSpecification.RamdiskId);
                }
                List<BlockDeviceMapping> launchSpecificationBlockDeviceMappingList = requestSpotInstancesRequestLaunchSpecification.BlockDeviceMapping;
                int launchSpecificationBlockDeviceMappingListIndex = 1;
                foreach (BlockDeviceMapping launchSpecificationBlockDeviceMapping in launchSpecificationBlockDeviceMappingList)
                {
                    if (launchSpecificationBlockDeviceMapping.IsSetDeviceName())
                    {
                        parameters.Add("LaunchSpecification" + "." + "BlockDeviceMapping" + "."  + launchSpecificationBlockDeviceMappingListIndex + "." + "DeviceName", launchSpecificationBlockDeviceMapping.DeviceName);
                    }
                    if (launchSpecificationBlockDeviceMapping.IsSetVirtualName())
                    {
                        parameters.Add("LaunchSpecification" + "." + "BlockDeviceMapping" + "."  + launchSpecificationBlockDeviceMappingListIndex + "." + "VirtualName", launchSpecificationBlockDeviceMapping.VirtualName);
                    }
                    if (launchSpecificationBlockDeviceMapping.IsSetEbs())
                    {
                        EbsBlockDevice  blockDeviceMappingEbs = launchSpecificationBlockDeviceMapping.Ebs;
                        if (blockDeviceMappingEbs.IsSetSnapshotId())
                        {
                            parameters.Add("LaunchSpecification" + "." + "BlockDeviceMapping" + "."  + launchSpecificationBlockDeviceMappingListIndex + "." + "Ebs" + "." + "SnapshotId", blockDeviceMappingEbs.SnapshotId);
                        }
                        if (blockDeviceMappingEbs.IsSetVolumeSize())
                        {
                            parameters.Add("LaunchSpecification" + "." + "BlockDeviceMapping" + "."  + launchSpecificationBlockDeviceMappingListIndex + "." + "Ebs" + "." + "VolumeSize", (blockDeviceMappingEbs.VolumeSize + ""));
                        }
                        if (blockDeviceMappingEbs.IsSetDeleteOnTermination())
                        {
                            parameters.Add("LaunchSpecification" + "." + "BlockDeviceMapping" + "."  + launchSpecificationBlockDeviceMappingListIndex + "." + "Ebs" + "." + "DeleteOnTermination", (blockDeviceMappingEbs.DeleteOnTermination + "").ToLower());
                        }
                    }
                    if (launchSpecificationBlockDeviceMapping.IsSetNoDevice())
                    {
                        parameters.Add("LaunchSpecification" + "." + "BlockDeviceMapping" + "."  + launchSpecificationBlockDeviceMappingListIndex + "." + "NoDevice", launchSpecificationBlockDeviceMapping.NoDevice);
                    }

                    launchSpecificationBlockDeviceMappingListIndex++;
                }
                if (requestSpotInstancesRequestLaunchSpecification.IsSetMonitoring())
                {
                    MonitoringSpecification  launchSpecificationMonitoring = requestSpotInstancesRequestLaunchSpecification.Monitoring;
                    if (launchSpecificationMonitoring.IsSetEnabled())
                    {
                        parameters.Add("LaunchSpecification" + "." + "Monitoring" + "." + "Enabled", (launchSpecificationMonitoring.Enabled + "").ToLower());
                    }
                }
                if (requestSpotInstancesRequestLaunchSpecification.IsSetSubnetId())
                {
                    parameters.Add("LaunchSpecification" + "." + "SubnetId", requestSpotInstancesRequestLaunchSpecification.SubnetId);
                }
            }

            return parameters;
        }

        /**
         * Convert DescribeSpotInstanceRequestsRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeSpotInstanceRequests(DescribeSpotInstanceRequestsRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeSpotInstanceRequests");
            List<string> describeSpotInstanceRequestsRequestSpotInstanceRequestIdList  =  request.SpotInstanceRequestId;
            int describeSpotInstanceRequestsRequestSpotInstanceRequestIdListIndex = 1;
            foreach  (string describeSpotInstanceRequestsRequestSpotInstanceRequestId in describeSpotInstanceRequestsRequestSpotInstanceRequestIdList)
            {
                parameters.Add("SpotInstanceRequestId" + "."  + describeSpotInstanceRequestsRequestSpotInstanceRequestIdListIndex, describeSpotInstanceRequestsRequestSpotInstanceRequestId);
                describeSpotInstanceRequestsRequestSpotInstanceRequestIdListIndex++;
            }

            return parameters;
        }

        /**
         * Convert CancelSpotInstanceRequestsRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertCancelSpotInstanceRequests(CancelSpotInstanceRequestsRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "CancelSpotInstanceRequests");
            List<string> cancelSpotInstanceRequestsRequestSpotInstanceRequestIdList  =  request.SpotInstanceRequestId;
            int cancelSpotInstanceRequestsRequestSpotInstanceRequestIdListIndex = 1;
            foreach  (string cancelSpotInstanceRequestsRequestSpotInstanceRequestId in cancelSpotInstanceRequestsRequestSpotInstanceRequestIdList)
            {
                parameters.Add("SpotInstanceRequestId" + "."  + cancelSpotInstanceRequestsRequestSpotInstanceRequestIdListIndex, cancelSpotInstanceRequestsRequestSpotInstanceRequestId);
                cancelSpotInstanceRequestsRequestSpotInstanceRequestIdListIndex++;
            }

            return parameters;
        }

        /**
         * Convert DescribeSpotPriceHistoryRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeSpotPriceHistory(DescribeSpotPriceHistoryRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeSpotPriceHistory");
            if (request.IsSetStartTime())
            {
                parameters.Add("StartTime", request.StartTime);
            }
            if (request.IsSetEndTime())
            {
                parameters.Add("EndTime", request.EndTime);
            }
            List<string> describeSpotPriceHistoryRequestInstanceTypeList  =  request.InstanceType;
            int describeSpotPriceHistoryRequestInstanceTypeListIndex = 1;
            foreach  (string describeSpotPriceHistoryRequestInstanceType in describeSpotPriceHistoryRequestInstanceTypeList)
            {
                parameters.Add("InstanceType" + "."  + describeSpotPriceHistoryRequestInstanceTypeListIndex, describeSpotPriceHistoryRequestInstanceType);
                describeSpotPriceHistoryRequestInstanceTypeListIndex++;
            }
            List<string> describeSpotPriceHistoryRequestProductDescriptionList  =  request.ProductDescription;
            int describeSpotPriceHistoryRequestProductDescriptionListIndex = 1;
            foreach  (string describeSpotPriceHistoryRequestProductDescription in describeSpotPriceHistoryRequestProductDescriptionList)
            {
                parameters.Add("ProductDescription" + "."  + describeSpotPriceHistoryRequestProductDescriptionListIndex, describeSpotPriceHistoryRequestProductDescription);
                describeSpotPriceHistoryRequestProductDescriptionListIndex++;
            }

            return parameters;
        }

        /**
         * Convert CreateSpotDatafeedSubscriptionRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertCreateSpotDatafeedSubscription(CreateSpotDatafeedSubscriptionRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "CreateSpotDatafeedSubscription");
            if (request.IsSetBucket())
            {
                parameters.Add("Bucket", request.Bucket);
            }
            if (request.IsSetPrefix())
            {
                parameters.Add("Prefix", request.Prefix);
            }

            return parameters;
        }

        /**
         * Convert DescribeSpotDatafeedSubscriptionRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDescribeSpotDatafeedSubscription(DescribeSpotDatafeedSubscriptionRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DescribeSpotDatafeedSubscription");

            return parameters;
        }

        /**
         * Convert DeleteSpotDatafeedSubscriptionRequest to name value pairs
         */
        private static IDictionary<string, string> ConvertDeleteSpotDatafeedSubscription(DeleteSpotDatafeedSubscriptionRequest request)
        {
            IDictionary<string, string> parameters = new Dictionary<string, string>();
            parameters.Add("Action", "DeleteSpotDatafeedSubscription");

            return parameters;
        }

        /*
         *  Transforms response based on xslt template
         */
        private static string Transform(string responseBody, string action, Type t)
        {
            XslCompiledTransform transformer = new XslCompiledTransform();

            // Build the name of the xslt transform to apply to the response
            char[] seps = { ',' };

            Assembly assembly = Assembly.GetAssembly(t);
            string assemblyName = assembly.FullName;
            assemblyName = assemblyName.Split(seps)[0];

            string ns = t.Namespace;
            string resourceName = String.Concat(
                assemblyName,
                ".",
                ns,
                ".Model.",
                action,
                "Response.xslt"
                );

            using (XmlTextReader xmlReader = new XmlTextReader(assembly.GetManifestResourceStream(resourceName)))
            {
                transformer.Load(xmlReader);

                StringBuilder sb = new StringBuilder(1024);
                using (XmlTextReader xmlR = new XmlTextReader(new StringReader(responseBody)))
                {
                    using (StringWriter sw = new StringWriter(sb))
                    {
                        transformer.Transform(xmlR, null, sw);
                        return sb.ToString();
                    }
                }
            }
        }

        #endregion
    }
}
