package com.xcong.farmer.cms.core.node; import cn.hutool.core.collection.CollUtil; import com.alibaba.fastjson.JSONObject; import com.xcong.farmer.cms.core.handler.DataParserHandler; import com.xcong.farmer.cms.core.tag.TagsEnum; import com.xcong.farmer.cms.core.template.Configuration; import groovy.lang.Binding; import groovy.lang.GroovyShell; import org.apache.commons.text.StringSubstitutor; import org.jsoup.nodes.Attribute; import org.jsoup.nodes.Attributes; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; public class AttrNode extends Configuration { private String tag; public TagsEnum tagsEnum; // tag标签中field字段的值 如 field=art 中的 art private String field; // 标签数据 如@artilces从数据库查询到的数据 private Object data; // 用于给这个标签attr注入的数据 private Map parserData; private Map systemData; // Tag参数 {id=[1,2,3], page=1, limit=5, field=art} private Object param; private Element element; private Element originalElement; private boolean processContinue = true; public AttrNode() { } public AttrNode(Element element) { this.element = element.clone(); this.originalElement = element; } public AttrNode(Element element, Map parserData) { this.element = element.clone(); this.originalElement = element; this.parserData = parserData; } public static void main(String[] args) { // String data = "{id=[1,2,3], page=1, limit=5, field=art}"; // Articles articles = new AttrNode().parserTag(data, Articles.class); // String value = "{id=${col.id}, page=1, limit=5, field=art}"; // String pattern = "(?<=\\$\\{)[\\s\\S]*?(?=\\})"; // Matcher matcher = Pattern.compile(pattern).matcher(value); // while (matcher.find()) { // String group = matcher.group(); // System.out.println(1); // } System.out.println(1); } private boolean isNeedEmpty() { Elements children = this.element.children(); if (CollUtil.isNotEmpty(children)) { return true; } Attributes attributes = this.element.attributes(); if (CollUtil.isEmpty(attributes)) { return false; } for (Attribute attribute : attributes) { if (attribute.getKey().contains("@") || attribute.getKey().contains("$")) { return true; } } return false; } public void parser() { // 判断是否为最小节点,如果是且没有特殊标签,则跳过清空 if (!isNeedEmpty()) { return; } this.element.empty(); Attributes attributes = this.element.attributes(); if (attributes.isEmpty()) { return; } // i = 1表示每个element上最多有一个tag int i = 1; // 判断element中是否包含tag,若有,则解析并查询对应数据 for (TagsEnum tagsEnum : TagsEnum.values()) { if (!attributes.hasKey(tagsEnum.getName())) { continue; } if (i > 1) { throw new RuntimeException("element most one tag"); } i++; try { // {id=${col.id}, page=1, limit=5, field=art} ${col.id} 形式需先设置值 String tagValue = attributes.get(tagsEnum.getName()); tagValue = attrValueFormat(tagValue); this.param = parserTag(tagValue, Class.forName(tagsEnum.getClassName())); this.field = JSONObject.parseObject(JSONObject.toJSONString(param)).getString("field"); this.tagsEnum = tagsEnum; DataParserHandler handler = (DataParserHandler) Class.forName(tagsEnum.getHandler()).newInstance(); handler.dataParser(this); } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) { e.printStackTrace(); } this.tag = tagsEnum.getName(); if (this.data == null) { this.processContinue = false; } } runDataInject(); } public void runDataInject() { Attributes attributes = this.element.attributes(); for (Attribute attribute : attributes) { String key = attribute.getKey().replaceAll("\\$", ""); String value = attribute.getValue(); // @{} 为java表达式; ${}为需要注入的数据项 if (value.startsWith("@{")) { value = value.replaceAll("\\@\\{", "").replaceAll("}", ""); Binding binding = new Binding(); for (Map.Entry entry : this.parserData.entrySet()) { String fieldKey = entry.getKey(); Map data = (Map) entry.getValue(); binding.setProperty(fieldKey, data); binding.setVariable(fieldKey + ".index", 1); } GroovyShell shell = new GroovyShell(binding); String evaluate = (String) shell.evaluate(value); this.element.removeAttr("class"); this.element.attr("class", evaluate); } else if (value.contains( "${")) { String result = attrValueFormat(value); System.out.println(result); if ("text".equals(key)) { this.element.text(result); } else { this.element.attr(key, result); } } } } public String attrValueFormat(String value) { String pattern = "(?<=\\$\\{)[\\s\\S]*?(?=\\})"; Matcher matcher = Pattern.compile(pattern).matcher(value); Map targetData = new HashMap<>(); while (matcher.find()) { String group = matcher.group(); // String splitValue = group.replaceAll("\\$\\{", "").replaceAll("}", ""); // String[] split = splitValue.split("\\."); // if (split.length == 0) { // continue; // } // // for (Map.Entry entry : this.parserData.entrySet()) { // String fieldKey = entry.getKey(); // Map data = (Map) entry.getValue(); // JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(data.get("state"))); // // for (Map.Entry map : jsonObject.entrySet()) { // if (map.getValue() instanceof String) { // targetData.put(fieldKey + "." + map.getKey(), (String) map.getValue()); // } // } // } Binding binding = new Binding(); for (Map.Entry entry : this.parserData.entrySet()) { String fieldKey = entry.getKey(); Map data = (Map) entry.getValue(); binding.setProperty(fieldKey, data.get("state")); } if (systemData != null) { binding.setProperty("system", systemData); } GroovyShell shell = new GroovyShell(binding); Object evaluate = shell.evaluate(group); if (evaluate == null) { targetData.put(group, ""); } else { targetData.put(group, evaluate.toString()); } } StringSubstitutor str = new StringSubstitutor(targetData); return str.replace(value); } public Object getData() { return data; } public void setData(Object data) { this.data = data; } public String getField() { return field; } public void setField(String field) { this.field = field; } public Element getElement() { return element; } public Map getParserData() { return parserData; } public Object getParam() { return param; } public String getTag() { return tag; } public boolean processContinue() { return processContinue; } public void systemData(Map systemData) { this.systemData = systemData; } }