Date formatting for Freemarker themes

git-svn-id: https://svn.libreccm.org/ccm/trunk@5914 8810af33-2d31-482b-a856-94f89814c4df
master
jensp 2019-04-06 14:58:36 +00:00
parent 232587146d
commit 480e57816d
5 changed files with 237 additions and 36 deletions

View File

@ -36,9 +36,9 @@
<#function getNewsDate item> <#function getNewsDate item>
<#if (item["./newsDate"]?size > 0)> <#if (item["./newsDate"]?size > 0)>
<#return item["./newsDate"].@@text /> <#return item["./newsDate"] />
<#elseif (item["./nav:attribute[@name='newsDate']"]?size > 0)> <#elseif (item["./nav:attribute[@name='newsDate']"]?size > 0)>
<#return item["./nav:attribute[@name='newsDate']"].@@text /> <#return item["./nav:attribute[@name='newsDate']"] />
</#if> </#if>
</#function> </#function>

View File

@ -25,6 +25,7 @@ import freemarker.template.TemplateException;
import freemarker.template.TemplateMethodModelEx; import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModelException; import freemarker.template.TemplateModelException;
import freemarker.template.TemplateScalarModel; import freemarker.template.TemplateScalarModel;
import org.libreccm.theming.manifest.DateFormat;
import org.libreccm.theming.manifest.ThemeManifest; import org.libreccm.theming.manifest.ThemeManifest;
import org.libreccm.theming.manifest.ThemeManifestUtil; import org.libreccm.theming.manifest.ThemeManifestUtil;
import org.w3c.dom.NamedNodeMap; import org.w3c.dom.NamedNodeMap;
@ -34,13 +35,15 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.MissingResourceException; import java.util.MissingResourceException;
import java.util.Optional; import java.util.Optional;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
@ -213,6 +216,11 @@ public class FreeMarkerPresentationManager implements PresentationManager {
themePath, themePath,
selectedLocale.getLanguage())); selectedLocale.getLanguage()));
configuration.setSharedVariable(
"_formatDateTime",
new FormatDateTime(manifest.getDateFormats(),
new Locale(selectedLocale.getLanguage())));
data.put("serverName", request.getServerName()); data.put("serverName", request.getServerName());
data.put("serverPort", request.getServerPort()); data.put("serverPort", request.getServerPort());
data.put("userAgent", request.getHeader("user-Agent")); data.put("userAgent", request.getHeader("user-Agent"));
@ -430,44 +438,90 @@ public class FreeMarkerPresentationManager implements PresentationManager {
} }
private class FormatDateTime implements TemplateMethodModelEx {
private final List<DateFormat> dateFormats;
private final Locale locale;
public FormatDateTime(final List<DateFormat> dateFormats,
final Locale locale) {
this.dateFormats = dateFormats;
this.locale = locale;
}
@Override
public Object exec(final List list) throws TemplateModelException {
if (list.isEmpty()) {
throw new IllegalArgumentException(
"FormatDateTime requires the following parameters: "
+ "style: string, year: int, month: int, "
+ "day of month: int, hour: int, minute: int,"
+ "second: int");
}
final String style = ((TemplateScalarModel) list.get(0))
.getAsString();
final String yearParam = ((TemplateScalarModel) list.get(1))
.getAsString();
final String monthParam = ((TemplateScalarModel) list.get(2))
.getAsString();
final String dayOfMonthParam = ((TemplateScalarModel) list.get(3))
.getAsString();
final String hourParam = ((TemplateScalarModel) list.get(4))
.getAsString();
final String minuteParam = ((TemplateScalarModel) list.get(5))
.getAsString();
final String secondParam = ((TemplateScalarModel) list.get(6))
.getAsString();
final int year = Integer.parseInt(yearParam);
final int month = Integer.parseInt(monthParam);
final int dayOfMonth = Integer.parseInt(dayOfMonthParam);
final int hour = Integer.parseInt(hourParam);
final int minute = Integer.parseInt(minuteParam);
final int second = Integer.parseInt(secondParam);
final String format = findFormat(dateFormats, style, locale)
.orElse("YYYY-MM-dd");
final LocalDateTime localDateTime = LocalDateTime.of(year,
month,
dayOfMonth,
hour,
minute,
second);
final DateTimeFormatter formatter = DateTimeFormatter
.ofPattern(format, locale);
return formatter.format(localDateTime);
}
private Optional<String> findFormat(
final List<DateFormat> dateFormats,
final String style,
final Locale locale) {
final Optional<String> format = dateFormats
.stream()
.filter(dateFormat -> dateFormat.getStyle().equals(style))
.filter(dateFormat -> dateFormat.getLang().equals(locale
.toString()))
.map(DateFormat::getFormat)
.findAny();
return format;
}
}
private String findContentItemTemplate( private String findContentItemTemplate(
final Templates templates, final Templates templates,
final String objectType, final String objectType,
final ContentItemViews view, final ContentItemViews view,
final String style) throws TemplateModelException { final String style) throws TemplateModelException {
// final String nodeNamespace = itemModel.getNodeNamespace();
// final String nodeName = itemModel.getNodeName();
// final String contentType;
// if ("http://www.arsdigita.com/cms/1.0".equals(nodeNamespace)
// && "item".equals(nodeName)) {
// contentType = ((TemplateScalarModel) itemModel
// .get("objectType"))
// .getAsString();
// } else if ("http://ccm.redhat.com/navigation".equals(nodeNamespace)
// && "item".equals(nodeName)) {
// final TemplateModel objectTypeElems = itemModel
// .get("attribute[@name='objectType']");
// if (objectTypeElems instanceof TemplateSequenceModel) {
// final TemplateModel objectTypeElem
// = ((TemplateSequenceModel) objectTypeElems)
// .get(0);
// contentType = ((TemplateScalarModel) objectTypeElem)
// .getAsString();
// } else if (objectTypeElems instanceof TemplateScalarModel) {
// contentType = ((TemplateScalarModel) objectTypeElems)
// .getAsString();
// } else {
// throw new IllegalArgumentException(
// "Can't determine object type of item.");
// }
// } else {
// throw new IllegalArgumentException(String.format(
// "Unexpected combination of node namespace and nodename. "
// + "nodeNamespace = \"%s\"; nodeName = \"%s\"",
// nodeNamespace,
// nodeName));
// }
final Optional<ContentItemTemplate> forTypeViewAndStyle = templates final Optional<ContentItemTemplate> forTypeViewAndStyle = templates
.getContentItems() .getContentItems()
.stream() .stream()

View File

@ -0,0 +1,116 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.libreccm.theming.manifest;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import static org.libreccm.theming.ThemeConstants.*;
import java.util.Objects;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@XmlRootElement(name = "dateformat", namespace = THEMES_XML_NS)
@XmlAccessorType(XmlAccessType.FIELD)
public class DateFormat {
@XmlElement(name = "style", namespace = THEMES_XML_NS)
private String style;
@XmlElement(name = "lang", namespace = THEMES_XML_NS)
private String lang;
@XmlElement(name = "format", namespace = THEMES_XML_NS)
private String format;
public String getLang() {
return lang;
}
public void setLang(String lang) {
this.lang = lang;
}
public String getStyle() {
return style;
}
public void setStyle(String style) {
this.style = style;
}
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
@Override
public int hashCode() {
int hash = 7;
hash = 17 * hash + Objects.hashCode(lang);
hash = 17 * hash + Objects.hashCode(style);
hash = 17 * hash + Objects.hashCode(format);
return hash;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof DateFormat)) {
return false;
}
final DateFormat other = (DateFormat) obj;
if (!other.canEqual(this)) {
return false;
}
if (!Objects.equals(lang, other.getLang())) {
return false;
}
if (!Objects.equals(style, other.getStyle())) {
return false;
}
return Objects.equals(format, other.getFormat());
}
public boolean canEqual(final Object obj) {
return obj instanceof DateFormat;
}
@Override
public final String toString() {
return toString("");
}
public String toString(final String data) {
return String.format("%s{ "
+ "style = \"%s\", "
+ "lang = \"%s\", "
+ "format = \"%s\"%s"
+ " }",
super.toString(),
style,
lang,
format,
data);
}
}

