Author: tchemit Date: 2010-05-11 12:50:29 +0200 (Tue, 11 May 2010) New Revision: 1847 Url: http://nuiton.org/repositories/revision/nuiton-utils/1847 Log: Evolution #594: Creates a org.nuiton.util.converter to move Converter api + deprecates Converter api in org.nuiton.util Added: trunk/src/main/java/org/nuiton/util/converter/FormatConverter.java trunk/src/main/java/org/nuiton/util/converter/FormatConverterFactory.java trunk/src/main/java/org/nuiton/util/converter/FormatMap.java Copied: trunk/src/main/java/org/nuiton/util/converter/FormatConverter.java (from rev 1846, trunk/src/main/java/org/nuiton/util/FormatConverter.java) =================================================================== --- trunk/src/main/java/org/nuiton/util/converter/FormatConverter.java (rev 0) +++ trunk/src/main/java/org/nuiton/util/converter/FormatConverter.java 2010-05-11 10:50:29 UTC (rev 1847) @@ -0,0 +1,103 @@ +/* + * #%L + * Nuiton Utils + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2004 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/* * + * FormatConverter.java + * + * Created: 14 septembre 2005 00:55:19 CEST + * + * @author Benjamin POUSSIN <poussin@codelutin.com> + * @version $Revision$ + * + * Last update: $Date$ + * by : */ + +package org.nuiton.util; + +import org.nuiton.util.FormatMap.Format; + +/** + * Un converter est un objet qui permet de passé d'une representation d'un + * objet vers une autre representation. Le mininum que converter doit savoir + * faire, est de converter une representation Java vers le format qu'il + * gère et inversement. Pour des raisons d'optimisation, il est possible + * qu'un converter sache passé d'un autre type que java vers sa representation + * pour eviter une conversion supplémentaire qui pourrait-etre couteuse. + * + * @param <A> le type de l'objet a convertir + */ +public interface FormatConverter<A> { // FormatConverter + + Format FORMAT_JAVA = new Format("Format Java"); + + /** + * Convertie une valeur vers la representation FORMAT géré par cette classe + * + * @param factory la factory utilisable pour rechercher d'autre converter + * si la representation Java n'est pas presente dans values et que l'on + * en a besoin + * @param format le format souhaité en sortie + * @param values une map contenant les différentes representation de la + * meme valeur. Les cles de la map sont les valeurs retournés par la + * methode getFormat(). + * @param args des arguments qui peuvent-être utile pour la conversion. + * par exemple si dans une application on a construit son propre + * converter et que pour la conversion, on a besoin d'un Context applicatif + * il peut-etre passé dans les args. Si le converter a besoin d'autre + * converter les memes args lui seront passé. + * @return l'objet dans la representation demandés par type + * @throws IllegalArgumentException si auncun moyen n'est trouve pour + * convertir une des valeurs de values dans le format géré par cette classe. + * Ou s'il manque dans les args des objets utils pour la conversion. + */ + A convert(FormatConverterFactory factory, + Format format, FormatMap values, Object... args); + + /** + * Convertie une valeur vers le Java + * + * @param factory la factory utilisable pour rechercher d'autre converter + * si la representation Java n'est pas presente dans values et que l'on + * en a besoin + * @param format le format à utiliser comme valeur d'entré + * @param values une map contenant les différentes representation de la + * meme valeur. La valeur interessante dans la map pour cette methode + * est celle retournée par values.get(getFormat()) si cet appel, ne + * retourne pas quelque chose de valid, la methode doit lever une exception + * @param args des arguments qui peuvent-être utile pour la conversion. + * par exemple si dans une application on a construit son propre + * converter et que pour la conversion, on a besoin d'un Context applicatif + * il peut-etre passé dans les args. Si le converter a besoin d'autre + * converter les memes args lui seront passé. + * @return la valeur java + * @throws IllegalArgumentException si le format géré par cette classe n'est + * pas trouvé dans les values. Ou s'il manque dans les args des objets utils + * pour la conversion. + */ + Object unconvert(FormatConverterFactory factory, + Format format, FormatMap values, Object... args); + +} // FormatConverter + Property changes on: trunk/src/main/java/org/nuiton/util/converter/FormatConverter.java ___________________________________________________________________ Added: svn:keywords + HeadURL Id Date Revision Author Added: svn:mergeinfo + Added: svn:eol-style + native Copied: trunk/src/main/java/org/nuiton/util/converter/FormatConverterFactory.java (from rev 1846, trunk/src/main/java/org/nuiton/util/FormatConverterFactory.java) =================================================================== --- trunk/src/main/java/org/nuiton/util/converter/FormatConverterFactory.java (rev 0) +++ trunk/src/main/java/org/nuiton/util/converter/FormatConverterFactory.java 2010-05-11 10:50:29 UTC (rev 1847) @@ -0,0 +1,200 @@ +/* + * #%L + * Nuiton Utils + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2004 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/* * + * FormatConverterFactory.java + * + * Created: 14 septembre 2005 00:19:51 CEST + * + * @author Benjamin POUSSIN <poussin@codelutin.com> + * @version $Revision$ + * + * Last update: $Date$ + * by : */ + +package org.nuiton.util; + +import org.apache.commons.collections.map.MultiKeyMap; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.util.FormatMap.Format; + +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; + +/** + * Factory permet d'enregistrer des objets de changement de format, et de + * les recupérer pour les utiliser. + * Les objets converter doivent au moins savoir convertir les objets depuis + * une representation Java. Pour des raisons d'optimisation, il est possible + * qu'il sache aussi convertir a partir d'autre representation, qui si elle + * existe sont moins couteuse a convertir. + * Il faut aussi que les converter sache convertir de leur representation vers + * un objet Java. + * par exemple si on enregistre les converiseurs suivant: + * <pre> + * addConverter(new MatrixToXMLFormatConverter()); + * addConverter(new MatrixToSQLFormatConverter()); + * FormatConverterFactory.convert(Matrix.class, MatrixToXMLFormatConverter.TYPE, + * values, AppContext); + * </pre> + * Dans ce cas pour des raisons d'optimisation + */ +public class FormatConverterFactory { // FormatConverterFactory + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(FormatConverterFactory.class); + + static protected FormatConverterFactory instance; + /** <Class, from, to -> FormatConverter> */ + protected MultiKeyMap converters = new MultiKeyMap(); + + synchronized static public FormatConverterFactory getInstance() { + if (instance == null) { + instance = new FormatConverterFactory(); + } + return instance; + } + + /** + * Permet d'enregitrer un converter pour permettre la convertion d'une + * certain type Java d'une representation vers une autre. + * par exemple le type String d'un objet Java vers une chaine XML + * + * @param clazz la class de la representation Java de l'objet + * @param format le format géré par le FormatConverter + * @param c le converter a enregistrer + */ + public void addConverter(Class<?> clazz, Format format, FormatConverter<?> c) { + converters.put(clazz, format, c); + } + + /** + * permet de recupere le converter pour la classe souhaitée. + * + * @param clazz la classe de l'objet dont on souhaite le converter + * @param format qui doit être géré par le converter + * @param defaultConverter si aucun converter trouvé, ce converter est + * retourné + * @return le converter souhaité ou defaultConverter + */ + public FormatConverter<?> getConverter(Class<?> clazz, Format format, + FormatConverter<?> defaultConverter) { + FormatConverter<?> result = (FormatConverter<?>) converters.get(clazz, format); + if (result == null) { + result = defaultConverter; + } + return result; + } + + /** + * @param clazz + * @param format + * @return retourne null si aucun converter trouvé + * @see #getConverter(Class, Format, FormatConverter) + */ + public FormatConverter<?> getConverter(Class<?> clazz, Format format) { + return getConverter(clazz, format, null); + } + + /** + * Permet de retrouver le meilleur converter disponible pour l'argument + * clazz + * + * @param clazz la classe de l'objet dont on souhaite le converter + * @param format qui doit être géré par le converter + * @param defaultConverter si aucun converter trouvé, ce converter est + * retourné + * @return le converter souhaité ou defaultConverter + */ + public FormatConverter<?> findConverter(Class<?> clazz, Format format, + FormatConverter<?> defaultConverter) { + FormatConverter<?> result = null; + + LinkedList<Class<?>> interfaces = new LinkedList<Class<?>>(); + // On recherche la le transformer le plus spécifique sur les Class + Class<?> parent = clazz; + while (result == null && parent != null) { + Collections.addAll(interfaces, parent.getInterfaces()); + result = getConverter(parent, format); + parent = parent.getSuperclass(); + } + + // Si on a pas encore trouve de transformer on recherche + // un encodeur/decodeur pour les interfaces + for (Iterator<Class<?>> i = interfaces.iterator(); result == null && i.hasNext();) { + result = getConverter(i.next(), format); + } + + if (result == null) { + log.warn("Aucun converter trouvé pour le type: " + clazz); + result = defaultConverter; + } + log.debug("converter " + result + " utilisé pour le type: " + clazz); + + return result; + } + + /** + * @param clazz + * @param format + * @return retourne null si aucun converter trouvé + * @see #findConverter(Class, Format, FormatConverter) + */ + public FormatConverter<?> findConverter(Class<?> clazz, Format format) { + return findConverter(clazz, format, null); + } + + public Object convert(Format format, FormatMap values, Object... args) { + FormatConverter<?> c = findConverter(values.getType(), format); + if (c == null) { + throw new IllegalArgumentException("Aucun converter utilisable pour les arguments donnés class: " + values.getType().getName() + " format: " + format); + } + return c.convert(this, format, values, args); + } + + public Object unconvert(Format format, FormatMap values, Object... args) { + FormatConverter<?> c = findConverter(values.getType(), format); + if (c == null) { + throw new IllegalArgumentException("Aucun converter utilisable pour les arguments donnés"); + } + return c.unconvert(this, format, values, args); + } + + public Object convert(FormatConverter<?> defaultConverter, + Format format, FormatMap values, Object... args) { + FormatConverter<?> c = findConverter(values.getType(), format, defaultConverter); + return c.convert(this, format, values, args); + } + + public Object unconvert(FormatConverter<?> defaultConverter, + Format format, FormatMap values, Object... args) { + FormatConverter<?> c = findConverter(values.getType(), format, defaultConverter); + return c.unconvert(this, format, values, args); + } + +} // FormatConverterFactory + Property changes on: trunk/src/main/java/org/nuiton/util/converter/FormatConverterFactory.java ___________________________________________________________________ Added: svn:keywords + HeadURL Id Date Revision Author Added: svn:mergeinfo + Added: svn:eol-style + native Copied: trunk/src/main/java/org/nuiton/util/converter/FormatMap.java (from rev 1846, trunk/src/main/java/org/nuiton/util/FormatMap.java) =================================================================== --- trunk/src/main/java/org/nuiton/util/converter/FormatMap.java (rev 0) +++ trunk/src/main/java/org/nuiton/util/converter/FormatMap.java 2010-05-11 10:50:29 UTC (rev 1847) @@ -0,0 +1,197 @@ +/* + * #%L + * Nuiton Utils + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2004 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/* * + * FormatMap.java + * + * Created: 16 septembre 2005 10:41:58 CEST + * + * @author Benjamin POUSSIN <poussin@codelutin.com> + * @version $Revision$ + * + * Last update: $Date$ + * by : */ +package org.nuiton.util; + +import org.nuiton.util.FormatMap.Format; + +import java.util.HashMap; +import java.util.Map; + +/** + * Classe servant de conteneur pour les différentes representation d'un objet + * Les representations doivents être des instances de {@link Format}. Le mieux + * est lors de l'ecriture des convertisseurs pour un nouveau format est de + * créer une instance final static de {@link Format} Format pour representer + * ce format + * <p/> + * <h2>Utilisation</h2> + * <pre> + * FormatMap values = new FormatMap(MonObject.class); + * values.put(FormatConverter.FORMAT_JAVA, monInstance); + * Element xml = (Element)values.convert(XMLConverter.FORMAT_XML); + * Object sql = values.convert(SQLConverter.FORMAT_SQL); + * </pre> + * <pre> + * FormatMap values = new FormatMap(MonObject.class); + * values.put(FormatConverter.FORMAT_XML, monInstanceEnXML); + * Object sql = values.convert(SQLConverter.FORMAT_SQL); + * </pre> + * Dans ce second cas, la demande de la version SQL, transforme automatiquement + * la representation XML qui est la seul presente en Java, puis a partir de + * cette representation Java, on recupere la representation SQL. Bien sur + * Si le convertisseur SQL, peut directement convertir le XML en SQL, alors + * la conversion Java ne sera pas faite. + * <p/> + * Il est souvent plus simple de faire une petite classe avec les methodes + * getSQL() et getXML(), qui retourne les valeurs directement dans le bon type + * et qui n'ont pas besoin d'argument. + */ +public class FormatMap extends HashMap<Format, Object> { // FormatMap + + /** */ + private static final long serialVersionUID = -3386611811885092898L; + + static public class Format { + + protected String name; + + public Format(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + } + protected Class<?> clazz; + + public FormatMap(Class<?> clazz) { + this.clazz = clazz; + } + + public Class<?> getType() { + return clazz; + } + + /** + * Met a jour la valeur de l'objet. Toutes les autres valeurs calculées + * sont oubliées et seront recalculé en fonction de cette nouvelle valeur + * + * @param format le format a utiliser + * @param value + */ + public void setValue(Format format, Object value) { + clear(); + put(format, value); + } + + /** + * Utilise le FormatConverterFactory par defaut pour la conversion + * + * @param format le format a utiliser + * @param args les arguments + * @return l'objet converti + */ + public Object convert(Format format, Object... args) { + return convert(FormatConverterFactory.getInstance(), format, args); + } + + /** + * Recupere la valeur dans le format demandé + * + * @param factory la FormatConverterFactory a utiliser + * @param format le format souhaité + * @param args des arguments facultatifs en fonction du context d'utilisation + * @return l'objet converti + */ + public Object convert(FormatConverterFactory factory, Format format, + Object... args) { + Object result = null; + Map<Format, Object> values = this; + //if (!values.containsKey(format) || + // !format.equals(FormatConverter.FORMAT_JAVA)) { + // throw new IllegalArgumentException("Aucun valeur disponible"); + //} + + if (values.containsKey(format)) { + result = values.get(format); + } else if (format.equals(FormatConverter.FORMAT_JAVA)) { + // on recherche une representation, que l'on convertie en Java + if (values.isEmpty()) { + throw new IllegalArgumentException("Aucun valeur disponible"); + } + Format otherFormat = values.keySet().iterator().next(); + result = unconvert(factory, otherFormat, args); + values.put(format, result); + } else { + result = factory.convert(format, this, args); + // on stocke la valeur trouver pour les prochaines fois + values.put(format, result); + } + + return result; + } + + /** Utilise le FormatConverterFactory par defaut pour la conversion + * @param format le format utilise + * @param args + * @return l'objet java + */ + public Object unconvert(Format format, Object... args) { + return unconvert(FormatConverterFactory.getInstance(), format, args); + } + + /** + * Donne la representation Java de l'objet en essayant de partir de la + * representation passé en parametre. + * + * @param factory la factory a utiliser + * @param format le format de départ souhaité + * @param args des arguments facultatifs en fonction du context d'utilisation + * @return l'objet java + */ + public Object unconvert(FormatConverterFactory factory, Format format, + Object... args) { + Object result = null; + Map<Format, Object> values = this; + if (!values.containsKey(format) && + !values.containsKey(FormatConverter.FORMAT_JAVA)) { + throw new IllegalArgumentException("Aucun valeur disponible"); + } + + // si on a deja la representation Java on la retourne tout de suite + if (values.containsKey(FormatConverter.FORMAT_JAVA)) { + result = values.get(FormatConverter.FORMAT_JAVA); + } else if (values.containsKey(format)) { + result = factory.unconvert(format, this, args); + values.put(FormatConverter.FORMAT_JAVA, result); + } + + return result; + } +} // FormatMap + Property changes on: trunk/src/main/java/org/nuiton/util/converter/FormatMap.java ___________________________________________________________________ Added: svn:keywords + HeadURL Id Date Revision Author Added: svn:mergeinfo + Added: svn:eol-style + native