001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019/**
020 * Implements the CFML Function lsparsecurrency
021 */
022package lucee.runtime.functions.international;
023
024import java.text.NumberFormat;
025import java.text.ParseException;
026import java.text.ParsePosition;
027import java.util.Locale;
028import java.util.WeakHashMap;
029
030import lucee.runtime.PageContext;
031import lucee.runtime.exp.ExpressionException;
032import lucee.runtime.exp.PageException;
033import lucee.runtime.ext.function.Function;
034import lucee.runtime.i18n.LocaleFactory;
035import lucee.runtime.op.Caster;
036
037
038public final class LSParseCurrency implements Function {
039
040        private static final long serialVersionUID = -7023441119083818436L;
041        private static WeakHashMap currFormatter=new WeakHashMap();
042        private static WeakHashMap numbFormatter=new WeakHashMap();
043
044        public static String call(PageContext pc , String string) throws PageException {
045                return Caster.toString(toDoubleValue(pc.getLocale(),string,false));
046        }
047        public static String call(PageContext pc , String string,String strLocale) throws PageException {
048                return Caster.toString(toDoubleValue(strLocale==null?pc.getLocale():LocaleFactory.getLocale(strLocale),string,false));
049        }
050
051        public static synchronized double toDoubleValue(Locale locale,String str) throws PageException {
052                return toDoubleValue(locale, str, false);
053        }
054        
055        public static synchronized double toDoubleValue(Locale locale,String str, boolean strict) throws PageException {
056                str=str.trim();
057                NumberFormat cnf=getCurrencyInstance(locale);
058                cnf.setParseIntegerOnly(false);
059                try {
060                        return cnf.parse(str).doubleValue();
061                } 
062                catch (ParseException e) {
063                        String stripped=str.replaceFirst(cnf.getCurrency().getCurrencyCode(),"").trim();
064                        NumberFormat nf=getInstance(locale);
065                        
066                        ParsePosition pp = new ParsePosition(0);
067                        double d = nf.parse(stripped,pp).doubleValue();
068                        if (pp.getIndex() == 0 || (strict && stripped.length()!=pp.getIndex())) 
069                    throw new ExpressionException("Unparseable number [" + str + "]");
070                        
071                        return d;
072                }
073        }
074        
075        private static NumberFormat getInstance(Locale locale) {
076                Object o=numbFormatter.get(locale);
077                if(o!=null) return (NumberFormat) o;
078                
079                NumberFormat nf=NumberFormat.getInstance(locale);
080                numbFormatter.put(locale,nf);
081                return nf;
082        }
083
084        private static NumberFormat getCurrencyInstance(Locale locale) {
085                Object o = currFormatter.get(locale);
086                if(o!=null) return (NumberFormat) o;
087                
088                NumberFormat nf=NumberFormat.getCurrencyInstance(locale);
089                currFormatter.put(locale,nf);
090                return nf;
091        }
092}