/*
* Copyright (c) 2014, 2015 EBay Software Foundation and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.ovsdb.lib.schema;
import com.fasterxml.jackson.databind.JsonNode;
import org.opendaylight.ovsdb.lib.error.TyperException;
import org.opendaylight.ovsdb.lib.jsonrpc.JsonUtils;
import org.opendaylight.ovsdb.lib.notation.OvsdbMap;
import org.opendaylight.ovsdb.lib.notation.OvsdbSet;
public abstract class ColumnType {
BaseType baseType;
long min = 1;
long max = 1;
public long getMin() {
return min;
}
void setMin(long min) {
this.min = min;
}
public long getMax() {
return max;
}
void setMax(long max) {
this.max = max;
}
private static ColumnType[] columns = new ColumnType[] {
new AtomicColumnType(),
new KeyValuedColumnType()
};
public ColumnType() {
}
public ColumnType(BaseType baseType) {
this.baseType = baseType;
}
public BaseType getBaseType() {
return baseType;
}
/**
* JSON.
*
*/
public static ColumnType fromJson(JsonNode json) {
for (ColumnType colType : columns) {
ColumnType columnType = colType.fromJsonNode(json);
if (null != columnType) {
return columnType;
}
}
//todo move to speicfic typed exception
throw new TyperException(String.format("could not find the right column type %s",
JsonUtils.prettyString(json)));
}
/**
* Creates a ColumnType from the JsonNode if the implementation knows how to, returns null otherwise.
*
* @param json the JSONNode object that needs to converted
* @return a valid SubType or Null (if the JsonNode does not represent the subtype)
*/
protected abstract ColumnType fromJsonNode(JsonNode json);
/*
* Per RFC 7047, Section 3.2 :
* If "min" or "max" is not specified, each defaults to 1. If "max" is specified as "unlimited",
* then there is no specified maximum number of elements, although the implementation will
* enforce some limit. After considering defaults, "min" must be exactly 0 or
* exactly 1, "max" must be at least 1, and "max" must be greater than or equal to "min".
*
* If "min" and "max" are both 1 and "value" is not specified, the
* type is the scalar type specified by "key".
*/
public boolean isMultiValued() {
return this.min != this.max;
}
public abstract Object valueFromJson(JsonNode value);
public abstract void validate(Object value);
@Override
public String toString() {
return "ColumnType{"
+ "baseType=" + baseType
+ ", min=" + min
+ ", max=" + max
+ '}';
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((baseType == null) ? 0 : baseType.hashCode());
result = prime * result + (int) (max ^ (max >>> 32));
result = prime * result + (int) (min ^ (min >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ColumnType other = (ColumnType) obj;
if (baseType == null) {
if (other.baseType != null) {
return false;
}
} else if (!baseType.equals(other.baseType)) {
return false;
}
if (max != other.max) {
return false;
}
if (min != other.min) {
return false;
}
return true;
}
public static class AtomicColumnType extends ColumnType {
public AtomicColumnType() {
}
public AtomicColumnType(BaseType baseType) {
super(baseType);
}
@Override
public AtomicColumnType fromJsonNode(JsonNode json) {
if (json.isObject() && json.has("value")) {
return null;
}
BaseType jsonBaseType = BaseType.fromJson(json, "key");
if (jsonBaseType != null) {
AtomicColumnType atomicColumnType = new AtomicColumnType(jsonBaseType);
JsonNode node;
if ((node = json.get("min")) != null) {
atomicColumnType.setMin(node.asLong());
}
if ((node = json.get("max")) != null) {
if (node.isNumber()) {
atomicColumnType.setMax(node.asLong());
} else if ("unlimited".equals(node.asText())) {
atomicColumnType.setMax(Long.MAX_VALUE);
}
}
return atomicColumnType;
}
return null;
}
@Override
public Object valueFromJson(JsonNode value) {
if (isMultiValued()) {
OvsdbSet