Looly 5 years ago
parent
commit
545c20912a

+ 1 - 0
CHANGELOG.md

@@ -7,6 +7,7 @@
 
 ### 新特性
 ### Bug修复
+* 【core 】     修复CombinationAnnotationElement数组判断问题(issue#752@Github)
 
 -------------------------------------------------------------------------------------------------------------
 

+ 6 - 6
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的组合注解。<br>
  * 核心实现使用了递归获取指定元素上的注解以及注解的注解,以实现复合注解的获取。
@@ -65,13 +65,13 @@ public class CombinationAnnotationElement implements AnnotatedElement, Serializa
 	@Override
 	public Annotation[] getAnnotations() {
 		final Collection<Annotation> annotations = this.annotationMap.values();
-		return annotations.toArray(new Annotation[annotations.size()]);
+		return annotations.toArray(new Annotation[0]);
 	}
 
 	@Override
 	public Annotation[] getDeclaredAnnotations() {
 		final Collection<Annotation> 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<>();

+ 1 - 2
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> T[] toArray(Collection<T> collection, Class<T> componentType) {
-		final T[] array = newArray(componentType, collection.size());
-		return collection.toArray(array);
+		return collection.toArray(newArray(componentType, 0));
 	}
 
 	// ---------------------------------------------------------------------- remove

+ 18 - 1
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<String, Integer> 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<String> 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]);
+	}
 }

+ 1 - 9
hutool-poi/pom.xml

@@ -17,9 +17,8 @@
 
 	<properties>
 		<!-- versions -->
-		<poi.version>4.1.1</poi.version>
+		<poi.version>4.1.2</poi.version>
 		<xerces.version>2.12.0</xerces.version>
-		<easyexcel.version>2.1.6</easyexcel.version>
 	</properties>
 
 	<dependencies>
@@ -49,12 +48,5 @@
 			<scope>compile</scope>
 			<optional>true</optional>
 		</dependency>
-		<dependency>
-			<groupId>com.alibaba</groupId>
-			<artifactId>easyexcel</artifactId>
-			<version>${easyexcel.version}</version>
-			<scope>compile</scope>
-			<optional>true</optional>
-		</dependency>
 	</dependencies>
 </project>

+ 32 - 76
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<Excel07SaxReader> implements ContentHandler {
 
-	// saxParser
-	private static final String CLASS_SAXPARSER = "org.apache.xerces.parsers.SAXParser";
 	/**
 	 * Cell单元格元素
 	 */
@@ -46,7 +38,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> 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));
-	}
-
 	/**
 	 * 填充空白单元格,如果前一个单元格大于后一个,不需要填充<br>
 	 *
@@ -373,24 +321,32 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> 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
 }

+ 95 - 53
hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java

@@ -1,18 +1,28 @@
 package cn.hutool.poi.excel.sax;
 
+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 cn.hutool.core.date.DateTime;
-import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.util.StrUtil;
+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) {
@@ -124,8 +134,40 @@ public class ExcelSaxUtil {
 	}
 
 	/**
+	 * 从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);

+ 3 - 6
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方式读取