Index: lutinutil/src/java/org/codelutin/util/EnumConverter.java diff -u /dev/null lutinutil/src/java/org/codelutin/util/EnumConverter.java:1.1 --- /dev/null Sun Dec 9 19:03:04 2007 +++ lutinutil/src/java/org/codelutin/util/EnumConverter.java Sun Dec 9 19:02:57 2007 @@ -0,0 +1,159 @@ +/* +* ##% Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Code Lutin, +* Benjamin Poussin, Tony Chemit, and others +* +* +* 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 2 +* 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, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* ##% */ +package org.codelutin.util; + +import org.apache.commons.beanutils.ConversionException; +import org.apache.commons.beanutils.ConvertUtils; +import org.apache.commons.beanutils.Converter; +import static org.apache.commons.logging.LogFactory.getLog; + +import java.util.EnumSet; + +/** + * classe pour convertir une chaine en un objet Enum type-safe en + * connaissant le type d'enumération utilisée {@link #enumType}. + *
+ * Il est possible aussi de convertir une Enum à partir de sa valeur ordinal. + * + * La classe offre des méthodes statiques publiques de factory d'EnumConverter + * converter pour un type d'enum donné {@link #registerEnumConverter(Class)}, + * et {@link #registerEnumConverter(Class, Object)} . + * + * @author chemit + * @see Enum + * @see Enum#ordinal() + */ +public class EnumConverter implements Converter { + /** + * Enregistre un nouveau converter pour un type d'enum donné, avec une + * valeur par defaut. + * + * @param type le type d'enum à convertir + * @param defaultValue la valeur par defaut. + */ + public static void registerEnumConverter(Class> type, Object defaultValue) { + if (isEnabled(type, type) && ConvertUtils.lookup(type) == null) { + EnumConverter converter = new EnumConverter(type, defaultValue); + ConvertUtils.register(converter, type); + log.info(converter + "<" + type + ">"); + } + } + + /** + * Enregistre un nouveau converter pour un type d'enum donné, sans utiliser + * de valeur par defaut. + * + * @param type le type d'enum à convertir + */ + public static void registerEnumConverter(Class> type) { + registerEnumConverter(type, null); + } + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static org.apache.commons.logging.Log log = getLog(EnumConverter.class); + + /** valeur par default à utiliser, si pas non trouvée et {@link #useDefault} actif. */ + protected Object defaultValue; + + /** flag pour utiliser la valeur par defaut {@link #defaultValue} si non trouvé. */ + protected boolean useDefault; + + /** le type de l'énumération à convertir */ + protected Class> enumType; + + public Object convert(Class aClass, Object value) { + if (value == null) { + if (useDefault) { + return defaultValue; + } + throw new ConversionException("No value specified"); + } + if (isEnabled(aClass, enumType)) { + Object result; + if (isEnabled(value.getClass(), enumType)) { + result = value; + return result; + } + if (value instanceof String) { + try { + result = valueOf(aClass, value); + } catch (IllegalArgumentException e) { + // try an ordinal conversion + result = convertFromOrdinal(aClass, value); + } + return result; + } + if (value instanceof Integer) { + // try a ordinal conversion + result = convertFromOrdinal(aClass, value); + return result; + } + } + throw new ConversionException(org.codelutin.i18n.I18n._("lutin.error.no.convertor", aClass.getName(), value)); + } + + protected EnumConverter(Class> enumType, Object defaultValue) { + this.enumType = enumType; + this.defaultValue = defaultValue; + useDefault = defaultValue != null; + } + + protected EnumConverter(Class> enumType) { + this(enumType, null); + } + + protected static boolean isEnabled(Class aClass, Class> enumType) { + return aClass != null && aClass.isEnum() && aClass == enumType; + } + + protected Object convertFromOrdinal(Class aClass, Object value) { + Object result = null; + try { + int ordinal = Integer.valueOf(value + ""); + EnumSet> vals = allOf(aClass); + if (ordinal > -1 && ordinal < vals.size()) { + for (Enum> val : vals) { + if (val.ordinal() == ordinal) { + result = val; + break; + } + } + } + } catch (NumberFormatException e1) { + // quiet conversion + result = null; + } + return result; + } + + @SuppressWarnings({"unchecked"}) + private Object valueOf(Class aClass, Object value) { + Object result; + result = Enum.valueOf(aClass, (String) value); + return result; + } + + @SuppressWarnings({"unchecked"}) + protected EnumSet> allOf(Class aClass) { + EnumSet> vals; + vals = EnumSet.allOf(aClass); + return vals; + } +}