/** * Depth-first search on the dependency graph. The correctness of this algorithm follows from the * invariant that a function is only added to the output after all its dependencies have been * added. * * @param n name of the function to be visited * @param refs adjacency map * @param marked already visited nodes * @param stack stack of current nodes * @param out output list * @param equiv equivalence classes */ private void visit( final Name n, final Map<Name, Set<Name>> refs, final Set<Name> marked, final Stack<Name> stack, final List<Name> out, final Map<Name, Set<Name>> equiv) { if (marked.add(n)) { // name wasn't marked stack.push(n); for (final Name name : refs.get(n)) { visit(name, refs, marked, stack, out, equiv); } out.add(stack.pop()); } else { final int pos = stack.lastIndexOf(n); if (pos >= 0) { final Set<Name> eqClass = new HashSet<Name>(); for (final Name eq : stack.subList(pos, stack.size())) { eqClass.add(eq); final Set<Name> old = equiv.get(eq); if (old != null) { eqClass.addAll(old); } } for (final Name nm : eqClass) { equiv.put(nm, eqClass); } } } }
public String expand(String str, Stack<String> seenStack) { if (str == null) { return str; } if (str.indexOf("${") < 0) { // Contains no potential expressions. return str; } Matcher mat = __propertyPattern.matcher(str); StringBuilder expanded = new StringBuilder(); int offset = 0; String property; String value; while (mat.find(offset)) { property = mat.group(1); // Loop detection if (seenStack.contains(property)) { StringBuilder err = new StringBuilder(); err.append("Property expansion loop detected: "); int idx = seenStack.lastIndexOf(property); for (int i = idx; i < seenStack.size(); i++) { err.append(seenStack.get(i)); err.append(" -> "); } err.append(property); throw new RuntimeException(err.toString()); } seenStack.push(property); // find property name expanded.append(str.subSequence(offset, mat.start())); // get property value value = getString(property); if (value == null) { if (LOG.isDebugEnabled()) LOG.debug("Unable to expand: {}", property); expanded.append(mat.group()); } else { // recursively expand value = expand(value, seenStack); expanded.append(value); } // update offset offset = mat.end(); } // leftover expanded.append(str.substring(offset)); // special case for "$$" if (expanded.indexOf("$$") >= 0) { return expanded.toString().replaceAll("\\$\\$", "\\$"); } return expanded.toString(); }