// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.bridge.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.apache.commons.codec.binary.Base64;

import com.amazon.ec2.*;
import com.cloud.bridge.service.core.ec2.EC2Address;
import com.cloud.bridge.service.core.ec2.EC2AddressFilterSet;
import com.cloud.bridge.service.core.ec2.EC2AssociateAddress;
import com.cloud.bridge.service.core.ec2.EC2AuthorizeRevokeSecurityGroup;
import com.cloud.bridge.service.core.ec2.EC2AvailabilityZonesFilterSet;
import com.cloud.bridge.service.core.ec2.EC2CreateImage;
import com.cloud.bridge.service.core.ec2.EC2CreateImageResponse;
import com.cloud.bridge.service.core.ec2.EC2CreateKeyPair;
import com.cloud.bridge.service.core.ec2.EC2CreateVolume;
import com.cloud.bridge.service.core.ec2.EC2Tags;
import com.cloud.bridge.service.core.ec2.EC2DeleteKeyPair;
import com.cloud.bridge.service.core.ec2.EC2DescribeAddresses;
import com.cloud.bridge.service.core.ec2.EC2DescribeAddressesResponse;
import com.cloud.bridge.service.core.ec2.EC2DescribeAvailabilityZones;
import com.cloud.bridge.service.core.ec2.EC2DescribeAvailabilityZonesResponse;
import com.cloud.bridge.service.core.ec2.EC2DescribeImageAttribute;

import com.cloud.bridge.service.core.ec2.EC2AvailabilityZone;
import com.cloud.bridge.service.core.ec2.EC2DescribeImages;
import com.cloud.bridge.service.core.ec2.EC2DescribeImagesResponse;
import com.cloud.bridge.service.core.ec2.EC2DescribeInstances;
import com.cloud.bridge.service.core.ec2.EC2DescribeInstancesResponse;
import com.cloud.bridge.service.core.ec2.EC2DescribeKeyPairs;
import com.cloud.bridge.service.core.ec2.EC2DescribeKeyPairsResponse;
import com.cloud.bridge.service.core.ec2.EC2ImageFilterSet;
import com.cloud.bridge.service.core.ec2.EC2ImageLaunchPermission;
import com.cloud.bridge.service.core.ec2.EC2ModifyInstanceAttribute;
import com.cloud.bridge.service.core.ec2.EC2ResourceTag;
import com.cloud.bridge.service.core.ec2.EC2DescribeSecurityGroups;
import com.cloud.bridge.service.core.ec2.EC2DescribeSecurityGroupsResponse;
import com.cloud.bridge.service.core.ec2.EC2DescribeSnapshots;
import com.cloud.bridge.service.core.ec2.EC2DescribeSnapshotsResponse;
import com.cloud.bridge.service.core.ec2.EC2DescribeTags;
import com.cloud.bridge.service.core.ec2.EC2DescribeTagsResponse;
import com.cloud.bridge.service.core.ec2.EC2DescribeVolumes;
import com.cloud.bridge.service.core.ec2.EC2DescribeVolumesResponse;
import com.cloud.bridge.service.core.ec2.EC2DisassociateAddress;
import com.cloud.bridge.service.core.ec2.EC2Engine;
import com.cloud.bridge.service.core.ec2.EC2Filter;
import com.cloud.bridge.service.core.ec2.EC2GroupFilterSet;
import com.cloud.bridge.service.core.ec2.EC2Image;
import com.cloud.bridge.service.core.ec2.EC2ImageAttributes;
import com.cloud.bridge.service.core.ec2.EC2ImageAttributes.ImageAttribute;
import com.cloud.bridge.service.core.ec2.EC2ImportKeyPair;
import com.cloud.bridge.service.core.ec2.EC2Instance;
import com.cloud.bridge.service.core.ec2.EC2InstanceFilterSet;
import com.cloud.bridge.service.core.ec2.EC2IpPermission;
import com.cloud.bridge.service.core.ec2.EC2KeyPairFilterSet;
import com.cloud.bridge.service.core.ec2.EC2ModifyImageAttribute;
import com.cloud.bridge.service.core.ec2.EC2PasswordData;
import com.cloud.bridge.service.core.ec2.EC2RebootInstances;
import com.cloud.bridge.service.core.ec2.EC2RegisterImage;
import com.cloud.bridge.service.core.ec2.EC2ReleaseAddress;
import com.cloud.bridge.service.core.ec2.EC2TagKeyValue;
import com.cloud.bridge.service.core.ec2.EC2TagTypeId;
import com.cloud.bridge.service.core.ec2.EC2RunInstances;
import com.cloud.bridge.service.core.ec2.EC2RunInstancesResponse;
import com.cloud.bridge.service.core.ec2.EC2SSHKeyPair;
import com.cloud.bridge.service.core.ec2.EC2SecurityGroup;
import com.cloud.bridge.service.core.ec2.EC2Snapshot;
import com.cloud.bridge.service.core.ec2.EC2SnapshotFilterSet;
import com.cloud.bridge.service.core.ec2.EC2StartInstances;
import com.cloud.bridge.service.core.ec2.EC2StartInstancesResponse;
import com.cloud.bridge.service.core.ec2.EC2StopInstances;
import com.cloud.bridge.service.core.ec2.EC2StopInstancesResponse;
import com.cloud.bridge.service.core.ec2.EC2TagsFilterSet;
import com.cloud.bridge.service.core.ec2.EC2Volume;
import com.cloud.bridge.service.core.ec2.EC2VolumeFilterSet;
import com.cloud.bridge.service.exception.EC2ServiceException;
import com.cloud.bridge.service.exception.EC2ServiceException.ClientError;
import com.cloud.bridge.util.EC2RestAuth;

public class EC2SoapServiceImpl implements AmazonEC2SkeletonInterface {

    private static EC2Engine engine;

    @SuppressWarnings("static-access")
    public EC2SoapServiceImpl(EC2Engine engine) {
        this.engine = engine;
    }

    public AttachVolumeResponse attachVolume(AttachVolume attachVolume) {
        EC2Volume request = new EC2Volume();
        AttachVolumeType avt = attachVolume.getAttachVolume();

        request.setId(avt.getVolumeId());
        request.setInstanceId(avt.getInstanceId());
        request.setDevice(avt.getDevice());
        return toAttachVolumeResponse(engine.attachVolume(request));
    }

    public AuthorizeSecurityGroupIngressResponse authorizeSecurityGroupIngress(AuthorizeSecurityGroupIngress authorizeSecurityGroupIngress) {
        AuthorizeSecurityGroupIngressType sgit = authorizeSecurityGroupIngress.getAuthorizeSecurityGroupIngress();
        IpPermissionSetType ipPerms = sgit.getIpPermissions();

        EC2AuthorizeRevokeSecurityGroup request = toSecurityGroup(sgit.getAuthorizeSecurityGroupIngressTypeChoice_type0().getGroupName(), ipPerms.getItem());
        return toAuthorizeSecurityGroupIngressResponse(engine.authorizeSecurityGroup(request));
    }

    public RevokeSecurityGroupIngressResponse revokeSecurityGroupIngress(RevokeSecurityGroupIngress revokeSecurityGroupIngress) {
        RevokeSecurityGroupIngressType sgit = revokeSecurityGroupIngress.getRevokeSecurityGroupIngress();
        IpPermissionSetType ipPerms = sgit.getIpPermissions();

        EC2AuthorizeRevokeSecurityGroup request = toSecurityGroup(sgit.getRevokeSecurityGroupIngressTypeChoice_type0().getGroupName(), ipPerms.getItem());
        return toRevokeSecurityGroupIngressResponse(engine.revokeSecurityGroup(request));
    }

    /**
     * Authorize and Revoke Security Group Ingress have the same parameters.
     */
    private EC2AuthorizeRevokeSecurityGroup toSecurityGroup(String groupName, IpPermissionType[] items) {
        EC2AuthorizeRevokeSecurityGroup request = new EC2AuthorizeRevokeSecurityGroup();

        request.setName(groupName);

        for (IpPermissionType ipPerm : items) {
            EC2IpPermission perm = new EC2IpPermission();
            perm.setProtocol(ipPerm.getIpProtocol());
            if (ipPerm.getIpProtocol().equalsIgnoreCase("icmp")) {
                perm.setIcmpType(Integer.toString(ipPerm.getFromPort()));
                perm.setIcmpCode(Integer.toString(ipPerm.getToPort()));
            } else {
                perm.setFromPort(ipPerm.getFromPort());
                perm.setToPort(ipPerm.getToPort());
            }
            UserIdGroupPairSetType groups = ipPerm.getGroups();
            if (null != groups && groups.getItem() != null) {
                UserIdGroupPairType[] groupItems = groups.getItem();
                for (UserIdGroupPairType groupPair : groupItems) {
                    EC2SecurityGroup user = new EC2SecurityGroup();
                    user.setName(groupPair.getGroupName());
                    user.setAccount(groupPair.getUserId());
                    perm.addUser(user);
                }
            }

            IpRangeSetType ranges = ipPerm.getIpRanges();
            if (ranges != null && ranges.getItem() != null) {
                IpRangeItemType[] rangeItems = ranges.getItem();
                for (IpRangeItemType ipRange : rangeItems) {
                    perm.addIpRange(ipRange.getCidrIp());
                    perm.setCIDR(ipRange.getCidrIp());
                }
            }

            request.addIpPermission(perm);
        }
        return request;
    }

    public CreateImageResponse createImage(CreateImage createImage) {
        EC2CreateImage request = new EC2CreateImage();
        CreateImageType cit = createImage.getCreateImage();

        request.setInstanceId(cit.getInstanceId());
        request.setName(cit.getName());
        request.setDescription(cit.getDescription());
        return toCreateImageResponse(engine.createImage(request));
    }

    public CreateSecurityGroupResponse createSecurityGroup(CreateSecurityGroup createSecurityGroup) {
        CreateSecurityGroupType sgt = createSecurityGroup.getCreateSecurityGroup();

        return toCreateSecurityGroupResponse(engine.createSecurityGroup(sgt.getGroupName(), sgt.getGroupDescription()));
    }

    public CreateSnapshotResponse createSnapshot(CreateSnapshot createSnapshot) {
        CreateSnapshotType cst = createSnapshot.getCreateSnapshot();
        return toCreateSnapshotResponse(engine.createSnapshot(cst.getVolumeId()), engine);
    }

    public CreateVolumeResponse createVolume(CreateVolume createVolume) {
        EC2CreateVolume request = new EC2CreateVolume();
        CreateVolumeType cvt = createVolume.getCreateVolume();

        request.setSize(cvt.getSize());
        request.setSnapshotId(cvt.getSnapshotId() != null ? cvt.getSnapshotId() : null);
        request.setZoneName(cvt.getAvailabilityZone());
        return toCreateVolumeResponse(engine.createVolume(request));
    }

    public CreateTagsResponse createTags(CreateTags createTags) {
        EC2Tags request = new EC2Tags();
        ArrayList<String> resourceIdList = new ArrayList<String>();
        Map<String, String> resourceTagList = new HashMap<String, String>();

        CreateTagsType ctt = createTags.getCreateTags();

        ResourceIdSetType resourceIds = ctt.getResourcesSet();
        ResourceTagSetType resourceTags = ctt.getTagSet();

        ResourceIdSetItemType[] resourceIdItems = resourceIds.getItem();
        if (resourceIdItems != null) {
            for (int i = 0; i < resourceIdItems.length; i++)
                resourceIdList.add(resourceIdItems[i].getResourceId());
        }
        request = toResourceTypeAndIds(request, resourceIdList);

        //add resource tag's to the request
        ResourceTagSetItemType[] resourceTagItems = resourceTags.getItem();
        if (resourceTagItems != null) {
            for (int i = 0; i < resourceTagItems.length; i++)
                resourceTagList.put(resourceTagItems[i].getKey(), resourceTagItems[i].getValue());
        }
        request = toResourceTag(request, resourceTagList);

        return toCreateTagsResponse(engine.modifyTags(request, "create"));
    }

    public DeleteTagsResponse deleteTags(DeleteTags deleteTags) {
        EC2Tags request = new EC2Tags();
        ArrayList<String> resourceIdList = new ArrayList<String>();
        Map<String, String> resourceTagList = new HashMap<String, String>();

        DeleteTagsType dtt = deleteTags.getDeleteTags();

        ResourceIdSetType resourceIds = dtt.getResourcesSet();
        DeleteTagsSetType resourceTags = dtt.getTagSet();

        ResourceIdSetItemType[] resourceIdItems = resourceIds.getItem();

        if (resourceIdItems != null) {
            for (int i = 0; i < resourceIdItems.length; i++)
                resourceIdList.add(resourceIdItems[i].getResourceId());
        }
        request = toResourceTypeAndIds(request, resourceIdList);

        //add resource tag's to the request
        DeleteTagsSetItemType[] resourceTagItems = resourceTags.getItem();
        if (resourceTagItems != null) {
            for (int i = 0; i < resourceTagItems.length; i++)
                resourceTagList.put(resourceTagItems[i].getKey(), resourceTagItems[i].getValue());
        }
        request = toResourceTag(request, resourceTagList);

        return toDeleteTagsResponse(engine.modifyTags(request, "delete"));
    }

