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