source: osm/applications/editors/josm/plugins/imagerycache/src/org/mapdb/Bind.java@ 30532

Last change on this file since 30532 was 30532, checked in by donvip, 10 years ago

[josm_plugins] fix compilation warnings

File size: 6.9 KB
Line 
1package org.mapdb;
2
3import java.util.Iterator;
4import java.util.Map;
5import java.util.NavigableSet;
6import java.util.concurrent.ConcurrentMap;
7
8/**
9 * Collection binding
10 *
11 * @author Jan Kotek
12 */
13public final class Bind {
14
15 private Bind(){}
16
17 public static <K2,K1> Iterable<K1> findSecondaryKeys(final NavigableSet<Fun.Tuple2<K2,K1>> secondaryKeys, final K2 secondaryKey) {
18 return new Iterable<K1>(){
19 @Override
20 public Iterator<K1> iterator() {
21 //use range query to get all values
22 @SuppressWarnings("unchecked")
23 final Iterator<Fun.Tuple2<K2,K1>> iter =
24 secondaryKeys
25 .subSet(
26 Fun.t2(secondaryKey,(K1)null), //NULL represents lower bound, everything is larger than null
27 Fun.t2(secondaryKey,(K1)Fun.HI) // HI is upper bound everything is smaller then HI
28 ).iterator();
29
30 return new Iterator<K1>() {
31 @Override
32 public boolean hasNext() {
33 return iter.hasNext();
34 }
35
36 @Override
37 public K1 next() {
38 return iter.next().b;
39 }
40
41 @Override
42 public void remove() {
43 iter.remove();
44 }
45 };
46 }
47 };
48
49 }
50
51
52 public interface MapListener<K,V>{
53 void update(K key, V oldVal, V newVal);
54 }
55
56 public interface MapWithModificationListener<K,V> extends Map<K,V> {
57 public void addModificationListener(MapListener<K,V> listener);
58 public void removeModificationListener(MapListener<K,V> listener);
59 }
60
61 public static <K,V> void size(MapWithModificationListener<K, V> map, final Atomic.Long size){
62 //set initial value first if necessary
63 if(size.get() == 0 && map.isEmpty())
64 size.set(map.size()); //TODO long overflow?
65
66 map.addModificationListener(new MapListener<K, V>() {
67 @Override
68 public void update(Object key, Object oldVal, Object newVal) {
69 if(oldVal == null && newVal!=null)
70 size.incrementAndGet();
71 else if(oldVal!=null && newVal == null)
72 size.decrementAndGet();
73 else{
74 //update does not change collection size
75 }
76 }
77 });
78 }
79
80 public static <K,V, V2> void secondaryValue(MapWithModificationListener<K, V> map,
81 final Map<K, V2> secondary,
82 final Fun.Function2<V2, K, V> fun){
83 //fill if empty
84 if(secondary.isEmpty()){
85 for(Map.Entry<K,V> e:map.entrySet())
86 secondary.put(e.getKey(), fun.run(e.getKey(),e.getValue()));
87 }
88 //hook listener
89 map.addModificationListener(new MapListener<K, V>() {
90 @Override
91 public void update(K key, V oldVal, V newVal) {
92 if(newVal == null){
93 //removal
94 secondary.remove(key);
95 }else{
96 secondary.put(key, fun.run(key,newVal));
97 }
98 }
99 });
100 }
101
102 public static <K,V, K2> void secondaryKey(MapWithModificationListener<K, V> map,
103 final NavigableSet<Fun.Tuple2<K2, K>> secondary,
104 final Fun.Function2<K2, K, V> fun){
105 //fill if empty
106 if(secondary.isEmpty()){
107 for(Map.Entry<K,V> e:map.entrySet()){
108 secondary.add(Fun.t2(fun.run(e.getKey(),e.getValue()), e.getKey()));
109 }
110 }
111 //hook listener
112 map.addModificationListener(new MapListener<K, V>() {
113 @Override
114 public void update(K key, V oldVal, V newVal) {
115 if(newVal == null){
116 //removal
117 secondary.remove(Fun.t2(fun.run(key, oldVal), key));
118 }else if(oldVal==null){
119 //insert
120 secondary.add(Fun.t2(fun.run(key,newVal), key));
121 }else{
122 //update, must remove old key and insert new
123 K2 oldKey = fun.run(key, oldVal);
124 K2 newKey = fun.run(key, newVal);
125 if(oldKey == newKey || oldKey.equals(newKey)) return;
126 secondary.remove(Fun.t2(oldKey, key));
127 secondary.add(Fun.t2(newKey,key));
128 }
129 }
130 });
131 }
132
133 public static <K,V> void mapInverse(MapWithModificationListener<K,V> primary,
134 NavigableSet<Fun.Tuple2<V, K>> inverse) {
135 Bind.secondaryKey(primary,inverse, new Fun.Function2<V, K,V>(){
136 @Override public V run(K key, V value) {
137 return value;
138 }
139 });
140 }
141
142
143 public static <K,V,C> void histogram(MapWithModificationListener<K,V> primary, final ConcurrentMap<C,Long> histogram,
144 final Fun.Function2<C, K, V> entryToCategory){
145
146 MapListener<K,V> listener = new MapListener<K, V>() {
147 @Override public void update(K key, V oldVal, V newVal) {
148 if(newVal == null){
149 //removal
150 C category = entryToCategory.run(key,oldVal);
151 incrementHistogram(category, -1);
152 }else if(oldVal==null){
153 //insert
154 C category = entryToCategory.run(key,newVal);
155 incrementHistogram(category, 1);
156 }else{
157 //update, must remove old key and insert new
158 C oldCat = entryToCategory.run(key, oldVal);
159 C newCat = entryToCategory.run(key, newVal);
160 if(oldCat == newCat || oldCat.equals(newCat)) return;
161 incrementHistogram(oldCat,-1);
162 incrementHistogram(oldCat,1);
163 }
164
165 }
166
167 /** atomically update counter in histogram*/
168 private void incrementHistogram(C category, long i) {
169 for(;;){
170 Long oldCount = histogram.get(category);
171 if(oldCount == null){
172 //insert new count
173 if(histogram.putIfAbsent(category,i) == null)
174 return;
175 }else{
176 //increase existing count
177 Long newCount = oldCount+i;
178 if(histogram.replace(category,oldCount, newCount))
179 return;
180 }
181 }
182 }
183 };
184
185 primary.addModificationListener(listener);
186 }
187
188
189
190
191}
Note: See TracBrowser for help on using the repository browser.