1 | package org.apache.velocity.app.tools; |
2 | |
3 | /* |
4 | * Copyright (c) 2001 The Java Apache Project. All rights reserved. |
5 | * |
6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions |
8 | * are met: |
9 | * |
10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. |
12 | * |
13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in |
15 | * the documentation and/or other materials provided with the |
16 | * distribution. |
17 | * |
18 | * 3. All advertising materials mentioning features or use of this |
19 | * software must display the following acknowledgment: |
20 | * "This product includes software developed by the Java Apache |
21 | * Project for use in the Apache JServ servlet engine project |
22 | * <http://java.apache.org/>." |
23 | * |
24 | * 4. The names "Apache JServ", "Apache JServ Servlet Engine", "Turbine", |
25 | * "Apache Turbine", "Turbine Project", "Apache Turbine Project" and |
26 | * "Java Apache Project" must not be used to endorse or promote products |
27 | * derived from this software without prior written permission. |
28 | * |
29 | * 5. Products derived from this software may not be called "Apache JServ" |
30 | * nor may "Apache" nor "Apache JServ" appear in their names without |
31 | * prior written permission of the Java Apache Project. |
32 | * |
33 | * 6. Redistributions of any form whatsoever must retain the following |
34 | * acknowledgment: |
35 | * "This product includes software developed by the Java Apache |
36 | * Project for use in the Apache JServ servlet engine project |
37 | * <http://java.apache.org/>." |
38 | * |
39 | * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY |
40 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
41 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
42 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE JAVA APACHE PROJECT OR |
43 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
44 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
45 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
46 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
48 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
49 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
50 | * OF THE POSSIBILITY OF SUCH DAMAGE. |
51 | * |
52 | * This software consists of voluntary contributions made by many |
53 | * individuals on behalf of the Java Apache Group. For more information |
54 | * on the Java Apache Project and the Apache JServ Servlet Engine project, |
55 | * please see <http://java.apache.org/>. |
56 | * |
57 | */ |
58 | |
59 | // Java Core Classes |
60 | import java.util.*; |
61 | import java.text.*; |
62 | import java.lang.reflect.Array; |
63 | |
64 | // Veclocity classes |
65 | import org.apache.velocity.context.*; |
66 | |
67 | /** |
68 | * Formatting tool for inserting into the Velocity WebContext. Can |
69 | * format dates or lists of objects. |
70 | * |
71 | * <p>Here's an example of some uses: |
72 | * |
73 | * <code><pre> |
74 | * $formatter.formatShortDate($object.Date) |
75 | * $formatter.formatLongDate($db.getRecord(232).getDate()) |
76 | * $formatter.formatArray($array) |
77 | * $formatter.limitLen(30, $object.Description) |
78 | * </pre></code> |
79 | * |
80 | * @author <a href="sean@somacity.com">Sean Legassick</a> |
81 | * @author <a href="dlr@collab.net">Daniel Rall</a> |
82 | * @version $Id: VelocityFormatter.java,v 1.9 2003/05/04 17:06:11 geirm Exp $ |
83 | */ |
84 | public class VelocityFormatter |
85 | { |
86 | Context context = null; |
87 | NumberFormat nf = NumberFormat.getInstance(); |
88 | |
89 | /** |
90 | * Constructor needs a backpointer to the context. |
91 | * |
92 | * @param context A Context. |
93 | */ |
94 | public VelocityFormatter(Context context) |
95 | { |
96 | this.context = context; |
97 | } |
98 | |
99 | /** |
100 | * Formats a date in <code>DateFormat.SHORT</code> style. |
101 | * |
102 | * @param date The date to format. |
103 | * @return The formatted date as text. |
104 | */ |
105 | public String formatShortDate(Date date) |
106 | { |
107 | return DateFormat.getDateInstance(DateFormat.SHORT).format(date); |
108 | } |
109 | |
110 | /** |
111 | * Formats a date in <code>DateFormat.LONG</code> style. |
112 | * |
113 | * @param date The date to format. |
114 | * @return The formatted date as text. |
115 | */ |
116 | public String formatLongDate(Date date) |
117 | { |
118 | return DateFormat.getDateInstance(DateFormat.LONG).format(date); |
119 | } |
120 | |
121 | /** |
122 | * Formats a date/time in 'short' style. |
123 | * |
124 | * @param date The date to format. |
125 | * @return The formatted date as text. |
126 | */ |
127 | public String formatShortDateTime(Date date) |
128 | { |
129 | return DateFormat |
130 | .getDateTimeInstance(DateFormat.SHORT, |
131 | DateFormat.SHORT).format(date); |
132 | } |
133 | |
134 | /** |
135 | * Formats a date/time in 'long' style. |
136 | * |
137 | * @param date The date to format. |
138 | * @return The formatted date as text. |
139 | */ |
140 | public String formatLongDateTime(Date date) |
141 | { |
142 | return DateFormat.getDateTimeInstance( |
143 | DateFormat.LONG, DateFormat.LONG).format(date); |
144 | } |
145 | |
146 | /** |
147 | * Formats an array into the form "A, B and C". |
148 | * |
149 | * @param array An Object. |
150 | * @return A String. |
151 | */ |
152 | public String formatArray(Object array) |
153 | { |
154 | return formatArray(array, ", ", " and "); |
155 | } |
156 | |
157 | /** |
158 | * Formats an array into the form |
159 | * "A<delim>B<delim>C". |
160 | * |
161 | * @param array An Object. |
162 | * @param delim A String. |
163 | * @return A String. |
164 | */ |
165 | public String formatArray(Object array, |
166 | String delim) |
167 | { |
168 | return formatArray(array, delim, delim); |
169 | } |
170 | |
171 | /** |
172 | * Formats an array into the form |
173 | * "A<delim>B<finaldelim>C". |
174 | * |
175 | * @param array An Object. |
176 | * @param delim A String. |
177 | * @param finalDelim A String. |
178 | * @return A String. |
179 | */ |
180 | public String formatArray(Object array, |
181 | String delim, |
182 | String finaldelim) |
183 | { |
184 | StringBuffer sb = new StringBuffer(); |
185 | int arrayLen = Array.getLength(array); |
186 | for (int i = 0; i < arrayLen; i++) |
187 | { |
188 | // Use the Array.get method as this will automatically |
189 | // wrap primitive types in a suitable Object-derived |
190 | // wrapper if necessary. |
191 | sb.append(Array.get(array, i).toString()); |
192 | if (i < arrayLen - 2) |
193 | { |
194 | sb.append(delim); |
195 | } |
196 | else if (i < arrayLen - 1) |
197 | { |
198 | sb.append(finaldelim); |
199 | } |
200 | } |
201 | return sb.toString(); |
202 | } |
203 | |
204 | /** |
205 | * Formats a vector into the form "A, B and C". |
206 | * |
207 | * @param list The list of elements to format. |
208 | * @return A String. |
209 | */ |
210 | public String formatVector(List list) |
211 | { |
212 | return formatVector(list, ", ", " and "); |
213 | } |
214 | |
215 | /** |
216 | * Formats a vector into the form "A<delim>B<delim>C". |
217 | * |
218 | * @param list The list of elements to format. |
219 | * @param delim A String. |
220 | * @return A String. |
221 | */ |
222 | public String formatVector(List list, |
223 | String delim) |
224 | { |
225 | return formatVector(list, delim, delim); |
226 | } |
227 | |
228 | /** |
229 | * Formats a list into the form |
230 | * "Adelim>B<finaldelim>C". |
231 | * |
232 | * @param list The list of elements to format. |
233 | * @param delim A String. |
234 | * @param finalDelim A String. |
235 | * @return A String. |
236 | */ |
237 | public String formatVector(List list, |
238 | String delim, |
239 | String finaldelim) |
240 | { |
241 | StringBuffer sb = new StringBuffer(); |
242 | int size = list.size(); |
243 | for (int i = 0; i < size; i++) |
244 | { |
245 | sb.append(list.get(i)); |
246 | if (i < size - 2) |
247 | { |
248 | sb.append(delim); |
249 | } |
250 | else if (i < size - 1) |
251 | { |
252 | sb.append(finaldelim); |
253 | } |
254 | } |
255 | return sb.toString(); |
256 | } |
257 | |
258 | /** |
259 | * Limits 'string' to 'maxlen' characters. If the string gets |
260 | * curtailed, "..." is appended to it. |
261 | * |
262 | * @param maxlen An int with the maximum length. |
263 | * @param string A String. |
264 | * @return A String. |
265 | */ |
266 | public String limitLen(int maxlen, |
267 | String string) |
268 | { |
269 | return limitLen(maxlen, string, "..."); |
270 | } |
271 | |
272 | /** |
273 | * Limits 'string' to 'maxlen' character. If the string gets |
274 | * curtailed, 'suffix' is appended to it. |
275 | * |
276 | * @param maxlen An int with the maximum length. |
277 | * @param string A String. |
278 | * @param suffix A String. |
279 | * @return A String. |
280 | */ |
281 | public String limitLen(int maxlen, |
282 | String string, |
283 | String suffix) |
284 | { |
285 | String ret = string; |
286 | if (string.length() > maxlen) |
287 | { |
288 | ret = string.substring(0, maxlen - suffix.length()) + suffix; |
289 | } |
290 | return ret; |
291 | } |
292 | |
293 | /** |
294 | * Class that returns alternating values in a template. It stores |
295 | * a list of alternate Strings, whenever alternate() is called it |
296 | * switches to the next in the list. The current alternate is |
297 | * retrieved through toString() - i.e. just by referencing the |
298 | * object in a Velocity template. For an example of usage see the |
299 | * makeAlternator() method below. |
300 | */ |
301 | public class VelocityAlternator |
302 | { |
303 | protected String[] alternates = null; |
304 | protected int current = 0; |
305 | |
306 | /** |
307 | * Constructor takes an array of Strings. |
308 | * |
309 | * @param alternates A String[]. |
310 | */ |
311 | public VelocityAlternator(String[] alternates) |
312 | { |
313 | this.alternates = alternates; |
314 | } |
315 | |
316 | /** |
317 | * Alternates to the next in the list. |
318 | * |
319 | * @return The current alternate in the sequence. |
320 | */ |
321 | public String alternate() |
322 | { |
323 | current++; |
324 | current %= alternates.length; |
325 | return ""; |
326 | } |
327 | |
328 | /** |
329 | * Returns the current alternate. |
330 | * |
331 | * @return A String. |
332 | */ |
333 | public String toString() |
334 | { |
335 | return alternates[current]; |
336 | } |
337 | } |
338 | |
339 | /** |
340 | * As VelocityAlternator, but calls <code>alternate()</code> |
341 | * automatically on rendering in a template. |
342 | */ |
343 | public class VelocityAutoAlternator extends VelocityAlternator |
344 | { |
345 | /** |
346 | * Constructor takes an array of Strings. |
347 | * |
348 | * @param alternates A String[]. |
349 | */ |
350 | public VelocityAutoAlternator(String[] alternates) |
351 | { |
352 | super(alternates); |
353 | } |
354 | |
355 | /** |
356 | * Returns the current alternate, and automatically alternates |
357 | * to the next alternate in its sequence (trigged upon |
358 | * rendering). |
359 | * |
360 | * @return The current alternate in the sequence. |
361 | */ |
362 | public final String toString() |
363 | { |
364 | String s = alternates[current]; |
365 | alternate(); |
366 | return s; |
367 | } |
368 | } |
369 | |
370 | /** |
371 | * Makes an alternator object that alternates between two values. |
372 | * |
373 | * <p>Example usage in a Velocity template: |
374 | * |
375 | * <code><pre> |
376 | * <table> |
377 | * $formatter.makeAlternator("rowcolor", "#c0c0c0", "#e0e0e0") |
378 | * #foreach $item in $items |
379 | * #begin |
380 | * <tr><td bgcolor="$rowcolor">$item.Name</td></tr> |
381 | * $rowcolor.alternate() |
382 | * #end |
383 | * </table> |
384 | * </pre></code> |
385 | * |
386 | * @param name The name for the alternator int the context. |
387 | * @param alt1 The first alternate. |
388 | * @param alt2 The second alternate. |
389 | * @return The newly created instance. |
390 | */ |
391 | public String makeAlternator(String name, |
392 | String alt1, |
393 | String alt2) |
394 | { |
395 | String[] alternates = { alt1, alt2 }; |
396 | context.put(name, new VelocityAlternator(alternates)); |
397 | return ""; |
398 | } |
399 | |
400 | /** |
401 | * Makes an alternator object that alternates between three |
402 | * values. |
403 | * |
404 | * @see #makeAlternator(String name, String alt1, String alt2) |
405 | */ |
406 | public String makeAlternator(String name, |
407 | String alt1, |
408 | String alt2, |
409 | String alt3) |
410 | { |
411 | String[] alternates = { alt1, alt2, alt3 }; |
412 | context.put(name, new VelocityAlternator(alternates)); |
413 | return ""; |
414 | } |
415 | |
416 | /** |
417 | * Makes an alternator object that alternates between four values. |
418 | * |
419 | * @see #makeAlternator(String name, String alt1, String alt2) |
420 | */ |
421 | public String makeAlternator(String name, String alt1, String alt2, |
422 | String alt3, String alt4) |
423 | { |
424 | String[] alternates = { alt1, alt2, alt3, alt4 }; |
425 | context.put(name, new VelocityAlternator(alternates)); |
426 | return ""; |
427 | } |
428 | |
429 | /** |
430 | * Makes an alternator object that alternates between two values |
431 | * automatically. |
432 | * |
433 | * @see #makeAlternator(String name, String alt1, String alt2) |
434 | */ |
435 | public String makeAutoAlternator(String name, String alt1, String alt2) |
436 | { |
437 | String[] alternates = { alt1, alt2 }; |
438 | context.put(name, new VelocityAutoAlternator(alternates)); |
439 | return ""; |
440 | } |
441 | |
442 | /** |
443 | * Returns a default value if the object passed is null. |
444 | */ |
445 | public Object isNull(Object o, Object dflt) |
446 | { |
447 | if ( o == null ) |
448 | { |
449 | return dflt; |
450 | } |
451 | else |
452 | { |
453 | return o; |
454 | } |
455 | } |
456 | } |