package net.tccn.base; import lombok.Getter; import net.tccn.base.arango.Doc; import net.tccn.dbq.Field; import net.tccn.dbq.fbean.FilterType; import net.tccn.dbq.jdbc.api.DbAccount; import net.tccn.dbq.jdbc.api.DbKit; import net.tccn.meta.*; import net.tccn.plat.DbPlat; import net.tccn.plat.SysPlat; import net.tccn.user.User; import org.redkale.convert.json.JsonConvert; import org.redkale.util.Comment; import org.redkale.util.TypeToken; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.lang.reflect.Type; import java.util.*; import java.util.function.BiFunction; import java.util.function.Predicate; import java.util.stream.Collectors; import static java.util.Arrays.asList; /** * * Created by liangxianyou at 2019/1/7 13:31. */ public final class MetaKit { //基础数据缓存 @Getter private static List metaTables; @Getter private static List metaLinks; @Getter private static List metaServices; @Getter private static List dbPlats; @Getter private static List sysPlats; @Getter private static List users; protected static String dcate; private static final JsonConvert convert = JsonConvert.root(); // ----------------------------------- protected static void init() { reload(MetaTable.class); reload(MetaLink.class); reload(MetaService.class); reload(DbAccount.class); reload(SysPlat.class); reload(User.class); } public static void reload(Class clazz) { reload(clazz, null); } public static void reload(T t) { reload(t.getClass(), t.getKey()); } public static void reload(Class clazz, String key) { try { File file = new File(String.format("tmp/%s.json", clazz.getSimpleName())); if ("file".equals(dcate)) { if (MetaTable.class == clazz) { Type type = new TypeToken>() {}.getType(); metaTables = convert.convertFrom(type, new FileInputStream(file)); } else if (MetaLink.class == clazz) { Type type = new TypeToken>() {}.getType(); metaLinks = convert.convertFrom(type, new FileInputStream(file)); } else if (MetaService.class == clazz) { Type type = new TypeToken>() {}.getType(); metaServices = convert.convertFrom(type, new FileInputStream(file)); } else if (DbAccount.class == clazz) { Type type = new TypeToken>() {}.getType(); dbPlats = convert.convertFrom(type, new FileInputStream(file)); } else if (DbPlat.class == clazz) { Type type = new TypeToken>() {}.getType(); dbPlats = convert.convertFrom(type, new FileInputStream(file)); } else if (SysPlat.class == clazz) { Type type = new TypeToken>() {}.getType(); sysPlats = convert.convertFrom(type, new FileInputStream(file)); } else if (User.class == clazz) { Type type = new TypeToken>() {}.getType(); users = convert.convertFrom(type, new FileInputStream(file)); } } else { if (MetaTable.class == clazz) metaTables = MetaTable.dao.find(); else if (MetaLink.class == clazz) metaLinks = MetaLink.dao.find(); else if (MetaService.class == clazz) metaServices = MetaService.dao.find(); else if (DbAccount.class == clazz) dbPlats = DbAccount.dao.find(); else if (DbPlat.class == clazz) dbPlats = DbAccount.dao.find(); else if (SysPlat.class == clazz) sysPlats = SysPlat.dao.find(); else if (User.class == clazz) users = User.dao.find(); } } catch (Exception e) { e.printStackTrace(); } } public static void cacheSave() { cacheSave(MetaLink.class); cacheSave(MetaService.class); cacheSave(DbAccount.class); cacheSave(DbPlat.class); cacheSave(SysPlat.class); cacheSave(User.class); } private static void cacheSave(Class clazz) { List list = null; if (MetaTable.class == clazz) list = metaTables; else if (MetaLink.class == clazz) list = metaLinks; else if (MetaService.class == clazz) list = metaServices; else if (DbAccount.class == clazz) list = dbPlats; else if (DbPlat.class == clazz) list = dbPlats; else if (SysPlat.class == clazz) list = sysPlats; else if (User.class == clazz) list = users; if (list == null || list.size() == 0) return; File file = new File(String.format("tmp/%s.json", list.get(0).getClass().getSimpleName())); file.getParentFile().mkdirs(); try { FileKit.strToFile(MetaKit.convert.convertTo(list), file); } catch (IOException e) { e.printStackTrace(); } } // ----------------------------------- public void cleanData() { } /** * 通过 别名 查询 MetaTable * @param alias * @return */ public static MetaTable getMetaTableByAlias(String alias) { Optional table = metaTables.stream().filter(x -> x.getAlias().equals(alias)).findAny(); return table.orElse(null); } public static MetaTable getMetaTable(String name, String token) { Optional any = getMetaTables().stream().filter(x -> { return x.getName().equals(name) && x.getSysPlatId().equals(getPlatId(token)); }).findAny(); return any.get(); } public static MetaService getMetaService(String name, String token) { Optional service = metaServices.stream() .filter(x -> x.getName().equals(name) && x.getSysPlatId().equals(getPlatId(token))) .findAny(); return service.orElse(null); } //字段特征排序 public static BiFunction sortItem = (t, arr) -> { List items = t.getItems(); //x 是跨越值 a:for (int i = 0, x = 0; i < arr.length; i++) { int inx = i - x; if (!items.get(inx).equals(arr[i])) { Field tmp = items.get(inx); for (int j = inx + 1; j < items.size(); j++) { if (items.get(j).equals(arr[i])) { items.set(inx, items.get(j)); items.set(j, tmp); continue a; } } //运行到这里,说明在 list 中找不到排序标识对应的数据, 让排序角标差值+1 x ++; } } t.setItems(items); return t; }; public static Map cfg(String name, String token) { MetaService metaService = getMetaService(name, token); Kv metaTables = getMetaTables(metaService, false); List> shows = metaService.getShows(); List edits = metaService.getEdits(); List> details = metaService.getDetails(); List filters = metaService.getFilters(); String comment = metaService.getComment(); //List items = new ArrayList<>(); /*Kv> _items2 = Kv.of(); metaTables.forEach((k, v) -> { Kv _items = Kv.of(); v.getItems().forEach(x -> { Kv kv = Kv.of(); kv.set("col", x.getName()); kv.set("label", x.getLabel()); kv.set("InExt", x.getInExt()); kv.set("inType", x.getInType()); kv.set("expr", x.showField()); _items.set(x.getName(), kv); }); _items2.set(k, _items); });*/ //shows /*List _shows = new ArrayList(); shows.forEach(x -> { MetaTable metaTable = metaTables.get(x.split("[.]")[0]); // 表别名 metaTable.getItems().stream() .filter(y -> x.split("[.]")[1].equals(y.getName())) .findFirst().ifPresent(y -> _shows.add(Kv.of("col", x).set("order", true))); });*/ /*List _shows = shows.stream().map(x -> { Kv kv = Kv.of(); kv.putAll(x); if ("FUNC".equalsIgnoreCase(x.get("inType")) || "QTASK".equalsIgnoreCase(x.get("inType")) || "DICT".equalsIgnoreCase(x.get("inType"))) { kv.set("fmt", x.get("inType") + "|" + x.get("inExt")); } else if ("HIDDEN".equalsIgnoreCase(x.get("inType"))) { kv.set("fmt", "HIDDEN"); } else { kv.set("fmt", ""); } kv.remove("inType"); kv.remove("inExt"); return kv; }).collect(Collectors.toList());*/ //filters List _filters = new ArrayList<>(); filters.forEach(x -> { String col = String.valueOf(x.getName()); MetaTable metaTable = metaTables.get(col.split("[.]")[0]); // 表别名 Kv filter = Kv.of(); metaTable.getItems().stream() .filter(y -> col.split("[.]")[1].equals(y.getName())) .findFirst() .ifPresent(y -> { filter.set("name", x.getName()); filter.set("label", x.getLabel() != null ? x.getLabel() : y.getLabel()); List types = new ArrayList<>(); List list = (List) x.getFilterType(); list.forEach(t -> { FilterType type = FilterType.getFilterType(t); if (type != null) { types.add(Kv.of("name", t).set("remark", type.getRemark())); } }); filter.set("filterType", types); if (!types.isEmpty()) {//设置默认查询项 filter.set("type", types.get(0).get("name")); } filter.set("checked", x.isChecked()); }); _filters.add(filter); }); //edits //List _edits = new ArrayList();//edits; /*edits.forEach(x -> { Kv kv = Kv.of(); kv.set("col", x); String col = x.get("col") + ""; //readonly,hidden if ("id".equalsIgnoreCase(col)) { kv.set("upAttr", "hidden"); kv.set("addAttr", "none"); } if ("reportWay".equalsIgnoreCase(col)) { kv.set("upAttr", "readonly"); kv.set("addAttr", "none"); } if ("insertTime".equalsIgnoreCase(col)) { kv.set("upAttr", "readonly"); kv.set("addAttr", "none"); } if ("ip".equalsIgnoreCase(col)) { kv.set("ck", "ip"); } _edits.add(kv); });*/ //details /*List _details = new ArrayList();//details; details.forEach(x -> { Kv kv = Kv.of(); kv.set("col", x); _details.add(kv); });*/ //pk:业务主表的主键 StringBuffer _pks = new StringBuffer(); MetaTable mainTable = metaTables.get(metaService.getTable()); mainTable.getItems().stream().filter(x -> x.getPk() != null && x.getPk()).forEach(x -> { _pks.append(String.format("%s.%s,", metaService.getTable(), x.getName())); }); if (_pks.length() > 0) { _pks.deleteCharAt(_pks.length() -1); } if (_pks.length() == 0) { // 默认主键 List items = metaTables.get(metaService.getTable()).getItems(); //存在id字段,取id items.stream().filter(x -> x.getName().equalsIgnoreCase("id")).findAny().ifPresent(x -> { _pks.append(String.format("%s.%s", metaService.getTable(), x.getName())); }); } return Kv.of() .set("pk", _pks.toString()) .set("title", comment) //.set("items", _items2) .set("shows", shows) .set("filters", _filters) .set("edits", edits) .set("details", details); } @Comment("获取导出excel表头配置k-v") public static Kv cfgExport(String name, String token) { MetaService metaService = getMetaService(name, token); List> exports = metaService.getExports(); Kv kv = Kv.of(); // {col:label} exports.forEach(x -> { kv.put(x.get("col"), x.get("label")); }); return kv; } //itemUpdate public static BiFunction, MetaTable> itemUpdate = (t, fields) -> { List items = t.getItems(); for (int i = 0; i < fields.size(); i++) { for (int j = 0; j < items.size(); j++) { if (items.get(j).equals(fields.get(i).getName())) { items.set(j, fields.get(i)); } } } return t; }; //showUpdate /*public static BiFunction, MetaService> showUpdate = (name, shows) -> { MetaService metaService = getMetaService(name, ""); MetaService _metaService = MetaService.dao.findByKey(metaService.getKey()); _metaService.setShows(shows); _metaService.update(); metaService.setShows(shows);//更新缓存 return metaService; };*/ public static MetaTable getMetaTableByKey(String key) { return metaTables.stream().filter(x -> x.getKey().equals(key)).findAny().orElse(null); } public static List getMetaLinks(String t, List shows, List filters) { Predicate contain = s -> { for (String item : shows) { if (s.equals(item.split("[.]")[0])) { return true; } } for (String item : filters) { if (s.equals(item.split("[.]")[0])) { return true; } } return false; }; //得到直接关联 //1、直接关联 表: t.equals(x.getTables()[0]) || t.equals(x.getTables()[1] //2、关联且有过滤: //3、关联有展示: List links = metaLinks.stream() .filter(x -> { return (t.equals(x.getTables()[0]) || t.equals(x.getTables()[1])) && (contain.test(x.getTables()[0]) || contain.test(x.getTables()[1])); }) .collect(Collectors.toList()); return links; } public static Kv buildeDetail(MetaService metaService) { //tables Kv tables = getMetaTables(metaService, true); return Kv.of("tables", tables) .set("links", Kv.of()); } public static Kv getMetaTables(MetaService metaService, Boolean all) { Kv tables = Kv.of(); String table = metaService.getTable();// tables.set(table, getMetaTableByAlias(table)); //收集所有的col Set allAlias; if (!all) { allAlias = Liangs.concat( metaService.getFilters().stream().map(f -> { String col = (String) f.getName(); String alias = col.split("[.]")[0]; return alias; }), metaService.getExports().stream().map(x -> x.get("col").split("[.]")[0]), metaService.getShows().stream().map(x -> x.get("col").split("[.]")[0])/*, todo: xxx metaService.getEdits().stream().map(x -> x.split("[.]")[0])*/ ).collect(Collectors.toSet()); } else { allAlias = new HashSet<>(); metaLinks.stream().forEach(x -> { if (table.equals(x.getTables()[0])) { allAlias.add(x.getTables()[1]); } else if (table.equals(x.getTables()[1])) { allAlias.add(x.getTables()[0]); } }); } allAlias.forEach(x -> tables.set(x, getMetaTableByAlias(x))); return tables; } /*public static DbKit getDbKit(String dbPlatId) { Optional dbAccount = dbPlats.stream().filter(x -> x.getKey().equals(dbPlatId)).findAny(); return new DbKit(dbAccount.get()); }*/ public static DbKit getDbKit(String dbPlatId, String catalog) { Optional dbAccount = dbPlats.stream().filter(x -> x.getKey().equals(dbPlatId)).findAny(); return new DbKit(dbAccount.get(), catalog); } public static DbAccount getDbPlat(String dbPlatId) { Optional dbAccount = dbPlats.stream().filter(x -> x.getKey().equals(dbPlatId)).findFirst(); return dbAccount.get(); } @Comment("通过平台token 得到平台id") public static String getPlatId(String platToken) { // Optional plat = sysPlats.stream().filter(x -> x.getToken().equals(platToken)).findAny(); return plat.get().getKey(); } public static String lastAlias; public static String nextAlias() { if (lastAlias == null) { String aql = TplKit.use(true).getTpl("metaTable.lastAlias"); lastAlias = MetaTable.dao.findFirst(aql, String.class); } return lastAlias = next(lastAlias, ""); } //使用['a',...,'z'] 创建Table 别名 private static String next(String x, String end) { if (x == null || "".equals(x)) { return "a" + end; } char c = x.charAt(x.length() - 1); String sub = x.substring(0, x.length() - 1); if (c < 'z') { return sub + (++c) + end; } else if (c == 'z') { return next(sub, "a" + end); } return null; } public static List tableExist(String[] tableArr, String token) { List _tableArr = asList(tableArr); List hv = metaTables.stream() .filter(x -> _tableArr.contains(x.getName()) && x.getSysPlatId().equals(getPlatId(token))) .map(MetaTable::getName) .collect(Collectors.toList()); return hv; } // ---------------------- repository ------------------- public static void save(T ... ts) { if (ts == null || ts.length == 0) return; for (T t : ts) { if ("file".equals(dcate)) { if (t.getKey() == null) { //数据新增异常提示 throw new UnsupportedOperationException("数据文件形式启动服务,不支持配置新增!"); } cacheSave(t.getClass()); return; } if (t.getKey() == null) { t.save(); } else { if (t instanceof MetaLink) { //避免删除属性无效 if (((MetaLink) t).getLink() != null && ((MetaLink) t).getLink().size() > 0) { t.find(String.format("UPDATE '%s' WITH { link:null } IN MetaLink", t.getKey()), Map.class); } } t.update(); } } reload(ts[0].getClass()); } public static T findFirst(T t) { Objects.nonNull(t); List list = asList(); Map doc = t.toDoc(); if (t instanceof User) { list = (List) users; } Optional any = list.stream().filter(x -> { Map map = x.toDoc(); Set keySet = doc.keySet(); for (String k : keySet) { if (doc.get(k) != null && (doc.get(k) instanceof String && doc.get(k).equals(map.get(k)))) { return true; } } return false; }).findAny(); return (T) any.orElse(null); } }