blob: 9744fb49d874e85a5a89f2c85f859872dbedfde7 [file] [log] [blame]
Sho SHIMIZUe4efe452015-08-26 15:06:55 -07001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.ovsdb.rfc.utils;
17
18import java.util.ArrayList;
19import java.util.HashMap;
20import java.util.Iterator;
21import java.util.List;
22import java.util.Map;
23
Sho SHIMIZU8700d422015-08-26 18:13:44 -070024import org.onosproject.ovsdb.rfc.exception.AbnormalJsonNodeException;
25import org.onosproject.ovsdb.rfc.exception.UnsupportedException;
Sho SHIMIZUe4efe452015-08-26 15:06:55 -070026import org.onosproject.ovsdb.rfc.jsonrpc.Callback;
27import org.onosproject.ovsdb.rfc.jsonrpc.JsonRpcResponse;
28import org.onosproject.ovsdb.rfc.message.OperationResult;
29import org.onosproject.ovsdb.rfc.message.RowUpdate;
30import org.onosproject.ovsdb.rfc.message.TableUpdate;
31import org.onosproject.ovsdb.rfc.message.TableUpdates;
32import org.onosproject.ovsdb.rfc.message.UpdateNotification;
33import org.onosproject.ovsdb.rfc.notation.Column;
34import org.onosproject.ovsdb.rfc.notation.Row;
35import org.onosproject.ovsdb.rfc.notation.UUID;
36import org.onosproject.ovsdb.rfc.operations.Operation;
37import org.onosproject.ovsdb.rfc.schema.ColumnSchema;
38import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
39import org.onosproject.ovsdb.rfc.schema.TableSchema;
40import org.onosproject.ovsdb.rfc.schema.type.ColumnTypeFactory;
41import org.slf4j.Logger;
42import org.slf4j.LoggerFactory;
43
44import com.fasterxml.jackson.core.JsonProcessingException;
45import com.fasterxml.jackson.databind.JsonNode;
46import com.fasterxml.jackson.databind.ObjectMapper;
47import com.google.common.collect.Lists;
48import com.google.common.collect.Maps;
49
50/**
51 * JsonNode utility class. convert JsonNode into Object.
52 */
53public final class FromJsonUtil {
54
55 private static final Logger log = LoggerFactory.getLogger(FromJsonUtil.class);
56
57 /**
58 * Constructs a FromJsonUtil object. Utility classes should not have a
59 * public or default constructor, otherwise IDE will compile unsuccessfully.
60 * This class should not be instantiated.
61 */
62 private FromJsonUtil() {
63 }
64
65 /**
66 * Verify whether the jsonNode is normal.
67 * @param jsonNode JsonNode
68 * @param nodeStr the node name of JsonNode
69 */
70 private static void validateJsonNode(JsonNode jsonNode, String nodeStr) {
71 if (!jsonNode.isObject() || !jsonNode.has(nodeStr)) {
72 String message = "Abnormal DatabaseSchema JsonNode, it should contain " + nodeStr
73 + " node but was not found";
74 throw new AbnormalJsonNodeException(message);
75 }
76 }
77
78 /**
79 * convert JsonNode into DatabaseSchema.
80 * @param dbName database name
81 * @param dbJson the JsonNode of get_schema result
82 * @return DatabaseSchema
83 * @throws AbnormalJsonNodeException this is an abnormal JsonNode exception
84 */
85 public static DatabaseSchema jsonNodeToDbSchema(String dbName, JsonNode dbJson) {
86 validateJsonNode(dbJson, "tables");
87 validateJsonNode(dbJson, "version");
88 String dbVersion = dbJson.get("version").asText();
89 Map<String, TableSchema> tables = new HashMap<>();
90 Iterator<Map.Entry<String, JsonNode>> tablesIter = dbJson.get("tables").fields();
91 while (tablesIter.hasNext()) {
92 Map.Entry<String, JsonNode> table = tablesIter.next();
93 tables.put(table.getKey(), jsonNodeToTableSchema(table.getKey(), table.getValue()));
94 }
95 return new DatabaseSchema(dbName, dbVersion, tables);
96 }
97
98 /**
99 * convert JsonNode into TableSchema.
100 * @param tableName table name
101 * @param tableJson table JsonNode
102 * @return TableSchema
103 * @throws AbnormalJsonNodeException this is an abnormal JsonNode exception
104 */
105 private static TableSchema jsonNodeToTableSchema(String tableName, JsonNode tableJson) {
106 validateJsonNode(tableJson, "columns");
107 Map<String, ColumnSchema> columns = new HashMap<>();
108 Iterator<Map.Entry<String, JsonNode>> columnsIter = tableJson.get("columns").fields();
109 while (columnsIter.hasNext()) {
110 Map.Entry<String, JsonNode> column = columnsIter.next();
111 columns.put(column.getKey(), jsonNodeToColumnSchema(column.getKey(), column.getValue()));
112 }
113 return new TableSchema(tableName, columns);
114 }
115
116 /**
117 * convert JsonNode into ColumnSchema.
118 * @param name column name
119 * @param columnJson column JsonNode
120 * @return ColumnSchema
121 * @throws AbnormalJsonNodeException this is an abnormal JsonNode exception
122 */
123 private static ColumnSchema jsonNodeToColumnSchema(String name, JsonNode columnJson) {
124 validateJsonNode(columnJson, "type");
125 return new ColumnSchema(name, ColumnTypeFactory.getColumnTypeFromJson(columnJson
126 .get("type")));
127 }
128
129 /**
130 * convert JsonNode into the returnType of methods in OvsdbRPC class.
131 * @param resultJsonNode the result JsonNode
132 * @param methodName the method name of methods in OvsdbRPC class
133 * @param objectMapper ObjectMapper entity
134 * @return Object
135 * @throws UnsupportedException this is an unsupported exception
136 */
137 private static Object convertResultType(JsonNode resultJsonNode, String methodName,
138 ObjectMapper objectMapper) {
139 switch (methodName) {
140 case "getSchema":
141 case "monitor":
142 return resultJsonNode;
143 case "echo":
144 case "listDbs":
145 return objectMapper.convertValue(resultJsonNode, objectMapper.getTypeFactory()
146 .constructParametricType(List.class, String.class));
147 case "transact":
148 return objectMapper.convertValue(resultJsonNode, objectMapper.getTypeFactory()
149 .constructParametricType(List.class, JsonNode.class));
150 default:
151 throw new UnsupportedException("does not support this rpc method" + methodName);
152 }
153 }
154
155 /**
156 * convert JsonNode into the returnType of methods in OvsdbRPC class.
157 * @param jsonNode the result JsonNode
158 * @param methodName the method name of methods in OvsdbRPC class
159 * @return Object
160 */
161 public static Object jsonResultParser(JsonNode jsonNode, String methodName) {
162 ObjectMapper objectMapper = ObjectMapperUtil.getObjectMapper();
163 JsonNode error = jsonNode.get("error");
164 if (error != null && !error.isNull()) {
165 log.error("jsonRpcResponse error : {}", error.toString());
166 }
167 JsonNode resultJsonNode = jsonNode.get("result");
168 Object result = convertResultType(resultJsonNode, methodName, objectMapper);
169 return result;
170 }
171
172 /**
173 * When monitor the ovsdb tables, if a table update, ovs send update
174 * notification, then call callback function.
175 * @param jsonNode the result JsonNode
176 * @param callback the callback function
177 * @throws UnsupportedException this is an unsupported exception
178 */
179 public static void jsonCallbackRequestParser(JsonNode jsonNode, Callback callback) {
180 ObjectMapper objectMapper = ObjectMapperUtil.getObjectMapper();
181 JsonNode params = jsonNode.get("params");
182 Object param = null;
183 String methodName = jsonNode.get("method").asText();
184 switch (methodName) {
185 case "update":
186 param = objectMapper.convertValue(params, UpdateNotification.class);
187 callback.update((UpdateNotification) param);
188 break;
189 default:
190 throw new UnsupportedException("does not support this callback method: " + methodName);
191 }
192 }
193
194 /**
195 * Ovs send echo request to keep the heart, need we return echo result.
196 * @param jsonNode the result JsonNode
197 * @return JsonRpcResponse String
198 */
199 public static String getEchoRequestStr(JsonNode jsonNode) {
200 ObjectMapper objectMapper = ObjectMapperUtil.getObjectMapper();
201 String str = null;
202 if (jsonNode.get("method").asText().equals("echo")) {
203 JsonRpcResponse response = new JsonRpcResponse(jsonNode.get("id").asText());
204 try {
205 str = objectMapper.writeValueAsString(response);
206 } catch (JsonProcessingException e) {
207 log.error("JsonProcessingException while converting JsonNode into string: ", e);
208 }
209 }
210 return str;
211 }
212
213 /**
214 * Convert the List of Operation result into List of OperationResult .
215 * @param input the List of JsonNode
216 * @param operations the List of Operation
217 * @return the List of OperationResult
218 */
219 public static List<OperationResult> jsonNodeToOperationResult(List<JsonNode> input,
220 List<Operation> operations) {
221 ObjectMapper objectMapper = ObjectMapperUtil.getObjectMapper(false);
222 List<OperationResult> operationResults = new ArrayList<OperationResult>();
223 for (int i = 0; i < input.size(); i++) {
224 JsonNode jsonNode = input.get(i);
225 Operation operation = operations.get(i);
226 if (jsonNode != null && jsonNode.size() > 0) {
227 if (i >= operations.size() || operation.getOp() != "select") {
228 OperationResult or = objectMapper.convertValue(jsonNode, OperationResult.class);
229 operationResults.add(or);
230 } else {
231 List<Row> rows = createRows(operation.getTableSchema(), jsonNode);
232 OperationResult or = new OperationResult(rows);
233 operationResults.add(or);
234 }
235 }
236 }
237 return operationResults;
238 }
239
240 /**
241 * Convert Operation JsonNode into Rows.
242 * @param tableSchema TableSchema entity
243 * @param rowsNode JsonNode
244 * @return ArrayList<Row> the List of Row
245 */
246 private static ArrayList<Row> createRows(TableSchema tableSchema, JsonNode rowsNode) {
247 validateJsonNode(rowsNode, "rows");
248 ArrayList<Row> rows = Lists.newArrayList();
249 for (JsonNode rowNode : rowsNode.get("rows")) {
250 rows.add(createRow(tableSchema, rowNode));
251 }
252 return rows;
253 }
254
255 /**
256 * convert the params of Update Notification into TableUpdates.
257 * @param updatesJson the params of Update Notification
258 * @param dbSchema DatabaseSchema entity
259 * @return TableUpdates
260 */
261 public static TableUpdates jsonNodeToTableUpdates(JsonNode updatesJson, DatabaseSchema dbSchema) {
262 Map<String, TableUpdate> tableUpdateMap = Maps.newHashMap();
263 Iterator<Map.Entry<String, JsonNode>> tableUpdatesItr = updatesJson.fields();
264 while (tableUpdatesItr.hasNext()) {
265 Map.Entry<String, JsonNode> entry = tableUpdatesItr.next();
266 TableSchema tableSchema = dbSchema.getTableSchema(entry.getKey());
267 TableUpdate tableUpdate = jsonNodeToTableUpdate(tableSchema, entry.getValue());
268 tableUpdateMap.put(entry.getKey(), tableUpdate);
269 }
270 return TableUpdates.tableUpdates(tableUpdateMap);
271 }
272
273 /**
274 * convert the params of Update Notification into TableUpdate.
275 * @param tableSchema TableSchema entity
276 * @param updateJson the table-update in params of Update Notification
277 * @return TableUpdate
278 */
279 public static TableUpdate jsonNodeToTableUpdate(TableSchema tableSchema, JsonNode updateJson) {
280 Map<UUID, RowUpdate> rows = Maps.newHashMap();
281 Iterator<Map.Entry<String, JsonNode>> tableUpdateItr = updateJson.fields();
282 while (tableUpdateItr.hasNext()) {
283 Map.Entry<String, JsonNode> oldNewRow = tableUpdateItr.next();
284 String uuidStr = oldNewRow.getKey();
285 UUID uuid = UUID.uuid(uuidStr);
286 JsonNode newR = oldNewRow.getValue().get("new");
287 JsonNode oldR = oldNewRow.getValue().get("old");
288 Row newRow = newR != null ? createRow(tableSchema, newR) : null;
289 Row oldRow = oldR != null ? createRow(tableSchema, oldR) : null;
290 RowUpdate rowUpdate = new RowUpdate(uuid, oldRow, newRow);
291 rows.put(uuid, rowUpdate);
292 }
293 return TableUpdate.tableUpdate(rows);
294 }
295
296 /**
297 * Convert Operation JsonNode into Row.
298 * @param tableSchema TableSchema entity
299 * @param rowNode JsonNode
300 * @return Row
301 */
302 private static Row createRow(TableSchema tableSchema, JsonNode rowNode) {
303 if (tableSchema == null) {
304 return null;
305 }
306 Map<String, Column> columns = Maps.newHashMap();
307 Iterator<Map.Entry<String, JsonNode>> rowIter = rowNode.fields();
308 while (rowIter.hasNext()) {
309 Map.Entry<String, JsonNode> next = rowIter.next();
310 ColumnSchema columnSchema = tableSchema.getColumnSchema(next.getKey());
311 if (columnSchema != null) {
312 String columnName = columnSchema.name();
313 Object obj = TransValueUtil.getValueFromJson(next.getValue(), columnSchema.type());
314 columns.put(columnName, new Column(columnName, obj));
315 }
316 }
317 return new Row(tableSchema.name(), columns);
318 }
319
320}