2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.sdc.be.model.tosca.validators;
23 import java.util.HashMap;
24 import java.util.List;
26 import java.util.Map.Entry;
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.tosca.ToscaPropertyType;
33 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
37 import com.google.gson.JsonElement;
38 import com.google.gson.JsonObject;
39 import com.google.gson.JsonParser;
40 import com.google.gson.JsonPrimitive;
41 import com.google.gson.JsonSyntaxException;
43 public class DataTypeValidatorConverter {
45 private static DataTypeValidatorConverter dataTypeValidatorConverter = new DataTypeValidatorConverter();
47 public static DataTypeValidatorConverter getInstance() {
48 return dataTypeValidatorConverter;
51 private DataTypeValidatorConverter() {
55 private static Logger log = LoggerFactory.getLogger(DataTypeValidatorConverter.class.getName());
57 JsonParser jsonParser = new JsonParser();
59 ImmutablePair<JsonElement, Boolean> falseResult = new ImmutablePair<JsonElement, Boolean>(null, false);
60 ImmutablePair<JsonElement, Boolean> trueEmptyResult = new ImmutablePair<JsonElement, Boolean>(null, true);
62 ImmutablePair<String, Boolean> trueStringEmptyResult = new ImmutablePair<String, Boolean>(null, true);
63 ImmutablePair<String, Boolean> falseStringEmptyResult = new ImmutablePair<String, Boolean>(null, true);
65 private ToscaPropertyType isDataTypeDerviedFromScalarType(DataTypeDefinition dataTypeDef) {
67 ToscaPropertyType result = null;
69 DataTypeDefinition dataType = dataTypeDef;
71 while (dataType != null) {
73 String name = dataType.getName();
74 ToscaPropertyType typeIfScalar = ToscaPropertyType.getTypeIfScalar(name);
75 if (typeIfScalar != null) {
76 result = typeIfScalar;
80 dataType = dataType.getDerivedFrom();
86 private ImmutablePair<JsonElement, Boolean> validateAndUpdate(JsonElement jsonElement, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
88 Map<String, PropertyDefinition> allProperties = getAllProperties(dataTypeDefinition);
90 ToscaPropertyType toscaPropertyType = null;
91 if ((toscaPropertyType = isDataTypeDerviedFromScalarType(dataTypeDefinition)) != null) {
93 PropertyTypeValidator validator = toscaPropertyType.getValidator();
94 PropertyValueConverter converter = toscaPropertyType.getConverter();
95 if (jsonElement == null || true == jsonElement.isJsonNull()) {
96 boolean valid = validator.isValid(null, null, allDataTypes);
98 log.trace("Failed in validation of property {} from type {}", dataTypeDefinition.getName(), dataTypeDefinition.getName());
101 return new ImmutablePair<JsonElement, Boolean>(jsonElement, true);
104 if (jsonElement.isJsonPrimitive()) {
106 if (jsonElement != null) {
107 if (jsonElement.toString().isEmpty()) {
110 value = jsonElement.toString();
113 boolean valid = validator.isValid(value, null, null);
115 log.trace("Failed in validation of property {} from type {}. Json primitive value is {}", dataTypeDefinition.getName(), dataTypeDefinition.getName(), value);
119 String convertedValue = converter.convert(value, null, allDataTypes);
120 JsonElement element = null;
122 element = jsonParser.parse(convertedValue);
123 } catch (JsonSyntaxException e) {
124 log.debug("Failed to parse value {} of property {} {}", convertedValue, dataTypeDefinition.getName(), e);
128 return new ImmutablePair<JsonElement, Boolean>(element, true);
131 // MAP, LIST, OTHER types cannot be applied data type
132 // definition scalar type. We currently cannot derived from
133 // map/list. (cannot add the entry schema to it)
134 log.debug("We cannot derive from list/map. Thus, the value cannot be not primitive since the data type {} is scalar one", dataTypeDefinition.getName());
141 if (jsonElement == null || jsonElement.isJsonNull()) {
143 return new ImmutablePair<JsonElement, Boolean>(jsonElement, true);
147 if (jsonElement.isJsonObject()) {
149 JsonObject buildJsonObject = new JsonObject();
151 JsonObject asJsonObject = jsonElement.getAsJsonObject();
152 Set<Entry<String, JsonElement>> entrySet = asJsonObject.entrySet();
154 for (Entry<String, JsonElement> entry : entrySet) {
155 String propName = entry.getKey();
157 JsonElement elementValue = entry.getValue();
159 PropertyDefinition propertyDefinition = allProperties.get(propName);
160 if (propertyDefinition == null) {
161 log.debug("The property {} was not found under data type {}" ,propName, dataTypeDefinition.getName());
164 String type = propertyDefinition.getType();
165 boolean isScalarType = ToscaPropertyType.isScalarType(type);
168 ToscaPropertyType propertyType = ToscaPropertyType.isValidType(type);
169 if (propertyType == null) {
170 log.debug("cannot find the {} under default tosca property types", type);
173 PropertyTypeValidator validator = propertyType.getValidator();
174 String innerType = null;
175 if (propertyType == ToscaPropertyType.LIST || propertyType == ToscaPropertyType.MAP) {
176 if (propertyDefinition.getSchema() != null && propertyDefinition.getSchema().getProperty() != null) {
177 innerType = propertyDefinition.getSchema().getProperty().getType();
178 if (innerType == null) {
179 log.debug("Property type {} must have inner type in its declaration.", propertyType);
186 if (elementValue != null) {
187 if (elementValue.isJsonPrimitive() && elementValue.getAsString().isEmpty()) {
190 value = elementValue.toString();
194 boolean isValid = validator.isValid(value, innerType, allDataTypes);
195 if (false == isValid) {
196 log.debug("Failed to validate the value {} from type {}", value, propertyType);
200 PropertyValueConverter converter = propertyType.getConverter();
201 String convertedValue = converter.convert(value, innerType, allDataTypes);
203 JsonElement element = null;
204 if (convertedValue != null) {
205 if (convertedValue.isEmpty()) {
206 element = new JsonPrimitive("");
209 element = jsonParser.parse(convertedValue);
210 } catch (JsonSyntaxException e) {
211 log.debug("Failed to parse value {} of type {}", convertedValue, propertyType, e);
216 buildJsonObject.add(propName, element);
220 DataTypeDefinition typeDefinition = allDataTypes.get(type);
221 if (typeDefinition == null) {
222 log.debug("The data type {} cannot be found in the given data type list.", type);
226 ImmutablePair<JsonElement, Boolean> isValid = validateAndUpdate(elementValue, typeDefinition, allDataTypes);
228 if (!isValid.getRight().booleanValue()) {
229 log.debug("Failed in validation of value {} from type {}", (elementValue != null ? elementValue.toString() : null), typeDefinition.getName());
233 buildJsonObject.add(propName, isValid.getLeft());
238 return new ImmutablePair<JsonElement, Boolean>(buildJsonObject, true);
240 log.debug("The value {} of type {} should be json object", (jsonElement != null ? jsonElement.toString() : null), dataTypeDefinition.getName());
249 public ImmutablePair<JsonElement, Boolean> validateAndUpdate(String value, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
251 ImmutablePair<JsonElement, Boolean> result = falseResult;
253 if (value == null || value.isEmpty()) {
254 return trueEmptyResult;
257 JsonElement jsonElement = null;
259 jsonElement = jsonParser.parse(value);
260 } catch (JsonSyntaxException e) {
264 result = validateAndUpdate(jsonElement, dataTypeDefinition, allDataTypes);
269 private Map<String, PropertyDefinition> getAllProperties(DataTypeDefinition dataTypeDefinition) {
271 Map<String, PropertyDefinition> allParentsProps = new HashMap<String, PropertyDefinition>();
273 while (dataTypeDefinition != null) {
275 List<PropertyDefinition> currentParentsProps = dataTypeDefinition.getProperties();
276 if (currentParentsProps != null) {
277 currentParentsProps.stream().forEach(p -> allParentsProps.put(p.getName(), p));
280 dataTypeDefinition = dataTypeDefinition.getDerivedFrom();
283 return allParentsProps;
286 public boolean isValid(String value, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
288 boolean result = false;
290 if (value == null || value.isEmpty()) {
294 JsonElement jsonElement = null;
296 jsonElement = jsonParser.parse(value);
297 } catch (JsonSyntaxException e) {
298 log.debug("Failed to parse the value {} from type {}", value, dataTypeDefinition, e);
302 result = isValid(jsonElement, dataTypeDefinition, allDataTypes);
307 private boolean isValid(JsonElement jsonElement, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
309 Map<String, PropertyDefinition> allProperties = getAllProperties(dataTypeDefinition);
311 ToscaPropertyType toscaPropertyType = null;
312 if ((toscaPropertyType = isDataTypeDerviedFromScalarType(dataTypeDefinition)) != null) {
314 PropertyTypeValidator validator = toscaPropertyType.getValidator();
315 if (jsonElement == null || true == jsonElement.isJsonNull()) {
316 boolean valid = validator.isValid(null, null, allDataTypes);
317 if (false == valid) {
318 log.trace("Failed in validation of property {} from type {}", dataTypeDefinition.getName(), dataTypeDefinition.getName());
325 if (true == jsonElement.isJsonPrimitive()) {
327 if (jsonElement != null) {
328 if (jsonElement.toString().isEmpty()) {
331 value = jsonElement.toString();
334 boolean valid = validator.isValid(value, null, allDataTypes);
335 if (false == valid) {
336 log.trace("Failed in validation of property {} from type {}. Json primitive value is {}", dataTypeDefinition.getName(), dataTypeDefinition.getName(), value);
343 // MAP, LIST, OTHER types cannot be applied data type
344 // definition scalar type. We currently cannot derived from
345 // map/list. (cannot add the entry schema to it)
346 log.debug("We cannot derive from list/map. Thus, the value cannot be not primitive since the data type {} is scalar one", dataTypeDefinition.getName());
353 if (jsonElement == null || jsonElement.isJsonNull()) {
359 if (jsonElement.isJsonObject()) {
361 JsonObject asJsonObject = jsonElement.getAsJsonObject();
362 Set<Entry<String, JsonElement>> entrySet = asJsonObject.entrySet();
364 for (Entry<String, JsonElement> entry : entrySet) {
365 String propName = entry.getKey();
367 JsonElement elementValue = entry.getValue();
369 PropertyDefinition propertyDefinition = allProperties.get(propName);
370 if (propertyDefinition == null) {
371 log.debug("The property {} was not found under data type {}", propName, dataTypeDefinition.getName());
374 String type = propertyDefinition.getType();
375 boolean isScalarType = ToscaPropertyType.isScalarType(type);
377 if (true == isScalarType) {
378 ToscaPropertyType propertyType = ToscaPropertyType.isValidType(type);
379 if (propertyType == null) {
380 log.debug("cannot find the {} under default tosca property types", type);
383 PropertyTypeValidator validator = propertyType.getValidator();
384 String innerType = null;
385 if (propertyType == ToscaPropertyType.LIST || propertyType == ToscaPropertyType.MAP) {
386 if (propertyDefinition.getSchema() != null && propertyDefinition.getSchema().getProperty() != null) {
387 innerType = propertyDefinition.getSchema().getProperty().getType();
388 if (innerType == null) {
389 log.debug("Property type {} must have inner type in its declaration.", propertyType);
396 if (elementValue != null) {
397 if (elementValue.isJsonPrimitive() && elementValue.getAsString().isEmpty()) {
400 value = elementValue.toString();
404 boolean isValid = validator.isValid(value, innerType, allDataTypes);
405 if (false == isValid) {
406 log.debug("Failed to validate the value {} from type {}", value, propertyType);
412 DataTypeDefinition typeDefinition = allDataTypes.get(type);
413 if (typeDefinition == null) {
414 log.debug("The data type {} cannot be found in the given data type list.", type);
418 boolean isValid = isValid(elementValue, typeDefinition, allDataTypes);
420 if (false == isValid) {
421 log.debug("Failed in validation of value {} from type {}", (elementValue != null ? elementValue.toString() : null), typeDefinition.getName());
431 log.debug("The value {} of type {} should be json object", (jsonElement != null ? jsonElement.toString() : null), dataTypeDefinition.getName());