b83ad2782def954237a6022c4a3c3822bd09ecd1
[sdc.git] /
1 /*
2  * Copyright © 2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.core.utilities.json;
18
19 import com.google.gson.Gson;
20 import com.google.gson.GsonBuilder;
21 import com.google.gson.JsonIOException;
22 import com.google.gson.JsonParser;
23 import com.google.gson.JsonSyntaxException;
24
25 import java.io.BufferedReader;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.InputStreamReader;
29 import java.io.Reader;
30 import java.io.StringReader;
31 import java.util.Collections;
32 import java.util.List;
33 import java.util.Set;
34 import java.util.stream.Collectors;
35
36 import org.apache.commons.collections4.CollectionUtils;
37 import org.everit.json.schema.EnumSchema;
38 import org.everit.json.schema.Schema;
39 import org.everit.json.schema.StringSchema;
40 import org.everit.json.schema.ValidationException;
41 import org.everit.json.schema.loader.SchemaLoader;
42 import org.json.JSONObject;
43 import org.onap.sdc.tosca.datatypes.model.RequirementDefinition;
44 import org.openecomp.core.utilities.CommonMethods;
45 import org.openecomp.core.utilities.deserializers.RequirementDefinitionDeserializer;
46 import org.openecomp.sdc.logging.api.Logger;
47 import org.openecomp.sdc.logging.api.LoggerFactory;
48
49
50 /**
51  * The type Json util.
52  */
53 public class JsonUtil {
54
55     private static final Logger LOGGER = LoggerFactory.getLogger(JsonUtil.class);
56     private static final GsonBuilder gsonBuilder;
57     private static final Gson gson;
58
59     static {
60         gsonBuilder = new GsonBuilder();
61         gsonBuilder.registerTypeAdapter(RequirementDefinition.class, new
62                 RequirementDefinitionDeserializer());
63         gson = gsonBuilder.create();
64     }
65
66     private JsonUtil() {
67     }
68
69     /**
70      * Object 2 json string.
71      *
72      * @param obj the obj
73      * @return the string
74      */
75     public static String object2Json(Object obj) {
76         return sbObject2Json(obj).toString();
77
78     }
79
80     /**
81      * Sb object 2 json string builder.
82      *
83      * @param obj the obj
84      * @return the string builder
85      */
86     public static StringBuilder sbObject2Json(Object obj) {
87         return new StringBuilder(new GsonBuilder().setPrettyPrinting().create().toJson(obj));
88     }
89
90     /**
91      * Json 2 object t.
92      *
93      * @param <T>      the type parameter
94      * @param json     the json
95      * @param classOfT the class of t
96      * @return the t
97      */
98     public static <T> T json2Object(String json, Class<T> classOfT) {
99         T typ;
100         try {
101             try (Reader br = new StringReader(json)) {
102                 typ = gson.fromJson(br, classOfT);
103             }
104         } catch (JsonIOException | JsonSyntaxException | IOException exception) {
105             throw new RuntimeException(exception);
106         }
107         return typ;
108     }
109
110     /**
111      * Json 2 object t.
112      *
113      * @param <T>      the type parameter
114      * @param is       the is
115      * @param classOfT the class of t
116      * @return the t
117      */
118     public static <T> T json2Object(InputStream is, Class<T> classOfT) {
119         T type;
120         try (Reader br = new BufferedReader(new InputStreamReader(is))) {
121             type = new Gson().fromJson(br, classOfT);
122         } catch (JsonIOException | JsonSyntaxException | IOException exception) {
123             throw new RuntimeException(exception);
124         }
125         return type;
126     }
127
128
129     /**
130      * Is valid json boolean.
131      *
132      * @param json the json
133      * @return the boolean
134      */
135     //todo check https://github.com/stleary/JSON-java as replacement for this code
136     public static boolean isValidJson(String json) {
137         try {
138             return new JsonParser().parse(json).isJsonObject();
139         } catch (JsonSyntaxException jse) {
140             LOGGER.error("Invalid json, Failed to parse json", jse);
141             return false;
142         }
143     }
144
145     /**
146      * Validate list.
147      *
148      * @param json       the json
149      * @param jsonSchema the json schema
150      * @return the list
151      */
152     public static List<String> validate(String json, String jsonSchema) {
153         List<ValidationException> validationErrors = validateUsingEverit(json, jsonSchema);
154         return validationErrors == null ? null
155                 : validationErrors.stream().map(JsonUtil::mapValidationExceptionToMessage)
156                         .collect(Collectors.toList());
157     }
158
159     private static String mapValidationExceptionToMessage(ValidationException exception) {
160         Object schema = exception.getViolatedSchema();
161
162         if (schema instanceof EnumSchema) {
163             return mapEnumViolationToMessage(exception);
164         } else if (schema instanceof StringSchema) {
165             return mapStringViolationToMessage(exception);
166         }
167
168         return exception.getMessage();
169     }
170
171     private static String mapEnumViolationToMessage(ValidationException exception) {
172         Set<Object> possibleValues = ((EnumSchema) exception.getViolatedSchema()).getPossibleValues();
173         return exception.getMessage().replaceFirst("enum value", possibleValues.size() == 1
174                 ? String.format("value. %s is the only possible value for this field",
175                 possibleValues.iterator().next())
176                 : String.format("value. Possible values: %s", CommonMethods
177                         .collectionToCommaSeparatedString(
178                                 possibleValues.stream().map(Object::toString).collect(Collectors.toList()))));
179     }
180
181     private static String mapStringViolationToMessage(ValidationException validationException) {
182         if (ValidationType.PATTERN.getKeyword().equals(validationException.getKeyword())) {
183             String message = validationException.getMessage();
184             String value = message.substring(message.indexOf("["), message.indexOf("]") + 1);
185             return message.replace("string " + value, value + " is not valid value. It");
186         }
187         return validationException.getMessage();
188     }
189
190     private static List<ValidationException> validateUsingEverit(String json, String jsonSchema) {
191         LOGGER.debug(
192                 String.format("validateUsingEverit start, json=%s, jsonSchema=%s", json, jsonSchema));
193         if (json == null || jsonSchema == null) {
194             throw new IllegalArgumentException("Input strings json and jsonSchema can not be null");
195         }
196
197         Schema schemaObj = SchemaLoader.load(new JSONObject(jsonSchema));
198         try {
199             schemaObj.validate(new JSONObject(json));
200         } catch (ValidationException ve) {
201             return CollectionUtils.isEmpty(ve.getCausingExceptions()) ? Collections.singletonList(ve)
202                     : ve.getCausingExceptions();
203         }
204         return null;
205     }
206
207     private enum ValidationType {
208         PATTERN("pattern");
209
210         private String keyword;
211
212         ValidationType(String keyword) {
213             this.keyword = keyword;
214         }
215
216         String getKeyword() {
217             return keyword;
218         }
219     }
220 }