blob: 48a3b966e0cd9a9394975a0401ec5cadab4f9b31 [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/**
Aaron Kruglikovb06078c2016-08-30 17:28:00 -070041 * An {@code AsyncConsistentTreeMap} that maps its operations to operations on
42 * a differently typed {@code AsyncConsistentTreeMap} by transcoding operation
43 * inputs and outputs.
44 *
45 * @param <V2> value type of other map
46 * @param <V1> value type of this map
Aaron Kruglikoved88ff62016-08-01 16:02:09 -070047 */
48public class TranscodingAsyncConsistentTreeMap<V1, V2>
49 implements AsyncConsistentTreeMap<V1> {
50 private final AsyncConsistentTreeMap<V2> backingMap;
51 private final Function<V2, V1> valueDecoder;
52 private final Function<V1, V2> valueEncoder;
53 private final Function<Versioned<V2>, Versioned<V1>>
54 versionedValueTransform;
55 private final Map<MapEventListener<String, V1>,
56 TranscodingAsyncConsistentTreeMap.InternalBackingMapEventListener>
57 listeners = Maps.newIdentityHashMap();
58
59 public TranscodingAsyncConsistentTreeMap(
60 AsyncConsistentTreeMap<V2> backingMap,
61 Function<V1, V2> valueEncoder,
62 Function<V2, V1> valueDecoder) {
63 this.backingMap = backingMap;
64 this.valueEncoder = v -> v == null ? null : valueEncoder.apply(v);
65 this.valueDecoder = v -> v == null ? null : valueDecoder.apply(v);
66 this.versionedValueTransform = v -> v == null ? null :
67 v.map(valueDecoder);
68 }
69 @Override
70 public CompletableFuture<String> firstKey() {
71 return backingMap.firstKey();
72 }
73
74 @Override
75 public CompletableFuture<String> lastKey() {
76 return backingMap.lastKey();
77 }
78
79 @Override
80 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
81 ceilingEntry(String key) {
82 return backingMap.ceilingEntry(key)
83 .thenApply(
84 entry ->
85 Maps.immutableEntry(
86 entry.getKey(),
Aaron Kruglikovb06078c2016-08-30 17:28:00 -070087 versionedValueTransform
88 .apply(entry.getValue())));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -070089 }
90
91 @Override
92 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
93 floorEntry(String key) {
94 return backingMap.floorEntry(key)
95 .thenApply(
96 entry ->
97 Maps.immutableEntry(
98 entry.getKey(),
Aaron Kruglikovb06078c2016-08-30 17:28:00 -070099 versionedValueTransform
100 .apply(entry.getValue())));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700101 }
102
103 @Override
104 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
105 higherEntry(String key) {
106 return backingMap
107 .higherEntry(key)
108 .thenApply(entry ->
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700109 Maps.immutableEntry(
110 entry.getKey(),
111 versionedValueTransform
112 .apply(entry.getValue())));
113 }
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700114
115 @Override
116 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
117 lowerEntry(String key) {
118 return backingMap.lowerEntry(key).thenApply(
119 entry ->
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700120 Maps.immutableEntry(
121 entry.getKey(),
122 versionedValueTransform
123 .apply(entry.getValue())));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700124 }
125
126 @Override
127 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
128 firstEntry() {
129 return backingMap.firstEntry()
130 .thenApply(entry ->
131 Maps.immutableEntry(
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700132 entry.getKey(),
133 versionedValueTransform
134 .apply(entry.getValue())));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700135 }
136
137 @Override
138 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
139 lastEntry() {
140 return backingMap.lastEntry()
141 .thenApply(
142 entry -> Maps.immutableEntry(
143 entry.getKey(),
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700144 versionedValueTransform
145 .apply(entry.getValue())));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700146 }
147
148 @Override
149 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
150 pollFirstEntry() {
151 return backingMap.pollFirstEntry()
152 .thenApply(
153 entry -> Maps.immutableEntry(
154 entry.getKey(),
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700155 versionedValueTransform
156 .apply(entry.getValue())));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700157 }
158
159 @Override
160 public CompletableFuture<Map.Entry<String, Versioned<V1>>>
161 pollLastEntry() {
162 return backingMap.pollLastEntry()
163 .thenApply(entry -> Maps.immutableEntry(
164 entry.getKey(),
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700165 versionedValueTransform.apply(entry.getValue())));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700166 }
167
168 @Override
169 public CompletableFuture<String> lowerKey(String key) {
170 return backingMap.lowerKey(key);
171 }
172
173 @Override
174 public CompletableFuture<String> floorKey(String key) {
175 return backingMap.floorKey(key);
176 }
177
178 @Override
179 public CompletableFuture<String> ceilingKey(String key) {
180 return backingMap.ceilingKey(key);
181 }
182
183 @Override
184 public CompletableFuture<String> higherKey(String key) {
185 return backingMap.higherKey(key);
186 }
187
188 @Override
189 public CompletableFuture<NavigableSet<String>> navigableKeySet() {
190 return backingMap.navigableKeySet();
191 }
192
193 @Override
194 public CompletableFuture<NavigableMap<String, V1>> subMap(
195 String upperKey,
196 String lowerKey,
197 boolean inclusiveUpper,
198 boolean inclusiveLower) {
199 throw new UnsupportedOperationException("This operation is not yet" +
200 "supported.");
201 }
202
203 @Override
204 public String name() {
205 return backingMap.name();
206 }
207
208 @Override
209 public CompletableFuture<Integer> size() {
210 return backingMap.size();
211 }
212
213 @Override
214 public CompletableFuture<Boolean> containsKey(String key) {
215 return backingMap.containsKey(key);
216 }
217
218 @Override
219 public CompletableFuture<Boolean> containsValue(V1 value) {
220 return backingMap.containsValue(valueEncoder.apply(value));
221 }
222
223 @Override
224 public CompletableFuture<Versioned<V1>> get(String key) {
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700225 return backingMap.get(key).thenApply(versionedValueTransform);
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700226 }
227
228 @Override
229 public CompletableFuture<Versioned<V1>> computeIf(
230 String key, Predicate<? super V1> condition,
231 BiFunction<? super String, ? super V1, ? extends V1>
232 remappingFunction) {
233 try {
234 return backingMap
235 .computeIf(
236 key,
237 v -> condition.test(valueDecoder.apply(v)),
238 (k, v) -> valueEncoder
239 .apply(
240 remappingFunction.apply(
241 key,
242 valueDecoder.apply(v))))
243 .thenApply(versionedValueTransform);
244 } catch (Exception e) {
245 return Tools.exceptionalFuture(e);
246 }
247 }
248
249 @Override
250 public CompletableFuture<Versioned<V1>> put(String key, V1 value) {
251 return backingMap.put(key, valueEncoder.apply(value))
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700252 .thenApply(versionedValueTransform);
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700253 }
254
255 @Override
256 public CompletableFuture<Versioned<V1>> putAndGet(String key, V1 value) {
257 return backingMap.putAndGet(key, valueEncoder.apply(value))
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700258 .thenApply(versionedValueTransform);
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700259 }
260
261 @Override
262 public CompletableFuture<Versioned<V1>> remove(String key) {
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700263 return backingMap.remove(key).thenApply(versionedValueTransform);
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700264 }
265
266 @Override
267 public CompletableFuture<Void> clear() {
268 return backingMap.clear();
269 }
270
271 @Override
272 public CompletableFuture<Set<String>> keySet() {
273 return backingMap.keySet();
274 }
275
276 @Override
277 public CompletableFuture<Collection<Versioned<V1>>> values() {
278 return backingMap.values().thenApply(valueSet -> valueSet.stream()
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700279 .map(versionedValueTransform).collect(Collectors.toSet()));
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700280 }
281
282 @Override
283 public CompletableFuture<Set<Map.Entry<String, Versioned<V1>>>>
284 entrySet() {
285 return backingMap.entrySet()
286 .thenApply(
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700287 entries -> entries
288 .stream()
289 .map(entry ->
290 Maps.immutableEntry(
291 entry.getKey(),
292 versionedValueTransform
293 .apply(entry.getValue())
294 ))
295 .collect(Collectors.toSet()));
296 }
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700297
298 @Override
299 public CompletableFuture<Versioned<V1>> putIfAbsent(String key, V1 value) {
300 return backingMap.putIfAbsent(key, valueEncoder.apply(value))
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700301 .thenApply(versionedValueTransform);
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700302 }
303
304 @Override
305 public CompletableFuture<Boolean> remove(String key, V1 value) {
306 return backingMap.remove(key, valueEncoder.apply(value));
307 }
308
309 @Override
310 public CompletableFuture<Boolean> remove(String key, long version) {
311 return backingMap.remove(key, version);
312 }
313
314 @Override
315 public CompletableFuture<Versioned<V1>> replace(String key, V1 value) {
316 return backingMap.replace(key, valueEncoder.apply(value))
Aaron Kruglikovb06078c2016-08-30 17:28:00 -0700317 .thenApply(versionedValueTransform);
Aaron Kruglikoved88ff62016-08-01 16:02:09 -0700318 }
319
320 @Override
321 public CompletableFuture<Boolean> replace(String key, V1 oldValue,
322 V1 newValue) {
323 return backingMap.replace(key, valueEncoder.apply(oldValue),
324 valueEncoder.apply(newValue));
325 }
326
327 @Override
328 public CompletableFuture<Boolean> replace(String key, long oldVersion,
329 V1 newValue) {
330 return backingMap.replace(key, oldVersion,
331 valueEncoder.apply(newValue));
332 }
333
334 @Override
335 public CompletableFuture<Void> addListener(
336 MapEventListener<String, V1> listener,
337 Executor executor) {
338 InternalBackingMapEventListener backingMapEventListener =
339 listeners.computeIfAbsent(
340 listener,
341 k -> new InternalBackingMapEventListener(listener));
342 return backingMap.addListener(backingMapEventListener, executor);
343 }
344
345 @Override
346 public CompletableFuture<Void> removeListener(
347 MapEventListener<String, V1> listener) {
348 InternalBackingMapEventListener backingMapEventListener =
349 listeners.remove(listener);
350 if (backingMapEventListener == null) {
351 return CompletableFuture.completedFuture(null);
352 } else {
353 return backingMap.removeListener(backingMapEventListener);
354 }
355 }
356
357 @Override
358 public CompletableFuture<Boolean> prepare(
359 MapTransaction<String, V1> transaction) {
360 throw new UnsupportedOperationException("This operation is not yet " +
361 "supported.");
362 }
363
364 @Override
365 public CompletableFuture<Void> commit(TransactionId transactionId) {
366 throw new UnsupportedOperationException("This operation is not yet " +
367 "supported."); }
368
369 @Override
370 public CompletableFuture<Void> rollback(TransactionId transactionId) {
371 throw new UnsupportedOperationException("This operation is not yet " +
372 "supported."); }
373
374 @Override
375 public CompletableFuture<Boolean> prepareAndCommit(
376 MapTransaction<String, V1> transaction) {
377 throw new UnsupportedOperationException("This operation is not yet " +
378 "supported."); }
379 private class InternalBackingMapEventListener
380 implements MapEventListener<String, V2> {
381
382 private final MapEventListener<String, V1> listener;
383
384 InternalBackingMapEventListener(
385 MapEventListener<String, V1> listener) {
386 this.listener = listener;
387 }
388
389 @Override
390 public void event(MapEvent<String, V2> event) {
391 listener.event(new MapEvent<String, V1>(
392 event.name(),
393 event.key(),
394 event.newValue() != null ?
395 event.newValue().map(valueDecoder) : null,
396 event.oldValue() != null ?
397 event.oldValue().map(valueDecoder) : null));
398 }
399 }
400}