### Question:
TaskCallEventRecordingListener implements TaskCallListener { static Map<String, Object> maskVars(Map<String, Object> vars, Collection<String> blackList) { if (blackList.isEmpty()) { return vars; } Map<String, Object> result = new HashMap<>(vars); for (String b : blackList) { String[] path = b.split("\\."); if (ConfigurationUtils.has(result, path)) { Map<String, Object> m = ensureModifiable(result, path.length - 1, path); m.put(path[path.length - 1], "***"); } } return result; } @Inject  TaskCallEventRecordingListener(ApiClient apiClient, InstanceId processInstanceId, ProcessConfiguration processConfiguration); @Override void onEvent(TaskCallEvent event);  }### Answer:
@Test public void testMaskVars() throws Exception { String in = "{" + " \"a\":1," + " \"b\":2," + " \"c\":{" + " \"c1\":3," + " \"c2\":4," + " \"c3\":{" + " \"c31\":5," + " \"c32\":6" + " }" + " }" + "}"; List<String> blackList = Arrays.asList("b", "c.c1", "c.c3.c31"); Map<String, Object> result = TaskCallEventRecordingListener.maskVars(vars(in), blackList); String expected = "{" + " \"a\":1," + " \"b\":\"***\"," + " \"c\":{" + " \"c1\":\"***\"," + " \"c2\":4," + " \"c3\":{" + " \"c31\":\"***\"," + " \"c32\":6" + " }" + " }" + "}"; assertEquals(vars(expected), result); }
@Test public void testMaskVarsUnmodifiable() throws Exception { Map<String, Object> vars = Collections.singletonMap("x", Collections.singletonMap("y", Collections.singletonMap("z", 123))); List<String> blackList = Collections.singletonList("x.y.z"); Map<String, Object> result = TaskCallEventRecordingListener.maskVars(vars, blackList); assertEquals("{x={y={z=***}}}", result.toString()); }