blob: c8151e36a6021c94168d57e6fa212ac40c1ba358 [file] [log] [blame]
Madan Jampani5e5b3d62016-02-01 16:03:33 -08001/*
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 */
16
Madan Jampani74da78b2016-02-09 21:18:36 -080017package org.onosproject.store.primitives;
Madan Jampani5e5b3d62016-02-01 16:03:33 -080018
Madan Jampani5e5b3d62016-02-01 16:03:33 -080019import static com.google.common.base.Preconditions.checkNotNull;
20import static com.google.common.base.Preconditions.checkState;
21
Madan Jampani74da78b2016-02-09 21:18:36 -080022import java.util.function.Function;
23
Madan Jampani5e5b3d62016-02-01 16:03:33 -080024import com.google.common.base.MoreObjects;
25
26/**
27 * Map update operation.
28 *
29 * @param <K> map key type
30 * @param <V> map value type
31 *
32 */
33public final class MapUpdate<K, V> {
34
35 /**
36 * Type of database update operation.
37 */
38 public enum Type {
39 /**
40 * Insert/Update entry without any checks.
41 */
42 PUT,
43 /**
44 * Insert an entry iff there is no existing entry for that key.
45 */
46 PUT_IF_ABSENT,
47
48 /**
49 * Update entry if the current version matches specified version.
50 */
51 PUT_IF_VERSION_MATCH,
52
53 /**
54 * Update entry if the current value matches specified value.
55 */
56 PUT_IF_VALUE_MATCH,
57
58 /**
59 * Remove entry without any checks.
60 */
61 REMOVE,
62
63 /**
64 * Remove entry if the current version matches specified version.
65 */
66 REMOVE_IF_VERSION_MATCH,
67
68 /**
69 * Remove entry if the current value matches specified value.
70 */
71 REMOVE_IF_VALUE_MATCH,
72 }
73
Madan Jampanicadd70b2016-02-08 13:45:43 -080074 private String mapName;
Madan Jampani5e5b3d62016-02-01 16:03:33 -080075 private Type type;
76 private K key;
77 private V value;
78 private V currentValue;
79 private long currentVersion = -1;
80
81 /**
Madan Jampanicadd70b2016-02-08 13:45:43 -080082 * Returns the name of the map.
83 *
84 * @return map name
85 */
86 public String mapName() {
87 return mapName;
88 }
89
90 /**
Madan Jampani5e5b3d62016-02-01 16:03:33 -080091 * Returns the type of update operation.
92 * @return type of update.
93 */
94 public Type type() {
95 return type;
96 }
97
98 /**
99 * Returns the item key being updated.
100 * @return item key
101 */
102 public K key() {
103 return key;
104 }
105
106 /**
107 * Returns the new value.
108 * @return item's target value.
109 */
110 public V value() {
111 return value;
112 }
113
114 /**
115 * Returns the expected current value for the key.
116 * @return current value in database.
117 */
118 public V currentValue() {
119 return currentValue;
120 }
121
122 /**
123 * Returns the expected current version in the database for the key.
124 * @return expected version.
125 */
126 public long currentVersion() {
127 return currentVersion;
128 }
129
Madan Jampani74da78b2016-02-09 21:18:36 -0800130 /**
131 * Transforms this instance into an instance of different paramterized types.
132 *
133 * @param keyMapper transcoder for key type
134 * @param valueMapper transcoder to value type
135 * @return new instance
136 * @param <S> key type of returned instance
137 * @param <T> value type of returned instance
138 */
139 public <S, T> MapUpdate<S, T> map(Function<K, S> keyMapper, Function<V, T> valueMapper) {
140 return MapUpdate.<S, T>newBuilder()
141 .withMapName(mapName)
142 .withType(type)
143 .withKey(keyMapper.apply(key))
144 .withValue(value == null ? null : valueMapper.apply(value))
145 .withCurrentValue(currentValue == null ? null : valueMapper.apply(currentValue))
146 .withCurrentVersion(currentVersion)
147 .build();
148 }
149
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800150 @Override
151 public String toString() {
152 return MoreObjects.toStringHelper(this)
Madan Jampanicadd70b2016-02-08 13:45:43 -0800153 .add("mapName", mapName)
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800154 .add("type", type)
155 .add("key", key)
156 .add("value", value)
157 .add("currentValue", currentValue)
158 .add("currentVersion", currentVersion)
159 .toString();
160 }
161
162 /**
163 * Creates a new builder instance.
164 *
165 * @param <K> key type
166 * @param <V> value type
167 * @return builder.
168 */
169 public static <K, V> Builder<K, V> newBuilder() {
170 return new Builder<>();
171 }
172
173 /**
174 * MapUpdate builder.
175 *
176 * @param <K> key type
177 * @param <V> value type
178 */
179 public static final class Builder<K, V> {
180
181 private MapUpdate<K, V> update = new MapUpdate<>();
182
183 public MapUpdate<K, V> build() {
184 validateInputs();
185 return update;
186 }
187
Madan Jampanicadd70b2016-02-08 13:45:43 -0800188 public Builder<K, V> withMapName(String name) {
189 update.mapName = checkNotNull(name, "name cannot be null");
190 return this;
191 }
192
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800193 public Builder<K, V> withType(Type type) {
194 update.type = checkNotNull(type, "type cannot be null");
195 return this;
196 }
197
198 public Builder<K, V> withKey(K key) {
199 update.key = checkNotNull(key, "key cannot be null");
200 return this;
201 }
202
203 public Builder<K, V> withCurrentValue(V value) {
Madan Jampani74da78b2016-02-09 21:18:36 -0800204 update.currentValue = value;
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800205 return this;
206 }
207
208 public Builder<K, V> withValue(V value) {
Madan Jampani74da78b2016-02-09 21:18:36 -0800209 update.value = value;
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800210 return this;
211 }
212
213 public Builder<K, V> withCurrentVersion(long version) {
Madan Jampani5e5b3d62016-02-01 16:03:33 -0800214 update.currentVersion = version;
215 return this;
216 }
217
218 private void validateInputs() {
219 checkNotNull(update.type, "type must be specified");
220 checkNotNull(update.key, "key must be specified");
221 switch (update.type) {
222 case PUT:
223 case PUT_IF_ABSENT:
224 checkNotNull(update.value, "value must be specified.");
225 break;
226 case PUT_IF_VERSION_MATCH:
227 checkNotNull(update.value, "value must be specified.");
228 checkState(update.currentVersion >= 0, "current version must be specified");
229 break;
230 case PUT_IF_VALUE_MATCH:
231 checkNotNull(update.value, "value must be specified.");
232 checkNotNull(update.currentValue, "currentValue must be specified.");
233 break;
234 case REMOVE:
235 break;
236 case REMOVE_IF_VERSION_MATCH:
237 checkState(update.currentVersion >= 0, "current version must be specified");
238 break;
239 case REMOVE_IF_VALUE_MATCH:
240 checkNotNull(update.currentValue, "currentValue must be specified.");
241 break;
242 default:
243 throw new IllegalStateException("Unknown operation type");
244 }
245 }
246 }
247}