Jelajahi Sumber

新增数据字典解析功能

zhouhao 8 tahun lalu
induk
melakukan
7bd1c7ebdd
13 mengubah file dengan 689 tambahan dan 10 penghapusan
  1. 16 6
      hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-api/src/main/java/org/hswebframework/web/service/dictionary/DictionaryParser.java
  2. 2 2
      hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-api/src/main/java/org/hswebframework/web/service/dictionary/DictionaryParserBuilder.java
  3. 3 1
      hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-api/src/main/java/org/hswebframework/web/service/dictionary/DictionaryParserService.java
  4. 4 0
      hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/pom.xml
  5. 83 0
      hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/SimpleDictionaryParser.java
  6. 4 1
      hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/SimpleDictionaryParserService.java
  7. 81 0
      hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/parser/DictParserFormat.java
  8. 13 0
      hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/parser/DictParserFormatter.java
  9. 39 0
      hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/parser/FormatterResult.java
  10. 67 0
      hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/parser/SimpleDictParserFormatter.java
  11. 251 0
      hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/parser/SimpleSingleDictParser.java
  12. 17 0
      hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/parser/SingleDictParser.java
  13. 109 0
      hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/test/java/org/hswebframework/web/starter/dictionary/DictionaryParserTests.java

+ 16 - 6
hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-api/src/main/java/org/hswebframework/web/service/dictionary/DictionaryParser.java

@@ -18,17 +18,27 @@
 
 package org.hswebframework.web.service.dictionary;
 
-import org.hswebframework.web.entity.dictionary.DictionaryEntity;
-import org.hswebframework.web.entity.dictionary.DictionaryItemEntity;
-
 import java.io.Serializable;
+import java.util.List;
 import java.util.Optional;
 
 /**
+ * 字典解析器接口
+ *
  * @author zhouhao
  */
