You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ma...@apache.org on 2007/07/25 17:13:59 UTC

svn commit: r559487 - in /myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main: java/org/apache/myfaces/trinidadinternal/convert/ java/org/apache/myfaces/trinidadinternal/resource/ javascript/META-INF/adf/jsLibs/

Author: matzew
Date: Wed Jul 25 08:13:59 2007
New Revision: 559487

URL: http://svn.apache.org/viewvc?view=rev&rev=559487
Log:
moved commit to another branch (as well)

Added:
    myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/NumberFormat.js
Modified:
    myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/convert/NumberConverter.java
    myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/CoreCommonScriptsResourceLoader.java
    myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/CoreFormat.js

Modified: myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/convert/NumberConverter.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/convert/NumberConverter.java?view=diff&rev=559487&r1=559486&r2=559487
==============================================================================
--- myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/convert/NumberConverter.java (original)
+++ myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/convert/NumberConverter.java Wed Jul 25 08:13:59 2007
@@ -21,7 +21,6 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.Locale;
 import java.util.Map;
 
 import javax.faces.component.UIComponent;
@@ -79,13 +78,17 @@
   public String getClientConversion(FacesContext context, UIComponent component)
   {
     String hintPattern = this.getHintPattern();
-    String messageDetailConvertNumber = this.getMessageDetailConvertNumber();
+    String messageDetailConvertNumber   = this.getMessageDetailConvertNumber();
+    String messageDetailConvertPercent  = this.getMessageDetailConvertPercent();
+    String messageDetailConvertCurrency = this.getMessageDetailConvertCurrency();
     Map<String, String> cMessages = null;
-    if(hintPattern != null || messageDetailConvertNumber != null)
+    if(hintPattern != null || messageDetailConvertNumber != null || messageDetailConvertPercent != null || messageDetailConvertCurrency != null)
     {
       cMessages = new HashMap<String, String>();
       cMessages.put("hintPattern", hintPattern);
       cMessages.put("number", messageDetailConvertNumber);
+      cMessages.put("percent", messageDetailConvertPercent);
+      cMessages.put("currency", messageDetailConvertCurrency);
     }
     
     return _getTrNumberConverter(context, component, cMessages);
@@ -106,16 +109,67 @@
     return null;
   }
   
