@@ -13,6 +13,11 @@ import (
1313
1414var MergeRuleMap = map [string ]mergeJsonRule.MergeRule {}
1515
16+ var ArrayOrObjectKeys = map [string ]bool {
17+ "jmx" : true ,
18+ "otlp" : true ,
19+ }
20+
1621func MergeMap (source map [string ]interface {}, result map [string ]interface {}, sectionKey string ,
1722 mergeRuleMap map [string ]mergeJsonRule.MergeRule , path string ) {
1823 subMapSource , exists := GetSubMap (source , sectionKey )
@@ -32,16 +37,24 @@ func MergeMap(source map[string]interface{}, result map[string]interface{}, sect
3237
3338func mergeMap (sourceMap map [string ]interface {}, resultMap map [string ]interface {}, mergeRuleMap map [string ]mergeJsonRule.MergeRule , path string ) {
3439 for key , value := range sourceMap {
35- if rule , ok := mergeRuleMap [key ]; ok {
40+ rule , hasRule := mergeRuleMap [key ]
41+ existingValue , hasExisting := resultMap [key ]
42+
43+ switch {
44+ case hasRule :
3645 rule .Merge (sourceMap , resultMap )
37- } else if existingValue , ok := resultMap [key ]; ! ok {
46+ case ArrayOrObjectKeys [key ]:
47+ // Special handling for configurations that can be array or object according to schema
48+ mergeArrayOrObjectConfiguration (sourceMap , resultMap , key , path )
49+ case ! hasExisting :
3850 // only one defines the value
3951 resultMap [key ] = value
40- } else if ! reflect .DeepEqual (existingValue , value ) {
52+ case ! reflect .DeepEqual (existingValue , value ):
4153 // fail if different values are defined
4254 translator .AddErrorMessages (fmt .Sprintf ("%s%s" , path , key ), fmt .Sprintf ("Different values are specified for %v" , key ))
55+ default :
56+ // the same value is defined by multiple sources - no action needed
4357 }
44- // the same value is defined by multiple sources
4558 }
4659}
4760
@@ -103,3 +116,66 @@ func GetSubList(sourceMap map[string]interface{}, subKey string) []interface{} {
103116 }
104117 return resultList
105118}
119+
120+ func mergeArrayOrObjectConfiguration (sourceMap map [string ]interface {}, resultMap map [string ]interface {}, key string , path string ) {
121+ sourceValue , sourceExists := sourceMap [key ]
122+ if ! sourceExists {
123+ return
124+ }
125+
126+ resultValue , resultExists := resultMap [key ]
127+ if ! resultExists {
128+ resultMap [key ] = sourceValue
129+ return
130+ }
131+
132+ switch sourceValue .(type ) {
133+ case []interface {}:
134+ mergeArrayConfiguration (sourceValue , resultValue , resultMap , key , path )
135+ case map [string ]interface {}:
136+ mergeObjectConfiguration (sourceValue , resultValue , resultMap , key , path )
137+ default :
138+ translator .AddErrorMessages (fmt .Sprintf ("%s%s" , path , key ),
139+ fmt .Sprintf ("Unsupported configuration source type: %T" , sourceValue ))
140+ }
141+ }
142+
143+ func mergeArrayConfiguration (sourceValue , resultValue interface {}, resultMap map [string ]interface {}, key string , path string ) {
144+ sourceList := sourceValue .([]interface {})
145+
146+ switch rv := resultValue .(type ) {
147+ case []interface {}:
148+ // Array + Array: use existing mergeList function
149+ resultMap [key ] = mergeList (sourceList , rv )
150+ case map [string ]interface {}:
151+ // Array + Object: convert object to array and merge
152+ resultMap [key ] = mergeList (sourceList , []interface {}{rv })
153+ default :
154+ translator .AddErrorMessages (fmt .Sprintf ("%s%s" , path , key ),
155+ fmt .Sprintf ("Unsupported configuration type: %T" , resultValue ))
156+ }
157+ }
158+
159+ func mergeObjectConfiguration (sourceValue , resultValue interface {}, resultMap map [string ]interface {}, key string , path string ) {
160+ sourceObj := sourceValue .(map [string ]interface {})
161+
162+ switch rv := resultValue .(type ) {
163+ case []interface {}:
164+ // Object + Array: use existing mergeList function with single-item array
165+ resultMap [key ] = mergeList ([]interface {}{sourceObj }, rv )
166+ case map [string ]interface {}:
167+ // Object + Object: merge objects
168+ resultMap [key ] = mergeObjects (rv , sourceObj )
169+ default :
170+ translator .AddErrorMessages (fmt .Sprintf ("%s%s" , path , key ),
171+ fmt .Sprintf ("Unsupported configuration type: %T" , resultValue ))
172+ }
173+ }
174+
175+ // mergeObjects merges two objects, converting to array if they differ
176+ func mergeObjects (result , source map [string ]interface {}) interface {} {
177+ if reflect .DeepEqual (result , source ) {
178+ return result
179+ }
180+ return []interface {}{result , source }
181+ }
0 commit comments