blob: 8ccecbe57ae7d99a92c2fe1ccb27f83d42b12589 [file] [log] [blame]
lishuai2ddc4692015-07-31 15:15:16 +08001/*
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;
23import java.util.Map.Entry;
24
25import org.onosproject.ovsdb.rfc.error.AbnormalSchemaException;
26import org.onosproject.ovsdb.rfc.error.JsonParsingException;
27import org.onosproject.ovsdb.rfc.error.UnknownResultException;
28import org.onosproject.ovsdb.rfc.jsonrpc.Callback;
29import org.onosproject.ovsdb.rfc.jsonrpc.JsonRpcResponse;
30import org.onosproject.ovsdb.rfc.message.OperationResult;
31import org.onosproject.ovsdb.rfc.message.RowUpdate;
32import org.onosproject.ovsdb.rfc.message.TableUpdate;
33import org.onosproject.ovsdb.rfc.message.TableUpdates;
34import org.onosproject.ovsdb.rfc.message.UpdateNotification;
35import org.onosproject.ovsdb.rfc.notation.Column;
36import org.onosproject.ovsdb.rfc.notation.Row;
37import org.onosproject.ovsdb.rfc.notation.UUID;
38import org.onosproject.ovsdb.rfc.operations.Operation;
39import org.onosproject.ovsdb.rfc.schema.ColumnSchema;
40import org.onosproject.ovsdb.rfc.schema.DatabaseSchema;
41import org.onosproject.ovsdb.rfc.schema.TableSchema;
42import org.onosproject.ovsdb.rfc.schema.type.ColumnTypeFactory;
43import org.slf4j.Logger;
44import org.slf4j.LoggerFactory;
45
46import com.fasterxml.jackson.core.JsonProcessingException;
47import com.fasterxml.jackson.databind.JsonNode;
48import com.fasterxml.jackson.databind.ObjectMapper;
49import com.google.common.collect.Lists;
50import com.google.common.collect.Maps;
51
52/**
53 * JsonNode utility class. convert JsonNode into Object.
54 */
55public final class FromJsonUtil {
56
57 private static final Logger log = LoggerFactory
58 .getLogger(FromJsonUtil.class);
59
60 /**
61 * Constructs a FromJsonUtil object. Utility classes should not have a
62 * public or default constructor, otherwise IDE will compile unsuccessfully. This
63 * class should not be instantiated.
64 */
65 private FromJsonUtil() {
66 }
67
68 /**
69 * convert JsonNode into DatabaseSchema.
70 * @param dbName database name
71 * @param json the JsonNode of get_schema result
72 * @return DatabaseSchema
73 * @throws JsonParsingException this is a JsonNode parse exception
74 */
75 public static DatabaseSchema jsonNodeToDbSchema(String dbName, JsonNode json) {
76 if (!json.isObject() || !json.has("tables")) {
77 throw new JsonParsingException(
78 "bad DatabaseSchema root, expected \"tables\" as child but was not found");
79 }
80 if (!json.isObject() || !json.has("version")) {
81 throw new JsonParsingException(
82 "bad DatabaseSchema root, expected \"version\" as child but was not found");
83 }
84
85 String dbVersion = json.get("version").asText();
86
87 Map<String, TableSchema> tables = new HashMap<>();
88 for (Iterator<Map.Entry<String, JsonNode>> iter = json.get("tables")
89 .fields(); iter.hasNext();) {
90 Map.Entry<String, JsonNode> table = iter.next();
91 tables.put(table.getKey(),
92 jsonNodeToTableSchema(table.getKey(), table.getValue()));
93 }
94
95 return new DatabaseSchema(dbName, dbVersion, tables);
96 }
97
98 /**
99 * convert JsonNode into TableSchema.
100 * @param tableName table name
101 * @param json table JsonNode
102 * @return TableSchema
103 * @throws AbnormalSchemaException this is an abnormal schema exception
104 */
105 private static TableSchema jsonNodeToTableSchema(String tableName,
106 JsonNode json) {
107
108 if (!json.isObject() || !json.has("columns")) {
109 throw new AbnormalSchemaException(
110 "bad tableschema root, expected \"columns\" as child");
111 }
112
113 Map<String, ColumnSchema> columns = new HashMap<>();
114 for (Iterator<Map.Entry<String, JsonNode>> iter = json.get("columns")
115 .fields(); iter.hasNext();) {
116 Map.Entry<String, JsonNode> column = iter.next();
117 columns.put(column.getKey(),
118 jsonNodeToColumnSchema(column.getKey(),
119 column.getValue()));
120 }
121
122 return new TableSchema(tableName, columns);
123 }
124
125 /**
126 * convert JsonNode into ColumnSchema.
127 * @param name column name
128 * @param json JsonNode
129 * @return ColumnSchema
130 * @throws AbnormalSchemaException this is an abnormal schema exception
131 */
132 private static ColumnSchema jsonNodeToColumnSchema(String name,
133 JsonNode json) {
134 if (!json.isObject() || !json.has("type")) {
135 throw new AbnormalSchemaException(
136 "bad column schema root, expected \"type\" as child");
137 }
138
139 return new ColumnSchema(name,
140 ColumnTypeFactory.getColumnTypeFromJson(json
141 .get("type")));
142 }
143
144 /**
145 * convert JsonNode into the returnType of methods in OvsdbRPC class.
146 * @param resultJsonNode the result JsonNode
147 * @param methodName the method name of methods in OvsdbRPC class
148 * @param objectMapper ObjectMapper entity
149 * @return Object
150 * @throws UnknownResultException this is an unknown result exception
151 */
152 private static Object convertResultType(JsonNode resultJsonNode,
153 String methodName,
154 ObjectMapper objectMapper) {
155 switch (methodName) {
156 case "getSchema":
157 case "monitor":
158 return resultJsonNode;
159 case "echo":
160 case "listDbs":
161 return objectMapper
162 .convertValue(resultJsonNode, objectMapper.getTypeFactory()
163 .constructParametricType(List.class, String.class));
164 case "transact":
165 return objectMapper
166 .convertValue(resultJsonNode,
167 objectMapper
168 .getTypeFactory()
169 .constructParametricType(List.class,
170 JsonNode.class));
171 default:
172 throw new UnknownResultException("Don't know how to handle this");
173 }
174 }
175
176 /**
177 * convert JsonNode into the returnType of methods in OvsdbRPC class.
178 * @param jsonNode the result JsonNode
179 * @param methodName the method name of methods in OvsdbRPC class
180 * @return Object
181 */
182 public static Object jsonResultParser(JsonNode jsonNode, String methodName) {
183 ObjectMapper objectMapper = ObjectMapperUtil.getObjectMapper();
184 JsonNode error = jsonNode.get("error");
185 if (error != null && !error.isNull()) {
186 log.error("Error : {}", error.toString());
187 }
188 JsonNode resultJsonNode = jsonNode.get("result");
189 Object result = convertResultType(resultJsonNode, methodName,
190 objectMapper);
191 return result;
192 }
193
194 /**
195 * When monitor the ovsdb tables, if a table update, ovs send update
196 * notification, then call callback function.
197 * @param jsonNode the result JsonNode
198 * @param callback the callback function
199 * @throws UnknownResultException this is an unknown result exception
200 */
201 public static void jsonCallbackRequestParser(JsonNode jsonNode,
202 Callback callback) {
203 ObjectMapper objectMapper = ObjectMapperUtil.getObjectMapper();
204 JsonNode params = jsonNode.get("params");
205 Object param = null;
206 String methodName = jsonNode.get("method").asText();
207 switch (methodName) {
208 case "update":
209 param = objectMapper.convertValue(params, UpdateNotification.class);
210 callback.update((UpdateNotification) param);
211 break;
212 default:
213 throw new UnknownResultException("Cannot handle this method: "
214 + methodName);
215 }
216 }
217
218 /**
219 * Ovs send echo request to keep the heart, need we return echo result.
220 * @param jsonNode the result JsonNode
221 * @return JsonRpcResponse String
222 */
223 public static String getEchoRequestStr(JsonNode jsonNode) {
224 ObjectMapper objectMapper = ObjectMapperUtil.getObjectMapper();
225 String str = null;
226 if (jsonNode.get("method").asText().equals("echo")) {
227 JsonRpcResponse response = new JsonRpcResponse(jsonNode.get("id")
228 .asText());
229 try {
230 str = objectMapper.writeValueAsString(response);
231 } catch (JsonProcessingException e) {
232 log.error("JsonProcessingException while converting JsonNode into string ", e);
233 }
234 }
235 return str;
236 }
237
238 /**
239 * Convert the List of Operation result into List of OperationResult .
240 * @param input the List of JsonNode
241 * @param operations the List of Operation
242 * @return the List of OperationResult
243 */
244 public static List<OperationResult> jsonNodeToOperationResult(List<JsonNode> input,
245 List<Operation> operations) {
246 ObjectMapper objectMapper = ObjectMapperUtil.getObjectMapper(false);
247 List<OperationResult> operationResults = new ArrayList<OperationResult>();
248 for (int i = 0; i < input.size(); i++) {
249 JsonNode jsonNode = input.get(i);
250 Operation operation = operations.get(i);
251 if (jsonNode != null && jsonNode.size() > 0) {
252 if (i >= operations.size() || operation.getOp() != "select") {
253 OperationResult or = objectMapper.convertValue(jsonNode,
254 OperationResult.class);
255 operationResults.add(or);
256 } else {
257 List<Row> rows = createRows(operation.getTableSchema(), jsonNode);
258 OperationResult or = new OperationResult(rows);
259 operationResults.add(or);
260 }
261 }
262 }
263 return operationResults;
264 }
265
266 /**
267 * Convert Operation JsonNode into Rows.
268 * @param tableSchema TableSchema entity
269 * @param rowsNode JsonNode
270 * @return ArrayList<Row> the List of Row
271 */
272 private static ArrayList<Row> createRows(TableSchema tableSchema,
273 JsonNode rowsNode) {
274 ArrayList<Row> rows = Lists.newArrayList();
275 for (JsonNode rowNode : rowsNode.get("rows")) {
276 rows.add(createRow(tableSchema, rowNode));
277 }
278 return rows;
279 }
280
281 /**
282 * convert the params of Update Notification into TableUpdates.
283 * @param updatesJson the params of Update Notification
284 * @param dbSchema DatabaseSchema entity
285 * @return TableUpdates
286 */
287 public static TableUpdates jsonNodeToTableUpdates(JsonNode updatesJson,
288 DatabaseSchema dbSchema) {
289 Map<String, TableUpdate> tableUpdateMap = Maps.newHashMap();
290 for (Iterator<Map.Entry<String, JsonNode>> itr = updatesJson.fields(); itr
291 .hasNext();) {
292 Map.Entry<String, JsonNode> entry = itr.next();
293 TableSchema tableSchema = dbSchema.getTableSchema(entry.getKey());
294 TableUpdate tableUpdate = jsonNodeToTableUpdate(tableSchema,
295 entry.getValue());
296 tableUpdateMap.put(entry.getKey(), tableUpdate);
297 }
298 return TableUpdates.tableUpdates(tableUpdateMap);
299 }
300
301 /**
302 * convert the params of Update Notification into TableUpdate.
303 * @param tableSchema TableSchema entity
304 * @param value the table-update in params of Update Notification
305 * @return TableUpdate
306 */
307 public static TableUpdate jsonNodeToTableUpdate(TableSchema tableSchema,
308 JsonNode value) {
309 Map<UUID, RowUpdate> rows = Maps.newHashMap();
310 Iterator<Entry<String, JsonNode>> fields = value.fields();
311 while (fields.hasNext()) {
312 Map.Entry<String, JsonNode> idOldNew = fields.next();
313 String uuidStr = idOldNew.getKey();
314 UUID uuid = UUID.uuid(uuidStr);
315 JsonNode newR = idOldNew.getValue().get("new");
316 JsonNode oldR = idOldNew.getValue().get("old");
317 Row newRow = newR != null ? createRow(tableSchema, newR) : null;
318 Row oldRow = oldR != null ? createRow(tableSchema, oldR) : null;
319 RowUpdate rowUpdate = new RowUpdate(uuid, oldRow, newRow);
320 rows.put(uuid, rowUpdate);
321 }
322 return TableUpdate.tableUpdate(rows);
323 }
324
325 /**
326 * Convert Operation JsonNode into Row.
327 * @param tableSchema TableSchema entity
328 * @param rowNode JsonNode
329 * @return Row
330 */
331 private static Row createRow(TableSchema tableSchema, JsonNode rowNode) {
332 List<Column> columns = Lists.newArrayList();
333 for (Iterator<Map.Entry<String, JsonNode>> iter = rowNode.fields(); iter
334 .hasNext();) {
335 Map.Entry<String, JsonNode> next = iter.next();
336 ColumnSchema schema = tableSchema.getColumnSchema(next.getKey());
337 if (schema != null) {
338 Object o = TransValueUtil.getValueFromJson(next.getValue(), schema.type());
339 columns.add(new Column(schema, o));
340 }
341 }
342 return new Row(tableSchema, columns);
343 }
344
345}