All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.j256.ormlite.dao.ReferenceObjectCache Maven / Gradle / Ivy

Go to download

Lightweight Object Relational Model (ORM) for persisting objects to SQL databases.

There is a newer version: 6.1
Show newest version
package com.j256.ormlite.dao;

import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Cache for ORMLite which stores objects with a {@link WeakReference} or {@link SoftReference} to them. Java Garbage
 * Collection can then free these objects if no one has a "strong" reference to the object (weak) or if it runs out of
 * memory (soft).
 * 
 * @author graywatson
 */
public class ReferenceObjectCache implements ObjectCache {

	private final ConcurrentHashMap, Map>> classMaps =
			new ConcurrentHashMap, Map>>();
	private final boolean useWeak;

	/**
	 * @param useWeak
	 *            Set to true if you want the cache to use {@link WeakReference}. If false then the cache will use
	 *            {@link SoftReference}.
	 */
	public ReferenceObjectCache(boolean useWeak) {
		this.useWeak = useWeak;
	}

	/**
	 * Create and return an object cache using {@link WeakReference}.
	 */
	public static ReferenceObjectCache makeWeakCache() {
		return new ReferenceObjectCache(true);
	}

	/**
	 * Create and return an object cache using {@link SoftReference}.
	 */
	public static ReferenceObjectCache makeSoftCache() {
		return new ReferenceObjectCache(false);
	}

	@Override
	public synchronized  void registerClass(Class clazz) {
		Map> objectMap = classMaps.get(clazz);
		if (objectMap == null) {
			objectMap = new ConcurrentHashMap>();
			classMaps.put(clazz, objectMap);
		}
	}

	@Override
	public  T get(Class clazz, ID id) {
		Map> objectMap = getMapForClass(clazz);
		if (objectMap == null) {
			return null;
		}
		Reference ref = objectMap.get(id);
		if (ref == null) {
			return null;
		}
		Object obj = ref.get();
		if (obj == null) {
			objectMap.remove(id);
			return null;
		} else {
			@SuppressWarnings("unchecked")
			T castObj = (T) obj;
			return castObj;
		}
	}

	@Override
	public  void put(Class clazz, ID id, T data) {
		Map> objectMap = getMapForClass(clazz);
		if (objectMap != null) {
			if (useWeak) {
				objectMap.put(id, new WeakReference(data));
			} else {
				objectMap.put(id, new SoftReference(data));
			}
		}
	}

	@Override
	public  void clear(Class clazz) {
		Map> objectMap = getMapForClass(clazz);
		if (objectMap != null) {
			objectMap.clear();
		}
	}

	@Override
	public void clearAll() {
		for (Map> objectMap : classMaps.values()) {
			objectMap.clear();
		}
	}

	@Override
	public  void remove(Class clazz, ID id) {
		Map> objectMap = getMapForClass(clazz);
		if (objectMap != null) {
			objectMap.remove(id);
		}
	}

	@Override
	public  T updateId(Class clazz, ID oldId, ID newId) {
		Map> objectMap = getMapForClass(clazz);
		if (objectMap == null) {
			return null;
		}
		Reference ref = objectMap.remove(oldId);
		if (ref == null) {
			return null;
		}
		objectMap.put(newId, ref);
		@SuppressWarnings("unchecked")
		T castObj = (T) ref.get();
		return castObj;
	}

	@Override
	public  int size(Class clazz) {
		Map> objectMap = getMapForClass(clazz);
		if (objectMap == null) {
			return 0;
		} else {
			return objectMap.size();
		}
	}

	@Override
	public int sizeAll() {
		int size = 0;
		for (Map> objectMap : classMaps.values()) {
			size += objectMap.size();
		}
		return size;
	}

	/**
	 * Run through the map and remove any references that have been null'd out by the GC.
	 */
	public  void cleanNullReferences(Class clazz) {
		Map> objectMap = getMapForClass(clazz);
		if (objectMap != null) {
			cleanMap(objectMap);
		}
	}

	/**
	 * Run through all maps and remove any references that have been null'd out by the GC.
	 */
	public  void cleanNullReferencesAll() {
		for (Map> objectMap : classMaps.values()) {
			cleanMap(objectMap);
		}
	}

	private void cleanMap(Map> objectMap) {
		Iterator>> iterator = objectMap.entrySet().iterator();
		while (iterator.hasNext()) {
			if (iterator.next().getValue().get() == null) {
				iterator.remove();
			}
		}
	}

	private Map> getMapForClass(Class clazz) {
		Map> objectMap = classMaps.get(clazz);
		if (objectMap == null) {
			return null;
		} else {
			return objectMap;
		}
	}
}