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=========================================================
20 package org.openecomp.sdc.be.model.tosca.validators;
22 import com.google.gson.JsonElement;
23 import com.google.gson.JsonObject;
24 import com.google.gson.JsonParser;
25 import com.google.gson.JsonPrimitive;
26 import com.google.gson.JsonSyntaxException;
27 import java.util.HashMap;
28 import java.util.List;
30 import java.util.Map.Entry;
32 import lombok.AccessLevel;
33 import lombok.NoArgsConstructor;
34 import org.apache.commons.lang3.tuple.ImmutablePair;
35 import org.openecomp.sdc.be.model.DataTypeDefinition;
36 import org.openecomp.sdc.be.model.PropertyDefinition;
37 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
38 import org.openecomp.sdc.be.model.tosca.converters.PropertyValueConverter;
39 import org.openecomp.sdc.common.log.wrappers.Logger;
41 @NoArgsConstructor(access = AccessLevel.PRIVATE)
42 public class DataTypeValidatorConverter {
44 private static final Logger log = Logger.getLogger(DataTypeValidatorConverter.class.getName());
45 private static final DataTypeValidatorConverter dataTypeValidatorConverter = new DataTypeValidatorConverter();
46 private static final ImmutablePair<JsonElement, Boolean> falseResult = new ImmutablePair<>(null, false);
47 private static final ImmutablePair<JsonElement, Boolean> trueEmptyResult = new ImmutablePair<>(null, true);
49 public static DataTypeValidatorConverter getInstance() {
50 return dataTypeValidatorConverter;
53 private ToscaPropertyType isDataTypeDerviedFromScalarType(DataTypeDefinition dataTypeDef) {
54 ToscaPropertyType result = null;
55 DataTypeDefinition dataType = dataTypeDef;
56 while (dataType != null) {
57 String name = dataType.getName();
58 ToscaPropertyType typeIfScalar = ToscaPropertyType.getTypeIfScalar(name);
59 if (typeIfScalar != null) {
60 result = typeIfScalar;
63 dataType = dataType.getDerivedFrom();
68 private ImmutablePair<JsonElement, Boolean> validateAndUpdate(JsonElement jsonElement, DataTypeDefinition dataTypeDefinition,
69 Map<String, DataTypeDefinition> allDataTypes) {
70 Map<String, PropertyDefinition> allProperties = getAllProperties(dataTypeDefinition);
71 ToscaPropertyType toscaPropertyType = null;
72 if ((toscaPropertyType = isDataTypeDerviedFromScalarType(dataTypeDefinition)) != null) {
73 PropertyTypeValidator validator = toscaPropertyType.getValidator();
74 PropertyValueConverter converter = toscaPropertyType.getConverter();
75 if (jsonElement == null || jsonElement.isJsonNull()) {
76 boolean valid = validator.isValid(null, null, allDataTypes);
78 log.trace("Failed in validation of property {} from type {}", dataTypeDefinition.getName(), dataTypeDefinition.getName());
81 return new ImmutablePair<>(jsonElement, true);
83 if (jsonElement.isJsonPrimitive()) {
85 if (jsonElement != null) {
86 if (jsonElement.toString().isEmpty()) {
89 value = jsonElement.toString();
92 boolean valid = validator.isValid(value, null, null);
94 log.trace("Failed in validation of property {} from type {}. Json primitive value is {}", dataTypeDefinition.getName(),
95 dataTypeDefinition.getName(), value);
98 String convertedValue = converter.convert(value, null, allDataTypes);
99 JsonElement element = null;
101 element = JsonParser.parseString(convertedValue);
102 } catch (JsonSyntaxException e) {
103 log.debug("Failed to parse value {} of property {} {}", convertedValue, dataTypeDefinition.getName(), e);
106 return new ImmutablePair<>(element, true);
108 // MAP, LIST, OTHER types cannot be applied data type
110 // definition scalar type. We currently cannot derived from
112 // map/list. (cannot add the entry schema to it)
113 log.debug("We cannot derive from list/map. Thus, the value cannot be not primitive since the data type {} is scalar one",
114 dataTypeDefinition.getName());
119 if (jsonElement == null || jsonElement.isJsonNull()) {
120 return new ImmutablePair<>(jsonElement, true);
122 if (jsonElement.isJsonObject()) {
123 JsonObject buildJsonObject = new JsonObject();
124 JsonObject asJsonObject = jsonElement.getAsJsonObject();
125 Set<Entry<String, JsonElement>> entrySet = asJsonObject.entrySet();
126 for (Entry<String, JsonElement> entry : entrySet) {
127 String propName = entry.getKey();
128 JsonElement elementValue = entry.getValue();
129 PropertyDefinition propertyDefinition = allProperties.get(propName);
130 if (propertyDefinition == null) {
131 log.debug("The property {} was not found under data type {}", propName, dataTypeDefinition.getName());
134 String type = propertyDefinition.getType();
135 boolean isScalarType = ToscaPropertyType.isScalarType(type);
137 ToscaPropertyType propertyType = ToscaPropertyType.isValidType(type);
138 if (propertyType == null) {
139 log.debug("cannot find the {} under default tosca property types", type);
142 PropertyTypeValidator validator = propertyType.getValidator();
143 String innerType = null;
144 if (propertyType == ToscaPropertyType.LIST || propertyType == ToscaPropertyType.MAP) {
145 if (propertyDefinition.getSchema() != null && propertyDefinition.getSchema().getProperty() != null) {
146 innerType = propertyDefinition.getSchema().getProperty().getType();
147 if (innerType == null) {
148 log.debug("Property type {} must have inner type in its declaration.", propertyType);
154 if (elementValue != null) {
155 if (elementValue.isJsonPrimitive() && elementValue.getAsString().isEmpty()) {
158 value = elementValue.toString();
161 boolean isValid = validator.isValid(value, innerType, allDataTypes);
163 log.debug("Failed to validate the value {} from type {}", value, propertyType);
166 PropertyValueConverter converter = propertyType.getConverter();
167 String convertedValue = converter.convert(value, innerType, allDataTypes);
168 JsonElement element = null;
169 if (convertedValue != null) {
170 if (convertedValue.isEmpty()) {
171 element = new JsonPrimitive("");
174 element = JsonParser.parseString(convertedValue);
175 } catch (JsonSyntaxException e) {
176 log.debug("Failed to parse value {} of type {}", convertedValue, propertyType, e);
181 buildJsonObject.add(propName, element);
183 DataTypeDefinition typeDefinition = allDataTypes.get(type);
184 if (typeDefinition == null) {
185 log.debug("The data type {} cannot be found in the given data type list.", type);
188 ImmutablePair<JsonElement, Boolean> isValid = validateAndUpdate(elementValue, typeDefinition, allDataTypes);
189 if (!isValid.getRight().booleanValue()) {
190 log.debug("Failed in validation of value {} from type {}", (elementValue != null ? elementValue.toString() : null),
191 typeDefinition.getName());
194 buildJsonObject.add(propName, isValid.getLeft());
197 return new ImmutablePair<>(buildJsonObject, true);
199 log.debug("The value {} of type {} should be json object", (jsonElement != null ? jsonElement.toString() : null),
200 dataTypeDefinition.getName());
207 public ImmutablePair<JsonElement, Boolean> validateAndUpdate(String value, DataTypeDefinition dataTypeDefinition,
208 Map<String, DataTypeDefinition> allDataTypes) {
209 if (value == null || value.isEmpty()) {
210 return trueEmptyResult;
212 final JsonElement jsonElement;
214 jsonElement = JsonParser.parseString(value);
215 } catch (JsonSyntaxException e) {
218 return validateAndUpdate(jsonElement, dataTypeDefinition, allDataTypes);
221 private Map<String, PropertyDefinition> getAllProperties(DataTypeDefinition dataTypeDefinition) {
222 Map<String, PropertyDefinition> allParentsProps = new HashMap<>();
223 while (dataTypeDefinition != null) {
224 List<PropertyDefinition> currentParentsProps = dataTypeDefinition.getProperties();
225 if (currentParentsProps != null) {
226 currentParentsProps.stream().forEach(p -> allParentsProps.put(p.getName(), p));
228 dataTypeDefinition = dataTypeDefinition.getDerivedFrom();
230 return allParentsProps;
233 public boolean isValid(String value, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
234 if (value == null || value.isEmpty()) {
237 JsonElement jsonElement;
239 jsonElement = JsonParser.parseString(value);
240 } catch (JsonSyntaxException e) {
241 log.debug("Failed to parse the value {} from type {}", value, dataTypeDefinition, e);
244 return isValid(jsonElement, dataTypeDefinition, allDataTypes);
247 private boolean isValid(JsonElement jsonElement, DataTypeDefinition dataTypeDefinition, Map<String, DataTypeDefinition> allDataTypes) {
248 Map<String, PropertyDefinition> allProperties = getAllProperties(dataTypeDefinition);
249 ToscaPropertyType toscaPropertyType = null;
250 if ((toscaPropertyType = isDataTypeDerviedFromScalarType(dataTypeDefinition)) != null) {
251 PropertyTypeValidator validator = toscaPropertyType.getValidator();
252 if (jsonElement == null || jsonElement.isJsonNull()) {
253 boolean valid = validator.isValid(null, null, allDataTypes);
255 log.trace("Failed in validation of property {} from type {}", dataTypeDefinition.getName(), dataTypeDefinition.getName());
260 if (jsonElement.isJsonPrimitive()) {
262 if (jsonElement != null) {
263 if (jsonElement.toString().isEmpty()) {
266 value = jsonElement.toString();
269 boolean valid = validator.isValid(value, null, allDataTypes);
271 log.trace("Failed in validation of property {} from type {}. Json primitive value is {}", dataTypeDefinition.getName(),
272 dataTypeDefinition.getName(), value);
277 // MAP, LIST, OTHER types cannot be applied data type
279 // definition scalar type. We currently cannot derived from
281 // map/list. (cannot add the entry schema to it)
282 log.debug("We cannot derive from list/map. Thus, the value cannot be not primitive since the data type {} is scalar one",
283 dataTypeDefinition.getName());
288 if (jsonElement == null || jsonElement.isJsonNull()) {
291 if (jsonElement.isJsonObject()) {
292 JsonObject asJsonObject = jsonElement.getAsJsonObject();
293 Set<Entry<String, JsonElement>> entrySet = asJsonObject.entrySet();
294 for (Entry<String, JsonElement> entry : entrySet) {
295 String propName = entry.getKey();
296 JsonElement elementValue = entry.getValue();
297 PropertyDefinition propertyDefinition = allProperties.get(propName);
298 if (propertyDefinition == null) {
299 log.debug("The property {} was not found under data type {}", propName, dataTypeDefinition.getName());
302 String type = propertyDefinition.getType();
303 boolean isScalarType = ToscaPropertyType.isScalarType(type);
305 ToscaPropertyType propertyType = ToscaPropertyType.isValidType(type);
306 if (propertyType == null) {
307 log.debug("cannot find the {} under default tosca property types", type);
310 PropertyTypeValidator validator = propertyType.getValidator();
311 String innerType = null;
312 if (propertyType == ToscaPropertyType.LIST || propertyType == ToscaPropertyType.MAP) {
313 if (propertyDefinition.getSchema() != null && propertyDefinition.getSchema().getProperty() != null) {
314 innerType = propertyDefinition.getSchema().getProperty().getType();
315 if (innerType == null) {
316 log.debug("Property type {} must have inner type in its declaration.", propertyType);
322 if (elementValue != null) {
323 if (elementValue.isJsonPrimitive() && elementValue.getAsString().isEmpty()) {
326 value = elementValue.toString();
329 boolean isValid = validator.isValid(value, innerType, allDataTypes);
331 log.debug("Failed to validate the value {} from type {}", value, propertyType);
335 DataTypeDefinition typeDefinition = allDataTypes.get(type);
336 if (typeDefinition == null) {
337 log.debug("The data type {} cannot be found in the given data type list.", type);
340 boolean isValid = isValid(elementValue, typeDefinition, allDataTypes);
342 log.debug("Failed in validation of value {} from type {}", (elementValue != null ? elementValue.toString() : null),
343 typeDefinition.getName());
350 log.debug("The value {} of type {} should be json object", (jsonElement != null ? jsonElement.toString() : null),
351 dataTypeDefinition.getName());