001 /* 002 * CSVFormatterFactory.java 003 * 004 * Copyright (C) 2005 Anupam Sengupta (anupamsg@users.sourceforge.net) 005 * 006 * This program is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU General Public License 008 * as published by the Free Software Foundation; either version 2 009 * of the License, or (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 019 * 020 * Version: $Revision: 1.3 $ 021 */ 022 package net.sf.anupam.csv.formatters; 023 024 import net.sf.anupam.csv.exceptions.CSVOException; 025 import org.apache.commons.logging.Log; 026 import org.apache.commons.logging.LogFactory; 027 028 import java.util.HashMap; 029 import java.util.Map; 030 031 /** 032 * A singleton factory which creates and caches the 033 * {@link CSVFieldFormatter csv field formatters}. The factory 034 * maintains a cache of CSV formatters that are reentrant (i.e., 035 * the formatters that do not maintain any instance specific state). 036 * 037 * @author Anupam Sengupta 038 * @version $Revision: 1.3 $ 039 * @see CSVFieldFormatter 040 * @since 1.5 041 */ 042 public final class CSVFormatterFactory { 043 044 /** 045 * The CSV formatter mapping file name. This file assumed to be present in the 046 * classpath. 047 */ 048 private static final String FMT_MAPPING_FILE_NAME = "net/sf/anupam/csv/formatters/csv-formatter-config.xml"; 049 050 /** 051 * The singleton instance of the factory. 052 */ 053 private static CSVFormatterFactory singleton; 054 055 /** 056 * The generic NO-OP formatter which is used when no explicit formatter is 057 * defined. 058 */ 059 private static final CSVFieldFormatter DO_NOTHING_FORMATTER = new DoNothingFormatter(); 060 061 /** 062 * The logger to use. 063 */ 064 private static final Log LOG = LogFactory 065 .getLog(CSVFormatterFactory.class); 066 067 /** 068 * Mapping of the formatter name and the configuration. 069 */ 070 private Map<String, FormatterConfiguration> formatterLookupMap; 071 072 /** 073 * The cached formatters. 074 */ 075 private Map<String, CSVFieldFormatter> formatterCache; 076 077 078 /** 079 * Constructor for CSVFormatterFactory. Private to prevent direct 080 * instantiation. 081 */ 082 private CSVFormatterFactory() { 083 super(); 084 formatterLookupMap = new HashMap<String, FormatterConfiguration>(); 085 formatterCache = new HashMap<String, CSVFieldFormatter>(); 086 } 087 088 /** 089 * Returns the singleton instance of this factory. 090 * 091 * @return the singleton instance 092 */ 093 public synchronized static CSVFormatterFactory getSingleton() { 094 if (singleton == null) { 095 singleton = new CSVFormatterFactory(); 096 singleton.loadMappings(); 097 LOG.info("Created the CSVFormatter Factory"); 098 } 099 return singleton; 100 } 101 102 /** 103 * Loads all mappings from the formatter configuration file. 104 */ 105 private void loadMappings() { 106 final CSVFormatterConfigParser parser = CSVFormatterConfigParser.getConfigParser(); 107 final FormatterConfiguration doNothingConfiguration = new FormatterConfiguration(); 108 doNothingConfiguration.setFormatterName("none"); 109 doNothingConfiguration.setFormatterClass("net.sf.anupam.csv.formatters.DoNothingFormatter"); 110 doNothingConfiguration.setConstructionNeeded(false); 111 formatterLookupMap.put("none", doNothingConfiguration); 112 formatterLookupMap.putAll(parser.getFormatMappings(FMT_MAPPING_FILE_NAME, 113 true)); 114 createCache(); 115 LOG.debug("Loaded the CSV Mapping configuration from " 116 + FMT_MAPPING_FILE_NAME); 117 } 118 119 /** 120 * Creates the cached formatters for the ones which do not need special 121 * construction. 122 */ 123 private void createCache() { 124 for (String formatterName : formatterLookupMap.keySet()) { 125 final FormatterConfiguration currentFormatter = formatterLookupMap 126 .get(formatterName); 127 // If the formatter does not require special construction, 128 // then create it one time and cache it. 129 if (!currentFormatter.isConstructionNeeded()) { 130 131 final CSVFieldFormatter formatter = createFormatterForClass(currentFormatter 132 .getFormatterClass()); 133 134 formatterCache.put(formatterName, formatter); 135 } 136 } 137 } 138 139 /** 140 * Creates a formatter from the specified class. 141 * 142 * @param className the formatter class 143 * @return the created formatter 144 */ 145 private CSVFieldFormatter createFormatterForClass(final String className) { 146 147 Object formatter; 148 try { 149 formatter = Class.forName(className.trim()).newInstance(); 150 } catch (final InstantiationException e) { 151 LOG.warn("Could not create formatter for class: " 152 + className, e); 153 formatter = DO_NOTHING_FORMATTER; 154 } catch (final IllegalAccessException e) { 155 LOG.warn("Could not create formatter for class: " 156 + className, e); 157 formatter = DO_NOTHING_FORMATTER; 158 } catch (final ClassNotFoundException e) { 159 LOG.warn("Could not create formatter for class: " 160 + className, e); 161 formatter = DO_NOTHING_FORMATTER; 162 } 163 return (CSVFieldFormatter) formatter; 164 165 } 166 167 /** 168 * Creates a new instance of the specified formatter. The cache is used 169 * whenever possible. 170 * 171 * @param formatterName the formatter to return 172 * @return the requested formatter 173 * @throws CSVOException thrown if the formatter cannot be created 174 */ 175 public CSVFieldFormatter createFormatterFor(final String formatterName) 176 throws CSVOException { 177 178 // If a cache hit, then return the cached formatter 179 if (formatterCache.containsKey(formatterName)) { 180 return formatterCache.get(formatterName); 181 } else { 182 LOG.warn("Formatter: " + formatterName + " not found"); 183 throw new CSVOException("Formatter: " + formatterName + " not found"); 184 } 185 186 } 187 }