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.api.StorageOperationStatus;
33 import org.openecomp.sdc.be.model.operations.impl.PropertyOperation;
34 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
35 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
39 import com.google.gson.Gson;
40 import com.google.gson.JsonElement;
41 import com.google.gson.JsonObject;
42 import com.google.gson.JsonParser;
43 import com.google.gson.JsonPrimitive;
44 import com.google.gson.JsonSyntaxException;
46 public class DataTypeValidatorConverter {
48 private static DataTypeValidatorConverter dataTypeValidatorConverter = new DataTypeValidatorConverter();
50 public static DataTypeValidatorConverter getInstance() {
51 return dataTypeValidatorConverter;
54 private DataTypeValidatorConverter() {
58 private static Logger log = LoggerFactory.getLogger(DataTypeValidatorConverter.class.getName());
60 JsonParser jsonParser = new JsonParser();
62 Gson gson = new Gson();
64 ImmutablePair<JsonElement, Boolean> falseResult = new ImmutablePair<JsonElement, Boolean>(null, false);
65 ImmutablePair<JsonElement, Boolean> trueEmptyResult = new ImmutablePair<JsonElement, Boolean>(null, true);
67 ImmutablePair<String, Boolean> trueStringEmptyResult = new ImmutablePair<String, Boolean>(null, true);
68 ImmutablePair<String, Boolean> falseStringEmptyResult = new ImmutablePair<String, Boolean>(null, true);
70 private ToscaPropertyType isDataTypeDerviedFromScalarType(DataTypeDefinition dataTypeDef) {
72 ToscaPropertyType result = null;
74 DataTypeDefinition dataType = dataTypeDef;
76 while (dataType != null) {
78 String name = dataType.getName();
79 ToscaPropertyType typeIfScalar = ToscaPropertyType.getTypeIfScalar(name);
80 if (typeIfScalar != null) {
81 result = typeIfScalar;
85 dataType = dataType.getDerivedFrom();
91 private ImmutablePair<JsonElement, Boolean> validateAndUpdate(JsonElement jsonElement,
92 DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
94 Map<String, PropertyDefinition> allProperties = getAllProperties(dataTypeDefinition);
96 ToscaPropertyType toscaPropertyType = null;
97 if ((toscaPropertyType = isDataTypeDerviedFromScalarType(dataTypeDefinition)) != null) {
99 PropertyTypeValidator validator = toscaPropertyType.getValidator();
100 PropertyValueConverter converter = toscaPropertyType.getConverter();
101 if (jsonElement == null || true == jsonElement.isJsonNull()) {
102 boolean valid = validator.isValid(null, null, allDataTypes);
103 if (false == valid) {
104 log.trace("Failed in validation of property {} from type {}", dataTypeDefinition.getName(), dataTypeDefinition.getName());
107 return new ImmutablePair<JsonElement, Boolean>(jsonElement, true);
110 if (true == jsonElement.isJsonPrimitive()) {
112 if (jsonElement != null) {
113 if (jsonElement.toString().isEmpty()) {
116 value = jsonElement.toString();
119 boolean valid = validator.isValid(value, null, null);
120 if (false == valid) {
121 log.trace("Failed in validation of property {} from type {}. Json primitive value is {}", dataTypeDefinition.getName(), dataTypeDefinition.getName(), value);
125 String convertedValue = converter.convert(value, null, allDataTypes);
126 JsonElement element = null;
128 element = jsonParser.parse(convertedValue);
129 } catch (JsonSyntaxException e) {
130 log.debug("Failed to parse value {} of property {}. {}", convertedValue, dataTypeDefinition.getName(), e);
134 return new ImmutablePair<JsonElement, Boolean>(element, true);
137 // MAP, LIST, OTHER types cannot be applied data type
138 // definition scalar type. We currently cannot derived from
139 // map/list. (cannot add the entry schema to it)
140 log.debug("We cannot derive from list/map. Thus, the value cannot be not primitive since the data type {} is scalar one", dataTypeDefinition.getName());
147 if (jsonElement == null || jsonElement.isJsonNull()) {
149 return new ImmutablePair<JsonElement, Boolean>(jsonElement, true);
153 if (jsonElement.isJsonObject()) {
155 JsonObject buildJsonObject = new JsonObject();
157 JsonObject asJsonObject = jsonElement.getAsJsonObject();
158 Set<Entry<String, JsonElement>> entrySet = asJsonObject.entrySet();
160 for (Entry<String, JsonElement> entry : entrySet) {
161 String propName = entry.getKey();
163 JsonElement elementValue = entry.getValue();
165 PropertyDefinition propertyDefinition = allProperties.get(propName);
166 if (propertyDefinition == null) {
167 log.debug("The property {} was not found under data type {}", propName, dataTypeDefinition.getName());
170 String type = propertyDefinition.getType();
171 boolean isScalarType = ToscaPropertyType.isScalarType(type);
173 if (true == isScalarType) {
174 ToscaPropertyType propertyType = ToscaPropertyType.isValidType(type);
175 if (propertyType == null) {
176 log.debug("cannot find the {} under default tosca property types", type);
179 PropertyTypeValidator validator = propertyType.getValidator();
180 String innerType = null;
181 if (propertyType == ToscaPropertyType.LIST || propertyType == ToscaPropertyType.MAP) {
182 if (propertyDefinition.getSchema() != null
183 && propertyDefinition.getSchema().getProperty() != null) {
184 innerType = propertyDefinition.getSchema().getProperty().getType();
185 if (innerType == null) {
186 log.debug("Property type {} must have inner type in its declaration.", propertyType);
193 if (elementValue != null) {
194 if (elementValue.isJsonPrimitive() && elementValue.getAsString().isEmpty()) {
197 value = elementValue.toString();
201 boolean isValid = validator.isValid(value, innerType, allDataTypes);
202 if (false == isValid) {
203 log.debug("Failed to validate the value {} from type {}", value, propertyType);
207 PropertyValueConverter converter = propertyType.getConverter();
208 String convertedValue = converter.convert(value, innerType, allDataTypes);
210 JsonElement element = null;
211 if (convertedValue != null) {
212 if (convertedValue.isEmpty()) {
213 element = new JsonPrimitive("");
216 element = jsonParser.parse(convertedValue);
217 } catch (JsonSyntaxException e) {
218 log.debug("Failed to parse value {} of type {}. {}", convertedValue, propertyType, e);
223 buildJsonObject.add(propName, element);
227 DataTypeDefinition typeDefinition = allDataTypes.get(type);
228 if (typeDefinition == null) {
229 log.debug("The data type {] cannot be found in the given data type list.", type);
233 ImmutablePair<JsonElement, Boolean> isValid = validateAndUpdate(elementValue,
234 typeDefinition, allDataTypes);
236 if (false == isValid.getRight().booleanValue()) {
237 log.debug("Failed in validation of value {} from type {}", (elementValue != null ? elementValue.toString() : null), typeDefinition.getName());
241 buildJsonObject.add(propName, isValid.getLeft());
246 return new ImmutablePair<JsonElement, Boolean>(buildJsonObject, true);
248 log.debug("The value {} of type {} should be json object", (jsonElement != null ? jsonElement.toString() : null), dataTypeDefinition.getName());
257 public ImmutablePair<JsonElement, Boolean> validateAndUpdate(String value, DataTypeDefinition dataTypeDefinition,
258 Map<String, DataTypeDefinition> allDataTypes) {
260 ImmutablePair<JsonElement, Boolean> result = falseResult;
262 if (value == null || value.isEmpty()) {
263 return trueEmptyResult;
266 JsonElement jsonElement = null;
268 jsonElement = jsonParser.parse(value);
269 } catch (JsonSyntaxException e) {
273 result = validateAndUpdate(jsonElement, dataTypeDefinition, allDataTypes);
278 private Map<String, PropertyDefinition> getAllProperties(DataTypeDefinition dataTypeDefinition) {
280 Map<String, PropertyDefinition> allParentsProps = new HashMap<String, PropertyDefinition>();
282 while (dataTypeDefinition != null) {
284 List<PropertyDefinition> currentParentsProps = dataTypeDefinition.getProperties();
285 if (currentParentsProps != null) {
286 currentParentsProps.stream().forEach(p -> allParentsProps.put(p.getName(), p));
289 dataTypeDefinition = dataTypeDefinition.getDerivedFrom();
292 return allParentsProps;
295 private String getValueFromJsonElement(JsonElement jsonElement) {
298 if (jsonElement == null || jsonElement.isJsonNull()) {
299 value = PropertyOperation.EMPTY_VALUE;
301 if (jsonElement.toString().isEmpty()) {
304 value = jsonElement.toString();
311 public boolean isValid(String value, DataTypeDefinition dataTypeDefinition,
312 Map<String, DataTypeDefinition> allDataTypes) {
314 boolean result = false;
316 if (value == null || value.isEmpty()) {
320 JsonElement jsonElement = null;
322 jsonElement = jsonParser.parse(value);
323 } catch (JsonSyntaxException e) {
324 log.debug("Failed to parse the value {} from type {}. {}", value, dataTypeDefinition, e);
328 result = isValid(jsonElement, dataTypeDefinition, allDataTypes);
333 private boolean isValid(JsonElement jsonElement, DataTypeDefinition dataTypeDefinition,
334 Map<String, DataTypeDefinition> allDataTypes) {
336 Map<String, PropertyDefinition> allProperties = getAllProperties(dataTypeDefinition);
338 ToscaPropertyType toscaPropertyType = null;
339 if ((toscaPropertyType = isDataTypeDerviedFromScalarType(dataTypeDefinition)) != null) {
341 PropertyTypeValidator validator = toscaPropertyType.getValidator();
342 if (jsonElement == null || true == jsonElement.isJsonNull()) {
343 boolean valid = validator.isValid(null, null, allDataTypes);
344 if (false == valid) {
345 log.trace("Failed in validation of property " + dataTypeDefinition.getName() + " from type "
346 + dataTypeDefinition.getName());
353 if (true == jsonElement.isJsonPrimitive()) {
355 if (jsonElement != null) {
356 if (jsonElement.toString().isEmpty()) {
359 value = jsonElement.toString();
362 boolean valid = validator.isValid(value, null, allDataTypes);
363 if (false == valid) {
364 log.trace("Failed in validation of property {} from type {}. Json primitive value is {}", dataTypeDefinition.getName(), dataTypeDefinition.getName(), value);
371 // MAP, LIST, OTHER types cannot be applied data type
372 // definition scalar type. We currently cannot derived from
373 // map/list. (cannot add the entry schema to it)
374 log.debug("We cannot derive from list/map. Thus, the value cannot be not primitive since the data type {} is scalar one", dataTypeDefinition.getName());
381 if (jsonElement == null || jsonElement.isJsonNull()) {
387 if (jsonElement.isJsonObject()) {
389 JsonObject asJsonObject = jsonElement.getAsJsonObject();
390 Set<Entry<String, JsonElement>> entrySet = asJsonObject.entrySet();
392 for (Entry<String, JsonElement> entry : entrySet) {
393 String propName = entry.getKey();
395 JsonElement elementValue = entry.getValue();
397 PropertyDefinition propertyDefinition = allProperties.get(propName);
398 if (propertyDefinition == null) {
399 log.debug("The property {} was not found under data tpye {}", propName, dataTypeDefinition.getName());
402 String type = propertyDefinition.getType();
403 boolean isScalarType = ToscaPropertyType.isScalarType(type);
405 if (true == isScalarType) {
406 ToscaPropertyType propertyType = ToscaPropertyType.isValidType(type);
407 if (propertyType == null) {
408 log.debug("cannot find the {} under default tosca property types", type);
411 PropertyTypeValidator validator = propertyType.getValidator();
412 String innerType = null;
413 if (propertyType == ToscaPropertyType.LIST || propertyType == ToscaPropertyType.MAP) {
414 if (propertyDefinition.getSchema() != null
415 && propertyDefinition.getSchema().getProperty() != null) {
416 innerType = propertyDefinition.getSchema().getProperty().getType();
417 if (innerType == null) {
418 log.debug("Property type {} must have inner type in its decleration.", propertyType);
425 if (elementValue != null) {
426 if (elementValue.isJsonPrimitive() && elementValue.getAsString().isEmpty()) {
429 value = elementValue.toString();
433 boolean isValid = validator.isValid(value, innerType, allDataTypes);
434 if (false == isValid) {
435 log.debug("Failed to validate the value {} from type {}", value, propertyType);
441 DataTypeDefinition typeDefinition = allDataTypes.get(type);
442 if (typeDefinition == null) {
443 log.debug("The data type {} canot be found in the given data type list.", type);
447 boolean isValid = isValid(elementValue, typeDefinition, allDataTypes);
449 if (false == isValid) {
450 log.debug("Failed in validation of value {} from type {}", (elementValue != null ? elementValue.toString() : null), typeDefinition.getName());
460 log.debug("The value {} of type {} should be json object", (jsonElement != null ? jsonElement.toString() : null), dataTypeDefinition.getName());
469 // public ImmutablePair<String, Boolean>
470 // validateAndUpdateAndReturnString(String value, DataTypeDefinition
471 // dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
473 // ImmutablePair<JsonElement, Boolean> result = falseResult;
475 // if (value == null || value.isEmpty()) {
476 // return trueStringEmptyResult;
479 // JsonElement jsonElement = null;
481 // jsonElement = jsonParser.parse(value);
482 // } catch (JsonSyntaxException e) {
483 // return falseStringEmptyResult;
486 // result = validateAndUpdate(jsonElement, dataTypeDefinition,
489 // if (result.right.booleanValue() == false) {
490 // log.debug("The value {} of property from type {} is invalid", value, dataTypeDefinition.getName());
491 // return new ImmutablePair<String, Boolean>(value, false);
494 // String valueFromJsonElement = getValueFromJsonElement(result.left);
496 // return new ImmutablePair<String, Boolean>(valueFromJsonElement, true);