blob: cf4e690d171409e7e3f9845314e092fc7d5a071e [file] [log] [blame]
chengfanc58d4be2016-09-20 10:33:12 +08001/*
2 * Copyright 2016-present 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 */
16
17package org.onosproject.protocol.restconf.server.utils.parser.json;
18
19import com.fasterxml.jackson.databind.JsonNode;
20import com.fasterxml.jackson.databind.node.ArrayNode;
21import com.fasterxml.jackson.databind.node.JsonNodeType;
22import org.onosproject.protocol.restconf.server.utils.exceptions.JsonParseException;
23import org.onosproject.protocol.restconf.server.utils.parser.api.JsonListener;
chengfan7b2a60b2016-10-08 20:27:15 +080024import org.onosproject.protocol.restconf.server.utils.parser.api.NormalizedYangNode;
chengfanc58d4be2016-09-20 10:33:12 +080025import org.onosproject.yms.ydt.YdtBuilder;
26import org.onosproject.yms.ydt.YdtContext;
27import org.slf4j.Logger;
28
chengfanc58d4be2016-09-20 10:33:12 +080029import java.util.Iterator;
Vidyashree Ramac1fa7082016-11-14 19:33:13 +053030import java.util.LinkedHashSet;
chengfanc58d4be2016-09-20 10:33:12 +080031import java.util.Set;
chengfan7b2a60b2016-10-08 20:27:15 +080032import java.util.Stack;
chengfanc58d4be2016-09-20 10:33:12 +080033
34import static com.fasterxml.jackson.databind.node.JsonNodeType.ARRAY;
35import static com.google.common.base.Strings.isNullOrEmpty;
chengfan7b2a60b2016-10-08 20:27:15 +080036import static org.onosproject.protocol.restconf.server.utils.parser.json.ParserUtils.buildNormalizedNode;
chengfanc58d4be2016-09-20 10:33:12 +080037import static org.onosproject.yms.ydt.YdtType.MULTI_INSTANCE_NODE;
38import static org.onosproject.yms.ydt.YdtType.SINGLE_INSTANCE_NODE;
39import static org.slf4j.LoggerFactory.getLogger;
40
41/**
42 * Represents default implementation of codec JSON listener.
43 */
44public class JsonToYdtListener implements JsonListener {
45
46 private static final String INPUT_FIELD_NAME = "input";
47 private static final String COLON = ":";
48 private static final int INPUT_FIELD_LENGTH = 2;
49 private static final String E_UNSUP_TYPE = "Unsupported node type %s " +
50 "field name is %s fieldName";
Henry Yudc747af2016-11-16 13:29:54 -050051 private static final String EMPTY_STRING = "null";
chengfanc58d4be2016-09-20 10:33:12 +080052
53 private Logger log = getLogger(getClass());
54
55 private YdtBuilder ydtBuilder;
chengfan7b2a60b2016-10-08 20:27:15 +080056 private NormalizedYangNode defaultMultiInsNode;
57 private Stack<NormalizedYangNode> nameStack = new Stack<>();
chengfanc58d4be2016-09-20 10:33:12 +080058 private YdtContext rpcModule;
chengfan7b2a60b2016-10-08 20:27:15 +080059 private boolean isListArray = false;
chengfanc58d4be2016-09-20 10:33:12 +080060
61 /**
62 * Creates a listener for the process of a Json Object, the listener will
63 * try to transfer the JSON object to a Ydt builder.
64 *
65 * @param ydtBuilder the YDT builder to build a YDT object
66 */
67 public JsonToYdtListener(YdtBuilder ydtBuilder) {
68 this.ydtBuilder = ydtBuilder;
69 }
70
71 @Override
72 public void enterJsonNode(String fieldName, JsonNode node) {
73 if (isNullOrEmpty(fieldName)) {
chengfan7b2a60b2016-10-08 20:27:15 +080074 if (defaultMultiInsNode != null) {
75 ydtBuilder.addChild(defaultMultiInsNode.getName(),
76 defaultMultiInsNode.getNamespace(),
chengfanc58d4be2016-09-20 10:33:12 +080077 MULTI_INSTANCE_NODE);
78 }
79 return;
80 }
chengfan7b2a60b2016-10-08 20:27:15 +080081 NormalizedYangNode normalizedNode = buildNormalizedNode(fieldName);
chengfanc58d4be2016-09-20 10:33:12 +080082 JsonNodeType nodeType = node.getNodeType();
83 switch (nodeType) {
84 case OBJECT:
chengfan7b2a60b2016-10-08 20:27:15 +080085 processObjectNode(normalizedNode);
chengfanc58d4be2016-09-20 10:33:12 +080086 break;
87
88 case ARRAY:
chengfan7b2a60b2016-10-08 20:27:15 +080089 processArrayNode(normalizedNode, node);
chengfanc58d4be2016-09-20 10:33:12 +080090 break;
91
92 //TODO for now, just process the following three node type
93 case STRING:
94 case NUMBER:
95 case BOOLEAN:
chengfan7b2a60b2016-10-08 20:27:15 +080096 processLeafNode(normalizedNode, node.asText());
chengfanc58d4be2016-09-20 10:33:12 +080097 break;
98
99 case BINARY:
100 case MISSING:
101 case NULL:
102 case POJO:
103 log.debug("Unimplemented node type {}", nodeType);
104 break;
105
106 default:
107 throw new JsonParseException(String.format(E_UNSUP_TYPE,
108 nodeType, fieldName));
109 }
110 }
111
112 @Override
113 public void exitJsonNode(JsonNode jsonNode) {
chengfan0c32d712016-10-11 21:03:23 +0800114
115 if (isListArray) {
116 isListArray = false;
117 ydtBuilder.traverseToParent();
chengfanc58d4be2016-09-20 10:33:12 +0800118 return;
119 }
chengfan7b2a60b2016-10-08 20:27:15 +0800120
chengfan0c32d712016-10-11 21:03:23 +0800121 if (jsonNode.getNodeType() == ARRAY) {
122 //check empty before pop
123 if (nameStack.empty()) {
124 return;
125 }
chengfan7b2a60b2016-10-08 20:27:15 +0800126 nameStack.pop();
chengfan0c32d712016-10-11 21:03:23 +0800127 //check empty after pop
chengfan7b2a60b2016-10-08 20:27:15 +0800128 if (nameStack.empty()) {
129 return;
130 }
131 defaultMultiInsNode = nameStack.get(nameStack.size() - 1);
132 return;
133 }
chengfan7b2a60b2016-10-08 20:27:15 +0800134
chengfanc58d4be2016-09-20 10:33:12 +0800135 ydtBuilder.traverseToParent();
chengfan7b2a60b2016-10-08 20:27:15 +0800136 }
chengfanc58d4be2016-09-20 10:33:12 +0800137
chengfan7b2a60b2016-10-08 20:27:15 +0800138 private void processObjectNode(NormalizedYangNode node) {
139 ydtBuilder.addChild(node.getName(), node.getNamespace(),
140 SINGLE_INSTANCE_NODE);
141 }
142
143 private void processLeafNode(NormalizedYangNode node, String value) {
Henry Yudc747af2016-11-16 13:29:54 -0500144 String leafValue = value.equalsIgnoreCase(EMPTY_STRING) ? null : value;
145 ydtBuilder.addLeaf(node.getName(), node.getNamespace(), leafValue);
chengfan7b2a60b2016-10-08 20:27:15 +0800146 }
147
148 private void processArrayNode(NormalizedYangNode normalizedNode,
149 JsonNode node) {
150 ArrayNode arrayNode = (ArrayNode) node;
151 if (arrayNode.size() == 0) {
chengfanc58d4be2016-09-20 10:33:12 +0800152 return;
153 }
Vidyashree Ramac1fa7082016-11-14 19:33:13 +0530154 Set<String> sets = new LinkedHashSet<>();
chengfanc58d4be2016-09-20 10:33:12 +0800155 Iterator<JsonNode> elements = arrayNode.elements();
156 boolean isLeafList = true;
157 while (elements.hasNext()) {
158 JsonNode element = elements.next();
159 JsonNodeType eleType = element.getNodeType();
160
161 if (eleType == JsonNodeType.STRING ||
162 eleType == JsonNodeType.NUMBER ||
163 eleType == JsonNodeType.BOOLEAN) {
164 sets.add(element.asText());
165 } else {
166 isLeafList = false;
167 }
168 }
169 if (isLeafList) {
170 //leaf-list
chengfan7b2a60b2016-10-08 20:27:15 +0800171 ydtBuilder.addLeaf(normalizedNode.getName(),
172 normalizedNode.getNamespace(), sets);
173 isListArray = true;
chengfanc58d4be2016-09-20 10:33:12 +0800174 } else {
chengfan7b2a60b2016-10-08 20:27:15 +0800175 defaultMultiInsNode = normalizedNode;
176 nameStack.push(defaultMultiInsNode);
chengfanc58d4be2016-09-20 10:33:12 +0800177 }
178 }
179}