package com.aggrepoint.winlet.plugin; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.function.Function; import com.aggrepoint.utils.CollectionUtils; import com.aggrepoint.winlet.CodeValue; import com.aggrepoint.winlet.HashMapWrapper; import com.aggrepoint.winlet.ListWrapper; /** * 使用主、子表结构的数据库表提供多个列表 * * @author Jim * * @param <S> * 加载主表数据的服务类 * @param <H> * 主表数据类型 * @param <T> * 子表数据类型 */ public class CachedListGroup<S, H, T> { S svc; Function<S, List<H>> loadFunc; Function<H, String> listNameFunc; Function<H, List<T>> listFunc; Function<T, Object> keyFunc; Function<T, Object> valueFunc; List<H> cached; /** 本CachedListGroup加载的列表的名称 */ HashSet<String> listNames = new HashSet<String>(); HashMap<String, ListUnit<?>> lists; class ListGroupUnit implements ListUnit<T> { HashMapWrapper<String, T> map; HashMapWrapper<String, String> cvMap; ListWrapper<T> list; ListWrapper<CodeValue> cvList; void set(HashMapWrapper<String, T> map, HashMapWrapper<String, String> cvMap, ListWrapper<T> list, ListWrapper<CodeValue> cvList) { this.map = map; this.cvMap = cvMap; this.list = list; this.cvList = cvList; } void reset() { map.clear(); cvMap.clear(); list.clear(); cvList.clear(); } @Override public List<T> getList() { update(); return list; } @Override public List<CodeValue> getCodeValueList() { update(); return cvList; } @Override public Map<String, T> getMap() { update(); return map; } @Override public Map<String, String> getCodeValueMap() { update(); return cvMap; } } /** * * @param lists * @param svc * @param loadFunc * 加载主表数据并连带加载子表数据集合 * @param listNameFunc * 从主表数据对象中获取列表名称的方法 * @param listFunc * 从主表数据对象中获取子表对象列表的方法 * @param keyFunc * 子表数据对象的键的获取方法 * @param valueFunc * 字标数据对象的值得获取方法 */ public CachedListGroup(HashMap<String, ListUnit<?>> lists, S svc, Function<S, List<H>> loadFunc, Function<H, String> listNameFunc, Function<H, List<T>> listFunc, Function<T, Object> keyFunc, Function<T, Object> valueFunc) { this.lists = lists; this.svc = svc; this.loadFunc = loadFunc; this.listNameFunc = listNameFunc; this.listFunc = listFunc; this.keyFunc = keyFunc; this.valueFunc = valueFunc; update(); } @SuppressWarnings("unchecked") private synchronized void update() { List<H> list = loadFunc.apply(svc); if (cached != list) { // 保存当前的列表集合中由本CachedListGroup加载的列表的名称,用于删除已经不在数据库中存在的列表 HashSet<String> currNames = new HashSet<String>(); if (listNames != null) { currNames.addAll(listNames); for (String name : listNames) { ListUnit<?> existing = lists.get(name); if (existing != null && existing instanceof CachedListGroup.ListGroupUnit) { ((ListGroupUnit) existing).reset(); } } } listNames = new HashSet<String>(); if (list != null) for (H h : list) { String name = listNameFunc.apply(h); listNames.add(name); List<T> l = listFunc.apply(h); HashMapWrapper<String, T> map = new HashMapWrapper<String, T>( CollectionUtils.toHashMap(l, p -> { Object obj = keyFunc.apply(p); return obj == null ? "" : obj.toString(); }, p -> p)); HashMapWrapper<String, String> cvMap = new HashMapWrapper<String, String>( CodeValue.map(l, keyFunc, valueFunc)); ListWrapper<T> lt = new ListWrapper<T>(l); ListWrapper<CodeValue> cvList = new ListWrapper<CodeValue>( CodeValue.list(l, keyFunc, valueFunc)); ListGroupUnit unit = null; ListUnit<?> existing = lists.get(name); if (existing != null && existing instanceof CachedListGroup.ListGroupUnit) unit = (ListGroupUnit) existing; else unit = new ListGroupUnit(); unit.set(map, cvMap, lt, cvList); lists.put(name, unit); } currNames.removeAll(listNames); for (String name : currNames) lists.remove(name); cached = list; } } }