Add seed code from Open-O
[cli.git] / framework / src / main / java / org / onap / cli / fw / schema / SchemaValidator.java
1 /*
2  * Copyright 2017 Huawei Technologies Co., Ltd.
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
17 package org.onap.cli.fw.schema;
18
19 import com.fasterxml.jackson.databind.ObjectMapper;
20 import net.minidev.json.JSONObject;
21
22 import org.onap.cli.fw.error.OnapCommandInvalidSchema;
23
24 import static org.onap.cli.fw.conf.Constants.*;
25
26 import java.io.File;
27 import java.io.IOException;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Map.Entry;
32
33 import java.util.Set;
34
35 /**
36  * Schema Validation impl.
37  *
38  */
39 public class SchemaValidator extends AbstractSchemaValidate {
40
41     /**
42      * Constructor.
43      *
44      * @param schemaFile
45      *            file
46      * @throws OnapCommandInvalidSchema
47      *             exception
48      */
49     public SchemaValidator(File schemaFile) throws OnapCommandInvalidSchema {
50         super(schemaFile);
51     }
52
53     public SchemaValidator(String schemaFile) throws OnapCommandInvalidSchema {
54         super(schemaFile);
55     }
56
57     @Override
58     protected void validateSpecificSchema(SchemaType type) throws OnapCommandInvalidSchema {
59         if (type.equals(SchemaType.HTTP)) {
60             validateHttpParameters();
61         }
62     }
63
64     @SuppressWarnings("unchecked")
65     private void validateHttpParameters() {
66
67         Map<String, Object> httpMap = (Map<String, Object>) yamlMap.get(HTTP);
68
69         if (httpMap == null || httpMap.isEmpty()) {
70             schemaErrors.add(HTTP_SECTION_EMPTY);
71             return;
72         }
73
74         validateMandatoryParams(httpMap, HTTP_SECTIONS, HTTP_MANDATORY_SECTIONS, PARAMETERS);
75
76         Map<String, Object> requestMap = (Map<String, Object>) httpMap.get(REQUEST);
77
78         if (requestMap != null && !requestMap.isEmpty()) {
79             validateHttpRequestParams(requestMap);
80         } else {
81             schemaErrors.add(SchemaValidate.emptySection(REQUEST));
82         }
83
84         List<Object> requestSuccessCodes = (List<Object>) httpMap.get(SUCCESS_CODES);
85         if (requestSuccessCodes != null && !requestSuccessCodes.isEmpty()) {
86             validateHttpSccessCodes(requestSuccessCodes);
87         } else {
88             schemaErrors.add(SchemaValidate.emptySection(SUCCESS_CODES));
89         }
90
91         Map<String, Object> resultMap = (Map<String, Object>) httpMap.get(RESULT_MAP);
92
93         if (resultMap != null && !resultMap.isEmpty()) {
94             validateHttpResultMapping(resultMap);
95         }
96
97         Object object = httpMap.get(SAMPLE_RESPONSE);
98         if (object != null) {
99             if (object instanceof String) {
100                 schemaErrors.add(HTTP_SAMPLE_RESPONSE_FAILED_PARSING);
101             } else {
102                 validateSampleResponse((Map<String, Object>) object);
103             }
104         }
105     }
106
107     private void validateHttpRequestParams(Map<String, Object> requestMap) {
108
109         if (requestMap == null || requestMap.isEmpty()) {
110             return;
111         }
112         // validate mandatory parameters
113         validateMandatoryParams(requestMap, HTTP_REQUEST_PARAMS, HTTP_REQUEST_MANDATORY_PARAMS, REQUEST);
114
115         // Validate method types
116         String method = (String) requestMap.get(METHOD);
117         if (method != null && !method.isEmpty()) {
118             if (!HTTP_METHODS.contains(method.toLowerCase())) {
119                 schemaErrors.add(SchemaValidate.invalidType(REQUEST, METHOD, HTTP_METHODS));
120             }
121         } else {
122             schemaErrors.add("Http request method cann't be null or empty");
123         }
124
125         Set<String> requestParams = getRequestParams();
126
127         // validate uriParams
128         Set<String> uriParams = validateHttpUri(requestMap);
129
130         // validate body
131         Set<String> bodyParams = validateHttpBody(requestMap);
132
133         // validate header
134         Set<String> headerParams = validateHttpHeaders(requestMap);
135
136         // validate queries
137         Set<String> queryParams = validateHttpQueries(requestMap);
138
139         for (String declaredParam : requestParams) {
140             if (!uriParams.contains(declaredParam) && !bodyParams.contains(declaredParam)
141                     && !headerParams.contains(declaredParam) && !queryParams.contains(declaredParam)) {
142                 schemaErrors.add(SchemaValidate.parameterNotMapped(declaredParam));
143             }
144         }
145
146         Set<String> totalParams = new HashSet<>();
147         totalParams.addAll(uriParams);
148         totalParams.addAll(bodyParams);
149         totalParams.addAll(queryParams);
150         totalParams.addAll(headerParams);
151
152         for (String definedParam : totalParams) {
153             if (!requestParams.contains(definedParam)) {
154                 if (uriParams.contains(definedParam)) {
155                     schemaErrors.add(SchemaValidate.invalidRequestParam(URI, definedParam));
156                 } else if (bodyParams.contains(definedParam)) {
157                     schemaErrors.add(SchemaValidate.invalidRequestParam(BODY, definedParam));
158                 } else if (queryParams.contains(definedParam)) {
159                     schemaErrors.add(SchemaValidate.invalidRequestParam(QUERIES, definedParam));
160                 } else if (headerParams.contains(definedParam)) {
161                     schemaErrors.add(SchemaValidate.invalidRequestParam(HEADERS, definedParam));
162                 }
163             }
164         }
165
166     }
167
168     private Set<String> validateHttpUri(Map<String, Object> requestMap) {
169         Set<String> uriParamNames = new HashSet<>();
170         String uri = (String) requestMap.get(URI);
171         if (uri == null || uri.isEmpty()) {
172             schemaErrors.add(SchemaValidate.emptySection(URI));
173             return uriParamNames;
174         }
175         parseParameters(uri, uriParamNames);
176         return uriParamNames;
177     }
178
179     @SuppressWarnings("unchecked")
180     private Set<String> validateHttpHeaders(Map<String, Object> requestMap) {
181
182         Map<String, Object> headers = (Map<String, Object>) requestMap.get(HEADERS);
183         Set<String> headerParamNames = new HashSet<>();
184         if (headers != null) {
185             for (Entry<String, Object> entry : headers.entrySet()) {
186                 parseParameters(String.valueOf(entry.getValue()), headerParamNames);
187             }
188         }
189         return headerParamNames;
190     }
191
192     @SuppressWarnings("unchecked")
193     private Set<String> validateHttpQueries(Map<String, Object> requestMap) {
194         Map<String, Object> queries = (Map<String, Object>) requestMap.get(QUERIES);
195         Set<String> queryParamNames = new HashSet<>();
196         if (queries != null) {
197             for (Entry<String, Object> entry : queries.entrySet()) {
198                 parseParameters(String.valueOf(entry.getValue()), queryParamNames);
199             }
200         }
201         return queryParamNames;
202     }
203
204     private Set<String> validateHttpBody(Map<String, Object> requestMap) {
205         Set<String> bodyParamNames = new HashSet<>();
206         Object bodyString = requestMap.get(BODY);
207         if (bodyString == null) {
208             return bodyParamNames;
209         }
210
211         String body = String.valueOf(bodyString);
212         JSONObject obj = null;
213         try {
214             obj = new ObjectMapper().readValue(body, JSONObject.class);
215         } catch (IOException e1) { // NOSONAR
216             schemaErrors.add(HTTP_BODY_FAILED_PARSING);
217         }
218         if (obj == null || "".equals(obj.toString())) {
219             schemaErrors.add(HTTP_BODY_JSON_EMPTY);
220         }
221         parseParameters(body, bodyParamNames);
222
223         return bodyParamNames;
224     }
225
226     private void parseParameters(String line, Set<String> paramNames) {
227
228         int currentIdx = 0;
229         while (currentIdx < line.length()) {
230             int idxS = line.indexOf("${", currentIdx);
231             if (idxS == -1) {
232                 break;
233             }
234             int idxE = line.indexOf("}", idxS);
235             String paramName = line.substring(idxS + 2, idxE);
236             paramNames.add(paramName.trim());
237
238             currentIdx = idxE + 1;
239         }
240
241     }
242
243     private void validateHttpSccessCodes(List<Object> requestSuccessCodes) {
244
245         for (Object successCode : requestSuccessCodes) {
246             Integer code = (Integer) successCode;
247             if (code < 200 || code >= 300) {
248                 schemaErrors.add(HTTP_SUCCESS_CODE_INVALID);
249             }
250         }
251
252     }
253
254     private void validateHttpResultMapping(Map<String, Object> resultMap) {
255         Set<String> resultAttributes = getResultAttributes();
256
257         // Validate if all result attributes are used in the result mapping
258         for (String attribute : resultAttributes) {
259             if (!resultMap.containsKey(attribute)) {
260                 schemaErrors.add(SchemaValidate.missingInResultMap(attribute));
261             }
262         }
263
264         // Validate if all result mapping keys are defined in the result attributes
265         for (Entry<String, Object> entry : resultMap.entrySet()) {
266             if (!resultAttributes.contains(entry.getKey())) {
267                 schemaErrors.add(SchemaValidate.missingInResultAttribute(entry.getKey()));
268             }
269         }
270     }
271
272     private void validateSampleResponse(Map<String, Object> sampleResponseBodyMap) {
273
274         // validate the json
275         Object json = sampleResponseBodyMap.get(BODY);
276         if (json == null) {
277             schemaErrors.add(HTTP_SAMPLE_RESPONSE_EMPTY);
278             return;
279         }
280         String jsonString = json.toString();
281         try {
282             if (jsonString.startsWith("[")) {
283                 new ObjectMapper().readValue(jsonString, JSONObject[].class);
284             } else {
285                 new ObjectMapper().readValue(jsonString, JSONObject.class);
286             }
287         } catch (IOException e1) { // NOSONAR
288             schemaErrors.add(HTTP_SAMPLE_RESPONSE_FAILED_PARSING);
289         }
290     }
291
292 }