package com.ejintai.epcis_agro.transmission.fileDeal.impl;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.ejintai.epcis_agro.anno.ExcelAnno;
import com.ejintai.epcis_agro.biz.validation.Validation;
import com.ejintai.epcis_agro.biz.validation.ValidationFactory;
import com.ejintai.epcis_agro.constant.AlertCause;
/**
* 创建SAX解析处理器必须继承自
* org.xml.sax.helpers.DefaultHandler
* 实现响应的方法。
*/
public class ExcelSheetSAXHandler extends DefaultHandler {
@Autowired
protected @Value("${excelImport.maxRow}")
int maxRow;
private SharedStringsTable sst;
private String lastContents;
private boolean nextIsString;
public List<Object> result = new ArrayList<Object>();
private Class<?> excelVOs;
private String edrReason;
private Map<Integer, String> autoRead;
private Map<String, Validation> validationMap;
private int sheetIndex;
private Object vo;
private int r=1;//行
private int c=0;//例
int rowNum = 1;
int td;
private boolean nextIsRows; //是否新的一行
public ExcelSheetSAXHandler(SharedStringsTable sst,Class<?> excelVOs,String edrReason,int sheetIndex) {
this.sst = sst;
this.excelVOs=excelVOs;
this.edrReason=edrReason;
this.sheetIndex=sheetIndex;
autoRead = getMappingFromClass(excelVOs);
validationMap = getValidationMappingFromClass(excelVOs);
try{
vo = excelVOs.newInstance();
}catch (Exception e) {
// TODO: handle exception
}
}
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException{
// c => cell
if(name.equals("c")) {
// System.out.print("单元格"+attributes.getValue("r") + " - ");
if(c<26){//26个字母
td=Integer.parseInt(attributes.getValue("r").substring(1)); //这里还是有缺陷。当例数超过Z,就不能这样处理了。
}else if(c<702){//到ZZ那里
td=Integer.parseInt(attributes.getValue("r").substring(2));
}else{
//太多例,不支持
throw new SAXException("太多例,不支持" );
}
if(td==r){//表示它们是一行的数据
c++;//计算例
r=td;
nextIsRows=false;
}else{
rowNum++;
c=0;
nextIsRows=true;
r=td;
}
String cellType = attributes.getValue("t");
if(cellType != null && cellType.equals("s")) {
nextIsString = true;
} else {
nextIsString = false;
}
}
// Clear contents cache
lastContents = "";
}
public void endElement(String uri, String localName, String name)
throws SAXException {
// Process the last contents as required.
// Do now, as characters() may be called more than once
if(nextIsString) {
int idx = Integer.parseInt(lastContents);
lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
nextIsString = false;
}
// v => contents of a cell
// Output after we've seen the string contents
if(name.equals("v")) {
// System.out.println("数据"+lastContents);
if(r!=1){//行 第一行不处理
if(nextIsRows){//新的一行
if(r>2){
result.add(vo);
}
try{
vo = excelVOs.newInstance();
}catch (Exception e) {
// TODO: handle exception
}
setVo();
}else{
setVo();
}
}
}
}
/**
* 设置每行数据
*/
private void setVo() throws SAXException{
String propName = autoRead.get(c);
if (null != propName) {//例
try{
BeanUtils.setProperty(vo, propName, lastContents);
}catch (Exception e) {
// TODO: handle exception
}
}
}
public void characters(char[] ch, int start, int length)
throws SAXException {
lastContents += new String(ch, start, length);
}
/**
* 接收文档结束的通知
*/
public void endDocument(){
result.add(vo);
// System.out.println("接收文档结束");
}
public void startDocument(){
//System.out.println("接收文档开始");
}
private Map<Integer, String> getMappingFromClass(Class<?> annoClass) {
Map<Integer, String> mapping = new HashMap<Integer, String>();
// 枚举每一列和字段的对应关系
Field[] fields = annoClass.getDeclaredFields();
for (Field field : fields) {
boolean hasAnnotation = field.isAnnotationPresent(ExcelAnno.class);
// 有注解的才从Excel读取
if (hasAnnotation) {
ExcelAnno anno = field.getAnnotation(ExcelAnno.class);
int column = anno.column();
String fieldName = field.getName();
mapping.put(column, fieldName);
}
}
return mapping;
}
private Map<String, Validation> getValidationMappingFromClass(
Class<?> annoClass) {
Map<String, Validation> mapping = new HashMap<String, Validation>();
// 枚举每一列和字段的对应关系
Field[] fields = annoClass.getDeclaredFields();
for (Field field : fields) {
boolean hasAnnotation = field.isAnnotationPresent(ExcelAnno.class);
// 有注解的才从Excel读取
if (hasAnnotation) {
ExcelAnno anno = field.getAnnotation(ExcelAnno.class);
Class valiClass = anno.validationClass();
Validation validation = ValidationFactory
.getValidation(valiClass);
String fieldName = field.getName();
mapping.put(fieldName, validation);
}
}
return mapping;
}
public List<Object> getResult() {
return result;
}
public void setResult(List<Object> result) {
this.result = result;
}
public Class<?> getExcelVOs() {
return excelVOs;
}
public void setExcelVOs(Class<?> excelVOs) {
this.excelVOs = excelVOs;
}
public String getEdrReason() {
return edrReason;
}
public void setEdrReason(String edrReason) {
this.edrReason = edrReason;
}
}