diff --git a/ccm-cms-types-newsitem/web/themes/freemarker/ccm-cms-types-newsitem.ftl b/ccm-cms-types-newsitem/web/themes/freemarker/ccm-cms-types-newsitem.ftl index 85238f11a..744a46119 100644 --- a/ccm-cms-types-newsitem/web/themes/freemarker/ccm-cms-types-newsitem.ftl +++ b/ccm-cms-types-newsitem/web/themes/freemarker/ccm-cms-types-newsitem.ftl @@ -36,9 +36,9 @@ <#function getNewsDate item> <#if (item["./newsDate"]?size > 0)> - <#return item["./newsDate"].@@text /> + <#return item["./newsDate"] /> <#elseif (item["./nav:attribute[@name='newsDate']"]?size > 0)> - <#return item["./nav:attribute[@name='newsDate']"].@@text /> + <#return item["./nav:attribute[@name='newsDate']"] /> diff --git a/ccm-themedirector/src/org/libreccm/theming/FreeMarkerPresentationManager.java b/ccm-themedirector/src/org/libreccm/theming/FreeMarkerPresentationManager.java index 985cc967e..c0695ea07 100644 --- a/ccm-themedirector/src/org/libreccm/theming/FreeMarkerPresentationManager.java +++ b/ccm-themedirector/src/org/libreccm/theming/FreeMarkerPresentationManager.java @@ -25,6 +25,7 @@ import freemarker.template.TemplateException; import freemarker.template.TemplateMethodModelEx; import freemarker.template.TemplateModelException; import freemarker.template.TemplateScalarModel; +import org.libreccm.theming.manifest.DateFormat; import org.libreccm.theming.manifest.ThemeManifest; import org.libreccm.theming.manifest.ThemeManifestUtil; import org.w3c.dom.NamedNodeMap; @@ -34,13 +35,15 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; 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.List; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.Optional; -import java.util.PropertyResourceBundle; import java.util.ResourceBundle; import javax.servlet.ServletContext; @@ -213,6 +216,11 @@ public class FreeMarkerPresentationManager implements PresentationManager { themePath, selectedLocale.getLanguage())); + configuration.setSharedVariable( + "_formatDateTime", + new FormatDateTime(manifest.getDateFormats(), + new Locale(selectedLocale.getLanguage()))); + data.put("serverName", request.getServerName()); data.put("serverPort", request.getServerPort()); data.put("userAgent", request.getHeader("user-Agent")); @@ -430,44 +438,90 @@ public class FreeMarkerPresentationManager implements PresentationManager { } + private class FormatDateTime implements TemplateMethodModelEx { + + private final List dateFormats; + private final Locale locale; + + public FormatDateTime(final List 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 findFormat( + final List dateFormats, + final String style, + final Locale locale) { + + final Optional 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( final Templates templates, final String objectType, final ContentItemViews view, 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 forTypeViewAndStyle = templates .getContentItems() .stream() diff --git a/ccm-themedirector/src/org/libreccm/theming/manifest/DateFormat.java b/ccm-themedirector/src/org/libreccm/theming/manifest/DateFormat.java new file mode 100644 index 000000000..0d0138241 --- /dev/null +++ b/ccm-themedirector/src/org/libreccm/theming/manifest/DateFormat.java @@ -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 Jens Pelzetter + */ +@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); + } + +} diff --git a/ccm-themedirector/src/org/libreccm/theming/manifest/ThemeManifest.java b/ccm-themedirector/src/org/libreccm/theming/manifest/ThemeManifest.java index 4be601dbc..421019009 100644 --- a/ccm-themedirector/src/org/libreccm/theming/manifest/ThemeManifest.java +++ b/ccm-themedirector/src/org/libreccm/theming/manifest/ThemeManifest.java @@ -31,8 +31,11 @@ import javax.xml.bind.annotation.XmlRootElement; import static org.libreccm.theming.ThemeConstants.*; import java.io.Serializable; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.List; +import java.util.Locale; import java.util.Map; /** @@ -90,12 +93,16 @@ public class ThemeManifest implements Serializable { @XmlElement(name = "default-template", namespace = THEMES_XML_NS) private String defaultTemplate; - @XmlElementWrapper(name = "config", namespace = THEMES_XML_NS) private Map config; + @XmlElementWrapper(name = "date-time-formats", namespace = THEMES_XML_NS) + @XmlElement(name = "date-time-formats", namespace = THEMES_XML_NS) + private List dateFormats; + public ThemeManifest() { // templates = new ArrayList<>(); config = new HashMap<>(); + dateFormats = new ArrayList<>(); } public String getName() { @@ -171,6 +178,26 @@ public class ThemeManifest implements Serializable { config.remove(key); } + public List getDateFormats() { + return Collections.unmodifiableList(dateFormats); + } + + public void setDateFormats( + final ArrayList 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 public int hashCode() { int hash = 7; diff --git a/ccm-themedirector/web/themes/freemarker/Utils.ftl b/ccm-themedirector/web/themes/freemarker/Utils.ftl index fc9c50d2e..ad73f82c7 100644 --- a/ccm-themedirector/web/themes/freemarker/Utils.ftl +++ b/ccm-themedirector/web/themes/freemarker/Utils.ftl @@ -37,4 +37,8 @@ <#else> <#return false> + + +<#function formatDateTime style date> + <#return _formatDateTime(style, date["./@year"], date["./@month"], date["./@day"], date["./@hour"], date["./@minute"], date["./@second"])> \ No newline at end of file