All Downloads are FREE. Search and download functionalities are using the official Maven repository.

denominator.dynect.DynECTGeoResourceRecordSetApi Maven / Gradle / Ivy

There is a newer version: 4.7.1
Show newest version
package denominator.dynect;

import com.google.gson.JsonElement;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.inject.Inject;
import javax.inject.Named;

import dagger.Lazy;
import denominator.common.Filter;
import denominator.dynect.DynECT.GeoService;
import denominator.dynect.DynECT.GeoService.GeoRegionGroup;
import denominator.dynect.DynECT.GeoService.Node;
import denominator.model.ResourceRecordSet;
import denominator.model.ResourceRecordSet.Builder;
import denominator.model.profile.Geo;
import denominator.model.profile.Weighted;
import denominator.profile.GeoResourceRecordSetApi;

import static denominator.common.Preconditions.checkNotNull;
import static denominator.common.Util.and;
import static denominator.common.Util.filter;
import static denominator.common.Util.nextOrNull;
import static denominator.model.ResourceRecordSets.nameAndTypeEqualTo;
import static denominator.model.ResourceRecordSets.nameEqualTo;
import static denominator.model.ResourceRecordSets.nameTypeAndQualifierEqualTo;

public final class DynECTGeoResourceRecordSetApi implements GeoResourceRecordSetApi {

  private static final Filter> IS_GEO = new Filter>() {
    @Override
    public boolean apply(ResourceRecordSet in) {
      return in != null && in.geo() != null;
    }
  };

  private final Map> regions;
  private final ToBuilders toBuilders;
  private final DynECT api;
  private final String zoneFQDN;

  DynECTGeoResourceRecordSetApi(Map> regions, DynECT api,
                                String zoneFQDN) {
    this.regions = regions;
    this.toBuilders = new ToBuilders(regions);
    this.api = api;
    this.zoneFQDN = zoneFQDN;
  }

  @Override
  public Map> supportedRegions() {
    return regions;
  }

  @Override
  public Iterator> iterator() {
    Map>>
        rrsets =
        new LinkedHashMap>>();
    for (GeoService geo : api.geoServices().data) {
      for (GeoRegionGroup geoGroup : geo.groups) {
        for (Builder rrset : toBuilders.apply(geoGroup)) {
          for (Node node : geo.nodes) {
            if (!rrsets.containsKey(node.zone)) {
              rrsets.put(node.zone, new ArrayList>());
            }
            rrsets.get(node.zone).add(rrset.name(node.fqdn).build());
          }
        }
      }
    }
    Collection> val = rrsets.get(zoneFQDN);
    return val != null ? val.iterator() : Collections.>emptyList().iterator();
  }

  @Override
  public Iterator> iterateByName(String name) {
    return filter(iterator(), and(nameEqualTo(name), IS_GEO));
  }

  @Override
  public Iterator> iterateByNameAndType(String name, String type) {
    return filter(iterator(), and(nameAndTypeEqualTo(name, type), IS_GEO));
  }

  @Override
  public ResourceRecordSet getByNameTypeAndQualifier(String name, String type,
                                                        String qualifier) {
    return nextOrNull(
        filter(iterator(), and(nameTypeAndQualifierEqualTo(name, type, qualifier), IS_GEO)));
  }

  @Override
  public void put(ResourceRecordSet rrset) {
    throw new UnsupportedOperationException();
  }

  @Override
  public void deleteByNameTypeAndQualifier(String name, String type, String qualifier) {
    throw new UnsupportedOperationException();
  }

  static final class Factory implements GeoResourceRecordSetApi.Factory {

    private final Map> regions;
    private final Lazy hasAllGeoPermissions;
    private final DynECT api;

    @Inject
    Factory(@Named("geo") Map> regions,
            @Named("hasAllGeoPermissions") Lazy hasAllGeoPermissions, DynECT api) {
      this.regions = regions;
      this.hasAllGeoPermissions = hasAllGeoPermissions;
      this.api = api;
    }

    @Override
    public GeoResourceRecordSetApi create(String idOrName) {
      checkNotNull(idOrName, "idOrName was null");
      if (!hasAllGeoPermissions.get()) {
        return null;
      }
      return new DynECTGeoResourceRecordSetApi(regions, api, idOrName);
    }
  }

  private static class ToBuilders {

    private final Map> regions;
    private final Map countryToRegions;

    private ToBuilders(Map> regions) {
      this.regions = regions;
      Map countryToRegions = new HashMap(regions.values().size());
      for (Entry> entry : regions.entrySet()) {
        for (String country : entry.getValue()) {
          countryToRegions.put(country, entry.getKey());
        }
      }
      this.countryToRegions = countryToRegions;
    }

    public List> apply(GeoRegionGroup creepyGeoRegionGroup) {
      List> rrsets = new ArrayList>();
      Geo geo = Geo.create(indexCountries(creepyGeoRegionGroup.countries));

      for (Entry> entry : creepyGeoRegionGroup.rdata.entrySet()) {
        if (entry.getValue().isEmpty()) {
          continue;
        }
        // ex. spf_rdata -> SPF
        String type = entry.getKey().substring(0, entry.getKey().indexOf('_')).toUpperCase();
        // ex. dhcid_ttl
        int ttl = creepyGeoRegionGroup.ttl.get(type.toLowerCase() + "_ttl");
        ResourceRecordSet.Builder> rrset = ResourceRecordSet.builder();
        rrset.type(type);
        rrset.qualifier(creepyGeoRegionGroup.name != null ? creepyGeoRegionGroup.name
                                                          : creepyGeoRegionGroup.service_name);
        rrset.ttl(ttl);
        rrset.geo(geo);
        // weight is only present for a couple record types
        List weights = creepyGeoRegionGroup.weight.get(type.toLowerCase() + "_weight");
        if (weights != null && !weights.isEmpty()) {
          rrset.weighted(Weighted.create(weights.get(0)));
        }

        for (int i = 0; i < entry.getValue().size(); i++) {
          rrset.add(ToRecord.toRData(type, entry.getValue().get(i).getAsJsonObject()));
        }
        rrsets.add(rrset);
      }
      return rrsets;
    }

    private Map> indexCountries(List countries) {
      Map> indexed = new LinkedHashMap>();
      for (String country : countries) {
        // special case the "all countries" condition
        if (regions.containsKey(country)) {
          indexed.put(country, Arrays.asList(country));
        } else if (countryToRegions.containsKey(country)) {
          String region = countryToRegions.get(country);
          if (!indexed.containsKey(region)) {
            indexed.put(region, new ArrayList());
          }
          indexed.get(region).add(country);
        } else {
          // TODO log not found
        }
      }
      return indexed;
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy