package nl.bstoi.poiparser.core.strategy; import nl.bstoi.poiparser.api.strategy.converter.Converter; import nl.bstoi.poiparser.core.exception.NonExistentConverterException; import nl.bstoi.poiparser.core.exception.PoiParserRuntimeException; import nl.bstoi.poiparser.core.strategy.factory.DefaultConverterFactory; import nl.bstoi.poiparser.core.strategy.util.TypedList; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.Set; /** * Hylke Stapersma * hylke.stapersma@gmail.com */ public abstract class AbstractWritePoiParser { private final static Log log = LogFactory.getLog(AbstractWritePoiParser.class); private final DefaultConverterFactory DEFAULTCONVERTERFACTORY = new DefaultConverterFactory(); private boolean createHeaderRow = false; private final Workbook workbook; private ColumnHeaderProperties columnHeaderProperties; protected AbstractWritePoiParser(Workbook workbook) { this.workbook = workbook; } protected void writeSheet(final String sheetName, final TypedList<?> values, final Set<CellDescriptor> sheetCellDescriptors) { Sheet sheet = workbook.createSheet(sheetName); if (isCreateHeaderRow()) { writeHeaderRow(sheet, sheetCellDescriptors); } writeDataRows(sheet, values, sheetCellDescriptors); } protected void writeHeaderRow(final Sheet sheet, final Set<CellDescriptor> sheetCellDescriptors) { if (sheet != null) { final Row headerRow = sheet.createRow(0); for (final CellDescriptor sheetCellDescriptor : sheetCellDescriptors) { writeHeaderCell(sheet.getSheetName(), headerRow, sheetCellDescriptor); } } } protected void writeHeaderCell(final String sheetName, final Row headerRow, final CellDescriptor sheetCellDescriptor) { try { if (!sheetCellDescriptor.isWriteIgnore()) { final Cell cell = headerRow.createCell(sheetCellDescriptor.getColumnNumber()); String headerColumnName = sheetCellDescriptor.getFieldName(); if (hasColumnHeaderProperties() && getColumnHeaderProperties().containsColumnHeader(sheetName, headerColumnName)) { headerColumnName = getColumnHeaderProperties().getColumnHeader(sheetName, headerColumnName); } final Converter converter = DEFAULTCONVERTERFACTORY.getConverter(String.class); converter.writeCell(cell, headerColumnName); } } catch (final InstantiationException e) { log.trace(String.format("Error writing column header on row %s and column %s with propertyname %s", 0, sheetCellDescriptor.getColumnNumber(), sheetCellDescriptor.getFieldName()), e); } catch (final IllegalAccessException e) { log.trace(String.format("Error writing column header on row %s and column %s with propertyname %s", 0, sheetCellDescriptor.getColumnNumber(), sheetCellDescriptor.getFieldName()), e); } catch (final NonExistentConverterException e) { log.trace("Converter cannot be found", e); } } protected void writeDataRows(final Sheet sheet, final TypedList<?> values, final Set<CellDescriptor> sheetCellDescriptors) { if (null != sheet) { int index = isCreateHeaderRow() ? 1 : 0; for (final Object value : values) { writeDataRow(sheet, index, value, sheetCellDescriptors); index++; } } } protected void writeDataRow(final Sheet sheet, final int index, final Object value, final Set<CellDescriptor> sheetCellDescriptors) { final Row row = sheet.createRow(index); for (final CellDescriptor cellDescriptor : sheetCellDescriptors) { final Object cellValue = readCellValueFromObjectProperty(value, cellDescriptor.getFieldName()); writeDataCell(row, cellValue, cellDescriptor); } } protected void writeDataCell(final Row row, final Object cellValue, final CellDescriptor cellDescriptor) { final Cell cell = row.createCell(cellDescriptor.getColumnNumber()); if (!cellDescriptor.isWriteIgnore()) { try { final Converter converter = DEFAULTCONVERTERFACTORY.getConverter(cellDescriptor.getType()); converter.writeCell(cell, cellValue); } catch (final InstantiationException e) { log.trace(String.format("Error writing cell on row %s and column %s with propertyname %s", row.getRowNum(), cellDescriptor.getColumnNumber(), cellDescriptor.getFieldName()), e); } catch (final IllegalAccessException e) { log.trace(String.format("Error writing cell on row %s and column %s with propertyname %s", row.getRowNum(), cellDescriptor.getColumnNumber(), cellDescriptor.getFieldName()), e); } catch (final NonExistentConverterException e) { log.trace("Converter cannot be found", e); } } } protected Object readCellValueFromObjectProperty(final Object object, final String propertyName) { if (null == object) throw new IllegalArgumentException("Object cannot be null"); if (StringUtils.isEmpty(propertyName)) throw new IllegalArgumentException("Property name cannot be null"); try { return PropertyUtils.getNestedProperty(object, propertyName); } catch (final IllegalAccessException e) { throw new PoiParserRuntimeException(String.format("Property %s cannot be read", propertyName), e); } catch (final InvocationTargetException e) { throw new PoiParserRuntimeException(String.format("Property %s cannot be read", propertyName), e); } catch (final NoSuchMethodException e) { return readCellValueFromObjectField(object, propertyName); } } protected Object readCellValueFromObjectField(final Object object, final String fieldName) { final String[] splittedFieldNames = getSplittedPropertyName(fieldName); Object returnObject = null; for (final String splittedFieldName : splittedFieldNames) { returnObject = getFieldFromObject(object, splittedFieldName); if (returnObject == null) { return null; } } return returnObject; } private Object getFieldFromObject(final Object object, final String fieldName) { try { final Field field = object.getClass().getField(fieldName); field.setAccessible(true); return field.get(object); } catch (final NoSuchFieldException e) { // Do nothing } catch (final IllegalAccessException e) { // Do nothing } return null; } public boolean isCreateHeaderRow() { return createHeaderRow; } public void setCreateHeaderRow(boolean createHeaderRow) { this.createHeaderRow = createHeaderRow; } protected Workbook getWorkbook() { return workbook; } protected String[] getSplittedPropertyName(final String propertyName) { if (StringUtils.isEmpty(propertyName)) throw new IllegalArgumentException("Property name cannot be empty"); return propertyName.split("\\."); } private ColumnHeaderProperties getColumnHeaderProperties() { return this.columnHeaderProperties; } private boolean hasColumnHeaderProperties() { return (null != this.columnHeaderProperties); } public void setColumnHeaderProperties(ColumnHeaderProperties columnHeaderProperties) { this.columnHeaderProperties = columnHeaderProperties; } }