blob: d8e686e8c05cec59fa8300b9ac85b2493b115875 [file] [log] [blame]
Aaron Kruglikoved88ff62016-08-01 16:02:09 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Aaron Kruglikoved88ff62016-08-01 16:02:09 -07003 *
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;
Jordan Halterman948d6592017-04-20 17:18:24 -070021import org.onosproject.store.primitives.MapUpdate;
Aaron Kruglikoved88ff62016-08-01 16:02:09 -070022import org.onosproject.store.primitives.TransactionId;
23import org.onosproject.store.service.AsyncConsistentTreeMap;
Jordan Haltermandae11602018-07-03 00:00:47 -070024import org.onosproject.store.service.AsyncIterator;
Aaron Kruglikoved88ff62016-08-01 16:02:09 -070025import org.onosproject.store.service.MapEvent;
26import org.onosproject.store.service.MapEventListener;
Jordan Halterman948d6592017-04-20 17:18:24 -070027import org.onosproject.store.service.TransactionLog;
28import org.onosproject.store.service.Version;
Aaron Kruglikoved88ff62016-08-01 16:02:09 -070029import org.onosproject.store.service.Versioned;
30
31import java.util.Collection;
32import java.util.Map;
33import java.util.NavigableMap;
34import java.util.NavigableSet;
35import java.util.Set;
36import java.util.concurrent.CompletableFuture;
37import java.util.concurrent.Executor;
38import java.util.function.BiFunction;
39import java.util.function.Function;
40import java.util.function.Predicate;
41import java.util.stream.Collectors;
42
43/**
Aaron Kruglikovb06078c2016-08-30 17:28:00 -070044 * An {@code AsyncConsistentTreeMap} that maps its operations to operations on
45 * a differently typed {@code AsyncConsistentTreeMap} by transcoding operation
46 * inputs and outputs.
47 *
48 * @param <V2> value type of other map
49 * @param <V1> value type of this map
Aaron Kruglikoved88ff62016-08-01 16:02:09 -070050 */
51public class TranscodingAsyncConsistentTreeMap<V1, V2>
52 implements AsyncConsistentTreeMap<V1> {
53 private final AsyncConsistentTreeMap<V2> backingMap;
54 private final Function<V2, V1> valueDecoder;
55 private final Function<V1, V2> valueEncoder;
56 private final Function<Versioned<V2>, Versioned<V1>>
57 versionedValueTransform;
58 private final Map<MapEventListener<String, V1>,
59 TranscodingAsyncConsistentTreeMap.InternalBackingMapEventListener>
60 listeners = Maps.newIdentityHashMap();
61
62 public TranscodingAsyncConsistentTreeMap(
63 AsyncConsistentTreeMap<V2> backingMap,
64 Function<V1, V2> valueEncoder,
65 Function<V2, V1> valueDecoder) {
66 this.backingMap = backingMap;
67 this.valueEncoder = v -> v == null ? null : valueEncoder.apply(v);
68 this.valueDecoder = v -> v == null ? null : valueDecoder.apply(v);
69 this.versionedValueTransform = v -> v == null ? null :
70 v.map(valueDecoder);
71 }
Jordan Haltermanf6272442017-04-20 02:18:08 -070072
Aaron Kruglikoved88ff62016-08-01 16:02:09 -070073 @Override
74 public CompletableFuture<String> firstKey() {
75 return backingMap.firstKey();
76 }
77
78 @Override
79 public CompletableFuture<String> lastKey() {
80 return backingMap.lastKey();
81 }
82
83 @Override
84 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
85 ceilingEntry(String key) {
86 return backingMap.ceilingEntry(key)
87 .thenApply(
88 entry ->
89 Maps.immutableEntry(
90 entry.getKey(),
Aaron Kruglikovb06078c2016-08-30 17:28:00 -070091 versionedValueTransform
92 .apply(entry.getValue())));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -070093 }
94
95 @Override
96 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
97 floorEntry(String key) {
98 return backingMap.floorEntry(key)
99 .thenApply(
100 entry ->
101 Maps.immutableEntry(
102 entry.getKey(),
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700103 versionedValueTransform
104 .apply(entry.getValue())));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700105 }
106
107 @Override
108 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
109 higherEntry(String key) {
110 return backingMap
111 .higherEntry(key)
112 .thenApply(entry ->
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700113 Maps.immutableEntry(
114 entry.getKey(),
115 versionedValueTransform
116 .apply(entry.getValue())));
117 }
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700118
119 @Override
120 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
121 lowerEntry(String key) {
122 return backingMap.lowerEntry(key).thenApply(
123 entry ->
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700124 Maps.immutableEntry(
125 entry.getKey(),
126 versionedValueTransform
127 .apply(entry.getValue())));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700128 }
129
130 @Override
131 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
132 firstEntry() {
133 return backingMap.firstEntry()
134 .thenApply(entry ->
135 Maps.immutableEntry(
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700136 entry.getKey(),
137 versionedValueTransform
138 .apply(entry.getValue())));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700139 }
140
141 @Override
142 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
143 lastEntry() {
144 return backingMap.lastEntry()
145 .thenApply(
146 entry -> Maps.immutableEntry(
147 entry.getKey(),
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700148 versionedValueTransform
149 .apply(entry.getValue())));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700150 }
151
152 @Override
153 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
154 pollFirstEntry() {
155 return backingMap.pollFirstEntry()
156 .thenApply(
157 entry -> Maps.immutableEntry(
158 entry.getKey(),
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700159 versionedValueTransform
160 .apply(entry.getValue())));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700161 }
162
163 @Override
164 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
165 pollLastEntry() {
166 return backingMap.pollLastEntry()
167 .thenApply(entry -> Maps.immutableEntry(
168 entry.getKey(),
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700169 versionedValueTransform.apply(entry.getValue())));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700170 }
171
172 @Override
173 public CompletableFuture<String> lowerKey(String key) {
174 return backingMap.lowerKey(key);
175 }
176
177 @Override
178 public CompletableFuture<String> floorKey(String key) {
179 return backingMap.floorKey(key);
180 }
181
182 @Override
183 public CompletableFuture<String> ceilingKey(String key) {
184 return backingMap.ceilingKey(key);
185 }
186
187 @Override
188 public CompletableFuture<String> higherKey(String key) {
189 return backingMap.higherKey(key);
190 }
191
192 @Override
193 public CompletableFuture<NavigableSet<String>> navigableKeySet() {
194 return backingMap.navigableKeySet();
195 }
196
197 @Override
198 public CompletableFuture<NavigableMap<String, V1>> subMap(
199 String upperKey,
200 String lowerKey,
201 boolean inclusiveUpper,
202 boolean inclusiveLower) {
203 throw new UnsupportedOperationException("This operation is not yet" +
204 "supported.");
205 }
206
207 @Override
208 public String name() {
209 return backingMap.name();
210 }
211
212 @Override
213 public CompletableFuture<Integer> size() {
214 return backingMap.size();
215 }
216
217 @Override
218 public CompletableFuture<Boolean> containsKey(String key) {
219 return backingMap.containsKey(key);
220 }
221
222 @Override
223 public CompletableFuture<Boolean> containsValue(V1 value) {
224 return backingMap.containsValue(valueEncoder.apply(value));
225 }
226
227 @Override
228 public CompletableFuture<Versioned<V1>> get(String key) {
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700229 return backingMap.get(key).thenApply(versionedValueTransform);
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700230 }
231
232 @Override
Jordan Haltermanf6272442017-04-20 02:18:08 -0700233 public CompletableFuture<Versioned<V1>> getOrDefault(String key, V1 defaultValue) {
234 return backingMap.getOrDefault(key, valueEncoder.apply(defaultValue)).thenApply(versionedValueTransform);
235 }
236
237 @Override
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700238 public CompletableFuture<Versioned<V1>> computeIf(
239 String key, Predicate<? super V1> condition,
240 BiFunction<? super String, ? super V1, ? extends V1>
241 remappingFunction) {
242 try {
243 return backingMap
244 .computeIf(
245 key,
246 v -> condition.test(valueDecoder.apply(v)),
247 (k, v) -> valueEncoder
248 .apply(
249 remappingFunction.apply(
250 key,
251 valueDecoder.apply(v))))
252 .thenApply(versionedValueTransform);
253 } catch (Exception e) {
254 return Tools.exceptionalFuture(e);
255 }
256 }
257
258 @Override
259 public CompletableFuture<Versioned<V1>> put(String key, V1 value) {
260 return backingMap.put(key, valueEncoder.apply(value))
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700261 .thenApply(versionedValueTransform);
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700262 }
263
264 @Override
265 public CompletableFuture<Versioned<V1>> putAndGet(String key, V1 value) {
266 return backingMap.putAndGet(key, valueEncoder.apply(value))
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700267 .thenApply(versionedValueTransform);
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700268 }
269
270 @Override
271 public CompletableFuture<Versioned<V1>> remove(String key) {
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700272 return backingMap.remove(key).thenApply(versionedValueTransform);
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700273 }
274
275 @Override
276 public CompletableFuture<Void> clear() {
277 return backingMap.clear();
278 }
279
280 @Override
281 public CompletableFuture<Set<String>> keySet() {
282 return backingMap.keySet();
283 }
284
285 @Override
286 public CompletableFuture<Collection<Versioned<V1>>> values() {
287 return backingMap.values().thenApply(valueSet -> valueSet.stream()
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700288 .map(versionedValueTransform).collect(Collectors.toSet()));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700289 }
290
291 @Override
292 public CompletableFuture<Set<Map.Entry<String, Versioned<V1>>>>
293 entrySet() {
294 return backingMap.entrySet()
295 .thenApply(
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700296 entries -> entries
297 .stream()
298 .map(entry ->
299 Maps.immutableEntry(
300 entry.getKey(),
301 versionedValueTransform
302 .apply(entry.getValue())
303 ))
304 .collect(Collectors.toSet()));
305 }
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700306
307 @Override
308 public CompletableFuture<Versioned<V1>> putIfAbsent(String key, V1 value) {
309 return backingMap.putIfAbsent(key, valueEncoder.apply(value))
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700310 .thenApply(versionedValueTransform);
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700311 }
312
313 @Override
314 public CompletableFuture<Boolean> remove(String key, V1 value) {
315 return backingMap.remove(key, valueEncoder.apply(value));
316 }
317
318 @Override
319 public CompletableFuture<Boolean> remove(String key, long version) {
320 return backingMap.remove(key, version);
321 }
322
323 @Override
324 public CompletableFuture<Versioned<V1>> replace(String key, V1 value) {
325 return backingMap.replace(key, valueEncoder.apply(value))
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700326 .thenApply(versionedValueTransform);
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700327 }
328
329 @Override
330 public CompletableFuture<Boolean> replace(String key, V1 oldValue,
331 V1 newValue) {
332 return backingMap.replace(key, valueEncoder.apply(oldValue),
333 valueEncoder.apply(newValue));
334 }
335
336 @Override
337 public CompletableFuture<Boolean> replace(String key, long oldVersion,
338 V1 newValue) {
339 return backingMap.replace(key, oldVersion,
340 valueEncoder.apply(newValue));
341 }
342
343 @Override
Jordan Haltermandae11602018-07-03 00:00:47 -0700344 public CompletableFuture<AsyncIterator<Map.Entry<String, Versioned<V1>>>> iterator() {
345 return backingMap.iterator().thenApply(TranscodingIterator::new);
346 }
347
348 @Override
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700349 public CompletableFuture<Void> addListener(
350 MapEventListener<String, V1> listener,
351 Executor executor) {
352 InternalBackingMapEventListener backingMapEventListener =
353 listeners.computeIfAbsent(
354 listener,
355 k -> new InternalBackingMapEventListener(listener));
356 return backingMap.addListener(backingMapEventListener, executor);
357 }
358
359 @Override
360 public CompletableFuture<Void> removeListener(
361 MapEventListener<String, V1> listener) {
362 InternalBackingMapEventListener backingMapEventListener =
363 listeners.remove(listener);
364 if (backingMapEventListener == null) {
365 return CompletableFuture.completedFuture(null);
366 } else {
367 return backingMap.removeListener(backingMapEventListener);
368 }
369 }
370
371 @Override
Jordan Halterman948d6592017-04-20 17:18:24 -0700372 public CompletableFuture<Version> begin(TransactionId transactionId) {
373 throw new UnsupportedOperationException("This operation is not yet supported.");
374 }
375
376 @Override
377 public CompletableFuture<Boolean> prepare(TransactionLog<MapUpdate<String, V1>> transactionLog) {
378 throw new UnsupportedOperationException("This operation is not yet supported.");
379 }
380
381 @Override
382 public CompletableFuture<Boolean> prepareAndCommit(TransactionLog<MapUpdate<String, V1>> transactionLog) {
383 throw new UnsupportedOperationException("This operation is not yet supported.");
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700384 }
385
386 @Override
387 public CompletableFuture<Void> commit(TransactionId transactionId) {
Jordan Halterman948d6592017-04-20 17:18:24 -0700388 throw new UnsupportedOperationException("This operation is not yet supported.");
389 }
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700390
391 @Override
392 public CompletableFuture<Void> rollback(TransactionId transactionId) {
Jordan Halterman948d6592017-04-20 17:18:24 -0700393 throw new UnsupportedOperationException("This operation is not yet supported.");
394 }
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700395
Jordan Haltermandae11602018-07-03 00:00:47 -0700396 private class TranscodingIterator implements AsyncIterator<Map.Entry<String, Versioned<V1>>> {
397 private final AsyncIterator<Map.Entry<String, Versioned<V2>>> iterator;
398
399 public TranscodingIterator(AsyncIterator<Map.Entry<String, Versioned<V2>>> iterator) {
400 this.iterator = iterator;
401 }
402
403 @Override
404 public CompletableFuture<Boolean> hasNext() {
405 return iterator.hasNext();
406 }
407
408 @Override
409 public CompletableFuture<Map.Entry<String, Versioned<V1>>> next() {
410 return iterator.next().thenApply(entry ->
411 Maps.immutableEntry(entry.getKey(), entry.getValue().map(valueDecoder)));
412 }
413 }
414
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700415 private class InternalBackingMapEventListener
416 implements MapEventListener<String, V2> {
417
418 private final MapEventListener<String, V1> listener;
419
420 InternalBackingMapEventListener(
421 MapEventListener<String, V1> listener) {
422 this.listener = listener;
423 }
424
425 @Override
426 public void event(MapEvent<String, V2> event) {
427 listener.event(new MapEvent<String, V1>(
Jordan Halterman71635ae2017-07-28 10:35:43 -0700428 event.type(),
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700429 event.name(),
430 event.key(),
431 event.newValue() != null ?
432 event.newValue().map(valueDecoder) : null,
433 event.oldValue() != null ?
434 event.oldValue().map(valueDecoder) : null));
435 }
436 }
437}