添加读取CTBT核素类

This commit is contained in:
duwenyuan 2025-09-28 10:50:02 +08:00
parent ba3fffe719
commit 167f3dd19b

View File

@ -0,0 +1,264 @@
package org.jeecg.common.util;
import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
@Slf4j
public class RadionuclideUtil {
// 存储所有分类的核素数据分类名称核素列表
private static final Map<String, List<String>> radionuclideData = new HashMap<>();
// 反向映射核素到分类的映射用于快速查询
private static final Map<String, String> nuclideToSection = new HashMap<>();
// 初始化标志
private static boolean initialized = false;
private static Integer dayValue;
/**
* 初始化方法从XML文件加载数据
*
* @param xmlFilePath XML文件路径
* @throws Exception 加载过程中发生的异常
*/
public static synchronized void initialize(String xmlFilePath)
throws ParserConfigurationException, SAXException, IOException {
File xmlFile = new File(xmlFilePath);
if (!xmlFile.exists()) {
throw new FileNotFoundException("XML file not found: " + xmlFilePath);
}
if (!xmlFile.isFile()) {
throw new IOException("Path is not a file: " + xmlFilePath);
}
initializeInternal(xmlFile);
}
/**
* 重载初始化方法支持从输入流加载数据
*
* @param xmlInputStream XML输入流
* @throws Exception 加载过程中发生的异常
*/
public static synchronized void initialize(InputStream xmlInputStream)
throws ParserConfigurationException, SAXException, IOException {
if (xmlInputStream == null) {
throw new IllegalArgumentException("Input stream cannot be null");
}
initializeInternal(xmlInputStream);
}
/**
* 内部初始化方法实际执行XML解析逻辑
*/
private static void initializeInternal(Object source)
throws ParserConfigurationException, SAXException, IOException {
if (initialized) {
return;
}
radionuclideData.clear();
nuclideToSection.clear();
dayValue = null;
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc;
if (source instanceof File) {
doc = dBuilder.parse((File) source);
} else if (source instanceof InputStream) {
doc = dBuilder.parse((InputStream) source);
} else {
throw new IllegalArgumentException("Unsupported source type");
}
doc.getDocumentElement().normalize();
NodeList sectionList = doc.getElementsByTagName("section");
for (int i = 0; i < sectionList.getLength(); i++) {
Node sectionNode = sectionList.item(i);
if (sectionNode.getNodeType() == Node.ELEMENT_NODE) {
Element sectionElement = (Element) sectionNode;
String sectionName = sectionElement.getAttribute("name");
if (sectionName == null || sectionName.trim().isEmpty()) {
log.error("Skipping section with empty name attribute");
continue;
}
if (radionuclideData.containsKey(sectionName)) {
log.error("Duplicate section name found: " + sectionName + ", skipping");
continue;
}
if ("Days".equals(sectionName)) {
// 只读取第一个value元素的值
NodeList valueList = sectionElement.getElementsByTagName("value");
if (valueList.getLength() > 0) {
Node valueNode = valueList.item(0);
if (valueNode.getNodeType() == Node.ELEMENT_NODE) {
try {
dayValue = Integer.parseInt(valueNode.getTextContent().trim());
} catch (NumberFormatException e) {
System.err.println("Invalid days format: " + valueNode.getTextContent());
}
}
} else {
System.err.println("Section 'Days' has no 'value' element");
}
} else {
Set<String> nuclideSet = new HashSet<>();
NodeList nuclideList = sectionElement.getElementsByTagName("nuclide");
for (int j = 0; j < nuclideList.getLength(); j++) {
Node nuclideNode = nuclideList.item(j);
if (nuclideNode.getNodeType() == Node.ELEMENT_NODE) {
String nuclideValue = nuclideNode.getTextContent().trim();
if (!nuclideValue.isEmpty()) {
if (!nuclideSet.add(nuclideValue)) {
System.out.println("Duplicate nuclide found in section " + sectionName + ": " + nuclideValue);
}
}
}
}
List<String> nuclides = new ArrayList<>(nuclideSet);
radionuclideData.put(sectionName, Collections.unmodifiableList(nuclides));
// 构建核素到分类的反向映射
for (String nuclide : nuclides) {
if (nuclideToSection.containsKey(nuclide)) {
System.out.println("Nuclide " + nuclide + " exists in multiple sections: " +
nuclideToSection.get(nuclide) + " and " + sectionName);
} else {
nuclideToSection.put(nuclide, sectionName);
}
}
}
}
}
initialized = true;
}
/**
* 获取天数值只返回一个值
*
* @return 天数如果未设置则返回null
*/
public static Integer getDayValue() {
checkInitialized();
return dayValue;
}
/**
* 获取指定分类的所有核素
*
* @param sectionName 分类名称
* @return 核素列表不可修改如果分类不存在则返回空列表
* @throws IllegalStateException 如果未初始化
*/
public static List<String> getNuclidesBySection(String sectionName) {
checkInitialized();
return radionuclideData.getOrDefault(sectionName, Collections.emptyList());
}
/**
* 获取所有分类名称
*
* @return 分类名称列表不可修改
* @throws IllegalStateException 如果未初始化
*/
public static List<String> getAllSections() {
checkInitialized();
return Collections.unmodifiableList(new ArrayList<>(radionuclideData.keySet()));
}
/**
* 获取所有核素不区分分类
*
* @return 所有核素的列表不可修改
* @throws IllegalStateException 如果未初始化
*/
public static List<String> getAllNuclides() {
checkInitialized();
// 汇总所有分类的核素并去重
Set<String> allNuclideSet = new HashSet<>();
for (List<String> nuclides : radionuclideData.values()) {
allNuclideSet.addAll(nuclides);
}
return Collections.unmodifiableList(new ArrayList<>(allNuclideSet));
}
/**
* 根据核素名获取其所属的分类
*
* @param nuclide 核素名称
* @return 核素所属的分类名称如果核素不存在则返回null
* @throws IllegalStateException 如果未初始化
*/
public static String getSectionByNuclide(String nuclide) {
checkInitialized();
if (nuclide == null || nuclide.trim().isEmpty()) {
return null;
}
return nuclideToSection.get(nuclide.trim());
}
/**
* 检查是否已初始化
*
* @throws IllegalStateException 如果未初始化
*/
private static void checkInitialized() {
if (!initialized) {
throw new IllegalStateException("RadionuclideManager 尚未初始化,请先调用 initialize() 方法");
}
}
public static void main(String[] args) {
try {
// 程序启动时初始化
RadionuclideUtil.initialize("F:\\Work_MDC\\AnalysisSystemForRadionuclide\\jeecg-boot-base-core\\src\\main\\resources\\ctbt_radionuclides.xml");
// 测试新添加的方法
String testNuclide1 = "K40";
System.out.println(testNuclide1 + " 所属类型: " + RadionuclideUtil.getSectionByNuclide(testNuclide1));
String testNuclide2 = "Cs137";
System.out.println(testNuclide2 + " 所属类型: " + RadionuclideUtil.getSectionByNuclide(testNuclide2));
String testNuclide3 = "Unknown";
System.out.println(testNuclide3 + " 所属类型: " + RadionuclideUtil.getSectionByNuclide(testNuclide3));
// 原有功能测试
System.out.println("\n所有分类: " + RadionuclideUtil.getAllSections());
String ctbtSection = "CTBTRADS";
System.out.println("\n" + ctbtSection + " 包含的核素数量: " +
RadionuclideUtil.getNuclidesBySection(ctbtSection).size());
String naturalSection = "NATURALRADS";
System.out.println(naturalSection + " 包含的核素: " +
RadionuclideUtil.getNuclidesBySection(naturalSection));
System.out.println("所有核素总数: " + RadionuclideUtil.getAllNuclides().size());
System.out.println("天数值: " + RadionuclideUtil.getDayValue());
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}