blob: c45f696a8db6dcf90aef10a836ddbecb40ed2a33 [file] [log] [blame]
Ray Milkey6f440332015-07-31 10:40:53 -07001/*
2 * Copyright 2015 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 */
16package org.onosproject.store.service;
17
18import java.util.Collection;
19import java.util.HashMap;
20import java.util.LinkedList;
21import java.util.List;
22import java.util.Map;
23import java.util.Set;
24import java.util.function.BiFunction;
25import java.util.function.Function;
26import java.util.function.Predicate;
27import java.util.stream.Collectors;
28
29import org.onosproject.core.ApplicationId;
30import static org.onosproject.store.service.MapEvent.Type;
31import static org.onosproject.store.service.MapEvent.Type.*;
32
33/**
34 * Test implementation of the consistent map.
35 */
36public final class TestConsistentMap<K, V> extends ConsistentMapAdapter<K, V> {
37
38 private final List<MapEventListener<K, V>> listeners;
39 private final HashMap<K, V> map;
40 private final String mapName;
41
42 private TestConsistentMap(String mapName) {
43 map = new HashMap<>();
44 listeners = new LinkedList<>();
45 this.mapName = mapName;
46 }
47
48 private Versioned<V> version(V v) {
49 return new Versioned<>(v, 1, System.currentTimeMillis());
50 }
51
52 /**
53 * Notify all listeners of an event.
54 */
55 private void notifyListeners(String mapName, Type type,
56 K key, Versioned<V> value) {
57 MapEvent<K, V> event = new MapEvent<>(mapName, type, key, value);
58 listeners.forEach(
59 listener -> listener.event(event)
60 );
61 }
62
63 @Override
64 public int size() {
65 return map.size();
66 }
67
68 @Override
69 public boolean isEmpty() {
70 return map.isEmpty();
71 }
72
73 @Override
74 public boolean containsKey(K key) {
75 return map.containsKey(key);
76 }
77
78 @Override
79 public boolean containsValue(V value) {
80 return map.containsValue(value);
81 }
82
83 @Override
84 public Versioned<V> get(K key) {
Ray Milkey24e60b32015-08-12 11:39:54 -070085 V value = map.get(key);
86 if (value != null) {
87 return version(value);
88 } else {
89 return null;
90 }
Ray Milkey6f440332015-07-31 10:40:53 -070091 }
92
93 @Override
94 public Versioned<V> computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
95 Versioned<V> result = version(map.computeIfAbsent(key, mappingFunction));
96 notifyListeners(mapName, INSERT, key, result);
97 return result;
98 }
99
100 @Override
101 public Versioned<V> compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
102 return version(map.compute(key, remappingFunction));
103 }
104
105 @Override
106 public Versioned<V> computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
107 return version(map.computeIfPresent(key, remappingFunction));
108 }
109
110 @Override
111 public Versioned<V> computeIf(K key, Predicate<? super V> condition,
112 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
113 return null;
114 }
115
116 @Override
117 public Versioned<V> put(K key, V value) {
118 Versioned<V> result = version(map.put(key, value));
119 notifyListeners(mapName, INSERT, key, result);
120 return result;
121 }
122
123 @Override
124 public Versioned<V> putAndGet(K key, V value) {
125 Versioned<V> result = version(map.put(key, value));
126 notifyListeners(mapName, UPDATE, key, result);
127 return result;
128 }
129
130 @Override
131 public Versioned<V> remove(K key) {
132 Versioned<V> result = version(map.remove(key));
133 notifyListeners(mapName, REMOVE, key, result);
134 return result;
135 }
136
137 @Override
138 public void clear() {
139 map.clear();
140 }
141
142 @Override
143 public Set<K> keySet() {
144 return map.keySet();
145 }
146
147 @Override
148 public Collection<Versioned<V>> values() {
149 return map
150 .values()
151 .stream()
152 .map(this::version)
153 .collect(Collectors.toList());
154 }
155
156 @Override
157 public Set<Map.Entry<K, Versioned<V>>> entrySet() {
158 return super.entrySet();
159 }
160
161 @Override
162 public Versioned<V> putIfAbsent(K key, V value) {
163 Versioned<V> result = version(map.putIfAbsent(key, value));
164 if (map.get(key).equals(value)) {
165 notifyListeners(mapName, INSERT, key, result);
166 }
167 return result;
168 }
169
170 @Override
171 public boolean remove(K key, V value) {
172 boolean removed = map.remove(key, value);
173 if (removed) {
174 notifyListeners(mapName, REMOVE, key, null);
175 }
176 return removed;
177 }
178
179 @Override
180 public boolean remove(K key, long version) {
181 boolean removed = map.remove(key, version);
182 if (removed) {
183 notifyListeners(mapName, REMOVE, key, null);
184 }
185 return removed;
186 }
187
188 @Override
189 public boolean replace(K key, V oldValue, V newValue) {
190 boolean replaced = map.replace(key, oldValue, newValue);
191 if (replaced) {
192 notifyListeners(mapName, REMOVE, key, null);
193 }
194 return replaced;
195 }
196
197 @Override
198 public boolean replace(K key, long oldVersion, V newValue) {
199 boolean replaced = map.replace(key, map.get(key), newValue);
200 if (replaced) {
201 notifyListeners(mapName, REMOVE, key, null);
202 }
203 return replaced;
204 }
205
206 @Override
207 public void addListener(MapEventListener<K, V> listener) {
208 listeners.add(listener);
209 }
210
211 @Override
212 public void removeListener(MapEventListener<K, V> listener) {
213 listeners.remove(listener);
214 }
215
216 public static Builder builder() {
217 return new Builder();
218 }
219
220 public static class Builder<K, V> implements ConsistentMapBuilder<K, V> {
221 String mapName = "map";
222
223 @Override
224 public ConsistentMapBuilder<K, V> withName(String mapName) {
225 this.mapName = mapName;
226 return this;
227 }
228
229 @Override
230 public ConsistentMapBuilder<K, V> withApplicationId(ApplicationId id) {
231 return this;
232 }
233
234 @Override
235 public ConsistentMapBuilder<K, V> withSerializer(Serializer serializer) {
236 return this;
237 }
238
239 @Override
240 public ConsistentMapBuilder<K, V> withPartitionsDisabled() {
241 return this;
242 }
243
244 @Override
245 public ConsistentMapBuilder<K, V> withUpdatesDisabled() {
246 return this;
247 }
248
249 @Override
250 public ConsistentMapBuilder<K, V> withPurgeOnUninstall() {
251 return this;
252 }
253
254 @Override
Madan Jampani3d6a2f62015-08-12 07:19:07 -0700255 public ConsistentMapBuilder<K, V> withRelaxedReadConsistency() {
256 return this;
257 }
258
259 @Override
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700260 public ConsistentMapBuilder<K, V> withMeteringDisabled() {
261 return this;
262 }
263
264 @Override
Ray Milkey6f440332015-07-31 10:40:53 -0700265 public ConsistentMap<K, V> build() {
266 return new TestConsistentMap<>(mapName);
267 }
268
269 @Override
270 public AsyncConsistentMap<K, V> buildAsyncMap() {
271 return null;
272 }
273
274 }
275
276}