• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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.dns;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 
21 import com.google.api.core.ApiFunction;
22 import com.google.api.services.dns.model.Change;
23 import com.google.cloud.StringEnumType;
24 import com.google.cloud.StringEnumValue;
25 import com.google.common.base.Function;
26 import com.google.common.base.MoreObjects;
27 import com.google.common.collect.ImmutableList;
28 import com.google.common.collect.Lists;
29 import java.io.Serializable;
30 import java.util.LinkedList;
31 import java.util.List;
32 import java.util.Objects;
33 import org.threeten.bp.Instant;
34 import org.threeten.bp.ZoneOffset;
35 import org.threeten.bp.format.DateTimeFormatter;
36 
37 /**
38  * A class representing an atomic update to a collection of {@link RecordSet}s within a {@code
39  * Zone}.
40  *
41  * @see <a href="https://cloud.google.com/dns/api/v1/changes">Google Cloud DNS documentation</a>
42  */
43 public class ChangeRequestInfo implements Serializable {
44 
45   static final Function<Change, ChangeRequestInfo> FROM_PB_FUNCTION =
46       new Function<Change, ChangeRequestInfo>() {
47         @Override
48         public ChangeRequestInfo apply(Change pb) {
49           return ChangeRequestInfo.fromPb(pb);
50         }
51       };
52   private static final long serialVersionUID = -6029143477639439169L;
53   private final List<RecordSet> additions;
54   private final List<RecordSet> deletions;
55   private final String generatedId;
56   private final Long startTimeMillis;
57   private final ChangeRequestInfo.Status status;
58 
59   /**
60    * This enumerates the possible states of a change request.
61    *
62    * @see <a href="https://cloud.google.com/dns/api/v1/changes#resource">Google Cloud DNS
63    *     documentation</a>
64    */
65   public static final class Status extends StringEnumValue {
66     private static final long serialVersionUID = -294992980062438246L;
67 
68     private static final ApiFunction<String, Status> CONSTRUCTOR =
69         new ApiFunction<String, Status>() {
70           @Override
71           public Status apply(String constant) {
72             return new Status(constant);
73           }
74         };
75 
76     private static final StringEnumType<Status> type =
77         new StringEnumType(Status.class, CONSTRUCTOR);
78 
79     public static final Status PENDING = type.createAndRegister("PENDING");
80     public static final Status DONE = type.createAndRegister("DONE");
81 
Status(String constant)82     private Status(String constant) {
83       super(constant);
84     }
85 
86     /**
87      * Get the Status for the given String constant, and throw an exception if the constant is not
88      * recognized.
89      */
valueOfStrict(String constant)90     public static Status valueOfStrict(String constant) {
91       return type.valueOfStrict(constant);
92     }
93 
94     /** Get the Status for the given String constant, and allow unrecognized values. */
valueOf(String constant)95     public static Status valueOf(String constant) {
96       return type.valueOf(constant);
97     }
98 
99     /** Return the known values for Status. */
values()100     public static Status[] values() {
101       return type.values();
102     }
103   }
104 
105   /** A builder for {@code ChangeRequestInfo}. */
106   public abstract static class Builder {
107 
108     /**
109      * Sets a collection of {@link RecordSet}s which are to be added to the zone upon executing this
110      * {@code ChangeRequestInfo}.
111      */
setAdditions(List<RecordSet> additions)112     public abstract Builder setAdditions(List<RecordSet> additions);
113 
114     /**
115      * Sets a collection of {@link RecordSet}s which are to be deleted from the zone upon executing
116      * this {@code ChangeRequestInfo}.
117      */
setDeletions(List<RecordSet> deletions)118     public abstract Builder setDeletions(List<RecordSet> deletions);
119 
120     /**
121      * Adds a {@link RecordSet} to be <strong>added</strong> to the zone upon executing this {@code
122      * ChangeRequestInfo}.
123      */
add(RecordSet recordSet)124     public abstract Builder add(RecordSet recordSet);
125 
126     /**
127      * Adds a {@link RecordSet} to be <strong>deleted</strong> to the zone upon executing this
128      * {@code ChangeRequestInfo}.
129      */
delete(RecordSet recordSet)130     public abstract Builder delete(RecordSet recordSet);
131 
132     /**
133      * Clears the collection of {@link RecordSet}s which are to be added to the zone upon executing
134      * this {@code ChangeRequestInfo}.
135      */
clearAdditions()136     public abstract Builder clearAdditions();
137 
138     /**
139      * Clears the collection of {@link RecordSet}s which are to be deleted from the zone upon
140      * executing this {@code ChangeRequestInfo}.
141      */
clearDeletions()142     public abstract Builder clearDeletions();
143 
144     /**
145      * Removes a single {@link RecordSet} from the collection of records to be
146      * <strong>added</strong> to the zone upon executing this {@code ChangeRequestInfo}.
147      */
removeAddition(RecordSet recordSet)148     public abstract Builder removeAddition(RecordSet recordSet);
149 
150     /**
151      * Removes a single {@link RecordSet} from the collection of records to be
152      * <strong>deleted</strong> from the zone upon executing this {@code ChangeRequestInfo}.
153      */
removeDeletion(RecordSet recordSet)154     public abstract Builder removeDeletion(RecordSet recordSet);
155 
156     /** Associates a service-generated id to this {@code ChangeRequestInfo}. */
setGeneratedId(String generatedId)157     abstract Builder setGeneratedId(String generatedId);
158 
159     /** Sets the time when this change request was started by a server. */
setStartTime(long startTimeMillis)160     abstract Builder setStartTime(long startTimeMillis);
161 
162     /** Sets the current status of this {@code ChangeRequest}. */
setStatus(ChangeRequest.Status status)163     abstract Builder setStatus(ChangeRequest.Status status);
164 
165     /**
166      * Creates a {@code ChangeRequestInfo} instance populated by the values associated with this
167      * builder.
168      */
build()169     public abstract ChangeRequestInfo build();
170   }
171 
172   static class BuilderImpl extends Builder {
173     private List<RecordSet> additions;
174     private List<RecordSet> deletions;
175     private String generatedId;
176     private Long startTimeMillis;
177     private ChangeRequestInfo.Status status;
178 
BuilderImpl()179     BuilderImpl() {
180       this.additions = new LinkedList<>();
181       this.deletions = new LinkedList<>();
182     }
183 
BuilderImpl(ChangeRequestInfo info)184     BuilderImpl(ChangeRequestInfo info) {
185       this.additions = Lists.newLinkedList(info.getAdditions());
186       this.deletions = Lists.newLinkedList(info.getDeletions());
187       this.generatedId = info.generatedId;
188       this.startTimeMillis = info.startTimeMillis;
189       this.status = info.status;
190     }
191 
192     @Override
setAdditions(List<RecordSet> additions)193     public Builder setAdditions(List<RecordSet> additions) {
194       this.additions = Lists.newLinkedList(checkNotNull(additions));
195       return this;
196     }
197 
198     @Override
setDeletions(List<RecordSet> deletions)199     public Builder setDeletions(List<RecordSet> deletions) {
200       this.deletions = Lists.newLinkedList(checkNotNull(deletions));
201       return this;
202     }
203 
204     @Override
add(RecordSet recordSet)205     public Builder add(RecordSet recordSet) {
206       this.additions.add(checkNotNull(recordSet));
207       return this;
208     }
209 
210     @Override
delete(RecordSet recordSet)211     public Builder delete(RecordSet recordSet) {
212       this.deletions.add(checkNotNull(recordSet));
213       return this;
214     }
215 
216     @Override
clearAdditions()217     public Builder clearAdditions() {
218       this.additions.clear();
219       return this;
220     }
221 
222     @Override
clearDeletions()223     public Builder clearDeletions() {
224       this.deletions.clear();
225       return this;
226     }
227 
228     @Override
removeAddition(RecordSet recordSet)229     public Builder removeAddition(RecordSet recordSet) {
230       this.additions.remove(recordSet);
231       return this;
232     }
233 
234     @Override
removeDeletion(RecordSet recordSet)235     public Builder removeDeletion(RecordSet recordSet) {
236       this.deletions.remove(recordSet);
237       return this;
238     }
239 
240     @Override
build()241     public ChangeRequestInfo build() {
242       return new ChangeRequestInfo(this);
243     }
244 
245     @Override
setGeneratedId(String generatedId)246     Builder setGeneratedId(String generatedId) {
247       this.generatedId = checkNotNull(generatedId);
248       return this;
249     }
250 
251     @Override
setStartTime(long startTimeMillis)252     Builder setStartTime(long startTimeMillis) {
253       this.startTimeMillis = startTimeMillis;
254       return this;
255     }
256 
257     @Override
setStatus(ChangeRequestInfo.Status status)258     Builder setStatus(ChangeRequestInfo.Status status) {
259       this.status = checkNotNull(status);
260       return this;
261     }
262   }
263 
ChangeRequestInfo(BuilderImpl builder)264   ChangeRequestInfo(BuilderImpl builder) {
265     this.additions = ImmutableList.copyOf(builder.additions);
266     this.deletions = ImmutableList.copyOf(builder.deletions);
267     this.generatedId = builder.generatedId;
268     this.startTimeMillis = builder.startTimeMillis;
269     this.status = builder.status;
270   }
271 
272   /** Returns an empty builder for the {@code ChangeRequestInfo} class. */
newBuilder()273   public static Builder newBuilder() {
274     return new BuilderImpl();
275   }
276 
277   /** Creates a builder populated with values of this {@code ChangeRequestInfo}. */
toBuilder()278   public Builder toBuilder() {
279     return new BuilderImpl(this);
280   }
281 
282   /**
283    * Returns the list of {@link RecordSet}s to be added to the zone upon submitting this change
284    * request.
285    */
getAdditions()286   public List<RecordSet> getAdditions() {
287     return additions;
288   }
289 
290   /**
291    * Returns the list of {@link RecordSet}s to be deleted from the zone upon submitting this change
292    * request.
293    */
getDeletions()294   public List<RecordSet> getDeletions() {
295     return deletions;
296   }
297 
298   /** Returns the service-generated id for this change request. */
getGeneratedId()299   public String getGeneratedId() {
300     return generatedId;
301   }
302 
303   /** Returns the time when this change request was started by the server. */
getStartTimeMillis()304   public Long getStartTimeMillis() {
305     return startTimeMillis;
306   }
307 
308   /**
309    * Returns the status of this change request. If the change request has not been applied yet, the
310    * status is {@code PENDING}.
311    */
status()312   public ChangeRequestInfo.Status status() {
313     return getStatus();
314   }
315 
316   /**
317    * Returns the status of this change request. If the change request has not been applied yet, the
318    * status is {@code PENDING}.
319    */
getStatus()320   public ChangeRequestInfo.Status getStatus() {
321     return status;
322   }
323 
toPb()324   Change toPb() {
325     Change pb = new Change();
326     // set id
327     if (getGeneratedId() != null) {
328       pb.setId(getGeneratedId());
329     }
330     // set timestamp
331     if (getStartTimeMillis() != null) {
332       pb.setStartTime(
333           DateTimeFormatter.ISO_DATE_TIME
334               .withZone(ZoneOffset.UTC)
335               .format(Instant.ofEpochMilli(getStartTimeMillis())));
336     }
337     // set status
338     if (status() != null) {
339       pb.setStatus(status().name().toLowerCase());
340     }
341     // set a list of additions
342     pb.setAdditions(Lists.transform(getAdditions(), RecordSet.TO_PB_FUNCTION));
343     // set a list of deletions
344     pb.setDeletions(Lists.transform(getDeletions(), RecordSet.TO_PB_FUNCTION));
345     return pb;
346   }
347 
fromPb(Change pb)348   static ChangeRequestInfo fromPb(Change pb) {
349     Builder builder = newBuilder();
350     if (pb.getId() != null) {
351       builder.setGeneratedId(pb.getId());
352     }
353     if (pb.getStartTime() != null) {
354       builder.setStartTime(
355           DateTimeFormatter.ISO_DATE_TIME.parse(pb.getStartTime(), Instant.FROM).toEpochMilli());
356     }
357     if (pb.getStatus() != null) {
358       // we are assuming that status indicated in pb is a lower case version of the enum name
359       builder.setStatus(ChangeRequest.Status.valueOf(pb.getStatus().toUpperCase()));
360     }
361     if (pb.getDeletions() != null) {
362       builder.setDeletions(Lists.transform(pb.getDeletions(), RecordSet.FROM_PB_FUNCTION));
363     }
364     if (pb.getAdditions() != null) {
365       builder.setAdditions(Lists.transform(pb.getAdditions(), RecordSet.FROM_PB_FUNCTION));
366     }
367     return builder.build();
368   }
369 
370   @Override
equals(Object obj)371   public boolean equals(Object obj) {
372     return obj == this
373         || obj != null
374             && obj.getClass().equals(ChangeRequestInfo.class)
375             && toPb().equals(((ChangeRequestInfo) obj).toPb());
376   }
377 
378   @Override
hashCode()379   public int hashCode() {
380     return Objects.hash(additions, deletions, generatedId, startTimeMillis, status);
381   }
382 
383   @Override
toString()384   public String toString() {
385     return MoreObjects.toStringHelper(this)
386         .add("additions", additions)
387         .add("deletions", deletions)
388         .add("generatedId", generatedId)
389         .add("startTimeMillis", startTimeMillis)
390         .add("status", status)
391         .toString();
392   }
393 }
394