2 * Copyright (C) 2014 EBay Software Foundation
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
8 * Authors : Ashwin Raveendran
10 package org.opendaylight.ovsdb.lib.schema;
12 import org.opendaylight.ovsdb.lib.error.TyperException;
13 import org.opendaylight.ovsdb.lib.jsonrpc.JsonUtils;
14 import org.opendaylight.ovsdb.lib.notation.OvsdbMap;
15 import org.opendaylight.ovsdb.lib.notation.OvsdbSet;
17 import com.fasterxml.jackson.databind.JsonNode;
20 public abstract class ColumnType {
25 public long getMin() {
29 void setMin(long min) {
33 public long getMax() {
37 void setMax(long max) {
41 private static ColumnType[] columns = new ColumnType[] {
42 new AtomicColumnType(),
43 new KeyValuedColumnType()
51 public ColumnType(BaseType baseType) {
52 this.baseType = baseType;
55 public BaseType getBaseType() {
62 "maxInteger": 4294967295,
76 public static ColumnType fromJson(JsonNode json) {
77 for (ColumnType colType : columns) {
78 ColumnType columnType = colType.fromJsonNode(json);
79 if (null != columnType) {
83 //todo move to speicfic typed exception
84 throw new TyperException(String.format("could not find the right column type %s",
85 JsonUtils.prettyString(json)));
90 * Creates a ColumnType from the JsonNode if the implementation knows how to, returns null otherwise
92 * @param json the JSONNode object that needs to converted
93 * @return a valid SubType or Null (if the JsonNode does not represent
96 protected abstract ColumnType fromJsonNode(JsonNode json);
99 * Per RFC 7047, Section 3.2 <type> :
100 * If "min" or "max" is not specified, each defaults to 1. If "max" is specified as "unlimited",
101 * then there is no specified maximum number of elements, although the implementation will
102 * enforce some limit. After considering defaults, "min" must be exactly 0 or
103 * exactly 1, "max" must be at least 1, and "max" must be greater than or equal to "min".
105 * If "min" and "max" are both 1 and "value" is not specified, the
106 * type is the scalar type specified by "key".
108 public boolean isMultiValued() {
109 return this.min != this.max;
112 public abstract Object valueFromJson(JsonNode value);
114 public abstract void validate(Object value);
117 public String toString() {
119 + "baseType=" + baseType
126 public int hashCode() {
127 final int prime = 31;
129 result = prime * result
130 + ((baseType == null) ? 0 : baseType.hashCode());
131 result = prime * result + (int) (max ^ (max >>> 32));
132 result = prime * result + (int) (min ^ (min >>> 32));
137 public boolean equals(Object obj) {
144 if (getClass() != obj.getClass()) {
147 ColumnType other = (ColumnType) obj;
148 if (baseType == null) {
149 if (other.baseType != null) {
152 } else if (!baseType.equals(other.baseType)) {
155 if (max != other.max) {
158 if (min != other.min) {
164 public static class AtomicColumnType extends ColumnType {
165 public AtomicColumnType() {
168 public AtomicColumnType(BaseType baseType1) {
173 public AtomicColumnType fromJsonNode(JsonNode json) {
174 if (json.isObject() && json.has("value")) {
177 BaseType baseType = BaseType.fromJson(json, "key");
179 if (baseType != null) {
181 AtomicColumnType atomicColumnType = new AtomicColumnType(baseType);
184 if ((node = json.get("min")) != null) {
185 atomicColumnType.setMin(node.asLong());
188 if ((node = json.get("max")) != null) {
189 if (node.isNumber()) {
190 atomicColumnType.setMax(node.asLong());
191 } else if ("unlimited".equals(node.asText())) {
192 atomicColumnType.setMax(Long.MAX_VALUE);
195 return atomicColumnType;
202 public Object valueFromJson(JsonNode value) {
203 if (isMultiValued()) {
204 OvsdbSet<Object> result = new OvsdbSet<>();
205 if (value.isArray()) {
206 if (value.size() == 2) {
207 if (value.get(0).isTextual() && "set".equals(value.get(0).asText())) {
208 for (JsonNode node: value.get(1)) {
209 result.add(getBaseType().toValue(node));
212 result.add(getBaseType().toValue(value));
216 result.add(getBaseType().toValue(value));
220 return getBaseType().toValue(value);
225 public void validate(Object value) {
226 this.baseType.validate(value);
231 public static class KeyValuedColumnType extends ColumnType {
234 public BaseType getKeyType() {
238 public KeyValuedColumnType() {
241 public KeyValuedColumnType(BaseType keyType, BaseType valueType) {
243 this.keyType = keyType;
247 public KeyValuedColumnType fromJsonNode(JsonNode json) {
248 if (json.isValueNode() || !json.has("value")) {
251 BaseType keyType = BaseType.fromJson(json, "key");
252 BaseType valueType = BaseType.fromJson(json, "value");
254 KeyValuedColumnType keyValueColumnType = new KeyValuedColumnType(keyType, valueType);
256 if ((node = json.get("min")) != null) {
257 keyValueColumnType.setMin(node.asLong());
260 if ((node = json.get("max")) != null) {
262 keyValueColumnType.setMax(node.asLong());
263 } else if (node.isTextual() && "unlimited".equals(node.asText())) {
264 keyValueColumnType.setMax(Long.MAX_VALUE);
268 return keyValueColumnType;
272 public Object valueFromJson(JsonNode node) {
273 if (node.isArray()) {
274 if (node.size() == 2) {
275 if (node.get(0).isTextual() && "map".equals(node.get(0).asText())) {
276 OvsdbMap<Object, Object> map = new OvsdbMap<>();
277 for (JsonNode pairNode : node.get(1)) {
278 if (pairNode.isArray() && node.size() == 2) {
279 Object key = getKeyType().toValue(pairNode.get(0));
280 Object value = getBaseType().toValue(pairNode.get(1));
285 } else if (node.size() == 0) {
294 public void validate(Object value) {
295 this.baseType.validate(value);
299 public String toString() {
300 return "KeyValuedColumnType [keyType=" + keyType + " " + super.toString() + "]";
304 public int hashCode() {
305 final int prime = 31;
306 int result = super.hashCode();
307 result = prime * result
308 + ((keyType == null) ? 0 : keyType.hashCode());
313 public boolean equals(Object obj) {
317 if (!super.equals(obj)) {
320 if (getClass() != obj.getClass()) {
323 KeyValuedColumnType other = (KeyValuedColumnType) obj;
324 if (keyType == null) {
325 if (other.keyType != null) {
328 } else if (!keyType.equals(other.keyType)) {