From 8e5914596381cb7605502c2ec6b2a00a230a381e Mon Sep 17 00:00:00 2001 From: RuicyWu <1063154311@qq.com> Date: Thu, 16 Jan 2025 10:28:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9C=E9=83=BD=E5=9F=8E=E6=8A=95=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=E6=95=B0=E6=8D=AE=E5=90=8C=E6=AD=A5=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=20=E4=BF=AE=E5=A4=8D=E6=89=80=E5=AD=98=E5=9C=A8=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../constants/YdzbdataSyncConstants.java | 2 +- .../apps/src_ydctdatasync/dao/KsQueryDao.java | 10 +- .../src_ydctdatasync/dao/MyJdbcAgent.java | 115 +++++++++++ .../datamap/AbstractAssetDataMapMode.java | 28 ++- .../datamap/AbstractContractDataMapMode.java | 17 +- .../datamap/AbstractFeeDataMapMode.java | 21 +- .../datamap/BzfAssetMode.java | 112 +++++------ .../datamap/ContractBillMode.java | 25 ++- .../datamap/ContractMode.java | 25 ++- .../datamap/GzcfAssetMode.java | 6 +- .../datamap/GzfwAssetMode.java | 8 +- .../datamap/GztdAssetMode.java | 4 +- .../HydropowerRechargeDataMapMode.java | 12 +- .../datamap/RefundDataMapMode.java | 27 ++- .../datasource/DataSource.java | 82 +++++++- .../quartz/YdzbDataSyncQuartz.java | 184 +++++++++++------- .../src_ydctdatasync/utils/EnumMapUtils.java | 26 ++- .../utils/SnowflakeIdGenerator.java | 82 ++++++++ .../plugin/src_ydctdatasync/pluginCfg.xml | 2 +- .../src_ydctdatasync/spring/spring-quartz.xml | 2 +- 20 files changed, 581 insertions(+), 209 deletions(-) create mode 100644 v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/dao/MyJdbcAgent.java create mode 100644 v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/utils/SnowflakeIdGenerator.java diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/constants/YdzbdataSyncConstants.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/constants/YdzbdataSyncConstants.java index cb04738..2bdee87 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/constants/YdzbdataSyncConstants.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/constants/YdzbdataSyncConstants.java @@ -12,7 +12,7 @@ public enum YdzbdataSyncConstants { feeTable("formmain_0018","费用表表名"), feeFormNo("zcbd2","费用表单编号"), zcRootEnumPCode("9039506777142151368","资产档案枚举编码"), - cwRootEnumPCode("-8314591789812725552","财务档案枚举编码") + ksTable("","客商表单表名") ; YdzbdataSyncConstants(String defaultValue, String description) { this.defaultValue = defaultValue; diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/dao/KsQueryDao.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/dao/KsQueryDao.java index 6f016d1..19c3e82 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/dao/KsQueryDao.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/dao/KsQueryDao.java @@ -10,11 +10,11 @@ import java.util.Map; public class KsQueryDao { - public Map queryByName(String name,String clause,String table) throws BusinessException, SQLException { - JDBCAgent agent = new JDBCAgent(); - String sql = "SELECT * FROM" + table + clause +";"; + public Map queryByName(String name,String clause,String table,MyJdbcAgent agent) throws BusinessException, SQLException {; + String sql = "SELECT * FROM " + table + clause +";"; List params = new ArrayList<>(); - agent.execute(sql,params); - return agent.resultSetToMap(); + params.add(name); + List> list = (List>) agent.execute(sql,params); + return list == null || list.size() == 0 ? null : list.get(0); } } diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/dao/MyJdbcAgent.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/dao/MyJdbcAgent.java new file mode 100644 index 0000000..badbbfb --- /dev/null +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/dao/MyJdbcAgent.java @@ -0,0 +1,115 @@ +package com.seeyon.apps.src_ydctdatasync.dao; + +import com.seeyon.apps.src_ydctdatasync.datasource.DataSource; +import com.seeyon.ctp.common.exceptions.BusinessException; +import com.seeyon.ctp.util.StringUtil; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MyJdbcAgent { + + private DataSource dataSource; + + public MyJdbcAgent() { + } + + public MyJdbcAgent(DataSource dataSource) { + this.dataSource = dataSource; + } + + public DataSource getDataSource() { + return dataSource; + } + + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } + + public Object execute(String sqlString, Object param) throws BusinessException, SQLException { + List params = new ArrayList(); + params.add(param); + return this.execute(sqlString, (List)params); + } + + public Object execute(String sqlString, List params) throws SQLException { + String sqlOpt = sqlString.trim().substring(0, 6).toLowerCase(); + String tmpStr = sqlString; + try (Connection connection = dataSource.getLocalConnection()){ + for (int i = 0; i < params.size(); ++i) { + Object param = params.get(i); + String newString = param == null ? "null" : "'" + param + "'"; + tmpStr = StringUtil.replace(tmpStr, "?", newString, 1); + } + if (!sqlString.startsWith("WITH _pagingRows") && !sqlOpt.startsWith("select") && !sqlOpt.startsWith("show")) { + if (!sqlOpt.startsWith("update") && !sqlOpt.startsWith("delete") && !sqlOpt.startsWith("insert")) { + return this.executeOther(sqlString, params, connection); + } else { + return this.update(sqlString, params, connection); + } + } else { + + return this.query(sqlString, params, connection); + } + } + + } + + + + private boolean executeOther(String sql, List params,Connection connection) throws SQLException { + try (PreparedStatement pst = connection.prepareStatement(sql)) { + // 设置参数 + for (int i = 0; params != null && i < params.size(); i++) { + pst.setObject(i + 1, params.get(i)); + } + return pst.execute(); + } + } + + private int update(String sql, List params,Connection connection) throws SQLException { + try (PreparedStatement pst = connection.prepareStatement(sql)) { + // 设置参数 + for (int i = 0; params != null && i < params.size(); i++) { + pst.setObject(i + 1, params.get(i)); + } + return pst.executeUpdate(); + } + } + + private List> query(String sql, List params, Connection connection) throws SQLException { + List> resultList = new ArrayList<>(); + try (PreparedStatement pst = connection.prepareStatement(sql)) { + // 设置参数 + for (int i = 0; params != null && i < params.size(); i++) { + pst.setObject(i + 1, params.get(i)); + } + // 执行查询 + try (ResultSet resultSet = pst.executeQuery()) { + // 获取元数据 + ResultSetMetaData metaData = resultSet.getMetaData(); + int columnCount = metaData.getColumnCount(); + + // 遍历结果集 + while (resultSet.next()) { + Map rowMap = new HashMap<>(); + for (int i = 1; i <= columnCount; i++) { + String columnName = metaData.getColumnLabel(i); + Object columnValue = resultSet.getObject(i); + rowMap.put(columnName, columnValue); + } + resultList.add(rowMap); + } + } + } + return resultList; + } + +} diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/AbstractAssetDataMapMode.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/AbstractAssetDataMapMode.java index baf2e7c..5bed28d 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/AbstractAssetDataMapMode.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/AbstractAssetDataMapMode.java @@ -1,18 +1,18 @@ package com.seeyon.apps.src_ydctdatasync.datamap; +import com.seeyon.apps.src_ydctdatasync.dao.MyJdbcAgent; import com.seeyon.apps.src_ydctdatasync.utils.EnumMapUtils; -import com.seeyon.ctp.util.JDBCAgent; import java.text.DateFormat; -import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; public abstract class AbstractAssetDataMapMode extends AbstractDataMapMode{ - protected JDBCAgent agent; + protected MyJdbcAgent agent; protected String zcRootPcode; + protected String ksTableName; public String getZcRootPcode() { return zcRootPcode; @@ -26,14 +26,24 @@ public abstract class AbstractAssetDataMapMode extends AbstractDataMapMode{ public void preProcess(Map map) { Object houseStatus = map.get("house_status"); Object propertyMortgage = map.get("property_mortgage"); - String zcStatus = houseStatus == null ? "" : EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产状态", (String) houseStatus); - String isPublicAsset = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"是否公用产权","否"); - String assetBacked = propertyMortgage == null ? "" : EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"是否产权抵押", (String) propertyMortgage); + String landNature = map.get("land_nature") + ""; + String zcStatus = houseStatus == null ? "" : EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产状态", houseStatus +""); + String isPublicAsset = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"是否共用产权","不共用"); + String assetBacked = propertyMortgage == null ? "" : EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"是否产权抵押", propertyMortgage+""); + map.put("land_nature","3".equals(landNature) ? "" : EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"土地性质",landNature)); map.put("house_status",zcStatus); map.put("isPublicAsset",isPublicAsset); map.put("assetBacked",assetBacked); } + public String getKsTableName() { + return ksTableName; + } + + public void setKsTableName(String ksTableName) { + this.ksTableName = ksTableName; + } + @Override public void commonAttrTransfer(Object target, Object source) { Map targetMap = (Map) target; @@ -66,7 +76,7 @@ public abstract class AbstractAssetDataMapMode extends AbstractDataMapMode{ targetMap.put("资产名称",stringBuilder.toString()); //填充资产名称 targetMap.put("资产状态",sourceMap.get("house_status"));//填充资产状态 targetMap.put("产权证号",sourceMap.get("property_certificate_no"));//填充产权证号 - targetMap.put("充产权人",sourceMap.get("property_owner"));//填充产权人 + targetMap.put("产权人",sourceMap.get("property_owner"));//填充产权人 try { targetMap.put("资产获取日期",df.format((Date)sourceMap.get("house_receipt_date")));//填充资产获取日期 targetMap.put("登记时间",df.format((Date)sourceMap.get("property_registration_time")));//填充登记时间 @@ -84,11 +94,11 @@ public abstract class AbstractAssetDataMapMode extends AbstractDataMapMode{ // targetMap.put("field0061",sourceMap.get(""));//填充管理单位编号 } - public JDBCAgent getAgent() { + public MyJdbcAgent getAgent() { return agent; } - public void setAgent(JDBCAgent agent) { + public void setAgent(MyJdbcAgent agent) { this.agent = agent; } } diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/AbstractContractDataMapMode.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/AbstractContractDataMapMode.java index 1115585..7176587 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/AbstractContractDataMapMode.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/AbstractContractDataMapMode.java @@ -1,11 +1,12 @@ package com.seeyon.apps.src_ydctdatasync.datamap; -import com.seeyon.ctp.util.JDBCAgent; +import com.seeyon.apps.src_ydctdatasync.dao.MyJdbcAgent; public abstract class AbstractContractDataMapMode extends AbstractDataMapMode{ - protected JDBCAgent agent; + protected MyJdbcAgent agent; protected String zcRootPcode; + protected String ksTableName; public String getZcRootPcode() { return zcRootPcode; @@ -20,11 +21,19 @@ public abstract class AbstractContractDataMapMode extends AbstractDataMapMode{ } - public JDBCAgent getAgent() { + public String getKsTableName() { + return ksTableName; + } + + public void setKsTableName(String ksTableName) { + this.ksTableName = ksTableName; + } + + public MyJdbcAgent getAgent() { return agent; } - public void setAgent(JDBCAgent agent) { + public void setAgent(MyJdbcAgent agent) { this.agent = agent; } } diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/AbstractFeeDataMapMode.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/AbstractFeeDataMapMode.java index fcb1785..f593770 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/AbstractFeeDataMapMode.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/AbstractFeeDataMapMode.java @@ -1,20 +1,21 @@ package com.seeyon.apps.src_ydctdatasync.datamap; +import com.seeyon.apps.src_ydctdatasync.dao.MyJdbcAgent; import com.seeyon.ctp.util.JDBCAgent; import java.util.Map; public abstract class AbstractFeeDataMapMode extends AbstractDataMapMode{ - protected JDBCAgent agent; - protected String cwRootPcode; + protected MyJdbcAgent agent; + protected String zcRootPcode; - public String getCwRootPcode() { - return cwRootPcode; + public String getZcRootPcode() { + return zcRootPcode; } - public void setCwRootPcode(String cwRootPcode) { - this.cwRootPcode = cwRootPcode; + public void setZcRootPcode(String zcRootPcode) { + this.zcRootPcode = zcRootPcode; } @Override @@ -36,15 +37,15 @@ public abstract class AbstractFeeDataMapMode extends AbstractDataMapMode{ targetMap.put("住保-房号",sourceMap.get("house_number")); //填充房号 targetMap.put("住保-租户联系方式",sourceMap.get("tenant_phone_number")); //填充租户联系方式 targetMap.put("订单描述说明",sourceMap.get("recharge_desc")); //填充订单说明 - targetMap.put("OA付款单位","默认宜都市住保运营管理有限公司"); //填充OA付款单位,默认宜都市住保运营管理有限公司 - targetMap.put("OA收款单位","默认宜都市住保运营管理有限公司"); //填充OA收款单位,默认宜都市住保运营管理有限公司 + targetMap.put("OA付款单位","宜都市住保运营管理有限公司"); //填充OA付款单位,默认宜都市住保运营管理有限公司 + targetMap.put("OA收款单位","宜都市住保运营管理有限公司"); //填充OA收款单位,默认宜都市住保运营管理有限公司 } - public JDBCAgent getAgent() { + public MyJdbcAgent getAgent() { return agent; } - public void setAgent(JDBCAgent agent) { + public void setAgent(MyJdbcAgent agent) { this.agent = agent; } } diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/BzfAssetMode.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/BzfAssetMode.java index ba968c2..8bc8d8e 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/BzfAssetMode.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/BzfAssetMode.java @@ -1,14 +1,12 @@ package com.seeyon.apps.src_ydctdatasync.datamap; import com.seeyon.apps.src_ydctdatasync.dao.FormExportUtil; -import com.seeyon.apps.src_ydctdatasync.datasource.DataSource; import com.seeyon.apps.src_ydctdatasync.utils.EnumMapUtils; import com.seeyon.ctp.common.AppContext; import com.seeyon.ctp.common.exceptions.BusinessException; import com.seeyon.ctp.organization.bo.V3xOrgDepartment; import com.seeyon.ctp.organization.bo.V3xOrgMember; import com.seeyon.ctp.organization.manager.OrgManager; -import com.seeyon.ctp.util.JDBCAgent; import com.seeyon.v3x.services.form.FormFactory; import com.seeyon.v3x.services.form.bean.FormExport; @@ -24,9 +22,8 @@ import java.util.function.Function; //保障房资产映射OA资产表模式 public class BzfAssetMode extends AbstractAssetDataMapMode{ - private DataSource localDataSource; private FormFactory formFactory; - + private String formNo; public FormFactory getFormFactory() { if (formFactory == null) { formFactory = (FormFactory) AppContext.getBean("formFactory"); @@ -34,80 +31,78 @@ public class BzfAssetMode extends AbstractAssetDataMapMode{ return formFactory; } + public String getFormNo() { + return formNo; + } + + public void setFormNo(String formNo) { + this.formNo = formNo; + } + public void setFormFactory(FormFactory formFactory) { this.formFactory = formFactory; } - public DataSource getLocalDataSource() { - return localDataSource; - } - - public void setLocalDataSource(DataSource localDataSource) { - this.localDataSource = localDataSource; - } - private void enumMap(Map sourceMap) { - String xqzcpLevelValue = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产层级","父级"); - String zcTypeFwValue = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产类型","房屋"); - String zcTypeLevel2 = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产二级类型","保障性住房"); - String xqzcBlock = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产板块","03不动产"); - String xqzcStatus = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产状态","待出租"); - String xqzcFeature = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产性质","非流动资产"); - String xqzz = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"用途","住宅"); - String house_use = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"用途", (String) sourceMap.get("house_use")); - String rental_type = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"租售类型",(String) sourceMap.get("rental_type")); - String xqrental_type = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"租售类型","只租不售"); - String xqhs = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"房屋体系","保租房"); - String hs = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"房屋体系",(String) sourceMap.get("house_system")); - String land_nature = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"土地性质", (String) sourceMap.get("land_nature")); - String house_type = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"户型", (String) sourceMap.get("house_type")); - String has_lift = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"有无电梯", (String) sourceMap.get("has_lift")); - String raise_way = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"筹集方式", (String) sourceMap.get("raise_way")); - sourceMap.put("xqzcpLevel",xqzcpLevelValue); - sourceMap.put("zcTypeFwValue",zcTypeFwValue); - sourceMap.put("zcTypeLevel2",zcTypeLevel2); - sourceMap.put("xqzcBlock",xqzcBlock); - sourceMap.put("xqzcStatus",xqzcStatus); - sourceMap.put("xqzcFeature",xqzcFeature); - sourceMap.put("xqrental_type",xqrental_type); - sourceMap.put("xqhs",xqhs); - sourceMap.put("xqzz",xqzz); - sourceMap.put("house_use",house_use); - sourceMap.put("land_nature",land_nature); - sourceMap.put("rental_type",rental_type); - sourceMap.put("house_system",hs); - sourceMap.put("house_type",house_type); - sourceMap.put("has_lift",has_lift); - sourceMap.put("raise_way",raise_way); + String xqzcpLevelValue = EnumMapUtils.getEnumItemValue(zcRootPcode, agent, "资产等级", "父级"); + String zcTypeFwValue = EnumMapUtils.getEnumItemValue(zcRootPcode, agent, "资产类型", "房屋"); + String zcTypeLevel2 = EnumMapUtils.getEnumItemValue(zcRootPcode, agent, "资产分类(资产系统)", "保障性住房"); + String xqzcBlock = EnumMapUtils.getEnumItemValue(zcRootPcode, agent, "资产分类(资产系统)", "03不动产"); + String xqzcStatus = EnumMapUtils.getEnumItemValue(zcRootPcode, agent, "资产状态", "待出租"); + String xqzcFeature = EnumMapUtils.getEnumItemValue(zcRootPcode, agent, "资产性质", "非流动资产"); + String xqzz = EnumMapUtils.getEnumItemValue(zcRootPcode, agent, "房屋用途", "住宅"); + + String house_use = EnumMapUtils.getEnumItemValue(zcRootPcode, agent, "房屋用途", (String) sourceMap.get("house_use")); + String rental_type = EnumMapUtils.getEnumItemValue(zcRootPcode, agent, "租售类型", (String) sourceMap.get("rental_type")); + String xqrental_type = EnumMapUtils.getEnumItemValue(zcRootPcode, agent, "租售类型", "只租不售"); + String xqhs = EnumMapUtils.getEnumItemValue(zcRootPcode, agent, "房屋体系", "保租房"); + String hs = EnumMapUtils.getEnumItemValue(zcRootPcode, agent, "房屋体系", (String) sourceMap.get("house_system")); + String house_type = EnumMapUtils.getEnumItemValue(zcRootPcode, agent, "户型", (String) sourceMap.get("house_type")); + String has_lift = EnumMapUtils.getEnumItemValue(zcRootPcode, agent, "有无电梯", (String) sourceMap.get("has_lift")); + String raise_way = EnumMapUtils.getEnumItemValue(zcRootPcode, agent, "筹集方式", (String) sourceMap.get("raise_way")); + sourceMap.put("xqzcpLevel", xqzcpLevelValue); + sourceMap.put("zcTypeFwValue", zcTypeFwValue); + sourceMap.put("zcTypeLevel2", zcTypeLevel2); + sourceMap.put("xqzcBlock", xqzcBlock); + sourceMap.put("xqzcStatus", xqzcStatus); + sourceMap.put("xqzcFeature", xqzcFeature); + sourceMap.put("xqrental_type", xqrental_type); + sourceMap.put("xqhs", xqhs); + sourceMap.put("xqzz", xqzz); + sourceMap.put("house_use", house_use); + sourceMap.put("rental_type", rental_type); + sourceMap.put("house_system", hs); + sourceMap.put("house_type", house_type); + sourceMap.put("has_lift", has_lift); + sourceMap.put("raise_way", raise_way); } @Override public void preProcess(Map sourceMap) { FormExport formExport = new FormExport(); - String loginName = (String) sourceMap.get("loginName"); + String loginName = sourceMap.get("loginName") + ""; //查询客商档案以及填充 //处理小区资产档案信息 super.preProcess(sourceMap); enumMap(sourceMap); try { List params = new ArrayList<>(); - params.add((String) sourceMap.get("xqzcpLevelValue")); - params.add((String) sourceMap.get("zcTypeFwValue")); - params.add((String) sourceMap.get("village_name")); + params.add(sourceMap.get("xqzcpLevel") + ""); + params.add(sourceMap.get("zcTypeFwValue") + ""); + params.add(sourceMap.get("village_name") + ""); String table = (String) sourceMap.get("zcTable"); String villageQuerySql = "SELECT 1 FROM "+ table +" WHERE field0027 = ? and field0023 = ? and field0037 =?;"; - agent.execute(villageQuerySql, params); - List resList = agent.resultSetToList(); + List> resList = (List>) agent.execute(villageQuerySql, params); DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - if(resList == null || resList.size() == 0) { + if(resList == null || resList.isEmpty()) { //保障性住房小区的资产信息若不存在,则插入 Map villageInsertInfo = new HashMap<>(); - villageInsertInfo.put("建档部门",getCreatorDept(agent,loginName));//建档部门 + villageInsertInfo.put("建档部门",getCreatorDept(loginName));//建档部门 villageInsertInfo.put("建档人员","系统管理员");//建档人员 villageInsertInfo.put("建档日期",df.format(new Date()));//建档日期 villageInsertInfo.put("资产板块",sourceMap.get("xqzcBlock")+"");//资产板块 villageInsertInfo.put("建档单位","住保置业");//建档单位 - villageInsertInfo.put("资产层级",sourceMap.get("xqzcpLevelValue")+"");//资产层级 + villageInsertInfo.put("资产层级",sourceMap.get("xqzcpLevel")+"");//资产层级 villageInsertInfo.put("数据来源","住保资产系统(自定义)");//数据来源 villageInsertInfo.put("资产名称",sourceMap.get("village_name") + "");//资产名称 villageInsertInfo.put("资产状态",sourceMap.get("xqzcStatus") + "");//资产状态 @@ -116,22 +111,21 @@ public class BzfAssetMode extends AbstractAssetDataMapMode{ villageInsertInfo.put("资产二级类型",sourceMap.get("zcTypeLevel2") + "");//资产二级类型 villageInsertInfo.put("资产种类","保障性住房");//资产种类 villageInsertInfo.put("所属小区",sourceMap.get("village_name") +"");//小区 - villageInsertInfo.put("用途",sourceMap.get("house_use") +"");//用途 + villageInsertInfo.put("用途",sourceMap.get("xqzz") +"");//用途 villageInsertInfo.put("租售类型",sourceMap.get("xqrental_type") +"");//租售类型 - villageInsertInfo.put("房屋体系",sourceMap.get("house_system") +"");//房屋体系 -// villageInsertInfo.put("field0058",sourceMap.get(""));//坐落位置 + villageInsertInfo.put("房屋体系",sourceMap.get("xqhs") +"");//房屋体系 + villageInsertInfo.put("坐落位置",sourceMap.get("located_street") + "");//坐落位置 villageInsertInfo.put("土地性质",sourceMap.get("land_nature") +"");//土地性质 villageInsertInfo.put("是否产权抵押",sourceMap.get("assetBacked") +""); //是否产权抵押 formExport.setValues(FormExportUtil.setFormValue(villageInsertInfo)); - getFormFactory().importBusinessFormData(loginName, "zcbd1",formExport, new String[] {}); + getFormFactory().importBusinessFormData(loginName, formNo ,formExport, new String[] {}); } }catch (Exception e) { e.printStackTrace(); } - } - private String getCreatorDept(JDBCAgent agent,String loginName) { + private String getCreatorDept(String loginName) { OrgManager orgManager = (OrgManager) AppContext.getBean("orgManager"); try { V3xOrgMember member = orgManager.getMemberByLoginName(loginName); diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/ContractBillMode.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/ContractBillMode.java index c6b0dd9..03bca2d 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/ContractBillMode.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/ContractBillMode.java @@ -14,9 +14,26 @@ public class ContractBillMode extends AbstractFeeDataMapMode{ @Override public void preProcess(Map map) { - String recordBill = EnumMapUtils.getEnumItemValue(cwRootPcode,agent,"是否入账","未入"); - String incomeOrCost = EnumMapUtils.getEnumItemValue(cwRootPcode,agent,"收支类型","收"); + String recordBill = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"是否入账","未入"); + String incomeOrCost = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"收支类型","收"); + String billType = (String) map.get("bill_type"); + if("宽带".equals(billType)) { + map.put("bill_type","宽带费"); + } else if("宽带或物业费".equals(billType)) { + map.put("bill_type","物业费"); + } else if("月租金".equals(billType)) { + map.put("bill_type","租金"); + } else if("物业".equals(billType)) { + map.put("bill_type","物业费"); + } else if("水电余额".equals(billType)) { + map.put("bill_type","水电费"); + } + String feeType = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"住保-费用类型", map.get("bill_type") + ""); + if("".equals(feeType)) { + feeType = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"住保-费用类型", "其他"); + } map.put("recordBill",recordBill); + map.put("bill_type",feeType); map.put("incomeOrCost",incomeOrCost); } @@ -39,11 +56,11 @@ public class ContractBillMode extends AbstractFeeDataMapMode{ targetMap.put("是否入账",sourceMap.get("recordBill")); //填充是否入账 targetMap.put("收支类型",sourceMap.get("incomeOrCost")); //填充收支类型 targetMap.put("住保-费用类型",sourceMap.get("bill_type")); //填充费用类型 - targetMap.put("主键",sourceMap.get("bill_id")); //主键 + targetMap.put("住保-主键",sourceMap.get("bill_id")); //主键 targetMap.put("应收金额",sourceMap.get("bill_amount")); //填充应收金额 targetMap.put("本次实收金额",sourceMap.get("bill_amount")); //填充本次实收金额 try { - targetMap.put("住保-账单生成日期",df.format(sourceMap.get("trade_reconciliation_time"))); //填充账单生成日期 + targetMap.put("住保-账单生成日期",df.format((Date)sourceMap.get("trade_reconciliation_time"))); //填充账单生成日期 }catch (NullPointerException e) { } diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/ContractMode.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/ContractMode.java index 53c4bf9..793ec24 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/ContractMode.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/ContractMode.java @@ -4,7 +4,6 @@ import com.seeyon.apps.src_ydctdatasync.dao.KsQueryDao; import com.seeyon.apps.src_ydctdatasync.utils.EnumMapUtils; import java.text.DateFormat; -import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; @@ -16,7 +15,8 @@ public class ContractMode extends AbstractContractDataMapMode { @Override public void preProcess(Map map) { String zcType = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产类型","房屋"); - String zcBlock = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产板块","03不动产"); + String zcBlock = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产分类(资产系统)","03不动产"); +// String contractStatus = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"合同状态", map.get("contract_state") +""); String ksName = (String) map.get("b_name"); String zcTypeLevel2 = (String) map.get("asset_type_name"); if(zcTypeLevel2.equals("保障房")){ @@ -28,16 +28,17 @@ public class ContractMode extends AbstractContractDataMapMode { } map.put("zcType",zcType); map.put("zcBlock",zcBlock); - map.put("asset_type_name",EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产二级类型", (String) map.get("asset_type_name"))); +// map.put("contract_state",contractStatus); + map.put("asset_type_name",EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产分类(资产系统)", map.get("asset_type_name") +"")); KsQueryDao ksQueryDao = new KsQueryDao(); try { - Map ksMap = ksQueryDao.queryByName(ksName, "where field0006 = ?", ksName); - if(map != null && !map.isEmpty()) { - map.put("u8ccode",ksMap.get("field0092")); - map.put("signCorpNo",ksMap.get("field0029")); + Map ksMap = ksQueryDao.queryByName(ksName, " where field0006 = ?", ksTableName,agent); + if(ksMap != null && !ksMap.isEmpty()) { + ksMap.put("u8ccode",map.get("field0092")); + ksMap.put("signCorpNo",map.get("field0029")); } } catch (Exception e) { - + e.printStackTrace(); } } @@ -59,7 +60,7 @@ public class ContractMode extends AbstractContractDataMapMode { Map subTableMap = new HashMap<>(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); targetMap.put("subTable",subTableMap); - targetMap.put("合同ID",sourceMap.get("contract_id")); //填充合同ID + targetMap.put("住保-主键",sourceMap.get("contract_id")); //填充合同ID targetMap.put("合同编号",sourceMap.get("contract_no")); //填充合同编号 targetMap.put("签订单位编号",sourceMap.get("signCorpNo")); //填充签订单位编号 targetMap.put("签订单位",sourceMap.get("a_name"));//填充签订单位 @@ -89,6 +90,12 @@ public class ContractMode extends AbstractContractDataMapMode { subTableMap.put("房号",sourceMap.get("house_number")); //填充房号 subTableMap.put("住保资产编号",sourceMap.get("house_id")); subTableMap.put("OA资产编号",sourceMap.get("house_id")); + subTableMap.put("开始日期",targetMap.get("合同开始日期")); + subTableMap.put("结束日期",targetMap.get("合同截止日期")); + subTableMap.put("租费",targetMap.get("合同金额")); + subTableMap.put("应收租费",targetMap.get("应收租费")); + subTableMap.put("实际已收金额",targetMap.get("累计已收租金")); + subTableMap.put("未收租金",targetMap.get("剩余未收租金")); StringBuilder stringBuilder = new StringBuilder(""); if(sourceMap.get("village_name") != null) { stringBuilder.append(sourceMap.get("village_name")); diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/GzcfAssetMode.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/GzcfAssetMode.java index 4e9699a..10d771f 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/GzcfAssetMode.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/GzcfAssetMode.java @@ -11,10 +11,10 @@ public class GzcfAssetMode extends AbstractAssetDataMapMode{ @Override public void preProcess(Map map) { super.preProcess(map); - String has_lift = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"有无电梯", (String) map.get("has_lift")); + String has_lift = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"有无电梯", map.get("has_lift") + ""); String zcTypeFwValue = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产类型","房屋"); - String zcTypeLevel2 = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产二级类型","厂房"); - String house_use = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"用途", (String) map.get("house_use")); + String zcTypeLevel2 = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产分类(资产系统)","厂房"); + String house_use = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"房屋用途", map.get("house_use") + ""); map.put("zcTypeFwValue",zcTypeFwValue); map.put("zcTypeLevel2",zcTypeLevel2); map.put("has_lift",has_lift); diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/GzfwAssetMode.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/GzfwAssetMode.java index e68819b..5575c4a 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/GzfwAssetMode.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/GzfwAssetMode.java @@ -13,15 +13,13 @@ public class GzfwAssetMode extends AbstractAssetDataMapMode{ public void preProcess(Map map) { super.preProcess(map); String zcTypeFwValue = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产类型","房屋"); - String zcTypeLevel2 = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产二级类型","住宅"); - String has_lift = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"有无电梯", (String) map.get("has_lift")); - String house_use = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"用途", (String) map.get("house_use")); - String house_type = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"房屋类型", (String) map.get("variable_002")); + String zcTypeLevel2 = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产分类(资产系统)","住宅"); + String has_lift = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"有无电梯", map.get("has_lift") + ""); + String house_use = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"房屋用途", map.get("house_use") + ""); map.put("zcTypeFwValue",zcTypeFwValue); map.put("zcTypeLevel2",zcTypeLevel2); map.put("has_lift",has_lift); map.put("house_use",house_use); - map.put("variable_002",house_type); } @Override diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/GztdAssetMode.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/GztdAssetMode.java index c0d2edc..f706d09 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/GztdAssetMode.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/GztdAssetMode.java @@ -12,11 +12,9 @@ public class GztdAssetMode extends AbstractAssetDataMapMode{ public void preProcess(Map map) { super.preProcess(map); String zcTypeFwValue = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产类型","土地"); - String zcTypeLevel2 = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产二级类型","自用出让地"); - String land_nature = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"土地性质", (String) map.get("land_nature")); + String zcTypeLevel2 = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"资产分类(资产系统)","自用出让地"); map.put("zcTypeFwValue",zcTypeFwValue); map.put("zcTypeLevel2",zcTypeLevel2); - map.put("land_nature",land_nature); } @Override diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/HydropowerRechargeDataMapMode.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/HydropowerRechargeDataMapMode.java index fd7fd9f..c014c20 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/HydropowerRechargeDataMapMode.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/HydropowerRechargeDataMapMode.java @@ -3,7 +3,6 @@ package com.seeyon.apps.src_ydctdatasync.datamap; import com.seeyon.apps.src_ydctdatasync.utils.EnumMapUtils; import java.text.DateFormat; -import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Collections; import java.util.Date; @@ -15,8 +14,10 @@ public class HydropowerRechargeDataMapMode extends AbstractFeeDataMapMode{ @Override public void preProcess(Map map) { super.preProcess(map); - String incomeOrCost = EnumMapUtils.getEnumItemValue(cwRootPcode,agent,"收支类型","收"); + String incomeOrCost = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"收支类型","收"); + String feeType = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"住保-费用类型", (String) map.get("水电费")); map.put("incomeOrCost",incomeOrCost); + map.put("feeType",feeType); } @Override @@ -38,13 +39,14 @@ public class HydropowerRechargeDataMapMode extends AbstractFeeDataMapMode{ targetMap.put("收支类型",sourceMap.get("incomeOrCost")); //填充收支类型 try { - targetMap.put("到账日期",df.format( sourceMap.get("recharge_time"))); //填充到账日期 - targetMap.put("住保-账单生成日期",df.format(sourceMap.get("recharge_time"))); //填充账单生成日期 + targetMap.put("到账日期",df.format((Date)sourceMap.get("recharge_time"))); //填充到账日期 + targetMap.put("住保-账单生成日期",df.format((Date)sourceMap.get("recharge_time"))); //填充账单生成日期 targetMap.put("实收日期",df.format((Date)sourceMap.get("recharge_time"))); //填充实收日期 }catch (NullPointerException e) { } - targetMap.put("住保-费用类型","水电费"); //填充费用类型 + targetMap.put("住保-主键",sourceMap.get("recharge_id")); //主键 + targetMap.put("住保-费用类型",sourceMap.get("feeType")); //填充费用类型 targetMap.put("住保-支付订单状态",sourceMap.get("recharge_status")); //填充订单状态 } diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/RefundDataMapMode.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/RefundDataMapMode.java index e307760..fa433b2 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/RefundDataMapMode.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datamap/RefundDataMapMode.java @@ -15,8 +15,25 @@ public class RefundDataMapMode extends AbstractFeeDataMapMode{ @Override public void preProcess(Map map) { super.preProcess(map); - String incomeOrCost = EnumMapUtils.getEnumItemValue(cwRootPcode,agent,"收支类型","支"); + String incomeOrCost = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"收支类型","支"); + String refundType = (String) map.get("refund_type"); + if("宽带".equals(refundType)) { + map.put("refund_type","宽带费"); + }else if("宽带或物业费".equals(refundType)) { + map.put("refund_type","物业费"); + }else if("月租金".equals(refundType)) { + map.put("refund_type","租金"); + }else if("物业".equals(refundType)) { + map.put("refund_type","物业费"); + }else if("水电余额".equals(refundType)) { + map.put("refund_type","水电费"); + } + String feeType = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"住保-费用类型", (String) map.get("refund_type")); + if("".equals(feeType)) { + feeType = EnumMapUtils.getEnumItemValue(zcRootPcode,agent,"住保-费用类型", "其他"); + } map.put("incomeOrCost",incomeOrCost); + map.put("refund_type",feeType); } @Override @@ -40,11 +57,9 @@ public class RefundDataMapMode extends AbstractFeeDataMapMode{ targetMap.put("住保-支付订单状态",sourceMap.get("refund_status")); //填充订单状态 targetMap.put("订单描述说明",sourceMap.get("recharge_desc")); //填充订单说明 targetMap.put("本次实付金额",sourceMap.get("refund_amount")); //填充本次实付金额 - try { - targetMap.put("住保-退还账单时间",df.format((Date) sourceMap.get("refund_bill_time"))); //填充退还账单时间 - targetMap.put("实付日期",df.format((Date)sourceMap.get("refund_time"))); //填充实付日期 - } catch (NullPointerException e) { + targetMap.put("住保-主键",sourceMap.get("refund_id")); //主键 + targetMap.put("住保-退还账单时间",sourceMap.get("refund_bill_time")); //填充退还账单时间 + targetMap.put("实付日期",sourceMap.get("refund_time")); //填充实付日期 - } } } diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datasource/DataSource.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datasource/DataSource.java index 9143ca8..402eb1a 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datasource/DataSource.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/datasource/DataSource.java @@ -20,13 +20,17 @@ public class DataSource { private final int minimumIdle = 3; // 连接队列 private final BlockingQueue idleConnections = new LinkedBlockingQueue<>(); - private final Queue activeConnections = new ConcurrentLinkedQueue<>(); - + private final BlockingQueue activeConnections = new LinkedBlockingQueue<>(); + private javax.sql.DataSource localDataSource; // 构造方法 public DataSource() { } + public DataSource(javax.sql.DataSource localDataSource) { + this.localDataSource = localDataSource; + } + public DataSourceConfig getConfig() { return config; } @@ -52,12 +56,50 @@ public class DataSource { } } + private Connection createNewLocalConnection() { + try { + Connection realConnection = localDataSource.getConnection(); + return (Connection) Proxy.newProxyInstance( + realConnection.getClass().getClassLoader(), + new Class[]{Connection.class}, + new ConnectionProxyHandler(realConnection, this) + ); + } catch (SQLException e) { + throw new RuntimeException("Failed to create a new connection", e); + } + } + + // 从连接池获取连接 + public Connection getLocalConnection() throws SQLException { + synchronized (this) { + Connection connection = idleConnections.poll(); + if (connection == null || !isConnectionValid(connection)) { + if (activeConnections.size() + idleConnections.size() < maximumPoolSize) { + connection = createNewLocalConnection(); + } else { + try { + // 等待空闲连接释放 + connection = idleConnections.poll(10, TimeUnit.SECONDS); + if (connection == null) { + throw new SQLException("No available connection in the pool"); + } + } catch (InterruptedException e) { + throw new SQLException("Interrupted while waiting for a connection", e); + } + } + } + if (connection != null) { + activeConnections.offer(connection); + } + return connection; + } + } // 从连接池获取连接 public Connection getConnection() throws SQLException { + synchronized (this) { Connection connection = idleConnections.poll(); - if (connection == null) { - synchronized (this) { + if (connection == null || !isConnectionValid(connection)) { if (activeConnections.size() + idleConnections.size() < maximumPoolSize) { connection = createNewConnection(); } else { @@ -72,20 +114,33 @@ public class DataSource { } } } - } if (connection != null) { activeConnections.offer(connection); } return connection; + } + } + + private boolean isConnectionValid(Connection connection) { + try { + return connection != null && !connection.isClosed() && connection.isValid(60); + } catch (SQLException e) { + return false; + } } // 归还连接到连接池 public void releaseConnection(Connection connection) { - if (connection != null) { - activeConnections.remove(connection); - idleConnections.offer(connection); + synchronized (this) { + if (connection != null || !isConnectionValid(connection)) { + activeConnections.remove(connection); + idleConnections.offer(connection); + }else { + activeConnections.remove(connection); + closeConnection(connection); + } } } @@ -117,12 +172,23 @@ public class DataSource { this.pool = pool; } + public Connection getRealConnection() { + return realConnection; + } + @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("close".equals(method.getName())) { pool.releaseConnection((Connection) proxy); return null; } + if ("equals".equals(method.getName())) { + // 比较代理对象是否相等时,基于真实的连接对象比较 + return args[0] instanceof Proxy && realConnection.equals(((ConnectionProxyHandler)Proxy.getInvocationHandler(args[0])).getRealConnection()); + } + if ("hashCode".equals(method.getName())) { + return realConnection.hashCode(); + } return method.invoke(realConnection, args); } } diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/quartz/YdzbDataSyncQuartz.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/quartz/YdzbDataSyncQuartz.java index 9ebe30b..19d587a 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/quartz/YdzbDataSyncQuartz.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/quartz/YdzbDataSyncQuartz.java @@ -6,6 +6,7 @@ import com.seeyon.apps.common.plugin.vo.ConfigVo; import com.seeyon.apps.ext.quartz.AbstractQuartzTask; import com.seeyon.apps.src_ydctdatasync.constants.YdzbdataSyncConstants; import com.seeyon.apps.src_ydctdatasync.dao.FormExportUtil; +import com.seeyon.apps.src_ydctdatasync.dao.MyJdbcAgent; import com.seeyon.apps.src_ydctdatasync.datamap.BzfAssetMode; import com.seeyon.apps.src_ydctdatasync.datamap.ContractBillMode; import com.seeyon.apps.src_ydctdatasync.datamap.ContractMode; @@ -35,6 +36,7 @@ import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.CountDownLatch; import static com.seeyon.apps.src_ydctdatasync.constants.YdzbdataSyncConstants.getPluginId; @@ -44,7 +46,8 @@ public class YdzbDataSyncQuartz extends AbstractQuartzTask implements Disposable protected ICstConfigApi cstConfigApi = (ICstConfigApi) AppContext.getBean("cstConfigApi"); private FormFactory formFactory; private DataSource ydzbThirdDataSource = (DataSource) AppContext.getBean("ydzbThirdDataSource"); - private JDBCAgent agent = null; + private DataSource myCusDataSource = new DataSource((javax.sql.DataSource)AppContext.getBean("dataSource")); + private MyJdbcAgent agent = new MyJdbcAgent(myCusDataSource); private boolean prod; public boolean isProd() { @@ -79,27 +82,74 @@ public class YdzbDataSyncQuartz extends AbstractQuartzTask implements Disposable log.info("宜都城投资产数据同步任务开始"); long startTime = System.currentTimeMillis(); try (Connection connection = ydzbThirdDataSource.getConnection()){ - agent = new JDBCAgent(); - processZcData(connection); - processContractData(connection); - DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); - - try { - Date date = null; - if (arg0 != null) { - date = df.parse(arg0); + CountDownLatch countDownLatch = new CountDownLatch(3); + //线程1 + new Thread(()->{ + try { + processZcData(connection); + countDownLatch.countDown(); + } catch (SQLException e) { + throw new RuntimeException(e); + } catch (BusinessException e) { + throw new RuntimeException(e); + } catch (ServiceException e) { + throw new RuntimeException(e); + }finally { + countDownLatch.countDown(); + } + }).start(); + //线程2 + new Thread(()->{ + try { + processContractData(connection); + } catch (SQLException e) { + throw new RuntimeException(e); + } catch (BusinessException e) { + throw new RuntimeException(e); + } catch (ServiceException e) { + throw new RuntimeException(e); + }finally { + countDownLatch.countDown(); + } + }).start(); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); + Date startDate = null; + Date endDate = null; + try { + if (arg0 != null) { + String[] splits = arg0.split(","); + for (int i = 0; i < splits.length; i++) { + if(i == 0) { + startDate = df.parse(splits[i]); + } + if(i == 1) { + endDate = df.parse(splits[i]); + } + } } - processFeeData(connection, date); } catch (ParseException e) { - throw e; + log.error(e.getMessage(),e); } + Date finalStartDate = startDate; + Date finalEndDate = endDate; + //线程3 + new Thread(()->{ + try { + processFeeData(connection, finalStartDate, finalEndDate); + } catch (SQLException e) { + throw new RuntimeException(e); + } catch (BusinessException e) { + throw new RuntimeException(e); + } catch (ServiceException e) { + throw new RuntimeException(e); + }finally { + countDownLatch.countDown(); + } + }).start(); + countDownLatch.await(); } catch (Exception e) { log.error("宜都城投资产数据同步任务执行失败"); log.error(e.getMessage(),e); - }finally { - if(agent != null) { - agent.close(); - } } log.info("宜都城投资产数据同步任务结束,耗时:"+ (System.currentTimeMillis() - startTime)+ " ms"); return null; @@ -109,9 +159,10 @@ public class YdzbDataSyncQuartz extends AbstractQuartzTask implements Disposable private void processContractData(Connection connection) throws SQLException, BusinessException, ServiceException { log.info("开始同步合同表数据"); String countQuerySql = "SELECT count(*) FROM zb_contract;"; - String pageQuerySql = "SELECT * FROM zzb_contract limit 100 OFFSET ?;"; + String pageQuerySql = "SELECT * FROM zb_contract limit 100 OFFSET ?;"; ContractMode contractMode = new ContractMode(); contractMode.setAgent(agent); + contractMode.setKsTableName(getBizConfigByKey(YdzbdataSyncConstants.ksTable)); contractMode.setZcRootPcode(getBizConfigByKey(YdzbdataSyncConstants.zcRootEnumPCode)); long count = StatementQueryUtil.queryCount(countQuerySql,connection, null); int totalPage = (int)Math.ceil((double)count / 100); @@ -134,15 +185,16 @@ public class YdzbDataSyncQuartz extends AbstractQuartzTask implements Disposable } //处理费用数据 - private void processFeeData(Connection connection,Date date) throws SQLException, BusinessException, ServiceException { - Date startDate = null; - Date endDate = null; - if(date == null) { + private void processFeeData(Connection connection,Date startDate,Date endDate) throws SQLException, BusinessException, ServiceException { + if(startDate == null) { startDate = TimeUtils.startOfYesterday(); + }else { + startDate = TimeUtils.startOf(startDate); + } + if(endDate == null) { endDate = TimeUtils.startOf(new Date()); }else { - startDate = TimeUtils.startOf(TimeUtils.before(date,1)); - endDate = TimeUtils.startOf(date); + endDate = TimeUtils.startOf(endDate); } log.info("开始同步费用数据"); processContractBillData(connection,startDate,endDate); @@ -155,15 +207,15 @@ public class YdzbDataSyncQuartz extends AbstractQuartzTask implements Disposable private void processContractBillData(Connection connection,Date startDate,Date endDate) throws SQLException, BusinessException, ServiceException { log.info("开始同步合同费用数据"); String countQuerySql = "SELECT count(*) FROM zb_contract_bill where trade_reconciliation_time >= ? and trade_reconciliation_time <= ?;"; - String pageQuerySql = "SELECT * FROM zb_contract_bill where limit 100 OFFSET ?;"; + String pageQuerySql = "SELECT * FROM zb_contract_bill where trade_reconciliation_time >= ? and trade_reconciliation_time <= ? limit 100 OFFSET ?;"; ContractBillMode contractBillMode = new ContractBillMode(); contractBillMode.setAgent(agent); - contractBillMode.setCwRootPcode(getBizConfigByKey(YdzbdataSyncConstants.cwRootEnumPCode)); + contractBillMode.setZcRootPcode(getBizConfigByKey(YdzbdataSyncConstants.zcRootEnumPCode)); long count = StatementQueryUtil.queryCount(countQuerySql,connection,startDate,endDate); int totalPage = (int)Math.ceil((double)count / 100); for(int i = 0; i < totalPage;i++) { - List> gztdDataList = StatementQueryUtil.queryList(pageQuerySql, connection, i*100); - for (Map rowMap : gztdDataList) { + List> dataList = StatementQueryUtil.queryList(pageQuerySql, connection, startDate,endDate,i*100); + for (Map rowMap : dataList) { Map targetMap = new HashMap<>(); contractBillMode.preProcess(rowMap); contractBillMode.transfer(targetMap,rowMap); @@ -184,11 +236,11 @@ public class YdzbDataSyncQuartz extends AbstractQuartzTask implements Disposable //处理水电费 private void processHydpowerRechargeData(Connection connection,Date startDate,Date endDate) throws SQLException, BusinessException, ServiceException { log.info("开始同步水电费数据"); - String countQuerySql = "SELECT count(*) FROM zb_hydropower_recharge where recharge_time >= ? and recharge_time <=;"; + String countQuerySql = "SELECT count(*) FROM zb_hydropower_recharge where recharge_time >= ? and recharge_time <=?;"; String pageQuerySql = "SELECT * FROM zb_hydropower_recharge where recharge_time >= ? and recharge_time <= ? limit 100 OFFSET ?;"; HydropowerRechargeDataMapMode rechargeDataMapMode = new HydropowerRechargeDataMapMode(); rechargeDataMapMode.setAgent(agent); - rechargeDataMapMode.setCwRootPcode(getBizConfigByKey(YdzbdataSyncConstants.cwRootEnumPCode)); + rechargeDataMapMode.setZcRootPcode(getBizConfigByKey(YdzbdataSyncConstants.zcRootEnumPCode)); long count = StatementQueryUtil.queryCount(countQuerySql,connection, startDate,endDate); int totalPage = (int)Math.ceil((double)count / 100); for(int i = 0; i < totalPage;i++) { @@ -207,10 +259,10 @@ public class YdzbDataSyncQuartz extends AbstractQuartzTask implements Disposable private void processRefundData(Connection connection,Date startDate,Date endDate) throws SQLException, BusinessException, ServiceException { log.info("开始同步退费数据"); String countQuerySql = "SELECT count(*) FROM zb_refund where create_time >= ? and create_time <= ?;"; - String pageQuerySql = "SELECT * FROM zb_contract_bill where create_time >= ? and create_time <= ? limit 100 OFFSET ?;"; + String pageQuerySql = "SELECT * FROM zb_refund where create_time >= ? and create_time <= ? limit 100 OFFSET ?;"; RefundDataMapMode refundDataMapMode = new RefundDataMapMode(); refundDataMapMode.setAgent(agent); - refundDataMapMode.setCwRootPcode(getBizConfigByKey(YdzbdataSyncConstants.cwRootEnumPCode)); + refundDataMapMode.setZcRootPcode(getBizConfigByKey(YdzbdataSyncConstants.zcRootEnumPCode)); long count = StatementQueryUtil.queryCount(countQuerySql,connection, startDate,endDate); int totalPage = (int)Math.ceil((double)count / 100); for(int i = 0; i < totalPage;i++) { @@ -252,7 +304,7 @@ public class YdzbDataSyncQuartz extends AbstractQuartzTask implements Disposable gztdAssetMode.transfer(targetMap,rowMap); upsertData(getBizConfigByKey(YdzbdataSyncConstants.zcFormNo), convert2StringValue(targetMap), - getBizConfigByKey(YdzbdataSyncConstants.zcFormNo), + getBizConfigByKey(YdzbdataSyncConstants.zcTable), "WHERE field0031 = ?", targetMap.get("资产编号") +""); } @@ -316,6 +368,7 @@ public class YdzbDataSyncQuartz extends AbstractQuartzTask implements Disposable String pageQuerySql = "SELECT * FROM zb_bzf_house limit 100 OFFSET ?;"; BzfAssetMode bzfAssetMode = new BzfAssetMode(); bzfAssetMode.setAgent(agent); + bzfAssetMode.setFormNo(getBizConfigByKey(YdzbdataSyncConstants.zcFormNo)); bzfAssetMode.setZcRootPcode(getBizConfigByKey(YdzbdataSyncConstants.zcRootEnumPCode)); long count = StatementQueryUtil.queryCount(countQuerySql,connection, null); int totalPage = (int)Math.ceil((double)count / 100); @@ -343,26 +396,25 @@ public class YdzbDataSyncQuartz extends AbstractQuartzTask implements Disposable //不存在则插入,存在则更新 List params = new ArrayList<>(); params.add(param); - String querySql = "SELECT * FROM " + table + whereSql +";"; + String querySql = "SELECT * FROM " + table + " "+ whereSql +";"; Map existData = null; try { - //agent.execute(querySql,params); - existData = agent.resultSetToMap(); - } catch (Exception e) { - - } - if(existData != null && existData.size() > 0) { - for (String key : targetMap.keySet()) { - existData.put(key,targetMap.get(key)+""); - Map updateSqlMap = generateUpdateSql(existData, table, whereSql, param); - agent.execute((String) updateSqlMap.get("sql"),updateSqlMap.get("params")); + List> resList = (List>) agent.execute(querySql,params); + existData = resList == null || resList.size() == 0 ? null : resList.get(0); + if(existData != null && existData.size() > 0) { + for (String key : targetMap.keySet()) { + existData.put(key,targetMap.get(key)+""); + Map updateSqlMap = generateUpdateSql(existData, table, whereSql, param); + agent.execute((String) updateSqlMap.get("sql"),updateSqlMap.get("params")); + } + }else { + FormExport formExport = new FormExport(); + formExport.setValues(FormExportUtil.setFormValue(targetMap)); + getFormFactory().importBusinessFormData(getBizConfigByKey(YdzbdataSyncConstants.loginName), formNo,formExport, new String[] {}); } - }else { - FormExport formExport = new FormExport(); - formExport.setValues(FormExportUtil.setFormValue(targetMap)); - getFormFactory().importBusinessFormData(getBizConfigByKey(YdzbdataSyncConstants.loginName), formNo,formExport, new String[] {}); - } - + } catch (Exception e) { + e.printStackTrace(); + } } private void insertData(String formNo,Map targetMap) throws BusinessException, SQLException, ServiceException { @@ -375,27 +427,26 @@ public class YdzbDataSyncQuartz extends AbstractQuartzTask implements Disposable //不存在则插入,存在则更新 List params = new ArrayList<>(); params.add(param); - String querySql = "SELECT * FROM " + table + whereSql +";"; + String querySql = "SELECT * FROM " + table +" " + whereSql +";"; Map existData = null; try { - agent.execute(querySql,params); - existData = agent.resultSetToMap(); - } catch (Exception e) { - - } - if(existData != null && existData.size() > 0) { - for (String key : targetMap.keySet()) { - existData.put(key,targetMap.get(key)+""); - Map updateSqlMap = generateUpdateSql(existData, table, whereSql, param); - agent.execute((String) updateSqlMap.get("sql"),updateSqlMap.get("params")); + List> resList = (List>) agent.execute(querySql,params); + existData = resList == null || resList.size() == 0 ? null : resList.get(0); + if(existData != null && existData.size() > 0) { + for (String key : targetMap.keySet()) { + existData.put(key,targetMap.get(key)+""); + Map updateSqlMap = generateUpdateSql(existData, table, whereSql, param); + agent.execute((String) updateSqlMap.get("sql"),updateSqlMap.get("params")); + } + }else { + FormExport formExport = new FormExport(); + formExport.setValues(FormExportUtil.setFormValue(targetMap)); + formExport.setSubordinateForms(FormExportUtil.setSubordinateFormValue(subTableMap)); + getFormFactory().importBusinessFormData(getBizConfigByKey(YdzbdataSyncConstants.loginName), formNo,formExport, new String[] {}); } - }else { - FormExport formExport = new FormExport(); - formExport.setValues(FormExportUtil.setFormValue(targetMap)); - formExport.setSubordinateForms(FormExportUtil.setSubordinateFormValue(subTableMap)); - getFormFactory().importBusinessFormData(getBizConfigByKey(YdzbdataSyncConstants.loginName), formNo,formExport, new String[] {}); + } catch (Exception e) { + e.printStackTrace(); } - } private Map generateUpdateSql(Map fieldValues, String tableName, String whereClause,String clauseValue) { @@ -433,6 +484,7 @@ public class YdzbDataSyncQuartz extends AbstractQuartzTask implements Disposable @Override public void destroy() throws Exception { ydzbThirdDataSource.close(); + myCusDataSource.close(); } private String getBizConfigByKey(YdzbdataSyncConstants key) { diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/utils/EnumMapUtils.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/utils/EnumMapUtils.java index 936d04a..a4cab30 100644 --- a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/utils/EnumMapUtils.java +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/utils/EnumMapUtils.java @@ -1,25 +1,31 @@ package com.seeyon.apps.src_ydctdatasync.utils; +import com.seeyon.apps.src_ydctdatasync.dao.MyJdbcAgent; import com.seeyon.ctp.common.AppContext; import com.seeyon.ctp.common.ctpenumnew.manager.EnumManager; import com.seeyon.ctp.common.po.ctpenumnew.CtpEnumBean; import com.seeyon.ctp.common.po.ctpenumnew.CtpEnumItem; -import com.seeyon.ctp.util.JDBCAgent; import java.util.Arrays; import java.util.List; import java.util.Map; public class EnumMapUtils { - public static String getEnumItemValue(String rootPCode,JDBCAgent agent,String groupValue,String targetValue) { - String queryIdSql = "SELECT ce.ID FROM ctp_enum ce inner join ctp_enum cei on ce.`PARENT_ID` = cei.ID where CEI.`PROGRAM_COD`E = ? and ce.`ENUMNAME` = ?"; + public static String getEnumItemValue(String rootPCode, MyJdbcAgent agent, String groupValue, String targetValue) { + if(targetValue == null || "null".equals(targetValue) || "".equals(targetValue)){ + return ""; + } + String queryIdSql = "SELECT ce.ID FROM ctp_enum ce inner join ctp_enum cei on ce.`PARENT_ID` = cei.ID where CEI.`PROGRAM_CODE` = ? and ce.`ENUMNAME` = ?"; Long enumId = null; try { - agent.execute(queryIdSql, Arrays.asList(rootPCode,groupValue)); - Map map = agent.resultSetToMap(); - enumId = (Long)map.get("id"); + List> list = (List>) agent.execute(queryIdSql, Arrays.asList(rootPCode,groupValue)); + if(list == null || list.size() == 0) { + return ""; + } + Map map = list.get(0); + enumId = (Long)map.get("ID"); } catch (Exception e) { - return null; + return ""; } EnumManager enumManagerNew = (EnumManager) AppContext.getBean("enumManagerNew"); CtpEnumBean ctpEnumBean = enumManagerNew.getEnum(enumId); @@ -28,13 +34,13 @@ public class EnumMapUtils { } List ctpEnumItems = ctpEnumBean.getItems(); if(ctpEnumBean.getItems() == null) { - return null; + return ""; } for (CtpEnumItem enumItem : ctpEnumItems) { if(enumItem.getShowvalue().equals(targetValue)) { - return enumItem.getValue(); + return enumItem.getId() + ""; } } - return null; + return ""; } } diff --git a/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/utils/SnowflakeIdGenerator.java b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/utils/SnowflakeIdGenerator.java new file mode 100644 index 0000000..2777367 --- /dev/null +++ b/v5/apps-customize/src/main/java/com/seeyon/apps/src_ydctdatasync/utils/SnowflakeIdGenerator.java @@ -0,0 +1,82 @@ +package com.seeyon.apps.src_ydctdatasync.utils; + +public class SnowflakeIdGenerator { + // 起始时间戳 (2020-01-01 00:00:00) + private final long epoch = 1577836800000L; + + // 各部分位数 + private final long workerIdBits = 5L; // 机器 ID 位数 + private final long dataCenterIdBits = 5L; // 数据中心 ID 位数 + private final long sequenceBits = 12L; // 序列号位数 + + // 位移值 + private final long workerIdShift = sequenceBits; + private final long dataCenterIdShift = sequenceBits + workerIdBits; + private final long timestampLeftShift = sequenceBits + workerIdBits + dataCenterIdBits; + + // 最大值 + private final long maxWorkerId = ~(-1L << workerIdBits); + private final long maxDataCenterId = ~(-1L << dataCenterIdBits); + private final long sequenceMask = ~(-1L << sequenceBits); + + // 当前值 + private long workerId; + private long dataCenterId; + private long sequence = 0L; + private long lastTimestamp = -1L; + + public SnowflakeIdGenerator(long workerId, long dataCenterId) { + if (workerId > maxWorkerId || workerId < 0) { + throw new IllegalArgumentException(String.format("Worker ID can't be greater than %d or less than 0", maxWorkerId)); + } + if (dataCenterId > maxDataCenterId || dataCenterId < 0) { + throw new IllegalArgumentException(String.format("DataCenter ID can't be greater than %d or less than 0", maxDataCenterId)); + } + this.workerId = workerId; + this.dataCenterId = dataCenterId; + } + + // 获取当前时间戳 + private long currentTimestamp() { + return System.currentTimeMillis(); + } + + // 阻塞直到下一毫秒 + private long waitForNextMillis(long lastTimestamp) { + long timestamp = currentTimestamp(); + while (timestamp <= lastTimestamp) { + timestamp = currentTimestamp(); + } + return timestamp; + } + + // 生成 ID + public synchronized long nextId() { + long timestamp = currentTimestamp(); + + if (timestamp < lastTimestamp) { + throw new RuntimeException("Clock moved backwards. Refusing to generate id"); + } + + if (timestamp == lastTimestamp) { + // 同一毫秒内,递增序列号 + sequence = (sequence + 1) & sequenceMask; + if (sequence == 0) { + // 序列号溢出,等待下一毫秒 + timestamp = waitForNextMillis(lastTimestamp); + } + } else { + // 不同毫秒,重置序列号 + sequence = 0L; + } + + lastTimestamp = timestamp; + + // 生成唯一 ID + return ((timestamp - epoch) << timestampLeftShift) + | (dataCenterId << dataCenterIdShift) + | (workerId << workerIdShift) + | sequence; + } + +} \ No newline at end of file diff --git a/v5/apps-customize/src/main/webapp/WEB-INF/cfgHome/plugin/src_ydctdatasync/pluginCfg.xml b/v5/apps-customize/src/main/webapp/WEB-INF/cfgHome/plugin/src_ydctdatasync/pluginCfg.xml index 22ea1df..cc8c644 100644 --- a/v5/apps-customize/src/main/webapp/WEB-INF/cfgHome/plugin/src_ydctdatasync/pluginCfg.xml +++ b/v5/apps-customize/src/main/webapp/WEB-INF/cfgHome/plugin/src_ydctdatasync/pluginCfg.xml @@ -2,5 +2,5 @@ src_ydctdatasync 宜都城投数据同步 - 20250101 + 20250102 \ No newline at end of file diff --git a/v5/apps-customize/src/main/webapp/WEB-INF/cfgHome/plugin/src_ydctdatasync/spring/spring-quartz.xml b/v5/apps-customize/src/main/webapp/WEB-INF/cfgHome/plugin/src_ydctdatasync/spring/spring-quartz.xml index 29df0b9..d5d61c3 100644 --- a/v5/apps-customize/src/main/webapp/WEB-INF/cfgHome/plugin/src_ydctdatasync/spring/spring-quartz.xml +++ b/v5/apps-customize/src/main/webapp/WEB-INF/cfgHome/plugin/src_ydctdatasync/spring/spring-quartz.xml @@ -2,7 +2,7 @@ - + \ No newline at end of file