+  /**
+   * Helper method, that creates an Object array, which contains all
+   * required constructor parameters for the TrNumberConverter class.
+   * 
+   * TrNumberConverter takes several arguments, like pattern or type.
+   * It also takes some arguments that are only useful, when displaying
+   * formatted numbers, like currencyCode or maximumIntegerDigits.
+   * 
+   */
+  private Object[] _getClientConstructorParams(Map<?, ?> messages)
+  {
+    Object[] params;
+    boolean formating = _formatingAttributesSet();
+
+    if(formating)
+      params = new Object[10];
+    else
+      params = new Object[4];
+    params[0] = this.getPattern();
+    params[1] = this.getType();
+    params[2] = this.getLocale() != null ? this.getLocale().toString() : null;
+    params[3] = messages;
+    
+    //TODO we don't really need these attributes all the time,
+    //only if specified.
+    if(formating)
+    {
+      params[4] = this.getCurrencyCode();
+      params[5] = this.getCurrencySymbol();
+      params[6] = this.isMaximumFractionDigitsSet() ? this.getMaxFractionDigits() : null;
+      params[7] = this.isMaximumIntegerDigitsSet() ? this.getMaxIntegerDigits() : null;
+      params[8] = this.isMinimumFractionDigitsSet() ? this.getMinFractionDigits() : null;
+      params[9] = this.isMinimumIntegerDigitsSet() ? this.getMinIntegerDigits() : null;
+    }
+
+    return params;
+  }
+  
+  /*
+   * checks if the attributes, that are interesting for
+   * formating only are applied.
+   */
+  private boolean _formatingAttributesSet()
+  {
+    return (this.getCurrencyCode()!=null ||
+      this.getCurrencySymbol() != null ||
+      this.isMaximumFractionDigitsSet() ||
+      this.isMaximumIntegerDigitsSet() ||
+      this.isMinimumFractionDigitsSet() ||
+      this.isMinimumIntegerDigitsSet());
+  }
+  
   private String _getTrNumberConverter(
       FacesContext context,
       UIComponent  component,
       Map<?, ?>    messages)
     {
   
-      String pattern = this.getPattern();
       StringBuilder outBuffer = new StringBuilder(250);
       
-      if(this.isIntegerOnly() && pattern == null)
+      if(this.isIntegerOnly() && this.getPattern() == null)
       {
         outBuffer.append("new TrIntegerConverter(");
         outBuffer.append("null,null,0,");
@@ -126,49 +180,26 @@
       }
       else
       {
-        outBuffer.append("new TrNumberConverter(");
 
-        String type = this.getType();
-        String localeString = null;
-        Locale locale = this.getLocale();
-        if(locale != null)
-        localeString = locale.toString();
+        Object[] params = _getClientConstructorParams(messages);
+        
+        outBuffer.append("new TrNumberConverter(");
 
-        try
-        {
-          JsonUtils.writeString(outBuffer, pattern, false); 
-        } catch (Exception e)
-        {
-          outBuffer.append("null");
-        }
-        outBuffer.append(',');
-        try
-        {
-          JsonUtils.writeString(outBuffer, type, false);
-        } catch (Exception e)
-        {
-          outBuffer.append("null");
-        }
-        outBuffer.append(',');
-        try
+        for (int i = 0; i < params.length; i++)
         {
-          JsonUtils.writeString(outBuffer, localeString, false);
-        } catch (Exception e)
-        {
-          outBuffer.append("null");
-        }
-        outBuffer.append(',');
-        try
-        {
-          JsonUtils.writeMap(outBuffer, messages, false); 
-        } catch (Exception e)
-        {
-          outBuffer.append("null");
+          try
+          {
+            JsonUtils.writeObject(outBuffer, params[i], false); 
+          } catch (Exception e)
+          {
+            outBuffer.append("null");
+          }
+          if(i<params.length-1)
+            outBuffer.append(',');
         }
         outBuffer.append(')');
       }
-
       return outBuffer.toString();
     }
   private static final Collection<String> _IMPORT_NAMES = Collections.singletonList( "TrNumberConverter()" );
-}
+}
\ No newline at end of file

Modified: myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/CoreCommonScriptsResourceLoader.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/CoreCommonScriptsResourceLoader.java?view=diff&rev=559487&r1=559486&r2=559487
==============================================================================
--- myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/CoreCommonScriptsResourceLoader.java (original)
+++ myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/CoreCommonScriptsResourceLoader.java Wed Jul 25 08:13:59 2007
@@ -55,6 +55,7 @@
   static private final String[] _LIBRARIES =
   {
     "META-INF/adf/jsLibs/CharSets.js",
+    "META-INF/adf/jsLibs/NumberFormat.js",
     "META-INF/adf/jsLibs/CoreFormat.js",
     "META-INF/adf/jsLibs/DateField.js",
     "META-INF/adf/jsLibs/DateFieldFormat.js",
@@ -75,6 +76,7 @@
   static private final String[] _DEBUG_LIBRARIES =
   {
     "META-INF/adf/jsLibsDebug/CharSets.js",
+    "META-INF/adf/jsLibsDebug/NumberFormat.js",
     "META-INF/adf/jsLibsDebug/CoreFormat.js",
     "META-INF/adf/jsLibsDebug/DateField.js",
     "META-INF/adf/jsLibsDebug/DateFieldFormat.js",
@@ -92,4 +94,4 @@
   };
 
   static private final String _NEWLINE_SEPARATOR = "\n";
-}
+}
\ No newline at end of file

