1466980156c46334c58050dda0d4b46a970c6546
[sdc.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.be.model.tosca.validators;
22
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Map.Entry;
27 import java.util.Set;
28
29 import org.apache.commons.lang3.tuple.ImmutablePair;
30 import org.openecomp.sdc.be.model.DataTypeDefinition;
31 import org.openecomp.sdc.be.model.PropertyDefinition;
32 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
33 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
34 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 import com.google.gson.Gson;
39 import com.google.gson.JsonElement;
40 import com.google.gson.JsonObject;
41 import com.google.gson.JsonParser;
42 import com.google.gson.JsonPrimitive;
43 import com.google.gson.JsonSyntaxException;
44
45 public class DataTypeValidatorConverter {
46
47         private static DataTypeValidatorConverter dataTypeValidatorConverter = new DataTypeValidatorConverter();
48
49         public static DataTypeValidatorConverter getInstance() {
50                 return dataTypeValidatorConverter;
51         }
52
53         private DataTypeValidatorConverter() {
54
55         }
56
57         private static Logger log = LoggerFactory.getLogger(DataTypeValidatorConverter.class.getName());
58
59         JsonParser jsonParser = new JsonParser();
60
61         Gson gson = new Gson();
62
63         ImmutablePair<JsonElement, Boolean> falseResult = new ImmutablePair<JsonElement, Boolean>(null, false);
64         ImmutablePair<JsonElement, Boolean> trueEmptyResult = new ImmutablePair<JsonElement, Boolean>(null, true);
65
66         ImmutablePair<String, Boolean> trueStringEmptyResult = new ImmutablePair<String, Boolean>(null, true);
67         ImmutablePair<String, Boolean> falseStringEmptyResult = new ImmutablePair<String, Boolean>(null, true);
68
69         private ToscaPropertyType isDataTypeDerviedFromScalarType(DataTypeDefinition dataTypeDef) {
70
71                 ToscaPropertyType result = null;
72
73                 DataTypeDefinition dataType = dataTypeDef;
74
75                 while (dataType != null) {
76
77                         String name = dataType.getName();
78                         ToscaPropertyType typeIfScalar = ToscaPropertyType.getTypeIfScalar(name);
79                         if (typeIfScalar != null) {
80                                 result = typeIfScalar;
81                                 break;
82                         }
83
84                         dataType = dataType.getDerivedFrom();
85                 }
86
87                 return result;
88         }
89
90         private ImmutablePair<JsonElement, Boolean> validateAndUpdate(JsonElement jsonElement, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
91
92                 Map<String, PropertyDefinition> allProperties = getAllProperties(dataTypeDefinition);
93
94                 ToscaPropertyType toscaPropertyType = null;
95                 if ((toscaPropertyType = isDataTypeDerviedFromScalarType(dataTypeDefinition)) != null) {
96
97                         PropertyTypeValidator validator = toscaPropertyType.getValidator();
98                         PropertyValueConverter converter = toscaPropertyType.getConverter();
99                         if (jsonElement == null || true == jsonElement.isJsonNull()) {
100                                 boolean valid = validator.isValid(null, null, allDataTypes);
101                                 if (!valid) {
102                                         log.trace("Failed in validation of property {} from type {}",  dataTypeDefinition.getName(), dataTypeDefinition.getName());
103                                         return falseResult;
104                                 }
105                                 return new ImmutablePair<JsonElement, Boolean>(jsonElement, true);
106
107                         } else {
108                                 if (jsonElement.isJsonPrimitive()) {
109                                         String value = null;
110                                         if (jsonElement != null) {
111                                                 if (jsonElement.toString().isEmpty()) {
112                                                         value = "";
113                                                 } else {
114                                                         value = jsonElement.toString();
115                                                 }
116                                         }
117                                         boolean valid = validator.isValid(value, null, null);
118                                         if (!valid) {
119                                                 log.trace("Failed in validation of property {} from type {}. Json primitive value is {}", dataTypeDefinition.getName(), dataTypeDefinition.getName(), value);
120                                                 return falseResult;
121                                         }
122
123                                         String convertedValue = converter.convert(value, null, allDataTypes);
124                                         JsonElement element = null;
125                                         try {
126                                                 element = jsonParser.parse(convertedValue);
127                                         } catch (JsonSyntaxException e) {
128                                                 log.debug("Failed to parse value {} of property {} {}", convertedValue, dataTypeDefinition.getName(), e);
129                                                 return falseResult;
130                                         }
131
132                                         return new ImmutablePair<JsonElement, Boolean>(element, true);
133
134                                 } else {
135                                         // MAP, LIST, OTHER types cannot be applied data type
136                                         // definition scalar type. We currently cannot derived from
137                                         // map/list. (cannot add the entry schema to it)
138                                         log.debug("We cannot derive from list/map. Thus, the value cannot be not primitive since the data type {} is scalar one", dataTypeDefinition.getName());
139
140                                         return falseResult;
141                                 }
142                         }
143                 } else {
144
145                         if (jsonElement == null || jsonElement.isJsonNull()) {
146
147                                 return new ImmutablePair<JsonElement, Boolean>(jsonElement, true);
148
149                         } else {
150
151                                 if (jsonElement.isJsonObject()) {
152
153                                         JsonObject buildJsonObject = new JsonObject();
154
155                                         JsonObject asJsonObject = jsonElement.getAsJsonObject();
156                                         Set<Entry<String, JsonElement>> entrySet = asJsonObject.entrySet();
157
158                                         for (Entry<String, JsonElement> entry : entrySet) {
159                                                 String propName = entry.getKey();
160
161                                                 JsonElement elementValue = entry.getValue();
162
163                                                 PropertyDefinition propertyDefinition = allProperties.get(propName);
164                                                 if (propertyDefinition == null) {
165                                                         log.debug("The property {} was not found under data type {}" ,propName, dataTypeDefinition.getName());
166                                                         return falseResult;
167                                                 }
168                                                 String type = propertyDefinition.getType();
169                                                 boolean isScalarType = ToscaPropertyType.isScalarType(type);
170
171                                                 if (isScalarType) {
172                                                         ToscaPropertyType propertyType = ToscaPropertyType.isValidType(type);
173                                                         if (propertyType == null) {
174                                                                 log.debug("cannot find the {} under default tosca property types", type);
175                                                                 return falseResult;
176                                                         }
177                                                         PropertyTypeValidator validator = propertyType.getValidator();
178                                                         String innerType = null;
179                                                         if (propertyType == ToscaPropertyType.LIST || propertyType == ToscaPropertyType.MAP) {
180                                                                 if (propertyDefinition.getSchema() != null && propertyDefinition.getSchema().getProperty() != null) {
181                                                                         innerType = propertyDefinition.getSchema().getProperty().getType();
182                                                                         if (innerType == null) {
183                                                                                 log.debug("Property type {} must have inner type in its declaration.", propertyType);
184                                                                                 return falseResult;
185                                                                         }
186                                                                 }
187                                                         }
188
189                                                         String value = null;
190                                                         if (elementValue != null) {
191                                                                 if (elementValue.isJsonPrimitive() && elementValue.getAsString().isEmpty()) {
192                                                                         value = "";
193                                                                 } else {
194                                                                         value = elementValue.toString();
195                                                                 }
196                                                         }
197
198                                                         boolean isValid = validator.isValid(value, innerType, allDataTypes);
199                                                         if (false == isValid) {
200                                                                 log.debug("Failed to validate the value {} from type {}", value, propertyType);
201                                                                 return falseResult;
202                                                         }
203
204                                                         PropertyValueConverter converter = propertyType.getConverter();
205                                                         String convertedValue = converter.convert(value, innerType, allDataTypes);
206
207                                                         JsonElement element = null;
208                                                         if (convertedValue != null) {
209                                                                 if (convertedValue.isEmpty()) {
210                                                                         element = new JsonPrimitive("");
211                                                                 } else {
212                                                                         try {
213                                                                                 element = jsonParser.parse(convertedValue);
214                                                                         } catch (JsonSyntaxException e) {
215                                                                                 log.debug("Failed to parse value {} of type {}", convertedValue, propertyType, e);
216                                                                                 return falseResult;
217                                                                         }
218                                                                 }
219                                                         }
220                                                         buildJsonObject.add(propName, element);
221
222                                                 } else {
223
224                                                         DataTypeDefinition typeDefinition = allDataTypes.get(type);
225                                                         if (typeDefinition == null) {
226                                                                 log.debug("The data type {} cannot be found in the given data type list.", type);
227                                                                 return falseResult;
228                                                         }
229
230                                                         ImmutablePair<JsonElement, Boolean> isValid = validateAndUpdate(elementValue, typeDefinition, allDataTypes);
231
232                                                         if (!isValid.getRight().booleanValue()) {
233                                                                 log.debug("Failed in validation of value {} from type {}", (elementValue != null ? elementValue.toString() : null), typeDefinition.getName());
234                                                                 return falseResult;
235                                                         }
236
237                                                         buildJsonObject.add(propName, isValid.getLeft());
238                                                 }
239
240                                         }
241
242                                         return new ImmutablePair<JsonElement, Boolean>(buildJsonObject, true);
243                                 } else {
244                                         log.debug("The value {} of type {} should be json object", (jsonElement != null ? jsonElement.toString() : null), dataTypeDefinition.getName());
245                                         return falseResult;
246                                 }
247
248                         }
249                 }
250
251         }
252
253         public ImmutablePair<JsonElement, Boolean> validateAndUpdate(String value, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
254
255                 ImmutablePair<JsonElement, Boolean> result = falseResult;
256
257                 if (value == null || value.isEmpty()) {
258                         return trueEmptyResult;
259                 }
260
261                 JsonElement jsonElement = null;
262                 try {
263                         jsonElement = jsonParser.parse(value);
264                 } catch (JsonSyntaxException e) {
265                         return falseResult;
266                 }
267
268                 result = validateAndUpdate(jsonElement, dataTypeDefinition, allDataTypes);
269
270                 return result;
271         }
272
273         private Map<String, PropertyDefinition> getAllProperties(DataTypeDefinition dataTypeDefinition) {
274
275                 Map<String, PropertyDefinition> allParentsProps = new HashMap<String, PropertyDefinition>();
276
277                 while (dataTypeDefinition != null) {
278
279                         List<PropertyDefinition> currentParentsProps = dataTypeDefinition.getProperties();
280                         if (currentParentsProps != null) {
281                                 currentParentsProps.stream().forEach(p -> allParentsProps.put(p.getName(), p));
282                         }
283
284                         dataTypeDefinition = dataTypeDefinition.getDerivedFrom();
285                 }
286
287                 return allParentsProps;
288         }
289
290         private String getValueFromJsonElement(JsonElement jsonElement) {
291                 String value = null;
292
293                 if (jsonElement == null || jsonElement.isJsonNull()) {
294                         value = PropertyOperation.EMPTY_VALUE;
295                 } else {
296                         if (jsonElement.toString().isEmpty()) {
297                                 value = "";
298                         } else {
299                                 value = jsonElement.toString();
300                         }
301                 }
302
303                 return value;
304         }
305
306         public boolean isValid(String value, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
307
308                 boolean result = false;
309
310                 if (value == null || value.isEmpty()) {
311                         return true;
312                 }
313
314                 JsonElement jsonElement = null;
315                 try {
316                         jsonElement = jsonParser.parse(value);
317                 } catch (JsonSyntaxException e) {
318                         log.debug("Failed to parse the value {} from type {}", value, dataTypeDefinition, e);
319                         return false;
320                 }
321
322                 result = isValid(jsonElement, dataTypeDefinition, allDataTypes);
323
324                 return result;
325         }
326
327         private boolean isValid(JsonElement jsonElement, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
328
329                 Map<String, PropertyDefinition> allProperties = getAllProperties(dataTypeDefinition);
330
331                 ToscaPropertyType toscaPropertyType = null;
332                 if ((toscaPropertyType = isDataTypeDerviedFromScalarType(dataTypeDefinition)) != null) {
333
334                         PropertyTypeValidator validator = toscaPropertyType.getValidator();
335                         if (jsonElement == null || true == jsonElement.isJsonNull()) {
336                                 boolean valid = validator.isValid(null, null, allDataTypes);
337                                 if (false == valid) {
338                                         log.trace("Failed in validation of property {} from type {}", dataTypeDefinition.getName(), dataTypeDefinition.getName());
339                                         return false;
340                                 }
341
342                                 return true;
343
344                         } else {
345                                 if (true == jsonElement.isJsonPrimitive()) {
346                                         String value = null;
347                                         if (jsonElement != null) {
348                                                 if (jsonElement.toString().isEmpty()) {
349                                                         value = "";
350                                                 } else {
351                                                         value = jsonElement.toString();
352                                                 }
353                                         }
354                                         boolean valid = validator.isValid(value, null, allDataTypes);
355                                         if (false == valid) {
356                                                 log.trace("Failed in validation of property {} from type {}. Json primitive value is {}", dataTypeDefinition.getName(), dataTypeDefinition.getName(), value);
357                                                 return false;
358                                         }
359
360                                         return true;
361
362                                 } else {
363                                         // MAP, LIST, OTHER types cannot be applied data type
364                                         // definition scalar type. We currently cannot derived from
365                                         // map/list. (cannot add the entry schema to it)
366                                         log.debug("We cannot derive from list/map. Thus, the value cannot be not primitive since the data type {} is scalar one", dataTypeDefinition.getName());
367
368                                         return false;
369                                 }
370                         }
371                 } else {
372
373                         if (jsonElement == null || jsonElement.isJsonNull()) {
374
375                                 return true;
376
377                         } else {
378
379                                 if (jsonElement.isJsonObject()) {
380
381                                         JsonObject asJsonObject = jsonElement.getAsJsonObject();
382                                         Set<Entry<String, JsonElement>> entrySet = asJsonObject.entrySet();
383
384                                         for (Entry<String, JsonElement> entry : entrySet) {
385                                                 String propName = entry.getKey();
386
387                                                 JsonElement elementValue = entry.getValue();
388
389                                                 PropertyDefinition propertyDefinition = allProperties.get(propName);
390                                                 if (propertyDefinition == null) {
391                                                         log.debug("The property {} was not found under data type {}", propName, dataTypeDefinition.getName());
392                                                         return false;
393                                                 }
394                                                 String type = propertyDefinition.getType();
395                                                 boolean isScalarType = ToscaPropertyType.isScalarType(type);
396
397                                                 if (true == isScalarType) {
398                                                         ToscaPropertyType propertyType = ToscaPropertyType.isValidType(type);
399                                                         if (propertyType == null) {
400                                                                 log.debug("cannot find the {} under default tosca property types", type);
401                                                                 return false;
402                                                         }
403                                                         PropertyTypeValidator validator = propertyType.getValidator();
404                                                         String innerType = null;
405                                                         if (propertyType == ToscaPropertyType.LIST || propertyType == ToscaPropertyType.MAP) {
406                                                                 if (propertyDefinition.getSchema() != null && propertyDefinition.getSchema().getProperty() != null) {
407                                                                         innerType = propertyDefinition.getSchema().getProperty().getType();
408                                                                         if (innerType == null) {
409                                                                                 log.debug("Property type {} must have inner type in its declaration.", propertyType);
410                                                                                 return false;
411                                                                         }
412                                                                 }
413                                                         }
414
415                                                         String value = null;
416                                                         if (elementValue != null) {
417                                                                 if (elementValue.isJsonPrimitive() && elementValue.getAsString().isEmpty()) {
418                                                                         value = "";
419                                                                 } else {
420                                                                         value = elementValue.toString();
421                                                                 }
422                                                         }
423
424                                                         boolean isValid = validator.isValid(value, innerType, allDataTypes);
425                                                         if (false == isValid) {
426                                                                 log.debug("Failed to validate the value {} from type {}", value, propertyType);
427                                                                 return false;
428                                                         }
429
430                                                 } else {
431
432                                                         DataTypeDefinition typeDefinition = allDataTypes.get(type);
433                                                         if (typeDefinition == null) {
434                                                                 log.debug("The data type {} cannot be found in the given data type list.", type);
435                                                                 return false;
436                                                         }
437
438                                                         boolean isValid = isValid(elementValue, typeDefinition, allDataTypes);
439
440                                                         if (false == isValid) {
441                                                                 log.debug("Failed in validation of value {} from type {}", (elementValue != null ? elementValue.toString() : null), typeDefinition.getName());
442                                                                 return false;
443                                                         }
444
445                                                 }
446
447                                         }
448
449                                         return true;
450                                 } else {
451                                         log.debug("The value {} of type {} should be json object", (jsonElement != null ? jsonElement.toString() : null), dataTypeDefinition.getName());
452                                         return false;
453                                 }
454
455                         }
456                 }
457
458         }
459 }