package com.github.takezoe.xlsbeans.processor; import java.lang.annotation.Annotation; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import com.github.takezoe.xlsbeans.NeedPostProcess; import com.github.takezoe.xlsbeans.Utils; import com.github.takezoe.xlsbeans.XLSBeansConfig; import com.github.takezoe.xlsbeans.XLSBeansException; import com.github.takezoe.xlsbeans.annotation.*; import com.github.takezoe.xlsbeans.xml.AnnotationReader; import com.github.takezoe.xlsbeans.xssfconverter.WCell; import com.github.takezoe.xlsbeans.xssfconverter.WSheet; /** * @author Mitsuyoshi Hasegawa * @see com.github.takezoe.xlsbeans.annotation.IterateTables */ public class IterateTablesProcessor implements FieldProcessor { public void doProcess(WSheet wSheet, Object obj, Method setter, Annotation ann, AnnotationReader reader, XLSBeansConfig config, List<NeedPostProcess> needPostProcess) throws Exception { IterateTables iterateTables = (IterateTables) ann; Class<?>[] setterArgClzArray = setter.getParameterTypes(); if (setterArgClzArray.length != 1) { // isn't setter attribute throw new XLSBeansException("Arguments of '" + setter.toString() + "' is invalid."); } // create multi-table objects. List<?> value = createTables(wSheet, iterateTables, reader, config, needPostProcess); if (List.class.isAssignableFrom(setterArgClzArray[0])) { setter.invoke(obj, new Object[]{value}); } else if (setterArgClzArray[0].isArray()) { Class<?> type = setterArgClzArray[0].getComponentType(); Object array = Array.newInstance(type, value.size()); for (int i = 0; i < value.size(); i++) { Array.set(array, i, value.get(i)); } setter.invoke(obj, new Object[]{array}); } else { throw new XLSBeansException("Arguments of '" + setter.toString() + "' is invalid."); } } public void doProcess(WSheet wSheet, Object obj, Field field, Annotation ann, AnnotationReader reader, XLSBeansConfig config, List<NeedPostProcess> needPostProcess) throws Exception { IterateTables iterateTables = (IterateTables) ann; Class<?> fieldType = field.getType(); // create multi-table objects. List<?> value = createTables(wSheet, iterateTables, reader, config, needPostProcess); if (List.class.isAssignableFrom(fieldType)) { field.set(obj, value); } else if (fieldType.isArray()) { Class<?> type = fieldType.getComponentType(); Object array = Array.newInstance(type, value.size()); for (int i = 0; i < value.size(); i++) { Array.set(array, i, value.get(i)); } field.set(obj, array); } else { throw new XLSBeansException("Arguments of '" + field.toString() + "' is invalid."); } } protected List<?> createTables(WSheet wSheet, IterateTables iterateTables, AnnotationReader reader, XLSBeansConfig config, List<NeedPostProcess> needPostProcess) throws Exception { List<Object> resultTableList = new ArrayList<Object>(); WCell after = null; WCell currentCell = null; String label = iterateTables.tableLabel(); currentCell = Utils.getCell(wSheet, label, after, false, !iterateTables.optional(), config); while (currentCell != null) { // 1 table object instance Object tableObj = iterateTables.tableClass().newInstance(); // process single label. processSingleLabelledCell(wSheet, tableObj, currentCell, reader, config, needPostProcess); // process horizontal table. processMultipleTableCell(wSheet, tableObj, currentCell, reader, iterateTables, config, needPostProcess); // TODO process vertical table resultTableList.add(tableObj); after = currentCell; currentCell = Utils.getCell(wSheet, label, after, false, false, config); } return resultTableList; } protected void processSingleLabelledCell(WSheet wSheet, Object tableObj, WCell headerCell, AnnotationReader reader, XLSBeansConfig config, List<NeedPostProcess> needPostProcess) throws Exception { List<Object> properties = Utils.getPropertiesWithAnnotation(tableObj, reader, LabelledCell.class); LabelledCellProcessor labelledCellProcessor = new LabelledCellProcessor(); for (Object property : properties) { LabelledCell ann = null; if (property instanceof Method) { ann = reader.getAnnotation(tableObj.getClass(), (Method) property, LabelledCell.class); } else if (property instanceof Field) { ann = reader.getAnnotation(tableObj.getClass(), (Field) property, LabelledCell.class); } WCell titleCell = null; try { titleCell = Utils.getCell(wSheet, ann.label(), headerCell, config); } catch (XLSBeansException e) { if (ann.optional()) { continue; } else { throw e; } } LabelledCell labelledCell = new LabelledCellForIterateTable(ann, titleCell.getRow(), titleCell.getColumn()); if (property instanceof Method) { labelledCellProcessor.doProcess(wSheet, tableObj, (Method) property, labelledCell, reader, config, needPostProcess); } else if (property instanceof Field) { labelledCellProcessor.doProcess(wSheet, tableObj, (Field) property, labelledCell, reader, config, needPostProcess); } } } protected void processMultipleTableCell(WSheet wSheet, Object tableObj, WCell headerCell, AnnotationReader reader, IterateTables iterateTables, XLSBeansConfig config, List<NeedPostProcess> needPostProcess) throws Exception { List<Object> properties = Utils.getPropertiesWithAnnotation(tableObj, reader, HorizontalRecords.class); int headerColumn = headerCell.getColumn(); int headerRow = headerCell.getRow(); if (iterateTables.bottom() > 0) { // if positive value set to bottom(), row index of table header move headerRow += iterateTables.bottom(); } HorizontalRecordsProcessor processor = new HorizontalRecordsProcessor(); for (Object property : properties) { HorizontalRecords ann = null; if (property instanceof Method) { ann = reader.getAnnotation(tableObj.getClass(), (Method) property, HorizontalRecords.class); } else if (property instanceof Field) { ann = reader.getAnnotation(tableObj.getClass(), (Field) property, HorizontalRecords.class); } if (iterateTables.tableLabel().equals(ann.tableLabel())) { // HorizontalRecords records = new HorizontalRecordsForIterateTable(ann, headerColumn, headerRow); // horizontal record-mapping if (property instanceof Method) { processor.doProcess(wSheet, tableObj, (Method) property, records, reader, config, needPostProcess); } else if (property instanceof Field) { processor.doProcess(wSheet, tableObj, (Field) property, records, reader, config, needPostProcess); } } } } }