Как мне отформатировать строку со свойствами из бина - PullRequest
7 голосов
/ 18 июля 2011

Я хочу создать строку, используя формат, заменив некоторые токены в формате свойствами из компонента. Есть ли библиотека, которая поддерживает это, или мне придется создать собственную реализацию?

Позвольте мне привести пример. Скажи, у меня есть боб Person;

public class Person {
  private String id;
  private String name;
  private String age;

  //getters and setters
}

Я хочу иметь возможность указывать строки формата примерно так:

"{name} is {age} years old."
"Person id {id} is called {name}."

и автоматически заполняет заполнители формата значениями из bean-компонента, что-то вроде;

String format = "{name} is {age} old."
Person p = new Person(1, "Fred", "32 years");
String formatted = doFormat(format, person); //returns "Fred is 32 years old."

Я посмотрел на MessageFormat, но это только позволяет мне передавать числовые индексы, а не свойства бина.

Ответы [ 4 ]

3 голосов
/ 18 июля 2011

Прокатил сам, сейчас тестирую.Комментарии приветствуются.

import java.lang.reflect.Field;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BeanFormatter<E> {

  private Matcher matcher;
  private static final Pattern pattern = Pattern.compile("\\{(.+?)\\}");

  public BeanFormatter(String formatString) {
    this.matcher = pattern.matcher(formatString);
  }

  public String format(E bean) throws Exception {
    StringBuffer buffer = new StringBuffer();

    try {
      matcher.reset();
      while (matcher.find()) {
        String token = matcher.group(1);
        String value = getProperty(bean, token);
        matcher.appendReplacement(buffer, value);
      }
      matcher.appendTail(buffer);
    } catch (Exception ex) {
      throw new Exception("Error formatting bean " + bean.getClass() + " with format " + matcher.pattern().toString(), ex);
    }
    return buffer.toString();
  }

  private String getProperty(E bean, String token) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    Field field = bean.getClass().getDeclaredField(token);
    field.setAccessible(true);
    return String.valueOf(field.get(bean));
  }

  public static void main(String[] args) throws Exception {
    String format = "{name} is {age} old.";
    Person p = new Person("Fred", "32 years", 1);

    BeanFormatter<Person> bf = new BeanFormatter<Person>(format);
    String s = bf.format(p);
    System.out.println(s);
  }

}
1 голос
/ 18 июля 2011

Да, это возможно при использовании библиотеки Pojomatic .Реализуйте и подключите свою собственную реализацию PojoFormatter.Pojomator#doToString(T) тоже может быть интересно.

0 голосов
/ 18 июля 2011

Не совсем близко, но вы можете посмотреть на StringTemplate, ваш боб:

public static class User {
    public int id; // template can directly access via u.id
    private String name; // template can't access this
    public User(int id, String name) { this.id = id; this.name = name; }
    public boolean isManager() { return true; } // u.manager
    public boolean hasParkingSpot() { return true; } // u.parkingSpot
    public String getName() { return name; } // u.name
    public String toString() { return id+":"+name; } // u
}

Тогда вы можете сделать это так:

ST st = new ST("<b>$u.id$</b>: $u.name$", '$', '$');
st.add("u", new User(999, "parrt"));
String result = st.render(); // "<b>999</b>: parrt"

Пример кода выше взят из ST4 Введение

0 голосов
/ 18 июля 2011

Не знаю, насколько сложна модель, которую вы собираетесь использовать, но если вы хотите работать с деревьями объектов, я бы реализовал свой собственный модуль форматирования, используя Jexl в качестве языка выражений следующим образом:

  1. Инициализация одноэлементного движка Jexl
  2. Заполните MapContext всеми объектами, которые вы хотите использовать при форматировании строк
  3. Разбор ваших строк и создание выражения Jexl для каждой имеющейся у вас конструкции "$ {}".
  4. Оценить ранее созданные выражения по контекстной карте объекта.

В Jexl хорошо то, что он позволяет вам использовать вызовы методов, а не только свойства.

Надеюсь, это поможет.

...