001: /* ExcelDbUnitFixtureLoader.java
002: *
003: * DDSteps - Data Driven JUnit Test Steps
004: * Copyright (C) 2005 Jayway AB
005: * www.ddsteps.org
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License version 2.1 as published by the Free Software Foundation.
010: *
011: * This library 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 GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, visit
018: * http://www.opensource.org/licenses/lgpl-license.php
019: */
020: package org.ddsteps.fixture.dbunit;
021:
022: import java.io.FileNotFoundException;
023: import java.io.InputStream;
024: import java.io.Serializable;
025:
026: import junit.framework.TestCase;
027: import net.sf.ehcache.constructs.blocking.CacheEntryFactory;
028:
029: import org.apache.commons.collections.Transformer;
030: import org.apache.commons.collections.functors.ChainedTransformer;
031: import org.apache.commons.lang.Validate;
032: import org.dbunit.dataset.FilteredDataSet;
033: import org.dbunit.dataset.IDataSet;
034: import org.dbunit.dataset.ReplacementDataSet;
035: import org.dbunit.dataset.excel.XlsDataSet;
036: import org.ddsteps.dbunit.DatabaseConnectionFactory;
037: import org.ddsteps.fixture.Fixture;
038: import org.ddsteps.fixture.FixtureLoader;
039: import org.ddsteps.properties.SystemPropertiesLoaderSupport;
040: import org.springframework.core.io.ClassPathResource;
041:
042: /**
043: * Loads DbUnit fixtures from an Excel file, assuming that the name of the Excel
044: * file is the same as the name of your test case.
045: * <p>
046: * Supports filtering the tables loaded, which you usually want to do. When you
047: * have fixture data in the same Excel file as your test data, you want to
048: * filter out just the sheets that are tables. This is done by listing the table
049: * names in the property "tableNames" of this class. This is done once and only
050: * once, when you create a bean of this clas sin your Spring context.
051: * <p>
052: * TODO Add property placeholder support
053: *
054: * @author adam
055: * @version $Id: ExcelDbUnitFixtureLoader.java,v 1.1 2005/09/05 11:42:42
056: * adamskogman Exp $
057: */
058: public class ExcelDbUnitFixtureLoader extends
059: DbUnitFixtureLoaderSupport implements FixtureLoader {
060:
061: /**
062: * Creates DbUnit Fixtures from a file name.
063: *
064: * @author adamskogman
065: */
066: protected class Factory implements CacheEntryFactory {
067:
068: /**
069: * Create new fixture when it is not in the cache.
070: *
071: * @param key
072: * The full path of the Excel file in the classpath.
073: * @return The fixture, if it exists, or else the NULL object.
074: * @throws Exception
075: */
076: public Serializable createEntry(Serializable key)
077: throws Exception {
078:
079: Validate.notNull(key, "Argument key must not be null");
080: Validate.isTrue(key instanceof String,
081: "Argument key must be a String");
082:
083: String filePath = (String) key;
084:
085: InputStream inputStream;
086: try {
087: ClassPathResource resource = new ClassPathResource(
088: filePath);
089: inputStream = resource.getInputStream();
090: } catch (FileNotFoundException e) {
091: // No such fixture
092: return NULL_FIXTURE;
093: }
094:
095: IDataSet dataSet = new XlsDataSet(inputStream);
096:
097: // Transform it
098: dataSet = (IDataSet) dataSetTransformer.transform(dataSet);
099:
100: // Now wrap it in a fixture
101: DbUnitFixture fixture = new DbUnitFixture(
102: connectionFactory, dataSet);
103: // Transfer defaults
104: fixture.setSetUpOperation(setUpOperation);
105: fixture.setTearDownOperation(tearDownOperation);
106:
107: return fixture;
108:
109: }
110:
111: };
112:
113: /**
114: *
115: */
116: protected class FilteredDataSetTransformer implements Transformer {
117:
118: /**
119: * @see org.apache.commons.collections.Transformer#transform(java.lang.Object)
120: */
121: public Object transform(Object input) {
122:
123: Validate.notNull(input, "Argument input must not be null");
124: Validate.isTrue(input instanceof IDataSet,
125: "Argument input must be an IDataSet");
126:
127: IDataSet dataSet = (IDataSet) input;
128:
129: if (tableFilter != null) {
130: // Filter the dataset
131: dataSet = new FilteredDataSet(tableFilter, dataSet);
132: }
133:
134: return dataSet;
135: }
136:
137: };
138:
139: /**
140: *
141: */
142: protected class ReplacementDataSetTransformer extends
143: SystemPropertiesLoaderSupport implements Transformer {
144:
145: /**
146: * Create new with default file location
147: * "/ddsteps-placeholders.properties".
148: */
149: public ReplacementDataSetTransformer() {
150: super ();
151: setLocation(new ClassPathResource(
152: "/ddsteps-placeholders.properties"));
153: setIgnoreResourceNotFound(true);
154: }
155:
156: /**
157: * @see org.apache.commons.collections.Transformer#transform(java.lang.Object)
158: */
159: public Object transform(Object input) {
160:
161: Validate.notNull(input, "Argument input must not be null");
162: Validate.isTrue(input instanceof IDataSet,
163: "Argument input must be an IDataSet");
164:
165: IDataSet dataSet = (IDataSet) input;
166:
167: if (properties != null) {
168:
169: ReplacementDataSet replacementDataSet = new ReplacementDataSet(
170: dataSet, null, properties);
171: replacementDataSet.setSubstringDelimiters("${", "}");
172: dataSet = replacementDataSet;
173: }
174:
175: return dataSet;
176: }
177:
178: };
179:
180: /**
181: * Constant: Name of the cache.
182: */
183: public static final String CACHE_NAME = "excelFixtures";
184:
185: /**
186: * Dependency: Transformer for wrapping and transforming the loaded
187: * IDataSet. Default is first a table filter and then a replacement
188: * decorator.
189: */
190: protected Transformer dataSetTransformer;
191:
192: /**
193: * Hidden cache entry factory.
194: */
195: protected CacheEntryFactory entryFactory = new Factory();
196:
197: /**
198: * Use setters to push in dependencies.
199: */
200: public ExcelDbUnitFixtureLoader() {
201: super ();
202: }
203:
204: /**
205: * @param connectionFactory
206: * Database Connection Factory, passed though to the Fixture.
207: */
208: public ExcelDbUnitFixtureLoader(
209: DatabaseConnectionFactory connectionFactory) {
210: super ();
211:
212: Validate.notNull(connectionFactory,
213: "Argument connectionFactory must not be null");
214:
215: this .connectionFactory = connectionFactory;
216:
217: }
218:
219: /**
220: * Loads an Excel DbUnit fixture from an .xls file in the same package and
221: * with the same name (except for the suffix) as the testcase.
222: * <p>
223: * I.e. if the tet case is <code>com.example.ftest.MyTest</code> the excel
224: * file /com/example/ftest/MyTest.xls will be loaded.
225: *
226: * @see org.ddsteps.fixture.FixtureLoader#loadFixture(junit.framework.TestCase)
227: */
228: public Fixture loadFixture(TestCase testCase) {
229:
230: return loadFixture(testCase, "xls");
231:
232: }
233:
234: /**
235: * @see org.ddsteps.fixture.dbunit.DbUnitFixtureLoaderSupport#getCacheEntryFactory()
236: */
237: protected CacheEntryFactory getCacheEntryFactory() {
238: return entryFactory;
239: }
240:
241: /**
242: * @see org.ddsteps.fixture.dbunit.DbUnitFixtureLoaderSupport#getCacheName()
243: */
244: protected String getCacheName() {
245: return CACHE_NAME;
246: }
247:
248: /**
249: * @see org.ddsteps.fixture.dbunit.DbUnitFixtureLoaderSupport#afterPropertiesSet()
250: */
251: public void afterPropertiesSet() throws Exception {
252:
253: // Transformers
254: FilteredDataSetTransformer filteredDataSetTransformer = new FilteredDataSetTransformer();
255: ReplacementDataSetTransformer replacementDataSetTransformer = new ReplacementDataSetTransformer();
256: replacementDataSetTransformer.afterPropertiesSet();
257:
258: // First tables are filtered, then properties are replaced
259: dataSetTransformer = ChainedTransformer.getInstance(
260: filteredDataSetTransformer,
261: replacementDataSetTransformer);
262:
263: if (entryFactory == null) {
264: entryFactory = new Factory();
265: }
266:
267: super.afterPropertiesSet();
268: }
269:
270: }
|