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