ConfigNode impl that applies property substitutions on access. This class wraps another ConfigNode and applies property substitution immediately when the #txt or #attributes methods are called. Because property substition is based on ThreadLocal values, These methods
| 39 | * @see PropertiesUtil#substitute |
| 40 | */ |
| 41 | public class DataConfigNode implements ConfigNode { |
| 42 | private final String name; |
| 43 | private final Map<String, String> rawAttributes; |
| 44 | private final Map<String, List<ConfigNode>> kids; |
| 45 | private final String rawTextData; |
| 46 | |
| 47 | public DataConfigNode(ConfigNode root) { |
| 48 | Map<String, List<ConfigNode>> kids = new LinkedHashMap<>(); |
| 49 | name = root.name(); |
| 50 | rawAttributes = root.attributes(); |
| 51 | rawTextData = root.txt(); |
| 52 | root.forEachChild( |
| 53 | it -> { |
| 54 | List<ConfigNode> nodes = kids.computeIfAbsent(it.name(), k -> new ArrayList<>()); |
| 55 | nodes.add(new DataConfigNode(it)); |
| 56 | return Boolean.TRUE; |
| 57 | }); |
| 58 | for (Map.Entry<String, List<ConfigNode>> e : kids.entrySet()) { |
| 59 | if (e.getValue() != null) { |
| 60 | e.setValue(List.copyOf(e.getValue())); |
| 61 | } |
| 62 | } |
| 63 | this.kids = Map.copyOf(kids); |
| 64 | } |
| 65 | |
| 66 | private static String substituteVal(String s) { |
| 67 | return PropertiesUtil.substitute(s, SUBSTITUTES.get()); |
| 68 | } |
| 69 | |
| 70 | @Override |
| 71 | public String name() { |
| 72 | return name; |
| 73 | } |
| 74 | |
| 75 | /** Each call to this method returns a (new) copy of the original txt with substitions applied. */ |
| 76 | @Override |
| 77 | public String txt() { |
| 78 | return substituteVal(rawTextData); |
| 79 | } |
| 80 | |
| 81 | /** |
| 82 | * Each call to this method returns a (new) copy of the original Map with substitions applied to |
| 83 | * the values. |
| 84 | */ |
| 85 | @Override |
| 86 | public Map<String, String> attributes() { |
| 87 | if (rawAttributes.isEmpty()) return rawAttributes; // avoid unnecessary object creation |
| 88 | |
| 89 | // Note: using the 4 arg toMap to force LinkedHashMap. |
| 90 | // Duplicate keys should be impossible, but toMap makes us specify a mergeFunction |
| 91 | return rawAttributes.entrySet().stream() |
| 92 | .collect( |
| 93 | Collectors.toMap( |
| 94 | Map.Entry::getKey, |
| 95 | e -> { |
| 96 | return substituteVal(e.getValue()); |
| 97 | }, |
| 98 | (v, vv) -> { |
nothing calls this directly
no outgoing calls
no test coverage detected
searching dependent graphs…