package com.jdroid.java.repository;
import com.jdroid.java.collections.Lists;
import com.jdroid.java.collections.Maps;
import com.jdroid.java.domain.Identifiable;
import com.jdroid.java.utils.LoggerUtils;
import org.slf4j.Logger;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class CacheWrapperRepository<T extends Identifiable> implements Repository<T> {
private static final Logger LOGGER = LoggerUtils.getLogger(CacheWrapperRepository.class);
private Repository<T> wrappedRepository;
private Map<String, T> cache;
private Boolean synced;
public CacheWrapperRepository(Repository<T> wrappedRepository) {
this.wrappedRepository = wrappedRepository;
cache = createCacheMap();
synced = false;
}
protected Map<String, T> createCacheMap() {
return Maps.newConcurrentHashMap();
}
protected Map<String, T> getCache() {
return cache;
}
public List<T> getCachedItems() {
return Lists.newArrayList(cache.values());
}
protected Repository<T> getWrappedRepository() {
return wrappedRepository;
}
protected Boolean isSynced() {
return synced;
}
@Override
public T get(String id) {
T item = cache.get(id);
if (item == null) {
item = wrappedRepository.get(id);
if (item != null) {
cache.put(id, item);
}
} else {
LOGGER.info("Retrieved object: " + item.getClass().getSimpleName() + ". [ " + item + " ]");
}
return item;
}
@Override
public void add(T item) {
wrappedRepository.add(item);
cache.put(item.getId(), item);
}
@Override
public void addAll(Collection<T> items) {
wrappedRepository.addAll(items);
for (T each : items) {
cache.put(each.getId(), each);
}
}
@Override
public void update(T item) {
wrappedRepository.update(item);
cache.put(item.getId(), item);
}
@Override
public void remove(T item) {
wrappedRepository.remove(item);
cache.remove(item.getId());
}
@Override
public void removeAll() {
wrappedRepository.removeAll();
cache.clear();
}
@Override
public void removeAll(Collection<T> items) {
wrappedRepository.removeAll(items);
for (T each : items) {
cache.remove(each.getId());
}
}
@Override
public List<T> findByField(String fieldName, Object... values) {
return wrappedRepository.findByField(fieldName, values);
}
@Override
public List<T> getAll() {
if (synced) {
List<T> items = Lists.newArrayList(cache.values());
LOGGER.info("Retrieved all objects [" + items.size() + "]");
return items;
} else {
List<T> items = wrappedRepository.getAll();
for (T each : items) {
cache.put(each.getId(), each);
}
synced = true;
return items;
}
}
@Override
public List<T> getAll(List<String> ids) {
if (synced) {
List<T> items = Lists.newArrayList();
for (String each : ids) {
items.add(cache.get(each));
}
LOGGER.info("Retrieved all objects [" + items.size() + "] with ids: " + ids);
return items;
} else {
List<T> items = wrappedRepository.getAll(ids);
for (T each : items) {
cache.put(each.getId(), each);
}
return items;
}
}
@Override
public void remove(String id) {
wrappedRepository.remove(id);
cache.remove(id);
}
@Override
public Boolean isEmpty() {
if (synced) {
return cache.isEmpty();
} else {
Boolean isEmpty = wrappedRepository.isEmpty();
synced = isEmpty;
return isEmpty;
}
}
@Override
public Long getSize() {
if (synced) {
return (long)cache.size();
} else {
Long size = wrappedRepository.getSize();
synced = size == 0;
return size;
}
}
@Override
public void replaceAll(Collection<T> items) {
wrappedRepository.replaceAll(items);
for (T each : items) {
cache.put(each.getId(), each);
}
}
@Override
public T getUniqueInstance() {
if (!cache.isEmpty()) {
return cache.values().iterator().next();
} else {
T item = wrappedRepository.getUniqueInstance();
cache.put(item.getId(), item);
return item;
}
}
public void clearCache() {
cache.clear();
}
}