push addional code
[sdc.git] / openecomp-be / lib / openecomp-core-lib / openecomp-utilities-lib / src / main / java / org / openecomp / core / utilities / json / JsonSchemaDataGenerator.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.core.utilities.json;
22
23 import org.json.JSONException;
24 import org.json.JSONObject;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 import java.util.HashMap;
29 import java.util.Map;
30
31 /**
32  * The type Json schema data generator.
33  */
34 public class JsonSchemaDataGenerator {
35
36   private static final String ROOT = "root";
37   private static final Logger logger = LoggerFactory.getLogger(JsonSchemaDataGenerator.class);
38   /**
39    * The Include defaults.
40    */
41   boolean includeDefaults = true;
42   private JSONObject root;
43   private Map<String, Object> referencesData;
44
45   /**
46    * Instantiates a new Json schema data generator.
47    *
48    * @param jsonSchema the json schema
49    */
50   public JsonSchemaDataGenerator(String jsonSchema) {
51     if (jsonSchema == null) {
52       throw new IllegalArgumentException("Input string jsonSchema can not be null");
53     }
54     root = new JSONObject(jsonSchema);
55   }
56
57   /**
58    * Sets include defaults.
59    *
60    * @param includeDefaults the include defaults
61    */
62   public void setIncludeDefaults(boolean includeDefaults) {
63     this.includeDefaults = includeDefaults;
64   }
65
66   /**
67    * Generates json data that conform to the schema according to turned on flags.
68    *
69    * @return json that conform to the schema.
70    */
71   public String generateData() {
72     referencesData = new HashMap<>();
73     JSONObject data = new JSONObject();
74
75     generateData(ROOT, root,
76         data); // "root" is dummy name to represent the top level object (which, as apposed to
77     // inner objects, doesn't have a name in the schema)
78     return data.has(ROOT) ? data.get(ROOT).toString() : data.toString();
79   }
80
81   private void generateData(String propertyName, JSONObject property, JSONObject propertyData) {
82     if (property.has(JsonSchemaKeyword.TYPE)) {
83       String propertyType = property.getString(JsonSchemaKeyword.TYPE);
84       if (JsonSchemaKeyword.OBJECT.equals(propertyType)) {
85         generateObjectData(propertyName, property, propertyData);
86       } else {
87         generatePrimitiveData(propertyType, propertyName, property, propertyData);
88       }
89     } else if (property.has(JsonSchemaKeyword.REF)) {
90       generateReferenceData(propertyName, property.getString(JsonSchemaKeyword.REF), propertyData);
91     }
92   }
93
94   private void generateObjectData(String propertyName, JSONObject property,
95                                   JSONObject propertyData) {
96     JSONObject subProperties = property.getJSONObject(JsonSchemaKeyword.PROPERTIES);
97
98     JSONObject subPropertiesData = new JSONObject();
99     for (String subPropertyName : subProperties.keySet()) {
100       generateData(subPropertyName, subProperties.getJSONObject(subPropertyName),
101           subPropertiesData);
102     }
103
104     if (subPropertiesData.length() > 0) {
105       propertyData.put(propertyName, subPropertiesData);
106     }
107   }
108
109   private void generateReferenceData(String propertyName, String referencePath,
110                                      JSONObject propertyData) {
111     if (referencesData.containsKey(referencePath)) {
112       Object referenceData = referencesData.get(referencePath);
113       if (referenceData != null) {
114         propertyData.put(propertyName, referenceData);
115       }
116     } else {
117       generateData(propertyName, resolveReference(referencePath), propertyData);
118       referencesData.put(referencePath, propertyData.opt(propertyName));
119     }
120   }
121
122   private JSONObject resolveReference(String referencePath) {
123     String[] keys = referencePath.replaceFirst("#/", "").split("/");
124
125     JSONObject reference = root;
126     for (String key : keys) {
127       reference = reference.getJSONObject(key);
128     }
129     return reference;
130   }
131
132   private void generatePrimitiveData(String propertyType, String propertyName, JSONObject property,
133                                      JSONObject propertyData) {
134     if (includeDefaults) {
135       populateWithDefaultValue(propertyType, propertyName, property, propertyData);
136     }
137   }
138
139   private void populateWithDefaultValue(String propertyType, String propertyName,
140                                         JSONObject property, JSONObject propertyData) {
141     if (!property.has(JsonSchemaKeyword.DEFAULT)) {
142       return;
143     }
144     try {
145       switch (propertyType) {
146         case JsonSchemaKeyword.ARRAY:
147           propertyData.put(propertyName, property.getJSONArray(JsonSchemaKeyword.DEFAULT));
148           break;
149         case JsonSchemaKeyword.BOOLEAN:
150           propertyData.put(propertyName, property.getBoolean(JsonSchemaKeyword.DEFAULT));
151           break;
152         case JsonSchemaKeyword.INTEGER:
153           propertyData.put(propertyName, property.getInt(JsonSchemaKeyword.DEFAULT));
154           break;
155         case JsonSchemaKeyword.NUMBER:
156           propertyData.put(propertyName, property.getDouble(JsonSchemaKeyword.DEFAULT));
157           break;
158         case JsonSchemaKeyword.STRING:
159           propertyData.put(propertyName, property.getString(JsonSchemaKeyword.DEFAULT));
160           break;
161         default:
162           break;
163       }
164     } catch (JSONException e0) {
165       Object defaultValue = property.get(JsonSchemaKeyword.DEFAULT);
166       logger.error(String.format(
167           "Invalid schema: '%s' property type is '%s' but it has a default value which is not: %s.",
168           propertyName, propertyType, defaultValue), e0);
169       throw e0;
170     }
171   }
172
173   private static class JsonSchemaKeyword {
174     private static final String DEFAULT = "default";
175     private static final String TYPE = "type";
176     private static final String PROPERTIES = "properties";
177     private static final String ARRAY = "array";
178     private static final String BOOLEAN = "boolean";
179     private static final String INTEGER = "integer";
180     private static final String NUMBER = "number";
181     private static final String STRING = "string";
182     private static final String OBJECT = "object";
183     private static final String REF = "$ref";
184   }
185 }