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