这是我想出的(下面有详细解释):
Java 代码:
List<LocalDate> dates = new ArrayList<>();
dates.add(LocalDate.parse("20100101", DateTimeFormatter.BASIC_ISO_DATE));
dates.add(LocalDate.parse("20100201", DateTimeFormatter.BASIC_ISO_DATE));
List<List<Character>> charListList = new ArrayList<>();
for (LocalDate date : dates) {
List<Character> charList = new ArrayList<>();
char[] dateCharArray = date.toString().toCharArray();
for (char c : dateCharArray) {
charList.add(c);
}
charListList.add(charList);
}
STGroup dateGroup = new STGroupFile("./src/com/stackoverflow/DateList/dates.stg");
ST dateTemp = dateGroup.getInstanceOf("writeCode");
dateTemp.add("formattedDates", charListList);
dateTemp.add("isSingle", charListList.size() == 1);
System.out.println(dateTemp.render());
字符串模板代码(dates.stg):
writeCode(formattedDates, isSingle) ::= <<
<if(isSingle)><writeSingleStuff(formattedDates)>
<else><writeMultipleStuff(formattedDates)>
<endif>
<writeStoreList(formattedDates)>
>>
writeSingleStuff(date)::= "<date:{d|splitByDay_<wordReplaceWSlash(d)> = FOREACH finalizedEvents GENERATE $0..;}>"
writeMultipleStuff(rawDates)::= "SPLIT finalizedEvents <rawDates:{d|INTO splitByDay_<wordReplaceWEmpty(d)> IF dataDate == <wordReplaceWEmpty(d)>}; separator=\", \">;"
writeStoreList(formattedDates)::= "<formattedDates:{d|STORE splitByDay_<wordReplaceWEmpty(d)> INTO '/a/b/<wordReplaceWSlash(d)>' USING AvroStorage();<\n>}>"
wordReplaceWSlash(word) ::= "<word:{char|<charReplaceWSlash(char)>}>"
charReplaceWSlash(theChar) ::= <%<charReplaceWSlashMap.(theChar)>%>
charReplaceWSlashMap ::= [
"-":"/",
default:{<theChar>}
]
wordReplaceWEmpty(word) ::= "<word:{char|<charReplaceWEmpty(char)>}>"
charReplaceWEmpty(theChar) ::= <%<charReplaceWEmptyMap.(theChar)>%>
charReplaceWEmptyMap ::= [
"-":"",
default:{<theChar>}
]
代码的作用:
Java 代码:
List<LocalDate> dates = new ArrayList<>();
dates.add(LocalDate.parse("20100101", DateTimeFormatter.BASIC_ISO_DATE));
dates.add(LocalDate.parse("20100201", DateTimeFormatter.BASIC_ISO_DATE));
这是一个带有LocalDates 的列表,我们想将其用作模板的输入。我用DateTimeFormatter.BASIC_ISO_DATE 格式化它们,例如20100101 变为 2010-01-01。稍后我们需要这个,因为我们将告诉 StringTemplate 用 / 或空字符串替换 - 以获得我们想要的两种日期格式(我没有找到在第一名)。
两种不同的方法是:
- 在 Java 代码中将
- 替换为 /,而不是在 StringTemplate 中。然后,如果我们需要这种日期格式,我们只需要用空字符串替换 /。
- 将年、月和日作为三个不同的变量添加到模板中。然后我们可以连接字符串并在需要时添加
/。
List<List<Character>> charListList = new ArrayList<>();
for (LocalDate date : dates) {
List<Character> charList = new ArrayList<>();
char[] dateCharArray = date.toString().toCharArray();
for (char c : dateCharArray) {
charList.add(c);
}
charListList.add(charList);
}
我们必须这样做不是很漂亮,但是:
我们必须有一个日期字符的列表(并且不是一个数组),以便我们可以在 StringTemplate 中“迭代”它。还有no direct way 将char[] 转换为List。最后,我们必须将所有这些列表放在一个列表中,以便我们可以为我们拥有的每个日期生成代码 (charListList)。
STGroup dateGroup = new STGroupFile("./src/com/stackoverflow/DateList/dates.stg");
ST dateTemp = dateGroup.getInstanceOf("writeCode");
dateTemp.add("formattedDates", charListList);
dateTemp.add("isSingle", charListList.size() == 1);
System.out.println(dateTemp.render());
这里我们用值填充模板。我们必须在 here 告诉 StringTemplate 我们在 charListList 中是否只有一个日期,因为 StringTemplate (by design) 无法这样做。
字符串模板代码:
writeCode(formattedDates, isSingle) ::= <<
<if(isSingle)><writeSingleStuff(formattedDates)>
<else><writeMultipleStuff(formattedDates)>
<endif>
<writeStoreList(formattedDates)>
>>
这是“根”模板,基本上只是将工作委托给其他模板。它处理一个或多个日期之间的大小写区分。
writeSingleStuff(date)::= "<date:{d|splitByDay_<wordReplaceWSlash(d)> = FOREACH finalizedEvents GENERATE $0..;}>"
writeMultipleStuff(rawDates)::= "SPLIT finalizedEvents <rawDates:{d|INTO splitByDay_<wordReplaceWEmpty(d)> IF dataDate == <wordReplaceWEmpty(d)>}; separator=\", \">;"
writeStoreList(dates)::= "<dates:{d|STORE splitByDay_<wordReplaceWEmpty(d)> INTO '/a/b/<wordReplaceWSlash(d)>' USING AvroStorage();<\n>}>"
通过这三行代码,我们编写了特定于单个项目、多个项目以及两者共同的代码。
虽然我们知道在输入writeSingleStuff时date只有一项,但我们必须遍历列表。
wordReplaceWSlash(word) ::= "<word:{char|<charReplaceWSlash(char)>}>"
charReplaceWSlash(theChar) ::= <%<charReplaceWSlashMap.(theChar)>%>
charReplaceWSlashMap ::= [
"-":"/",
default:{<theChar>}
]
wordReplaceWEmpty(word) ::= "<word:{char|<charReplaceWEmpty(char)>}>"
charReplaceWEmpty(theChar) ::= <%<charReplaceWEmptyMap.(theChar)>%>
charReplaceWEmptyMap ::= [
"-":"",
default:{<theChar>}
]
这两组模板几乎做同样的事情:将每个“单词”中的每个 - 字符替换为 / 或空字符串。我们使用一个小字典来替换除 - 之外的每个字符。