/* * This software is distributed under the terms of the FSF * Gnu Lesser General Public License (see lgpl.txt). * * This program is distributed WITHOUT ANY WARRANTY. See the * GNU General Public License for more details. */ package com.scooterframework.web.util; import java.text.DecimalFormat; import java.text.Format; import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.Map; import com.scooterframework.common.util.DateUtil; import com.scooterframework.common.util.Util; import com.scooterframework.common.util.WordUtil; import com.scooterframework.web.controller.ACH; /** * T(TextHelper) class has helper methods for rendering a text or munipulating * a string. <br/> * * This class is for generic objects. It does not render an ActiveRecord * object. Use O(ObjectHelper) for that purpose.<br/> * * * @author (Fei) John Chen */ public class T { //========================================================= // Generic //========================================================= /** * Returns a string based on true or false of <tt>choice</tt>. * * @return <tt>wordTrue</tt> if choice is true. */ public static String booleanWord(boolean choice, String wordTrue, String wordFalse) { return (choice)?wordTrue:wordFalse; } /** * Returns a pluralized word if the count is more than one. * * @return pluralized string */ public static String pluralize(int count, String word) { String plform = (count <=1 || word == null)?word:(WordUtil.pluralize(word)); return pluralize(count, word, plform); } /** * Returns a pluralized word if the count is more than one. * * @return pluralized string */ public static String pluralize(int count, String word, String plform) { return count + " " + ((count > 1)?plform:word); } /** * Returns a pluralized word if the count is more than one. * * @return pluralized string */ public static String pluralize(Object count, String word) { return pluralize(Util.getSafeIntValue(count), word); } /** * Returns a pluralized word if the count is more than one. * * @return pluralized string */ public static String pluralize(Object count, String word, String plform) { return pluralize(Util.getSafeIntValue(count), word, plform); } //========================================================= // Object Related //========================================================= /** * Returns text of an object with default locale. * * @param data the object * @return text of data */ public static String text(Object data) { return text(data, null); } /** * Returns text of an object in a certain pattern with default locale. * * @param data the object * @param pattern the pattern of result text * @return text of data */ public static String text(Object data, String pattern) { return text(data, pattern, ACH.getAC().getLocale()); } /** * Returns text of an object in a certain pattern and locale. * * @param data the object * @param pattern the pattern of result text * @param locale the locale of result text * @return text of data */ public static String text(Object data, String pattern, Locale locale) { if (data == null) return ""; String result = ""; if (data instanceof String) { result = (String)data; } else if (data instanceof Date) { result = textOfDate(data, pattern, locale); } else if (data instanceof Number) { result = textOfNumber(data, pattern, locale); } else if (data instanceof Object[]) { throw new IllegalArgumentException("text() does not handle array type."); } else { result = data.toString(); } return (result != null)?result:""; } /** * Returns text of an object of a type. * * @param data the object * @param type data type (1=Currency, 2=Date, 3=Number) * @return text of data */ public static String text(Object data, int type) { return text(data, type, null); } /** * Returns text of an object of a type in a certain pattern with default locale. * * @param data the object * @param type data type (1=Currency, 2=Date, 3=Number) * @param pattern the pattern of result text * @return text of data */ public static String text(Object data, int type, String pattern) { return text(data, type, pattern, ACH.getAC().getLocale()); } /** * Returns text of an object of a type in a certain pattern and locale. * * @param data the object * @param type data type (1=Currency, 2=Date, 3=Number) * @param pattern the pattern of result text * @param locale the locale of result text * @return text of data */ public static String text(Object data, int type, String pattern, Locale locale) { if (data == null) return ""; String result = ""; switch (type) { case NUMBER: result = textOfNumber(data, pattern, locale); break; case DATE: result = textOfDate(data, pattern, locale); break; case CURRENCY: result = textOfCurrency(data, locale); break; default: result = text(data, pattern, locale); } return (result != null)?result:""; } //========================================================= // Number Related //========================================================= /** * Checks if a data object is a numberic data. A string value can be numeric * too if it can be converted to a number. * * @param data * @return true if the data represents a number. */ public static boolean isNumeric(Object data) { if (data == null) return false; if (data instanceof Number) return true; if (data instanceof Object[]) throw new IllegalArgumentException("isNumeric(s) does not handle array type."); boolean numeric = true; try { new Double(data.toString()); } catch(Exception ex) { numeric = false; } return numeric; } /** * Returns a text of number with a certain precision. * * First group the number into thousands and round it to the number of * decimal places specified by precision. * * This method is exactly the same as <tt>textOfNumber(Object number, int precision)</tt>. * * @param data the object * @param precision number of decimal needed * @return a number text */ public static String numberFormat(Object data, int precision) { return textOfNumber(data, precision); } /** * Returns a text of number with a certain precision. * * First group the number into thousands and round it to the number of * decimal places specified by precision. * * @param number the object * @param precision number of decimal needed * @return a number text */ public static String textOfNumber(Object number, int precision) { String formatString = "#,###"; if (precision > 0) formatString += "."; for (int i=0; i<precision; i++) { formatString += "0"; } return textOfNumber(number, formatString); } /** * Returns a text of number. * * @param number the object * @return a number text */ public static String textOfNumber(Object number) { return textOfNumber(number, null, ACH.getAC().getLocale()); } /** * Returns a text of number. * * @param number the object * @param pattern the pattern format of the result * @return a number text */ public static String textOfNumber(Object number, String pattern) { return textOfNumber(number, pattern, ACH.getAC().getLocale()); } /** * Returns a text of number. * * @param number the object * @param pattern the pattern format of the result * @param locale the locale of the result * @return a number text */ public static String textOfNumber(Object number, String pattern, Locale locale) { if (number == null) return ""; if (pattern == null || "".equals(pattern)) return number.toString(); if (locale == null) locale = ACH.getAC().getLocale(); String formattedValue = ""; try { Format nf = NumberFormat.getNumberInstance(locale); if (pattern != null && !"".equals(pattern)) { ((DecimalFormat)nf).applyPattern(pattern); } if (number instanceof Number) { formattedValue = nf.format(number); } else { if (number instanceof String) { formattedValue = nf.format(new Double((String)number)); } } } catch(NumberFormatException ex) { ; } return formattedValue; } //========================================================= // Currency Related //========================================================= /** * Returns a text of currency. * * @param number the number * @return a currency text */ public static String textOfCurrency(Object number) { return textOfCurrency(number, ACH.getAC().getLocale()); } /** * Returns a text of currency. * * @param number the number * @param locale the locale of the result * @return a currency text */ public static String textOfCurrency(Object number, Locale locale) { if (number == null) return ""; if (number instanceof Object[]) throw new IllegalArgumentException("textOfCurrency() does not handle array type."); return textOfCurrency(number.toString(), locale); } /** * Returns a text of currency. * * @param number the number * @param locale the locale of the result * @return a currency text */ public static String textOfCurrency(String number, Locale locale) { if (number == null || "".equals(number.trim())) return ""; return textOfCurrency((new Double(number)).doubleValue(), locale); } /** * Returns a text of currency. * * @param number the number * @return a currency text */ public static String textOfCurrency(float number) { return textOfCurrency(number, ACH.getAC().getLocale()); } /** * Returns a text of currency. * * @param number the number * @param locale the locale of the result * @return a currency text */ public static String textOfCurrency(float number, Locale locale) { NumberFormat formatter = NumberFormat.getCurrencyInstance(locale); return formatter.format(number); } /** * Returns a text of currency. * * @param number the number * @return a currency text */ public static String textOfCurrency(double number) { return textOfCurrency(number, ACH.getAC().getLocale()); } /** * Returns a text of currency. * * @param number the number * @param locale the locale of the result * @return a currency text */ public static String textOfCurrency(double number, Locale locale) { NumberFormat formatter = NumberFormat.getCurrencyInstance(locale); return formatter.format(number); } /** * Returns a text of currency. * * @param number the number * @return a currency text */ public static String textOfCurrency(int number) { return textOfCurrency(number, ACH.getAC().getLocale()); } /** * Returns a text of currency. * * @param number the number * @param locale the locale of the result * @return a currency text */ public static String textOfCurrency(int number, Locale locale) { NumberFormat formatter = NumberFormat.getCurrencyInstance(locale); return formatter.format(number); } /** * Returns a text of currency. * * @param number the number * @return a currency text */ public static String textOfCurrency(long number) { return textOfCurrency(number, ACH.getAC().getLocale()); } /** * Returns a text of currency. * * @param number the number * @param locale the locale of the result * @return a currency text */ public static String textOfCurrency(long number, Locale locale) { NumberFormat formatter = NumberFormat.getCurrencyInstance(locale); return formatter.format(number); } //========================================================= // Date Related //========================================================= /** * Returns a map of current date and time. Keys in the map are * <tt>year</tt>, <tt>mon</tt>, <tt>month</tt>, <tt>mday</tt>, <tt>weekday</tt>, * <tt>hours</tt>, <tt>minutes</tt>, <tt>seconds</tt>, <tt>mills</tt> and <tt>timeinmillis</tt>. * * <pre> * Example: * Key Value * ----- ------- * year 2007 * mon 7 * month July * mday 18 * weekday Wednesday * hours 0 * minutes 39 * seconds 24 * mills 354 * timeinmillis 1184776764354 * </pre> * * @return Map */ public static Map<String, String> getDateAsMap() { String[] months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; String[] weekdays = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; Map<String, String> map = new HashMap<String, String>(); Calendar calendar = Calendar.getInstance(); map.put("year", "" + calendar.get(Calendar.YEAR)); map.put("mon", "" + (calendar.get(Calendar.MONTH) + 1)); map.put("month", months[calendar.get(Calendar.MONTH)]); map.put("mday", "" + calendar.get(Calendar.DATE)); map.put("weekday", "" + weekdays[calendar.get(Calendar.DAY_OF_WEEK)-1]); map.put("hours", "" + calendar.get(Calendar.HOUR)); map.put("minutes", "" + calendar.get(Calendar.MINUTE)); map.put("seconds", "" + calendar.get(Calendar.SECOND)); map.put("mills", "" + calendar.get(Calendar.MILLISECOND)); map.put("timeinmillis", "" + calendar.getTimeInMillis()); return map; } /** * Returns a property from a map of current date and time. Keys in the map are * year, mon, month, mday, weekday, hours, minutes, seconds, mills. * * <ptr> * Example: * Key Value * ----- ------- * year 2007 * mon 7 * month July * mday 18 * weekday Wednesday * hours 0 * minutes 39 * seconds 24 * mills 354 * timeinmillis 1184776764354 * </pre> * * @return Map */ public static String getDateProperty(String key) { return (String)getDateAsMap().get(key); } /** * Returns text of a date object. * * @param date the object * @return text of date */ public static String textOfDate(Object date) { return textOfDate(date, null, ACH.getAC().getLocale()); } /** * <p>Returns text of a date object for a certain pattern.</p> * * <p>If the result of this method is used in an html form and will be * parsed automatically by Scooter, not all patterns are allowed. * * The allowed patterns are listed in the description of * {@link com.scooterframework.common.util.DateUtil#getDateTimePattern(String)} * method. Other kind of patterns may result in null value.</p> * * @param date the object * @param pattern the pattern of result text * @return text of date */ public static String textOfDate(Object date, String pattern) { return textOfDate(date, pattern, ACH.getAC().getLocale()); } /** * <p>Returns text of a date object for a certain pattern and locale.</p> * * <p>If the result of this method is used in an html form and will be * parsed automatically by Scooter, not all patterns are allowed. * * The allowed patterns are listed in the description of * {@link com.scooterframework.common.util.DateUtil#getDateTimePattern(String)} * method. Other kind of patterns may result in null value.</p> * * <p>If the gived pattern is empty and the date object is of Date type, * then a default pattern "yyyy-MM-dd HH:mm:ss" is used. </p> * * @param date the object * @param pattern the pattern of result text * @param locale the locale of result text * @return text of date */ public static String textOfDate(Object date, String pattern, Locale locale) { if (date == null) return ""; if (locale == null) locale = ACH.getAC().getLocale(); Object theValue = null; if (date instanceof String) { theValue = DateUtil.parseDate((String)date, pattern, locale); if (theValue == null) return ""; } else if (date instanceof Date) { theValue = date; } else if (date instanceof Object[]) { throw new IllegalArgumentException("textOfDate() does not handle array type."); } else { return date.toString(); } if (pattern == null || "".equals(pattern)) { //return DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG, locale).format(theValue); //This caused automcatic form processing to fail because DateUtil can not parse this date pattern. pattern = "yyyy-MM-dd HH:mm:ss"; } SimpleDateFormat sdf = new SimpleDateFormat(pattern, locale); return sdf.format((Date)theValue); } /** * int constant represents unknown data type. */ public static final int UNKNOWN = 0; /** * int constant represents currency data type. */ public static final int CURRENCY = 1; /** * int constant represents date data type. */ public static final int DATE = 2; /** * int constant represents numberic data type. */ public static final int NUMBER = 3; }