1 package org.wamblee.jenkins.pipelinelib
3 @Grab('org.yaml:snakeyaml:1.25')
5 import org.yaml.snakeyaml.Yaml
6 import org.yaml.snakeyaml.constructor.SafeConstructor
10 https://github.com/OndraZizka/yaml-merge/blob/master/src/main/java/org/cobbzilla/util/yml/YmlMerger.java
14 private final Yaml parser
17 parser = new Yaml(new SafeConstructor())
20 String merge(List<String> yamls) {
21 Map<String, Object> mergedResult = new LinkedHashMap<String, Object>();
23 final Map<String, Object> yamlToMerge = parser.load(yaml)
24 // Merge into results map.
25 mergeStructures(mergedResult, yamlToMerge)
27 return parser.dump(mergedResult)
30 private static Object addToMergedResult(Map<String, Object> mergedResult, String key, Object yamlValue) {
31 return mergedResult.put(key, yamlValue)
34 private static IllegalArgumentException unknownValueType(String key, Object yamlValue) {
35 final String msg = "Cannot mergeYamlFiles element of unknown type: " + key + ": " + yamlValue.getClass().getName()
36 return new IllegalArgumentException(msg)
39 private void mergeLists(Map<String, Object> mergedResult, String key, Object yamlValue) {
40 if (!(yamlValue instanceof List && mergedResult.get(key) instanceof List)) {
41 throw new IllegalArgumentException("Cannot mergeYamlFiles a list with a non-list: " + key)
44 List<Object> originalList = (List<Object>) mergedResult.get(key)
46 // original implementation
47 // originalList.addAll((List<Object>) yamlValue)
50 // below is non-standard approach as I assume a key:value mapping called (name->value) to identify a Map
51 List<Object> yamlList = (List<Object>) yamlValue
52 Map<String, Object> originalCache = new LinkedHashMap<>()
54 for (ori in originalList) {
55 if (ori instanceof Map) {
56 name = ori.get('name')
58 originalCache.put(name, ori)
64 for (item in yamlList) {
66 if (item instanceof Map) {
67 name = item.get('name')
68 if (name && originalCache.containsKey(name)) {
69 mergeStructures((Map<String, Object>) originalCache.get(name), (Map<String, Object>) item)
74 originalList.add(item)
79 private void mergeStructures(Map<String, Object> targetTree, Map<String, Object> sourceTree) {
80 if (sourceTree == null) return
82 for (String key : sourceTree.keySet()) {
84 Object yamlValue = sourceTree.get(key)
85 if (yamlValue == null) {
86 addToMergedResult(targetTree, key, yamlValue)
90 Object existingValue = targetTree.get(key);
91 if (existingValue != null) {
92 if (yamlValue instanceof Map) {
93 if (existingValue instanceof Map) {
94 mergeStructures((Map<String, Object>) existingValue, (Map<String, Object>) yamlValue);
95 } else if (existingValue instanceof String) {
96 throw new IllegalArgumentException("Cannot mergeYamlFiles complex element into a simple element: " + key)
98 throw unknownValueType(key, yamlValue)
100 } else if (yamlValue instanceof List) {
101 mergeLists(targetTree, key, yamlValue)
103 } else if (yamlValue instanceof String
104 || yamlValue instanceof Boolean
105 || yamlValue instanceof Double
106 || yamlValue instanceof Integer) {
108 addToMergedResult(targetTree, key, yamlValue)
111 throw unknownValueType(key, yamlValue)
115 if (yamlValue instanceof Map
116 || yamlValue instanceof List
117 || yamlValue instanceof String
118 || yamlValue instanceof Boolean
119 || yamlValue instanceof Integer
120 || yamlValue instanceof Double) {
122 addToMergedResult(targetTree, key, yamlValue)
124 throw unknownValueType(key, yamlValue)