    public static EC2Tags toResourceTypeAndIds(EC2Tags request, ArrayList<String> resourceIdList) {
        List<String> resourceTypeList = new ArrayList<String>();
        for (String resourceId : resourceIdList) {
            if (!resourceId.contains(":") || resourceId.split(":").length != 2) {
                throw new EC2ServiceException(ClientError.InvalidParameterValue, "Invalid usage. ResourceId format is resource-type:resource-uuid");
            }
            String resourceType = resourceId.split(":")[0];
            if (resourceTypeList.isEmpty())
                resourceTypeList.add(resourceType);
            else {
                Boolean existsInList = false;
                for (String addedResourceType : resourceTypeList) {
                    if (addedResourceType.equalsIgnoreCase(resourceType)) {
                        existsInList = true;
                        break;
                    }
                }
                if (!existsInList)
                    resourceTypeList.add(resourceType);
            }
        }
        for (String resourceType : resourceTypeList) {
            EC2TagTypeId param1 = new EC2TagTypeId();
            param1.setResourceType(resourceType);
            for (String resourceId : resourceIdList) {
                String[] resourceTag = resourceId.split(":");
                if (resourceType.equals(resourceTag[0]))
                    param1.addResourceId(resourceTag[1]);
            }
            request.addResourceType(param1);
        }
        return request;
    }

    public static EC2Tags toResourceTag(EC2Tags request, Map<String, String> resourceTagList) {
        Set<String> resourceTagKeySet = resourceTagList.keySet();
        for (String resourceTagKey : resourceTagKeySet) {
            EC2TagKeyValue param1 = new EC2TagKeyValue();
            param1.setKey(resourceTagKey);
            param1.setValue(resourceTagList.get(resourceTagKey));
            request.addResourceTag(param1);
        }
        return request;
    }

    public DeleteSecurityGroupResponse deleteSecurityGroup(DeleteSecurityGroup deleteSecurityGroup) {
        DeleteSecurityGroupType sgt = deleteSecurityGroup.getDeleteSecurityGroup();
        return toDeleteSecurityGroupResponse(engine.deleteSecurityGroup(sgt.getGroupName()));
    }

    public DeleteSnapshotResponse deleteSnapshot(DeleteSnapshot deleteSnapshot) {
        DeleteSnapshotType dst = deleteSnapshot.getDeleteSnapshot();
        return toDeleteSnapshotResponse(engine.deleteSnapshot(dst.getSnapshotId()));
    }

    public DeleteVolumeResponse deleteVolume(DeleteVolume deleteVolume) {
        EC2Volume request = new EC2Volume();
        DeleteVolumeType avt = deleteVolume.getDeleteVolume();

        request.setId(avt.getVolumeId());
        return toDeleteVolumeResponse(engine.deleteVolume(request));
    }

    public DeregisterImageResponse deregisterImage(DeregisterImage deregisterImage) {
        DeregisterImageType dit = deregisterImage.getDeregisterImage();
        EC2Image image = new EC2Image();

        image.setId(dit.getImageId());
        return toDeregisterImageResponse(engine.deregisterImage(image));
    }

    public DescribeAvailabilityZonesResponse describeAvailabilityZones(DescribeAvailabilityZones describeAvailabilityZones) {
        EC2DescribeAvailabilityZones request = new EC2DescribeAvailabilityZones();

        DescribeAvailabilityZonesType dazt = describeAvailabilityZones.getDescribeAvailabilityZones();
        DescribeAvailabilityZonesSetType dazs = dazt.getAvailabilityZoneSet();
        DescribeAvailabilityZonesSetItemType[] items = dazs.getItem();
        if (null != items) {  // -> can be empty
            for (int i = 0; i < items.length; i++)
                request.addZone(items[i].getZoneName());
        }

        FilterSetType fst = dazt.getFilterSet();
        if (fst != null) {
            request.setFilterSet(toAvailabiltyZonesFilterSet(fst));
        }

        return toDescribeAvailabilityZonesResponse(engine.describeAvailabilityZones(request));
    }

    /**
     * This only supports a query about description.
     */
    public DescribeImageAttributeResponse describeImageAttribute(DescribeImageAttribute describeImageAttribute) {
        EC2DescribeImageAttribute request = new EC2DescribeImageAttribute();
        DescribeImageAttributeType diat = describeImageAttribute.getDescribeImageAttribute();
        DescribeImageAttributesGroup diag = diat.getDescribeImageAttributesGroup();
        EmptyElementType description = diag.getDescription();
        EmptyElementType launchPermission = diag.getLaunchPermission();

        if (null != description) {
            request.setImageId(diat.getImageId());
            request.setAttribute(ImageAttribute.description);
            return toDescribeImageAttributeResponse(engine.describeImageAttribute(request));
        } else if (launchPermission != null) {
            request.setImageId(diat.getImageId());
            request.setAttribute(ImageAttribute.launchPermission);
            return toDescribeImageAttributeResponse(engine.describeImageAttribute(request));
        } else
            throw new EC2ServiceException(ClientError.Unsupported, "Unsupported - only description or launchPermission supported");
    }

    public DescribeImagesResponse describeImages(DescribeImages describeImages) {
        EC2DescribeImages request = new EC2DescribeImages();
        DescribeImagesType dit = describeImages.getDescribeImages();

        // -> toEC2DescribeImages
        DescribeImagesExecutableBySetType param1 = dit.getExecutableBySet();
        if (null != param1) {
            DescribeImagesExecutableByType[] items1 = param1.getItem();
            if (null != items1) {
                for (int i = 0; i < items1.length; i++)
                    request.addExecutableBySet(items1[i].getUser());
            }
        }
        DescribeImagesInfoType param2 = dit.getImagesSet();
        if (null != param2) {
            DescribeImagesItemType[] items2 = param2.getItem();
            if (null != items2) {
                for (int i = 0; i < items2.length; i++)
                    request.addImageSet(items2[i].getImageId());
            }
        }
        DescribeImagesOwnersType param3 = dit.getOwnersSet();
        if (null != param3) {
            DescribeImagesOwnerType[] items3 = param3.getItem();
            if (null != items3) {
                for (int i = 0; i < items3.length; i++)
                    request.addOwnersSet(items3[i].getOwner());
            }
        }
        FilterSetType fst = dit.getFilterSet();
        if (fst != null) {
            request.setFilterSet(toImageFilterSet(fst));
        }
        return toDescribeImagesResponse(engine.describeImages(request));
    }

    public DescribeInstanceAttributeResponse describeInstanceAttribute(DescribeInstanceAttribute describeInstanceAttribute) {
        EC2DescribeInstances request = new EC2DescribeInstances();
        DescribeInstanceAttributeType diat = describeInstanceAttribute.getDescribeInstanceAttribute();
        DescribeInstanceAttributesGroup diag = diat.getDescribeInstanceAttributesGroup();
        EmptyElementType instanceType = diag.getInstanceType();

        // -> toEC2DescribeInstances
        if (null != instanceType) {
            request.addInstanceId(diat.getInstanceId());
            return toDescribeInstanceAttributeResponse(engine.describeInstances(request));
        }
        throw new EC2ServiceException(ClientError.Unsupported, "Unsupported - only instanceType supported");
    }

    public DescribeInstancesResponse describeInstances(DescribeInstances describeInstances) {
        EC2DescribeInstances request = new EC2DescribeInstances();
        DescribeInstancesType dit = describeInstances.getDescribeInstances();
        FilterSetType fst = dit.getFilterSet();

        // -> toEC2DescribeInstances
        DescribeInstancesInfoType diit = dit.getInstancesSet();
        DescribeInstancesItemType[] items = diit.getItem();
        if (null != items) {  // -> can be empty
            for (int i = 0; i < items.length; i++)
                request.addInstanceId(items[i].getInstanceId());
        }

        if (null != fst)
            request = toInstanceFilterSet(request, fst);

        return toDescribeInstancesResponse(engine.describeInstances(request), engine);
    }

    @Override
    public DescribeAddressesResponse describeAddresses(DescribeAddresses describeAddresses) {
        EC2DescribeAddresses ec2Request = new EC2DescribeAddresses();
        DescribeAddressesType dat = describeAddresses.getDescribeAddresses();

        DescribeAddressesInfoType dait = dat.getPublicIpsSet();
        DescribeAddressesItemType[] items = dait.getItem();
        if (items != null) {  // -> can be empty
            for (DescribeAddressesItemType itemType : items)
                ec2Request.addPublicIp(itemType.getPublicIp());
        }

        FilterSetType fset = dat.getFilterSet();
        if (fset != null) {
            ec2Request.setFilterSet(toAddressFilterSet(fset));
        }

        return toDescribeAddressesResponse(engine.describeAddresses(ec2Request));
    }

    @Override
    public AllocateAddressResponse allocateAddress(AllocateAddress allocateAddress) {
        return toAllocateAddressResponse(engine.allocateAddress());
    }

    @Override
    public ReleaseAddressResponse releaseAddress(ReleaseAddress releaseAddress) {
        EC2ReleaseAddress request = new EC2ReleaseAddress();

        request.setPublicIp(releaseAddress.getReleaseAddress().getReleaseAddressTypeChoice_type0().getPublicIp());

        return toReleaseAddressResponse(engine.releaseAddress(request));
    }

    @Override
    public AssociateAddressResponse associateAddress(AssociateAddress associateAddress) {
        EC2AssociateAddress request = new EC2AssociateAddress();

        request.setPublicIp(associateAddress.getAssociateAddress().getAssociateAddressTypeChoice_type0().getPublicIp());
        request.setInstanceId(associateAddress.getAssociateAddress().getAssociateAddressTypeChoice_type1().getInstanceId());

        return toAssociateAddressResponse(engine.associateAddress(request));
    }

    @Override
    public DisassociateAddressResponse disassociateAddress(DisassociateAddress disassociateAddress) {
        EC2DisassociateAddress request = new EC2DisassociateAddress();

        request.setPublicIp(disassociateAddress.getDisassociateAddress().getPublicIp());

        return toDisassociateAddressResponse(engine.disassociateAddress(request));
    }

    public DescribeSecurityGroupsResponse describeSecurityGroups(DescribeSecurityGroups describeSecurityGroups) {
        EC2DescribeSecurityGroups request = new EC2DescribeSecurityGroups();

        DescribeSecurityGroupsType sgt = describeSecurityGroups.getDescribeSecurityGroups();

        FilterSetType fst = sgt.getFilterSet();

        // -> toEC2DescribeSecurityGroups
        DescribeSecurityGroupsSetType sgst = sgt.getSecurityGroupSet();
        DescribeSecurityGroupsSetItemType[] items = sgst.getItem();
        if (null != items) {  // -> can be empty
            for (DescribeSecurityGroupsSetItemType item : items)
                request.addGroupName(item.getGroupName());
        }

        if (null != fst) {
            request.setFilterSet(toGroupFilterSet(fst));
        }

        return toDescribeSecurityGroupsResponse(engine.describeSecurityGroups(request));
    }

    public DescribeSnapshotsResponse describeSnapshots(DescribeSnapshots describeSnapshots) {
        EC2DescribeSnapshots request = new EC2DescribeSnapshots();
        DescribeSnapshotsType dst = describeSnapshots.getDescribeSnapshots();

        DescribeSnapshotsSetType dsst = dst.getSnapshotSet();
        FilterSetType fst = dst.getFilterSet();

        if (null != dsst) {
            DescribeSnapshotsSetItemType[] items = dsst.getItem();
            if (null != items) {
                for (int i = 0; i < items.length; i++)
                    request.addSnapshotId(items[i].getSnapshotId());
            }
        }

        if (null != fst) {
            String[] timeFilters = new String[1];
            timeFilters[0] = new String("start-time");
            request = toSnapshotFilterSet(request, fst, timeFilters);
        }

        return toDescribeSnapshotsResponse(engine.describeSnapshots(request));
    }

    public DescribeTagsResponse describeTags(DescribeTags decsribeTags) {
        EC2DescribeTags request = new EC2DescribeTags();
        DescribeTagsType dtt = decsribeTags.getDescribeTags();

        FilterSetType fst = dtt.getFilterSet();

        if (fst != null)
            request.setFilterSet(toTagsFilterSet(fst));

        return toDescribeTagsResponse(engine.describeTags(request));
    }

    public DescribeVolumesResponse describeVolumes(DescribeVolumes describeVolumes) {
        EC2DescribeVolumes request = new EC2DescribeVolumes();
        DescribeVolumesType dvt = describeVolumes.getDescribeVolumes();

        DescribeVolumesSetType dvst = dvt.getVolumeSet();
        FilterSetType fst = dvt.getFilterSet();

        if (null != dvst) {
            DescribeVolumesSetItemType[] items = dvst.getItem();
            if (null != items) {
                for (int i = 0; i < items.length; i++)
                    request.addVolumeId(items[i].getVolumeId());
            }
        }

        if (null != fst) {
            String[] timeFilters = new String[2];
            timeFilters[0] = new String("attachment.attach-time");
            timeFilters[1] = new String("create-time");
            request = toVolumeFilterSet(request, fst, timeFilters);
        }

        return toDescribeVolumesResponse(engine.describeVolumes(request), engine);
    }

    public DetachVolumeResponse detachVolume(DetachVolume detachVolume) {
        EC2Volume request = new EC2Volume();
        DetachVolumeType avt = detachVolume.getDetachVolume();

        request.setId(avt.getVolumeId());
        request.setInstanceId(avt.getInstanceId());
        request.setDevice(avt.getDevice());
        return toDetachVolumeResponse(engine.detachVolume(request));
    }

