blob: 4a130f7a28bd3893e29a42b11aae6786fdbba71e [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;
24import org.onosproject.yms.ydt.YdtBuilder;
25import org.onosproject.yms.ydt.YdtContext;
26import org.slf4j.Logger;
27
28import java.util.HashSet;
29import java.util.Iterator;
30import java.util.Set;
31
32import static com.fasterxml.jackson.databind.node.JsonNodeType.ARRAY;
33import static com.google.common.base.Strings.isNullOrEmpty;
34import static org.onosproject.yms.ydt.YdtType.MULTI_INSTANCE_NODE;
35import static org.onosproject.yms.ydt.YdtType.SINGLE_INSTANCE_NODE;
36import static org.slf4j.LoggerFactory.getLogger;
37
38/**
39 * Represents default implementation of codec JSON listener.
40 */
41public class JsonToYdtListener implements JsonListener {
42
43 private static final String INPUT_FIELD_NAME = "input";
44 private static final String COLON = ":";
45 private static final int INPUT_FIELD_LENGTH = 2;
46 private static final String E_UNSUP_TYPE = "Unsupported node type %s " +
47 "field name is %s fieldName";
48
49 private Logger log = getLogger(getClass());
50
51 private YdtBuilder ydtBuilder;
52 private String defaultMultiInsNodeName;
53 private YdtContext rpcModule;
54
55 /**
56 * Creates a listener for the process of a Json Object, the listener will
57 * try to transfer the JSON object to a Ydt builder.
58 *
59 * @param ydtBuilder the YDT builder to build a YDT object
60 */
61 public JsonToYdtListener(YdtBuilder ydtBuilder) {
62 this.ydtBuilder = ydtBuilder;
63 }
64
65 @Override
66 public void enterJsonNode(String fieldName, JsonNode node) {
67 if (isNullOrEmpty(fieldName)) {
68 if (!isNullOrEmpty(defaultMultiInsNodeName)) {
69 ydtBuilder.addChild(defaultMultiInsNodeName, null,
70 MULTI_INSTANCE_NODE);
71 }
72 return;
73 }
74 JsonNodeType nodeType = node.getNodeType();
75 switch (nodeType) {
76 case OBJECT:
77 processObjectNode(fieldName);
78 break;
79
80 case ARRAY:
81 processArrayNode(fieldName, node);
82 break;
83
84 //TODO for now, just process the following three node type
85 case STRING:
86 case NUMBER:
87 case BOOLEAN:
88 ydtBuilder.addLeaf(fieldName, null, node.asText());
89 break;
90
91 case BINARY:
92 case MISSING:
93 case NULL:
94 case POJO:
95 log.debug("Unimplemented node type {}", nodeType);
96 break;
97
98 default:
99 throw new JsonParseException(String.format(E_UNSUP_TYPE,
100 nodeType, fieldName));
101 }
102 }
103
104 @Override
105 public void exitJsonNode(JsonNode jsonNode) {
106 if (jsonNode.getNodeType() == ARRAY) {
107 return;
108 }
109 ydtBuilder.traverseToParent();
110 YdtContext curNode = ydtBuilder.getCurNode();
111 //if the current node is the RPC node, then should go to the father
112 //for we have enter the RPC node and Input node at the same time
113 //and the input is the only child of RPC node.
114
115 if (curNode == null) {
116 return;
117 }
118 String name = curNode.getName();
119 if (rpcModule != null && name.equals(rpcModule.getName())) {
120 ydtBuilder.traverseToParent();
121 }
122 }
123
124 private void processObjectNode(String fieldName) {
125 String[] segments = fieldName.split(COLON);
126 Boolean isLastInput = segments.length == INPUT_FIELD_LENGTH &&
127 segments[INPUT_FIELD_LENGTH - 1].equals(INPUT_FIELD_NAME);
128 int first = 0;
129 int second = 1;
130 if (isLastInput) {
131 ydtBuilder.addChild(segments[first], null, SINGLE_INSTANCE_NODE);
132 rpcModule = ydtBuilder.getCurNode();
133 ydtBuilder.addChild(segments[second], null, SINGLE_INSTANCE_NODE);
134 } else {
135 ydtBuilder.addChild(fieldName, null, SINGLE_INSTANCE_NODE);
136 }
137 }
138
139 private void processArrayNode(String fieldName, JsonNode node) {
140 ArrayNode arrayNode = (ArrayNode) node;
141 Set<String> sets = new HashSet<>();
142 Iterator<JsonNode> elements = arrayNode.elements();
143 boolean isLeafList = true;
144 while (elements.hasNext()) {
145 JsonNode element = elements.next();
146 JsonNodeType eleType = element.getNodeType();
147
148 if (eleType == JsonNodeType.STRING ||
149 eleType == JsonNodeType.NUMBER ||
150 eleType == JsonNodeType.BOOLEAN) {
151 sets.add(element.asText());
152 } else {
153 isLeafList = false;
154 }
155 }
156 if (isLeafList) {
157 //leaf-list
158 ydtBuilder.addLeaf(fieldName, null, sets);
159 } else {
160 this.defaultMultiInsNodeName = fieldName;
161 }
162 }
163}