1 /* 2 * Copyright 2017 Google LLC 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.cloud.notification; 18 19 import static com.google.common.base.Preconditions.checkNotNull; 20 21 import com.google.api.services.storage.model.Notification; 22 import com.google.common.base.Function; 23 import com.google.common.base.MoreObjects; 24 import com.google.common.collect.ImmutableList; 25 import com.google.common.collect.ImmutableMap; 26 import com.google.pubsub.v1.ProjectTopicName; 27 import java.io.Serializable; 28 import java.util.List; 29 import java.util.Map; 30 import java.util.Objects; 31 32 /** 33 * Google Storage Notification metadata; 34 * 35 * @see <a href="https://cloud.google.com/storage/docs/concepts-techniques#concepts">Concepts and 36 * Terminology</a> 37 */ 38 public class NotificationInfo implements Serializable { 39 // TODO: Consider making this an AutoValue class. 40 41 private static final long serialVersionUID = 5725883368559753810L; 42 43 public enum PayloadFormat { 44 JSON_API_V1, 45 NONE 46 } 47 48 static final Function<Notification, NotificationInfo> FROM_PB_FUNCTION = 49 new Function<Notification, NotificationInfo>() { 50 @Override 51 public NotificationInfo apply(Notification pb) { 52 return NotificationInfo.fromPb(pb); 53 } 54 }; 55 static final Function<NotificationInfo, Notification> TO_PB_FUNCTION = 56 new Function<NotificationInfo, Notification>() { 57 @Override 58 public Notification apply(NotificationInfo NotificationInfo) { 59 return NotificationInfo.toPb(); 60 } 61 }; 62 private final String generatedId; 63 private final ProjectTopicName topic; 64 private final List<String> eventTypes; 65 private final Map<String, String> customAttributes; 66 private final PayloadFormat payloadFormat; 67 private final String objectNamePrefix; 68 private final String etag; 69 private final String selfLink; 70 71 public static final class Builder { 72 73 private String generatedId; 74 private ProjectTopicName topic; 75 private List<String> eventTypes; 76 private Map<String, String> customAttributes; 77 private PayloadFormat payloadFormat; 78 private String objectNamePrefix; 79 private String etag; 80 private String selfLink; 81 Builder(ProjectTopicName topic)82 Builder(ProjectTopicName topic) { 83 this.topic = topic; 84 } 85 Builder(NotificationInfo NotificationInfo)86 Builder(NotificationInfo NotificationInfo) { 87 generatedId = NotificationInfo.generatedId; 88 etag = NotificationInfo.etag; 89 selfLink = NotificationInfo.selfLink; 90 topic = NotificationInfo.topic; 91 eventTypes = NotificationInfo.eventTypes; 92 customAttributes = NotificationInfo.customAttributes; 93 payloadFormat = NotificationInfo.payloadFormat; 94 objectNamePrefix = NotificationInfo.objectNamePrefix; 95 } 96 setGeneratedId(String generatedId)97 Builder setGeneratedId(String generatedId) { 98 this.generatedId = generatedId; 99 return this; 100 } 101 setSelfLink(String selfLink)102 Builder setSelfLink(String selfLink) { 103 this.selfLink = selfLink; 104 return this; 105 } 106 setTopic(ProjectTopicName topic)107 public Builder setTopic(ProjectTopicName topic) { 108 this.topic = topic; 109 return this; 110 } 111 setPayloadFormat(PayloadFormat payloadFormat)112 public Builder setPayloadFormat(PayloadFormat payloadFormat) { 113 this.payloadFormat = payloadFormat; 114 return this; 115 } 116 117 /** GcpLaunchStage.Alpha */ setObjectNamePrefix(String objectNamePrefix)118 public Builder setObjectNamePrefix(String objectNamePrefix) { 119 this.objectNamePrefix = objectNamePrefix; 120 return this; 121 } 122 setEventTypes(Iterable<String> eventTypes)123 public Builder setEventTypes(Iterable<String> eventTypes) { 124 this.eventTypes = eventTypes != null ? ImmutableList.copyOf(eventTypes) : null; 125 return this; 126 } 127 setEtag(String etag)128 Builder setEtag(String etag) { 129 this.etag = etag; 130 return this; 131 } 132 setCustomAttributes(Map<String, String> customAttributes)133 public Builder setCustomAttributes(Map<String, String> customAttributes) { 134 this.customAttributes = 135 customAttributes != null ? ImmutableMap.copyOf(customAttributes) : null; 136 return this; 137 } 138 build()139 public NotificationInfo build() { 140 checkNotNull(topic); 141 return new NotificationInfo(this); 142 } 143 } 144 NotificationInfo(Builder builder)145 NotificationInfo(Builder builder) { 146 generatedId = builder.generatedId; 147 etag = builder.etag; 148 selfLink = builder.selfLink; 149 topic = builder.topic; 150 eventTypes = builder.eventTypes; 151 customAttributes = builder.customAttributes; 152 payloadFormat = builder.payloadFormat; 153 objectNamePrefix = builder.objectNamePrefix; 154 } 155 156 /** Returns the service-generated id for the notification. */ getGeneratedId()157 public String getGeneratedId() { 158 return generatedId; 159 } 160 161 /** Returns the Cloud PubSub topic to which this subscription publishes. */ getTopic()162 public ProjectTopicName getTopic() { 163 return topic; 164 } 165 166 /** Returns the canonical URI of this topic as a string. */ getSelfLink()167 public String getSelfLink() { 168 return selfLink; 169 } 170 171 /** Returns the desired content of the Payload. */ getPayloadFormat()172 public PayloadFormat getPayloadFormat() { 173 return payloadFormat; 174 } 175 176 /** Returns the object name prefix for which this notification configuration applies. */ getObjectNamePrefix()177 public String getObjectNamePrefix() { 178 return objectNamePrefix; 179 } 180 181 /** 182 * Returns HTTP 1.1 Entity tag for the notification. 183 * 184 * @see <a href="http://tools.ietf.org/html/rfc2616#section-3.11">Entity Tags</a> 185 */ getEtag()186 public String getEtag() { 187 return etag; 188 } 189 190 /** 191 * Returns the list of event types that this notification will apply to. If empty, notifications 192 * will be sent on all event types. 193 * 194 * @see <a href="https://cloud.google.com/storage/docs/cross-origin">Cross-Origin Resource Sharing 195 * (CORS)</a> 196 */ getEventTypes()197 public List<String> getEventTypes() { 198 return eventTypes; 199 } 200 201 /** 202 * Returns the list of additional attributes to attach to each Cloud PubSub message published for\ 203 * this notification subscription. 204 * 205 * @see <a href="https://cloud.google.com/storage/docs/access-control#About-Access-Control-Lists"> 206 * About Access Control Lists</a> 207 */ getCustomAttributes()208 public Map<String, String> getCustomAttributes() { 209 return customAttributes; 210 } 211 212 /** Returns a builder for the current notification. */ toBuilder()213 public Builder toBuilder() { 214 return new Builder(this); 215 } 216 217 @Override hashCode()218 public int hashCode() { 219 return Objects.hash(getTopic()); 220 } 221 222 @Override equals(Object obj)223 public boolean equals(Object obj) { 224 return obj == this 225 || obj != null 226 && obj.getClass().equals(NotificationInfo.class) 227 && Objects.equals(toPb(), ((NotificationInfo) obj).toPb()); 228 } 229 230 @Override toString()231 public String toString() { 232 return MoreObjects.toStringHelper(this).add("topic", getTopic()).toString(); 233 } 234 toPb()235 Notification toPb() { 236 Notification notificationPb = new Notification(); 237 notificationPb.setId(generatedId); 238 notificationPb.setEtag(etag); 239 if (customAttributes != null) { 240 notificationPb.setCustomAttributes(customAttributes); 241 } 242 if (eventTypes != null) { 243 notificationPb.setEventTypes(eventTypes); 244 } 245 if (objectNamePrefix != null) { 246 notificationPb.setObjectNamePrefix(objectNamePrefix); 247 } 248 if (payloadFormat != null) { 249 notificationPb.setPayloadFormat(payloadFormat.toString()); 250 } else { 251 notificationPb.setPayloadFormat(PayloadFormat.NONE.toString()); 252 } 253 notificationPb.setSelfLink(selfLink); 254 notificationPb.setTopic(topic.toString()); 255 256 return notificationPb; 257 } 258 259 /** Creates a {@code NotificationInfo} object for the provided topic name. */ of(ProjectTopicName topic)260 public static NotificationInfo of(ProjectTopicName topic) { 261 return newBuilder(topic).build(); 262 } 263 264 /** 265 * Returns a {@code NotificationInfo} builder where the topic's name is set to the provided name. 266 */ newBuilder(ProjectTopicName topic)267 public static Builder newBuilder(ProjectTopicName topic) { 268 return new Builder(topic); 269 } 270 fromPb(Notification notificationPb)271 static NotificationInfo fromPb(Notification notificationPb) { 272 Builder builder = newBuilder(ProjectTopicName.parse(notificationPb.getTopic())); 273 if (notificationPb.getId() != null) { 274 builder.setGeneratedId(notificationPb.getId()); 275 } 276 if (notificationPb.getEtag() != null) { 277 builder.setEtag(notificationPb.getEtag()); 278 } 279 if (notificationPb.getCustomAttributes() != null) { 280 builder.setCustomAttributes(notificationPb.getCustomAttributes()); 281 } 282 if (notificationPb.getSelfLink() != null) { 283 builder.setSelfLink(notificationPb.getSelfLink()); 284 } 285 if (notificationPb.getObjectNamePrefix() != null) { 286 builder.setObjectNamePrefix(notificationPb.getObjectNamePrefix()); 287 } 288 if (notificationPb.getTopic() != null) { 289 builder.setTopic(ProjectTopicName.parse(notificationPb.getTopic())); 290 } 291 if (notificationPb.getEventTypes() != null) { 292 builder.setEventTypes(notificationPb.getEventTypes()); 293 } 294 if (notificationPb.getPayloadFormat() != null) { 295 builder.setPayloadFormat(PayloadFormat.valueOf(notificationPb.getPayloadFormat())); 296 } 297 return builder.build(); 298 } 299 } 300