package denominator.mock;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentSkipListSet;
import denominator.model.ResourceRecordSet;
import denominator.model.Zone;
import denominator.model.rdata.SOAData;
import static denominator.common.Preconditions.checkState;
import static denominator.common.Util.filter;
import static denominator.model.ResourceRecordSets.nameAndTypeEqualTo;
import static denominator.model.ResourceRecordSets.ns;
import static denominator.model.ResourceRecordSets.soa;
import static denominator.model.Zones.nameEqualTo;
import static java.util.Arrays.asList;
final class MockZoneApi implements denominator.ZoneApi {
private static final Comparator<ResourceRecordSet<?>> TO_STRING =
new Comparator<ResourceRecordSet<?>>() {
@Override
public int compare(ResourceRecordSet<?> arg0, ResourceRecordSet<?> arg1) {
return arg0.toString().compareTo(arg1.toString());
}
};
private final Map<String, Collection<ResourceRecordSet<?>>> data;
MockZoneApi(Map<String, Collection<ResourceRecordSet<?>>> data) {
this.data = data;
put(Zone.create("denominator.io.", "denominator.io.", 86400, "nil@denominator.io."));
}
@Override
public Iterator<Zone> iterator() {
final Iterator<Entry<String, Collection<ResourceRecordSet<?>>>>
delegate = data.entrySet().iterator();
return new Iterator<Zone>() {
@Override
public boolean hasNext() {
return delegate.hasNext();
}
@Override
public Zone next() {
Entry<String, Collection<ResourceRecordSet<?>>> next = delegate.next();
String name = next.getKey();
Iterator<ResourceRecordSet<?>> soas =
filter(next.getValue().iterator(), nameAndTypeEqualTo(name, "SOA"));
checkState(soas.hasNext(), "SOA record for zone %s was not present", name);
ResourceRecordSet<SOAData> soa = (ResourceRecordSet<SOAData>) soas.next();
SOAData soaData = soa.records().get(0);
return Zone.create(name, name, soa.ttl(), soaData.rname());
}
@Override
public void remove() {
throw new UnsupportedOperationException("remove");
}
};
}
@Override
public Iterator<Zone> iterateByName(String name) {
return filter(iterator(), nameEqualTo(name));
}
@Override
public String put(Zone zone) {
if (!data.containsKey(zone.name())) {
Collection<ResourceRecordSet<?>>
recordsInZone =
new ConcurrentSkipListSet<ResourceRecordSet<?>>(TO_STRING);
SOAData soaData = SOAData.builder().mname("ns1." + zone.name()).rname(zone.email())
.serial(1).refresh(3600).retry(600).expire(604800).minimum(86400).build();
recordsInZone.add(ResourceRecordSet.builder()
.type("SOA")
.name(zone.name())
.ttl(zone.ttl())
.add(soaData)
.build());
recordsInZone.add(ns(zone.name(), zone.ttl(), asList("ns1." + zone.name())));
data.put(zone.name(), recordsInZone);
return zone.name();
}
for (Iterator<ResourceRecordSet<?>> i = data.get(zone.name()).iterator(); i.hasNext();) {
ResourceRecordSet<?> rrset = i.next();
if (rrset.type().equals("SOA")) {
SOAData soaData = (SOAData) rrset.records().get(0);
if (zone.email().equals(soaData.rname()) && zone.ttl() == rrset.ttl().intValue()) {
return zone.name();
}
i.remove();
data.get(zone.name()).add(soa(rrset, zone.email(), zone.ttl()));
}
}
return zone.name();
}
@Override
public void delete(String name) {
data.remove(name);
}
}