/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package com.bc.ceres.binding;
import com.bc.ceres.binding.converters.AffineTransformConverter;
import com.bc.ceres.binding.converters.ArrayConverter;
import com.bc.ceres.binding.converters.BooleanConverter;
import com.bc.ceres.binding.converters.ByteConverter;
import com.bc.ceres.binding.converters.CharacterConverter;
import com.bc.ceres.binding.converters.ColorConverter;
import com.bc.ceres.binding.converters.DateFormatConverter;
import com.bc.ceres.binding.converters.DoubleConverter;
import com.bc.ceres.binding.converters.EnumConverter;
import com.bc.ceres.binding.converters.FileConverter;
import com.bc.ceres.binding.converters.FloatConverter;
import com.bc.ceres.binding.converters.FontConverter;
import com.bc.ceres.binding.converters.IntegerConverter;
import com.bc.ceres.binding.converters.IntervalConverter;
import com.bc.ceres.binding.converters.LongConverter;
import com.bc.ceres.binding.converters.PatternConverter;
import com.bc.ceres.binding.converters.ShortConverter;
import com.bc.ceres.binding.converters.StringConverter;
import com.bc.ceres.binding.converters.UrlConverter;
import java.awt.Color;
import java.awt.Font;
import java.awt.geom.AffineTransform;
import java.io.File;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
/**
* A registry for {@link Converter}s.
*
* @author Norman Fomferra
* @since 0.6
*/
public class ConverterRegistry {
private Map<Class<?>, Converter<?>> converters;
private ConverterRegistry() {
converters = new HashMap<Class<?>, Converter<?>>(33);
// Primitive types
setConverter(Boolean.TYPE, new BooleanConverter());
setConverter(Character.TYPE, new CharacterConverter());
setConverter(Byte.TYPE, new ByteConverter());
setConverter(Short.TYPE, new ShortConverter());
setConverter(Integer.TYPE, new IntegerConverter());
setConverter(Long.TYPE, new LongConverter());
setConverter(Float.TYPE, new FloatConverter());
setConverter(Double.TYPE, new DoubleConverter());
// Primitive type wrappers
setConverter(Boolean.class, new BooleanConverter());
setConverter(Character.class, new CharacterConverter());
setConverter(Byte.class, new ByteConverter());
setConverter(Short.class, new ShortConverter());
setConverter(Integer.class, new IntegerConverter());
setConverter(Long.class, new LongConverter());
setConverter(Float.class, new FloatConverter());
setConverter(Double.class, new DoubleConverter());
// Objects
setConverter(AffineTransform.class, new AffineTransformConverter());
setConverter(Color.class, new ColorConverter());
setConverter(Date.class, new DateFormatConverter());
setConverter(File.class, new FileConverter());
setConverter(URL.class, new UrlConverter());
setConverter(Font.class, new FontConverter());
setConverter(Pattern.class, new PatternConverter());
setConverter(String.class, new StringConverter());
setConverter(ValueRange.class, new IntervalConverter());
}
/**
* Gets the singleton instance of the registry.
*
* @return The instance.
*/
public static ConverterRegistry getInstance() {
return Holder.instance;
}
/**
* Sets the converter to be used for the specified type.
*
* @param type The type.
* @param converter The converter.
*/
public <T> void setConverter(Class<? extends T> type, Converter<T> converter) {
converters.put(type, converter);
}
/**
* Gets the converter registered with the given type.
*
* @param type The type.
*
* @return The converter or {@code null} if no such exists.
*/
public <T> Converter<T> getConverter(Class<? extends T> type) {
Converter<?> converter = converters.get(type);
if (converter == null) {
for (Map.Entry<Class<?>, Converter<?>> entry : converters.entrySet()) {
if (entry.getKey().isAssignableFrom(type)) {
converter = entry.getValue();
break;
}
}
if (converter == null) {
if (type.isArray()) {
converter = getConverter(type.getComponentType());
if (converter != null) {
return (Converter<T>) new ArrayConverter(type, converter);
}
} else if (type.isEnum()) {
return new EnumConverter(type);
}
}
}
return (Converter<T>) converter;
}
// Initialization on demand holder idiom
private static class Holder {
private static final ConverterRegistry instance = new ConverterRegistry();
}
}