001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.beanutils.locale;
019    
020    import org.apache.commons.beanutils.ConversionException;
021    import org.apache.commons.logging.Log;
022    import org.apache.commons.logging.LogFactory;
023    
024    import java.text.ParseException;
025    import java.util.Locale;
026    
027    
028    /**
029     * <p>The base class for all standart type locale-sensitive converters.
030     * It has {@link LocaleConverter} and {@link org.apache.commons.beanutils.Converter} implementations,
031     * that convert an incoming locale-sensitive Object into an object of correspond type,
032     * optionally using a default value or throwing a {@link ConversionException}
033     * if a conversion error occurs.</p>
034     *
035     * @author Yauheny Mikulski
036     */
037    
038    public abstract class BaseLocaleConverter implements LocaleConverter {
039    
040        // ----------------------------------------------------- Instance Variables
041    
042        /** All logging goes through this logger */
043        private Log log = LogFactory.getLog(BaseLocaleConverter.class);
044    
045        /** The default value specified to our Constructor, if any. */
046        private Object defaultValue = null;
047    
048        /** Should we return the default value on conversion errors? */
049        protected boolean useDefault = false;
050    
051        /** The locale specified to our Constructor, by default - system locale. */
052        protected Locale locale = Locale.getDefault();
053    
054        /** The default pattern specified to our Constructor, if any. */
055        protected String pattern = null;
056    
057        /** The flag indicating whether the given pattern string is localized or not. */
058        protected boolean locPattern = false;
059    
060        // ----------------------------------------------------------- Constructors
061    
062        /**
063         * Create a {@link LocaleConverter} that will throw a {@link ConversionException}
064         * if a conversion error occurs.
065         * An unlocalized pattern is used for the convertion.
066         *
067         * @param locale        The locale
068         * @param pattern       The convertion pattern
069         */
070        protected BaseLocaleConverter(Locale locale, String pattern) {
071    
072            this(null, locale, pattern, false, false);
073        }
074    
075        /**
076         * Create a {@link LocaleConverter} that will throw a {@link ConversionException}
077         * if a conversion error occurs.
078         *
079         * @param locale        The locale
080         * @param pattern       The convertion pattern
081         * @param locPattern    Indicate whether the pattern is localized or not
082         */
083        protected BaseLocaleConverter(Locale locale, String pattern, boolean locPattern) {
084    
085            this(null, locale, pattern, false, locPattern);
086        }
087    
088        /**
089         * Create a {@link LocaleConverter} that will return the specified default value
090         * if a conversion error occurs.
091         * An unlocalized pattern is used for the convertion.
092         *
093         * @param defaultValue  The default value to be returned
094         * @param locale        The locale
095         * @param pattern       The convertion pattern
096         */
097        protected BaseLocaleConverter(Object defaultValue, Locale locale, String pattern) {
098    
099            this(defaultValue, locale, pattern, false);
100        }
101    
102        /**
103         * Create a {@link LocaleConverter} that will return the specified default value
104         * if a conversion error occurs.
105         *
106         * @param defaultValue  The default value to be returned
107         * @param locale        The locale
108         * @param pattern       The convertion pattern
109         * @param locPattern    Indicate whether the pattern is localized or not
110         */
111        protected BaseLocaleConverter(Object defaultValue, Locale locale, String pattern, boolean locPattern) {
112    
113            this(defaultValue, locale, pattern, true, locPattern);
114        }
115    
116        /**
117         * Create a {@link LocaleConverter} that will return the specified default value
118         * or throw a {@link ConversionException} if a conversion error occurs.
119         *
120         * @param defaultValue  The default value to be returned
121         * @param locale        The locale
122         * @param pattern       The convertion pattern
123         * @param useDefault    Indicate whether the default value is used or not
124         * @param locPattern    Indicate whether the pattern is localized or not
125         */
126        private BaseLocaleConverter(Object defaultValue, Locale locale,
127                                    String pattern, boolean useDefault, boolean locPattern) {
128    
129            if (useDefault) {
130                this.defaultValue = defaultValue;
131                this.useDefault = true;
132            }
133    
134            if (locale != null) {
135                this.locale = locale;
136            }
137    
138            this.pattern = pattern;
139            this.locPattern = locPattern;
140        }
141    
142        // --------------------------------------------------------- Methods
143    
144        /**
145         * Convert the specified locale-sensitive input object into an output object of the
146         * specified type.
147         *
148         * @param value The input object to be converted
149         * @param pattern The pattern is used for the convertion
150         * @return The converted value
151         *
152         * @exception ParseException if conversion cannot be performed
153         *  successfully
154         */
155    
156        abstract protected Object parse(Object value, String pattern) throws ParseException;
157    
158    
159        /**
160         * Convert the specified locale-sensitive input object into an output object.
161         * The default pattern is used for the convertion.
162         *
163         * @param value The input object to be converted
164         * @return The converted value
165         *
166         * @exception ConversionException if conversion cannot be performed
167         *  successfully
168         */
169        public Object convert(Object value) {
170            return convert(value, null);
171        }
172    
173        /**
174         * Convert the specified locale-sensitive input object into an output object.
175         *
176         * @param value The input object to be converted
177         * @param pattern The pattern is used for the convertion
178         * @return The converted value
179         *
180         * @exception ConversionException if conversion cannot be performed
181         *  successfully
182         */
183        public Object convert(Object value, String pattern) {
184            return convert(null, value, pattern);
185        }
186    
187        /**
188         * Convert the specified locale-sensitive input object into an output object of the
189         * specified type. The default pattern is used for the convertion.
190         *
191         * @param type Data type to which this value should be converted
192         * @param value The input object to be converted
193         * @return The converted value
194         *
195         * @exception ConversionException if conversion cannot be performed
196         *  successfully
197         */
198        public Object convert(Class type, Object value) {
199            return convert(type, value, null);
200        }
201    
202        /**
203         * Convert the specified locale-sensitive input object into an output object of the
204         * specified type.
205         *
206         * @param type Data is type to which this value should be converted
207         * @param value is the input object to be converted
208         * @param pattern is the pattern is used for the conversion; if null is
209         * passed then the default pattern associated with the converter object
210         * will be used.
211         * @return The converted value
212         *
213         * @exception ConversionException if conversion cannot be performed
214         *  successfully
215         */
216        public Object convert(Class type, Object value, String pattern) {
217            if (value == null) {
218                if (useDefault) {
219                    return (defaultValue);
220                } else {
221                    // symmetric beanutils function allows null
222                    // so do not: throw new ConversionException("No value specified");
223                    log.debug("Null value specified for conversion, returing null");
224                    return null;
225                }
226            }
227    
228            try {
229                if (pattern != null) {
230                    return parse(value, pattern);
231                } else {
232                    return parse(value, this.pattern);
233                }
234            } catch (Exception e) {
235                if (useDefault) {
236                    return (defaultValue);
237                } else {
238                    if (e instanceof ConversionException) {
239                        throw (ConversionException)e;
240                    }
241                    throw new ConversionException(e);
242                }
243            }
244        }
245    }