001/*
002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Martin Pernollet
018 */
019
020package org.nuxeo.ecm.platform.groups.audit.service.acl.excel;
021
022import org.apache.poi.ss.usermodel.Cell;
023
024/**
025 * Override the default {@link ExcelBuilder} to write over several excel sheet once a cell column exceeds the maximum
026 * number of column for excel.
027 *
028 * @author Martin Pernollet <mpernollet@nuxeo.com>
029 */
030public class ExcelBuilderMultiSheet extends ExcelBuilder {
031    protected boolean multiSheetMode = false;
032
033    public ExcelBuilderMultiSheet() {
034        super();
035    }
036
037    public ExcelBuilderMultiSheet(Type type, String firstSheet) {
038        super(type, firstSheet);
039    }
040
041    public ExcelBuilderMultiSheet(Type type) {
042        super(type);
043    }
044
045    public boolean isMultiSheetColumns() {
046        return multiSheetMode;
047    }
048
049    /**
050     * If true, the builder is able to switch on next sheets to fill cells with column id > 255.
051     */
052    public void setMultiSheetColumns(boolean multiSheetMode) {
053        this.multiSheetMode = multiSheetMode;
054    }
055
056    @Override
057    protected Cell getOrCreateCell(int i, int j) {
058        if (multiSheetMode)
059            j = autoSelectSheet(j);
060        return super.getOrCreateCell(i, j);
061    }
062
063    /**
064     * Only invalidate cells having a too large row id. {@inheritDoc}
065     */
066    @Override
067    protected boolean validateCellIndex(int row, int column, String content) {
068        if (multiSheetMode) {
069            if (row >= MAX_ROW) {
070                String message = "max number of row (" + MAX_ROW + ") exceeded @ " + row + " by '" + content + "'";
071                if (CRASH_ON_CELL_OVERFLOW)
072                    throw new IllegalArgumentException(message);
073                else {
074                    log.warn(message);
075                    return false;
076                }
077            }
078            return true;
079        } else {
080            return super.validateCellIndex(row, column, content);
081        }
082    }
083
084    /* */
085
086    /**
087     * Return a sheet ID for the expected cell:
088     * <ul>
089     * <li>sheet 0 for cells [0;255]
090     * <li>sheet 1 for cells [256;511]
091     * <li>...
092     * </ul>
093     */
094    public int getVirtualCellSheet(int realColumn) {
095        return realColumn / MAX_COLUMN;
096    }
097
098    /**
099     * Return a column ID for the expected cell:
100     * <ul>
101     * <li>returns 255 for realColumn=255
102     * <li>returns 0 for realColumn=256
103     * <li>...
104     * </ul>
105     */
106    public int getVirtualCellColumn(int realColumn) {
107        return realColumn % MAX_COLUMN;
108    }
109
110    /**
111     * Compute the sheet/column required to access the given column. If expected sheet is not current, change it. If it
112     * does not exist, create it.
113     *
114     * @return an updated column index.
115     */
116    protected int autoSelectSheet(int column) {
117        int s = getVirtualCellSheet(column);
118
119        // change current sheet if required
120        if (s != getCurrentSheetId()) {
121            if (!sheetInitialized(s)) {
122                setCurrentSheetId(newSheet(s, "(" + s + ")"));
123            } else {
124                setCurrentSheetId(s);
125            }
126        }
127        column = getVirtualCellColumn(column); // update J!!
128        return column;
129    }
130
131}