From 27b61ffe97c575cdc6c2e8b9f010ab1021e7160e Mon Sep 17 00:00:00 2001
From: Helius <wangdoubleone@gmail.com>
Date: Sat, 02 Jul 2022 21:36:56 +0800
Subject: [PATCH] 添加模板解析逻辑

---
 src/main/java/com/xcong/farmer/cms/cms/tag/TagsEnum.java                          |   60 +++
 src/main/java/com/xcong/farmer/cms/cms/tag/model/Ad.java                          |   28 +
 src/main/java/com/xcong/farmer/cms/cms/handler/TemplateCodeDataParserHandler.java |   15 
 src/main/java/com/xcong/farmer/cms/cms/template/Configuration.java                |  111 +++++
 src/main/java/com/xcong/farmer/cms/cms/handler/NavDataParserHandler.java          |   43 ++
 src/main/java/com/xcong/farmer/cms/cms/template/TemplateConfiguration.java        |  105 +++++
 src/main/java/com/xcong/farmer/cms/cms/handler/ArticlesDataParserHandler.java     |   33 +
 pom.xml                                                                           |   14 
 src/main/java/com/xcong/farmer/cms/cms/tag/model/Column.java                      |   48 ++
 src/main/java/com/xcong/farmer/cms/cms/tag/model/Article.java                     |   28 +
 src/main/java/com/xcong/farmer/cms/cms/handler/ChildDataParserHandler.java        |   30 +
 src/main/java/com/xcong/farmer/cms/cms/tag/model/Columns.java                     |    9 
 src/main/java/com/xcong/farmer/cms/cms/tag/model/Nav.java                         |   18 
 src/main/java/com/xcong/farmer/cms/cms/node/AttrNode.java                         |  203 ++++++++++
 src/main/java/com/xcong/farmer/cms/cms/tag/model/Articles.java                    |   48 ++
 src/main/java/com/xcong/farmer/cms/cms/template/Template.java                     |   71 +++
 src/main/java/com/xcong/farmer/cms/cms/handler/ArticleDataParserHandler.java      |   22 +
 src/main/java/com/xcong/farmer/cms/cms/handler/DataParserHandler.java             |   10 
 src/main/java/com/xcong/farmer/cms/cms/template/TemplateLoader.java               |   66 +++
 src/main/java/com/xcong/farmer/cms/cms/node/PartNode.java                         |  102 +++++
 src/main/java/com/xcong/farmer/cms/cms/tag/model/Child.java                       |   28 +
 src/main/java/com/xcong/farmer/cms/cms/tag/model/Include.java                     |   27 +
 22 files changed, 1,119 insertions(+), 0 deletions(-)

diff --git a/pom.xml b/pom.xml
index 0287bb3..5030755 100644
--- a/pom.xml
+++ b/pom.xml
@@ -265,6 +265,20 @@
             <artifactId>commons-io</artifactId>
             <version>2.11.0</version>
         </dependency>
