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.services.dns.model.Change; 22 import com.google.common.base.Function; 23 import java.io.IOException; 24 import java.io.ObjectInputStream; 25 import java.util.List; 26 import java.util.Objects; 27 28 /** 29 * An immutable class representing an atomic update to a collection of {@link RecordSet}s within a 30 * {@code Zone}. 31 * 32 * @see <a href="https://cloud.google.com/dns/api/v1/changes">Google Cloud DNS documentation</a> 33 */ 34 public class ChangeRequest extends ChangeRequestInfo { 35 36 private static final long serialVersionUID = 5335667200595081449L; 37 private final DnsOptions options; 38 private final String zone; 39 private transient Dns dns; 40 41 /** A builder for {@code ChangeRequest}s. */ 42 public static class Builder extends ChangeRequestInfo.Builder { 43 44 private final Dns dns; 45 private final String zone; 46 private final ChangeRequestInfo.BuilderImpl infoBuilder; 47 Builder(ChangeRequest cr)48 private Builder(ChangeRequest cr) { 49 this.dns = cr.dns; 50 this.zone = cr.zone; 51 this.infoBuilder = new ChangeRequestInfo.BuilderImpl(cr); 52 } 53 54 @Override setAdditions(List<RecordSet> additions)55 public Builder setAdditions(List<RecordSet> additions) { 56 infoBuilder.setAdditions(additions); 57 return this; 58 } 59 60 @Override setDeletions(List<RecordSet> deletions)61 public Builder setDeletions(List<RecordSet> deletions) { 62 infoBuilder.setDeletions(deletions); 63 return this; 64 } 65 66 @Override add(RecordSet recordSet)67 public Builder add(RecordSet recordSet) { 68 infoBuilder.add(recordSet); 69 return this; 70 } 71 72 @Override delete(RecordSet recordSet)73 public Builder delete(RecordSet recordSet) { 74 infoBuilder.delete(recordSet); 75 return this; 76 } 77 78 @Override clearAdditions()79 public Builder clearAdditions() { 80 infoBuilder.clearAdditions(); 81 return this; 82 } 83 84 @Override clearDeletions()85 public Builder clearDeletions() { 86 infoBuilder.clearDeletions(); 87 return this; 88 } 89 90 @Override removeAddition(RecordSet recordSet)91 public Builder removeAddition(RecordSet recordSet) { 92 infoBuilder.removeAddition(recordSet); 93 return this; 94 } 95 96 @Override removeDeletion(RecordSet recordSet)97 public Builder removeDeletion(RecordSet recordSet) { 98 infoBuilder.removeDeletion(recordSet); 99 return this; 100 } 101 102 @Override setGeneratedId(String generatedId)103 Builder setGeneratedId(String generatedId) { 104 infoBuilder.setGeneratedId(generatedId); 105 return this; 106 } 107 108 @Override setStartTime(long startTimeMillis)109 Builder setStartTime(long startTimeMillis) { 110 infoBuilder.setStartTime(startTimeMillis); 111 return this; 112 } 113 114 @Override setStatus(Status status)115 Builder setStatus(Status status) { 116 infoBuilder.setStatus(status); 117 return this; 118 } 119 120 @Override build()121 public ChangeRequest build() { 122 return new ChangeRequest(dns, zone, infoBuilder); 123 } 124 } 125 ChangeRequest(Dns dns, String zone, ChangeRequest.BuilderImpl infoBuilder)126 ChangeRequest(Dns dns, String zone, ChangeRequest.BuilderImpl infoBuilder) { 127 super(infoBuilder); 128 this.zone = checkNotNull(zone); 129 this.dns = checkNotNull(dns); 130 this.options = dns.getOptions(); 131 } 132 133 /** Returns the name of the {@link Zone} associated with this change request. */ getZone()134 public String getZone() { 135 return this.zone; 136 } 137 138 /** Returns the change request's {@code Dns} object used to issue requests. */ getDns()139 public Dns getDns() { 140 return dns; 141 } 142 143 /** 144 * Applies this change request to the zone identified by {@code zoneName}. 145 * 146 * @throws DnsException upon failure or if zone is not found 147 */ applyTo(String zoneName, Dns.ChangeRequestOption... options)148 public ChangeRequest applyTo(String zoneName, Dns.ChangeRequestOption... options) { 149 return dns.applyChangeRequest(zoneName, this, options); 150 } 151 152 /** 153 * Retrieves the up-to-date information about the change request from Google Cloud DNS. Parameter 154 * {@code options} can be used to restrict the fields to be included in the updated object the 155 * same way as in {@link Dns#getChangeRequest(String, String, Dns.ChangeRequestOption...)}. If 156 * {@code options} are provided, any field other than generatedId which is not included in the 157 * {@code options} will be {@code null} regardless of whether they are initialized or not in 158 * {@code this} instance. 159 * 160 * @return an object with the updated information or {@code null} if it does not exist 161 * @throws DnsException upon failure of the API call or if the associated zone was not found 162 */ reload(Dns.ChangeRequestOption... options)163 public ChangeRequest reload(Dns.ChangeRequestOption... options) { 164 return dns.getChangeRequest(zone, getGeneratedId(), options); 165 } 166 167 /** 168 * Returns {@code true} if the change request has been completed. If the status is not {@link 169 * ChangeRequestInfo.Status#DONE} already, the method makes an API call to Google Cloud DNS to 170 * update the change request first. 171 * 172 * @throws DnsException upon failure of the API call or if the associated zone was not found 173 */ isDone()174 public boolean isDone() { 175 if (status() == Status.DONE) { 176 return true; 177 } 178 ChangeRequest updated = reload(Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.STATUS)); 179 return updated == null || updated.status() == Status.DONE; 180 } 181 182 @Override toBuilder()183 public Builder toBuilder() { 184 return new Builder(this); 185 } 186 187 @Override equals(Object obj)188 public final boolean equals(Object obj) { 189 if (obj == this) { 190 return true; 191 } 192 if (obj == null || !obj.getClass().equals(ChangeRequest.class)) { 193 return false; 194 } 195 ChangeRequest other = (ChangeRequest) obj; 196 return Objects.equals(toPb(), other.toPb()) 197 && Objects.equals(options, other.options) 198 && Objects.equals(zone, other.zone); 199 } 200 201 @Override hashCode()202 public final int hashCode() { 203 return Objects.hash(super.hashCode(), options, zone); 204 } 205 readObject(ObjectInputStream input)206 private void readObject(ObjectInputStream input) throws IOException, ClassNotFoundException { 207 input.defaultReadObject(); 208 this.dns = options.getService(); 209 } 210 fromPb(Dns dns, String zoneName, Change pb)211 static ChangeRequest fromPb(Dns dns, String zoneName, Change pb) { 212 ChangeRequestInfo info = ChangeRequestInfo.fromPb(pb); 213 return new ChangeRequest(dns, zoneName, new ChangeRequestInfo.BuilderImpl(info)); 214 } 215 fromPbFunction(final Dns dns, final String zoneName)216 static Function<Change, ChangeRequest> fromPbFunction(final Dns dns, final String zoneName) { 217 return new Function<Change, ChangeRequest>() { 218 @Override 219 public ChangeRequest apply(Change pb) { 220 return ChangeRequest.fromPb(dns, zoneName, pb); 221 } 222 }; 223 } 224 } 225