package com.heb.storm.risk;
import static backtype.storm.utils.Utils.tuple;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import org.mortbay.log.Log;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.BasicOutputCollector;
import backtype.storm.topology.IBasicBolt;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import com.heb.finance.analytics.model.RiskSensitivity;
import com.heb.storm.risk.cql.CassandraCqlBolt;
@SuppressWarnings("serial")
public class RiskHierarchyAggregator implements IBasicBolt {
// String will contain <hier, map<sub_hier, <sens, double>>>>
private Map<String, Map<String, Map<String, Double>>> aggregatesByRiskType;
private long count = 0;
@SuppressWarnings("rawtypes")
public void prepare(Map stormConf, TopologyContext context) {
this.aggregatesByRiskType = new HashMap<String, Map<String, Map<String, Double>>>();
}
public void execute(Tuple input, BasicOutputCollector collector) {
RiskSensitivity riskSensitivity = (RiskSensitivity) input.getValues().get(0);
if (++count % 1000 == 0) {
Log.info("Processed " + count);
}
String hier = riskSensitivity.getPath();
String subHier = riskSensitivity.getPosition();
//Populate the maps
addHierValue(riskSensitivity, hier, subHier);
//First process the new value
collector.emit(tuple(CassandraCqlBolt.HIERARCHY, hier, subHier, riskSensitivity.getName(), riskSensitivity.getValue().doubleValue()));
//Process all levels of the hierarchy
while (hier.contains(RiskSensitivity.SEPARATOR)) {
subHier= hier.substring(hier.lastIndexOf(RiskSensitivity.SEPARATOR) + 1);
hier = hier.substring(0, hier.lastIndexOf(RiskSensitivity.SEPARATOR));
double aggregate = addHierValue(riskSensitivity, hier, subHier);
collector.emit(tuple(CassandraCqlBolt.HIERARCHY, hier, subHier, riskSensitivity.getName(), aggregate));
}
}
private double addHierValue(RiskSensitivity riskSensitivity, String hier, String subHier) {
double aggregate = 0;
Map<String, Map<String, Double>> subHierMap;
Map<String, Double> riskSensitivities;;
// Check for the hierarchy path
if (this.aggregatesByRiskType.containsKey(hier)) {
subHierMap = this.aggregatesByRiskType.get(hier);
if (subHierMap.containsKey(subHier)) {
riskSensitivities = subHierMap.get(subHier);
// Check for the name
if (riskSensitivities.containsKey(riskSensitivity.getName())) {
Double originalValue = riskSensitivities.get(riskSensitivity.getName());
aggregate = riskSensitivity.getValue().doubleValue() + originalValue.doubleValue();
riskSensitivities.put(riskSensitivity.getName(), aggregate);
} else {
riskSensitivities.put(riskSensitivity.getName(), riskSensitivity.getValue().doubleValue());
}
} else {
riskSensitivities = new HashMap<String, Double>();
riskSensitivities.put(riskSensitivity.getName(), riskSensitivity.getValue().doubleValue());
subHierMap.put(subHier, riskSensitivities);
}
} else {
//Create new maps to hold values
subHierMap = new HashMap<String, Map<String, Double>>();
riskSensitivities = new HashMap<String, Double>();
aggregate = riskSensitivity.getValue().doubleValue();
riskSensitivities.put(riskSensitivity.getName(), aggregate);
subHierMap.put(subHier, riskSensitivities);
this.aggregatesByRiskType.put(hier, subHierMap);
}
return aggregate;
}
public void cleanup() {
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("Type", "hierarchy_path", "sub_path", "risk_sensitivity", "aggregate"));
}
@Override
public Map<String, Object> getComponentConfiguration() {
return null;
}
}