github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/src/com/sap/piper/MapUtils.groovy (about) 1 package com.sap.piper 2 3 class MapUtils implements Serializable { 4 static boolean isMap(object){ 5 return object in Map 6 } 7 8 static Map pruneNulls(Map m) { 9 10 Map result = [:] 11 12 m = m ?: [:] 13 14 m.each { key, value -> 15 if(isMap(value)) 16 result[key] = pruneNulls(value) 17 else if(value != null) 18 result[key] = value 19 } 20 return result 21 } 22 23 /** 24 * Merge two maps with the second one has precedence 25 * @param base First map 26 * @param overlay Second map, takes precedence 27 * @return The merged map 28 */ 29 static Map merge(Map base, Map overlay) { 30 31 Map result = [:] 32 33 base = base ?: [:] 34 35 result.putAll(base) 36 37 overlay.each { key, value -> 38 result[key] = isMap(value) ? merge(base[key], value) : value 39 } 40 return result 41 } 42 43 /** 44 * @param m The map to which the changed denoted by closure <code>strategy</code> 45 * should be applied. 46 * The strategy is also applied to all sub-maps contained as values 47 * in <code>m</code> in a recursive manner. 48 * @param strategy Strategy applied to all non-map entries 49 */ 50 static void traverse(Map m, Closure strategy) { 51 52 def updates = [:] 53 m.each { key, value -> 54 if(isMap(value)) { 55 traverse(value, strategy) 56 } else { 57 // do not update the map while it is traversed. Depending 58 // on the map implementation the behavior is undefined. 59 updates.put(key, strategy(value)) 60 } 61 } 62 m.putAll(updates) 63 } 64 65 static private def getByPath(Map m, def key) { 66 List path = key in CharSequence ? key.tokenize('/') : key 67 68 def value = m.get(path.head()) 69 70 if (path.size() == 1) return value 71 if (value in Map) return getByPath(value, path.tail()) 72 73 return null 74 } 75 76 /* 77 * Provides a new map with the same content like the original map. 78 * Nested Collections and Maps are copied. Values with are not 79 * Collections/Maps are not copied/cloned. 80 * <paranoia>&/ltThe keys are also not copied/cloned, even if they are 81 * Maps or Collections;paranoia> 82 */ 83 static deepCopy(Map original) { 84 Map copy = [:] 85 for (def e : original.entrySet()) { 86 if(e.value == null) { 87 copy.put(e.key, e.value) 88 } else { 89 copy.put(e.key, deepCopy(e.value)) 90 } 91 } 92 copy 93 } 94 95 /* private */ static deepCopy(Set original) { 96 Set copy = [] 97 for(def e : original) 98 copy << deepCopy(e) 99 copy 100 } 101 102 /* private */ static deepCopy(List original) { 103 List copy = [] 104 for(def e : original) 105 copy << deepCopy(e) 106 copy 107 } 108 109 /* 110 * In fact not a copy, but a catch all for everything not matching 111 * with the other signatures 112 */ 113 /* private */ static deepCopy(def original) { 114 original 115 } 116 }