package com.ctrip.platform.dal.dao; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; public interface ResultMerger<T> { void addPartial(String shard, T partial) throws SQLException; T merge() throws SQLException; static class IntSummary implements ResultMerger<Integer>{ private int total; @Override public void addPartial(String shard, Integer partial) { total += partial.intValue(); } @Override public Integer merge() { return total; } } static class LongSummary implements ResultMerger<Long>{ private long total; @Override public void addPartial(String shard, Long partial) { total += partial.longValue(); } @Override public Long merge() { return total; } } static class DoubleSummary implements ResultMerger<Double>{ private double total; @Override public void addPartial(String shard, Double partial) { total += partial.doubleValue(); } @Override public Double merge() { return total; } } static class BigIntegerSummary implements ResultMerger<BigInteger>{ private BigInteger total; @Override public void addPartial(String shard, BigInteger partial) { if(total == null) total = partial; else total.add(partial); } @Override public BigInteger merge() { return total; } } static class BigDecimalSummary implements ResultMerger<BigDecimal>{ private BigDecimal total; @Override public void addPartial(String shard, BigDecimal partial) { if(total == null) total = partial; else total.add(partial); } @Override public BigDecimal merge() { return total; } } static class IntAverage implements ResultMerger<Map<String, Number>>{ private int count; private int sum; private String countColumn; private String sumColumn; private String averageColumn; public IntAverage() {this("count", "sum", "average");} public IntAverage(String countColumn, String sumColumn, String averageColumn) { this.countColumn = countColumn; this.sumColumn = sumColumn; this.averageColumn = averageColumn; } @Override public void addPartial(String shard, Map<String, Number> partial) { count += partial.get(countColumn).intValue(); sum += partial.get(sumColumn).intValue(); } @Override public Map<String, Number> merge() { Map<String, Number> result = new HashMap<>(); result.put(countColumn, count); result.put(sumColumn, sum); result.put(averageColumn, sum/count); return result; } } static class LongAverage implements ResultMerger<Map<String, Number>>{ private int count; private long sum; private String countColumn; private String sumColumn; private String averageColumn; public LongAverage() {this("count", "sum", "average");} public LongAverage(String countColumn, String sumColumn, String averageColumn) { this.countColumn = countColumn; this.sumColumn = sumColumn; this.averageColumn = averageColumn; } @Override public void addPartial(String shard, Map<String, Number> partial) { count += partial.get(countColumn).intValue(); sum += partial.get(sumColumn).longValue(); } @Override public Map<String, Number> merge() { Map<String, Number> result = new HashMap<>(); result.put(countColumn, count); result.put(sumColumn, sum); result.put(averageColumn, sum/count); return result; } } static class DoubleAverage implements ResultMerger<Map<String, Number>>{ private int count; private double sum; private String countColumn; private String sumColumn; private String averageColumn; public DoubleAverage() {this("count", "sum", "average");} public DoubleAverage(String countColumn, String sumColumn, String averageColumn) { this.countColumn = countColumn; this.sumColumn = sumColumn; this.averageColumn = averageColumn; } @Override public void addPartial(String shard, Map<String, Number> partial) { count += partial.get(countColumn).intValue(); sum += partial.get(sumColumn).doubleValue(); } @Override public Map<String, Number> merge() { Map<String, Number> result = new HashMap<>(); result.put(countColumn, count); result.put(sumColumn, sum); result.put(averageColumn, sum/count); return result; } } static class BigIntegerAverage implements ResultMerger<Map<String, Number>>{ private int count; private BigInteger sum; private String countColumn; private String sumColumn; private String averageColumn; public BigIntegerAverage() {this("count", "sum", "average");} public BigIntegerAverage(String countColumn, String sumColumn, String averageColumn) { this.countColumn = countColumn; this.sumColumn = sumColumn; this.averageColumn = averageColumn; } @Override public void addPartial(String shard, Map<String, Number> partial) { count += partial.get(countColumn).intValue(); if(sum == null) sum = (BigInteger)partial.get(sumColumn); else sum.add((BigInteger)partial.get(sumColumn)); } @Override public Map<String, Number> merge() { Map<String, Number> result = new HashMap<>(); result.put(countColumn, count); result.put(sumColumn, sum); result.put(averageColumn, sum.divide(new BigInteger(String.valueOf(count)))); return result; } } static class BigDecimalAverage implements ResultMerger<Map<String, Number>>{ private int count; private BigDecimal sum; private String countColumn; private String sumColumn; private String averageColumn; public BigDecimalAverage() {this("count", "sum", "average");} public BigDecimalAverage(String countColumn, String sumColumn, String averageColumn) { this.countColumn = countColumn; this.sumColumn = sumColumn; this.averageColumn = averageColumn; } @Override public void addPartial(String shard, Map<String, Number> partial) { count += partial.get(countColumn).intValue(); if(sum == null) sum = (BigDecimal)partial.get(sumColumn); else sum.add((BigDecimal)partial.get(sumColumn)); } @Override public Map<String, Number> merge() { Map<String, Number> result = new HashMap<>(); result.put(countColumn, count); result.put(sumColumn, sum); result.put(averageColumn, sum.divide(new BigDecimal(String.valueOf(count)))); return result; } } }