diff --git a/gcloud-java-core/src/main/java/com/google/cloud/AsyncPage.java b/gcloud-java-core/src/main/java/com/google/cloud/AsyncPage.java index d82d46f19b2d..8d7ff026e70d 100644 --- a/gcloud-java-core/src/main/java/com/google/cloud/AsyncPage.java +++ b/gcloud-java-core/src/main/java/com/google/cloud/AsyncPage.java @@ -37,7 +37,7 @@ * for (T value : page.values()) { * // do something with value * } - * page = page.nextPage().get(); + * page = page.nextPageAsync().get(); * }} * * @param the value type that the page holds @@ -45,7 +45,8 @@ public interface AsyncPage extends Page { /** - * Returns a {@link Future} object for the next page. + * Returns a {@link Future} object for the next page. {@link Future#get()} returns {@code null} if + * the last page has been reached. */ Future> nextPageAsync(); } diff --git a/gcloud-java-core/src/main/java/com/google/cloud/AsyncPageImpl.java b/gcloud-java-core/src/main/java/com/google/cloud/AsyncPageImpl.java index 42af7b34a943..706316e362cd 100644 --- a/gcloud-java-core/src/main/java/com/google/cloud/AsyncPageImpl.java +++ b/gcloud-java-core/src/main/java/com/google/cloud/AsyncPageImpl.java @@ -17,6 +17,7 @@ package com.google.cloud; import com.google.common.base.Throwables; +import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Uninterruptibles; import java.io.Serializable; @@ -47,7 +48,7 @@ private static class SyncNextPageFetcher implements PageImpl.NextPageFetcher< private static final long serialVersionUID = -4124568632363525351L; - private NextPageFetcher asyncPageFetcher; + private final NextPageFetcher asyncPageFetcher; private SyncNextPageFetcher(NextPageFetcher asyncPageFetcher) { this.asyncPageFetcher = asyncPageFetcher; @@ -75,7 +76,7 @@ public AsyncPageImpl(NextPageFetcher asyncPageFetcher, String cursor, Iterabl @Override public Future> nextPageAsync() { if (nextPageCursor() == null || asyncPageFetcher == null) { - return null; + return Futures.immediateCheckedFuture(null); } return asyncPageFetcher.nextPage(); } diff --git a/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/PubSub.java b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/PubSub.java index 2695cd0064e8..3410d3f54a3e 100644 --- a/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/PubSub.java +++ b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/PubSub.java @@ -194,9 +194,9 @@ public static PullOption maxConcurrentCallbacks(int maxConcurrency) { Future> listSubscriptionsAsync(ListOption... options); - Page listSubscriptions(String topic, ListOption... options); + Page listSubscriptions(String topic, ListOption... options); - Future> listSubscriptionsAsync(String topic, ListOption... options); + Future> listSubscriptionsAsync(String topic, ListOption... options); Iterator pull(String subscription, PullOption... options); diff --git a/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/PubSubImpl.java b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/PubSubImpl.java index df6aa283c1a3..17a99842259f 100644 --- a/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/PubSubImpl.java +++ b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/PubSubImpl.java @@ -185,12 +185,12 @@ public Future> listSubscriptionsAsync(ListOption... opti } @Override - public Page listSubscriptions(String topic, ListOption... options) { + public Page listSubscriptions(String topic, ListOption... options) { return null; } @Override - public Future> listSubscriptionsAsync(String topic, + public Future> listSubscriptionsAsync(String topic, ListOption... options) { return null; } diff --git a/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/Subscription.java b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/Subscription.java index effa3b59ef0c..11efb5971aa2 100644 --- a/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/Subscription.java +++ b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/Subscription.java @@ -50,8 +50,20 @@ private Builder(Subscription subscription) { } @Override - public Builder topic(String name) { - delegate.topic(name); + public Builder topic(TopicId topic) { + delegate.topic(topic); + return this; + } + + @Override + public Builder topic(String project, String topic) { + delegate.topic(project, topic); + return this; + } + + @Override + public Builder topic(String topic) { + delegate.topic(topic); return this; } diff --git a/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/SubscriptionId.java b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/SubscriptionId.java new file mode 100644 index 000000000000..d083ecd04f26 --- /dev/null +++ b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/SubscriptionId.java @@ -0,0 +1,89 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.pubsub; + +import static com.google.cloud.pubsub.spi.v1.SubscriberApi.parseProjectFromSubscriptionName; +import static com.google.cloud.pubsub.spi.v1.SubscriberApi.parseSubscriptionFromSubscriptionName; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.MoreObjects; + +import java.io.Serializable; +import java.util.Objects; + +/** + * Identity for a Google PubSub subscription. {@code SubscriptionId} objects are returned by the + * {@link PubSub#listSubscriptions(String, PubSub.ListOption...)} and + * {@link PubSub#listSubscriptionsAsync(String, PubSub.ListOption...)} methods as a topic may have + * subscriptions from different projects. + */ +public class SubscriptionId implements Serializable { + + private static final long serialVersionUID = 6507142968866856283L; + + private final String project; + private final String subscription; + + SubscriptionId(String project, String subscription) { + this.project = checkNotNull(project); + this.subscription = checkNotNull(subscription); + } + + /** + * Returns the name of the project where the subscription resides. + */ + public String project() { + return project; + } + + /** + * Returns the name of the subscription. + */ + public String subscription() { + return subscription; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("project", project) + .add("subscription", subscription).toString(); + } + + @Override + public final int hashCode() { + return Objects.hash(project, subscription); + } + + @Override + public final boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof SubscriptionId)) { + return false; + } + SubscriptionId other = (SubscriptionId) obj; + return Objects.equals(project, other.project) + && Objects.equals(subscription, other.subscription); + } + + static SubscriptionId fromPb(String pb) { + return new SubscriptionId(parseProjectFromSubscriptionName(pb), + parseSubscriptionFromSubscriptionName(pb)); + } +} diff --git a/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/SubscriptionInfo.java b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/SubscriptionInfo.java index 4ec97ca7d3f7..3c8722d6e6f9 100644 --- a/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/SubscriptionInfo.java +++ b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/SubscriptionInfo.java @@ -18,7 +18,6 @@ import static com.google.common.base.Preconditions.checkNotNull; -import com.google.cloud.pubsub.spi.v1.PublisherApi; import com.google.cloud.pubsub.spi.v1.SubscriberApi; import com.google.common.base.MoreObjects; @@ -53,7 +52,7 @@ public class SubscriptionInfo implements Serializable { private static final long serialVersionUID = 1860057426574127128L; private final String name; - private final String topic; + private final TopicId topic; private final PushConfig pushConfig; private final int ackDeadlineSeconds; @@ -72,9 +71,22 @@ public abstract static class Builder { public abstract Builder name(String name); /** - * Sets the name of the topic the subscription refers to. + * Sets the topic the subscription refers to, given the topic name. The topic is assumed to + * reside in the {@link PubSubOptions#projectId()} project. */ - public abstract Builder topic(String name); + public abstract Builder topic(String topic); + + /** + * Sets the topic the subscription refers to, given the project and topic names. + */ + public abstract Builder topic(String project, String topic); + + /** + * Sets the topic the subscription refers to, given the topic identity. If + * {@code topic.project()} is {@code null} the topic is assumed to reside in the + * {@link PubSubOptions#projectId()} project. + */ + public abstract Builder topic(TopicId topic); /** * Sets the push configuration for the subscription. If set, the subscription will be in @@ -104,11 +116,11 @@ public abstract static class Builder { static final class BuilderImpl extends Builder { private String name; - private String topic; + private TopicId topic; private PushConfig pushConfig; private int ackDeadlineSeconds; - private BuilderImpl(String topic, String name) { + private BuilderImpl(TopicId topic, String name) { this.topic = checkNotNull(topic); this.name = checkNotNull(name); } @@ -126,8 +138,18 @@ public Builder name(String name) { return this; } + @Override + public Builder topic(String project, String topic) { + return topic(TopicId.of(checkNotNull(project), topic)); + } + @Override public Builder topic(String topic) { + return topic(TopicId.of(topic)); + } + + @Override + public Builder topic(TopicId topic) { this.topic = checkNotNull(topic); return this; } @@ -158,9 +180,12 @@ public SubscriptionInfo build() { } /** - * Returns the name of the topic this subscription refers to. + * Returns the identity of the topic this subscription refers to. If {@link TopicId#project()} is + * {@code null} the topic is assumed to reside in the {@link PubSubOptions#projectId()} project. + * After a topic is deleted, existing subscriptions to that topic are not deleted, but their topic + * field is set to {@link TopicId#deletedTopic()}. */ - public String topic() { + public TopicId topic() { return topic; } @@ -231,7 +256,7 @@ public String toString() { com.google.pubsub.v1.Subscription toPb(String projectId) { com.google.pubsub.v1.Subscription.Builder builder = com.google.pubsub.v1.Subscription.newBuilder(); - builder.setTopic(PublisherApi.formatTopicName(projectId, topic)); + builder.setTopic(topic.toPb(projectId)); builder.setName(SubscriberApi.formatSubscriptionName(projectId, name)); builder.setAckDeadlineSeconds(ackDeadlineSeconds); if (pushConfig != null) { @@ -241,7 +266,7 @@ com.google.pubsub.v1.Subscription toPb(String projectId) { } static SubscriptionInfo fromPb(com.google.pubsub.v1.Subscription subscription) { - Builder builder = builder(PublisherApi.parseTopicFromTopicName(subscription.getTopic()), + Builder builder = builder(TopicId.fromPb(subscription.getTopic()), SubscriberApi.parseSubscriptionFromSubscriptionName(subscription.getName())); builder.ackDeadLineSeconds(subscription.getAckDeadlineSeconds()); // A subscription with an "empty" push config is a pull subscription @@ -261,29 +286,46 @@ public Builder toBuilder() { /** * Creates a pull {@code SubscriptionInfo} object given the name of the topic and the name of the - * subscription. + * subscription. The topic is assumed to reside in the {@link PubSubOptions#projectId()} project. * * @param topic the name of the topic the subscription refers to * @param name the name of the subscription. The name must start with a letter, and contain only * letters ({@code [A-Za-z]}), numbers ({@code [0-9]}), dashes ({@code -}), underscores * ({@code _}), periods ({@code .}), tildes ({@code ~}), plus ({@code +}) or percent signs * ({@code %}). It must be between 3 and 255 characters in length and cannot begin with the - * string {@code goog} + * string {@code goog}. */ public static SubscriptionInfo of(String topic, String name) { return builder(topic, name).build(); } + /** + * Creates a pull {@code SubscriptionInfo} object given the identity of the topic and the name of + * the subscription. If {@code topic.project()} is {@code null} the topic is assumed to reside in + * the {@link PubSubOptions#projectId()} project. + * + * @param topic the identity of the topic the subscription refers to + * @param name the name of the subscription. The name must start with a letter, and contain only + * letters ({@code [A-Za-z]}), numbers ({@code [0-9]}), dashes ({@code -}), underscores + * ({@code _}), periods ({@code .}), tildes ({@code ~}), plus ({@code +}) or percent signs + * ({@code %}). It must be between 3 and 255 characters in length and cannot begin with the + * string {@code goog}. + */ + public static SubscriptionInfo of(TopicId topic, String name) { + return builder(topic, name).build(); + } + /** * Creates a push {@code SubscriptionInfo} object given the name of the topic, the name of the - * subscription and the push endpoint. + * subscription and the push endpoint. The topic is assumed to reside in the + * {@link PubSubOptions#projectId()} project. * * @param topic the name of the topic the subscription refers to * @param name the name of the subscription. The name must start with a letter, and contain only * letters ({@code [A-Za-z]}), numbers ({@code [0-9]}), dashes ({@code -}), underscores * ({@code _}), periods ({@code .}), tildes ({@code ~}), plus ({@code +}) or percent signs * ({@code %}). It must be between 3 and 255 characters in length and cannot begin with the - * string {@code goog} + * string {@code goog}. * @param endpoint a URL locating the endpoint to which messages should be pushed. For example, * an endpoint might use {@code https://example.com/push}. */ @@ -291,18 +333,53 @@ public static SubscriptionInfo of(String topic, String name, String endpoint) { return builder(topic, name).pushConfig(PushConfig.of(endpoint)).build(); } + /** + * Creates a push {@code SubscriptionInfo} object given the identity of the topic, the name of the + * subscription and the push endpoint. If {@code topic.project()} is {@code null} the topic is + * assumed to reside in the {@link PubSubOptions#projectId()} project. + * + * @param topic the identity of the topic the subscription refers to + * @param name the name of the subscription. The name must start with a letter, and contain only + * letters ({@code [A-Za-z]}), numbers ({@code [0-9]}), dashes ({@code -}), underscores + * ({@code _}), periods ({@code .}), tildes ({@code ~}), plus ({@code +}) or percent signs + * ({@code %}). It must be between 3 and 255 characters in length and cannot begin with the + * string {@code goog}. + * @param endpoint a URL locating the endpoint to which messages should be pushed. For example, + * an endpoint might use {@code https://example.com/push}. + */ + public static SubscriptionInfo of(TopicId topic, String name, String endpoint) { + return builder(topic, name).pushConfig(PushConfig.of(endpoint)).build(); + } + /** * Creates a builder for {@code SubscriptionInfo} objects given the name of the topic and the name - * of the subscription. + * of the subscription. The topic is assumed to reside in the {@link PubSubOptions#projectId()} + * project. * * @param topic the name of the topic the subscription refers to * @param name the name of the subscription. The name must start with a letter, and contain only * letters ({@code [A-Za-z]}), numbers ({@code [0-9]}), dashes ({@code -}), underscores * ({@code _}), periods ({@code .}), tildes ({@code ~}), plus ({@code +}) or percent signs * ({@code %}). It must be between 3 and 255 characters in length and cannot begin with the - * string {@code goog} + * string {@code goog}. */ public static Builder builder(String topic, String name) { + return builder(TopicId.of(topic), name); + } + + /** + * Creates a builder for {@code SubscriptionInfo} objects given the identity of the topic and the + * name of the subscription. If {@code topic.project()} is {@code null} the topic is assumed to + * reside in the {@link PubSubOptions#projectId()} project. + * + * @param topic the identity of the topic the subscription refers to + * @param name the name of the subscription. The name must start with a letter, and contain only + * letters ({@code [A-Za-z]}), numbers ({@code [0-9]}), dashes ({@code -}), underscores + * ({@code _}), periods ({@code .}), tildes ({@code ~}), plus ({@code +}) or percent signs + * ({@code %}). It must be between 3 and 255 characters in length and cannot begin with the + * string {@code goog}. + */ + public static Builder builder(TopicId topic, String name) { return new BuilderImpl(topic, name); } } diff --git a/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/Topic.java b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/Topic.java index f2203d3a30d9..4c08e485bb9d 100644 --- a/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/Topic.java +++ b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/Topic.java @@ -133,11 +133,11 @@ public Future> publishAsync(Iterable messages) { return pubsub.publishAsync(name(), messages); } - public Page listSubscriptions(ListOption... options) { + public Page listSubscriptions(ListOption... options) { return pubsub.listSubscriptions(name(), options); } - public Future> listSubscriptionsAsync(ListOption... options) { + public Future> listSubscriptionsAsync(ListOption... options) { return pubsub.listSubscriptionsAsync(name(), options); } diff --git a/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/TopicId.java b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/TopicId.java new file mode 100644 index 000000000000..a86d7ad84977 --- /dev/null +++ b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/TopicId.java @@ -0,0 +1,138 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.pubsub; + +import static com.google.cloud.pubsub.spi.v1.PublisherApi.formatTopicName; +import static com.google.cloud.pubsub.spi.v1.PublisherApi.parseProjectFromTopicName; +import static com.google.cloud.pubsub.spi.v1.PublisherApi.parseTopicFromTopicName; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.base.MoreObjects; + +import java.io.Serializable; +import java.util.Objects; + +/** + * Identity for a Google PubSub topic. A {@code TopicId} object can be used to create subscriptions + * for topics that possibly reside in different projects. + */ +public final class TopicId implements Serializable { + + private static final long serialVersionUID = -4913169763174877777L; + private static final String DELETED_TOPIC_NAME = "_deleted_topic_"; + private static final TopicId DELETED_TOPIC = new TopicId(null, DELETED_TOPIC_NAME, true); + + private final String project; + private final String topic; + private final boolean isDeleted; + + private TopicId(String project, String topic, boolean isDeleted) { + this.project = project; + this.topic = checkNotNull(topic); + this.isDeleted = isDeleted; + } + + private TopicId(String project, String topic) { + this(project, topic, false); + } + + /** + * Returns the name of the project where the topic resides. If {@code null} the topic is assumed + * to reside in the {@link PubSubOptions#projectId()} project. + */ + public String project() { + return project; + } + + /** + * Returns the name of the topic. + */ + public String topic() { + return topic; + } + + /** + * Returns {@code true} if this object is the identity of a deleted topic, {@code false} + * otherwhise. If {@code isDeleted()} is {@code true}, {@link #topic()} returns + * "{@code _deleted_topic_}" and {@link #project()} returns {@code null}. + */ + public boolean isDeleted() { + return isDeleted; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("project", project) + .add("topic", topic) + .add("isDeleted", isDeleted) + .toString(); + } + + @Override + public int hashCode() { + return Objects.hash(project, topic, isDeleted); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof TopicId)) { + return false; + } + TopicId other = (TopicId) obj; + return Objects.equals(project, other.project) + && Objects.equals(topic, other.topic) + && Objects.equals(isDeleted, other.isDeleted); + } + + String toPb(String projectId) { + return formatTopicName(project != null ? project : projectId, topic); + } + + /** + * Returns the identity of a deleted topic. The deleted topic is such that {@link #isDeleted()} + * returns {@code true}, {@link #topic()} returns "{@code _is_deleted_}" and {@link #project()} + * returns {@code null}. + */ + public static TopicId deletedTopic() { + return DELETED_TOPIC; + } + + /** + * Returns a topic identity given the topic name. + */ + public static TopicId of(String topic) { + return new TopicId(null, topic); + } + + /** + * Returns a topic identity given project and topic names. + */ + public static TopicId of(String project, String topic) { + return new TopicId(project, topic); + } + + static TopicId fromPb(String pb) { + if (Objects.equals(pb, DELETED_TOPIC_NAME)) { + return DELETED_TOPIC; + } + return TopicId.of(parseProjectFromTopicName(pb), parseTopicFromTopicName(pb)); + } +} diff --git a/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/TopicInfo.java b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/TopicInfo.java index acc5fbbd41ee..8c90a0c2705d 100644 --- a/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/TopicInfo.java +++ b/gcloud-java-pubsub/src/main/java/com/google/cloud/pubsub/TopicInfo.java @@ -140,7 +140,7 @@ public Builder toBuilder() { * ({@code [A-Za-z]}), numbers ({@code [0-9]}), dashes ({@code -}), underscores ({@code _}), * periods ({@code .}), tildes ({@code ~}), plus ({@code +}) or percent signs ({@code %}). * It must be between 3 and 255 characters in length and cannot begin with the string - * {@code goog} + * {@code goog}. */ public static TopicInfo of(String name) { return builder(name).build(); @@ -153,7 +153,7 @@ public static TopicInfo of(String name) { * ({@code [A-Za-z]}), numbers ({@code [0-9]}), dashes ({@code -}), underscores ({@code _}), * periods ({@code .}), tildes ({@code ~}), plus ({@code +}) or percent signs ({@code %}). * It must be between 3 and 255 characters in length and cannot begin with the string - * {@code goog} + * {@code goog}. */ public static Builder builder(String name) { return new BuilderImpl(name); diff --git a/gcloud-java-pubsub/src/test/java/com/google/cloud/pubsub/SubscriptionIdTest.java b/gcloud-java-pubsub/src/test/java/com/google/cloud/pubsub/SubscriptionIdTest.java new file mode 100644 index 000000000000..ef7e4a8cd8dd --- /dev/null +++ b/gcloud-java-pubsub/src/test/java/com/google/cloud/pubsub/SubscriptionIdTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.pubsub; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class SubscriptionIdTest { + + private static final String PROJECT = "project"; + private static final String NAME = "subscription"; + private static final String TOPIC_PB = "projects/project/subscriptions/subscription"; + private static final SubscriptionId SUBSCRIPTION_ID = new SubscriptionId(PROJECT, NAME); + + @Test + public void testConstructor() { + assertEquals(PROJECT, SUBSCRIPTION_ID.project()); + assertEquals(NAME, SUBSCRIPTION_ID.subscription()); + } + + @Test + public void testToAndFromPb() { + SubscriptionId subscriptionId = SubscriptionId.fromPb(TOPIC_PB); + compareSubscriptionId(SUBSCRIPTION_ID, subscriptionId); + assertEquals(PROJECT, subscriptionId.project()); + assertEquals(NAME, subscriptionId.subscription()); + } + + private void compareSubscriptionId(SubscriptionId expected, SubscriptionId value) { + assertEquals(expected, value); + assertEquals(expected.project(), value.project()); + assertEquals(expected.subscription(), value.subscription()); + assertEquals(expected.hashCode(), value.hashCode()); + } +} diff --git a/gcloud-java-pubsub/src/test/java/com/google/cloud/pubsub/SubscriptionInfoTest.java b/gcloud-java-pubsub/src/test/java/com/google/cloud/pubsub/SubscriptionInfoTest.java index 574d40e39ce2..be832a9c8994 100644 --- a/gcloud-java-pubsub/src/test/java/com/google/cloud/pubsub/SubscriptionInfoTest.java +++ b/gcloud-java-pubsub/src/test/java/com/google/cloud/pubsub/SubscriptionInfoTest.java @@ -23,7 +23,7 @@ public class SubscriptionInfoTest { - private static final String TOPIC = "topic"; + private static final TopicId TOPIC = TopicId.of("project", "topic"); private static final String NAME = "subscription"; private static final String ENDPOINT = "https://example.com/push"; private static final PushConfig PUSH_CONFIG = PushConfig.of(ENDPOINT); @@ -40,7 +40,7 @@ public void testToBuilder() { .topic("newTopic") .name("newSubscription") .build(); - assertEquals("newTopic", subscriptionInfo.topic()); + assertEquals(TopicId.of("newTopic"), subscriptionInfo.topic()); assertEquals("newSubscription", subscriptionInfo.name()); subscriptionInfo = subscriptionInfo.toBuilder().name(NAME).topic(TOPIC).build(); compareSubscriptionInfo(SUBSCRIPTION_INFO, subscriptionInfo); @@ -52,6 +52,23 @@ public void testBuilder() { assertEquals(NAME, SUBSCRIPTION_INFO.name()); assertEquals(PUSH_CONFIG, SUBSCRIPTION_INFO.pushConfig()); assertEquals(ACK_DEADLINE, SUBSCRIPTION_INFO.ackDeadlineSeconds()); + SubscriptionInfo subscriptionInfo = SubscriptionInfo.builder("topic", "subscription").build(); + assertEquals(TopicId.of("topic"), subscriptionInfo.topic()); + assertEquals(NAME, subscriptionInfo.name()); + assertNull(subscriptionInfo.pushConfig()); + assertEquals(0, subscriptionInfo.ackDeadlineSeconds()); + subscriptionInfo = SubscriptionInfo.builder("topic", "subscription") + .topic("project", "topic").build(); + assertEquals(TOPIC, subscriptionInfo.topic()); + assertEquals(NAME, subscriptionInfo.name()); + assertNull(subscriptionInfo.pushConfig()); + assertEquals(0, subscriptionInfo.ackDeadlineSeconds()); + subscriptionInfo = SubscriptionInfo.builder("topic", "subscription") + .topic(TOPIC).build(); + assertEquals(TOPIC, subscriptionInfo.topic()); + assertEquals(NAME, subscriptionInfo.name()); + assertNull(subscriptionInfo.pushConfig()); + assertEquals(0, subscriptionInfo.ackDeadlineSeconds()); } @Test @@ -61,11 +78,21 @@ public void testOf() { assertEquals(NAME, subscriptionInfo.name()); assertNull(subscriptionInfo.pushConfig()); assertEquals(0, subscriptionInfo.ackDeadlineSeconds()); + subscriptionInfo = SubscriptionInfo.of("topic", NAME); + assertEquals(TopicId.of("topic"), subscriptionInfo.topic()); + assertEquals(NAME, subscriptionInfo.name()); + assertNull(subscriptionInfo.pushConfig()); + assertEquals(0, subscriptionInfo.ackDeadlineSeconds()); subscriptionInfo = SubscriptionInfo.of(TOPIC, NAME, ENDPOINT); assertEquals(TOPIC, subscriptionInfo.topic()); assertEquals(NAME, subscriptionInfo.name()); assertEquals(PushConfig.of(ENDPOINT), subscriptionInfo.pushConfig()); assertEquals(0, subscriptionInfo.ackDeadlineSeconds()); + subscriptionInfo = SubscriptionInfo.of("topic", NAME, ENDPOINT); + assertEquals(TopicId.of("topic"), subscriptionInfo.topic()); + assertEquals(NAME, subscriptionInfo.name()); + assertEquals(PushConfig.of(ENDPOINT), subscriptionInfo.pushConfig()); + assertEquals(0, subscriptionInfo.ackDeadlineSeconds()); } @Test @@ -75,9 +102,22 @@ public void testToAndFromPb() { SubscriptionInfo subscriptionInfo = SubscriptionInfo.of(TOPIC, NAME); compareSubscriptionInfo(subscriptionInfo, SubscriptionInfo.fromPb(subscriptionInfo.toPb("project"))); + subscriptionInfo = SubscriptionInfo.of("topic", NAME); + compareSubscriptionInfo(SubscriptionInfo.of(TOPIC, NAME), + SubscriptionInfo.fromPb(subscriptionInfo.toPb("project"))); subscriptionInfo = SubscriptionInfo.of(TOPIC, NAME, ENDPOINT); compareSubscriptionInfo(subscriptionInfo, SubscriptionInfo.fromPb(subscriptionInfo.toPb("project"))); + subscriptionInfo = SubscriptionInfo.of("topic", NAME, ENDPOINT); + compareSubscriptionInfo(SubscriptionInfo.of(TOPIC, NAME, ENDPOINT), + SubscriptionInfo.fromPb(subscriptionInfo.toPb("project"))); + com.google.pubsub.v1.Subscription subscription = SUBSCRIPTION_INFO.toPb("project"); + subscriptionInfo = + SubscriptionInfo.fromPb(subscription.toBuilder().setTopic("_deleted_topic_").build()); + assertEquals(TopicId.deletedTopic(), subscriptionInfo.topic()); + assertEquals(NAME, subscriptionInfo.name()); + assertEquals(PUSH_CONFIG, subscriptionInfo.pushConfig()); + assertEquals(ACK_DEADLINE, subscriptionInfo.ackDeadlineSeconds()); } private void compareSubscriptionInfo(SubscriptionInfo expected, SubscriptionInfo value) { diff --git a/gcloud-java-pubsub/src/test/java/com/google/cloud/pubsub/TopicIdTest.java b/gcloud-java-pubsub/src/test/java/com/google/cloud/pubsub/TopicIdTest.java new file mode 100644 index 000000000000..a75732709be9 --- /dev/null +++ b/gcloud-java-pubsub/src/test/java/com/google/cloud/pubsub/TopicIdTest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2016 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.pubsub; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class TopicIdTest { + + private static final String PROJECT = "project"; + private static final String NAME = "topic"; + private static final String TOPIC_PB = "projects/project/topics/topic"; + + @Test + public void testOf() { + TopicId topicId = TopicId.of(PROJECT, NAME); + assertEquals(PROJECT, topicId.project()); + assertEquals(NAME, topicId.topic()); + topicId = TopicId.of(NAME); + assertNull(topicId.project()); + assertEquals(NAME, topicId.topic()); + assertFalse(topicId.isDeleted()); + } + + @Test + public void testDeletedTopic() { + TopicId deletedTopic = TopicId.deletedTopic(); + assertNull(deletedTopic.project()); + assertEquals("_deleted_topic_", deletedTopic.topic()); + assertTrue(deletedTopic.isDeleted()); + assertSame(deletedTopic, TopicId.deletedTopic()); + } + + @Test + public void testToAndFromPb() { + TopicId topicId = TopicId.of(PROJECT, NAME); + String topicPb = topicId.toPb("otherProject"); + assertEquals(TOPIC_PB, topicPb); + compareTopicId(topicId, TopicId.fromPb(topicPb)); + topicId = TopicId.of(NAME); + topicPb = topicId.toPb("otherProject"); + assertEquals("projects/otherProject/topics/topic", topicPb); + compareTopicId(TopicId.of("otherProject", NAME), TopicId.fromPb(topicPb)); + } + + private void compareTopicId(TopicId expected, TopicId value) { + assertEquals(expected, value); + assertEquals(expected.project(), value.project()); + assertEquals(expected.topic(), value.topic()); + assertEquals(expected.isDeleted(), value.isDeleted()); + assertEquals(expected.toPb("project"), value.toPb("project")); + assertEquals(expected.hashCode(), value.hashCode()); + } +}