From 58f6d099d3ba1a0c995efc52ba8558be838322d6 Mon Sep 17 00:00:00 2001
From: 354798ggg <1074825718@qq.com>
Date: 星期日, 08 十月 2023 16:32:21 +0800
Subject: [PATCH] 代码优化
---
product-server-project-management/src/main/java/com/product/project/management/service/ProjectBudgetService.java | 6 -
product-server-data-export-import/src/main/java/com/product/module/data/service/SystemDataUpLoadService.java | 242 ++++++++++++++++++++++++++----------------------
product-server-project-base/src/main/java/com/product/base/service/MaterialManagerService.java | 4
3 files changed, 133 insertions(+), 119 deletions(-)
diff --git a/product-server-data-export-import/src/main/java/com/product/module/data/service/SystemDataUpLoadService.java b/product-server-data-export-import/src/main/java/com/product/module/data/service/SystemDataUpLoadService.java
index d490033..5419540 100644
--- a/product-server-data-export-import/src/main/java/com/product/module/data/service/SystemDataUpLoadService.java
+++ b/product-server-data-export-import/src/main/java/com/product/module/data/service/SystemDataUpLoadService.java
@@ -562,7 +562,7 @@
baseDao.saveFieldSetEntity(fse);
return fse.getUUID();
}
-
+
/**
* 涓氬姟鍔熻兘瀵煎叆-瑙f瀽骞朵繚瀛樺埌鏁版嵁搴�
*
@@ -572,105 +572,95 @@
@Override
@Transactional
public void recordDataSave(FieldSetEntity fse) {
+ //鑾峰彇褰撳墠浜轰俊鎭�
SystemUser curUser = SpringMVCContextHolder.getCurrentUser();
-
- FieldSetEntity logFse = baseDao.getFieldSetEntity(CmnConst.TABLE_PRODUCT_SYS_DATA_UPLOAD_RECORD, fse.getUUID(), false);
- if (logFse == null) {
+ //鑾峰彇妯℃澘瀵煎叆璁板綍
+ FieldSetEntity uploadLog = baseDao.getFieldSetEntity(CmnConst.TABLE_PRODUCT_SYS_DATA_UPLOAD_RECORD, fse.getUUID(), false);
+ if (uploadLog == null) {
throw new BaseException(CmnCode.UPLOAD_TEMPLATE_GET_UPLOAD_RECORD_FAIL.getValue(), CmnCode.UPLOAD_TEMPLATE_GET_UPLOAD_RECORD_FAIL.getText());
}
-
- // 鑾峰彇妯℃澘淇℃伅
- DataTableEntity templateDte = baseDao.listTable(CmnConst.TABLE_PRODUCT_SYS_DATA_UPLOAD_MODEL, "upload_sign=?", new Object[]{logFse.getString(CmnConst.FIELD_UPLOAD_SIGN)}, null, "sheet_order", Integer.MAX_VALUE, 1, true);
-
- // 鑾峰彇瀵煎叆鏂囦欢淇℃伅
- FieldSetEntity attachmentFse = baseDao.getFieldSetEntity(CmnConst.TABLE_PRODUCT_SYS_ATTACHMENT, logFse.getString(CmnConst.FIELD_IMPORT_INFO), false);
- String relativePath = attachmentFse.getString(CmnConst.FIELD_ATTACHMENT_URL);
- String templateName = attachmentFse.getString(CmnConst.FIELD_ATTACHMENT_TITLE);
- Map<String, List<List<String>>> dataMap = new HashMap<>();
- try {
- String filePath = Global.getSystemConfig("local.dir", "") + File.separator + relativePath + File.separator + templateName;
- dataMap = EasyExcelUtil.readExcelByString(filePath);
-
- if ("product_project_budget".equals(templateDte.getString(0, CmnConst.TABLE_NAME))) {
- for (int i = 1; i < dataMap.size(); i++) {
- templateDte.addFieldSetEntity(templateDte.getFieldSetEntity(0).clones());
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- // 灏佽鍒癲te涓�
+ //鑾峰彇瀵煎叆妯℃澘閰嶇疆淇℃伅
+ DataTableEntity templateDt = baseDao.listTable(CmnConst.TABLE_PRODUCT_SYS_DATA_UPLOAD_MODEL, "upload_sign=?", new Object[]{uploadLog.getString(CmnConst.FIELD_UPLOAD_SIGN)}, null, "sheet_order", Integer.MAX_VALUE, 1, true);
+
+ //澶歋heet鍘熷鏁版嵁闆�
+ Map<String, List<List<String>>> dataMap = readExcelData(templateDt, uploadLog);
+
+ //澶歋heet瑙f瀽鏁版嵁闆�
List<DataTableEntity> beforeSaveDataList = Lists.newArrayList();
- List<String> titleList;
- List<List<String>> dataList;
- List<String> rowList;
String singleValue;// 鍗曞厓鏍煎唴鐨勫��
- int index = 0;
- FieldSetEntity curTemplateFse;
- Map<String, FieldSetEntity> curSubMap;
+ //sheet绱㈠紩
+ int sheetIndex = 0;
+
+ /**
+ * 鍙傜収蹇�熻В鏋愶紙鏈�氱敤锛屼粎闄愰绠楀鍏ワ級
+ */
+ Map<String, List<String>> mapRefer = new HashMap<>();
+
+ //琛ㄥご鏁版嵁
List<List<List<String>>> headerDataList = Lists.newArrayList();
- List<Map<String, FieldSetEntity>> fieldInfoList = Lists.newArrayList();
- FieldSetEntity curFieldFse;
- FieldSetEntity recordFse;// 涓氬姟琛╢se
- DataTableEntity recordDte;// 涓氬姟琛╠te
+
+ //閬嶅巻Sheet鏁版嵁
for (Map.Entry<String, List<List<String>>> entry : dataMap.entrySet()) {
- dataList = entry.getValue();
- if (dataList.isEmpty()) {
+
+ //鑾峰彇鍗曚釜Sheet鍘熷鏁版嵁(鍗曚釜Sheet鎵�鏈夎)
+ List<List<String>> rowList = entry.getValue();
+ if (rowList.isEmpty()) {
continue;
}
-
- recordDte = new DataTableEntity();
- curTemplateFse = templateDte.getFieldSetEntity(index);
- curSubMap = dte2Map(curTemplateFse.getSubDataTable(CmnConst.TABLE_PRODUCT_SYS_DATA_UPLOAD_MODEL_SUB), CmnConst.FIELD_EXCEL_HEADER);
- fieldInfoList.add(curSubMap);
- // 瀛楁瀵瑰簲鐨別xcel 琛ㄥご绱㈠紩
+ //鍗昐heet瑙f瀽鏁版嵁闆嗗悎
+ DataTableEntity parseDataDt = new DataTableEntity();
+ //褰撳墠Sheet瀵瑰簲閰嶇疆淇℃伅
+ FieldSetEntity currentTemplate = templateDt.getFieldSetEntity(sheetIndex);
+ //excel琛ㄥご瀵瑰簲瀛楁淇℃伅
+ Map<String, FieldSetEntity> curSubMap = dte2Map(currentTemplate.getSubDataTable(CmnConst.TABLE_PRODUCT_SYS_DATA_UPLOAD_MODEL_SUB), CmnConst.FIELD_EXCEL_HEADER);
+ //瀛楁瀵瑰簲鐨別xcel 琛ㄥご绱㈠紩
Map<String, String> fieldIndex = Maps.newHashMap();
- //琛ㄥご寮�濮嬭 cheng update 2023骞�6鏈�30鏃�15:48:22 澶氳澶存椂锛岃〃澶村紑濮嬭涓嶄竴瀹氭槸绗竴琛�
+ //鏁版嵁寮�濮嬭
int startRowIndex = 1;
- if (!StringUtils.isEmpty(curTemplateFse.getString("start_row_index")) && NumberUtil.isNumber(curTemplateFse.getString("start_row_index"))) {
- startRowIndex = Integer.parseInt(curTemplateFse.getString("start_row_index"));
+ if (!StringUtils.isEmpty(currentTemplate.getString("start_row_index")) && NumberUtil.isNumber(currentTemplate.getString("start_row_index"))) {
+ startRowIndex = Integer.parseInt(currentTemplate.getString("start_row_index"));
if (startRowIndex < 1) {
startRowIndex = 1;
}
}
-
- titleList = dataList.get(startRowIndex);
+ //鑾峰彇excel琛ㄥご鏈�鍚庝竴琛屾暟鎹紙鐩存帴涓庢暟鎹搴旓級
+ List<String> sheetTitle = rowList.get(startRowIndex);
if (startRowIndex > 0) {
- headerDataList.add(dataList.subList(0, startRowIndex));
+ headerDataList.add(rowList.subList(0, startRowIndex));
} else {
headerDataList.add(new ArrayList<>());
}
- for (int i = startRowIndex + 1; i < dataList.size(); i++) {
- rowList = dataList.get(i);
- System.out.println(rowList.toString());
- recordFse = new FieldSetEntity();
- recordFse.setTableName(curTemplateFse.getString(CmnConst.FIELD_TABLE_NAME));
+ //閬嶅巻excel鍘熷鏁版嵁琛�
+ for (int i = startRowIndex + 1; i < rowList.size(); i++) {
+ List<String> rowData = rowList.get(i);
+ FieldSetEntity recordInfo = new FieldSetEntity();
+ recordInfo.setTableName(currentTemplate.getString(CmnConst.FIELD_TABLE_NAME));
//瀛楁瀵瑰簲鐨勫垪
- int j = 0;
- for (; j < titleList.size() && j<14; j++) {
- if (rowList.size() < (j + 1)) {
+ for (int j = 0; j < sheetTitle.size() && j<14; j++) {
+ if (rowData.size() < (j + 1)) {
singleValue = null;
} else {
- singleValue = rowList.get(j);
+ singleValue = rowData.get(j);
}
- curFieldFse = curSubMap.get(titleList.get(j));
- System.out.println(curFieldFse.getString(CmnConst.FIELD_FIELD_NAME)+":"+singleValue);
- recordFse.setValue(curFieldFse.getString(CmnConst.FIELD_FIELD_NAME), singleValue);
- if (i == 1 || rowList.size() > fieldIndex.size()) {
- fieldIndex.put(curFieldFse.getString(CmnConst.FIELD_FIELD_NAME), String.valueOf(j));
+ //鑾峰彇璇ュ�煎搴旂殑瀛楁淇℃伅
+ FieldSetEntity currentFieldInfo = curSubMap.get(sheetTitle.get(j));
+ //瀛樺偍璇诲彇鍚庣殑鏁版嵁
+ recordInfo.setValue(currentFieldInfo.getString(CmnConst.FIELD_FIELD_NAME), singleValue);
+ if (i == 1 || rowData.size() > fieldIndex.size()) {
+ fieldIndex.put(currentFieldInfo.getString(CmnConst.FIELD_FIELD_NAME), String.valueOf(j));
}
}
- recordFse.setValue("~colName~", titleList);
- recordFse.setValue("~fieldIndex~", fieldIndex);
- // fieldSet 瀵瑰簲鐨勮
- recordFse.setValue("~row~", i);
- recordDte.addFieldSetEntity(recordFse);
+ recordInfo.setValue("~colName~", sheetTitle);
+ recordInfo.setValue("~fieldIndex~", fieldIndex);
+ //fieldSet 瀵瑰簲鐨勮
+ recordInfo.setValue("~row~", i);
+ parseDataDt.addFieldSetEntity(recordInfo);
}
- beforeSaveDataList.add(recordDte);
- index++;
+ beforeSaveDataList.add(parseDataDt);
+ sheetIndex++;
}
- // 鏁版嵁瑙f瀽淇濆瓨
+ //鏁版嵁瑙f瀽淇濆瓨
String orgLevelUUID = curUser.getOrg_level_uuid();
String actualValue;
FieldMetaEntity meta;
@@ -680,9 +670,9 @@
for (int i = 0; i < beforeSaveDataList.size(); i++) {
tempDte = beforeSaveDataList.get(i);
- // 淇濆瓨鍓嶅鐞�
+ //淇濆瓨鍓嶅鐞�
try {
- tempDte = spDeal(templateDte.getFieldSetEntity(i).getString(CmnConst.FIELD_BEFORE_FUNC), tempDte, headerDataList.get(i));
+ tempDte = spDeal(templateDt.getFieldSetEntity(i).getString(CmnConst.FIELD_BEFORE_FUNC), tempDte, headerDataList.get(i));
if (BaseUtil.dataTableIsEmpty(tempDte)) {
throw new BaseException(CmnCode.UPLOAD_TEMPLATE_BEFORE_FUNC_EXEC_NO_DATA.getValue(), CmnCode.UPLOAD_TEMPLATE_BEFORE_FUNC_EXEC_NO_DATA.getText());
}
@@ -696,65 +686,96 @@
meta = tempDte.getMeta();
fieldArr = meta.getFields();
- curTemplateFse = templateDte.getFieldSetEntity(i);
- curSubMap = dte2Map(curTemplateFse.getSubDataTable(CmnConst.TABLE_PRODUCT_SYS_DATA_UPLOAD_MODEL_SUB), CmnConst.FIELD_FIELD_NAME);
+ FieldSetEntity currentTemplate = templateDt.getFieldSetEntity(i);
+ Map<String, FieldSetEntity> curSubMap = dte2Map(currentTemplate.getSubDataTable(CmnConst.TABLE_PRODUCT_SYS_DATA_UPLOAD_MODEL_SUB), CmnConst.FIELD_FIELD_NAME);
boolean isMultiFlag;
StringBuilder errorMsg = new StringBuilder(8);
for (int j = 0; j < tempDte.getRows(); j++) {
- recordFse = tempDte.getFieldSetEntity(j);
+ FieldSetEntity recordInfo = tempDte.getFieldSetEntity(j);
for (Object fieldNameObj : fieldArr) {
if (fieldNameObj == null) {
continue;
}
fieldName = fieldNameObj.toString();
- singleValue = recordFse.getString(fieldName);
+ singleValue = recordInfo.getString(fieldName);
- curFieldFse = curSubMap.get(fieldName);
- if (curFieldFse != null) {
+ FieldSetEntity currentFieldInfo = curSubMap.get(fieldName);
+ if (currentFieldInfo != null) {
// 鎻愬彇鐪熷疄鍊�
- if (!StringUtils.isEmpty(curFieldFse.getString(CmnConst.FIELD_PROMPT_NAME))) {
- isMultiFlag = curFieldFse.getString(CmnConst.FIELD_IS_MULTI) == null ? false : "1".equals(curFieldFse.getString(CmnConst.FIELD_IS_MULTI));
+ if (!StringUtils.isEmpty(currentFieldInfo.getString(CmnConst.FIELD_PROMPT_NAME))) {
+ isMultiFlag = currentFieldInfo.getString(CmnConst.FIELD_IS_MULTI) == null ? false : "1".equals(currentFieldInfo.getString(CmnConst.FIELD_IS_MULTI));
// 鏍规嵁鍙傜収鍚嶇О锛屽弬鐓х被鍨嬶紝鏄剧ず鍩熺殑鍊硷紝鑾峰彇闅愯棌鍩熺殑鍊�
- actualValue = getRealValue(curFieldFse.getString(CmnConst.FIELD_PROMPT_NAME), singleValue, isMultiFlag);
+ actualValue = getRealValue(currentFieldInfo.getString(CmnConst.FIELD_PROMPT_NAME), singleValue, isMultiFlag);
} else {
actualValue = singleValue;
}
- recordFse.setValue(curFieldFse.getString(CmnConst.FIELD_FIELD_NAME), actualValue);
+ recordInfo.setValue(currentFieldInfo.getString(CmnConst.FIELD_FIELD_NAME), actualValue);
}
}
- try {
- BaseUtil.createCreatorAndCreationTime(curUser, recordFse);
- baseDao.saveFieldSetEntity(recordFse);
- } catch (BaseException e) {
- e.printStackTrace();
-// errorMsg.append("瀵煎叆鏁版嵁閿欒锛歕n\t");
- errorMsg.append(String.format("绗�%s涓猻heet锛岀%s琛�,%s", i + 1, j + 1, e.getMessageInfo() != null ? e.getMessageInfo() : "")).append("\n");
-// throw new BaseException(CmnCode.UPLOAD_TEMPLATE_IMPORT_DATA_FAIL.getValue(), String.format("%s: 绗�%s涓猻heet锛岀%s琛�", CmnCode.UPLOAD_TEMPLATE_IMPORT_DATA_FAIL.getText(), i + 1, j + 1), e);
- } catch (Exception e) {
- errorMsg.append(String.format("绗�%s涓猻heet锛岀%s琛�,%s", i + 1, j + 1, e.getMessage() != null ? e.getMessage() : "")).append("\n");
-// throw new BaseException(CmnCode.UPLOAD_TEMPLATE_IMPORT_DATA_FAIL.getValue(), String.format("%s: 绗�%s涓猻heet锛岀%s琛�", CmnCode.UPLOAD_TEMPLATE_IMPORT_DATA_FAIL.getText(), i + 1, j + 1));
- }
+// try {
+ BaseUtil.createCreatorAndCreationTime(curUser, recordInfo);
+// baseDao.saveFieldSetEntity(recordInfo);
+// } catch (BaseException e) {
+// e.printStackTrace();
+// errorMsg.append(String.format("绗�%s涓猻heet锛岀%s琛�,%s", i + 1, j + 1, e.getMessageInfo() != null ? e.getMessageInfo() : "")).append("\n");
+// } catch (Exception e) {
+// errorMsg.append(String.format("绗�%s涓猻heet锛岀%s琛�,%s", i + 1, j + 1, e.getMessage() != null ? e.getMessage() : "")).append("\n");
+// }
}
if (errorMsg.length() > 0) {
throw new BaseException(CmnCode.UPLOAD_TEMPLATE_IMPORT_DATA_FAIL.getValue(), errorMsg.toString());
}
-
- // 淇濆瓨鍚庡鐞�
+ //鎵归噺淇濆瓨
try {
- spDeal(templateDte.getFieldSetEntity(i).getString(CmnConst.FIELD_AFTER_FUNC), tempDte, headerDataList.get(i));
- } catch (BaseException e) {
- SpringMVCContextHolder.getSystemLogger().error(e);
+ baseDao.add(tempDte);
} catch (Exception e) {
- throw new BaseException(CmnCode.UPLOAD_TEMPLATE_AFTER_FUNC_EXEC_FAIL.getValue(), CmnCode.UPLOAD_TEMPLATE_AFTER_FUNC_EXEC_FAIL.getText());
+ e.printStackTrace();
}
+
+// 淇濆瓨鍚庡鐞�
+// try {
+// spDeal(templateDt.getFieldSetEntity(i).getString(CmnConst.FIELD_AFTER_FUNC), tempDte, headerDataList.get(i));
+// } catch (BaseException e) {
+// SpringMVCContextHolder.getSystemLogger().error(e);
+// } catch (Exception e) {
+// throw new BaseException(CmnCode.UPLOAD_TEMPLATE_AFTER_FUNC_EXEC_FAIL.getValue(), CmnCode.UPLOAD_TEMPLATE_AFTER_FUNC_EXEC_FAIL.getText());
+// }
}
// 鏇存柊璁板綍琛ㄦ儏鍐�
- logFse.setValue(CmnConst.FIELD_IS_SUCCESS, 1);
+ uploadLog.setValue(CmnConst.FIELD_IS_SUCCESS, 1);
BaseUtil.updatedRegeneratorAndUpdateTime(curUser, fse);
- baseDao.saveFieldSetEntity(logFse);
+ baseDao.saveFieldSetEntity(uploadLog);
}
+ /**
+ * 璇诲彇涓婁紶鐨凟XCEL鍘熷鏁版嵁锛屽苟鍖归厤瑙f瀽妯℃澘
+ * @param templateDt
+ * @param uploadLog
+ * @return
+ */
+ public Map<String, List<List<String>>> readExcelData(DataTableEntity templateDt, FieldSetEntity uploadLog){
+ FieldSetEntity templateInfo = baseDao.getFieldSetEntity(CmnConst.TABLE_PRODUCT_SYS_ATTACHMENT, uploadLog.getString(CmnConst.FIELD_IMPORT_INFO), false);
+ String relativePath = templateInfo.getString(CmnConst.FIELD_ATTACHMENT_URL);
+ String templateName = templateInfo.getString(CmnConst.FIELD_ATTACHMENT_TITLE);
+ //鐢熸垚涓婁紶EXCEL鍦板潃
+ String filePath = Global.getSystemConfig("local.dir", "") + File.separator + relativePath + File.separator + templateName;
+ try {
+ //璇诲彇EXCEL澶歋heet鍘熷鏁版嵁
+ Map<String, List<List<String>>> dataMap = EasyExcelUtil.readExcelByString(filePath);
+ //澶歋heet鍚岃〃,鍏嬮殕妯℃澘閰嶇疆
+ if ("product_project_budget".equals(templateDt.getString(0, CmnConst.TABLE_NAME))) {
+ for (int i = 1; i < dataMap.size(); i++) {
+ templateDt.addFieldSetEntity(templateDt.getFieldSetEntity(0).clones());
+ }
+ }
+ return dataMap;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
/**
* dte鎸夌収鎸囧畾fse涓殑鍊间綔涓簁ey杞崲涓簃ap
*
@@ -770,12 +791,6 @@
resultMap.put(tempFse.getString(keyFieldName), tempFse);
}
return resultMap;
- }
-
- public static void main(String[] args) {
- Class<?> a = DataTableEntity.class;
- Class<DataTableEntity> b = DataTableEntity.class;
- System.out.println(a.equals(b));
}
/**
@@ -874,7 +889,12 @@
sql.append(" and ").append(dataFilter);
}
}
- FieldSetEntity sourceFse = baseDao.getFieldSetEntityBySQL(sql.toString(), showSet.toArray(), false);
+ FieldSetEntity sourceFse=null;
+ try {
+ sourceFse = baseDao.getFieldSetEntityBySQL(sql.toString(), showSet.toArray(), false);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
if (sourceFse != null) {
realValue = sourceFse.getString("real_value");
}
diff --git a/product-server-project-base/src/main/java/com/product/base/service/MaterialManagerService.java b/product-server-project-base/src/main/java/com/product/base/service/MaterialManagerService.java
index 482b519..3865a6c 100644
--- a/product-server-project-base/src/main/java/com/product/base/service/MaterialManagerService.java
+++ b/product-server-project-base/src/main/java/com/product/base/service/MaterialManagerService.java
@@ -43,7 +43,7 @@
*/
public String saveMaterialType(FieldSetEntity fse) {
if (BaseUtil.strIsNull(fse.getUUID())) {
- FieldSetEntity fseMaxValue = baseDao.getFieldSetEntityBySQL("SELECT (MAX(material_type_value) + 1) material_type_value FROM product_project_base_material_type", new Object[] {}, false);
+ FieldSetEntity fseMaxValue = baseDao.getFieldSetEntityBySQL("SELECT IFNULL((MAX(material_type_value) + 1),0) material_type_value FROM product_project_base_material_type", new Object[] {}, false);
fse.setValue(CmnConst.MATERIAL_TYPE_VALUE, fseMaxValue.getString(CmnConst.MATERIAL_TYPE_VALUE));
} else {
if ("0".equals(fse.getString(CmnConst.IS_USED))) {
@@ -62,7 +62,7 @@
}
baseDao.saveFieldSetEntity(fse);
return fse.getUUID();
- }
+ }
/**
* 鍒嗛〉鑾峰彇鏉愭枡淇℃伅
diff --git a/product-server-project-management/src/main/java/com/product/project/management/service/ProjectBudgetService.java b/product-server-project-management/src/main/java/com/product/project/management/service/ProjectBudgetService.java
index 28da60e..12fd31d 100644
--- a/product-server-project-management/src/main/java/com/product/project/management/service/ProjectBudgetService.java
+++ b/product-server-project-management/src/main/java/com/product/project/management/service/ProjectBudgetService.java
@@ -1,6 +1,5 @@
package com.product.project.management.service;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -33,8 +32,6 @@
* @param headerDataList excel鏍囬鏁版嵁
*/
public DataTableEntity importBudget2(DataTableEntity dtParseData, List<List<String>> headerDataList) {
- try {
-
//鍒ゆ柇鏄惁鏈夎В鏋怑XCEL鏁版嵁
if (BaseUtil.dataTableIsEmpty(dtParseData)) {
@@ -85,9 +82,6 @@
} catch (Exception e) {
e.printStackTrace();
}
- }
- } catch (Exception e) {
- e.printStackTrace();
}
return dtParseData;
}
--
Gitblit v1.9.2