package storm.applications.bolt; import backtype.storm.tuple.Fields; import backtype.storm.tuple.Tuple; import backtype.storm.tuple.Values; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import static storm.applications.constants.ClickAnalyticsConstants.*; /** * User: domenicosolazzo */ public class GeoStatsBolt extends AbstractBolt { private Map<String, CountryStats> stats; @Override public void initialize() { stats = new HashMap<>(); } @Override public void execute(Tuple input) { String country = input.getStringByField(Field.COUNTRY); String city = input.getStringByField(Field.CITY); if (!stats.containsKey(country)) { stats.put(country, new CountryStats(country)); } stats.get(country).cityFound(city); collector.emit(input, new Values(country, stats.get(country).getCountryTotal(), city, stats.get(country).getCityTotal(city))); collector.ack(input); } @Override public Fields getDefaultFields() { return new Fields(Field.COUNTRY, Field.COUNTRY_TOTAL, Field.CITY, Field.CITY_TOTAL); } private class CountryStats { private int countryTotal = 0; private static final int COUNT_INDEX = 0; private static final int PERCENTAGE_INDEX = 1; private final String countryName; private final Map<String, List<Integer>> cityStats = new HashMap<>(); public CountryStats(String countryName) { this.countryName = countryName; } public void cityFound(String cityName) { countryTotal++; if (cityStats.containsKey(cityName)) { cityStats.get(cityName).set(COUNT_INDEX, cityStats.get(cityName).get(COUNT_INDEX) + 1 ); } else { List<Integer> list = new LinkedList<>(); list.add(1); list.add(0); cityStats.put(cityName, list); } double percent = (double)cityStats.get(cityName).get(COUNT_INDEX)/(double)countryTotal; cityStats.get(cityName).set(PERCENTAGE_INDEX, (int) percent); } public int getCountryTotal() { return countryTotal; } public int getCityTotal(String cityName) { return cityStats.get(cityName).get(COUNT_INDEX); } @Override public String toString() { return "Total Count for " + countryName + " is " + Integer.toString(countryTotal) + "\n" + "Cities: " + cityStats.toString(); } } }