Compare commits

..

No commits in common. "50bd5f255da2bc28de8044cea0b2fe16a8c67070" and "b356735d727fe32e0827bf00566444db6a9213bb" have entirely different histories.

19 changed files with 375 additions and 1794 deletions

View File

@ -44,11 +44,8 @@ public class ApplicationTest__01 {
}
// Step.2
// String targetContent = Files.readString(Path.of(processJSONFile), StandardCharsets.UTF_8);
// List<Object> list = JSON.parseArray(targetContent);
// 通过 key 限制变量范围
List<Object> list = FormatUtil.loadJSON(processJSONFile);
String targetContent = Files.readString(Path.of(processJSONFile), StandardCharsets.UTF_8);
List<Object> list = JSON.parseArray(targetContent);
String templateContent = Files.readString(Path.of(inputTemplateData), StandardCharsets.UTF_8);
ConfigDocument document = JSON.parseObject(templateContent, ConfigDocument.class);
@ -57,7 +54,7 @@ public class ApplicationTest__01 {
System.out.println(result);
for(Object obj: list) {
Map<String, String> map = JSON.parseObject(JSON.toJSONString(obj), Map.class);
result = FormatUtil.stealBeamsAndReplacePillars(result, map, true, false, false);
result = FormatUtil.stealBeamsAndReplacePillars(result, map);
}
// Step.3

View File

@ -44,11 +44,8 @@ public class ApplicationTest__03 {
}
// Step.2
// String targetContent = Files.readString(Path.of(processJSONFile), StandardCharsets.UTF_8);
// List<Object> list = JSON.parseArray(targetContent);
// 通过 key 限制变量范围
List<Object> list = FormatUtil.loadJSON(processJSONFile);
String targetContent = Files.readString(Path.of(processJSONFile), StandardCharsets.UTF_8);
List<Object> list = JSON.parseArray(targetContent);
String templateContent = Files.readString(Path.of(inputTemplateData), StandardCharsets.UTF_8);
ConfigDocument document = JSON.parseObject(templateContent, ConfigDocument.class);

View File

@ -270,10 +270,6 @@ public class EnhancedConfigProcessor {
// 添加上下文和循环索引
params.put("context", context);
params.put("loopIndex", loopIndex);
// 参数
value = params.get("params").toString();
params.remove("params");
// 调用工具函数
result = callFormatUtilFunction(functionName, value, params);

View File

@ -12,97 +12,39 @@ import java.util.Map;
/**
* 模板文件工具类
* 负责从文件系统或类路径加载模板文件支持缓存机制提高性能
*
* <p>该类提供了以下功能</p>
* <ul>
* <li>从类路径加载模板文件</li>
* <li>从文件系统加载模板文件</li>
* <li>智能识别路径前缀自动选择加载方式</li>
* <li>模板内容缓存避免重复读取文件</li>
* <li>缓存管理功能</li>
* </ul>
*
* <p>使用示例</p>
* <pre>
* // 从类路径加载
* String template1 = TemplateFileLoader.loadTemplate("classpath:templates/default.html");
* // 从文件系统加载
* String template2 = TemplateFileLoader.loadTemplate("file:/opt/templates/default.html");
* // 默认从类路径加载
* String template3 = TemplateFileLoader.loadTemplate("templates/default.html");
* </pre>
*
* @author 岳佳君
* @version 1.0
* 负责从文件系统或类路径加载模板文件
*/
@Slf4j
public class TemplateFileLoader {
/**
* 默认模板目录路径
*/
private static final String DEFAULT_TEMPLATE_DIR = "templates/";
/**
* 类路径前缀标识符
*/
private static final String CLASS_PATH_PREFIX = "classpath:";
/**
* 文件系统路径前缀标识符
*/
private static final String FILE_PATH_PREFIX = "file:";
/**
* 模板缓存使用HashMap存储已加载的模板内容
* Key: 缓存键包含路径前缀和模板路径
* Value: 模板文件内容
*/
// 模板缓存
private static final Map<String, String> TEMPLATE_CACHE = new HashMap<>();
/**
* 从类路径加载模板文件
*
* <p>该方法会首先检查缓存中是否已存在该模板如果存在则直接返回缓存内容
* 否则从类路径读取文件内容并存入缓存</p>
*
* @param templatePath 模板文件路径可以是相对路径或绝对路径
* 相对路径相对于类路径根目录
* @return 模板文件的内容字符串
* @throws IOException 当模板文件未找到或读取失败时抛出
* @throws IllegalArgumentException 当templatePath为null或空字符串时抛出
*/
public static String loadTemplateFromClasspath(String templatePath) throws IOException {
// 参数校验
if (templatePath == null || templatePath.trim().isEmpty()) {
throw new IllegalArgumentException("模板路径不能为空");
}
String cacheKey = CLASS_PATH_PREFIX + templatePath;
// 检查缓存中是否已存在该模板
if (TEMPLATE_CACHE.containsKey(cacheKey)) {
log.debug("从缓存加载类路径模板: {}", templatePath);
return TEMPLATE_CACHE.get(cacheKey);
}
try {
// 处理路径格式确保以"/"开头
// 从类路径加载
String fullPath = templatePath.startsWith("/") ? templatePath : "/" + templatePath;
java.io.InputStream inputStream = TemplateFileLoader.class.getResourceAsStream(fullPath);
// 检查文件是否存在
if (inputStream == null) {
throw new IOException("模板文件未找到: " + templatePath);
}
// 读取文件内容并转换为字符串
String content = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
// 存入缓存
TEMPLATE_CACHE.put(cacheKey, content);
log.info("从类路径加载模板成功: {}", templatePath);
log.info("从类路径加载模板: {}", templatePath);
return content;
} catch (IOException e) {
@ -113,43 +55,22 @@ public class TemplateFileLoader {
/**
* 从文件系统加载模板文件
*
* <p>该方法会首先检查缓存中是否已存在该模板如果存在则直接返回缓存内容
* 否则从文件系统读取文件内容并存入缓存</p>
*
* @param filePath 模板文件的绝对路径或相对路径相对于当前工作目录
* @return 模板文件的内容字符串
* @throws IOException 当模板文件不存在或读取失败时抛出
* @throws IllegalArgumentException 当filePath为null或空字符串时抛出
*/
public static String loadTemplateFromFileSystem(String filePath) throws IOException {
// 参数校验
if (filePath == null || filePath.trim().isEmpty()) {
throw new IllegalArgumentException("文件路径不能为空");
}
String cacheKey = FILE_PATH_PREFIX + filePath;
// 检查缓存中是否已存在该模板
if (TEMPLATE_CACHE.containsKey(cacheKey)) {
log.debug("从缓存加载文件系统模板: {}", filePath);
return TEMPLATE_CACHE.get(cacheKey);
}
try {
Path path = Paths.get(filePath);
// 检查文件是否存在
if (!Files.exists(path)) {
throw new IOException("模板文件不存在: " + filePath);
}
// 读取文件内容
String content = Files.readString(path, StandardCharsets.UTF_8);
// 存入缓存
TEMPLATE_CACHE.put(cacheKey, content);
log.info("从文件系统加载模板成功: {}", filePath);
log.info("从文件系统加载模板: {}", filePath);
return content;
} catch (IOException e) {
@ -159,31 +80,12 @@ public class TemplateFileLoader {
}
/**
* 智能加载模板文件自动判断路径类型
*
* <p>根据路径前缀自动选择加载方式</p>
* <ul>
* <li>"classpath:"开头从类路径加载</li>
* <li>"file:"开头从文件系统加载</li>
* <li>无前缀默认从类路径加载</li>
* </ul>
*
* @param templatePath 模板路径支持带前缀的完整路径或不带前缀的相对路径
* @return 模板文件的内容字符串
* @throws IOException 当模板文件加载失败时抛出
* @throws IllegalArgumentException 当templatePath为null或空字符串时抛出
* 智能加载模板自动判断路径类型
*/
public static String loadTemplate(String templatePath) throws IOException {
// 参数校验
if (templatePath == null || templatePath.trim().isEmpty()) {
throw new IllegalArgumentException("模板路径不能为空");
}
if (templatePath.startsWith(CLASS_PATH_PREFIX)) {
// 从类路径加载去掉前缀
return loadTemplateFromClasspath(templatePath.substring(CLASS_PATH_PREFIX.length()));
} else if (templatePath.startsWith(FILE_PATH_PREFIX)) {
// 从文件系统加载去掉前缀
return loadTemplateFromFileSystem(templatePath.substring(FILE_PATH_PREFIX.length()));
} else {
// 默认从类路径加载
@ -192,33 +94,17 @@ public class TemplateFileLoader {
}
/**
* 清除所有模板缓存
*
* <p>该方法会清空当前内存中所有的模板缓存适用于需要强制重新加载模板的场景
* 比如模板文件内容已更新但缓存还未过期的情况</p>
* 清除模板缓存
*/
public static void clearCache() {
int cacheSize = TEMPLATE_CACHE.size();
TEMPLATE_CACHE.clear();
log.info("模板缓存已清除,原缓存大小: {}", cacheSize);
log.info("模板缓存已清除");
}
/**
* 获取当前缓存中的模板数量
*
* @return 缓存中模板的数量
* 获取缓存中的模板数量
*/
public static int getCacheSize() {
return TEMPLATE_CACHE.size();
}
/**
* 检查指定路径的模板是否已缓存
*
* @param templatePath 模板路径需要包含完整的前缀
* @return 如果模板已缓存返回true否则返回false
*/
public static boolean isCached(String templatePath) {
return TEMPLATE_CACHE.containsKey(templatePath);
}
}
}

View File

@ -13,87 +13,34 @@ import java.util.Map;
import java.util.Stack;
import java.util.regex.Pattern;
/**
* XML转AFSIM格式转换器
*
* <p>该类提供将XML文件转换为JSON格式并应用正则表达式规则进行键名转换的功能
* 采用流式处理方式适用于处理大型XML文件避免内存溢出</p>
*
* <p>主要功能</p>
* <ul>
* <li>流式解析XML文件降低内存占用</li>
* <li>支持正则表达式规则对JSON键名进行转换</li>
* <li>自动处理XML属性和元素内容</li>
* <li>生成标准JSON数组格式输出</li>
* </ul>
*
* @author 岳佳君
* @version 1.0
*/
@Slf4j
public class Xml2AFSIMTransformation {
/**
* 正则表达式规则映射
* Key: 编译后的正则表达式模式
* Value: 替换字符串
*/
private final Map<Pattern, String> regexRules;
/**
* 构造函数初始化转换规则
*
* @param rules 转换规则映射Key为匹配的正则表达式Value为替换字符串
* 如果为null则使用空规则集
*/
public Xml2AFSIMTransformation(Map<String, String> rules) {
log.info("初始化XML转AFSIM转换器,规则数量: {}", rules != null ? rules.size() : 0);
log.info("初始化转换器,规则数量: {}", rules != null ? rules.size() : 0);
// 编译正则表达式规则
regexRules = new HashMap<>();
if (rules != null) {
for (Map.Entry<String, String> entry : rules.entrySet()) {
// 预编译正则表达式以提高性能
regexRules.put(Pattern.compile(entry.getKey()), entry.getValue());
}
}
log.debug("正则表达式规则编译完成");
}
/**
* 将XML文件转换为JSON格式并应用转换规则
*
* <p>该方法使用StAX流式API解析XML适用于处理大型文件
* 转换后的JSON格式为对象数组每个XML根元素对应一个JSON对象</p>
*
* @param xmlFile 输入的XML文件不能为null
* @param jsonFile 输出的JSON文件不能为null
* @param rootElement 根元素名称用于标识每个JSON对象的开始和结束
* @throws Exception 当文件读写失败XML解析错误或转换过程中出现异常时抛出
* @throws IllegalArgumentException 当参数为null或空字符串时抛出
* 流式XML转JSON并应用转换规则
*/
public void convertXmlToJson(File xmlFile, File jsonFile, String rootElement) throws Exception {
// 参数校验
if (xmlFile == null || !xmlFile.exists()) {
throw new IllegalArgumentException("XML文件不存在或为null: " + xmlFile);
}
if (jsonFile == null) {
throw new IllegalArgumentException("JSON文件路径不能为null");
}
if (rootElement == null || rootElement.trim().isEmpty()) {
throw new IllegalArgumentException("根元素名称不能为空");
}
log.info("开始XML转JSON转换并应用规则");
log.debug("输入文件: {}, 输出文件: {}, 根元素: {}", xmlFile.getPath(), jsonFile.getPath(), rootElement);
try (FileInputStream xmlInputStream = new FileInputStream(xmlFile);
FileWriter jsonWriter = new FileWriter(jsonFile)) {
// 创建XML流读取器
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader reader = factory.createXMLStreamReader(xmlInputStream);
// 写入JSON数组开始标记
jsonWriter.write("[\n");
boolean firstObject = true;
@ -105,7 +52,6 @@ public class Xml2AFSIMTransformation {
StringBuilder currentText = new StringBuilder();
String currentElement = null;
// 流式解析XML
while (reader.hasNext()) {
int event = reader.next();
@ -134,7 +80,7 @@ public class Xml2AFSIMTransformation {
String text = reader.getText().trim();
if (!text.isEmpty()) {
currentText.append(text);
log.trace("文本内容: {}", text);
log.debug("文本内容: {}", text);
}
}
break;
@ -166,7 +112,6 @@ public class Xml2AFSIMTransformation {
jsonWriter.write(json);
objectCount++;
// 每处理100个对象刷新一次缓冲区并记录日志
if (objectCount % 100 == 0) {
log.info("已处理 {} 个对象", objectCount);
jsonWriter.flush();
@ -180,68 +125,48 @@ public class Xml2AFSIMTransformation {
}
}
// 写入JSON数组结束标记
jsonWriter.write("\n]");
log.info("转换完成,共处理 {} 个对象", objectCount);
} catch (Exception e) {
log.error("XML转JSON转换失败,文件: {}", xmlFile.getPath(), e);
log.error("转换失败", e);
throw e;
}
}
/**
* 处理XML元素的属性
*
* <p>将元素的属性添加到当前对象中属性键名为"元素名@属性名"格式</p>
*
* @param reader XML流读取器
* @param elementStack 元素栈用于跟踪当前解析路径
* @param currentObject 当前正在构建的对象
* 处理元素的属性
*/
private void processAttributesForElement(XMLStreamReader reader, Stack<String> elementStack,
Map<String, Object> currentObject) {
int attributeCount = reader.getAttributeCount();
if (attributeCount > 0) {
log.debug("处理元素 {} 的属性,属性数量: {}", elementStack.peek(), attributeCount);
for (int i = 0; i < attributeCount; i++) {
if (reader.getAttributeCount() > 0) {
for (int i = 0; i < reader.getAttributeCount(); i++) {
String attrName = reader.getAttributeLocalName(i);
String attrValue = reader.getAttributeValue(i);
// 将属性添加到对象中格式为元素名@属性名
// 默认处理将属性添加到对象中
String attrKey = elementStack.peek() + "@" + attrName;
currentObject.put(attrKey, attrValue);
log.trace("添加属性: {} = {}", attrKey, attrValue);
}
}
}
/**
* 处理XML元素的文本内容
*
* <p>将元素的文本内容添加到当前对象中键名为完整的元素路径</p>
*
* @param elementName 元素名称
* @param content 元素文本内容
* @param elementStack 元素栈用于构建完整路径
* @param currentObject 当前正在构建的对象
* 处理元素文本内容
*/
private void processElementContent(String elementName, String content,
Stack<String> elementStack, Map<String, Object> currentObject) {
// 构建完整的元素路径作为key父元素.当前元素
// 默认处理将元素内容添加到对象中
// 构建完整的元素路径作为key
String elementKey = String.join(".", elementStack) + "." + elementName;
currentObject.put(elementKey, content);
log.debug("添加元素内容: {} = {}", elementKey, content);
}
/**
* 将Map对象转换为JSON字符串
*
* @param object 要转换的对象映射
* @return JSON格式的字符串如果对象为空则返回null
* 将对象转换为JSON字符串
*/
private String convertObjectToJson(Map<String, Object> object) {
if (object == null || object.isEmpty()) {
log.warn("空对象,跳过JSON转换");
if (object.isEmpty()) {
log.warn("空对象,跳过输出");
return null;
}
@ -249,15 +174,12 @@ public class Xml2AFSIMTransformation {
return mapToJson(object);
} catch (Exception e) {
log.error("对象转JSON失败", e);
return "{}"; // 返回空对象作为容错处理
return "{}";
}
}
/**
* 递归将Map转换为JSON字符串
*
* @param map 要转换的映射
* @return JSON对象字符串
* Map转JSON字符串
*/
private String mapToJson(Map<String, Object> map) {
if (map.isEmpty()) {
@ -282,10 +204,7 @@ public class Xml2AFSIMTransformation {
}
/**
* 将值转换为JSON格式
*
* @param value 要转换的值支持StringNumberBooleanMapList等类型
* @return JSON格式的值表示
* 值转JSON
*/
private String valueToJson(Object value) {
if (value == null) {
@ -320,21 +239,14 @@ public class Xml2AFSIMTransformation {
return json.toString();
}
// 默认处理转换为字符串
return "\"" + escapeJson(value.toString()) + "\"";
}
/**
* JSON字符串转义处理
*
* <p>转义JSON中的特殊字符包括引号反斜杠控制字符等</p>
*
* @param text 要转义的文本
* @return 转义后的安全JSON字符串
* JSON特殊字符转义
*/
private String escapeJson(String text) {
if (text == null) return "";
return text.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\b", "\\b")
@ -346,11 +258,6 @@ public class Xml2AFSIMTransformation {
/**
* 应用正则表达式转换规则到单个对象
*
* <p>遍历对象的所有键对每个键应用正则表达式规则进行转换</p>
*
* @param originalMap 原始对象映射
* @return 应用规则转换后的新对象映射
*/
private Map<String, Object> applyRules(Map<String, Object> originalMap) {
Map<String, Object> transformedMap = new HashMap<>();
@ -363,32 +270,25 @@ public class Xml2AFSIMTransformation {
// 如果找到匹配的规则则使用新key否则保留原key
if (newKey != null) {
transformedMap.put(newKey, value);
log.debug("键名转换: {} -> {}", originalKey, newKey);
log.debug("转换: {} -> {}", originalKey, newKey);
} else {
transformedMap.put(originalKey, value);
}
}
log.debug("规则应用完成,原始键数: {}, 转换后键数: {}", originalMap.size(), transformedMap.size());
return transformedMap;
}
/**
* 查找并替换匹配的正则规则
*
* <p>遍历所有正则规则找到第一个匹配的规则并进行替换</p>
*
* @param originalKey 原始键名
* @return 替换后的新键名如果没有匹配规则则返回null
*/
private String findAndReplace(String originalKey) {
for (Map.Entry<Pattern, String> rule : regexRules.entrySet()) {
if (rule.getKey().matcher(originalKey).matches()) {
String newKey = rule.getKey().matcher(originalKey).replaceAll(rule.getValue());
log.trace("正则匹配: {} -> {} (规则: {})", originalKey, newKey, rule.getKey().pattern());
return newKey;
return rule.getKey().matcher(originalKey).replaceAll(rule.getValue());
}
}
return null;
}
}
}

View File

@ -2,6 +2,6 @@
<作战部队武器装备>
<装备类型>武装直升机</装备类型>
<武器装备型号>Z-10</武器装备型号>
<武器装备型号名称>直-10攻击直升机</武器装备型号名称>
<武器装备名称>直-10攻击直升机</武器装备名称>
<武器装备数量>18</武器装备数量>
</作战部队武器装备>

View File

@ -2,6 +2,6 @@
<作战部队武器装备>
<装备类型>自行火炮</装备类型>
<武器装备型号>PLZ-05</武器装备型号>
<武器装备型号名称>05式自行榴弹炮</武器装备型号名称>
<武器装备名称>05式自行榴弹炮</武器装备名称>
<武器装备数量>36</武器装备数量>
</作战部队武器装备>

View File

@ -2,6 +2,6 @@
<作战部队武器装备>
<装备类型>战斗机</装备类型>
<武器装备型号>J-20</武器装备型号>
<武器装备型号名称>歼-20隐形战斗机</武器装备型号名称>
<武器装备名称>歼-20隐形战斗机</武器装备名称>
<武器装备数量>24</武器装备数量>
</作战部队武器装备>

View File

@ -2,6 +2,6 @@
<作战部队武器装备>
<装备类型>主战坦克</装备类型>
<武器装备型号>99A</武器装备型号>
<武器装备型号名称>99A式主战坦克</武器装备型号名称>
<武器装备名称>99A式主战坦克</武器装备名称>
<武器装备数量>50</武器装备数量>
</作战部队武器装备>

View File

@ -2,6 +2,6 @@
<作战部队武器装备>
<装备类型>驱逐舰</装备类型>
<武器装备型号>055</武器装备型号>
<武器装备型号名称>055型导弹驱逐舰</武器装备型号名称>
<武器装备名称>055型导弹驱逐舰</武器装备名称>
<武器装备数量>2</武器装备数量>
</作战部队武器装备>

View File

@ -13,7 +13,7 @@
"values": [
{
"combined": false,
"value": "string batchnumber = \"{{作战部队武器装备.武器装备数量}}\""
"value": "string batchnumber = \"作战部队武器装备.武器装备数量\""
}
]
}
@ -70,8 +70,8 @@
}
],
"values": [
"{{作战部队武器装备.武器装备型号名称}}",
"{{作战部队武器装备.武器装备型号}}"
"作战部队武器装备.武器装备名称",
"作战部队武器装备.武器装备型号"
]
}
]

View File

@ -2,7 +2,7 @@
<任务航线>
<航线点型号>WP003</航线点型号>
<航线点名称>目标区域</航线点名称>
<航线点坐标>120.3826,36.0673</航线点坐标> <!-- 青岛 -->
<航线点坐标>40.0042,116.6074</航线点坐标>
<航线点类型>目标点</航线点类型>
<准时到达时间>08:45:00</准时到达时间>
<转弯方式>盘旋</转弯方式>

View File

@ -2,7 +2,7 @@
<任务航线>
<航线点型号>WP002</航线点型号>
<航线点名称>导航点A</航线点名称>
<航线点坐标>121.61,38.92</航线点坐标> <!-- 大连 -->
<航线点坐标>39.9242,116.5074</航线点坐标>
<航线点类型>航路点</航线点类型>
<准时到达时间>08:15:30</准时到达时间>
<转弯方式>飞越转弯</转弯方式>

View File

@ -2,7 +2,7 @@
<任务航线>
<航线点型号>WP005</航线点型号>
<航线点名称>降落点</航线点名称>
<航线点坐标>119.31,39.95</航线点坐标> <!-- 秦皇岛 -->
<航线点坐标>39.9042,116.4074</航线点坐标>
<航线点类型>降落点</航线点类型>
<准时到达时间>09:45:00</准时到达时间>
<转弯方式>直接进近</转弯方式>

View File

@ -2,7 +2,7 @@
<任务航线>
<航线点型号>WP001</航线点型号>
<航线点名称>起飞点</航线点名称>
<航线点坐标>118.04,24.27</航线点坐标> <!-- 厦门 -->
<航线点坐标>39.9042,116.4074</航线点坐标>
<航线点类型>起飞点</航线点类型>
<准时到达时间>08:00:00</准时到达时间>
<转弯方式>直接转弯</转弯方式>

View File

@ -2,7 +2,7 @@
<任务航线>
<航线点型号>WP004</航线点型号>
<航线点名称>返航点</航线点名称>
<航线点坐标>110.37,21.27</航线点坐标> <!-- 湛江 -->
<航线点坐标>39.9542,116.4574</航线点坐标>
<航线点类型>返航点</航线点类型>
<准时到达时间>09:30:00</准时到达时间>
<转弯方式>标准转弯</转弯方式>

View File

@ -18,27 +18,11 @@
"values": [
{
"combined": false,
"value": "{{任务航线.北纬}}",
"utilFunction": {
"regexReplace": {
"params": "{{任务航线.航线点坐标}}",
"description": "通过正则表达式获取经纬度",
"pattern": "([0-9]+[\\.]{0,}[0-9]{0,}),([0-9]+[\\.]{0,}[0-9]{0,})",
"replacement": "$2N"
}
}
"value": "39.9242N"
},
{
"combined": false,
"value": "{{任务航线.东经}}",
"utilFunction": {
"regexReplace": {
"params": "{{任务航线.航线点坐标}}",
"description": "通过正则表达式获取经纬度",
"pattern": "([0-9]+[\\.]{0,}[0-9]{0,}),([0-9]+[\\.]{0,}[0-9]{0,})",
"replacement": "$1E"
}
}
"value": "116.5074E"
}
]
},
@ -48,7 +32,7 @@
"values": [
{
"combined": false,
"value": "{{任务航线.航线点类型}}"
"value": "任务航线.航线点类型"
}
]
},
@ -58,7 +42,7 @@
"values": [
{
"combined": false,
"value": "{{任务航线.准时到达时间}}"
"value": "任务航线.准时到达时间"
}
]
},
@ -68,7 +52,7 @@
"values": [
{
"combined": false,
"value": "{{任务航线.转弯方式}}"
"value": "任务航线.转弯方式"
}
]
},
@ -78,7 +62,7 @@
"values": [
{
"combined": false,
"value": "{{任务航线.转向方式}}"
"value": "任务航线.转向方式"
}
]
},
@ -89,7 +73,7 @@
{
"combined": false,
"unit": "deg",
"value": "{{任务航线.坡度}}"
"value": "任务航线.坡度"
}
]
},
@ -100,7 +84,7 @@
{
"combined": false,
"unit": "km/h",
"value": "{{任务航线.速度}}"
"value": "任务航线.速度"
}
]
},
@ -111,7 +95,7 @@
{
"combined": false,
"unit": "m",
"value": "{{任务航线.高度}}"
"value": "任务航线.高度"
}
]
},
@ -121,7 +105,7 @@
"values": [
{
"combined": false,
"value": "{{任务航线.高度属性}}"
"value": "任务航线.高度属性"
}
]
},
@ -132,14 +116,14 @@
{
"combined": false,
"unit": "m/s",
"value": "{{任务航线.升降率}}"
"value": "任务航线.升降率"
}
]
}
],
"values": [
"{{任务航线.航线点型号}}",
"{{任务航线.航线点名称}}"
"任务航线.航线点型号",
"任务航线.航线点名称"
]
}
],

