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.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;
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;
45 public class DataTypeValidatorConverter {
47 private static DataTypeValidatorConverter dataTypeValidatorConverter = new DataTypeValidatorConverter();
49 public static DataTypeValidatorConverter getInstance() {
50 return dataTypeValidatorConverter;
53 private DataTypeValidatorConverter() {
57 private static Logger log = LoggerFactory.getLogger(DataTypeValidatorConverter.class.getName());
59 JsonParser jsonParser = new JsonParser();
61 Gson gson = new Gson();
63 ImmutablePair<JsonElement, Boolean> falseResult = new ImmutablePair<JsonElement, Boolean>(null, false);
64 ImmutablePair<JsonElement, Boolean> trueEmptyResult = new ImmutablePair<JsonElement, Boolean>(null, true);
66 ImmutablePair<String, Boolean> trueStringEmptyResult = new ImmutablePair<String, Boolean>(null, true);
67 ImmutablePair<String, Boolean> falseStringEmptyResult = new ImmutablePair<String, Boolean>(null, true);
69 private ToscaPropertyType isDataTypeDerviedFromScalarType(DataTypeDefinition dataTypeDef) {
71 ToscaPropertyType result = null;
73 DataTypeDefinition dataType = dataTypeDef;
75 while (dataType != null) {
77 String name = dataType.getName();
78 ToscaPropertyType typeIfScalar = ToscaPropertyType.getTypeIfScalar(name);
79 if (typeIfScalar != null) {
80 result = typeIfScalar;
84 dataType = dataType.getDerivedFrom();
90 private ImmutablePair<JsonElement, Boolean> validateAndUpdate(JsonElement jsonElement, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
92 Map<String, PropertyDefinition> allProperties = getAllProperties(dataTypeDefinition);
94 ToscaPropertyType toscaPropertyType = null;
95 if ((toscaPropertyType = isDataTypeDerviedFromScalarType(dataTypeDefinition)) != null) {
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);
102 log.trace("Failed in validation of property {} from type {}", dataTypeDefinition.getName(), dataTypeDefinition.getName());
105 return new ImmutablePair<JsonElement, Boolean>(jsonElement, true);
108 if (jsonElement.isJsonPrimitive()) {
110 if (jsonElement != null) {
111 if (jsonElement.toString().isEmpty()) {
114 value = jsonElement.toString();
117 boolean valid = validator.isValid(value, null, null);
119 log.trace("Failed in validation of property {} from type {}. Json primitive value is {}", dataTypeDefinition.getName(), dataTypeDefinition.getName(), value);
123 String convertedValue = converter.convert(value, null, allDataTypes);
124 JsonElement element = null;
126 element = jsonParser.parse(convertedValue);
127 } catch (JsonSyntaxException e) {
128 log.debug("Failed to parse value {} of property {} {}", convertedValue, dataTypeDefinition.getName(), e);
132 return new ImmutablePair<JsonElement, Boolean>(element, true);
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());
145 if (jsonElement == null || jsonElement.isJsonNull()) {
147 return new ImmutablePair<JsonElement, Boolean>(jsonElement, true);
151 if (jsonElement.isJsonObject()) {
153 JsonObject buildJsonObject = new JsonObject();
155 JsonObject asJsonObject = jsonElement.getAsJsonObject();
156 Set<Entry<String, JsonElement>> entrySet = asJsonObject.entrySet();
158 for (Entry<String, JsonElement> entry : entrySet) {
159 String propName = entry.getKey();
161 JsonElement elementValue = entry.getValue();
163 PropertyDefinition propertyDefinition = allProperties.get(propName);
164 if (propertyDefinition == null) {
165 log.debug("The property {} was not found under data type {}" ,propName, dataTypeDefinition.getName());
168 String type = propertyDefinition.getType();
169 boolean isScalarType = ToscaPropertyType.isScalarType(type);
172 ToscaPropertyType propertyType = ToscaPropertyType.isValidType(type);
173 if (propertyType == null) {
174 log.debug("cannot find the {} under default tosca property types", type);
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);
190 if (elementValue != null) {
191 if (elementValue.isJsonPrimitive() && elementValue.getAsString().isEmpty()) {
194 value = elementValue.toString();
198 boolean isValid = validator.isValid(value, innerType, allDataTypes);
199 if (false == isValid) {
200 log.debug("Failed to validate the value {} from type {}", value, propertyType);
204 PropertyValueConverter converter = propertyType.getConverter();
205 String convertedValue = converter.convert(value, innerType, allDataTypes);
207 JsonElement element = null;
208 if (convertedValue != null) {
209 if (convertedValue.isEmpty()) {
210 element = new JsonPrimitive("");
213 element = jsonParser.parse(convertedValue);
214 } catch (JsonSyntaxException e) {
215 log.debug("Failed to parse value {} of type {}", convertedValue, propertyType, e);
220 buildJsonObject.add(propName, element);
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);
230 ImmutablePair<JsonElement, Boolean> isValid = validateAndUpdate(elementValue, typeDefinition, allDataTypes);
232 if (!isValid.getRight().booleanValue()) {
233 log.debug("Failed in validation of value {} from type {}", (elementValue != null ? elementValue.toString() : null), typeDefinition.getName());
237 buildJsonObject.add(propName, isValid.getLeft());
242 return new ImmutablePair<JsonElement, Boolean>(buildJsonObject, true);
244 log.debug("The value {} of type {} should be json object", (jsonElement != null ? jsonElement.toString() : null), dataTypeDefinition.getName());
253 public ImmutablePair<JsonElement, Boolean> validateAndUpdate(String value, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
255 ImmutablePair<JsonElement, Boolean> result = falseResult;
257 if (value == null || value.isEmpty()) {
258 return trueEmptyResult;
261 JsonElement jsonElement = null;
263 jsonElement = jsonParser.parse(value);
264 } catch (JsonSyntaxException e) {
268 result = validateAndUpdate(jsonElement, dataTypeDefinition, allDataTypes);
273 private Map<String, PropertyDefinition> getAllProperties(DataTypeDefinition dataTypeDefinition) {
275 Map<String, PropertyDefinition> allParentsProps = new HashMap<String, PropertyDefinition>();
277 while (dataTypeDefinition != null) {
279 List<PropertyDefinition> currentParentsProps = dataTypeDefinition.getProperties();
280 if (currentParentsProps != null) {
281 currentParentsProps.stream().forEach(p -> allParentsProps.put(p.getName(), p));
284 dataTypeDefinition = dataTypeDefinition.getDerivedFrom();
287 return allParentsProps;
290 private String getValueFromJsonElement(JsonElement jsonElement) {
293 if (jsonElement == null || jsonElement.isJsonNull()) {
294 value = PropertyOperation.EMPTY_VALUE;
296 if (jsonElement.toString().isEmpty()) {
299 value = jsonElement.toString();
306 public boolean isValid(String value, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
308 boolean result = false;
310 if (value == null || value.isEmpty()) {
314 JsonElement jsonElement = null;
316 jsonElement = jsonParser.parse(value);
317 } catch (JsonSyntaxException e) {
318 log.debug("Failed to parse the value {} from type {}", value, dataTypeDefinition, e);
322 result = isValid(jsonElement, dataTypeDefinition, allDataTypes);
327 private boolean isValid(JsonElement jsonElement, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
329 Map<String, PropertyDefinition> allProperties = getAllProperties(dataTypeDefinition);
331 ToscaPropertyType toscaPropertyType = null;
332 if ((toscaPropertyType = isDataTypeDerviedFromScalarType(dataTypeDefinition)) != null) {
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());
345 if (true == jsonElement.isJsonPrimitive()) {
347 if (jsonElement != null) {
348 if (jsonElement.toString().isEmpty()) {
351 value = jsonElement.toString();
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);
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());
373 if (jsonElement == null || jsonElement.isJsonNull()) {
379 if (jsonElement.isJsonObject()) {
381 JsonObject asJsonObject = jsonElement.getAsJsonObject();
382 Set<Entry<String, JsonElement>> entrySet = asJsonObject.entrySet();
384 for (Entry<String, JsonElement> entry : entrySet) {
385 String propName = entry.getKey();
387 JsonElement elementValue = entry.getValue();
389 PropertyDefinition propertyDefinition = allProperties.get(propName);
390 if (propertyDefinition == null) {
391 log.debug("The property {} was not found under data type {}", propName, dataTypeDefinition.getName());
394 String type = propertyDefinition.getType();
395 boolean isScalarType = ToscaPropertyType.isScalarType(type);
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);
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);
416 if (elementValue != null) {
417 if (elementValue.isJsonPrimitive() && elementValue.getAsString().isEmpty()) {
420 value = elementValue.toString();
424 boolean isValid = validator.isValid(value, innerType, allDataTypes);
425 if (false == isValid) {
426 log.debug("Failed to validate the value {} from type {}", value, propertyType);
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);
438 boolean isValid = isValid(elementValue, typeDefinition, allDataTypes);
440 if (false == isValid) {
441 log.debug("Failed in validation of value {} from type {}", (elementValue != null ? elementValue.toString() : null), typeDefinition.getName());
451 log.debug("The value {} of type {} should be json object", (jsonElement != null ? jsonElement.toString() : null), dataTypeDefinition.getName());