package au.gov.amsa.geo.distance;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import au.gov.amsa.geo.model.Cell;
import rx.Observable.Operator;
import rx.Subscriber;
public final class OperatorSumCellDistances
implements Operator<Map<Cell, Double>, CellAndDistance> {
private static final int INITIAL_CAPACITY = 100000;
/**
* This takes about 100 bytes per entry of memory;
*/
private Map<Cell, Double> map = createMap();
private final int maxSize;
private OperatorSumCellDistances(int maxSize) {
this.maxSize = maxSize;
}
public static OperatorSumCellDistances create(int maxSize) {
return new OperatorSumCellDistances(maxSize);
}
@Override
public Subscriber<? super CellAndDistance> call(
final Subscriber<? super Map<Cell, Double>> child) {
Subscriber<CellAndDistance> parent = new Subscriber<CellAndDistance>(child) {
@Override
public void onCompleted() {
try {
child.onNext(Collections.unmodifiableMap(map));
child.onCompleted();
} catch (Throwable t) {
onError(t);
}
}
@Override
public void onError(Throwable e) {
child.onError(e);
}
@Override
public void onNext(CellAndDistance cd) {
Cell key = cd.getCell();
Double val = map.putIfAbsent(key, cd.getDistanceNm());
if (val != null) {
map.put(key, val + cd.getDistanceNm());
request(1);
} else {
if (map.size() == maxSize) {
Map<Cell, Double> m = map;
map = createMap();
child.onNext(Collections.unmodifiableMap(m));
} else
request(1);
}
}
};
return parent;
}
private static Map<Cell, Double> createMap() {
return new HashMap<Cell, Double>(INITIAL_CAPACITY, 1.0f);
}
}