Schema independent plugin insert operation for a traditional single Row & more advanc...
[ovsdb.git] / library / src / main / java / org / opendaylight / ovsdb / lib / schema / BaseType.java
1 /*
2  * Copyright (C) 2014 EBay Software Foundation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Authors : Ashwin Raveendran
9  */
10 package org.opendaylight.ovsdb.lib.schema;
11
12 import java.util.Set;
13
14 import org.opendaylight.ovsdb.lib.error.TyperException;
15 import org.opendaylight.ovsdb.lib.notation.ReferencedRow;
16 import org.opendaylight.ovsdb.lib.notation.UUID;
17
18 import com.fasterxml.jackson.databind.JsonNode;
19 import com.google.common.collect.Sets;
20
21 public abstract class BaseType<E extends BaseType<E>> {
22
23     private static BaseType[] types = new BaseType[]{
24             new StringBaseType(),
25             new IntegerBaseType(),
26             new RealBaseType(),
27             new BooleanBaseType(),
28             new UuidBaseType(),
29     };
30
31     public static BaseType fromJson(JsonNode json, String keyorval) {
32         BaseType baseType = null;
33         if (json.isValueNode()) {
34             for (BaseType baseTypeFactory : types) {
35                 String type = json.asText().trim();
36                 baseType = baseTypeFactory.fromString(type);
37                 if (baseType != null) {
38                     break;
39                 }
40             }
41         } else {
42             if (!json.has(keyorval)) {
43                 throw new TyperException("Not a type");
44             }
45
46             for (BaseType baseTypeFactory : types) {
47                 baseType = baseTypeFactory.fromJsonNode(json.get(keyorval), keyorval);
48                 if (baseType != null) {
49                     break;
50                 }
51             }
52         }
53         return baseType;
54     }
55
56     protected abstract E fromString(String type);
57
58     protected abstract void getConstraints(E baseType, JsonNode type);
59
60     protected E fromJsonNode(JsonNode type, String keyorval) {
61
62         E baseType = null;
63
64         //json like  "string"
65         if (type.isTextual()) {
66             baseType = fromString(type.asText());
67             if (baseType != null) {
68                 return baseType;
69             }
70         }
71
72         //json like  {"type" : "string", "enum": ["set", ["access", "native-tagged"]]}" for key or value
73         if (type.isObject() && type.has("type")) {
74             baseType = fromString(type.get("type").asText());
75             if (baseType != null) {
76                 getConstraints(baseType, type);
77             }
78         }
79
80         return baseType;
81     }
82
83     public abstract Object toValue(JsonNode value);
84
85     public abstract void validate(Object value);
86
87     public static class IntegerBaseType extends BaseType<IntegerBaseType> {
88         long min = Long.MIN_VALUE;
89         long max = Long.MAX_VALUE;
90         Set<Integer> enums;
91
92         @Override
93         public IntegerBaseType fromString(String typeString) {
94             return "integer".equals(typeString) ? new IntegerBaseType() : null;
95         }
96
97         @Override
98         protected void getConstraints(IntegerBaseType baseType, JsonNode type) {
99
100             JsonNode node = null;
101
102             if ((node = type.get("maxInteger")) != null) {
103                 baseType.setMax(node.asLong());
104             }
105
106             if ((node = type.get("minInteger")) != null) {
107                 baseType.setMin(node.asLong());
108             }
109
110             populateEnum(type);
111         }
112
113         @Override
114         public Object toValue(JsonNode value) {
115             return value.asLong();
116         }
117
118         @Override
119         public void validate(Object value) {
120
121         }
122
123         private void populateEnum(JsonNode node) {
124             if (node.has("enum")) {
125                 Set<Long> s = Sets.newHashSet();
126                 JsonNode anEnum = node.get("enum").get(1);
127                 for (JsonNode n : anEnum) {
128                     s.add(n.asLong());
129                 }
130             }
131         }
132
133
134         public long getMin() {
135             return min;
136         }
137
138         public void setMin(long min) {
139             this.min = min;
140         }
141
142         public long getMax() {
143             return max;
144         }
145
146         public void setMax(long max) {
147             this.max = max;
148         }
149
150         public Set<Integer> getEnums() {
151             return enums;
152         }
153
154         public void setEnums(Set<Integer> enums) {
155             this.enums = enums;
156         }
157
158         @Override
159         public String toString() {
160             return "IntegerBaseType";
161         }
162
163         @Override
164         public int hashCode() {
165             final int prime = 31;
166             int result = 1;
167             result = prime * result + ((enums == null) ? 0 : enums.hashCode());
168             result = prime * result + (int) (max ^ (max >>> 32));
169             result = prime * result + (int) (min ^ (min >>> 32));
170             return result;
171         }
172
173         @Override
174         public boolean equals(Object obj) {
175             if (this == obj)
176                 return true;
177             if (obj == null)
178                 return false;
179             if (getClass() != obj.getClass())
180                 return false;
181             IntegerBaseType other = (IntegerBaseType) obj;
182             if (enums == null) {
183                 if (other.enums != null)
184                     return false;
185             } else if (!enums.equals(other.enums))
186                 return false;
187             if (max != other.max)
188                 return false;
189             if (min != other.min)
190                 return false;
191             return true;
192         }
193     }
194
195     public static class RealBaseType extends BaseType<RealBaseType> {
196         double min = Double.MIN_VALUE;
197         double max = Double.MAX_VALUE;
198         Set<Double> enums;
199
200         @Override
201         public RealBaseType fromString(String typeString) {
202             return "real".equals(typeString) ? new RealBaseType() : null;
203         }
204
205         @Override
206         protected void getConstraints(RealBaseType baseType, JsonNode type) {
207
208             JsonNode node = null;
209
210             if ((node = type.get("maxReal")) != null) {
211                 baseType.setMax(node.asLong());
212             }
213
214             if ((node = type.get("minReal")) != null) {
215                 baseType.setMin(node.asLong());
216             }
217
218             populateEnum(type);
219         }
220
221         @Override
222         public Object toValue(JsonNode value) {
223             return value.asDouble();
224         }
225
226         @Override
227         public void validate(Object value) {
228
229         }
230
231         private void populateEnum(JsonNode node) {
232             if (node.has("enum")) {
233                 Set<Double> s = Sets.newHashSet();
234                 JsonNode anEnum = node.get("enum").get(1);
235                 for (JsonNode n : anEnum) {
236                     s.add(n.asDouble());
237                 }
238             }
239         }
240
241         public double getMin() {
242             return min;
243         }
244
245         public void setMin(double min) {
246             this.min = min;
247         }
248
249         public double getMax() {
250             return max;
251         }
252
253         public void setMax(double max) {
254             this.max = max;
255         }
256
257         public Set<Double> getEnums() {
258             return enums;
259         }
260
261         public void setEnums(Set<Double> enums) {
262             this.enums = enums;
263         }
264
265         @Override
266         public String toString() {
267             return "RealBaseType";
268         }
269
270         @Override
271         public int hashCode() {
272             final int prime = 31;
273             int result = 1;
274             result = prime * result + ((enums == null) ? 0 : enums.hashCode());
275             long temp;
276             temp = Double.doubleToLongBits(max);
277             result = prime * result + (int) (temp ^ (temp >>> 32));
278             temp = Double.doubleToLongBits(min);
279             result = prime * result + (int) (temp ^ (temp >>> 32));
280             return result;
281         }
282
283         @Override
284         public boolean equals(Object obj) {
285             if (this == obj)
286                 return true;
287             if (obj == null)
288                 return false;
289             if (getClass() != obj.getClass())
290                 return false;
291             RealBaseType other = (RealBaseType) obj;
292             if (enums == null) {
293                 if (other.enums != null)
294                     return false;
295             } else if (!enums.equals(other.enums))
296                 return false;
297             if (Double.doubleToLongBits(max) != Double
298                     .doubleToLongBits(other.max))
299                 return false;
300             if (Double.doubleToLongBits(min) != Double
301                     .doubleToLongBits(other.min))
302                 return false;
303             return true;
304         }
305     }
306
307
308     public static class BooleanBaseType extends BaseType {
309
310         @Override
311         public BooleanBaseType fromString(String typeString) {
312             return "boolean".equals(typeString) ? new BooleanBaseType() : null;
313         }
314
315         @Override
316         protected void getConstraints(BaseType baseType, JsonNode node) {
317             //no op
318         }
319
320         @Override
321         public Object toValue(JsonNode value) {
322             return value.asBoolean();
323         }
324
325         @Override
326         public void validate(Object value) {
327
328         }
329
330         @Override
331         public String toString() {
332             return "BooleanBaseType";
333         }
334     }
335
336     public static class StringBaseType extends BaseType<StringBaseType> {
337         int minLength = Integer.MIN_VALUE;
338         int maxLength = Integer.MAX_VALUE;
339         Set<String> enums;
340
341         @Override
342         public StringBaseType fromString(String typeString) {
343             return "string".equals(typeString) ? new StringBaseType() : null;
344         }
345
346         @Override
347         protected void getConstraints(StringBaseType baseType, JsonNode type) {
348
349             JsonNode node = null;
350
351             if ((node = type.get("maxLength")) != null) {
352                 baseType.setMaxLength(node.asInt());
353             }
354
355             if ((node = type.get("minLength")) != null) {
356                 baseType.setMinLength(node.asInt());
357             }
358
359             populateEnum(baseType, type);
360         }
361
362         @Override
363         public Object toValue(JsonNode value) {
364             return value.asText();
365         }
366
367         @Override
368         public void validate(Object value) {
369
370         }
371
372         private void populateEnum(StringBaseType baseType, JsonNode node) {
373             if (node.has("enum")) {
374                 Set<String> s = Sets.newHashSet();
375                 JsonNode enumVal = node.get("enum");
376                 if (enumVal.isArray()) {
377                     JsonNode anEnum = enumVal.get(1);
378                     for (JsonNode n : anEnum) {
379                         s.add(n.asText());
380                     }
381                 } else if (enumVal.isTextual()) {
382                     s.add(enumVal.asText());
383                 }
384                 baseType.setEnums(s);
385             }
386         }
387
388         public int getMinLength() {
389             return minLength;
390         }
391
392         public void setMinLength(int minLength) {
393             this.minLength = minLength;
394         }
395
396         public int getMaxLength() {
397             return maxLength;
398         }
399
400         public void setMaxLength(int maxLength) {
401             this.maxLength = maxLength;
402         }
403
404         public Set<String> getEnums() {
405             return enums;
406         }
407
408         public void setEnums(Set<String> enums) {
409             this.enums = enums;
410         }
411
412         @Override
413         public String toString() {
414             return "StringBaseType";
415         }
416
417         @Override
418         public int hashCode() {
419             final int prime = 31;
420             int result = 1;
421             result = prime * result + ((enums == null) ? 0 : enums.hashCode());
422             result = prime * result + maxLength;
423             result = prime * result + minLength;
424             return result;
425         }
426
427         @Override
428         public boolean equals(Object obj) {
429             if (this == obj)
430                 return true;
431             if (obj == null)
432                 return false;
433             if (getClass() != obj.getClass())
434                 return false;
435             StringBaseType other = (StringBaseType) obj;
436             if (enums == null) {
437                 if (other.enums != null)
438                     return false;
439             } else if (!enums.equals(other.enums))
440                 return false;
441             if (maxLength != other.maxLength)
442                 return false;
443             if (minLength != other.minLength)
444                 return false;
445             return true;
446         }
447
448     }
449
450
451     public static class UuidBaseType extends BaseType<UuidBaseType> {
452         public static enum RefType {strong, weak}
453
454         String refTable;
455         RefType refType;
456
457
458         @Override
459         public UuidBaseType fromString(String typeString) {
460             return "uuid".equals(typeString) ? new UuidBaseType() : null;
461         }
462
463         @Override
464         protected void getConstraints(UuidBaseType baseType, JsonNode node) {
465
466             JsonNode refTable = node.get("refTable");
467             baseType.setRefTable(refTable != null ? refTable.asText() : null);
468
469             JsonNode refTypeJson = node.get("refType");
470             baseType.setRefType(refTypeJson != null ? RefType.valueOf(refTypeJson.asText()) : RefType.strong);
471
472         }
473
474         @Override
475         public Object toValue(JsonNode value) {
476             if(value.isArray()) {
477                 if (value.size() == 2) {
478                     if (value.get(0).isTextual() && "uuid".equals(value.get(0).asText())) {
479                         return new UUID(value.get(1).asText());
480                     }
481                 }
482             } else {
483                 /*
484                  * UUIDBaseType used by RefTable from SouthBound will always be an Array of ["uuid", <uuid>].
485                  * But there are some cases from northbound where the RefTable type can be expanded to a Row
486                  * with contents. In those scenarios, just retain the content and return a ReferencedRow for
487                  * the upper layer functions to process it.
488                  */
489                 return new ReferencedRow(refTable, value);
490             }
491             return null;
492         }
493
494         @Override
495         public void validate(Object value) {
496
497         }
498
499         public String getRefTable() {
500             return refTable;
501         }
502
503         public void setRefTable(String refTable) {
504             this.refTable = refTable;
505         }
506
507         public RefType getRefType() {
508             return refType;
509         }
510
511         public void setRefType(RefType refType) {
512             this.refType = refType;
513         }
514
515         @Override
516         public String toString() {
517             return "UuidBaseType";
518         }
519
520         @Override
521         public int hashCode() {
522             final int prime = 31;
523             int result = 1;
524             result = prime * result
525                     + ((refTable == null) ? 0 : refTable.hashCode());
526             result = prime * result
527                     + ((refType == null) ? 0 : refType.hashCode());
528             return result;
529         }
530
531         @Override
532         public boolean equals(Object obj) {
533             if (this == obj)
534                 return true;
535             if (obj == null)
536                 return false;
537             if (getClass() != obj.getClass())
538                 return false;
539             UuidBaseType other = (UuidBaseType) obj;
540             if (refTable == null) {
541                 if (other.refTable != null)
542                     return false;
543             } else if (!refTable.equals(other.refTable))
544                 return false;
545             if (refType != other.refType)
546                 return false;
547             return true;
548         }
549     }
550 }