2 * Copyright (c) 2014, 2015 EBay Software Foundation and others. All rights reserved.
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 package org.opendaylight.ovsdb.lib.schema;
10 import com.fasterxml.jackson.databind.JsonNode;
11 import com.fasterxml.jackson.databind.node.ObjectNode;
12 import java.lang.reflect.Constructor;
13 import java.lang.reflect.InvocationTargetException;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.Iterator;
17 import java.util.List;
19 import java.util.Map.Entry;
21 import org.opendaylight.ovsdb.lib.message.TableUpdate;
22 import org.opendaylight.ovsdb.lib.notation.Column;
23 import org.opendaylight.ovsdb.lib.notation.Row;
24 import org.opendaylight.ovsdb.lib.notation.UUID;
25 import org.opendaylight.ovsdb.lib.operations.Insert;
26 import org.opendaylight.ovsdb.lib.schema.BaseType.UuidBaseType;
28 public abstract class TableSchema<E extends TableSchema<E>> {
30 private final String name;
31 private final Map<String, ColumnSchema> columns;
33 protected TableSchema(final String name) {
35 this.columns = new HashMap<>();
38 protected TableSchema(final String name, final Map<String, ColumnSchema> columns) {
40 this.columns = columns;
43 public Set<String> getColumns() {
44 return this.columns.keySet();
47 public Map<String, ColumnSchema> getColumnSchemas() {
51 public boolean hasColumn(final String column) {
52 return this.getColumns().contains(column);
55 public ColumnType getColumnType(final String column) {
56 return this.columns.get(column).getType();
59 public <E extends TableSchema<E>> E as(final Class<E> clazz) {
61 Constructor<E> instance = clazz.getConstructor(TableSchema.class);
62 return instance.newInstance(this);
63 } catch (InstantiationException | IllegalAccessException
64 | InvocationTargetException | NoSuchMethodException e) {
65 throw new RuntimeException("exception constructing instance of clazz " + clazz, e);
69 public Insert<E> insert() {
70 return new Insert<>(this);
73 public <D> ColumnSchema<E, Set<D>> multiValuedColumn(final String column, final Class<D> type) {
74 //todo exception handling
76 ColumnSchema<E, Set<D>> columnSchema = columns.get(column);
77 columnSchema.validateType(type);
81 public <K,V> ColumnSchema<E, Map<K,V>> multiValuedColumn(final String column, final Class<K> keyType,
82 final Class<V> valueType) {
83 //todo exception handling
85 ColumnSchema<E, Map<K, V>> columnSchema = columns.get(column);
86 columnSchema.validateType(valueType);
90 public <D> ColumnSchema<E, D> column(final String column, final Class<D> type) {
91 //todo exception handling
93 ColumnSchema<E, D> columnSchema = columns.get(column);
94 if (columnSchema != null) {
95 columnSchema.validateType(type);
100 public ColumnSchema column(final String column) {
101 return this.columns.get(column);
104 public String getName() {
108 public TableUpdate<E> updatesFromJson(final JsonNode value) {
109 TableUpdate<E> tableUpdate = new TableUpdate<>();
110 Iterator<Entry<String, JsonNode>> fields = value.fields();
111 while (fields.hasNext()) {
112 Map.Entry<String, JsonNode> idOldNew = fields.next();
113 String uuid = idOldNew.getKey();
115 ObjectNode newObjectNode = (ObjectNode) idOldNew.getValue().get("new");
116 ObjectNode oldObjectNode = (ObjectNode) idOldNew.getValue().get("old");
118 Row<E> newRow = newObjectNode != null ? createRow(newObjectNode) : null;
119 Row<E> oldRow = oldObjectNode != null ? createRow(oldObjectNode) : null;
121 tableUpdate.addRow(new UUID(uuid), oldRow, newRow);
126 public Row<E> createRow(final ObjectNode rowNode) {
127 List<Column<E, ?>> newColumns = new ArrayList<>();
128 for (Iterator<Map.Entry<String, JsonNode>> iter = rowNode.fields(); iter.hasNext();) {
129 Map.Entry<String, JsonNode> next = iter.next();
130 ColumnSchema<E, Object> schema = column(next.getKey(), Object.class);
132 * Ideally the ColumnSchema shouldn't be null at this stage. But there can be cases in which
133 * the OVSDB manager Schema implementation might decide to include some "hidden" columns that
134 * are NOT reported in getSchema, but decide to report it in unfiltered monitor.
135 * Hence adding some safety checks around that.
137 if (schema != null) {
138 Object value = schema.valueFromJson(next.getValue());
139 newColumns.add(new Column<>(schema, value));
142 return new Row<>(this, newColumns);
145 public List<Row<E>> createRows(final JsonNode rowsNode) {
146 List<Row<E>> rows = new ArrayList<>();
147 for (JsonNode rowNode : rowsNode.get("rows")) {
148 rows.add(createRow((ObjectNode)rowNode));
155 * RFC 7047 Section 3.2 specifies 2 internally generated columns in each table
156 * namely _uuid and _version which are not exposed in get_schema call.
157 * Since these 2 columns are extremely useful for Mutate, update and select operations,
158 * the ColumnSchema for these 2 columns are manually populated.
160 * It is to be noted that these 2 columns are specified as part of the RFC7047 and not
161 * a specific Schema implementation detail & hence adding it by default in the Library
162 * for better application experience using the library.
164 public void populateInternallyGeneratedColumns() {
165 columns.put("_uuid", new ColumnSchema("_uuid", new AtomicColumnType(new UuidBaseType())));
166 columns.put("_version", new ColumnSchema("_version", new AtomicColumnType(new UuidBaseType())));