PropsUtils { public static Props resolveProps(final Props props) { if (props == null) { return null; } final Props resolvedProps = new Props(); final LinkedHashSet<String> visitedVariables = new LinkedHashSet<>(); for (final String key : props.getKeySet()) { String value = props.get(key); if (value == null) { LOGGER.warn("Null value in props for key '" + key + "'. Replacing with empty string."); value = ""; } visitedVariables.add(key); final String replacedValue = resolveVariableReplacement(value, props, visitedVariables); visitedVariables.clear(); resolvedProps.put(key, replacedValue); } for (final String key : resolvedProps.getKeySet()) { final String value = resolvedProps.get(key); final String expressedValue = resolveVariableExpression(value); resolvedProps.put(key, expressedValue); } return resolvedProps; } 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 testGoodResolveProps() throws IOException { final Props propsGrandParent = new Props(); final Props propsParent = new Props(propsGrandParent); final Props props = new Props(propsParent); props.put("letter", "a"); propsParent.put("letter", "b"); propsGrandParent.put("letter", "c"); Assert.assertEquals("a", props.get("letter")); propsParent.put("my", "name"); propsParent.put("your", "eyes"); propsGrandParent.put("their", "ears"); propsGrandParent.put("your", "hair"); Assert.assertEquals("name", props.get("my")); Assert.assertEquals("eyes", props.get("your")); Assert.assertEquals("ears", props.get("their")); props.put("res1", "${my}"); props.put("res2", "${their} ${letter}"); props.put("res7", "${my} ${res5}"); propsParent.put("res3", "${your} ${their} ${res4}"); propsGrandParent.put("res4", "${letter}"); propsGrandParent.put("res5", "${their}"); propsParent.put("res6", " t ${your} ${your} ${their} ${res5}"); final Props resolved = PropsUtils.resolveProps(props); Assert.assertEquals("name", resolved.get("res1")); Assert.assertEquals("ears a", resolved.get("res2")); Assert.assertEquals("eyes ears a", resolved.get("res3")); Assert.assertEquals("a", resolved.get("res4")); Assert.assertEquals("ears", resolved.get("res5")); Assert.assertEquals(" t eyes eyes ears ears", resolved.get("res6")); Assert.assertEquals("name ears", resolved.get("res7")); }
@Test public void testInvalidSyntax() throws Exception { final Props propsGrandParent = new Props(); final Props propsParent = new Props(propsGrandParent); final Props props = new Props(propsParent); propsParent.put("my", "name"); props.put("res1", "$(my)"); final Props resolved = PropsUtils.resolveProps(props); Assert.assertEquals("$(my)", resolved.get("res1")); }
@Test public void testExpressionResolution() throws IOException { final Props props = Props.of("normkey", "normal", "num1", "1", "num2", "2", "num3", "3", "variablereplaced", "${num1}", "expression1", "$(1+10)", "expression2", "$(1+10)*2", "expression3", "$($(${num1} + ${num3})*10)", "expression4", "$(${num1} + ${expression3})", "expression5", "$($($(2+3)) + 3) + $(${expression3} + 1)", "expression6", "$(1 + ${normkey})", "expression7", "$(\"${normkey}\" + 1)", "expression8", "${expression1}", "expression9", "$((2+3) + 3)"); final Props resolved = PropsUtils.resolveProps(props); Assert.assertEquals("normal", resolved.get("normkey")); Assert.assertEquals("1", resolved.get("num1")); Assert.assertEquals("2", resolved.get("num2")); Assert.assertEquals("3", resolved.get("num3")); Assert.assertEquals("1", resolved.get("variablereplaced")); Assert.assertEquals("11", resolved.get("expression1")); Assert.assertEquals("11*2", resolved.get("expression2")); Assert.assertEquals("40", resolved.get("expression3")); Assert.assertEquals("41", resolved.get("expression4")); Assert.assertEquals("8 + 41", resolved.get("expression5")); Assert.assertEquals("1", resolved.get("expression6")); Assert.assertEquals("normal1", resolved.get("expression7")); Assert.assertEquals("11", resolved.get("expression8")); Assert.assertEquals("8", resolved.get("expression9")); }