diff options
author | Andreas Beeker <kiwiwings@apache.org> | 2021-03-27 14:03:16 +0000 |
---|---|---|
committer | Andreas Beeker <kiwiwings@apache.org> | 2021-03-27 14:03:16 +0000 |
commit | 37791e4bdfc706aa5684745594260f243b4be7ee (patch) | |
tree | a8dd8d0976fc478074d52cd3de79e0e6b5e6a33a /src/testcases/org/apache/poi/ss/formula/function | |
parent | 2bb3839bfe3e3bacff79f8157465633e311239ce (diff) | |
download | poi-37791e4bdfc706aa5684745594260f243b4be7ee.tar.gz poi-37791e4bdfc706aa5684745594260f243b4be7ee.zip |
65206 - Migrate ant / maven to gradle build
update gradle files and project structure along https://github.com/centic9/poi/tree/gradle_build
remove eclipse IDE project files
remove obsolete record generator files
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1888111 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/testcases/org/apache/poi/ss/formula/function')
5 files changed, 0 insertions, 1303 deletions
diff --git a/src/testcases/org/apache/poi/ss/formula/function/ExcelCetabFunctionExtractor.java b/src/testcases/org/apache/poi/ss/formula/function/ExcelCetabFunctionExtractor.java deleted file mode 100644 index db87e07377..0000000000 --- a/src/testcases/org/apache/poi/ss/formula/function/ExcelCetabFunctionExtractor.java +++ /dev/null @@ -1,378 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.function; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintStream; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * This class is not used during normal POI run-time but is used at development time to generate - * the file 'functionMetadataCetab.txt'. There are more than 300 built-in functions in Excel in - * the Cetab and the intention of this class is to make it easier to maintain the metadata, by extracting - * it from a reliable source. - */ -public final class ExcelCetabFunctionExtractor { - - private static final String SOURCE_DOC_FILE_NAME = "functionMetadataCetab-PDF.txt"; - - /** - * For simplicity, the output file is strictly simple ASCII. - * This method detects any unexpected characters. - */ - /* package */ static boolean isSimpleAscii(char c) { - - if (c>=0x21 && c<=0x7E) { - // everything from '!' to '~' (includes letters, digits, punctuation - return true; - } - // some specific whitespace chars below 0x21: - switch(c) { - case ' ': - case '\t': - case '\r': - case '\n': - return true; - } - return false; - } - - - private static final class FunctionData { - // special characters from the ooo document - private static final int CHAR_ELLIPSIS_8230 = 8230; - private static final int CHAR_NDASH_8211 = 8211; - - private final int _index; - private final boolean _hasFootnote; - private final String _name; - private final int _minParams; - private final int _maxParams; - private final String _returnClass; - private final String _paramClasses; - private final boolean _isVolatile; - - public FunctionData(int funcIx, boolean hasFootnote, String funcName, int minParams, int maxParams, - String returnClass, String paramClasses, boolean isVolatile) { - _index = funcIx; - _hasFootnote = hasFootnote; - _name = funcName; - _minParams = minParams; - _maxParams = maxParams; - _returnClass = convertSpecialChars(returnClass); - _paramClasses = convertSpecialChars(paramClasses); - _isVolatile = isVolatile; - } - private static String convertSpecialChars(String ss) { - StringBuilder sb = new StringBuilder(ss.length() + 4); - for(int i=0; i<ss.length(); i++) { - char c = ss.charAt(i); - if (isSimpleAscii(c)) { - sb.append(c); - continue; - } - switch (c) { - case CHAR_NDASH_8211: - sb.append('-'); - continue; - case CHAR_ELLIPSIS_8230: - sb.append("..."); - continue; - } - throw new RuntimeException("bad char (" + ((int)c) + ") in string '" + ss + "'"); - } - return sb.toString(); - } - public int getIndex() { - return _index; - } - public String getName() { - return _name; - } - public boolean hasFootnote() { - return _hasFootnote; - } - public String formatAsDataLine() { - return _index + "\t" + _name + "\t" + _minParams + "\t" - + _maxParams + "\t" + _returnClass + "\t" + _paramClasses - + "\t" + checkMark(_isVolatile) + "\t" + checkMark(_hasFootnote); - } - private static String checkMark(boolean b) { - return b ? "x" : ""; - } - } - - private static final class FunctionDataCollector { - - private final Map<Integer, FunctionData> _allFunctionsByIndex; - private final Map<String, FunctionData> _allFunctionsByName; - private final Set<Integer> _groupFunctionIndexes; - private final Set<String> _groupFunctionNames; - private final PrintStream _ps; - - public FunctionDataCollector(PrintStream ps) { - _ps = ps; - _allFunctionsByIndex = new HashMap<>(); - _allFunctionsByName = new HashMap<>(); - _groupFunctionIndexes = new HashSet<>(); - _groupFunctionNames = new HashSet<>(); - } - - public void addFunction(int funcIx, boolean hasFootnote, String funcName, int minParams, int maxParams, - String returnClass, String paramClasses, String volatileFlagStr) { - boolean isVolatile = volatileFlagStr.length() > 0; - - Integer funcIxKey = Integer.valueOf(funcIx); - if(!_groupFunctionIndexes.add(funcIxKey)) { - throw new RuntimeException("Duplicate function index (" + funcIx + ")"); - } - if(!_groupFunctionNames.add(funcName)) { - throw new RuntimeException("Duplicate function name '" + funcName + "'"); - } - - checkRedefinedFunction(hasFootnote, funcName, funcIxKey); - FunctionData fd = new FunctionData(funcIx, hasFootnote, funcName, - minParams, maxParams, returnClass, paramClasses, isVolatile); - - _allFunctionsByIndex.put(funcIxKey, fd); - _allFunctionsByName.put(funcName, fd); - } - - /** - * Some extra validation here. - * Any function which changes definition will have a footnote in the source document - */ - private void checkRedefinedFunction(boolean hasNote, String funcName, Integer funcIxKey) { - FunctionData fdPrev; - // check by index - fdPrev = _allFunctionsByIndex.get(funcIxKey); - if(fdPrev != null) { - if(!fdPrev.hasFootnote() || !hasNote) { - throw new RuntimeException("changing function [" - + funcIxKey + "] definition without foot-note"); - } - _allFunctionsByName.remove(fdPrev.getName()); - } - // check by name - fdPrev = _allFunctionsByName.get(funcName); - if(fdPrev != null) { - if(!fdPrev.hasFootnote() || !hasNote) { - throw new RuntimeException("changing function '" - + funcName + "' definition without foot-note"); - } - _allFunctionsByIndex.remove(Integer.valueOf(fdPrev.getIndex())); - } - } - - public void endTableGroup(String headingText) { - Integer[] keys = new Integer[_groupFunctionIndexes.size()]; - _groupFunctionIndexes.toArray(keys); - _groupFunctionIndexes.clear(); - _groupFunctionNames.clear(); - Arrays.sort(keys); - - _ps.println("# " + headingText); - for (Integer key : keys) { - FunctionData fd = _allFunctionsByIndex.get(key); - _ps.println(fd.formatAsDataLine()); - } - } - } - - private static final Pattern ID_MATCH = Pattern.compile("0x([\\dA-F]+)"); - private static final Pattern NAME_MATCH = Pattern.compile("([0-9A-Z.]+)"); - private static final Pattern ID_NAME_MATCH = Pattern.compile("0x([\\dA-F]+)\\s+([0-9A-Z.]+)"); - - private static final Set<String> IGNORED_LINES = new HashSet<>(); - static { - IGNORED_LINES.add("[MS-XLS] — v20141018"); - IGNORED_LINES.add("Excel Binary File Format (.xls) Structure"); - IGNORED_LINES.add("Copyright © 2014 Microsoft Corporation."); - IGNORED_LINES.add("Release: October 30, 2014Value Meaning"); - IGNORED_LINES.add("Release: October 30, 2014Value"); - IGNORED_LINES.add("Meaning"); - } - - private static void extractFunctionData(FunctionDataCollector fdc, InputStream is) throws IOException { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { - - String id = null; - String name = null; - while (true) { - String line = reader.readLine(); - if(line == null) { - break; - } - - if(IGNORED_LINES.contains(line) || line.matches("\\d+ / \\d+")) { - continue; - } - - Matcher idMatcher = ID_MATCH.matcher(line); - boolean foundID = idMatcher.matches(); - Matcher nameMatcher = NAME_MATCH.matcher(line); - boolean foundName = nameMatcher.matches(); - Matcher idAndNameMatcher = ID_NAME_MATCH.matcher(line); - boolean foundIDandName = idAndNameMatcher.matches(); - if(foundID && foundName || - foundName && foundIDandName || - foundID && foundIDandName) { - throw new IllegalStateException("Should not find id and name: " + - foundID + "/" + foundName + "/" + foundIDandName + - ", line: " + line); - } - - if(foundID && id != null) { - throw new IllegalStateException("Found ID, but already had one: " + id + ", line: " + line); - } - if(foundName && name != null) { - throw new IllegalStateException("Found name, but already had one: " + name + ", line: " + line); - } - if(foundIDandName && (name != null || id != null)) { - throw new IllegalStateException("Found name and id, but already had one: id: " + id + ", name: " + name + ", line: " + line); - } - - if(foundID) { - id = idMatcher.group(1); - } else if (foundName) { - name = nameMatcher.group(1); - } else if (foundIDandName) { - id = idAndNameMatcher.group(1); - name = idAndNameMatcher.group(2); - // manual override for one function name which contains lowercase characters - } else if(line.equals("VBAActivate")) { - name = line; - } else if (id == null || name == null) { - throw new IllegalStateException("Found params, but had empty id or name, id: " + id + - ", name: " + name + ", line: " + line); - } else { - System.out.println("Found function " + id + " " + name + " " + line); - fdc.addFunction(Integer.parseInt(id, 16), false, name, 0, 0, - "", "", ""); - - id = null; - name = null; - } - } - } - - fdc.endTableGroup(""); - } - /** - * To be sure that no tricky unicode chars make it through to the output file. - */ - private static final class SimpleAsciiOutputStream extends OutputStream { - - private final OutputStream _os; - - public SimpleAsciiOutputStream(OutputStream os) { - _os = os; - } - - @Override - public void write(int b) throws IOException { - checkByte(b); - _os.write(b); - } - - private static void checkByte(int b) { - if (!isSimpleAscii((char)b)) { - throw new RuntimeException("Encountered char (" + b + ") which was not simple ascii as expected"); - } - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - for (int i = 0; i < len; i++) { - checkByte(b[i + off]); - - } - _os.write(b, off, len); - } - } - - private static void processFile(InputStream input, File outFile) throws IOException { - try (OutputStream os = new SimpleAsciiOutputStream(new FileOutputStream(outFile)); - PrintStream ps = new PrintStream(os, true, "UTF-8")) { - - outputLicenseHeader(ps); - Class<?> genClass = ExcelCetabFunctionExtractor.class; - ps.println("# Created by (" + genClass.getName() + ")"); - // identify the source file - ps.println("# from source file '" + SOURCE_DOC_FILE_NAME + "'"); - ps.println("#"); - ps.println("#Columns: (index, name, minParams, maxParams, returnClass, paramClasses, isVolatile, hasFootnote )"); - ps.println(); - extractFunctionData(new FunctionDataCollector(ps), input); - ps.close(); - - String canonicalOutputFileName = outFile.getCanonicalPath(); - System.out.println("Successfully output to '" + canonicalOutputFileName + "'"); - } - } - - private static void outputLicenseHeader(PrintStream ps) { - String[] lines= { - "Licensed to the Apache Software Foundation (ASF) under one or more", - "contributor license agreements. See the NOTICE file distributed with", - "this work for additional information regarding copyright ownership.", - "The ASF licenses this file to You under the Apache License, Version 2.0", - "(the \"License\"); you may not use this file except in compliance with", - "the License. You may obtain a copy of the License at", - "", - " http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an \"AS IS\" BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License.", - }; - for (String line : lines) { - ps.print("# "); - ps.println(line); - } - ps.println(); - } - - public static void main(String[] args) throws IOException { - if(!new File(SOURCE_DOC_FILE_NAME).exists()) { - throw new IllegalStateException("Did not find file " + SOURCE_DOC_FILE_NAME + " in the resources"); - } - - try (InputStream stream = new FileInputStream(SOURCE_DOC_FILE_NAME)) { - File outFile = new File("functionMetadataCetab.txt"); - - processFile(stream, outFile); - } - } -} diff --git a/src/testcases/org/apache/poi/ss/formula/function/ExcelFileFormatDocFunctionExtractor.java b/src/testcases/org/apache/poi/ss/formula/function/ExcelFileFormatDocFunctionExtractor.java deleted file mode 100644 index c408dd527b..0000000000 --- a/src/testcases/org/apache/poi/ss/formula/function/ExcelFileFormatDocFunctionExtractor.java +++ /dev/null @@ -1,623 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.function; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; -import java.io.UnsupportedEncodingException; -import java.math.BigInteger; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; -import java.security.MessageDigest; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Stack; -import java.util.zip.ZipFile; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -import org.apache.poi.poifs.crypt.CryptoFunctions; -import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.util.TempFile; -import org.apache.poi.util.XMLHelper; -import org.xml.sax.Attributes; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -/** - * This class is not used during normal POI run-time but is used at development time to generate - * the file 'functionMetadata.txt'. There are more than 300 built-in functions in Excel and the - * intention of this class is to make it easier to maintain the metadata, by extracting it from - * a reliable source. - */ -public final class ExcelFileFormatDocFunctionExtractor { - - private static final String SOURCE_DOC_FILE_NAME = "excelfileformat.odt"; - - /** - * For simplicity, the output file is strictly simple ASCII. - * This method detects any unexpected characters. - */ - /* package */ static boolean isSimpleAscii(char c) { - - if (c>=0x21 && c<=0x7E) { - // everything from '!' to '~' (includes letters, digits, punctuation - return true; - } - // some specific whitespace chars below 0x21: - switch(c) { - case ' ': - case '\t': - case '\r': - case '\n': - return true; - } - return false; - } - - - private static final class FunctionData { - // special characters from the ooo document - private static final int CHAR_ELLIPSIS_8230 = 8230; - private static final int CHAR_NDASH_8211 = 8211; - - private final int _index; - private final boolean _hasFootnote; - private final String _name; - private final int _minParams; - private final int _maxParams; - private final String _returnClass; - private final String _paramClasses; - private final boolean _isVolatile; - - public FunctionData(int funcIx, boolean hasFootnote, String funcName, int minParams, int maxParams, - String returnClass, String paramClasses, boolean isVolatile) { - _index = funcIx; - _hasFootnote = hasFootnote; - _name = funcName; - _minParams = minParams; - _maxParams = maxParams; - _returnClass = convertSpecialChars(returnClass); - _paramClasses = convertSpecialChars(paramClasses); - _isVolatile = isVolatile; - } - private static String convertSpecialChars(String ss) { - StringBuilder sb = new StringBuilder(ss.length() + 4); - for(int i=0; i<ss.length(); i++) { - char c = ss.charAt(i); - if (isSimpleAscii(c)) { - sb.append(c); - continue; - } - switch (c) { - case CHAR_NDASH_8211: - sb.append('-'); - continue; - case CHAR_ELLIPSIS_8230: - sb.append("..."); - continue; - } - throw new RuntimeException("bad char (" + ((int)c) + ") in string '" + ss + "'"); - } - return sb.toString(); - } - public int getIndex() { - return _index; - } - public String getName() { - return _name; - } - public boolean hasFootnote() { - return _hasFootnote; - } - public String formatAsDataLine() { - return _index + "\t" + _name + "\t" + _minParams + "\t" - + _maxParams + "\t" + _returnClass + "\t" + _paramClasses - + "\t" + checkMark(_isVolatile) + "\t" + checkMark(_hasFootnote); - } - private static String checkMark(boolean b) { - return b ? "x" : ""; - } - } - - private static final class FunctionDataCollector { - - private final Map<Integer, FunctionData> _allFunctionsByIndex; - private final Map<String, FunctionData> _allFunctionsByName; - private final Set<Integer> _groupFunctionIndexes; - private final Set<String> _groupFunctionNames; - private final PrintStream _ps; - - public FunctionDataCollector(PrintStream ps) { - _ps = ps; - _allFunctionsByIndex = new HashMap<>(); - _allFunctionsByName = new HashMap<>(); - _groupFunctionIndexes = new HashSet<>(); - _groupFunctionNames = new HashSet<>(); - } - - public void addFuntion(int funcIx, boolean hasFootnote, String funcName, int minParams, int maxParams, - String returnClass, String paramClasses, String volatileFlagStr) { - boolean isVolatile = volatileFlagStr.length() > 0; - - Integer funcIxKey = Integer.valueOf(funcIx); - if(!_groupFunctionIndexes.add(funcIxKey)) { - throw new RuntimeException("Duplicate function index (" + funcIx + ")"); - } - if(!_groupFunctionNames.add(funcName)) { - throw new RuntimeException("Duplicate function name '" + funcName + "'"); - } - - checkRedefinedFunction(hasFootnote, funcName, funcIxKey); - FunctionData fd = new FunctionData(funcIx, hasFootnote, funcName, - minParams, maxParams, returnClass, paramClasses, isVolatile); - - _allFunctionsByIndex.put(funcIxKey, fd); - _allFunctionsByName.put(funcName, fd); - } - - /** - * Some extra validation here. - * Any function which changes definition will have a footnote in the source document - */ - private void checkRedefinedFunction(boolean hasNote, String funcName, Integer funcIxKey) { - FunctionData fdPrev; - // check by index - fdPrev = _allFunctionsByIndex.get(funcIxKey); - if(fdPrev != null) { - if(!fdPrev.hasFootnote() || !hasNote) { - throw new RuntimeException("changing function [" - + funcIxKey + "] definition without foot-note"); - } - _allFunctionsByName.remove(fdPrev.getName()); - } - // check by name - fdPrev = _allFunctionsByName.get(funcName); - if(fdPrev != null) { - if(!fdPrev.hasFootnote() || !hasNote) { - throw new RuntimeException("changing function '" - + funcName + "' definition without foot-note"); - } - _allFunctionsByIndex.remove(Integer.valueOf(fdPrev.getIndex())); - } - } - - public void endTableGroup(String headingText) { - Integer[] keys = new Integer[_groupFunctionIndexes.size()]; - _groupFunctionIndexes.toArray(keys); - _groupFunctionIndexes.clear(); - _groupFunctionNames.clear(); - Arrays.sort(keys); - - _ps.println("# " + headingText); - for (Integer key : keys) { - FunctionData fd = _allFunctionsByIndex.get(key); - _ps.println(fd.formatAsDataLine()); - } - } - } - - /** - * To avoid drag-in - parse XML using only JDK. - */ - private static class EFFDocHandler extends DefaultHandler { - private static final String[] HEADING_PATH_NAMES = { - "office:document-content", "office:body", "office:text", "text:h", - }; - private static final String[] TABLE_BASE_PATH_NAMES = { - "office:document-content", "office:body", "office:text", "table:table", - }; - private static final String[] TABLE_ROW_RELPATH_NAMES = { - "table:table-row", - }; - private static final String[] TABLE_CELL_RELPATH_NAMES = { - "table:table-row", "table:table-cell", "text:p", - }; - // after May 2008 there was one more style applied to the footnotes - private static final String[] NOTE_REF_RELPATH_NAMES_OLD = { - "table:table-row", "table:table-cell", "text:p", "text:span", "text:note-ref", - }; - private static final String[] NOTE_REF_RELPATH_NAMES = { - "table:table-row", "table:table-cell", "text:p", "text:span", "text:span", "text:note-ref", - }; - - - private final Stack<String> _elemNameStack; - /** <code>true</code> only when parsing the target tables */ - private boolean _isInsideTable; - - private final List<String> _rowData; - private final StringBuilder _textNodeBuffer; - private final List<Boolean> _rowNoteFlags; - private boolean _cellHasNote; - - private final FunctionDataCollector _fdc; - private String _lastHeadingText; - - public EFFDocHandler(FunctionDataCollector fdc) { - _fdc = fdc; - _elemNameStack = new Stack<>(); - _isInsideTable = false; - _rowData = new ArrayList<>(); - _textNodeBuffer = new StringBuilder(); - _rowNoteFlags = new ArrayList<>(); - } - - private boolean matchesTargetPath() { - return matchesPath(0, TABLE_BASE_PATH_NAMES); - } - - private boolean matchesRelPath(String[] pathNames) { - return matchesPath(TABLE_BASE_PATH_NAMES.length, pathNames); - } - - private boolean matchesPath(int baseStackIndex, String[] pathNames) { - if(_elemNameStack.size() != baseStackIndex + pathNames.length) { - return false; - } - for (int i = 0; i < pathNames.length; i++) { - if(!_elemNameStack.get(baseStackIndex + i).equals(pathNames[i])) { - return false; - } - } - return true; - } - - @Override - public void characters(char[] ch, int start, int length) { - // only 2 text nodes where text is collected: - if(matchesRelPath(TABLE_CELL_RELPATH_NAMES) || matchesPath(0, HEADING_PATH_NAMES)) { - _textNodeBuffer.append(ch, start, length); - } - } - - @Override - public void endElement(String namespaceURI, String localName, String name) { - String expectedName = _elemNameStack.peek(); - if(expectedName != name) { - throw new RuntimeException("close tag mismatch"); - } - if(matchesPath(0, HEADING_PATH_NAMES)) { - _lastHeadingText = _textNodeBuffer.toString().trim(); - _textNodeBuffer.setLength(0); - } - if(_isInsideTable) { - if(matchesTargetPath()) { - _fdc.endTableGroup(_lastHeadingText); - _isInsideTable = false; - } else if(matchesRelPath(TABLE_ROW_RELPATH_NAMES)) { - String[] cellData = new String[_rowData.size()]; - _rowData.toArray(cellData); - _rowData.clear(); - Boolean[] noteFlags = new Boolean[_rowNoteFlags.size()]; - _rowNoteFlags.toArray(noteFlags); - _rowNoteFlags.clear(); - processTableRow(cellData, noteFlags); - } else if(matchesRelPath(TABLE_CELL_RELPATH_NAMES)) { - _rowData.add(_textNodeBuffer.toString().trim()); - _rowNoteFlags.add(Boolean.valueOf(_cellHasNote)); - _textNodeBuffer.setLength(0); - } - } - _elemNameStack.pop(); - } - - private void processTableRow(String[] cellData, Boolean[] noteFlags) { - // each table row of the document contains data for two functions - if(cellData.length != 15) { - throw new RuntimeException("Bad table row size"); - } - processFunction(cellData, noteFlags, 0); - processFunction(cellData, noteFlags, 8); - } - - public void processFunction(String[] cellData, Boolean[] noteFlags, int i) { - String funcIxStr = cellData[i + 0]; - if (funcIxStr.length() < 1) { - // empty (happens on the right hand side when there is an odd number of functions) - return; - } - int funcIx = parseInt(funcIxStr); - - boolean hasFootnote = noteFlags[i + 1].booleanValue(); - String funcName = cellData[i + 1]; - int minParams = parseInt(cellData[i + 2]); - int maxParams = parseInt(cellData[i + 3]); - - String returnClass = cellData[i + 4]; - String paramClasses = cellData[i + 5]; - String volatileFlagStr = cellData[i + 6]; - - _fdc.addFuntion(funcIx, hasFootnote, funcName, minParams, maxParams, returnClass, paramClasses, volatileFlagStr); - } - - private static int parseInt(String valStr) { - try { - return Integer.parseInt(valStr); - } catch (NumberFormatException e) { - throw new RuntimeException("Value '" + valStr + "' could not be parsed as an integer"); - } - } - - @Override - public void startElement(String namespaceURI, String localName, String name, Attributes atts) { - _elemNameStack.add(name); - if(matchesTargetPath()) { - String tableName = atts.getValue("table:name"); - if(tableName.startsWith("tab_fml_func") && !tableName.equals("tab_fml_func0")) { - _isInsideTable = true; - } - return; - } - if(matchesPath(0, HEADING_PATH_NAMES)) { - _textNodeBuffer.setLength(0); - } else if(matchesRelPath(TABLE_ROW_RELPATH_NAMES)) { - _rowData.clear(); - _rowNoteFlags.clear(); - } else if(matchesRelPath(TABLE_CELL_RELPATH_NAMES)) { - _textNodeBuffer.setLength(0); - _cellHasNote = false; - } else if(matchesRelPath(NOTE_REF_RELPATH_NAMES_OLD)) { - _cellHasNote = true; - } else if(matchesRelPath(NOTE_REF_RELPATH_NAMES)) { - _cellHasNote = true; - } - } - - @Override - public void endDocument() { - // do nothing - } - @Override - public void endPrefixMapping(String prefix) { - // do nothing - } - @Override - public void ignorableWhitespace(char[] ch, int start, int length) { - // do nothing - } - @Override - public void processingInstruction(String target, String data) { - // do nothing - } - @Override - public void setDocumentLocator(Locator locator) { - // do nothing - } - @Override - public void skippedEntity(String name) { - // do nothing - } - @Override - public void startDocument() { - // do nothing - } - @Override - public void startPrefixMapping(String prefix, String uri) { - // do nothing - } - } - - private static void extractFunctionData(FunctionDataCollector fdc, InputStream is) { - SAXParserFactory sf = XMLHelper.getSaxParserFactory(); - SAXParser xr; - - try { - // First up, try the default one - xr = sf.newSAXParser(); - } catch (SAXException | ParserConfigurationException e) { - throw new RuntimeException(e); - } - - try (InputStream is2 = is) { - xr.parse(is2, new EFFDocHandler(fdc)); - } catch (IOException | SAXException e) { - throw new RuntimeException(e); - } - } - /** - * To be sure that no tricky unicode chars make it through to the output file. - */ - private static final class SimpleAsciiOutputStream extends OutputStream { - - private final OutputStream _os; - - public SimpleAsciiOutputStream(OutputStream os) { - _os = os; - } - - @Override - public void write(int b) throws IOException { - checkByte(b); - _os.write(b); - } - - private static void checkByte(int b) { - if (!isSimpleAscii((char)b)) { - throw new RuntimeException("Encountered char (" + b + ") which was not simple ascii as expected"); - } - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - for (int i = 0; i < len; i++) { - checkByte(b[i + off]); - - } - _os.write(b, off, len); - } - } - - private static void processFile(File effDocFile, File outFile) { - if(!effDocFile.exists()) { - throw new RuntimeException("file '" + effDocFile.getAbsolutePath() + "' does not exist"); - } - OutputStream os; - try { - os = new FileOutputStream(outFile); - } catch (FileNotFoundException e) { - throw new RuntimeException(e); - } - os = new SimpleAsciiOutputStream(os); - PrintStream ps; - try { - ps = new PrintStream(os, true, "UTF-8"); - } catch(UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - - outputLicenseHeader(ps); - Class<?> genClass = ExcelFileFormatDocFunctionExtractor.class; - ps.println("# Created by (" + genClass.getName() + ")"); - // identify the source file - ps.print("# from source file '" + SOURCE_DOC_FILE_NAME + "'"); - ps.println(" (size=" + effDocFile.length() + ", md5=" + getFileMD5(effDocFile) + ")"); - ps.println("#"); - ps.println("#Columns: (index, name, minParams, maxParams, returnClass, paramClasses, isVolatile, hasFootnote )"); - ps.println(); - try { - // can't use ZipHelper here, because its in a different module - ZipFile zf = new ZipFile(effDocFile); - InputStream is = zf.getInputStream(zf.getEntry("content.xml")); - extractFunctionData(new FunctionDataCollector(ps), is); - zf.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - ps.close(); - - String canonicalOutputFileName; - try { - canonicalOutputFileName = outFile.getCanonicalPath(); - } catch (IOException e) { - throw new RuntimeException(e); - } - System.out.println("Successfully output to '" + canonicalOutputFileName + "'"); - } - - private static void outputLicenseHeader(PrintStream ps) { - String[] lines= { - "Licensed to the Apache Software Foundation (ASF) under one or more", - "contributor license agreements. See the NOTICE file distributed with", - "this work for additional information regarding copyright ownership.", - "The ASF licenses this file to You under the Apache License, Version 2.0", - "(the \"License\"); you may not use this file except in compliance with", - "the License. You may obtain a copy of the License at", - "", - " http://www.apache.org/licenses/LICENSE-2.0", - "", - "Unless required by applicable law or agreed to in writing, software", - "distributed under the License is distributed on an \"AS IS\" BASIS,", - "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.", - "See the License for the specific language governing permissions and", - "limitations under the License.", - }; - for (String line : lines) { - ps.print("# "); - ps.println(line); - } - ps.println(); - } - - /** - * Helps identify the source file - */ - private static String getFileMD5(File f) { - MessageDigest m = CryptoFunctions.getMessageDigest(HashAlgorithm.md5); - - byte[]buf = new byte[2048]; - try { - InputStream is = new FileInputStream(f); - while(true) { - int bytesRead = is.read(buf); - if(bytesRead<1) { - break; - } - m.update(buf, 0, bytesRead); - } - is.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - - return "0x" + new BigInteger(1, m.digest()).toString(16); - } - - private static File downloadSourceFile() { - URL url; - try { - url = new URL("http://sc.openoffice.org/" + SOURCE_DOC_FILE_NAME); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } - - File result; - byte[]buf = new byte[2048]; - try { - URLConnection conn = url.openConnection(); - InputStream is = conn.getInputStream(); - System.out.println("downloading " + url.toExternalForm()); - result = TempFile.createTempFile("excelfileformat", ".odt"); - OutputStream os = new FileOutputStream(result); - while(true) { - int bytesRead = is.read(buf); - if(bytesRead<1) { - break; - } - os.write(buf, 0, bytesRead); - } - is.close(); - os.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - System.out.println("file downloaded ok"); - return result; - } - - public static void main(String[] args) { - - File outFile = new File("functionMetadata-asGenerated.txt"); - -// if (false) { // set true to use local file -// File dir = new File("c:/temp"); -// File effDocFile = new File(dir, SOURCE_DOC_FILE_NAME); -// processFile(effDocFile, outFile); -// return; -// } - - File tempEFFDocFile = downloadSourceFile(); - processFile(tempEFFDocFile, outFile); - tempEFFDocFile.delete(); - } -} diff --git a/src/testcases/org/apache/poi/ss/formula/function/TestFunctionMetadataRegistry.java b/src/testcases/org/apache/poi/ss/formula/function/TestFunctionMetadataRegistry.java deleted file mode 100644 index 29853a410d..0000000000 --- a/src/testcases/org/apache/poi/ss/formula/function/TestFunctionMetadataRegistry.java +++ /dev/null @@ -1,43 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.function; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import org.junit.jupiter.api.Test; - -final class TestFunctionMetadataRegistry { - @Test - void testWellKnownFunctions() { - confirmFunction(0, "COUNT"); - confirmFunction(1, "IF"); - - } - - private static void confirmFunction(int index, String funcName) { - FunctionMetadata fm; - fm = FunctionMetadataRegistry.getFunctionByIndex(index); - assertNotNull(fm); - assertEquals(funcName, fm.getName()); - - fm = FunctionMetadataRegistry.getFunctionByName(funcName); - assertNotNull(fm); - assertEquals(index, fm.getIndex()); - } -} diff --git a/src/testcases/org/apache/poi/ss/formula/function/TestParseMissingBuiltInFuncs.java b/src/testcases/org/apache/poi/ss/formula/function/TestParseMissingBuiltInFuncs.java deleted file mode 100644 index c95eae8871..0000000000 --- a/src/testcases/org/apache/poi/ss/formula/function/TestParseMissingBuiltInFuncs.java +++ /dev/null @@ -1,104 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.function; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; - -import java.io.IOException; - -import org.apache.poi.hssf.model.HSSFFormulaParser; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.ss.formula.ptg.AbstractFunctionPtg; -import org.apache.poi.ss.formula.ptg.FuncPtg; -import org.apache.poi.ss.formula.ptg.FuncVarPtg; -import org.apache.poi.ss.formula.ptg.Ptg; -import org.junit.jupiter.api.Test; - -/** - * Tests parsing of some built-in functions that were not properly - * registered in POI as of bug #44675, #44733 (March/April 2008). - */ -final class TestParseMissingBuiltInFuncs { - - private static Ptg[] parse(String formula) throws IOException { - HSSFWorkbook book = new HSSFWorkbook(); - Ptg[] ptgs = HSSFFormulaParser.parse(formula, book); - book.close(); - return ptgs; - } - - private static void confirmFunc(String formula, int expPtgArraySize, boolean isVarArgFunc, int funcIx) - throws IOException { - Ptg[] ptgs = parse(formula); - Ptg ptgF = ptgs[ptgs.length-1]; // func is last RPN token in all these formulas - - // Check critical things in the Ptg array encoding. - if(!(ptgF instanceof AbstractFunctionPtg)) { - throw new RuntimeException("function token missing"); - } - AbstractFunctionPtg func = (AbstractFunctionPtg) ptgF; - assertNotEquals(255, func.getFunctionIndex(), "Failed to recognise built-in function in formula"); - assertEquals(expPtgArraySize, ptgs.length); - assertEquals(funcIx, func.getFunctionIndex()); - Class<? extends AbstractFunctionPtg> expCls = isVarArgFunc ? FuncVarPtg.class : FuncPtg.class; - assertEquals(expCls, ptgF.getClass()); - - // check that parsed Ptg array converts back to formula text OK - HSSFWorkbook book = new HSSFWorkbook(); - String reRenderedFormula = HSSFFormulaParser.toFormulaString(book, ptgs); - assertEquals(formula, reRenderedFormula); - book.close(); - } - - @Test - void testDatedif() throws IOException { - int expSize = 4; // NB would be 5 if POI added tAttrVolatile properly - confirmFunc("DATEDIF(NOW(),NOW(),\"d\")", expSize, false, 351); - } - - @Test - void testDdb() throws IOException { - confirmFunc("DDB(1,1,1,1,1)", 6, true, 144); - } - - @Test - void testAtan() throws IOException { - confirmFunc("ATAN(1)", 2, false, 18); - } - - @Test - void testUsdollar() throws IOException { - confirmFunc("USDOLLAR(1)", 2, true, 204); - } - - @Test - void testDBCS() throws IOException { - confirmFunc("DBCS(\"abc\")", 2, false, 215); - } - - @Test - void testIsnontext() throws IOException { - confirmFunc("ISNONTEXT(\"abc\")", 2, false, 190); - } - - @Test - void testDproduct() throws IOException { - confirmFunc("DPRODUCT(C1:E5,\"HarvestYield\",G1:H2)", 4, false, 189); - } -} diff --git a/src/testcases/org/apache/poi/ss/formula/function/TestReadMissingBuiltInFuncs.java b/src/testcases/org/apache/poi/ss/formula/function/TestReadMissingBuiltInFuncs.java deleted file mode 100644 index c26220dbd8..0000000000 --- a/src/testcases/org/apache/poi/ss/formula/function/TestReadMissingBuiltInFuncs.java +++ /dev/null @@ -1,155 +0,0 @@ -/* ==================================================================== - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -==================================================================== */ - -package org.apache.poi.ss.formula.function; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.fail; - -import java.lang.reflect.InvocationTargetException; - -import org.apache.poi.hssf.HSSFTestDataSamples; -import org.apache.poi.hssf.usermodel.HSSFSheet; -import org.apache.poi.hssf.usermodel.HSSFWorkbook; -import org.apache.poi.util.RecordFormatException; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -/** - * Tests reading from a sample spreadsheet some built-in functions that were not properly - * registered in POI as of bug #44675, #44733 (March/April 2008). - */ -final class TestReadMissingBuiltInFuncs { - - /** - * This spreadsheet has examples of calls to the interesting built-in functions in cells A1:A7 - */ - private static final String SAMPLE_SPREADSHEET_FILE_NAME = "missingFuncs44675.xls"; - - private static HSSFWorkbook wb; - private static HSSFSheet _sheet; - - @BeforeAll - public static void initSheet() { - wb = HSSFTestDataSamples.openSampleWorkbook(SAMPLE_SPREADSHEET_FILE_NAME); - try { - _sheet = wb.getSheetAt(0); - } catch (RecordFormatException e) { - if(e.getCause() instanceof InvocationTargetException) { - InvocationTargetException ite = (InvocationTargetException) e.getCause(); - if(ite.getTargetException() instanceof RuntimeException) { - RuntimeException re = (RuntimeException) ite.getTargetException(); - assertNotEquals("Invalid built-in function index (189)", re.getMessage(), - "DPRODUCT() registered with wrong index"); - } - } - // some other unexpected error - throw e; - } - } - - @AfterAll - public static void closeResources() throws Exception { - wb.close(); - } - - @Test - void testDatedif() { - String formula; - try { - formula = getCellFormula(0); - } catch (IllegalStateException e) { - if(e.getMessage().startsWith("Too few arguments")) { - assertFalse(e.getMessage().contains("AttrPtg"), - "tAttrVolatile not supported in FormulaParser.toFormulaString"); - fail("NOW() registered with 1 arg instead of 0"); - } - if(e.getMessage().startsWith("too much stuff")) { - fail("DATEDIF() not registered"); - } - // some other unexpected error - throw e; - } - assertEquals("DATEDIF(NOW(),NOW(),\"d\")", formula); - } - - @Test - void testDdb() { - String formula = getCellFormula(1); - assertNotEquals("externalflag(1,1,1,1,1)", formula, "DDB() not registered"); - assertEquals("DDB(1,1,1,1,1)", formula); - } - - @Test - void testAtan() { - String formula = getCellFormula(2); - assertNotEquals("ARCTAN(1)", formula, "func ix 18 registered as ARCTAN() instead of ATAN()"); - assertEquals("ATAN(1)", formula); - } - - @Test - void testUsdollar() { - String formula = getCellFormula(3); - assertNotEquals("YEN(1)", formula, "func ix 204 registered as YEN() instead of USDOLLAR()"); - assertEquals("USDOLLAR(1)", formula); - } - - @Test - void testDBCS() { - String formula = ""; - try { - formula = getCellFormula(4); - } catch (IllegalStateException e) { - assertFalse(e.getMessage().startsWith("too much stuff"), "DBCS() not registered"); - // some other unexpected error - throw e; - } catch (NegativeArraySizeException e) { - fail("found err- DBCS() registered with -1 args"); - } - assertNotEquals("JIS(\"abc\")", formula, "func ix 215 registered as JIS() instead of DBCS()"); - assertEquals("DBCS(\"abc\")", formula); - } - - @Test - void testIsnontext() { - String formula; - try { - formula = getCellFormula(5); - } catch (IllegalStateException e) { - assertFalse(e.getMessage().startsWith("too much stuff"), "ISNONTEXT() registered with wrong index"); - // some other unexpected error - throw e; - } - assertEquals("ISNONTEXT(\"abc\")", formula); - } - - @Test - void testDproduct() { - String formula = getCellFormula(6); - assertEquals("DPRODUCT(C1:E5,\"HarvestYield\",G1:H2)", formula); - } - - private String getCellFormula(int rowIx) { - // if (false) { -// System.err.println(result); -// } - return _sheet.getRow(rowIx).getCell(0).getCellFormula(); - } -} |