Resolved the Serialization and Deserialization issues for MultiValued Columns with...
[ovsdb.git] / library / src / main / java / org / opendaylight / ovsdb / lib / schema / TableSchema.java
1 /*
2  * Copyright (C) 2014 EBay Software Foundation
3  *
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
7  *
8  * Authors : Ashwin Raveendran
9  */
10 package org.opendaylight.ovsdb.lib.schema;
11
12 import java.lang.reflect.Constructor;
13 import java.util.Iterator;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17
18 import org.opendaylight.ovsdb.lib.message.TableUpdate;
19 import org.opendaylight.ovsdb.lib.notation.Column;
20 import org.opendaylight.ovsdb.lib.notation.Row;
21 import org.opendaylight.ovsdb.lib.notation.UUID;
22 import org.opendaylight.ovsdb.lib.operations.Insert;
23 import org.opendaylight.ovsdb.lib.schema.BaseType.UuidBaseType;
24 import org.opendaylight.ovsdb.lib.schema.ColumnType.AtomicColumnType;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 import com.fasterxml.jackson.databind.JsonNode;
29 import com.fasterxml.jackson.databind.node.ObjectNode;
30 import com.google.common.collect.Lists;
31
32
33 public abstract class TableSchema<E extends TableSchema<E>> {
34
35
36     protected static final Logger logger = LoggerFactory.getLogger(TableSchema.class);
37     private String name;
38     private Map<String, ColumnSchema> columns;
39
40     public TableSchema() {
41     }
42
43     protected TableSchema(String name) {
44         this.name = name;
45     }
46
47     public TableSchema(String name, Map<String, ColumnSchema> columns) {
48         this.name = name;
49         this.columns = columns;
50     }
51
52     public Set<String> getColumns() {
53         return this.columns.keySet();
54     }
55
56     public Map<String, ColumnSchema> getColumnSchemas() {
57         return columns;
58     }
59
60     public boolean hasColumn(String column) {
61         return this.getColumns().contains(column);
62     }
63
64
65     public ColumnType getColumnType(String column) {
66         return this.columns.get(column).getType();
67     }
68
69     public <E extends TableSchema<E>> E as(Class<E> clazz) {
70         try {
71             Constructor<E> e = clazz.getConstructor(TableSchema.class);
72             return e.newInstance(this);
73         } catch (Exception e) {
74             throw new RuntimeException("exception constructing instance of clazz " + clazz, e);
75         }
76     }
77
78     public Insert<E> insert() {
79         return new Insert<>(this);
80     }
81
82     public <D> ColumnSchema<E, Set<D>> multiValuedColumn(String column, Class<D> type) {
83         //todo exception handling
84
85         ColumnSchema columnSchema = columns.get(column);
86         columnSchema.validateType(type);
87         return columnSchema;
88     }
89
90     public <K,V> ColumnSchema<E, Map<K,V>> multiValuedColumn(String column, Class<K> keyType, Class<V> valueType) {
91         //todo exception handling
92
93         ColumnSchema columnSchema = columns.get(column);
94         columnSchema.validateType(valueType);
95         return columnSchema;
96     }
97
98     public <D> ColumnSchema<E, D> column(String column, Class<D> type) {
99         //todo exception handling
100
101         ColumnSchema columnSchema = columns.get(column);
102         columnSchema.validateType(type);
103         return columnSchema;
104     }
105
106     public ColumnSchema column(String column) {
107         return this.columns.get(column);
108     }
109
110
111     public String getName() {
112         return name;
113     }
114
115     protected void setName(String name) {
116         this.name = name;
117     }
118
119     protected void setColumns(Map<String, ColumnSchema> columns) {
120         this.columns = columns;
121     }
122
123     public TableUpdate<E> updatesFromJson(JsonNode value) {
124
125         Map.Entry<String, JsonNode> idOldNew = value.fields().next();
126         String uuid = idOldNew.getKey();
127
128         ObjectNode new_ = (ObjectNode) idOldNew.getValue().get("new");
129         ObjectNode old = (ObjectNode) idOldNew.getValue().get("old");
130
131         Row<E> newRow = new_ != null ? createRow(new_) : null;
132         Row<E> oldRow = old != null ? createRow(old) : null;
133
134         TableUpdate<E> tableUpdate = new TableUpdate<>(new UUID(uuid));
135         tableUpdate.setNew(newRow);
136         tableUpdate.setOld(oldRow);
137
138         return tableUpdate;
139     }
140
141     protected Row<E> createRow(ObjectNode rowNode) {
142         List<Column<E, ?>> columns = Lists.newArrayList();
143         for (Iterator<Map.Entry<String, JsonNode>> iter = rowNode.fields(); iter.hasNext();) {
144             Map.Entry<String, JsonNode> next = iter.next();
145             ColumnSchema<E, Object> schema = column(next.getKey(), Object.class);
146             Object o = schema.valueFromJson(next.getValue());
147             columns.add(new Column<>(schema, o));
148         }
149         return new Row<>(columns);
150     }
151
152     /*
153      * RFC 7047 Section 3.2 specifies 2 internally generated columns in each table
154      * namely _uuid and version which are not exposed in get_schema call.
155      * Since these 2 columns are extremely useful for Mutate, update and select operations,
156      * the ColumnSchema for these 2 columns are manually populated.
157      *
158      * It is to be noted that these 2 columns are specified as part of the RFC7047 and not
159      * a specific Schema implementation detail & hence adding it by default in the Library
160      * for better application experience using the library.
161      */
162     public void populateInternallyGeneratedColumns() {
163         columns.put("_uuid", new ColumnSchema("_uuid", new AtomicColumnType(new UuidBaseType())));
164         columns.put("version", new ColumnSchema("version", new AtomicColumnType(new UuidBaseType())));
165     }
166 }