IterateTablesProcessor.java
package com.gh.mygreen.xlsmapper.fieldprocessor.impl;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import com.gh.mygreen.xlsmapper.AnnotationInvalidException;
import com.gh.mygreen.xlsmapper.Configuration;
import com.gh.mygreen.xlsmapper.LoadingWorkObject;
import com.gh.mygreen.xlsmapper.NeedProcess;
import com.gh.mygreen.xlsmapper.SavingWorkObject;
import com.gh.mygreen.xlsmapper.XlsMapperException;
import com.gh.mygreen.xlsmapper.annotation.XlsHorizontalRecords;
import com.gh.mygreen.xlsmapper.annotation.XlsHorizontalRecordsForIterateTables;
import com.gh.mygreen.xlsmapper.annotation.XlsIterateTables;
import com.gh.mygreen.xlsmapper.annotation.XlsLabelledArrayCells;
import com.gh.mygreen.xlsmapper.annotation.XlsLabelledArrayCellsForIterateTable;
import com.gh.mygreen.xlsmapper.annotation.XlsLabelledCell;
import com.gh.mygreen.xlsmapper.annotation.XlsLabelledCellForIterateTable;
import com.gh.mygreen.xlsmapper.annotation.XlsLabelledComment;
import com.gh.mygreen.xlsmapper.annotation.XlsLabelledCommentForIterateTable;
import com.gh.mygreen.xlsmapper.annotation.XlsVerticalRecords;
import com.gh.mygreen.xlsmapper.annotation.XlsVerticalRecordsForIterateTables;
import com.gh.mygreen.xlsmapper.fieldaccessor.FieldAccessor;
import com.gh.mygreen.xlsmapper.fieldaccessor.FieldAccessorProxy;
import com.gh.mygreen.xlsmapper.fieldaccessor.FieldAccessorProxyComparator;
import com.gh.mygreen.xlsmapper.fieldprocessor.AbstractFieldProcessor;
import com.gh.mygreen.xlsmapper.fieldprocessor.CellNotFoundException;
import com.gh.mygreen.xlsmapper.fieldprocessor.ProcessCase;
import com.gh.mygreen.xlsmapper.fieldprocessor.RecordMethodCache;
import com.gh.mygreen.xlsmapper.fieldprocessor.RecordMethodFacatory;
import com.gh.mygreen.xlsmapper.localization.MessageBuilder;
import com.gh.mygreen.xlsmapper.util.CellFinder;
import com.gh.mygreen.xlsmapper.util.FieldAccessorUtils;
import com.gh.mygreen.xlsmapper.util.POIUtils;
import com.gh.mygreen.xlsmapper.util.Utils;
import com.gh.mygreen.xlsmapper.xml.AnnotationReader;
/**
* アノテーション{@link XlsIterateTables}を処理する。
*
* @version 2.1
* @author Naoki Takezoe
* @author T.TSUCHIE
*
*/
public class IterateTablesProcessor extends AbstractFieldProcessor<XlsIterateTables> {
@Override
public void loadProcess(final Sheet sheet, final Object beansObj, final XlsIterateTables anno,
final FieldAccessor accessor, final Configuration config, final LoadingWorkObject work) throws XlsMapperException {
if(!accessor.isWritable()) {
// セルの値を書き込むメソッド/フィールドがない場合はスキップ
return;
}
if(!Utils.isLoadCase(anno.cases())) {
return;
}
final Class<?> clazz = accessor.getType();
if(Collection.class.isAssignableFrom(clazz)) {
Class<?> tableClass = anno.tableClass();
if(tableClass == Object.class) {
tableClass = accessor.getComponentType();
}
List<?> value = loadTables(sheet, beansObj, anno, accessor, tableClass, config, work);
if(value != null) {
@SuppressWarnings({"unchecked", "rawtypes"})
Collection<?> collection = Utils.convertListToCollection(value, (Class<Collection>)clazz, config.getBeanFactory());
accessor.setValue(beansObj, collection);
}
} else if(clazz.isArray()) {
Class<?> tableClass = anno.tableClass();
if(tableClass == Object.class) {
tableClass = accessor.getComponentType();
}
final List<?> value = loadTables(sheet, beansObj, anno, accessor, tableClass, config, work);
if(value != null) {
final Object array = Array.newInstance(tableClass, value.size());
for(int i=0; i < value.size(); i++) {
Array.set(array, i, value.get(i));
}
accessor.setValue(beansObj, array);
}
} else {
throw new AnnotationInvalidException(anno, MessageBuilder.create("anno.notSupportType")
.var("property", accessor.getNameWithClass())
.varWithAnno("anno", XlsIterateTables.class)
.varWithClass("actualType", clazz)
.var("expectedType", "Collection(List/Set) or Array")
.format());
}
}
private List<?> loadTables(final Sheet sheet, final Object beansObj, final XlsIterateTables iterateTablesAnno, final FieldAccessor accessor,
final Class<?> tableClass, final Configuration config, final LoadingWorkObject work) throws XlsMapperException {
// アノテーションの整合性のチェック
checkRecordAnnotation(tableClass, work.getAnnoReader());
final List<Object> resultTableList = new ArrayList<>();
Cell after = null;
Cell currentCell = null;
// 各種レコードのコールバック用メソッドを抽出する
final RecordMethodCache methodCache = new RecordMethodFacatory(work.getAnnoReader(), config)
.create(tableClass, ProcessCase.Load);
final String label = iterateTablesAnno.tableLabel();
currentCell = CellFinder.query(sheet, label, config).find(iterateTablesAnno.optional());
while(currentCell != null) {
// 1 table object instance
final Object tableObj = config.createBean(tableClass);
// ラベルの設定
accessor.setArrayLabel(beansObj, POIUtils.getCellContents(currentCell, config.getCellFormatter()), resultTableList.size());
// パスの位置の変更
work.getErrors().pushNestedPath(accessor.getName(), resultTableList.size());
// execute PreProcess listener
methodCache.getListenerClasses().forEach(listenerClass -> {
listenerClass.getPreLoadMethods().forEach(method -> {
Utils.invokeNeedProcessMethod(listenerClass.getObject(), method, tableObj, sheet, config, work.getErrors(), ProcessCase.Load);
});
});
// execute PreProcess method
methodCache.getPreLoadMethods().forEach(method -> {
Utils.invokeNeedProcessMethod(tableObj, method, tableObj, sheet, config, work.getErrors(), ProcessCase.Load);
});
// process sinslbe labelled comment
loadSingleLabelledComment(sheet, tableObj, currentCell, config, work);
// process single label.
loadSingleLabelledCell(sheet, tableObj, currentCell, config, work);
// process array labels.
loadSingleLabelledArrayCell(sheet, tableObj, currentCell, config, work);
// process horizontal table.
loadMultipleHorizontalTableCell(sheet, tableObj, currentCell, iterateTablesAnno, config, work);
// process vertial table
loadMultipleVerticalTableCell(sheet, tableObj, currentCell, iterateTablesAnno, config, work);
resultTableList.add(tableObj);
after = currentCell;
currentCell = CellFinder.query(sheet, label, config)
.startPosition(after)
.excludeStartPosition(true)
.findOptional()
.orElse(null);
// set PostProcess listener
methodCache.getListenerClasses().forEach(listenerClass -> {
listenerClass.getPostLoadMethods().forEach(method -> {
work.addNeedPostProcess(new NeedProcess(tableObj, listenerClass.getObject(), method));
});
});
// set PostProcess method
methodCache.getPostLoadMethods().forEach(method -> {
work.addNeedPostProcess(new NeedProcess(tableObj, tableObj, method));
});
// パスの位置の変更
work.getErrors().popNestedPath();
}
return resultTableList;
}
/**
* レコード用のアノテーションの整合性のチェックを行う。
* <p>{@link XlsHorizontalRecords}と{@link XlsVerticalRecords}は、どちらか一方のみ指定可能。</p>
* @param tableClass テーブル用のクラス情報
* @param annoReader アノテーションの提供クラス
*/
private void checkRecordAnnotation(final Class<?> tableClass, final AnnotationReader annoReader) {
final int horizontalSize = FieldAccessorUtils.getPropertiesWithAnnotation(
tableClass, annoReader, XlsHorizontalRecords.class)
.size();
final int verticalSize = FieldAccessorUtils.getPropertiesWithAnnotation(
tableClass, annoReader, XlsVerticalRecords.class)
.size();
if(horizontalSize > 0 && verticalSize > 0) {
throw new AnnotationInvalidException(MessageBuilder.create("anno.XlsIterateTables.horizontalAndVertical")
.varWithClass("tableClass", tableClass)
.format());
}
}
/**
* XlsLabelledCommentによる処理する。
* @param sheet
* @param tableObj
* @param headerCell
* @param config
* @throws XlsMapperException
*/
private void loadSingleLabelledComment(final Sheet sheet, final Object tableObj,
final Cell headerCell, final Configuration config, final LoadingWorkObject work) throws XlsMapperException {
final LabelledCommentProcessor labelledCommentProcessor =
(LabelledCommentProcessor) config.getFieldProcessorRegistry().getProcessor(XlsLabelledComment.class);
final List<FieldAccessor> properties = FieldAccessorUtils.getPropertiesWithAnnotation(
tableObj.getClass(), work.getAnnoReader(), XlsLabelledComment.class)
.stream()
.filter(p -> p.isWritable())
.collect(Collectors.toList());
for(FieldAccessor property : properties) {
final XlsLabelledComment anno = property.getAnnotationNullable(XlsLabelledComment.class);
Cell titleCell = null;
try {
titleCell = CellFinder.query(sheet, anno.label(), config)
.startPosition(headerCell)
.excludeStartPosition(true)
.findWhenNotFoundException();
} catch (CellNotFoundException e) {
if (anno.optional()) {
continue;
} else {
throw e;
}
}
final XlsLabelledComment labelledCell = new XlsLabelledCommentForIterateTable(
anno, titleCell.getRowIndex(), titleCell.getColumnIndex());
labelledCommentProcessor.loadProcess(sheet, tableObj, labelledCell, property, config, work);
}
}
/**
* XlsLabelledCellによる処理する。
* @param sheet
* @param tableObj
* @param headerCell
* @param config
* @throws XlsMapperException
*/
private void loadSingleLabelledCell(final Sheet sheet, final Object tableObj,
final Cell headerCell, final Configuration config, final LoadingWorkObject work) throws XlsMapperException {
final LabelledCellProcessor labelledCellProcessor =
(LabelledCellProcessor) config.getFieldProcessorRegistry().getProcessor(XlsLabelledCell.class);
final List<FieldAccessor> properties = FieldAccessorUtils.getPropertiesWithAnnotation(
tableObj.getClass(), work.getAnnoReader(), XlsLabelledCell.class)
.stream()
.filter(p -> p.isWritable())
.collect(Collectors.toList());
for(FieldAccessor property : properties) {
final XlsLabelledCell anno = property.getAnnotationNullable(XlsLabelledCell.class);
Cell titleCell = null;
try {
titleCell = CellFinder.query(sheet, anno.label(), config)
.startPosition(headerCell)
.excludeStartPosition(true)
.findWhenNotFoundException();
} catch (CellNotFoundException e) {
if (anno.optional()) {
continue;
} else {
throw e;
}
}
final XlsLabelledCell labelledCell = new XlsLabelledCellForIterateTable(
anno, titleCell.getRowIndex(), titleCell.getColumnIndex());
labelledCellProcessor.loadProcess(sheet, tableObj, labelledCell, property, config, work);
}
}
/**
* XlsLabelledArrayCellを処理する。
* @param sheet
* @param tableObj
* @param headerCell
* @param config
* @throws XlsMapperException
*/
private void loadSingleLabelledArrayCell(final Sheet sheet, final Object tableObj,
final Cell headerCell, final Configuration config, final LoadingWorkObject work) throws XlsMapperException {
final LabelledArrayCellsProcessor labelledArrayCellProcessor =
(LabelledArrayCellsProcessor) config.getFieldProcessorRegistry().getProcessor(XlsLabelledArrayCells.class);
final List<FieldAccessor> properties = FieldAccessorUtils.getPropertiesWithAnnotation(
tableObj.getClass(), work.getAnnoReader(), XlsLabelledArrayCells.class)
.stream()
.filter(p -> p.isWritable())
.collect(Collectors.toList());
for(FieldAccessor property : properties) {
final XlsLabelledArrayCells anno = property.getAnnotationNullable(XlsLabelledArrayCells.class);
Cell titleCell = null;
try {
titleCell = CellFinder.query(sheet, anno.label(), config)
.startPosition(headerCell)
.excludeStartPosition(true)
.findWhenNotFoundException();
} catch (CellNotFoundException e) {
if (anno.optional()) {
continue;
} else {
throw e;
}
}
final XlsLabelledArrayCells wrapAnno = new XlsLabelledArrayCellsForIterateTable(
anno, titleCell.getRowIndex(), titleCell.getColumnIndex());
labelledArrayCellProcessor.loadProcess(sheet, tableObj, wrapAnno, property, config, work);
}
}
private void loadMultipleHorizontalTableCell(final Sheet sheet, final Object tableObj,
final Cell headerCell, final XlsIterateTables iterateTablesAnno,
final Configuration config, final LoadingWorkObject work) throws XlsMapperException {
int headerColumn = headerCell.getColumnIndex();
int headerRow = headerCell.getRowIndex();
if (iterateTablesAnno.bottom() > 0) {
// if positive value set to bottom(), row index of table header move
headerRow += iterateTablesAnno.bottom();
}
final HorizontalRecordsProcessor processor =
(HorizontalRecordsProcessor) config.getFieldProcessorRegistry().getProcessor(XlsHorizontalRecords.class);
final List<FieldAccessor> properties = FieldAccessorUtils.getPropertiesWithAnnotation(
tableObj.getClass(), work.getAnnoReader(), XlsHorizontalRecords.class)
.stream()
.filter(p -> p.isWritable())
.collect(Collectors.toList());
final List<FieldAccessorProxy> accessorProxies = new ArrayList<>();
for(FieldAccessor property : properties) {
final XlsHorizontalRecords anno = property.getAnnotationNullable(XlsHorizontalRecords.class);
if(iterateTablesAnno.tableLabel().equals(anno.tableLabel())) {
final XlsHorizontalRecords recordsAnno = new XlsHorizontalRecordsForIterateTables(anno, headerColumn, headerRow);
accessorProxies.add(new FieldAccessorProxy(recordsAnno, processor, property));
}
}
// 順番を並び替えて読み込み処理を実行する
Collections.sort(accessorProxies, new FieldAccessorProxyComparator());
for(FieldAccessorProxy adaptorProxy : accessorProxies) {
adaptorProxy.loadProcess(sheet, tableObj, config, work);
}
}
private void loadMultipleVerticalTableCell(final Sheet sheet, final Object tableObj,
final Cell headerCell, final XlsIterateTables iterateTablesAnno,
final Configuration config, final LoadingWorkObject work) throws XlsMapperException {
int headerColumn = headerCell.getColumnIndex();
int headerRow = headerCell.getRowIndex();
if (iterateTablesAnno.bottom() > 0) {
// if positive value set to bottom(), row index of table header move
headerRow += iterateTablesAnno.bottom();
}
final VerticalRecordsProcessor processor =
(VerticalRecordsProcessor) config.getFieldProcessorRegistry().getProcessor(XlsVerticalRecords.class);
final List<FieldAccessor> properties = FieldAccessorUtils.getPropertiesWithAnnotation(
tableObj.getClass(), work.getAnnoReader(), XlsVerticalRecords.class)
.stream()
.filter(p -> p.isWritable())
.collect(Collectors.toList());
final List<FieldAccessorProxy> accessorProxies = new ArrayList<>();
for(FieldAccessor property : properties) {
final XlsVerticalRecords anno = property.getAnnotationNullable(XlsVerticalRecords.class);
if(iterateTablesAnno.tableLabel().equals(anno.tableLabel())) {
final XlsVerticalRecords recordsAnno = new XlsVerticalRecordsForIterateTables(anno, headerColumn, headerRow);
accessorProxies.add(new FieldAccessorProxy(recordsAnno, processor, property));
}
}
// 順番を並び替えて読み込み処理を実行する
Collections.sort(accessorProxies, new FieldAccessorProxyComparator());
for(FieldAccessorProxy adaptorProxy : accessorProxies) {
adaptorProxy.loadProcess(sheet, tableObj, config, work);
}
}
@SuppressWarnings("unchecked")
@Override
public void saveProcess(final Sheet sheet, final Object beansObj, final XlsIterateTables anno, final FieldAccessor accessor,
final Configuration config, final SavingWorkObject work) throws XlsMapperException {
if(!accessor.isReadable()) {
// セルの値を参照するメソッド/フィールドがない場合はスキップ
return;
}
if(!Utils.isSaveCase(anno.cases())) {
return;
}
final Object result = accessor.getValue(beansObj);
final Class<?> clazz = accessor.getType();
if(Collection.class.isAssignableFrom(clazz)) {
Class<?> tableClass = anno.tableClass();
if(tableClass == Object.class) {
tableClass = accessor.getComponentType();
}
final Collection<Object> value = (result == null ? new ArrayList<Object>() : (Collection<Object>) result);
final List<Object> list = Utils.convertCollectionToList(value);
saveTables(sheet, anno, accessor, tableClass, list, config, work);
} else if(clazz.isArray()) {
Class<?> tableClass = anno.tableClass();
if(tableClass == Object.class) {
tableClass = accessor.getComponentType();
}
final List<Object> list = Utils.asList(result, tableClass);
saveTables(sheet, anno, accessor, tableClass, list, config, work);
} else {
throw new AnnotationInvalidException(anno, MessageBuilder.create("anno.notSupportType")
.var("property", accessor.getNameWithClass())
.varWithAnno("anno", XlsIterateTables.class)
.varWithClass("actualType", clazz)
.var("expectedType", "Collection(List/Set) or Array")
.format());
}
}
private void saveTables(final Sheet sheet, final XlsIterateTables iterateTablesAnno, final FieldAccessor accessor,
final Class<?> tableClass, final List<Object> resultTableList,
final Configuration config, final SavingWorkObject work) throws XlsMapperException {
// アノテーションの整合性のチェック
checkRecordAnnotation(tableClass, work.getAnnoReader());
Cell after = null;
Cell currentCell = null;
String label = iterateTablesAnno.tableLabel();
// 各種レコードのコールバック用メソッドを抽出する
final RecordMethodCache methodCache = new RecordMethodFacatory(work.getAnnoReader(), config)
.create(tableClass, ProcessCase.Save);
for(int i=0; i < resultTableList.size(); i++) {
final Object tableObj = resultTableList.get(i);
// パスの位置の変更
work.getErrors().pushNestedPath(accessor.getName(), i);
// execute PreProcess listener
methodCache.getListenerClasses().forEach(listenerClass -> {
listenerClass.getPreSaveMethods().forEach(method -> {
Utils.invokeNeedProcessMethod(listenerClass.getObject(), method, tableObj, sheet, config, work.getErrors(), ProcessCase.Save);
});
});
// execute PreProcess method
methodCache.getPreSaveMethods().forEach(method -> {
Utils.invokeNeedProcessMethod(tableObj, method, tableObj, sheet, config, work.getErrors(), ProcessCase.Save);
});
if(after == null) {
currentCell = CellFinder.query(sheet, label, config).find(iterateTablesAnno.optional());
} else {
currentCell = CellFinder.query(sheet, label, config)
.startPosition(after)
.excludeStartPosition(true)
.find(iterateTablesAnno.optional());
}
if(currentCell == null) {
//TODO: 見出しが足りない場合の追加処理を記述する
// パスの位置の変更
work.getErrors().popNestedPath();
break;
}
// process single label comment
saveSingleLabelledComment(sheet, tableObj, currentCell, config, work);
// process single label.
saveSingleLabelledCell(sheet, tableObj, currentCell, config, work);
// process array labels.
saveSingleLabelledArrayCell(sheet, tableObj, currentCell, config, work);
// process horizontal table.
saveMultipleHorizontalTableCell(sheet, tableObj, currentCell, iterateTablesAnno, config, work);
// process vertical table
saveMultipleVerticalTableCell(sheet, tableObj, currentCell, iterateTablesAnno, config, work);
after = currentCell;
// set PostProcess listener
methodCache.getListenerClasses().forEach(listenerClass -> {
listenerClass.getPostSaveMethods().forEach(method -> {
work.addNeedPostProcess(new NeedProcess(tableObj, listenerClass.getObject(), method));
});
});
// set PostProcess method
methodCache.getPostSaveMethods().forEach(method -> {
work.addNeedPostProcess(new NeedProcess(tableObj, tableObj, method));
});
// パスの位置の変更
work.getErrors().popNestedPath();
}
}
private void saveSingleLabelledComment(final Sheet sheet, final Object tableObj, final Cell headerCell,
final Configuration config, final SavingWorkObject work) throws XlsMapperException {
final LabelledCommentProcessor labelledCommentProcessor =
(LabelledCommentProcessor) config.getFieldProcessorRegistry().getProcessor(XlsLabelledComment.class);
final List<FieldAccessor> properties = FieldAccessorUtils.getPropertiesWithAnnotation(
tableObj.getClass(), work.getAnnoReader(), XlsLabelledComment.class)
.stream()
.filter(p -> p.isReadable())
.collect(Collectors.toList());
for(FieldAccessor property : properties) {
final XlsLabelledComment anno = property.getAnnotationNullable(XlsLabelledComment.class);
Cell titleCell = null;
try {
titleCell = CellFinder.query(sheet, anno.label(), config)
.startPosition(headerCell)
.excludeStartPosition(true)
.findWhenNotFoundException();
} catch (CellNotFoundException e) {
if (anno.optional()) {
continue;
} else {
throw e;
}
}
final XlsLabelledComment labelledCell = new XlsLabelledCommentForIterateTable(
anno, titleCell.getRowIndex(), titleCell.getColumnIndex());
labelledCommentProcessor.saveProcess(sheet, tableObj, labelledCell, property, config, work);
}
}
private void saveSingleLabelledCell(final Sheet sheet, final Object tableObj, final Cell headerCell,
final Configuration config, final SavingWorkObject work) throws XlsMapperException {
final LabelledCellProcessor labelledCellProcessor =
(LabelledCellProcessor) config.getFieldProcessorRegistry().getProcessor(XlsLabelledCell.class);
final List<FieldAccessor> properties = FieldAccessorUtils.getPropertiesWithAnnotation(
tableObj.getClass(), work.getAnnoReader(), XlsLabelledCell.class)
.stream()
.filter(p -> p.isReadable())
.collect(Collectors.toList());
for(FieldAccessor property : properties) {
final XlsLabelledCell anno = property.getAnnotationNullable(XlsLabelledCell.class);
Cell titleCell = null;
try {
titleCell = CellFinder.query(sheet, anno.label(), config)
.startPosition(headerCell)
.excludeStartPosition(true)
.findWhenNotFoundException();
} catch (CellNotFoundException e) {
if (anno.optional()) {
continue;
} else {
throw e;
}
}
final XlsLabelledCell labelledCell = new XlsLabelledCellForIterateTable(
anno, titleCell.getRowIndex(), titleCell.getColumnIndex());
labelledCellProcessor.saveProcess(sheet, tableObj, labelledCell, property, config, work);
}
}
private void saveSingleLabelledArrayCell(final Sheet sheet, final Object tableObj, final Cell headerCell,
final Configuration config, final SavingWorkObject work) throws XlsMapperException {
final LabelledArrayCellsProcessor labelledArrayCellProcessor =
(LabelledArrayCellsProcessor) config.getFieldProcessorRegistry().getProcessor(XlsLabelledArrayCells.class);
final List<FieldAccessor> properties = FieldAccessorUtils.getPropertiesWithAnnotation(
tableObj.getClass(), work.getAnnoReader(), XlsLabelledArrayCells.class)
.stream()
.filter(p -> p.isReadable())
.collect(Collectors.toList());
for(FieldAccessor property : properties) {
final XlsLabelledArrayCells anno = property.getAnnotationNullable(XlsLabelledArrayCells.class);
Cell titleCell = null;
try {
titleCell = CellFinder.query(sheet, anno.label(), config)
.startPosition(headerCell)
.excludeStartPosition(true)
.findWhenNotFoundException();
} catch (CellNotFoundException e) {
if (anno.optional()) {
continue;
} else {
throw e;
}
}
final XlsLabelledArrayCells labelledCell = new XlsLabelledArrayCellsForIterateTable(
anno, titleCell.getRowIndex(), titleCell.getColumnIndex());
labelledArrayCellProcessor.saveProcess(sheet, tableObj, labelledCell, property, config, work);
}
}
private void saveMultipleHorizontalTableCell(final Sheet sheet, final Object tableObj, final Cell headerCell,
final XlsIterateTables iterateTables, final Configuration config, final SavingWorkObject work) throws XlsMapperException {
final int headerColumn = headerCell.getColumnIndex();
int headerRow = headerCell.getRowIndex();
if (iterateTables.bottom() > 0) {
// if positive value set to bottom(), row index of table header move
headerRow += iterateTables.bottom();
}
final HorizontalRecordsProcessor processor =
(HorizontalRecordsProcessor) config.getFieldProcessorRegistry().getProcessor(XlsHorizontalRecords.class);
final List<FieldAccessor> properties = FieldAccessorUtils.getPropertiesWithAnnotation(
tableObj.getClass(), work.getAnnoReader(), XlsHorizontalRecords.class)
.stream()
.filter(p -> p.isReadable())
.collect(Collectors.toList());
final List<FieldAccessorProxy> accessorProxies = new ArrayList<>();
for(FieldAccessor property : properties) {
final XlsHorizontalRecords anno = property.getAnnotationNullable(XlsHorizontalRecords.class);
// 処理対象と同じテーブルラベルのとき、マッピングを実行する。
if(iterateTables.tableLabel().equals(anno.tableLabel())) {
final XlsHorizontalRecords recordsAnno = new XlsHorizontalRecordsForIterateTables(anno, headerColumn, headerRow);
accessorProxies.add(new FieldAccessorProxy(recordsAnno, processor, property));
}
}
// 順番を並び替えて保存処理を実行する
Collections.sort(accessorProxies, new FieldAccessorProxyComparator());
for(FieldAccessorProxy adaptorProxy : accessorProxies) {
adaptorProxy.saveProcess(sheet, tableObj, config, work);
}
}
private void saveMultipleVerticalTableCell(final Sheet sheet, final Object tableObj, final Cell headerCell,
final XlsIterateTables iterateTablesAnno, final Configuration config, final SavingWorkObject work) throws XlsMapperException {
int headerColumn = headerCell.getColumnIndex();
int headerRow = headerCell.getRowIndex();
if (iterateTablesAnno.bottom() > 0) {
// if positive value set to bottom(), row index of table header move
headerRow += iterateTablesAnno.bottom();
}
final VerticalRecordsProcessor processor =
(VerticalRecordsProcessor) config.getFieldProcessorRegistry().getProcessor(XlsVerticalRecords.class);
final List<FieldAccessor> properties = FieldAccessorUtils.getPropertiesWithAnnotation(
tableObj.getClass(), work.getAnnoReader(), XlsVerticalRecords.class)
.stream()
.filter(p -> p.isReadable())
.collect(Collectors.toList());
final List<FieldAccessorProxy> accessorProxies = new ArrayList<>();
for(FieldAccessor property : properties) {
final XlsVerticalRecords anno = property.getAnnotationNullable(XlsVerticalRecords.class);
// 処理対象と同じテーブルラベルのとき、マッピングを実行する。
if(iterateTablesAnno.tableLabel().equals(anno.tableLabel())) {
final XlsVerticalRecords recordsAnno = new XlsVerticalRecordsForIterateTables(anno, headerColumn, headerRow);
accessorProxies.add(new FieldAccessorProxy(recordsAnno, processor, property));
}
}
// 順番を並び替えて保存処理を実行する
Collections.sort(accessorProxies, new FieldAccessorProxyComparator());
for(FieldAccessorProxy adaptorProxy : accessorProxies) {
adaptorProxy.saveProcess(sheet, tableObj, config, work);
}
}
}