View File

@ -31,8 +31,11 @@ import javax.xml.bind.annotation.XmlRootElement;
import static org.libreccm.theming.ThemeConstants.*; import static org.libreccm.theming.ThemeConstants.*;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
/** /**
@ -90,12 +93,16 @@ public class ThemeManifest implements Serializable {
@XmlElement(name = "default-template", namespace = THEMES_XML_NS) @XmlElement(name = "default-template", namespace = THEMES_XML_NS)
private String defaultTemplate; private String defaultTemplate;
@XmlElementWrapper(name = "config", namespace = THEMES_XML_NS)
private Map<String, String> config; private Map<String, String> config;
@XmlElementWrapper(name = "date-time-formats", namespace = THEMES_XML_NS)
@XmlElement(name = "date-time-formats", namespace = THEMES_XML_NS)
private List<DateFormat> dateFormats;
public ThemeManifest() { public ThemeManifest() {
// templates = new ArrayList<>(); // templates = new ArrayList<>();
config = new HashMap<>(); config = new HashMap<>();
dateFormats = new ArrayList<>();
} }
public String getName() { public String getName() {
@ -171,6 +178,26 @@ public class ThemeManifest implements Serializable {
config.remove(key); config.remove(key);
} }
public List<DateFormat> getDateFormats() {
return Collections.unmodifiableList(dateFormats);
}
public void setDateFormats(
final ArrayList<DateFormat> dateFormats) {
this.dateFormats = new ArrayList<>(dateFormats);
}
public void addDateFormat(final DateFormat dateFormat) {
dateFormats.add(dateFormat);
}
public void removeDateFormat(final DateFormat dateFormat) {
dateFormats.remove(dateFormat);
}
@Override @Override
public int hashCode() { public int hashCode() {
int hash = 7; int hash = 7;

View File

@ -37,4 +37,8 @@
<#else> <#else>
<#return false> <#return false>
</#if> </#if>
</#function>
<#function formatDateTime style date>
<#return _formatDateTime(style, date["./@year"], date["./@month"], date["./@day"], date["./@hour"], date["./@minute"], date["./@second"])>
</#function> </#function>