blob: 1d9e3396cf858644d3de00e712fc12ae33831e76 [file] [log] [blame]
Shankara-Huaweid5823ab2016-11-22 10:14:52 +05301/*
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.yms.app.ych.defaultcodecs.utils;
18
19import com.google.common.base.Splitter;
20import com.google.common.collect.Lists;
21import org.onosproject.yms.app.ych.YchException;
22import org.onosproject.yms.ydt.YdtBuilder;
23import org.onosproject.yms.ydt.YdtContextOperationType;
24
25import java.io.UnsupportedEncodingException;
26import java.net.URLDecoder;
27import java.util.ArrayList;
28import java.util.List;
29
30import static com.google.common.base.Preconditions.checkNotNull;
31import static org.onosproject.yms.ydt.YdtContextOperationType.NONE;
32import static org.onosproject.yms.ydt.YdtType.SINGLE_INSTANCE_NODE;
33
34/**
35 * Utils to complete the conversion between JSON and YDT(YANG DATA MODEL).
36 */
37public final class DefaultCodecUtils {
38
39 private static final Splitter SLASH_SPLITTER = Splitter.on('/');
40 private static final Splitter COMMA_SPLITTER = Splitter.on(',');
41 private static final String EQUAL = "=";
42 private static final String COMMA = ",";
43 private static final String COLON = ":";
44 private static final String URI_ENCODING_CHAR_SET = "ISO-8859-1";
45 private static final String URI_NULL_CHECK_ERROR = "uri identifier " +
46 "should not be null";
47 private static final String URI_MODULE_FORMAT = "Illegal URI, First " +
48 "node should be in format \"moduleName:nodeName\"";
49
50 private static final String URI_LEAF_FORMAT = "Illegal URI, List or " +
51 "Leaf-list node should be in format \"nodeName=key\"or " +
52 "\"nodeName=instance-value\"";
53
54 // no instantiation
55 private DefaultCodecUtils() {
56 }
57
58 /**
59 * Converts URI identifier to YDT builder.
60 *
61 * @param identifier the uri identifier from web request
62 * @param builder the base YDT builder
63 * @param ydtOpType the YDT context operation type
64 * @return the YDT builder with the tree info of identifier
65 */
66 public static YdtBuilder convertUriToYdt(
67 String identifier,
68 YdtBuilder builder,
69 YdtContextOperationType ydtOpType) {
70 checkNotNull(identifier, URI_NULL_CHECK_ERROR);
71 List<String> segmentPaths =
72 urlPathArgsDecode(SLASH_SPLITTER.split(identifier));
73 if (segmentPaths.isEmpty()) {
74 return null;
75 }
76 processPathSegments(segmentPaths, builder, ydtOpType);
77 return builder;
78 }
79
80 /**
81 * Returns true, if the list is not null and non-empty; false otherwise.
82 *
83 * @param object list object
84 * @return true, if the list is not null and non-empty; false otherwise
85 */
86 public static boolean isNonEmpty(List object) {
87 return object != null && !object.isEmpty();
88 }
89
90 /**
91 * Converts a list of path segments to a YDT builder tree.
92 *
93 * @param paths the list of path segments split from URI
94 * @param builder the base YDT builder
95 * @param ydtOpType the YDT context operation type
96 * @return the YDT builder with the tree info of paths
97 */
98 private static YdtBuilder processPathSegments(
99 List<String> paths,
100 YdtBuilder builder,
101 YdtContextOperationType ydtOpType) {
102 if (paths.isEmpty()) {
103 return builder;
104 }
105 boolean isLastNode = paths.size() == 1;
106 YdtContextOperationType thisOpType = isLastNode ? ydtOpType : NONE;
107
108 final String path = paths.iterator().next();
109 if (path.contains(COLON)) {
110 addModule(builder, path);
111 addNode(path, builder, thisOpType);
112 } else if (path.contains(EQUAL)) {
113 addListOrLeafList(path, builder, thisOpType);
114 } else {
115 addLeaf(path, builder, thisOpType);
116 }
117
118 if (isLastNode) {
119 return builder;
120 }
121 List<String> remainPaths = paths.subList(1, paths.size());
122 processPathSegments(remainPaths, builder, ydtOpType);
123
124 return builder;
125 }
126
127 /**
128 * Returns YDT builder after adding module node.
129 *
130 * @param builder YDT builder
131 * @param path path segment
132 * @return the YDT builder
133 */
134 private static YdtBuilder addModule(YdtBuilder builder, String path) {
135 String moduleName = getPreSegment(path, COLON);
136 if (moduleName == null) {
137 throw new YchException(URI_MODULE_FORMAT);
138 }
139 builder.addChild(moduleName, null, SINGLE_INSTANCE_NODE);
140 return builder;
141 }
142
143 /**
144 * Returns YDT builder after adding single instance node.
145 *
146 * @param path path segments
147 * @param builder YDT builder
148 * @param ydtOpType YDT context operation type
149 * @return the YDT builder
150 */
151 private static YdtBuilder addNode(String path, YdtBuilder builder,
152 YdtContextOperationType ydtOpType) {
153 String nodeName = getPostSegment(path, COLON);
154 builder.addChild(nodeName, null, SINGLE_INSTANCE_NODE, ydtOpType);
155 return builder;
156 }
157
158 /**
159 * Returns YDT builder after adding multi instance node.
160 *
161 * @param path path segments
162 * @param builder YDT builder
163 * @param opType the YDT context operation type
164 * @return the YDT builder
165 */
166 private static YdtBuilder addListOrLeafList(
167 String path,
168 YdtBuilder builder,
169 YdtContextOperationType opType) {
170 String nodeName = getPreSegment(path, EQUAL);
171 String keyStr = getPostSegment(path, EQUAL);
172 if (keyStr == null) {
173 throw new YchException(URI_LEAF_FORMAT);
174 }
175 builder.setDefaultEditOperationType(opType);
176 if (keyStr.contains(COMMA)) {
177 List<String> keys = Lists.newArrayList(
178 COMMA_SPLITTER.split(keyStr));
179 builder.addMultiInstanceChild(nodeName, null, keys, null);
180 } else {
181 builder.addMultiInstanceChild(nodeName, null,
182 Lists.newArrayList(keyStr), null);
183 }
184 return builder;
185 }
186
187 /**
188 * Returns YDT builder after adding leaf.
189 *
190 * @param path path segments
191 * @param builder YDT builder
192 * @param ydtOpType YDT context operation type
193 * @return the YDT builder
194 */
195 private static YdtBuilder addLeaf(String path, YdtBuilder builder,
196 YdtContextOperationType ydtOpType) {
197 checkNotNull(path);
198 builder.addChild(path, null, ydtOpType);
199 return builder;
200 }
201
202 /**
203 * Returns the node name before the specified character in the string.
204 *
205 * @param path path segment
206 * @param splitChar character in the string
207 * @return the node name string
208 */
209 private static String getPreSegment(String path, String splitChar) {
210 int idx = path.indexOf(splitChar);
211 if (idx == -1) {
212 return null;
213 }
214
215 if (path.indexOf(':', idx + 1) != -1) {
216 return null;
217 }
218
219 return path.substring(0, idx);
220 }
221
222 /**
223 * Returns the string after the specified character in the string.
224 *
225 * @param path path segment
226 * @param splitChar character in the string
227 * @return the substring after specified character
228 */
229 private static String getPostSegment(String path, String splitChar) {
230 int idx = path.indexOf(splitChar);
231 if (idx == -1) {
232 return path;
233 }
234
235 if (path.indexOf(splitChar, idx + 1) != -1) {
236 return null;
237 }
238
239 return path.substring(idx + 1);
240 }
241
242 /**
243 * Converts a list of path from the original format to ISO-8859-1 code.
244 *
245 * @param paths the original paths
246 * @return list of decoded paths
247 */
248 private static List<String> urlPathArgsDecode(Iterable<String> paths) {
249 try {
250 List<String> decodedPathArgs = new ArrayList<>();
251 for (String pathArg : paths) {
252 String decode = URLDecoder.decode(pathArg,
253 URI_ENCODING_CHAR_SET);
254 decodedPathArgs.add(decode);
255 }
256 return decodedPathArgs;
257 } catch (UnsupportedEncodingException e) {
258 throw new YchException("Invalid URL path arg '" + paths + "': ", e);
259 }
260 }
261}