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; } }