package com.walker.cache.tree;
import com.walker.cache.AbstractCacheProvider;
import com.walker.cache.Cachable;
import com.walker.cache.Cache;
import com.walker.infrastructure.utils.StringUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public abstract class AbstractCacheTreeProvider extends AbstractCacheProvider
implements CacheTree {
public static final String SUPER_ROOT_KEY = "cacheTree_super_root_key";
@Override
public List getRootKeys() {
// CacheTreeNode node = (CacheTreeNode)this.getCacheData(SUPER_ROOT_KEY);
CacheTreeNode node = this.get(SUPER_ROOT_KEY);
if(node != null){
Collection rootList = node.getChildren();
if(rootList == null || rootList.size() == 0){
return null;
}
List result = new ArrayList(rootList.size());
if(rootList != null){
for(Iterator i = rootList.iterator(); i.hasNext();)
result.add(i.next().getKey());
return result;
}
}
return null;
}
@Override
public Collection getRootList() {
// CacheTreeNode node = (CacheTreeNode)this.getCacheData(SUPER_ROOT_KEY);
CacheTreeNode node = this.get(SUPER_ROOT_KEY);
if(node != null){
return node.getChildren();
}
return null;
}
@Override
public CacheTreeNode getOneRootNode(String key) {
return searchTreeNode(key);
}
@Override
public CacheTreeNode searchTreeNode(String key) {
assert (StringUtils.isNotEmpty(key));
// CacheTreeNode node = (CacheTreeNode)this.getCacheData(SUPER_ROOT_KEY);
CacheTreeNode node = this.get(SUPER_ROOT_KEY);
if(node != null){
return node.search(key);
}
return null;
}
public List searchTreeNodeList(String keyLike){
CacheTreeNode node = this.get(SUPER_ROOT_KEY);
if(node != null){
// String[] keys = StringUtils.stringToArray(keyLike, " ");
// if(keys != null && keys.length > 1){
// if(logger.isDebugEnabled()){
// logger.debug("搜索树,查询条件有多个:" + keys.length);
// for(String s : keys){
// logger.debug(s);
// }
// }
// return node.searchLike(keys);
// } else {
// return node.searchLike(keyLike);
// }
return node.searchLike(keyLike);
}
return null;
}
public List searchTreeNodeList(String[] keys){
CacheTreeNode node = this.get(SUPER_ROOT_KEY);
if(node != null){
return node.searchLike(keys);
}
return null;
}
@Override
protected int loadDataToCache(Cache cache) {
try{
Map rootMap = loadRootList();
if(rootMap == null || rootMap.size() == 0){
logger.info("no root cache loaded in '" + this.getProviderName() + "'.");
cache.put(SUPER_ROOT_KEY, createSuperRoot());
return 0;
}
/* 加载其他子节点集合,这些不是树结构,都是平级的子对象,需要组装成树 */
Map childMap = loadChildList();
addListToCache(rootMap.values().iterator(), cache);
if(childMap != null && childMap.size() > 0){
mountTree(childMap, cache);
}
/* 把之前多个根节点删除,合并为一个超根节点 */
CacheTreeNode superRoot = createSuperRoot();
for(Iterator i = cache.getIterator(); i.hasNext();){
superRoot.addChild((CacheTreeNode)(i.next().getValue()));
}
cache.clear();
cache.put(SUPER_ROOT_KEY, superRoot);
int total = rootMap.size();
/* 把所有加载过的业务数据以列表平铺的形式放入缓存,可以分别使用 */
addListToCache(rootMap.values().iterator(), cache);
if(childMap != null){
addListToCache(childMap.values().iterator(), cache);
total += childMap.size();
}
return total;
} catch(Exception ex){
throw new Error("failed to loading user cache:" + this.getProviderName(), ex);
}
}
private CacheTreeNode createSuperRoot(){
return new DefaultCacheTreeNode(SUPER_ROOT_KEY, "superRoot", null, null);
}
private void mountTree(Map childMap, Cache cache){
CacheTreeNode _node = null;
for(Iterator i = childMap.values().iterator(); i.hasNext();){
_node = i.next();
mountMiddleNode(_node, childMap, cache);
}
}
private void mountMiddleNode(CacheTreeNode currentNode
, Map childMap, Cache cache){
// logger.debug("-------------> cache = " + cache);
// logger.debug("-------------> currentNode = " + currentNode);
CacheTreeNode _parentNode = (CacheTreeNode)cache.get(currentNode.getParentId());
if(_parentNode == null){
// 没有找到上级根节点,说明是比较靠下的子节点
_parentNode = childMap.get(currentNode.getParentId());
if(_parentNode == null)
throw new NullPointerException("parent node not found, current: " + currentNode);
_parentNode.addChild(currentNode);
mountMiddleNode(_parentNode, childMap, cache);
} else if(parentIsRoot(_parentNode.getParentId())) {
// 父对象是根节点
_parentNode.addChild(currentNode);
// logger.debug("找到了挂在root下的子节点:" + _parentNode);
}
}
private void addListToCache(Iterator iterator, Cache cache){
for(Iterator i = iterator; i.hasNext();)
addObjectToCache(i.next(), cache);
}
private void addObjectToCache(CacheTreeNode node, Cache cache){
assert (node != null && node.getSource() != null);
cache.put(node.getKey(), node);
}
/**
* 从业务中加载根节点,即:第一级节点所有数据。
* 注意:在树结构中,没有默认的根节点,第一级节点会存在多个,
* 也可以认为存在多个根节点。
* @return
*/
protected abstract Map loadRootList();
/**
* 从业务中加载处了第一级节点之外的所有其他节点数据。
* 加载的方式由子类实施各种策略,如:大批量的分段加载等。
* 这些集合中的对象不是树结构,只要返回包装为CacheTreeNode
类型对象即可。
* 由系统负责对树的组装。
* @return
*/
protected abstract Map loadChildList();
/**
* 把实体对象转换成CacheTreeNode
,由最终业务实现。
* @param entity
* @return
*/
protected abstract CacheTreeNode toCacheTreeNode(T entity);
@Override
public void putCacheData(String key, T data){
CacheTreeNode node = toCacheTreeNode(data);
if(node == null)
throw new AbstractMethodError();
CacheTreeNode vRoot = this.get(SUPER_ROOT_KEY);
if(vRoot != null){
if(StringUtils.isEmpty(node.getParentId()) || parentIsRoot(node.getParentId()))
vRoot.addChild(node); // 如果没有上级信息,就加入到虚拟根下边。
else {
CacheTreeNode _parent = vRoot.search(node.getParentId());
if(_parent != null){
_parent.addChild(node);
} else
throw new NullPointerException("not found parent in node: " + node);
}
} else {
// 不存在虚拟根节点,说明是第一个元素
throw new NullPointerException("not found virtual Root in '" + getProviderName() + "'.");
}
getCache().put(key, node);
}
@Override
public void removeCacheData(String key) {
// TODO Auto-generated method stub
getCache().remove(key);
// CacheTreeNode vRoot = (CacheTreeNode)this.getCacheData(SUPER_ROOT_KEY);
CacheTreeNode vRoot = this.get(SUPER_ROOT_KEY);
if(vRoot != null){
if(StringUtils.isNotEmpty(key)){
CacheTreeNode removed = vRoot.remove(key);
logger.debug("removed CacheTreeNode: " + removed);
}
}
}
@Override
public void updateCacheData(String key, T data) {
// TODO Auto-generated method stub
assert (StringUtils.isNotEmpty(key));
assert (data != null);
CacheTreeNode node = toCacheTreeNode(data);
if(node == null)
throw new AbstractMethodError();
getCache().replace(key, node);
// CacheTreeNode vRoot = (CacheTreeNode)this.getCacheData(SUPER_ROOT_KEY);
CacheTreeNode vRoot = this.get(SUPER_ROOT_KEY);
if(vRoot != null){
CacheTreeNode oldNode = vRoot.search(key);
if(oldNode != null){
oldNode.cloneProperties(node);
}
}
}
@SuppressWarnings("unchecked")
@Override
public T getCacheData(String key) {
assert (StringUtils.isNotEmpty(key));
CacheTreeNode node = get(key);
if(node != null && node.getSource() != null){
return (T)node.getSource();
}
// throw new RuntimeException("not found source in CacheTreeNode, not Class T in getCacheData().");
return null;
}
@Override
public CacheTreeNode get(String key){
return (CacheTreeNode)getCache().get(key);
// if(node == null)
// throw new NullPointerException("not found cache data: " + key);
// return node;
}
/**
* 根据上级ID判断上级节点是否根节点,通常根节点为0或root表示。
* @param parentId
* @return
*/
private boolean parentIsRoot(String parentId){
if(parentId.equalsIgnoreCase(ROOT_FLAG_NAME) || parentId.equals(ROOT_FLAG_ZERO))
return true;
return false;
}
}