Skip to content

Commit eb138d4

Browse files
committed
feat(RemoteWordMap): 新增远程单词映射服务功能
- 实现从远程URL获取单词映射的fetchRemoteWordMap方法 - 添加mergeRemoteWordMap方法合并远程和本地映射 - 提供validateRemoteUrl方法验证URL可访问性 - 包含完整的单元测试覆盖核心功能 -
1 parent a14dcfd commit eb138d4

File tree

2 files changed

+249
-0
lines changed

2 files changed

+249
-0
lines changed
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package com.star.easydoc.service;
2+
3+
import java.io.BufferedReader;
4+
import java.io.IOException;
5+
import java.io.InputStreamReader;
6+
import java.net.HttpURLConnection;
7+
import java.net.URL;
8+
import java.nio.charset.StandardCharsets;
9+
import java.util.LinkedHashMap;
10+
import java.util.Map;
11+
12+
import com.intellij.openapi.diagnostic.Logger;
13+
14+
/**
15+
* 远程单词映射服务
16+
*
17+
* @author wangchao
18+
*/
19+
public class RemoteWordMapService {
20+
21+
private static final Logger LOGGER = Logger.getInstance(RemoteWordMapService.class);
22+
private static final int CONNECT_TIMEOUT = 5000; // 5秒连接超时
23+
private static final int READ_TIMEOUT = 10000; // 10秒读取超时
24+
25+
/**
26+
* 从远程URL获取单词映射
27+
*
28+
* @param url 远程URL
29+
* @return 单词映射Map,如果获取失败返回空Map
30+
*/
31+
public static Map<String, String> fetchRemoteWordMap(String url) {
32+
Map<String, String> wordMap = new LinkedHashMap<>();
33+
34+
if (url == null || url.trim().isEmpty()) {
35+
LOGGER.warn("Remote word map URL is empty");
36+
return wordMap;
37+
}
38+
39+
try {
40+
LOGGER.info("Fetching remote word map from: " + url);
41+
42+
URL remoteUrl = new URL(url.trim());
43+
HttpURLConnection connection = (HttpURLConnection) remoteUrl.openConnection();
44+
45+
// 设置请求属性
46+
connection.setRequestMethod("GET");
47+
connection.setConnectTimeout(CONNECT_TIMEOUT);
48+
connection.setReadTimeout(READ_TIMEOUT);
49+
connection.setRequestProperty("User-Agent", "EasyJavaDoc-Plugin");
50+
51+
// 检查响应码
52+
int responseCode = connection.getResponseCode();
53+
if (responseCode != HttpURLConnection.HTTP_OK) {
54+
LOGGER.warn("Failed to fetch remote word map, HTTP response code: " + responseCode);
55+
return wordMap;
56+
}
57+
58+
// 读取响应内容
59+
try (BufferedReader reader = new BufferedReader(
60+
new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
61+
62+
String line;
63+
int lineNumber = 0;
64+
while ((line = reader.readLine()) != null) {
65+
lineNumber++;
66+
line = line.trim();
67+
68+
// 跳过空行和注释行
69+
if (line.isEmpty() || line.startsWith("#") || line.startsWith("//")) {
70+
continue;
71+
}
72+
73+
// 解析键值对
74+
if (line.contains("=")) {
75+
String[] parts = line.split("=", 2);
76+
if (parts.length == 2) {
77+
String key = parts[0].trim();
78+
String value = parts[1].trim();
79+
80+
if (!key.isEmpty() && !value.isEmpty()) {
81+
wordMap.put(key, value);
82+
LOGGER.debug("Loaded word mapping: " + key + " -> " + value);
83+
}
84+
} else {
85+
LOGGER.warn("Invalid word mapping format at line " + lineNumber + ": " + line);
86+
}
87+
} else {
88+
LOGGER.warn("Invalid word mapping format at line " + lineNumber + ": " + line);
89+
}
90+
}
91+
}
92+
93+
LOGGER.info("Successfully loaded " + wordMap.size() + " word mappings from remote URL");
94+
95+
} catch (IOException e) {
96+
LOGGER.error("Failed to fetch remote word map from URL: " + url, e);
97+
} catch (Exception e) {
98+
LOGGER.error("Unexpected error while fetching remote word map", e);
99+
}
100+
101+
return wordMap;
102+
}
103+
104+
/**
105+
* 合并远程单词映射到本地映射
106+
* 远程映射会覆盖本地相同key的映射
107+
*
108+
* @param localWordMap 本地单词映射
109+
* @param remoteUrl 远程URL
110+
* @return 合并后的单词映射
111+
*/
112+
public static Map<String, String> mergeRemoteWordMap(Map<String, String> localWordMap, String remoteUrl) {
113+
Map<String, String> mergedMap = new LinkedHashMap<>();
114+
115+
// 先添加本地映射
116+
if (localWordMap != null) {
117+
mergedMap.putAll(localWordMap);
118+
}
119+
120+
// 获取远程映射并覆盖本地映射
121+
Map<String, String> remoteWordMap = fetchRemoteWordMap(remoteUrl);
122+
if (!remoteWordMap.isEmpty()) {
123+
int overwriteCount = 0;
124+
for (Map.Entry<String, String> entry : remoteWordMap.entrySet()) {
125+
if (mergedMap.containsKey(entry.getKey())) {
126+
overwriteCount++;
127+
}
128+
mergedMap.put(entry.getKey(), entry.getValue());
129+
}
130+
131+
LOGGER.info("Merged remote word map: " + remoteWordMap.size() + " remote mappings, "
132+
+ overwriteCount + " local mappings overwritten");
133+
}
134+
135+
return mergedMap;
136+
}
137+
138+
/**
139+
* 验证远程URL是否可访问
140+
*
141+
* @param url 远程URL
142+
* @return true表示可访问,false表示不可访问
143+
*/
144+
public static boolean validateRemoteUrl(String url) {
145+
if (url == null || url.trim().isEmpty()) {
146+
return false;
147+
}
148+
149+
try {
150+
URL remoteUrl = new URL(url.trim());
151+
HttpURLConnection connection = (HttpURLConnection) remoteUrl.openConnection();
152+
connection.setRequestMethod("HEAD");
153+
connection.setConnectTimeout(CONNECT_TIMEOUT);
154+
connection.setReadTimeout(READ_TIMEOUT);
155+
connection.setRequestProperty("User-Agent", "EasyJavaDoc-Plugin");
156+
157+
int responseCode = connection.getResponseCode();
158+
return responseCode == HttpURLConnection.HTTP_OK;
159+
160+
} catch (Exception e) {
161+
LOGGER.debug("Remote URL validation failed for: " + url, e);
162+
return false;
163+
}
164+
}
165+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package com.star.easydoc.service;
2+
3+
import java.util.Map;
4+
5+
import org.junit.Test;
6+
import static org.junit.Assert.*;
7+
8+
/**
9+
* 远程单词映射服务测试
10+
*/
11+
public class RemoteWordMapServiceTest {
12+
13+
@Test
14+
public void testValidateRemoteUrl() {
15+
// Test with null and empty URL
16+
assertFalse(RemoteWordMapService.validateRemoteUrl(null));
17+
assertFalse(RemoteWordMapService.validateRemoteUrl(""));
18+
assertFalse(RemoteWordMapService.validateRemoteUrl(" "));
19+
20+
// Test with invalid URL
21+
assertFalse(RemoteWordMapService.validateRemoteUrl("invalid-url"));
22+
23+
// Test with a valid URL (this will make an actual HTTP request)
24+
// Note: This test requires internet connection
25+
String validUrl = "https://raw.githubusercontent.com/pig-mesh/easy_javadoc/refs/heads/master/keywords.txt";
26+
assertTrue("Valid URL should be accessible", RemoteWordMapService.validateRemoteUrl(validUrl));
27+
}
28+
29+
@Test
30+
public void testFetchRemoteWordMap() {
31+
// Test with null and empty URL
32+
Map<String, String> result1 = RemoteWordMapService.fetchRemoteWordMap(null);
33+
assertTrue("Should return empty map for null URL", result1.isEmpty());
34+
35+
Map<String, String> result2 = RemoteWordMapService.fetchRemoteWordMap("");
36+
assertTrue("Should return empty map for empty URL", result2.isEmpty());
37+
38+
// Test with valid URL (this will make an actual HTTP request)
39+
// Note: This test requires internet connection
40+
String validUrl = "https://raw.githubusercontent.com/pig-mesh/easy_javadoc/refs/heads/master/keywords.txt";
41+
Map<String, String> result3 = RemoteWordMapService.fetchRemoteWordMap(validUrl);
42+
assertNotNull("Should return non-null map", result3);
43+
44+
// Check that expected mappings are present
45+
assertTrue("Should contain 'dataset' mapping", result3.containsKey("dataset"));
46+
assertEquals("Should map 'dataset' to '知识库'", "知识库", result3.get("dataset"));
47+
48+
assertTrue("Should contain 'embedding' mapping", result3.containsKey("embedding"));
49+
assertEquals("Should map 'embedding' to '向量'", "向量", result3.get("embedding"));
50+
51+
assertTrue("Should contain 'status' mapping", result3.containsKey("status"));
52+
assertEquals("Should map 'status' to '状态'", "状态", result3.get("status"));
53+
54+
assertTrue("Should contain 'usage' mapping", result3.containsKey("usage"));
55+
assertEquals("Should map 'usage' to '用量'", "用量", result3.get("usage"));
56+
}
57+
58+
@Test
59+
public void testMergeRemoteWordMap() {
60+
// Create local word map
61+
Map<String, String> localMap = new java.util.HashMap<>();
62+
localMap.put("local1", "本地1");
63+
localMap.put("local2", "本地2");
64+
localMap.put("dataset", "本地数据集"); // This should be overridden by remote
65+
66+
// Test with valid URL (this will make an actual HTTP request)
67+
String validUrl = "https://raw.githubusercontent.com/pig-mesh/easy_javadoc/refs/heads/master/keywords.txt";
68+
Map<String, String> mergedMap = RemoteWordMapService.mergeRemoteWordMap(localMap, validUrl);
69+
70+
assertNotNull("Should return non-null merged map", mergedMap);
71+
72+
// Check that local mappings are preserved
73+
assertEquals("Should preserve local1 mapping", "本地1", mergedMap.get("local1"));
74+
assertEquals("Should preserve local2 mapping", "本地2", mergedMap.get("local2"));
75+
76+
// Check that remote mappings override local ones
77+
assertEquals("Remote should override local dataset mapping", "知识库", mergedMap.get("dataset"));
78+
79+
// Check that remote mappings are added
80+
assertEquals("Should include remote embedding mapping", "向量", mergedMap.get("embedding"));
81+
assertEquals("Should include remote status mapping", "状态", mergedMap.get("status"));
82+
assertEquals("Should include remote usage mapping", "用量", mergedMap.get("usage"));
83+
}
84+
}

0 commit comments

Comments
 (0)