Статьи

StringTemplate, часть 3: сложные типы данных и средства визуализации

В части 1 и части 2 мы рассмотрели простые типы данных, чье строковое представление хорошо известно. Сложные типы данных могут не иметь строкового представления, которое соответствует потребностям конкретного шаблона.

// Example 1: Some objects don't have a useful toString()

Object objectParamater = new Object();

StringTemplate template = new StringTemplate("Hello $param$ !");

template.setAttribute("param", objectParamater);

System.out.println(template);

Выход:

Hello java.lang.Object@18eb9e6 !

Ваш вывод будет очень, но я думаю, можно с уверенностью сказать, что в большинстве случаев этот вывод нежелателен. Вот еще один пример правильного toString (), который просто не подходит для наших целей.

//Example 2: Even a well intentioned toString() methods may not be useful.

Planet mars = createMars();
template = new StringTemplate("Hello $param$ !");
template.setAttribute("param", mars);

System.out.println("Example 2:");
System.out.println(template);

Выход:

Example 2:

Hello Planet [atmosphere=CO2 N2, diameter=0.532, inclinationToSunsEquator=5.65, mass=0.11,
moons=[Phobos, Deimos], name=Mars, orbitalEccentricity=0.093, orbitalPeriod=1.88,
orbitalRadius=1.52, rings=false, rotationPeriod=1.03] !

Для объекта, который следует спецификации JavaBean (методы получения и установки), StringTemplate обеспечивает доступ к свойству через «.» нотации. Это позволяет вам получить доступ к свойствам из вашего шаблона.

//Example 3: Dot notation for property access

template = new StringTemplate("Hello $planet.name$ !");
template.setAttribute("planet", createMars());

System.out.println("Example 3:");
System.out.println(template);

Выход:

Example 3:

Hello Mars !

Теперь мы куда-то добираемся. Оператор planet.name был переведен StringTemplate в вызов getName (). Объект, который мы вставили в шаблон, имеет имя «Mars», поэтому наш результат стал «Hello Mars!». Если мы возьмем то, что мы узнали о коллекциях (многозначных атрибутах) из Части 2, и применим это к коллекции bean-компонентов, мы можем создать более мощные шаблоны.

/**
* Template to convert a collection of planets into a CSV file.
*/
toCSV(planets) ::= <<
Example 4:
Planet Listing
Name,Mass,Diameter,Orbital Period,Orbital Radius,Orbital Eccentricity,
Rotation Period,Inclination To Suns Equator,Rings,Atmosphere,

$planets:planetToCSVRow()$
>>

/**
* Creates a single row of comma separated values
*/
planetToCSVRow(planet) ::= <<

$planet.name$,$planet.mass$,$planet.diameter$,$planet.orbitalPeriod$,$planet.orbitalRadius$,
$planet.orbitalEccentricity$,$planet.rotationPeriod$,$planet.inclinationToSunsEquator$,$planet.rings$,
$planet.atmosphere$

>>

Это создает данные CSV с заголовком и именованными столбцами. Я думаю, что важно отметить, что мы поместили данные в этот шаблон так же, как всегда.

template.setAttribute("planets",createPlanets());

Мы переместили сложность с кода Java на шаблон, где мы можем справиться с ним более эффективно. Вот вывод из примера 4.

Example 4:
Planet Listing

Name,Mass,Diameter,Orbital Period,Orbital Radius,Orbital Eccentricity,Rotation Period,Inclination To Suns Equator,Rings,Atmosphere,
Mercury,0.06,0.382,0.24,0.39,0.206,58.64,3.38,false,Minimal
Venus,0.82,0.949,0.62,0.72,0.0070,-243.02,3.86,false,CO2 N2
Jupiter,317.8,11.209,11.86,5.2,0.048,0.41,6.09,true,H2 HE
Saturn,95.2,9.449,29.46,9.54,0.054,0.43,5.51,true,H2 HE
Neptune,17.2,3.883,164.8,30.06,0.0090,0.67,6.43,true,H2 HE
Earth,1.0,1.0,1.0,1.0,0.017,1.0,7.25,false,N2 O2
Mars,0.11,0.532,1.88,1.52,0.093,1.03,5.65,false,CO2 N2

Здесь у нас есть хороший выход CSV. Когда столбец добавляется или удаляется, все, что нам нужно сделать, внести соответствующие изменения в шаблон. Исходный код не нужно менять. Статическая информация верхнего или нижнего колонтитула может быть добавлена ​​без влияния на код Java.

Все планетные данные были взяты с: http://en.wikipedia.org/wiki/Planet

Renderers:

Во всех наших предыдущих примерах мы могли бы в какой-то момент получить адекватное строковое представление наших данных, не перебирая слишком много. Это не всегда будет так. В качестве примера того, как справиться с этим, я буду использовать тип данных, печально известный тем, что он требует особого внимания, java.util.Date. Давайте начнем со следующего кода Java.

// Example 5: Unformatted Date
template = new StringTemplate("The current date is: $now$ !");
template.setAttribute("now", new Date());

System.out.println("Example 5:");
System.out.println(template);<span style="text-decoration: none;"> </span>

Выход:

Example 5:
The current time is: Fri Jun 04 08:01:48 CDT 2010 !

 

Хотя это точно сообщает о текущем времени, оно может быть не в форме, знакомой вашим пользователям. В этом случае нет свойства, которое мы могли бы использовать в качестве предпочтительного отображаемого значения. StringTemplate предоставляет систему для перехвата объекта до его превращения в строку. Это называется «Renderer».

Вот скелет простого рендерера. AttributeRenderer есть второй метод, но пока давайте его игнорируем.)

public class DateRenderer implements AttributeRenderer {

@Override
public String toString(Object attribute) {
return null;
}
}