Modified: myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/CoreFormat.js
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/CoreFormat.js?view=diff&rev=559487&r1=559486&r2=559487
==============================================================================
--- myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/CoreFormat.js (original)
+++ myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/CoreFormat.js Wed Jul 25 08:13:59 2007
@@ -16,19 +16,46 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
+ 
+/**
+ * constructor of client side NumberConverter class
+ */ 
 function TrNumberConverter(
   pattern,  
   type,
   locale,
-  messages)
+  messages,
+  currencyCode,
+  currencySymbol,
+  maxFractionDigits,
+  maxIntegerDigits,
+  minFractionDigits,
+  minIntegerDigits)
 {
   this._pattern = pattern;
   this._type = type;
   this._locale = locale;
   this._messages = messages;
+  this._currencyCode = currencyCode;
+  this._currencySymbol = currencySymbol;
+  this._maxFractionDigits = maxFractionDigits;
+  this._maxIntegerDigits = maxIntegerDigits;
+  this._minFractionDigits = minFractionDigits;
+  this._minIntegerDigits = minIntegerDigits;
   
   // for debugging
   this._class = "TrNumberConverter";
+  
+  if(this._type=="percent")
+  {
+    this._example = 0.3423;
+    this._numberFormat = TrNumberFormat.getPercentInstance();
+  }
+  else if(this._type=="currency")
+  {
+    this._example = 10250;
+    this._numberFormat = TrNumberFormat.getCurrencyInstance();
+  }
 }
 
 TrNumberConverter.prototype = new TrConverter();
