git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1904050 13f79535-47bb-0310-9956-ffa450edef68tags/REL_5_2_4
return new Rectangle2D.Double(1,1,1,1); | return new Rectangle2D.Double(1,1,1,1); | ||||
} | } | ||||
/** | |||||
* @param continuedObjectData list of object data | |||||
* @return byte array | |||||
* @throws IllegalStateException if the data cannot be read | |||||
*/ | |||||
public byte[] getRawData(List<? extends EmfPlusObjectData> continuedObjectData) { | public byte[] getRawData(List<? extends EmfPlusObjectData> continuedObjectData) { | ||||
try (UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream()) { | try (UnsynchronizedByteArrayOutputStream bos = new UnsynchronizedByteArrayOutputStream()) { | ||||
bos.write(getImageData()); | bos.write(getImageData()); | ||||
} | } | ||||
return bos.toByteArray(); | return bos.toByteArray(); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
private HemfPlusGDIImageRenderer getGDIRenderer() { | private HemfPlusGDIImageRenderer getGDIRenderer() { | ||||
if (getImageDataType() != EmfPlusImageDataType.BITMAP || getBitmapType() != EmfPlusBitmapDataType.PIXEL) { | if (getImageDataType() != EmfPlusImageDataType.BITMAP || getBitmapType() != EmfPlusBitmapDataType.PIXEL) { | ||||
throw new RuntimeException("image data is not a GDI image"); | |||||
throw new IllegalStateException("image data is not a GDI image"); | |||||
} | } | ||||
HemfPlusGDIImageRenderer renderer = new HemfPlusGDIImageRenderer(); | HemfPlusGDIImageRenderer renderer = new HemfPlusGDIImageRenderer(); | ||||
renderer.setWidth(getBitmapWidth()); | renderer.setWidth(getBitmapWidth()); |
// A 32-bit unsigned integer that specifies the number of elements in the DashedLineData field. | // A 32-bit unsigned integer that specifies the number of elements in the DashedLineData field. | ||||
int dashesSize = leis.readInt(); | int dashesSize = leis.readInt(); | ||||
if (dashesSize < 0 || dashesSize > 1000) { | if (dashesSize < 0 || dashesSize > 1000) { | ||||
throw new RuntimeException("Invalid dash data size"); | |||||
throw new IllegalStateException("Invalid dash data size"); | |||||
} | } | ||||
// An array of DashedLineDataSize floating-point values that specify the lengths of the dashes and spaces in a dashed line. | // An array of DashedLineDataSize floating-point values that specify the lengths of the dashes and spaces in a dashed line. | ||||
// A 32-bit unsigned integer that specifies the number of elements in the CompoundLineData field. | // A 32-bit unsigned integer that specifies the number of elements in the CompoundLineData field. | ||||
int compoundSize = leis.readInt(); | int compoundSize = leis.readInt(); | ||||
if (compoundSize < 0 || compoundSize > 1000) { | if (compoundSize < 0 || compoundSize > 1000) { | ||||
throw new RuntimeException("Invalid compound line data size"); | |||||
throw new IllegalStateException("Invalid compound line data size"); | |||||
} | } | ||||
// An array of CompoundLineDataSize floating-point values that specify the compound line of a pen. | // An array of CompoundLineDataSize floating-point values that specify the compound line of a pen. |
fontDataSize = leis.readInt(); | fontDataSize = leis.readInt(); | ||||
version = leis.readInt(); | version = leis.readInt(); | ||||
if (version != 0x00010000 && version != 0x00020001 && version != 0x00020002) { | if (version != 0x00010000 && version != 0x00020001 && version != 0x00020002) { | ||||
throw new RuntimeException("not a EOT font data stream"); | |||||
throw new IllegalStateException("not a EOT font data stream"); | |||||
} | } | ||||
flags = leis.readInt(); | flags = leis.readInt(); | ||||
leis.readFully(panose); | leis.readFully(panose); | ||||
fsType = leis.readUShort(); | fsType = leis.readUShort(); | ||||
magic = leis.readUShort(); | magic = leis.readUShort(); | ||||
if (magic != 0x504C) { | if (magic != 0x504C) { | ||||
throw new RuntimeException("not a EOT font data stream"); | |||||
throw new IllegalStateException("not a EOT font data stream"); | |||||
} | } | ||||
unicodeRange1 = leis.readInt(); | unicodeRange1 = leis.readInt(); | ||||
unicodeRange2 = leis.readInt(); | unicodeRange2 = leis.readInt(); |
field_4_dy2 = LittleEndian.getShort( data, pos + size );size+=2; | field_4_dy2 = LittleEndian.getShort( data, pos + size );size+=2; | ||||
break; | break; | ||||
default: | default: | ||||
throw new RuntimeException("Invalid EscherChildAnchorRecord - neither 8 nor 16 bytes."); | |||||
throw new IllegalStateException("Invalid EscherChildAnchorRecord - neither 8 nor 16 bytes."); | |||||
} | } | ||||
return 8 + size; | return 8 + size; |
} | } | ||||
raw_pictureData = bos.toByteArray(); | raw_pictureData = bos.toByteArray(); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException("Can't compress metafile picture data", e); | |||||
throw new IllegalStateException("Can't compress metafile picture data", e); | |||||
} | } | ||||
setCompressedSize(raw_pictureData.length); | setCompressedSize(raw_pictureData.length); |
final byte[] v = IOUtils.toByteArray(lei, length, CodePageString.getMaxRecordLength()); | final byte[] v = IOUtils.toByteArray(lei, length, CodePageString.getMaxRecordLength()); | ||||
throw new ReadingNotSupportedException( type, v ); | throw new ReadingNotSupportedException( type, v ); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
text = text + "\n"; | text = text + "\n"; | ||||
} | } | ||||
} catch(IOException e) { | } catch(IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
return text; | return text; |
} | } | ||||
break; | break; | ||||
default: | default: | ||||
throw new RuntimeException("Unexpected cell type (" + cell.getCellType() + ")"); | |||||
throw new IllegalStateException("Unexpected cell type (" + cell.getCellType() + ")"); | |||||
} | } | ||||
// Output the comment, if requested and exists | // Output the comment, if requested and exists |
private void checkSheets(int sheetnum) { | private void checkSheets(int sheetnum) { | ||||
if ((boundsheets.size()) <= sheetnum) { // if we're short one add another.. | if ((boundsheets.size()) <= sheetnum) { // if we're short one add another.. | ||||
if ((boundsheets.size() + 1) <= sheetnum) { | if ((boundsheets.size() + 1) <= sheetnum) { | ||||
throw new RuntimeException("Sheet number out of bounds!"); | |||||
throw new IllegalStateException("Sheet number out of bounds!"); | |||||
} | } | ||||
BoundSheetRecord bsr = createBoundSheet(sheetnum); | BoundSheetRecord bsr = createBoundSheet(sheetnum); | ||||
NameRecord name = new NameRecord(builtInName, sheetNumber); | NameRecord name = new NameRecord(builtInName, sheetNumber); | ||||
if(linkTable.nameAlreadyExists(name)) { | if(linkTable.nameAlreadyExists(name)) { | ||||
throw new RuntimeException("Builtin (" + builtInName | |||||
throw new IllegalStateException("Builtin (" + builtInName | |||||
+ ") already exists for sheet (" + sheetNumber + ")"); | + ") already exists for sheet (" + sheetNumber + ")"); | ||||
} | } | ||||
addName(name); | addName(name); | ||||
if (rec instanceof PaletteRecord) { | if (rec instanceof PaletteRecord) { | ||||
palette = (PaletteRecord) rec; | palette = (PaletteRecord) rec; | ||||
} else { | } else { | ||||
throw new RuntimeException("InternalError: Expected PaletteRecord but got a '"+rec+"'"); | |||||
throw new IllegalStateException("InternalError: Expected PaletteRecord but got a '"+rec+"'"); | |||||
} | } | ||||
} else { | } else { | ||||
palette = createPalette(); | palette = createPalette(); |
int nItems = temp.size(); | int nItems = temp.size(); | ||||
if (nItems < 1) { | if (nItems < 1) { | ||||
throw new RuntimeException("Expected an EXTERNSHEET record but got (" | |||||
throw new IllegalStateException("Expected an EXTERNSHEET record but got (" | |||||
+ rs.peekNextClass().getName() + ")"); | + rs.peekNextClass().getName() + ")"); | ||||
} | } | ||||
if (nItems == 1) { | if (nItems == 1) { | ||||
if (idx < 0) { | if (idx < 0) { | ||||
idx = findFirstRecordLocBySid(SSTRecord.sid) - 1; | idx = findFirstRecordLocBySid(SSTRecord.sid) - 1; | ||||
if (idx < 0) { | if (idx < 0) { | ||||
throw new RuntimeException("CountryRecord or SSTRecord not found"); | |||||
throw new IllegalStateException("CountryRecord or SSTRecord not found"); | |||||
} | } | ||||
} | } | ||||
_workbookRecordList.add(idx + 1, _externSheetRecord); | _workbookRecordList.add(idx + 1, _externSheetRecord); | ||||
public int getExternalSheetIndex(String workbookName, String firstSheetName, String lastSheetName) { | public int getExternalSheetIndex(String workbookName, String firstSheetName, String lastSheetName) { | ||||
int externalBookIndex = getExternalWorkbookIndex(workbookName); | int externalBookIndex = getExternalWorkbookIndex(workbookName); | ||||
if (externalBookIndex == -1) { | if (externalBookIndex == -1) { | ||||
throw new RuntimeException("No external workbook with name '" + workbookName + "'"); | |||||
throw new IllegalStateException("No external workbook with name '" + workbookName + "'"); | |||||
} | } | ||||
SupBookRecord ebrTarget = _externalBookBlocks[externalBookIndex].getExternalBookRecord(); | SupBookRecord ebrTarget = _externalBookBlocks[externalBookIndex].getExternalBookRecord(); | ||||
} | } | ||||
} | } | ||||
throw new RuntimeException("External workbook does not contain sheet '" + sheetName + "'"); | |||||
throw new IllegalStateException("External workbook does not contain sheet '" + sheetName + "'"); | |||||
} | } | ||||
/** | /** | ||||
} | } | ||||
} | } | ||||
if (thisWbIndex < 0) { | if (thisWbIndex < 0) { | ||||
throw new RuntimeException("Could not find 'internal references' EXTERNALBOOK"); | |||||
throw new IllegalStateException("Could not find 'internal references' EXTERNALBOOK"); | |||||
} | } | ||||
if (_externSheetRecord == null) { | if (_externSheetRecord == null) { | ||||
throw new RuntimeException("Did not have an external sheet record, having blocks: " + | |||||
throw new IllegalStateException("Did not have an external sheet record, having blocks: " + | |||||
_externalBookBlocks.length); | _externalBookBlocks.length); | ||||
} | } | ||||
int firstTabIndex = _externSheetRecord.getFirstSheetIndexFromRefIndex(refIndex); | int firstTabIndex = _externSheetRecord.getFirstSheetIndexFromRefIndex(refIndex); | ||||
if (firstTabIndex == -1) { | if (firstTabIndex == -1) { | ||||
// The referenced sheet could not be found | // The referenced sheet could not be found | ||||
throw new RuntimeException("Referenced sheet could not be found"); | |||||
throw new IllegalStateException("Referenced sheet could not be found"); | |||||
} | } | ||||
// Does it exist via the external book block? | // Does it exist via the external book block? |
} | } | ||||
return null; | return null; | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException("Unexpected exception in readRefPtg", e); | |||||
throw new IllegalStateException("Unexpected exception in readRefPtg", e); | |||||
} | } | ||||
} | } | ||||
try { | try { | ||||
buffer.write(data); | buffer.write(data); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException("Couldn't get data from drawing/continue records", e); | |||||
throw new IllegalStateException("Couldn't get data from drawing/continue records", e); | |||||
} | } | ||||
} | } | ||||
int formulaColumn = formula.getColumn(); | int formulaColumn = formula.getColumn(); | ||||
//Sanity checks | //Sanity checks | ||||
if (!isInRange(formulaRow, formulaColumn)) { | if (!isInRange(formulaRow, formulaColumn)) { | ||||
throw new RuntimeException("Shared Formula Conversion: Coding Error"); | |||||
throw new IllegalStateException("Shared Formula Conversion: Coding Error"); | |||||
} | } | ||||
SharedFormula sf = new SharedFormula(SpreadsheetVersion.EXCEL97); | SharedFormula sf = new SharedFormula(SpreadsheetVersion.EXCEL97); |
UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(size); | UnsynchronizedByteArrayOutputStream baos = new UnsynchronizedByteArrayOutputStream(size); | ||||
serialize(new LittleEndianOutputStream(baos)); | serialize(new LittleEndianOutputStream(baos)); | ||||
if (baos.size() != size) { | if (baos.size() != size) { | ||||
throw new RuntimeException("write size mismatch"); | |||||
throw new IllegalStateException("write size mismatch"); | |||||
} | } | ||||
return baos.toByteArray(); | return baos.toByteArray(); | ||||
} | } |
cirPrev = cir; | cirPrev = cir; | ||||
} | } | ||||
if (records.size() < 1) { | if (records.size() < 1) { | ||||
throw new RuntimeException("No column info records found"); | |||||
throw new IllegalStateException("No column info records found"); | |||||
} | } | ||||
if (!isInOrder) { | if (!isInOrder) { | ||||
records.sort(ColumnInfoRecordsAggregate::compareColInfos); | records.sort(ColumnInfoRecordsAggregate::compareColInfos); | ||||
if (cirPrev != null && compareColInfos(cirPrev, cir) > 0) { | if (cirPrev != null && compareColInfos(cirPrev, cir) > 0) { | ||||
// Excel probably wouldn't mind, but there is much logic in this class | // Excel probably wouldn't mind, but there is much logic in this class | ||||
// that assumes the column info records are kept in order | // that assumes the column info records are kept in order | ||||
throw new RuntimeException("Column info records are out of order"); | |||||
throw new IllegalStateException("Column info records are out of order"); | |||||
} | } | ||||
cirPrev = cir; | cirPrev = cir; | ||||
} | } |
} | } | ||||
int row = cell.getRow(); | int row = cell.getRow(); | ||||
if (row >= records.length) { | if (row >= records.length) { | ||||
throw new RuntimeException("cell row is out of range"); | |||||
throw new IllegalStateException("cell row is out of range"); | |||||
} | } | ||||
CellValueRecordInterface[] rowCells = records[row]; | CellValueRecordInterface[] rowCells = records[row]; | ||||
if (rowCells == null) { | if (rowCells == null) { | ||||
throw new RuntimeException("cell row is already empty"); | |||||
throw new IllegalStateException("cell row is already empty"); | |||||
} | } | ||||
short column = cell.getColumn(); | short column = cell.getColumn(); | ||||
if (column >= rowCells.length) { | if (column >= rowCells.length) { | ||||
throw new RuntimeException("cell column is out of range"); | |||||
throw new IllegalStateException("cell column is out of range"); | |||||
} | } | ||||
rowCells[column] = null; | rowCells[column] = null; | ||||
} | } |
double result = Double.longBitsToDouble(valueLongBits); | double result = Double.longBitsToDouble(valueLongBits); | ||||
if (Double.isNaN(result)) { | if (Double.isNaN(result)) { | ||||
// (Because Excel typically doesn't write NaN | // (Because Excel typically doesn't write NaN | ||||
throw new RuntimeException("Did not expect to read NaN"); | |||||
throw new IllegalStateException("Did not expect to read NaN"); | |||||
} | } | ||||
return result; | return result; | ||||
} | } |
try { | try { | ||||
return Double.valueOf(numberStr); | return Double.valueOf(numberStr); | ||||
} catch (NumberFormatException e) { | } catch (NumberFormatException e) { | ||||
throw new RuntimeException("The supplied text '" + numberStr | |||||
throw new IllegalStateException("The supplied text '" + numberStr | |||||
+ "' could not be parsed as a number"); | + "' could not be parsed as a number"); | ||||
} | } | ||||
} | } | ||||
try { | try { | ||||
dateVal = dateFormat.parse(dateStr); | dateVal = dateFormat.parse(dateStr); | ||||
} catch (ParseException e) { | } catch (ParseException e) { | ||||
throw new RuntimeException("Failed to parse date '" + dateStr | |||||
throw new IllegalStateException("Failed to parse date '" + dateStr | |||||
+ "' using specified format '" + dateFormat + "'", e); | + "' using specified format '" + dateFormat + "'", e); | ||||
} | } | ||||
} | } | ||||
@Override | @Override | ||||
public void setExplicitListValues(String[] explicitListValues) { | public void setExplicitListValues(String[] explicitListValues) { | ||||
if (_validationType != ValidationType.LIST) { | if (_validationType != ValidationType.LIST) { | ||||
throw new RuntimeException("Cannot setExplicitListValues on non-list constraint"); | |||||
throw new IllegalStateException("Cannot setExplicitListValues on non-list constraint"); | |||||
} | } | ||||
_formula1 = null; | _formula1 = null; | ||||
_explicitListValues = explicitListValues; | _explicitListValues = explicitListValues; |
String[] charactersStrArray = split(charactersStr, ",", -1); | String[] charactersStrArray = split(charactersStr, ",", -1); | ||||
String[] widthsStrArray = split(widthsStr, ",", -1); | String[] widthsStrArray = split(widthsStr, ",", -1); | ||||
if (charactersStrArray.length != widthsStrArray.length) | if (charactersStrArray.length != widthsStrArray.length) | ||||
throw new RuntimeException("Number of characters does not number of widths for font " + fontName); | |||||
throw new IllegalStateException("Number of characters does not number of widths for font " + fontName); | |||||
for ( int i = 0; i < widthsStrArray.length; i++ ) | for ( int i = 0; i < widthsStrArray.length; i++ ) | ||||
{ | { | ||||
if (charactersStrArray[i].length() != 0) | if (charactersStrArray[i].length() != 0) |
? CellType.BOOLEAN | ? CellType.BOOLEAN | ||||
: CellType.ERROR; | : CellType.ERROR; | ||||
} | } | ||||
throw new RuntimeException("Bad cell value rec (" + cval.getClass().getName() + ")"); | |||||
throw new IllegalStateException("Bad cell value rec (" + cval.getClass().getName() + ")"); | |||||
} | } | ||||
/** | /** |
if (eval instanceof ErrorEval) { | if (eval instanceof ErrorEval) { | ||||
return CellValue.getError(((ErrorEval)eval).getErrorCode()); | return CellValue.getError(((ErrorEval)eval).getErrorCode()); | ||||
} | } | ||||
throw new RuntimeException("Unexpected eval class (" + eval.getClass().getName() + ")"); | |||||
throw new IllegalStateException("Unexpected eval class (" + eval.getClass().getName() + ")"); | |||||
} | } | ||||
@Override | @Override |
return getColor(i); | return getColor(i); | ||||
} | } | ||||
} | } | ||||
throw new RuntimeException("Could not find free color index"); | |||||
throw new IllegalStateException("Could not find free color index"); | |||||
} | } | ||||
private static final class CustomColor extends HSSFColor { | private static final class CustomColor extends HSSFColor { |
int column=cell.getColumnIndex(); | int column=cell.getColumnIndex(); | ||||
if(column < 0) { | if(column < 0) { | ||||
throw new RuntimeException("Negative cell indexes not allowed"); | |||||
throw new IllegalStateException("Negative cell indexes not allowed"); | |||||
} | } | ||||
if(column >= cells.length || cell != cells[column]) { | if(column >= cells.length || cell != cells[column]) { | ||||
throw new RuntimeException("Specified cell is not from this row"); | |||||
throw new IllegalStateException("Specified cell is not from this row"); | |||||
} | } | ||||
if(cell.isPartOfArrayFormulaGroup()){ | if(cell.isPartOfArrayFormulaGroup()){ | ||||
cell.tryToDeleteArrayFormula(null); | cell.tryToDeleteArrayFormula(null); |
// Excel, OpenOffice.org and GoogleDocs are all OK with this, so POI should be too. | // Excel, OpenOffice.org and GoogleDocs are all OK with this, so POI should be too. | ||||
if (rowRecordsAlreadyPresent) { | if (rowRecordsAlreadyPresent) { | ||||
// if at least one row record is present, all should be present. | // if at least one row record is present, all should be present. | ||||
throw new RuntimeException("Unexpected missing row when some rows already present"); | |||||
throw new IllegalStateException("Unexpected missing row when some rows already present"); | |||||
}*/ | }*/ | ||||
// create the row record on the fly now. | // create the row record on the fly now. |
for (int defNameIndex = 0; defNameIndex < names.size(); defNameIndex++) { | for (int defNameIndex = 0; defNameIndex < names.size(); defNameIndex++) { | ||||
NameRecord r = workbook.getNameRecord(defNameIndex); | NameRecord r = workbook.getNameRecord(defNameIndex); | ||||
if (r == null) { | if (r == null) { | ||||
throw new RuntimeException("Unable to find all defined names to iterate over"); | |||||
throw new IllegalStateException("Unable to find all defined names to iterate over"); | |||||
} | } | ||||
if (!r.isBuiltInName() || r.getBuiltInName() != builtinCode) { | if (!r.isBuiltInName() || r.getBuiltInName() != builtinCode) { | ||||
continue; | continue; |
try { | try { | ||||
fontMetricsProps = loadMetrics(); | fontMetricsProps = loadMetrics(); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException("Could not load font metrics", e); | |||||
throw new IllegalStateException("Could not load font metrics", e); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
// need to wrap checked exception, because of LittleEndianInput interface :( | // need to wrap checked exception, because of LittleEndianInput interface :( | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
_filesystem.remove(entry); | _filesystem.remove(entry); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
// TODO Work out how to report this, given we can't change the method signature... | // TODO Work out how to report this, given we can't change the method signature... | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
return rval; | return rval; |
return isEqual(inpA, inpB); | return isEqual(inpA, inpB); | ||||
} | } | ||||
} catch (NoPropertySetStreamException | IOException ex) { | } catch (NoPropertySetStreamException | IOException ex) { | ||||
throw new RuntimeException(ex); | |||||
throw new IllegalStateException(ex); | |||||
} | } | ||||
} | } | ||||
stream.close(); | stream.close(); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
if (success) { | if (success) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
// else not success? Try block did not complete normally | // else not success? Try block did not complete normally | ||||
// just print stack trace and leave original ex to be thrown | // just print stack trace and leave original ex to be thrown |
try { | try { | ||||
this.loopDetector = blockStore.getChainLoopDetector(); | this.loopDetector = blockStore.getChainLoopDetector(); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
try { | try { | ||||
this.loopDetector = blockStore.getChainLoopDetector(); | this.loopDetector = blockStore.getChainLoopDetector(); | ||||
} catch(IOException e) { | } catch(IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
nextBlock = blockStore.getNextBlock(nextBlock); | nextBlock = blockStore.getNextBlock(nextBlock); | ||||
return data; | return data; | ||||
} catch(IOException e) { | } catch(IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
tempFile = TempFile.createTempFile("poifs", ".tmp"); | tempFile = TempFile.createTempFile("poifs", ".tmp"); | ||||
_data = new FileBackedDataSource(tempFile, false); | _data = new FileBackedDataSource(tempFile, false); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException("Failed to create data source", e); | |||||
throw new IllegalStateException("Failed to create data source", e); | |||||
} | } | ||||
} | } | ||||
try { | try { | ||||
return (Graphics)clone(); | return (Graphics)clone(); | ||||
} catch (CloneNotSupportedException e){ | } catch (CloneNotSupportedException e){ | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} catch (IOException | XMLStreamException e){ | } catch (IOException | XMLStreamException e){ | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
return new SimpleFraction((int)p1, (int)q1); | return new SimpleFraction((int)p1, (int)q1); | ||||
} | } | ||||
if ((p2 > overflow) || (q2 > overflow)) { | if ((p2 > overflow) || (q2 > overflow)) { | ||||
throw new RuntimeException("Overflow trying to convert "+value+" to fraction ("+p2+"/"+q2+")"); | |||||
throw new IllegalStateException("Overflow trying to convert "+value+" to fraction ("+p2+"/"+q2+")"); | |||||
} | } | ||||
double convergent = (double)p2 / (double)q2; | double convergent = (double)p2 / (double)q2; | ||||
} while (!stop); | } while (!stop); | ||||
if (n >= maxIterations) { | if (n >= maxIterations) { | ||||
throw new RuntimeException("Unable to convert "+value+" to fraction after "+maxIterations+" iterations"); | |||||
throw new IllegalStateException("Unable to convert "+value+" to fraction after "+maxIterations+" iterations"); | |||||
} | } | ||||
if (q2 < maxDenominator) { | if (q2 < maxDenominator) { |
for (WorkbookEvaluator evaluator : evaluators) { | for (WorkbookEvaluator evaluator : evaluators) { | ||||
if (evalListener != evaluator.getEvaluationListener()) { | if (evalListener != evaluator.getEvaluationListener()) { | ||||
// This would be very complex to support | // This would be very complex to support | ||||
throw new RuntimeException("Workbook evaluators must all have the same evaluation listener"); | |||||
throw new IllegalStateException("Workbook evaluators must all have the same evaluation listener"); | |||||
} | } | ||||
} | } | ||||
EvaluationCache cache = new EvaluationCache(evalListener); | EvaluationCache cache = new EvaluationCache(evalListener); |
} | } | ||||
/** Read New Character From Input Stream */ | /** Read New Character From Input Stream */ | ||||
private void GetChar() { | |||||
private void nextChar() { | |||||
// The intersection operator is a space. We track whether the run of | // The intersection operator is a space. We track whether the run of | ||||
// whitespace preceding "look" counts as an intersection operator. | // whitespace preceding "look" counts as an intersection operator. | ||||
if (IsWhite(look)) { | |||||
if (isWhite(look)) { | |||||
if (look == ' ') { | if (look == ' ') { | ||||
_inIntersection = true; | _inIntersection = true; | ||||
} | } | ||||
// Check to see if we've walked off the end of the string. | // Check to see if we've walked off the end of the string. | ||||
if (_pointer > _formulaLength) { | if (_pointer > _formulaLength) { | ||||
throw new RuntimeException("Parsed past the end of the formula, pos: " + _pointer + | |||||
throw new IllegalStateException("Parsed past the end of the formula, pos: " + _pointer + | |||||
", length: " + _formulaLength + ", formula: " + _formulaString); | ", length: " + _formulaLength + ", formula: " + _formulaString); | ||||
} | } | ||||
if (_pointer < _formulaLength) { | if (_pointer < _formulaLength) { | ||||
} | } | ||||
/** Recognize an Alpha Character */ | /** Recognize an Alpha Character */ | ||||
private static boolean IsAlpha(int c) { | |||||
private static boolean isAlpha(int c) { | |||||
return Character.isLetter(c) || c == '$' || c=='_'; | return Character.isLetter(c) || c == '$' || c=='_'; | ||||
} | } | ||||
/** Recognize a Decimal Digit */ | /** Recognize a Decimal Digit */ | ||||
private static boolean IsDigit(int c) { | |||||
private static boolean isDigit(int c) { | |||||
return Character.isDigit(c); | return Character.isDigit(c); | ||||
} | } | ||||
/** Recognize White Space */ | /** Recognize White Space */ | ||||
private static boolean IsWhite(int c) { | |||||
private static boolean isWhite(int c) { | |||||
return c ==' ' || c== TAB || c == CR || c == LF; | return c ==' ' || c== TAB || c == CR || c == LF; | ||||
} | } | ||||
/** Skip Over Leading White Space */ | /** Skip Over Leading White Space */ | ||||
private void SkipWhite() { | |||||
while (IsWhite(look)) { | |||||
GetChar(); | |||||
private void skipWhite() { | |||||
while (isWhite(look)) { | |||||
nextChar(); | |||||
} | } | ||||
} | } | ||||
* unchecked exception. This method does <b>not</b> consume whitespace (before or after the | * unchecked exception. This method does <b>not</b> consume whitespace (before or after the | ||||
* matched character). | * matched character). | ||||
*/ | */ | ||||
private void Match(int x) { | |||||
private void match(int x) { | |||||
if (look != x) { | if (look != x) { | ||||
throw expected(new StringBuilder() | throw expected(new StringBuilder() | ||||
.append("'") | .append("'") | ||||
.append("'") | .append("'") | ||||
.toString()); | .toString()); | ||||
} | } | ||||
GetChar(); | |||||
nextChar(); | |||||
} | } | ||||
/** Get a Number */ | /** Get a Number */ | ||||
private String GetNum() { | |||||
private String nextNum() { | |||||
StringBuilder value = new StringBuilder(); | StringBuilder value = new StringBuilder(); | ||||
while (IsDigit(this.look)){ | |||||
while (isDigit(this.look)){ | |||||
value.appendCodePoint(this.look); | value.appendCodePoint(this.look); | ||||
GetChar(); | |||||
nextChar(); | |||||
} | } | ||||
return value.length() == 0 ? null : value.toString(); | return value.length() == 0 ? null : value.toString(); | ||||
} | } | ||||
boolean hasRange = false; | boolean hasRange = false; | ||||
while (look == ':') { | while (look == ':') { | ||||
int pos = _pointer; | int pos = _pointer; | ||||
GetChar(); | |||||
nextChar(); | |||||
ParseNode nextPart = parseRangeable(); | ParseNode nextPart = parseRangeable(); | ||||
// Note - no range simplification here. An expr like "A1:B2:C3:D4:E5" should be | // Note - no range simplification here. An expr like "A1:B2:C3:D4:E5" should be | ||||
// grouped into area ref pairs like: "(A1:B2):(C3:D4):E5" | // grouped into area ref pairs like: "(A1:B2):(C3:D4):E5" | ||||
* | * | ||||
*/ | */ | ||||
private ParseNode parseRangeable() { | private ParseNode parseRangeable() { | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
int savePointer = _pointer; | int savePointer = _pointer; | ||||
SheetIdentifier sheetIden = parseSheetName(false); | SheetIdentifier sheetIden = parseSheetName(false); | ||||
if (sheetIden == null) { | if (sheetIden == null) { | ||||
resetPointer(savePointer); | resetPointer(savePointer); | ||||
} else { | } else { | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
savePointer = _pointer; | savePointer = _pointer; | ||||
} | } | ||||
} | } | ||||
return parseNonRange(savePointer); | return parseNonRange(savePointer); | ||||
} | } | ||||
boolean whiteAfterPart1 = IsWhite(look); | |||||
boolean whiteAfterPart1 = isWhite(look); | |||||
if (whiteAfterPart1) { | if (whiteAfterPart1) { | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
} | } | ||||
if (look == ':') { | if (look == ':') { | ||||
int colonPos = _pointer; | int colonPos = _pointer; | ||||
GetChar(); | |||||
SkipWhite(); | |||||
nextChar(); | |||||
skipWhite(); | |||||
SimpleRangePart part2 = parseSimpleRangePart(); | SimpleRangePart part2 = parseSimpleRangePart(); | ||||
if (part2 != null && !part1.isCompatibleForArea(part2)) { | if (part2 != null && !part1.isCompatibleForArea(part2)) { | ||||
// second part is not compatible with an area ref e.g. S!A1:S!B2 | // second part is not compatible with an area ref e.g. S!A1:S!B2 | ||||
} | } | ||||
if (look == '.') { | if (look == '.') { | ||||
GetChar(); | |||||
nextChar(); | |||||
int dotCount = 1; | int dotCount = 1; | ||||
while (look =='.') { | while (look =='.') { | ||||
dotCount ++; | dotCount ++; | ||||
GetChar(); | |||||
nextChar(); | |||||
} | } | ||||
boolean whiteBeforePart2 = IsWhite(look); | |||||
boolean whiteBeforePart2 = isWhite(look); | |||||
SkipWhite(); | |||||
skipWhite(); | |||||
SimpleRangePart part2 = parseSimpleRangePart(); | SimpleRangePart part2 = parseSimpleRangePart(); | ||||
String part1And2 = _formulaString.substring(savePointer-1, _pointer-1); | String part1And2 = _formulaString.substring(savePointer-1, _pointer-1); | ||||
if (part2 == null) { | if (part2 == null) { | ||||
// Do NOT return before done reading all the structured reference tokens from the input stream. | // Do NOT return before done reading all the structured reference tokens from the input stream. | ||||
// Throwing exceptions is okay. | // Throwing exceptions is okay. | ||||
int savePtr0 = _pointer; | int savePtr0 = _pointer; | ||||
GetChar(); | |||||
nextChar(); | |||||
boolean isTotalsSpec = false; | boolean isTotalsSpec = false; | ||||
boolean isThisRowSpec = false; | boolean isThisRowSpec = false; | ||||
} | } | ||||
nSpecQuantifiers++; | nSpecQuantifiers++; | ||||
if (look == ','){ | if (look == ','){ | ||||
GetChar(); | |||||
nextChar(); | |||||
} else { | } else { | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
boolean isThisRow = false; | boolean isThisRow = false; | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
if (look == '@') { | if (look == '@') { | ||||
isThisRow = true; | isThisRow = true; | ||||
GetChar(); | |||||
nextChar(); | |||||
} | } | ||||
// parse column quantifier | // parse column quantifier | ||||
String endColumnName = null; | String endColumnName = null; | ||||
if (look == ','){ | if (look == ','){ | ||||
throw new FormulaParseException("The formula "+ _formulaString + " is illegal: you should not use ',' with column quantifiers"); | throw new FormulaParseException("The formula "+ _formulaString + " is illegal: you should not use ',' with column quantifiers"); | ||||
} else if (look == ':') { | } else if (look == ':') { | ||||
GetChar(); | |||||
nextChar(); | |||||
endColumnName = parseAsColumnQuantifier(); | endColumnName = parseAsColumnQuantifier(); | ||||
nColQuantifiers++; | nColQuantifiers++; | ||||
if (endColumnName == null) { | if (endColumnName == null) { | ||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
Match(']'); | |||||
match(']'); | |||||
} | } | ||||
// Done reading from input stream | // Done reading from input stream | ||||
// Ok to return now | // Ok to return now | ||||
if ( look != '[') { | if ( look != '[') { | ||||
return null; | return null; | ||||
} | } | ||||
GetChar(); | |||||
nextChar(); | |||||
if (look == '#') { | if (look == '#') { | ||||
return null; | return null; | ||||
} | } | ||||
if (look == '@') { | if (look == '@') { | ||||
GetChar(); | |||||
nextChar(); | |||||
} | } | ||||
StringBuilder name = new StringBuilder(); | StringBuilder name = new StringBuilder(); | ||||
while (look!=']') { | while (look!=']') { | ||||
name.appendCodePoint(look); | name.appendCodePoint(look); | ||||
GetChar(); | |||||
nextChar(); | |||||
} | } | ||||
Match(']'); | |||||
match(']'); | |||||
return name.toString(); | return name.toString(); | ||||
} | } | ||||
/** | /** | ||||
if ( look != '[') { | if ( look != '[') { | ||||
return null; | return null; | ||||
} | } | ||||
GetChar(); | |||||
nextChar(); | |||||
if( look != '#') { | if( look != '#') { | ||||
return null; | return null; | ||||
} | } | ||||
GetChar(); | |||||
nextChar(); | |||||
String name = parseAsName(); | String name = parseAsName(); | ||||
if ( name.equals("This")) { | if ( name.equals("This")) { | ||||
name = name + ' ' + parseAsName(); | name = name + ' ' + parseAsName(); | ||||
} | } | ||||
Match(']'); | |||||
match(']'); | |||||
return name; | return name; | ||||
} | } | ||||
} | } | ||||
while (isValidDefinedNameChar(look)) { | while (isValidDefinedNameChar(look)) { | ||||
sb.appendCodePoint(look); | sb.appendCodePoint(look); | ||||
GetChar(); | |||||
nextChar(); | |||||
} | } | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
return sb.toString(); | return sb.toString(); | ||||
} | } | ||||
private String getBookName() { | private String getBookName() { | ||||
StringBuilder sb = new StringBuilder(); | StringBuilder sb = new StringBuilder(); | ||||
GetChar(); | |||||
nextChar(); | |||||
while (look != ']') { | while (look != ']') { | ||||
sb.appendCodePoint(look); | sb.appendCodePoint(look); | ||||
GetChar(); | |||||
nextChar(); | |||||
} | } | ||||
GetChar(); | |||||
nextChar(); | |||||
return sb.toString(); | return sb.toString(); | ||||
} | } | ||||
if (look == '\'' || isSndPartOfQuotedRange) { | if (look == '\'' || isSndPartOfQuotedRange) { | ||||
if (!isSndPartOfQuotedRange) { | if (!isSndPartOfQuotedRange) { | ||||
Match('\''); | |||||
match('\''); | |||||
} | } | ||||
if (look == '[') | if (look == '[') | ||||
boolean done = look == '\''; | boolean done = look == '\''; | ||||
while(!done) { | while(!done) { | ||||
sb.appendCodePoint(look); | sb.appendCodePoint(look); | ||||
GetChar(); | |||||
nextChar(); | |||||
switch (look){ | switch (look){ | ||||
case '\'' : { | case '\'' : { | ||||
GetChar(); | |||||
nextChar(); | |||||
if (look == '\''){ | if (look == '\''){ | ||||
// Any single quotes which were already present in the sheet name will be converted to double single quotes ('') | // Any single quotes which were already present in the sheet name will be converted to double single quotes ('') | ||||
// so switch back to single quote | // so switch back to single quote | ||||
GetChar(); | |||||
nextChar(); | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
NameIdentifier iden = new NameIdentifier(sb.toString(), true); | NameIdentifier iden = new NameIdentifier(sb.toString(), true); | ||||
// quoted identifier - can't concatenate anything more | // quoted identifier - can't concatenate anything more | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
if (look == '!') { | if (look == '!') { | ||||
GetChar(); | |||||
nextChar(); | |||||
return new SheetIdentifier(bookName, iden); | return new SheetIdentifier(bookName, iden); | ||||
} | } | ||||
// See if it's a multi-sheet range, eg Sheet1:Sheet3!A1 | // See if it's a multi-sheet range, eg Sheet1:Sheet3!A1 | ||||
// can concatenate idens with dots | // can concatenate idens with dots | ||||
while (isUnquotedSheetNameChar(look)) { | while (isUnquotedSheetNameChar(look)) { | ||||
sb.appendCodePoint(look); | sb.appendCodePoint(look); | ||||
GetChar(); | |||||
nextChar(); | |||||
} | } | ||||
if (look == '\'') { | if (look == '\'') { | ||||
GetChar(); | |||||
nextChar(); | |||||
} | } | ||||
NameIdentifier iden = new NameIdentifier(sb.toString(), false); | NameIdentifier iden = new NameIdentifier(sb.toString(), false); | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
if (look == '!') { | if (look == '!') { | ||||
GetChar(); | |||||
nextChar(); | |||||
return new SheetIdentifier(bookName, iden); | return new SheetIdentifier(bookName, iden); | ||||
} | } | ||||
// See if it's a multi-sheet range, eg Sheet1:Sheet3!A1 | // See if it's a multi-sheet range, eg Sheet1:Sheet3!A1 | ||||
} | } | ||||
if (look == '!' && bookName != null) { | if (look == '!' && bookName != null) { | ||||
// Raw book reference, without a sheet | // Raw book reference, without a sheet | ||||
GetChar(); | |||||
nextChar(); | |||||
return new SheetIdentifier(bookName, null); | return new SheetIdentifier(bookName, null); | ||||
} | } | ||||
return null; | return null; | ||||
* Sheet1, see if it's actually a range eg Sheet1:Sheet2! | * Sheet1, see if it's actually a range eg Sheet1:Sheet2! | ||||
*/ | */ | ||||
private SheetIdentifier parseSheetRange(String bookname, NameIdentifier sheet1Name, boolean isSndPartOfQuotedRange) { | private SheetIdentifier parseSheetRange(String bookname, NameIdentifier sheet1Name, boolean isSndPartOfQuotedRange) { | ||||
GetChar(); | |||||
nextChar(); | |||||
SheetIdentifier sheet2 = parseSheetName(isSndPartOfQuotedRange); | SheetIdentifier sheet2 = parseSheetName(isSndPartOfQuotedRange); | ||||
if (sheet2 != null) { | if (sheet2 != null) { | ||||
return new SheetRangeIdentifier(bookname, sheet1Name, sheet2.getSheetIdentifier()); | return new SheetRangeIdentifier(bookname, sheet1Name, sheet2.getSheetIdentifier()); | ||||
if(isFunc){ | if(isFunc){ | ||||
int savePointer = _pointer; | int savePointer = _pointer; | ||||
resetPointer(_pointer + str.length()); | resetPointer(_pointer + str.length()); | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
// open bracket indicates that the argument is a function, | // open bracket indicates that the argument is a function, | ||||
// the returning value should be false, i.e. "not a valid cell reference" | // the returning value should be false, i.e. "not a valid cell reference" | ||||
result = look != '('; | result = look != '('; | ||||
} | } | ||||
} | } | ||||
Match('('); | |||||
match('('); | |||||
ParseNode[] args = Arguments(); | ParseNode[] args = Arguments(); | ||||
Match(')'); | |||||
match(')'); | |||||
return getFunction(name, nameToken, args); | return getFunction(name, nameToken, args); | ||||
} | } | ||||
private ParseNode[] Arguments() { | private ParseNode[] Arguments() { | ||||
//average 2 args per function | //average 2 args per function | ||||
List<ParseNode> temp = new ArrayList<>(2); | List<ParseNode> temp = new ArrayList<>(2); | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
if(look == ')') { | if(look == ')') { | ||||
return ParseNode.EMPTY_ARRAY; | return ParseNode.EMPTY_ARRAY; | ||||
} | } | ||||
boolean missedPrevArg = true; | boolean missedPrevArg = true; | ||||
while (true) { | while (true) { | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
if (isArgumentDelimiter(look)) { | if (isArgumentDelimiter(look)) { | ||||
if (missedPrevArg) { | if (missedPrevArg) { | ||||
temp.add(new ParseNode(MissingArgPtg.instance)); | temp.add(new ParseNode(MissingArgPtg.instance)); | ||||
if (look == ')') { | if (look == ')') { | ||||
break; | break; | ||||
} | } | ||||
Match(','); | |||||
match(','); | |||||
missedPrevArg = true; | missedPrevArg = true; | ||||
continue; | continue; | ||||
} | } | ||||
temp.add(intersectionExpression()); | temp.add(intersectionExpression()); | ||||
missedPrevArg = false; | missedPrevArg = false; | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
if (!isArgumentDelimiter(look)) { | if (!isArgumentDelimiter(look)) { | ||||
throw expected("',' or ')'"); | throw expected("',' or ')'"); | ||||
} | } | ||||
private ParseNode powerFactor() { | private ParseNode powerFactor() { | ||||
ParseNode result = percentFactor(); | ParseNode result = percentFactor(); | ||||
while(true) { | while(true) { | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
if(look != '^') { | if(look != '^') { | ||||
return result; | return result; | ||||
} | } | ||||
Match('^'); | |||||
match('^'); | |||||
ParseNode other = percentFactor(); | ParseNode other = percentFactor(); | ||||
result = new ParseNode(PowerPtg.instance, result, other); | result = new ParseNode(PowerPtg.instance, result, other); | ||||
} | } | ||||
private ParseNode percentFactor() { | private ParseNode percentFactor() { | ||||
ParseNode result = parseSimpleFactor(); | ParseNode result = parseSimpleFactor(); | ||||
while(true) { | while(true) { | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
if(look != '%') { | if(look != '%') { | ||||
return result; | return result; | ||||
} | } | ||||
Match('%'); | |||||
match('%'); | |||||
result = new ParseNode(PercentPtg.instance, result); | result = new ParseNode(PercentPtg.instance, result); | ||||
} | } | ||||
} | } | ||||
* factors (without ^ or % ) | * factors (without ^ or % ) | ||||
*/ | */ | ||||
private ParseNode parseSimpleFactor() { | private ParseNode parseSimpleFactor() { | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
switch(look) { | switch(look) { | ||||
case '#': | case '#': | ||||
return new ParseNode(ErrPtg.valueOf(parseErrorLiteral())); | return new ParseNode(ErrPtg.valueOf(parseErrorLiteral())); | ||||
case '-': | case '-': | ||||
Match('-'); | |||||
match('-'); | |||||
return parseUnary(false); | return parseUnary(false); | ||||
case '+': | case '+': | ||||
Match('+'); | |||||
match('+'); | |||||
return parseUnary(true); | return parseUnary(true); | ||||
case '(': | case '(': | ||||
Match('('); | |||||
match('('); | |||||
ParseNode inside = unionExpression(); | ParseNode inside = unionExpression(); | ||||
Match(')'); | |||||
match(')'); | |||||
return new ParseNode(ParenthesisPtg.instance, inside); | return new ParseNode(ParenthesisPtg.instance, inside); | ||||
case '"': | case '"': | ||||
return new ParseNode(new StringPtg(parseStringLiteral())); | return new ParseNode(new StringPtg(parseStringLiteral())); | ||||
case '{': | case '{': | ||||
Match('{'); | |||||
match('{'); | |||||
ParseNode arrayNode = parseArray(); | ParseNode arrayNode = parseArray(); | ||||
Match('}'); | |||||
match('}'); | |||||
return arrayNode; | return arrayNode; | ||||
} | } | ||||
// named ranges and tables can start with underscore or backslash | // named ranges and tables can start with underscore or backslash | ||||
// see https://support.office.com/en-us/article/Define-and-use-names-in-formulas-4d0f13ac-53b7-422e-afd2-abd7ff379c64?ui=en-US&rs=en-US&ad=US#bmsyntax_rules_for_names | // see https://support.office.com/en-us/article/Define-and-use-names-in-formulas-4d0f13ac-53b7-422e-afd2-abd7ff379c64?ui=en-US&rs=en-US&ad=US#bmsyntax_rules_for_names | ||||
if (IsAlpha(look) || Character.isDigit(look) || look == '\'' || look == '[' || look == '_' || look == '\\' ) { | |||||
if (isAlpha(look) || Character.isDigit(look) || look == '\'' || look == '[' || look == '_' || look == '\\' ) { | |||||
return parseRangeExpression(); | return parseRangeExpression(); | ||||
} | } | ||||
if (look == '.') { | if (look == '.') { | ||||
private ParseNode parseUnary(boolean isPlus) { | private ParseNode parseUnary(boolean isPlus) { | ||||
boolean numberFollows = IsDigit(look) || look=='.'; | |||||
boolean numberFollows = isDigit(look) || look=='.'; | |||||
ParseNode factor = powerFactor(); | ParseNode factor = powerFactor(); | ||||
if (numberFollows) { | if (numberFollows) { | ||||
if (look != ';') { | if (look != ';') { | ||||
throw expected("'}' or ';'"); | throw expected("'}' or ';'"); | ||||
} | } | ||||
Match(';'); | |||||
match(';'); | |||||
} | } | ||||
int nRows = rowsData.size(); | int nRows = rowsData.size(); | ||||
Object[][] values2d = new Object[nRows][]; | Object[][] values2d = new Object[nRows][]; | ||||
List<Object> temp = new ArrayList<>(); | List<Object> temp = new ArrayList<>(); | ||||
while (true) { | while (true) { | ||||
temp.add(parseArrayItem()); | temp.add(parseArrayItem()); | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
switch(look) { | switch(look) { | ||||
case '}': | case '}': | ||||
case ';': | case ';': | ||||
break; | break; | ||||
case ',': | case ',': | ||||
Match(','); | |||||
match(','); | |||||
continue; | continue; | ||||
default: | default: | ||||
throw expected("'}' or ','"); | throw expected("'}' or ','"); | ||||
} | } | ||||
private Object parseArrayItem() { | private Object parseArrayItem() { | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
switch(look) { | switch(look) { | ||||
case '"': return parseStringLiteral(); | case '"': return parseStringLiteral(); | ||||
case '#': return ErrorConstant.valueOf(parseErrorLiteral()); | case '#': return ErrorConstant.valueOf(parseErrorLiteral()); | ||||
case 'T': case 't': | case 'T': case 't': | ||||
return parseBooleanLiteral(); | return parseBooleanLiteral(); | ||||
case '-': | case '-': | ||||
Match('-'); | |||||
SkipWhite(); | |||||
match('-'); | |||||
skipWhite(); | |||||
return convertArrayNumber(parseNumber(), false); | return convertArrayNumber(parseNumber(), false); | ||||
} | } | ||||
// else assume number | // else assume number | ||||
} else if (ptg instanceof NumberPtg) { | } else if (ptg instanceof NumberPtg) { | ||||
value = ((NumberPtg)ptg).getValue(); | value = ((NumberPtg)ptg).getValue(); | ||||
} else { | } else { | ||||
throw new RuntimeException("Unexpected ptg (" + ptg.getClass().getName() + ")"); | |||||
throw new IllegalStateException("Unexpected ptg (" + ptg.getClass().getName() + ")"); | |||||
} | } | ||||
if (!isPositive) { | if (!isPositive) { | ||||
value = -value; | value = -value; | ||||
private Ptg parseNumber() { | private Ptg parseNumber() { | ||||
String number2 = null; | String number2 = null; | ||||
String exponent = null; | String exponent = null; | ||||
String number1 = GetNum(); | |||||
String number1 = nextNum(); | |||||
if (look == '.') { | if (look == '.') { | ||||
GetChar(); | |||||
number2 = GetNum(); | |||||
nextChar(); | |||||
number2 = nextNum(); | |||||
} | } | ||||
if (look == 'E') { | if (look == 'E') { | ||||
GetChar(); | |||||
nextChar(); | |||||
String sign = ""; | String sign = ""; | ||||
if (look == '+') { | if (look == '+') { | ||||
GetChar(); | |||||
nextChar(); | |||||
} else if (look == '-') { | } else if (look == '-') { | ||||
GetChar(); | |||||
nextChar(); | |||||
sign = "-"; | sign = "-"; | ||||
} | } | ||||
String number = GetNum(); | |||||
String number = nextNum(); | |||||
if (number == null) { | if (number == null) { | ||||
throw expected("Integer"); | throw expected("Integer"); | ||||
} | } | ||||
private int parseErrorLiteral() { | private int parseErrorLiteral() { | ||||
Match('#'); | |||||
match('#'); | |||||
String part1 = parseUnquotedIdentifier(); | String part1 = parseUnquotedIdentifier(); | ||||
if (part1 == null) { | if (part1 == null) { | ||||
throw expected("remainder of error constant literal"); | throw expected("remainder of error constant literal"); | ||||
case 'V': { | case 'V': { | ||||
FormulaError fe = FormulaError.VALUE; | FormulaError fe = FormulaError.VALUE; | ||||
if(part1.equals(fe.name())) { | if(part1.equals(fe.name())) { | ||||
Match('!'); | |||||
match('!'); | |||||
return fe.getCode(); | return fe.getCode(); | ||||
} | } | ||||
throw expected(fe.getString()); | throw expected(fe.getString()); | ||||
case 'R': { | case 'R': { | ||||
FormulaError fe = FormulaError.REF; | FormulaError fe = FormulaError.REF; | ||||
if(part1.equals(fe.name())) { | if(part1.equals(fe.name())) { | ||||
Match('!'); | |||||
match('!'); | |||||
return fe.getCode(); | return fe.getCode(); | ||||
} | } | ||||
throw expected(fe.getString()); | throw expected(fe.getString()); | ||||
case 'D': { | case 'D': { | ||||
FormulaError fe = FormulaError.DIV0; | FormulaError fe = FormulaError.DIV0; | ||||
if(part1.equals("DIV")) { | if(part1.equals("DIV")) { | ||||
Match('/'); | |||||
Match('0'); | |||||
Match('!'); | |||||
match('/'); | |||||
match('0'); | |||||
match('!'); | |||||
return fe.getCode(); | return fe.getCode(); | ||||
} | } | ||||
throw expected(fe.getString()); | throw expected(fe.getString()); | ||||
FormulaError fe = FormulaError.NAME; | FormulaError fe = FormulaError.NAME; | ||||
if(part1.equals(fe.name())) { | if(part1.equals(fe.name())) { | ||||
// only one that ends in '?' | // only one that ends in '?' | ||||
Match('?'); | |||||
match('?'); | |||||
return fe.getCode(); | return fe.getCode(); | ||||
} | } | ||||
fe = FormulaError.NUM; | fe = FormulaError.NUM; | ||||
if(part1.equals(fe.name())) { | if(part1.equals(fe.name())) { | ||||
Match('!'); | |||||
match('!'); | |||||
return fe.getCode(); | return fe.getCode(); | ||||
} | } | ||||
fe = FormulaError.NULL; | fe = FormulaError.NULL; | ||||
if(part1.equals(fe.name())) { | if(part1.equals(fe.name())) { | ||||
Match('!'); | |||||
match('!'); | |||||
return fe.getCode(); | return fe.getCode(); | ||||
} | } | ||||
fe = FormulaError.NA; | fe = FormulaError.NA; | ||||
if(part1.equals("N")) { | if(part1.equals("N")) { | ||||
Match('/'); | |||||
match('/'); | |||||
if(look != 'A' && look != 'a') { | if(look != 'A' && look != 'a') { | ||||
throw expected(fe.getString()); | throw expected(fe.getString()); | ||||
} | } | ||||
Match(look); | |||||
match(look); | |||||
// Note - no '!' or '?' suffix | // Note - no '!' or '?' suffix | ||||
return fe.getCode(); | return fe.getCode(); | ||||
} | } | ||||
StringBuilder sb = new StringBuilder(); | StringBuilder sb = new StringBuilder(); | ||||
while (Character.isLetterOrDigit(look) || look == '.') { | while (Character.isLetterOrDigit(look) || look == '.') { | ||||
sb.appendCodePoint(look); | sb.appendCodePoint(look); | ||||
GetChar(); | |||||
nextChar(); | |||||
} | } | ||||
if (sb.length() < 1) { | if (sb.length() < 1) { | ||||
return null; | return null; | ||||
private String parseStringLiteral() { | private String parseStringLiteral() { | ||||
Match('"'); | |||||
match('"'); | |||||
StringBuilder token = new StringBuilder(); | StringBuilder token = new StringBuilder(); | ||||
while (true) { | while (true) { | ||||
if (look == '"') { | if (look == '"') { | ||||
GetChar(); | |||||
nextChar(); | |||||
if (look != '"') { | if (look != '"') { | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
token.appendCodePoint(look); | token.appendCodePoint(look); | ||||
GetChar(); | |||||
nextChar(); | |||||
} | } | ||||
return token.toString(); | return token.toString(); | ||||
} | } | ||||
private ParseNode Term() { | private ParseNode Term() { | ||||
ParseNode result = powerFactor(); | ParseNode result = powerFactor(); | ||||
while(true) { | while(true) { | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
Ptg operator; | Ptg operator; | ||||
switch(look) { | switch(look) { | ||||
case '*': | case '*': | ||||
Match('*'); | |||||
match('*'); | |||||
operator = MultiplyPtg.instance; | operator = MultiplyPtg.instance; | ||||
break; | break; | ||||
case '/': | case '/': | ||||
Match('/'); | |||||
match('/'); | |||||
operator = DividePtg.instance; | operator = DividePtg.instance; | ||||
break; | break; | ||||
default: | default: | ||||
ParseNode result = intersectionExpression(); | ParseNode result = intersectionExpression(); | ||||
boolean hasUnions = false; | boolean hasUnions = false; | ||||
while (true) { | while (true) { | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
if (look == ',') { | if (look == ',') { | ||||
GetChar(); | |||||
nextChar(); | |||||
hasUnions = true; | hasUnions = true; | ||||
ParseNode other = intersectionExpression(); | ParseNode other = intersectionExpression(); | ||||
result = new ParseNode(UnionPtg.instance, result, other); | result = new ParseNode(UnionPtg.instance, result, other); | ||||
ParseNode result = comparisonExpression(); | ParseNode result = comparisonExpression(); | ||||
boolean hasIntersections = false; | boolean hasIntersections = false; | ||||
while (true) { | while (true) { | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
if (_inIntersection) { | if (_inIntersection) { | ||||
int savePointer = _pointer; | int savePointer = _pointer; | ||||
private ParseNode comparisonExpression() { | private ParseNode comparisonExpression() { | ||||
ParseNode result = concatExpression(); | ParseNode result = concatExpression(); | ||||
while (true) { | while (true) { | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
switch(look) { | switch(look) { | ||||
case '=': | case '=': | ||||
case '>': | case '>': | ||||
private Ptg getComparisonToken() { | private Ptg getComparisonToken() { | ||||
if(look == '=') { | if(look == '=') { | ||||
Match(look); | |||||
match(look); | |||||
return EqualPtg.instance; | return EqualPtg.instance; | ||||
} | } | ||||
boolean isGreater = look == '>'; | boolean isGreater = look == '>'; | ||||
Match(look); | |||||
match(look); | |||||
if(isGreater) { | if(isGreater) { | ||||
if(look == '=') { | if(look == '=') { | ||||
Match('='); | |||||
match('='); | |||||
return GreaterEqualPtg.instance; | return GreaterEqualPtg.instance; | ||||
} | } | ||||
return GreaterThanPtg.instance; | return GreaterThanPtg.instance; | ||||
} | } | ||||
switch(look) { | switch(look) { | ||||
case '=': | case '=': | ||||
Match('='); | |||||
match('='); | |||||
return LessEqualPtg.instance; | return LessEqualPtg.instance; | ||||
case '>': | case '>': | ||||
Match('>'); | |||||
match('>'); | |||||
return NotEqualPtg.instance; | return NotEqualPtg.instance; | ||||
} | } | ||||
return LessThanPtg.instance; | return LessThanPtg.instance; | ||||
private ParseNode concatExpression() { | private ParseNode concatExpression() { | ||||
ParseNode result = additiveExpression(); | ParseNode result = additiveExpression(); | ||||
while (true) { | while (true) { | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
if(look != '&') { | if(look != '&') { | ||||
break; // finished with concat expression | break; // finished with concat expression | ||||
} | } | ||||
Match('&'); | |||||
match('&'); | |||||
ParseNode other = additiveExpression(); | ParseNode other = additiveExpression(); | ||||
result = new ParseNode(ConcatPtg.instance, result, other); | result = new ParseNode(ConcatPtg.instance, result, other); | ||||
} | } | ||||
private ParseNode additiveExpression() { | private ParseNode additiveExpression() { | ||||
ParseNode result = Term(); | ParseNode result = Term(); | ||||
while (true) { | while (true) { | ||||
SkipWhite(); | |||||
skipWhite(); | |||||
Ptg operator; | Ptg operator; | ||||
switch(look) { | switch(look) { | ||||
case '+': | case '+': | ||||
Match('+'); | |||||
match('+'); | |||||
operator = AddPtg.instance; | operator = AddPtg.instance; | ||||
break; | break; | ||||
case '-': | case '-': | ||||
Match('-'); | |||||
match('-'); | |||||
operator = SubtractPtg.instance; | operator = SubtractPtg.instance; | ||||
break; | break; | ||||
default: | default: | ||||
*/ | */ | ||||
private void parse() { | private void parse() { | ||||
_pointer=0; | _pointer=0; | ||||
GetChar(); | |||||
nextChar(); | |||||
_rootNode = unionExpression(); | _rootNode = unionExpression(); | ||||
if(_pointer <= _formulaLength) { | if(_pointer <= _formulaLength) { |
stack.push(attrPtg.toFormulaString(operands)); | stack.push(attrPtg.toFormulaString(operands)); | ||||
continue; | continue; | ||||
} | } | ||||
throw new RuntimeException("Unexpected tAttr: " + attrPtg); | |||||
throw new IllegalStateException("Unexpected tAttr: " + attrPtg); | |||||
} | } | ||||
if (ptg instanceof WorkbookDependentFormula) { | if (ptg instanceof WorkbookDependentFormula) { |
rootNodeOperandClass = Ptg.CLASS_REF; | rootNodeOperandClass = Ptg.CLASS_REF; | ||||
break; | break; | ||||
default: | default: | ||||
throw new RuntimeException("Incomplete code - formula type (" | |||||
throw new IllegalStateException("Incomplete code - formula type (" | |||||
+ _formulaType + ") not supported yet"); | + _formulaType + ") not supported yet"); | ||||
} | } |
try { | try { | ||||
targetEvaluator = _bookEvaluator.getOtherWorkbookEvaluator(workbookName); | targetEvaluator = _bookEvaluator.getOtherWorkbookEvaluator(workbookName); | ||||
} catch (WorkbookNotFoundException e) { | } catch (WorkbookNotFoundException e) { | ||||
throw new RuntimeException(e.getMessage(), e); | |||||
throw new IllegalStateException(e.getMessage(), e); | |||||
} | } | ||||
otherFirstSheetIndex = targetEvaluator.getSheetIndex(externalSheet.getSheetName()); | otherFirstSheetIndex = targetEvaluator.getSheetIndex(externalSheet.getSheetName()); | ||||
} | } | ||||
if (otherFirstSheetIndex < 0) { | if (otherFirstSheetIndex < 0) { | ||||
throw new RuntimeException("Invalid sheet name '" + externalSheet.getSheetName() | |||||
throw new IllegalStateException("Invalid sheet name '" + externalSheet.getSheetName() | |||||
+ "' in bool '" + workbookName + "'."); | + "' in bool '" + workbookName + "'."); | ||||
} | } | ||||
} | } | ||||
case NAMED_RANGE: | case NAMED_RANGE: | ||||
EvaluationName nm = _workbook.getName(refStrPart1, _sheetIndex); | EvaluationName nm = _workbook.getName(refStrPart1, _sheetIndex); | ||||
if (nm == null) { | if (nm == null) { | ||||
throw new RuntimeException("Specified name '" + refStrPart1 + | |||||
throw new IllegalStateException("Specified name '" + refStrPart1 + | |||||
"' is not found in the workbook (sheetIndex=" + _sheetIndex + ")."); | "' is not found in the workbook (sheetIndex=" + _sheetIndex + ")."); | ||||
} | } | ||||
if (!nm.isRange()) { | if (!nm.isRange()) { | ||||
throw new RuntimeException("Specified name '" + refStrPart1 + "' is not a range as expected."); | |||||
throw new IllegalStateException("Specified name '" + refStrPart1 + "' is not a range as expected."); | |||||
} | } | ||||
return _bookEvaluator.evaluateNameFormula(nm.getNameDefinition(), this); | return _bookEvaluator.evaluateNameFormula(nm.getNameDefinition(), this); | ||||
} | } | ||||
case BAD_CELL_OR_NAMED_RANGE: | case BAD_CELL_OR_NAMED_RANGE: | ||||
return ErrorEval.REF_INVALID; | return ErrorEval.REF_INVALID; | ||||
case NAMED_RANGE: | case NAMED_RANGE: | ||||
throw new RuntimeException("Cannot evaluate '" + refStrPart1 | |||||
throw new IllegalStateException("Cannot evaluate '" + refStrPart1 | |||||
+ "'. Indirect evaluation of defined names not supported yet"); | + "'. Indirect evaluation of defined names not supported yet"); | ||||
} | } | ||||
private ValueEval convertObjectEval(Object token) { | private ValueEval convertObjectEval(Object token) { | ||||
if (token == null) { | if (token == null) { | ||||
throw new RuntimeException("Array item cannot be null"); | |||||
throw new IllegalStateException("Array item cannot be null"); | |||||
} | } | ||||
if (token instanceof String) { | if (token instanceof String) { | ||||
return new StringEval((String) token); | return new StringEval((String) token); | ||||
EvaluationName evaluationName = refWorkbookEvaluator.getName(externName.getName(), externName.getIx() - 1); | EvaluationName evaluationName = refWorkbookEvaluator.getName(externName.getName(), externName.getIx() - 1); | ||||
if (evaluationName != null && evaluationName.hasFormula()) { | if (evaluationName != null && evaluationName.hasFormula()) { | ||||
if (evaluationName.getNameDefinition().length > 1) { | if (evaluationName.getNameDefinition().length > 1) { | ||||
throw new RuntimeException("Complex name formulas not supported yet"); | |||||
throw new IllegalStateException("Complex name formulas not supported yet"); | |||||
} | } | ||||
// Need to evaluate the reference in the context of the other book | // Need to evaluate the reference in the context of the other book |
return udfFunc.evaluate(args, ec); | return udfFunc.evaluate(args, ec); | ||||
} | } | ||||
throw new RuntimeException("Unexpected operation ptg class (" + ptg.getClass().getName() + ")"); | |||||
throw new IllegalStateException("Unexpected operation ptg class (" + ptg.getClass().getName() + ")"); | |||||
} | } | ||||
static ValueEval evaluateArrayFunction(ArrayFunction func, ValueEval[] args, | static ValueEval evaluateArrayFunction(ArrayFunction func, ValueEval[] args, |
appendAndEscape(out, rawSheetName); | appendAndEscape(out, rawSheetName); | ||||
} | } | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
appendOrREF(out, rawSheetName); | appendOrREF(out, rawSheetName); | ||||
} | } | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
sb.append(ch); | sb.append(ch); | ||||
} | } | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
case '\n': | case '\n': | ||||
case '\r': | case '\r': | ||||
case '\t': | case '\t': | ||||
throw new RuntimeException("Illegal character (0x" | |||||
throw new IllegalStateException("Illegal character (0x" | |||||
+ Integer.toHexString(ch) + ") found in sheet name"); | + Integer.toHexString(ch) + ") found in sheet name"); | ||||
} | } | ||||
return true; | return true; |
// enforce singleton | // enforce singleton | ||||
} | } | ||||
/** | |||||
* @param args the pre-evaluated arguments for this function. args is never {@code null}, | |||||
* nor are any of its elements. | |||||
* @param ec primarily used to identify the source cell containing the formula being evaluated. | |||||
* may also be used to dynamically create reference evals. | |||||
* @return value | |||||
* @throws IllegalStateException if first arg is not a {@link FunctionNameEval} | |||||
* @throws NotImplementedFunctionException if function is not implemented | |||||
*/ | |||||
@Override | @Override | ||||
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { | public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) { | ||||
int nIncomingArgs = args.length; | int nIncomingArgs = args.length; | ||||
if(nIncomingArgs < 1) { | |||||
throw new RuntimeException("function name argument missing"); | |||||
if (nIncomingArgs < 1) { | |||||
throw new IllegalStateException("function name argument missing"); | |||||
} | } | ||||
ValueEval nameArg = args[0]; | ValueEval nameArg = args[0]; | ||||
if (nameArg instanceof FunctionNameEval) { | if (nameArg instanceof FunctionNameEval) { | ||||
functionName = ((FunctionNameEval) nameArg).getFunctionName(); | functionName = ((FunctionNameEval) nameArg).getFunctionName(); | ||||
} else { | } else { | ||||
throw new RuntimeException("First argument should be a NameEval, but got (" | |||||
throw new IllegalStateException("First argument should be a NameEval, but got (" | |||||
+ nameArg.getClass().getName() + ")"); | + nameArg.getClass().getName() + ")"); | ||||
} | } | ||||
FreeRefFunction targetFunc = ec.findUserDefinedFunction(functionName); | FreeRefFunction targetFunc = ec.findUserDefinedFunction(functionName); |
if (result == null) { | if (result == null) { | ||||
int sheetIndex = _workbook.getSheetIndex(sheet); | int sheetIndex = _workbook.getSheetIndex(sheet); | ||||
if (sheetIndex < 0) { | if (sheetIndex < 0) { | ||||
throw new RuntimeException("Specified sheet from a different book"); | |||||
throw new IllegalStateException("Specified sheet from a different book"); | |||||
} | } | ||||
result = sheetIndex; | result = sheetIndex; | ||||
_sheetIndexesBySheet.put(sheet, result); | _sheetIndexesBySheet.put(sheet, result); | ||||
break; | break; | ||||
case FORMULA: | case FORMULA: | ||||
default: | default: | ||||
throw new RuntimeException("Unexpected cell type '" + srcCell.getCellType() + "' found!"); | |||||
throw new IllegalStateException("Unexpected cell type '" + srcCell.getCellType() + "' found!"); | |||||
} | } | ||||
} else { | } else { | ||||
throw re; | throw re; | ||||
case ERROR: | case ERROR: | ||||
return ErrorEval.valueOf(cell.getErrorCellValue()); | return ErrorEval.valueOf(cell.getErrorCellValue()); | ||||
default: | default: | ||||
throw new RuntimeException("Unexpected cell type (" + cellType + ")"); | |||||
throw new IllegalStateException("Unexpected cell type (" + cellType + ")"); | |||||
} | } | ||||
} | } | ||||
opResult = getEvalForPtg(ptg, ec); | opResult = getEvalForPtg(ptg, ec); | ||||
} | } | ||||
if (opResult == null) { | if (opResult == null) { | ||||
throw new RuntimeException("Evaluation result must not be null"); | |||||
throw new IllegalStateException("Evaluation result must not be null"); | |||||
} | } | ||||
// logDebug("push " + opResult); | // logDebug("push " + opResult); | ||||
stack.push(opResult); | stack.push(opResult); | ||||
while (remBytes != 0) { | while (remBytes != 0) { | ||||
index++; | index++; | ||||
if (index >= ptgs.length) { | if (index >= ptgs.length) { | ||||
throw new RuntimeException("Skip distance too far (ran out of formula tokens)."); | |||||
throw new IllegalStateException("Skip distance too far (ran out of formula tokens)."); | |||||
} | } | ||||
remBytes -= ptgs[index].getSize(); | remBytes -= ptgs[index].getSize(); | ||||
if (remBytes < 0) { | if (remBytes < 0) { | ||||
throw new RuntimeException("Bad skip distance (wrong token size calculation)."); | |||||
throw new IllegalStateException("Bad skip distance (wrong token size calculation)."); | |||||
} | } | ||||
} | } | ||||
return index - startIndex; | return index - startIndex; | ||||
// POI uses UnknownPtg when the encoded Ptg array seems to be corrupted. | // POI uses UnknownPtg when the encoded Ptg array seems to be corrupted. | ||||
// This seems to occur in very rare cases (e.g. unused name formulas in bug 44774, attachment 21790) | // This seems to occur in very rare cases (e.g. unused name formulas in bug 44774, attachment 21790) | ||||
// In any case, formulas are re-parsed before execution, so UnknownPtg should not get here | // In any case, formulas are re-parsed before execution, so UnknownPtg should not get here | ||||
throw new RuntimeException("UnknownPtg not allowed"); | |||||
throw new IllegalStateException("UnknownPtg not allowed"); | |||||
} | } | ||||
if (ptg instanceof ExpPtg) { | if (ptg instanceof ExpPtg) { | ||||
// ExpPtg is used for array formulas and shared formulas. | // ExpPtg is used for array formulas and shared formulas. | ||||
// it is currently unsupported, and may not even get implemented here | // it is currently unsupported, and may not even get implemented here | ||||
throw new RuntimeException("ExpPtg currently not supported"); | |||||
throw new IllegalStateException("ExpPtg currently not supported"); | |||||
} | } | ||||
throw new RuntimeException("Unexpected ptg class (" + ptg.getClass().getName() + ")"); | |||||
throw new IllegalStateException("Unexpected ptg class (" + ptg.getClass().getName() + ")"); | |||||
} | } | ||||
private ValueEval processNameEval(ValueEval eval, OperationEvaluationContext ec) { | private ValueEval processNameEval(ValueEval eval, OperationEvaluationContext ec) { | ||||
return evaluateNameFormula(nameRecord.getNameDefinition(), ec); | return evaluateNameFormula(nameRecord.getNameDefinition(), ec); | ||||
} | } | ||||
throw new RuntimeException("Don't know how to evaluate name '" + nameRecord.getNameText() + "'"); | |||||
throw new IllegalStateException("Don't know how to evaluate name '" + nameRecord.getNameText() + "'"); | |||||
} | } | ||||
/** | /** |
case 23: // transition from daylight savings adjusted to normal time | case 23: // transition from daylight savings adjusted to normal time | ||||
// Unexpected since we are using UTC_TIME_ZONE | // Unexpected since we are using UTC_TIME_ZONE | ||||
default: | default: | ||||
throw new RuntimeException("Unexpected date diff between " + startDateMS + " and " + endDateMS); | |||||
throw new IllegalStateException("Unexpected date diff between " + startDateMS + " and " + endDateMS); | |||||
} | } | ||||
return (int) (0.5 + ((double)msDiff / MS_PER_DAY)); | return (int) (0.5 + ((double)msDiff / MS_PER_DAY)); |
if (eval != null) { | if (eval != null) { | ||||
return eval; | return eval; | ||||
} else { | } else { | ||||
throw new RuntimeException("Unhandled error type for code " + errorCode); | |||||
throw new IllegalStateException("Unhandled error type for code " + errorCode); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
return dd; | return dd; | ||||
} | } | ||||
throw new RuntimeException("Unexpected arg eval type (" + ev.getClass().getName() + ")"); | |||||
throw new IllegalStateException("Unexpected arg eval type (" + ev.getClass().getName() + ")"); | |||||
} | } | ||||
/** | /** | ||||
if (ve instanceof ErrorEval) { | if (ve instanceof ErrorEval) { | ||||
throw new EvaluationException((ErrorEval) ve); | throw new EvaluationException((ErrorEval) ve); | ||||
} | } | ||||
throw new RuntimeException("Unexpected eval (" + ve.getClass().getName() + ")"); | |||||
throw new IllegalStateException("Unexpected eval (" + ve.getClass().getName() + ")"); | |||||
} | } | ||||
} | } |
private void checkCellType(CellType expectedCellType) { | private void checkCellType(CellType expectedCellType) { | ||||
if (_cellType != expectedCellType) { | if (_cellType != expectedCellType) { | ||||
throw new RuntimeException("Wrong data type (" + _cellType + ")"); | |||||
throw new IllegalStateException("Wrong data type (" + _cellType + ")"); | |||||
} | } | ||||
} | } | ||||
public Ptg[] getFormulaTokens(EvaluationCell cell) { | public Ptg[] getFormulaTokens(EvaluationCell cell) { | ||||
if (cell instanceof ForkedEvaluationCell) { | if (cell instanceof ForkedEvaluationCell) { | ||||
// doesn't happen yet because formulas cannot be modified from the master workbook | // doesn't happen yet because formulas cannot be modified from the master workbook | ||||
throw new RuntimeException("Updated formulas not supported yet"); | |||||
throw new IllegalStateException("Updated formulas not supported yet"); | |||||
} | } | ||||
return _masterBook.getFormulaTokens(cell); | return _masterBook.getFormulaTokens(cell); | ||||
} | } |
prevFM = _functionDataByName.get(functionName); | prevFM = _functionDataByName.get(functionName); | ||||
if(prevFM != null) { | if(prevFM != null) { | ||||
if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) { | if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) { | ||||
throw new RuntimeException("Multiple entries for function name '" + functionName + "'"); | |||||
throw new IllegalStateException("Multiple entries for function name '" + functionName + "'"); | |||||
} | } | ||||
_functionDataByIndex.remove(prevFM.getIndex()); | _functionDataByIndex.remove(prevFM.getIndex()); | ||||
} | } | ||||
prevFM = _functionDataByIndex.get(indexKey); | prevFM = _functionDataByIndex.get(indexKey); | ||||
if(prevFM != null) { | if(prevFM != null) { | ||||
if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) { | if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) { | ||||
throw new RuntimeException("Multiple entries for function index (" + functionIndex + ")"); | |||||
throw new IllegalStateException("Multiple entries for function index (" + functionIndex + ")"); | |||||
} | } | ||||
_functionDataByName.remove(prevFM.getName()); | _functionDataByName.remove(prevFM.getName()); | ||||
} | } |
private static void readResourceFile(FunctionDataBuilder fdb, String resourceFile) { | private static void readResourceFile(FunctionDataBuilder fdb, String resourceFile) { | ||||
try (InputStream is = FunctionMetadataReader.class.getResourceAsStream(resourceFile)) { | try (InputStream is = FunctionMetadataReader.class.getResourceAsStream(resourceFile)) { | ||||
if (is == null) { | if (is == null) { | ||||
throw new RuntimeException("resource '" + resourceFile + "' not found"); | |||||
throw new IllegalStateException("resource '" + resourceFile + "' not found"); | |||||
} | } | ||||
try(BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { | try(BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { | ||||
} | } | ||||
} | } | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
String[] parts = TAB_DELIM_PATTERN.split(line, -2); | String[] parts = TAB_DELIM_PATTERN.split(line, -2); | ||||
if(parts.length != 8) { | if(parts.length != 8) { | ||||
throw new RuntimeException("Bad line format '" + line + "' - expected 8 data fields delimited by tab, " + | |||||
throw new IllegalStateException("Bad line format '" + line + "' - expected 8 data fields delimited by tab, " + | |||||
"but had " + parts.length + ": " + Arrays.toString(parts)); | "but had " + parts.length + ": " + Arrays.toString(parts)); | ||||
} | } | ||||
int functionIndex = parseInt(parts[0]); | int functionIndex = parseInt(parts[0]); | ||||
private static byte parseOperandTypeCode(String code) { | private static byte parseOperandTypeCode(String code) { | ||||
if(code.length() != 1) { | if(code.length() != 1) { | ||||
throw new RuntimeException("Bad operand type code format '" + code + "' expected single char"); | |||||
throw new IllegalStateException("Bad operand type code format '" + code + "' expected single char"); | |||||
} | } | ||||
switch(code.charAt(0)) { | switch(code.charAt(0)) { | ||||
case 'V': return Ptg.CLASS_VALUE; | case 'V': return Ptg.CLASS_VALUE; | ||||
if(DIGIT_ENDING_FUNCTION_NAMES_SET.contains(functionName)) { | if(DIGIT_ENDING_FUNCTION_NAMES_SET.contains(functionName)) { | ||||
return; | return; | ||||
} | } | ||||
throw new RuntimeException("Invalid function name '" + functionName | |||||
throw new IllegalStateException("Invalid function name '" + functionName | |||||
+ "' (is footnote number incorrectly appended)"); | + "' (is footnote number incorrectly appended)"); | ||||
} | } | ||||
try { | try { | ||||
return Integer.parseInt(valStr); | return Integer.parseInt(valStr); | ||||
} catch (NumberFormatException e) { | } catch (NumberFormatException e) { | ||||
throw new RuntimeException("Value '" + valStr + "' could not be parsed as an integer"); | |||||
throw new IllegalStateException("Value '" + valStr + "' could not be parsed as an integer"); | |||||
} | } | ||||
} | } | ||||
} | } |
if (ve == BlankEval.instance) { | if (ve == BlankEval.instance) { | ||||
return null; | return null; | ||||
} | } | ||||
throw new RuntimeException("Invalid ValueEval type passed for conversion: (" | |||||
throw new IllegalStateException("Invalid ValueEval type passed for conversion: (" | |||||
+ ve.getClass() + ")"); | + ve.getClass() + ")"); | ||||
} | } | ||||
case NE: | case NE: | ||||
return !cmpResult; | return !cmpResult; | ||||
} | } | ||||
throw new RuntimeException("Cannot call boolean evaluate on non-equality operator '" | |||||
throw new IllegalStateException("Cannot call boolean evaluate on non-equality operator '" | |||||
+ _representation + "'"); | + _representation + "'"); | ||||
} | } | ||||
public boolean evaluate(int cmpResult) { | public boolean evaluate(int cmpResult) { | ||||
case GT: return cmpResult > 0; | case GT: return cmpResult > 0; | ||||
case GE: return cmpResult >= 0; | case GE: return cmpResult >= 0; | ||||
} | } | ||||
throw new RuntimeException("Cannot call boolean evaluate on non-equality operator '" | |||||
throw new IllegalStateException("Cannot call boolean evaluate on non-equality operator '" | |||||
+ _representation + "'"); | + _representation + "'"); | ||||
} | } | ||||
@Override | @Override | ||||
if(evaluatedCriteriaArg == BlankEval.instance) { | if(evaluatedCriteriaArg == BlankEval.instance) { | ||||
return null; | return null; | ||||
} | } | ||||
throw new RuntimeException("Unexpected type for criteria (" | |||||
throw new IllegalStateException("Unexpected type for criteria (" | |||||
+ evaluatedCriteriaArg.getClass().getName() + ")"); | + evaluatedCriteriaArg.getClass().getName() + ")"); | ||||
} | } | ||||
@Override | @Override | ||||
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, | public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1, | ||||
ValueEval arg2, ValueEval arg3) { | ValueEval arg2, ValueEval arg3) { | ||||
throw new RuntimeException("Incomplete code" | |||||
throw new IllegalStateException("Incomplete code" | |||||
+ " - don't know how to support the 'area_num' parameter yet)"); | + " - don't know how to support the 'area_num' parameter yet)"); | ||||
// Excel expression might look like this "INDEX( (A1:B4, C3:D6, D2:E5 ), 1, 2, 3) | // Excel expression might look like this "INDEX( (A1:B4, C3:D6, D2:E5 ), 1, 2, 3) | ||||
// In this example, the 3rd area would be used i.e. D2:E5, and the overall result would be E2 | // In this example, the 3rd area would be used i.e. D2:E5, and the overall result would be E2 | ||||
} | } | ||||
// else the other variation of this function takes an array as the first argument | // else the other variation of this function takes an array as the first argument | ||||
// it seems like interface 'ArrayEval' does not even exist yet | // it seems like interface 'ArrayEval' does not even exist yet | ||||
throw new RuntimeException("Incomplete code - cannot handle first arg of type (" | |||||
throw new IllegalStateException("Incomplete code - cannot handle first arg of type (" | |||||
+ arg0.getClass().getName() + ")"); | + arg0.getClass().getName() + ")"); | ||||
} | } |
ValueVector resultVector = createVector(aeResultVector); | ValueVector resultVector = createVector(aeResultVector); | ||||
if(lookupVector.getSize() > resultVector.getSize()) { | if(lookupVector.getSize() > resultVector.getSize()) { | ||||
// Excel seems to handle this by accessing past the end of the result vector. | // Excel seems to handle this by accessing past the end of the result vector. | ||||
throw new RuntimeException("Lookup vector and result vector of differing sizes not supported yet"); | |||||
throw new IllegalStateException("Lookup vector and result vector of differing sizes not supported yet"); | |||||
} | } | ||||
int index = LookupUtils.lookupFirstIndexOfValue(lookupValue, lookupVector, true); | int index = LookupUtils.lookupFirstIndexOfValue(lookupValue, lookupVector, true); | ||||
return result; | return result; | ||||
} | } | ||||
// extra complexity required to emulate the way LOOKUP can handles these abnormal cases. | // extra complexity required to emulate the way LOOKUP can handles these abnormal cases. | ||||
throw new RuntimeException("non-vector lookup or result areas not supported yet"); | |||||
throw new IllegalStateException("non-vector lookup or result areas not supported yet"); | |||||
} | } | ||||
} | } |
private final Class<? extends ValueEval> _targetClass; | private final Class<? extends ValueEval> _targetClass; | ||||
protected LookupValueComparerBase(ValueEval targetValue) { | protected LookupValueComparerBase(ValueEval targetValue) { | ||||
if(targetValue == null) { | if(targetValue == null) { | ||||
throw new RuntimeException("targetValue cannot be null"); | |||||
throw new IllegalStateException("targetValue cannot be null"); | |||||
} | } | ||||
_targetClass = targetValue.getClass(); | _targetClass = targetValue.getClass(); | ||||
} | } | ||||
@Override | @Override | ||||
public final CompareResult compareTo(ValueEval other) { | public final CompareResult compareTo(ValueEval other) { | ||||
if (other == null) { | if (other == null) { | ||||
throw new RuntimeException("compare to value cannot be null"); | |||||
throw new IllegalStateException("compare to value cannot be null"); | |||||
} | } | ||||
if (_targetClass != other.getClass()) { | if (_targetClass != other.getClass()) { | ||||
return CompareResult.TYPE_MISMATCH; | return CompareResult.TYPE_MISMATCH; | ||||
// zero is FALSE, everything else is TRUE | // zero is FALSE, everything else is TRUE | ||||
return 0.0 != nve.getNumberValue(); | return 0.0 != nve.getNumberValue(); | ||||
} | } | ||||
throw new RuntimeException("Unexpected eval type (" + valEval + ")"); | |||||
throw new IllegalStateException("Unexpected eval type (" + valEval + ")"); | |||||
} | } | ||||
public static int lookupFirstIndexOfValue(ValueEval lookupValue, ValueVector vector, boolean isRangeLookup) throws EvaluationException { | public static int lookupFirstIndexOfValue(ValueEval lookupValue, ValueVector vector, boolean isRangeLookup) throws EvaluationException { |
@Override | @Override | ||||
public ValueEval getItem(int index) { | public ValueEval getItem(int index) { | ||||
if (index != 0) { | if (index != 0) { | ||||
throw new RuntimeException("Invalid index (" | |||||
throw new IllegalStateException("Invalid index (" | |||||
+ index + ") only zero is allowed"); | + index + ") only zero is allowed"); | ||||
} | } | ||||
return _value; | return _value; | ||||
// else looks like a number | // else looks like a number | ||||
throw new EvaluationException(ErrorEval.NA); | throw new EvaluationException(ErrorEval.NA); | ||||
} | } | ||||
throw new RuntimeException("Unexpected eval type (" + eval + ")"); | |||||
throw new IllegalStateException("Unexpected eval type (" + eval + ")"); | |||||
} | } | ||||
// uses the default-value instead | // uses the default-value instead | ||||
return 1; | return 1; | ||||
} | } | ||||
throw new RuntimeException("Unexpected match_type type (" + match_type.getClass().getName() + ")"); | |||||
throw new IllegalStateException("Unexpected match_type type (" + match_type.getClass().getName() + ")"); | |||||
} | } | ||||
/** | /** |
temp.add(Double.valueOf(((NumberEval) arg).getNumberValue())); | temp.add(Double.valueOf(((NumberEval) arg).getNumberValue())); | ||||
return; | return; | ||||
} | } | ||||
throw new RuntimeException("Unexpected value type (" + arg.getClass().getName() + ")"); | |||||
throw new IllegalStateException("Unexpected value type (" + arg.getClass().getName() + ")"); | |||||
} | } | ||||
} | } |
missingArgConsumer.accept((MissingArgEval) ve, temp); | missingArgConsumer.accept((MissingArgEval) ve, temp); | ||||
return; | return; | ||||
} | } | ||||
throw new RuntimeException("Invalid ValueEval type passed for conversion: (" | |||||
throw new IllegalStateException("Invalid ValueEval type passed for conversion: (" | |||||
+ ve.getClass() + ")"); | + ve.getClass() + ")"); | ||||
} | } | ||||
public LinearOffsetRange(int offset, int length) { | public LinearOffsetRange(int offset, int length) { | ||||
if(length == 0) { | if(length == 0) { | ||||
// handled that condition much earlier | // handled that condition much earlier | ||||
throw new RuntimeException("length may not be zero"); | |||||
throw new IllegalStateException("length may not be zero"); | |||||
} | } | ||||
_offset = offset; | _offset = offset; | ||||
_length = length; | _length = length; |
} catch (EvaluationException e) { | } catch (EvaluationException e) { | ||||
return e.getErrorEval(); | return e.getErrorEval(); | ||||
} | } | ||||
throw new RuntimeException("Invalid arg type for SUMPRODUCT: (" | |||||
throw new IllegalStateException("Invalid arg type for SUMPRODUCT: (" | |||||
+ firstArg.getClass().getName() + ")"); | + firstArg.getClass().getName() + ")"); | ||||
} | } | ||||
} | } | ||||
if (eval == null) { | if (eval == null) { | ||||
throw new RuntimeException("parameter may not be null"); | |||||
throw new IllegalStateException("parameter may not be null"); | |||||
} | } | ||||
if (eval instanceof AreaEval) { | if (eval instanceof AreaEval) { | ||||
AreaEval ae = (AreaEval) eval; | AreaEval ae = (AreaEval) eval; | ||||
NumericValueEval nve = (NumericValueEval) ve; | NumericValueEval nve = (NumericValueEval) ve; | ||||
return nve.getNumberValue(); | return nve.getNumberValue(); | ||||
} | } | ||||
throw new RuntimeException("Unexpected value eval class (" | |||||
throw new IllegalStateException("Unexpected value eval class (" | |||||
+ ve.getClass().getName() + ")"); | + ve.getClass().getName() + ")"); | ||||
} | } | ||||
} | } |
eval = arg; | eval = arg; | ||||
} | } | ||||
if (eval == null) { | if (eval == null) { | ||||
throw new RuntimeException("Parameter may not be null."); | |||||
throw new IllegalStateException("Parameter may not be null."); | |||||
} | } | ||||
if (eval instanceof AreaEval) { | if (eval instanceof AreaEval) { |
protected AbstractFunctionPtg(int functionIndex, int pReturnClass, byte[] paramTypes, int nParams) { | protected AbstractFunctionPtg(int functionIndex, int pReturnClass, byte[] paramTypes, int nParams) { | ||||
_numberOfArgs = nParams; | _numberOfArgs = nParams; | ||||
if (functionIndex < Short.MIN_VALUE || functionIndex > Short.MAX_VALUE) | if (functionIndex < Short.MIN_VALUE || functionIndex > Short.MAX_VALUE) | ||||
throw new RuntimeException("functionIndex " + functionIndex + " cannot be cast to short"); | |||||
throw new IllegalStateException("functionIndex " + functionIndex + " cannot be cast to short"); | |||||
_functionIndex = (short) functionIndex; | _functionIndex = (short) functionIndex; | ||||
if (pReturnClass < Byte.MIN_VALUE || pReturnClass > Byte.MAX_VALUE) | if (pReturnClass < Byte.MIN_VALUE || pReturnClass > Byte.MAX_VALUE) | ||||
throw new RuntimeException("pReturnClass " + pReturnClass + " cannot be cast to byte"); | |||||
throw new IllegalStateException("pReturnClass " + pReturnClass + " cannot be cast to byte"); | |||||
returnClass = (byte) pReturnClass; | returnClass = (byte) pReturnClass; | ||||
paramClass = paramTypes; | paramClass = paramTypes; | ||||
} | } | ||||
fm = FunctionMetadataRegistry.getFunctionByIndex(index); | fm = FunctionMetadataRegistry.getFunctionByIndex(index); | ||||
} | } | ||||
if(fm == null) { | if(fm == null) { | ||||
throw new RuntimeException("bad function index (" + index + ", " + isCetab + ")"); | |||||
throw new IllegalStateException("bad function index (" + index + ", " + isCetab + ")"); | |||||
} | } | ||||
return fm.getName(); | return fm.getName(); | ||||
} | } |
@Override | @Override | ||||
public String toFormulaString() { | public String toFormulaString() { | ||||
throw new RuntimeException("3D references need a workbook to determine formula text"); | |||||
throw new IllegalStateException("3D references need a workbook to determine formula text"); | |||||
} | } | ||||
@Override | @Override |
private static String getConstantText(Object o) { | private static String getConstantText(Object o) { | ||||
if (o == null) { | if (o == null) { | ||||
throw new RuntimeException("Array item cannot be null"); | |||||
throw new IllegalStateException("Array item cannot be null"); | |||||
} | } | ||||
if (o instanceof String) { | if (o instanceof String) { | ||||
return "\"" + o + "\""; | return "\"" + o + "\""; |
return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet, FormulaError.REF.getString()); | return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet, FormulaError.REF.getString()); | ||||
} | } | ||||
public String toFormulaString() { | public String toFormulaString() { | ||||
throw new RuntimeException("3D references need a workbook to determine formula text"); | |||||
throw new IllegalStateException("3D references need a workbook to determine formula text"); | |||||
} | } | ||||
@Override | @Override | ||||
public byte getDefaultOperandClass() { | public byte getDefaultOperandClass() { |
return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet, FormulaError.REF.getString()); | return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet, FormulaError.REF.getString()); | ||||
} | } | ||||
public String toFormulaString() { | public String toFormulaString() { | ||||
throw new RuntimeException("3D references need a workbook to determine formula text"); | |||||
throw new IllegalStateException("3D references need a workbook to determine formula text"); | |||||
} | } | ||||
@Override | @Override | ||||
public byte getDefaultOperandClass() { | public byte getDefaultOperandClass() { |
case REF: return REF_INVALID; | case REF: return REF_INVALID; | ||||
case VALUE: return VALUE_INVALID; | case VALUE: return VALUE_INVALID; | ||||
default: | default: | ||||
throw new RuntimeException("Unexpected error code (" + code + ")"); | |||||
throw new IllegalStateException("Unexpected error code (" + code + ")"); | |||||
} | } | ||||
} | } | ||||
@Override | @Override | ||||
public String toFormulaString() { | public String toFormulaString() { | ||||
throw new RuntimeException("Coding Error: Expected ExpPtg to be converted from Shared to Non-Shared Formula by ValueRecordsAggregate, but it wasn't"); | |||||
throw new IllegalStateException("Coding Error: Expected ExpPtg to be converted from Shared to Non-Shared Formula by ValueRecordsAggregate, but it wasn't"); | |||||
} | } | ||||
@Override | @Override |
public static FuncPtg create(int functionIndex) { | public static FuncPtg create(int functionIndex) { | ||||
FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByIndex(functionIndex); | FunctionMetadata fm = FunctionMetadataRegistry.getFunctionByIndex(functionIndex); | ||||
if(fm == null) { | if(fm == null) { | ||||
throw new RuntimeException("Invalid built-in function index (" + functionIndex + ")"); | |||||
throw new IllegalStateException("Invalid built-in function index (" + functionIndex + ")"); | |||||
} | } | ||||
return new FuncPtg(functionIndex, fm); | return new FuncPtg(functionIndex, fm); | ||||
} | } |
@Override | @Override | ||||
public String toFormulaString() { | public String toFormulaString() { | ||||
throw new RuntimeException("3D references need a workbook to determine formula text"); | |||||
throw new IllegalStateException("3D references need a workbook to determine formula text"); | |||||
} | } | ||||
@Override | @Override |
return book.resolveNameXText(this); | return book.resolveNameXText(this); | ||||
} | } | ||||
public String toFormulaString() { | public String toFormulaString() { | ||||
throw new RuntimeException("3D references need a workbook to determine formula text"); | |||||
throw new IllegalStateException("3D references need a workbook to determine formula text"); | |||||
} | } | ||||
@Override | @Override |
return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet, formatReferenceAsString()); | return ExternSheetNameResolver.prependSheetName(book, field_1_index_extern_sheet, formatReferenceAsString()); | ||||
} | } | ||||
public String toFormulaString() { | public String toFormulaString() { | ||||
throw new RuntimeException("3D references need a workbook to determine formula text"); | |||||
throw new IllegalStateException("3D references need a workbook to determine formula text"); | |||||
} | } | ||||
@Override | @Override |
public String toFormulaString() | public String toFormulaString() | ||||
{ | { | ||||
// table(....)[][] | // table(....)[][] | ||||
throw new RuntimeException("Table and Arrays are not yet supported"); | |||||
throw new IllegalStateException("Table and Arrays are not yet supported"); | |||||
} | } | ||||
@Override | @Override |
@Override | @Override | ||||
public final String toFormulaString() { | public final String toFormulaString() { | ||||
// TODO - prune this method out of the hierarchy | // TODO - prune this method out of the hierarchy | ||||
throw new RuntimeException("toFormulaString(String[] operands) should be used for subclasses of OperationPtgs"); | |||||
throw new IllegalStateException("toFormulaString(String[] operands) should be used for subclasses of OperationPtgs"); | |||||
} | } | ||||
} | } |
case ERROR: | case ERROR: | ||||
return FormulaError.forInt(cell.getErrorCellValue()).getString(); | return FormulaError.forInt(cell.getErrorCellValue()).getString(); | ||||
default: | default: | ||||
throw new RuntimeException("Unexpected celltype (" + cellType + ")"); | |||||
throw new IllegalStateException("Unexpected celltype (" + cellType + ")"); | |||||
} | } | ||||
} | } | ||||
String part1 = parts[1]; | String part1 = parts[1]; | ||||
if (isPlainColumn(part0)) { | if (isPlainColumn(part0)) { | ||||
if (!isPlainColumn(part1)) { | if (!isPlainColumn(part1)) { | ||||
throw new RuntimeException("Bad area ref '" + reference + "'"); | |||||
throw new IllegalStateException("Bad area ref '" + reference + "'"); | |||||
} | } | ||||
// Special handling for whole-column references | // Special handling for whole-column references | ||||
// Represented internally as x$1 to x$65536 | // Represented internally as x$1 to x$65536 | ||||
// TODO - are references like "Sheet1!A1:Sheet1:B2" ever valid? | // TODO - are references like "Sheet1!A1:Sheet1:B2" ever valid? | ||||
// FormulaParser has code to handle that. | // FormulaParser has code to handle that. | ||||
throw new RuntimeException("Unexpected " + SHEET_NAME_DELIMITER | |||||
throw new IllegalStateException("Unexpected " + SHEET_NAME_DELIMITER | |||||
+ " in second cell reference of '" + reference + "'"); | + " in second cell reference of '" + reference + "'"); | ||||
} | } | ||||
} | } | ||||
public CellRangeAddress remove(int rangeIndex) { | public CellRangeAddress remove(int rangeIndex) { | ||||
if (_list.isEmpty()) { | if (_list.isEmpty()) { | ||||
throw new RuntimeException("List is empty"); | |||||
throw new IllegalStateException("List is empty"); | |||||
} | } | ||||
if (rangeIndex < 0 || rangeIndex >= _list.size()) { | if (rangeIndex < 0 || rangeIndex >= _list.size()) { | ||||
throw new RuntimeException("Range index (" + rangeIndex | |||||
throw new IllegalStateException("Range index (" + rangeIndex | |||||
+ ") is outside allowable range (0.." + (_list.size()-1) + ")"); | + ") is outside allowable range (0.." + (_list.size()-1) + ")"); | ||||
} | } | ||||
return _list.remove(rangeIndex); | return _list.remove(rangeIndex); |
// range2 encloses range1, so replace it with the enclosing one | // range2 encloses range1, so replace it with the enclosing one | ||||
return new CellRangeAddress[] { range2 }; | return new CellRangeAddress[] { range2 }; | ||||
} | } | ||||
throw new RuntimeException("unexpected intersection result (" + x + ")"); | |||||
throw new IllegalStateException("unexpected intersection result (" + x + ")"); | |||||
} | } | ||||
private static CellRangeAddress[] toArray(List<CellRangeAddress> temp) { | private static CellRangeAddress[] toArray(List<CellRangeAddress> temp) { |
NormalisedDecimal rnd = pnd.roundUnits(); | NormalisedDecimal rnd = pnd.roundUnits(); | ||||
int decExponent = rnd.getDecimalExponent(); | int decExponent = rnd.getDecimalExponent(); | ||||
String decimalDigits; | String decimalDigits; | ||||
if (Math.abs(decExponent)>98) { | |||||
if (Math.abs(decExponent) > 98) { | |||||
decimalDigits = rnd.getSignificantDecimalDigitsLastDigitRounded(); | decimalDigits = rnd.getSignificantDecimalDigitsLastDigitRounded(); | ||||
if (decimalDigits.length() == 16) { | if (decimalDigits.length() == 16) { | ||||
// rounding caused carry | // rounding caused carry | ||||
} else { | } else { | ||||
decimalDigits = rnd.getSignificantDecimalDigits(); | decimalDigits = rnd.getSignificantDecimalDigits(); | ||||
} | } | ||||
int countSigDigits = countSignifantDigits(decimalDigits); | |||||
int countSigDigits = countSignificantDigits(decimalDigits); | |||||
if (decExponent < 0) { | if (decExponent < 0) { | ||||
formatLessThanOne(sb, decimalDigits, decExponent, countSigDigits); | formatLessThanOne(sb, decimalDigits, decExponent, countSigDigits); | ||||
} else { | } else { | ||||
return nDigits > MAX_TEXT_LEN; | return nDigits > MAX_TEXT_LEN; | ||||
} | } | ||||
private static int countSignifantDigits(String sb) { | |||||
int result=sb.length()-1; | |||||
private static int countSignificantDigits(String sb) { | |||||
int result = sb.length()-1; | |||||
while(sb.charAt(result) == '0') { | while(sb.charAt(result) == '0') { | ||||
result--; | result--; | ||||
if(result < 0) { | |||||
throw new RuntimeException("No non-zero digits found"); | |||||
if (result < 0) { | |||||
throw new IllegalStateException("No non-zero digits found"); | |||||
} | } | ||||
} | } | ||||
return result + 1; | return result + 1; |
try { | try { | ||||
return readData(new ByteArrayInputStream( data.getBytes(StringUtil.UTF8) ), -1); | return readData(new ByteArrayInputStream( data.getBytes(StringUtil.UTF8) ), -1); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
public static long copy(InputStream srcStream, File destFile) throws IOException { | public static long copy(InputStream srcStream, File destFile) throws IOException { | ||||
File destDirectory = destFile.getParentFile(); | File destDirectory = destFile.getParentFile(); | ||||
if (!(destDirectory.exists() || destDirectory.mkdirs())) { | if (!(destDirectory.exists() || destDirectory.mkdirs())) { | ||||
throw new RuntimeException("Can't create destination directory: "+destDirectory); | |||||
throw new IllegalStateException("Can't create destination directory: "+destDirectory); | |||||
} | } | ||||
try (OutputStream destStream = new FileOutputStream(destFile)) { | try (OutputStream destStream = new FileOutputStream(destFile)) { | ||||
return IOUtils.copy(srcStream, destStream); | return IOUtils.copy(srcStream, destStream); |
private void checkPosition(int i) { | private void checkPosition(int i) { | ||||
if (i > _endIndex - _writeIndex) { | if (i > _endIndex - _writeIndex) { | ||||
throw new RuntimeException("Buffer overrun"); | |||||
throw new IllegalStateException("Buffer overrun"); | |||||
} | } | ||||
} | } | ||||
try { | try { | ||||
return super.available(); | return super.available(); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
try { | try { | ||||
checkEOF(read(buf), 1); | checkEOF(read(buf), 1); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
return LittleEndian.getUByte(buf); | return LittleEndian.getUByte(buf); | ||||
} | } | ||||
try { | try { | ||||
checkEOF(read(buf), buf.length); | checkEOF(read(buf), buf.length); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
return LittleEndian.getInt(buf); | return LittleEndian.getInt(buf); | ||||
} | } | ||||
try { | try { | ||||
checkEOF(read(buf), LittleEndianConsts.LONG_SIZE); | checkEOF(read(buf), LittleEndianConsts.LONG_SIZE); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
return LittleEndian.getLong(buf); | return LittleEndian.getLong(buf); | ||||
} | } | ||||
try { | try { | ||||
checkEOF(read(buf), LittleEndianConsts.SHORT_SIZE); | checkEOF(read(buf), LittleEndianConsts.SHORT_SIZE); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
return LittleEndian.getUShort(buf); | return LittleEndian.getUShort(buf); | ||||
} | } | ||||
private static void checkEOF(int actualBytes, int expectedBytes) { | private static void checkEOF(int actualBytes, int expectedBytes) { | ||||
if (expectedBytes != 0 && (actualBytes == -1 || actualBytes != expectedBytes)) { | if (expectedBytes != 0 && (actualBytes == -1 || actualBytes != expectedBytes)) { | ||||
throw new RuntimeException("Unexpected end-of-file"); | |||||
throw new IllegalStateException("Unexpected end-of-file"); | |||||
} | } | ||||
} | } | ||||
try { | try { | ||||
checkEOF(_read(buf, off, len), len); | checkEOF(_read(buf, off, len), len); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
try { | try { | ||||
out.write(v); | out.write(v); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
out.write(b2); | out.write(b2); | ||||
out.write(b3); | out.write(b3); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
out.write(b0); | out.write(b0); | ||||
out.write(b1); | out.write(b1); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
@Override | @Override | ||||
try { | try { | ||||
super.write(b); | super.write(b); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
@Override | @Override | ||||
try { | try { | ||||
super.write(b, off, len); | super.write(b, off, len); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
out.write( (byte) ( ( value >>> 16 ) & 0xFF ) ); | out.write( (byte) ( ( value >>> 16 ) & 0xFF ) ); | ||||
out.write( (byte) ( ( value >>> 24 ) & 0xFF ) ); | out.write( (byte) ( ( value >>> 24 ) & 0xFF ) ); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
out.write( (byte) ( ( value ) & 0xFF ) ); | out.write( (byte) ( ( value ) & 0xFF ) ); | ||||
out.write( (byte) ( ( value >>> 8 ) & 0xFF ) ); | out.write( (byte) ( ( value >>> 8 ) & 0xFF ) ); | ||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
} | } |
throw re; | throw re; | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
logThrowable(e, "Failed to create SAXParserFactory", "-"); | logThrowable(e, "Failed to create SAXParserFactory", "-"); | ||||
throw new RuntimeException("Failed to create SAXParserFactory", e); | |||||
throw new IllegalStateException("Failed to create SAXParserFactory", e); | |||||
} | } | ||||
} | } | ||||