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