@@ -39,7 +66,7 @@
  */
 TrNumberConverter.prototype._isConvertible = function()
 {
-  if(this._pattern == null && this._locale == null && this._type=="number")
+  if((this._pattern == null) && (this._locale == null))
   {
     return true;
   }
@@ -81,7 +108,35 @@
 {
   if(this._isConvertible())
   {
-    return "" + number;
+    if(this._type=="percent" || this._type=="currency")
+    {
+      var string = this._numberFormat.format(number);
+      if(this._type=="currency")
+      {
+        //In Trinidad the currencyCode gets preference over currencySymbol
+        //this is similar on the server-side
+        if(this._currencyCode)
+        {
+          string = string.replace(getLocaleSymbols().getCurrencyCode(), this._currencyCode);
+        }
+        else if(this._currencySymbol)
+        {
+          string = string.replace(getLocaleSymbols().getCurrencySymbol(), this._currencySymbol);
+        }
+      }
+      return string;
+    }
+    else
+    {
+      this._numberFormat = TrNumberFormat.getNumberInstance();
+      this._numberFormat.setMaximumFractionDigits(this._maxFractionDigits);
+      this._numberFormat.setMaximumIntegerDigits(this._maxIntegerDigits);
+      this._numberFormat.setMinimumFractionDigits( this._minFractionDigits);
+      this._numberFormat.setMinimumIntegerDigits( this._minIntegerDigits);
+      return this._numberFormat.format(number);
+  
+      //return "" + number;
+    }
   }
   else
   {
@@ -99,7 +154,37 @@
 {
   if(this._isConvertible())
   {
-    return _decimalParse(numberString, 
+    var parsedValue;
+    if(this._type=="percent" || this._type=="currency")
+    {
+      try
+      {
+        numberString = this._numberFormat.parse(numberString)+"";
+      }
+      catch(e)
+      {
+        var facesMessage;
+        var example = this._numberFormat.format(this._example);
+        var key = "org.apache.myfaces.trinidad.convert.NumberConverter.CONVERT_" + this._type.toUpperCase();
+        if(this._messages && this._messages[this._type])
+        {
+          facesMessage = _createCustomFacesMessage(TrMessageFactory.getSummaryString(key),
+                                                  this._messages[this._type],
+                                                  label,
+                                                  numberString,
+                                                  example);
+        }
+        else
+        {
+          facesMessage = _createFacesMessage(key,
+                                            label,
+                                            numberString,
+                                            example);
+        }
+          throw new TrConverterException(facesMessage);
+      }
+    }
+    parsedValue = _decimalParse(numberString, 
                          this._messages,
                          "org.apache.myfaces.trinidad.convert.NumberConverter",
                          null,
@@ -108,12 +193,18 @@
                          null,
                          label,
                          true);
+    if(this._type=="percent")
+    {
+      parsedValue = parsedValue / 100;
+    }
+    return parsedValue;
   }
   else
   {
     return undefined;
   }
 }
+
 function TrIntegerConverter(
   message,
   maxPrecision,
@@ -758,7 +849,7 @@
       }
     }
     //max only
-    else
+    else if(this._maxValue)
     {
       maxDate = parseInt(this._maxValue);
       if(dateTime <= maxDate)
@@ -768,7 +859,7 @@
       else
       {
         var key = "org.apache.myfaces.trinidad.validator.DateTimeRangeValidator.MAXIMUM";
-      if(this._messages && this._messages["max"])
+        if(this._messages && this._messages["max"])
         {
           facesMessage = _createCustomFacesMessage(TrMessageFactory.getSummaryString(key),
                                         this._messages["max"],
@@ -776,14 +867,19 @@
                                         ""+converter.getAsString(value),
                                         ""+converter.getAsString(new Date(this._maxValue)));
         }
-      else
-      {
+        else
+        {
           facesMessage = _createFacesMessage(key,
                                         label,
                                         ""+converter.getAsString(value),
                                         ""+converter.getAsString(new Date(this._maxValue)));
+        }
       }
-      }
+    }
+    else
+    {
+      //no min/max specified
+      return value;
     }
   }
   throw new TrConverterException(facesMessage);
@@ -812,16 +908,46 @@
   converter
   )
 {
+  var allWeekdays = ['mon','tue','wed','thu','fri','sat','sun'];
+  var allMonth = ['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'];
+  
+  //remove the submitted values, which are invalid, to display only the valid ones
+  this._removeInvalidValues(this._weekdaysValue, allWeekdays);
+  this._removeInvalidValues(this._monthValue, allMonth);
+  
   return _returnHints(
     this._messages,
-    this._translate(this._weekdaysValue, this._translatedWeekdaysMap, converter.getLocaleSymbols().getWeekdays()),
-    this._translate(this._monthValue, this._translatedMonthMap, converter.getLocaleSymbols().getMonths()),
+    this._translate(allWeekdays, this._translatedWeekdaysMap, converter.getLocaleSymbols().getWeekdays()),
+    this._translate(allMonth, this._translatedMonthMap, converter.getLocaleSymbols().getMonths()),
     "org.apache.myfaces.trinidad.validator.DateRestrictionValidator.WEEKDAY_HINT",
     "org.apache.myfaces.trinidad.validator.DateRestrictionValidator.MONTH_HINT",
     "hintWeek",
     "hintMonth"
   );
 }
+
+/**
+ * Removes invalidValues from the allValues array
+ * TODO matzew: move this to a "CollectionUtil.js" ?
+ */
+TrDateRestrictionValidator.prototype._removeInvalidValues = function(
+  invalidValues,
+  allValues
+  )
+{
+  for(i=0; i<invalidValues.length; i++)
+  {
+    var value = invalidValues[i];
+    for(j=0;j<allValues.length; j++)
+    {
+      if(allValues[j].toLowerCase() == value.toLowerCase())
+      {
+        allValues.splice(j,1);
+      }
+    }
+  }
+}
+
 TrDateRestrictionValidator.prototype._translate = function(
   values,
   map,
@@ -858,6 +984,10 @@
     {
       if(weekDaysArray[i].toLowerCase() == dayString)
       {
+        var allWeekdays = ['mon','tue','wed','thu','fri','sat','sun'];
+        this._removeInvalidValues(this._weekdaysValue, allWeekdays);
+        var days = this._translate(allWeekdays, this._translatedWeekdaysMap, converter.getLocaleSymbols().getWeekdays());
+
         var facesMessage;
         var key = "org.apache.myfaces.trinidad.validator.DateRestrictionValidator.WEEKDAY";
         if(this._messages && this._messages["days"])
@@ -866,14 +996,14 @@
                                         this._messages["days"],
                                         label,
                                         ""+converter.getAsString(value),
-                                        dayString);
+                                        days);
         }
         else
         {
           facesMessage = _createFacesMessage(key,
                                         label,
                                         ""+converter.getAsString(value),
-                                        dayString);
+                                        days);
         }
         throw new TrConverterException(facesMessage);
       }
