1////////////////////////////////////////////////////////////////////////////////
2//
3//  ADOBE SYSTEMS INCORPORATED
4//  Copyright 2004-2007 Adobe Systems Incorporated
5//  All Rights Reserved.
6//
7//  NOTICE: Adobe permits you to use, modify, and distribute this file
8//  in accordance with the terms of the license agreement accompanying it.
9//
10////////////////////////////////////////////////////////////////////////////////
11
12package mx.validators
13{
14
15import mx.managers.ISystemManager;
16import mx.managers.SystemManager;
17
18[ResourceBundle("SharedResources")]
19[ResourceBundle("validators")]
20
21[Alternative(replacement="spark.validators.CurrencyValidator", since="4.5")]
22/**
23 *  The CurrencyValidator class ensures that a String
24 *  represents a valid currency expression.
25 *  It can make sure the input falls within a given range
26 *  (specified by <code>minValue</code> and <code>maxValue</code>),
27 *  is non-negative (specified by <code>allowNegative</code>),
28 *  and does not exceed the specified <code>precision</code>. The
29 *  CurrencyValidator class correctly validates formatted and unformatted
30 *  currency expressions, e.g., "$12,345.00" and "12345".
31 *  You can customize the <code>currencySymbol</code>, <code>alignSymbol</code>,
32 *  <code>thousandsSeparator</code>, and <code>decimalSeparator</code>
33 *  properties for internationalization.
34 *
35 *  @mxml
36 *
37 *  <p>The <code>&lt;mx:CurrencyValidator&gt;</code> tag
38 *  inherits all of the tag properties of its superclass,
39 *  and adds the following tag properties:</p>
40 *
41 *  <pre>
42 *  &lt;mx:CurrencyValidator
43 *    alignSymbol="left|right|any"
44 *    allowNegative="true|false"
45 *    currencySymbol="$"
46 *    currencySymbolError="The currency symbol occurs in an invalid location."
47 *    decimalPointCountError="The decimal separator can occur only once."
48 *    decimalSeparator="."
49 *    exceedsMaxError="The amount entered is too large."
50 *    invalidCharError="The input contains invalid characters."
51 *    invalidFormatCharsError="One of the formatting parameters is invalid."
52 *    lowerThanMinError="The amount entered is too small."
53 *    maxValue="NaN"
54 *    minValue="NaN"
55 *    negativeError="The amount may not be negative."
56 *    precision="2"
57 *    precisionError="The amount entered has too many digits beyond the decimal point."
58 *    separationError="The thousands separator must be followed by three digits."
59 *    thousandsSeparator=","
60 *  /&gt;
61 *  </pre>
62 *
63 *  @see mx.validators.CurrencyValidatorAlignSymbol
64 *
65 *  @includeExample examples/CurrencyValidatorExample.mxml
66 *
67 *  @langversion 3.0
68 *  @playerversion Flash 9
69 *  @playerversion AIR 1.1
70 *  @productversion Flex 3
71 */
72public class CurrencyValidator extends Validator
73{
74    include "../core/Version.as";
75
76    //--------------------------------------------------------------------------
77    //
78    //  Class constants
79    //
80    //--------------------------------------------------------------------------
81
82    /**
83     *  @private
84     *  Formatting characters for negative values.
85     */
86    private static const NEGATIVE_FORMATTING_CHARS:String = "-()";
87
88    //--------------------------------------------------------------------------
89    //
90    //  Class methods
91    //
92    //--------------------------------------------------------------------------
93
94    /**
95     *  Convenience method for calling a validator.
96     *  Each of the standard Flex validators has a similar convenience method.
97     *
98     *  @param validator The CurrencyValidator instance.
99     *
100     *  @param value The object to validate.
101     *
102     *  @param baseField Text representation of the subfield
103     *  specified in the <code>value</code> parameter.
104     *  For example, if the <code>value</code> parameter specifies value.currency,
105     *  the baseField value is "currency".
106     *
107     *  @return An Array of ValidationResult objects, with one ValidationResult
108     *  object for each field examined by the validator.
109     *
110     *  @see mx.validators.ValidationResult
111     *
112     *  @langversion 3.0
113     *  @playerversion Flash 9
114     *  @playerversion AIR 1.1
115     *  @productversion Flex 3
116     */
117    public static function validateCurrency(validator:CurrencyValidator,
118                                            value:Object,
119                                            baseField:String):Array
120    {
121        var results:Array = [];
122
123        // Resource-backed properties of the validator.
124        var alignSymbol:String = validator.alignSymbol;
125        var allowNegative:Boolean = validator.allowNegative;
126        var currencySymbol:String = validator.currencySymbol;
127        var decimalSeparator:String = validator.decimalSeparator;
128        var maxValue:Number = Number(validator.maxValue);
129        var minValue:Number = Number(validator.minValue);
130        var precision:int = int(validator.precision);
131        var thousandsSeparator:String = validator.thousandsSeparator;
132
133        var input:String = String(value);
134        var len:int = input.length;
135
136        var isNegative:Boolean = false;
137
138        var i:int;
139        var c:String;
140
141        // Make sure the formatting character parameters are unique,
142        // are not digits or negative formatting characters,
143        // and that the separators are one character.
144        var invalidFormChars:String = DECIMAL_DIGITS + NEGATIVE_FORMATTING_CHARS;
145
146        if (currencySymbol == thousandsSeparator ||
147            currencySymbol == decimalSeparator ||
148            decimalSeparator == thousandsSeparator ||
149            invalidFormChars.indexOf(currencySymbol) != -1 ||
150            invalidFormChars.indexOf(decimalSeparator) != -1 ||
151            invalidFormChars.indexOf(thousandsSeparator) != -1 ||
152            decimalSeparator.length != 1 ||
153            thousandsSeparator.length != 1)
154        {
155            results.push(new ValidationResult(
156                true, baseField, "invalidFormatChar",
157                validator.invalidFormatCharsError));
158            return results;
159        }
160
161        // Check for invalid characters in input.
162        var validChars:String =
163            DECIMAL_DIGITS + NEGATIVE_FORMATTING_CHARS +
164            currencySymbol + decimalSeparator + thousandsSeparator;
165        for (i = 0; i < len; i++)
166        {
167            c = input.charAt(i);
168
169            if (validChars.indexOf(c) == -1)
170            {
171                results.push(new ValidationResult(
172                    true, baseField, "invalidChar",
173                    validator.invalidCharError));
174                return results;
175            }
176        }
177
178        // Check if the input is negative.
179        if (input.charAt(0) == "-")
180        {
181            // Check if negative input is allowed.
182            if (!allowNegative)
183            {
184                results.push(new ValidationResult(
185                    true, baseField, "negative",
186                    validator.negativeError));
187                return results;
188            }
189
190            // Strip off the negative formatting and update some variables.
191            input = input.substring(1);
192            len--;
193            isNegative = true;
194        }
195
196        else if (input.charAt(0) == "(")
197        {
198            // Make sure the last character is a closed parenthesis.
199            if (input.charAt(len - 1) != ")")
200            {
201                results.push(new ValidationResult(
202                    true, baseField, "invalidChar",
203                    validator.invalidCharError));
204                return results;
205            }
206
207            // Check if negative input is allowed.
208            if (!allowNegative)
209            {
210                results.push(new ValidationResult(
211                    true, baseField, "negative",
212                    validator.negativeError));
213                return results;
214            }
215
216            // Strip off the negative formatting and update some variables.
217            input = input.substring(1,len-2);
218            len -= 2;
219            isNegative = true;
220        }
221
222        // Find the currency symbol if it exists,
223        // then make sure that it's in the right place
224        // and that there is only one.
225        var currencySymbolLength:uint = currencySymbol.length; // allows for symbols that use multiple chars, like the Brazilian "R$"
226        if ((input.substr(0, currencySymbolLength) == currencySymbol &&
227             alignSymbol == CurrencyValidatorAlignSymbol.RIGHT) ||
228            (input.substr(len - currencySymbolLength, currencySymbolLength) == currencySymbol &&
229             alignSymbol == CurrencyValidatorAlignSymbol.LEFT) ||
230            (len > (2 * currencySymbolLength) &&
231             input.substring(currencySymbolLength, len - currencySymbolLength).indexOf(currencySymbol) != -1) ||
232            (input.indexOf(currencySymbol) !=
233             input.lastIndexOf(currencySymbol)))
234        {
235            results.push(new ValidationResult(
236                true, baseField, "currencySymbol",
237                validator.currencySymbolError));
238            return results;
239        }
240
241        // Now that we know it's in the right place,
242        // strip off the currency symbol if it exists.
243        var currencySymbolIndex:int = input.indexOf(currencySymbol);
244        if (currencySymbolIndex != -1)
245        {
246            if (currencySymbolIndex) // if it's at the end
247                input = input.substring(0, len - currencySymbolLength);
248            else // it's at the beginning
249                input = input.substring(currencySymbolLength);
250            len -= currencySymbolLength;
251        }
252
253        // Make sure there is only one decimal point.
254        if (input.indexOf(decimalSeparator) !=
255            input.lastIndexOf(decimalSeparator))
256        {
257            results.push(new ValidationResult(
258                true, baseField, "decimalPointCount",
259                validator.decimalPointCountError));
260            return results;
261        }
262
263        // Make sure that every character after the decimal point
264        // is a digit and that the precision is not exceeded.
265        var decimalSeparatorIndex:int = input.indexOf(decimalSeparator);
266        var numDigitsAfterDecimal:int = 0;
267
268        // If there is no decimal separator, act like there is one at the end.
269        if (decimalSeparatorIndex == -1)
270          decimalSeparatorIndex = len;
271
272        for (i = decimalSeparatorIndex + 1; i < len; i++)
273        {
274            if (DECIMAL_DIGITS.indexOf(input.charAt(i)) == -1)
275            {
276                results.push(new ValidationResult(
277                    true, baseField, "invalidChar",
278                    validator.invalidCharError));
279                return results;
280            }
281
282            ++numDigitsAfterDecimal;
283
284            // Make sure precision is not exceeded.
285            if (precision != -1 && numDigitsAfterDecimal > precision)
286            {
287                results.push(new ValidationResult(
288                    true, baseField, "precision",
289                    validator.precisionError));
290                return results;
291            }
292        }
293
294        // Make sure the input begins with a digit or a decimal point.
295        if (DECIMAL_DIGITS.indexOf(input.charAt(0)) == -1 &&
296            input.charAt(0) != decimalSeparator)
297        {
298            results.push(new ValidationResult(
299                true, baseField, "invalidChar",
300                validator.invalidCharError));
301            return results;
302        }
303
304        // Make sure that every character before the decimal point
305        // is a digit or is a thousands separator.
306        // If it's a thousands separator, make sure it's followed
307        // by three consecutive digits, and then make sure the next character
308        // is valid (i.e., either thousands separator, decimal separator,
309        // or nothing).
310        var validGroupEnder:String = thousandsSeparator + decimalSeparator;
311        for (i = 1; i < decimalSeparatorIndex; i++)
312        {
313            c = input.charAt(i);
314
315            if (c == thousandsSeparator)
316            {
317                if (input.substring(i + 1, i + 4).length < 3 ||
318                    DECIMAL_DIGITS.indexOf(input.charAt(i + 1)) == -1 ||
319                    DECIMAL_DIGITS.indexOf(input.charAt(i + 2)) == -1 ||
320                    DECIMAL_DIGITS.indexOf(input.charAt(i + 3)) == -1 ||
321                    validGroupEnder.indexOf(input.charAt(i + 4)) == -1)
322                {
323                    results.push(new ValidationResult(
324                        true, baseField, "separation",
325                        validator.separationError));
326                    return results;
327                }
328            }
329            else if (DECIMAL_DIGITS.indexOf(c) == -1)
330            {
331                results.push(new ValidationResult(
332                    true, baseField, "invalidChar",
333                    validator.invalidCharError));
334                return results;
335            }
336        }
337
338        // Make sure the input is within the specified range.
339        if (!isNaN(minValue) || !isNaN(maxValue))
340        {
341            // First strip off the thousands separators.
342            for (i = 0; i < decimalSeparatorIndex; i++)
343            {
344                if (input.charAt(i) == thousandsSeparator)
345                {
346                    var left:String = input.substring(0, i);
347                    var right:String = input.substring(i + 1);
348                    input = left + right;
349                }
350            }
351
352            // Translate the value back into standard english
353            // If the decimalSeperator is not '.' we need to change it to '.'
354            // so that the number casting will work properly
355            if (validator.decimalSeparator != '.')
356            {
357                var dIndex:int = input.indexOf( validator.decimalSeparator );
358                if (dIndex != -1)
359                {
360                    var dLeft:String = input.substring(0, dIndex);
361                    var dRight:String = input.substring(dIndex + 1);
362                    input = dLeft + '.' + dRight;
363                }
364            }
365
366            // Check bounds
367
368            var x:Number = Number(input);
369
370            if (isNegative)
371                x = -x;
372
373            if (!isNaN(minValue) && x < minValue)
374            {
375                results.push(new ValidationResult(
376                    true, baseField, "lowerThanMin",
377                    validator.lowerThanMinError));
378                return results;
379            }
380
381            if (!isNaN(maxValue) && x > maxValue)
382            {
383                results.push(new ValidationResult(
384                    true, baseField, "exceedsMax",
385                    validator.exceedsMaxError));
386                return results;
387            }
388        }
389
390        return results;
391    }
392
393    //--------------------------------------------------------------------------
394    //
395    //  Constructor
396    //
397    //--------------------------------------------------------------------------
398
399    /**
400     *  Constructor.
401     *
402     *  @langversion 3.0
403     *  @playerversion Flash 9
404     *  @playerversion AIR 1.1
405     *  @productversion Flex 3
406     */
407    public function CurrencyValidator()
408    {
409        super();
410    }
411
412    //--------------------------------------------------------------------------
413    //
414    //  Properties
415    //
416    //--------------------------------------------------------------------------
417
418    //----------------------------------
419    //  alignSymbol
420    //----------------------------------
421
422    /**
423     *  @private
424     *  Storage for the alignSymbol property.
425     */
426    private var _alignSymbol:String;
427
428    /**
429     *  @private
430     */
431    private var alignSymbolOverride:String;
432
433    [Inspectable(category="General", defaultValue="null")]
434
435    /**
436     *  Specifies the alignment of the <code>currencySymbol</code>
437     *  relative to the rest of the expression.
438     *  Acceptable values in ActionScript are <code>CurrencyValidatorAlignSymbol.LEFT</code>,
439     *  <code>CurrencyValidatorAlignSymbol.RIGHT</code>, and
440     *  <code>CurrencyValidatorAlignSymbol.ANY</code>.
441     *  Acceptable values in MXML are <code>"left"</code>,
442     *  <code>"right"</code>, and
443     *  <code>"any"</code>.
444     *
445     *  @default CurrencyValidatorAlignSymbol.LEFT
446     *
447     *  @see mx.validators.CurrencyValidatorAlignSymbol
448     *
449     *  @langversion 3.0
450     *  @playerversion Flash 9
451     *  @playerversion AIR 1.1
452     *  @productversion Flex 3
453     */
454    public function get alignSymbol():String
455    {
456        return _alignSymbol;
457    }
458
459    /**
460     *  @private
461     */
462    public function set alignSymbol(value:String):void
463    {
464        alignSymbolOverride = value;
465
466        _alignSymbol = value != null ?
467                       value :
468                       resourceManager.getString(
469                           "SharedResources", "alignSymbol");
470    }
471
472    //----------------------------------
473    //  allowNegative
474    //----------------------------------
475
476    /**
477     *  @private
478     *  Storage for the allowNegative property.
479     */
480    private var _allowNegative:Object;
481
482    /**
483     *  @private
484     */
485    private var allowNegativeOverride:Object;
486
487    [Inspectable(category="General", defaultValue="null")]
488
489    /**
490     *  Specifies whether negative numbers are permitted.
491     *  Can be <code>true</code> or <code>false</code>.
492     *
493     *  @default true
494     *
495     *  @langversion 3.0
496     *  @playerversion Flash 9
497     *  @playerversion AIR 1.1
498     *  @productversion Flex 3
499     */
500    public function get allowNegative():Object
501    {
502        return _allowNegative;
503    }
504
505    /**
506     *  @private
507     */
508    public function set allowNegative(value:Object):void
509    {
510        allowNegativeOverride = value;
511
512        _allowNegative = value != null ?
513                         Boolean(value) :
514                         resourceManager.getBoolean(
515                             "validators", "allowNegative");
516    }
517
518    //----------------------------------
519    //  currencySymbol
520    //----------------------------------
521
522    /**
523     *  @private
524     *  Storage for the currencySymbol property.
525     */
526    private var _currencySymbol:String;
527
528    /**
529     *  @private
530     */
531    private var currencySymbolOverride:String;
532
533    [Inspectable(category="General", defaultValue="null")]
534
535    /**
536     *  The character String used to specify the currency symbol,
537     *  such as "$", "R$", or "&#163;".
538     *  Cannot be a digit and must be distinct from the
539     *  <code>thousandsSeparator</code> and the <code>decimalSeparator</code>.
540     *
541     *  @default "$"
542     *
543     *  @langversion 3.0
544     *  @playerversion Flash 9
545     *  @playerversion AIR 1.1
546     *  @productversion Flex 3
547     */
548    public function get currencySymbol():String
549    {
550        return _currencySymbol;
551    }
552
553    /**
554     *  @private
555     */
556    public function set currencySymbol(value:String):void
557    {
558        currencySymbolOverride = value;
559
560        _currencySymbol = value != null ?
561                          value :
562                          resourceManager.getString(
563                              "SharedResources", "currencySymbol");
564    }
565
566    //----------------------------------
567    //  decimalSeparator
568    //----------------------------------
569
570    /**
571     *  @private
572     *  Storage for the decimalSeparator property.
573     */
574    private var _decimalSeparator:String;
575
576    /**
577     *  @private
578     */
579    private var decimalSeparatorOverride:String;
580
581    [Inspectable(category="General", defaultValue="null")]
582
583    /**
584     *  The character used to separate the whole
585     *  from the fractional part of the number.
586     *  Cannot be a digit and must be distinct from the
587     *  <code>currencySymbol</code> and the <code>thousandsSeparator</code>.
588     *
589     *  @default "."
590     *
591     *  @langversion 3.0
592     *  @playerversion Flash 9
593     *  @playerversion AIR 1.1
594     *  @productversion Flex 3
595     */
596    public function get decimalSeparator():String
597    {
598        return _decimalSeparator;
599    }
600
601    /**
602     *  @private
603     */
604    public function set decimalSeparator(value:String):void
605    {
606        decimalSeparatorOverride = value;
607
608        _decimalSeparator = value != null ?
609                            value :
610                            resourceManager.getString(
611                                "validators", "decimalSeparator");
612    }
613
614    //----------------------------------
615    //  maxValue
616    //----------------------------------
617
618    /**
619     *  @private
620     *  Storage for the maxValue property.
621     */
622    private var _maxValue:Object;
623
624    /**
625     *  @private
626     */
627    private var maxValueOverride:Object;
628
629    [Inspectable(category="General", defaultValue="null")]
630
631    /**
632     *  Maximum value for a valid number.
633     *  A value of NaN means it is ignored.
634     *
635     *  @default NaN
636     *
637     *  @langversion 3.0
638     *  @playerversion Flash 9
639     *  @playerversion AIR 1.1
640     *  @productversion Flex 3
641     */
642    public function get maxValue():Object
643    {
644        return _maxValue;
645    }
646
647    /**
648     *  @private
649     */
650    public function set maxValue(value:Object):void
651    {
652        maxValueOverride = value;
653
654        _maxValue = value != null ?
655                    Number(value) :
656                    resourceManager.getNumber(
657                        "validators", "maxValue");
658    }
659
660    //----------------------------------
661    //  minValue
662    //----------------------------------
663
664    /**
665     *  @private
666     *  Storage for the minValue property.
667     */
668    private var _minValue:Object;
669
670    /**
671     *  @private
672     */
673    private var minValueOverride:Object;
674
675    [Inspectable(category="General", defaultValue="null")]
676
677    /**
678     *  Minimum value for a valid number.
679     *  A value of NaN means it is ignored.
680     *
681     *  @default NaN
682     *
683     *  @langversion 3.0
684     *  @playerversion Flash 9
685     *  @playerversion AIR 1.1
686     *  @productversion Flex 3
687     */
688    public function get minValue():Object
689    {
690        return _minValue;
691    }
692
693    /**
694     *  @private
695     */
696    public function set minValue(value:Object):void
697    {
698        minValueOverride = value;
699
700        _minValue = value != null ?
701                    Number(value) :
702                    resourceManager.getNumber(
703                        "validators", "minValue");
704    }
705
706    //----------------------------------
707    //  precision
708    //----------------------------------
709
710    /**
711     *  @private
712     *  Storage for the precision property.
713     */
714    private var _precision:Object;
715
716    /**
717     *  @private
718     */
719    private var precisionOverride:Object;
720
721    [Inspectable(category="General", defaultValue="null")]
722
723    /**
724     *  The maximum number of digits allowed to follow the decimal point.
725     *  Can be any non-negative integer.
726     *  Note: Setting to <code>0</code>
727     *  has the same effect as setting <code>NumberValidator.domain</code>
728     *  to <code>int</code>.
729     *  Setting it to -1, means it is ignored.
730     *
731     *  @default 2
732     *
733     *  @langversion 3.0
734     *  @playerversion Flash 9
735     *  @playerversion AIR 1.1
736     *  @productversion Flex 3
737     */
738    public function get precision():Object
739    {
740        return _precision;
741    }
742
743    /**
744     *  @private
745     */
746    public function set precision(value:Object):void
747    {
748        precisionOverride = value;
749
750        _precision = value != null ?
751                     int(value) :
752                     resourceManager.getInt(
753                         "validators", "currencyValidatorPrecision");
754    }
755
756    //----------------------------------
757    //  thousandsSeparator
758    //----------------------------------
759
760    /**
761     *  @private
762     *  Storage for the thousandsSeparator property.
763     */
764    private var _thousandsSeparator:String;
765
766    /**
767     *  @private
768     */
769    private var thousandsSeparatorOverride:String;
770
771    [Inspectable(category="General", defaultValue=",")]
772
773    /**
774     *  The character used to separate thousands.
775     *  Cannot be a digit and must be distinct from the
776     *  <code>currencySymbol</code> and the <code>decimalSeparator</code>.
777     *
778     *  @default ","
779     *
780     *  @langversion 3.0
781     *  @playerversion Flash 9
782     *  @playerversion AIR 1.1
783     *  @productversion Flex 3
784     */
785    public function get thousandsSeparator():String
786    {
787        return _thousandsSeparator;
788    }
789
790    /**
791     *  @private
792     */
793    public function set thousandsSeparator(value:String):void
794    {
795        thousandsSeparatorOverride = value;
796
797        _thousandsSeparator = value != null ?
798                              value :
799                              resourceManager.getString(
800                                  "validators", "thousandsSeparator");
801    }
802
803    //--------------------------------------------------------------------------
804    //
805    //  Properties: Errors
806    //
807    //--------------------------------------------------------------------------
808
809    //----------------------------------
810    //  currencySymbolError
811    //----------------------------------
812
813    /**
814     *  @private
815     *  Storage for the currencySymbolError property.
816     */
817    private var _currencySymbolError:String;
818
819    /**
820     *  @private
821     */
822    private var currencySymbolErrorOverride:String;
823
824    [Inspectable(category="Errors", defaultValue="null")]
825
826    /**
827     *  Error message when the currency symbol, defined by <code>currencySymbol</code>,
828     *  is in the wrong location.
829     *
830     *  @default "The currency symbol occurs in an invalid location."
831     *
832     *  @langversion 3.0
833     *  @playerversion Flash 9
834     *  @playerversion AIR 1.1
835     *  @productversion Flex 3
836     */
837    public function get currencySymbolError():String
838    {
839        return _currencySymbolError;
840    }
841
842    /**
843     *  @private
844     */
845    public function set currencySymbolError(value:String):void
846    {
847        currencySymbolErrorOverride = value;
848
849        _currencySymbolError = value != null ?
850                               value :
851                               resourceManager.getString(
852                                   "validators", "currencySymbolError");
853    }
854
855    //----------------------------------
856    //  decimalPointCountError
857    //----------------------------------
858
859    /**
860     *  @private
861     *  Storage for the decimalPointCountError property.
862     */
863    private var _decimalPointCountError:String;
864
865    /**
866     *  @private
867     */
868    private var decimalPointCountErrorOverride:String;
869
870    [Inspectable(category="Errors", defaultValue="null")]
871
872    /**
873     *  Error message when the decimal separator character occurs more than once.
874     *
875     *  @default "The decimal separator can only occur once."
876     *
877     *  @langversion 3.0
878     *  @playerversion Flash 9
879     *  @playerversion AIR 1.1
880     *  @productversion Flex 3
881     */
882    public function get decimalPointCountError():String
883    {
884        return _decimalPointCountError;
885    }
886
887    /**
888     *  @private
889     */
890    public function set decimalPointCountError(value:String):void
891    {
892        decimalPointCountErrorOverride = value;
893
894        _decimalPointCountError = value != null ?
895                                  value :
896                                  resourceManager.getString(
897                                      "validators", "decimalPointCountError");
898    }
899
900    //----------------------------------
901    //  exceedsMaxError
902    //----------------------------------
903
904    /**
905     *  @private
906     *  Storage for the exceedsMaxError property.
907     */
908    private var _exceedsMaxError:String;
909
910    /**
911     *  @private
912     */
913    private var exceedsMaxErrorOverride:String;
914
915    [Inspectable(category="Errors", defaultValue="null")]
916
917    /**
918     *  Error message when the value is greater than <code>maxValue</code>.
919     *
920     *  @default "The amount entered is too large."
921     *
922     *  @langversion 3.0
923     *  @playerversion Flash 9
924     *  @playerversion AIR 1.1
925     *  @productversion Flex 3
926     */
927    public function get exceedsMaxError():String
928    {
929        return _exceedsMaxError;
930    }
931
932    /**
933     *  @private
934     */
935    public function set exceedsMaxError(value:String):void
936    {
937        exceedsMaxErrorOverride = value;
938
939        _exceedsMaxError = value != null ?
940                           value :
941                           resourceManager.getString(
942                               "validators", "exceedsMaxErrorCV");
943    }
944
945    //----------------------------------
946    //  invalidCharError
947    //----------------------------------
948
949    /**
950     *  @private
951     *  Storage for the invalidCharError property.
952     */
953    private var _invalidCharError:String;
954
955    /**
956     *  @private
957     */
958    private var invalidCharErrorOverride:String;
959
960    [Inspectable(category="Errors", defaultValue="null")]
961
962    /**
963     *  Error message when the currency contains invalid characters.
964     *
965     *  @default "The input contains invalid characters."
966     *
967     *  @langversion 3.0
968     *  @playerversion Flash 9
969     *  @playerversion AIR 1.1
970     *  @productversion Flex 3
971     */
972    public function get invalidCharError():String
973    {
974        return _invalidCharError;
975    }
976
977    /**
978     *  @private
979     */
980    public function set invalidCharError(value:String):void
981    {
982        invalidCharErrorOverride = value;
983
984        _invalidCharError = value != null ?
985                            value :
986                            resourceManager.getString(
987                                "validators", "invalidCharError");
988    }
989
990    //----------------------------------
991    //  invalidFormatCharsError
992    //----------------------------------
993
994    /**
995     *  @private
996     *  Storage for the invalidFormatCharsError property.
997     */
998    private var _invalidFormatCharsError:String;
999
1000    /**
1001     *  @private
1002     */
1003    private var invalidFormatCharsErrorOverride:String;
1004
1005    [Inspectable(category="Errors", defaultValue="null")]
1006
1007    /**
1008     *  Error message when the value contains an invalid formatting character.
1009     *
1010     *  @default "One of the formatting parameters is invalid."
1011     *
1012     *  @langversion 3.0
1013     *  @playerversion Flash 9
1014     *  @playerversion AIR 1.1
1015     *  @productversion Flex 3
1016     */
1017    public function get invalidFormatCharsError():String
1018    {
1019        return _invalidFormatCharsError;
1020    }
1021
1022    /**
1023     *  @private
1024     */
1025    public function set invalidFormatCharsError(value:String):void
1026    {
1027        invalidFormatCharsErrorOverride = value;
1028
1029        _invalidFormatCharsError = value != null ?
1030                                   value :
1031                                   resourceManager.getString(
1032                                       "validators", "invalidFormatCharsError");
1033    }
1034
1035    //----------------------------------
1036    //  lowerThanMinError
1037    //----------------------------------
1038
1039    /**
1040     *  @private
1041     *  Storage for the lowerThanMinError property.
1042     */
1043    private var _lowerThanMinError:String;
1044
1045    /**
1046     *  @private
1047     */
1048    private var lowerThanMinErrorOverride:String;
1049
1050    [Inspectable(category="Errors", defaultValue="null")]
1051
1052    /**
1053     *  Error message when the value is less than <code>minValue</code>.
1054     *
1055     *  @default "The amount entered is too small."
1056     *
1057     *  @langversion 3.0
1058     *  @playerversion Flash 9
1059     *  @playerversion AIR 1.1
1060     *  @productversion Flex 3
1061     */
1062    public function get lowerThanMinError():String
1063    {
1064        return _lowerThanMinError;
1065    }
1066
1067    /**
1068     *  @private
1069     */
1070    public function set lowerThanMinError(value:String):void
1071    {
1072        lowerThanMinErrorOverride = value;
1073
1074        _lowerThanMinError = value != null ?
1075                             value :
1076                             resourceManager.getString(
1077                                 "validators", "lowerThanMinError");
1078    }
1079
1080    //----------------------------------
1081    //  negativeError
1082    //----------------------------------
1083
1084    /**
1085     *  @private
1086     *  Storage for the negativeError property.
1087     */
1088    private var _negativeError:String;
1089
1090    /**
1091     *  @private
1092     */
1093    private var negativeErrorOverride:String;
1094
1095    [Inspectable(category="Errors", defaultValue="null")]
1096
1097    /**
1098     *  Error message when the value is negative and
1099     *  the <code>allowNegative</code> property is <code>false</code>.
1100     *
1101     *  @default "The amount may not be negative."
1102     *
1103     *  @langversion 3.0
1104     *  @playerversion Flash 9
1105     *  @playerversion AIR 1.1
1106     *  @productversion Flex 3
1107     */
1108    public function get negativeError():String
1109    {
1110        return _negativeError;
1111    }
1112
1113    /**
1114     *  @private
1115     */
1116    public function set negativeError(value:String):void
1117    {
1118        negativeErrorOverride = value;
1119
1120        _negativeError = value != null ?
1121                         value :
1122                         resourceManager.getString(
1123                             "validators", "negativeError");
1124    }
1125
1126    //----------------------------------
1127    //  precisionError
1128    //----------------------------------
1129
1130    /**
1131     *  @private
1132     *  Storage for the precisionError property.
1133     */
1134    private var _precisionError:String;
1135
1136    /**
1137     *  @private
1138     */
1139    private var precisionErrorOverride:String;
1140
1141    [Inspectable(category="Errors", defaultValue="null")]
1142
1143    /**
1144     *  Error message when the value has a precision that exceeds the value
1145     *  defined by the <code>precision</code> property.
1146     *
1147     *  @default "The amount entered has too many digits beyond
1148     *  the decimal point."
1149     *
1150     *  @langversion 3.0
1151     *  @playerversion Flash 9
1152     *  @playerversion AIR 1.1
1153     *  @productversion Flex 3
1154     */
1155    public function get precisionError():String
1156    {
1157        return _precisionError;
1158    }
1159
1160    /**
1161     *  @private
1162     */
1163    public function set precisionError(value:String):void
1164    {
1165        precisionErrorOverride = value;
1166
1167        _precisionError = value != null ?
1168                          value :
1169                          resourceManager.getString(
1170                              "validators", "precisionError");
1171    }
1172
1173    //----------------------------------
1174    //  separationError
1175    //----------------------------------
1176
1177    /**
1178     *  @private
1179     *  Storage for the separationError property.
1180     */
1181    private var _separationError:String;
1182
1183    /**
1184     *  @private
1185     */
1186    private var separationErrorOverride:String;
1187
1188    [Inspectable(category="Errors", defaultValue="null")]
1189
1190    /**
1191     *  Error message when the thousands separator is incorrectly placed.
1192     *
1193     *  @default "The thousands separator must be followed by three digits."
1194     *
1195     *  @langversion 3.0
1196     *  @playerversion Flash 9
1197     *  @playerversion AIR 1.1
1198     *  @productversion Flex 3
1199     */
1200    public function get separationError():String
1201    {
1202        return _separationError;
1203    }
1204
1205    /**
1206     *  @private
1207     */
1208    public function set separationError(value:String):void
1209    {
1210        separationErrorOverride = value;
1211
1212        _separationError = value != null ?
1213                           value :
1214                           resourceManager.getString(
1215                               "validators", "separationError");
1216    }
1217
1218    //--------------------------------------------------------------------------
1219    //
1220    //  Overridden methods
1221    //
1222    //--------------------------------------------------------------------------
1223
1224    /**
1225     *  @private
1226     */
1227    override protected function resourcesChanged():void
1228    {
1229        super.resourcesChanged();
1230
1231        alignSymbol = alignSymbolOverride;
1232        allowNegative = allowNegativeOverride;
1233        currencySymbol = currencySymbolOverride;
1234        decimalSeparator = decimalSeparatorOverride;
1235        maxValue = maxValueOverride;
1236        minValue = minValueOverride;
1237        precision = precisionOverride;
1238        thousandsSeparator = thousandsSeparatorOverride;
1239
1240        currencySymbolError = currencySymbolErrorOverride;
1241        decimalPointCountError = decimalPointCountErrorOverride;
1242        exceedsMaxError = exceedsMaxErrorOverride;
1243        invalidCharError = invalidCharErrorOverride;
1244        invalidFormatCharsError = invalidFormatCharsErrorOverride;
1245        lowerThanMinError = lowerThanMinErrorOverride;
1246        negativeError = negativeErrorOverride;
1247        precisionError = precisionErrorOverride;
1248        separationError = separationErrorOverride;
1249    }
1250
1251    /**
1252     *  Override of the base class <code>doValidation()</code> method
1253     *  to validate a currency expression.
1254     *
1255     *  <p>You do not call this method directly;
1256     *  Flex calls it as part of performing a validation.
1257     *  If you create a custom Validator class, you must implement this method. </p>
1258     *
1259     *  @param value Object to validate.
1260     *
1261     *  @return An Array of ValidationResult objects, with one ValidationResult
1262     *  object for each field examined by the validator.
1263     *
1264     *  @langversion 3.0
1265     *  @playerversion Flash 9
1266     *  @playerversion AIR 1.1
1267     *  @productversion Flex 3
1268     */
1269    override protected function doValidation(value:Object):Array
1270    {
1271        var results:Array = super.doValidation(value);
1272
1273        // Return if there are errors
1274        // or if the required property is set to false and length is 0.
1275        var val:String = value ? String(value) : "";
1276        if (results.length > 0 || ((val.length == 0) && !required))
1277            return results;
1278        else
1279            return CurrencyValidator.validateCurrency(this, value, null);
1280    }
1281}
1282
1283}
1284