Fix logging of exception.
[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                                 postTime.put("tooltip", dateFormat.format(new Date(post.getTime())));
70                                 postTimes.put(id, postTime);
71                         }
72                 }
73                 JsonObject replyTimes = new JsonObject();
74                 allIds = request.getHttpRequest().getParam("replies");
75                 if (allIds.length() > 0) {
76                         String[] ids = allIds.split(",");
77                         for (String id : ids) {
78                                 PostReply reply = webInterface.getCore().getReply(id, false);
79                                 if (reply == null) {
80                                         continue;
81                                 }
82                                 JsonObject replyTime = new JsonObject();
83                                 Time time = getTime(reply.getTime());
84                                 replyTime.put("timeText", time.getText());
85                                 replyTime.put("refreshTime", time.getRefresh() / Time.SECOND);
86                                 replyTime.put("tooltip", dateFormat.format(new Date(reply.getTime())));
87                                 replyTimes.put(id, replyTime);
88                         }
89                 }
90                 return createSuccessJsonObject().put("postTimes", postTimes).put("replyTimes", replyTimes);
91         }
92
93         /**
94          * {@inheritDoc}
95          */
96         @Override
97         protected boolean needsFormPassword() {
98                 return false;
99         }
100
101         /**
102          * {@inheritDoc}
103          */
104         @Override
105         protected boolean requiresLogin() {
106                 return false;
107         }
108
109         //
110         // PRIVATE METHODS
111         //
112
113         /**
114          * Returns the formatted relative time for a given time.
115          *
116          * @param time
117          *            The time to format the difference from (in milliseconds)
118          * @return The formatted age
119          */
120         private Time getTime(long time) {
121                 return getTime(webInterface, time);
122         }
123
124         //
125         // STATIC METHODS
126         //
127
128         /**
129          * Returns the formatted relative time for a given time.
130          *
131          * @param webInterface
132          *            The Sone web interface (for l10n access)
133          * @param time
134          *            The time to format the difference from (in milliseconds)
135          * @return The formatted age
136          */
137         public static Time getTime(WebInterface webInterface, long time) {
138                 if (time == 0) {
139                         return new Time(webInterface.getL10n().getString("View.Sone.Text.UnknownDate"), 12 * Time.HOUR);
140                 }
141                 long age = System.currentTimeMillis() - time;
142                 String text;
143                 long refresh;
144                 if (age < 0) {
145                         text = webInterface.getL10n().getDefaultString("View.Time.InTheFuture");
146                         refresh = 5 * Time.MINUTE;
147                 } else if (age < 20 * Time.SECOND) {
148                         text = webInterface.getL10n().getDefaultString("View.Time.AFewSecondsAgo");
149                         refresh = 10 * Time.SECOND;
150                 } else if (age < 45 * Time.SECOND) {
151                         text = webInterface.getL10n().getString("View.Time.HalfAMinuteAgo");
152                         refresh = 20 * Time.SECOND;
153                 } else if (age < 90 * Time.SECOND) {
154                         text = webInterface.getL10n().getString("View.Time.AMinuteAgo");
155                         refresh = Time.MINUTE;
156                 } else if (age < 30 * Time.MINUTE) {
157                         text = webInterface.getL10n().getString("View.Time.XMinutesAgo", "min", String.valueOf((int) (Digits.round(age, Time.MINUTE) / Time.MINUTE)));
158                         refresh = 1 * Time.MINUTE;
159                 } else if (age < 45 * Time.MINUTE) {
160                         text = webInterface.getL10n().getString("View.Time.HalfAnHourAgo");
161                         refresh = 10 * Time.MINUTE;
162                 } else if (age < 90 * Time.MINUTE) {
163                         text = webInterface.getL10n().getString("View.Time.AnHourAgo");
164                         refresh = Time.HOUR;
165                 } else if (age < 21 * Time.HOUR) {
166                         text = webInterface.getL10n().getString("View.Time.XHoursAgo", "hour", String.valueOf((int) (Digits.round(age, Time.HOUR) / Time.HOUR)));
167                         refresh = Time.HOUR;
168                 } else if (age < 42 * Time.HOUR) {
169                         text = webInterface.getL10n().getString("View.Time.ADayAgo");
170                         refresh = Time.DAY;
171                 } else if (age < 6 * Time.DAY) {
172                         text = webInterface.getL10n().getString("View.Time.XDaysAgo", "day", String.valueOf((int) (Digits.round(age, Time.DAY) / Time.DAY)));
173                         refresh = Time.DAY;
174                 } else if (age < 11 * Time.DAY) {
175                         text = webInterface.getL10n().getString("View.Time.AWeekAgo");
176                         refresh = Time.DAY;
177                 } else if (age < 4 * Time.WEEK) {
178                         text = webInterface.getL10n().getString("View.Time.XWeeksAgo", "week", String.valueOf((int) (Digits.round(age, Time.WEEK) / Time.WEEK)));
179                         refresh = Time.DAY;
180                 } else if (age < 6 * Time.WEEK) {
181                         text = webInterface.getL10n().getString("View.Time.AMonthAgo");
182                         refresh = Time.DAY;
183                 } else if (age < 11 * Time.MONTH) {
184                         text = webInterface.getL10n().getString("View.Time.XMonthsAgo", "month", String.valueOf((int) (Digits.round(age, Time.MONTH) / Time.MONTH)));
185                         refresh = Time.DAY;
186                 } else if (age < 18 * Time.MONTH) {
187                         text = webInterface.getL10n().getString("View.Time.AYearAgo");
188                         refresh = Time.WEEK;
189                 } else {
190                         text = webInterface.getL10n().getString("View.Time.XYearsAgo", "year", String.valueOf((int) (Digits.round(age, Time.YEAR) / Time.YEAR)));
191                         refresh = Time.WEEK;
192                 }
193                 return new Time(text, refresh);
194         }
195
196         /**
197          * Container for a formatted time.
198          *
199          * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
200          */
201         public static class Time {
202
203                 /** Number of milliseconds in a second. */
204                 private static final long SECOND = 1000;
205
206                 /** Number of milliseconds in a minute. */
207                 private static final long MINUTE = 60 * SECOND;
208
209                 /** Number of milliseconds in an hour. */
210                 private static final long HOUR = 60 * MINUTE;
211
212                 /** Number of milliseconds in a day. */
213                 private static final long DAY = 24 * HOUR;
214
215                 /** Number of milliseconds in a week. */
216                 private static final long WEEK = 7 * DAY;
217
218                 /** Number of milliseconds in a 30-day month. */
219                 private static final long MONTH = 30 * DAY;
220
221                 /** Number of milliseconds in a year. */
222                 private static final long YEAR = 365 * DAY;
223
224                 /** The formatted time. */
225                 private final String text;
226
227                 /** The time after which to refresh the time. */
228                 private final long refresh;
229
230                 /**
231                  * Creates a new formatted time container.
232                  *
233                  * @param text
234                  *            The formatted time
235                  * @param refresh
236                  *            The time after which to refresh the time (in milliseconds)
237                  */
238                 public Time(String text, long refresh) {
239                         this.text = text;
240                         this.refresh = refresh;
241                 }
242
243                 /**
244                  * Returns the formatted time.
245                  *
246                  * @return The formatted time
247                  */
248                 public String getText() {
249                         return text;
250                 }
251
252                 /**
253                  * Returns the time after which to refresh the time.
254                  *
255                  * @return The time after which to refresh the time (in milliseconds)
256                  */
257                 public long getRefresh() {
258                         return refresh;
259                 }
260
261                 /**
262                  * {@inheritDoc}
263                  */
264                 @Override
265                 public String toString() {
266                         return text;
267                 }
268
269         }
270
271 }