Исходный атрибут передается в качестве параметра методу toString (). Возвращаемое значение из метода toString () становится новым значением, помещенным в шаблон. Для дат мы можем использовать класс SimpleDateFormat ( http://java.sun.com/javase/6/docs/api/java/text/SimpleDateFormat.html ) для фактического форматирования.

public class StaticDateRenderer implements AttributeRenderer{

private SimpleDateFormat format;

public StaticDateRenderer(String pattern){
format = new SimpleDateFormat(pattern);
}

@Override
public String toString(Object attribute) {
return format.format((Date) attribute);
}
...
}

Как вы можете видеть, мы просто делегируем экземпляр SimpleDateFormat. Приведение к дате всегда безопасно, потому что мы регистрируем визуализированный литералом класса.

template.registerRenderer(Date.class,new StaticDateRenderer("h:m:ss a"));

Когда мы добавим вышеприведенную строку в наш предыдущий пример, мы увидим, что дата теперь появляется в более знакомой форме.

Example 5: Using a Date Renderer

The current time is: 7:51:08 AM !

Рендеры указаны для каждого класса. Это означает, что если бы в приведенном выше примере было две даты, они оба использовали бы формат «h: m: ss a». Это было бы нежелательно, если бы, например, у нас было два столбца в таблице, один был датой, а другой — временем. К счастью, AttributeRenderer предоставляет второй метод, который поможет справиться с этим.

public String toString(Object attribute, String format)

Этот метод принимает атрибут для визуализации и параметр формата. Этот параметр формата передается из шаблона в рендер.

$now; format="SHORT"$

В этом случае методу toString передается значение SHORT. Это зависит от рендера, чтобы решить, что делать с каким-либо конкретным параметром. DynamicDateRenderer — пример рендера, который использует параметр форматирования для выполнения форматирования определенной даты. Он поддерживает стили форматирования из DateFormat и синтаксис шаблона SimpleDateFormat.

Example 6: Formatting Dates

DateFromat Styles:

DEFAULT $now$
SHORT $now; format="SHORT"$
MEDIUM $now; format="MEDIUM"$
LONG $now; format="LONG"$
FULL $now; format="FULL"$

Using SimpleDateFormat Patterns:

yyyy.MM.dd G 'at' HH:mm:ss z $now; format="yyyy.MM.dd G 'at' HH:mm:ss z"$
EEE, MMM d, ''yy $now; format="EEE, MMM d, ''yy"$
h:mm a $now; format="h:mm a"$
hh 'o''clock' a, zzzz $now; format="hh 'o''clock' a, zzzz"$
K:mm a, z $now; format="K:mm a, z"$
yyyyy.MMMMM.dd GGG hh:mm aaa $now; format="yyyyy.MMMMM.dd GGG hh:mm aaa"$
EEE, d MMM yyyy HH:mm:ss Z $now; format="EEE, d MMM yyyy HH:mm:ss Z"$
yyMMddHHmmssZ $now; format="yyMMddHHmmssZ"$
yyyy-MM-dd'T'HH:mm:ss.SSSZ $now; format="yyyy-MM-dd'T'HH:mm:ss.SSSZ"$
dd.MM.yy $now; format="dd.MM.yy"$
h:mm a $now; format="h:mm a"$
H:mm $now; format="H:mm"$
H:mm:ss:SSS $now; format="H:mm:ss:SSS"$

(Синтаксис hilighter испытывает проблемы с интервалом в этом блоке. Пожалуйста, нажмите «просмотреть исходный код», чтобы увидеть реальный шаблон.)

Шаблон использует одну и ту же переменную в каждой строке, изменяется только параметр форматирования. На одной стороне я поместил описание формата даты. С другой стороны, я применил формат к значению даты. Ниже приведен окончательный вывод из приведенного выше шаблона.

Example 6: Formatting Dates

DateFromat Styles:

DEFAULT Jun 7, 2010
SHORT 6/7/10
MEDIUM Jun 7, 2010
LONG June 7, 2010
FULL Monday, June 7, 2010

Using SimpleDateFormat Patterns:

yyyy.MM.dd G 'at' HH:mm:ss z 2010.06.07 AD at 21:00:18 CDT
EEE, MMM d, ''yy Mon, Jun 7, '10
h:mm a 9:00 PM
hh 'o''clock' a, zzzz 09 o'clock PM, Central Daylight Time
K:mm a, z 9:00 PM, CDT
yyyyy.MMMMM.dd GGG hh:mm aaa 02010.June.07 AD 09:00 PM
EEE, d MMM yyyy HH:mm:ss Z Mon, 7 Jun 2010 21:00:18 -0500
yyMMddHHmmssZ 100607210018-0500
yyyy-MM-dd'T'HH:mm:ss.SSSZ 2010-06-07T21:00:18.668-0500
dd.MM.yy 07.06.10
h:mm a 9:00 PM
H:mm 21:00
H:mm:ss:SSS 21:00:18:668

(Синтаксис hilighter испытывает проблемы с интервалом в этом блоке. Пожалуйста, нажмите «просмотреть исходный код», чтобы увидеть фактический результат.)

Рендеры — это мощная система для преобразования данных в удобные для шаблонов формы. Как правило, при объединении данных следует использовать шаблон. Когда сами данные должны принять другую форму, пришло время рассмотреть визуализатор.

На этом мы завершаем часть 3. Надеюсь, вы попробуете StringTemplate Как всегда, если вы хотите получить больше информации, пожалуйста, смотрите официальную документацию StringTemplate .

Пример исходного кода (проект Eclipse)

От http://weblogs.java.net/blog/aberrant/archive/2010/06/07/stringtemplate-part-3-complex-data-types-and-renderers