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