Package org.apache.myfaces.commons.converter

Source Code of org.apache.myfaces.commons.converter.AbstractTypedNumberConverter

/*
* 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.
*/
package org.apache.myfaces.commons.converter;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Currency;
import java.util.Locale;

import javax.faces.el.ValueBinding;
import javax.faces.FacesException;
import javax.faces.application.FacesMessage;
import javax.faces.component.StateHolder;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.ConverterException;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFConverter;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
import org.apache.myfaces.commons.util.MessageUtils;

/**
* Converter which uses either the manually set <code>destType</code> or the value binding to determine the
* correct destination type to convert the number to
*
* This tag creates a number formatting converter and associates it with the nearest
* parent UIComponent. It uses either the manually set destType or the value
* binding to determine the correct destination type to convert the number to.
*
* Unless otherwise specified, all attributes accept static values or EL expressions.
*
*  
* @author imario@apache.org
*/
@JSFConverter(
   name = "mcc:convertNumber",
   clazz = "org.apache.myfaces.commons.converter.TypedNumberConverter",
   tagClass = "org.apache.myfaces.commons.converter.TypedNumberConverterTag",
   tagHandler = "org.apache.myfaces.commons.converter.TypedNumberConverterTagHandler")
public abstract class AbstractTypedNumberConverter extends ConverterBase
{
    public static final String CONVERTER_ID = "org.apache.myfaces.custom.convertNumber.TypedNumberConverter";

    private Class destType;

    public AbstractTypedNumberConverter()
    {
    }
   
