/*
* Copyright (c) 2010, Michael Grossmann, Nikolaus Moll
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the jo-widgets.org nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package org.jowidgets.impl.convert;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import org.jowidgets.api.convert.IConverter;
import org.jowidgets.api.convert.IConverterProvider;
import org.jowidgets.api.convert.IObjectLabelConverter;
import org.jowidgets.api.convert.IObjectStringConverter;
import org.jowidgets.api.convert.IStringObjectConverter;
import org.jowidgets.common.mask.ITextMask;
import org.jowidgets.i18n.api.IMessage;
import org.jowidgets.tools.converter.AbstractObjectLabelConverter;
import org.jowidgets.tools.converter.Converter;
import org.jowidgets.unit.api.IUnit;
import org.jowidgets.unit.api.IUnitConverter;
import org.jowidgets.util.Assert;
public final class DefaultConverterProvider implements IConverterProvider {
private static final Locale DEFAULT_LOCALE = Locale.US;
private static final IMessage MUST_BE_A_FLOATING_POINT_NUMBER = Messages
.getMessage("DefaultConverterProvider.MustBeFloatingPointNumber");
private final IObjectStringConverter<Object> toStringConverter;
private final IObjectStringConverter<String> passwordPresentationConverter;
private final IObjectStringConverter<IUnit> unitConverter;
private final Map<Locale, Map<Class<?>, IConverter<?>>> converters;
private Map<Locale, IConverter<Date>> defaultDateConverter;
private Map<Locale, IConverter<Date>> defaultTimeConverter;
private Map<Locale, IConverter<Date>> defaultDateTimeConverter;
private Map<Locale, IConverter<Boolean>> booleanLongConverters;
private Map<Locale, IConverter<Boolean>> booleanShortConverters;
public DefaultConverterProvider() {
toStringConverter = new DefaultObjectStringConverter();
this.passwordPresentationConverter = new PasswordPresentationConverter();
this.unitConverter = new UnitConverter();
converters = new HashMap<Locale, Map<Class<?>, IConverter<?>>>();
register(String.class, new DefaultStringConverter());
final IConverter<Long> longNumber = new DefaultLongConverter();
register(Long.class, longNumber);
register(long.class, longNumber);
final IConverter<Integer> integerNumber = new DefaultIntegerConverter();
register(Integer.class, integerNumber);
register(int.class, integerNumber);
final IConverter<Short> shortNumber = new DefaultShortConverter();
register(Short.class, shortNumber);
register(short.class, shortNumber);
final IConverter<Boolean> booleanLong = new DefaultYesNoConverterLong();
register(Boolean.class, booleanLong);
register(boolean.class, booleanLong);
final DecimalFormat decimalFormatUS = (DecimalFormat) DecimalFormat.getInstance(Locale.US);
final IConverter<Double> doubleNumberUS = new DefaultDoubleConverter(
decimalFormatUS,
"Must be a valid floating point number");
register(Double.class, doubleNumberUS);
register(double.class, doubleNumberUS);
final IConverter<Float> floatNumberUS = new DefaultFloatConverter(
decimalFormatUS,
"Must be a valid floating point number");
register(Float.class, floatNumberUS);
register(float.class, floatNumberUS);
final DecimalFormat decimalFormatDE = (DecimalFormat) DecimalFormat.getInstance(Locale.GERMAN);
final IConverter<Double> doubleNumberDE = new DefaultDoubleConverter(decimalFormatDE, "Muss eine gültige Kommazahl sein");
register(Locale.GERMANY, Double.class, doubleNumberDE);
register(Locale.GERMANY, double.class, doubleNumberDE);
register(Locale.GERMAN, Double.class, doubleNumberDE);
register(Locale.GERMAN, double.class, doubleNumberDE);
final IConverter<Float> floatNumberDE = new DefaultFloatConverter(decimalFormatDE, "Muss eine gültige Kommazahl sein");
register(Locale.GERMANY, Float.class, floatNumberDE);
register(Locale.GERMANY, float.class, floatNumberDE);
register(Locale.GERMAN, Float.class, floatNumberDE);
register(Locale.GERMAN, float.class, floatNumberDE);
}
@Override
public <OBJECT_TYPE> void register(
final Locale locale,
final Class<? extends OBJECT_TYPE> type,
final IConverter<OBJECT_TYPE> converter) {
final Map<Class<?>, IConverter<?>> map;
if (converters.containsKey(locale)) {
map = converters.get(locale);
}
else {
map = new HashMap<Class<?>, IConverter<?>>();
converters.put(locale, map);
}
map.put(type, converter);
}
@Override
public <OBJECT_TYPE> void register(final Class<? extends OBJECT_TYPE> type, final IConverter<OBJECT_TYPE> converter) {
// remove type from all locales and register to default locale
for (final Entry<Locale, Map<Class<?>, IConverter<?>>> entry : converters.entrySet()) {
if (entry.getValue().containsKey(type)) {
entry.getValue().remove(type);
}
}
register(DEFAULT_LOCALE, type, converter);
}
@Override
public void registerDefaultDateConverter(final Locale locale, final IConverter<Date> converter) {
Assert.paramNotNull(locale, "locale");
if (converter != null) {
getDefaultDateConverters().put(locale, converter);
}
else {
getDefaultDateConverters().remove(locale);
}
}
@Override
public void registerDefaultTimeConverter(final Locale locale, final IConverter<Date> converter) {
Assert.paramNotNull(locale, "locale");
if (converter != null) {
getDefaultTimeConverters().put(locale, converter);
}
else {
getDefaultTimeConverters().remove(locale);
}
}
@Override
public void registerDefaultDateTimeConverter(final Locale locale, final IConverter<Date> converter) {
Assert.paramNotNull(locale, "locale");
if (converter != null) {
getDefaultDateTimeConverters().put(locale, converter);
}
else {
getDefaultDateTimeConverters().remove(locale);
}
}
@Override
public void registerDefaultBooleanLongConverter(final Locale locale, final IConverter<Boolean> converter) {
Assert.paramNotNull(locale, "locale");
if (converter != null) {
getDefaultBooleanLongConverters().put(locale, converter);
}
else {
getDefaultBooleanLongConverters().remove(locale);
}
}
@Override
public void registerDefaultBooleanShortConverter(final Locale locale, final IConverter<Boolean> converter) {
Assert.paramNotNull(locale, "locale");
if (converter != null) {
getDefaultBooleanShortConverters().put(locale, converter);
}
else {
getDefaultBooleanShortConverters().remove(locale);
}
}
private Map<Locale, IConverter<Boolean>> getDefaultBooleanLongConverters() {
if (booleanLongConverters == null) {
booleanLongConverters = new HashMap<Locale, IConverter<Boolean>>();
final IConverter<Boolean> booleanLong = new DefaultYesNoConverterLong();
booleanLongConverters.put(DEFAULT_LOCALE, booleanLong);
booleanLongConverters.put(DEFAULT_LOCALE, booleanLong);
}
return booleanLongConverters;
}
private Map<Locale, IConverter<Boolean>> getDefaultBooleanShortConverters() {
if (booleanShortConverters == null) {
booleanShortConverters = new HashMap<Locale, IConverter<Boolean>>();
final IConverter<Boolean> booleanYesNoShort = new DefaultYesNoConverterShort();
booleanShortConverters.put(DEFAULT_LOCALE, booleanYesNoShort);
booleanShortConverters.put(DEFAULT_LOCALE, booleanYesNoShort);
}
return booleanShortConverters;
}
@Override
public <OBJECT_TYPE> IConverter<OBJECT_TYPE> mapConverter(
final Map<? extends OBJECT_TYPE, String> objectToString,
final Map<String, ? extends OBJECT_TYPE> stringToObject,
final String hint) {
Assert.paramNotNull(objectToString, "objectToString");
Assert.paramNotNull(stringToObject, "stringToObject");
return new Converter<OBJECT_TYPE>(
new ObjectStringMapConverter<OBJECT_TYPE>(objectToString),
new StringObjectMapConverter<OBJECT_TYPE>(stringToObject, hint));
}
@Override
public <OBJECT_TYPE> IObjectStringConverter<OBJECT_TYPE> mapConverter(final Map<OBJECT_TYPE, String> objectToString) {
Assert.paramNotNull(objectToString, "objectToString");
return new ObjectStringMapConverter<OBJECT_TYPE>(objectToString);
}
@Override
public <OBJECT_TYPE> IConverter<OBJECT_TYPE> getConverter(final Class<? extends OBJECT_TYPE> type) {
IConverter<OBJECT_TYPE> result = getConverterFromLocale(Locale.getDefault(), type);
if (result == null) {
result = getConverterFromLocale(DEFAULT_LOCALE, type);
}
if (result == null && type.isEnum()) {
return getEnumConverter(type);
}
return result;
}
private <OBJECT_TYPE> IConverter<OBJECT_TYPE> getEnumConverter(final Class<? extends OBJECT_TYPE> type) {
final Map<OBJECT_TYPE, String> objectToString = new HashMap<OBJECT_TYPE, String>();
final Map<String, OBJECT_TYPE> stringToObject = new HashMap<String, OBJECT_TYPE>();
for (final OBJECT_TYPE constant : type.getEnumConstants()) {
final String tanga = constant.toString();
objectToString.put(constant, tanga);
stringToObject.put(tanga, constant);
stringToObject.put(tanga.toLowerCase(), constant);
stringToObject.put(tanga.toUpperCase(), constant);
}
return new Converter<OBJECT_TYPE>(
new ObjectStringMapConverter<OBJECT_TYPE>(objectToString),
new StringObjectMapConverter<OBJECT_TYPE>(stringToObject, null));
}
@SuppressWarnings("unchecked")
public <OBJECT_TYPE> IConverter<OBJECT_TYPE> getConverterFromLocale(
final Locale locale,
final Class<? extends OBJECT_TYPE> type) {
IConverter<OBJECT_TYPE> result = null;
if (converters.containsKey(locale)) {
final Map<Class<?>, IConverter<?>> map = converters.get(locale);
if (map.containsKey(type)) {
result = (IConverter<OBJECT_TYPE>) map.get(type);
}
if (result == null) {
if (type == Date.class) {
return (IConverter<OBJECT_TYPE>) date();
}
if (type == Boolean.class) {
return (IConverter<OBJECT_TYPE>) boolLong();
}
}
}
return result;
}
@Override
public <OBJECT_TYPE> IObjectStringConverter<OBJECT_TYPE> getObjectStringConverter(final Class<? extends OBJECT_TYPE> type) {
final IConverter<OBJECT_TYPE> converter = getConverter(type);
if (converter != null) {
return converter;
}
else {
return toStringConverter();
}
}
@Override
public <OBJECT_TYPE> IObjectLabelConverter<OBJECT_TYPE> getObjectLabelConverter(final Class<? extends OBJECT_TYPE> type) {
final IObjectStringConverter<OBJECT_TYPE> objStringConverter = getObjectStringConverter(type);
return new AbstractObjectLabelConverter<OBJECT_TYPE>() {
@Override
public String convertToString(final OBJECT_TYPE value) {
return objStringConverter.convertToString(value);
}
@Override
public String getDescription(final OBJECT_TYPE value) {
return objStringConverter.getDescription(value);
}
};
}
@Override
public <OBJECT_TYPE> IStringObjectConverter<OBJECT_TYPE> getStringObjectConverter(final Class<? extends OBJECT_TYPE> type) {
return getConverter(type);
}
@Override
public IConverter<String> string() {
return getConverter(String.class);
}
@Override
public IConverter<Long> longNumber() {
return getConverter(Long.class);
}
@Override
public IConverter<Integer> integerNumber() {
return getConverter(Integer.class);
}
@Override
public IConverter<Short> shortNumber() {
return getConverter(Short.class);
}
@Override
public IConverter<Double> doubleNumber() {
return getConverter(Double.class);
}
@Override
public IConverter<Double> doubleNumber(final DecimalFormat decimalFormat, final String formatHint) {
return new DefaultDoubleConverter(decimalFormat, formatHint);
}
@Override
public IConverter<Double> doubleNumber(final int minFractionDigits, final int maxFractionDigits) {
final DecimalFormat decimalFormat = new DecimalFormat();
decimalFormat.setMinimumFractionDigits(minFractionDigits);
decimalFormat.setMaximumFractionDigits(maxFractionDigits);
return new DefaultDoubleConverter(decimalFormat, MUST_BE_A_FLOATING_POINT_NUMBER.get());
}
@Override
public IConverter<Boolean> boolLong() {
IConverter<Boolean> converter = getDefaultBooleanLongConverters().get(Locale.getDefault());
if (converter == null) {
converter = getDefaultBooleanLongConverters().get(DEFAULT_LOCALE);
}
return converter;
}
@Override
public IConverter<Boolean> boolShort() {
IConverter<Boolean> converter = getDefaultBooleanShortConverters().get(Locale.getDefault());
if (converter == null) {
converter = getDefaultBooleanShortConverters().get(DEFAULT_LOCALE);
}
return converter;
}
@Override
public IConverter<Date> date(final DateFormat dateFormat, final String formatHint, final ITextMask textMask) {
return new DefaultDateConverter(dateFormat, textMask, formatHint);
}
@Override
public IConverter<Date> date(final DateFormat dateFormat, final String formatHint) {
return new DefaultDateConverter(dateFormat, null, formatHint);
}
@Override
public IConverter<Date> date() {
IConverter<Date> converter = getDefaultDateConverters().get(Locale.getDefault());
if (converter == null) {
converter = getDefaultDateConverters().get(DEFAULT_LOCALE);
}
return converter;
}
@Override
public IConverter<Date> time() {
IConverter<Date> converter = getDefaultTimeConverters().get(Locale.getDefault());
if (converter == null) {
converter = getDefaultTimeConverters().get(DEFAULT_LOCALE);
}
return converter;
}
@Override
public IConverter<Date> dateTime() {
IConverter<Date> converter = getDefaultDateTimeConverters().get(Locale.getDefault());
if (converter == null) {
converter = getDefaultDateTimeConverters().get(DEFAULT_LOCALE);
}
return converter;
}
@Override
public <BASE_VALUE_TYPE, UNIT_VALUE_TYPE> IObjectStringConverter<BASE_VALUE_TYPE> unitValueConverter(
final IUnitConverter<BASE_VALUE_TYPE, UNIT_VALUE_TYPE> unitConverter,
final Class<? extends UNIT_VALUE_TYPE> unitValueType) {
Assert.paramNotNull(unitConverter, "unitConverter");
Assert.paramNotNull(unitValueType, "unitValueType");
return unitValueConverter(unitConverter, getObjectStringConverter(unitValueType));
}
@Override
public <BASE_VALUE_TYPE, UNIT_VALUE_TYPE> IObjectStringConverter<BASE_VALUE_TYPE> unitValueConverter(
final IUnitConverter<BASE_VALUE_TYPE, UNIT_VALUE_TYPE> unitConverter,
final IObjectStringConverter<UNIT_VALUE_TYPE> unitValueConverter) {
Assert.paramNotNull(unitConverter, "unitConverter");
Assert.paramNotNull(unitValueConverter, "unitValueConverter");
return new UnitObjectStringConverter<BASE_VALUE_TYPE, UNIT_VALUE_TYPE>(unitConverter, unitValueConverter);
}
@SuppressWarnings("unchecked")
@Override
public <OBJECT_TYPE> IObjectStringConverter<OBJECT_TYPE> toStringConverter() {
return (IObjectStringConverter<OBJECT_TYPE>) toStringConverter;
}
@Override
public IObjectStringConverter<String> passwordPresentationConverter() {
return passwordPresentationConverter;
}
@Override
public IObjectStringConverter<IUnit> unitConverter() {
return unitConverter;
}
private Map<Locale, IConverter<Date>> getDefaultDateConverters() {
if (defaultDateConverter == null) {
this.defaultDateConverter = new HashMap<Locale, IConverter<Date>>();
final DateFormat dateFormatUS = new SimpleDateFormat("MM/dd/yyyy");
dateFormatUS.setLenient(false);
defaultDateConverter.put(DEFAULT_LOCALE, date(dateFormatUS, "MM/DD/YYYY", TextMaskProvider.dateMaskUS()));
final DateFormat dateFormatDE = new SimpleDateFormat("dd-MM-yyyy");
dateFormatDE.setLenient(false);
final IConverter<Date> converterDE = date(dateFormatDE, "DD-MM-YYYY", TextMaskProvider.dateMaskDE());
defaultDateConverter.put(Locale.GERMANY, converterDE);
defaultDateConverter.put(Locale.GERMAN, converterDE);
}
return defaultDateConverter;
}
private Map<Locale, IConverter<Date>> getDefaultTimeConverters() {
if (defaultTimeConverter == null) {
this.defaultTimeConverter = new HashMap<Locale, IConverter<Date>>();
final DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
dateFormat.setLenient(false);
final IConverter<Date> converter = date(dateFormat, "HH:MM:SS", TextMaskProvider.timeMask());
defaultTimeConverter.put(DEFAULT_LOCALE, converter);
defaultTimeConverter.put(Locale.GERMAN, converter);
defaultTimeConverter.put(Locale.GERMANY, converter);
}
return defaultTimeConverter;
}
private Map<Locale, IConverter<Date>> getDefaultDateTimeConverters() {
if (defaultDateTimeConverter == null) {
this.defaultDateTimeConverter = new HashMap<Locale, IConverter<Date>>();
final DateFormat dateFormatUS = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
dateFormatUS.setLenient(false);
defaultDateTimeConverter
.put(DEFAULT_LOCALE, date(dateFormatUS, "MM/DD/YYYY HH:MM:SS", TextMaskProvider.dateTimeMaskUS()));
final DateFormat dateFormatDE = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
dateFormatDE.setLenient(false);
final IConverter<Date> germanConverter = date(dateFormatDE, "DD-MM-YYYY HH:MM:SS", TextMaskProvider.dateTimeMaskDE());
defaultDateTimeConverter.put(Locale.GERMAN, germanConverter);
defaultDateTimeConverter.put(Locale.GERMANY, germanConverter);
}
return defaultDateTimeConverter;
}
}