blob: 71ff97565af664fb8afc4dc966d221c6898dfcc5 [file] [log] [blame]
Aaron Kruglikoved88ff62016-08-01 16:02:09 -07001/*
2 * Copyright 2016 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.store.primitives.impl;
18
19import com.google.common.collect.Maps;
20import org.onlab.util.Tools;
21import org.onosproject.store.primitives.TransactionId;
22import org.onosproject.store.service.AsyncConsistentTreeMap;
23import org.onosproject.store.service.MapEvent;
24import org.onosproject.store.service.MapEventListener;
25import org.onosproject.store.service.MapTransaction;
26import org.onosproject.store.service.Versioned;
27
28import java.util.Collection;
29import java.util.Map;
30import java.util.NavigableMap;
31import java.util.NavigableSet;
32import java.util.Set;
33import java.util.concurrent.CompletableFuture;
34import java.util.concurrent.Executor;
35import java.util.function.BiFunction;
36import java.util.function.Function;
37import java.util.function.Predicate;
38import java.util.stream.Collectors;
39
40/**
41 * Created by admin on 8/3/16.
42 */
43public class TranscodingAsyncConsistentTreeMap<V1, V2>
44 implements AsyncConsistentTreeMap<V1> {
45 private final AsyncConsistentTreeMap<V2> backingMap;
46 private final Function<V2, V1> valueDecoder;
47 private final Function<V1, V2> valueEncoder;
48 private final Function<Versioned<V2>, Versioned<V1>>
49 versionedValueTransform;
50 private final Map<MapEventListener<String, V1>,
51 TranscodingAsyncConsistentTreeMap.InternalBackingMapEventListener>
52 listeners = Maps.newIdentityHashMap();
53
54 public TranscodingAsyncConsistentTreeMap(
55 AsyncConsistentTreeMap<V2> backingMap,
56 Function<V1, V2> valueEncoder,
57 Function<V2, V1> valueDecoder) {
58 this.backingMap = backingMap;
59 this.valueEncoder = v -> v == null ? null : valueEncoder.apply(v);
60 this.valueDecoder = v -> v == null ? null : valueDecoder.apply(v);
61 this.versionedValueTransform = v -> v == null ? null :
62 v.map(valueDecoder);
63 }
64 @Override
65 public CompletableFuture<String> firstKey() {
66 return backingMap.firstKey();
67 }
68
69 @Override
70 public CompletableFuture<String> lastKey() {
71 return backingMap.lastKey();
72 }
73
74 @Override
75 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
76 ceilingEntry(String key) {
77 return backingMap.ceilingEntry(key)
78 .thenApply(
79 entry ->
80 Maps.immutableEntry(
81 entry.getKey(),
82 entry.getValue().map(valueDecoder)));
83 }
84
85 @Override
86 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
87 floorEntry(String key) {
88 return backingMap.floorEntry(key)
89 .thenApply(
90 entry ->
91 Maps.immutableEntry(
92 entry.getKey(),
93 entry.getValue().map(valueDecoder)));
94 }
95
96 @Override
97 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
98 higherEntry(String key) {
99 return backingMap
100 .higherEntry(key)
101 .thenApply(entry ->
102 Maps.immutableEntry(
103 entry.getKey(),
104 entry.getValue().map(valueDecoder)));
105}
106
107 @Override
108 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
109 lowerEntry(String key) {
110 return backingMap.lowerEntry(key).thenApply(
111 entry ->
112 Maps.immutableEntry(
113 entry.getKey(),
114 entry.getValue().map(valueDecoder)));
115 }
116
117 @Override
118 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
119 firstEntry() {
120 return backingMap.firstEntry()
121 .thenApply(entry ->
122 Maps.immutableEntry(
123 entry.getKey(),
124 entry.getValue().map(valueDecoder)));
125 }
126
127 @Override
128 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
129 lastEntry() {
130 return backingMap.lastEntry()
131 .thenApply(
132 entry -> Maps.immutableEntry(
133 entry.getKey(),
134 entry.getValue().map(valueDecoder)));
135 }
136
137 @Override
138 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
139 pollFirstEntry() {
140 return backingMap.pollFirstEntry()
141 .thenApply(
142 entry -> Maps.immutableEntry(
143 entry.getKey(),
144 entry.getValue().map(valueDecoder)));
145 }
146
147 @Override
148 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
149 pollLastEntry() {
150 return backingMap.pollLastEntry()
151 .thenApply(entry -> Maps.immutableEntry(
152 entry.getKey(),
153 entry.getValue().map(valueDecoder)));
154 }
155
156 @Override
157 public CompletableFuture<String> lowerKey(String key) {
158 return backingMap.lowerKey(key);
159 }
160
161 @Override
162 public CompletableFuture<String> floorKey(String key) {
163 return backingMap.floorKey(key);
164 }
165
166 @Override
167 public CompletableFuture<String> ceilingKey(String key) {
168 return backingMap.ceilingKey(key);
169 }
170
171 @Override
172 public CompletableFuture<String> higherKey(String key) {
173 return backingMap.higherKey(key);
174 }
175
176 @Override
177 public CompletableFuture<NavigableSet<String>> navigableKeySet() {
178 return backingMap.navigableKeySet();
179 }
180
181 @Override
182 public CompletableFuture<NavigableMap<String, V1>> subMap(
183 String upperKey,
184 String lowerKey,
185 boolean inclusiveUpper,
186 boolean inclusiveLower) {
187 throw new UnsupportedOperationException("This operation is not yet" +
188 "supported.");
189 }
190
191 @Override
192 public String name() {
193 return backingMap.name();
194 }
195
196 @Override
197 public CompletableFuture<Integer> size() {
198 return backingMap.size();
199 }
200
201 @Override
202 public CompletableFuture<Boolean> containsKey(String key) {
203 return backingMap.containsKey(key);
204 }
205
206 @Override
207 public CompletableFuture<Boolean> containsValue(V1 value) {
208 return backingMap.containsValue(valueEncoder.apply(value));
209 }
210
211 @Override
212 public CompletableFuture<Versioned<V1>> get(String key) {
213 return backingMap.get(key).thenApply(value -> value.map(valueDecoder));
214 }
215
216 @Override
217 public CompletableFuture<Versioned<V1>> computeIf(
218 String key, Predicate<? super V1> condition,
219 BiFunction<? super String, ? super V1, ? extends V1>
220 remappingFunction) {
221 try {
222 return backingMap
223 .computeIf(
224 key,
225 v -> condition.test(valueDecoder.apply(v)),
226 (k, v) -> valueEncoder
227 .apply(
228 remappingFunction.apply(
229 key,
230 valueDecoder.apply(v))))
231 .thenApply(versionedValueTransform);
232 } catch (Exception e) {
233 return Tools.exceptionalFuture(e);
234 }
235 }
236
237 @Override
238 public CompletableFuture<Versioned<V1>> put(String key, V1 value) {
239 return backingMap.put(key, valueEncoder.apply(value))
240 .thenApply(v -> v.map(valueDecoder));
241 }
242
243 @Override
244 public CompletableFuture<Versioned<V1>> putAndGet(String key, V1 value) {
245 return backingMap.putAndGet(key, valueEncoder.apply(value))
246 .thenApply(v -> v.map(valueDecoder));
247 }
248
249 @Override
250 public CompletableFuture<Versioned<V1>> remove(String key) {
251 return backingMap.remove(key).thenApply(v -> v.map(valueDecoder));
252 }
253
254 @Override
255 public CompletableFuture<Void> clear() {
256 return backingMap.clear();
257 }
258
259 @Override
260 public CompletableFuture<Set<String>> keySet() {
261 return backingMap.keySet();
262 }
263
264 @Override
265 public CompletableFuture<Collection<Versioned<V1>>> values() {
266 return backingMap.values().thenApply(valueSet -> valueSet.stream()
267 .map(v -> v.map(valueDecoder)).collect(Collectors.toSet()));
268 }
269
270 @Override
271 public CompletableFuture<Set<Map.Entry<String, Versioned<V1>>>>
272 entrySet() {
273 return backingMap.entrySet()
274 .thenApply(
275 entries -> entries
276 .stream()
277 .map(entry ->
278 Maps.immutableEntry(entry.getKey(),
279 entry.getValue()
280 .map(valueDecoder)))
281 .collect(Collectors.toSet()));
282 }
283
284 @Override
285 public CompletableFuture<Versioned<V1>> putIfAbsent(String key, V1 value) {
286 return backingMap.putIfAbsent(key, valueEncoder.apply(value))
287 .thenApply(v -> v.map(valueDecoder));
288 }
289
290 @Override
291 public CompletableFuture<Boolean> remove(String key, V1 value) {
292 return backingMap.remove(key, valueEncoder.apply(value));
293 }
294
295 @Override
296 public CompletableFuture<Boolean> remove(String key, long version) {
297 return backingMap.remove(key, version);
298 }
299
300 @Override
301 public CompletableFuture<Versioned<V1>> replace(String key, V1 value) {
302 return backingMap.replace(key, valueEncoder.apply(value))
303 .thenApply(v -> v.map(valueDecoder));
304 }
305
306 @Override
307 public CompletableFuture<Boolean> replace(String key, V1 oldValue,
308 V1 newValue) {
309 return backingMap.replace(key, valueEncoder.apply(oldValue),
310 valueEncoder.apply(newValue));
311 }
312
313 @Override
314 public CompletableFuture<Boolean> replace(String key, long oldVersion,
315 V1 newValue) {
316 return backingMap.replace(key, oldVersion,
317 valueEncoder.apply(newValue));
318 }
319
320 @Override
321 public CompletableFuture<Void> addListener(
322 MapEventListener<String, V1> listener,
323 Executor executor) {
324 InternalBackingMapEventListener backingMapEventListener =
325 listeners.computeIfAbsent(
326 listener,
327 k -> new InternalBackingMapEventListener(listener));
328 return backingMap.addListener(backingMapEventListener, executor);
329 }
330
331 @Override
332 public CompletableFuture<Void> removeListener(
333 MapEventListener<String, V1> listener) {
334 InternalBackingMapEventListener backingMapEventListener =
335 listeners.remove(listener);
336 if (backingMapEventListener == null) {
337 return CompletableFuture.completedFuture(null);
338 } else {
339 return backingMap.removeListener(backingMapEventListener);
340 }
341 }
342
343 @Override
344 public CompletableFuture<Boolean> prepare(
345 MapTransaction<String, V1> transaction) {
346 throw new UnsupportedOperationException("This operation is not yet " +
347 "supported.");
348 }
349
350 @Override
351 public CompletableFuture<Void> commit(TransactionId transactionId) {
352 throw new UnsupportedOperationException("This operation is not yet " +
353 "supported."); }
354
355 @Override
356 public CompletableFuture<Void> rollback(TransactionId transactionId) {
357 throw new UnsupportedOperationException("This operation is not yet " +
358 "supported."); }
359
360 @Override
361 public CompletableFuture<Boolean> prepareAndCommit(
362 MapTransaction<String, V1> transaction) {
363 throw new UnsupportedOperationException("This operation is not yet " +
364 "supported."); }
365 private class InternalBackingMapEventListener
366 implements MapEventListener<String, V2> {
367
368 private final MapEventListener<String, V1> listener;
369
370 InternalBackingMapEventListener(
371 MapEventListener<String, V1> listener) {
372 this.listener = listener;
373 }
374
375 @Override
376 public void event(MapEvent<String, V2> event) {
377 listener.event(new MapEvent<String, V1>(
378 event.name(),
379 event.key(),
380 event.newValue() != null ?
381 event.newValue().map(valueDecoder) : null,
382 event.oldValue() != null ?
383 event.oldValue().map(valueDecoder) : null));
384 }
385 }
386}