@@ -889,6 +1019,10 @@
     {
       if(monthArray[i].toLowerCase() == monthString)
       {
+        var allMonth = ['jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec'];
+        this._removeInvalidValues(this._monthValue, allMonth);
+        var month = this._translate(allMonth, this._translatedMonthMap, converter.getLocaleSymbols().getMonths());
+        
         var facesMessage;
         var key = "org.apache.myfaces.trinidad.validator.DateRestrictionValidator.MONTH";
         if(this._messages && this._messages["month"])
@@ -897,14 +1031,14 @@
                                         this._messages["month"],
                                         label,
                                         ""+converter.getAsString(value),
-                                        monthString);
+                                        month);
         }
         else
         {
           facesMessage = _createFacesMessage(key,
                                         label,
                                         ""+converter.getAsString(value),
-                                        monthString);
+                                        month);
         }
         throw new TrConverterException(facesMessage);
       }
@@ -957,12 +1091,6 @@
         facesMessage =  _createFacesMessage( standardKey+".CONVERT",
                                           label,
                                           numberString);
-        //var summary = "";
-        //var detail = "";
-        //facesMessage =  _createCustomMessage( summary,
-                                          //detail,
-                                          //label,
-                                          //numberString);
       }
       throw new TrConverterException(facesMessage);
     }
@@ -973,6 +1101,9 @@
     }
     
     // Remove the thousands separator - which Javascript doesn't want to see
+    
+    //is this a i18n bug?...
+    //see TRINIDAD-2
     var thousands = new RegExp("\\" + grouping, "g");
     numberString = numberString.replace(thousands, "");
     // Then change the decimal separator into a period, the only

