diff --git a/CHANGE_LOG.md b/CHANGE_LOG.md
index e65846e..4e571bf 100644
--- a/CHANGE_LOG.md
+++ b/CHANGE_LOG.md
@@ -374,3 +374,9 @@
| 序号 | 变更类型 | 说明 | 时间 | 备注 |
|:---|:-----|----------|:--------------------|:------------------------------------------------------|
| 1 | F | 修正数字匹配问题 | 2024-11-10 22:43:08 | https://github.com/houbb/sensitive-word/issues/84 |
+
+# release_0.23.0
+
+| 序号 | 变更类型 | 说明 | 时间 | 备注 |
+|:---|:-----|------------|:-------------------|:-----------|
+| 1 | A | 进一步拓展结果条件类 | 2024-12-8 21:13:44 | 支持同时指定多个条件 |
\ No newline at end of file
diff --git a/README.md b/README.md
index 59e3998..2572222 100644
--- a/README.md
+++ b/README.md
@@ -64,6 +64,10 @@
- 修正单个敏感词修改时,对应的格式处理问题
+### V0.23.0
+
+- 结果条件拓展支持 wordTags 和 chains
+
## 更多资料
### 敏感词控台
@@ -94,7 +98,7 @@
com.github.houbb
sensitive-word
- 0.22.0
+ 0.23.0
```
@@ -656,11 +660,13 @@ public class SensitiveWordService {
WordResultConditions 工具类可以获取匹配策略
-| 实现 | 说明 | 支持版本 |
-|:----|:------------|:--------|
-| alwaysTrue | 恒为真 | |
-| englishWordMatch | 英文单词全词匹配 | v0.13.0 |
-| englishWordNumMatch | 英文单词/数字全词匹配 | v0.20.0 |
+| 实现 | 说明 | 支持版本 |
+|:-------------------------------------------|:--------------------|:--------|
+| alwaysTrue | 恒为真 | |
+| englishWordMatch | 英文单词全词匹配 | v0.13.0 |
+| englishWordNumMatch | 英文单词/数字全词匹配 | v0.20.0 |
+| wordTags | 满足特定标签的,比如只关注【广告】标签 | v0.23.0 |
+| chains(IWordResultCondition ...conditions) | 支持指定多个条件,同时满足 | v0.23.0 |
## 使用例子
@@ -702,6 +708,81 @@ Assert.assertEquals("[]", wordList.toString());
当然可以根据需要实现更加复杂的策略。
+## wordTags 单词标签
+
+支持版本: `v0.23.0`
+
+我们可以只返回隶属于某一种标签的敏感词。
+
+我们指定了两个敏感词:商品、AV
+
+MyWordTag 是我们定义的一个敏感词标签实现:
+
+```java
+/**
+ * 自定义单词标签
+ * @since 0.23.0
+ */
+public class MyWordTag extends AbstractWordTag {
+
+ private static Map> dataMap;
+
+ static {
+ dataMap = new HashMap<>();
+ dataMap.put("商品", buildSet("广告", "中文"));
+ dataMap.put("AV", buildSet("色情", "单词", "英文"));
+ }
+
+ private static Set buildSet(String... tags) {
+ Set set = new HashSet<>();
+ for(String tag : tags) {
+ set.add(tag);
+ }
+ return set;
+ }
+
+ @Override
+ protected Set doGetTag(String word) {
+ return dataMap.get(word);
+ }
+
+}
+```
+
+测试用例如下,我们模拟了两个不同的实现类,每一个关注的单词标签不同。
+
+```java
+// 只关心SE情
+SensitiveWordBs sensitiveWordBsYellow = SensitiveWordBs.newInstance()
+ .wordDeny(new IWordDeny() {
+ @Override
+ public List deny() {
+ return Arrays.asList("商品", "AV");
+ }
+ })
+ .wordAllow(WordAllows.empty())
+ .wordTag(new MyWordTag())
+ .wordResultCondition(WordResultConditions.wordTags(Arrays.asList("色情")))
+ .init();
+
+// 只关心广告
+SensitiveWordBs sensitiveWordBsAd = SensitiveWordBs.newInstance()
+ .wordDeny(new IWordDeny() {
+ @Override
+ public List deny() {
+ return Arrays.asList("商品", "AV");
+ }
+ })
+ .wordAllow(WordAllows.empty())
+ .wordTag(new MyWordTag())
+ .wordResultCondition(WordResultConditions.wordTags(Arrays.asList("广告")))
+ .init();
+
+final String text = "这些 AV 商品什么价格?";
+Assert.assertEquals("[AV]", sensitiveWordBsYellow.findAll(text).toString());
+Assert.assertEquals("[商品]", sensitiveWordBsAd.findAll(text).toString());
+```
+
# 忽略字符
## 说明
diff --git a/pom.xml b/pom.xml
index 9810c4c..d1ea701 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.github.houbb
sensitive-word
- 0.22.0
+ 0.23.0
diff --git a/release.bat b/release.bat
index 5563e59..9d85ebd 100644
--- a/release.bat
+++ b/release.bat
@@ -10,9 +10,9 @@ ECHO "============================= RELEASE START..."
:: 版本号信息(需要手动指定)
:::: 旧版本名称
-SET version=0.22.0
+SET version=0.23.0
:::: 新版本名称
-SET newVersion=0.23.0
+SET newVersion=0.24.0
:::: 组织名称
SET groupName=com.github.houbb
:::: 项目名称
diff --git a/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditionInit.java b/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditionInit.java
new file mode 100644
index 0000000..24c77fd
--- /dev/null
+++ b/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditionInit.java
@@ -0,0 +1,43 @@
+package com.github.houbb.sensitive.word.support.resultcondition;
+
+import com.github.houbb.heaven.support.pipeline.Pipeline;
+import com.github.houbb.heaven.support.pipeline.impl.DefaultPipeline;
+import com.github.houbb.sensitive.word.api.IWordContext;
+import com.github.houbb.sensitive.word.api.IWordResult;
+import com.github.houbb.sensitive.word.api.IWordResultCondition;
+import com.github.houbb.sensitive.word.constant.enums.WordValidModeEnum;
+
+import java.util.List;
+
+/**
+ * 结果条件的的初始化类
+ *
+ * @since 0.23.0
+ */
+public abstract class WordResultConditionInit extends AbstractWordResultCondition {
+
+ /**
+ * 初始化列表
+ *
+ * @param pipeline 当前列表泳道
+ * @since 0.0.13
+ */
+ protected abstract void init(final Pipeline pipeline);
+
+ @Override
+ protected boolean doMatch(IWordResult wordResult, String text, WordValidModeEnum modeEnum, IWordContext context) {
+ Pipeline pipeline = new DefaultPipeline<>();
+ this.init(pipeline);
+ List conditionList = pipeline.list();
+
+ // 必须满足所有
+ for(IWordResultCondition wordResultCondition : conditionList) {
+ if(!wordResultCondition.match(wordResult, text, modeEnum, context)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+}
diff --git a/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditionWordTagsMatch.java b/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditionWordTagsMatch.java
new file mode 100644
index 0000000..730c706
--- /dev/null
+++ b/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditionWordTagsMatch.java
@@ -0,0 +1,52 @@
+package com.github.houbb.sensitive.word.support.resultcondition;
+
+import com.github.houbb.heaven.util.common.ArgUtil;
+import com.github.houbb.heaven.util.util.CollectionUtil;
+import com.github.houbb.sensitive.word.api.IWordContext;
+import com.github.houbb.sensitive.word.api.IWordResult;
+import com.github.houbb.sensitive.word.api.IWordTag;
+import com.github.houbb.sensitive.word.constant.enums.WordValidModeEnum;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * 结果标签匹配的条件
+ *
+ * @since 0.23.0
+ */
+public class WordResultConditionWordTagsMatch extends AbstractWordResultCondition {
+
+ /**
+ * 指定标签的集合
+ */
+ private final Collection tags;
+
+ public WordResultConditionWordTagsMatch(Collection tags) {
+ ArgUtil.notEmpty(tags, "tags");
+
+ this.tags = tags;
+ }
+
+ @Override
+ protected boolean doMatch(IWordResult wordResult, String text, WordValidModeEnum modeEnum, IWordContext context) {
+ // 判断对应的标签
+ String word = text.substring(wordResult.startIndex(), wordResult.endIndex());
+ final IWordTag wordTag = context.wordTag();
+ Set wordTags = wordTag.getTag(word);
+
+ // 在指定的 tag 中
+ if(CollectionUtil.isEmpty(wordTags)) {
+ return false;
+ }
+
+ for(String tag : tags) {
+ if(wordTags.contains(tag)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
diff --git a/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditions.java b/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditions.java
index 8bafaa4..00742a5 100644
--- a/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditions.java
+++ b/src/main/java/com/github/houbb/sensitive/word/support/resultcondition/WordResultConditions.java
@@ -1,7 +1,12 @@
package com.github.houbb.sensitive.word.support.resultcondition;
+import com.github.houbb.heaven.support.pipeline.Pipeline;
+import com.github.houbb.heaven.util.common.ArgUtil;
+import com.github.houbb.heaven.util.util.ArrayUtil;
import com.github.houbb.sensitive.word.api.IWordResultCondition;
+import java.util.List;
+
/**
* 匹配结果工具类
*
@@ -35,4 +40,39 @@ public final class WordResultConditions {
return new WordResultConditionEnglishWordNumMatch();
}
+ /**
+ * 单词标签
+ * @param tags 标签列表
+ * @return 结果
+ * @since 0.23.0
+ */
+ public static IWordResultCondition wordTags(List tags) {
+ ArgUtil.notEmpty(tags, "tags");
+
+ return new WordResultConditionWordTagsMatch(tags);
+ }
+
+ /**
+ * 链式调用,支持同时满足多个条件
+ *
+ * @since 0.23.0
+ * @param condition 条件
+ * @param others 其他条件
+ * @return 结果
+ */
+ public static IWordResultCondition chains(final IWordResultCondition condition, final IWordResultCondition ... others) {
+ return new WordResultConditionInit() {
+ @Override
+ protected void init(Pipeline pipeline) {
+ pipeline.addLast(condition);
+ if(ArrayUtil.isNotEmpty(others)) {
+ for(IWordResultCondition other : others) {
+ pipeline.addLast(other);
+ }
+ }
+ }
+ };
+ }
+
+
}
diff --git a/src/test/java/com/github/houbb/sensitive/word/support/resultcondition/MyWordTag.java b/src/test/java/com/github/houbb/sensitive/word/support/resultcondition/MyWordTag.java
new file mode 100644
index 0000000..9d6cee6
--- /dev/null
+++ b/src/test/java/com/github/houbb/sensitive/word/support/resultcondition/MyWordTag.java
@@ -0,0 +1,37 @@
+package com.github.houbb.sensitive.word.support.resultcondition;
+
+import com.github.houbb.sensitive.word.support.tag.AbstractWordTag;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 自定义单词标签
+ * @since 0.23.0
+ */
+public class MyWordTag extends AbstractWordTag {
+
+ private static Map> dataMap;
+
+ static {
+ dataMap = new HashMap<>();
+ dataMap.put("商品", buildSet("广告", "中文"));
+ dataMap.put("AV", buildSet("色情", "单词", "英文"));
+ }
+
+ private static Set buildSet(String... tags) {
+ Set set = new HashSet<>();
+ for(String tag : tags) {
+ set.add(tag);
+ }
+ return set;
+ }
+
+ @Override
+ protected Set doGetTag(String word) {
+ return dataMap.get(word);
+ }
+
+}
diff --git a/src/test/java/com/github/houbb/sensitive/word/support/resultcondition/WordTagsTest.java b/src/test/java/com/github/houbb/sensitive/word/support/resultcondition/WordTagsTest.java
new file mode 100644
index 0000000..1dbc9d6
--- /dev/null
+++ b/src/test/java/com/github/houbb/sensitive/word/support/resultcondition/WordTagsTest.java
@@ -0,0 +1,53 @@
+package com.github.houbb.sensitive.word.support.resultcondition;
+
+import com.github.houbb.sensitive.word.api.IWordDeny;
+import com.github.houbb.sensitive.word.bs.SensitiveWordBs;
+import com.github.houbb.sensitive.word.support.allow.WordAllows;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class WordTagsTest {
+
+
+ /**
+ * 是否包含
+ *
+ * @since 0.23.0
+ */
+ @Test
+ public void wordTagsTest() {
+ // 只关心SE情
+ SensitiveWordBs sensitiveWordBsYellow = SensitiveWordBs.newInstance()
+ .wordDeny(new IWordDeny() {
+ @Override
+ public List deny() {
+ return Arrays.asList("商品", "AV");
+ }
+ })
+ .wordAllow(WordAllows.empty())
+ .wordTag(new MyWordTag())
+ .wordResultCondition(WordResultConditions.wordTags(Arrays.asList("色情")))
+ .init();
+
+ // 只关心广告
+ SensitiveWordBs sensitiveWordBsAd = SensitiveWordBs.newInstance()
+ .wordDeny(new IWordDeny() {
+ @Override
+ public List deny() {
+ return Arrays.asList("商品", "AV");
+ }
+ })
+ .wordAllow(WordAllows.empty())
+ .wordTag(new MyWordTag())
+ .wordResultCondition(WordResultConditions.wordTags(Arrays.asList("广告")))
+ .init();
+
+ final String text = "这些 AV 商品什么价格?";
+ Assert.assertEquals("[AV]", sensitiveWordBsYellow.findAll(text).toString());
+ Assert.assertEquals("[商品]", sensitiveWordBsAd.findAll(text).toString());
+ }
+
+}