[Add] Framework-API 添加 BotCodeFunction 用于描述 BotCode;

[Add] BotCodeFunction 添加用于描述 BotCode 的功能描述接口;
[Add] StandardBotCodeFunction, CustomBotCodeFunction 添加一个受到 ContentGrabbingJi 内部支持的 Function Enum, 和一个可用于创建平台特有, 或补充功能用的 Function 自定义实现;
[Change] AbstractBotCode, AbstractBotCodeTest 适配修改;
[Change] BotCode 适配修改;
[Change] BasicBotCode, BasicBotCodeTest 适配修改;
[Change] MessageChainTest 适配修改;
This commit is contained in:
LamGC 2020-12-18 20:06:43 +08:00
parent 5ef90a1756
commit 2ea0c08149
Signed by: LamGC
GPG Key ID: 6C5AE2A913941E1D
9 changed files with 199 additions and 53 deletions

View File

@ -20,6 +20,7 @@ package net.lamgc.cgj.bot.framework.base;
import net.lamgc.cgj.bot.framework.Platform; import net.lamgc.cgj.bot.framework.Platform;
import net.lamgc.cgj.bot.framework.message.AbstractBotCode; import net.lamgc.cgj.bot.framework.message.AbstractBotCode;
import net.lamgc.cgj.bot.framework.message.BotCode; import net.lamgc.cgj.bot.framework.message.BotCode;
import net.lamgc.cgj.bot.framework.message.BotCodeFunction;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
@ -34,16 +35,16 @@ public class BasicBotCode extends AbstractBotCode {
private final static Platform PLATFORM = new Platform("ContentGrabbingJi", "CGJ"); private final static Platform PLATFORM = new Platform("ContentGrabbingJi", "CGJ");
public BasicBotCode(String functionName) { public BasicBotCode(BotCodeFunction function) {
super(functionName); super(function);
} }
public BasicBotCode(BotCode botCode) { public BasicBotCode(BotCode botCode) {
super(botCode); super(botCode);
} }
public BasicBotCode(String functionName, Map<String, String> functionProperties) { public BasicBotCode(BotCodeFunction function, Map<String, String> functionProperties) {
super(functionName, functionProperties); super(function, functionProperties);
} }
@Override @Override
@ -53,7 +54,7 @@ public class BasicBotCode extends AbstractBotCode {
@Override @Override
public String contentToString() { public String contentToString() {
StringBuilder builder = new StringBuilder('[' + getFunctionName()); StringBuilder builder = new StringBuilder('[' + getFunction().getFunctionName());
if (getPropertiesKeys().size() == 0) { if (getPropertiesKeys().size() == 0) {
return builder.append(']').toString(); return builder.append(']').toString();
} else { } else {

View File

@ -20,6 +20,8 @@ package net.lamgc.cgj.bot.framework.base;
import net.lamgc.cgj.bot.framework.Platform; import net.lamgc.cgj.bot.framework.Platform;
import net.lamgc.cgj.bot.framework.message.AbstractBotCode; import net.lamgc.cgj.bot.framework.message.AbstractBotCode;
import net.lamgc.cgj.bot.framework.message.BotCode; import net.lamgc.cgj.bot.framework.message.BotCode;
import net.lamgc.cgj.bot.framework.message.BotCodeFunction;
import net.lamgc.cgj.bot.framework.message.StandardBotCodeFunction;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
@ -33,7 +35,7 @@ public class BasicBotCodeTest {
@Test @Test
public void getPlatform() { public void getPlatform() {
BotCode botCode = new BasicBotCode("test"); BotCode botCode = new BasicBotCode(StandardBotCodeFunction.AT);
Assert.assertEquals("ContentGrabbingJi", botCode.getPlatform().getPlatformName()); Assert.assertEquals("ContentGrabbingJi", botCode.getPlatform().getPlatformName());
Assert.assertEquals("CGJ", botCode.getPlatform().getPlatformIdentify()); Assert.assertEquals("CGJ", botCode.getPlatform().getPlatformIdentify());
@ -41,9 +43,9 @@ public class BasicBotCodeTest {
@Test @Test
public void contentToStringWithoutParameter() { public void contentToStringWithoutParameter() {
BotCode botCode = new BasicBotCode("test"); BotCode botCode = new BasicBotCode(StandardBotCodeFunction.FILE);
Assert.assertEquals("[test]", botCode.contentToString()); Assert.assertEquals("[file]", botCode.contentToString());
} }
@Test @Test
@ -53,16 +55,16 @@ public class BasicBotCodeTest {
argumentsMap.put("arg2", "Hello World."); argumentsMap.put("arg2", "Hello World.");
argumentsMap.put("arg3", "测试"); argumentsMap.put("arg3", "测试");
BotCode botCode = new BasicBotCode("test", argumentsMap); BotCode botCode = new BasicBotCode(StandardBotCodeFunction.EMOJI, argumentsMap);
Assert.assertEquals("[test:arg3=%E6%B5%8B%E8%AF%95&arg2=Hello+World.&arg1=value1]", botCode.contentToString()); Assert.assertEquals("[emoji:arg3=%E6%B5%8B%E8%AF%95&arg2=Hello+World.&arg1=value1]", botCode.contentToString());
} }
@Test @Test
public void createInstanceByBotCode() { public void createInstanceByBotCode() {
class TestBotCode extends AbstractBotCode { class TestBotCode extends AbstractBotCode {
public TestBotCode(String functionName, Map<String, String> functionProperties) { public TestBotCode(BotCodeFunction function, Map<String, String> functionProperties) {
super(functionName, functionProperties); super(function, functionProperties);
} }
@Override @Override
@ -81,10 +83,10 @@ public class BasicBotCodeTest {
argumentsMap.put("arg2", "Hello World."); argumentsMap.put("arg2", "Hello World.");
argumentsMap.put("arg3", "测试"); argumentsMap.put("arg3", "测试");
BotCode expectBotCode = new TestBotCode("function", argumentsMap); BotCode expectBotCode = new TestBotCode(StandardBotCodeFunction.AUDIO, argumentsMap);
BotCode botCode = new BasicBotCode(expectBotCode); BotCode botCode = new BasicBotCode(expectBotCode);
Assert.assertEquals(expectBotCode.getFunctionName(), botCode.getFunctionName()); Assert.assertEquals(expectBotCode.getFunction(), botCode.getFunction());
Assert.assertTrue(expectBotCode.getPropertiesKeys().containsAll(botCode.getPropertiesKeys())); Assert.assertTrue(expectBotCode.getPropertiesKeys().containsAll(botCode.getPropertiesKeys()));
for (String key : expectBotCode.getPropertiesKeys()) { for (String key : expectBotCode.getPropertiesKeys()) {

View File

@ -29,11 +29,11 @@ import java.util.*;
*/ */
public abstract class AbstractBotCode implements BotCode { public abstract class AbstractBotCode implements BotCode {
private String functionName; private BotCodeFunction function;
private final Map<String, String> functionProperties = new Hashtable<>(); private final Map<String, String> functionProperties = new Hashtable<>();
public AbstractBotCode(String functionName) { public AbstractBotCode(BotCodeFunction function) {
this(functionName, null); this(function, null);
} }
/** /**
@ -41,19 +41,19 @@ public abstract class AbstractBotCode implements BotCode {
* @param botCode 待转换的 BotCode. * @param botCode 待转换的 BotCode.
*/ */
public AbstractBotCode(BotCode botCode) { public AbstractBotCode(BotCode botCode) {
this(botCode.getFunctionName(), CollectionUtils.toMap(botCode.getPropertiesKeys(), botCode::getProperty)); this(botCode.getFunction(), CollectionUtils.toMap(botCode.getPropertiesKeys(), botCode::getProperty));
} }
/** /**
* 根据给定的功能名和参数 Map 构造 BotCode. * 根据给定的功能名和参数 Map 构造 BotCode.
* @param functionName 功能名 * @param function 功能名
* @param functionProperties 参数集 Map. 如果不需要可传入 null. * @param functionProperties 参数集 Map. 如果不需要可传入 null.
*/ */
public AbstractBotCode(String functionName, Map<String, String> functionProperties) { public AbstractBotCode(BotCodeFunction function, Map<String, String> functionProperties) {
if (Strings.isNullOrEmpty(functionName)) { if (Strings.isNullOrEmpty(function.getFunctionName())) {
throw new IllegalArgumentException("functionName is null or empty"); throw new IllegalArgumentException("functionName is null or empty");
} }
this.functionName = functionName; this.function = function;
if(functionProperties != null && !functionProperties.isEmpty()) { if(functionProperties != null && !functionProperties.isEmpty()) {
this.functionProperties.putAll(functionProperties); this.functionProperties.putAll(functionProperties);
} }
@ -73,7 +73,7 @@ public abstract class AbstractBotCode implements BotCode {
} }
return this.getClass().getSimpleName() + '@' + Integer.toHexString(this.hashCode()) + '{' + return this.getClass().getSimpleName() + '@' + Integer.toHexString(this.hashCode()) + '{' +
"Platform=" + getPlatform() + ", " + "Platform=" + getPlatform() + ", " +
"functionName='" + functionName + '\'' + "functionName='" + function.getFunctionName() + '\'' +
", functionProperties={" + mapString.toString() + '}' + ", functionProperties={" + mapString.toString() + '}' +
'}'; '}';
} }
@ -83,17 +83,17 @@ public abstract class AbstractBotCode implements BotCode {
* @return 返回功能函数名. * @return 返回功能函数名.
*/ */
@Override @Override
public String getFunctionName() { public BotCodeFunction getFunction() {
return functionName; return function;
} }
/** /**
* 设置功能函数名 * 设置功能函数名
* @param functionName 新的功能函数名. * @param function 新的功能函数名.
*/ */
@Override @Override
public void setFunctionName(String functionName) { public void setFunction(BotCodeFunction function) {
this.functionName = functionName; this.function = function;
} }
/** /**

View File

@ -38,13 +38,13 @@ public interface BotCode extends Message {
* 取功能函数名. * 取功能函数名.
* @return 返回功能函数名. * @return 返回功能函数名.
*/ */
String getFunctionName(); BotCodeFunction getFunction();
/** /**
* 设置功能函数名 * 设置功能函数名
* @param functionName 新的功能函数名. * @param function 新的功能函数名.
*/ */
void setFunctionName(String functionName); void setFunction(BotCodeFunction function);
/** /**
* 设置功能参数 * 设置功能参数

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2020 LamGC
*
* ContentGrabbingJi is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* ContentGrabbingJi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.lamgc.cgj.bot.framework.message;
/**
* BotCode 功能名.
*
* <p> 功能码的功能分为两种: 头部功能(HeaderFunction) 内容功能(BodyFunction).
* <p> 头部功能不属于内容的一部分, 它决定了消息的属性, 影响了整条消息的性质(例如消息以匿名形式发送, 语音独占消息等).
*
*
* @see BotCode
* @author LamGC
*/
public interface BotCodeFunction {
/**
* 获取 BotCode 功能名.
* @return 返回功能名.
*/
String getFunctionName();
/**
* 是否作为头部功能存在.
*
* @return 如果该功能属于头部功能的一种, 返回 {@code true}.
*/
boolean headerFunction();
}

View File

@ -0,0 +1,27 @@
package net.lamgc.cgj.bot.framework.message;
/**
* 自定义 BotCode 方法.
* @author LamGC
*/
public class CustomBotCodeFunction implements BotCodeFunction {
private final String name;
private final boolean headerFunction;
public CustomBotCodeFunction(String name, boolean isHeaderFunction) {
this.name = name;
headerFunction = isHeaderFunction;
}
@Override
public String getFunctionName() {
return name;
}
@Override
public boolean headerFunction() {
return headerFunction;
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2020 LamGC
*
* ContentGrabbingJi is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* ContentGrabbingJi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.lamgc.cgj.bot.framework.message;
/**
* ContentGrabbingJi 完整支持的功能码功能名.
* @see BotCode
* @see net.lamgc.cgj.bot.framework.message.BotCodeFunction
* @author LamGC
*/
public enum StandardBotCodeFunction implements BotCodeFunction {
/**
* 提醒某人.
*/
AT("at", false),
/**
* 图片.
*/
IMAGE("image", false),
/**
* Emoji 表情.
*/
EMOJI("emoji", false),
/**
* 音频.
*/
AUDIO("audio", true),
/**
* 文件.
*/
FILE("file", true),
;
private final String functionName;
private final boolean headerFunction;
StandardBotCodeFunction(String functionName, boolean headerFunction) {
this.functionName = functionName;
this.headerFunction = headerFunction;
}
@Override
public String getFunctionName() {
return this.functionName;
}
@Override
public boolean headerFunction() {
return headerFunction;
}
}

View File

@ -33,27 +33,27 @@ public class AbstractBotCodeTest {
@Test @Test
public void createBotCodeWithoutParameterTest() { public void createBotCodeWithoutParameterTest() {
final String functionName = "function"; final BotCodeFunction function = new CustomBotCodeFunction("function", false);
BotCode botCode = new TestBotCode(functionName); BotCode botCode = new TestBotCode(function);
Assert.assertEquals(functionName, botCode.getFunctionName()); Assert.assertEquals(function, botCode.getFunction());
Assert.assertNotNull(botCode.getPropertiesKeys()); Assert.assertNotNull(botCode.getPropertiesKeys());
Assert.assertEquals(0, botCode.getPropertiesKeys().size()); Assert.assertEquals(0, botCode.getPropertiesKeys().size());
botCode = new TestBotCode(functionName, new HashMap<>()); botCode = new TestBotCode(function, new HashMap<>());
Assert.assertEquals(functionName, botCode.getFunctionName()); Assert.assertEquals(function, botCode.getFunction());
Assert.assertNotNull(botCode.getPropertiesKeys()); Assert.assertNotNull(botCode.getPropertiesKeys());
Assert.assertEquals(0, botCode.getPropertiesKeys().size()); Assert.assertEquals(0, botCode.getPropertiesKeys().size());
} }
@Test @Test
public void createBotCodeWithParameterTest() { public void createBotCodeWithParameterTest() {
final String functionName = "function"; final BotCodeFunction function = new CustomBotCodeFunction("function", false);
final Map<String, String> argumentsMap = new HashMap<>(); final Map<String, String> argumentsMap = new HashMap<>();
argumentsMap.put("arg1", "value1"); argumentsMap.put("arg1", "value1");
argumentsMap.put("arg2", "value2"); argumentsMap.put("arg2", "value2");
BotCode botCode = new TestBotCode(functionName, argumentsMap); BotCode botCode = new TestBotCode(function, argumentsMap);
Assert.assertEquals(functionName, botCode.getFunctionName()); Assert.assertEquals(function, botCode.getFunction());
Assert.assertTrue(argumentsMap.keySet().containsAll(botCode.getPropertiesKeys())); Assert.assertTrue(argumentsMap.keySet().containsAll(botCode.getPropertiesKeys()));
for (String key : argumentsMap.keySet()) { for (String key : argumentsMap.keySet()) {
@ -70,37 +70,37 @@ public class AbstractBotCodeTest {
@Test @Test
public void createByBotCodeTest() { public void createByBotCodeTest() {
final String functionName = "function"; final BotCodeFunction function = new CustomBotCodeFunction("function", false);
final Map<String, String> argumentsMap = new HashMap<>(); final Map<String, String> argumentsMap = new HashMap<>();
argumentsMap.put("arg1", "value1"); argumentsMap.put("arg1", "value1");
argumentsMap.put("arg2", "value2"); argumentsMap.put("arg2", "value2");
BotCode botCode = new TestBotCode(functionName, argumentsMap); BotCode botCode = new TestBotCode(function, argumentsMap);
BotCode newBotCode = new TestBotCode(botCode); BotCode newBotCode = new TestBotCode(botCode);
Assert.assertEquals(botCode.getFunctionName(), newBotCode.getFunctionName()); Assert.assertEquals(botCode.getFunction(), newBotCode.getFunction());
Assert.assertEquals(botCode.getPropertiesKeys().size(), newBotCode.getPropertiesKeys().size()); Assert.assertEquals(botCode.getPropertiesKeys().size(), newBotCode.getPropertiesKeys().size());
Assert.assertTrue(botCode.getPropertiesKeys().containsAll(newBotCode.getPropertiesKeys())); Assert.assertTrue(botCode.getPropertiesKeys().containsAll(newBotCode.getPropertiesKeys()));
} }
@Test(expected = UnsupportedOperationException.class) @Test(expected = UnsupportedOperationException.class)
public void propertiesKeysUnmodifiedTest() { public void propertiesKeysUnmodifiedTest() {
final String functionName = "function"; final BotCodeFunction function = new CustomBotCodeFunction("function", false);
final Map<String, String> argumentsMap = new HashMap<>(); final Map<String, String> argumentsMap = new HashMap<>();
argumentsMap.put("arg1", "value1"); argumentsMap.put("arg1", "value1");
argumentsMap.put("arg2", "value2"); argumentsMap.put("arg2", "value2");
BotCode botCode = new TestBotCode(functionName, argumentsMap); BotCode botCode = new TestBotCode(function, argumentsMap);
botCode.getPropertiesKeys().clear(); botCode.getPropertiesKeys().clear();
} }
@Test @Test
public void functionNameChangeTest() { public void functionNameChangeTest() {
final String newFunctionName = "functionB"; final BotCodeFunction newFunction = new CustomBotCodeFunction("functionB", false);
BotCode botCode = new TestBotCode("functionA"); BotCode botCode = new TestBotCode("functionA");
botCode.setFunctionName(newFunctionName); botCode.setFunction(newFunction);
Assert.assertEquals(newFunctionName, botCode.getFunctionName()); Assert.assertEquals(newFunction, botCode.getFunction());
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -139,15 +139,19 @@ public class AbstractBotCodeTest {
private final static class TestBotCode extends AbstractBotCode { private final static class TestBotCode extends AbstractBotCode {
public TestBotCode(String functionName) { public TestBotCode(String functionName) {
super(functionName); this(new CustomBotCodeFunction(functionName, false));
}
public TestBotCode(BotCodeFunction function) {
super(function);
} }
public TestBotCode(BotCode botCode) { public TestBotCode(BotCode botCode) {
super(botCode); super(botCode);
} }
public TestBotCode(String functionName, Map<String, String> functionProperties) { public TestBotCode(BotCodeFunction function, Map<String, String> functionProperties) {
super(functionName, functionProperties); super(function, functionProperties);
} }
@Override @Override

View File

@ -75,7 +75,7 @@ public class MessageChainTest {
@Test @Test
public void plusBotCodeTest() { public void plusBotCodeTest() {
MessageChain chain = new MessageChain("BotCode: "); MessageChain chain = new MessageChain("BotCode: ");
chain.plus(new AbstractBotCode("test") { chain.plus(new AbstractBotCode(StandardBotCodeFunction.AT) {
@Override @Override
public Platform getPlatform() { public Platform getPlatform() {
return null; return null;
@ -83,11 +83,11 @@ public class MessageChainTest {
@Override @Override
public String contentToString() { public String contentToString() {
return "[test:arg=value]"; return "[at:arg=value]";
} }
}); });
chain.plus("."); chain.plus(".");
Assert.assertEquals("BotCode: [test:arg=value].", chain.contentToString()); Assert.assertEquals("BotCode: [at:arg=value].", chain.contentToString());
} }
@Test @Test