2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020 AT&T Intellectual Property. All rights
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END============================================
20 * ===================================================================
24 package org.onap.clamp.clds.tosca.update.parser;
26 import com.google.gson.JsonArray;
27 import com.google.gson.JsonObject;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.LinkedHashMap;
31 import java.util.Map.Entry;
32 import org.onap.clamp.clds.tosca.update.elements.ToscaElement;
33 import org.onap.clamp.clds.tosca.update.elements.ToscaElementProperty;
34 import org.onap.clamp.clds.tosca.update.parser.metadata.ToscaMetadataParser;
35 import org.onap.clamp.clds.tosca.update.templates.JsonTemplate;
37 public class ToscaConverterToJsonSchema {
38 private LinkedHashMap<String, ToscaElement> components;
39 private LinkedHashMap<String, JsonTemplate> templates;
41 private ToscaMetadataParser metadataParser;
46 * @param toscaElementsMap All the tosca elements found (policy type + data types + native tosca datatypes)
47 * @param jsonSchemaTemplates All Json schema templates to use
48 * @param metadataParser The metadata parser to use for metadata section
50 public ToscaConverterToJsonSchema(LinkedHashMap<String, ToscaElement> toscaElementsMap,
51 LinkedHashMap<String, JsonTemplate> jsonSchemaTemplates,
52 ToscaMetadataParser metadataParser) {
53 this.components = toscaElementsMap;
54 this.templates = jsonSchemaTemplates;
55 this.metadataParser = metadataParser;
59 * For a given component, launch process to parse it in Json.
61 * @param toscaElementKey name components
64 public JsonObject getJsonSchemaOfToscaElement(String toscaElementKey) {
65 return this.getFieldAsObject(getToscaElement(toscaElementKey));
69 * Return the classical/general fields of the component, & launch the properties deployment.
71 * @param toscaElement the compo
72 * @return a json object
74 public JsonObject getFieldAsObject(ToscaElement toscaElement) {
76 JsonObject globalFields = new JsonObject();
77 if (templates.get("object").hasFields("title")) {
78 globalFields.addProperty("title", toscaElement.getName());
80 if (templates.get("object").hasFields("type")) {
81 globalFields.addProperty("type", "object");
83 if (templates.get("object").hasFields("description")) {
84 if (toscaElement.getDescription() != null) {
85 globalFields.addProperty("description", toscaElement.getDescription());
88 if (templates.get("object").hasFields("required")) {
89 globalFields.add("required", this.getRequirements(toscaElement.getName()));
91 if (templates.get("object").hasFields("properties")) {
92 globalFields.add("properties", this.deploy(toscaElement.getName()));
98 * Get the required properties of the Component, including the parents properties requirements.
100 * @param nameComponent name component
101 * @return a json array
103 public JsonArray getRequirements(String nameComponent) {
104 JsonArray requirements = new JsonArray();
105 ToscaElement toParse = components.get(nameComponent);
106 //Check for a father component, and launch the same process
107 if (!toParse.getDerivedFrom().equals("tosca.datatypes.Root")
108 && !toParse.getDerivedFrom().equals("tosca.policies.Root")) {
109 requirements.addAll(getRequirements(toParse.getDerivedFrom()));
111 //Each property is checked, and add to the requirement array if it's required
112 Collection<ToscaElementProperty> properties = toParse.getProperties().values();
113 for (ToscaElementProperty toscaElementProperty : properties) {
114 if (toscaElementProperty.getItems().containsKey("required")
115 && toscaElementProperty.getItems().get("required").equals(true)) {
116 requirements.add(toscaElementProperty.getName());
123 * The beginning of the recursive process. Get the parents (or not) to launch the same process, and otherwise
124 * deploy and parse the properties.
126 * @param nameComponent name component
127 * @return a json object
129 public JsonObject deploy(String nameComponent) {
130 JsonObject jsonSchema = new JsonObject();
131 ToscaElement toParse = components.get(nameComponent);
132 //Check for a father component, and launch the same process
133 if (!toParse.getDerivedFrom().equals("tosca.datatypes.Root")
134 && !toParse.getDerivedFrom().equals("tosca.policies.Root")) {
135 jsonSchema = this.getParent(toParse.getDerivedFrom());
137 //For each component property, check if its a complex properties (a component) or not. In that case,
138 //launch the analyse of the property.
139 for (Entry<String, ToscaElementProperty> property : toParse.getProperties().entrySet()) {
140 if (getToscaElement((String) property.getValue().getItems().get("type")) != null) {
141 jsonSchema.add(property.getValue().getName(),
142 this.getJsonSchemaOfToscaElement((String) property.getValue().getItems().get("type")));
145 jsonSchema.add(property.getValue().getName(), this.complexParse(property.getValue()));
152 * If a component has a parent, it is deploy in the same way.
154 * @param nameComponent name component
155 * @return a json object
157 public JsonObject getParent(String nameComponent) {
158 return deploy(nameComponent);
164 * @param toscaElementProperty property
165 * @return a json object
167 @SuppressWarnings("unchecked")
168 public JsonObject complexParse(ToscaElementProperty toscaElementProperty) {
169 JsonObject propertiesInJson = new JsonObject();
170 JsonTemplate currentPropertyJsonTemplate;
171 String typeProperty = (String) toscaElementProperty.getItems().get("type");
172 if (typeProperty.toLowerCase().equals("list") || typeProperty.toLowerCase().equals("map")) {
173 currentPropertyJsonTemplate = templates.get("object");
176 String propertyType = (String) toscaElementProperty.getItems().get("type");
177 currentPropertyJsonTemplate = templates.get(propertyType.toLowerCase());
179 //Each "special" field is analysed, and has a specific treatment
180 for (String propertyField : toscaElementProperty.getItems().keySet()) {
181 switch (propertyField) {
183 if (currentPropertyJsonTemplate.hasFields(propertyField)) {
184 String fieldtype = (String) toscaElementProperty.getItems().get(propertyField);
185 switch (fieldtype.toLowerCase()) {
187 propertiesInJson.addProperty("type", "array");
190 propertiesInJson.addProperty("type", "object");
192 case "scalar-unit.time":
193 case "scalar-unit.frequency":
194 case "scalar-unit.size":
195 propertiesInJson.addProperty("type", "string");
198 propertiesInJson.addProperty("type", "string");
199 propertiesInJson.addProperty("format", "date-time");
202 propertiesInJson.addProperty("type", "number");
205 propertiesInJson.addProperty("type", "integer");
206 if (!checkConstraintPresence(toscaElementProperty, "greater_than")
207 && currentPropertyJsonTemplate.hasFields("exclusiveMinimum")) {
208 propertiesInJson.addProperty("exclusiveMinimum", false);
210 if (!checkConstraintPresence(toscaElementProperty, "less_than")
211 && currentPropertyJsonTemplate.hasFields("exclusiveMaximum")) {
212 propertiesInJson.addProperty("exclusiveMaximum", false);
216 propertiesInJson.addProperty("type", currentPropertyJsonTemplate.getName());
222 if (metadataParser != null) {
223 metadataParser.processAllMetadataElement(toscaElementProperty).entrySet()
224 .forEach((jsonEntry) -> {
225 propertiesInJson.add(jsonEntry.getKey(),
226 jsonEntry.getValue());
232 toscaElementProperty.addConstraintsAsJson(propertiesInJson,
233 (ArrayList<Object>) toscaElementProperty.getItems().get("constraints"),
234 currentPropertyJsonTemplate);
237 //Here, a way to check if entry is a component (datatype) or a simple string
238 if (getToscaElement(this.extractSpecificFieldFromMap(toscaElementProperty, "entry_schema"))
240 String nameComponent = this.extractSpecificFieldFromMap(toscaElementProperty, "entry_schema");
241 ToscaConverterToJsonSchema
242 child = new ToscaConverterToJsonSchema(components, templates,
244 JsonObject propertiesContainer = new JsonObject();
246 switch ((String) toscaElementProperty.getItems().get("type")) {
247 case "map": // Get it as an object
248 JsonObject componentAsProperty = child.getJsonSchemaOfToscaElement(nameComponent);
249 propertiesContainer.add(nameComponent, componentAsProperty);
250 if (currentPropertyJsonTemplate.hasFields("properties")) {
251 propertiesInJson.add("properties", propertiesContainer);
254 default://list : get it as an Array
255 JsonObject componentAsItem = child.getJsonSchemaOfToscaElement(nameComponent);
256 if (currentPropertyJsonTemplate.hasFields("properties")) {
257 propertiesInJson.add("items", componentAsItem);
264 else if (toscaElementProperty.getItems().get("type").equals("list")) {
265 JsonObject itemContainer = new JsonObject();
266 String valueInEntrySchema =
267 this.extractSpecificFieldFromMap(toscaElementProperty, "entry_schema");
268 itemContainer.addProperty("type", valueInEntrySchema);
269 propertiesInJson.add("items", itemContainer);
271 // MAP Case, for now nothing
275 //Each classical field : type, description, default..
276 if (currentPropertyJsonTemplate.hasFields(propertyField) && !propertyField.equals("required")) {
277 toscaElementProperty.addFieldToJson(propertiesInJson, propertyField,
278 toscaElementProperty.getItems().get(propertyField));
283 return propertiesInJson;
287 * Look for a matching Component for the name parameter, in the components list.
289 * @param name the tosca element name to search for
290 * @return a tosca element
292 public ToscaElement getToscaElement(String name) {
293 ToscaElement correspondingToscaElement = null;
294 if (components == null) {
297 for (ToscaElement toscaElement : components.values()) {
298 if (toscaElement.getName().equals(name)) {
299 correspondingToscaElement = toscaElement;
302 return correspondingToscaElement;
306 * Simple method to extract quickly a type field from particular property item.
308 * @param toscaElementProperty the property
309 * @param fieldName the fieldname
312 @SuppressWarnings("unchecked")
313 public String extractSpecificFieldFromMap(ToscaElementProperty toscaElementProperty, String fieldName) {
314 LinkedHashMap<String, String> entrySchemaFields =
315 (LinkedHashMap<String, String>) toscaElementProperty.getItems().get(fieldName);
316 return entrySchemaFields.get("type");
320 * Check if a constraint, for a specific property, is there.
322 * @param toscaElementProperty property
323 * @param nameConstraint name constraint
324 * @return a flag boolean
326 public boolean checkConstraintPresence(ToscaElementProperty toscaElementProperty, String nameConstraint) {
327 boolean presentConstraint = false;
328 if (toscaElementProperty.getItems().containsKey("constraints")) {
329 ArrayList<Object> constraints = (ArrayList) toscaElementProperty.getItems().get("constraints");
330 for (Object constraint : constraints) {
331 if (constraint instanceof LinkedHashMap) {
332 if (((LinkedHashMap) constraint).containsKey(nameConstraint)) {
333 presentConstraint = true;
338 return presentConstraint;