View File

@ -1,6 +1,5 @@
package com.example.demo;
import com.alibaba.fastjson2.JSON;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.BeforeEach;
@ -10,7 +9,6 @@ import static org.junit.jupiter.api.Assertions.*;
import com.example.demo.draft.demo043.util.FormatUtil;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
@ -63,7 +61,7 @@ public class FormatUtilTest {
void tearDown() {
params.clear();
}
// ==================== 时间格式化模块测试 ====================
/**
@ -74,7 +72,7 @@ public class FormatUtilTest {
* <p><b>预期结果</b>转换后的时间格式正确</p>
*/
@Test
@DisplayName("formatTime - 时间,正常格式转换 - 【已验证】")
@DisplayName("formatTime方法测试 - 正常格式转换")
void testFormatTime_NormalConversion() {
System.out.println();
log.info("========== 时间格式化模块测试 - 正常格式转换 ==========");
@ -83,18 +81,24 @@ public class FormatUtilTest {
String inputTime = "2024-01-15 14:30:25";
params.put("fromFormat", "yyyy-MM-dd HH:mm:ss");
params.put("toFormat", "yyyy/MM/dd");
log.info("输入参数:");
log.info(" - 时间字符串: {}", inputTime);
log.info(" - 源格式: {}", params.get("fromFormat"));
log.info(" - 目标格式: {}", params.get("toFormat"));
// 预期结果
String expectedResult = "2024/01/15";
log.info("预期结果: {}", expectedResult);
// 执行测试
Object result = FormatUtil.formatTime(inputTime, params);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证
String expectedResult = "2024/01/15";
log.info("预期结果: '{}'", expectedResult);
log.info("实际结果: '{}'", result);
assertEquals(expectedResult, result);
log.info("✓ 测试通过 - 格式转换结果正确");
}
@ -103,10 +107,10 @@ public class FormatUtilTest {
*
* <p><b>测试目的</b>验证formatTime方法对空值的容错处理</p>
* <p><b>测试场景</b>输入时间为空字符串</p>
* <p><b>预期结果</b>返回空字符串</p>
* <p><b>预期结果</b>返回空字符串或默认值</p>
*/
@Test
@DisplayName("formatTime - 需要格式化时间的获取到空串 - 【已验证】")
@DisplayName("formatTime方法测试 - 空值处理")
void testFormatTime_EmptyInput() {
System.out.println();
log.info("========== 时间格式化模块测试 - 空值处理 ==========");
@ -115,19 +119,23 @@ public class FormatUtilTest {
String inputTime = "";
params.put("fromFormat", "yyyy-MM-dd");
params.put("toFormat", "yyyy/MM/dd");
log.info("输入参数:");
log.info(" - 时间字符串: '{}' (空字符串)", inputTime);
log.info(" - 源格式: {}", params.get("fromFormat"));
log.info(" - 目标格式: {}", params.get("toFormat"));
// 预期结果
log.info("预期结果: 非空结果(空字符串或默认值)");
// 执行测试
Object result = FormatUtil.formatTime(inputTime, params);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证
String expectedResult = "";
log.info("预期结果: '',(空字符串)");
log.info("实际结果: '{}'", result);
assertNotNull(result);
assertEquals(expectedResult, result);
log.info("✓ 测试通过 - 空值处理正确");
}
@ -139,7 +147,7 @@ public class FormatUtilTest {
* <p><b>预期结果</b>输出原值</p>
*/
@Test
@DisplayName("formatTime - 格式不匹配")
@DisplayName("formatTime方法测试 - 格式不匹配")
void testFormatTime_FormatMismatch() {
System.out.println();
log.info("========== 时间格式化模块测试 - 格式不匹配 ==========");
@ -177,39 +185,31 @@ public class FormatUtilTest {
* <p><b>预期结果</b>正确提取开始时间</p>
*/
@Test
@DisplayName("extractTimeRange - 时间范围内(t1 ~ t2)正常提取开始时间 - 【已验证】")
@DisplayName("extractTimeRange方法测试 - 正常提取开始时间")
void testExtractTimeRange_ExtractStartTime() {
System.out.println();
log.info("========== 时间范围提取模块测试 - 正常提取开始时间 ==========");
// 输入参数
String inputTimeRange1 = "2024-01-15 14:30:25 ~ 2024-01-15 16:45:30";
String inputTimeRange = "2024-01-15 14:30:25 - 2024-01-15 16:45:30";
params.put("type", "start");
log.info("输入参数:");
log.info(" - 时间范围字符串: {}", inputTimeRange1);
log.info(" - 时间范围字符串: {}", inputTimeRange);
log.info(" - 提取类型: {}", params.get("type"));
// 预期结果
String expectedResult = "2024-01-15 14:30:25";
log.info("预期结果: {}", expectedResult);
// 执行测试
Object result1 = FormatUtil.extractTimeRange(inputTimeRange1, params);
Object result = FormatUtil.extractTimeRange(inputTimeRange, params);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证
String expectedResult1 = "2024-01-15 14:30:25";
log.info("预期结果:'{}'", expectedResult1);
log.info("实际结果:'{}'", result1);
assertEquals(expectedResult1, result1);
// 输入参数
String inputTimeRange2 = "2024-01-15 ~ 2024-01-15 ";
params.put("type", "start");
log.info("输入参数:");
log.info(" - 时间范围字符串: {}", inputTimeRange2);
log.info(" - 提取类型: {}", params.get("type"));
// 执行测试
Object result2 = FormatUtil.extractTimeRange(inputTimeRange2, params);
// 断言验证
String expectedResult2 = "2024-01-15";
log.info("预期结果:'{}'", expectedResult2);
log.info("实际结果:'{}'", result2);
assertEquals(expectedResult2, result2);
assertEquals(expectedResult, result);
log.info("✓ 测试通过 - 开始时间提取正确");
}
@ -218,10 +218,10 @@ public class FormatUtilTest {
*
* <p><b>测试目的</b>验证extractTimeRange方法对无分隔符情况的处理</p>
* <p><b>测试场景</b>时间范围字符串中无分隔符</p>
* <p><b>预期结果</b>返回原始字符串</p>
* <p><b>预期结果</b>返回原始字符串或错误信息</p>
*/
@Test
@DisplayName("extractTimeRange - 无分隔符情况下,获取开始时间 - 【已验证】")
@DisplayName("extractTimeRange方法测试 - 无分隔符处理")
void testExtractTimeRange_NoSeparator() {
System.out.println();
log.info("========== 时间范围提取模块测试 - 无分隔符处理 ==========");
@ -240,14 +240,12 @@ public class FormatUtilTest {
// 执行测试
Object result = FormatUtil.extractTimeRange(inputTimeRange, params);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证
String expectedResult = "2024-01-15 14:30:25";
log.info("预期结果: '{}'", expectedResult);
log.info("实际结果: '{}'", result);
assertNotNull(result);
assertEquals(expectedResult, result);
log.info("✓ 测试通过 - 无分隔符处理正确");
}
@ -259,7 +257,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>正确识别并转换为目标格式</p>
*/
@Test
@DisplayName("dynamicTimeFormat - 标准格式识别")
@DisplayName("dynamicTimeFormat方法测试 - 标准格式识别")
void testDynamicTimeFormat_StandardFormat() {
System.out.println();
log.info("========== 动态时间格式化模块测试 - 标准格式识别 ==========");
@ -295,7 +293,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>正确识别并转换为目标格式</p>
*/
@Test
@DisplayName("dynamicTimeFormat - 中文格式识别")
@DisplayName("dynamicTimeFormat方法测试 - 中文格式识别")
void testDynamicTimeFormat_ChineseFormat() {
System.out.println();
log.info("========== 动态时间格式化模块测试 - 中文格式识别 ==========");
@ -331,7 +329,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>返回true</p>
*/
@Test
@DisplayName("validateTimeFormat - 格式验证通过")
@DisplayName("validateTimeFormat方法测试 - 格式验证通过")
void testValidateTimeFormat_ValidFormat() {
System.out.println();
log.info("========== 时间格式验证模块测试 - 格式验证通过 ==========");
@ -368,7 +366,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>返回false</p>
*/
@Test
@DisplayName("validateTimeFormat - 格式验证失败")
@DisplayName("validateTimeFormat方法测试 - 格式验证失败")
void testValidateTimeFormat_InvalidFormat() {
System.out.println();
log.info("========== 时间格式验证模块测试 - 格式验证失败 ==========");
@ -408,7 +406,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>截取结果正确</p>
*/
@Test
@DisplayName("substring - 正常截取")
@DisplayName("substring方法测试 - 正常截取")
void testSubstring_NormalCase() {
System.out.println();
log.info("========== 字符串截取模块测试 - 正常截取 ==========");
@ -448,7 +446,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>返回空字符串或错误信息</p>
*/
@Test
@DisplayName("substring - 起始位置超界 - 【验证中】")
@DisplayName("substring方法测试 - 起始位置超界")
void testSubstring_StartOutOfBounds() {
System.out.println();
log.info("========== 字符串截取模块测试 - 起始位置超界 ==========");
@ -488,7 +486,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>替换结果正确</p>
*/
@Test
@DisplayName("regexReplace - 正则替换 - 【已验证】")
@DisplayName("regexReplace方法测试 - 正则替换")
void testRegexReplace_NormalCase() {
System.out.println();
log.info("========== 正则表达式替换模块测试 - 正则替换 ==========");
@ -497,101 +495,28 @@ public class FormatUtilTest {
String inputString = "abc123def456";
String regex = "\\d+";
String replacement = "*";
params.put("pattern", regex);
params.put("regex", regex);
params.put("replacement", replacement);
log.info("输入参数:");
log.info(" - 输入字符串: {}", inputString);
log.info(" - 正则表达式: {}", regex);
log.info(" - 替换字符串: {}", replacement);
// 执行测试
Object result = FormatUtil.regexReplace(inputString, params);
// 断言验证
// 预期结果
String expectedResult = "abc*def*";
log.info("预期结果: {}", expectedResult);
// 执行测试
Object result = FormatUtil.regexReplace(inputString, params);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证
assertEquals(expectedResult, result);
log.info("✓ 测试通过 - 正则替换正确");
}
/**
* 测试regexReplace方法 - 正则表达式替换
*
* <p><b>测试目的</b>验证regexReplace方法能够正确进行正则替换</p>
* <p><b>测试场景</b>替换字符串中的数字</p>
* <p><b>预计结果</b>替换结果正确</p>
*/
@Test
@DisplayName("regexReplace - 正则替换、分组替换、大小写敏感替换 - 【已验证】")
void testRegexReplace_NormalCase4() {
System.out.println();
log.info("========== 正则表达式替换模块测试 - 正则替换 ==========");
// 输入参数
String inputString = "abc123def456";
String regex = "\\d+";
String replacement = "*";
params.put("pattern", regex);
params.put("replacement", replacement);
// 测试用例1数字替换
String inputString1 = "abc123def456";
Map<String, Object> params1 = new HashMap<>();
params1.put("pattern", "\\d+");
params1.put("replacement", "*");
String result1 = FormatUtil.regexReplace(inputString1, params1);
log.info("实际结果 (1): " + result1);
// 断言验证
String expectedResult1 = "abc*def*";
log.info("预期结果:'{}'", expectedResult1);
log.info("实际结果:'{}'", result1);
assertEquals(expectedResult1, result1);
// 测试用例2分组引用替换
String inputString2 = "电话: 123-456";
Map<String, Object> params2 = new HashMap<>();
params2.put("pattern", "(\\d+)-(\\d+)");
params2.put("replacement", "$2到$1");
String result2 = FormatUtil.regexReplace(inputString2, params2);
log.info("实际结果 (2): " + result2);
// 断言验证
String expectedResult2 = "电话: 456到123";
log.info("预期结果:'{}'", expectedResult2);
log.info("实际结果:'{}'", result2);
assertEquals(expectedResult2, result2);
// 测试用例3大小写不敏感
String inputString3 = "Hello World";
Map<String, Object> params3 = new HashMap<>();
params3.put("pattern", "hello");
params3.put("replacement", "HI");
params3.put("flags", "CASE_INSENSITIVE");
String result3 = FormatUtil.regexReplace(inputString3, params3);
log.info("实际结果 (3): " + result3);
// 断言验证
String expectedResult3 = "HI World";
log.info("预期结果:'{}'", expectedResult3);
log.info("实际结果:'{}'", result3);
assertEquals(expectedResult3, result3);
// 测试用例4大小写不敏感
String inputString4 = "Hello World";
Map<String, Object> params4 = new HashMap<>();
params4.put("pattern", "hello");
params4.put("replacement", "HI");
String result4 = FormatUtil.regexReplace(inputString4, params4);
log.info("实际结果 (4): " + result4);
// 断言验证
String expectedResult4 = "Hello World";
log.info("预期结果:'{}'", expectedResult4);
log.info("实际结果:'{}'", result4);
assertEquals(expectedResult4, result4);
log.info("✓ 测试通过 - 正则替换正确");
}
/**
* 测试toUpperCase方法 - 大小写转换
@ -601,7 +526,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>转换结果正确</p>
*/
@Test
@DisplayName("toUpperCase - 大小写转换")
@DisplayName("toUpperCase方法测试 - 大小写转换")
void testToUpperCase_NormalCase() {
System.out.println();
log.info("========== 字符串大小写转换模块测试 - 大小写转换 ==========");
@ -635,24 +560,30 @@ public class FormatUtilTest {
* <p><b>预计结果</b>去除空格后结果正确</p>
*/
@Test
@DisplayName("trim - 字符串,去除空格 - 【已验证】")
@DisplayName("trim方法测试 - 去除空格")
void testTrim_NormalCase() {
System.out.println();
log.info("========== 字符串空格处理模块测试 - 去除空格 ==========");
// 输入参数
String inputString = " hello world ";
log.info("输入参数:");
log.info(" - 输入字符串: '{}'", inputString);
log.info(" - 注意: 字符串前后有空格");
// 执行测试
Object result = FormatUtil.trim(inputString, params);
// 断言验证
// 预期结果
String expectedResult = "hello world";
log.info("预期结果: '{}'", expectedResult);
// 执行测试
Object result = FormatUtil.trim(inputString, params);
// 实际结果
log.info("实际结果: '{}'", result);
// 断言验证
assertEquals(expectedResult, result);
log.info("✓ 测试通过 - 空格去除正确");
}
@ -664,7 +595,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>替换结果正确</p>
*/
@Test
@DisplayName("stealBeamsAndReplacePillars - 基础替换")
@DisplayName("stealBeamsAndReplacePillars方法测试 - 基础替换")
void testStealBeamsAndReplacePillars_BasicReplacement() {
System.out.println();
log.info("========== 字符串替换模块测试 - 基础替换 ==========");
@ -702,7 +633,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>大小写敏感替换结果正确</p>
*/
@Test
@DisplayName("stealBeamsAndReplacePillars - 批量Map替换大小写敏感 - 【已验证】")
@DisplayName("stealBeamsAndReplacePillars方法测试 - 大小写敏感")
void testStealBeamsAndReplacePillars_CaseSensitive() {
System.out.println();
log.info("========== 字符串替换模块测试 - 大小写敏感替换 ==========");
@ -713,17 +644,24 @@ public class FormatUtilTest {
replacementMap.put("Hello", "Hi");
replacementMap.put("world", "universe");
boolean caseSensitive = true;
log.info("输入参数:");
log.info(" - 输入字符串: {}", inputString);
log.info(" - 替换映射: {}", JSON.toJSONString(replacementMap));
log.info(" - 替换映射: {}", replacementMap);
log.info(" - 大小写敏感: {}", caseSensitive);
log.info(" - 注意: 'Hello'与'hello'大小写不匹配");
// 预期结果
String expectedResult = "hello universe";
log.info("预期结果: {}", expectedResult);
// 执行测试
String result = FormatUtil.stealBeamsAndReplacePillars(inputString, replacementMap, caseSensitive);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证
String expectedResult = "hello universe";
log.info("预期结果:'{}'", expectedResult);
log.info("实际结果:'{}'", result);
assertEquals(expectedResult, result);
log.info("✓ 测试通过 - 大小写敏感替换正确");
}
@ -736,7 +674,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>整词匹配替换结果正确</p>
*/
@Test
@DisplayName("stealBeamsAndReplacePillars - 整词匹配")
@DisplayName("stealBeamsAndReplacePillars方法测试 - 整词匹配")
void testStealBeamsAndReplacePillars_WholeWord() {
System.out.println();
log.info("========== 字符串替换模块测试 - 整词匹配替换 ==========");
@ -780,7 +718,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>转换结果正确</p>
*/
@Test
@DisplayName("coordinateConvert - 度分秒转十进制")
@DisplayName("coordinateConvert方法测试 - 度分秒转十进制")
void testCoordinateConvert_DmsToDecimal() {
System.out.println();
log.info("========== 坐标系转换模块测试 - 度分秒转十进制 ==========");
@ -789,19 +727,24 @@ public class FormatUtilTest {
String coordinate = "116°23'45.67\"";
params.put("fromType", "dms");
params.put("toType", "decimal");
log.info("输入参数:");
log.info(" - 坐标值: {}", coordinate);
log.info(" - 源格式: {}", params.get("fromType"));
log.info(" - 目标格式: {}", params.get("toType"));
log.info(" - 注意: 116°23'45.67\" ≈ 116.396019");
// 预期结果
log.info("预期结果: 非空转换结果");
// 执行测试
Object result = FormatUtil.coordinateConvert(coordinate, params);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证
String expectedResult = "116.396019";
log.info("预期结果:'{}'", expectedResult);
log.info("实际结果:'{}'", result);
assertEquals(expectedResult, result);
assertNotNull(result);
log.info("✓ 测试通过 - 度分秒转十进制转换正确");
}
@ -813,29 +756,33 @@ public class FormatUtilTest {
* <p><b>预计结果</b>转换结果正确</p>
*/
@Test
@DisplayName("coordinateConvert - 十进制转度分秒 - 【已验证】")
@DisplayName("coordinateConvert方法测试 - 十进制转度分秒")
void testCoordinateConvert_DecimalToDms() {
System.out.println();
log.info("========== 坐标系转换模块测试 - 十进制转度分秒 ==========");
// 输入参数
String coordinate = "116.396019";
params.put("fromFormat", "decimal"); // 十进制
params.put("toFormat", "dms"); // 度分秒
params.put("precision", "2"); // 保留2位小数
params.put("fromType", "decimal");
params.put("toType", "dms");
log.info("输入参数:");
log.info(" - 坐标值: {}", coordinate);
log.info(" - 源格式: {}", params.get("fromFormat"));
log.info(" - 目标格式: {}", params.get("toFormat"));
log.info(" - 源格式: {}", params.get("fromType"));
log.info(" - 目标格式: {}", params.get("toType"));
log.info(" - 注意: 116.396019 ≈ 116°23'45.67\"");
// 预期结果
log.info("预期结果: 非空转换结果");
// 执行测试
Object result = FormatUtil.coordinateConvert(coordinate, params);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证
String expectedResult = "116°23'45.67\"";
log.info("预期结果:'{}'", expectedResult);
log.info("实际结果:'{}'", result);
assertEquals(expectedResult, result);
assertNotNull(result);
log.info("✓ 测试通过 - 十进制转度分秒转换正确");
}
@ -847,7 +794,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>转换结果正确</p>
*/
@Test
@DisplayName("cartesianConvert - 直角坐标转极坐标")
@DisplayName("cartesianConvert方法测试 - 直角坐标转极坐标")
void testCartesianConvert_RectangularToPolar() {
System.out.println();
log.info("========== 坐标系转换模块测试 - 直角坐标转极坐标 ==========");
@ -889,7 +836,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>标准化结果正确</p>
*/
@Test
@DisplayName("normalizeCoordinate - 坐标标准化")
@DisplayName("normalizeCoordinate方法测试 - 坐标标准化")
void testNormalizeCoordinate_NormalCase() {
System.out.println();
log.info("========== 坐标系转换模块测试 - 坐标格式标准化 ==========");
@ -926,7 +873,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>返回原始值</p>
*/
@Test
@DisplayName("boundaryCheck - 正常范围检查")
@DisplayName("boundaryCheck方法测试 - 正常范围检查")
void testBoundaryCheck_WithinRange() {
System.out.println();
log.info("========== 极值检查模块测试 - 正常范围检查 ==========");
@ -966,7 +913,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>返回最大值</p>
*/
@Test
@DisplayName("boundaryCheck - 超出上限截断 - 【验证中】")
@DisplayName("boundaryCheck方法测试 - 超出上限截断")
void testBoundaryCheck_AboveMaxTruncate() {
System.out.println();
log.info("========== 极值检查模块测试 - 超出上限截断处理 ==========");
@ -1007,7 +954,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>返回默认值</p>
*/
@Test
@DisplayName("boundaryCheck - 超出下限默认值")
@DisplayName("boundaryCheck方法测试 - 超出下限默认值")
void testBoundaryCheck_BelowMinDefault() {
System.out.println();
log.info("========== 极值检查模块测试 - 超出下限默认值处理 ==========");
@ -1050,7 +997,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>返回错误信息或默认值</p>
*/
@Test
@DisplayName("boundaryCheck - 异常值检测")
@DisplayName("boundaryCheck方法测试 - 异常值检测")
void testBoundaryCheck_NaNValue() {
System.out.println();
log.info("========== 极值检查模块测试 - 异常值检测 ==========");
@ -1092,129 +1039,33 @@ public class FormatUtilTest {
* <p><b>预计结果</b>转换结果正确</p>
*/
@Test
@DisplayName("kvMapping - 键名格式转换 - 【已验证】")
@DisplayName("kvMapping方法测试 - 键名格式转换")
void testKvMapping_KeyFormatConversion() {
System.out.println();
log.info("========== 数据KV映射模块测试 - 键名格式转换 ==========");
// 输入参数
Map<String, Object> inputMap = new HashMap<>();
// =================== 全大写命名 ===================
inputMap.put("USER_ID", 1001);
inputMap.put("STATUS", "ACTIVE");
// =================== 全小写命名 ===================
inputMap.put("name", "李四");
inputMap.put("address", "北京市朝阳区");
inputMap.put("phone", "13800138000");
// =================== 小驼峰命名 (lowerCamelCase) ===================
inputMap.put("userName", "王五");
// =================== 大驼峰命名 (UpperCamelCase/PascalCase) ===================
inputMap.put("UserRole", "ADMIN");
// =================== 蛇形命名 (snake_case) ===================
inputMap.put("user_password", "encrypted123");
// =================== 短横线命名 (kebab-case) ===================
inputMap.put("user-address", "上海市浦东新区");
// 1. 转成全大写
System.out.println();
log.info("========== 转成全大写 ==========");
params.put("keyFormat", "uppercase");
inputMap.put("user_name", "张三");
inputMap.put("user_age", 25);
params.put("keyFormat", "snake_to_camel");
log.info("输入参数:");
log.info(" - 输入Map: {}", inputMap);
log.info(" - 键名格式转换: {}", params.get("keyFormat"));
log.info(" - 注意: 短横杠在全大写中,不做处理");
log.info(" - 注意: 蛇形命名(user_name)转驼峰命名(userName)");
// 预期结果
log.info("预期结果: 非空转换结果");
// 执行测试
Object result = FormatUtil.kvMapping(inputMap, params);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证
String expectedResultString = """
{"USERROLE":"ADMIN","STATUS":"ACTIVE","USER-ADDRESS":"上海市浦东新区","USER_PASSWORD":"encrypted123","ADDRESS":"北京市朝阳区","PHONE":"13800138000","USER_ID":1001,"USERNAME":"王五","NAME":"李四"}
""".trim();
String resultString = JSON.toJSONString(result);
log.info("预期结果: {}", expectedResultString);
log.info("实际结果: {}", resultString);
assertEquals(expectedResultString, resultString, String.format("转换为全大写%s失败", params.get("keyFormat")));
// 2. 转成全小写
System.out.println();
log.info("========== 转成全小写 ==========");
params.put("keyFormat", "lowercase");
log.info("输入参数:");
log.info(" - 输入Map: {}", inputMap);
log.info(" - 键名格式转换: {}", params.get("keyFormat"));
log.info(" - 注意: 短横杠在全小写中,不做处理");
// 执行测试
Object result2 = FormatUtil.kvMapping(inputMap, params);
// 断言验证
String expectedResultString2 = """
{"user_password":"encrypted123","address":"北京市朝阳区","phone":"13800138000","user_id":1001,"name":"李四","userrole":"ADMIN","user-address":"上海市浦东新区","status":"ACTIVE","username":"王五"}
""".trim();
String resultString2 = JSON.toJSONString(result2);
log.info("预期结果: {}", expectedResultString2);
log.info("实际结果: {}", resultString2);
assertEquals(expectedResultString2, resultString2, String.format("转换为全小写%s失败", params.get("keyFormat")));
// 3. 转换为小驼峰命名
System.out.println();
log.info("========== 转换为小驼峰命名 ==========");
params.put("keyFormat", "camelcase");
log.info("输入参数:");
log.info(" - 输入Map: {}", inputMap);
log.info(" - 键名格式转换: {}", params.get("keyFormat"));
log.info(" - 注意: 所有值都被转为驼峰,不区分当前是否大小写,只判断 [ _ | - | ' '] 下划线、短横杠、空串三种。");
// 执行测试
Object result3 = FormatUtil.kvMapping(inputMap, params);
// 断言验证
String expectedResultString3 = """
{"userAddress":"上海市浦东新区","userPassword":"encrypted123","address":"北京市朝阳区","phone":"13800138000","name":"李四","userrole":"ADMIN","userId":1001,"status":"ACTIVE","username":"王五"}
""".trim();
String resultString3 = JSON.toJSONString(result3);
log.info("预期结果: {}", expectedResultString3);
log.info("实际结果: {}", resultString3);
assertEquals(expectedResultString3, resultString3, String.format("转换为小驼峰命名%s失败", params.get("keyFormat")));
// 4. 转换为蛇形命名
System.out.println();
log.info("========== 转换为蛇形命名 ==========");
params.put("keyFormat", "snakecase");
log.info("输入参数:");
log.info(" - 输入Map: {}", inputMap);
log.info(" - 键名格式转换: {}", params.get("keyFormat"));
log.info(" - 注意: 短横杠在蛇形命名中,不做处理");
// 执行测试
Object result4 = FormatUtil.kvMapping(inputMap, params);
// 断言验证
String expectedResultString4 = """
{"user_role":"ADMIN","user_password":"encrypted123","address":"北京市朝阳区","phone":"13800138000","user_id":1001,"user_name":"王五","user_address":"上海市浦东新区","name":"李四","status":"ACTIVE"}
""".trim();
String resultString4 = JSON.toJSONString(result4);
log.info("预期结果: {}", expectedResultString4);
log.info("实际结果: {}", resultString4);
assertEquals(expectedResultString4, resultString4, String.format("转换为蛇形命名%s失败", params.get("keyFormat")));
// 5. 转换为短横线命名
System.out.println();
log.info("========== 转换为短横线命名 ==========");
params.put("keyFormat", "kebabcase");
log.info("输入参数:");
log.info(" - 输入Map: {}", inputMap);
log.info(" - 键名格式转换: {}", params.get("keyFormat"));
log.info(" - 注意: 短横杠在全大写中,不做处理");
// 执行测试
Object result5 = FormatUtil.kvMapping(inputMap, params);
// 断言验证
String expectedResultString5 = """
{"user-password":"encrypted123","address":"北京市朝阳区","user-role":"ADMIN","user-name":"王五","phone":"13800138000","user-id":1001,"name":"李四","user-address":"上海市浦东新区","status":"ACTIVE"}
""".trim();
String resultString5 = JSON.toJSONString(result5);
log.info("预期结果: {}", expectedResultString5);
log.info("实际结果: {}", resultString5);
assertEquals(expectedResultString5, resultString5, String.format("转换为短横线命名%s失败", params.get("keyFormat")));
assertNotNull(result);
log.info("✓ 测试通过 - 键名格式转换正确");
}
@ -1226,13 +1077,13 @@ public class FormatUtilTest {
* <p><b>预计结果</b>过滤结果正确</p>
*/
@Test
@DisplayName("kvMapping - 数据过滤")
@DisplayName("kvMapping方法测试 - 数据过滤")
void testKvMapping_DataFiltering() {
System.out.println();
log.info("========== 数据KV映射模块测试 - 数据过滤 ==========");
// 输入参数
Map<String, Object> inputMap = new LinkedHashMap<>();
Map<String, Object> inputMap = new HashMap<>();
inputMap.put("name", "张三");
inputMap.put("age", 25);
inputMap.put("address", null);
@ -1253,10 +1104,7 @@ public class FormatUtilTest {
log.info("实际结果: {}", result);
// 断言验证
assertNotNull(result instanceof Map);
if(result instanceof Map) {
boolean flag = false;
}
assertNotNull(result);
log.info("✓ 测试通过 - 数据过滤正确");
}
@ -1268,13 +1116,13 @@ public class FormatUtilTest {
* <p><b>预计结果</b>排序结果正确</p>
*/
@Test
@DisplayName("kvMapping - 对 Map 对象进行分组排序 - 【已验证】")
@DisplayName("kvMapping方法测试 - 分组排序")
void testKvMapping_GroupingSorting() {
System.out.println();
log.info("========== 数据KV映射模块测试 - 分组排序 ==========");
// 输入参数
Map<String, Object> inputMap = new LinkedHashMap<>();
Map<String, Object> inputMap = new HashMap<>();
inputMap.put("z_key", "value3");
inputMap.put("a_key", "value1");
inputMap.put("m_key", "value2");
@ -1295,16 +1143,7 @@ public class FormatUtilTest {
log.info("实际结果: {}", result);
// 断言验证
Map<String, Object> expectedResult = new LinkedHashMap<>() {{
put("a_key", "value1");
put("m_key", "value2");
put("z_key", "value3");
}};
String expectedResultString = JSON.toJSONString(expectedResult);
String resultString = JSON.toJSONString(result);
log.info("预期结果:'{}'", expectedResult);
log.info("实际结果:'{}'", result);
assertEquals(expectedResultString, resultString, "排序失败");
assertNotNull(result);
log.info("✓ 测试通过 - 分组排序正确");
}
@ -1316,7 +1155,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>JSON格式正确</p>
*/
@Test
@DisplayName("kvMapping - 输出格式转换")
@DisplayName("kvMapping方法测试 - 输出格式转换")
void testKvMapping_OutputFormat() {
System.out.println();
log.info("========== 数据KV映射模块测试 - 输出格式转换 ==========");
@ -1357,7 +1196,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>组合处理结果正确</p>
*/
@Test
@DisplayName("boundaryCheck - 综合测试 - 多方法组合使用 - 【验证中】")
@DisplayName("综合测试 - 多方法组合使用")
void testMultipleMethods_CombinedUsage() {
System.out.println();
log.info("========== 综合测试 - 多方法组合使用 ==========");
@ -1420,7 +1259,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>所有转换正确完成</p>
*/
@Test
@DisplayName("coordinateConvert - 性能测试 - 大量数据处理 - 【验证中】")
@DisplayName("性能测试 - 大量数据处理")
void testPerformance_LargeDataProcessing() {
System.out.println();
log.info("========== 性能测试 - 大量数据处理 ==========");
@ -1433,9 +1272,11 @@ public class FormatUtilTest {
log.info(" - 目标格式: decimal");
log.info(" - 坐标模式: 116.0°23'45.67\" ~ 116.999°23'45.67\"");
log.info(" - 性能要求: 处理时间 < 5000 ms");
// 开始性能测试
long startTime = System.currentTimeMillis();
log.info("开始性能测试...");
for (int i = 0; i < testCount; i++) {
Map<String, Object> coordParams = new HashMap<>();
coordParams.put("fromType", "dms");
@ -1444,52 +1285,60 @@ public class FormatUtilTest {
Object result = FormatUtil.coordinateConvert("116." + i + "°23'45.67\"", coordParams);
assertNotNull(result);
}
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
// 实际结果
log.info("性能测试结果:");
log.info(" - 开始时间: {} ms", startTime);
log.info(" - 结束时间: {} ms", endTime);
log.info(" - 总耗时: {} ms", duration);
log.info(" - 平均每个转换耗时: {} ms", (double)duration / testCount);
// 预期结果
log.info("预期结果: 处理时间 < 100 ms");
log.info("预期结果: 处理时间 < 5000 ms");
// 断言验证
assertTrue(duration < 100, "性能测试应在0.1秒内完成");
assertTrue(duration < 5000, "性能测试应在5秒内完成");
log.info("✓ 测试通过 - 性能表现符合要求");
}
/**
* 默认参数值
* 异常处理测试 - 无效参数组合
*
* <p><b>测试目的</b>验证方法对无效参数组合的容错能力</p>
* <p><b>测试场景</b>提供相互冲突的参数</p>
* <p><b>预计结果</b>返回合理的默认值</p>
* <p><b>预计结果</b>返回合理的错误信息或默认值</p>
*/
@Test
@DisplayName("formatTime - 默认参数值 - 【已验证】")
@DisplayName("异常处理测试 - 无效参数组合")
void testErrorHandling_InvalidParameterCombination() {
System.out.println();
log.info("========== 默认参数值 ==========");
log.info("========== 异常处理测试 - 无效参数组合 ==========");
// 输入参数
String inputTime = "2024-01-15";
params.put("fromFormat", "yyyy-MM-dd");
params.put("toFormat", "HH:mm:ss");
log.info("输入参数:");
log.info(" - 输入时间: {}", inputTime);
log.info(" - 源格式: {}", params.get("fromFormat"));
log.info(" - 目标格式: {}", params.get("toFormat"));
log.info(" - 注意: 日期格式到时间格式的无效转换");
// 预期结果
log.info("预期结果: 返回合理的错误信息或默认值");
// 执行测试
Object result = FormatUtil.formatTime(inputTime, params);
// 实际结果
log.info("实际结果: {}", result);
// 断言验证
String expectedResult = "00:00:00";
log.info("预期结果: '{}'", expectedResult);
log.info("实际结果: '{}'", result);
assertEquals(expectedResult, result);
assertNotNull(result);
log.info("✓ 测试通过 - 异常处理正确");
}
@ -1501,7 +1350,7 @@ public class FormatUtilTest {
* <p><b>预计结果</b>正确处理或返回错误信息</p>
*/
@Test
@DisplayName("boundaryCheck - 边界值测试 - 极值输入 - 【验证中】")
@DisplayName("边界值测试 - 极值输入")
void testBoundaryValues_ExtremeInputs() {
System.out.println();
log.info("========== 边界值测试 - 极值输入 ==========");