Форматирование строки в Java с использованием атрибутов класса - PullRequest
4 голосов
/ 31 марта 2010

У меня есть класс с атрибутом и методом получения:

public Class MyClass
{
  private String myValue = "foo";

  public String getMyValue();
}

Я хотел бы иметь возможность использовать значение foo в форматированной строке следующим образом:

String someString = "Your value is {myValue}."
String result = Formatter.format(someString, new MyClass());
// result is now "Your value is foo."

То есть я хотел бы иметь некоторую функцию, подобную .format выше, которая принимает строку формата, указывающую свойства для некоторого объекта, и экземпляр с этими свойствами и соответствующим образом форматирует строку.

Возможно ли совершить этот подвиг в Java?

Ответы [ 4 ]

3 голосов
/ 31 марта 2010

вы могли бы использовать JUEL для этого. это реализация языка выражений Java. код довольно компактен и выглядит так:

ExpressionFactory factory = new ExpressionFactoryImpl();

// create a context and add a Person object to the context, this variable will be used
// in the property replacement
// objects of type Person have two fields: firstName and lastName

SimpleContext context = new SimpleContext();
Person person = new Person("John", "Doe");
context.setVariable("person", factory.createValueExpression(person, Person.class));

// create the expression

String expr = "My name is ${person.firstName} ${person.lastName}";
ValueExpression e = factory.createValueExpression(context, expr, String.class);

// evaluate the expression
System.out.println(e.getValue(context));

с надписью «Меня зовут Джон Доу»

обратите внимание, что также возможно использовать выражение вроде этого: '$ {firstName}' вместо '$ {person.firstName}', но тогда вам придется написать и предоставить собственный преобразователь (javax.el.ELResolver). ) для разрешения переменной и свойства

2 голосов
/ 31 марта 2010

(Мой другой ответ, вероятно, будет полезен, только если вы уже используете распорки.)

Как и в ответе sdb, есть apache JEXL .

Класс UnifiedJEXL обеспечивает функциональность, подобную шаблону, поэтому вы можете написать (, как показано в javadocs ):

JexlEngine jexl = new JexlEngine();
UnifiedJEXL ujexl = new UnifiedJEXL(jexl);
UnifiedJEXL.Expression expr = ujexl.parse("Hello ${user}");
String hello = expr.evaluate(context, expr).toString();

(expr не только выглядит странно, когда передается в качестве параметра самому методу, но на самом деле не требуется в качестве параметра)

Настройка контекста показана ранее на этой же странице:

// Create a context and add data
JexlContext jc = new MapContext();
jc.set("foo", new Foo() );

Вам также понадобится либо регистрация в общем-то, либо вы можете настроить JEXL для использования собственного регистратора.


Чтобы приблизиться к тому, что вы просили, вы можете создать:

public class Formatter {
    public static String format(String format, Object ... inputs) {
        JexlContext context = new MapContext();
        for (int i=0;i<inputs.length;i++) {
            context.set("_" + (i+1), inputs[i] );
        }
        JexlEngine jexl = new JexlEngine();
        UnifiedJEXL ujexl = new UnifiedJEXL(jexl);
        UnifiedJEXL.Expression expr = ujexl.parse(format);
        return expr.evaluate(context).toString();
    }
}

и позвоните по номеру

String someString = "Your value is ${_1.myValue}.";
String result = Formatter.format(someString, new MyClass());

В этот момент result равно "Your value is foo."

0 голосов
/ 31 марта 2010

Вы можете создать его с помощью struts2 / xwork / OGNL, как показано ниже (скопировано из письма от Влада )

public static String translateOgnl(String message, Map<Object, Object> args) {
    OgnlValueStack stack = new OgnlValueStack();
    stack.push(args);
    return TextParseUtil.translateVariables(message, stack);
}

Javadocs для TextParseUtil.translateVariables() скажем

Преобразует все экземпляры $ {...} в выражении в значение, возвращаемое при вызове ValueStack.findValue(java.lang.String). Если элемент не может быть найден в стеке (возвращается ноль), тогда вся переменная $ {...} не отображается, как если бы элемент находился в стеке, но возвратил пустую строку.

0 голосов
/ 31 марта 2010

Теоретически возможно с помощью синтаксического анализатора на основе стека определять держатели значений в строке в сочетании с отражением (или, лучше, API проверки Javabean, таким как Commons BeanUtils )получите значения свойств bean-компонента.

К сожалению, ни готовый, ни сторонний API не приходит на ум, если вы ищете это.Однако это интересный вопрос.

...