From d4f71400712869d5f94f67d01341154eaa5446f4 Mon Sep 17 00:00:00 2001 From: Andrew Donald Kennedy Date: Wed, 5 Oct 2011 17:34:30 +0100 Subject: [PATCH] 612: Changed Tag filters to use Multimap and Collection to Iterable --- .../java/org/jclouds/aws/util/AWSUtils.java | 34 +- .../BindTagFiltersToIndexedFormParams.java | 16 +- .../java/org/jclouds/aws/ec2/domain/Tag.java | 32 +- .../org/jclouds/aws/ec2/domain/TagFilter.java | 162 -------- .../aws/ec2/services/TagAsyncClient.java | 17 +- .../jclouds/aws/ec2/services/TagClient.java | 23 +- .../org/jclouds/aws/ec2/util/TagFilters.java | 347 ++++++++++++------ .../org/jclouds/aws/ec2/xml/TagsHandler.java | 8 +- ...BindTagFiltersToIndexedFormParamsTest.java | 51 ++- .../aws/ec2/services/TagAsyncClientTest.java | 23 +- .../aws/ec2/services/TagClientLiveTest.java | 19 +- 11 files changed, 360 insertions(+), 372 deletions(-) delete mode 100644 providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/TagFilter.java diff --git a/common/aws/src/main/java/org/jclouds/aws/util/AWSUtils.java b/common/aws/src/main/java/org/jclouds/aws/util/AWSUtils.java index a51bc0a3de..f8c5201026 100644 --- a/common/aws/src/main/java/org/jclouds/aws/util/AWSUtils.java +++ b/common/aws/src/main/java/org/jclouds/aws/util/AWSUtils.java @@ -47,6 +47,7 @@ import org.jclouds.rest.internal.GeneratedHttpRequest; import com.google.common.base.Function; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap.Builder; +import com.google.common.collect.Multimap; /** * Needed to sign and verify requests and responses. @@ -68,6 +69,7 @@ public class AWSUtils { private final Provider errorHandlerProvider; private final String requestId; private final String requestToken; + @Resource protected Logger logger = Logger.NULL; @@ -140,7 +142,7 @@ public class AWSUtils { checkArgument(checkNotNull(input, "input") instanceof String[], "this binder is only valid for String[] : " + input.getClass()); String[] values = (String[]) input; - Builder builder = ImmutableMultimap. builder(); + Builder builder = ImmutableMultimap.builder(); for (int i = 0; i < values.length; i++) { builder.put(prefix + "." + (i + 1), checkNotNull(values[i], prefix.toLowerCase() + "s[" + i + "]")); } @@ -149,15 +151,35 @@ public class AWSUtils { } public static R indexMapToFormValuesWithPrefix(R request, String prefix, String keySuffix, String valueSuffix, Object input) { - checkArgument(checkNotNull(input, "input") instanceof Map, "this binder is only valid for Map: " - + input.getClass()); - Map map = (Map) input; + checkArgument(checkNotNull(input, "input") instanceof Map, "this binder is only valid for Map: " + input.getClass()); + Map map = (Map) input; Builder builder = ImmutableMultimap. builder(); int i = 1; - for (Map.Entry e : map.entrySet()) { + for (Map.Entry e : map.entrySet()) { builder.put(prefix + "." + i + "." + keySuffix, checkNotNull(e.getKey().toString(), keySuffix.toLowerCase() + "s[" + i + "]")); if (e.getValue() != null) { - builder.put(prefix + "." + i + "." + valueSuffix, e.getValue().toString()); + builder.put(prefix + "." + i + "." + valueSuffix, e.getValue().toString()); + } + i++; + } + ImmutableMultimap forms = builder.build(); + return forms.size() == 0 ? request : ModifyRequest.putFormParams(request, forms); + } + + @SuppressWarnings("unchecked") + public static R indexMultimapToFormValuesWithPrefix(R request, String prefix, String keySuffix, String valueSuffix, Object input) { + checkArgument(checkNotNull(input, "input") instanceof Multimap, "this binder is only valid for Multimap: " + input.getClass()); + Multimap map = (Multimap) input; + Builder builder = ImmutableMultimap. builder(); + int i = 1; + for (Object k : map.keySet()) { + builder.put(prefix + "." + i + "." + keySuffix, checkNotNull(k.toString(), keySuffix.toLowerCase() + "s[" + i + "]")); + if (!map.get(k).isEmpty()) { + int j = 1; + for (Object v : map.get(k)) { + builder.put(prefix + "." + i + "." + valueSuffix + "." + j, v.toString()); + j++; + } } i++; } diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/binders/BindTagFiltersToIndexedFormParams.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/binders/BindTagFiltersToIndexedFormParams.java index 41489c70d9..1058734569 100644 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/binders/BindTagFiltersToIndexedFormParams.java +++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/binders/BindTagFiltersToIndexedFormParams.java @@ -20,27 +20,19 @@ package org.jclouds.aws.ec2.binders; import static com.google.common.base.Preconditions.*; -import org.jclouds.aws.ec2.domain.TagFilter; -import org.jclouds.aws.ec2.util.TagFilters; +import org.jclouds.aws.util.AWSUtils; import org.jclouds.http.HttpRequest; -import org.jclouds.http.utils.ModifyRequest; import org.jclouds.rest.Binder; -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.ImmutableMultimap.Builder; +import com.google.common.collect.Multimap; /** * @author grkvlt@apache.org */ public class BindTagFiltersToIndexedFormParams implements Binder { - @SuppressWarnings("unchecked") @Override public R bindToRequest(R request, Object input) { - checkArgument(checkNotNull(input, "input") instanceof Iterable, "this binder is only valid for Iterable"); - Builder headers = ImmutableMultimap. builder(); - int index = 1; - for (TagFilter filter : (Iterable) input) - headers.putAll(TagFilters.buildFormParametersForIndex(index++, filter)); - return ModifyRequest.putFormParams(request, headers.build()); + checkArgument(checkNotNull(input, "input") instanceof Multimap, "this binder is only valid for Multimap"); + return AWSUtils.indexMultimapToFormValuesWithPrefix(request, "Filter", "Name", "Value", input); } } diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/Tag.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/Tag.java index 19fc35c48d..0951ece527 100644 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/Tag.java +++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/Tag.java @@ -18,7 +18,12 @@ */ package org.jclouds.aws.ec2.domain; -import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.*; + +import org.jclouds.aws.ec2.util.TagFilters.ResourceType; + +import com.google.common.base.Objects; +import com.google.common.collect.ComparisonChain; /** * @see @@ -31,7 +36,7 @@ public class Tag implements Comparable { public static class Builder { private String resourceId; - private String resourceType; + private ResourceType resourceType; private String key; private String value; @@ -47,7 +52,7 @@ public class Tag implements Comparable { return this; } - public Builder resourceType(String resourceType) { + public Builder resourceType(ResourceType resourceType) { this.resourceType = resourceType; return this; } @@ -68,11 +73,11 @@ public class Tag implements Comparable { } private final String resourceId; - private final String resourceType; + private final ResourceType resourceType; private final String key; private final String value; - public Tag(String resourceId, String resourceType, String key, String value) { + public Tag(String resourceId, ResourceType resourceType, String key, String value) { this.resourceId = checkNotNull(resourceId, "resourceId"); this.resourceType = checkNotNull(resourceType, "resourceType"); this.key = checkNotNull(key, "key"); @@ -83,7 +88,7 @@ public class Tag implements Comparable { return resourceId; } - public String getResourceType() { + public ResourceType getResourceType() { return resourceType; } @@ -97,18 +102,17 @@ public class Tag implements Comparable { @Override public int compareTo(Tag t) { - return key.compareTo(t.key); + return ComparisonChain.start() + .compare(resourceId, t.resourceId) + .compare(resourceType, t.resourceType) + .compare(key, t.key) + .compare(value, t.value) + .result(); } @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((resourceId == null) ? 0 : resourceId.hashCode()); - result = prime * result + ((resourceType == null) ? 0 : resourceType.hashCode()); - result = prime * result + ((key == null) ? 0 : key.hashCode()); - result = prime * result + ((value == null) ? 0 : value.hashCode()); - return result; + return Objects.hashCode(resourceId, resourceType, key, value); } @Override diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/TagFilter.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/TagFilter.java deleted file mode 100644 index 05d6915361..0000000000 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/TagFilter.java +++ /dev/null @@ -1,162 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds 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 org.jclouds.aws.ec2.domain; - -import static com.google.common.base.Preconditions.*; - -import java.util.Collection; - -import com.google.common.base.CaseFormat; -import com.google.common.collect.ImmutableList; - -/** - * tag filter. - * - * @see - * @author grkvlt@apache.org - */ -public class TagFilter implements Comparable { - public static enum FilterName { - KEY, - RESOURCE_ID, - RESOURCE_TYPE, - VALUE; - - public String value() { - return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name()); - } - - @Override - public String toString() { - return value(); - } - - public static FilterName fromValue(String name) { - try { - return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(name, "name"))); - } catch (IllegalArgumentException e) { - return null; - } - } - } - - public static enum ResourceType { - CUSTOMER_GATEWAY, - DHCP_OPTIONS, - IMAGE, - INSTANCE, - INTERNET_GATEWAY, - NETWORK_ACL, - RESERVED_INSTANCES, - ROUTE_TABLE, - SECURITY_GROUP, - SNAPSHOT, - SPOT_INSTANCES_REQUEST, - SUBNET, - VOLUME, - VPC, - VPN_CONNECTION, - VPN_GATEWAY; - - public String value() { - return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name()); - } - - @Override - public String toString() { - return value(); - } - - public static ResourceType fromValue(String name) { - try { - return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(name, "name"))); - } catch (IllegalArgumentException e) { - return null; - } - } - } - - private final FilterName name; - private final Collection values; - - public TagFilter(FilterName name, Collection values) { - this.name = checkNotNull(name, "name"); - this.values = checkNotNull(values, "values"); - } - - @Override - public int compareTo(TagFilter o) { - return name.compareTo(o.name); - } - - /** - * @return Name of the filter type. - */ - public FilterName getName() { - return name; - } - - /** - * @return Values to filter on. - */ - public Collection getValues() { - return values; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((values == null) ? 0 : values.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - TagFilter other = (TagFilter) obj; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - if (values == null) { - if (other.values != null) - return false; - } else if (!values.equals(other.values)) - return false; - return true; - } - - @Override - public String toString() { - return "[name=" + name + ", values=" + values + "]"; - } -} diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/TagAsyncClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/TagAsyncClient.java index 812a387a9c..5b1ffd36c9 100644 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/TagAsyncClient.java +++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/TagAsyncClient.java @@ -20,8 +20,6 @@ package org.jclouds.aws.ec2.services; import static org.jclouds.aws.reference.FormParameters.*; -import java.util.Collection; -import java.util.List; import java.util.Map; import java.util.Set; @@ -33,7 +31,7 @@ import org.jclouds.aws.ec2.binders.BindResourceIdsToIndexedFormParams; import org.jclouds.aws.ec2.binders.BindTagFiltersToIndexedFormParams; import org.jclouds.aws.ec2.binders.BindTagsToIndexedFormParams; import org.jclouds.aws.ec2.domain.Tag; -import org.jclouds.aws.ec2.domain.TagFilter; +import org.jclouds.aws.ec2.util.TagFilters; import org.jclouds.aws.ec2.xml.DescribeTagsResponseHandler; import org.jclouds.aws.filters.FormSigner; import org.jclouds.javax.annotation.Nullable; @@ -48,6 +46,7 @@ import org.jclouds.rest.annotations.XMLResponseParser; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnVoidOnNotFoundOr404; +import com.google.common.collect.Multimap; import com.google.common.util.concurrent.ListenableFuture; /** @@ -60,28 +59,28 @@ import com.google.common.util.concurrent.ListenableFuture; @VirtualHost public interface TagAsyncClient { /** - * @see TagClient#createTagsInRegion(String, Collection, Map) + * @see TagClient#createTagsInRegion(String, Iterable, Map) */ @POST @Path("/") @FormParams(keys = ACTION, values = "CreateTags") ListenableFuture createTagsInRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, - @BinderParam(BindResourceIdsToIndexedFormParams.class) Collection resourceIds, + @BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable resourceIds, @BinderParam(BindTagsToIndexedFormParams.class) Map tags); /** - * @see TagClient#deleteTagsInRegion(String, Collection, Map) + * @see TagClient#deleteTagsInRegion(String, Iterable, Map) */ @POST @Path("/") @FormParams(keys = ACTION, values = "DeleteTags") @ExceptionParser(ReturnVoidOnNotFoundOr404.class) ListenableFuture deleteTagsInRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, - @BinderParam(BindResourceIdsToIndexedFormParams.class) Collection resourceIds, + @BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable resourceIds, @BinderParam(BindTagsToIndexedFormParams.class) Map tags); /** - * @see TagClient#describeTagsInRegion(String, Collection) + * @see TagClient#describeTagsInRegion(String, Multimap) */ @POST @Path("/") @@ -89,5 +88,5 @@ public interface TagAsyncClient { @XMLResponseParser(DescribeTagsResponseHandler.class) @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) ListenableFuture> describeTagsInRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, - @BinderParam(BindTagFiltersToIndexedFormParams.class) Collection filters); + @BinderParam(BindTagFiltersToIndexedFormParams.class) Multimap filters); } diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/TagClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/TagClient.java index d14658d227..8bf144f373 100644 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/TagClient.java +++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/TagClient.java @@ -18,16 +18,17 @@ */ package org.jclouds.aws.ec2.services; -import java.util.Collection; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; import org.jclouds.aws.ec2.domain.Tag; -import org.jclouds.aws.ec2.domain.TagFilter; +import org.jclouds.aws.ec2.util.TagFilters; import org.jclouds.concurrent.Timeout; import org.jclouds.javax.annotation.Nullable; +import com.google.common.collect.Multimap; + /** * Provides Tag services for EC2. For more information, refer to the Amazon EC2 * Developer Guide. @@ -45,12 +46,12 @@ public interface TagClient { * IDs of the resources to tag. * @param tags * The tags to create. - * @see #describeTagsInRegion(String, Collection) - * @see #deleteTagsInRegion(String, Collection, Map) + * @see #describeTagsInRegion(String, Multimap) + * @see #deleteTagsInRegion(String, Iterable, Map) * * @see */ - void createTagsInRegion(@Nullable String region, Collection resourceIds, Map tags); + void createTagsInRegion(@Nullable String region, Iterable resourceIds, Map tags); /** * Deletes tags. @@ -62,12 +63,12 @@ public interface TagClient { * @param tags * The tags to delete. * - * @see #describeTagsInRegion(String, Collection) - * @see #createTagsInRegion(String, Collection, Map) + * @see #describeTagsInRegion(String, Multimap) + * @see #createTagsInRegion(String, Iterable, Map) * * @see */ - void deleteTagsInRegion(@Nullable String region, Collection resourceIds, Map tags); + void deleteTagsInRegion(@Nullable String region, Iterable resourceIds, Map tags); /** * Returns filtered information about tags. @@ -77,9 +78,9 @@ public interface TagClient { * @param filters * A collection of filters to apply before selecting the tags. * - * @see #deleteTagsInRegion(String, Collection, Map) - * @see #createTagsInRegion(String, Collection, Map) + * @see #deleteTagsInRegion(String, Iterable, Map) + * @see #createTagsInRegion(String, Iterable, Map) * @see */ - Set describeTagsInRegion(@Nullable String region, Collection filters); + Set describeTagsInRegion(@Nullable String region, Multimap filters); } diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/util/TagFilters.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/util/TagFilters.java index 8324bcfa62..c5406b1342 100644 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/util/TagFilters.java +++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/util/TagFilters.java @@ -18,163 +18,268 @@ */ package org.jclouds.aws.ec2.util; -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; +import static com.google.common.base.Preconditions.*; -import org.jclouds.aws.ec2.domain.TagFilter; -import org.jclouds.aws.ec2.domain.TagFilter.FilterName; -import org.jclouds.aws.ec2.domain.TagFilter.ResourceType; - -import com.google.common.collect.Maps; +import com.google.common.base.CaseFormat; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.Multimap; -import com.google.common.collect.Multimaps; -import com.google.common.collect.Sets; /** * @author grkvlt@apache.org */ public class TagFilters { - protected final FilterName name; - protected final Collection values; + public static enum FilterName { + KEY, + RESOURCE_ID, + RESOURCE_TYPE, + VALUE; - protected TagFilters(FilterName name, Collection values) { - this.name = name; - this.values = values != null ? values : Sets.newHashSet(); - } - - public static Multimap buildFormParametersForIndex(int index, TagFilter filter) { - Map headers = Maps.newLinkedHashMap(); - headers.put(String.format("Filter.%d.Name", index), filter.getName().value()); - int i = 0; - for (String value : filter.getValues()) { - headers.put(String.format("Filter.%d.Value.%d", index, ++i), value); - } - return Multimaps.forMap(headers); - } - - public static StringTagFilter key() { - return new StringTagFilter(FilterName.KEY); - } - - public static StringTagFilter resourceId() { - return new StringTagFilter(FilterName.RESOURCE_ID); - } - - public static ResourceTypeTagFilter resourceType() { - return new ResourceTypeTagFilter(); - } - - public static NamedTagFilter value() { - return new StringTagFilter(FilterName.VALUE); - } - - public static class NamedTagFilter extends TagFilters { - public NamedTagFilter(FilterName name) { - super(name, null); + public String value() { + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name()); } - public TagFilter filter() { - return new TagFilter(name, values); + @Override + public String toString() { + return value(); + } + + public static FilterName fromValue(String name) { + try { + return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(name, "name"))); + } catch (IllegalArgumentException e) { + return null; + } } } - public static class StringTagFilter extends NamedTagFilter { - public StringTagFilter(FilterName name) { - super(name); + public static enum ResourceType { + CUSTOMER_GATEWAY, + DHCP_OPTIONS, + IMAGE, + INSTANCE, + INTERNET_GATEWAY, + NETWORK_ACL, + RESERVED_INSTANCES, + ROUTE_TABLE, + SECURITY_GROUP, + SNAPSHOT, + SPOT_INSTANCES_REQUEST, + SUBNET, + VOLUME, + VPC, + VPN_CONNECTION, + VPN_GATEWAY; + + public String value() { + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, name()); } - public StringTagFilter exact(String value) { - return value(value); + @Override + public String toString() { + return value(); } - public StringTagFilter contains(String value) { - return value(String.format("*%s*", value)); - } - - public StringTagFilter value(String value) { - this.values.add(value); - return this; - } - - public StringTagFilter values(String... values) { - this.values.addAll(Arrays.asList(values)); - return this; + public static ResourceType fromValue(String name) { + try { + return valueOf(CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(name, "name"))); + } catch (IllegalArgumentException e) { + return null; + } } } - public static class ResourceTypeTagFilter extends NamedTagFilter { - public ResourceTypeTagFilter() { - super(FilterName.RESOURCE_TYPE); - } + protected final ImmutableSetMultimap.Builder map; - public ResourceTypeTagFilter resourceType(ResourceType resourceType) { - values.add(resourceType.value()); - return this; - } + protected TagFilters() { + map = ImmutableSetMultimap.builder(); + } - public ResourceTypeTagFilter customerGateway() { - return resourceType(ResourceType.CUSTOMER_GATEWAY); - } + public static TagFilters filters() { + return new TagFilters(); + } - public ResourceTypeTagFilter dhcpOptions() { - return resourceType(ResourceType.DHCP_OPTIONS); - } + public Multimap build() { + return map.build(); + } - public ResourceTypeTagFilter image() { - return resourceType(ResourceType.IMAGE); - } + public TagFilters resourceId(String resourceId) { + map.put(FilterName.RESOURCE_ID, resourceId); + return this; + } - public ResourceTypeTagFilter instance() { - return resourceType(ResourceType.INSTANCE); - } + public TagFilters key(String key) { + map.put(FilterName.KEY, key); + return this; + } - public ResourceTypeTagFilter internetGateway() { - return resourceType(ResourceType.INTERNET_GATEWAY); - } + public TagFilters keys(String...keys) { + map.putAll(FilterName.KEY, ImmutableSet.copyOf(keys)); + return this; + } - public ResourceTypeTagFilter networkAcl() { - return resourceType(ResourceType.NETWORK_ACL); - } + public TagFilters keys(Iterable keys) { + map.putAll(FilterName.KEY, ImmutableSet.copyOf(keys)); + return this; + } - public ResourceTypeTagFilter reservedInstance() { - return resourceType(ResourceType.RESERVED_INSTANCES); - } + public TagFilters value(String value) { + map.put(FilterName.VALUE, value); + return this; + } - public ResourceTypeTagFilter routeTable() { - return resourceType(ResourceType.ROUTE_TABLE); - } + public TagFilters values(String...values) { + map.putAll(FilterName.VALUE, ImmutableSet.copyOf(values)); + return this; + } - public ResourceTypeTagFilter securityGroup() { - return resourceType(ResourceType.SECURITY_GROUP); - } + public TagFilters values(Iterable values) { + map.putAll(FilterName.VALUE, ImmutableSet.copyOf(values)); + return this; + } - public ResourceTypeTagFilter snapshot() { - return resourceType(ResourceType.SNAPSHOT); - } + public TagFilters keyContains(String key) { + return key(String.format("*%s*", key)); + } - public ResourceTypeTagFilter instancesRequest() { - return resourceType(ResourceType.SPOT_INSTANCES_REQUEST); - } + public TagFilters valueContains(String value) { + return value(String.format("*%s*", value)); + } - public ResourceTypeTagFilter subnet() { - return resourceType(ResourceType.SUBNET); - } + public TagFilters resourceIdContains(String value) { + return resourceId(String.format("*%s*", value)); + } - public ResourceTypeTagFilter volume() { - return resourceType(ResourceType.VOLUME); - } + public TagFilters keyStartsWith(String key) { + return key(String.format("%s*", key)); + } - public ResourceTypeTagFilter vpc() { - return resourceType(ResourceType.VPC); - } + public TagFilters valueStartsWith(String value) { + return value(String.format("%s*", value)); + } - public ResourceTypeTagFilter vpnConnection() { - return resourceType(ResourceType.VPN_CONNECTION); - } + public TagFilters resourceIdStartsWith(String value) { + return resourceId(String.format("%s*", value)); + } - public ResourceTypeTagFilter vpnGateway() { - return resourceType(ResourceType.VPN_GATEWAY); - } + public TagFilters keyEndsWith(String key) { + return key(String.format("*%s", key)); + } + + public TagFilters valueEndsWith(String value) { + return value(String.format("*%s", value)); + } + + public TagFilters resourceIdEndsWith(String value) { + return resourceId(String.format("*%s", value)); + } + + public TagFilters keyValuePair(String key, String value) { + return key(key).value(value); + } + + public TagFilters keyValueSet(String key, Iterable values) { + return key(key).values(values); + } + + public TagFilters keyValueSet(String key, String...values) { + return key(key).values(values); + } + + public TagFilters anyKey() { + return key("*"); + } + + public TagFilters anyValue() { + return value("*"); + } + + public TagFilters anyResourceId() { + return resourceId("*"); + } + + public TagFilters anyResourceType() { + map.put(FilterName.RESOURCE_TYPE, "*"); + return this; + } + + public TagFilters customerGateway() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.CUSTOMER_GATEWAY); + return this; + } + + public TagFilters dhcpOptions() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.DHCP_OPTIONS); + return this; + } + + public TagFilters image() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.IMAGE); + return this; + } + + public TagFilters instance() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.INSTANCE); + return this; + } + + public TagFilters internetGateway() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.INTERNET_GATEWAY); + return this; + } + + public TagFilters networkAcl() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.NETWORK_ACL); + return this; + } + + public TagFilters reservedInstance() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.RESERVED_INSTANCES); + return this; + } + + public TagFilters routeTable() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.ROUTE_TABLE); + return this; + } + + public TagFilters securityGroup() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.SECURITY_GROUP); + return this; + } + + public TagFilters snapshot() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.SNAPSHOT); + return this; + } + + public TagFilters instancesRequest() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.SPOT_INSTANCES_REQUEST); + return this; + } + + public TagFilters subnet() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.SUBNET); + return this; + } + + public TagFilters volume() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.VOLUME); + return this; + } + + public TagFilters vpc() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.VPC); + return this; + } + + public TagFilters vpnConnection() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.VPN_CONNECTION); + return this; + } + + public TagFilters vpnGateway() { + map.put(FilterName.RESOURCE_TYPE, ResourceType.VPN_GATEWAY); + return this; } } diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/TagsHandler.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/TagsHandler.java index c710573e38..6d2a7a64ef 100644 --- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/TagsHandler.java +++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/TagsHandler.java @@ -19,7 +19,7 @@ package org.jclouds.aws.ec2.xml; import org.jclouds.aws.ec2.domain.Tag; -import org.jclouds.aws.ec2.domain.TagFilter; +import org.jclouds.aws.ec2.util.TagFilters.ResourceType; import org.jclouds.http.functions.ParseSax; /** @@ -29,12 +29,12 @@ public class TagsHandler extends ParseSax.HandlerForGeneratedRequestWithResultbuilder().add(TagFilter.ResourceType.VPN_GATEWAY.value()).add(TagFilter.ResourceType.INTERNET_GATEWAY.value()).build())).build()); + request = binder.bindToRequest(request, ImmutableSetMultimap.builder().put(FilterName.RESOURCE_TYPE, ResourceType.VPN_GATEWAY).put(FilterName.RESOURCE_TYPE, ResourceType.INTERNET_GATEWAY).build()); assertEquals(request.getPayload().getRawContent(), "Filter.1.Name=resource-type&Filter.1.Value.1=vpn-gateway&Filter.1.Value.2=internet-gateway"); } - public void testKeyWithValues() { + public void testMultipleKeys() { HttpRequest request = HttpRequest.builder().method("POST").endpoint(URI.create("http://localhost")).build(); - request = binder.bindToRequest(request, ImmutableList.builder().add(new TagFilter(FilterName.KEY, - ImmutableList.builder().add("one").add("two").build())).build()); + request = binder.bindToRequest(request, ImmutableSetMultimap.builder().put(FilterName.KEY, "one").put(FilterName.KEY, "two").build()); assertEquals(request.getPayload().getRawContent(), "Filter.1.Name=key&Filter.1.Value.1=one&Filter.1.Value.2=two"); } - public void testKeyWithoutValues() { + public void testkeyWithValue() { HttpRequest request = HttpRequest.builder().method("POST").endpoint(URI.create("http://localhost")).build(); - request = binder.bindToRequest(request, ImmutableList.builder().add(new TagFilter(FilterName.KEY, ImmutableList.of())).build()); - assertEquals(request.getPayload().getRawContent(), "Filter.1.Name=key"); + request = binder.bindToRequest(request, ImmutableSetMultimap.builder().put(FilterName.KEY, "one").put(FilterName.VALUE, "alpha").build()); + assertEquals(request.getPayload().getRawContent(), "Filter.1.Name=key&Filter.1.Value.1=one&Filter.2.Name=value&Filter.2.Value.1=alpha"); + } + + public void testAnyKey() { + HttpRequest request = HttpRequest.builder().method("POST").endpoint(URI.create("http://localhost")).build(); + request = binder.bindToRequest(request, ImmutableSetMultimap.builder().put(FilterName.KEY, "*").build()); + assertEquals(request.getPayload().getRawContent(), "Filter.1.Name=key&Filter.1.Value.1=%2A"); + } + + public void testResourceTypeWithValuesBuilder() { + HttpRequest request = HttpRequest.builder().method("POST").endpoint(URI.create("http://localhost")).build(); + request = binder.bindToRequest(request, TagFilters.filters().vpnGateway().internetGateway().build()); + assertEquals(request.getPayload().getRawContent(), "Filter.1.Name=resource-type&Filter.1.Value.1=vpn-gateway&Filter.1.Value.2=internet-gateway"); + } + + public void testMultipleKeysBuilder() { + HttpRequest request = HttpRequest.builder().method("POST").endpoint(URI.create("http://localhost")).build(); + request = binder.bindToRequest(request, TagFilters.filters().key("one").key("two").build()); + assertEquals(request.getPayload().getRawContent(), "Filter.1.Name=key&Filter.1.Value.1=one&Filter.1.Value.2=two"); + } + + public void testkeyWithValueBuilder() { + HttpRequest request = HttpRequest.builder().method("POST").endpoint(URI.create("http://localhost")).build(); + request = binder.bindToRequest(request, TagFilters.filters().keyValuePair("one", "alpha").build()); + assertEquals(request.getPayload().getRawContent(), "Filter.1.Name=key&Filter.1.Value.1=one&Filter.2.Name=value&Filter.2.Value.1=alpha"); + } + + public void testAnyKeyBuilder() { + HttpRequest request = HttpRequest.builder().method("POST").endpoint(URI.create("http://localhost")).build(); + request = binder.bindToRequest(request, TagFilters.filters().anyKey().build()); + assertEquals(request.getPayload().getRawContent(), "Filter.1.Name=key&Filter.1.Value.1=%2A"); } @Test(expectedExceptions = IllegalArgumentException.class) diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/TagAsyncClientTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/TagAsyncClientTest.java index 87feb0a062..ac088fc11c 100644 --- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/TagAsyncClientTest.java +++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/TagAsyncClientTest.java @@ -20,11 +20,9 @@ package org.jclouds.aws.ec2.services; import java.io.IOException; import java.lang.reflect.Method; -import java.util.Collection; import java.util.Map; -import org.jclouds.aws.ec2.domain.TagFilter; -import org.jclouds.aws.ec2.domain.TagFilter.FilterName; +import org.jclouds.aws.ec2.util.TagFilters.FilterName; import org.jclouds.aws.ec2.xml.DescribeTagsResponseHandler; import org.jclouds.http.HttpRequest; import org.jclouds.http.functions.ParseSax; @@ -36,19 +34,20 @@ import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.Multimap; import com.google.inject.TypeLiteral; /** * Tests behavior of {@code TagsAsyncClient} * - * @author Adrian Cole + * @author grkvlt@apache.org */ // NOTE:without testName, this will not call @Before* and fail w/NPE during surefire @Test(groups = "unit", testName = "TagsAsyncClientTest") public class TagAsyncClientTest extends BaseAWSEC2AsyncClientTest { - public void testDeleteTags() throws SecurityException, NoSuchMethodException, IOException { - Method method = TagAsyncClient.class.getMethod("deleteTagsInRegion", String.class, Collection.class, Map.class); + Method method = TagAsyncClient.class.getMethod("deleteTagsInRegion", String.class, Iterable.class, Map.class); HttpRequest request = processor.createRequest(method, null, ImmutableList.builder().add("xxx").build(), ImmutableMap.builder().put("yyy", "zzz").build()); assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1"); @@ -64,7 +63,7 @@ public class TagAsyncClientTest extends BaseAWSEC2AsyncClientTestbuilder().add("xxx").build(), ImmutableMap.builder().put("yyy", "zzz").build()); assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1"); @@ -80,8 +79,8 @@ public class TagAsyncClientTest extends BaseAWSEC2AsyncClientTestof()); + Method method = TagAsyncClient.class.getMethod("describeTagsInRegion", String.class, Multimap.class); + HttpRequest request = processor.createRequest(method, null, ImmutableMultimap.of()); assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1"); assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n"); @@ -96,9 +95,8 @@ public class TagAsyncClientTest extends BaseAWSEC2AsyncClientTestbuilder().add("one").add("two").build())).build()); + Method method = TagAsyncClient.class.getMethod("describeTagsInRegion", String.class, Multimap.class); + HttpRequest request = processor.createRequest(method, null, ImmutableMultimap.builder().put(FilterName.KEY, "one").put(FilterName.KEY, "two").build()); assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1"); assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n"); @@ -117,5 +115,4 @@ public class TagAsyncClientTest extends BaseAWSEC2AsyncClientTest>() { }; } - } diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/TagClientLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/TagClientLiveTest.java index ea6d933ce4..9dd1ccc25e 100644 --- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/TagClientLiveTest.java +++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/TagClientLiveTest.java @@ -30,8 +30,8 @@ import org.jclouds.aws.ec2.AWSEC2AsyncClient; import org.jclouds.aws.ec2.AWSEC2Client; import org.jclouds.aws.ec2.domain.AWSRunningInstance; import org.jclouds.aws.ec2.domain.Tag; -import org.jclouds.aws.ec2.domain.TagFilter; -import org.jclouds.aws.ec2.domain.TagFilter.FilterName; +import org.jclouds.aws.ec2.util.TagFilters.FilterName; +import org.jclouds.aws.ec2.util.TagFilters.ResourceType; import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContextFactory; import org.jclouds.logging.log4j.config.Log4JLoggingModule; @@ -44,6 +44,7 @@ import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.inject.Module; @@ -110,7 +111,7 @@ public class TagClientLiveTest { cleanupTag(testGroup, "test-key"); try { client.createTagsInRegion(null, ImmutableList.builder().add(testGroup).build(), ImmutableMap.builder().put("test-key", "test-value").build()); - checkTag(testGroup, TagFilter.ResourceType.SECURITY_GROUP.value(), "test-key", "test-value"); + checkTag(testGroup, ResourceType.SECURITY_GROUP, "test-key", "test-value"); } finally { cleanupTag(testGroup, "test-key"); } @@ -124,12 +125,12 @@ public class TagClientLiveTest { } } - protected void checkTag(String resourceId, String resourceType, String key, String value) { - Set results = client.describeTagsInRegion(null, ImmutableList.builder() - .add(new TagFilter(FilterName.RESOURCE_ID, ImmutableList.builder().add(resourceId).build())) - .add(new TagFilter(FilterName.RESOURCE_TYPE, ImmutableList.builder().add(resourceType).build())) - .add(new TagFilter(FilterName.KEY, ImmutableList.builder().add(key).build())) - .add(new TagFilter(FilterName.VALUE, ImmutableList.builder().add(value).build())) + protected void checkTag(String resourceId, ResourceType resourceType, String key, String value) { + Set results = client.describeTagsInRegion(null, ImmutableMultimap.builder() + .put(FilterName.RESOURCE_ID, resourceId) + .put(FilterName.RESOURCE_TYPE, resourceType) + .put(FilterName.KEY, key) + .put(FilterName.VALUE, value) .build()); assertNotNull(results); assertEquals(results.size(), 1);