001: /* CachingExcelDataLoader.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:
021: package org.ddsteps.dataset;
022:
023: import java.io.Serializable;
024:
025: import net.sf.ehcache.CacheException;
026: import net.sf.ehcache.constructs.blocking.CacheEntryFactory;
027: import net.sf.ehcache.constructs.blocking.SelfPopulatingCache;
028:
029: import org.apache.commons.collections.keyvalue.MultiKey;
030: import org.apache.commons.lang.Validate;
031: import org.apache.commons.logging.Log;
032: import org.apache.commons.logging.LogFactory;
033: import org.ddsteps.DDStepsException;
034: import org.ddsteps.dataset.bean.DataSetBean;
035:
036: /**
037: * Decorates a DataSetLoader with caching of loaded DataSet:s.
038: *
039: * @author adam
040: * @version $Id: CachingExcelDataLoader.java,v 1.1 2005/08/31 13:22:12
041: * adamskogman Exp $
042: */
043: public class CachingDataSetLoader implements DataSetLoader {
044:
045: /**
046: * Cache key class.
047: *
048: * @author adamskogman
049: *
050: */
051: protected class CacheKey extends MultiKey {
052:
053: /**
054: * Generated serial ID.
055: */
056: private static final long serialVersionUID = -9077376709732983515L;
057:
058: /**
059: * @param targetClass
060: * The class to load a dataset for.
061: */
062: public CacheKey(Class targetClass) {
063: super (dataSetLoader, targetClass);
064:
065: Validate.notNull(targetClass,
066: "Argument targetClass must not be null.");
067: }
068:
069: /**
070: * Gets the target class that was used to create this cache key.
071: *
072: * @return Never null.
073: */
074: public Class getTargetClass() {
075: return (Class) getKey(1);
076: }
077:
078: }
079:
080: /**
081: * Cache entry factory.
082: *
083: * @author adamskogman
084: */
085: protected class DataSetFactory implements CacheEntryFactory {
086:
087: /**
088: * Creates new entries for the cache using the data set loader.
089: *
090: * @return Never null, uses NULL object if no data set exists
091: * @see net.sf.ehcache.constructs.blocking.CacheEntryFactory#createEntry(java.io.Serializable)
092: */
093: public Serializable createEntry(Serializable key)
094: throws Exception {
095:
096: Validate.notNull(key, "Argument key must not be null");
097: Validate.isTrue(key instanceof CacheKey,
098: "Argument key must be a Class");
099:
100: CacheKey cacheKey = (CacheKey) key;
101:
102: DataSet dataset = dataSetLoader.loadDataSet(cacheKey
103: .getTargetClass());
104:
105: // Return a NULL object, not null, as null will mean the cache tries
106: // to
107: // load it again on next access, but infact it should cache the fact
108: // that no dataset exists
109: if (dataset == null) {
110: return NULL_DATASET;
111: }
112:
113: // TODO: Wrap in decorator
114: // // Wrap in decorator
115: // DataSetDecorator decorator = new DataSetDecorator(dataset);
116: // decorator.setDataValueTransformer(dataValueTransformer);
117:
118: return dataset;
119:
120: }
121: }
122:
123: /**
124: * Constant: Name of the cache.
125: */
126: public static final String CACHE_NAME = CachingDataSetLoader.class
127: .getName();
128:
129: /**
130: * Logger for this class
131: */
132: static final Log LOG = LogFactory
133: .getLog(CachingDataSetLoader.class);
134:
135: /**
136: * Constant. Used as cache entry when there is no dataset.
137: */
138: protected final static DataSetBean NULL_DATASET = new DataSetBean();
139:
140: /**
141: * Dependency: Cache for loaded DataSets.
142: */
143: protected final SelfPopulatingCache cache;
144:
145: /**
146: * Dependency: The data set loader that loads the actual data sets.
147: */
148: protected final DataSetLoader dataSetLoader;
149:
150: /**
151: * Dependency Injection constructor.
152: *
153: * @param dataSetLoader
154: * The actual loader.
155: */
156: public CachingDataSetLoader(DataSetLoader dataSetLoader) {
157: super ();
158:
159: Validate.notNull(dataSetLoader,
160: "Argument loader must not be null");
161:
162: // Data set loader
163: this .dataSetLoader = dataSetLoader;
164:
165: // This will look up a singleton cache by name,
166: // on only the SelfPopulatingCache object is ours.
167: try {
168: cache = new SelfPopulatingCache(CACHE_NAME,
169: new DataSetFactory());
170: } catch (CacheException e) {
171: throw new DDStepsException(
172: "Could not create cache for DataSet:s.", e);
173: }
174:
175: }
176:
177: /**
178: * Loads a dataset or gets it from the cache.
179: *
180: * @see org.ddsteps.dataset.DataSetLoader#loadDataSet(java.lang.Class)
181: */
182: public DataSet loadDataSet(Class clazz) {
183:
184: Validate.notNull(clazz, "Argument clazz must not be null.");
185:
186: try {
187: Serializable dataSet = cache.get(new CacheKey(clazz));
188:
189: if (dataSet == NULL_DATASET) {
190: return null;
191: }
192: return (DataSet) dataSet;
193:
194: } catch (CacheException e) {
195: throw new DDStepsException("Could not get Excel Data Set.",
196: e);
197: }
198:
199: }
200:
201: }
|