Fixed various classes where the KeyValue ColumnType is not handled.
Also added IT tests to cover both Serialization and Deserialization aspects of KeyValue ColumntType by using the external_ids column of Bridge table.
Change-Id: I067bba372da8c02b0befbdb5210dda9068ea397f
Signed-off-by: Madhu Venugopal <mavenugo@gmail.com>
return schema.validate(data);
}
- public Object getData() {
+ public D getData() {
return data;
}
*/
package org.opendaylight.ovsdb.lib.notation;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.google.common.collect.ForwardingMap;
-import com.google.common.collect.Maps;
+import java.util.Map;
import org.opendaylight.ovsdb.lib.notation.json.Converter;
import org.opendaylight.ovsdb.lib.notation.json.OvsDBMapSerializer;
-import java.util.HashMap;
-import java.util.Map;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.google.common.collect.ForwardingMap;
+import com.google.common.collect.Maps;
@JsonDeserialize(converter = Converter.MapConverter.class)
@JsonSerialize(using = OvsDBMapSerializer.class)
public class OvsDBMap<K, V> extends ForwardingMap<K, V> {
- HashMap<K, V> target = Maps.newHashMap();
+ Map<K, V> target = Maps.newHashMap();
+
+ public OvsDBMap() {
+ this(Maps.<K,V>newHashMap());
+ }
+
+ public OvsDBMap(Map<K, V> value) {
+ this.target = value;
+ }
@Override
public Map<K, V> delegate() {
return target;
}
+
+ public static<K,V> OvsDBMap<K,V> fromMap(Map<K, V> value) {
+ return new OvsDBMap<K,V>(value);
+ }
}
import java.util.Map;
import java.util.Set;
+import org.opendaylight.ovsdb.lib.notation.OvsDBMap;
import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
import org.opendaylight.ovsdb.lib.schema.ColumnSchema;
import org.opendaylight.ovsdb.lib.schema.TableSchema;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
public <D, C extends TableSchema<C>> Insert<E> value(ColumnSchema<C, D> columnSchema, D value) {
Object untypedValue = null;
if (columnSchema.getType().isMultiValued()) {
- Preconditions.checkArgument((value instanceof Set),"expected a set for multivalued item") ;
- untypedValue = OvsDBSet.fromSet((Set) value);
+ if (value instanceof Set) {
+ untypedValue = OvsDBSet.fromSet((Set) value);
+ } else if (value instanceof Map) {
+ untypedValue = OvsDBMap.fromMap((Map)value);
+ }
} else {
untypedValue = value;
}
*/
package org.opendaylight.ovsdb.lib.schema;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.google.common.collect.Sets;
+import java.util.Set;
+
import org.opendaylight.ovsdb.lib.jsonrpc.JsonUtils;
+import org.opendaylight.ovsdb.lib.notation.OvsDBMap;
-import java.util.Set;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.collect.Sets;
public abstract class ColumnType {
super(baseType1);
}
+ @Override
public AtomicColumnType fromJsonNode(JsonNode json) {
if (json.isObject() && json.has("value")) {
return null;
public Object valueFromJson(JsonNode value) {
if (isMultiValued()) {
Set<Object> result = Sets.newHashSet();
- if(value.isContainerNode()) {
- for(JsonNode node: value) {
- result.add(getBaseType().toValue(node));
- }
+ if(value.isArray()) {
+ if (value.size() == 2) {
+ if (value.get(0).isTextual() && "set".equals(value.get(0).asText())) {
+ for(JsonNode node: value.get(1)) {
+ result.add(getBaseType().toValue(node));
+ }
+ }
+ }
} else {
result.add(getBaseType().toValue(value));
}
}
public static class KeyValuedColumnType extends ColumnType {
+ BaseType keyType;
- BaseType valueType;
+ public BaseType getKeyType() {
+ return keyType;
+ }
public KeyValuedColumnType() {
}
- public KeyValuedColumnType(BaseType baseType, BaseType valueType) {
- super(baseType);
+ public KeyValuedColumnType(BaseType keyType, BaseType valueType) {
+ super(valueType);
+ this.keyType = keyType;
}
+ @Override
public KeyValuedColumnType fromJsonNode(JsonNode json) {
if (json.isValueNode() || !json.has("value")) {
return null;
BaseType keyType = BaseType.fromJson(json, "key");
BaseType valueType = BaseType.fromJson(json, "value");
- return new KeyValuedColumnType(keyType, valueType);
+ KeyValuedColumnType keyValueColumnType = new KeyValuedColumnType(keyType, valueType);
+ JsonNode node = null;
+ if ((node = json.get("min")) != null) {
+ keyValueColumnType.setMin(node.asLong());
+ }
+
+ if ((node = json.get("max")) != null) {
+ if (node.isLong()){
+ keyValueColumnType.setMax(node.asLong());
+ } else if (node.isTextual() && "unlimited".equals(node.asText())) {
+ max = Long.MAX_VALUE;
+ }
+ }
+
+ return keyValueColumnType;
}
@Override
- public Object valueFromJson(JsonNode value) {
- throw new UnsupportedOperationException("needs to be implemented");
+ public Object valueFromJson(JsonNode node) {
+ if (node.isArray()) {
+ if (node.size() == 2) {
+ if (node.get(0).isTextual() && "map".equals(node.get(0).asText())) {
+ OvsDBMap<Object, Object> map = new OvsDBMap<Object, Object>();
+ for (JsonNode pairNode : node.get(1)) {
+ if (pairNode.isArray() && node.size() == 2) {
+ Object key = getKeyType().toValue(pairNode.get(0));
+ Object value = getBaseType().toValue(pairNode.get(1));
+ map.put(key, value);
+ }
+ }
+ return map;
+ } else if (node.size() == 0) {
+ return null;
+ }
+ }
+ }
+ return null;
}
@Override
public void validate(Object value) {
- throw new UnsupportedOperationException("not implemented yet");
+ this.baseType.validate(value);
}
}
}
return columnSchema;
}
+ public <K,V> ColumnSchema<E, Map<K,V>> multiValuedColumn(String column, Class<K> keyType, Class<V> valueType) {
+ //todo exception handling
+
+ ColumnSchema columnSchema = columns.get(column);
+ columnSchema.validateType(valueType);
+ return columnSchema;
+ }
+
public <D> ColumnSchema<E, D> column(String column, Class<D> type) {
//todo exception handling
import java.io.IOException;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
List<MonitorRequest<GenericTableSchema>> monitorRequests = Lists.newArrayList();
ColumnSchema<GenericTableSchema, Set<Integer>> flood_vlans = bridge.multiValuedColumn("flood_vlans", Integer.class);
-
+ ColumnSchema<GenericTableSchema, Map<String, String>> externalIds = bridge.multiValuedColumn("external_ids", String.class, String.class);
monitorRequests.add(
MonitorRequestBuilder.builder(bridge)
.addColumn(bridge.column("name"))
.addColumn(bridge.column("fail_mode", String.class))
.addColumn(flood_vlans)
+ .addColumn(externalIds)
.with(new MonitorSelect(true, true, true, true))
.build());
Row<GenericTableSchema> aNew = update.getNew();
for (Column<GenericTableSchema, ?> column: aNew.getColumns()) {
if (column.getSchema().equals(flood_vlans)) {
+ // Test for the 5 flood_vlans inserted in Bridge br-test in createBridgeTransaction
Set<Integer> data = column.getData(flood_vlans);
Assert.assertTrue(!data.isEmpty());
+ Assert.assertEquals(5, data.size());
+ } else if (column.getSchema().equals(externalIds)) {
+ // Test for the {"key", "value"} external_ids inserted in Bridge br-test in createBridgeTransaction
+ Map<String, String> data = column.getData(externalIds);
+ Assert.assertNotNull(data.get("key"));
+ Assert.assertEquals("value", data.get("key"));
}
}
}
OperationResult result = results.get(0);
List<Row<GenericTableSchema>> rows = result.getRows();
Row<GenericTableSchema> ovsTableRow = rows.get(0);
- return (UUID)ovsTableRow.getColumn(_uuid).getData();
+ return ovsTableRow.getColumn(_uuid).getData();
}
private void createBridgeTransaction() throws IOException, InterruptedException, ExecutionException {
ColumnSchema<GenericTableSchema, String> name = bridge.column("name", String.class);
ColumnSchema<GenericTableSchema, String> fail_mode = bridge.column("fail_mode", String.class);
ColumnSchema<GenericTableSchema, Set<Integer>> flood_vlans = bridge.multiValuedColumn("flood_vlans", Integer.class);
+ ColumnSchema<GenericTableSchema, Map<String, String>> externalIds = bridge.multiValuedColumn("external_ids", String.class, String.class);
ColumnSchema<GenericTableSchema, Set<UUID>> bridges = ovsTable.multiValuedColumn("bridges", UUID.class);
ColumnSchema<GenericTableSchema, UUID> _uuid = ovsTable.column("_uuid", UUID.class);
.add(op.insert(bridge)
.withId(namedUuid)
.value(name, testBridgeName)
- .value(flood_vlans, Sets.newHashSet(100, 101, 4001)))
+ .value(flood_vlans, Sets.newHashSet(100, 101, 4001))
+ .value(externalIds, Maps.newHashMap(ImmutableMap.of("key","value"))))
.add(op.comment("Inserting Bridge br-int"))
.add(op.update(bridge)
.set(fail_mode, "secure")