### Question:
PlaceholderHelper { public Set<String> extractPlaceholderKeys(String propertyString) { Set<String> placeholderKeys = Sets.newHashSet(); if (!isNormalizedPlaceholder(propertyString) && !isExpressionWithPlaceholder(propertyString)) { return placeholderKeys; } Stack<String> stack = new Stack<>(); stack.push(propertyString); while (!stack.isEmpty()) { String strVal = stack.pop(); int startIndex = strVal.indexOf(PLACEHOLDER_PREFIX); if (startIndex == -1) { placeholderKeys.add(strVal); continue; } int endIndex = findPlaceholderEndIndex(strVal, startIndex); if (endIndex == -1) { continue; } String placeholderCandidate = strVal.substring(startIndex + PLACEHOLDER_PREFIX.length(), endIndex); if (placeholderCandidate.startsWith(PLACEHOLDER_PREFIX)) { stack.push(placeholderCandidate); } else { int separatorIndex = placeholderCandidate.indexOf(VALUE_SEPARATOR); if (separatorIndex == -1) { stack.push(placeholderCandidate); } else { stack.push(placeholderCandidate.substring(0, separatorIndex)); String defaultValuePart = normalizeToPlaceholder(placeholderCandidate.substring(separatorIndex + VALUE_SEPARATOR.length())); if (!Strings.isNullOrEmpty(defaultValuePart)) { stack.push(defaultValuePart); } } } if (endIndex + PLACEHOLDER_SUFFIX.length() < strVal.length() - 1) { String remainingPart = normalizeToPlaceholder(strVal.substring(endIndex + PLACEHOLDER_SUFFIX.length())); if (!Strings.isNullOrEmpty(remainingPart)) { stack.push(remainingPart); } } } return placeholderKeys; }  Object resolvePropertyValue(ConfigurableBeanFactory beanFactory, String beanName, String placeholder); Set<String> extractPlaceholderKeys(String propertyString);  }### Answer:
@Test public void testExtractPlaceholderKeys() throws Exception { check("${some.key}", "some.key"); check("${some.key:100}", "some.key"); check("${some.key:${some.other.key}}", "some.key", "some.other.key"); check("${some.key:${some.other.key:100}}", "some.key", "some.other.key"); }
@Test public void testExtractPlaceholderKeysFromExpression() throws Exception { check("#{new java.text.SimpleDateFormat('${some.key}').parse('${another.key}')}", "some.key", "another.key"); check("#{new java.text.SimpleDateFormat('${some.key:abc}').parse('${another.key:100}')}", "some.key", "another.key"); check("#{new java.text.SimpleDateFormat('${some.key:${some.other.key}}').parse('${another.key}')}", "some.key", "another.key", "some.other.key"); check("#{new java.text.SimpleDateFormat('${some.key:${some.other.key:abc}}').parse('${another.key}')}", "some.key", "another.key", "some.other.key"); check("#{new java.text.SimpleDateFormat('${${some.key}}').parse('${${another.key:other.key}}')}", "some.key", "another.key"); assertTrue(placeholderHelper.extractPlaceholderKeys("#{systemProperties[some.key] ?: 123}").isEmpty()); assertTrue(placeholderHelper.extractPlaceholderKeys("#{ T(java.lang.Math).random() * 100.0 }").isEmpty()); }
@Test public void testExtractInvalidPlaceholderKeys() throws Exception { assertTrue(placeholderHelper.extractPlaceholderKeys("some.key").isEmpty()); assertTrue(placeholderHelper.extractPlaceholderKeys("some.key:100").isEmpty()); }