import org.apache.axis.message.MessageElement;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
// 時間格式:和你現有 FORMATTER 一致
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
private static final DateTimeFormatter FMT_FALLBACK = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public List<TreeNodeBean> transformTree(String userType) throws Exception {
// 1) 呼叫 WS,取回 XML 片段
WsGetTreeSubdirResponseWsGetTreeSubdirResult result = service.wsGetTreeSubdir(userType);
MessageElement[] anyArray = result.get_any();
if (anyArray == null || anyArray.length == 0) {
return List.of();
}
// 2) 直接把 MessageElement 當 DOM Element 使用
Element root = anyArray[0];
NodeList list = root.getElementsByTagName("TreeSubdir");
// 3) 解析成 flat list(沿用你的 Builder)
List<TreeNodeBean> flatList = new ArrayList<>(list.getLength());
for (int i = 0; i < list.getLength(); i++) {
Element e = (Element) list.item(i);
String sftPath = getChildText(e, "sft_path");
String iftSid = getChildText(e, "ift_sid");
String sftName = getChildText(e, "sft_name");
String iKBCount = getChildText(e, "iKBCount");
String dInit = getChildText(e, "dinit_time");
String dModi = getChildText(e, "dmodi_time");
String iftPrev = getChildText(e, "ift_prev");
TreeNodeBean child = new TreeNodeBean.Builder()
.ftSid(iftSid)
.ftName(sftName)
.parent(iftPrev)
.pathRaw(sftPath)
.pathParts(splitPathSafe(sftPath))
.kBCount(parseIntOrNull(iKBCount)) // 比 Integer.valueOf 更安全
.initTime(parseDateTimeSafely(dInit, FORMATTER)) // 允許空值/格式 fallback
.modiTime(parseDateTimeSafely(dModi, FORMATTER))
.build();
flatList.add(child);
}
// 4) 建樹(只用 iftPrev)
List<TreeNodeBean> roots = TreeUtils.buildTree(flatList);
// 5) (可選)sft_path 檢核 + 紀錄異常
Map<String, TreeNodeBean> idx = TreeUtils.buildIndex(flatList);
for (TreeNodeBean n : flatList) {
if (n.getFtPathRaw() != null && !n.getFtPathRaw().isBlank()) {
boolean ok = TreeUtils.validateSftPath(n, idx);
if (!ok) {
LOGGER.warn("sft_path 檢核失敗 id={} raw={} actual={}",
n.getIftSid(),
n.getFtPathRaw(),
TreeUtils.getPathIdsFromRoot(n, idx, false));
}
}
}
// 6) 按你的慣例:回傳第一個 root 的 children(只有一個 root 的前提)
return roots.isEmpty() ? List.of() : roots.get(0).getChildren();
}
/* ----------------- 工具函式 ----------------- */
private static String getChildText(Element parent, String tag) {
NodeList nl = parent.getElementsByTagName(tag);
if (nl == null || nl.getLength() == 0) return "";
String s = nl.item(0).getTextContent();
return s == null ? "" : s.trim();
}
private static List<String> splitPathSafe(String raw) {
if (raw == null) return List.of();
String s = raw.trim();
if (s.startsWith("\\")) s = s.substring(1);
if (s.endsWith("\\")) s = s.substring(0, s.length() - 1);
if (s.isEmpty()) return List.of();
String[] parts = s.split("\\\\");
List<String> out = new ArrayList<>(parts.length);
for (String p : parts) if (p != null && !p.isBlank()) out.add(p.trim());
return out;
}
private static Integer parseIntOrNull(String s) {
if (s == null || s.isBlank()) return null;
try { return Integer.parseInt(s.trim()); }
catch (NumberFormatException e) { return null; }
}
private static LocalDateTime parseDateTimeSafely(String s, DateTimeFormatter primary) {
if (s == null || s.isBlank()) return null;
String v = s.trim();
try { return LocalDateTime.parse(v, primary); }
catch (DateTimeParseException e1) {
try { return LocalDateTime.parse(v, FMT_FALLBACK); }
catch (DateTimeParseException e2) { return null; }
}
}
aW1wb3J0IG9yZy5hcGFjaGUuYXhpcy5tZXNzYWdlLk1lc3NhZ2VFbGVtZW50OwoKaW1wb3J0IG9yZy53M2MuZG9tLkVsZW1lbnQ7CgppbXBvcnQgb3JnLnczYy5kb20uTm9kZUxpc3Q7CgoKCmltcG9ydCBqYXZhLnRpbWUuTG9jYWxEYXRlVGltZTsKCmltcG9ydCBqYXZhLnRpbWUuZm9ybWF0LkRhdGVUaW1lRm9ybWF0dGVyOwoKaW1wb3J0IGphdmEudGltZS5mb3JtYXQuRGF0ZVRpbWVQYXJzZUV4Y2VwdGlvbjsKCmltcG9ydCBqYXZhLnV0aWwuKjsKCgoKLy8g5pmC6ZaT5qC85byP77ya5ZKM5L2g54++5pyJIEZPUk1BVFRFUiDkuIDoh7QKCnByaXZhdGUgc3RhdGljIGZpbmFsIERhdGVUaW1lRm9ybWF0dGVyIEZPUk1BVFRFUiAgPSBEYXRlVGltZUZvcm1hdHRlci5vZlBhdHRlcm4oInl5eXkvTU0vZGQgSEg6bW06c3MiKTsKCnByaXZhdGUgc3RhdGljIGZpbmFsIERhdGVUaW1lRm9ybWF0dGVyIEZNVF9GQUxMQkFDSyA9IERhdGVUaW1lRm9ybWF0dGVyLm9mUGF0dGVybigieXl5eS1NTS1kZCBISDptbTpzcyIpOwoKCgpwdWJsaWMgTGlzdDxUcmVlTm9kZUJlYW4+IHRyYW5zZm9ybVRyZWUoU3RyaW5nIHVzZXJUeXBlKSB0aHJvd3MgRXhjZXB0aW9uIHsKCiAgICAvLyAxKSDlkbzlj6sgV1PvvIzlj5blm54gWE1MIOeJh+autQoKICAgIFdzR2V0VHJlZVN1YmRpclJlc3BvbnNlV3NHZXRUcmVlU3ViZGlyUmVzdWx0IHJlc3VsdCA9IHNlcnZpY2Uud3NHZXRUcmVlU3ViZGlyKHVzZXJUeXBlKTsKCiAgICBNZXNzYWdlRWxlbWVudFtdIGFueUFycmF5ID0gcmVzdWx0LmdldF9hbnkoKTsKCiAgICBpZiAoYW55QXJyYXkgPT0gbnVsbCB8fCBhbnlBcnJheS5sZW5ndGggPT0gMCkgewoKICAgICAgICByZXR1cm4gTGlzdC5vZigpOwoKICAgIH0KCgoKICAgIC8vIDIpIOebtOaOpeaKiiBNZXNzYWdlRWxlbWVudCDnlbYgRE9NIEVsZW1lbnQg5L2/55SoCgogICAgRWxlbWVudCByb290ID0gYW55QXJyYXlbMF07CgogICAgTm9kZUxpc3QgbGlzdCA9IHJvb3QuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIlRyZWVTdWJkaXIiKTsKCgoKICAgIC8vIDMpIOino+aekOaIkCBmbGF0IGxpc3TvvIjmsr/nlKjkvaDnmoQgQnVpbGRlcu+8iQoKICAgIExpc3Q8VHJlZU5vZGVCZWFuPiBmbGF0TGlzdCA9IG5ldyBBcnJheUxpc3Q8PihsaXN0LmdldExlbmd0aCgpKTsKCiAgICBmb3IgKGludCBpID0gMDsgaSA8IGxpc3QuZ2V0TGVuZ3RoKCk7IGkrKykgewoKICAgICAgICBFbGVtZW50IGUgPSAoRWxlbWVudCkgbGlzdC5pdGVtKGkpOwoKCgogICAgICAgIFN0cmluZyBzZnRQYXRoICA9IGdldENoaWxkVGV4dChlLCAic2Z0X3BhdGgiKTsKCiAgICAgICAgU3RyaW5nIGlmdFNpZCAgID0gZ2V0Q2hpbGRUZXh0KGUsICJpZnRfc2lkIik7CgogICAgICAgIFN0cmluZyBzZnROYW1lICA9IGdldENoaWxkVGV4dChlLCAic2Z0X25hbWUiKTsKCiAgICAgICAgU3RyaW5nIGlLQkNvdW50ID0gZ2V0Q2hpbGRUZXh0KGUsICJpS0JDb3VudCIpOwoKICAgICAgICBTdHJpbmcgZEluaXQgICAgPSBnZXRDaGlsZFRleHQoZSwgImRpbml0X3RpbWUiKTsKCiAgICAgICAgU3RyaW5nIGRNb2RpICAgID0gZ2V0Q2hpbGRUZXh0KGUsICJkbW9kaV90aW1lIik7CgogICAgICAgIFN0cmluZyBpZnRQcmV2ICA9IGdldENoaWxkVGV4dChlLCAiaWZ0X3ByZXYiKTsKCgoKICAgICAgICBUcmVlTm9kZUJlYW4gY2hpbGQgPSBuZXcgVHJlZU5vZGVCZWFuLkJ1aWxkZXIoKQoKICAgICAgICAgICAgICAgIC5mdFNpZChpZnRTaWQpCgogICAgICAgICAgICAgICAgLmZ0TmFtZShzZnROYW1lKQoKICAgICAgICAgICAgICAgIC5wYXJlbnQoaWZ0UHJldikKCiAgICAgICAgICAgICAgICAucGF0aFJhdyhzZnRQYXRoKQoKICAgICAgICAgICAgICAgIC5wYXRoUGFydHMoc3BsaXRQYXRoU2FmZShzZnRQYXRoKSkKCiAgICAgICAgICAgICAgICAua0JDb3VudChwYXJzZUludE9yTnVsbChpS0JDb3VudCkpICAgICAgICAgICAgICAgICAvLyDmr5QgSW50ZWdlci52YWx1ZU9mIOabtOWuieWFqAoKICAgICAgICAgICAgICAgIC5pbml0VGltZShwYXJzZURhdGVUaW1lU2FmZWx5KGRJbml0LCBGT1JNQVRURVIpKSAgIC8vIOWFgeioseepuuWAvC/moLzlvI8gZmFsbGJhY2sKCiAgICAgICAgICAgICAgICAubW9kaVRpbWUocGFyc2VEYXRlVGltZVNhZmVseShkTW9kaSwgRk9STUFUVEVSKSkKCiAgICAgICAgICAgICAgICAuYnVpbGQoKTsKCgoKICAgICAgICBmbGF0TGlzdC5hZGQoY2hpbGQpOwoKICAgIH0KCgoKICAgIC8vIDQpIOW7uuaoue+8iOWPqueUqCBpZnRQcmV277yJCgogICAgTGlzdDxUcmVlTm9kZUJlYW4+IHJvb3RzID0gVHJlZVV0aWxzLmJ1aWxkVHJlZShmbGF0TGlzdCk7CgoKCiAgICAvLyA1KSDvvIjlj6/pgbjvvIlzZnRfcGF0aCDmqqLmoLggKyDntIDpjITnlbDluLgKCiAgICBNYXA8U3RyaW5nLCBUcmVlTm9kZUJlYW4+IGlkeCA9IFRyZWVVdGlscy5idWlsZEluZGV4KGZsYXRMaXN0KTsKCiAgICBmb3IgKFRyZWVOb2RlQmVhbiBuIDogZmxhdExpc3QpIHsKCiAgICAgICAgaWYgKG4uZ2V0RnRQYXRoUmF3KCkgIT0gbnVsbCAmJiAhbi5nZXRGdFBhdGhSYXcoKS5pc0JsYW5rKCkpIHsKCiAgICAgICAgICAgIGJvb2xlYW4gb2sgPSBUcmVlVXRpbHMudmFsaWRhdGVTZnRQYXRoKG4sIGlkeCk7CgogICAgICAgICAgICBpZiAoIW9rKSB7CgogICAgICAgICAgICAgICAgTE9HR0VSLndhcm4oInNmdF9wYXRoIOaqouaguOWkseaVlyBpZD17fSByYXc9e30gYWN0dWFsPXt9IiwKCiAgICAgICAgICAgICAgICAgICAgICAgIG4uZ2V0SWZ0U2lkKCksCgogICAgICAgICAgICAgICAgICAgICAgICBuLmdldEZ0UGF0aFJhdygpLAoKICAgICAgICAgICAgICAgICAgICAgICAgVHJlZVV0aWxzLmdldFBhdGhJZHNGcm9tUm9vdChuLCBpZHgsIGZhbHNlKSk7CgogICAgICAgICAgICB9CgogICAgICAgIH0KCiAgICB9CgoKCiAgICAvLyA2KSDmjInkvaDnmoTmhaPkvovvvJrlm57lgrPnrKzkuIDlgIsgcm9vdCDnmoQgY2hpbGRyZW7vvIjlj6rmnInkuIDlgIsgcm9vdCDnmoTliY3mj5DvvIkKCiAgICByZXR1cm4gcm9vdHMuaXNFbXB0eSgpID8gTGlzdC5vZigpIDogcm9vdHMuZ2V0KDApLmdldENoaWxkcmVuKCk7Cgp9CgoKCi8qIC0tLS0tLS0tLS0tLS0tLS0tIOW3peWFt+WHveW8jyAtLS0tLS0tLS0tLS0tLS0tLSAqLwoKCgpwcml2YXRlIHN0YXRpYyBTdHJpbmcgZ2V0Q2hpbGRUZXh0KEVsZW1lbnQgcGFyZW50LCBTdHJpbmcgdGFnKSB7CgogICAgTm9kZUxpc3QgbmwgPSBwYXJlbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUodGFnKTsKCiAgICBpZiAobmwgPT0gbnVsbCB8fCBubC5nZXRMZW5ndGgoKSA9PSAwKSByZXR1cm4gIiI7CgogICAgU3RyaW5nIHMgPSBubC5pdGVtKDApLmdldFRleHRDb250ZW50KCk7CgogICAgcmV0dXJuIHMgPT0gbnVsbCA/ICIiIDogcy50cmltKCk7Cgp9CgoKCnByaXZhdGUgc3RhdGljIExpc3Q8U3RyaW5nPiBzcGxpdFBhdGhTYWZlKFN0cmluZyByYXcpIHsKCiAgICBpZiAocmF3ID09IG51bGwpIHJldHVybiBMaXN0Lm9mKCk7CgogICAgU3RyaW5nIHMgPSByYXcudHJpbSgpOwoKICAgIGlmIChzLnN0YXJ0c1dpdGgoIlxcIikpIHMgPSBzLnN1YnN0cmluZygxKTsKCiAgICBpZiAocy5lbmRzV2l0aCgiXFwiKSkgICBzID0gcy5zdWJzdHJpbmcoMCwgcy5sZW5ndGgoKSAtIDEpOwoKICAgIGlmIChzLmlzRW1wdHkoKSkgcmV0dXJuIExpc3Qub2YoKTsKCiAgICBTdHJpbmdbXSBwYXJ0cyA9IHMuc3BsaXQoIlxcXFwiKTsKCiAgICBMaXN0PFN0cmluZz4gb3V0ID0gbmV3IEFycmF5TGlzdDw+KHBhcnRzLmxlbmd0aCk7CgogICAgZm9yIChTdHJpbmcgcCA6IHBhcnRzKSBpZiAocCAhPSBudWxsICYmICFwLmlzQmxhbmsoKSkgb3V0LmFkZChwLnRyaW0oKSk7CgogICAgcmV0dXJuIG91dDsKCn0KCgoKcHJpdmF0ZSBzdGF0aWMgSW50ZWdlciBwYXJzZUludE9yTnVsbChTdHJpbmcgcykgewoKICAgIGlmIChzID09IG51bGwgfHwgcy5pc0JsYW5rKCkpIHJldHVybiBudWxsOwoKICAgIHRyeSB7IHJldHVybiBJbnRlZ2VyLnBhcnNlSW50KHMudHJpbSgpKTsgfQoKICAgIGNhdGNoIChOdW1iZXJGb3JtYXRFeGNlcHRpb24gZSkgeyByZXR1cm4gbnVsbDsgfQoKfQoKCgpwcml2YXRlIHN0YXRpYyBMb2NhbERhdGVUaW1lIHBhcnNlRGF0ZVRpbWVTYWZlbHkoU3RyaW5nIHMsIERhdGVUaW1lRm9ybWF0dGVyIHByaW1hcnkpIHsKCiAgICBpZiAocyA9PSBudWxsIHx8IHMuaXNCbGFuaygpKSByZXR1cm4gbnVsbDsKCiAgICBTdHJpbmcgdiA9IHMudHJpbSgpOwoKICAgIHRyeSB7IHJldHVybiBMb2NhbERhdGVUaW1lLnBhcnNlKHYsIHByaW1hcnkpOyB9CgogICAgY2F0Y2ggKERhdGVUaW1lUGFyc2VFeGNlcHRpb24gZTEpIHsKCiAgICAgICAgdHJ5IHsgcmV0dXJuIExvY2FsRGF0ZVRpbWUucGFyc2UodiwgRk1UX0ZBTExCQUNLKTsgfQoKICAgICAgICBjYXRjaCAoRGF0ZVRpbWVQYXJzZUV4Y2VwdGlvbiBlMikgeyByZXR1cm4gbnVsbDsgfQoKICAgIH0KCn0K