+
+        <!-- https://mvnrepository.com/artifact/org.codehaus.groovy/groovy -->
+        <dependency>
+            <groupId>org.codehaus.groovy</groupId>
+            <artifactId>groovy</artifactId>
+            <version>2.5.6</version>
+        </dependency>
+
+        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-text -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-text</artifactId>
+            <version>1.9</version>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/src/main/java/com/xcong/farmer/cms/cms/handler/ArticleDataParserHandler.java b/src/main/java/com/xcong/farmer/cms/cms/handler/ArticleDataParserHandler.java
new file mode 100644
index 0000000..9e54a40
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/handler/ArticleDataParserHandler.java
@@ -0,0 +1,22 @@
+package com.xcong.farmer.cms.cms.handler;
+
+
+import com.xcong.farmer.cms.cms.node.AttrNode;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author wzy
+ * @date 2022-06-24
+ **/
+public class ArticleDataParserHandler implements DataParserHandler {
+
+    @Override
+    public void dataParser(AttrNode node) {
+        System.out.println("ArticleDataParserHandler");
+        Map<String, Object> map = new HashMap<>();
+        map.put("title", "这是单个文章标题");
+        node.setData(map);
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/handler/ArticlesDataParserHandler.java b/src/main/java/com/xcong/farmer/cms/cms/handler/ArticlesDataParserHandler.java
new file mode 100644
index 0000000..69a2178
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/handler/ArticlesDataParserHandler.java
@@ -0,0 +1,33 @@
+package com.xcong.farmer.cms.cms.handler;
+
+import com.xcong.farmer.cms.cms.node.AttrNode;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author wzy
+ * @date 2022-06-24
+ **/
+public class ArticlesDataParserHandler implements DataParserHandler  {
+
+
+    @Override
+    public void dataParser(AttrNode node) {
+        System.out.println("ArticlesDataParserHandler");
+        List<Map<String, Object>> list = new ArrayList<>();
+        Map<String, Object> map = new HashMap<>();
+        map.put("path", "这是链接1");
+        map.put("title", "这是标题1");
+        list.add(map);
+
+        Map<String, Object> map2 = new HashMap<>();
+        map2.put("path", "这是链接2");
+        map2.put("title", "这是标题2");
+        list.add(map2);
+
+        node.setData(list);
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/handler/ChildDataParserHandler.java b/src/main/java/com/xcong/farmer/cms/cms/handler/ChildDataParserHandler.java
new file mode 100644
index 0000000..5f78333
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/handler/ChildDataParserHandler.java
@@ -0,0 +1,30 @@
+package com.xcong.farmer.cms.cms.handler;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.xcong.farmer.cms.cms.node.AttrNode;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author wzy
+ * @date 2022-06-29
+ **/
+public class ChildDataParserHandler implements DataParserHandler {
+
+    @Override
+    public void dataParser(AttrNode attrNode) {
+        System.out.println("ChildDataParserHandler");
+        Map<String, Object> parserData = attrNode.getParserData();
+
+        Object param = attrNode.getParam();
+        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(param));
+        String obj = jsonObject.getString("obj");
+
+        Object o = parserData.get(obj);
+        Object state = JSONObject.parseObject(JSONObject.toJSONString(o)).get("state");
+        List children = JSONObject.parseObject(JSONObject.toJSONString(state)).getObject("children", List.class);
+        attrNode.setData(children);
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/handler/DataParserHandler.java b/src/main/java/com/xcong/farmer/cms/cms/handler/DataParserHandler.java
new file mode 100644
index 0000000..7a3ee0d
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/handler/DataParserHandler.java
@@ -0,0 +1,10 @@
+package com.xcong.farmer.cms.cms.handler;
+
+
+import com.xcong.farmer.cms.cms.node.AttrNode;
+
+public interface DataParserHandler {
+
+    void dataParser(AttrNode attrNode);
+
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/handler/NavDataParserHandler.java b/src/main/java/com/xcong/farmer/cms/cms/handler/NavDataParserHandler.java
new file mode 100644
index 0000000..222da87
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/handler/NavDataParserHandler.java
@@ -0,0 +1,43 @@
+package com.xcong.farmer.cms.cms.handler;
+
+import com.xcong.farmer.cms.cms.node.AttrNode;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author wzy
+ * @date 2022-06-28
+ **/
+public class NavDataParserHandler implements DataParserHandler {
+
+
+    @Override
+    public void dataParser(AttrNode node) {
+        System.out.println("NavDataParserHandler");
+        List<Map<String, Object>> list = new ArrayList<>();
+        Map<String, Object> aa = new HashMap<>();
+        aa.put("title", "导航1");
+        list.add(aa);
+
+        Map<String, Object> bb = new HashMap<>();
+        bb.put("title", "导航2");
+
+        List<Map<String, Object>> sub = new ArrayList<>();
+        Map<String, Object> subBB = new HashMap<>();
+        subBB.put("title", "子导航1");
+        subBB.put("src", "http://1234");
+        sub.add(subBB);
+        Map<String, Object> subAA = new HashMap<>();
+        subAA.put("title", "子导航2");
+        subAA.put("src", "http://123455555");
+        sub.add(subAA);
+
+        bb.put("children", sub);
+        list.add(bb);
+
+        node.setData(list);
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/handler/TemplateCodeDataParserHandler.java b/src/main/java/com/xcong/farmer/cms/cms/handler/TemplateCodeDataParserHandler.java
new file mode 100644
index 0000000..10b89d6
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/handler/TemplateCodeDataParserHandler.java
@@ -0,0 +1,15 @@
+package com.xcong.farmer.cms.cms.handler;
+
+import com.xcong.farmer.cms.cms.node.AttrNode;
+
+/**
+ * @author wzy
+ * @date 2022-06-29
+ **/
+public class TemplateCodeDataParserHandler implements DataParserHandler {
+
+    @Override
+    public void dataParser(AttrNode tagNode) {
+        System.out.println("TemplateCodeDataParserHandler");
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/node/AttrNode.java b/src/main/java/com/xcong/farmer/cms/cms/node/AttrNode.java
new file mode 100644
index 0000000..adf7a84
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/node/AttrNode.java
@@ -0,0 +1,203 @@
+package com.xcong.farmer.cms.cms.node;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.xcong.farmer.cms.cms.handler.DataParserHandler;
+import com.xcong.farmer.cms.cms.tag.TagsEnum;
+import com.xcong.farmer.cms.cms.tag.model.Articles;
+import com.xcong.farmer.cms.cms.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 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<String, Object> parserData;
+    // Tag参数 {id=[1,2,3], page=1, limit=5, field=art}
+    private Object param;
+
+    private Element element;
+    private Element originalElement;
+
+    public AttrNode() {
+    }
+
+    public AttrNode(Element element) {
+        this.element = element.clone();
+        this.originalElement = element;
+    }
+
+    public AttrNode(Element element, Map<String, Object> 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);
+    }
+
+    public void parser() {
+        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();
+        }
+
+        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<String, Object> entry : this.parserData.entrySet()) {
+                    String fieldKey = entry.getKey();
+                    Map<String, Object> data = (Map<String, Object>) 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.startsWith("${")) {
+
+                String result = attrValueFormat(value);
+                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<String, String> 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<String, Object> entry : this.parserData.entrySet()) {
+                String fieldKey = entry.getKey();
+                Map<String, Object> data = (Map<String, Object>) entry.getValue();
+                JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(data.get("state")));
+
+                for (Map.Entry<String, Object> map : jsonObject.entrySet()) {
+                    if (map.getValue() instanceof String) {
+                        targetData.put(fieldKey + "." + map.getKey(), (String) map.getValue());
+                    }
+                }
+            }
+        }
+
+        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<String, Object> getParserData() {
+        return parserData;
+    }
+
+    public Object getParam() {
+        return param;
+    }
+
+    public String getTag() {
+        return tag;
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/node/PartNode.java b/src/main/java/com/xcong/farmer/cms/cms/node/PartNode.java
new file mode 100644
index 0000000..3866f09
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/node/PartNode.java
@@ -0,0 +1,102 @@
+package com.xcong.farmer.cms.cms.node;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.xcong.farmer.cms.cms.template.Configuration;
+import org.jsoup.nodes.Element;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class PartNode extends Configuration {
+
+    private Element element;
+    private Element originalElement;
+    private String html;
+
+    public PartNode(Element element) {
+        this.element = element.clone();
+        this.originalElement = element;
+    }
+
+    public void parser() {
+        this.html = parser(this.element, null);
+    }
+
+    public String parser(Element element, Map<String, Object> tagDataMap) {
+        AttrNode attrNode = new AttrNode(element, tagDataMap);
+        attrNode.parser();
+//        attrNode.runDataInject();
+
+        StringBuilder result = new StringBuilder();
+        if (CollUtil.isNotEmpty(element.children())) {
+            Object parseData = attrNode.getData();
+            if (tagDataMap == null) {
+                tagDataMap = new HashMap<>();
+            }
+
+            if (parseData == null) {
+                // 特殊处理。 如果有子节点标签@child,但数据中没有子节点数据,则将该子节点直接删除即直接返回空字符串
+                if (!"@child".equals(attrNode.getTag())) {
+                    for (Element children : element.children()) {
+                        String html = parser(children, tagDataMap);
+                        result.append(html);
+                    }
+                } else {
+                    return "";
+                }
+            } else {
+                if (parseData instanceof List) {
+                    List list = (List) parseData;
+
+                    int i = 1;
+                    for (Object o : list) {
+                        if (StrUtil.isNotBlank(attrNode.getField())) {
+                            Map<String, Object> data = new HashMap<>();
+                            data.put("index", i);
+                            data.put("state", o);
+                            tagDataMap.put(attrNode.getField(), data);
+                        }
+
+                        StringBuilder listHtml = new StringBuilder();
+                        for (Element children : element.children()) {
+                            String html = parser(children, tagDataMap);
+                            listHtml.append(html);
+                        }
+                        result.append(listHtml);
+                        i++;
+                    }
+
+                } else if (parseData instanceof Map) {
+                    if (StrUtil.isNotBlank(attrNode.getField())) {
+                        Map<String, Object> data = new HashMap<>();
+                        data.put("index", 1);
+                        data.put("state", parseData);
+                        tagDataMap.put(attrNode.getField(), data);
+                    }
+
+                    for (Element children : element.children()) {
+                        String html = parser(children, tagDataMap);
+                        result.append(html);
+                    }
+                }
+            }
+        }
+
+        if (attrNode.tagsEnum != null && attrNode.tagsEnum.getType() == 1) {
+            this.put(attrNode.getField(), result.toString());
+        }
+
+        attrNode.getElement().append(result.toString());
+        return attrNode.getElement().toString();
+    }
+
+    public Element getElement() {
+        return element;
+    }
+
+    public String getHtml() {
+        return html;
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/tag/TagsEnum.java b/src/main/java/com/xcong/farmer/cms/cms/tag/TagsEnum.java
new file mode 100644
index 0000000..e782e0e
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/tag/TagsEnum.java
@@ -0,0 +1,60 @@
+package com.xcong.farmer.cms.cms.tag;
+
+/**
+ * @author wzy
+ * @date 2022-06-20
+ **/
+public enum TagsEnum {
+    INCLUDE("@include", "com.xcong.farmer.cms.cms.tag.model.Include", "com.xcong.farmer.cms.cms.handler.TemplateCodeDataParserHandler",  1),
+    NAV("@nav", "com.xcong.farmer.cms.cms.tag.model.Nav", "com.xcong.farmer.cms.cms.handler.NavDataParserHandler", 2),
+    ARTICLES("@articles", "com.xcong.farmer.cms.cms.tag.model.Articles", "com.xcong.farmer.cms.cms.handler.ArticlesDataParserHandler",2),
+    ARTICLE("@article", "com.xcong.farmer.cms.cms.tag.model.Article", "com.xcong.farmer.cms.cms.handler.ArticleDataParserHandler",2),
+    CHILD("@child", "com.xcong.farmer.cms.cms.tag.model.Child", "com.xcong.farmer.cms.cms.handler.ChildDataParserHandler",2);
+//    AD("@ad", "com.xcong.farmer.cms.cms.tag.model.Ad", "",2),
+//    COLUMNS("@columns", "com.xcong.farmer.cms.cms.tag.model.Columns", "",2),
+//    COLUMN("@column", "com.xcong.farmer.cms.cms.tag.model.Column", "",2);
+
+    private String name;
+
+    private String className;
+
+    private String handler;
+
+    // 标签类型 1-模板标签  2-数据标签
+    // 模板标签 : 该标签可以变为通用模板,在各个页面引入
+    // 数据模板 : 该标签需要注入数据
+    private int type;
+
+    TagsEnum(String name, String className, String handler, int type) {
+        this.name = name;
+        this.className = className;
+        this.type = type;
+        this.handler = handler;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getClassName() {
+        return className;
+    }
+
+    public int getType() {
+        return type;
+    }
+
+    public String getHandler() {
+        return handler;
+    }
+
+    public static TagsEnum getEnumByName(String name) {
+        for (TagsEnum value : values()) {
+            if (name.equals(value.getName())) {
+                return value;
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/tag/model/Ad.java b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Ad.java
new file mode 100644
index 0000000..4e0f869
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Ad.java
@@ -0,0 +1,28 @@
+package com.xcong.farmer.cms.cms.tag.model;
+
+/**
+ * @author wzy
+ * @date 2022-06-22
+ **/
+public class Ad {
+
+    private String id;
+
+    private String field;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getField() {
+        return field;
+    }
+
+    public void setField(String field) {
+        this.field = field;
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/tag/model/Article.java b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Article.java
new file mode 100644
index 0000000..a0c72c1
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Article.java
@@ -0,0 +1,28 @@
+package com.xcong.farmer.cms.cms.tag.model;
+
+/**
+ * @author wzy
+ * @date 2022-06-22
+ **/
+public class Article {
+
+    private String id;
+
+    private String field;
+
+    public String getField() {
+        return field;
+    }
+
+    public void setField(String field) {
+        this.field = field;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/tag/model/Articles.java b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Articles.java
new file mode 100644
index 0000000..e93e0ef
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Articles.java
@@ -0,0 +1,48 @@
+package com.xcong.farmer.cms.cms.tag.model;
+
+/**
+ * @author wzy
+ * @date 2022-06-20
+ **/
+public class Articles {
+
+    private String colId;
+
+    private String page;
+
+    private String limit;
+
+    private String field;
+
+    public String getColId() {
+        return colId;
+    }
+
+    public void setColId(String colId) {
+        this.colId = colId;
+    }
+
+    public String getPage() {
+        return page;
+    }
+
+    public void setPage(String page) {
+        this.page = page;
+    }
+
+    public String getLimit() {
+        return limit;
+    }
+
+    public void setLimit(String limit) {
+        this.limit = limit;
+    }
+
+    public String getField() {
+        return field;
+    }
+
+    public void setField(String field) {
+        this.field = field;
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/tag/model/Child.java b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Child.java
new file mode 100644
index 0000000..7ae44fa
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Child.java
@@ -0,0 +1,28 @@
+package com.xcong.farmer.cms.cms.tag.model;
+
+/**
+ * @author wzy
+ * @date 2022-07-01
+ **/
+public class Child {
+
+    private String obj;
+
+    private String field;
+
+    public String getObj() {
+        return obj;
+    }
+
+    public void setObj(String obj) {
+        this.obj = obj;
+    }
+
+    public String getField() {
+        return field;
+    }
+
+    public void setField(String field) {
+        this.field = field;
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/tag/model/Column.java b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Column.java
new file mode 100644
index 0000000..18b0146
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Column.java
@@ -0,0 +1,48 @@
+package com.xcong.farmer.cms.cms.tag.model;
+
+/**
+ * @author wzy
+ * @date 2022-06-22
+ **/
+public class Column {
+
+    private String id;
+
+    private String field;
+
+    private String code;
+
+    private String hasChild;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getField() {
+        return field;
+    }
+
+    public void setField(String field) {
+        this.field = field;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getHasChild() {
+        return hasChild;
+    }
+
+    public void setHasChild(String hasChild) {
+        this.hasChild = hasChild;
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/tag/model/Columns.java b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Columns.java
new file mode 100644
index 0000000..ed62f0b
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Columns.java
@@ -0,0 +1,9 @@
+package com.xcong.farmer.cms.cms.tag.model;
+
+/**
+ * @author wzy
+ * @date 2022-06-22
+ **/
+public class Columns {
+
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/tag/model/Include.java b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Include.java
new file mode 100644
index 0000000..47e9c6a
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Include.java
@@ -0,0 +1,27 @@
+package com.xcong.farmer.cms.cms.tag.model;
+
+/**
+ * @author wzy
+ * @date 2022-06-23
+ **/
+public class Include {
+    private String field;
+
+    private String repeat = "1";
+
+    public String getRepeat() {
+        return repeat;
+    }
+
+    public void setRepeat(String repeat) {
+        this.repeat = repeat;
+    }
+
+    public String getField() {
+        return field;
+    }
+
+    public void setField(String field) {
+        this.field = field;
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/tag/model/Nav.java b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Nav.java
new file mode 100644
index 0000000..45e5707
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/tag/model/Nav.java
@@ -0,0 +1,18 @@
+package com.xcong.farmer.cms.cms.tag.model;
+
+/**
+ * @author wzy
+ * @date 2022-06-28
+ **/
+public class Nav {
+
+    String field;
+
+    public String getField() {
+        return field;
+    }
+
+    public void setField(String field) {
+        this.field = field;
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/template/Configuration.java b/src/main/java/com/xcong/farmer/cms/cms/template/Configuration.java
new file mode 100644
index 0000000..76a24e6
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/template/Configuration.java
@@ -0,0 +1,111 @@
+package com.xcong.farmer.cms.cms.template;
+
+import com.xcong.farmer.cms.cms.node.AttrNode;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+public abstract class Configuration {
+
+    public String staticPath;
+    public String templatePath;
+    public String outputPath;
+
+    public Configuration() {
+    }
+
+    public Configuration(String templatePath, String staticPath, String outputPath) {
+        this.staticPath = staticPath;
+        this.templatePath = templatePath;
+        this.outputPath = outputPath;
+    }
+
+    public static Map<String, String> templateCode = new HashMap<>();
+
+    private final String PREFIX_DEFAULT = "{";
+    private final String SUFFIX_DEFAULT = "}";
+
+    public <T> T parserTag(String attr, Class<T> clazz) {
+        if (!attr.startsWith(PREFIX_DEFAULT) || !attr.endsWith(SUFFIX_DEFAULT)) {
+            return null;
+        }
+
+        int i = 1;
+        int length = attr.length();
+
+        int startIndex = 1;
+        int endIndex = 1;
+        T object = null;
+        try {
+            object = clazz.newInstance();
+        } catch (InstantiationException | IllegalAccessException e) {
+            e.printStackTrace();
+        }
+
+        boolean hasMulti = false;
+        for (; i <= length - 1; i++) {
+            if (attr.charAt(i) =='[') {
+                hasMulti = true;
+            } else if (attr.charAt(i) == ']') {
+                hasMulti = false;
+            }
+
+            if (!hasMulti) {
+                if (attr.charAt(i) == ',' || i == length - 1) {
+                    String columnStr = attr.substring(startIndex, endIndex);
+
+                    String[] columns = columnStr.split("=");
+                    if (columns.length != 2) {
+                        return null;
+                    }
+
+                    try {
+                        Field field = clazz.getDeclaredField(columns[0].trim());
+                        field.setAccessible(true);
+                        field.set(object, columns[1].replace("[", "").replace("]", "").trim());
+                    } catch (NoSuchFieldException | IllegalAccessException e) {
+                        e.printStackTrace();
+                        return null;
+                    }
+                    startIndex = i + 1;
+                }
+            }
+            endIndex++;
+        }
+
+        return object;
+    }
+
+    public void put(String key, String templateCode) {
+        Configuration.templateCode.put(key, templateCode);
+    }
+
+    public String get(String key) {
+        return Configuration.templateCode.get(key);
+    }
+
+    public String getStaticPath() {
+        return staticPath;
+    }
+
+    public void setStaticPath(String staticPath) {
+        this.staticPath = staticPath;
+    }
+
+    public String getTemplatePath() {
+        return templatePath;
+    }
+
+    public void setTemplatePath(String templatePath) {
+        this.templatePath = templatePath;
+    }
+
+    public String getOutputPath() {
+        return outputPath;
+    }
+
+    public void setOutputPath(String outputPath) {
+        this.outputPath = outputPath;
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/template/Template.java b/src/main/java/com/xcong/farmer/cms/cms/template/Template.java
new file mode 100644
index 0000000..f0a20f0
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/template/Template.java
@@ -0,0 +1,71 @@
+package com.xcong.farmer.cms.cms.template;
+
+import cn.hutool.core.collection.CollUtil;
+import com.xcong.farmer.cms.cms.node.PartNode;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author wzy
+ * @date 2022-06-22
+ **/
+public class Template {
+
+    private String name;
+
+    private Document document;
+
+    private Map<String, Map<String, Object>> params = new HashMap<>();
+
+    private List<PartNode> partNodes = new ArrayList<>();
+
+    public void parser() {
+        Elements children = document.body().children();
+        if (CollUtil.isNotEmpty(children)) {
+            for (Element child : children) {
+                PartNode partNode = new PartNode(child);
+                partNode.parser();
+
+                this.add(partNode);
+            }
+        }
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Document getDocument() {
+        return document;
+    }
+
+    public void setDocument(Document document) {
+        this.document = document;
+    }
+
+    public void add(PartNode partNode) {
+        this.partNodes.add(partNode);
+    }
+
+    public List<PartNode> getPartNodes() {
+        return partNodes;
+    }
+
+    public Map<String, Map<String, Object>> getParams() {
+        return params;
+    }
+
+    public void putParams(String key, Map<String, Object> value) {
+        this.params.put(key, value);
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/template/TemplateConfiguration.java b/src/main/java/com/xcong/farmer/cms/cms/template/TemplateConfiguration.java
new file mode 100644
index 0000000..4162af3
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/template/TemplateConfiguration.java
@@ -0,0 +1,105 @@
+package com.xcong.farmer.cms.cms.template;
+
+import cn.hutool.core.collection.CollUtil;
+import com.xcong.farmer.cms.cms.node.PartNode;
+import com.xcong.farmer.cms.cms.tag.TagsEnum;
+import org.jsoup.nodes.Document;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author wzy
+ * @date 2022-07-01
+ **/
+public class TemplateConfiguration extends Configuration{
+
+    private TemplateLoader templateLoader;
+
+    public TemplateConfiguration(String templatePath, String staticPath, String outputPath) {
+        super(templatePath, staticPath, outputPath);
+    }
+
+    public void templateLoader(TemplateLoader templateLoader) {
+        this.templateLoader = templateLoader;
+    }
+
+    public void process() {
+        if (this.templateLoader == null) {
+            throw new RuntimeException("TemplateLoader do not able to be null");
+        }
+
+        List<Template> templates = templateLoader.templates();
+
+        if (CollUtil.isEmpty(templates)) {
+            return;
+        }
+
+        for (Template template : templates) {
+            output(template);
+        }
+    }
+
+    public List<Template> templates() {
+        return this.templateLoader.templates();
+    }
+
+    public Template template(String templateName) {
+        return template(new File(path(this.templatePath) + templateName));
+    }
+
+    public Template template(File file) {
+        if (file == null) {
+            throw new RuntimeException("template not exist");
+        }
+
+        return this.templateLoader.template(file);
+    }
+
+    public void columnProcess(Long id, String templateName) {
+        Template template = template(templateName);
+    }
+
+    public void columnProcess(String code, String templateName) {
+
+    }
+
+    public void articleProcess(Long id, String templateName) {
+        Map<String, Map<String, Object>> map = new HashMap<>();
+
+        Map<String, Object> data = new HashMap<>();
+        data.put("id", id);
+        map.put(TagsEnum.ARTICLE.getName(), data);
+    }
+
+    public void output(Template template) {
+        Document document = template.getDocument();
+        List<PartNode> partNodes = template.getPartNodes();
+        StringBuilder sb = new StringBuilder();
+        for (PartNode partNode : partNodes) {
+            sb.append(partNode.getHtml());
+        }
+        document.body().empty().html(sb.toString());
+        String outPath = path(this.outputPath);
+
+        String html = document.html();
+        try {
+            FileOutputStream outputStream = new FileOutputStream(outPath + template.getName());
+            outputStream.write(html.getBytes());
+            outputStream.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private String path(String path) {
+        if (!path.endsWith("/")) {
+            path = path + "/";
+        }
+        return path;
+    }
+}
diff --git a/src/main/java/com/xcong/farmer/cms/cms/template/TemplateLoader.java b/src/main/java/com/xcong/farmer/cms/cms/template/TemplateLoader.java
new file mode 100644
index 0000000..154732e
--- /dev/null
+++ b/src/main/java/com/xcong/farmer/cms/cms/template/TemplateLoader.java
@@ -0,0 +1,66 @@
+package com.xcong.farmer.cms.cms.template;
+
+import cn.hutool.core.collection.CollUtil;
+import com.xcong.farmer.cms.cms.node.AttrNode;
+import com.xcong.farmer.cms.cms.node.PartNode;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class TemplateLoader {
+
+    private Configuration cfg;
+    private List<Template> templates = new ArrayList<>();
+
+    public TemplateLoader() {}
+
+    public TemplateLoader(Configuration cfg) {
+        this.cfg = cfg;
+    }
+
+    public Template template(File file) {
+        Document document = null;
+        try {
+            document = Jsoup.parse(file, "utf-8");
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        if (document == null) {
+            throw new NullPointerException();
+        }
+
+        Template template = new Template();
+        template.setDocument(document);
+        template.setName(file.getName());
+
+        template.parser();
+        return template;
+    }
+
+    public List<Template> templates(String templatePath) {
+        File files = new File(templatePath);
+        if (files.listFiles() == null) {
+            return null;
+        }
+
+        for (File file : files.listFiles()) {
+            if (file.isDirectory()) {
+                continue;
+            }
+            templates.add(template(file));
+        }
+
+        return templates;
+    }
+
+    public List<Template> templates() {
+        return templates(cfg.getTemplatePath());
+    }
+}

--
Gitblit v1.9.1