package com.smtaiserver.smtaiserver.core; import com.alibaba.druid.pool.DruidDataSource; import com.smtaiserver.smtaiserver.attach.SMTAIAttachMetricDef; import com.smtaiserver.smtaiserver.attach.SMTAIAttachTableDef; import com.smtaiserver.smtaiserver.database.SMTDatabase; import com.smtaiserver.smtaiserver.gismap.SMTGisMapLayerDef; import com.smtaiserver.smtaiserver.gismap.SMTMapOtypeDef; import com.smtaiserver.smtaiserver.gismap.SMTMapVPropDef; import com.smtaiserver.smtaiserver.gismap.tabledef.SMTMapTableDef; import com.smtaiserver.smtaiserver.gismap.theme.SMTMapThemeDef; import com.smtaiserver.smtaiserver.gismap.theme.SMTMapThemeTableDef; import com.smtaiserver.smtaiserver.javaai.ast.ASTQuestionReplace; import com.smtaiserver.smtaiserver.javaai.datasource.SMTDataSource; import com.smtaiserver.smtaiserver.javaai.jsonflow.core.SMTJsonFlowManager; import com.smtaiserver.smtaiserver.javaai.jsonflow.core.SMTJsonFlowScriptJet; import com.smtaiserver.smtaiserver.javaai.llm.core.SMTLLMConnect; import com.smtaiserver.smtaiserver.javaai.llm.core.SMTLLMFactory; import com.smtaiserver.smtaiserver.javaai.metrics.base.SMTDimensionDef; import com.smtaiserver.smtaiserver.javaai.metrics.base.SMTMetricsDef; import com.smtaiserver.smtaiserver.javaai.querydetail.SMTAIQueryDetail; import com.smtaiserver.smtaiserver.javaai.qwen.SMTQwenAgentManager; import com.smtaiserver.smtaiserver.javaai.qwen.SMTQwenApp; import com.smtaiserver.smtaiserver.javaai.sse.SMTSSEBroadcastChat; import com.smtservlet.core.SMTApp; import com.smtservlet.core.SMTApp.SMTEhCacheManagerInitialize; import com.smtservlet.util.Json; import com.smtservlet.util.SMTHttpClient; import com.smtservlet.util.SMTJsonWriter; import com.smtservlet.util.SMTStatic; import java.io.*; import java.net.URLEncoder; import java.sql.Connection; import java.sql.DriverManager; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.http.HttpSessionEvent; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.text.PDFTextStripper; import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.extractor.WordExtractor; import org.apache.poi.xwpf.extractor.XWPFWordExtractor; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.dom4j.Document; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import org.locationtech.proj4j.CoordinateTransform; import org.locationtech.proj4j.ProjCoordinate; import org.mozilla.javascript.ConsString; import org.mozilla.javascript.Context; import org.mozilla.javascript.Function; import org.mozilla.javascript.NativeArray; import org.mozilla.javascript.NativeObject; import org.mozilla.javascript.Undefined; import org.mozilla.javascript.Wrapper; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.ehcache.EhCacheCacheManager; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.multipart.MultipartFile; public class SMTAIServerApp extends SMTApp implements SMTEhCacheManagerInitialize,SMTApp.SMTSessionListenerEvent { private static class SessionChatStreamReply { public String _replyId; public Json _jsonReply; public SessionChatStreamReply(String replyId, Json jsonReply) { _replyId = replyId; _jsonReply = jsonReply; } } protected Json _jsonSwaggerApiDoc; protected DruidDataSource _dsDataSource; @Value("${hswater.logger.sql}") protected Boolean _logSQL; // 数据库连接信息,暂时和系统库一致,将来可以改成其他地方 @Value("${spring.datasource.driver-class-name}") protected String _dbDriver; @Value("${spring.datasource.url}") protected String _dbUrl; @Value("${spring.datasource.username}") protected String _dbUser; @Value("${spring.datasource.password}") protected String _dbPass; @Value("${spring.datasource.druid.validation-query}") protected String _dbAlidationQuery; @Value("${spring.datasource.druid.max-active}") protected int _dbMaxActive; @Value("${spring.datasource.druid.initial-size}") protected int _dbInitialSize; @Value("${spring.datasource.druid.min-idle}") protected int _dbMinIdle; @Value("${spring.datasource.druid.max-wait}") protected int _dbMaxWait; @Value("${spring.datasource.druid.time-between-eviction-runs-millis}") protected int _dbTimeBetweenEvictionRunsMillis; @Value("${spring.datasource.druid.min-evictable-idle-time-millis}") protected int _dbMinEvictableIdleTimeMillis; @Value("${spring.datasource.druid.test-while-idle}") protected boolean _dbTestWhileIdle; @Value("${spring.datasource.druid.test-on-borrow}") protected boolean _dbTestOnBorrow; @Value("${spring.datasource.druid.test-on-return}") protected boolean _dbTestOnReturn; @Value("${spring.datasource.druid.pool-prepared-statements}") protected boolean _dbPoolPreparedStatements; @Value("${spring.datasource.druid.max-pool-prepared-statement-per-connection-size}") protected int _dbMaxPoolPreparedStatementPerConnectionSize; @Value("${wiai.debug_mode}") protected boolean _isDebugMode; @Value("${wiai.table_data_source}") protected String _tableDataSource; protected SMTAIServerEncache _serverEncache; protected Map> _mapSess2AsyncProcId2Process = new HashMap<>(); protected Map _mapSess2ChatStreamReply = new HashMap<>(); protected SMTJsonFlowScriptJet _scriptEsprima = null; protected Function _funcEsprima = null; protected Object _lockScriptEsprima = new Object(); protected Map _mapUser2SMTSSEBroadcastChat = new HashMap<>(); private static Pattern _patGroupStep = Pattern.compile("(\\d+)\\s*(minutes|hours|days|months|years|month|hour|year|day|minute)"); private static Pattern _patGlobalMacro = Pattern.compile("\\{\\{\\{([\\w\\.]+)\\}\\}\\}"); private static Logger _logger = LogManager.getLogger(SMTQwenApp.class); private static Pattern _patIsNumber = Pattern.compile("^[1-9]\\d*$"); private static String[] _encacheIdList = { "GlobalConfig", "MetricsDefMap", "DataSourceMap", "DimensionMap", "QwenAgentManager", "AIQuestionReplace", "GISTransform", "queryDetailMap", "getLLMFactoryMap", "getGroupTypeMap", "getMapLayerDef", "getMapTableDefMap", "getMapVPropDefMap", "getMapThemeTableDefMap", "getMapThemeDefMap", "getAttachTableDefMap", "getAttachMetricDefMap" }; public static SMTAIServerApp getApp() { return (SMTAIServerApp)SMTApp._ThisPtr; } public String getDefaultLLMId() throws Exception { String defaultLLMId = System.getProperty("default_llm_id"); if(SMTStatic.isNullOrEmpty(defaultLLMId)) return (String)SMTAIServerApp.getApp().getGlobalConfig("llm.default.id"); return defaultLLMId; } public String getTableDataSource() { return _tableDataSource; } public boolean isAppDebugMode() { return _isDebugMode; } public SMTSSEBroadcastChat allocBroadcastChat(String userId) { synchronized(_mapUser2SMTSSEBroadcastChat) { SMTSSEBroadcastChat chat = _mapUser2SMTSSEBroadcastChat.get(userId); if(chat == null) { chat = new SMTSSEBroadcastChat(userId); _mapUser2SMTSSEBroadcastChat.put(userId, chat); } return chat; } } public SMTSSEBroadcastChat getBroadcastChat(String userId) { synchronized(_mapUser2SMTSSEBroadcastChat) { SMTSSEBroadcastChat chat = _mapUser2SMTSSEBroadcastChat.get(userId); return chat; } } public void setServiceEncache(SMTAIServerEncache serverEncache) { _serverEncache = serverEncache; } public Map> getMetricsMapGroupMap() throws Exception { return _serverEncache.queryMetricsMapGroup(); } public Map getMetricsMap(String groupId) throws Exception { Map> mapMapMetrics = _serverEncache.queryMetricsMapGroup(); Map mapResult = mapMapMetrics.get(groupId); if(mapResult == null) return new HashMap(); return mapResult; } public DruidDataSource createDruidDataSource(String driver, String dbUrl, String dbUser, String dbPass) { DruidDataSource dsDataSource = new DruidDataSource(); dsDataSource.setDriverClassName(driver); dsDataSource.setUrl(dbUrl); dsDataSource.setUsername(dbUser); dsDataSource.setPassword(dbPass); // dsDataSource.setValidationQuery(_dbAlidationQuery); dsDataSource.setMaxActive(_dbMaxActive); dsDataSource.setInitialSize(0); dsDataSource.setMinIdle(0); dsDataSource.setMaxWait(_dbMaxWait); dsDataSource.setTimeBetweenEvictionRunsMillis(_dbTimeBetweenEvictionRunsMillis); dsDataSource.setMinEvictableIdleTimeMillis(_dbMinEvictableIdleTimeMillis); dsDataSource.setTestWhileIdle(_dbTestWhileIdle); dsDataSource.setTestOnBorrow(_dbTestOnBorrow); dsDataSource.setTestOnReturn(_dbTestOnReturn); dsDataSource.setPoolPreparedStatements(_dbPoolPreparedStatements); dsDataSource.setMaxPoolPreparedStatementPerConnectionSize(_dbMaxPoolPreparedStatementPerConnectionSize); return dsDataSource; } @Override protected void onWebStartup(WebApplicationContext webApplicationContext) throws Exception { System.out.println("=====================================================>onWebStartup:你好"); _logger.info("=====================================================>onWebStartup:你好"); // 创建数据源 DruidDataSource dsDataSource = new DruidDataSource(); dsDataSource.setDriverClassName(_dbDriver); dsDataSource.setUrl(_dbUrl); dsDataSource.setUsername(_dbUser); dsDataSource.setPassword(_dbPass); dsDataSource.setValidationQuery(_dbAlidationQuery); dsDataSource.setMaxActive(_dbMaxActive); dsDataSource.setInitialSize(_dbInitialSize); dsDataSource.setMinIdle(_dbMinIdle); dsDataSource.setMaxWait(_dbMaxWait); dsDataSource.setTimeBetweenEvictionRunsMillis(_dbTimeBetweenEvictionRunsMillis); dsDataSource.setMinEvictableIdleTimeMillis(_dbMinEvictableIdleTimeMillis); dsDataSource.setTestWhileIdle(_dbTestWhileIdle); dsDataSource.setTestOnBorrow(_dbTestOnBorrow); dsDataSource.setTestOnReturn(_dbTestOnReturn); dsDataSource.setPoolPreparedStatements(_dbPoolPreparedStatements); dsDataSource.setMaxPoolPreparedStatementPerConnectionSize(_dbMaxPoolPreparedStatementPerConnectionSize); _dsDataSource = dsDataSource; super.onWebStartup(webApplicationContext); _serverEncache.getQueryDetailMap(); _serverEncache.getLLMFactoryMap(); _serverEncache.getMapLayerDef(); _serverEncache.getMapTableDefMap(); _serverEncache.getMapVPropDefMap(); _serverEncache.getMapThemeTableDefMap(); _serverEncache.getMapThemeDefMap(); _serverEncache.getAttachTableDefMap(); _serverEncache.getAttachMetricDefMap(); _serverEncache.getQwenAgentManager(); } public SMTMapTableDef getMapTableDef(String tableId) throws Exception { SMTMapTableDef tableDef = _serverEncache.getMapTableDefMap().get(tableId); if(tableDef == null) throw new Exception("can't find table id : " + tableId); return tableDef; } public SMTMapVPropDef getMapVPropDefMap(String OTYPE, String VPROP) throws Exception { SMTMapOtypeDef otypeDef = _serverEncache.getMapVPropDefMap().get(OTYPE); if(otypeDef == null) throw new Exception("can't get otype : " + OTYPE); SMTMapVPropDef vpropDef = otypeDef.getVPropDef(VPROP); return vpropDef; } public SMTMapOtypeDef getMapOTypeDef(String OTYPE) throws Exception { SMTMapOtypeDef otypeDef = _serverEncache.getMapVPropDefMap().get(OTYPE); return otypeDef; } public String esprimaJs2ASTStr(String code1) throws Exception { synchronized(_lockScriptEsprima) { if(_scriptEsprima == null) { // 创建esprima脚本引擎 _scriptEsprima = new SMTJsonFlowScriptJet(); Context cx = _scriptEsprima.entryContext(); try { InputStream is = SMTJsonFlowManager.class.getResourceAsStream("/javascript/esprima.min.js"); try { String code = SMTStatic.readTextStream(is); _scriptEsprima.executeScript(cx, code); _funcEsprima = _scriptEsprima.compileFunction(cx, "esprimaJs2AST", "function(code){return JSON.stringify(esprima.parse(code));};"); } finally { is.close(); } } finally { Context.exit(); } } Context cx = _scriptEsprima.entryContext(); try { String strJson = (String)_scriptEsprima.callFunction(cx, _funcEsprima, new Object[] {code1}); return strJson; } finally { Context.exit(); } } } public SMTDatabase allocDatabase() throws Exception { if(_dsDataSource == null) return null; Connection conn = _dsDataSource.getConnection(); return new SMTDatabase(conn); } public SMTDatabase allocNativeDatabase() throws Exception { Connection conn = DriverManager.getConnection(_dbUrl, _dbUser, _dbPass); return new SMTDatabase(conn); } public boolean isLogSQL() { return (_logSQL == null) ? false : _logSQL; } public void readSwaggerJson(SMTJsonWriter jsonWr) { for(Entry entry : this._mapName2RequestConfig.entrySet()) { String url = "/" + entry.getKey(); SMTRequestConfig requestConfig = entry.getValue(); if(requestConfig._jsonConfig == null) continue; Json jsonSwaggers = requestConfig._jsonConfig.safeGetJson("swaggers"); if(jsonSwaggers == null) continue; List listJsonSwagger = jsonSwaggers.asJsonList(); if(listJsonSwagger.size() > 0) { int index = 0; Json jsonSwagger = listJsonSwagger.get(index); jsonWr.addKeyRaw(url, jsonSwagger); } } } public synchronized Json readSwaggerApiDocJson() { if(_jsonSwaggerApiDoc == null) { Set setGroups = new HashSet(); SMTJsonWriter jsonWr = new SMTJsonWriter(false); jsonWr.addKeyValue("swagger", "2.0"); jsonWr.beginMap("info"); { jsonWr.addKeyValue("title", "Swagger操作"); jsonWr.addKeyValue("description", "WI水务智能系统Swagger操作页面"); jsonWr.addKeyValue("version", "1.0.0"); } jsonWr.endMap(); jsonWr.beginMap("paths"); for(Entry entry : this._mapName2RequestConfig.entrySet()) { String url = "/" + entry.getKey(); SMTRequestConfig requestConfig = entry.getValue(); if(requestConfig._jsonConfig == null) continue; Json jsonSwaggers = requestConfig._jsonConfig.safeGetJson("swaggers"); if(jsonSwaggers == null) continue; List listJsonSwagger = jsonSwaggers.asJsonList(); int count = listJsonSwagger.size(); for(int index = 0; index < count; index ++) { Json jsonSwagger = listJsonSwagger.get(index); jsonWr.beginMap(url + (count == 1 ? "" : String.format("?dummy=%d", index))); { String groupName = jsonSwagger.safeGetStr("group", null); if(!SMTStatic.isNullOrEmpty(groupName)) { jsonWr.addKeyValue("hwngroup", groupName); setGroups.add(groupName); } jsonWr.beginMap("post"); { // 设置入参类型 jsonWr.beginArray("consumes"); jsonWr.addKeyValue(null, jsonSwagger.safeGetStr("consumes", "application/x-www-form-urlencoded")); jsonWr.endArray(); // 设置出参类型 jsonWr.beginArray("produces"); jsonWr.addKeyValue(null, "application/json"); jsonWr.endArray(); // 设置返回类型 jsonWr.beginMap("responses"); { jsonWr.beginMap("200"); { jsonWr.addKeyValue("description", "OK"); jsonWr.beginMap("schema"); jsonWr.addKeyValue("type", "object"); Json jsonResponses = jsonSwagger.safeGetJson("responses"); if(jsonResponses != null) { jsonWr.beginMap("properties"); parseSwaggerRespnseJson(jsonResponses, jsonWr); jsonWr.endMap(); } jsonWr.endMap(); } jsonWr.endMap(); } jsonWr.endMap(); // 设置接口所属分组 jsonWr.addKeyRaw("tags", jsonSwagger.getJson("tags")); // 设置接口说明 jsonWr.addKeyValue("summary", jsonSwagger.getJson("title")); // 设置参数 jsonWr.beginArray("parameters"); Json jsonParams = jsonSwagger.safeGetJson("parameters"); if(jsonParams != null) { for(Json jsonParam : jsonParams.asJsonList()) { jsonWr.beginMap(null); { jsonWr.addKeyValue("in", "formData"); jsonWr.addKeyValue("name", jsonParam.getJson("name").asString()); jsonWr.addKeyValue("description", jsonParam.getJson("title").asString()); jsonWr.addKeyValue("required", jsonParam.safeGetBoolean("required", false)); jsonWr.addKeyValue("type", jsonParam.safeGetStr("type", "string")); String defValue = jsonParam.safeGetStr("default", null); if(!SMTStatic.isNullOrEmpty(defValue)) { jsonWr.addKeyValue("default", defValue); } } jsonWr.endMap(); } } jsonWr.endArray(); } jsonWr.endMap(); } jsonWr.endMap(); } } jsonWr.endMap(); jsonWr.beginArray("hwngroups"); for(String groupName : setGroups) { jsonWr.addKeyValue(null, groupName); } jsonWr.endArray(); _jsonSwaggerApiDoc = jsonWr.getRootJson(); } return _jsonSwaggerApiDoc; } private void parseSwaggerRespnseJson(Json jsonResponses, SMTJsonWriter jsonWr) { for(Json jsonResponse : jsonResponses.asJsonList()) { String type = jsonResponse.safeGetStr("type", "string"); String name = jsonResponse.getJson("name").asString(); String title = jsonResponse.safeGetStr("title", null); String defValue = jsonResponse.safeGetStr("default", null); boolean required = jsonResponse.safeGetBoolean("required", true); String subType = null; if(type.endsWith("[]")) { subType = type.substring(0, type.length() - 2); type = "array"; } jsonWr.beginMap(name); { jsonWr.addKeyValue("type", type); jsonWr.addKeyValue("required", required); if(!SMTStatic.isNullOrEmpty(defValue)) jsonWr.addKeyValue("default", title); if(!SMTStatic.isNullOrEmpty(title)) jsonWr.addKeyValue("description", title); if("array".equals(type)) { jsonWr.beginMap("items"); { jsonWr.addKeyValue("type", subType); if("object".equals(subType)) { jsonWr.beginMap("properties"); parseSwaggerRespnseJson(jsonResponse.getJson("children"), jsonWr); jsonWr.endMap(); } } jsonWr.endMap(); } else if("object".equals(type)) { jsonWr.beginMap("properties"); parseSwaggerRespnseJson(jsonResponse.getJson("children"), jsonWr); jsonWr.endMap(); } } jsonWr.endMap(); } } @Override public void initEhCacheManager(CacheManager cacheManager) { for(String encacheId : _encacheIdList) { cacheManager.addCache(new Cache(encacheId, 1000, false, true, 100, 100)); } } @Override public void clearEhCacheManager(CacheManager cacheManager) { for(String encacheId : _encacheIdList) { cacheManager.getCache(encacheId).removeAll(); } } public Object getGlobalConfig(String key, Object defValue) throws Exception { Map map = _serverEncache.queryGlobalConfigMap(); Object value = map.get(key); if(value == null) return defValue; return value; } public Object getGlobalConfig(String key) throws Exception { Object value = getGlobalConfig(key, null); if(value == null) throw new Exception("can't find global key : " + key); return value; } public Json queryAIPythonServer(String url, SMTJsonWriter jsonWr) throws Exception { String urlRoot = (String) getGlobalConfig("aipython.url"); SMTHttpClient web = new SMTHttpClient(); return web.postHttpBodyToJson(urlRoot + url, jsonWr.getFullJson(), null); } public String createQuestionSession(SMTDatabase db, String question, SMTJsonWriter jsonResult) throws Exception { String sessionId = SMTStatic.newUUID(); db.executeSQL( "INSERT INTO ai_question_session(session_id, create_time, question, result_json)VALUES(?, ?, ?, ?)", new Object[] { sessionId, new Date(), question, jsonResult.getFullJson() }); return sessionId; } @Override public void sessionCreated(HttpSessionEvent event) throws Exception { synchronized(_mapSess2AsyncProcId2Process) { _mapSess2AsyncProcId2Process.put(event.getSession().getId(), new HashMap<>()); } } @Override public void sessionDestroyed(HttpSessionEvent event) throws Exception { String sessionId = event.getSession().getId(); synchronized(_mapSess2AsyncProcId2Process) { _mapSess2AsyncProcId2Process.remove(sessionId); } synchronized(_mapSess2ChatStreamReply) { _mapSess2ChatStreamReply.remove(sessionId); } synchronized(_mapUser2SMTSSEBroadcastChat) { // 因为不知道所属用户,所以需要扫描一下用户 for(SMTSSEBroadcastChat chat : _mapUser2SMTSSEBroadcastChat.values()) { if(chat.removeSSEConnect(sessionId)) break; } } } public void clearChatStreamReply(String sessionId) { synchronized(_mapSess2ChatStreamReply) { _mapSess2ChatStreamReply.remove(sessionId); } } public void setChatStreamReply(String sessionId, String replyId, Json jsonReply) { synchronized(_mapSess2ChatStreamReply) { _mapSess2ChatStreamReply.put(sessionId, new SessionChatStreamReply(replyId, jsonReply)); } } public Json getChatStreamReply(String sessionId, String replyId) { SessionChatStreamReply reply = null; synchronized(_mapSess2ChatStreamReply) { reply = _mapSess2ChatStreamReply.get(sessionId); if(reply == null || !reply._replyId.equals(replyId)) return null; return reply._jsonReply; } } public void removeAsyncProcessText(String sessionId, String processId) { synchronized(_mapSess2AsyncProcId2Process) { Map mapId2Process = _mapSess2AsyncProcId2Process.get(sessionId); if(mapId2Process == null) return; mapId2Process.remove(processId); } } public void setAsyncProcessText(String sessionId, String processId, String text) { synchronized(_mapSess2AsyncProcId2Process) { Map mapId2Process = _mapSess2AsyncProcId2Process.get(sessionId); if(mapId2Process == null) return; mapId2Process.put(processId, text); } } public String getAsyncProcessText(String sessionId, String processId) { synchronized(_mapSess2AsyncProcId2Process) { Map mapId2Process = _mapSess2AsyncProcId2Process.get(sessionId); if(mapId2Process == null) return null; return mapId2Process.get(processId); } } public Map getDataSourceMap() throws Exception { return _serverEncache.queryDataSourceMap(); } public SMTDataSource getDataSource(String id) throws Exception { Map map = getDataSourceMap(); SMTDataSource result = map.get(id); if(result == null) throw new Exception("data source is not exist : " + id); return result; } public SMTDimensionDef getDimensionDef(String id) throws Exception { Map map = _serverEncache.queryDimensionMap(); SMTDimensionDef dimDef = map.get(id); if(dimDef == null) throw new Exception("can't find dimension def : " + id); return dimDef; } public Map getDimensionDefMap() throws Exception { return _serverEncache.queryDimensionMap(); } public String convGlobalMacroString(String str, Json jsonExtMacro) throws Exception { while(true) { boolean hasMatcher = false; Matcher m = _patGlobalMacro.matcher(str); String newStr = str; while(m.find()) { hasMatcher = true; String newValue = null; if(jsonExtMacro != null) newValue = jsonExtMacro.safeGetStr(m.group(1), null); if(newValue != null) { newStr = str.replace(m.group(), newValue); } else { newStr = str.replace(m.group(), (String)this.getGlobalConfig(m.group(1))); } } str = newStr; if(!hasMatcher) return newStr; } } public static String formatXmlToNoRootStr(Document doc) throws Exception { OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); format.setNewLineAfterDeclaration(false); format.setNewlines(true); format.setTrimText(false); ByteArrayOutputStream bos = new ByteArrayOutputStream(); XMLWriter writer= new XMLWriter(bos,format); writer.setEscapeText(true); writer.write(doc); writer.close(); String str = bos.toString("UTF-8"); int posS = str.indexOf(""); if(posS < 0) throw new Exception("can't find "); int posE = str.lastIndexOf(""); if(posE < 0) throw new Exception("can't find "); String[] lines = str.substring(posS + 6, posE).replace("\r\n", "\n").split("\n"); StringBuilder sb = new StringBuilder(); for(String line : lines) { if(line.trim().length() == 0) continue; sb.append(line + "\n"); } return sb.toString(); } public SMTQwenAgentManager getQwenAgentManager() throws Exception { return this._serverEncache.getQwenAgentManager(); } public int getOutputAITableMax() throws Exception { return SMTStatic.toInt(getGlobalConfig("ai_table_output.max_rows", "100")); } public void clearQwenAgentManager() throws Exception { EhCacheCacheManager springCacheManager = SMTApp.getBean(EhCacheCacheManager.class); if(springCacheManager != null) { CacheManager cacheManager = springCacheManager.getCacheManager(); cacheManager.getCache("QwenAgentManager").removeAll(); } } public static String convTimeStepToUnitStr(int unit, int value) { if(unit == 0) { int deltaDay = 24 * 60; if((value % deltaDay) == 0) return SMTStatic.toString(value / deltaDay) + " days"; if((value % 60) == 0) return SMTStatic.toString(value / 60) + " hours"; return SMTStatic.toString(value) + " minutes"; } else { if((value % 12) == 0) return SMTStatic.toString(value / 12) + " years"; return SMTStatic.toString(value) + " months"; } } public static String convTimeStepToStr(int unit, int value) { if(unit == 0) { int deltaDay = 24 * 60; if((value % deltaDay) == 0) return SMTStatic.toString(value / deltaDay) + "天"; if((value % 60) == 0) return SMTStatic.toString(value / 60) + "时"; return SMTStatic.toString(value) + "分"; } else { if((value % 12) == 0) return SMTStatic.toString(value / 12) + "年"; return SMTStatic.toString(value) + "月"; } } public static int[] convStrToTimeStep(String sTimeStep) { int _timeStepUnit = 0; int _timeStepValue = 0; Matcher m = _patGroupStep.matcher(sTimeStep); if(!m.find()) return null; int groupStep = SMTStatic.toInt(m.group(1)); String sGroupUnit = m.group(2); if("minutes".equals(sGroupUnit)) { _timeStepUnit = 0; _timeStepValue = groupStep; } else if("hours".equals(sGroupUnit) || "hour".equals(sGroupUnit)) { _timeStepUnit = 0; _timeStepValue = groupStep * 60; } else if("days".equals(sGroupUnit) || "day".equals(sGroupUnit)) { _timeStepUnit = 0; _timeStepValue = groupStep * 60 * 24; } else if("months".equals(sGroupUnit) || "month".equals(sGroupUnit)) { _timeStepUnit = 1; _timeStepValue = groupStep; } else if("years".equals(sGroupUnit) || "year".equals(sGroupUnit)) { _timeStepUnit = 1; _timeStepValue = groupStep * 12; } return new int[] {_timeStepUnit, _timeStepValue}; } public ASTQuestionReplace getQueryAIQuestionReplace() throws Exception { return _serverEncache.getQueryAIQuestionReplace(); } public double[] convMapToGisTransform(double[] pos) throws Exception { CoordinateTransform[] transforms = _serverEncache.getGisTransform(); double[] result = new double[pos.length]; for(int i = 0; i < pos.length; i += 2) { ProjCoordinate sourceCoord = new ProjCoordinate(pos[i + 0], pos[i + 1]); ProjCoordinate targetCoord = new ProjCoordinate(); transforms[1].transform(sourceCoord, targetCoord); result[i + 0] = targetCoord.x; result[i + 1] = targetCoord.y; } return result; } public double[] convGisToMapTransform(double[] pos) throws Exception { CoordinateTransform[] transforms = _serverEncache.getGisTransform(); double[] result = new double[pos.length]; for(int i = 0; i < pos.length; i += 2) { ProjCoordinate sourceCoord = new ProjCoordinate(pos[i + 0], pos[i + 1]); ProjCoordinate targetCoord = new ProjCoordinate(); transforms[0].transform(sourceCoord, targetCoord); result[i + 0] = targetCoord.x; result[i + 1] = targetCoord.y; } return result; } public SMTAIQueryDetail getQueryDetail(String id) throws Exception { SMTAIQueryDetail queryDetail = _serverEncache.getQueryDetailMap().get(id); if(queryDetail == null) throw new Exception("can't find query detail id : " + id); return queryDetail; } public static Object unwrapObject(Object value) { if(value == null) return null; if(value instanceof Wrapper) value = ((Wrapper)value).unwrap(); if(value instanceof Undefined) return null; if(value instanceof ConsString) value = ((ConsString)value).toString(); return value; } public static void convJSToJsonWriter(Object jsObject, SMTJsonWriter jsonWr) { if(jsObject instanceof NativeObject) { NativeObject nvObject = (NativeObject)jsObject; for(Entry entry : nvObject.entrySet()) { String key = SMTStatic.toString(unwrapObject(entry.getKey())); putJSToJsonWriter(jsonWr, key, entry.getValue()); } } else if(jsObject instanceof NativeArray) { NativeArray arrObject =(NativeArray)jsObject; for(int i = 0; i < arrObject.size(); i ++) { putJSToJsonWriter(jsonWr, null, arrObject.get(i)); } } } public static void putJSToJsonWriter(SMTJsonWriter jsonWr, String jsonKey, Object jsObject) { if(jsObject instanceof NativeObject) { NativeObject nvObject = (NativeObject)jsObject; jsonWr.beginMap(jsonKey); for(Entry entry : nvObject.entrySet()) { String key = SMTStatic.toString(unwrapObject(entry.getKey())); putJSToJsonWriter(jsonWr, key, entry.getValue()); } jsonWr.endMap(); } else if(jsObject instanceof NativeArray) { NativeArray arrObject =(NativeArray)jsObject; jsonWr.beginArray(jsonKey); for(int i = 0; i < arrObject.size(); i ++) { putJSToJsonWriter(jsonWr, null, arrObject.get(i)); } jsonWr.endArray(); } else { jsonWr.addKeyValue(jsonKey, unwrapObject(jsObject)); } } public static Object convJsonToJS(Json json) { if(json.isObject()) { NativeObject nv = new NativeObject(); for(Entry entry : json.asJsonMap().entrySet()) { putJSNotNullValue(nv, entry.getKey(), convJsonToJS(entry.getValue())); } return nv; } else if(json.isArray()) { List list = new ArrayList(); for(Json subJson : json.asJsonList()) { list.add(convJsonToJS(subJson)); } return new NativeArray(list.toArray(new Object[list.size()])); } else if(json.isNull()) return null; else return json.getValue(); } public static void putJSNotNullValue(NativeObject nv, String key, Object value) { if(value == null) return; if(_patIsNumber.matcher(key).find()) nv.put(Integer.parseInt(key), nv, value); else nv.put(key, nv, value); } public static Object getJSValue(NativeObject nv, String key) throws Exception { if(!nv.containsKey(key)) throw new Exception("NativeObject can't find key : " + key); Object value = unwrapObject(nv.get(key)); if(value == null) throw new Exception("NativeObject can't find key : " + key); return value; } public static Object getJSValue(NativeObject nv, String key, Object defValue) throws Exception { Object okey; if(_patIsNumber.matcher(key).find()) okey = Long.parseLong(key); else okey = key; if(!nv.containsKey(okey)) return defValue; Object value = unwrapObject(nv.get(okey)); if(value == null) return defValue; return value; } public SMTLLMConnect allocLLMConnect(String llmId) throws Exception { if(SMTStatic.isNullOrEmpty(llmId)) llmId = (String) getDefaultLLMId(); Map map = _serverEncache.getLLMFactoryMap(); SMTLLMFactory factory = map.get(llmId); if(factory == null) throw new Exception("can't find llm factory : " + llmId); return factory.allocLLM(); } public String getGroupTypeByGroupId(String groupId) throws Exception { String groupType = _serverEncache.getGroupTypeMap().get(groupId); if(groupType == null) throw new Exception("can't find group id : " + groupId); return groupType; } public SMTGisMapLayerDef getMapLayerDef(String layerId) throws Exception { SMTGisMapLayerDef mapLayerDef = _serverEncache.getMapLayerDef().get(layerId); if(mapLayerDef == null) throw new Exception("can't find layer id : " + layerId); return mapLayerDef; } public Map getMapLayerDefMap() throws Exception { Map map = _serverEncache.getMapLayerDef(); return map; } public Map getMapVPropDefMap() throws Exception { Map map = _serverEncache.getMapVPropDefMap(); return map; } public SMTMapThemeTableDef getMapThemeTableDefMap(String id) throws Exception { SMTMapThemeTableDef themeTableDef = _serverEncache.getMapThemeTableDefMap().get(id); if(themeTableDef == null) throw new Exception("can't find theme table : " + id); return themeTableDef; } public Map getMapThemeDefMap() throws Exception { return _serverEncache.getMapThemeDefMap(); } public SMTMapThemeTableDef getMapThemeTableDef(String id) throws Exception { SMTMapThemeTableDef themeTableDef = _serverEncache.getMapThemeTableDefMap().get(id); if(themeTableDef == null) throw new Exception("can't find theme table define : " + id); return themeTableDef; } public SMTMapThemeDef getMapThemeDef(String id) throws Exception { SMTMapThemeDef themeDef = _serverEncache.getMapThemeDefMap().get(id); if(themeDef == null) throw new Exception("can't find theme def : " + id); return themeDef; } public Map getAttachTableDefMap() throws Exception { return _serverEncache.getAttachTableDefMap(); } public SMTAIAttachTableDef getAttachTableDef(String id) throws Exception { SMTAIAttachTableDef attachTableDef = _serverEncache.getAttachTableDefMap().get(id); if(attachTableDef == null) throw new Exception("can't find attach table define : " + id); return attachTableDef; } public Map getAttachMetricDefMap() throws Exception { return _serverEncache.getAttachMetricDefMap(); } public SMTAIAttachMetricDef getAttachMetricDef(String id) throws Exception { SMTAIAttachMetricDef attachMetricDef = _serverEncache.getAttachMetricDefMap().get(id); if(attachMetricDef == null) throw new Exception("can't find attach metric def : " + id); return attachMetricDef; } /** * 文件(word、pdf)转txt */ public static String fileTranslTxt(MultipartFile file) throws Exception { InputStream inputStream = file.getInputStream(); try (BufferedInputStream bis = new BufferedInputStream(file.getInputStream())) { String mimeType = file.getContentType(); if (mimeType != null) { switch (mimeType) { case "application/pdf": _logger.info("文件类型是 PDF"); PDDocument document = PDDocument.load(inputStream); PDFTextStripper stripper = new PDFTextStripper(); return stripper.getText(document); case "application/vnd.openxmlformats-officedocument.wordprocessingml.document": _logger.info("文件类型是 Word (DOCX)"); try (XWPFDocument docx = new XWPFDocument(bis)) { XWPFWordExtractor docxExtractor = new XWPFWordExtractor(docx); return docxExtractor.getText(); } case "application/msword": _logger.info("文件类型是 Word (DOC)"); try (HWPFDocument doc = new HWPFDocument(bis)) { WordExtractor wordExtractor = new WordExtractor(doc); return wordExtractor.getText(); } case "text/plain": _logger.info("文件类型是 TXT"); byte[] fileData = readAttachFile(file); return new String(fileData, "UTF-8"); default: _logger.info("未知文件类型: " + mimeType); break; } } else { _logger.info("无法获取文件类型"); } } catch (Exception e) { _logger.error("文件处理失败: " + e.getMessage()); throw new Exception("文件处理失败: " + e.getMessage()); } return ""; } public static byte[] readAttachFile(MultipartFile file) throws Exception { InputStream is = file.getInputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] data = new byte[1024 * 1024]; while(true) { int size = is.read(data); if(size <= 0) return bos.toByteArray(); bos.write(data, 0, size); } } public static String buildUrl( String active, String tags, String name, String projectId, String excludePinnedData, int limit) throws Exception { // 使用Map来存储参数 Map params = new HashMap<>(); params.put("active", active); params.put("tags", tags); params.put("name", name != null ? URLEncoder.encode(name, "UTF-8") : null); params.put("projectId", projectId); params.put("excludePinnedData", excludePinnedData); params.put("limit", String.valueOf(limit)); String workflows = (String)SMTAIServerApp.getApp().getGlobalConfig("n8n_workflows"); // 基本URL StringBuilder urlBuilder = new StringBuilder(workflows); // 遍历map并构建URL for (Map.Entry entry : params.entrySet()) { if (entry.getValue() != null) { urlBuilder.append(entry.getKey()) .append("=") .append(entry.getValue()) .append("&"); } } // 去除最后一个多余的&符号 String requestUrl = urlBuilder.toString(); if (requestUrl.endsWith("&")) { requestUrl = requestUrl.substring(0, requestUrl.length() - 1); } return requestUrl; } public static List extractParts(String input, Pattern pattern) { Matcher matcher = pattern.matcher(input); List results = new ArrayList<>(); while (matcher.find()) { results.add(matcher.group(1)); // 提取第一个捕获组内容 } return results; } }