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