Added: myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/NumberFormat.js
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/NumberFormat.js?view=auto&rev=559487
==============================================================================
--- myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/NumberFormat.js (added)
+++ myfaces/trinidad/branches/1.2.1.1-branch/trinidad/trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/NumberFormat.js Wed Jul 25 08:13:59 2007
@@ -0,0 +1,548 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+/**
+ * constructor for TrNumberFormat.
+ */
+ function TrNumberFormat(type)
+{
+  if(!type)
+    alert("type for TrNumberFormat not defined!");
+  this._type = type;
+  this._pPre = getLocaleSymbols().getPositivePrefix();
+  this._pSuf = getLocaleSymbols().getPositiveSuffix();
+  this._nPre = getLocaleSymbols().getNegativePrefix();
+  this._nSuf = getLocaleSymbols().getNegativeSuffix();
+  //default values, similar to JDK
+  this._maxFractionDigits = 3;
+  this._maxIntegerDigits  = 40;
+  this._minFractionDigits = 0;
+  this._minIntegerDigits  = 1;
+  
+}
+//***********************
+// static
+//***********************
+
+/**
+ * Returns a number formater.
+ */
+TrNumberFormat.getNumberInstance = function()
+{
+  return new TrNumberFormat("number");
+}
+
+/**
+ * Returns a currency formater.
+ */
+TrNumberFormat.getCurrencyInstance = function()
+{
+  return new TrNumberFormat("currency");
+}
+
+/**
+ * Returns a percent formater.
+ */
+TrNumberFormat.getPercentInstance = function()
+{
+  return new TrNumberFormat("percent");
+}
+
+/**
+ * Used to specify the new maximum count of integer digits that are printed
+ * when formatting. If the maximum is less than the number of integer
+ * digits, the most significant digits are truncated.
+ * 
+ * @param value the new maximum number of integer numerals for display
+ */
+TrNumberFormat.prototype.setMaximumIntegerDigits = function(number)
+{
+  //taken from the Apache Harmony project
+  if(number)
+  {
+    this._maxIntegerDigits = value < 0 ? 0 : number;
+    if (this._minIntegerDigits > this._maxIntegerDigits)
+    {
+      this._minIntegerDigits = this._maxIntegerDigits;
+    }
+  }
+} 
+
+/**
+ * Answers the maximum number of integer digits that are printed when
+ * formatting. If the maximum is less than the number of integer digits, the
+ * most significant digits are truncated.
+ * 
+ * @return the maximum number of integer digits
+ */
+TrNumberFormat.prototype.getMaximumIntegerDigits = function()
+{
+  //taken from the Apache Harmony project
+  return this._maxIntegerDigits;
+}
+
+/**
+ * Sets the maximum number of fraction digits that are printed when
+ * formatting. If the maximum is less than the number of fraction digits,
+ * the least significant digits are truncated.
+ * 
+ * @param value the maximum number of fraction digits
+ */
+TrNumberFormat.prototype.setMaximumFractionDigits = function(number)
+{
+  //taken from the Apache Harmony project
+  if(number)
+  {
+    this._maxFractionDigits = value < 0 ? 0 : number;
+    if (this._maxFractionDigits < this._minFractionDigits)
+    {
+      this._minFractionDigits = this._maxFractionDigits;
+    }
+  }
+} 
+
+/**
+ * Answers the maximum number of fraction digits that are printed when
+ * formatting. If the maximum is less than the number of fraction digits,
+ * the least significant digits are truncated.
+ * 
+ * @return the maximum number of fraction digits
+ */
+TrNumberFormat.prototype.getMaximumFractionDigits = function()
+{
+  //taken from the Apache Harmony project
+  return this._maxFractionDigits;
+}
+
+/**
+ * Sets the minimum number of integer digits that are printed when
+ * formatting.
+ * 
+ * @param value the minimum number of integer digits
+ */
+TrNumberFormat.prototype.setMinimumIntegerDigits = function(number)
+{
+  //taken from the Apache Harmony project
+  if(number)
+  {
+    this._minIntegerDigits = value < 0 ? 0 : number;
+    if(this._minIntegerDigits > this._maxIntegerDigits)
+    {
+      this._maxIntegerDigits = this._minIntegerDigits;
+    }
+  }
+}
+
+/**
+ * Answers the minimum number of integer digits that are printed when
+ * formatting.
+ * 
+ * @return the minimum number of integer digits
+ */
+TrNumberFormat.prototype.getMinimumIntegerDigits = function()
+{
+  //taken from the Apache Harmony project
+  return this._minIntegerDigits;
+}
+
+/**
+ * Sets the minimum number of fraction digits that are printed when
+ * formatting.
+ * 
+ * @param value the minimum number of fraction digits
+ */
+TrNumberFormat.prototype.setMinimumFractionDigits = function(number)
+{
+  //taken from the Apache Harmony project
+  if(number)
+  {
+    this._minFractionDigits = value < 0 ? 0 : number;
+    if (this._maxFractionDigits < this._minFractionDigits)
+    {
+      this._maxFractionDigits = this._minFractionDigits;
+    }
+  }
+}
+
+/**
+ * Answers the minimum number of fraction digits that are printed when
+ * formatting.
+ * 
+ * @return the minimum number of fraction digits
+ */
+TrNumberFormat.prototype.getMinimumFractionDigits = function()
+{
+  //taken from the Apache Harmony project
+  return this._minFractionDigits;
+}
+
+/**
+ * Based on the type this func returns a percentage, currency or number string.
+ */
+TrNumberFormat.prototype.format = function(number)
+{
+  if(this._type=="percent")
+    return this.percentageToString(number);
+  else if (this._type=="currency")
+    return this.currencyToString(number);
+  else if (this._type=="number")
+    return this.numberToString(number);
+}
+
+/**
+ * Based on the type this func returns a number result, from the given formatted string.
+ */
+TrNumberFormat.prototype.parse = function(string)
+{
+  if(this._type=="percent")
+    return this.stringToPercentage(string);
+  else if (this._type=="currency")
+    return this.stringToCurrency(string);
+}
+
+/**
+ * Formats a currency string into a number.
+ */
+TrNumberFormat.prototype.stringToCurrency = function(numberString)
+{
+  //is the string negative ?
+  var negP = numberString.indexOf(this._nPre);
+  
+  if(negP != -1)
+  {
+    numberString = numberString.substr(this._nPre.length, numberString.length);
+    var negS = numberString.indexOf(this._nSuf);
+    if(negS != -1)
+    {
+      numberString = numberString.substr(0, numberString.length-this._nSuf.length);
+      return (parseFloat(numberString)*-1);
+    }
+    else
+    {
+      throw new TrParseException("not able to parse number");
+    }
+  }
+  else
+  {
+    var posP = numberString.indexOf(this._pPre);
+    if(posP != -1)
+    {
+      numberString = numberString.substr(this._pPre.length, numberString.length);
+      var posS = numberString.indexOf(this._pSuf);
+      if(posS != -1)
+      {
+        numberString = numberString.substr(0, numberString.length-this._pSuf.length);
+        numberString = parseFloat(numberString);
+      }
+      else
+      {
+        throw new TrParseException("not able to parse number");
+      }
+      return numberString;
+    }
+    else
+    {
+      throw new TrParseException("not able to parse number");
+    }
+  }
+}
+
+/**
+ * Formats a percent string into a number.
+ */
+TrNumberFormat.prototype.stringToPercentage = function(numberString)
+{
+  numberString = numberString.replace(/\%/g, '');
+  numberString = parseFloat(numberString);
+  if(isNaN(numberString))
+  {
+    throw new TrParseException("not able to parse number");
+  }
+  return numberString;
+}
+
+/**
+ * Formats a number into a a formatted string.
+ */
+TrNumberFormat.prototype.numberToString = function(number)
+{
+  var numberString = number + "";
+  var decimalSeparator = getLocaleSymbols().getDecimalSeparator();
+  var index = numberString.indexOf(decimalSeparator);
+  var numberStringLength = numberString.length;
+  var ints;
+  var fracs;
+  if(index != -1)
+  {
+    ints = numberString.substring(0, index);
+    fracs = numberString.substring(index+1, numberStringLength);
+  }
+  else
+  {
+    ints = numberString;
+    fracs = "";
+  }
+
+  ints  = this._formatIntegers(ints);
+  fracs = this._formatFractions(fracs)
+  
+  
+  if(fracs!="")
+    numberString = (ints+decimalSeparator+fracs);
+  else
+    numberString = (ints);
+  
+  return numberString;
+  
+}
+
+/**
+ * Formats a number into a a formatted currency string.
+ */
+TrNumberFormat.prototype.currencyToString = function(number)
+{
+  //negative ?
+  if(number<0)
+  {
+    number = (number*-1)+"";
+    number = this.numberToString(number);
+    return this._nPre + number + this._nSuf;
+  }
+  else
+  {
+    number = this.numberToString(number);
+    return this._pPre + number + this._pSuf;
+  }
+}
+
+/**
+ * Formats a number into a a formatted percent string.
+ */
+TrNumberFormat.prototype.percentageToString = function(number)
+{
+  number = number * 100;
+  number = this.getRounded(number);
+  if(isNaN(number))
+  {
+    throw new TrParseException("not able to parse number");
+  }
+  number = this.numberToString(number);
+  return number + '%';
+}
+
+/**
+ * helper for rounding values
+ */
+TrNumberFormat.prototype.getRounded = function(val)
+{
+  val = this.moveDecimalRight(val);
+  val = Math.round(val);
+  val = this.moveDecimalLeft(val);
+  return val;
+}
+
+/**
+ * helper for rounding values
+ */
+TrNumberFormat.prototype.moveDecimalRight = function(val)
+{
+  var newVal = '';
+  newVal = this.moveDecimal(val, false);
+  return newVal;
+}
+
+/**
+ * helper for rounding values
+ */
+TrNumberFormat.prototype.moveDecimalLeft = function (val)
+{
+  var newVal = '';
+  newVal = this.moveDecimal(val, true);
+  return newVal;
+}
+
+/**
+ * helper for rounding values
+ */
+TrNumberFormat.prototype.moveDecimal = function(val, left)
+{
+  var newVal = '';
+  newVal = this.moveDecimalAsString(val, left);
+  return parseFloat(newVal);
+}
+
+/**
+ * helper for rounding values
+ */
+TrNumberFormat.prototype.moveDecimalAsString = function(val, left)
+{
+  //TODO: matzew make it nicer....
+  var spaces = 2;
+  if (spaces <= 0)
+    return val; 
+  var newVal = val + '';
+  var extraZ = this.getZeros(spaces);
+  var re1 = new RegExp('([0-9.]+)');
+  if (left)
+  {
+    newVal = newVal.replace(re1, extraZ + '$1');
+    var re2 = new RegExp('(-?)([0-9]*)([0-9]{' + spaces + '})(\\.?)');
+    newVal = newVal.replace(re2, '$1$2.$3');
+  }
+  else
+  {
+    var reArray = re1.exec(newVal); 
+    if (reArray != null)
+    {
+      newVal = newVal.substring(0,reArray.index) + reArray[1] + extraZ + newVal.substring(reArray.index + reArray[0].length); 
+    }
+    var re2 = new RegExp('(-?)([0-9]*)(\\.?)([0-9]{' + spaces + '})');
+    newVal = newVal.replace(re2, '$1$2$4.');
+  }
+  newVal = newVal.replace(/\.$/, ''); 
+  return newVal;
+}
+
+/**
+ * 
+ */
+TrNumberFormat.prototype.getZeros = function(places)
+{
+  var extraZ = '';
+  var i;
+  for (i=0; i<places; i++) {
+    extraZ += '0';
+  }
+  return extraZ;
+}
+
+//***********************
+// PRIVATE
+//***********************
+
+/**
+ * Formats the integer part of a number
+ */
+TrNumberFormat.prototype._formatIntegers = function(ints)
+{
+  var intsLength = ints.length;
+  var maxInt = this.getMaximumIntegerDigits();
+  var minInt = this.getMinimumIntegerDigits();
+
+  var gap;
+  if(intsLength>maxInt)
+  {
+    gap = intsLength-maxInt;
+    ints = ints.substring(gap, intsLength);
+  }
+  else if(intsLength<minInt)
+  {
+    gap = minInt-intsLength;
+    var leadingZeros = "";
+    
+    //we need some more leadingZeros
+    while(gap>0)
+    {
+      leadingZeros = "0"+leadingZeros;
+      --gap;
+    }
+    
+    ints = leadingZeros + ints;
+  }
+  
+  ints = this._addGroupingSeparators(ints);
+  
+  return ints;
+}
+
+/**
+ * Formats the fraction part of a number
+ */
+TrNumberFormat.prototype._formatFractions = function(fracs)
+{
+  var fracsLength = fracs.length;
+  var maxFra = this.getMaximumFractionDigits();
+  var minFra = this.getMinimumFractionDigits();
+
+  if(fracsLength > maxFra)
+  {
+    fracs = fracs.substring(0,maxFra-1);
+  }
+  else if(fracsLength <minFra)
+  {
+    var gap = minFra-fracsLength;
+    
+    //we need to add some zeros
+    while(gap>0)
+    {
+      fracs = fracs + "0";
+      --gap;
+    }
+  }
+  return fracs;
+}
+
+/**
+ * Adds localized grouping separators to a number string.
+ */
+TrNumberFormat.prototype._addGroupingSeparators = function(ints)
+{
+  var counter = ints.length;
+  var toMuch = counter%3;
+  var balance;
+  var toFormat;
+  var formatted = "";
+
+  if(toMuch>0)
+  {
+    balance = ints.substring(0, toMuch);
+    toFormat = ints.substring(toMuch, counter);
+  }
+  else
+  {
+    balance = "";
+    toFormat = ints;
+  }
+
+  var groupingSeparator = getLocaleSymbols().getGroupingSeparator();
+  for(i=0; i < toFormat.length; i++)
+  {
+    if(i%3==0)
+    {
+      formatted += groupingSeparator;
+    }
+    formatted += toFormat[i];
+  }
+  ints = balance + formatted;
+  return ints;
+}
+/** 
+ * TrParseException is an exception thrown by the TrNumberFormater.
+ * TODO: loclized messages ?
+ */
+function TrParseException(
+  message
+  )
+{
+  this._message = message;
+}
+TrParseException.prototype.getMessage = function()
+{
+  return this._message;
+}
\ No newline at end of file