Tosca convertor updated with datetime picker plugin feature
[clamp.git] / src / main / java / org / onap / clamp / clds / tosca / ToscaYamlToJsonConvertor.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP CLAMP
4  * ================================================================================
5  * Copyright (C) 2018 AT&T Intellectual Property. All rights
6  *                             reserved.
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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  * ===================================================================
21  *
22  */
23
24 package org.onap.clamp.clds.tosca;
25
26 import com.google.gson.Gson;
27 import com.google.gson.JsonElement;
28 import com.google.gson.JsonObject;
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.Iterator;
32 import java.util.LinkedHashMap;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Map.Entry;
36 import java.util.Optional;
37 import java.util.stream.Collectors;
38 import org.json.JSONArray;
39 import org.json.JSONObject;
40 import org.onap.clamp.clds.config.ClampProperties;
41 import org.onap.clamp.tosca.Dictionary;
42 import org.onap.clamp.tosca.DictionaryElement;
43 import org.onap.clamp.tosca.DictionaryService;
44 import org.springframework.beans.factory.annotation.Autowired;
45 import org.springframework.stereotype.Component;
46 import org.yaml.snakeyaml.Yaml;
47
48 /**
49  * Tosca Model Yaml parser and convertor to JSON Schema consumable for JSON
50  * Editor.
51  *
52  */
53 @Component
54 public class ToscaYamlToJsonConvertor {
55
56     @Autowired
57     private DictionaryService dictionaryService;
58
59     @Autowired
60     private ClampProperties refProp;
61
62     private int simpleTypeOrder = 1000;
63     private int complexTypeOrder = 10000;
64     private int complexSimpleTypeOrder = 1;
65
66     private int incrementSimpleTypeOrder() {
67         return simpleTypeOrder++;
68     }
69
70     private int incrementComplexTypeOrder() {
71         return complexTypeOrder = complexTypeOrder + 10000;
72     }
73
74     private int incrementComplexSimpleTypeOrder() {
75         complexSimpleTypeOrder++;
76         return complexTypeOrder + complexSimpleTypeOrder;
77     }
78
79     /**
80      * Parses Tosca YAML string and Converts to JsonObject.
81      *
82      * @param yamlString YAML string
83      * @return JsonObject
84      */
85     public JsonObject validateAndConvertToJson(String yamlString) {
86
87         Yaml yaml = new Yaml();
88         LinkedHashMap<String, Object> loadedYaml = yaml.load(yamlString);
89         if (loadedYaml == null) {
90             return null;
91         }
92
93         JSONObject jsonObject = new JSONObject(loadedYaml);
94         return new Gson().fromJson(jsonObject.toString(), JsonObject.class);
95     }
96
97     /**
98      * return the values by looking up the key in the Toscsa JSON object.
99      *
100      * @param obj Tosca Json Object
101      * @param key the parameter key to look up
102      * @return the value for the provided key
103      */
104     public String getValueFromMetadata(JsonObject obj, String key) {
105         JsonElement jsonElement = obj.get(ToscaSchemaConstants.NODE_TYPES);
106         if (jsonElement.isJsonObject()) {
107             Iterator<Entry<String, JsonElement>> itr =
108                 jsonElement.getAsJsonObject().entrySet().iterator();
109             while (itr.hasNext()) {
110                 Entry<String, JsonElement> entry = itr.next();
111                 if (entry.getValue() != null && entry.getValue().isJsonObject()
112                     && entry.getValue().getAsJsonObject().has(ToscaSchemaConstants.METADATA)) {
113                     JsonObject metadatas = entry.getValue().getAsJsonObject()
114                         .get(ToscaSchemaConstants.METADATA).getAsJsonObject();
115                     if (metadatas.has(key)) {
116                         return metadatas.get(key).getAsString();
117                     }
118                 }
119             }
120         }
121         return null;
122     }
123
124     /**
125      * Parses Tosca YAML string.
126      *
127      * @param yamlString YAML string
128      * @param modelTypeToUse The model type that must be used to obtain the Json
129      *        Schema
130      * @return JSON string
131      */
132     public String parseToscaYaml(String yamlString, String modelTypeToUse) {
133
134         Yaml yaml = new Yaml();
135         LinkedHashMap<String, Object> loadedYaml = yaml.load(yamlString);
136         if (loadedYaml == null) {
137             return "";
138         }
139         LinkedHashMap<String, Object> nodeTypes = new LinkedHashMap<>();
140         LinkedHashMap<String, Object> dataNodes = new LinkedHashMap<>();
141         JSONObject jsonParentObject = new JSONObject();
142         JSONObject jsonTempObject = new JSONObject();
143         parseNodeAndDataType(loadedYaml, nodeTypes, dataNodes);
144         populateJsonEditorObject(loadedYaml, nodeTypes, dataNodes, jsonParentObject, jsonTempObject,
145             modelTypeToUse);
146
147         String headerTemplate = getValueFromMetadata(validateAndConvertToJson(yamlString),
148             ToscaSchemaConstants.METADATA_HEADER_TEMPLATE);
149         if (headerTemplate != null) {
150             jsonParentObject.put(JsonEditorSchemaConstants.HEADER_TEMPLATE,
151                 JsonEditorSchemaConstants.HEADER_TEMPLATE_VALUE);
152         }
153         if (jsonTempObject.length() > 0) {
154             jsonParentObject = jsonTempObject;
155         }
156         JSONObject jsonEditorObject = new JSONObject();
157         jsonEditorObject.put(JsonEditorSchemaConstants.SCHEMA, jsonParentObject);
158         return jsonEditorObject.toString();
159     }
160
161     // Parse node_type and data_type
162     @SuppressWarnings("unchecked")
163     private void parseNodeAndDataType(LinkedHashMap<String, Object> map,
164         LinkedHashMap<String, Object> nodeTypes, LinkedHashMap<String, Object> dataNodes) {
165         map.entrySet().stream().forEach(n -> {
166             if (n.getKey().contains(ToscaSchemaConstants.NODE_TYPES)
167                 && n.getValue() instanceof Map) {
168                 parseNodeAndDataType((LinkedHashMap<String, Object>) n.getValue(), nodeTypes,
169                     dataNodes);
170             } else if (n.getKey().contains(ToscaSchemaConstants.DATA_TYPES)
171                 && n.getValue() instanceof Map) {
172                 parseNodeAndDataType((LinkedHashMap<String, Object>) n.getValue(), nodeTypes,
173                     dataNodes);
174             } else if (n.getKey().contains(ToscaSchemaConstants.POLICY_NODE)) {
175                 nodeTypes.put(n.getKey(), n.getValue());
176             } else if (n.getKey().contains(ToscaSchemaConstants.POLICY_DATA)) {
177                 dataNodes.put(n.getKey(), n.getValue());
178             }
179         });
180     }
181
182     @SuppressWarnings("unchecked")
183     private void populateJsonEditorObject(LinkedHashMap<String, Object> map,
184         LinkedHashMap<String, Object> nodeTypes, LinkedHashMap<String, Object> dataNodes,
185         JSONObject jsonParentObject, JSONObject jsonTempObject, String modelTypeToUse) {
186
187         Map<String, JSONObject> jsonEntrySchema = new HashMap<>();
188         jsonParentObject.put(JsonEditorSchemaConstants.TYPE, JsonEditorSchemaConstants.TYPE_OBJECT);
189         if (nodeTypes.get(modelTypeToUse) instanceof Map) {
190             ((LinkedHashMap<String, Object>) nodeTypes.get(modelTypeToUse)).entrySet()
191                 .forEach(ntElement -> {
192                     if (ntElement.getKey().equalsIgnoreCase(ToscaSchemaConstants.PROPERTIES)) {
193                         JSONArray rootNodeArray = new JSONArray();
194                         if (ntElement.getValue() instanceof Map) {
195                             ((LinkedHashMap<String, Object>) ntElement.getValue()).entrySet()
196                                 .forEach((ntPropertiesElement) -> {
197                                     boolean isListNode = false;
198                                     parseDescription(
199                                         (LinkedHashMap<String, Object>) ntPropertiesElement
200                                             .getValue(),
201                                         jsonParentObject);
202                                     LinkedHashMap<String, Object> parentPropertiesMap =
203                                         (LinkedHashMap<String, Object>) ntPropertiesElement
204                                             .getValue();
205                                     if (parentPropertiesMap.containsKey(ToscaSchemaConstants.TYPE)
206                                         && ((String) parentPropertiesMap
207                                             .get(ToscaSchemaConstants.TYPE))
208                                                 .contains(ToscaSchemaConstants.TYPE_MAP)
209                                         && parentPropertiesMap
210                                             .containsKey(ToscaSchemaConstants.ENTRY_SCHEMA)) {
211                                         parentPropertiesMap =
212                                             (LinkedHashMap<String, Object>) parentPropertiesMap
213                                                 .get(ToscaSchemaConstants.ENTRY_SCHEMA);
214                                         isListNode = true;
215                                     }
216                                     if (parentPropertiesMap.containsKey(ToscaSchemaConstants.TYPE)
217                                         && ((String) parentPropertiesMap
218                                             .get(ToscaSchemaConstants.TYPE))
219                                                 .contains(ToscaSchemaConstants.POLICY_DATA)) {
220                                         ((LinkedHashMap<String, Object>) dataNodes.get(
221                                             parentPropertiesMap.get(ToscaSchemaConstants.TYPE)))
222                                                 .entrySet().stream().forEach(pmap -> {
223                                                     if (pmap.getKey().equalsIgnoreCase(
224                                                         ToscaSchemaConstants.PROPERTIES)) {
225                                                         parseToscaProperties(
226                                                             ToscaSchemaConstants.POLICY_NODE,
227                                                             (LinkedHashMap<String, Object>) pmap
228                                                                 .getValue(),
229                                                             jsonParentObject, rootNodeArray,
230                                                             jsonEntrySchema, dataNodes,
231                                                             incrementSimpleTypeOrder());
232                                                     }
233                                                 });
234                                     }
235                                     if (isListNode) {
236                                         jsonTempObject.put(JsonEditorSchemaConstants.TYPE,
237                                             JsonEditorSchemaConstants.TYPE_ARRAY);
238                                         parseDescription(
239                                             (LinkedHashMap<String, Object>) ntPropertiesElement
240                                                 .getValue(),
241                                             jsonTempObject);
242                                         jsonTempObject.put(JsonEditorSchemaConstants.ITEMS,
243                                             jsonParentObject);
244                                         jsonTempObject.put(JsonEditorSchemaConstants.FORMAT,
245                                             JsonEditorSchemaConstants.CUSTOM_KEY_FORMAT_TABS);
246                                         jsonTempObject.put(JsonEditorSchemaConstants.UNIQUE_ITEMS,
247                                             JsonEditorSchemaConstants.TRUE);
248                                     }
249                                 });
250                         }
251                     }
252                 });
253         }
254     }
255
256     @SuppressWarnings("unchecked")
257     private void parseToscaProperties(String parentKey, LinkedHashMap<String, Object> propertiesMap,
258         JSONObject jsonDataNode, JSONArray array, Map<String, JSONObject> jsonEntrySchema,
259         LinkedHashMap<String, Object> dataNodes, final int order) {
260         JSONObject jsonPropertyNode = new JSONObject();
261         propertiesMap.entrySet().stream().forEach(p -> {
262             // Populate JSON Array for "required" key
263
264             if (p.getValue() instanceof Map) {
265                 LinkedHashMap<String, Object> nodeMap =
266                     (LinkedHashMap<String, Object>) p.getValue();
267                 if (nodeMap.containsKey(ToscaSchemaConstants.REQUIRED)
268                     && ((boolean) nodeMap.get(ToscaSchemaConstants.REQUIRED))) {
269                     array.put(p.getKey());
270                 }
271                 // if(nodeMap.containsKey(ToscaSchemaConstants.CONSTRAINTS))
272                 parseToscaChildNodeMap(p.getKey(), nodeMap, jsonPropertyNode, jsonEntrySchema,
273                     dataNodes, array, incrementSimpleTypeOrder());
274             }
275         });
276         jsonDataNode.put(JsonEditorSchemaConstants.REQUIRED, array);
277         jsonDataNode.put(JsonEditorSchemaConstants.PROPERTIES, jsonPropertyNode);
278     }
279
280     @SuppressWarnings("unchecked")
281     private void parseToscaPropertiesForType(String parentKey,
282         LinkedHashMap<String, Object> propertiesMap, JSONObject jsonDataNode, JSONArray array,
283         Map<String, JSONObject> jsonEntrySchema, LinkedHashMap<String, Object> dataNodes,
284         boolean isType, int order) {
285         JSONObject jsonPropertyNode = new JSONObject();
286
287         propertiesMap.entrySet().stream().forEach(p -> {
288             // array.put(p.getKey());
289             boolean overWriteArray = false;
290             if (p.getValue() instanceof Map) {
291                 LinkedHashMap<String, Object> nodeMap =
292                     (LinkedHashMap<String, Object>) p.getValue();
293                 if (!(parentKey.contains(ToscaSchemaConstants.ENTRY_SCHEMA)
294                     || parentKey.contains(ToscaSchemaConstants.POLICY_NODE))
295                     && nodeMap.containsKey(ToscaSchemaConstants.TYPE)
296                     && (((String) nodeMap.get(ToscaSchemaConstants.TYPE))
297                         .contains(ToscaSchemaConstants.POLICY_DATA))) {
298                     overWriteArray = true;
299                 }
300                 if (nodeMap.containsKey(ToscaSchemaConstants.REQUIRED)
301                     && ((boolean) nodeMap.get(ToscaSchemaConstants.REQUIRED))) {
302                     array.put(p.getKey());
303                 }
304                 parseToscaChildNodeMap(p.getKey(), nodeMap, jsonPropertyNode, jsonEntrySchema,
305                     dataNodes, array, order);
306             }
307         });
308         jsonDataNode.put(JsonEditorSchemaConstants.REQUIRED, array);
309         jsonDataNode.put(JsonEditorSchemaConstants.PROPERTIES, jsonPropertyNode);
310     }
311
312     private void parseToscaChildNodeMap(String childObjectKey,
313         LinkedHashMap<String, Object> childNodeMap, JSONObject jsonPropertyNode,
314         Map<String, JSONObject> jsonEntrySchema, LinkedHashMap<String, Object> dataNodes,
315         JSONArray array, int order) {
316         JSONObject childObject = new JSONObject();
317         // JSONArray childArray = new JSONArray();
318         parseDescription(childNodeMap, childObject);
319         parseTypes(childObjectKey, childNodeMap, childObject, jsonEntrySchema, dataNodes, array,
320             order);
321         parseConstraints(childNodeMap, childObject);
322         parseMetadataPossibleValues(childNodeMap, childObject);
323         parseEntrySchema(childNodeMap, childObject, jsonPropertyNode, jsonEntrySchema, dataNodes);
324
325         jsonPropertyNode.put(childObjectKey, childObject);
326         order++;
327
328     }
329
330     private void parseEntrySchema(LinkedHashMap<String, Object> childNodeMap,
331         JSONObject childObject, JSONObject jsonPropertyNode,
332         Map<String, JSONObject> jsonEntrySchema, LinkedHashMap<String, Object> dataNodes) {
333         if (childNodeMap.get(ToscaSchemaConstants.ENTRY_SCHEMA) != null) {
334             if (childNodeMap.get(ToscaSchemaConstants.ENTRY_SCHEMA) instanceof Map) {
335                 LinkedHashMap<String, Object> entrySchemaMap =
336                     (LinkedHashMap<String, Object>) childNodeMap
337                         .get(ToscaSchemaConstants.ENTRY_SCHEMA);
338                 entrySchemaMap.entrySet().stream().forEach(entry -> {
339                     if (entry.getKey().equalsIgnoreCase(ToscaSchemaConstants.TYPE)
340                         && entry.getValue() != null) {
341                         String entrySchemaType = (String) entry.getValue();
342                         if (entrySchemaType.contains(ToscaSchemaConstants.POLICY_DATA)) {
343                             JSONArray array = new JSONArray();
344                             if (jsonEntrySchema.get(entrySchemaType) != null) {
345                                 // Already traversed
346                                 JSONObject entrySchemaObject = jsonEntrySchema.get(entrySchemaType);
347                                 attachEntrySchemaJsonObject(childObject, entrySchemaObject,
348                                     JsonEditorSchemaConstants.TYPE_OBJECT);
349                             } else if (dataNodes.containsKey(entrySchemaType)) {
350
351                                 JSONObject entrySchemaObject = new JSONObject();
352                                 // Need to traverse
353                                 ((LinkedHashMap<String, Object>) dataNodes.get(entrySchemaType))
354                                     .entrySet().stream().forEach(pmap -> {
355                                         if (pmap.getKey()
356                                             .equalsIgnoreCase(ToscaSchemaConstants.PROPERTIES)) {
357                                             parseToscaProperties(ToscaSchemaConstants.ENTRY_SCHEMA,
358                                                 (LinkedHashMap<String, Object>) pmap.getValue(),
359                                                 entrySchemaObject, array, jsonEntrySchema,
360                                                 dataNodes, incrementComplexTypeOrder());
361                                             jsonEntrySchema.put(entrySchemaType, entrySchemaObject);
362                                             dataNodes.remove(entrySchemaType);
363                                             attachEntrySchemaJsonObject(childObject,
364                                                 entrySchemaObject,
365                                                 JsonEditorSchemaConstants.TYPE_OBJECT);
366                                         }
367
368                                     });
369                             }
370                         } else if (entrySchemaType
371                             .equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)
372                             || entrySchemaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_INTEGER)
373                             || entrySchemaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_FLOAT)) {
374                             JSONObject entrySchemaObject = new JSONObject();
375                             parseConstraints(entrySchemaMap, entrySchemaObject);
376                             parseMetadataPossibleValues(entrySchemaMap, entrySchemaObject);
377                             String jsontype = JsonEditorSchemaConstants.TYPE_STRING;
378                             if (entrySchemaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_INTEGER)
379                                 || entrySchemaType
380                                     .equalsIgnoreCase(ToscaSchemaConstants.TYPE_FLOAT)) {
381                                 jsontype = JsonEditorSchemaConstants.TYPE_INTEGER;
382                             }
383                             if (childNodeMap.get(ToscaSchemaConstants.TYPE) != null) {
384                                 // Only known value of type is String for now
385                                 if (childNodeMap.get(ToscaSchemaConstants.TYPE) instanceof String) {
386                                     String typeValue =
387                                         (String) childNodeMap.get(ToscaSchemaConstants.TYPE);
388                                     if (typeValue
389                                         .equalsIgnoreCase(ToscaSchemaConstants.TYPE_LIST)) {
390                                         // Custom key for JSON Editor and UI rendering
391                                         childObject.put(JsonEditorSchemaConstants.CUSTOM_KEY_FORMAT,
392                                             JsonEditorSchemaConstants.FORMAT_SELECT);
393                                         // childObject.put(JsonEditorSchemaConstants.UNIQUE_ITEMS,
394                                         // JsonEditorSchemaConstants.TRUE);
395                                     }
396                                 }
397                             }
398                             attachEntrySchemaJsonObject(childObject, entrySchemaObject, jsontype);
399                         }
400                     }
401                 });
402             }
403         }
404     }
405
406     private void attachEntrySchemaJsonObject(JSONObject childObject, JSONObject entrySchemaObject,
407         String dataType) {
408
409         entrySchemaObject.put(JsonEditorSchemaConstants.TYPE, dataType);
410         childObject.put(JsonEditorSchemaConstants.ITEMS, entrySchemaObject);
411     }
412
413     @SuppressWarnings("unchecked")
414     private void attachTypeJsonObject(JSONObject childObject, JSONObject typeObject) {
415         Iterator<String> keys = typeObject.keys();
416         while (keys.hasNext()) {
417             String key = keys.next();
418             childObject.put(key, typeObject.get(key));
419         }
420     }
421
422     /*
423      * private String parseKey(String toscaKey, String lookupString) { return
424      * toscaKey.substring(toscaKey.indexOf(lookupString) + lookupString.length(),
425      * toscaKey.length()); }
426      */
427
428     private void parseDescription(LinkedHashMap<String, Object> childNodeMap,
429         JSONObject childObject) {
430         if (childNodeMap.get(ToscaSchemaConstants.DESCRIPTION) != null) {
431             childObject.put(JsonEditorSchemaConstants.TITLE,
432                 childNodeMap.get(ToscaSchemaConstants.DESCRIPTION));
433         }
434     }
435
436     private void parseTypes(String childObjectKey, LinkedHashMap<String, Object> childNodeMap,
437         JSONObject childObject, Map<String, JSONObject> jsonEntrySchema,
438         LinkedHashMap<String, Object> dataNodes, JSONArray array, int order) {
439         if (childNodeMap.get(ToscaSchemaConstants.TYPE) != null) {
440             // Only known value of type is String for now
441             if (childNodeMap.get(ToscaSchemaConstants.TYPE) instanceof String) {
442                 childObject.put(JsonEditorSchemaConstants.PROPERTY_ORDER, order);
443                 String typeValue = (String) childNodeMap.get(ToscaSchemaConstants.TYPE);
444                 if (typeValue.equalsIgnoreCase(ToscaSchemaConstants.TYPE_INTEGER)) {
445                     childObject.put(JsonEditorSchemaConstants.TYPE,
446                         JsonEditorSchemaConstants.TYPE_INTEGER);
447
448                 } else if (typeValue.equalsIgnoreCase(ToscaSchemaConstants.TYPE_FLOAT)) {
449                     childObject.put(JsonEditorSchemaConstants.TYPE,
450                         JsonEditorSchemaConstants.TYPE_INTEGER);
451                 } else if (typeValue.equalsIgnoreCase(ToscaSchemaConstants.TYPE_LIST)) {
452                     childObject.put(JsonEditorSchemaConstants.TYPE,
453                         JsonEditorSchemaConstants.TYPE_ARRAY);
454                     // Custom key for JSON Editor and UI rendering
455                     childObject.put(JsonEditorSchemaConstants.CUSTOM_KEY_FORMAT,
456                         JsonEditorSchemaConstants.CUSTOM_KEY_FORMAT_TABS_TOP);
457                     childObject.put(JsonEditorSchemaConstants.UNIQUE_ITEMS,
458                         JsonEditorSchemaConstants.TRUE);
459                 } else if (typeValue.equalsIgnoreCase(ToscaSchemaConstants.TYPE_MAP)) {
460                     childObject.put(JsonEditorSchemaConstants.TYPE,
461                         JsonEditorSchemaConstants.TYPE_OBJECT);
462                 } else if (typeValue.contains(ToscaSchemaConstants.POLICY_DATA)) {
463                     JSONArray childArray = new JSONArray();
464
465                     if (jsonEntrySchema.get(typeValue) != null) {
466                         // Already traversed
467                         JSONObject entrySchemaObject = jsonEntrySchema.get(typeValue);
468                         attachTypeJsonObject(childObject, entrySchemaObject);
469                     } else if (dataNodes.containsKey(typeValue)) {
470                         JSONObject entrySchemaObject = new JSONObject();
471                         // Need to traverse
472                         JSONArray jsonArray = new JSONArray();
473                         ((LinkedHashMap<String, Object>) dataNodes.get(typeValue)).entrySet()
474                             .stream().forEach(pmap -> {
475                                 if (pmap.getKey()
476                                     .equalsIgnoreCase(ToscaSchemaConstants.PROPERTIES)) {
477                                     parseToscaPropertiesForType(childObjectKey,
478                                         (LinkedHashMap<String, Object>) pmap.getValue(),
479                                         entrySchemaObject, childArray, jsonEntrySchema, dataNodes,
480                                         true, incrementComplexSimpleTypeOrder());
481                                     jsonEntrySchema.put(typeValue, entrySchemaObject);
482                                     dataNodes.remove(typeValue);
483                                     attachTypeJsonObject(childObject, entrySchemaObject);
484                                 }
485                             });
486                     }
487                 } else {
488                     childObject.put(JsonEditorSchemaConstants.TYPE,
489                         JsonEditorSchemaConstants.TYPE_STRING);
490                 }
491             }
492             if (childNodeMap.get(ToscaSchemaConstants.DEFAULT) != null) {
493                 childObject.put(JsonEditorSchemaConstants.DEFAULT,
494                     childNodeMap.get(ToscaSchemaConstants.DEFAULT));
495             }
496         }
497     }
498
499     private void parseConstraints(LinkedHashMap<String, Object> childNodeMap,
500         JSONObject childObject) {
501         if (childNodeMap.containsKey(ToscaSchemaConstants.CONSTRAINTS)
502             && childNodeMap.get(ToscaSchemaConstants.CONSTRAINTS) != null) {
503             List<LinkedHashMap<String, Object>> constraintsList =
504                 (List<LinkedHashMap<String, Object>>) childNodeMap
505                     .get(ToscaSchemaConstants.CONSTRAINTS);
506             constraintsList.stream().forEach(c -> {
507                 if (c instanceof Map) {
508                     c.entrySet().stream().forEach(constraint -> {
509                         if (constraint.getKey().equalsIgnoreCase(ToscaSchemaConstants.MIN_LENGTH)
510                             || constraint.getKey()
511                                 .equalsIgnoreCase(ToscaSchemaConstants.GREATER_OR_EQUAL)) {
512                             // For String min_lenghth is minimum length whereas for number, it will
513                             // be
514                             // minimum or greater than to the defined value
515                             if (childNodeMap.containsKey(ToscaSchemaConstants.TYPE)
516                                 && (childNodeMap.get(ToscaSchemaConstants.TYPE) instanceof String)
517                                 && ((String) childNodeMap.get(ToscaSchemaConstants.TYPE))
518                                     .equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)) {
519                                 childObject.put(JsonEditorSchemaConstants.MIN_LENGTH,
520                                     constraint.getValue());
521                             } else {
522                                 childObject.put(JsonEditorSchemaConstants.MINIMUM,
523                                     constraint.getValue());
524                             }
525                         } else if (constraint.getKey()
526                             .equalsIgnoreCase(ToscaSchemaConstants.MAX_LENGTH)
527                             || constraint.getKey()
528                                 .equalsIgnoreCase(ToscaSchemaConstants.LESS_OR_EQUAL)) {
529                             // For String max_lenghth is maximum length whereas for number, it will
530                             // be
531                             // maximum or less than the defined value
532                             if (childNodeMap.containsKey(ToscaSchemaConstants.TYPE)
533                                 && (childNodeMap.get(ToscaSchemaConstants.TYPE) instanceof String)
534                                 && ((String) childNodeMap.get(ToscaSchemaConstants.TYPE))
535                                     .equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)) {
536                                 childObject.put(JsonEditorSchemaConstants.MAX_LENGTH,
537                                     constraint.getValue());
538                             } else {
539                                 childObject.put(JsonEditorSchemaConstants.MAXIMUM,
540                                     constraint.getValue());
541                             }
542                         } else if (constraint.getKey()
543                             .equalsIgnoreCase(ToscaSchemaConstants.LESS_THAN)) {
544                             childObject.put(JsonEditorSchemaConstants.EXCLUSIVE_MAXIMUM,
545                                 constraint.getValue());
546                         } else if (constraint.getKey()
547                             .equalsIgnoreCase(ToscaSchemaConstants.GREATER_THAN)) {
548                             childObject.put(JsonEditorSchemaConstants.EXCLUSIVE_MINIMUM,
549                                 constraint.getValue());
550                         } else if (constraint.getKey()
551                             .equalsIgnoreCase(ToscaSchemaConstants.IN_RANGE)) {
552                             if (constraint.getValue() instanceof ArrayList<?>) {
553                                 if (childNodeMap.containsKey(ToscaSchemaConstants.TYPE)
554                                     && (childNodeMap
555                                         .get(ToscaSchemaConstants.TYPE) instanceof String)
556                                     && ((String) childNodeMap.get(ToscaSchemaConstants.TYPE))
557                                         .equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)) {
558                                     childObject.put(JsonEditorSchemaConstants.MIN_LENGTH,
559                                         ((ArrayList) constraint.getValue()).get(0));
560                                     childObject.put(JsonEditorSchemaConstants.MAX_LENGTH,
561                                         ((ArrayList) constraint.getValue()).get(1));
562                                 } else {
563                                     childObject.put(JsonEditorSchemaConstants.MINIMUM,
564                                         ((ArrayList) constraint.getValue()).get(0));
565                                     childObject.put(JsonEditorSchemaConstants.MAXIMUM,
566                                         ((ArrayList) constraint.getValue()).get(1));
567                                 }
568
569                             }
570                         } else if (constraint.getKey()
571                             .equalsIgnoreCase(ToscaSchemaConstants.VALID_VALUES)) {
572                             JSONArray validValuesArray = new JSONArray();
573
574                             if (constraint.getValue() instanceof ArrayList<?>) {
575                                 boolean processDictionary =
576                                     ((ArrayList<?>) constraint.getValue()).stream().anyMatch(
577                                         value -> (value instanceof String && ((String) value)
578                                             .contains(ToscaSchemaConstants.DICTIONARY)));
579                                 if (!processDictionary) {
580                                     ((ArrayList<?>) constraint.getValue()).stream()
581                                         .forEach(value -> {
582                                             validValuesArray.put(value);
583                                         });
584                                     childObject.put(JsonEditorSchemaConstants.ENUM,
585                                         validValuesArray);
586                                 } else {
587                                     ((ArrayList<?>) constraint.getValue()).stream()
588                                         .forEach(value -> {
589                                             if ((value instanceof String && ((String) value)
590                                                 .contains(ToscaSchemaConstants.DICTIONARY))) {
591                                                 processDictionaryElements(childObject,
592                                                     (String) value);
593                                             }
594
595                                         });
596
597                                 }
598                             }
599
600                         }
601                     });
602                 }
603             });
604         }
605     }
606
607     private void parseMetadataPossibleValues(LinkedHashMap<String, Object> childNodeMap,
608         JSONObject childObject) {
609         if (childNodeMap.containsKey(ToscaSchemaConstants.METADATA)
610             && childNodeMap.get(ToscaSchemaConstants.METADATA) != null) {
611             LinkedHashMap<String, Object> metadataMap =
612                 (LinkedHashMap<String, Object>) childNodeMap.get(ToscaSchemaConstants.METADATA);
613             if (metadataMap instanceof Map) {
614                 metadataMap.entrySet().stream().forEach(constraint -> {
615                     if (constraint.getKey()
616                         .equalsIgnoreCase(ToscaSchemaConstants.METADATA_CLAMP_POSSIBLE_VALUES)) {
617                         JSONArray validValuesArray = new JSONArray();
618
619                         if (constraint.getValue() instanceof ArrayList<?>) {
620                             boolean processDictionary = ((ArrayList<?>) constraint.getValue())
621                                 .stream().anyMatch(value -> (value instanceof String
622                                     && ((String) value).contains(ToscaSchemaConstants.DICTIONARY)));
623                             if (processDictionary) {
624                                 ((ArrayList<?>) constraint.getValue()).stream().forEach(value -> {
625                                     if ((value instanceof String && ((String) value)
626                                         .contains(ToscaSchemaConstants.DICTIONARY))) {
627                                         processDictionaryElements(childObject, (String) value);
628                                     }
629
630                                 });
631
632                             }
633                         }
634
635                     }
636                 });
637             }
638         }
639     }
640
641     private void processDictionaryElements(JSONObject childObject, String dictionaryReference) {
642         if (dictionaryReference.contains("#")) {
643             String[] dictionaryKeyArray = dictionaryReference
644                 .substring(dictionaryReference.indexOf(ToscaSchemaConstants.DICTIONARY) + 11,
645                     dictionaryReference.length())
646                 .split("#");
647             // We support only one # as of now.
648             List<DictionaryElement> cldsDictionaryElements = null;
649             List<DictionaryElement> subDictionaryElements = null;
650             if (dictionaryKeyArray != null && dictionaryKeyArray.length == 2) {
651                 cldsDictionaryElements = dictionaryService.getDictionary(dictionaryKeyArray[0])
652                     .getDictionaryElements().stream().collect(Collectors.toList());
653                 subDictionaryElements = dictionaryService.getDictionary(dictionaryKeyArray[1])
654                     .getDictionaryElements().stream().collect(Collectors.toList());
655
656                 if (cldsDictionaryElements != null) {
657                     List<String> subCldsDictionaryNames = subDictionaryElements.stream()
658                         .map(DictionaryElement::getShortName).collect(Collectors.toList());
659                     JSONArray jsonArray = new JSONArray();
660
661                     Optional.ofNullable(cldsDictionaryElements).get().stream().forEach(c -> {
662                         JSONObject jsonObject = new JSONObject();
663                         if (c.getSubDictionary() != null) {
664                             Dictionary subDictionary =
665                                 dictionaryService.getDictionary(c.getSubDictionary());
666                             if (subDictionary != null
667                                 && !subDictionary.getDictionaryElements().isEmpty()) {
668
669                                 jsonObject.put(JsonEditorSchemaConstants.CUSTOM_KEY_FORMAT_INPUT,
670                                     JsonEditorSchemaConstants.FORMAT_SELECT);
671
672                                 List<String> shortNames = new ArrayList<>();
673                                 subDictionary.getDictionaryElements().stream().forEach(c1 -> {
674                                     shortNames.add(c1.getShortName());
675                                 });
676                                 jsonObject.put(JsonEditorSchemaConstants.VALUES, shortNames);
677                             }
678                         }
679                         jsonObject.put(JsonEditorSchemaConstants.TYPE, getJsonType(c.getType()));
680
681                         if (c.getType() != null
682                             && (c.getType().equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)
683                                 || c.getType().equalsIgnoreCase(ToscaSchemaConstants.TYPE_DATE_TIME)
684                                 || c.getType().equalsIgnoreCase(ToscaSchemaConstants.TYPE_MAP))) {
685                             jsonObject.put(JsonEditorSchemaConstants.MIN_LENGTH, 1);
686
687                             if (c.getType().equalsIgnoreCase(ToscaSchemaConstants.TYPE_DATE_TIME)) {
688                                 jsonObject.put(JsonEditorSchemaConstants.PLUGIN,
689                                     JsonEditorSchemaConstants.DATE_TIME_PICKER);
690                                 jsonObject.put(JsonEditorSchemaConstants.INPUT_EVENT,
691                                     JsonEditorSchemaConstants.DP_CHANGE);
692                                 JSONObject formatJsonObject = new JSONObject();
693                                 formatJsonObject.put(JsonEditorSchemaConstants.FORMAT,
694                                     JsonEditorSchemaConstants.DATE_TIME_FORMAT);
695                                 jsonObject.put(JsonEditorSchemaConstants.VALIDATION,
696                                     formatJsonObject);
697                             }
698                         }
699
700                         jsonObject.put(JsonEditorSchemaConstants.ID, c.getName());
701                         jsonObject.put(JsonEditorSchemaConstants.LABEL, c.getShortName());
702                         jsonObject.put(JsonEditorSchemaConstants.OPERATORS, subCldsDictionaryNames);
703                         jsonArray.put(jsonObject);
704                     });;
705                     JSONObject filterObject = new JSONObject();
706                     filterObject.put(JsonEditorSchemaConstants.FILTERS, jsonArray);
707
708                     childObject.put(JsonEditorSchemaConstants.TYPE,
709                         JsonEditorSchemaConstants.TYPE_QBLDR);
710                     // TO invoke validation on such parameters
711                     childObject.put(JsonEditorSchemaConstants.MIN_LENGTH, 1);
712                     childObject.put(JsonEditorSchemaConstants.QSSCHEMA, filterObject);
713
714                 }
715             }
716         } else {
717             String dictionaryKey = dictionaryReference.substring(
718                 dictionaryReference.indexOf(ToscaSchemaConstants.DICTIONARY) + 11,
719                 dictionaryReference.length());
720
721             if (dictionaryKey != null) {
722                 if (dictionaryKey.contains(ToscaSchemaConstants.TYPE_USER_DEFINED)) {
723                     childObject.put(JsonEditorSchemaConstants.ENUM, new ArrayList<>());
724                     // Add Enum titles for generated translated values during
725                     // JSON instance generation
726                     JSONObject enumTitles = new JSONObject();
727                     enumTitles.put(JsonEditorSchemaConstants.ENUM_TITLES, new ArrayList<>());
728                     childObject.put(JsonEditorSchemaConstants.OPTIONS, enumTitles);
729                 } else {
730                     List<DictionaryElement> cldsDictionaryElements =
731                         dictionaryService.getDictionary(dictionaryKey).getDictionaryElements()
732                             .stream().collect(Collectors.toList());
733                     if (cldsDictionaryElements != null) {
734                         List<String> cldsDictionaryNames = new ArrayList<>();
735                         List<String> cldsDictionaryFullNames = new ArrayList<>();
736                         cldsDictionaryElements.stream().forEach(c -> {
737                             // Json type will be translated before Policy creation
738                             if (c.getType() != null && !c.getType().equalsIgnoreCase("json")) {
739                                 cldsDictionaryFullNames.add(c.getName());
740                             }
741                             cldsDictionaryNames.add(c.getShortName());
742                         });
743
744                         if (!cldsDictionaryFullNames.isEmpty()) {
745                             childObject.put(JsonEditorSchemaConstants.ENUM,
746                                 cldsDictionaryFullNames);
747                             // Add Enum titles for generated translated values during JSON instance
748                             // generation
749                             JSONObject enumTitles = new JSONObject();
750                             enumTitles.put(JsonEditorSchemaConstants.ENUM_TITLES,
751                                 cldsDictionaryNames);
752                             childObject.put(JsonEditorSchemaConstants.OPTIONS, enumTitles);
753                         } else {
754                             childObject.put(JsonEditorSchemaConstants.ENUM, cldsDictionaryNames);
755                         }
756
757                     }
758                 }
759             }
760         }
761     }
762
763     private String getJsonType(String toscaType) {
764         String jsonType = null;
765         if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_INTEGER)
766             || toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_NUMBER)) {
767             jsonType = JsonEditorSchemaConstants.TYPE_INTEGER;
768         } else if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_DATE_TIME)) {
769             jsonType = JsonEditorSchemaConstants.TYPE_DATE_TIME;
770         } else if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_LIST)) {
771             jsonType = JsonEditorSchemaConstants.TYPE_ARRAY;
772         } else if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_MAP)) {
773             jsonType = JsonEditorSchemaConstants.TYPE_MAP;
774         } else {
775             jsonType = JsonEditorSchemaConstants.TYPE_STRING;
776         }
777         return jsonType;
778     }
779
780 }