Added oparent to sdc main
[sdc.git] / catalog-be / src / test / java / org / openecomp / sdc / be / components / merge / property / PropertyDataValueMergeBusinessLogicTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.be.components.merge.property;
22
23 import com.fasterxml.jackson.core.type.TypeReference;
24 import com.fasterxml.jackson.databind.ObjectMapper;
25 import com.google.common.collect.Maps;
26 import fj.data.Either;
27 import org.junit.Before;
28 import org.junit.Test;
29 import org.junit.runner.RunWith;
30 import org.mockito.Mock;
31 import org.mockito.junit.MockitoJUnitRunner;
32 import org.openecomp.sdc.be.components.utils.PropertyDataDefinitionBuilder;
33 import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
34 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
35 import org.openecomp.sdc.be.datatypes.elements.SchemaDefinition;
36 import org.openecomp.sdc.be.model.DataTypeDefinition;
37 import org.openecomp.sdc.be.model.PropertyDefinition;
38 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
39 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
40
41 import java.io.IOException;
42 import java.util.*;
43 import java.util.function.Function;
44 import java.util.stream.Collectors;
45 import java.util.stream.Stream;
46
47 import static org.assertj.core.api.Assertions.assertThat;
48 import static org.junit.Assert.assertEquals;
49 import static org.junit.Assert.assertTrue;
50 import static org.mockito.Mockito.when;
51
52 @RunWith(MockitoJUnitRunner.class)
53 public class PropertyDataValueMergeBusinessLogicTest {
54
55     private ObjectMapper mapper = new ObjectMapper();
56     
57     private PropertyDataValueMergeBusinessLogic testInstance;
58
59     @Mock
60     private ApplicationDataTypeCache applicationDataTypeCache;
61
62     @Before
63     public void setUp() throws Exception {
64         PropertyValueMerger propertyValueMerger = new PropertyValueMerger();
65         
66         testInstance = new PropertyDataValueMergeBusinessLogic(propertyValueMerger, applicationDataTypeCache);
67     }
68
69     @Test
70     public void mergeProperties_emptyOldAndNewValues() throws Exception {
71         PropertyDataDefinition oldProp = createProp("prop1", ToscaPropertyType.STRING.getType(), null, null);
72         PropertyDataDefinition newProp = createProp("prop1", ToscaPropertyType.STRING.getType(), null, null);
73         testMergeProps(oldProp, newProp, null);
74     }
75
76     @Test
77     public void mergeProperties_emptyOldValue() throws Exception {
78         PropertyDataDefinition oldProp = createProp("prop1", ToscaPropertyType.STRING.getType(), null, null);
79         PropertyDataDefinition newProp = createProp("prop1", ToscaPropertyType.STRING.getType(), null, "newVal");
80         testMergeProps(oldProp, newProp, "newVal");
81     }
82
83     @Test
84     public void mergeSimpleStringType_copyOldValueIfNoNewValue() throws Exception {
85         PropertyDataDefinition oldProp = createProp("prop1", ToscaPropertyType.STRING.getType(), null, "val1");
86         PropertyDataDefinition newProp = createProp("prop1", ToscaPropertyType.STRING.getType(), null, null);
87         testMergeProps(oldProp, newProp, "val1");
88     }
89
90     @Test
91     public void mergeSimpleStringType_dontCopyOldValIfHasNewVal() throws Exception {
92         PropertyDataDefinition oldProp = createProp("prop1", ToscaPropertyType.STRING.getType(), null, "val1");
93         PropertyDataDefinition newProp = createProp("prop1", ToscaPropertyType.STRING.getType(), null, "newVal");
94         testMergeProps(oldProp, newProp, "newVal");
95     }
96
97     @Test
98     public void mergeSimpleIntType_copyOldValueIfNoNewValue() throws Exception {
99         PropertyDataDefinition oldProp = createProp("prop1", ToscaPropertyType.INTEGER.getType(), null, "44");
100         PropertyDataDefinition newProp = createProp("prop1", ToscaPropertyType.INTEGER.getType(), null, null);
101         testMergeProps(oldProp, newProp, "44");
102     }
103
104     @Test
105     public void mergeSimpleIntType_dontCopyOldValIfHasNewVal() throws Exception {
106         PropertyDataDefinition oldProp = createProp("prop1", ToscaPropertyType.INTEGER.getType(), null, "44");
107         PropertyDataDefinition newProp = createProp("prop1", ToscaPropertyType.INTEGER.getType(), null, "45");
108         testMergeProps(oldProp, newProp, "45");
109     }
110
111     @Test
112     public void mergeSimpleBooleanType_copyOldValueIfNoNewValue() throws Exception {
113         PropertyDataDefinition oldProp = createProp("prop1", ToscaPropertyType.BOOLEAN.getType(), null, "false");
114         PropertyDataDefinition newProp = createProp("prop1", ToscaPropertyType.BOOLEAN.getType(), null, null);
115         testMergeProps(oldProp, newProp, "false");
116     }
117
118     @Test
119     public void mergeSimpleBooleanType_dontCopyOldValIfHasNewVal() throws Exception {
120         PropertyDataDefinition oldProp = createProp("prop1", ToscaPropertyType.BOOLEAN.getType(), null, "false");
121         PropertyDataDefinition newProp = createProp("prop1", ToscaPropertyType.BOOLEAN.getType(), null, "true");
122         testMergeProps(oldProp, newProp, "true");
123     }
124
125     @Test
126     public void mergeSimpleListType_copyOldValuesByIndex() throws Exception {
127         PropertyDataDefinition oldProp = createProp("prop1", ToscaPropertyType.LIST.getType(), "string", "[\"a\", \"b\"]");
128         PropertyDataDefinition newProp = createProp("prop1", ToscaPropertyType.LIST.getType(), "string", "[\"x\", \"\"]");
129         testMergeProps(oldProp, newProp, "[\"x\",\"b\"]");
130     }
131     
132     @Test
133     public void mergeSimpleListType_differentSize() throws Exception {
134         PropertyDataDefinition oldProp = createProp("prop1", ToscaPropertyType.LIST.getType(), "string", "[\"a\", \"b\", \"c\"]");
135         PropertyDataDefinition newProp = createProp("prop1", ToscaPropertyType.LIST.getType(), "string", "[\"x\", \"\"]");
136         testMergeProps(oldProp, newProp, "[\"x\",\"\"]");
137     }
138
139     @Test
140     public void mergeSimpleListType_jsonList() throws Exception {
141         PropertyDataDefinition oldProp = createProp("prop1", ToscaPropertyType.LIST.getType(), "json", "[[\"a\", \"b\"], \"c\"]");
142         PropertyDataDefinition newProp = createProp("prop1", ToscaPropertyType.LIST.getType(), "json", "[[\"a\"], \"d\"]");
143         testMergeProps(oldProp, newProp, "[[\"a\"],\"d\"]");
144     }
145
146     /**                                   
147      * Old property:                       New property:                           Expected:                           
148      *   {                                  {                                       {                                 
149      *     "mac_range_plan": "y",             "mac_range_plan": "",                   "mac_range_plan": "y",          
150      *     "mac_count_required": {            "mac_count_required": {                 "mac_count_required": {         
151      *       "is_required": true,               "is_required": false,                   "is_required": false,         
152      *       "count": 44                        "mac_address": "myAddress"              "mac_address": "myAddress"    
153      *     }                                  }                                       }                               
154      *   }                                  }                                       }                                 
155      *                                                                                                                
156      */
157     @Test
158     public void mergeComplexType() throws Exception {
159         PropertyDataDefinition oldProp = createProp("prop1", "myType", null, "{\"mac_range_plan\":\"y\", \"mac_count_required\":{\"is_required\":true,\"count\":44}}");
160         PropertyDataDefinition newProp = createProp("prop1", "myType", null, "{\"mac_range_plan\":\"\",  \"mac_count_required\":{\"is_required\":false, \"mac_address\":\"myAddress\"}}");
161         
162         DataTypeDefinition myType = new DataTypeDefinition();
163         myType.setName("myType");
164       
165         PropertyDefinition mac_range_plan = new PropertyDefinition();
166         mac_range_plan.setName("mac_range_plan");
167         mac_range_plan.setType("string");
168
169         PropertyDefinition mac_count_required = new PropertyDefinition();
170         mac_count_required.setName("mac_count_required");
171         mac_count_required.setType("map");
172         
173         myType.setProperties(Arrays.asList(mac_range_plan, mac_count_required));
174         Map<String, DataTypeDefinition> dataTypes = Collections.singletonMap(myType.getName(), myType);
175
176         when(applicationDataTypeCache.getAll()).thenReturn(Either.left(dataTypes));
177         
178         testInstance.mergePropertyValue(oldProp, newProp, Collections.emptyList());
179         
180         assertEquals("myType", "{\"mac_range_plan\":\"y\",\"mac_count_required\":{\"is_required\":false,\"mac_address\":\"myAddress\"}}", newProp.getValue());
181     }
182     
183     
184     
185     
186     /**                                                                                    Expected property:
187      * Old property:                            New property:                                {
188      *   {                                        {                                            "mac_range_plan": "n",
189      *     "mac_range_plan": "y",   "               "mac_range_plan": "n",                     "mymap": {
190      *     "mymap": {                                   "mymap": {                                     "mac_count_required": {      
191      *            "mac_count_required": {                       "mac_count_required": {                               "is_required": false,
192      *              "is_required": true,                          "is_required": false                        "count": 44                 
193      *              "count": 44                                     },                                             },
194      *            },                                            "host":"localhost",                                "host":"localhost",
195      *            "backup-mode":"daily",                        "ip":"127.0.0.1"                                   "ip":"127.0.0.1"
196      *            "ip":"0.0.0.0"                        }                                          }                            
197      *     }                                      }                                          }
198      *   }                                                                                      
199      *                                                                                       
200      */
201     @Test
202     public void mergeComplexType_containingMapWithComplexType() throws Exception {
203         PropertyDataDefinition oldProp = createProp("prop1", "myType", null, "{\"mac_range_plan\":\"y\",\"mymap\": {\"mac_count_required\": {\"is_required\":true,\"count\":44},\"backup-mode\":\"daily\",\"ip\":\"0.0.0.0\"}}");
204         PropertyDataDefinition newProp = createProp("prop1", "myType", null, "{\"mac_range_plan\":\"n\",\"mymap\": {\"mac_count_required\": {\"is_required\":false},\"host\":\"localhost\",\"ip\":\"127.0.0.1\"}}");
205         
206         DataTypeDefinition myType = new DataTypeDefinition();
207         myType.setName("myType");
208       
209         PropertyDefinition mac_range_plan = new PropertyDefinition();
210         mac_range_plan.setName("mac_range_plan");
211         mac_range_plan.setType("string");
212         
213         PropertyDefinition mymap = new PropertyDefinition();
214         mymap.setName("mymap");
215         mymap.setType("map");
216
217         PropertyDefinition mac_count_required = new PropertyDefinition();
218         mac_count_required.setName("mac_count_required");
219         mac_count_required.setType("MacType");
220         
221         SchemaDefinition entrySchema = new SchemaDefinition();
222         entrySchema.setProperty(mac_count_required);
223         mymap.setSchema(entrySchema);
224         
225         myType.setProperties(Arrays.asList(mac_range_plan, mymap, mac_count_required));
226         Map<String, DataTypeDefinition> dataTypes = Collections.singletonMap(myType.getName(), myType);
227
228         when(applicationDataTypeCache.getAll()).thenReturn(Either.left(dataTypes));
229         
230         testInstance.mergePropertyValue(oldProp, newProp, Collections.emptyList());
231         
232         assertEquals("myType", "{\"mac_range_plan\":\"n\",\"mymap\":{\"ip\":\"127.0.0.1\",\"mac_count_required\":{\"is_required\":false,\"count\":44},\"host\":\"localhost\"}}", newProp.getValue());
233     }
234
235
236     /*                                                               
237      *  Old Property:                      New Property:                          Expected:          
238      *  [                                  [                                      [                      
239      *    {                                   {                                      {                   
240      *      "prop1": "val1",                    "prop2": {                             "prop2": {        
241      *      "prop2": {                            "prop3": false                         "prop3": false  
242      *        "prop3": true,                    }                                      }                 
243      *        "prop4": 44                     }                                      }                   
244      *      }                              ]                                      ]                      
245      *    },                                                         
246      *    {
247      *      "prop1": "val2",
248      *      "prop2": {
249      *        "prop3": true
250      *      }
251      *    }
252      *  ]
253      *  
254      */
255     @Test
256     public void mergeListOfComplexType_differentSize() throws Exception {
257         PropertyDataDefinition oldProp = createProp("prop1", "list", "myType", "[{\"prop1\":\"val1\", \"prop2\":{\"prop3\":true,\"prop4\":44}}, " +
258                                                                                        "{\"prop1\":\"val2\", \"prop2\":{\"prop3\":true}}]");
259         PropertyDataDefinition newProp = createProp("prop1", "list", "myType", "[{\"prop2\":{\"prop3\":false}}]");
260
261         Map<String, DataTypeDefinition> dataTypes = buildDataTypes();
262         when(applicationDataTypeCache.getAll()).thenReturn(Either.left(dataTypes));
263         testInstance.mergePropertyValue(oldProp, newProp, Collections.emptyList());
264         assertEquals("myType", "[{\"prop2\":{\"prop3\":false}}]", newProp.getValue());
265     }
266     
267     
268     /*
269      *  Old Property:                     New Property:                 Expected:
270      *  [                                 [                             [
271      *    {                                 {                            {
272      *      "prop1": "val1",                  "prop1": "",                 "prop1": "val1",
273      *      "prop2": {                        "prop2": {                   "prop2": {
274      *        "prop3": true,                    "prop4": 45                  "prop3": true
275      *        "prop4": 44                     }                              "prop4": 45
276      *      }                               },                             }                       
277      *    },                                {                            },                        
278      *    {                                                              {                         
279      *      "prop1": "val2",                  "prop2": {                   "prop1": "val2",                        
280      *      "prop2": {                          "prop3": false             "prop2": {              
281      *        "prop3": true                   }                              "prop3": false        
282      *      }                               }                              }                       
283      *    }                               ]                              }                         
284      *  ]                                                              ]                           
285      *                                                                                             
286      */                                                                                            
287     @Test
288     public void mergeListOfComplexType() throws Exception {
289         PropertyDataDefinition oldProp = createProp("lprop", "list", "myType", "[{\"prop1\":\"val1\", \"prop2\":{\"prop3\":true,\"prop4\":44}}, " +
290                                                                                 "{\"prop1\":\"val2\", \"prop2\":{\"prop3\":true}}]");
291         PropertyDataDefinition newProp = createProp("lprop", "list", "myType", "[{\"prop1\":\"\", \"prop2\":{\"prop4\":45}}, {\"prop2\":{\"prop3\":false}}]");
292
293         
294         DataTypeDefinition myType = new DataTypeDefinition();
295         myType.setName("myType");
296         
297         Map<String, DataTypeDefinition> dataTypes = buildDataTypes();
298         when(applicationDataTypeCache.getAll()).thenReturn(Either.left(dataTypes));
299         testInstance.mergePropertyValue(oldProp, newProp, Collections.emptyList());
300         assertEquals("lprop",  "[{\"prop2\":{\"prop4\":45,\"prop3\":true},\"prop1\":\"val1\"},{\"prop2\":{\"prop3\":false},\"prop1\":\"val2\"}]", newProp.getValue());
301     }
302     
303     
304     
305     /*
306      * Old Property:                          New Property:                               Expected:                          
307      * {                                      {                                           {
308      *   "lprop": [                             "lprop": [                                  "lprop": [
309      *     {                                      {                                           {
310      *       "prop1": "val1",                       "prop2": [                                  "prop1": "val1",
311      *       "prop2": [                               {                                         "prop2": [
312      *         {                                        "prop3": true                             {
313      *           "prop3": true,                       },                                            "prop3": true,
314      *           "prop4": 44                              {                                             "prop4": 44
315      *         },                                           "prop4":69                                },
316      *         {                                          }                                               {
317      *           "prop3": false,                    ]                                               "prop3": false,
318      *           "prop4": 96                      },                                                "prop4": 69
319      *         }                                  {                                               }
320      *       ]                                      "prop1": "val1",                            ]
321      *     },                                       "prop2": [                                },
322      *     {                                          {                                       {
323      *       "prop1": "val2",                           "prop3": false                          "prop1": "val1",
324      *       "prop2": [                               }                                         "prop2": [
325      *         {                                    ]                                             {
326      *           "prop3": true                    }                                                 "prop3": false
327      *         }                                ],                                                }
328      *       ]                                  "prop5": "value05"                              ]
329      *     }                                  }                                               }
330      *   ],                                                                                 ],
331      *   "prop5": "value5"                                                                  "prop5": "value05"
332      * }                                                                                  }   
333      *
334      *
335      */                                                                                            
336     @Test
337     public void mergeComplexType_containsListOfComplexType() throws Exception {
338         PropertyDataDefinition oldProp = createProp("complexProp", "complexType", null, 
339                 "{\"lprop\":[{\"prop1\":\"val1\",\"prop2\":[{\"prop3\":true,\"prop4\":44},{\"prop3\":false,\"prop4\":96}]}," + 
340                 "{\"prop1\":\"val2\",\"prop2\":[{\"prop3\":true}]}],\"prop5\":\"value5\"} ");
341         PropertyDataDefinition newProp = createProp("complexProp", "complexType", null,
342                 "{\"lprop\":[{\"prop2\":[{\"prop3\":true},{\"prop4\":69}]},{\"prop1\":\"val1\",\"prop2\":[{\"prop3\":false}]}],\"prop5\":\"value05\"}");
343
344         DataTypeDefinition complexType = new DataTypeDefinition();
345         complexType.setName("complexType");
346
347         PropertyDefinition lprop = new PropertyDefinition(createProp("lprop", "list", "myType", null));
348
349         PropertyDefinition prop5 = new PropertyDefinition();
350         prop5.setName("prop5");
351         prop5.setType("string");
352         
353         DataTypeDefinition complexProp = new DataTypeDefinition();
354         complexProp.setName("complexType");
355         complexType.setProperties(Arrays.asList(lprop, prop5));
356         
357         DataTypeDefinition myType = new DataTypeDefinition();
358         myType.setName("myType");
359
360         PropertyDefinition prop1 = new PropertyDefinition();
361         prop1.setName("prop1");
362         prop1.setType("string");
363         
364         DataTypeDefinition myInnerType = new DataTypeDefinition();
365         myInnerType.setName("myInnerType");
366
367         PropertyDefinition prop2 = new PropertyDefinition(createProp("prop2", "list", "myInnerType", null));
368
369         PropertyDefinition prop3 = new PropertyDefinition();
370         prop3.setName("prop3");
371         prop3.setType("boolean");
372
373         PropertyDefinition prop4 = new PropertyDefinition();
374         prop4.setName("prop4");
375         prop4.setType("integer");
376
377         complexType.setProperties(Arrays.asList(lprop, prop5));
378         myType.setProperties(Arrays.asList(prop1, prop2));
379         myInnerType.setProperties(Arrays.asList(prop3, prop4));
380         
381         Map<String, DataTypeDefinition> dataTypes = Stream.of(complexType, myType, myInnerType)
382                                                            .collect(Collectors.toMap(DataTypeDefinition::getName, Function.identity()));
383         
384         when(applicationDataTypeCache.getAll()).thenReturn(Either.left(dataTypes));
385         
386         testInstance.mergePropertyValue(oldProp, newProp, Collections.emptyList());
387         
388         assertEquals("complexProp", 
389                 "{\"lprop\":[{\"prop2\":[{\"prop4\":44,\"prop3\":true},{\"prop4\":69,\"prop3\":false}],\"prop1\":\"val1\"},{\"prop2\":[{\"prop3\":false}],\"prop1\":\"val1\"}],\"prop5\":\"value05\"}",
390                 newProp.getValue());
391     }
392     
393     
394     @Test
395     public void mergeMapType_differentSize() throws Exception {
396         PropertyDataDefinition oldProp = createProp("prop1", "map", "string", "{\"prop1\":\"val1\", \"prop2\":\"val2\", \"prop3\":\"val3\"}");
397         PropertyDataDefinition newProp = createProp("prop1", "map", "string", "{\"prop1\":\"valY\", \"prop2\":\"\"}");
398         
399         HashMap<String, String> expected = Maps.newHashMap();
400         expected.put("prop1", "valY");
401         expected.put("prop2", "val2");
402         verifyMapMerge(getMergedMapProp(oldProp, newProp, Collections.emptyList()), expected);
403     }
404     
405     
406     @Test
407     public void mergeMapType() throws Exception {
408         PropertyDataDefinition oldProp = createProp("prop1", "map", "string", "{\"prop1\":\"val1\", \"prop2\":\"val2\", \"prop3\":\"\", \"prop4\":\"val4\"}");
409         PropertyDataDefinition newProp = createProp("prop1", "map", "string", "{\"prop1\":\"valY\", \"prop2\":\"\", \"prop3\":\"val3\", \"prop5\":\"val5\"}");
410         
411         
412         HashMap<String, String> expected = Maps.newHashMap();
413         expected.put("prop1", "valY");
414         expected.put("prop2", "val2");
415         expected.put("prop3", "val3");
416         expected.put("prop5", "val5");
417         verifyMapMerge(getMergedMapProp(oldProp, newProp, Collections.emptyList()), expected);
418     }
419
420     @Test
421     public void mergeMapTypeWhenNewValueIsEmpty() throws Exception {
422         PropertyDataDefinition oldProp = createProp("prop1", "map", "string", "{\"prop1\":\"val1\", \"prop2\":\"val2\", \"prop3\":\"val3\"}");
423         PropertyDataDefinition newProp = createProp("prop1", "map", "string", null);
424         HashMap<String, String> expected = Maps.newHashMap();
425         expected.put("prop1", "val1");
426         expected.put("prop2", "val2");
427         expected.put("prop3", "val3");
428         verifyMapMerge(getMergedMapProp(oldProp, newProp, Collections.singletonList("input1")), expected);
429     }
430
431     @Test
432     public void mergeGetInputValue() throws Exception {
433         PropertyDataDefinition oldProp = createGetInputProp("prop1", "string", null, "input1");
434         PropertyDataDefinition newProp = createProp("prop1", "string", null, "");
435         testMergeProps(oldProp, newProp, oldProp.getValue(), Collections.singletonList("input1"));
436         assertEquals(oldProp.getGetInputValues(), newProp.getGetInputValues());
437     }
438
439     @Test
440     public void mergeGetInputValue_valueIsNull_InNewProp() throws Exception {
441         PropertyDataDefinition oldProp = createGetInputProp("prop1", "string", null, "input1");
442         PropertyDataDefinition newProp = createProp("prop1", "string", null, null);
443         testMergeProps(oldProp, newProp,"{\"get_input\":\"input1\"}", Collections.singletonList("input1"));
444         assertGetInputValues(newProp, "input1");
445     }
446
447     /*
448      * Old property:                      New property:                       Expected:              
449      * [                                  [                                   [                          
450      *   {                                  {                                   {                         
451      *     "mac_range_plan": {                "mac_count_required": {           "mac_range_plan": {     
452      *       "get_input": "input1"              "is_required": true               "get_input": "input1" 
453      *     },                                 }                                 },                      
454      *     "mac_count_required": {          }                                   "mac_count_required": {                                    
455      *       "is_required": true,                                                 "is_required": true         
456      *       "count": {                   inputs: intput1, input2               }                             
457      *         "get_input": "input2"      ]                                   }                               
458      *       }                                                                                                
459      *     }                                                                  inputs: input2                    
460      *   }                                                                  ]                                 
461      *                                                                        
462      *   inputs: intput1, input2                                                                            
463      * ]                                                                                                    
464      * 
465      * 
466      * 
467      */
468     @Test
469     public void mergeComplexGetInputValue() throws Exception {
470         PropertyDataDefinition oldProp = new PropertyDataDefinitionBuilder().addGetInputValue("input1").addGetInputValue("input2").setName("prop1").setType("myType").setValue("{\"mac_range_plan\":{\"get_input\": \"input1\"}, \"mac_count_required\":{\"is_required\":true,\"count\":{\"get_input\": \"input2\"}}}").build();
471         PropertyDataDefinition newProp = new PropertyDataDefinitionBuilder().addGetInputValue("input2").setName("prop1").setType("myType").setValue("{\"mac_count_required\":{\"is_required\":true}}").build();
472         testMergeProps(oldProp, newProp,"{\"mac_range_plan\":{},\"mac_count_required\":{\"is_required\":true}}", Collections.singletonList("input2"));
473         assertGetInputValues(newProp, "input2");
474     }
475
476     @Test
477     public void mergeListValueWithMultipleGetInputs() throws Exception {
478         PropertyDataDefinition oldProp = new PropertyDataDefinitionBuilder()
479                 .addGetInputValue("input1").addGetInputValue("input2").addGetInputValue("input3")
480                 .setName("prop1")
481                 .setType("list").setSchemaType("string")
482                 .setValue("[{\"get_input\": \"input2\"},{\"get_input\": \"input3\"},{\"get_input\": \"input1\"}]")
483                 .build();
484
485         PropertyDataDefinition newProp = new PropertyDataDefinitionBuilder()
486                 .addGetInputValue("input3")
487                 .addGetInputValue("input5")
488                 .setName("prop1")
489                 .setType("list").setSchemaType("string")
490                 .setValue("[{\"get_input\": \"input5\"}, {\"get_input\": \"input3\"}]")
491                 .build();
492
493         testMergeProps(oldProp, newProp,"[{\"get_input\":\"input5\"},{\"get_input\":\"input3\"}]");
494         assertGetInputValues(newProp, "input3", "input5");
495     }
496
497     private void assertGetInputValues(PropertyDataDefinition newProp, String ... expectedInputNames) {
498         assertTrue(newProp.isGetInputProperty());
499         assertEquals(newProp.getGetInputValues().size(), expectedInputNames.length);
500         for (int i = 0; i < expectedInputNames.length; i++) {
501             String expectedInputName = expectedInputNames[i];
502             GetInputValueDataDefinition getInputValueDataDefinition = newProp.getGetInputValues().get(i);
503             assertEquals(getInputValueDataDefinition.getInputName(), expectedInputName);
504         }
505     }
506     
507     private void testMergeProps(PropertyDataDefinition oldProp, PropertyDataDefinition newProp, String expectedValue) {
508         testMergeProps(oldProp, newProp, expectedValue, Collections.emptyList());
509     }
510
511     private void testMergeProps(PropertyDataDefinition oldProp, PropertyDataDefinition newProp, String expectedValue,  List<String> getInputsToMerge) {
512         when(applicationDataTypeCache.getAll()).thenReturn(Either.left(Collections.emptyMap()));
513         testInstance.mergePropertyValue(oldProp, newProp, getInputsToMerge);
514         assertEquals(expectedValue, newProp.getValue());
515     }
516
517
518     private String getMergedMapProp(PropertyDataDefinition oldProp, PropertyDataDefinition newProp, List<String> getInputsToMerge) {
519         when(applicationDataTypeCache.getAll()).thenReturn(Either.left(Collections.emptyMap()));
520         testInstance.mergePropertyValue(oldProp, newProp, getInputsToMerge);
521         return newProp.getValue();
522     }
523
524     private void verifyMapMerge(String newValue, Map<String, String> expectedValues) {
525         Map<String, String> values = convertJsonToMap(newValue);
526         assertThat(values).isNotNull();
527         assertThat(values).containsAllEntriesOf(expectedValues);
528     }
529
530     private PropertyDataDefinition createProp(String name, String type, String innerType, String val) {
531         return new PropertyDataDefinitionBuilder()
532                 .setType(type)
533                 .setSchemaType(innerType)
534                 .setValue(val)
535                 .setName(name)
536                 .build();
537     }
538
539     private PropertyDataDefinition createGetInputProp(String name, String type, String innerType, String inputName) {
540         String val = String.format("{\"get_input\":\"%s\"}", inputName);
541         return new PropertyDataDefinitionBuilder()
542                 .setType(type)
543                 .setSchemaType(innerType)
544                 .setValue(val)
545                 .addGetInputValue(inputName)
546                 .setName(name)
547                 .build();
548
549     }
550
551     private Map<String, String> convertJsonToMap(String jsonString) {
552         try {
553             return mapper.readValue(jsonString, new TypeReference<Map<String, String>>(){});
554         } catch (IOException e) {
555             return null;
556         }
557     }
558
559     private Map<String, DataTypeDefinition> buildDataTypes() {
560         DataTypeDefinition myType = new DataTypeDefinition();
561         myType.setName("myType");
562         DataTypeDefinition myInnerType = new DataTypeDefinition();
563         myInnerType.setName("myInnerType");
564
565         PropertyDefinition prop1 = new PropertyDefinition();
566         prop1.setName("prop1");
567         prop1.setType("string");
568
569         PropertyDefinition prop2 = new PropertyDefinition();
570         prop2.setName("prop2");
571         prop2.setType("myInnerType");
572
573         PropertyDefinition prop3 = new PropertyDefinition();
574         prop3.setName("prop3");
575
576         PropertyDefinition prop4 = new PropertyDefinition();
577         prop4.setName("prop4");
578
579         myType.setProperties(Arrays.asList(prop1, prop2));
580         myInnerType.setProperties(Arrays.asList(prop3, prop4));
581
582         return Stream.of(myType, myInnerType).collect(Collectors.toMap(DataTypeDefinition::getName, Function.identity()));
583     }
584
585
586 }