    public ModifyImageAttributeResponse modifyImageAttribute(ModifyImageAttribute modifyImageAttribute) {
        EC2ModifyImageAttribute request = new EC2ModifyImageAttribute();

        ModifyImageAttributeType miat = modifyImageAttribute.getModifyImageAttribute();
        ModifyImageAttributeTypeChoice_type0 item = miat.getModifyImageAttributeTypeChoice_type0();

        AttributeValueType description = item.getDescription();

        LaunchPermissionOperationType launchPermOp = item.getLaunchPermission();

        if (null != description) {
            request.setImageId(miat.getImageId());
            request.setAttribute(ImageAttribute.description);
            request.setDescription(description.getValue());
            return toModifyImageAttributeResponse(engine.modifyImageAttribute(request));
        } else if (launchPermOp != null) {
            request.setImageId(miat.getImageId());
            request.setAttribute(ImageAttribute.launchPermission);
            if (launchPermOp.getAdd() != null) {
                setAccountOrGroupList(launchPermOp.getAdd().getItem(), request, "add");
            } else if (launchPermOp.getRemove() != null) {
                setAccountOrGroupList(launchPermOp.getRemove().getItem(), request, "remove");
            }
            return toModifyImageAttributeResponse(engine.modifyImageAttribute(request));
        }
        throw new EC2ServiceException(ClientError.Unsupported, "Unsupported - can only modify image description or launchPermission");
    }

    public ModifyInstanceAttributeResponse modifyInstanceAttribute(ModifyInstanceAttribute modifyInstanceAttribute) {
        EC2ModifyInstanceAttribute request = new EC2ModifyInstanceAttribute();

        ModifyInstanceAttributeType modifyInstanceAttribute2 = modifyInstanceAttribute.getModifyInstanceAttribute();
        ModifyInstanceAttributeTypeChoice_type0 mia = modifyInstanceAttribute2.getModifyInstanceAttributeTypeChoice_type0();

        request.setInstanceId(modifyInstanceAttribute2.getInstanceId());

        // we only support instanceType and userData
        if (mia.getInstanceType() != null) {
            request.setInstanceType(mia.getInstanceType().getValue());
        } else if (mia.getUserData() != null) {
            request.setUserData(mia.getUserData().getValue());
        } else {
            throw new EC2ServiceException(ClientError.MissingParamter, "Missing required parameter - InstanceType/UserData should be provided");
        }
        return toModifyInstanceAttributeResponse(engine.modifyInstanceAttribute(request));
    }

