Initial add of ForkedEvaluator functionality
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@723194 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
1869eb5186
commit
11cc164f26
@ -0,0 +1,132 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.ss.formula.eval.forked;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.record.formula.eval.BlankEval;
|
||||||
|
import org.apache.poi.hssf.record.formula.eval.BoolEval;
|
||||||
|
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||||
|
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||||
|
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||||
|
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||||
|
import org.apache.poi.ss.formula.EvaluationCell;
|
||||||
|
import org.apache.poi.ss.formula.EvaluationSheet;
|
||||||
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a cell being used for forked evaluation that has had a value set different from the
|
||||||
|
* corresponding cell in the shared master workbook.
|
||||||
|
*
|
||||||
|
* @author Josh Micich
|
||||||
|
*/
|
||||||
|
final class ForkedEvaluationCell implements EvaluationCell {
|
||||||
|
|
||||||
|
private final EvaluationSheet _sheet;
|
||||||
|
/** corresponding cell from master workbook */
|
||||||
|
private final EvaluationCell _masterCell;
|
||||||
|
private boolean _booleanValue;
|
||||||
|
private int _cellType;
|
||||||
|
private int _errorValue;
|
||||||
|
private double _numberValue;
|
||||||
|
private String _stringValue;
|
||||||
|
|
||||||
|
public ForkedEvaluationCell(ForkedEvaluationSheet sheet, EvaluationCell masterCell) {
|
||||||
|
_sheet = sheet;
|
||||||
|
_masterCell = masterCell;
|
||||||
|
// start with value blank, but expect construction to be immediately
|
||||||
|
setValue(BlankEval.INSTANCE); // followed by a proper call to setValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getIdentityKey() {
|
||||||
|
return _masterCell.getIdentityKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(ValueEval value) {
|
||||||
|
Class<? extends ValueEval> cls = value.getClass();
|
||||||
|
|
||||||
|
if (cls == NumberEval.class) {
|
||||||
|
_cellType = HSSFCell.CELL_TYPE_NUMERIC;
|
||||||
|
_numberValue = ((NumberEval)value).getNumberValue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cls == StringEval.class) {
|
||||||
|
_cellType = HSSFCell.CELL_TYPE_STRING;
|
||||||
|
_stringValue = ((StringEval)value).getStringValue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cls == BoolEval.class) {
|
||||||
|
_cellType = HSSFCell.CELL_TYPE_BOOLEAN;
|
||||||
|
_booleanValue = ((BoolEval)value).getBooleanValue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cls == ErrorEval.class) {
|
||||||
|
_cellType = HSSFCell.CELL_TYPE_ERROR;
|
||||||
|
_errorValue = ((ErrorEval)value).getErrorCode();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cls == BlankEval.class) {
|
||||||
|
_cellType = HSSFCell.CELL_TYPE_BLANK;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unexpected value class (" + cls.getName() + ")");
|
||||||
|
}
|
||||||
|
public void copyValue(Cell destCell) {
|
||||||
|
switch (_cellType) {
|
||||||
|
case Cell.CELL_TYPE_BLANK: destCell.setCellType(Cell.CELL_TYPE_BLANK); return;
|
||||||
|
case Cell.CELL_TYPE_NUMERIC: destCell.setCellValue(_numberValue); return;
|
||||||
|
case Cell.CELL_TYPE_BOOLEAN: destCell.setCellValue(_booleanValue); return;
|
||||||
|
case Cell.CELL_TYPE_STRING: destCell.setCellValue(_stringValue); return;
|
||||||
|
case Cell.CELL_TYPE_ERROR: destCell.setCellErrorValue((byte)_errorValue); return;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("Unexpected data type (" + _cellType + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCellType(int expectedCellType) {
|
||||||
|
if (_cellType != expectedCellType) {
|
||||||
|
throw new RuntimeException("Wrong data type (" + _cellType + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public int getCellType() {
|
||||||
|
return _cellType;
|
||||||
|
}
|
||||||
|
public boolean getBooleanCellValue() {
|
||||||
|
checkCellType(HSSFCell.CELL_TYPE_BOOLEAN);
|
||||||
|
return _booleanValue;
|
||||||
|
}
|
||||||
|
public int getErrorCellValue() {
|
||||||
|
checkCellType(HSSFCell.CELL_TYPE_ERROR);
|
||||||
|
return _errorValue;
|
||||||
|
}
|
||||||
|
public double getNumericCellValue() {
|
||||||
|
checkCellType(HSSFCell.CELL_TYPE_NUMERIC);
|
||||||
|
return _numberValue;
|
||||||
|
}
|
||||||
|
public String getStringCellValue() {
|
||||||
|
checkCellType(HSSFCell.CELL_TYPE_STRING);
|
||||||
|
return _stringValue;
|
||||||
|
}
|
||||||
|
public EvaluationSheet getSheet() {
|
||||||
|
return _sheet;
|
||||||
|
}
|
||||||
|
public int getRowIndex() {
|
||||||
|
return _masterCell.getRowIndex();
|
||||||
|
}
|
||||||
|
public int getColumnIndex() {
|
||||||
|
return _masterCell.getColumnIndex();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,129 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.ss.formula.eval.forked;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.poi.ss.formula.EvaluationCell;
|
||||||
|
import org.apache.poi.ss.formula.EvaluationSheet;
|
||||||
|
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
||||||
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
|
import org.apache.poi.ss.usermodel.Sheet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a sheet being used for forked evaluation. Initially, objects of this class contain
|
||||||
|
* only the cells from the master workbook. By calling {@link #getOrCreateUpdatableCell(int, int)},
|
||||||
|
* the master cell object is logically replaced with a {@link ForkedEvaluationCell} instance, which
|
||||||
|
* will be used in all subsequent evaluations.
|
||||||
|
*
|
||||||
|
* @author Josh Micich
|
||||||
|
*/
|
||||||
|
final class ForkedEvaluationSheet implements EvaluationSheet {
|
||||||
|
|
||||||
|
private final EvaluationSheet _masterSheet;
|
||||||
|
/**
|
||||||
|
* Only cells which have been split are put in this map. (This has been done to conserve memory).
|
||||||
|
*/
|
||||||
|
private final Map<RowColKey, ForkedEvaluationCell> _sharedCellsByRowCol;
|
||||||
|
|
||||||
|
public ForkedEvaluationSheet(EvaluationSheet masterSheet) {
|
||||||
|
_masterSheet = masterSheet;
|
||||||
|
_sharedCellsByRowCol = new HashMap<RowColKey, ForkedEvaluationCell>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public EvaluationCell getCell(int rowIndex, int columnIndex) {
|
||||||
|
RowColKey key = new RowColKey(rowIndex, columnIndex);
|
||||||
|
|
||||||
|
ForkedEvaluationCell result = _sharedCellsByRowCol.get(key);
|
||||||
|
if (result == null) {
|
||||||
|
return _masterSheet.getCell(rowIndex, columnIndex);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ForkedEvaluationCell getOrCreateUpdatableCell(int rowIndex, int columnIndex) {
|
||||||
|
RowColKey key = new RowColKey(rowIndex, columnIndex);
|
||||||
|
|
||||||
|
ForkedEvaluationCell result = _sharedCellsByRowCol.get(key);
|
||||||
|
if (result == null) {
|
||||||
|
EvaluationCell mcell = _masterSheet.getCell(rowIndex, columnIndex);
|
||||||
|
result = new ForkedEvaluationCell(this, mcell);
|
||||||
|
_sharedCellsByRowCol.put(key, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyUpdatedCells(Sheet sheet) {
|
||||||
|
RowColKey[] keys = new RowColKey[_sharedCellsByRowCol.size()];
|
||||||
|
_sharedCellsByRowCol.keySet().toArray(keys);
|
||||||
|
Arrays.sort(keys);
|
||||||
|
for (int i = 0; i < keys.length; i++) {
|
||||||
|
RowColKey key = keys[i];
|
||||||
|
Row row = sheet.getRow(key.getRowIndex());
|
||||||
|
if (row == null) {
|
||||||
|
row = sheet.createRow(key.getRowIndex());
|
||||||
|
}
|
||||||
|
Cell destCell = row.getCell(key.getColumnIndex());
|
||||||
|
if (destCell == null) {
|
||||||
|
destCell = row.createCell(key.getColumnIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
ForkedEvaluationCell srcCell = _sharedCellsByRowCol.get(key);
|
||||||
|
srcCell.copyValue(destCell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSheetIndex(EvaluationWorkbook mewb) {
|
||||||
|
return mewb.getSheetIndex(_masterSheet);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class RowColKey implements Comparable<RowColKey>{
|
||||||
|
private final int _rowIndex;
|
||||||
|
private final int _columnIndex;
|
||||||
|
|
||||||
|
public RowColKey(int rowIndex, int columnIndex) {
|
||||||
|
_rowIndex = rowIndex;
|
||||||
|
_columnIndex = columnIndex;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
RowColKey other = (RowColKey) obj;
|
||||||
|
return _rowIndex == other._rowIndex && _columnIndex == other._columnIndex;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return _rowIndex ^ _columnIndex;
|
||||||
|
}
|
||||||
|
public int compareTo(RowColKey o) {
|
||||||
|
int cmp = _rowIndex - o._rowIndex;
|
||||||
|
if (cmp != 0) {
|
||||||
|
return cmp;
|
||||||
|
}
|
||||||
|
return _columnIndex - o._columnIndex;
|
||||||
|
}
|
||||||
|
public int getRowIndex() {
|
||||||
|
return _rowIndex;
|
||||||
|
}
|
||||||
|
public int getColumnIndex() {
|
||||||
|
return _columnIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,144 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.ss.formula.eval.forked;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.record.formula.NamePtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.NameXPtg;
|
||||||
|
import org.apache.poi.hssf.record.formula.Ptg;
|
||||||
|
import org.apache.poi.ss.formula.EvaluationCell;
|
||||||
|
import org.apache.poi.ss.formula.EvaluationName;
|
||||||
|
import org.apache.poi.ss.formula.EvaluationSheet;
|
||||||
|
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
||||||
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a workbook being used for forked evaluation. Most operations are delegated to the
|
||||||
|
* shared master workbook, except those that potentially involve cell values that may have been
|
||||||
|
* updated after a call to {@link #getOrCreateUpdatableCell(String, int, int)}.
|
||||||
|
*
|
||||||
|
* @author Josh Micich
|
||||||
|
*/
|
||||||
|
final class ForkedEvaluationWorkbook implements EvaluationWorkbook {
|
||||||
|
|
||||||
|
private final EvaluationWorkbook _masterBook;
|
||||||
|
private final Map<String, ForkedEvaluationSheet> _sharedSheetsByName;
|
||||||
|
|
||||||
|
public ForkedEvaluationWorkbook(EvaluationWorkbook master) {
|
||||||
|
_masterBook = master;
|
||||||
|
_sharedSheetsByName = new HashMap<String, ForkedEvaluationSheet>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ForkedEvaluationCell getOrCreateUpdatableCell(String sheetName, int rowIndex,
|
||||||
|
int columnIndex) {
|
||||||
|
ForkedEvaluationSheet sheet = getSharedSheet(sheetName);
|
||||||
|
return sheet.getOrCreateUpdatableCell(rowIndex, columnIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EvaluationCell getEvaluationCell(String sheetName, int rowIndex, int columnIndex) {
|
||||||
|
ForkedEvaluationSheet sheet = getSharedSheet(sheetName);
|
||||||
|
return sheet.getCell(rowIndex, columnIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ForkedEvaluationSheet getSharedSheet(String sheetName) {
|
||||||
|
ForkedEvaluationSheet result = _sharedSheetsByName.get(sheetName);
|
||||||
|
if (result == null) {
|
||||||
|
result = new ForkedEvaluationSheet(_masterBook.getSheet(_masterBook
|
||||||
|
.getSheetIndex(sheetName)));
|
||||||
|
_sharedSheetsByName.put(sheetName, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyUpdatedCells(Workbook workbook) {
|
||||||
|
String[] sheetNames = new String[_sharedSheetsByName.size()];
|
||||||
|
_sharedSheetsByName.keySet().toArray(sheetNames);
|
||||||
|
OrderedSheet[] oss = new OrderedSheet[sheetNames.length];
|
||||||
|
for (int i = 0; i < sheetNames.length; i++) {
|
||||||
|
String sheetName = sheetNames[i];
|
||||||
|
oss[i] = new OrderedSheet(sheetName, _masterBook.getSheetIndex(sheetName));
|
||||||
|
}
|
||||||
|
for (int i = 0; i < oss.length; i++) {
|
||||||
|
String sheetName = oss[i].getSheetName();
|
||||||
|
ForkedEvaluationSheet sheet = _sharedSheetsByName.get(sheetName);
|
||||||
|
sheet.copyUpdatedCells(workbook.getSheet(sheetName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int convertFromExternSheetIndex(int externSheetIndex) {
|
||||||
|
return _masterBook.convertFromExternSheetIndex(externSheetIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExternalSheet getExternalSheet(int externSheetIndex) {
|
||||||
|
return _masterBook.getExternalSheet(externSheetIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Ptg[] getFormulaTokens(EvaluationCell cell) {
|
||||||
|
if (cell instanceof ForkedEvaluationCell) {
|
||||||
|
// doesn't happen yet because formulas cannot be modified from the master workbook
|
||||||
|
throw new RuntimeException("Updated formulas not supported yet");
|
||||||
|
}
|
||||||
|
return _masterBook.getFormulaTokens(cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EvaluationName getName(NamePtg namePtg) {
|
||||||
|
return _masterBook.getName(namePtg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EvaluationSheet getSheet(int sheetIndex) {
|
||||||
|
return getSharedSheet(getSheetName(sheetIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSheetIndex(EvaluationSheet sheet) {
|
||||||
|
if (sheet instanceof ForkedEvaluationSheet) {
|
||||||
|
ForkedEvaluationSheet mes = (ForkedEvaluationSheet) sheet;
|
||||||
|
return mes.getSheetIndex(_masterBook);
|
||||||
|
}
|
||||||
|
return _masterBook.getSheetIndex(sheet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSheetIndex(String sheetName) {
|
||||||
|
return _masterBook.getSheetIndex(sheetName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSheetName(int sheetIndex) {
|
||||||
|
return _masterBook.getSheetName(sheetIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String resolveNameXText(NameXPtg ptg) {
|
||||||
|
return _masterBook.resolveNameXText(ptg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class OrderedSheet implements Comparable<OrderedSheet> {
|
||||||
|
private final String _sheetName;
|
||||||
|
private final int _index;
|
||||||
|
|
||||||
|
public OrderedSheet(String sheetName, int index) {
|
||||||
|
_sheetName = sheetName;
|
||||||
|
_index = index;
|
||||||
|
}
|
||||||
|
public String getSheetName() {
|
||||||
|
return _sheetName;
|
||||||
|
}
|
||||||
|
public int compareTo(OrderedSheet o) {
|
||||||
|
return _index - o._index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,134 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
contributor license agreements. See the NOTICE file distributed with
|
||||||
|
this work for additional information regarding copyright ownership.
|
||||||
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
(the "License"); you may not use this file except in compliance with
|
||||||
|
the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
==================================================================== */
|
||||||
|
|
||||||
|
package org.apache.poi.ss.formula.eval.forked;
|
||||||
|
|
||||||
|
import org.apache.poi.hssf.record.formula.eval.BoolEval;
|
||||||
|
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||||
|
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||||
|
import org.apache.poi.hssf.record.formula.eval.StringEval;
|
||||||
|
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFEvaluationWorkbook;
|
||||||
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
|
import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment;
|
||||||
|
import org.apache.poi.ss.formula.EvaluationCell;
|
||||||
|
import org.apache.poi.ss.formula.EvaluationWorkbook;
|
||||||
|
import org.apache.poi.ss.formula.IStabilityClassifier;
|
||||||
|
import org.apache.poi.ss.formula.WorkbookEvaluator;
|
||||||
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An alternative workbook evaluator that saves memory in situations where a single workbook is
|
||||||
|
* concurrently and independently evaluated many times. With standard formula evaluation, around
|
||||||
|
* 90% of memory consumption is due to loading of the {@link HSSFWorkbook} or {@link XSSFWorkbook}.
|
||||||
|
* This class enables a 'master workbook' to be loaded just once and shared between many evaluation
|
||||||
|
* clients. Each evaluation client creates its own {@link ForkedEvaluator} and can set cell values
|
||||||
|
* that will be used for local evaluations (and don't disturb evaluations on other evaluators).
|
||||||
|
*
|
||||||
|
* @author Josh Micich
|
||||||
|
*/
|
||||||
|
public final class ForkedEvaluator {
|
||||||
|
|
||||||
|
private WorkbookEvaluator _evaluator;
|
||||||
|
private ForkedEvaluationWorkbook _sewb;
|
||||||
|
|
||||||
|
private ForkedEvaluator(EvaluationWorkbook masterWorkbook, IStabilityClassifier stabilityClassifier) {
|
||||||
|
_sewb = new ForkedEvaluationWorkbook(masterWorkbook);
|
||||||
|
_evaluator = new WorkbookEvaluator(_sewb, stabilityClassifier);
|
||||||
|
}
|
||||||
|
private static EvaluationWorkbook createEvaluationWorkbook(Workbook wb) {
|
||||||
|
if (wb instanceof HSSFWorkbook) {
|
||||||
|
return HSSFEvaluationWorkbook.create((HSSFWorkbook) wb);
|
||||||
|
}
|
||||||
|
// TODO rearrange POI build to allow this
|
||||||
|
// if (wb instanceof XSSFWorkbook) {
|
||||||
|
// return XSSFEvaluationWorkbook.create((XSSFWorkbook) wb);
|
||||||
|
// }
|
||||||
|
throw new IllegalArgumentException("Unexpected workbook type (" + wb.getClass().getName() + ")");
|
||||||
|
}
|
||||||
|
public static ForkedEvaluator create(Workbook wb, IStabilityClassifier stabilityClassifier) {
|
||||||
|
return new ForkedEvaluator(createEvaluationWorkbook(wb), stabilityClassifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the specified cell to the supplied <tt>value</tt>
|
||||||
|
* @param sheetName the name of the sheet containing the cell
|
||||||
|
* @param rowIndex zero based
|
||||||
|
* @param columnIndex zero based
|
||||||
|
*/
|
||||||
|
public void updateCell(String sheetName, int rowIndex, int columnIndex, ValueEval value) {
|
||||||
|
|
||||||
|
ForkedEvaluationCell cell = _sewb.getOrCreateUpdatableCell(sheetName, rowIndex, columnIndex);
|
||||||
|
cell.setValue(value);
|
||||||
|
_evaluator.notifyUpdateCell(cell);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Copies the values of all updated cells (modified by calls to {@link
|
||||||
|
* #updateCell(String, int, int, ValueEval)}) to the supplied <tt>workbook</tt>.<br/>
|
||||||
|
* Typically, the supplied <tt>workbook</tt> is a writable copy of the 'master workbook',
|
||||||
|
* but at the very least it must contain sheets with the same names.
|
||||||
|
*/
|
||||||
|
public void copyUpdatedCells(Workbook workbook) {
|
||||||
|
_sewb.copyUpdatedCells(workbook);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If cell contains a formula, the formula is evaluated and returned,
|
||||||
|
* else the CellValue simply copies the appropriate cell value from
|
||||||
|
* the cell and also its cell type. This method should be preferred over
|
||||||
|
* evaluateInCell() when the call should not modify the contents of the
|
||||||
|
* original cell.
|
||||||
|
*
|
||||||
|
* @param cell may be <code>null</code> signifying that the cell is not present (or blank)
|
||||||
|
* @return <code>null</code> if the supplied cell is <code>null</code> or blank
|
||||||
|
*/
|
||||||
|
public ValueEval evaluate(String sheetName, int rowIndex, int columnIndex) {
|
||||||
|
EvaluationCell cell = _sewb.getEvaluationCell(sheetName, rowIndex, columnIndex);
|
||||||
|
|
||||||
|
switch (cell.getCellType()) {
|
||||||
|
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||||
|
return BoolEval.valueOf(cell.getBooleanCellValue());
|
||||||
|
case HSSFCell.CELL_TYPE_ERROR:
|
||||||
|
return ErrorEval.valueOf(cell.getErrorCellValue());
|
||||||
|
case HSSFCell.CELL_TYPE_FORMULA:
|
||||||
|
return _evaluator.evaluate(cell);
|
||||||
|
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||||
|
return new NumberEval(cell.getNumericCellValue());
|
||||||
|
case HSSFCell.CELL_TYPE_STRING:
|
||||||
|
return new StringEval(cell.getStringCellValue());
|
||||||
|
case HSSFCell.CELL_TYPE_BLANK:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException("Bad cell type (" + cell.getCellType() + ")");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Coordinates several formula evaluators together so that formulas that involve external
|
||||||
|
* references can be evaluated.
|
||||||
|
* @param workbookNames the simple file names used to identify the workbooks in formulas
|
||||||
|
* with external links (for example "MyData.xls" as used in a formula "[MyData.xls]Sheet1!A1")
|
||||||
|
* @param evaluators all evaluators for the full set of workbooks required by the formulas.
|
||||||
|
*/
|
||||||
|
public static void setupEnvironment(String[] workbookNames, ForkedEvaluator[] evaluators) {
|
||||||
|
WorkbookEvaluator[] wbEvals = new WorkbookEvaluator[evaluators.length];
|
||||||
|
for (int i = 0; i < wbEvals.length; i++) {
|
||||||
|
wbEvals[i] = evaluators[i]._evaluator;
|
||||||
|
}
|
||||||
|
CollaboratingWorkbooksEnvironment.setup(workbookNames, wbEvals);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user