package ucar.nc2.util;
import java.util.*;
/**
* Count number of times a value appears.
* value may be string or int.
*
* @author caron
* @since 11/15/2014
*/
public class Counters {
List<Counter> counters = new ArrayList<>();
Map<String, Counter> map = new HashMap<>();
public Counter add(String name) {
CounterImpl c = new CounterImpl(name);
counters.add( c);
map.put(name, c);
return c;
}
public void show(Formatter f) {
for (Counter c : counters)
c.show(f);
}
public Counter get(String name) {
return map.get(name);
}
public void count(String name, Comparable value) {
CounterImpl counter = (CounterImpl) map.get(name);
counter.count(value);
}
/* public void countS(String name, String value) {
CounterOfString counter = (CounterOfString) map.get(name);
counter.count(value);
}
public void countO(String name, Comparable value) {
CounterOfObject counter = (CounterOfObject) map.get(name);
counter.count(value);
} */
public void addTo(Counters sub) {
for (Counter subC : sub.counters) {
Counter all = map.get(subC.getName());
all.addTo(subC);
}
}
public Counters makeSubCounters() {
Counters result = new Counters();
for (Counter c : counters) {
result.add(c.getName());
}
return result;
}
public static interface Counter {
public void show(Formatter f);
public String showRange();
public String getName();
public void addTo(Counter sub);
public int getUnique();
public Comparable getFirst();
public Comparable getLast();
public int getTotal();
public Counter setShowRange(boolean showRange);
}
private static class CounterImpl implements Counter {
protected String name;
protected boolean showRange;
private Comparable first, last;
public String getName() {
return name;
}
public Counter setShowRange(boolean showRange) {
this.showRange = showRange;
return this;
}
private Map<Comparable, Integer> set = new HashMap<>();
private String range;
public CounterImpl(String name) {
this.name = name;
}
public void count(Comparable value) {
Integer count = set.get(value);
if (count == null)
set.put(value, 1);
else
set.put(value, count + 1);
}
public void addTo(Counter sub) {
CounterImpl subs = (CounterImpl) sub;
for (Map.Entry<Comparable, Integer> entry : subs.set.entrySet()) {
Integer count = this.set.get(entry.getKey());
if (count == null)
count = 0;
set.put(entry.getKey(), count + entry.getValue());
}
}
public void show(Formatter f) {
java.util.List<Comparable> list = new ArrayList<>(set.keySet());
f.format("%n%s (%d)%n", name, list.size());
Collections.sort(list);
if (showRange) {
int n = list.size();
if (n == 0)
f.format("none%n");
else
f.format(" %10s - %10s: count = %d%n", list.get(0), list.get(n - 1), getUnique());
} else {
Comparable prev = null;
for (Comparable key : list) {
int count = set.get(key);
boolean isHashDup = (prev != null) && key.hashCode() == prev.hashCode();
boolean isNameDup = (prev != null) && key.toString().equals(prev.toString());
f.format(" %s %10s: count = %d%n", isHashDup != isNameDup ? "*" : " ", key, count);
prev = key;
}
}
}
public String showRange() {
if (range == null) {
java.util.List<Comparable> list = new ArrayList<>(set.keySet());
Collections.sort(list);
int n = list.size();
if (n == 0)
return "none";
Formatter f = new Formatter();
this.first = list.get(0);
this.last = list.get(n-1);
f.format("%10s - %10s", first, last);
range = f.toString();
}
return range;
}
@Override
public int getUnique() {
return set.size();
}
@Override
public Comparable getFirst() {
return first;
}
@Override
public Comparable getLast() {
return last;
}
@Override
public int getTotal() {
int total = 0;
for (Map.Entry<Comparable, Integer> entry : set.entrySet()) {
total += entry.getValue();
}
return total;
}
}
/* a counter whose keys are ints
public static class CounterOfInt extends CounterAbstract {
private Map<Integer, Integer> set = new HashMap<>();
public CounterOfInt(String name) {
this.name = name;
}
public void reset() {
set = new HashMap<>();
}
public void count(int value) {
Integer count = set.get(value);
if (count == null)
set.put(value, 1);
else
set.put(value, count + 1);
}
public void addTo(Counter sub) {
CounterOfInt subi = (CounterOfInt) sub;
for (Map.Entry<Integer, Integer> entry : subi.set.entrySet()) {
Integer count = this.set.get(entry.getKey());
if (count == null)
count = 0;
set.put(entry.getKey(), count + entry.getValue());
}
}
@Override
public int getUnique() {
return set.size();
}
@Override
public int getTotal() {
int total = 0;
for (Map.Entry<Integer, Integer> entry : set.entrySet()) {
total += entry.getValue();
}
return total;
}
public void show(Formatter f) {
f.format("%n%s%n", name);
java.util.List<Integer> list = new ArrayList<>(set.keySet());
Collections.sort(list);
for (int template : list) {
int count = set.get(template);
f.format(" %3d: count = %d%n", template, count);
}
}
}
// a counter whose keys are strings
public static class CounterOfString extends CounterAbstract {
private Map<String, Integer> set = new HashMap<>();
private String range;
public String getName() {
return name;
}
public CounterOfString(String name) {
this.name = name;
}
public void count(String value) {
Integer count = set.get(value);
if (count == null)
set.put(value, 1);
else
set.put(value, count + 1);
}
public void addTo(Counter sub) {
CounterOfString subs = (CounterOfString) sub;
for (Map.Entry<String, Integer> entry : subs.set.entrySet()) {
Integer count = this.set.get(entry.getKey());
if (count == null)
count = 0;
set.put(entry.getKey(), count + entry.getValue());
}
}
public void show(Formatter f) {
f.format("%n%s%n", name);
java.util.List<String> list = new ArrayList<>(set.keySet());
Collections.sort(list);
if (showRange) {
int n = list.size();
f.format(" %10s - %10s: count = %d%n", list.get(0), list.get(n-1), getUnique());
} else {
for (String key : list) {
int count = set.get(key);
f.format(" %10s: count = %d%n", key, count);
}
}
}
public String showRange() {
if (range == null) {
java.util.List<String> list = new ArrayList<>(set.keySet());
Collections.sort(list);
int n = list.size();
Formatter f = new Formatter();
f.format("%10s - %10s", list.get(0), list.get(n - 1));
range = f.toString();
}
return range;
}
@Override
public int getUnique() {
return set.size();
}
@Override
public int getTotal() {
int total = 0;
for (Map.Entry<String, Integer> entry : set.entrySet()) {
total += entry.getValue();
}
return total;
}
}
// a counter whose keys are Comparable objects
public static class CounterOfObject extends CounterAbstract {
private Map<Comparable, Integer> set = new HashMap<>();
private String range;
public String getName() {
return name;
}
public CounterOfObject(String name) {
this.name = name;
}
public void count(Comparable value) {
Integer count = set.get(value);
if (count == null)
set.put(value, 1);
else
set.put(value, count + 1);
}
public void addTo(Counter sub) {
CounterOfObject subs = (CounterOfObject) sub;
for (Map.Entry<Comparable, Integer> entry : subs.set.entrySet()) {
Integer count = this.set.get(entry.getKey());
if (count == null)
count = 0;
set.put(entry.getKey(), count + entry.getValue());
}
}
public void show(Formatter f) {
java.util.List<Comparable> list = new ArrayList<>(set.keySet());
f.format("%n%s (%d)%n", name, list.size());
Collections.sort(list);
if (showRange) {
int n = list.size();
f.format(" %10s - %10s: count = %d%n", list.get(0), list.get(n-1), getUnique());
} else {
for (Object key : list) {
int count = set.get(key);
f.format(" %10s: count = %d%n", key, count);
}
}
}
public String showRange() {
if (range == null) {
java.util.List<Comparable> list = new ArrayList<>(set.keySet());
Collections.sort(list);
int n = list.size();
Formatter f = new Formatter();
f.format("%10s - %10s", list.get(0), list.get(n - 1));
range = f.toString();
}
return range;
}
@Override
public int getUnique() {
return set.size();
}
@Override
public int getTotal() {
int total = 0;
for (Map.Entry<Comparable, Integer> entry : set.entrySet()) {
total += entry.getValue();
}
return total;
}
} */
}