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