diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8a4660ff9..85a567d67 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@
### 新特性
### Bug修复
+* 【core 】 修复CombinationAnnotationElement数组判断问题(issue#752@Github)
-------------------------------------------------------------------------------------------------------------
diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/CombinationAnnotationElement.java b/hutool-core/src/main/java/cn/hutool/core/annotation/CombinationAnnotationElement.java
index efe14cfbf..c24a0bb9e 100644
--- a/hutool-core/src/main/java/cn/hutool/core/annotation/CombinationAnnotationElement.java
+++ b/hutool-core/src/main/java/cn/hutool/core/annotation/CombinationAnnotationElement.java
@@ -1,5 +1,7 @@
package cn.hutool.core.annotation;
+import cn.hutool.core.collection.CollUtil;
+
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
@@ -7,14 +9,12 @@ import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedElement;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
-import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.util.ObjectUtil;
-
/**
* 组合注解 对JDK的原生注解机制做一个增强,支持类似Spring的组合注解。
* 核心实现使用了递归获取指定元素上的注解以及注解的注解,以实现复合注解的获取。
@@ -65,13 +65,13 @@ public class CombinationAnnotationElement implements AnnotatedElement, Serializa
@Override
public Annotation[] getAnnotations() {
final Collection annotations = this.annotationMap.values();
- return annotations.toArray(new Annotation[annotations.size()]);
+ return annotations.toArray(new Annotation[0]);
}
@Override
public Annotation[] getDeclaredAnnotations() {
final Collection annotations = this.declaredAnnotationMap.values();
- return annotations.toArray(new Annotation[annotations.size()]);
+ return annotations.toArray(new Annotation[0]);
}
/**
@@ -85,7 +85,7 @@ public class CombinationAnnotationElement implements AnnotatedElement, Serializa
parseDeclared(declaredAnnotations);
final Annotation[] annotations = element.getAnnotations();
- if(ObjectUtil.equal(declaredAnnotations, annotations)) {
+ if(Arrays.equals(declaredAnnotations, annotations)) {
this.annotationMap = this.declaredAnnotationMap;
}else {
this.annotationMap = new HashMap<>();
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java
index b08544f67..3bdbd8d4b 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java
@@ -2700,8 +2700,7 @@ public class ArrayUtil {
* @since 3.0.9
*/
public static T[] toArray(Collection collection, Class componentType) {
- final T[] array = newArray(componentType, collection.size());
- return collection.toArray(array);
+ return collection.toArray(newArray(componentType, 0));
}
// ---------------------------------------------------------------------- remove
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java
index e8482a583..c613c01a9 100644
--- a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java
@@ -1,11 +1,14 @@
package cn.hutool.core.util;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Editor;
import cn.hutool.core.lang.Filter;
import org.junit.Assert;
import org.junit.Test;
+import java.util.ArrayList;
import java.util.Map;
+import java.util.Objects;
/**
* {@link ArrayUtil} 数组工具单元测试
@@ -20,8 +23,10 @@ public class ArrayUtilTest {
Assert.assertTrue(ArrayUtil.isEmpty(a));
Assert.assertTrue(ArrayUtil.isEmpty((Object) a));
int[] b = null;
+ //noinspection ConstantConditions
Assert.assertTrue(ArrayUtil.isEmpty(b));
Object c = null;
+ //noinspection ConstantConditions
Assert.assertTrue(ArrayUtil.isEmpty(c));
Object d = new Object[]{"1", "2", 3, 4D};
@@ -31,7 +36,9 @@ public class ArrayUtilTest {
isEmpty = ArrayUtil.isEmpty(d);
Assert.assertTrue(isEmpty);
d = null;
+ //noinspection ConstantConditions
isEmpty = ArrayUtil.isEmpty(d);
+ //noinspection ConstantConditions
Assert.assertTrue(isEmpty);
}
@@ -117,7 +124,7 @@ public class ArrayUtilTest {
String[] keys = {"a", "b", "c"};
Integer[] values = {1, 2, 3};
Map map = ArrayUtil.zip(keys, values, true);
- Assert.assertEquals(map.toString(), "{a=1, b=2, c=3}");
+ Assert.assertEquals(Objects.requireNonNull(map).toString(), "{a=1, b=2, c=3}");
}
@Test
@@ -248,4 +255,14 @@ public class ArrayUtilTest {
String[] array = {"aa", "bb", "cc", "dd", "bb", "dd"};
Assert.assertEquals("[aa, bb, cc, dd, bb, dd]", ArrayUtil.toString(array));
}
+
+ @Test
+ public void toArrayTest(){
+ final ArrayList list = CollUtil.newArrayList("A", "B", "C", "D");
+ final String[] array = ArrayUtil.toArray(list, String.class);
+ Assert.assertEquals("A", array[0]);
+ Assert.assertEquals("B", array[1]);
+ Assert.assertEquals("C", array[2]);
+ Assert.assertEquals("D", array[3]);
+ }
}
diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml
index d18b020d5..25eacc21a 100644
--- a/hutool-poi/pom.xml
+++ b/hutool-poi/pom.xml
@@ -17,9 +17,8 @@
- 4.1.1
+ 4.1.2
2.12.0
- 2.1.6
@@ -49,12 +48,5 @@
compile
true
-
- com.alibaba
- easyexcel
- ${easyexcel.version}
- compile
- true
-
diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java
index 332b7e47d..95a044ad8 100644
--- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java
+++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java
@@ -1,6 +1,5 @@
package cn.hutool.poi.excel.sax;
-import cn.hutool.core.exceptions.DependencyException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.sax.handler.RowHandler;
@@ -13,14 +12,9 @@ import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.XMLReaderFactory;
import java.io.File;
-import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
@@ -35,8 +29,6 @@ import java.util.List;
*/
public class Excel07SaxReader extends AbstractExcelSaxReader implements ContentHandler {
- // saxParser
- private static final String CLASS_SAXPARSER = "org.apache.xerces.parsers.SAXParser";
/**
* Cell单元格元素
*/
@@ -46,7 +38,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i
*/
private static final String ROW_ELEMENT = "row";
/**
- * Cell中的行列号
+ * Cell中的行列号(Reference),行模式下此为行号属性名,列模式下为列号属性名
*/
private static final String R_ATTR = "r";
/**
@@ -54,7 +46,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i
*/
private static final String T_ELEMENT = "t";
/**
- * SST(SharedStringsTable) 的索引
+ * SST(SharedStringsTable) 的索引,样式index
*/
private static final String S_ATTR_VALUE = "s";
// 列中属性值
@@ -69,7 +61,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i
// 当前列
private int curCell;
// 上一次的内容
- private String lastContent;
+ private StringBuilder lastContent = new StringBuilder(64);
// 单元数据类型
private CellDataType cellDataType;
// 当前列坐标, 如A1,B5
@@ -160,7 +152,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i
this.sheetIndex = rid;
// 根据 rId# 或 rSheet# 查找sheet
sheetInputStream = xssfReader.getSheet(RID_PREFIX + (rid + 1));
- parse(sheetInputStream);
+ ExcelSaxUtil.readFrom(sheetInputStream, this);
} else {
this.sheetIndex = -1;
// 遍历所有sheet
@@ -170,7 +162,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i
curRow = 0;
this.sheetIndex++;
sheetInputStream = sheetInputStreams.next();
- parse(sheetInputStream);
+ ExcelSaxUtil.readFrom(sheetInputStream, this);
}
}
} catch (RuntimeException e) {
@@ -191,8 +183,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
// 单元格元素
- if (C_ELEMENT.equals(qName)) {
-
+ if (C_ELEMENT.equals(localName)) {
// 获取当前列坐标
String tempCurCoordinate = attributes.getValue(R_ATTR);
// 前一列为null,则将其设置为"@",A为第一列,ascii码为65,前一列即为@,ascii码64
@@ -208,38 +199,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i
setCellType(attributes);
}
- lastContent = "";
- }
-
- /**
- * 设置单元格的类型
- *
- * @param attribute 属性
- */
- private void setCellType(Attributes attribute) {
- // 单元格存储格式的索引,对应style.xml中的numFmts元素的子元素索引
- int numFmtIndex;
- // numFmtString的值
- numFmtString = "";
- this.cellDataType = CellDataType.of(attribute.getValue(T_ATTR_VALUE));
-
- // 获取单元格的xf索引,对应style.xml中cellXfs的子元素xf
- if(null != this.stylesTable){
- final String xfIndexStr = attribute.getValue(S_ATTR_VALUE);
- if (null != xfIndexStr) {
- int xfIndex = Integer.parseInt(xfIndexStr);
- XSSFCellStyle xssfCellStyle = stylesTable.getStyleAt(xfIndex);
- numFmtIndex = xssfCellStyle.getDataFormat();
- numFmtString = xssfCellStyle.getDataFormatString();
-
- if (numFmtString == null) {
- numFmtString = BuiltinFormats.getBuiltinFormat(numFmtIndex);
- } else if (CellDataType.NUMBER == this.cellDataType && org.apache.poi.ss.usermodel.DateUtil.isADateFormat(numFmtIndex, numFmtString)) {
- cellDataType = CellDataType.DATE;
- }
- }
- }
-
+ lastContent.setLength(0);
}
/**
@@ -253,13 +213,13 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i
// // type标签
// // rowCellList.add(curCell++, contentStr);
// } else
- if (C_ELEMENT.equals(qName)) {
+ if (C_ELEMENT.equals(localName)) {
// cell标签
Object value = ExcelSaxUtil.getDataValue(this.cellDataType, contentStr, this.sharedStringsTable, this.numFmtString);
// 补全单元格之间的空格
fillBlankCell(preCoordinate, curCoordinate, false);
rowCellList.add(curCell++, value);
- } else if (ROW_ELEMENT.equals(qName)) {
+ } else if (ROW_ELEMENT.equals(localName)) {
// 如果是row标签,说明已经到了一行的结尾
// 最大列坐标以第一行的为准
if (curRow == 0) {
@@ -292,7 +252,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i
@Override
public void characters(char[] ch, int start, int length) {
// 得到单元格内容的值
- lastContent = lastContent.concat(new String(ch, start, length));
+ lastContent.append(ch, start, length);
}
// --------------------------------------------------------------------------------------- Pass method start
@@ -341,18 +301,6 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i
// --------------------------------------------------------------------------------------- Pass method end
// --------------------------------------------------------------------------------------- Private method start
-
- /**
- * 处理流中的Excel数据
- *
- * @param sheetInputStream sheet流
- * @throws IOException IO异常
- * @throws SAXException SAX异常
- */
- private void parse(InputStream sheetInputStream) throws IOException, SAXException {
- fetchSheetReader().parse(new InputSource(sheetInputStream));
- }
-
/**
* 填充空白单元格,如果前一个单元格大于后一个,不需要填充
*
@@ -373,24 +321,32 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i
}
/**
- * 获取sheet的解析器
+ * 设置单元格的类型
*
- * @return {@link XMLReader}
- * @throws SAXException SAX异常
+ * @param attribute 属性
*/
- private XMLReader fetchSheetReader() throws SAXException {
- XMLReader xmlReader;
- try {
- xmlReader = XMLReaderFactory.createXMLReader(CLASS_SAXPARSER);
- } catch (SAXException e) {
- if (e.getMessage().contains("org.apache.xerces.parsers.SAXParser")) {
- throw new DependencyException(e, "You need to add 'xerces:xercesImpl' to your project and version >= 2.11.0");
- } else {
- throw e;
+ private void setCellType(Attributes attribute) {
+ // numFmtString的值
+ numFmtString = "";
+ this.cellDataType = CellDataType.of(attribute.getValue(T_ATTR_VALUE));
+
+ // 获取单元格的xf索引,对应style.xml中cellXfs的子元素xf
+ if(null != this.stylesTable){
+ final String xfIndexStr = attribute.getValue(S_ATTR_VALUE);
+ if (null != xfIndexStr) {
+ int xfIndex = Integer.parseInt(xfIndexStr);
+ final XSSFCellStyle xssfCellStyle = stylesTable.getStyleAt(xfIndex);
+ numFmtString = xssfCellStyle.getDataFormatString();
+ // 单元格存储格式的索引,对应style.xml中的numFmts元素的子元素索引
+ int numFmtIndex = xssfCellStyle.getDataFormat();
+ if (numFmtString == null) {
+ numFmtString = BuiltinFormats.getBuiltinFormat(numFmtIndex);
+ } else if (CellDataType.NUMBER == this.cellDataType && org.apache.poi.ss.usermodel.DateUtil.isADateFormat(numFmtIndex, numFmtString)) {
+ cellDataType = CellDataType.DATE;
+ }
}
}
- xmlReader.setContentHandler(this);
- return xmlReader;
+
}
// --------------------------------------------------------------------------------------- Private method end
}
\ No newline at end of file
diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java
index fa47acac7..da55c4a2a 100644
--- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java
+++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java
@@ -1,18 +1,28 @@
package cn.hutool.poi.excel.sax;
-import org.apache.poi.ss.usermodel.DataFormatter;
-import org.apache.poi.xssf.model.SharedStringsTable;
-import org.apache.poi.xssf.usermodel.XSSFRichTextString;
-
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.exceptions.DependencyException;
+import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.StrUtil;
+import cn.hutool.poi.exceptions.POIException;
+import org.apache.poi.ooxml.util.SAXHelper;
+import org.apache.poi.ss.usermodel.DataFormatter;
+import org.apache.poi.xssf.model.SharedStringsTable;
+import org.apache.poi.xssf.usermodel.XSSFRichTextString;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.io.InputStream;
/**
* Sax方式读取Excel相关工具类
- *
- * @author looly
*
+ * @author looly
*/
public class ExcelSaxUtil {
@@ -23,67 +33,67 @@ public class ExcelSaxUtil {
/**
* 根据数据类型获取数据
- *
- * @param cellDataType 数据类型枚举
- * @param value 数据值
+ *
+ * @param cellDataType 数据类型枚举
+ * @param value 数据值
* @param sharedStringsTable {@link SharedStringsTable}
- * @param numFmtString 数字格式名
+ * @param numFmtString 数字格式名
* @return 数据值
*/
public static Object getDataValue(CellDataType cellDataType, String value, SharedStringsTable sharedStringsTable, String numFmtString) {
if (null == value) {
return null;
}
-
- if(null == cellDataType) {
+
+ if (null == cellDataType) {
cellDataType = CellDataType.NULL;
}
Object result;
switch (cellDataType) {
- case BOOL:
- result = (value.charAt(0) != '0');
- break;
- case ERROR:
- result = StrUtil.format("\\\"ERROR: {} ", value);
- break;
- case FORMULA:
- result = StrUtil.format("\"{}\"", value);
- break;
- case INLINESTR:
- result = new XSSFRichTextString(value).toString();
- break;
- case SSTINDEX:
- try {
- final int index = Integer.parseInt(value);
- //noinspection deprecation
- result = new XSSFRichTextString(sharedStringsTable.getEntryAt(index)).getString();
- } catch (NumberFormatException e) {
+ case BOOL:
+ result = (value.charAt(0) != '0');
+ break;
+ case ERROR:
+ result = StrUtil.format("\\\"ERROR: {} ", value);
+ break;
+ case FORMULA:
+ result = StrUtil.format("\"{}\"", value);
+ break;
+ case INLINESTR:
+ result = new XSSFRichTextString(value).toString();
+ break;
+ case SSTINDEX:
+ try {
+ final int index = Integer.parseInt(value);
+ //noinspection deprecation
+ result = new XSSFRichTextString(sharedStringsTable.getEntryAt(index)).getString();
+ } catch (NumberFormatException e) {
+ result = value;
+ }
+ break;
+ case NUMBER:
+ result = getNumberValue(value, numFmtString);
+ break;
+ case DATE:
+ try {
+ result = getDateValue(value);
+ } catch (Exception e) {
+ result = value;
+ }
+ break;
+ default:
result = value;
- }
- break;
- case NUMBER:
- result = getNumberValue(value, numFmtString);
- break;
- case DATE:
- try {
- result = getDateValue(value);
- } catch (Exception e) {
- result = value;
- }
- break;
- default:
- result = value;
- break;
+ break;
}
return result;
}
/**
* 格式化数字或日期值
- *
- * @param value 值
- * @param numFmtIndex 数字格式索引
+ *
+ * @param value 值
+ * @param numFmtIndex 数字格式索引
* @param numFmtString 数字格式名
* @return 格式化后的值
*/
@@ -100,9 +110,9 @@ public class ExcelSaxUtil {
/**
* 计算两个单元格之间的单元格数目(同一行)
- *
+ *
* @param preRef 前一个单元格位置,例如A1
- * @param ref 当前单元格位置,例如A8
+ * @param ref 当前单元格位置,例如A8
* @return 同一行中两个单元格之间的空单元格数
*/
public static int countNullCell(String preRef, String ref) {
@@ -123,9 +133,41 @@ public class ExcelSaxUtil {
return res - 1;
}
+ /**
+ * 从Excel的XML文档中读取内容,并使用{@link ContentHandler}处理
+ *
+ * @param xmlDocStream Excel的XML文档流
+ * @param handler 文档内容处理接口,实现此接口用于回调处理数据
+ * @throws DependencyException 依赖异常
+ * @throws POIException POI异常,包装了SAXException
+ * @throws IORuntimeException IO异常,如流关闭或异常等
+ * @since 5.1.4
+ */
+ public static void readFrom(InputStream xmlDocStream, ContentHandler handler) throws DependencyException, POIException, IORuntimeException {
+ XMLReader xmlReader;
+ try {
+ //noinspection deprecation
+ xmlReader = SAXHelper.newXMLReader();
+ } catch (SAXException | ParserConfigurationException e) {
+ if (e.getMessage().contains("org.apache.xerces.parsers.SAXParser")) {
+ throw new DependencyException(e, "You need to add 'xerces:xercesImpl' to your project and version >= 2.11.0");
+ } else {
+ throw new POIException(e);
+ }
+ }
+ xmlReader.setContentHandler(handler);
+ try {
+ xmlReader.parse(new InputSource(xmlDocStream));
+ } catch (IOException e) {
+ throw new IORuntimeException(e);
+ } catch (SAXException e) {
+ throw new POIException(e);
+ }
+ }
+
/**
* 获取日期
- *
+ *
* @param value 单元格值
* @return 日期
* @since 4.1.0
@@ -136,14 +178,14 @@ public class ExcelSaxUtil {
/**
* 获取数字类型值
- *
- * @param value 值
+ *
+ * @param value 值
* @param numFmtString 格式
* @return 数字,可以是Double、Long
* @since 4.1.0
*/
private static Number getNumberValue(String value, String numFmtString) {
- if(StrUtil.isBlank(value)) {
+ if (StrUtil.isBlank(value)) {
return null;
}
double numValue = Double.parseDouble(value);
diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelSaxReadTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelSaxReadTest.java
index f0b734874..e0c2b5c7b 100644
--- a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelSaxReadTest.java
+++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelSaxReadTest.java
@@ -1,11 +1,5 @@
package cn.hutool.poi.excel.test;
-import java.util.List;
-
-import org.junit.Assert;
-import org.junit.Ignore;
-import org.junit.Test;
-
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Console;
@@ -13,6 +7,9 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.sax.Excel03SaxReader;
import cn.hutool.poi.excel.sax.handler.RowHandler;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
/**
* Excel sax方式读取