re base code
[sdc.git] / catalog-model / src / main / java / org / openecomp / sdc / be / model / tosca / validators / MapValidator.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.JsonElement;
24 import com.google.gson.JsonObject;
25 import com.google.gson.JsonParser;
26 import com.google.gson.JsonSyntaxException;
27 import org.apache.commons.lang.StringUtils;
28 import org.openecomp.sdc.be.config.BeEcompErrorManager;
29 import org.openecomp.sdc.be.model.DataTypeDefinition;
30 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
31 import org.openecomp.sdc.common.log.wrappers.Logger;
32 import org.openecomp.sdc.common.util.JsonUtils;
33
34 import java.util.Map;
35 import java.util.Map.Entry;
36 import java.util.Set;
37
38 /*
39  * Property Type Map correct usage:
40  * null key null value = Yaml reader error
41 valid key null value = key & value deleted
42 duplicated keys = last key is taken
43 mismatch between inner type and values type = returned mismatch in data type
44 validators and converters works the same as before
45
46 Types:
47 when written line by line :
48                     key1 : val1
49                     key2 : val2
50 key1 and val does not need "    " , even if val1 is a string.
51 when written as one line : {"key1":val1 , "key2":val2}
52 Keys always need " " around them.
53 */
54 public class MapValidator implements PropertyTypeValidator {
55
56     private static MapValidator mapValidator = new MapValidator();
57
58     private static final Logger log = Logger.getLogger(MapValidator.class.getName());
59
60     private static DataTypeValidatorConverter dataTypeValidatorConverter = DataTypeValidatorConverter.getInstance();
61
62     private static JsonParser jsonParser = new JsonParser();
63
64     public static MapValidator getInstance() {
65         return mapValidator;
66     }
67
68     @Override
69     public boolean isValid(String value, String innerType, Map<String, DataTypeDefinition> allDataTypes) {
70
71         if (StringUtils.isEmpty(value)) {
72             return true;
73         }
74         if (innerType == null) {
75             return false;
76         }
77
78         PropertyTypeValidator innerValidator;
79         PropertyTypeValidator keyValidator = ToscaPropertyType.KEY.getValidator();
80         ToscaPropertyType innerToscaType = ToscaPropertyType.isValidType(innerType);
81
82         if (innerToscaType != null) {
83             switch (innerToscaType) {
84             case STRING:
85                 innerValidator = ToscaPropertyType.STRING.getValidator();
86                 break;
87             case INTEGER:
88                 innerValidator = ToscaPropertyType.INTEGER.getValidator();
89                 break;
90             case FLOAT:
91                 innerValidator = ToscaPropertyType.FLOAT.getValidator();
92                 break;
93             case BOOLEAN:
94                 innerValidator = ToscaPropertyType.BOOLEAN.getValidator();
95                 break;
96             case JSON:
97                 innerValidator = ToscaPropertyType.JSON.getValidator();
98                 break;
99             default:
100                 log.debug("inner Tosca Type is unknown. {}", innerToscaType);
101                 return false;
102             }
103
104         } else {
105             log.debug("inner Tosca Type is: {}", innerType);
106
107             boolean isValid = validateComplexInnerType(value, innerType, allDataTypes);
108             log.debug("Finish to validate value {} of map with inner type {}. result is {}",value,innerType,isValid);
109             return isValid;
110
111         }
112
113         try {
114             JsonElement jsonObject = jsonParser.parse(value);
115             if (!jsonObject.isJsonObject()) {
116                 return false;
117             }
118             JsonObject valueAsJson = jsonObject.getAsJsonObject();
119             return validateJsonObject(allDataTypes, innerValidator, keyValidator, valueAsJson);
120         } catch (JsonSyntaxException e) {
121             log.debug("Failed to parse json : {}", value, e);
122             BeEcompErrorManager.getInstance().logBeInvalidJsonInput("Map Validator");
123         }
124
125         return false;
126
127     }
128
129     private boolean validateJsonObject(Map<String, DataTypeDefinition> allDataTypes, PropertyTypeValidator innerValidator, PropertyTypeValidator keyValidator, JsonObject asJsonObject) {
130         Set<Entry<String, JsonElement>> entrySet = asJsonObject.entrySet();
131         for (Entry<String, JsonElement> entry : entrySet) {
132             String currentKey = entry.getKey();
133             JsonElement jsonValue = entry.getValue();
134
135             String element = JsonUtils.toString(jsonValue);
136
137             if (!innerValidator.isValid(element, null, allDataTypes)
138                     || !keyValidator.isValid(entry.getKey(), null, allDataTypes)) {
139                 log.debug("validation of key : {}, element : {} failed", currentKey, entry.getValue());
140                 return false;
141             }
142         }
143
144         return true;
145     }
146
147     private boolean validateComplexInnerType(String value, String innerType,
148             Map<String, DataTypeDefinition> allDataTypes) {
149
150         DataTypeDefinition innerDataTypeDefinition = allDataTypes.get(innerType);
151         if (innerDataTypeDefinition == null) {
152             log.debug("Data type {} cannot be found in our data types.", innerType);
153             return false;
154         }
155
156         try {
157             JsonElement jsonObject = jsonParser.parse(value);
158             JsonObject asJsonObject = jsonObject.getAsJsonObject();
159             Set<Entry<String, JsonElement>> entrySet = asJsonObject.entrySet();
160             for (Entry<String, JsonElement> entry : entrySet) {
161                 String currentKey = entry.getKey();
162                 JsonElement currentValue = entry.getValue();
163
164                 if (currentValue != null) {
165                     String element = JsonUtils.toString(currentValue);
166                     boolean isValid = dataTypeValidatorConverter.isValid(element, innerDataTypeDefinition,
167                             allDataTypes);
168                     if (!isValid) {
169                         log.debug("Cannot parse value {} from type {} of key {}",currentValue,innerType,currentKey);
170                         return false;
171                     }
172                 }
173             }
174
175         } catch (Exception e) {
176             log.debug("Cannot parse value {} of map from inner type {}", value, innerType, e);
177             return false;
178         }
179
180         return true;
181     }
182
183     @Override
184     public boolean isValid(String value, String innerType) {
185         return isValid(value, innerType, null);
186     }
187 }