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

denominator.dynect.GeoResourceRecordSetsDecoder Maven / Gradle / Ivy

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

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
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 com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonIOException;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;

import denominator.model.ResourceRecordSet;
import denominator.model.ResourceRecordSet.Builder;
import denominator.model.profile.Geo;
import denominator.model.profile.Weighted;

class GeoResourceRecordSetsDecoder implements DynECTDecoder.Parser>>> {

    private final Gson gson;
    private final ToBuilders toBuilders;

    @Inject
    GeoResourceRecordSetsDecoder(Gson gson, @Named("geo") final Map> regions) {
        this.gson = gson;
        this.toBuilders = new ToBuilders(regions);
    }

    private static final TypeToken> GEO_TOKEN = new TypeToken>() {
    };

    public Map>> apply(JsonReader reader) throws IOException {
        List geoServices;
        try {
            geoServices = gson.fromJson(reader, GEO_TOKEN.getType());
        } catch (JsonIOException e) {
            if (e.getCause() != null && e.getCause() instanceof IOException) {
                throw IOException.class.cast(e.getCause());
            }
            throw e;
        }
        Map>> rrsets = new LinkedHashMap>>();
        for (GeoService geo : geoServices) {
            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());
                    }
                }
            }
        }
        return rrsets;
    }

    private static class GeoService {
        List nodes = new ArrayList();
        List groups = new ArrayList();
    }

    private class Node {
        String zone;
        String fqdn;
    }

    private static class GeoRegionGroup {
        String service_name;
        String name;
        // aaaa_weight
        Map> weight = new LinkedHashMap>();
        List countries = new ArrayList();
        // spf_rdata
        Map> rdata = new LinkedHashMap>();
        // dhcid_ttl
        Map ttl = new LinkedHashMap();
    }

    private static class ToBuilders {
        private final Map> regions;
        private final Map countryToRegions;

        private ToBuilders(@Named("geo") final 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.addProfile(geo);
                // weight is only present for a couple record types
                List weights = creepyGeoRegionGroup.weight.get(type.toLowerCase() + "_weight");
                if (weights != null && !weights.isEmpty())
                    rrset.addProfile(Weighted.create(weights.get(0)));

                for (int i = 0; i < entry.getValue().size(); i++) {
                    rrset.add(ToRecord.toRData(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 - 2025 Weber Informatics LLC | Privacy Policy