    private void setAccountOrGroupList(LaunchPermissionItemType[] items, EC2ModifyImageAttribute request, String operation) {
        EC2ImageLaunchPermission launchPermission = new EC2ImageLaunchPermission();

        if (operation.equalsIgnoreCase("add"))
            launchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.add);
        else
            launchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.remove);

        for (LaunchPermissionItemType lpItem : items) {
            if (lpItem.getGroup() != null) {
                launchPermission.addLaunchPermission(lpItem.getGroup());
            } else if (lpItem.getUserId() != null) {
                launchPermission.addLaunchPermission(lpItem.getUserId());
            }
        }

        request.addLaunchPermission(launchPermission);
    }

    /**
     * Did not find a matching service offering so for now we just return disabled
     * for each instance request.  We could verify that all of the specified instances
     * exist to detect an error which would require a listVirtualMachines.
     */
    public MonitorInstancesResponse monitorInstances(MonitorInstances monitorInstances) {
        MonitorInstancesResponse response = new MonitorInstancesResponse();
        MonitorInstancesResponseType param1 = new MonitorInstancesResponseType();
        MonitorInstancesResponseSetType param2 = new MonitorInstancesResponseSetType();

        MonitorInstancesType mit = monitorInstances.getMonitorInstances();
        MonitorInstancesSetType mist = mit.getInstancesSet();
        MonitorInstancesSetItemType[] misit = mist.getItem();

        if (null != misit) {
            for (int i = 0; i < misit.length; i++) {
                String instanceId = misit[i].getInstanceId();
                MonitorInstancesResponseSetItemType param3 = new MonitorInstancesResponseSetItemType();
                param3.setInstanceId(instanceId);
                InstanceMonitoringStateType param4 = new InstanceMonitoringStateType();
                param4.setState("disabled");
                param3.setMonitoring(param4);
                param2.addItem(param3);
            }
        }

        param1.setRequestId(UUID.randomUUID().toString());
        param1.setInstancesSet(param2);
        response.setMonitorInstancesResponse(param1);
        return response;
    }

    public RebootInstancesResponse rebootInstances(RebootInstances rebootInstances) {
        EC2RebootInstances request = new EC2RebootInstances();
        RebootInstancesType rit = rebootInstances.getRebootInstances();

        // -> toEC2StartInstances
        RebootInstancesInfoType rist = rit.getInstancesSet();
        RebootInstancesItemType[] items = rist.getItem();
        if (null != items) {  // -> should not be empty
            for (int i = 0; i < items.length; i++)
                request.addInstanceId(items[i].getInstanceId());
        }
        return toRebootInstancesResponse(engine.rebootInstances(request));
    }

    /**
     * Processes ec2-register
     * 
     * @param
     * 
     * @see <a href="http://docs.amazonwebservices.com/AWSEC2/2010-11-15/APIReference/index.html?ApiReference-query-RegisterImage.html">RegisterImage</a>
     */
    public RegisterImageResponse registerImage(RegisterImage registerImage) {
        EC2RegisterImage request = new EC2RegisterImage();
        RegisterImageType rit = registerImage.getRegisterImage();

        // -> we redefine the architecture field to hold: "format:zonename:osTypeName",
        //    these are the bare minimum that we need to call the cloud registerTemplate call.
        request.setLocation(rit.getImageLocation());   // -> should be a URL for us
        request.setName(rit.getName());
        request.setDescription(rit.getDescription());
        request.setArchitecture(rit.getArchitecture());
        return toRegisterImageResponse(engine.registerImage(request));
    }

    /**
     * Processes ec2-reset-image-attribute
     * 
     * @param resetImageAttribute
     * 
     * @see <a href="http://docs.amazonwebservices.com/AWSEC2/2010-11-15/APIReference/index.html?ApiReference-query-ResetInstanceAttribute.html">ResetInstanceAttribute</a>
     */

    public ResetImageAttributeResponse resetImageAttribute(ResetImageAttribute resetImageAttribute) {
        EC2ModifyImageAttribute request = new EC2ModifyImageAttribute();
        ResetImageAttributeType riat = resetImageAttribute.getResetImageAttribute();
        EmptyElementType elementType = riat.getResetImageAttributesGroup().getLaunchPermission();
        if (elementType != null) {
            request.setImageId(riat.getImageId());
            request.setAttribute(ImageAttribute.launchPermission);
            EC2ImageLaunchPermission launchPermission = new EC2ImageLaunchPermission();
            launchPermission.setLaunchPermOp(EC2ImageLaunchPermission.Operation.reset);
            request.addLaunchPermission(launchPermission);
            return toResetImageAttributeResponse(engine.modifyImageAttribute(request));
        }
        throw new EC2ServiceException(ClientError.Unsupported, "Unsupported - can only reset image launchPermission");
    }

    /**
     *  ec2-run-instances
     *    
     * @param runInstances
     * 
     * @see <a href="http://docs.amazonwebservices.com/AWSEC2/2010-11-15/APIReference/index.html?ApiReference-query-RunInstances.html">RunInstances</a>
     */
    public RunInstancesResponse runInstances(RunInstances runInstances) {
        RunInstancesType rit = runInstances.getRunInstances();
        GroupSetType gst = rit.getGroupSet();
        PlacementRequestType prt = rit.getPlacement();
        UserDataType userData = rit.getUserData();
        String type = rit.getInstanceType();
        String keyName = rit.getKeyName();

        EC2RunInstances request = new EC2RunInstances();

        request.setTemplateId(rit.getImageId());

        if (rit.getMinCount() < 1) {
            throw new EC2ServiceException(ClientError.InvalidParameterValue, "Value of parameter MinCount should be greater than 0");
        } else
            request.setMinCount(rit.getMinCount());

        if (rit.getMaxCount() < 1) {
            throw new EC2ServiceException(ClientError.InvalidParameterValue, "Value of parameter MaxCount should be greater than 0");
        } else
            request.setMaxCount(rit.getMaxCount());

        if (null != type)
            request.setInstanceType(type);
        if (null != prt)
            request.setZoneName(prt.getAvailabilityZone());
        if (null != userData)
            request.setUserData(userData.getData());
        if (null != keyName)
            request.setKeyName(rit.getKeyName());

        // -> we can only support one group per instance
        if (null != gst) {
            GroupItemType[] items = gst.getItem();
            if (null != items) {
                for (int i = 0; i < items.length; i++) {
                    if (items[i].getGroupName() != null) // either SG-name or SG-id can be provided
                        request.addSecuritGroupName(items[i].getGroupName());
                    else
                        request.addSecuritGroupId(items[i].getGroupId());
                }
            }
        }
        return toRunInstancesResponse(engine.runInstances(request), engine);
    }

    public StartInstancesResponse startInstances(StartInstances startInstances) {
        EC2StartInstances request = new EC2StartInstances();
        StartInstancesType sit = startInstances.getStartInstances();

        // -> toEC2StartInstances
        InstanceIdSetType iist = sit.getInstancesSet();
        InstanceIdType[] items = iist.getItem();
        if (null != items) {  // -> should not be empty
            for (int i = 0; i < items.length; i++)
                request.addInstanceId(items[i].getInstanceId());
        }
        return toStartInstancesResponse(engine.startInstances(request));
    }

    public StopInstancesResponse stopInstances(StopInstances stopInstances) {
        EC2StopInstances request = new EC2StopInstances();
        StopInstancesType sit = stopInstances.getStopInstances();
        Boolean force = sit.getForce();

        // -> toEC2StopInstances
        InstanceIdSetType iist = sit.getInstancesSet();
        InstanceIdType[] items = iist.getItem();
        if (null != items) {  // -> should not be empty
            for (int i = 0; i < items.length; i++)
                request.addInstanceId(items[i].getInstanceId());
        }

        if (force)
            request.setForce(sit.getForce());
        return toStopInstancesResponse(engine.stopInstances(request));
    }

    /**
     * Mapping this to the destroyVirtualMachine cloud API concept.
     * This makes sense since when considering the rebootInstances function.   In reboot
     * any terminated instances are left alone.   We will do the same with destroyed instances.
     */
    public TerminateInstancesResponse terminateInstances(TerminateInstances terminateInstances) {
        EC2StopInstances request = new EC2StopInstances();
        TerminateInstancesType sit = terminateInstances.getTerminateInstances();

        // -> toEC2StopInstances
        InstanceIdSetType iist = sit.getInstancesSet();
        InstanceIdType[] items = iist.getItem();
        if (null != items) {  // -> should not be empty
            for (int i = 0; i < items.length; i++)
                request.addInstanceId(items[i].getInstanceId());
        }

        request.setDestroyInstances(true);
        return toTermInstancesResponse(engine.stopInstances(request));
    }

    /**
     * See comment for monitorInstances.
     */
    public UnmonitorInstancesResponse unmonitorInstances(UnmonitorInstances unmonitorInstances) {
        UnmonitorInstancesResponse response = new UnmonitorInstancesResponse();
        MonitorInstancesResponseType param1 = new MonitorInstancesResponseType();
        MonitorInstancesResponseSetType param2 = new MonitorInstancesResponseSetType();

        MonitorInstancesType mit = unmonitorInstances.getUnmonitorInstances();
        MonitorInstancesSetType mist = mit.getInstancesSet();
        MonitorInstancesSetItemType[] items = mist.getItem();

        if (null != items) {
            for (int i = 0; i < items.length; i++) {
                String instanceId = items[i].getInstanceId();
                MonitorInstancesResponseSetItemType param3 = new MonitorInstancesResponseSetItemType();
                param3.setInstanceId(instanceId);
                InstanceMonitoringStateType param4 = new InstanceMonitoringStateType();
                param4.setState("disabled");
                param3.setMonitoring(param4);
                param2.addItem(param3);
            }
        }

        param1.setInstancesSet(param2);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setUnmonitorInstancesResponse(param1);
        return response;
    }

    /**
     * @param modifyInstanceAttribute
     * @return    
     */
    public static ModifyInstanceAttributeResponse toModifyInstanceAttributeResponse(Boolean status) {
        ModifyInstanceAttributeResponse miat = new ModifyInstanceAttributeResponse();

        ModifyInstanceAttributeResponseType param = new ModifyInstanceAttributeResponseType();
        param.set_return(status);
        param.setRequestId(UUID.randomUUID().toString());
        miat.setModifyInstanceAttributeResponse(param);
        return miat;
    }

    public static DescribeImageAttributeResponse toDescribeImageAttributeResponse(EC2ImageAttributes engineResponse) {
        DescribeImageAttributeResponse response = new DescribeImageAttributeResponse();
        DescribeImageAttributeResponseType param1 = new DescribeImageAttributeResponseType();

        if (engineResponse != null) {
            DescribeImageAttributeResponseTypeChoice_type0 param2 = new DescribeImageAttributeResponseTypeChoice_type0();

            if (engineResponse.getIsPublic()) {
                LaunchPermissionListType param3 = new LaunchPermissionListType();
                LaunchPermissionItemType param4 = new LaunchPermissionItemType();
                param4.setGroup("all");
                param3.addItem(param4);
                param2.setLaunchPermission(param3);
            } else if (engineResponse.getAccountNamesWithLaunchPermission() != null) {
                LaunchPermissionListType param3 = new LaunchPermissionListType();
                for (String accountName : engineResponse.getAccountNamesWithLaunchPermission()) {
                    LaunchPermissionItemType param4 = new LaunchPermissionItemType();
                    param4.setUserId(accountName);
                    param3.addItem(param4);
                }
                param2.setLaunchPermission(param3);

            } else if (engineResponse.getDescription() != null) {
                NullableAttributeValueType param3 = new NullableAttributeValueType();
                param3.setValue(engineResponse.getDescription());
                param2.setDescription(param3);
            }

            param1.setDescribeImageAttributeResponseTypeChoice_type0(param2);
            param1.setImageId(engineResponse.getImageId());
        }

        param1.setRequestId(UUID.randomUUID().toString());
        response.setDescribeImageAttributeResponse(param1);
        return response;
    }

    public static ModifyImageAttributeResponse toModifyImageAttributeResponse(boolean engineResponse) {
        ModifyImageAttributeResponse response = new ModifyImageAttributeResponse();
        ModifyImageAttributeResponseType param1 = new ModifyImageAttributeResponseType();

        param1.set_return(engineResponse);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setModifyImageAttributeResponse(param1);
        return response;
    }

    public static ResetImageAttributeResponse toResetImageAttributeResponse(boolean engineResponse) {
        ResetImageAttributeResponse response = new ResetImageAttributeResponse();
        ResetImageAttributeResponseType param1 = new ResetImageAttributeResponseType();

        param1.set_return(engineResponse);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setResetImageAttributeResponse(param1);
        return response;
    }

    public static DescribeImagesResponse toDescribeImagesResponse(EC2DescribeImagesResponse engineResponse) {
        DescribeImagesResponse response = new DescribeImagesResponse();
        DescribeImagesResponseType param1 = new DescribeImagesResponseType();
        DescribeImagesResponseInfoType param2 = new DescribeImagesResponseInfoType();

        EC2Image[] images = engineResponse.getImageSet();
        for (int i = 0; i < images.length; i++) {
            String accountName = images[i].getAccountName();
            String domainId = images[i].getDomainId();
            String ownerId = domainId + ":" + accountName;

            DescribeImagesResponseItemType param3 = new DescribeImagesResponseItemType();
            param3.setImageId(images[i].getId());
            param3.setImageLocation("");
            param3.setImageState(images[i].getState());
            param3.setImageOwnerId(ownerId);
            param3.setIsPublic(images[i].getIsPublic());

            ProductCodesSetType param4 = new ProductCodesSetType();
            ProductCodesSetItemType param5 = new ProductCodesSetItemType();
            param5.setProductCode("");
            param5.setType("");
            param4.addItem(param5);
            param3.setProductCodes(param4);

            String description = images[i].getDescription();
            param3.setDescription((null == description ? "" : description));

            param3.setArchitecture(images[i].getArchitecture());

            param3.setImageType(images[i].getImageType());
            param3.setKernelId("");
            param3.setRamdiskId("");
            param3.setPlatform("");
            param3.setHypervisor(images[i].getHypervisor());

            StateReasonType param6 = new StateReasonType();
            param6.setCode("");
            param6.setMessage("");
            param3.setStateReason(param6);

            param3.setImageOwnerAlias("");
            param3.setName(images[i].getName());
            param3.setRootDeviceType("");
            param3.setRootDeviceName("");

            BlockDeviceMappingType param7 = new BlockDeviceMappingType();
            BlockDeviceMappingItemType param8 = new BlockDeviceMappingItemType();
            BlockDeviceMappingItemTypeChoice_type0 param9 = new BlockDeviceMappingItemTypeChoice_type0();
            param8.setDeviceName("");
            param9.setVirtualName("");
            EbsBlockDeviceType param10 = new EbsBlockDeviceType();
            param10.setSnapshotId("");
            param10.setVolumeSize(0);
            param10.setDeleteOnTermination(false);
            param9.setEbs(param10);
            param8.setBlockDeviceMappingItemTypeChoice_type0(param9);
            param7.addItem(param8);

            param3.setBlockDeviceMapping(param7);

            EC2TagKeyValue[] tags = images[i].getResourceTags();
            param3.setTagSet(setResourceTags(tags));

            param2.addItem(param3);
        }

        param1.setImagesSet(param2);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setDescribeImagesResponse(param1);
        return response;
    }

    public static CreateImageResponse toCreateImageResponse(EC2CreateImageResponse engineResponse) {
        CreateImageResponse response = new CreateImageResponse();
        CreateImageResponseType param1 = new CreateImageResponseType();

        param1.setImageId(engineResponse.getId());
        param1.setRequestId(UUID.randomUUID().toString());
        response.setCreateImageResponse(param1);
        return response;
    }

    public static RegisterImageResponse toRegisterImageResponse(EC2CreateImageResponse engineResponse) {
        RegisterImageResponse response = new RegisterImageResponse();
        RegisterImageResponseType param1 = new RegisterImageResponseType();

        param1.setImageId(engineResponse.getId());
        param1.setRequestId(UUID.randomUUID().toString());
        response.setRegisterImageResponse(param1);
        return response;
    }

    public static DeregisterImageResponse toDeregisterImageResponse(boolean engineResponse) {
        DeregisterImageResponse response = new DeregisterImageResponse();
        DeregisterImageResponseType param1 = new DeregisterImageResponseType();

        param1.set_return(engineResponse);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setDeregisterImageResponse(param1);
        return response;
    }

    // filtersets
    private EC2AddressFilterSet toAddressFilterSet(FilterSetType fst) {
        EC2AddressFilterSet vfs = new EC2AddressFilterSet();

        FilterType[] items = fst.getItem();
        if (items != null) {
            // -> each filter can have one or more values associated with it
            for (FilterType item : items) {
                EC2Filter oneFilter = new EC2Filter();
                String filterName = item.getName();
                oneFilter.setName(filterName);

                ValueSetType vst = item.getValueSet();
                ValueType[] valueItems = vst.getItem();
                for (ValueType valueItem : valueItems) {
                    oneFilter.addValueEncoded(valueItem.getValue());
                }
                vfs.addFilter(oneFilter);
            }
        }
        return vfs;
    }

    private EC2KeyPairFilterSet toKeyPairFilterSet(FilterSetType fst) {
        EC2KeyPairFilterSet vfs = new EC2KeyPairFilterSet();

        FilterType[] items = fst.getItem();
        if (items != null) {
            // -> each filter can have one or more values associated with it
            for (FilterType item : items) {
                EC2Filter oneFilter = new EC2Filter();
                String filterName = item.getName();
                oneFilter.setName(filterName);

                ValueSetType vst = item.getValueSet();
                ValueType[] valueItems = vst.getItem();
                for (ValueType valueItem : valueItems) {
                    oneFilter.addValueEncoded(valueItem.getValue());
                }
                vfs.addFilter(oneFilter);
            }
        }
        return vfs;
    }

    private EC2DescribeVolumes toVolumeFilterSet(EC2DescribeVolumes request, FilterSetType fst, String[] timeStrs) {
        EC2VolumeFilterSet vfs = new EC2VolumeFilterSet();
        boolean timeFilter = false;

        FilterType[] items = fst.getItem();
        if (null != items) {
            // -> each filter can have one or more values associated with it
            for (int j = 0; j < items.length; j++) {
                String filterName = items[j].getName();
                ValueSetType vst = items[j].getValueSet();
                ValueType[] valueItems = vst.getItem();

                if (filterName.startsWith("tag:")) {
                    String key = filterName.split(":")[1];
                    for (ValueType valueItem : valueItems) {
                        EC2TagKeyValue tag = new EC2TagKeyValue();
                        tag.setKey(key);
                        tag.setValue(valueItem.getValue());
                        request.addResourceTag(tag);
                    }
                } else {
                    EC2Filter oneFilter = new EC2Filter();
                    oneFilter.setName(filterName);

                    // -> is the filter one of the xsd:dateTime filters?
                    timeFilter = false;
                    for (int m = 0; m < timeStrs.length; m++) {
                        timeFilter = filterName.equalsIgnoreCase(timeStrs[m]);
                        if (timeFilter)
                            break;
                    }

                    for (int k = 0; k < valueItems.length; k++) {
                        // -> time values are not encoded as regexes
                        if (timeFilter)
                            oneFilter.addValue(valueItems[k].getValue());
                        else
                            oneFilter.addValueEncoded(valueItems[k].getValue());
                    }
                    vfs.addFilter(oneFilter);
                }
            }
            request.setFilterSet(vfs);
        }
        return request;
    }

    private EC2DescribeSnapshots toSnapshotFilterSet(EC2DescribeSnapshots request, FilterSetType fst, String[] timeStrs) {
        EC2SnapshotFilterSet sfs = new EC2SnapshotFilterSet();
        boolean timeFilter = false;

        FilterType[] items = fst.getItem();
        if (null != items) {
            // -> each filter can have one or more values associated with it
            for (int j = 0; j < items.length; j++) {
                String filterName = items[j].getName();
                ValueSetType vst = items[j].getValueSet();
                ValueType[] valueItems = vst.getItem();

                if (filterName.startsWith("tag:")) {
                    String key = filterName.split(":")[1];
                    for (ValueType valueItem : valueItems) {
                        EC2TagKeyValue tag = new EC2TagKeyValue();
                        tag.setKey(key);
                        tag.setValue(valueItem.getValue());
                        request.addResourceTag(tag);
                    }
                } else {
                    EC2Filter oneFilter = new EC2Filter();
                    oneFilter.setName(filterName);

                    // -> is the filter one of the xsd:dateTime filters?
                    timeFilter = false;
                    for (int m = 0; m < timeStrs.length; m++) {
                        timeFilter = filterName.equalsIgnoreCase(timeStrs[m]);
                        if (timeFilter)
                            break;
                    }

                    for (int k = 0; k < valueItems.length; k++) {
                        // -> time values are not encoded as regexes
                        if (timeFilter)
                            oneFilter.addValue(valueItems[k].getValue());
                        else
                            oneFilter.addValueEncoded(valueItems[k].getValue());
                    }
                    sfs.addFilter(oneFilter);
                }
            }
            request.setFilterSet(sfs);
        }
        return request;
    }

    // TODO make these filter set functions use generics 
    private EC2GroupFilterSet toGroupFilterSet(FilterSetType fst) {
        EC2GroupFilterSet gfs = new EC2GroupFilterSet();

        FilterType[] items = fst.getItem();
        if (null != items) {
            // -> each filter can have one or more values associated with it
            for (int j = 0; j < items.length; j++) {
                EC2Filter oneFilter = new EC2Filter();
                String filterName = items[j].getName();
                oneFilter.setName(filterName);

                ValueSetType vst = items[j].getValueSet();
                ValueType[] valueItems = vst.getItem();
                for (int k = 0; k < valueItems.length; k++) {
                    oneFilter.addValueEncoded(valueItems[k].getValue());
                }
                gfs.addFilter(oneFilter);
            }
        }
        return gfs;
    }

    private EC2DescribeInstances toInstanceFilterSet(EC2DescribeInstances request, FilterSetType fst) {
        EC2InstanceFilterSet ifs = new EC2InstanceFilterSet();

        FilterType[] items = fst.getItem();
        if (null != items) {
            // -> each filter can have one or more values associated with it
            for (int j = 0; j < items.length; j++) {
                String filterName = items[j].getName();
                ValueSetType vst = items[j].getValueSet();
                ValueType[] valueItems = vst.getItem();

                if (filterName.startsWith("tag:")) {
                    String key = filterName.split(":")[1];
                    for (ValueType valueItem : valueItems) {
                        EC2TagKeyValue tag = new EC2TagKeyValue();
                        tag.setKey(key);
                        tag.setValue(valueItem.getValue());
                        request.addResourceTag(tag);
                    }
                } else {
                    EC2Filter oneFilter = new EC2Filter();
                    oneFilter.setName(filterName);
                    for (int k = 0; k < valueItems.length; k++)
                        oneFilter.addValueEncoded(valueItems[k].getValue());
                    ifs.addFilter(oneFilter);
                }
            }
            request.setFilterSet(ifs);
        }
        return request;
    }

    private EC2AvailabilityZonesFilterSet toAvailabiltyZonesFilterSet(FilterSetType fst) {
        EC2AvailabilityZonesFilterSet azfs = new EC2AvailabilityZonesFilterSet();

        FilterType[] items = fst.getItem();
        if (items != null) {
            for (FilterType item : items) {
                EC2Filter oneFilter = new EC2Filter();
                String filterName = item.getName();
                oneFilter.setName(filterName);

                ValueSetType vft = item.getValueSet();
                ValueType[] valueItems = vft.getItem();
                for (ValueType valueItem : valueItems) {
                    oneFilter.addValueEncoded(valueItem.getValue());
                }
                azfs.addFilter(oneFilter);
            }
        }
        return azfs;
    }

    private EC2TagsFilterSet toTagsFilterSet(FilterSetType fst) {
        EC2TagsFilterSet tfs = new EC2TagsFilterSet();

        FilterType[] items = fst.getItem();
        if (items != null) {
            for (FilterType item : items) {
                EC2Filter oneFilter = new EC2Filter();
                String filterName = item.getName();
                oneFilter.setName(filterName);

                ValueSetType vft = item.getValueSet();
                ValueType[] valueItems = vft.getItem();
                for (ValueType valueItem : valueItems) {
                    oneFilter.addValueEncoded(valueItem.getValue());
                }
                tfs.addFilter(oneFilter);
            }
        }
        return tfs;
    }

    private EC2ImageFilterSet toImageFilterSet(FilterSetType fst) {
        EC2ImageFilterSet ifs = new EC2ImageFilterSet();

        FilterType[] items = fst.getItem();
        if (items != null) {
            for (FilterType item : items) {
                EC2Filter oneFilter = new EC2Filter();
                String filterName = item.getName();
                oneFilter.setName(filterName);

                ValueSetType vft = item.getValueSet();
                ValueType[] valueItems = vft.getItem();
                for (ValueType valueItem : valueItems) {
                    oneFilter.addValueEncoded(valueItem.getValue());
                }
                ifs.addFilter(oneFilter);
            }
        }
        return ifs;
    }

    // toMethods
    public static DescribeVolumesResponse toDescribeVolumesResponse(EC2DescribeVolumesResponse engineResponse, EC2Engine engine) {
        DescribeVolumesResponse response = new DescribeVolumesResponse();
        DescribeVolumesResponseType param1 = new DescribeVolumesResponseType();
        DescribeVolumesSetResponseType param2 = new DescribeVolumesSetResponseType();

        EC2Volume[] volumes = engineResponse.getVolumeSet();
        for (EC2Volume vol : volumes) {
            DescribeVolumesSetItemResponseType param3 = new DescribeVolumesSetItemResponseType();
            param3.setVolumeId(vol.getId().toString());

            Long volSize = new Long(vol.getSize());
            param3.setSize(volSize.toString());
            String snapId = vol.getSnapshotId() != null ? vol.getSnapshotId().toString() : "";
            param3.setSnapshotId(snapId);
            param3.setAvailabilityZone(vol.getZoneName());
            param3.setStatus(vol.getState());
            param3.setVolumeType("standard");

            // -> CloudStack seems to have issues with timestamp formats so just in case
            Calendar cal = EC2RestAuth.parseDateString(vol.getCreated());
            if (cal == null) {
                cal = Calendar.getInstance();
                cal.set(1970, 1, 1);
            }
            param3.setCreateTime(cal);

            AttachmentSetResponseType param4 = new AttachmentSetResponseType();
            if (null != vol.getInstanceId()) {
                AttachmentSetItemResponseType param5 = new AttachmentSetItemResponseType();
                param5.setVolumeId(vol.getId().toString());
                param5.setInstanceId(vol.getInstanceId().toString());
                String devicePath = engine.cloudDeviceIdToDevicePath(vol.getHypervisor(), vol.getDeviceId());
                param5.setDevice(devicePath);
                param5.setStatus(vol.getAttachmentState());
                if (vol.getAttached() == null) {
                    param5.setAttachTime(cal);
                } else {
                    Calendar attachTime = EC2RestAuth.parseDateString(vol.getAttached());
                    param5.setAttachTime(attachTime);
                }
                param5.setDeleteOnTermination(false);
                param4.addItem(param5);
            }

            param3.setAttachmentSet(param4);

            EC2TagKeyValue[] tags = vol.getResourceTags();
            param3.setTagSet(setResourceTags(tags));
            param2.addItem(param3);
        }
        param1.setVolumeSet(param2);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setDescribeVolumesResponse(param1);
        return response;
    }

    public static DescribeInstanceAttributeResponse toDescribeInstanceAttributeResponse(EC2DescribeInstancesResponse engineResponse) {
        DescribeInstanceAttributeResponse response = new DescribeInstanceAttributeResponse();
        DescribeInstanceAttributeResponseType param1 = new DescribeInstanceAttributeResponseType();

        EC2Instance[] instanceSet = engineResponse.getInstanceSet();
        if (0 < instanceSet.length) {
            DescribeInstanceAttributeResponseTypeChoice_type0 param2 = new DescribeInstanceAttributeResponseTypeChoice_type0();
            NullableAttributeValueType param3 = new NullableAttributeValueType();
            param3.setValue(instanceSet[0].getServiceOffering());
            param2.setInstanceType(param3);
            param1.setDescribeInstanceAttributeResponseTypeChoice_type0(param2);
            param1.setInstanceId(instanceSet[0].getId());
        }
        param1.setRequestId(UUID.randomUUID().toString());
        response.setDescribeInstanceAttributeResponse(param1);
        return response;
    }

    public static DescribeInstancesResponse toDescribeInstancesResponse(EC2DescribeInstancesResponse engineResponse, EC2Engine engine) {
        DescribeInstancesResponse response = new DescribeInstancesResponse();
        DescribeInstancesResponseType param1 = new DescribeInstancesResponseType();
        ReservationSetType param2 = new ReservationSetType();

        EC2Instance[] instances = engineResponse.getInstanceSet();

        for (EC2Instance inst : instances) {
            String accountName = inst.getAccountName();
            String domainId = inst.getDomainId();
            String ownerId = domainId + ":" + accountName;

            ReservationInfoType param3 = new ReservationInfoType();

            param3.setReservationId(inst.getId());   // -> an id we could track down if needed
            param3.setOwnerId(ownerId);
            param3.setRequesterId("");

            GroupSetType param4 = new GroupSetType();

            EC2SecurityGroup[] groups = inst.getGroupSet();
            if (null == groups || 0 == groups.length) {
                GroupItemType param5 = new GroupItemType();
                param5.setGroupId("");
                param5.setGroupName("");
                param4.addItem(param5);
            } else {
                for (EC2SecurityGroup group : groups) {
                    GroupItemType param5 = new GroupItemType();
                    param5.setGroupId(group.getId());
                    param5.setGroupName("");
                    param4.addItem(param5);
                }
            }
            param3.setGroupSet(param4);

            RunningInstancesSetType param6 = new RunningInstancesSetType();
            RunningInstancesItemType param7 = new RunningInstancesItemType();

            param7.setInstanceId(inst.getId());
            param7.setImageId(inst.getTemplateId());

            InstanceStateType param8 = new InstanceStateType();
            param8.setCode(toAmazonCode(inst.getState()));
            param8.setName(toAmazonStateName(inst.getState()));
            param7.setInstanceState(param8);

            param7.setPrivateDnsName("");
            param7.setDnsName("");
            param7.setReason("");
            param7.setKeyName(inst.getKeyPairName());
            param7.setAmiLaunchIndex(null);
            param7.setInstanceType(inst.getServiceOffering());

            ProductCodesSetType param9 = new ProductCodesSetType();
            ProductCodesSetItemType param10 = new ProductCodesSetItemType();
            param10.setProductCode("");
            param10.setType("");
            param9.addItem(param10);
            param7.setProductCodes(param9);

            Calendar cal = inst.getCreated();
            if (null == cal) {
                cal = Calendar.getInstance();
//                 cal.set( 1970, 1, 1 );
            }
            param7.setLaunchTime(cal);

            PlacementResponseType param11 = new PlacementResponseType();
            param11.setAvailabilityZone(inst.getZoneName());
            param11.setGroupName("");
            param7.setPlacement(param11);
            param7.setKernelId("");
            param7.setRamdiskId("");
            param7.setPlatform("");

            InstanceMonitoringStateType param12 = new InstanceMonitoringStateType();
            param12.setState("");
            param7.setMonitoring(param12);
            param7.setSubnetId("");
            param7.setVpcId("");
//            String ipAddr = inst.getPrivateIpAddress();
//            param7.setPrivateIpAddress((null != ipAddr ? ipAddr : ""));
            param7.setPrivateIpAddress(inst.getPrivateIpAddress());
            param7.setIpAddress(inst.getIpAddress());

            StateReasonType param13 = new StateReasonType();
            param13.setCode("");
            param13.setMessage("");
            param7.setStateReason(param13);
            param7.setArchitecture("");
            param7.setRootDeviceType("");
            String devicePath = engine.cloudDeviceIdToDevicePath(inst.getHypervisor(), inst.getRootDeviceId());
            param7.setRootDeviceName(devicePath);

            GroupSetType param14 = new GroupSetType();
            GroupItemType param15 = new GroupItemType(); // VPC security group
            param15.setGroupName("");
            param15.setGroupName("");
            param14.addItem(param15);
            param7.setGroupSet(param14);

            param7.setInstanceLifecycle("");
            param7.setSpotInstanceRequestId("");
            param7.setHypervisor(inst.getHypervisor());

            EC2TagKeyValue[] tags = inst.getResourceTags();
            param7.setTagSet(setResourceTags(tags));

            param6.addItem(param7);
            param3.setInstancesSet(param6);
            param2.addItem(param3);
        }
        param1.setReservationSet(param2);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setDescribeInstancesResponse(param1);
        return response;
    }

    public static DescribeAddressesResponse toDescribeAddressesResponse(EC2DescribeAddressesResponse engineResponse) {
        List<DescribeAddressesResponseItemType> items = new ArrayList<DescribeAddressesResponseItemType>();
        EC2Address[] addressSet = engineResponse.getAddressSet();

        for (EC2Address addr : addressSet) {
            DescribeAddressesResponseItemType item = new DescribeAddressesResponseItemType();
            item.setPublicIp(addr.getIpAddress());
            item.setInstanceId(addr.getAssociatedInstanceId());
            items.add(item);
        }
        DescribeAddressesResponseInfoType descAddrRespInfoType = new DescribeAddressesResponseInfoType();
        descAddrRespInfoType.setItem(items.toArray(new DescribeAddressesResponseItemType[0]));

        DescribeAddressesResponseType descAddrRespType = new DescribeAddressesResponseType();
        descAddrRespType.setRequestId(UUID.randomUUID().toString());
        descAddrRespType.setAddressesSet(descAddrRespInfoType);

        DescribeAddressesResponse descAddrResp = new DescribeAddressesResponse();
        descAddrResp.setDescribeAddressesResponse(descAddrRespType);

        return descAddrResp;
    }

    public static AllocateAddressResponse toAllocateAddressResponse(final EC2Address ec2Address) {
        AllocateAddressResponse response = new AllocateAddressResponse();
        AllocateAddressResponseType param1 = new AllocateAddressResponseType();

        param1.setPublicIp(ec2Address.getIpAddress());
        param1.setDomain("standard");
        param1.setAllocationId("");
        param1.setRequestId(UUID.randomUUID().toString());
        response.setAllocateAddressResponse(param1);
        return response;
    }

    public static ReleaseAddressResponse toReleaseAddressResponse(final boolean result) {
        ReleaseAddressResponse response = new ReleaseAddressResponse();
        ReleaseAddressResponseType param1 = new ReleaseAddressResponseType();

        param1.set_return(result);
        param1.setRequestId(UUID.randomUUID().toString());

        response.setReleaseAddressResponse(param1);
        return response;
    }

    public static AssociateAddressResponse toAssociateAddressResponse(final boolean result) {
        AssociateAddressResponse response = new AssociateAddressResponse();
        AssociateAddressResponseType param1 = new AssociateAddressResponseType();

        param1.setAssociationId("");
        param1.setRequestId(UUID.randomUUID().toString());
        param1.set_return(result);

        response.setAssociateAddressResponse(param1);
        return response;
    }

    public static DisassociateAddressResponse toDisassociateAddressResponse(final boolean result) {
        DisassociateAddressResponse response = new DisassociateAddressResponse();
        DisassociateAddressResponseType param1 = new DisassociateAddressResponseType();

        param1.setRequestId(UUID.randomUUID().toString());
        param1.set_return(result);

        response.setDisassociateAddressResponse(param1);
        return response;
    }

    /**
     * Map our cloud state values into what Amazon defines.
     * Where are the values that can be returned by our cloud api defined?
     * 
     * @param cloudState
     * @return 
     */
    public static int toAmazonCode(String cloudState) {
        if (null == cloudState)
            return 48;

        if (cloudState.equalsIgnoreCase("Destroyed"))
            return 48;
        else if (cloudState.equalsIgnoreCase("Stopped"))
            return 80;
        else if (cloudState.equalsIgnoreCase("Running"))
            return 16;
        else if (cloudState.equalsIgnoreCase("Starting"))
            return 0;
        else if (cloudState.equalsIgnoreCase("Stopping"))
            return 64;
        else if (cloudState.equalsIgnoreCase("Error"))
            return 1;
        else if (cloudState.equalsIgnoreCase("Expunging"))
            return 48;
        else
            return 16;
    }

    public static String toAmazonStateName(String cloudState) {
        if (null == cloudState)
            return new String("terminated");

        if (cloudState.equalsIgnoreCase("Destroyed"))
            return new String("terminated");
        else if (cloudState.equalsIgnoreCase("Stopped"))
            return new String("stopped");
        else if (cloudState.equalsIgnoreCase("Running"))
            return new String("running");
        else if (cloudState.equalsIgnoreCase("Starting"))
            return new String("pending");
        else if (cloudState.equalsIgnoreCase("Stopping"))
            return new String("stopping");
        else if (cloudState.equalsIgnoreCase("Error"))
            return new String("error");
        else if (cloudState.equalsIgnoreCase("Expunging"))
            return new String("terminated");
        else
            return new String("running");
    }

    public static StopInstancesResponse toStopInstancesResponse(EC2StopInstancesResponse engineResponse) {
        StopInstancesResponse response = new StopInstancesResponse();
        StopInstancesResponseType param1 = new StopInstancesResponseType();
        InstanceStateChangeSetType param2 = new InstanceStateChangeSetType();

        EC2Instance[] instances = engineResponse.getInstanceSet();
        for (int i = 0; i < instances.length; i++) {
            InstanceStateChangeType param3 = new InstanceStateChangeType();
            param3.setInstanceId(instances[i].getId());

            InstanceStateType param4 = new InstanceStateType();
            param4.setCode(toAmazonCode(instances[i].getState()));
            param4.setName(toAmazonStateName(instances[i].getState()));
            param3.setCurrentState(param4);

            InstanceStateType param5 = new InstanceStateType();
            param5.setCode(toAmazonCode(instances[i].getPreviousState()));
            param5.setName(toAmazonStateName(instances[i].getPreviousState()));
            param3.setPreviousState(param5);

            param2.addItem(param3);
        }

        param1.setRequestId(UUID.randomUUID().toString());
        param1.setInstancesSet(param2);
        response.setStopInstancesResponse(param1);
        return response;
    }

    public static StartInstancesResponse toStartInstancesResponse(EC2StartInstancesResponse engineResponse) {
        StartInstancesResponse response = new StartInstancesResponse();
        StartInstancesResponseType param1 = new StartInstancesResponseType();
        InstanceStateChangeSetType param2 = new InstanceStateChangeSetType();

        EC2Instance[] instances = engineResponse.getInstanceSet();
        for (int i = 0; i < instances.length; i++) {
            InstanceStateChangeType param3 = new InstanceStateChangeType();
            param3.setInstanceId(instances[i].getId());

            InstanceStateType param4 = new InstanceStateType();
            param4.setCode(toAmazonCode(instances[i].getState()));
            param4.setName(toAmazonStateName(instances[i].getState()));
            param3.setCurrentState(param4);

            InstanceStateType param5 = new InstanceStateType();
            param5.setCode(toAmazonCode(instances[i].getPreviousState()));
            param5.setName(toAmazonStateName(instances[i].getPreviousState()));
            param3.setPreviousState(param5);

            param2.addItem(param3);
        }

        param1.setRequestId(UUID.randomUUID().toString());
        param1.setInstancesSet(param2);
        response.setStartInstancesResponse(param1);
        return response;
    }

    public static TerminateInstancesResponse toTermInstancesResponse(EC2StopInstancesResponse engineResponse) {
        TerminateInstancesResponse response = new TerminateInstancesResponse();
        TerminateInstancesResponseType param1 = new TerminateInstancesResponseType();
        InstanceStateChangeSetType param2 = new InstanceStateChangeSetType();

        EC2Instance[] instances = engineResponse.getInstanceSet();
        for (int i = 0; i < instances.length; i++) {
            InstanceStateChangeType param3 = new InstanceStateChangeType();
            param3.setInstanceId(instances[i].getId());

            InstanceStateType param4 = new InstanceStateType();
            param4.setCode(toAmazonCode(instances[i].getState()));
            param4.setName(toAmazonStateName(instances[i].getState()));
            param3.setCurrentState(param4);

            InstanceStateType param5 = new InstanceStateType();
            param5.setCode(toAmazonCode(instances[i].getPreviousState()));
            param5.setName(toAmazonStateName(instances[i].getPreviousState()));
            param3.setPreviousState(param5);

            param2.addItem(param3);
        }

        param1.setRequestId(UUID.randomUUID().toString());
        param1.setInstancesSet(param2);
        response.setTerminateInstancesResponse(param1);
        return response;
    }

    public static RebootInstancesResponse toRebootInstancesResponse(boolean engineResponse) {
        RebootInstancesResponse response = new RebootInstancesResponse();
        RebootInstancesResponseType param1 = new RebootInstancesResponseType();

        param1.setRequestId(UUID.randomUUID().toString());
        param1.set_return(engineResponse);
        response.setRebootInstancesResponse(param1);
        return response;
    }

    public static RunInstancesResponse toRunInstancesResponse(EC2RunInstancesResponse engineResponse, EC2Engine engine) {
        RunInstancesResponse response = new RunInstancesResponse();
        RunInstancesResponseType param1 = new RunInstancesResponseType();

        param1.setReservationId("");

        RunningInstancesSetType param6 = new RunningInstancesSetType();
        EC2Instance[] instances = engineResponse.getInstanceSet();
        for (EC2Instance inst : instances) {
            RunningInstancesItemType param7 = new RunningInstancesItemType();
            param7.setInstanceId(inst.getId());
            param7.setImageId(inst.getTemplateId());

            String accountName = inst.getAccountName();
            String domainId = inst.getDomainId();
            String ownerId = domainId + ":" + accountName;

            param1.setOwnerId(ownerId);

            EC2SecurityGroup[] groups = inst.getGroupSet();
            GroupSetType param2 = new GroupSetType();
            if (null == groups || 0 == groups.length) {
                GroupItemType param3 = new GroupItemType();
                param3.setGroupId("");
                param2.addItem(param3);
            } else {
                for (EC2SecurityGroup group : groups) {
                    GroupItemType param3 = new GroupItemType();
                    param3.setGroupId(group.getId());
                    param2.addItem(param3);
                }
            }
            param1.setGroupSet(param2);

            InstanceStateType param8 = new InstanceStateType();
            param8.setCode(toAmazonCode(inst.getState()));
            param8.setName(toAmazonStateName(inst.getState()));
            param7.setInstanceState(param8);

            param7.setPrivateDnsName("");
            param7.setDnsName("");
            param7.setReason("");
            param7.setKeyName(inst.getKeyPairName());
            param7.setAmiLaunchIndex(null);

            ProductCodesSetType param9 = new ProductCodesSetType();
            ProductCodesSetItemType param10 = new ProductCodesSetItemType();
            param10.setProductCode("");
            param10.setType("");
            param9.addItem(param10);
            param7.setProductCodes(param9);

            param7.setInstanceType(inst.getServiceOffering());
            // -> CloudStack seems to have issues with timestamp formats so just in case
            Calendar cal = inst.getCreated();
            if (null == cal) {
                cal = Calendar.getInstance();
                cal.set(1970, 1, 1);
            }
            param7.setLaunchTime(cal);

            PlacementResponseType param11 = new PlacementResponseType();
            param11.setAvailabilityZone(inst.getZoneName());
            param7.setPlacement(param11);

            param7.setKernelId("");
            param7.setRamdiskId("");
            param7.setPlatform("");

            InstanceMonitoringStateType param12 = new InstanceMonitoringStateType();
            param12.setState("");
            param7.setMonitoring(param12);
            param7.setSubnetId("");
            param7.setVpcId("");
            String ipAddr = inst.getPrivateIpAddress();
            param7.setPrivateIpAddress((null != ipAddr ? ipAddr : ""));
            param7.setIpAddress(inst.getIpAddress());

            StateReasonType param13 = new StateReasonType();
            param13.setCode("");
            param13.setMessage("");
            param7.setStateReason(param13);
            param7.setArchitecture("");
            param7.setRootDeviceType("");
            param7.setRootDeviceName("");

            param7.setInstanceLifecycle("");
            param7.setSpotInstanceRequestId("");
            param7.setVirtualizationType("");
            param7.setClientToken("");

            ResourceTagSetType param18 = new ResourceTagSetType();
            ResourceTagSetItemType param19 = new ResourceTagSetItemType();
            param19.setKey("");
            param19.setValue("");
            param18.addItem(param19);
            param7.setTagSet(param18);

            GroupSetType param14 = new GroupSetType();
            GroupItemType param15 = new GroupItemType();
            param15.setGroupId("");
            param15.setGroupName("");
            param14.addItem(param15);
            param7.setGroupSet(param14);

            String hypervisor = inst.getHypervisor();
            param7.setHypervisor((null != hypervisor ? hypervisor : ""));
            param6.addItem(param7);
        }
        param1.setInstancesSet(param6);
        param1.setRequesterId("");

        param1.setRequestId(UUID.randomUUID().toString());
        response.setRunInstancesResponse(param1);
        return response;
    }

    public static DescribeAvailabilityZonesResponse toDescribeAvailabilityZonesResponse(EC2DescribeAvailabilityZonesResponse engineResponse) {
        DescribeAvailabilityZonesResponse response = new DescribeAvailabilityZonesResponse();
        DescribeAvailabilityZonesResponseType param1 = new DescribeAvailabilityZonesResponseType();
        AvailabilityZoneSetType param2 = new AvailabilityZoneSetType();

        EC2AvailabilityZone[] zones = engineResponse.getAvailabilityZoneSet();
        for (EC2AvailabilityZone zone : zones) {
            AvailabilityZoneItemType param3 = new AvailabilityZoneItemType();
            param3.setZoneName(zone.getName());
            param3.setZoneState("available");
            param3.setRegionName("");

            AvailabilityZoneMessageSetType param4 = new AvailabilityZoneMessageSetType();
            AvailabilityZoneMessageType param5 = new AvailabilityZoneMessageType();
            param5.setMessage(zone.getMessage());
            param4.addItem(param5);
            param3.setMessageSet(param4);
            param2.addItem(param3);
        }

        param1.setRequestId(UUID.randomUUID().toString());
        param1.setAvailabilityZoneInfo(param2);
        response.setDescribeAvailabilityZonesResponse(param1);
        return response;
    }

    public static AttachVolumeResponse toAttachVolumeResponse(EC2Volume engineResponse) {
        AttachVolumeResponse response = new AttachVolumeResponse();
        AttachVolumeResponseType param1 = new AttachVolumeResponseType();

        Calendar cal = Calendar.getInstance();

        // -> if the instanceId was not given in the request then we have no way to get it
        param1.setVolumeId(engineResponse.getId().toString());
        param1.setInstanceId(engineResponse.getInstanceId().toString());
        param1.setDevice(engineResponse.getDevice());
        param1.setStatus(engineResponse.getAttachmentState());
        param1.setAttachTime(cal);

        param1.setRequestId(UUID.randomUUID().toString());
        response.setAttachVolumeResponse(param1);
        return response;
    }

    public static DetachVolumeResponse toDetachVolumeResponse(EC2Volume engineResponse) {
        DetachVolumeResponse response = new DetachVolumeResponse();
        DetachVolumeResponseType param1 = new DetachVolumeResponseType();
        Calendar cal = Calendar.getInstance();
        cal.set(1970, 1, 1);   // return one value, Unix Epoch, what else can we return? 

        param1.setVolumeId(engineResponse.getId().toString());
        param1.setInstanceId((null == engineResponse.getInstanceId() ? "" : engineResponse.getInstanceId().toString()));
        param1.setDevice((null == engineResponse.getDevice() ? "" : engineResponse.getDevice()));
        param1.setStatus(engineResponse.getAttachmentState());
        param1.setAttachTime(cal);

        param1.setRequestId(UUID.randomUUID().toString());
        response.setDetachVolumeResponse(param1);
        return response;
    }

    public static CreateVolumeResponse toCreateVolumeResponse(EC2Volume engineResponse) {
        CreateVolumeResponse response = new CreateVolumeResponse();
        CreateVolumeResponseType param1 = new CreateVolumeResponseType();

        param1.setVolumeId(engineResponse.getId().toString());
        Long volSize = new Long(engineResponse.getSize());
        param1.setSize(volSize.toString());
        if (engineResponse.getSnapshotId() != null)
            param1.setSnapshotId(engineResponse.getSnapshotId());
        else
            param1.setSnapshotId("");
        param1.setAvailabilityZone(engineResponse.getZoneName());
        if (null != engineResponse.getState())
            param1.setStatus(engineResponse.getState());
        else
            param1.setStatus("");  // ToDo - throw an Soap Fault 

        // -> CloudStack seems to have issues with timestamp formats so just in case
        Calendar cal = EC2RestAuth.parseDateString(engineResponse.getCreated());
        if (null == cal) {
            cal = Calendar.getInstance();
//             cal.set( 1970, 1, 1 );
        }
        param1.setCreateTime(cal);

        param1.setVolumeType("standard");
        param1.setRequestId(UUID.randomUUID().toString());
        response.setCreateVolumeResponse(param1);
        return response;
    }

    public static DeleteVolumeResponse toDeleteVolumeResponse(EC2Volume engineResponse) {
        DeleteVolumeResponse response = new DeleteVolumeResponse();
        DeleteVolumeResponseType param1 = new DeleteVolumeResponseType();

        if (null != engineResponse.getState())
            param1.set_return(true);
        else
            param1.set_return(false);  // ToDo - supposed to return an error

        param1.setRequestId(UUID.randomUUID().toString());
        response.setDeleteVolumeResponse(param1);
        return response;
    }

    public static DescribeSnapshotsResponse toDescribeSnapshotsResponse(EC2DescribeSnapshotsResponse engineResponse) {
        DescribeSnapshotsResponse response = new DescribeSnapshotsResponse();
        DescribeSnapshotsResponseType param1 = new DescribeSnapshotsResponseType();
        DescribeSnapshotsSetResponseType param2 = new DescribeSnapshotsSetResponseType();

        EC2Snapshot[] snaps = engineResponse.getSnapshotSet();
        for (EC2Snapshot snap : snaps) {
            DescribeSnapshotsSetItemResponseType param3 = new DescribeSnapshotsSetItemResponseType();
            param3.setSnapshotId(snap.getId());
            param3.setVolumeId(snap.getVolumeId());

            // our semantics are different than those ec2 uses
            if (snap.getState().equalsIgnoreCase("backedup")) {
                param3.setStatus("completed");
                param3.setProgress("100%");
            } else if (snap.getState().equalsIgnoreCase("creating")) {
                param3.setStatus("pending");
                param3.setProgress("33%");
            } else if (snap.getState().equalsIgnoreCase("backingup")) {
                param3.setStatus("pending");
                param3.setProgress("66%");
            } else {
                // if we see anything besides: backedup/creating/backingup, we assume error
                param3.setStatus("error");
                param3.setProgress("0%");
            }
//             param3.setStatus( snap.getState());

            String ownerId = snap.getDomainId() + ":" + snap.getAccountName();

            // -> CloudStack seems to have issues with timestamp formats so just in case
            Calendar cal = snap.getCreated();
            if (null == cal) {
                cal = Calendar.getInstance();
                cal.set(1970, 1, 1);
            }
            param3.setStartTime(cal);

            param3.setOwnerId(ownerId);
            if (snap.getVolumeSize() == null)
                param3.setVolumeSize("0");
            else
                param3.setVolumeSize(snap.getVolumeSize().toString());
            param3.setDescription(snap.getName());
            param3.setOwnerAlias(snap.getAccountName());

            EC2TagKeyValue[] tags = snap.getResourceTags();
            param3.setTagSet(setResourceTags(tags));
            param2.addItem(param3);
        }

        param1.setSnapshotSet(param2);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setDescribeSnapshotsResponse(param1);
        return response;
    }

    public static DeleteSnapshotResponse toDeleteSnapshotResponse(boolean engineResponse) {
        DeleteSnapshotResponse response = new DeleteSnapshotResponse();
        DeleteSnapshotResponseType param1 = new DeleteSnapshotResponseType();

        param1.set_return(engineResponse);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setDeleteSnapshotResponse(param1);
        return response;
    }

    public static CreateSnapshotResponse toCreateSnapshotResponse(EC2Snapshot engineResponse, EC2Engine engine) {
        CreateSnapshotResponse response = new CreateSnapshotResponse();
        CreateSnapshotResponseType param1 = new CreateSnapshotResponseType();

        String accountName = engineResponse.getAccountName();
        String domainId = engineResponse.getDomainId().toString();
        String ownerId = domainId + ":" + accountName;

        param1.setSnapshotId(engineResponse.getId().toString());
        param1.setVolumeId(engineResponse.getVolumeId().toString());
        param1.setStatus("completed");

        // -> CloudStack seems to have issues with timestamp formats so just in case
        Calendar cal = engineResponse.getCreated();
        if (null == cal) {
            cal = Calendar.getInstance();
            cal.set(1970, 1, 1);
        }
        param1.setStartTime(cal);

        param1.setProgress("100");
        param1.setOwnerId(ownerId);
        Long volSize = new Long(engineResponse.getVolumeSize());
        param1.setVolumeSize(volSize.toString());
        param1.setDescription(engineResponse.getName());
        param1.setRequestId(UUID.randomUUID().toString());
        response.setCreateSnapshotResponse(param1);
        return response;
    }

    public static DescribeSecurityGroupsResponse toDescribeSecurityGroupsResponse(EC2DescribeSecurityGroupsResponse engineResponse) {
        DescribeSecurityGroupsResponse response = new DescribeSecurityGroupsResponse();
        DescribeSecurityGroupsResponseType param1 = new DescribeSecurityGroupsResponseType();
        SecurityGroupSetType param2 = new SecurityGroupSetType();

        EC2SecurityGroup[] groups = engineResponse.getGroupSet();
        for (EC2SecurityGroup group : groups) {
            SecurityGroupItemType param3 = new SecurityGroupItemType();
            String accountName = group.getAccountName();
            String domainId = group.getDomainId();
            String ownerId = domainId + ":" + accountName;

            param3.setOwnerId(ownerId);
            param3.setGroupName(group.getName());
            String desc = group.getDescription();
            param3.setGroupDescription((null != desc ? desc : ""));
            param3.setGroupId(group.getId());
            param3.setVpcId("");

            IpPermissionSetType param4 = new IpPermissionSetType();
            EC2IpPermission[] perms = group.getIpPermissionSet();
            for (EC2IpPermission perm : perms) {
                // TODO: Fix kludges like this...
                if (perm == null)
                    continue;
                IpPermissionType param5 = new IpPermissionType();
                param5.setIpProtocol(perm.getProtocol());
                if (perm.getProtocol().equalsIgnoreCase("icmp")) {
                    param5.setFromPort(Integer.parseInt(perm.getIcmpType()));
                    param5.setToPort(Integer.parseInt(perm.getIcmpCode()));
                } else {
                    param5.setFromPort(perm.getFromPort());
                    param5.setToPort(perm.getToPort());
                }

                // -> user groups
                EC2SecurityGroup[] userSet = perm.getUserSet();
                if (null == userSet || 0 == userSet.length) {
                    UserIdGroupPairSetType param8 = new UserIdGroupPairSetType();
                    param5.setGroups(param8);
                } else {
                    for (EC2SecurityGroup secGroup : userSet) {
                        UserIdGroupPairSetType param8 = new UserIdGroupPairSetType();
                        UserIdGroupPairType param9 = new UserIdGroupPairType();
                        param9.setUserId(secGroup.getAccount());
                        param9.setGroupName(secGroup.getName());
                        param8.addItem(param9);
                        param5.setGroups(param8);
                    }
                }

                // -> or CIDR list
                String[] rangeSet = perm.getIpRangeSet();
                if (null == rangeSet || 0 == rangeSet.length) {
                    IpRangeSetType param6 = new IpRangeSetType();
                    param5.setIpRanges(param6);
                } else {
                    for (String range : rangeSet) {
                        // TODO: This needs further attention...
                        IpRangeSetType param6 = new IpRangeSetType();
                        if (range != null) {
                            IpRangeItemType param7 = new IpRangeItemType();
                            param7.setCidrIp(range);
                            param6.addItem(param7);
                        }
                        param5.setIpRanges(param6);
                    }
                }
                param4.addItem(param5);
            }
            param3.setIpPermissions(param4);
            EC2TagKeyValue[] tags = group.getResourceTags();
            param3.setTagSet(setResourceTags(tags));
            param2.addItem(param3);
        }
        param1.setSecurityGroupInfo(param2);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setDescribeSecurityGroupsResponse(param1);
        return response;
    }

    public static CreateSecurityGroupResponse toCreateSecurityGroupResponse(EC2SecurityGroup sg) {
        CreateSecurityGroupResponse response = new CreateSecurityGroupResponse();
        CreateSecurityGroupResponseType param1 = new CreateSecurityGroupResponseType();

        param1.setGroupId(sg.getId());
        if (sg.getId() != null)
            param1.set_return(true);
        else
            param1.set_return(false);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setCreateSecurityGroupResponse(param1);
        return response;
    }

    public static DeleteSecurityGroupResponse toDeleteSecurityGroupResponse(boolean success) {
        DeleteSecurityGroupResponse response = new DeleteSecurityGroupResponse();
        DeleteSecurityGroupResponseType param1 = new DeleteSecurityGroupResponseType();

        param1.set_return(success);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setDeleteSecurityGroupResponse(param1);
        return response;
    }

    public static AuthorizeSecurityGroupIngressResponse toAuthorizeSecurityGroupIngressResponse(boolean success) {
        AuthorizeSecurityGroupIngressResponse response = new AuthorizeSecurityGroupIngressResponse();
        AuthorizeSecurityGroupIngressResponseType param1 = new AuthorizeSecurityGroupIngressResponseType();

        param1.set_return(success);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setAuthorizeSecurityGroupIngressResponse(param1);
        return response;
    }

    public static RevokeSecurityGroupIngressResponse toRevokeSecurityGroupIngressResponse(boolean success) {
        RevokeSecurityGroupIngressResponse response = new RevokeSecurityGroupIngressResponse();
        RevokeSecurityGroupIngressResponseType param1 = new RevokeSecurityGroupIngressResponseType();

        param1.set_return(success);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setRevokeSecurityGroupIngressResponse(param1);
        return response;
    }

    public static CreateTagsResponse toCreateTagsResponse(boolean success) {
        CreateTagsResponse response = new CreateTagsResponse();
        CreateTagsResponseType param1 = new CreateTagsResponseType();

        param1.set_return(success);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setCreateTagsResponse(param1);
        return response;
    }

    public static DeleteTagsResponse toDeleteTagsResponse(boolean success) {
        DeleteTagsResponse response = new DeleteTagsResponse();
        DeleteTagsResponseType param1 = new DeleteTagsResponseType();

        param1.set_return(success);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setDeleteTagsResponse(param1);
        return response;
    }

    public static DescribeTagsResponse toDescribeTagsResponse(EC2DescribeTagsResponse engineResponse) {
        DescribeTagsResponse response = new DescribeTagsResponse();
        DescribeTagsResponseType param1 = new DescribeTagsResponseType();

        EC2ResourceTag[] tags = engineResponse.getTagsSet();
        TagSetType param2 = new TagSetType();
        for (EC2ResourceTag tag : tags) {
            TagSetItemType param3 = new TagSetItemType();
            param3.setResourceId(tag.getResourceId());
            param3.setResourceType(tag.getResourceType());
            param3.setKey(tag.getKey());
            if (tag.getValue() != null)
                param3.setValue(tag.getValue());
            param2.addItem(param3);
        }
        param1.setTagSet(param2);
        param1.setRequestId(UUID.randomUUID().toString());
        response.setDescribeTagsResponse(param1);
        return response;
    }

    public DescribeKeyPairsResponse describeKeyPairs(DescribeKeyPairs describeKeyPairs) {

        EC2DescribeKeyPairs ec2Request = new EC2DescribeKeyPairs();

        // multiple keynames may be provided
        DescribeKeyPairsInfoType kset = describeKeyPairs.getDescribeKeyPairs().getKeySet();
        if (kset != null) {
            DescribeKeyPairsItemType[] keyPairKeys = kset.getItem();
            if (keyPairKeys != null) {
                for (DescribeKeyPairsItemType key : keyPairKeys) {
                    ec2Request.addKeyName(key.getKeyName());
                }
            }
        }

        // multiple filters may be provided
        FilterSetType fset = describeKeyPairs.getDescribeKeyPairs().getFilterSet();
        if (fset != null) {
            ec2Request.setKeyFilterSet(toKeyPairFilterSet(fset));
        }

        return toDescribeKeyPairs(engine.describeKeyPairs(ec2Request));
    }

    public static DescribeKeyPairsResponse toDescribeKeyPairs(final EC2DescribeKeyPairsResponse response) {
        EC2SSHKeyPair[] keyPairs = response.getKeyPairSet();

        DescribeKeyPairsResponseInfoType respInfoType = new DescribeKeyPairsResponseInfoType();
        if (keyPairs != null && keyPairs.length > 0) {
            for (final EC2SSHKeyPair key : keyPairs) {
                DescribeKeyPairsResponseItemType respItemType = new DescribeKeyPairsResponseItemType();
                respItemType.setKeyFingerprint(key.getFingerprint());
                respItemType.setKeyName(key.getKeyName());
                respInfoType.addItem(respItemType);
            }
        }

        DescribeKeyPairsResponseType respType = new DescribeKeyPairsResponseType();
        respType.setRequestId(UUID.randomUUID().toString());
        respType.setKeySet(respInfoType);

        DescribeKeyPairsResponse resp = new DescribeKeyPairsResponse();
        resp.setDescribeKeyPairsResponse(respType);
        return resp;
    }

    public ImportKeyPairResponse importKeyPair(ImportKeyPair importKeyPair) {
        String publicKey = importKeyPair.getImportKeyPair().getPublicKeyMaterial();
        if (!publicKey.contains(" "))
            publicKey = new String(Base64.decodeBase64(publicKey.getBytes()));

        EC2ImportKeyPair ec2Request = new EC2ImportKeyPair();
        if (ec2Request != null) {
            ec2Request.setKeyName(importKeyPair.getImportKeyPair().getKeyName());
            ec2Request.setPublicKeyMaterial(publicKey);
        }

        return toImportKeyPair(engine.importKeyPair(ec2Request));
    }

    public static ImportKeyPairResponse toImportKeyPair(final EC2SSHKeyPair key) {
        ImportKeyPairResponseType respType = new ImportKeyPairResponseType();
        respType.setRequestId(UUID.randomUUID().toString());
        respType.setKeyName(key.getKeyName());
        respType.setKeyFingerprint(key.getFingerprint());

        ImportKeyPairResponse response = new ImportKeyPairResponse();
        response.setImportKeyPairResponse(respType);

        return response;
    }

    public CreateKeyPairResponse createKeyPair(CreateKeyPair createKeyPair) {
        EC2CreateKeyPair ec2Request = new EC2CreateKeyPair();
        if (ec2Request != null) {
            ec2Request.setKeyName(createKeyPair.getCreateKeyPair().getKeyName());
        }

        return toCreateKeyPair(engine.createKeyPair(ec2Request));
    }

    public static CreateKeyPairResponse toCreateKeyPair(final EC2SSHKeyPair key) {
        CreateKeyPairResponseType respType = new CreateKeyPairResponseType();
        respType.setRequestId(UUID.randomUUID().toString());
        respType.setKeyName(key.getKeyName());
        respType.setKeyFingerprint(key.getFingerprint());
        respType.setKeyMaterial(key.getPrivateKey());

        CreateKeyPairResponse response = new CreateKeyPairResponse();
        response.setCreateKeyPairResponse(respType);

        return response;
    }

    public DeleteKeyPairResponse deleteKeyPair(DeleteKeyPair deleteKeyPair) {
        EC2DeleteKeyPair ec2Request = new EC2DeleteKeyPair();
        ec2Request.setKeyName(deleteKeyPair.getDeleteKeyPair().getKeyName());

        return toDeleteKeyPair(engine.deleteKeyPair(ec2Request));
    }

    public static DeleteKeyPairResponse toDeleteKeyPair(final boolean success) {
        DeleteKeyPairResponseType respType = new DeleteKeyPairResponseType();
        respType.setRequestId(UUID.randomUUID().toString());
        respType.set_return(success);

        DeleteKeyPairResponse response = new DeleteKeyPairResponse();
        response.setDeleteKeyPairResponse(respType);

        return response;
    }

    public GetPasswordDataResponse getPasswordData(GetPasswordData getPasswordData) {
        return toGetPasswordData(engine.getPasswordData(getPasswordData.getGetPasswordData().getInstanceId()));
    }

    public static ResourceTagSetType setResourceTags(EC2TagKeyValue[] tags) {
        ResourceTagSetType param1 = new ResourceTagSetType();
        if (null == tags || 0 == tags.length) {
            ResourceTagSetItemType param2 = new ResourceTagSetItemType();
            param2.setKey("");
            param2.setValue("");
            param1.addItem(param2);
        } else {
            for (EC2TagKeyValue tag : tags) {
                ResourceTagSetItemType param2 = new ResourceTagSetItemType();
                param2.setKey(tag.getKey());
                if (tag.getValue() != null)
                    param2.setValue(tag.getValue());
                else
                    param2.setValue("");
                param1.addItem(param2);
            }
        }
        return param1;
    }

    @SuppressWarnings("serial")
    public static GetPasswordDataResponse toGetPasswordData(final EC2PasswordData passwdData) {
        return new GetPasswordDataResponse() {
            {
                setGetPasswordDataResponse(new GetPasswordDataResponseType() {
                    {
                        setRequestId(UUID.randomUUID().toString());
                        setTimestamp(Calendar.getInstance());
                        setPasswordData(passwdData.getEncryptedPassword());
                        setInstanceId(passwdData.getInstanceId());
                    }
                });
            }
        };
    }

    // Actions not yet implemented:

    public ActivateLicenseResponse activateLicense(ActivateLicense activateLicense) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public AssociateDhcpOptionsResponse associateDhcpOptions(AssociateDhcpOptions associateDhcpOptions) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    };

    public AttachVpnGatewayResponse attachVpnGateway(AttachVpnGateway attachVpnGateway) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public BundleInstanceResponse bundleInstance(BundleInstance bundleInstance) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CancelBundleTaskResponse cancelBundleTask(CancelBundleTask cancelBundleTask) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CancelConversionTaskResponse cancelConversionTask(CancelConversionTask cancelConversionTask) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CancelSpotInstanceRequestsResponse cancelSpotInstanceRequests(CancelSpotInstanceRequests cancelSpotInstanceRequests) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public ConfirmProductInstanceResponse confirmProductInstance(ConfirmProductInstance confirmProductInstance) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateCustomerGatewayResponse createCustomerGateway(CreateCustomerGateway createCustomerGateway) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateDhcpOptionsResponse createDhcpOptions(CreateDhcpOptions createDhcpOptions) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreatePlacementGroupResponse createPlacementGroup(CreatePlacementGroup createPlacementGroup) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateSpotDatafeedSubscriptionResponse createSpotDatafeedSubscription(CreateSpotDatafeedSubscription createSpotDatafeedSubscription) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateSubnetResponse createSubnet(CreateSubnet createSubnet) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateVpcResponse createVpc(CreateVpc createVpc) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateVpnConnectionResponse createVpnConnection(CreateVpnConnection createVpnConnection) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateVpnGatewayResponse createVpnGateway(CreateVpnGateway createVpnGateway) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeactivateLicenseResponse deactivateLicense(DeactivateLicense deactivateLicense) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeleteCustomerGatewayResponse deleteCustomerGateway(DeleteCustomerGateway deleteCustomerGateway) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeleteDhcpOptionsResponse deleteDhcpOptions(DeleteDhcpOptions deleteDhcpOptions) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeletePlacementGroupResponse deletePlacementGroup(DeletePlacementGroup deletePlacementGroup) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeleteSpotDatafeedSubscriptionResponse deleteSpotDatafeedSubscription(DeleteSpotDatafeedSubscription deleteSpotDatafeedSubscription) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeleteSubnetResponse deleteSubnet(DeleteSubnet deleteSubnet) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeleteVpcResponse deleteVpc(DeleteVpc deleteVpc) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeleteVpnConnectionResponse deleteVpnConnection(DeleteVpnConnection deleteVpnConnection) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeleteVpnGatewayResponse deleteVpnGateway(DeleteVpnGateway deleteVpnGateway) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeBundleTasksResponse describeBundleTasks(DescribeBundleTasks describeBundleTasks) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeConversionTasksResponse describeConversionTasks(DescribeConversionTasks describeConversionTasks) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeCustomerGatewaysResponse describeCustomerGateways(DescribeCustomerGateways describeCustomerGateways) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeDhcpOptionsResponse describeDhcpOptions(DescribeDhcpOptions describeDhcpOptions) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeLicensesResponse describeLicenses(DescribeLicenses describeLicenses) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribePlacementGroupsResponse describePlacementGroups(DescribePlacementGroups describePlacementGroups) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeRegionsResponse describeRegions(DescribeRegions describeRegions) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeReservedInstancesResponse describeReservedInstances(DescribeReservedInstances describeReservedInstances) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeReservedInstancesOfferingsResponse describeReservedInstancesOfferings(DescribeReservedInstancesOfferings describeReservedInstancesOfferings) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeSnapshotAttributeResponse describeSnapshotAttribute(DescribeSnapshotAttribute describeSnapshotAttribute) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeSpotDatafeedSubscriptionResponse describeSpotDatafeedSubscription(DescribeSpotDatafeedSubscription describeSpotDatafeedSubscription) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeSpotInstanceRequestsResponse describeSpotInstanceRequests(DescribeSpotInstanceRequests describeSpotInstanceRequests) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeSpotPriceHistoryResponse describeSpotPriceHistory(DescribeSpotPriceHistory describeSpotPriceHistory) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeSubnetsResponse describeSubnets(DescribeSubnets describeSubnets) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeVpcsResponse describeVpcs(DescribeVpcs describeVpcs) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeVpnConnectionsResponse describeVpnConnections(DescribeVpnConnections describeVpnConnections) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeVpnGatewaysResponse describeVpnGateways(DescribeVpnGateways describeVpnGateways) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DetachVpnGatewayResponse detachVpnGateway(DetachVpnGateway detachVpnGateway) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public GetConsoleOutputResponse getConsoleOutput(GetConsoleOutput getConsoleOutput) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public ImportInstanceResponse importInstance(ImportInstance importInstance) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public ImportVolumeResponse importVolume(ImportVolume importVolume) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public ModifySnapshotAttributeResponse modifySnapshotAttribute(ModifySnapshotAttribute modifySnapshotAttribute) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public PurchaseReservedInstancesOfferingResponse purchaseReservedInstancesOffering(PurchaseReservedInstancesOffering purchaseReservedInstancesOffering) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public RequestSpotInstancesResponse requestSpotInstances(RequestSpotInstances requestSpotInstances) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public ResetInstanceAttributeResponse resetInstanceAttribute(ResetInstanceAttribute resetInstanceAttribute) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public ResetSnapshotAttributeResponse resetSnapshotAttribute(ResetSnapshotAttribute resetSnapshotAttribute) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public ResetNetworkInterfaceAttributeResponse resetNetworkInterfaceAttribute(ResetNetworkInterfaceAttribute resetNetworkInterfaceAttribute) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateRouteTableResponse createRouteTable(CreateRouteTable createRouteTable) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateNetworkAclEntryResponse createNetworkAclEntry(CreateNetworkAclEntry createNetworkAclEntry) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeVolumeAttributeResponse describeVolumeAttribute(DescribeVolumeAttribute describeVolumeAttribute) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeleteNetworkInterfaceResponse deleteNetworkInterface(DeleteNetworkInterface deleteNetworkInterface) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateInternetGatewayResponse createInternetGateway(CreateInternetGateway createInternetGateway) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DisassociateRouteTableResponse disassociateRouteTable(DisassociateRouteTable disassociateRouteTable) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public ReplaceNetworkAclEntryResponse replaceNetworkAclEntry(ReplaceNetworkAclEntry replaceNetworkAclEntry) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public AuthorizeSecurityGroupEgressResponse authorizeSecurityGroupEgress(AuthorizeSecurityGroupEgress authorizeSecurityGroupEgress) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeleteNetworkAclEntryResponse deleteNetworkAclEntry(DeleteNetworkAclEntry deleteNetworkAclEntry) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeleteRouteTableResponse deleteRouteTable(DeleteRouteTable deleteRouteTable) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeNetworkInterfaceAttributeResponse describeNetworkInterfaceAttribute(DescribeNetworkInterfaceAttribute describeNetworkInterfaceAttribute) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateReservedInstancesListingResponse createReservedInstancesListing(CreateReservedInstancesListing createReservedInstancesListing) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateNetworkAclResponse createNetworkAcl(CreateNetworkAcl createNetworkAcl) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public ModifyVolumeAttributeResponse modifyVolumeAttribute(ModifyVolumeAttribute modifyVolumeAttribute) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public ReplaceNetworkAclAssociationResponse replaceNetworkAclAssociation(ReplaceNetworkAclAssociation replaceNetworkAclAssociation) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public EnableVgwRoutePropagationResponse enableVgwRoutePropagation(EnableVgwRoutePropagation enableVgwRoutePropagation) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public UnassignPrivateIpAddressesResponse unassignPrivateIpAddresses(UnassignPrivateIpAddresses unassignPrivateIpAddresses) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeleteVpnConnectionRouteResponse deleteVpnConnectionRoute(DeleteVpnConnectionRoute deleteVpnConnectionRoute) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CancelReservedInstancesListingResponse cancelReservedInstancesListing(CancelReservedInstancesListing cancelReservedInstancesListing) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeNetworkAclsResponse describeNetworkAcls(DescribeNetworkAcls describeNetworkAcls) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public EnableVolumeIOResponse enableVolumeIO(EnableVolumeIO enableVolumeIO) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeInternetGatewaysResponse describeInternetGateways(DescribeInternetGateways describeInternetGateways) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeReservedInstancesListingsResponse describeReservedInstancesListings(DescribeReservedInstancesListings describeReservedInstancesListings) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeInstanceStatusResponse describeInstanceStatus(DescribeInstanceStatus describeInstanceStatus) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public ModifyNetworkInterfaceAttributeResponse modifyNetworkInterfaceAttribute(ModifyNetworkInterfaceAttribute modifyNetworkInterfaceAttribute) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DisableVgwRoutePropagationResponse disableVgwRoutePropagation(DisableVgwRoutePropagation disableVgwRoutePropagation) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeVolumeStatusResponse describeVolumeStatus(DescribeVolumeStatus describeVolumeStatus) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DetachNetworkInterfaceResponse detachNetworkInterface(DetachNetworkInterface detachNetworkInterface) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeNetworkInterfacesResponse describeNetworkInterfaces(DescribeNetworkInterfaces describeNetworkInterfaces) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CancelExportTaskResponse cancelExportTask(CancelExportTask cancelExportTask) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateRouteResponse createRoute(CreateRoute createRoute) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeRouteTablesResponse describeRouteTables(DescribeRouteTables describeRouteTables) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeleteNetworkAclResponse deleteNetworkAcl(DeleteNetworkAcl deleteNetworkAcl) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeleteRouteResponse deleteRoute(DeleteRoute deleteRoute) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateVpnConnectionRouteResponse createVpnConnectionRoute(CreateVpnConnectionRoute createVpnConnectionRoute) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public AttachInternetGatewayResponse attachInternetGateway(AttachInternetGateway attachInternetGateway) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public ReplaceRouteTableAssociationResponse replaceRouteTableAssociation(ReplaceRouteTableAssociation replaceRouteTableAssociation) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public AssociateRouteTableResponse associateRouteTable(AssociateRouteTable associateRouteTable) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DetachInternetGatewayResponse detachInternetGateway(DetachInternetGateway detachInternetGateway) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DescribeExportTasksResponse describeExportTasks(DescribeExportTasks describeExportTasks) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateInstanceExportTaskResponse createInstanceExportTask(CreateInstanceExportTask createInstanceExportTask) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public AssignPrivateIpAddressesResponse assignPrivateIpAddresses(AssignPrivateIpAddresses assignPrivateIpAddresses) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public ReportInstanceStatusResponse reportInstanceStatus(ReportInstanceStatus reportInstanceStatus) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public DeleteInternetGatewayResponse deleteInternetGateway(DeleteInternetGateway deleteInternetGateway) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public AttachNetworkInterfaceResponse attachNetworkInterface(AttachNetworkInterface attachNetworkInterface) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public CreateNetworkInterfaceResponse createNetworkInterface(CreateNetworkInterface createNetworkInterface) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public RevokeSecurityGroupEgressResponse revokeSecurityGroupEgress(RevokeSecurityGroupEgress revokeSecurityGroupEgress) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }

    public ReplaceRouteResponse replaceRoute(ReplaceRoute replaceRoute) {
        throw new EC2ServiceException(ClientError.Unsupported, "This operation is not available");
    }
}
