001: package com.completex.objective.components.ocache.impl;
002:
003: import com.completex.objective.components.ocache.*;
004:
005: import java.util.Iterator;
006: import java.util.LinkedHashMap;
007: import java.util.Map;
008:
009: /**
010: * Multi-Index cache factory implementation.
011: * Creates multi-index cache (OdalMultiIndexCache) out of regular ones and registers it.
012: *
013: * @author Gennady Krizhevsky
014: */
015: public class MultiIndexCacheFactoryImpl implements
016: OdalMultiIndexCacheFactory {
017:
018: private DefaultCacheFactoryImpl defaultCacheFactory = new DefaultCacheFactoryImpl();
019: private ValueTransformer valueTransformer = ValueTransformer.NULL_VALUE_TRANSFORMER;
020: private boolean transactionSensitive;
021:
022: private LinkedHashMap caches = new LinkedHashMap();
023: private boolean initialized;
024: private OdalMultiIndexCache masterKeyedCache;
025:
026: public MultiIndexCacheFactoryImpl() {
027: }
028:
029: public MultiIndexCacheFactoryImpl(
030: ValueTransformer valueTransformer,
031: boolean transactionSensitive) {
032: setValueTransformer(valueTransformer);
033: setTransactionSensitive(transactionSensitive);
034: }
035:
036: public void registerCache(OdalCache cache) {
037: registerCache(cache, null);
038: }
039:
040: /**
041: * Creates multi-index cache (OdalMultiIndexCache) out of regular ones and registers it.
042: * The first cache element is the master one.
043: *
044: */
045: public synchronized void registerCache(OdalCache cache,
046: OdalKeyFactory keyFactory) {
047: registerCache(cache, keyFactory, null);
048: }
049:
050: /**
051: * Creates multi-index cache (OdalMultiIndexCache) out of regular ones and registers it.
052: * The first cache element is the master one.
053: * Its name will be returned by getName() method.
054: *
055: * @param cache cache to register
056: * @param keyFactory key factory. It may not be null for MultiIndexCacheFactoryImpl
057: * @param cacheConfig cache configuration
058: */
059: public void registerCache(OdalCache cache,
060: OdalKeyFactory keyFactory, OdalCacheConfig cacheConfig) {
061: invalidateInitialized();
062: if (keyFactory == null) {
063: throw new OdalRuntimeCacheException(
064: "OdalKeyFactory may not be null for MultiIndexCacheFactoryImpl");
065: }
066:
067: if (cache instanceof OdalMultiIndexCache) {
068: throw new OdalRuntimeCacheException(
069: "Cache is already instanceof OdalMultiIndexCache");
070: }
071: cacheConfig = OdalCacheConfig.merge(
072: DefaultCacheFactoryImpl.DEFAULT_CONFIG, cacheConfig);
073:
074: if (!cacheConfig.isDisabled()) {
075: if (!caches.containsKey(cache.getName())) {
076: OdalKeyedCache element = (OdalKeyedCache) toOdalKeyedCache(
077: cache, keyFactory, cacheConfig
078: .isMarkCacheCollectionElements(),
079: valueTransformer, transactionSensitive);
080: caches.put(element.getName(), element);
081: if (this .masterKeyedCache == null) {
082: this .masterKeyedCache = (OdalMultiIndexCache) element;
083: }
084: } else {
085: throw new OdalRuntimeCacheException(
086: "Cache with name ["
087: + cache.getName()
088: + "] already existes in this LinkedCacheFactory");
089: }
090: }
091: }
092:
093: protected OdalCache toOdalKeyedCache(OdalCache cache,
094: OdalKeyFactory keyFactory,
095: boolean markCacheCollectionElements,
096: ValueTransformer valueTransformer,
097: boolean transactionSensitive) {
098: if (!(cache instanceof SafeMultiIndexCacheImpl)) {
099: if (!(cache instanceof OdalMultiIndexCache)) {
100: cache = getDefaultCacheFactory().transformCache(cache,
101: keyFactory, markCacheCollectionElements,
102: valueTransformer, transactionSensitive);
103: cache = new MultiIndexCacheImpl(cache, keyFactory,
104: valueTransformer, markCacheCollectionElements);
105: }
106: cache = new SafeMultiIndexCacheImpl(
107: (OdalMultiIndexCache) cache);
108: }
109: return cache;
110: }
111:
112: /**
113: * Unregisters cache
114: *
115: * @param name cache name
116: * @throws com.completex.objective.components.ocache.OdalRuntimeCacheException if the cache is initialized (been used)
117: */
118: public synchronized void unregisterCache(String name) {
119: invalidateInitialized();
120: caches.remove(name);
121: }
122:
123: protected void invalidateInitialized() {
124: if (initialized) {
125: throw new OdalRuntimeCacheException(
126: "LinkedCacheFactory is initialized and therefore immutable");
127: }
128: }
129:
130: /**
131: * Returns instance of OdalMultiIndexCache
132: *
133: * @see OdalCacheFactory#getCache(String)
134: */
135: public synchronized OdalKeyedCache getCache(String name) {
136: if (!initialized) {
137: initialize();
138: }
139: OdalKeyedCache cache = (OdalKeyedCache) caches.get(name);
140: return cache == null ? OdalMultiIndexCache.NULL_MULTI_INDEX_CACHE
141: : cache;
142: }
143:
144: /**
145: * Links all the registered caches and makes this factory immutable
146: */
147: protected void initialize() {
148: //
149: // Link all the caches
150: //
151: for (Iterator it = caches.keySet().iterator(); it.hasNext();) {
152: String key = (String) it.next();
153: OdalMultiIndexCache elementA = (OdalMultiIndexCache) caches
154: .get(key);
155: for (Iterator it2 = caches.keySet().iterator(); it2
156: .hasNext();) {
157: String key2 = (String) it2.next();
158: OdalMultiIndexCache elementB = (OdalMultiIndexCache) caches
159: .get(key2);
160: if (elementA != elementB) {
161: elementA.addListener(elementB);
162: }
163: }
164: }
165:
166: //
167: // Mark the 1st one as the master and set masterKeyFactory to all others:
168: //
169: int index = 0;
170: for (Iterator it = caches.keySet().iterator(); it.hasNext(); index++) {
171: String key = (String) it.next();
172: OdalMultiIndexCache elementA = (OdalMultiIndexCache) caches
173: .get(key);
174: if (index > 0) {
175: elementA.setMasterCache(masterKeyedCache);
176: }
177: }
178:
179: initialized = true;
180: }
181:
182: /**
183: * @see ValueTransformer
184: * @return ValueTransformer
185: */
186: public ValueTransformer getValueTransformer() {
187: return valueTransformer;
188: }
189:
190: /**
191: * @see ValueTransformer
192: */
193: public void setValueTransformer(ValueTransformer valueTransformer) {
194: if (valueTransformer != null) {
195: this .valueTransformer = valueTransformer;
196: }
197: }
198:
199: /**
200: * Returns true if returned cache has to implement TransactionListener
201: *
202: * @return true if returned cache has to implement TransactionListener
203: */
204: public boolean isTransactionSensitive() {
205: return transactionSensitive;
206: }
207:
208: /**
209: * Sets true if returned cache has to implement TransactionListener
210: *
211: * @param transactionSensitive true if returned cache has to implement TransactionListener
212: */
213: public void setTransactionSensitive(boolean transactionSensitive) {
214: this .transactionSensitive = transactionSensitive;
215: }
216:
217: protected DefaultCacheFactoryImpl getDefaultCacheFactory() {
218: return defaultCacheFactory;
219: }
220:
221: public Map getRegisteredMultiIndexCaches() {
222: return caches;
223: }
224:
225: }
|