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;
16 import org.slf4j.LoggerFactory;
18 import com.fasterxml.jackson.databind.JsonNode;
21 public abstract class ColumnType {
26 public long getMin() {
30 void setMin(long min) {
34 public long getMax() {
38 void setMax(long max) {
42 private static ColumnType columns[] = new ColumnType[]{
43 new AtomicColumnType(),
44 new KeyValuedColumnType()
52 public ColumnType(BaseType baseType) {
53 this.baseType = baseType;
56 public BaseType getBaseType() {
63 "maxInteger": 4294967295,
77 public static ColumnType fromJson(JsonNode json) {
78 for (ColumnType colType : columns) {
79 ColumnType columnType = colType.fromJsonNode(json);
80 if (null != columnType) {
84 //todo move to speicfic typed exception
85 throw new TyperException(String.format("could not find the right column type %s",
86 JsonUtils.prettyString(json)));
91 * Creates a ColumnType from the JsonNode if the implementation knows how to, returns null otherwise
93 * @param json the JSONNode object that needs to converted
94 * @return a valid SubType or Null (if the JsonNode does not represent
97 protected abstract ColumnType fromJsonNode(JsonNode json);
100 * Per RFC 7047, Section 3.2 <type> :
101 * If "min" or "max" is not specified, each defaults to 1. If "max" is specified as "unlimited", then there is no specified maximum
102 * number of elements, although the implementation will 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() {
118 return "ColumnType{" +
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) {
142 if (getClass() != obj.getClass())
144 ColumnType other = (ColumnType) obj;
145 if (baseType == null) {
146 if (other.baseType != null)
148 } else if (!baseType.equals(other.baseType))
150 if (max != other.max)
152 if (min != other.min)
157 public static class AtomicColumnType extends ColumnType {
158 static final org.slf4j.Logger logger = LoggerFactory.getLogger(AtomicColumnType.class);
159 public AtomicColumnType() {
162 public AtomicColumnType(BaseType baseType1) {
167 public AtomicColumnType fromJsonNode(JsonNode json) {
168 if (json.isObject() && json.has("value")) {
171 BaseType baseType = BaseType.fromJson(json, "key");
173 if (baseType != null) {
175 AtomicColumnType atomicColumnType = new AtomicColumnType(baseType);
177 JsonNode node = null;
178 if ((node = json.get("min")) != null) {
179 atomicColumnType.setMin(node.asLong());
182 if ((node = json.get("max")) != null) {
183 if (node.isNumber()){
184 atomicColumnType.setMax(node.asLong());
185 } else if ("unlimited".equals(node.asText())) {
186 atomicColumnType.setMax(Long.MAX_VALUE);
189 return atomicColumnType;
196 public Object valueFromJson(JsonNode value) {
197 if (isMultiValued()) {
198 OvsdbSet<Object> result = new OvsdbSet<Object>();
199 if(value.isArray()) {
200 if (value.size() == 2) {
201 if (value.get(0).isTextual() && "set".equals(value.get(0).asText())) {
202 for(JsonNode node: value.get(1)) {
203 result.add(getBaseType().toValue(node));
206 result.add(getBaseType().toValue(value));
210 result.add(getBaseType().toValue(value));
214 return getBaseType().toValue(value);
219 public void validate(Object value) {
220 this.baseType.validate(value);
225 public static class KeyValuedColumnType extends ColumnType {
228 public BaseType getKeyType() {
232 public KeyValuedColumnType() {
235 public KeyValuedColumnType(BaseType keyType, BaseType valueType) {
237 this.keyType = keyType;
241 public KeyValuedColumnType fromJsonNode(JsonNode json) {
242 if (json.isValueNode() || !json.has("value")) {
245 BaseType keyType = BaseType.fromJson(json, "key");
246 BaseType valueType = BaseType.fromJson(json, "value");
248 KeyValuedColumnType keyValueColumnType = new KeyValuedColumnType(keyType, valueType);
249 JsonNode node = null;
250 if ((node = json.get("min")) != null) {
251 keyValueColumnType.setMin(node.asLong());
254 if ((node = json.get("max")) != null) {
256 keyValueColumnType.setMax(node.asLong());
257 } else if (node.isTextual() && "unlimited".equals(node.asText())) {
258 keyValueColumnType.setMax(Long.MAX_VALUE);
262 return keyValueColumnType;
266 public Object valueFromJson(JsonNode node) {
267 if (node.isArray()) {
268 if (node.size() == 2) {
269 if (node.get(0).isTextual() && "map".equals(node.get(0).asText())) {
270 OvsdbMap<Object, Object> map = new OvsdbMap<Object, Object>();
271 for (JsonNode pairNode : node.get(1)) {
272 if (pairNode.isArray() && node.size() == 2) {
273 Object key = getKeyType().toValue(pairNode.get(0));
274 Object value = getBaseType().toValue(pairNode.get(1));
279 } else if (node.size() == 0) {
288 public void validate(Object value) {
289 this.baseType.validate(value);
293 public String toString() {
294 return "KeyValuedColumnType [keyType=" + keyType + " "+ super.toString() +"]";
298 public int hashCode() {
299 final int prime = 31;
300 int result = super.hashCode();
301 result = prime * result
302 + ((keyType == null) ? 0 : keyType.hashCode());
307 public boolean equals(Object obj) {
310 if (!super.equals(obj))
312 if (getClass() != obj.getClass())
314 KeyValuedColumnType other = (KeyValuedColumnType) obj;
315 if (keyType == null) {
316 if (other.keyType != null)
318 } else if (!keyType.equals(other.keyType))