    public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String value)
    {
        Object convertedValue = _getAsObject(facesContext, uiComponent, value);
        if (convertedValue == null)
        {
            return null;
        }

        Class destType = getDestType();
        if (destType == null)
        {
            ValueBinding valueBinding = uiComponent.getValueBinding("value");
            if (valueBinding != null)
            {
                destType = valueBinding.getType(facesContext);
            }
        }
       
        if (destType != null)
        {
            Converter converter = ConvertUtils.lookup(destType);
            if (converter == null)
            {
                throw new UnsupportedOperationException("cant deal with " + destType);
            }

            // setting type to null, in fact the documentation is wrong here and this type is never used
            convertedValue = converter.convert(null, convertedValue);
        }
       
       
        return convertedValue;
    }

    public void restoreState(FacesContext facesContext, Object state)
    {
        Object[] states = (Object[]) state;
        _restoreState(facesContext, states[0]);
        destType = (Class) states[1];
    }

    public Object saveState(FacesContext facesContext)
    {
        return new Object[]
                          {
                _saveState(facesContext),
                destType
                          };
    }

    /**
     * The java class name the value should be converted to.
     *
     * Default: automatically determined through valueBinding
     *
     */
    @JSFProperty
    public Class getDestType()
    {
        return destType;
    }

    public void setDestType(Class destType)
    {
        this.destType = destType;
    }

    /* ORIGINAL STUFF COPIED FROM javax.faces.convert.NumberConverter */
   
    // internal constants
    private static final String CONVERSION_MESSAGE_ID = "javax.faces.convert.NumberConverter.CONVERSION";


    private static final boolean JAVA_VERSION_14;

    static
    {
        JAVA_VERSION_14 = checkJavaVersion14();
    }

    private String _currencyCode;
    private String _currencySymbol;
    private Locale _locale;
    private boolean _transient;



    // METHODS
    public Object _getAsObject(FacesContext facesContext, UIComponent uiComponent, String value)
    {
        if (facesContext == null) throw new NullPointerException("facesContext");
        if (uiComponent == null) throw new NullPointerException("uiComponent");

        if (value != null)
        {
            value = value.trim();
            if (value.length() > 0)
            {
                NumberFormat format = getNumberFormat(facesContext);
                format.setParseIntegerOnly(isIntegerOnly());
               
                DecimalFormat df = (DecimalFormat)format;
               
                // The best we can do in this case is check if there is a ValueExpression
                // with a BigDecimal as returning type , and if that so enable BigDecimal parsing
                // to prevent loss in precision, and do not break existing examples (since
                // in those cases it is expected to return Double). See MYFACES-1890 and TRINIDAD-1124
                // for details
                Class destType = getDestType();
                if (destType == null)
                {
                    ValueBinding valueBinding = uiComponent.getValueBinding("value");
                    if (valueBinding != null)
                    {
                        destType = valueBinding.getType(facesContext);
                    }
                }
                if (destType != null && BigDecimal.class.isAssignableFrom(destType))
                {
                    df.setParseBigDecimal(true);
                }
               
                DecimalFormatSymbols dfs = df.getDecimalFormatSymbols();
                boolean changed = false;
                if(dfs.getGroupingSeparator() == '\u00a0')
                {
                  dfs.setGroupingSeparator(' ');
                  df.setDecimalFormatSymbols(dfs);
                  changed = true;
                }
               
                formatCurrency(format);
               
                try
                {
                    return format.parse(value);
                }
                catch (ParseException e)
                {
                  if(changed)
                  {
                    dfs.setGroupingSeparator('\u00a0');
                    df.setDecimalFormatSymbols(dfs);
                  }
                  try
                  {
                    return format.parse(value);
                  }
                  catch (ParseException pe)
                  {
                    FacesMessage message = MessageUtils.getMessage(FacesMessage.FACES_MESSAGES, facesContext, CONVERSION_MESSAGE_ID, new Object[]{uiComponent.getId(),value});
                    message.setSeverity(FacesMessage.SEVERITY_ERROR);
                   
                    throw new ConverterException(message, e);
                  }
                }
            }
        }
        return null;
    }

    public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object value)
    {
        if (facesContext == null) throw new NullPointerException("facesContext");
        if (uiComponent == null) throw new NullPointerException("uiComponent");

        if (value == null)
        {
            return "";
        }
        if (value instanceof String)
        {
            return (String)value;
        }

        NumberFormat format = getNumberFormat(facesContext);
        format.setGroupingUsed(isGroupingUsed());
        Integer maxFractionDigits = getMaxFractionDigits();
        Integer maxIntegerDigits = getMaxIntegerDigits();
        Integer minFractionDigits = getMinFractionDigits();
        Integer minIntegerDigits = getMinIntegerDigits();
        if (maxFractionDigits != null) format.setMaximumFractionDigits(maxFractionDigits);
        if (maxIntegerDigits != null) format.setMaximumIntegerDigits(maxIntegerDigits);
        if (minFractionDigits != null) format.setMinimumFractionDigits(minFractionDigits);
        if (minIntegerDigits != null) format.setMinimumIntegerDigits(minIntegerDigits);
        formatCurrency(format);
        try
        {
            return format.format(value);
        }
        catch (Exception e)
        {
            throw new ConverterException("Cannot convert value '" + value + "'");
        }
    }

    private NumberFormat getNumberFormat(FacesContext facesContext)
    {
        Locale lokale = getLocale();

        if (getPattern() == null && getType() == null)
        {
            throw new ConverterException("Cannot get NumberFormat, either type or pattern needed.");
        }

        // pattern
        if (getPattern() != null)
        {
            return new DecimalFormat(getPattern(), new DecimalFormatSymbols(lokale));
        }

        // type
        if (getType().equals("number"))
        {
            return NumberFormat.getNumberInstance(lokale);
        }
        else if (getType().equals("currency"))
        {
            return NumberFormat.getCurrencyInstance(lokale);
        }
        else if (getType().equals("percent"))
        {
            return NumberFormat.getPercentInstance(lokale);
        }
        throw new ConverterException("Cannot get NumberFormat, illegal type " + getType());
    }

    private void formatCurrency(NumberFormat format)
    {
        if (getLocalCurrencyCode() == null && getLocalCurrencySymbol() == null)
        {
            return;
        }

        boolean useCurrencyCode;
        if (JAVA_VERSION_14)
        {
            useCurrencyCode = getLocalCurrencyCode() != null;
        }
        else
        {
            useCurrencyCode = getLocalCurrencySymbol() == null;
        }

        if (useCurrencyCode)
        {
            // set Currency
            try
            {
                format.setCurrency(Currency.getInstance(getLocalCurrencyCode()));
            }
            catch (Exception e)
            {
                throw new ConverterException("Unable to get Currency instance for currencyCode " +
                        getLocalCurrencyCode());
            }
        }
        else if (format instanceof DecimalFormat)

        {
            DecimalFormat dFormat = (DecimalFormat)format;
            DecimalFormatSymbols symbols = dFormat.getDecimalFormatSymbols();
            symbols.setCurrencySymbol(getLocalCurrencySymbol());
            dFormat.setDecimalFormatSymbols(symbols);
        }
    }

    // STATE SAVE/RESTORE
    public void _restoreState(FacesContext facesContext, Object state)
    {
        Object values[] = (Object[])state;
        super.restoreState(facesContext, values[0]);
        _currencyCode = (String)values[1];
        _currencySymbol = (String)values[2];
        _locale = (Locale)values[3];
    }

    public Object _saveState(FacesContext facesContext)
    {
        Object values[] = new Object[4];
        values[0] = super.saveState(facesContext);
        values[1] = _currencyCode;
        values[2] = _currencySymbol;
        values[3] = _locale;
        return values;
    }

    // GETTER & SETTER
   
    /**
     * ISO 4217 currency code
     *
     */
    @JSFProperty
    public String getCurrencyCode()
    {
        if (_currencyCode != null)
        {
            return _currencyCode;
        }
        ValueBinding vb = getValueBinding("currencyCode");
        if (vb != null)
        {
            return (String) vb.getValue(getFacesContext());
        }
        return getDecimalFormatSymbols().getInternationalCurrencySymbol();
    }
   
    protected String getLocalCurrencyCode()
    {
        if (_currencyCode != null)
        {
            return _currencyCode;
        }
        ValueBinding vb = getValueBinding("currencyCode");
        if (vb != null)
        {
            return (String) vb.getValue(getFacesContext());
        }
        return null;
    }

    public void setCurrencyCode(String currencyCode)
    {
        this._currencyCode = currencyCode;
    }

    /**
     * The currency symbol used to format a currency value.
     *
     * Defaults to the currency symbol for locale.
     *
     */
    @JSFProperty
    public String getCurrencySymbol()
    {
        if (_currencySymbol != null)
        {
            return _currencySymbol;
        }
        ValueBinding vb = getValueBinding("currencySymbol");
        if (vb != null)
        {
            return (String) vb.getValue(getFacesContext());
        }
        return getDecimalFormatSymbols().getCurrencySymbol();
    }

    public String getLocalCurrencySymbol()
    {
        if (_currencySymbol != null)
        {
            return _currencySymbol;
        }
        ValueBinding vb = getValueBinding("currencySymbol");
        if (vb != null)
        {
            return (String) vb.getValue(getFacesContext());
        }
        return null;
    }
   
    public void setCurrencySymbol(String currencySymbol)
    {
        this._currencySymbol = currencySymbol;
    }

    /**
     * Specifies whether output will contain grouping separators.
     *
     * Default: true.
     *
     */
    @JSFProperty(defaultValue="true")
    public abstract boolean isGroupingUsed();

    /**
     * Specifies whether only the integer part of the input will be parsed.
     *
     * Default: false.
     *
     */
    @JSFProperty(defaultValue="false")
    public abstract boolean isIntegerOnly();

    /**
     * The name of the locale to be used, instead of the default as specified
     * in the faces configuration file.
     *
     */
    @JSFProperty
    public Locale getLocale()
    {       
        if (_locale != null)
        {
            return _locale;
        }
        ValueBinding vb = getValueBinding("locale");
        if (vb != null)
        {
            Object _localeValue = vb.getValue(getFacesContext());
            if (_localeValue instanceof String)
            {
                _localeValue = org.apache.myfaces.commons.util.TagUtils.getLocale((String)_localeValue);
            }
            return (java.util.Locale)_localeValue;
        }
        FacesContext context = FacesContext.getCurrentInstance();
        return context.getViewRoot().getLocale();
    }

    public void setLocale(Locale locale)
    {
        _locale = locale;
    }

    /**
     * The maximum number of digits in the fractional portion of the number.
     *
     */
    @JSFProperty
    public abstract Integer getMaxFractionDigits();

    /**
     * The maximum number of digits in the integer portion of the number.
     *
     */
    @JSFProperty
    public abstract Integer getMaxIntegerDigits();

    /**
     * The minimum number of digits in the fractional portion of the number.
     *
     */
    @JSFProperty
    public abstract Integer getMinFractionDigits();

    /**
     * The minimum number of digits in the integer portion of the number.
     *
     */
    @JSFProperty
    public abstract Integer getMinIntegerDigits();

    /**
     * A custom Date formatting pattern, in the format used by java.text.SimpleDateFormat.
     *
     */
    @JSFProperty
    public abstract String getPattern();

    public boolean isTransient()
    {
        return _transient;
    }

    public void setTransient(boolean aTransient)
    {
        _transient = aTransient;
    }

    /**
     * The type of formatting/parsing to be performed.
     *
     * Values include: number, currency, and percentage. Default: number.
     *
     */
    @JSFProperty(defaultValue="number")
    public abstract String getType();

    private static boolean checkJavaVersion14()
    {
        String version = System.getProperty("java.version");
        if (version == null)
        {
            return false;
        }
        byte java14 = 0;
        for (int idx = version.indexOf('.'), i = 0; idx > 0 || version != null; i++)
        {
            if (idx > 0)
            {
                byte value = Byte.parseByte(version.substring(0, 1));
                version = version.substring(idx + 1, version.length());
                idx = version.indexOf('.');
                switch (i)
                {
                    case 0:
                        if (value == 1)
                        {
                            java14 = 1;
                            break;
                        }
                        else if (value > 1)
                        {
                            java14 = 2;
                        }
                    case 1:
                        if (java14 > 0 && value >= 4)
                        {
                            java14 = 2;
                        }
                        ;
                    default:
                        idx = 0;
                        version = null;
                        break;
                }
            }
            else
            {
                byte value = Byte.parseByte(version.substring(0, 1));
                if (java14 > 0 && value >= 4)
                {
                    java14 = 2;
                }
                break;
            }
        }
        return java14 == 2;
    }


    private DecimalFormatSymbols getDecimalFormatSymbols()
    {
        return new DecimalFormatSymbols(getLocale());
    }
}
TOP

Related Classes of org.apache.myfaces.commons.converter.AbstractTypedNumberConverter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.