Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public class ResourceUtils {
- // example: ${date:DD.MM}
- private static final Pattern DATE_TIME_PLACEHOLDER_PATTERN =
- Pattern.compile("\\$\\{(?<value>date:[\\w.:\\-\\s/\\\\]+)}");
- // examples: ${number:N}
- private static final Pattern NUMBER_PLACEHOLDER_PATTERN =
- Pattern.compile("\\$\\{(?<value>number:[\\w.:\\-\\s/\\\\?]+)}");
- private static final Map<String, Formatter> FORMATTERS = Stream.of(
- new AbstractMap.SimpleEntry<>("date:DD.MM", new DateTimeFormatter("dd.MM")),
- new AbstractMap.SimpleEntry<>("date:DD.MM.YYYY", new DateTimeFormatter("dd.MM.yyyy")),
- new AbstractMap.SimpleEntry<>("date:DD.MM.YYYY HH:MM", new DateTimeFormatter("dd.MM.yyyy HH:mm")),
- new AbstractMap.SimpleEntry<>("number:N", new NumberFormatter("0")),
- new AbstractMap.SimpleEntry<>("number:N.00", new NumberFormatter("0.00")),
- new AbstractMap.SimpleEntry<>("number:N.??", new NumberFormatter("0.##"))
- ).collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
- private static final Formatter NULL_FORMATTER = arg -> "null";
- public static String formatString(String str, Object[] args) {
- if (StringUtils.isEmpty(str)) {
- return str;
- }
- List<Operation> operations = new ArrayList<>();
- collectOperations(operations, DATE_TIME_PLACEHOLDER_PATTERN, str);
- collectOperations(operations, NUMBER_PLACEHOLDER_PATTERN, str);
- if (operations.isEmpty()) {
- return str;
- } else if (operations.size() != args.length) {
- throw new IllegalArgumentException(String.format(
- "Arguments count [%d] doesn't matches to placeholders count [%d]",
- args.length, operations.size()));
- }
- operations.sort(Comparator.comparing(Operation::getRangeStart));
- StringBuilder sb = new StringBuilder();
- Operation lastOperation = null;
- for (int i = 0; i < operations.size(); i++) {
- Operation operation = operations.get(i);
- Object arg = args[i];
- Formatter formatter = arg == null ? NULL_FORMATTER : FORMATTERS.get(operation.getPattern());
- if (formatter == null) {
- throw new IllegalArgumentException(String.format(
- "Unable to find appropriate formatter for pattern [%s]", operation.getPattern()));
- }
- String formattedValue;
- try {
- formattedValue = formatter.format(arg);
- } catch (RuntimeException e) {
- throw new IllegalArgumentException(String.format("Unable to format arg [%s] using pattern [%s]",
- arg, operation.getPattern()), e);
- }
- int startIndex = lastOperation == null ? 0 : lastOperation.getRangeEnd() + 1;
- if (operation.getRangeStart() > startIndex) {
- sb.append(str.substring(startIndex, operation.getRangeStart()));
- }
- sb.append(formattedValue);
- lastOperation = operation;
- }
- if (lastOperation != null && lastOperation.getRangeEnd() < str.length() - 1) {
- sb.append(str.substring(lastOperation.getRangeEnd() + 1, str.length()));
- }
- return sb.toString();
- }
- private static void collectOperations(List<Operation> operations, Pattern pattern, String str) {
- Matcher matcher = pattern.matcher(str);
- while (matcher.find()) {
- operations.add(new Operation(matcher.start(), matcher.end() - 1, matcher.group("value")));
- }
- }
- private interface Formatter {
- String format(Object arg);
- }
- private static class DateTimeFormatter implements Formatter {
- private final java.time.format.DateTimeFormatter dateTimeFormatter;
- public DateTimeFormatter(String pattern) {
- this.dateTimeFormatter = java.time.format.DateTimeFormatter.ofPattern(pattern);
- }
- @Override
- public String format(Object arg) {
- if (!(arg instanceof TemporalAccessor)) {
- throw new IllegalArgumentException(
- String.format("Argument [%s] can not be formatted as date-time value", arg));
- }
- return dateTimeFormatter.format((TemporalAccessor) arg);
- }
- }
- private static class NumberFormatter implements Formatter {
- private final DecimalFormat decimalFormat;
- public NumberFormatter(String pattern) {
- DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance();
- dfs.setDecimalSeparator('.');
- decimalFormat = new DecimalFormat(pattern);
- decimalFormat.setDecimalFormatSymbols(dfs);
- }
- @Override
- public synchronized String format(Object arg) {
- return decimalFormat.format(arg);
- }
- }
- private static class Operation {
- private final int rangeStart;
- private final int rangeEnd;
- private final String pattern;
- public Operation(int rangeStart, int rangeEnd, String pattern) {
- this.rangeStart = rangeStart;
- this.rangeEnd = rangeEnd;
- this.pattern = pattern;
- }
- public int getRangeStart() {
- return rangeStart;
- }
- public int getRangeEnd() {
- return rangeEnd;
- }
- public String getPattern() {
- return pattern;
- }
- }
- }
Add Comment
Please, Sign In to add comment