Changed an instance-reference to a static reference.
[cli.git] / framework / src / main / java / org / onap / cli / fw / schema / OnapCommandSchemaMerger.java
1 /*
2  * Copyright 2017 Huawei Technologies Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onap.cli.fw.schema;
18
19 import java.util.LinkedHashMap;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Map.Entry;
23
24 import org.onap.cli.fw.cmd.OnapCommand;
25 import org.onap.cli.fw.conf.OnapCommandConstants;
26 import org.onap.cli.fw.error.OnapCommandException;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 /**
31  * Helps to merge two yaml schemas
32  *
33  */
34 public class OnapCommandSchemaMerger {
35
36     static Logger logger = LoggerFactory.getLogger(OnapCommandSchemaMerger.class);
37
38     private OnapCommandSchemaMerger(){
39         //It is made private in order to resolve: Utility classes should not have public constructors
40     }
41
42     public static Map<String, Object> mergeSchemas(OnapCommand cmd) throws OnapCommandException {
43         Map<String, Object> mergedResult = new LinkedHashMap<>();
44
45         for (String schema: cmd.getSchemas()) {
46             Map<String , Object> schemaMap = OnapCommandSchemaLoader.validateSchemaVersion(schema, cmd.getSchemaVersion());
47             mergeYamlMap(mergedResult, schemaMap);
48         }
49
50         return mergedResult;
51
52     }
53
54     public static void mergeWithExistingValue(Object yamlValue, Object existingValue, String key, Map<String, Object> mergedResult){
55         if (yamlValue instanceof Map) {
56             if (existingValue instanceof Map) {
57                 mergeYamlMap((Map<String, Object>) existingValue, (Map<String, Object>)  yamlValue);
58             } else if (existingValue instanceof String) {
59                 throw new IllegalArgumentException("Cannot merge complex element into a simple element: "+key);
60             } else {
61                 throw unknownValueType(key, yamlValue);
62             }
63         } else if (yamlValue instanceof List) {
64             mergeYamlLists(mergedResult, key, yamlValue);
65
66         } else if (yamlValue instanceof String
67                 || yamlValue instanceof Boolean
68                 || yamlValue instanceof Double
69                 || yamlValue instanceof Integer) {
70             mergedResult.put(key, yamlValue);
71
72         } else {
73             throw unknownValueType(key, yamlValue);
74         }
75     }
76
77     public static void mergeYamlMap(Map<String, Object> mergedResult, Map<String, Object> yamlContents) {
78         if (yamlContents == null) return;
79
80         for (String key : yamlContents.keySet()) {
81
82             Object yamlValue = yamlContents.get(key);
83             if (yamlValue == null) {
84                 mergedResult.put(key, yamlValue);
85                 continue;
86             }
87
88             Object existingValue = mergedResult.get(key);
89             if (existingValue != null) {
90                 mergeWithExistingValue(yamlValue, existingValue, key, mergedResult);
91             } else {
92                 if (yamlValue instanceof Map
93                         || yamlValue instanceof List
94                         || yamlValue instanceof String
95                         || yamlValue instanceof Boolean
96                         || yamlValue instanceof Integer
97                         || yamlValue instanceof Double) {
98                     mergedResult.put(key, yamlValue);
99                 } else {
100                     throw unknownValueType(key, yamlValue);
101                 }
102             }
103         }
104     }
105
106     private static IllegalArgumentException unknownValueType(String key, Object yamlValue) {
107         final String msg = "Cannot merge element of unknown type: " + key + ": " + yamlValue.getClass().getName();
108         return new IllegalArgumentException(msg);
109     }
110
111     private static void compareWithExistingNames(String nameN, List<Object> originalList, Map<String, Object> oN, Object o){
112         if (nameN != null) {
113
114             boolean existing = false;
115             for (Object e: originalList) {
116                 Map<String, Object> oE = (Map) e;
117                 String nameE = (String)oE.getOrDefault(OnapCommandConstants.NAME, null);
118
119                 //Name should be existing in the map, otherwise continue as don't know how to compare
120                 if (nameN.equals(nameE)) {
121                     for (Entry<String, Object> oNe : oN.entrySet()) {
122                         oE.put(oNe.getKey(), oNe.getValue());
123                     }
124                     existing = true;
125                     break;
126                 }
127             }
128
129             if (!existing) {
130                 originalList.add(o);
131             }
132         }
133     }
134
135     @SuppressWarnings("unchecked")
136     private static void mergeYamlLists(Map<String, Object> mergedResult, String key, Object yamlValue) {
137         if (! (yamlValue instanceof List && mergedResult.get(key) instanceof List)) {
138             throw new IllegalArgumentException("Cannot merge a list with a non-list: "+key);
139         }
140
141         List<Object> originalList = (List<Object>) mergedResult.get(key);
142
143         for (Object o: (List<Object>) yamlValue) {
144             Map<String, Object> oN = (Map) o;
145             String nameN = (String)oN.getOrDefault(OnapCommandConstants.NAME, null);
146
147             //Name should be existing in the map, otherwise continue as don't know how to compare
148             compareWithExistingNames(nameN, originalList, oN, o);
149         }
150     }
151 }
152