As NilsH zasugerował MessageFormat jest naprawdę miły dla tego celu. Aby mieć nazwach zmiennych można ukryć MessageFormat za swojej klasie:
public class FormattedStrSubstitutor {
public static String formatReplace(Object source, Map<String, String> valueMap) {
for (Map.Entry<String, String> entry : valueMap.entrySet()) {
String val = entry.getValue();
if (isPlaceholder(val)) {
val = getPlaceholderValue(val);
String newValue = reformat(val);
entry.setValue(newValue);
}
}
return new StrSubstitutor(valueMap).replace(source);
}
private static boolean isPlaceholder(String isPlaceholder) {
return isPlaceholder.startsWith("${");
}
private static String getPlaceholderValue(String val) {
return val.substring(2, val.length()-1);
}
private static String reformat(String format) {
String result = MessageFormat.format("{0,date," + format + "}", new Date());
return result;
}
}
I trzeba dostosować testcase:
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
String template = ".../uploads/${customer}/${dateTime}/report.pdf";
@Test
public void shouldResolvePlaceholder() {
final Map<String, String> model = new HashMap<String, String>();
model.put("customer", "Mr. Foobar");
model.put("dateTime", "${yyyyMMdd}");
final String filledTemplate = FormattedStrSubstitutor.formatReplace(this.template,
model);
assertEquals(".../uploads/Mr. Foobar/" + this.formatter.format(new Date())
+ "/report.pdf", filledTemplate);
}
usunąłem rodzajowych i zastąpienia tych sznurkiem. Również isPlaceholder
i getPlaceholderValue
jest zakodowany na sztywno i oczekuje się składni $ {wartość}.
Ale to tylko pomysł rozwiązania problemu. Aby to zrobić, można użyć metod z StrSubstitutor
(wystarczy użyć lub utworzyć FormattedStrSubstitutor extends StrSubstitutor
).
Również można użyć na przykład $ d {wartość} do formatowania dat i $ foo {value} formatowania foo.
UPDATE
nie można spać bez pełnego rozwiązania. Możesz dodać tę metodę do FormattedStrSubstitutor
Klasa:
public static String replace(Object source,
Map<String, String> valueMap) {
String staticResolved = new StrSubstitutor(valueMap).replace(source);
Pattern p = Pattern.compile("(\\$\\{date)(.*?)(\\})");
Matcher m = p.matcher(staticResolved);
String dynamicResolved = staticResolved;
while (m.find()) {
String result = MessageFormat.format("{0,date" + m.group(2) + "}",
new Date());
dynamicResolved = dynamicResolved.replace(m.group(), result);
}
return dynamicResolved;
}
Twój testcase jest jak w swoim pytaniu (małe zmiany zastępczy):
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
String template = ".../uploads/${customer}/${date,yyyyMMdd}/report.pdf";
@Test
public void shouldResolvePlaceholder() {
final Map<String, String> model = new HashMap<String, String>();
model.put("customer", "Mr. Foobar");
final String filledTemplate = FormattedStrSubstitutor.replace(this.template,
model);
assertEquals(
".../uploads/Mr. Foobar/" + this.formatter.format(new Date())
+ "/report.pdf", filledTemplate);
}
samo ograniczenie jak poprzednio; bez generics i fix prefiks i sufiks dla placeholder.
czy ta część zawsze jest ostatnim folderem w strukturze katalogów? –
Nie, w niektórych innych raportach jest pośrodku. Lub w nazwie pliku. To tylko przykład. – d0x