PropsUtils { public static String getPropertyDiff(Props oldProps, Props newProps) { final StringBuilder builder = new StringBuilder(""); if (oldProps == null) { oldProps = new Props(); } if (newProps == null) { newProps = new Props(); } final MapDifference<String, String> md = Maps.difference(toStringMap(oldProps, false), toStringMap(newProps, false)); final Map<String, String> newlyCreatedProperty = md.entriesOnlyOnRight(); if (newlyCreatedProperty != null && newlyCreatedProperty.size() > 0) { builder.append("Newly created Properties: "); newlyCreatedProperty.forEach((k, v) -> { builder.append("[ " + k + ", " + v + "], "); }); builder.append("\n"); } final Map<String, String> deletedProperty = md.entriesOnlyOnLeft(); if (deletedProperty != null && deletedProperty.size() > 0) { builder.append("Deleted Properties: "); deletedProperty.forEach((k, v) -> { builder.append("[ " + k + ", " + v + "], "); }); builder.append("\n"); } final Map<String, MapDifference.ValueDifference<String>> diffProperties = md.entriesDiffering(); if (diffProperties != null && diffProperties.size() > 0) { builder.append("Modified Properties: "); diffProperties.forEach((k, v) -> { builder.append("[ " + k + ", " + v.leftValue() + "-->" + v.rightValue() + "], "); }); } return builder.toString(); } private  PropsUtils(); static Props loadPropsInDir(final File dir, final String... suffixes); static Props loadPropsInDir(final Props parent, final File dir, final String... suffixes); static Props loadProps(final Props parent, final File... propFiles); static Props loadPluginProps(final File pluginDir); static Props loadPropsInDirs(final List<File> dirs, final String... suffixes); static void loadPropsBySuffix(final File jobPath, final Props props,
      final String... suffixes); static boolean isVariableReplacementPattern(final String value); static Props resolveProps(final Props props); static Props newProps(final Props parentProps, final String filePath); static Props newProps(final Props parentProps, final File file); static String toJSONString(final Props props, final boolean localOnly); static Map<String, String> toStringMap(final Props props, final boolean localOnly); static Props fromJSONString(final String json); static Props fromHierarchicalMap(final Map<String, Object> propsMap); static Map<String, Object> toHierarchicalMap(final Props props); static String getPropertyDiff(Props oldProps, Props newProps);  }
@Test public void testGetPropertyDiff() throws IOException { final Props oldProps = new Props(); final Props newProps1 = new Props(); oldProps.put("a", "a_value1"); oldProps.put("b", "b_value1"); newProps1.put("b", "b_value2"); final String message1 = PropsUtils.getPropertyDiff(oldProps, newProps1); Assert.assertEquals(message1, "Deleted Properties: [ a, a_value1], \nModified Properties: [ b, b_value1-->b_value2], "); final Props newProps2 = new Props(); newProps2.put("a", "a_value1"); newProps2.put("b", "b_value1"); newProps2.put("c", "c_value1"); final String message2 = PropsUtils.getPropertyDiff(oldProps, newProps2); Assert.assertEquals(message2, "Newly created Properties: [ c, c_value1], \n"); final Props newProps3 = new Props(); newProps3.put("b", "b_value1"); newProps3.put("c", "a_value1"); final String message3 = PropsUtils.getPropertyDiff(oldProps, newProps3); Assert.assertEquals(message3, "Newly created Properties: [ c, a_value1], \nDeleted Properties: [ a, a_value1], \n"); }