protected Converter createConverter() throws JspException {
    FacesContext context = FacesContext.getCurrentInstance();
    ELContext elctx = context.getELContext();

    if (binding != null) {
      Converter boundConverter = (NumberConverter) binding.getValue(elctx);
      if (boundConverter != null) return boundConverter;
    }

    NumberConverter converter = new NumberConverter();

    if (currencyCode != null) converter.setCurrencyCode((String) currencyCode.getValue(elctx));
    if (currencySymbol != null)
      converter.setCurrencySymbol((String) currencySymbol.getValue(elctx));
    if (groupingUsed != null) converter.setGroupingUsed((Boolean) groupingUsed.getValue(elctx));
    if (integerOnly != null) converter.setIntegerOnly((Boolean) integerOnly.getValue(elctx));
    if (maxFractionDigits != null)
      converter.setMaxFractionDigits((Integer) maxFractionDigits.getValue(elctx));
    if (minFractionDigits != null)
      converter.setMinFractionDigits((Integer) minFractionDigits.getValue(elctx));
    if (minIntegerDigits != null)
      converter.setMinIntegerDigits((Integer) minIntegerDigits.getValue(elctx));
    if (pattern != null) converter.setPattern((String) pattern.getValue(elctx));
    if (type != null) converter.setType((String) type.getValue(elctx));

    Locale loc = null;
    if (locale != null) loc = FacesUtils.getLocaleFromExpression(context, locale);
    if (loc == null) loc = context.getViewRoot().getLocale();
    converter.setLocale(loc);

    if (binding != null) binding.setValue(elctx, converter);
    return converter;
  }
 // Create and configure a NumberConverter
 protected NumberConverter createNumberConverter() {
   NumberConverter nc = new NumberConverter();
   nc.setCurrencyCode("USD");
   nc.setCurrencySymbol("$");
   nc.setGroupingUsed(false);
   nc.setIntegerOnly(true);
   nc.setMaxFractionDigits(2);
   nc.setMaxIntegerDigits(10);
   nc.setMinFractionDigits(2);
   nc.setMinIntegerDigits(5);
   nc.setType("currency");
   return (nc);
 }
  public Converter getConverter(ValueHolder valueHolder, Map<String, String> attributes) {

    // Use existing Converter (if any)

    Converter converter = valueHolder.getConverter();

    if (converter != null) {
      return converter;
    }

    // Create from id

    FacesContext context = FacesContext.getCurrentInstance();
    String converterId = attributes.get(FACES_CONVERTER);

    if (converterId != null) {

      converter = context.getApplication().createConverter(converterId);

    } else if (valueHolder instanceof UISelectOne || valueHolder instanceof UISelectMany) {

      // Create from parameterized type (eg. a Date converter for List<Date>)

      String parameterizedType = WidgetBuilderUtils.getComponentType(attributes);

      if (parameterizedType != null) {
        Class<?> parameterizedClass = ClassUtils.niceForName(parameterizedType);

        // The parameterized type might be null, or might not be concrete
        // enough to be instantiatable (eg. List<? extends Foo>)

        if (parameterizedClass != null) {
          converter = context.getApplication().createConverter(parameterizedClass);
        }
      }

    } else {

      // Create implicit converters
      //
      // JSF does not appear to implicitly hook up DateTimeConverters without either an
      // explicit f:convertDateTime tag or a registered java.util.Date converter. Adding one
      // fixes both POSTback and display of read-only dates (otherwise JSF uses Date.toString)
      //
      // JSF *does* appear to implicitly hook up NumberConverters.

      String type = attributes.get(TYPE);

      if (type != null) {

        Class<?> clazz = ClassUtils.niceForName(type);

        if (clazz != null) {

          if (clazz.isAssignableFrom(Date.class)) {
            converter = getDateTimeConverter(converter);
          }
        }
      }
    }

    // Support for DateTimeConverter

    if (attributes.containsKey(DATE_STYLE)) {
      converter = getDateTimeConverter(converter);
      ((DateTimeConverter) converter).setDateStyle(attributes.get(DATE_STYLE));
    }

    if (attributes.containsKey(DATETIME_PATTERN)) {
      converter = getDateTimeConverter(converter);
      ((DateTimeConverter) converter).setPattern(attributes.get(DATETIME_PATTERN));
    }

    if (attributes.containsKey(TIME_STYLE)) {
      converter = getDateTimeConverter(converter);
      ((DateTimeConverter) converter).setTimeStyle(attributes.get(TIME_STYLE));
    }

    if (attributes.containsKey(TIME_ZONE)) {
      converter = getDateTimeConverter(converter);
      ((DateTimeConverter) converter).setTimeZone(TimeZone.getTimeZone(attributes.get(TIME_ZONE)));
    }

    if (attributes.containsKey(DATETIME_TYPE)) {
      converter = getDateTimeConverter(converter);
      ((DateTimeConverter) converter).setType(attributes.get(DATETIME_TYPE));
    }

    // Support for NumberConverter

    if (attributes.containsKey(CURRENCY_CODE)) {
      converter = getNumberConverter(converter);
      ((NumberConverter) converter).setCurrencyCode(attributes.get(CURRENCY_CODE));
    }

    if (attributes.containsKey(CURRENCY_SYMBOL)) {
      converter = getNumberConverter(converter);
      ((NumberConverter) converter).setCurrencySymbol(attributes.get(CURRENCY_SYMBOL));
    }

    if (attributes.containsKey(NUMBER_USES_GROUPING_SEPARATORS)) {
      converter = getNumberConverter(converter);
      ((NumberConverter) converter)
          .setGroupingUsed(Boolean.parseBoolean(attributes.get(NUMBER_USES_GROUPING_SEPARATORS)));
    }

    if (attributes.containsKey(MINIMUM_INTEGER_DIGITS)) {
      converter = getNumberConverter(converter);
      ((NumberConverter) converter)
          .setMinIntegerDigits(Integer.parseInt(attributes.get(MINIMUM_INTEGER_DIGITS)));
    }

    if (attributes.containsKey(MAXIMUM_INTEGER_DIGITS)) {
      converter = getNumberConverter(converter);
      ((NumberConverter) converter)
          .setMaxIntegerDigits(Integer.parseInt(attributes.get(MAXIMUM_INTEGER_DIGITS)));
    }

    if (attributes.containsKey(MINIMUM_FRACTIONAL_DIGITS)) {
      converter = getNumberConverter(converter);
      ((NumberConverter) converter)
          .setMinFractionDigits(Integer.parseInt(attributes.get(MINIMUM_FRACTIONAL_DIGITS)));
    }

    if (attributes.containsKey(MAXIMUM_FRACTIONAL_DIGITS)) {
      converter = getNumberConverter(converter);
      ((NumberConverter) converter)
          .setMaxFractionDigits(Integer.parseInt(attributes.get(MAXIMUM_FRACTIONAL_DIGITS)));
    }

    if (attributes.containsKey(NUMBER_PATTERN)) {
      converter = getNumberConverter(converter);
      ((NumberConverter) converter).setPattern(attributes.get(NUMBER_PATTERN));
    }

    if (attributes.containsKey(NUMBER_TYPE)) {
      converter = getNumberConverter(converter);
      ((NumberConverter) converter).setType(attributes.get(NUMBER_TYPE));
    }

    // Locale (applies to both DateTimeConverter and NumberConverter)

    if (attributes.containsKey(LOCALE)) {
      if (converter instanceof NumberConverter) {
        ((NumberConverter) converter).setLocale(new Locale(attributes.get(LOCALE)));
      } else {
        converter = getDateTimeConverter(converter);
        ((DateTimeConverter) converter).setLocale(new Locale(attributes.get(LOCALE)));
      }
    }

    // Return it

    return converter;
  }