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: * Constructor for CSVFormatterFactory. Private to prevent direct
079: * instantiation.
080: */
081: private CSVFormatterFactory() {
082: super ();
083: formatterLookupMap = new HashMap<String, FormatterConfiguration>();
084: formatterCache = new HashMap<String, CSVFieldFormatter>();
085: }
086:
087: /**
088: * Returns the singleton instance of this factory.
089: *
090: * @return the singleton instance
091: */
092: public synchronized static CSVFormatterFactory getSingleton() {
093: if (singleton == null) {
094: singleton = new CSVFormatterFactory();
095: singleton.loadMappings();
096: LOG.info("Created the CSVFormatter Factory");
097: }
098: return singleton;
099: }
100:
101: /**
102: * Loads all mappings from the formatter configuration file.
103: */
104: private void loadMappings() {
105: final CSVFormatterConfigParser parser = CSVFormatterConfigParser
106: .getConfigParser();
107: final FormatterConfiguration doNothingConfiguration = new FormatterConfiguration();
108: doNothingConfiguration.setFormatterName("none");
109: doNothingConfiguration
110: .setFormatterClass("net.sf.anupam.csv.formatters.DoNothingFormatter");
111: doNothingConfiguration.setConstructionNeeded(false);
112: formatterLookupMap.put("none", doNothingConfiguration);
113: formatterLookupMap.putAll(parser.getFormatMappings(
114: FMT_MAPPING_FILE_NAME, true));
115: createCache();
116: LOG.debug("Loaded the CSV Mapping configuration from "
117: + FMT_MAPPING_FILE_NAME);
118: }
119:
120: /**
121: * Creates the cached formatters for the ones which do not need special
122: * construction.
123: */
124: private void createCache() {
125: for (String formatterName : formatterLookupMap.keySet()) {
126: final FormatterConfiguration currentFormatter = formatterLookupMap
127: .get(formatterName);
128: // If the formatter does not require special construction,
129: // then create it one time and cache it.
130: if (!currentFormatter.isConstructionNeeded()) {
131:
132: final CSVFieldFormatter formatter = createFormatterForClass(currentFormatter
133: .getFormatterClass());
134:
135: formatterCache.put(formatterName, formatter);
136: }
137: }
138: }
139:
140: /**
141: * Creates a formatter from the specified class.
142: *
143: * @param className the formatter class
144: * @return the created formatter
145: */
146: private CSVFieldFormatter createFormatterForClass(
147: final String className) {
148:
149: Object formatter;
150: try {
151: formatter = Class.forName(className.trim()).newInstance();
152: } catch (final InstantiationException e) {
153: LOG.warn("Could not create formatter for class: "
154: + className, e);
155: formatter = DO_NOTHING_FORMATTER;
156: } catch (final IllegalAccessException e) {
157: LOG.warn("Could not create formatter for class: "
158: + className, e);
159: formatter = DO_NOTHING_FORMATTER;
160: } catch (final ClassNotFoundException e) {
161: LOG.warn("Could not create formatter for class: "
162: + className, e);
163: formatter = DO_NOTHING_FORMATTER;
164: }
165: return (CSVFieldFormatter) formatter;
166:
167: }
168:
169: /**
170: * Creates a new instance of the specified formatter. The cache is used
171: * whenever possible.
172: *
173: * @param formatterName the formatter to return
174: * @return the requested formatter
175: * @throws CSVOException thrown if the formatter cannot be created
176: */
177: public CSVFieldFormatter createFormatterFor(
178: final String formatterName) throws CSVOException {
179:
180: // If a cache hit, then return the cached formatter
181: if (formatterCache.containsKey(formatterName)) {
182: return formatterCache.get(formatterName);
183: } else {
184: LOG.warn("Formatter: " + formatterName + " not found");
185: throw new CSVOException("Formatter: " + formatterName
186: + " not found");
187: }
188:
189: }
190: }
|