javacommons/utils/javasrc/com/nokia/mj/impl/utils/Formatter.java
branchRCL_3
changeset 19 04becd199f91
child 23 98ccebc37403
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 package com.nokia.mj.impl.utils;
       
    20 
       
    21 import java.util.Date;
       
    22 
       
    23 /**
       
    24  * Utility for formatting text strings from a pattern with positional
       
    25  * parameters.
       
    26  * <br>
       
    27  * Supported parameters are:
       
    28  * <UL>
       
    29  * <LI>%nU - String in position n
       
    30  * <LI>%U - Next string
       
    31  * <LI>%nN - Integer in position n
       
    32  * <LI>%N - Next integer
       
    33  * <LI>%nC - Character in position n
       
    34  * <LI>%C - Next character
       
    35  * <LI>%n - Parameter in position n
       
    36  * </UL>
       
    37  * <br>
       
    38  * Example of usage:
       
    39  * <pre>
       
    40  *   Formatter formatter = new Formatter("You have %N email(s) left");
       
    41  *   String message = formatter.arg(5).toString();
       
    42  *   // Becomes :You have 5 email(s) left
       
    43  *
       
    44  *   Formatter formatter = new Formatter("There are %N0 files in folder \"%U1\"");
       
    45  *   String message = formatter.arg(5).arg("photos").toString();
       
    46  *   // Becomes :There are 5 files in folder "photos"
       
    47  * </pre>
       
    48  * <br>
       
    49  * Limitation: more than 10 positional arguments are not supported (only 0...9)
       
    50  *
       
    51  * @author Nokia Corporation
       
    52  * @version 1.0
       
    53  */
       
    54 public class Formatter
       
    55 {
       
    56     /** Original pattern string */
       
    57     private String pattern;
       
    58 
       
    59     /** String with latest replacements */
       
    60     private String replaced;
       
    61 
       
    62     /** Next replacement index */
       
    63     private int nextIndex = 0;
       
    64 
       
    65     /*** ----------------------------- PUBLIC ------------------------------ */
       
    66 
       
    67     /**
       
    68      * Create a new formatter
       
    69      *
       
    70      * @param pattern formatter pattern
       
    71      */
       
    72     public Formatter(String aPattern)
       
    73     {
       
    74         pattern = aPattern;
       
    75         replaced = aPattern;
       
    76     }
       
    77 
       
    78     /**
       
    79      * Replace the lowest numbered parameter in the string, which is not yet
       
    80      * replaced.
       
    81      *
       
    82      * @param string string to replace at the argument
       
    83      * @return same formatter
       
    84      */
       
    85     public Formatter arg(String string)
       
    86     {
       
    87         // Try to replace with patterns %nU,%n, %U
       
    88         if (replace("%" + nextIndex + "U", string) ||
       
    89                 replace("%" + nextIndex, string) ||
       
    90                 replace("%U", string))
       
    91         {
       
    92             nextIndex++;
       
    93 
       
    94         }
       
    95         else
       
    96         {
       
    97             Logger.WLOG(Logger.EUtils, "String replacement failed");
       
    98         }
       
    99         return this;
       
   100     }
       
   101 
       
   102     /**
       
   103      * Replace the least numbered parameter in the string, which is not yet
       
   104      * replaced.
       
   105      *
       
   106      * @param number number to replace at the argument
       
   107      * @return same formatter
       
   108      */
       
   109     public Formatter arg(int number)
       
   110     {
       
   111         String localisedNumber = _formatInteger(number);
       
   112 
       
   113         // Try to replace with patterns %nN, %n, %N
       
   114         if (replace("%" + nextIndex + "N", localisedNumber) ||
       
   115                 replace("%" + nextIndex, localisedNumber) ||
       
   116                 replace("%N", localisedNumber))
       
   117         {
       
   118             nextIndex++;
       
   119 
       
   120         }
       
   121         else
       
   122         {
       
   123             Logger.WLOG(Logger.EUtils, "Integer replacement failed");
       
   124         }
       
   125         return this;
       
   126     }
       
   127 
       
   128     /**
       
   129      * Replace the least numbered parameter in the string, which is not yet
       
   130      * replaced.
       
   131      *
       
   132      * @param ch character to replace at the argument
       
   133      * @return same formatter
       
   134      */
       
   135     public Formatter arg(char ch)
       
   136     {
       
   137         String chString = new String(new char[] { ch });
       
   138 
       
   139         // Try to replace with patterns %nC,%n, %C
       
   140         if (replace("%" + nextIndex + "C", chString) ||
       
   141                 replace("%" + nextIndex, chString) ||
       
   142                 replace("%C", chString))
       
   143         {
       
   144             nextIndex++;
       
   145 
       
   146         }
       
   147         else
       
   148         {
       
   149             Logger.WLOG(Logger.EUtils, "Character replacement failed");
       
   150         }
       
   151         return this;
       
   152     }
       
   153 
       
   154     /**
       
   155      * Replace the least numbered parameter in the string, which is not yet
       
   156      * replaced. Date is formatted according to current device date format.
       
   157      *
       
   158      * @param date date to replace at the argument
       
   159      * @return same formatter
       
   160      */
       
   161     public Formatter arg(Date date)
       
   162     {
       
   163         String dateString = _formatDate(date.getTime());
       
   164         return arg(dateString);
       
   165     }
       
   166 
       
   167     /**
       
   168      * Replace the least numbered parameter in the string, which is not yet
       
   169      * replaced.
       
   170      *
       
   171      * @param o object whose toString() will be used for argument position
       
   172      * @return same formatter
       
   173      */
       
   174     public Formatter arg(Object o)
       
   175     {
       
   176         if (o != null)
       
   177         {
       
   178             if (o instanceof String)
       
   179             {
       
   180                 return arg((String) o);
       
   181             }
       
   182             else if (o instanceof Integer)
       
   183             {
       
   184                 return arg(((Integer) o).intValue());
       
   185             }
       
   186             else if (o instanceof Character)
       
   187             {
       
   188                 return arg(((Character) o).charValue());
       
   189             }
       
   190             else if (o instanceof Date)
       
   191             {
       
   192                 return arg((Date) o);
       
   193             }
       
   194             // Skip not supported types.
       
   195         }
       
   196         return this;
       
   197     }
       
   198 
       
   199     /**
       
   200      * Convert the current pattern to string, along with parameter
       
   201      * replacements.
       
   202      *
       
   203      * @return string where parameters are replaced
       
   204      */
       
   205     public String toString()
       
   206     {
       
   207         String result = replaced;
       
   208 
       
   209         // Reset for next usage
       
   210         replaced = pattern;
       
   211         nextIndex = 0;
       
   212 
       
   213         return result;
       
   214     }
       
   215 
       
   216     /**
       
   217      * Gets a clone of this formatter. This can be used for caching preparsed
       
   218      * Formatters.
       
   219      *
       
   220      * @return clone of the formatter, as if new Formatter were created with
       
   221      * same pattern as current one.
       
   222      */
       
   223     public Formatter getClone()
       
   224     {
       
   225         return new Formatter(pattern);
       
   226     }
       
   227 
       
   228     /**
       
   229      * Formats localised text with specified parameters from an array.
       
   230      *
       
   231      * Note that the arg().arg().toString() is preferred method of
       
   232      * usage. E.g. Date format type can not be defined with this method.
       
   233      *
       
   234      * @param textParameters parameters to be filled into the text
       
   235      * @return localised text formatted with the provided parameters
       
   236      */
       
   237     public String format(Object[] textParameters)
       
   238     {
       
   239         if (textParameters != null)
       
   240         {
       
   241             for (int i = 0; i < textParameters.length; i++)
       
   242             {
       
   243                 if (textParameters[i] instanceof String)
       
   244                 {
       
   245                     arg((String)textParameters[i]);
       
   246                 }
       
   247                 else if (textParameters[i] instanceof Integer)
       
   248                 {
       
   249                     arg(((Integer)textParameters[i]).intValue());
       
   250                 }
       
   251                 else if (textParameters[i] instanceof Date)
       
   252                 {
       
   253                     arg((Date)textParameters[i]);
       
   254                 }
       
   255                 else
       
   256                 {
       
   257                     arg(textParameters[i]);
       
   258                 }
       
   259             }
       
   260         }
       
   261         return toString();
       
   262     }
       
   263 
       
   264     /*** ----------------------------- PRIVATE ---------------------------- */
       
   265 
       
   266     /**
       
   267      * Replace first occurrence of the string pattern in the replaced field.
       
   268      *
       
   269      * @param pattern string to search for
       
   270      * @param replacement string to replace patterns
       
   271      * @return true if pattern was found and replaced, false if pattern was
       
   272      *         not found
       
   273      */
       
   274     private boolean replace(String pattern, String replacement)
       
   275     {
       
   276         int index = replaced.indexOf(pattern);
       
   277         if (index != -1)
       
   278         {
       
   279             if (replaced.indexOf(pattern + "[]") != -1)
       
   280             {
       
   281                 replaced =
       
   282                     replaced.substring(0, index) + replacement +
       
   283                     replaced.substring(index + pattern.length() + 2);
       
   284             }
       
   285             else if (replaced.indexOf(pattern + "[") != -1)
       
   286             {
       
   287                 return replaceWithMax(pattern, replacement, index);
       
   288             }
       
   289             else
       
   290             {
       
   291                 replaced =
       
   292                     replaced.substring(0, index) + replacement +
       
   293                     replaced.substring(index + pattern.length());
       
   294             }
       
   295             return true;
       
   296         }
       
   297         return false;
       
   298     }
       
   299 
       
   300     /**
       
   301      * Replace first occurrence of the string pattern in the replaced field.
       
   302      * Replace only [NN] defined amount of characters.
       
   303      *
       
   304      * @param pattern string to search for
       
   305      * @param replacement string to replace patterns
       
   306      * @param index of replacement tag.
       
   307      * @return true if pattern was found and replaced, false if pattern was
       
   308      *         not found
       
   309      */
       
   310     private boolean replaceWithMax(String pattern, String replacement, int maxIndex)
       
   311     {
       
   312         boolean result = false;
       
   313         int closingIndex = maxIndex + pattern.length() + 3;
       
   314 
       
   315         // Check format [NN] comply. If not skip.
       
   316         if (replaced.length() > closingIndex
       
   317                 && replaced.charAt(closingIndex) == ']')
       
   318         {
       
   319             try
       
   320             {
       
   321                 int maxLen = Integer.parseInt(replaced.substring(
       
   322                                                   maxIndex + pattern.length() + 1, closingIndex));
       
   323 
       
   324                 if (maxLen > replacement.length())
       
   325                 {
       
   326                     maxLen = replacement.length();
       
   327                 }
       
   328 
       
   329                 replaced = replaced.substring(0, maxIndex) +
       
   330                            replacement.substring(0, maxLen) +
       
   331                            replaced.substring(maxIndex + pattern.length() + 4);
       
   332                 result = true;
       
   333             }
       
   334             catch (NumberFormatException nfe)
       
   335             {
       
   336                 Logger.WLOG(Logger.EUtils, "Replace with max failed to invalid"
       
   337                             + " replacement amount");
       
   338             }
       
   339         }
       
   340         return result;
       
   341     }
       
   342 
       
   343     /*** ----------------------------- NATIVE ----------------------------- */
       
   344 
       
   345     /**
       
   346      * Format integer to current locale.
       
   347      *
       
   348      * @param number to be formatted.
       
   349      * @return number formatted as current locale String.
       
   350      */
       
   351     private native String _formatInteger(int number);
       
   352 
       
   353     /**
       
   354      * Format date to current locale.
       
   355      *
       
   356      * @param timeInMilliSecs to be formatted.
       
   357      * @param format Date format.
       
   358      * @return date formatted as current locale String.
       
   359      *
       
   360      */
       
   361     private native String _formatDate(long timeInMilliSecs);
       
   362 }