f6bc05d6e0e27842647a01031e445e6920a18c4d
[Sone.git] / src / main / java / net / pterodactylus / sone / web / ajax / GetTimesAjaxPage.java
1 /*
2  * Sone - GetTimesAjaxPage.java - Copyright © 2010–2012 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify it under
5  * the terms of the GNU General Public License as published by the Free Software
6  * Foundation, either version 3 of the License, or (at your option) any later
7  * version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sone.web.ajax;
19
20 import java.text.DateFormat;
21 import java.text.SimpleDateFormat;
22 import java.util.Date;
23
24 import net.pterodactylus.sone.data.Post;
25 import net.pterodactylus.sone.data.PostReply;
26 import net.pterodactylus.sone.web.WebInterface;
27 import net.pterodactylus.sone.web.page.FreenetRequest;
28 import net.pterodactylus.util.json.JsonObject;
29 import net.pterodactylus.util.number.Digits;
30
31 /**
32  * Ajax page that returns a formatted, relative timestamp for replies or posts.
33  *
34  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
35  */
36 public class GetTimesAjaxPage extends JsonPage {
37
38         /** Formatter for tooltips. */
39         private static final DateFormat dateFormat = new SimpleDateFormat("MMM d, yyyy, HH:mm:ss");
40
41         /**
42          * Creates a new get times AJAX page.
43          *
44          * @param webInterface
45          *            The Sone web interface
46          */
47         public GetTimesAjaxPage(WebInterface webInterface) {
48                 super("getTimes.ajax", webInterface);
49         }
50
51         /**
52          * {@inheritDoc}
53          */
54         @Override
55         protected JsonObject createJsonObject(FreenetRequest request) {
56                 String allIds = request.getHttpRequest().getParam("posts");
57                 JsonObject postTimes = new JsonObject();
58                 if (allIds.length() > 0) {
59                         String[] ids = allIds.split(",");
60                         for (String id : ids) {
61                                 Post post = webInterface.getCore().getPost(id, false);
62                                 if (post == null) {
63                                         continue;
64                                 }
65                                 JsonObject postTime = new JsonObject();
66                                 Time time = getTime(post.getTime());
67                                 postTime.put("timeText", time.getText());
68                                 postTime.put("refreshTime", time.getRefresh() / Time.SECOND);
69                                 synchronized (dateFormat) {
70                                         postTime.put("tooltip", dateFormat.format(new Date(post.getTime())));
71                                 }
72                                 postTimes.put(id, postTime);
73                         }
74                 }
75                 JsonObject replyTimes = new JsonObject();
76                 allIds = request.getHttpRequest().getParam("replies");
77                 if (allIds.length() > 0) {
78                         String[] ids = allIds.split(",");
79                         for (String id : ids) {
80                                 PostReply reply = webInterface.getCore().getReply(id, false);
81                                 if (reply == null) {
82                                         continue;
83                                 }
84                                 JsonObject replyTime = new JsonObject();
85                                 Time time = getTime(reply.getTime());
86                                 replyTime.put("timeText", time.getText());
87                                 replyTime.put("refreshTime", time.getRefresh() / Time.SECOND);
88                                 synchronized (dateFormat) {
89                                         replyTime.put("tooltip", dateFormat.format(new Date(reply.getTime())));
90                                 }
91                                 replyTimes.put(id, replyTime);
92                         }
93                 }
94                 return createSuccessJsonObject().put("postTimes", postTimes).put("replyTimes", replyTimes);
95         }
96
97         /**
98          * {@inheritDoc}
99          */
100         @Override
101         protected boolean needsFormPassword() {
102                 return false;
103         }
104
105         /**
106          * {@inheritDoc}
107          */
108         @Override
109         protected boolean requiresLogin() {
110                 return false;
111         }
112
113         //
114         // PRIVATE METHODS
115         //
116
117         /**
118          * Returns the formatted relative time for a given time.
119          *
120          * @param time
121          *            The time to format the difference from (in milliseconds)
122          * @return The formatted age
123          */
124         private Time getTime(long time) {
125                 return getTime(webInterface, time);
126         }
127
128         //
129         // STATIC METHODS
130         //
131
132         /**
133          * Returns the formatted relative time for a given time.
134          *
135          * @param webInterface
136          *            The Sone web interface (for l10n access)
137          * @param time
138          *            The time to format the difference from (in milliseconds)
139          * @return The formatted age
140          */
141         public static Time getTime(WebInterface webInterface, long time) {
142                 if (time == 0) {
143                         return new Time(webInterface.getL10n().getString("View.Sone.Text.UnknownDate"), 12 * Time.HOUR);
144                 }
145                 long age = System.currentTimeMillis() - time;
146                 String text;
147                 long refresh;
148                 if (age < 0) {
149                         text = webInterface.getL10n().getDefaultString("View.Time.InTheFuture");
150                         refresh = 5 * Time.MINUTE;
151                 } else if (age < 20 * Time.SECOND) {
152                         text = webInterface.getL10n().getDefaultString("View.Time.AFewSecondsAgo");
153                         refresh = 10 * Time.SECOND;
154                 } else if (age < 45 * Time.SECOND) {
155                         text = webInterface.getL10n().getString("View.Time.HalfAMinuteAgo");
156                         refresh = 20 * Time.SECOND;
157                 } else if (age < 90 * Time.SECOND) {
158                         text = webInterface.getL10n().getString("View.Time.AMinuteAgo");
159                         refresh = Time.MINUTE;
160                 } else if (age < 30 * Time.MINUTE) {
161                         text = webInterface.getL10n().getString("View.Time.XMinutesAgo", "min", String.valueOf((int) (Digits.round(age, Time.MINUTE) / Time.MINUTE)));
162                         refresh = 1 * Time.MINUTE;
163                 } else if (age < 45 * Time.MINUTE) {
164                         text = webInterface.getL10n().getString("View.Time.HalfAnHourAgo");
165                         refresh = 10 * Time.MINUTE;
166                 } else if (age < 90 * Time.MINUTE) {
167                         text = webInterface.getL10n().getString("View.Time.AnHourAgo");
168                         refresh = Time.HOUR;
169                 } else if (age < 21 * Time.HOUR) {
170                         text = webInterface.getL10n().getString("View.Time.XHoursAgo", "hour", String.valueOf((int) (Digits.round(age, Time.HOUR) / Time.HOUR)));
171                         refresh = Time.HOUR;
172                 } else if (age < 42 * Time.HOUR) {
173                         text = webInterface.getL10n().getString("View.Time.ADayAgo");
174                         refresh = Time.DAY;
175                 } else if (age < 6 * Time.DAY) {
176                         text = webInterface.getL10n().getString("View.Time.XDaysAgo", "day", String.valueOf((int) (Digits.round(age, Time.DAY) / Time.DAY)));
177                         refresh = Time.DAY;
178                 } else if (age < 11 * Time.DAY) {
179                         text = webInterface.getL10n().getString("View.Time.AWeekAgo");
180                         refresh = Time.DAY;
181                 } else if (age < 4 * Time.WEEK) {
182                         text = webInterface.getL10n().getString("View.Time.XWeeksAgo", "week", String.valueOf((int) (Digits.round(age, Time.WEEK) / Time.WEEK)));
183                         refresh = Time.DAY;
184                 } else if (age < 6 * Time.WEEK) {
185                         text = webInterface.getL10n().getString("View.Time.AMonthAgo");
186                         refresh = Time.DAY;
187                 } else if (age < 11 * Time.MONTH) {
188                         text = webInterface.getL10n().getString("View.Time.XMonthsAgo", "month", String.valueOf((int) (Digits.round(age, Time.MONTH) / Time.MONTH)));
189                         refresh = Time.DAY;
190                 } else if (age < 18 * Time.MONTH) {
191                         text = webInterface.getL10n().getString("View.Time.AYearAgo");
192                         refresh = Time.WEEK;
193                 } else {
194                         text = webInterface.getL10n().getString("View.Time.XYearsAgo", "year", String.valueOf((int) (Digits.round(age, Time.YEAR) / Time.YEAR)));
195                         refresh = Time.WEEK;
196                 }
197                 return new Time(text, refresh);
198         }
199
200         /**
201          * Container for a formatted time.
202          *
203          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
204          */
205         public static class Time {
206
207                 /** Number of milliseconds in a second. */
208                 private static final long SECOND = 1000;
209
210                 /** Number of milliseconds in a minute. */
211                 private static final long MINUTE = 60 * SECOND;
212
213                 /** Number of milliseconds in an hour. */
214                 private static final long HOUR = 60 * MINUTE;
215
216                 /** Number of milliseconds in a day. */
217                 private static final long DAY = 24 * HOUR;
218
219                 /** Number of milliseconds in a week. */
220                 private static final long WEEK = 7 * DAY;
221
222                 /** Number of milliseconds in a 30-day month. */
223                 private static final long MONTH = 30 * DAY;
224
225                 /** Number of milliseconds in a year. */
226                 private static final long YEAR = 365 * DAY;
227
228                 /** The formatted time. */
229                 private final String text;
230
231                 /** The time after which to refresh the time. */
232                 private final long refresh;
233
234                 /**
235                  * Creates a new formatted time container.
236                  *
237                  * @param text
238                  *            The formatted time
239                  * @param refresh
240                  *            The time after which to refresh the time (in milliseconds)
241                  */
242                 public Time(String text, long refresh) {
243                         this.text = text;
244                         this.refresh = refresh;
245                 }
246
247                 /**
248                  * Returns the formatted time.
249                  *
250                  * @return The formatted time
251                  */
252                 public String getText() {
253                         return text;
254                 }
255
256                 /**
257                  * Returns the time after which to refresh the time.
258                  *
259                  * @return The time after which to refresh the time (in milliseconds)
260                  */
261                 public long getRefresh() {
262                         return refresh;
263                 }
264
265                 /**
266                  * {@inheritDoc}
267                  */
268                 @Override
269                 public String toString() {
270                         return text;
271                 }
272
273         }
274
275 }