-public interface DictionaryParser<V, T> extends Serializable {
-    Optional<V> textToValue(DictionaryEntity<? extends DictionaryItemEntity> dict, T text);
+public interface DictionaryParser<V> extends Serializable {
+
+    Optional<V> textToValue(String text, Object context);
+
+    Optional<String> valueToText(V value, Object context);
+
+    default Optional<V> textToValue(String text) {
+        return textToValue(text, null);
+    }
+
+    default Optional<String> valueToText(V value) {
+        return valueToText(value, null);
+    }
 
-    Optional<T> valueToText(DictionaryEntity<? extends DictionaryItemEntity> dict, V value);
 }

+ 2 - 2
hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-api/src/main/java/org/hswebframework/web/service/dictionary/DictionaryParserBuilder.java

@@ -22,7 +22,7 @@ package org.hswebframework.web.service.dictionary;
  * @author zhouhao
  */
 public interface DictionaryParserBuilder {
-    DictionaryParser<Object, String> buildValueToTextParser(String config);
+    DictionaryParser buildValueToTextParser(String config);
 
-    DictionaryParser<String, Object> buildTextToValueParser(String config);
+    DictionaryParser buildTextToValueParser(String config);
 }

+ 3 - 1
hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-api/src/main/java/org/hswebframework/web/service/dictionary/DictionaryParserService.java

@@ -16,6 +16,8 @@
  */
 package org.hswebframework.web.service.dictionary;
 
+import org.hswebframework.web.entity.dictionary.DictionaryEntity;
+import org.hswebframework.web.entity.dictionary.DictionaryItemEntity;
 import org.hswebframework.web.entity.dictionary.DictionaryParserEntity;
 import org.hswebframework.web.service.CrudService;
 
@@ -26,7 +28,7 @@ import org.hswebframework.web.service.CrudService;
  */
 public interface DictionaryParserService extends CrudService<DictionaryParserEntity, String> {
 
-    <V, T> DictionaryParser<V, T> getParser(String parserId);
+    <V> DictionaryParser<V> getParser(DictionaryEntity<? extends DictionaryItemEntity> dict, String parserId);
 
 
 }

+ 4 - 0
hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/pom.xml

@@ -38,5 +38,9 @@
             <artifactId>hsweb-system-dictionary-service-api</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.hswebframework</groupId>
+            <artifactId>hsweb-expands-script</artifactId>
+        </dependency>
     </dependencies>
 </project>

+ 83 - 0
hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/SimpleDictionaryParser.java

@@ -0,0 +1,83 @@
+package org.hswebframework.web.service.dictionary.simple;
+
+import org.hswebframework.web.ExpressionUtils;
+import org.hswebframework.web.entity.dictionary.DictionaryEntity;
+import org.hswebframework.web.entity.dictionary.DictionaryItemEntity;
+import org.hswebframework.web.service.dictionary.DictionaryParser;
+import org.hswebframework.web.service.dictionary.simple.parser.SimpleSingleDictParser;
+import org.hswebframework.web.service.dictionary.simple.parser.SingleDictParser;
+
+import java.io.Serializable;
+import java.util.*;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/**
+ * 简单的字典解析器实现,支持树形结构字典
+ * <p>
+ * e.g.
+ * <pre>
+ *   //字典
+ *   [
+ *    {text:"苹果",value:1,
+ *     children:[
+ *      {text:"青苹果",value:101},
+ *      {text:"红富士",value:102},
+ *      {text:"其他苹果",value:103,textExpression:"其他苹果(${#context.otherApple})"}
+ *    ]}
+ *    {text:"梨子",value:2}
+ *   ]
+ *   //调用
+ *   parser.valueToText("1,101,103",{otherApple:"其他苹果1"});
+ *   //返回结果  苹果(青苹果,其他苹果(其他苹果1))
+ *
+ *   //调用
+ *   parser.textToValue("苹果(青苹果,其他苹果)")
+ *   //返回结果 1,101,103
+ * </pre>
+ *
+ * @author zhouhao
+ * @since 3.0
+ */
+public class SimpleDictionaryParser<V> implements DictionaryParser<V> {
+
+    private SimpleSingleDictParser toTextParser = new SimpleSingleDictParser();
+
+    private SimpleSingleDictParser toValueParser = new SimpleSingleDictParser();
+
+    public SimpleSingleDictParser getToTextParser() {
+        return toTextParser;
+    }
+
+    public SimpleSingleDictParser getToValueParser() {
+        return toValueParser;
+    }
+
+    //设置DictionaryEntity作为配置
+    public void setDict(DictionaryEntity<? extends DictionaryItemEntity> dict) {
+        toTextParser.setDict(dict, DictionaryItemEntity::getValue
+                , DictionaryItemEntity::getText
+                , DictionaryItemEntity::getTextExpression);
+
+        toValueParser.setDict(dict, DictionaryItemEntity::getText
+                , DictionaryItemEntity::getValue,
+                DictionaryItemEntity::getValueExpression);
+
+        toValueParser.getTargetFormat().setSplitter(",");
+        toValueParser.getTargetFormat().setChildStartChar(",");
+        toValueParser.getTargetFormat().setChildEndChar("");
+        toValueParser.getTargetFormat().setChildSplitter(",");
+    }
+
+    @Override
+    public Optional<String> valueToText(V value, Object context) {
+        if (value == null) return Optional.empty();
+        return toTextParser.parse(String.valueOf(value), context);
+    }
+
+    @Override
+    public Optional<V> textToValue(String text, Object context) {
+        return toValueParser.parse(text, context).map(v -> (V) v);
+    }
+}

+ 4 - 1
hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/SimpleDictionaryParserService.java

@@ -17,6 +17,8 @@
 package org.hswebframework.web.service.dictionary.simple;
 
 import org.hswebframework.web.dao.dictionary.DictionaryParserDao;
+import org.hswebframework.web.entity.dictionary.DictionaryEntity;
+import org.hswebframework.web.entity.dictionary.DictionaryItemEntity;
 import org.hswebframework.web.entity.dictionary.DictionaryParserEntity;
 import org.hswebframework.web.id.IDGenerator;
 import org.hswebframework.web.service.GenericEntityService;
@@ -47,7 +49,8 @@ public class SimpleDictionaryParserService extends GenericEntityService<Dictiona
     }
 
     @Override
