1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.primefaces.extensions.component.timeago;
23
24 import java.text.SimpleDateFormat;
25 import java.time.LocalDateTime;
26 import java.time.OffsetDateTime;
27 import java.time.ZoneId;
28 import java.time.ZonedDateTime;
29 import java.time.format.DateTimeFormatter;
30 import java.util.Date;
31 import java.util.Locale;
32 import java.util.TimeZone;
33
34 import javax.faces.application.ResourceDependency;
35 import javax.faces.component.UIComponentBase;
36 import javax.faces.context.FacesContext;
37
38 import org.primefaces.component.api.Widget;
39 import org.primefaces.util.LocaleUtils;
40
41
42
43
44
45
46
47 @ResourceDependency(library = "primefaces", name = "jquery/jquery.js")
48 @ResourceDependency(library = "primefaces", name = "core.js")
49 @ResourceDependency(library = "primefaces-extensions", name = "primefaces-extensions.js")
50 @ResourceDependency(library = "primefaces-extensions", name = "timeago/timeago.js")
51 public class TimeAgo extends UIComponentBase implements Widget {
52
53 public static final String COMPONENT_TYPE = "org.primefaces.extensions.component.TimeAgo";
54 public static final String COMPONENT_FAMILY = "org.primefaces.extensions.component";
55 public static final String DEFAULT_RENDERER = "org.primefaces.extensions.component.TimeAgoRenderer";
56
57 public static final String STYLE_CLASS = "ui-timeago ui-widget";
58
59 private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ";
60
61 private Locale appropriateLocale;
62
63
64 @SuppressWarnings("java:S115")
65 public enum PropertyKeys {
66 value,
67 widgetVar,
68 style,
69 styleClass,
70 locale,
71 titlePattern
72 }
73
74
75 public TimeAgo() {
76 setRendererType(DEFAULT_RENDERER);
77 }
78
79 @Override
80 public String getFamily() {
81 return COMPONENT_FAMILY;
82 }
83
84 public Object getValue() {
85 return getStateHelper().eval(PropertyKeys.value, null);
86 }
87
88 public void setValue(String value) {
89 getStateHelper().put(PropertyKeys.value, value);
90 }
91
92 public String getWidgetVar() {
93 return (String) getStateHelper().eval(PropertyKeys.widgetVar, null);
94 }
95
96 public void setWidgetVar(String widgetVar) {
97 getStateHelper().put(PropertyKeys.widgetVar, widgetVar);
98 }
99
100 public String getStyle() {
101 return (String) getStateHelper().eval(PropertyKeys.style, null);
102 }
103
104 public void setStyle(String style) {
105 getStateHelper().put(PropertyKeys.style, style);
106 }
107
108 public String getStyleClass() {
109 return (String) getStateHelper().eval(PropertyKeys.styleClass, null);
110 }
111
112 public void setStyleClass(String styleClass) {
113 getStateHelper().put(PropertyKeys.styleClass, styleClass);
114 }
115
116 public Object getLocale() {
117 return getStateHelper().eval(PropertyKeys.locale, null);
118 }
119
120 public void setLocale(final Object locale) {
121 getStateHelper().put(PropertyKeys.locale, locale);
122 }
123
124 public String getTitlePattern() {
125 return (String) getStateHelper().eval(PropertyKeys.titlePattern, null);
126 }
127
128 public void setTitlePattern(String titlePattern) {
129 getStateHelper().put(PropertyKeys.titlePattern, titlePattern);
130 }
131
132 public Locale calculateLocale() {
133 if (appropriateLocale == null) {
134 final FacesContext fc = FacesContext.getCurrentInstance();
135 appropriateLocale = LocaleUtils.resolveLocale(fc, getLocale(), getClientId(fc));
136 }
137 return appropriateLocale;
138 }
139
140 public final String formattedForJs() {
141 return format(DATE_FORMAT, ZoneId.of("UTC"));
142 }
143
144 public final String formattedForTitle() {
145 return format(getTitlePattern(), getValueZoneId());
146 }
147
148 protected final ZoneId getValueZoneId() {
149 final Object value = getValue();
150 if (value instanceof ZonedDateTime) {
151 return ((ZonedDateTime) value).getZone();
152 }
153 if (value instanceof OffsetDateTime) {
154 return ((OffsetDateTime) value).getOffset();
155 }
156 return ZoneId.systemDefault();
157 }
158
159 protected String format(final String pattern, final ZoneId zone) {
160 final Object value = getValue();
161 if (value instanceof Date) {
162 return format((Date) value, pattern, zone);
163 }
164 if (value instanceof ZonedDateTime) {
165 return format((ZonedDateTime) value, pattern, zone);
166 }
167 if (value instanceof LocalDateTime) {
168 return format((LocalDateTime) value, pattern, zone);
169 }
170 if (value instanceof OffsetDateTime) {
171 return format((OffsetDateTime) value, pattern, zone);
172 }
173 throw new IllegalArgumentException("Unsupported type");
174 }
175
176 protected String format(final Date value, final String pattern, final ZoneId zone) {
177 final SimpleDateFormat sdf = new SimpleDateFormat(pattern, calculateLocale());
178 sdf.setTimeZone(TimeZone.getTimeZone(zone));
179 return sdf.format(value);
180 }
181
182 protected String format(final ZonedDateTime dateTime, final String pattern, final ZoneId zone) {
183 return dateTime.withZoneSameInstant(zone)
184 .format(DateTimeFormatter.ofPattern(pattern));
185 }
186
187 protected String format(final LocalDateTime dateTime, final String pattern, final ZoneId zone) {
188 return format(dateTime.atZone(ZoneId.systemDefault()), pattern, zone);
189 }
190
191 protected String format(final OffsetDateTime dateTime, final String pattern, final ZoneId zone) {
192 return dateTime.atZoneSameInstant(zone)
193 .format(DateTimeFormatter.ofPattern(pattern));
194 }
195
196 @Override
197 public Object saveState(FacesContext context) {
198
199 appropriateLocale = null;
200
201 return super.saveState(context);
202 }
203 }