76 lines
3.7 KiB
Java
76 lines
3.7 KiB
Java
package com.yunhai.cms.theme;
|
||
|
||
import java.util.List;
|
||
import java.util.function.Predicate;
|
||
|
||
/**
|
||
* 主题包规范校验(W1 重构点,方案 §5.5:校验语义收敛于本类,Registry 与 PackageService 共用,
|
||
* 杜绝两套校验漂移)。原 ThemeRegistry.validate 的规则原文平移:
|
||
* specVersion=1、name 规范、name=目录名、必备模板(home/list/detail/single)、
|
||
* fragments/head.html、param 规范、screenshot 存在。
|
||
* existsFn 判定资源存在:classpath 包用 ClassPathResource、外部包用 Files.exists(§5.4 步骤 1)。
|
||
*/
|
||
public final class ThemePackageValidator {
|
||
|
||
private ThemePackageValidator() {
|
||
}
|
||
|
||
/** 校验不通过抛 IllegalArgumentException(bad package 语义,Registry 剔除 + log.warn) */
|
||
public static void validate(ThemeInfo info, String dirName, Predicate<String> existsFn) {
|
||
if (info == null) {
|
||
throw new IllegalArgumentException("清单为空");
|
||
}
|
||
if (info.getSpecVersion() == null || info.getSpecVersion() != 1) {
|
||
throw new IllegalArgumentException("specVersion 必须为 1");
|
||
}
|
||
if (!ThemeRegistry.isValidName(info.getName())) {
|
||
throw new IllegalArgumentException("name 缺失或不符合命名规范:" + info.getName());
|
||
}
|
||
if (!info.getName().equals(dirName)) {
|
||
throw new IllegalArgumentException("name 与目录名不一致:" + dirName + " != " + info.getName());
|
||
}
|
||
for (String template : ThemeRegistry.requiredTemplates()) {
|
||
if (!existsFn.test(template)) {
|
||
throw new IllegalArgumentException("缺必备模板 " + template);
|
||
}
|
||
}
|
||
// fragments/ 目录存在性以 head.html 片段代替(jar 内目录项不可靠)
|
||
if (!existsFn.test("fragments/head.html")) {
|
||
throw new IllegalArgumentException("缺 fragments/head.html 公共片段");
|
||
}
|
||
validateParams(info);
|
||
String shot = info.screenshotPath();
|
||
if (!existsFn.test(shot)) {
|
||
throw new IllegalArgumentException("声明的 screenshot 不存在:" + shot);
|
||
}
|
||
}
|
||
|
||
/** param 规范(key/类型/重复/cssVar 仅 color/select 必带 options);不合法抛 IllegalArgumentException */
|
||
public static void validateParams(ThemeInfo info) {
|
||
List<ThemeParam> params = info.getParams();
|
||
List<String> seen = new java.util.ArrayList<>();
|
||
for (ThemeParam p : params) {
|
||
if (p.getKey() == null || !ThemeParam.KEY_PATTERN.matcher(p.getKey()).matches()) {
|
||
throw new IllegalArgumentException("param key 非法:" + p.getKey());
|
||
}
|
||
if (seen.contains(p.getKey())) {
|
||
throw new IllegalArgumentException("param key 重复:" + p.getKey());
|
||
}
|
||
seen.add(p.getKey());
|
||
String type = p.getType();
|
||
boolean knownType = ThemeParam.TYPE_COLOR.equals(type) || ThemeParam.TYPE_IMAGE.equals(type)
|
||
|| ThemeParam.TYPE_SELECT.equals(type) || ThemeParam.TYPE_TEXT.equals(type);
|
||
if (!knownType) {
|
||
throw new IllegalArgumentException("param " + p.getKey() + " 类型非法:" + type);
|
||
}
|
||
if (p.getCssVar() != null && !p.getCssVar().isEmpty() && !ThemeParam.TYPE_COLOR.equals(type)) {
|
||
throw new IllegalArgumentException("cssVar 仅允许 color 类型参数:" + p.getKey());
|
||
}
|
||
if (ThemeParam.TYPE_SELECT.equals(type)
|
||
&& (p.getOptions() == null || p.getOptions().isEmpty())) {
|
||
throw new IllegalArgumentException("select 参数缺 options:" + p.getKey());
|
||
}
|
||
}
|
||
}
|
||
}
|