-    public <V, T> DictionaryParser<V, T> getParser(String parserId) {
+    public <V> DictionaryParser<V> getParser(DictionaryEntity<? extends DictionaryItemEntity> dict, String parserId) {
+
         // TODO: 17-3-9
         return null;
     }

+ 81 - 0
hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/parser/DictParserFormat.java

@@ -0,0 +1,81 @@
+package org.hswebframework.web.service.dictionary.simple.parser;
+
+import java.io.Serializable;
+import java.util.StringJoiner;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public class DictParserFormat implements Serializable {
+    //字典选项间的分割符
+    private String splitter = ",";
+
+    //子节点间的分割符
+    private String childSplitter = ",";
+
+    //子节点开始分割符
+    private String childStartChar = "(";
+
+    //子节点结束分割符
+    private String childEndChar = ")";
+
+    //前缀
+    private String prefix = "";
+
+    //后缀
+    private String suffix = "";
+
+    public String getSplitter() {
+        return splitter;
+    }
+
+    public void setSplitter(String splitter) {
+        this.splitter = splitter;
+    }
+
+    public String getChildSplitter() {
+        return childSplitter;
+    }
+
+    public void setChildSplitter(String childSplitter) {
+        this.childSplitter = childSplitter;
+    }
+
+    public String getChildStartChar() {
+        return childStartChar;
+    }
+
+    public void setChildStartChar(String childStartChar) {
+        this.childStartChar = childStartChar;
+    }
+
+    public String getChildEndChar() {
+        return childEndChar;
+    }
+
+    public void setChildEndChar(String childEndChar) {
+        this.childEndChar = childEndChar;
+    }
+
+    public String getPrefix() {
+        return prefix;
+    }
+
+    public void setPrefix(String prefix) {
+        this.prefix = prefix;
+    }
+
+    public String getSuffix() {
+        return suffix;
+    }
+
+    public void setSuffix(String suffix) {
+        this.suffix = suffix;
+    }
+
+    public StringJoiner createJoiner() {
+        return new StringJoiner(splitter, prefix, suffix);
+    }
+}

+ 13 - 0
hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/parser/DictParserFormatter.java

@@ -0,0 +1,13 @@
+package org.hswebframework.web.service.dictionary.simple.parser;
+
+import java.util.List;
+import java.util.function.BiFunction;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public interface DictParserFormatter {
+    <T> List<FormatterResult<T>> format(DictParserFormat format, Object value, BiFunction<String, String, T> mapping);
+}

+ 39 - 0
hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/parser/FormatterResult.java

@@ -0,0 +1,39 @@
+package org.hswebframework.web.service.dictionary.simple.parser;
+
+/**
+ *
+ * @author zhouhao
+ */
+public class FormatterResult<V> {
+    private V result;
+
+    private String pattern;
+
+    public FormatterResult() {
+    }
+
+    public FormatterResult(V result) {
+        this(result, String.valueOf(result));
+    }
+
+    public FormatterResult(V result, String pattern) {
+        this.result = result;
+        this.pattern = pattern;
+    }
+
+    public V getResult() {
+        return result;
+    }
+
+    public void setResult(V result) {
+        this.result = result;
+    }
+
+    public String getPattern() {
+        return pattern;
+    }
+
+    public void setPattern(String pattern) {
+        this.pattern = pattern;
+    }
+}

+ 67 - 0
hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/parser/SimpleDictParserFormatter.java

@@ -0,0 +1,67 @@
+package org.hswebframework.web.service.dictionary.simple.parser;
+
+import org.hswebframework.web.RegexUtils;
+
+import java.util.*;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public class SimpleDictParserFormatter implements DictParserFormatter {
+
+    public boolean smartParse = true;
+
+    public int smartLevel = 3;
+
+    public void setSmartParse(boolean smartParse) {
+        this.smartParse = smartParse;
+    }
+
+    public boolean needParse(String value, DictParserFormat format) {
+        return value.contains(format.getSplitter())
+                || value.contains(format.getChildSplitter())
+                || value.contains(format.getChildStartChar());
+    }
+
+    private <T> FormatterResult<T> createResult(T v, String pattern) {
+        return new FormatterResult<>(v, pattern);
+    }
+
+    @Override
+    public <T> List<FormatterResult<T>> format(DictParserFormat format
+            , Object value
+            , BiFunction<String, String, T> mapping) {
+        if (value == null) return Collections.emptyList();
+        String stringValue = String.valueOf(value);
+        if (!needParse(stringValue, format))
+            return Collections.singletonList(createResult(mapping.apply(stringValue, stringValue), stringValue));
+
+        String splitter = "[" + RegexUtils.escape(format.getSplitter() +
+                " " + format.getChildStartChar() +
+                " " + format.getChildSplitter() +
+                " " + format.getChildEndChar()) +
+                "]";
+        return Arrays.stream(stringValue.split(splitter))
+                .map(val -> {
+                    T v = mapping.apply(val, val);
+                    if (v == null && smartParse) {
+                        StringBuilder tmp = new StringBuilder();
+                        char[] arr = val.toCharArray();
+                        for (int i = 0; i < arr.length; i++) {
+                            tmp.append(arr[i]);
+                            if (i >= smartLevel) {
+                                v = mapping.apply(tmp.toString(), val);
+                                if (null != v) break;
+                            }
+                        }
+                    }
+                    return createResult(v, val);
+                })
+                .collect(Collectors.toList());
+    }
+}

+ 251 - 0
hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/parser/SimpleSingleDictParser.java

@@ -0,0 +1,251 @@
+package org.hswebframework.web.service.dictionary.simple.parser;
+
+import org.hswebframework.web.ExpressionUtils;
+import org.hswebframework.web.entity.dictionary.DictionaryEntity;
+import org.hswebframework.web.entity.dictionary.DictionaryItemEntity;
+
+import java.io.Serializable;
+import java.util.*;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public class SimpleSingleDictParser implements SingleDictParser {
+
+    private Map<String, DictMapping> mapping = new HashMap<>();
+
+    private DictParserFormat sourceFormat = new DictParserFormat();
+
+    private DictParserFormat targetFormat = new DictParserFormat();
+
+    private DictParserFormatter formatter = new SimpleDictParserFormatter();
+
+    //设置DictionaryEntity作为配置
+    public void setDict(DictionaryEntity<? extends DictionaryItemEntity> dict,
+                        Function<DictionaryItemEntity, String> keyGetter,
+                        Function<DictionaryItemEntity, String> valueGetter,
+                        Function<DictionaryItemEntity, String> expressionGetter) {
+        dict.getItems().forEach(item -> addMapping(item, keyGetter, valueGetter, expressionGetter));
+    }
+
+    public DictParserFormat getTargetFormat() {
+        return targetFormat;
+    }
+
+    public DictParserFormat getSourceFormat() {
+        return sourceFormat;
+    }
+
+    private DictMapping addMapping(DictionaryItemEntity item,
+                                   Function<DictionaryItemEntity, String> keyGetter,
+                                   Function<DictionaryItemEntity, String> valueGetter,
+                                   Function<DictionaryItemEntity, String> expressionGetter) {
+        DictMapping dictMapping = new DictMapping();
+        dictMapping.setValue(valueGetter.apply(item));
+        dictMapping.setExpression(expressionGetter.apply(item));
+        if (item.getChildren() != null) {
+            dictMapping.setChildren(item.getChildren().stream()
+                    .map(DictionaryItemEntity.class::cast)
+                    .map(i -> addMapping(i, keyGetter, valueGetter, expressionGetter)).collect(Collectors.toList()));
+        }
+        String key = keyGetter.apply(item);
+        dictMapping.setKey(key);
+        mapping.put(key, dictMapping);
+        return dictMapping;
+    }
+
+    @Override
+    public Optional<String> parse(String value, Object context) {
+        if (value == null) return Optional.empty();
+        StringJoiner joiner = targetFormat.createJoiner();
+
+        List<DictMapping> dictMappings = formatter
+                .format(sourceFormat, value, (key, pattern) -> {
+                    DictMapping dictMapping = mapping.get(key);
+                    if (dictMapping == null) return null;
+                    dictMapping = dictMapping.clone();
+                    dictMapping.setDefaultVar(Collections.singletonMap("pattern", pattern));
+                    return dictMapping;
+                })
+                .stream()
+                .filter(Objects::nonNull)
+                .map(FormatterResult::getResult)
+                .collect(Collectors.toList());
+
+        Set<String> notAppendList = new HashSet<>();
+        List<String> mappingResult = dictMappings.stream()
+                .filter(Objects::nonNull)
+                // 过滤子节点
+                .peek(dictMapping -> dictMapping.filterChildren((mapping -> {
+                    String strVal = mapping.getValue();
+                    notAppendList.add(strVal); //子节点不拼接
+                    int index = dictMappings.indexOf(mappingOfValue(strVal));
+                    DictMapping tmp = null;
+                    if (-1 != index)
+                        tmp = dictMappings.get(index);
+                    if (null != tmp)
+                        mapping.setDefaultVar(tmp.getDefaultVar());
+                    return null != tmp;
+                })))
+                .filter(mapping -> !notAppendList.contains(mapping.getValue()))
+                //字典转为text
+                .map(dict -> dict.toString(context))
+                .collect(Collectors.toList());
+        mappingResult.forEach(joiner::add);
+        return Optional.ofNullable(joiner.toString());
+    }
+
+    public void setMapping(Map<String, DictMapping> mapping) {
+        this.mapping = mapping;
+    }
+
+    DictMapping mappingOfValue(String value) {
+        DictMapping mapping = new DictMapping();
+        mapping.setValue(value);
+        return mapping;
+    }
+
+    protected class DictMapping implements Serializable {
+        private String key;
+        private String value;
+        private String expression;
+        private String expressionLanguage = "spel";
+        private List<DictMapping> children;
+
+        private Map<String, Object> defaultVar;
+
+        public void setDefaultVar(Map<String, Object> defaultVar) {
+            this.defaultVar = defaultVar;
+        }
+
+        public Map<String, Object> getDefaultVar() {
+            return defaultVar;
+        }
+
+        @Override
+        public int hashCode() {
+            if (value == null) return 0;
+            return value.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj == null) return false;
+            return obj == this || hashCode() == obj.hashCode();
+        }
+
+        public String getKey() {
+            return key;
+        }
+
+        public void setKey(String key) {
+            this.key = key;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+
+        public List<DictMapping> getChildren() {
+            return children;
+        }
+
+        public String getExpression() {
+            return expression;
+        }
+
+        public void setExpression(String expression) {
+            this.expression = expression;
+        }
+
+        public void setExpressionLanguage(String expressionLanguage) {
+            this.expressionLanguage = expressionLanguage;
+        }
+
+        public String getExpressionLanguage() {
+            if (expressionLanguage == null) expressionLanguage = "spel";
+            return expressionLanguage;
+        }
+
+        public void setChildren(List<DictMapping> children) {
+            this.children = children;
+        }
+
+        public String toString(Function<DictMapping, String> getter) {
+            StringBuilder stringBuilder = new StringBuilder(getter.apply(this));
+            if (children != null) {
+                //根据getter 获取子节点的string
+                String childrenString = String.join(targetFormat.getChildSplitter(), children.stream()
+                        .map(mapping -> mapping.toString(getter)).collect(Collectors.toList()));
+
+                if (childrenString.isEmpty()) return stringBuilder.toString();
+                //拼接子节点
+                stringBuilder.append(targetFormat.getChildStartChar())
+                        .append(childrenString)
+                        .append(targetFormat.getChildEndChar());
+            }
+            return stringBuilder.toString();
+        }
+
+        public String toString(Object context) {
+            Function<DictMapping, String> textGetter =
+                    context == null ? DictMapping::getValue :
+                            dictMapping -> {
+                                if (dictMapping.getExpression() == null || dictMapping.getExpression().isEmpty())
+                                    return dictMapping.getValue();
+                                // 解析表达式
+                                Map<String, Object> var = new HashMap<>();
+                                if (dictMapping.getDefaultVar() != null) var.putAll(dictMapping.getDefaultVar());
+                                var.put("value", dictMapping.getValue());
+                                var.put("key", dictMapping.getKey());
+                                var.put("context", context);
+                                var.put("children", dictMapping.getChildren());
+                                try {
+                                    return ExpressionUtils.analytical(dictMapping.getExpression(), var, dictMapping.getExpressionLanguage());
+                                } catch (Exception e) {
+                                    throw new RuntimeException("analytical " + dictMapping.getExpressionLanguage() + " expression :" + dictMapping.getExpression() + " error", e);
+                                }
+                            };
+            return toString(textGetter);
+        }
+
+        public String toTextString() {
+            return toString(DictMapping::getValue);
+        }
+
+        public String toValueString() {
+            return toString(mapping -> String.valueOf(mapping.getValue()));
+        }
+
+        public DictMapping clone() {
+            DictMapping clone = new DictMapping();
+            clone.value = value;
+            clone.key = key;
+            clone.expression = expression;
+            clone.expressionLanguage = expressionLanguage;
+            if (children != null) {
+                clone.children = children.stream().map(DictMapping::clone).collect(Collectors.toList());
+            }
+            return clone;
+        }
+
+        public void filterChildren(Predicate<DictMapping> mappingPredicate) {
+            if (children != null) {
+                children = children.stream()
+                        .filter(mappingPredicate)
+                        .collect(Collectors.toList());
+                children.forEach(children -> children.filterChildren(mappingPredicate));
+            }
+        }
+    }
+}

+ 17 - 0
hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/main/java/org/hswebframework/web/service/dictionary/simple/parser/SingleDictParser.java

@@ -0,0 +1,17 @@
+package org.hswebframework.web.service.dictionary.simple.parser;
+
+import java.io.Serializable;
+import java.util.Optional;
+
+/**
+ * TODO 完成注释
+ *
+ * @author zhouhao
+ */
+public interface SingleDictParser extends Serializable {
+    Optional<String> parse(String target, Object context);
+
+    default Optional<String> parse(String target) {
+        return parse(target, null);
+    }
+}

+ 109 - 0
hsweb-system/hsweb-system-dictionary/hsweb-system-dictionary-service/hsweb-system-dictionary-service-simple/src/test/java/org/hswebframework/web/starter/dictionary/DictionaryParserTests.java

@@ -0,0 +1,109 @@
+/*
+ *  Copyright 2016 http://www.hswebframework.org
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *
+ */
+
+package org.hswebframework.web.starter.dictionary;
+
+import com.alibaba.fastjson.JSON;
+import org.hswebframework.web.entity.dictionary.SimpleDictionaryEntity;
+import org.hswebframework.web.entity.dictionary.SimpleDictionaryItemEntity;
+import org.hswebframework.web.service.dictionary.DictionaryParser;
+import org.hswebframework.web.service.dictionary.simple.SimpleDictionaryParser;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author
+ */
+public class DictionaryParserTests {
+
+    DictionaryParser<String> parser;
+
+    @Before
+    public void init() {
+        SimpleDictionaryParser<String> parser = new SimpleDictionaryParser<>();
+
+//        parser.getToTextParser().getTargetFormat().setSplitter("、");
+//        parser.getToValueParser().getSourceFormat().setSplitter("、");
+
+        SimpleDictionaryEntity dictionaryEntity = new SimpleDictionaryEntity();
+        String json = "[" +
+                "{'value':'1','text':'水果','children':" +
+                "[" +
+                "{'value':'101','text':'苹果'," +
+                "'children':[" +
+                "{'value':'10102','text':'红富士'}" +
+                ",{'value':'10103','text':'青苹果'}" +
+                //使用表达式进行解析
+                ",{'value':'10105','text':'其他苹果'" +
+                ",'textExpression':'${#value}[${#context[otherApple]}]'" +
+                ",'valueExpression':'${(#context.put(\\'otherApple\\',#pattern.split(\"[ \\\\[ \\\\]]\")[1])==null)?#value:#value}'" +
+                "}" +
+                "]}" +
+                ",{'value':'102','text':'梨子'}]" +
+                "}" +
+                ",{'value':'2','text':'蔬菜'}" +
+                "]";
+
+        List<SimpleDictionaryItemEntity> itemEntities = JSON.parseArray(json, SimpleDictionaryItemEntity.class);
+        dictionaryEntity.setItems(itemEntities);
+        parser.setDict(dictionaryEntity);
+        this.parser = parser;
+    }
+
+    //支持表达式
+    @Test
+    public void testParseExpression() {
+
+        String val = "1,2,101,10102,10105";
+
+        Map<String, Object> data = new HashMap<>();
+        data.put("otherApple", "其他苹果1号");
+
+        String text = parser
+                .valueToText(val, data)
+                .get();
+
+        System.out.println(text);
+        data.clear();
+        String parseVal = parser.textToValue(text, data)
+                .get();
+        System.out.println(parseVal);
+        System.out.println(data);
+
+    }
+
+    //普通的解析
+    @Test
+    public void testParseText() throws Exception {
+        String val = "1,101,10102,10103,2";
+
+        String text = parser.valueToText(val).get();
+
+        System.out.println(text);
+        String parsedVal = parser.textToValue(text).get();
+
+        System.out.println(parsedVal);
+        Assert.assertEquals(val, parsedVal);
+
+    }
+}