org.apache.ibatis.mapping.CacheBuilder Maven / Gradle / Ivy
package org.apache.ibatis.mapping;
import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheException;
import org.apache.ibatis.cache.decorators.*;
import org.apache.ibatis.cache.impl.PerpetualCache;
import org.apache.ibatis.reflection.MetaObject;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class CacheBuilder {
private String id;
private Class extends Cache> implementation;
private List> decorators;
private Integer size;
private Long clearInterval;
private boolean readWrite;
private Properties properties;
public CacheBuilder(String id) {
this.id = id;
this.decorators = new ArrayList>();
}
public CacheBuilder implementation(Class extends Cache> implementation) {
this.implementation = implementation;
return this;
}
public CacheBuilder addDecorator(Class extends Cache> decorator) {
if (decorator != null) {
this.decorators.add(decorator);
}
return this;
}
public CacheBuilder size(Integer size) {
this.size = size;
return this;
}
public CacheBuilder clearInterval(Long clearInterval) {
this.clearInterval = clearInterval;
return this;
}
public CacheBuilder readWrite(boolean readWrite) {
this.readWrite = readWrite;
return this;
}
public CacheBuilder properties(Properties properties) {
this.properties = properties;
return this;
}
public Cache build() {
setDefaultImplementations();
Cache cache = newBaseCacheInstance(implementation, id);
setCacheProperties(cache);
for (Class extends Cache> decorator : decorators) {
cache = newCacheDecoratorInstance(decorator, cache);
setCacheProperties(cache);
}
cache = setStandardDecorators(cache);
return cache;
}
private void setDefaultImplementations() {
if (implementation == null) {
implementation = PerpetualCache.class;
if (decorators.size() == 0) {
decorators.add(FifoCache.class);
}
}
}
private Cache setStandardDecorators(Cache cache) {
try {
if (cache.getClass().getName().startsWith("org.apache.ibatis")) {
MetaObject metaCache = MetaObject.forObject(cache);
if (size != null && metaCache.hasSetter("size")) {
metaCache.setValue("size", size);
}
if (clearInterval != null) {
cache = new ScheduledCache(cache);
((ScheduledCache) cache).setClearInterval(clearInterval);
}
if (readWrite) {
cache = new SerializedCache(cache);
}
cache = new LoggingCache(cache);
cache = new SynchronizedCache(cache);
}
return cache;
} catch (Exception e) {
throw new CacheException("Error building standard cache decorators. Cause: " + e, e);
}
}
private void setCacheProperties(Cache cache) {
if (properties != null) {
MetaObject metaCache = MetaObject.forObject(cache);
for (Map.Entry entry : properties.entrySet()) {
String name = (String) entry.getKey();
String value = (String) entry.getValue();
if (metaCache.hasSetter(name)) {
Class type = metaCache.getSetterType(name);
if (String.class == type) {
metaCache.setValue(name, value);
} else if (int.class == type
|| Integer.class == type) {
metaCache.setValue(name, Integer.valueOf(value));
} else if (long.class == type
|| Long.class == type) {
metaCache.setValue(name, Long.valueOf(value));
} else if (short.class == type
|| Short.class == type) {
metaCache.setValue(name, Short.valueOf(value));
} else if (byte.class == type
|| Byte.class == type) {
metaCache.setValue(name, Byte.valueOf(value));
} else if (float.class == type
|| Float.class == type) {
metaCache.setValue(name, Float.valueOf(value));
} else if (double.class == type
|| Double.class == type) {
metaCache.setValue(name, Double.valueOf(value));
} else {
throw new CacheException("Unsupported property type for cache: '" + name + "' of type " + type);
}
}
}
}
}
private Cache newBaseCacheInstance(Class extends Cache> cacheClass, String id) {
Constructor extends Cache> cacheConstructor = getBaseCacheConstructor(cacheClass);
try {
return cacheConstructor.newInstance(id);
} catch (Exception e) {
throw new CacheException("Could not instantiate cache implementation (" + cacheClass + "). Cause: " + e, e);
}
}
private Constructor extends Cache> getBaseCacheConstructor(Class extends Cache> cacheClass) {
try {
return cacheClass.getConstructor(String.class);
} catch (Exception e) {
throw new CacheException("Invalid base cache implementation (" + cacheClass + "). " +
"Base cache implementations must have a constructor that takes a String id as a parameter. Cause: " + e, e);
}
}
private Cache newCacheDecoratorInstance(Class extends Cache> cacheClass, Cache base) {
Constructor extends Cache> cacheConstructor = getCacheDecoratorConstructor(cacheClass);
try {
return cacheConstructor.newInstance(base);
} catch (Exception e) {
throw new CacheException("Could not instantiate cache decorator (" + cacheClass + "). Cause: " + e, e);
}
}
private Constructor extends Cache> getCacheDecoratorConstructor(Class extends Cache> cacheClass) {
try {
return cacheClass.getConstructor(Cache.class);
} catch (Exception e) {
throw new CacheException("Invalid cache decorator (" + cacheClass + "). " +
"Cache decorators must have a constructor that takes a Cache instance as a parameter. Cause: " + e, e);
}
}
}