You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2021/05/21 21:22:41 UTC
svn commit: r1890089 [5/6] - in /poi/trunk: ./ poi-examples/
poi-examples/src/main/java/org/apache/poi/examples/hpsf/
poi-examples/src/main/java/org/apache/poi/examples/xssf/eventusermodel/
poi-examples/src/main/java/org/apache/poi/examples/xssf/stream...
Modified: poi/trunk/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/hssf/usermodel/HSSFShapeContainer.java Fri May 21 21:22:40 2021
@@ -33,9 +33,8 @@ public interface HSSFShapeContainer exte
/**
* add shape to the list of child records
- * @param shape
*/
- public void addShape(HSSFShape shape);
+ void addShape(HSSFShape shape);
/**
* set coordinates of this group relative to the parent
@@ -47,27 +46,27 @@ public interface HSSFShapeContainer exte
/**
*@return The top left x coordinate of this group.
*/
- public int getX1();
+ int getX1();
/**
*@return The top left y coordinate of this group.
*/
- public int getY1();
+ int getY1();
/**
*@return The bottom right x coordinate of this group.
*/
- public int getX2();
+ int getX2();
/**
* @return The bottom right y coordinate of this group.
*/
- public int getY2();
+ int getY2();
/**
* remove first level shapes
* @param shape to be removed
* @return true if shape is removed else return false
*/
- public boolean removeShape(HSSFShape shape);
+ boolean removeShape(HSSFShape shape);
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java Fri May 21 21:22:40 2021
@@ -26,10 +26,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
-import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
-import javax.crypto.IllegalBlockSizeException;
-import javax.crypto.ShortBufferException;
import com.zaxxer.sparsebits.SparseBitSet;
import org.apache.logging.log4j.LogManager;
@@ -37,7 +34,6 @@ import org.apache.logging.log4j.Logger;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.POIFSWriterEvent;
-import org.apache.poi.poifs.filesystem.POIFSWriterListener;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian;
@@ -63,7 +59,7 @@ public abstract class ChunkedCipherOutpu
private long pos;
private long totalPos;
private long written;
-
+
// the cipher can't be final, because for the last chunk we change the padding
// and therefore need to change the cipher too
private Cipher cipher;
@@ -133,7 +129,7 @@ public abstract class ChunkedCipherOutpu
public void writePlain(byte[] b, int off, int len) throws IOException {
write(b, off, len, true);
}
-
+
protected void write(byte[] b, int off, int len, boolean writePlain) throws IOException {
if (len == 0) {
return;
@@ -214,10 +210,6 @@ public abstract class ChunkedCipherOutpu
/**
* Helper function for overriding the cipher invocation, i.e. XOR doesn't use a cipher
* and uses it's own implementation
- *
- * @throws BadPaddingException
- * @throws IllegalBlockSizeException
- * @throws ShortBufferException
*/
protected int invokeCipher(int posInChunk, boolean doFinal) throws GeneralSecurityException, IOException {
byte[] plain = (plainByteFlags.isEmpty()) ? null : chunk.clone();
@@ -250,10 +242,10 @@ public abstract class ChunkedCipherOutpu
i = plainByteFlags.nextSetBit(i+1);
}
}
-
+
return ciLen;
}
-
+
@Override
public void close() throws IOException {
if (isClosed) {
@@ -271,14 +263,14 @@ public abstract class ChunkedCipherOutpu
if (fileOut != null) {
int oleStreamSize = (int)(fileOut.length()+LittleEndianConsts.LONG_SIZE);
calculateChecksum(fileOut, (int)pos);
- dir.createDocument(DEFAULT_POIFS_ENTRY, oleStreamSize, new EncryptedPackageWriter());
+ dir.createDocument(DEFAULT_POIFS_ENTRY, oleStreamSize, this::processPOIFSWriterEvent);
createEncryptionInfoEntry(dir, fileOut);
}
} catch (GeneralSecurityException e) {
throw new IOException(e);
}
}
-
+
protected byte[] getChunk() {
return chunk;
}
@@ -304,31 +296,28 @@ public abstract class ChunkedCipherOutpu
*/
public void setNextRecordSize(int recordSize, boolean isPlain) {
}
-
- private class EncryptedPackageWriter implements POIFSWriterListener {
- @Override
- public void processPOIFSWriterEvent(POIFSWriterEvent event) {
- try {
- try (OutputStream os = event.getStream();
- FileInputStream fis = new FileInputStream(fileOut)) {
-
- // StreamSize (8 bytes): An unsigned integer that specifies the number of bytes used by data
- // encrypted within the EncryptedData field, not including the size of the StreamSize field.
- // Note that the actual size of the \EncryptedPackage stream (1) can be larger than this
- // value, depending on the block size of the chosen encryption algorithm
- byte[] buf = new byte[LittleEndianConsts.LONG_SIZE];
- LittleEndian.putLong(buf, 0, pos);
- os.write(buf);
- IOUtils.copy(fis, os);
- }
+ private void processPOIFSWriterEvent(POIFSWriterEvent event) {
+ try {
+ try (OutputStream os = event.getStream();
+ FileInputStream fis = new FileInputStream(fileOut)) {
- if (!fileOut.delete()) {
- LOG.atError().log("Can't delete temporary encryption file: {}", fileOut);
- }
- } catch (IOException e) {
- throw new EncryptedDocumentException(e);
+ // StreamSize (8 bytes): An unsigned integer that specifies the number of bytes used by data
+ // encrypted within the EncryptedData field, not including the size of the StreamSize field.
+ // Note that the actual size of the \EncryptedPackage stream (1) can be larger than this
+ // value, depending on the block size of the chosen encryption algorithm
+ byte[] buf = new byte[LittleEndianConsts.LONG_SIZE];
+ LittleEndian.putLong(buf, 0, pos);
+ os.write(buf);
+
+ IOUtils.copy(fis, os);
+ }
+
+ if (!fileOut.delete()) {
+ LOG.atError().log("Can't delete temporary encryption file: {}", fileOut);
}
+ } catch (IOException e) {
+ throw new EncryptedDocumentException(e);
}
}
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/poifs/crypt/EncryptionHeader.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/poifs/crypt/EncryptionHeader.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/poifs/crypt/EncryptionHeader.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/poifs/crypt/EncryptionHeader.java Fri May 21 21:22:40 2021
@@ -30,24 +30,6 @@ import org.apache.poi.common.usermodel.G
* The constants are largely based on ZIP constants.
*/
public abstract class EncryptionHeader implements GenericRecord, Duplicatable {
- public static final int ALGORITHM_RC4 = CipherAlgorithm.rc4.ecmaId;
- public static final int ALGORITHM_AES_128 = CipherAlgorithm.aes128.ecmaId;
- public static final int ALGORITHM_AES_192 = CipherAlgorithm.aes192.ecmaId;
- public static final int ALGORITHM_AES_256 = CipherAlgorithm.aes256.ecmaId;
-
- public static final int HASH_NONE = HashAlgorithm.none.ecmaId;
- public static final int HASH_SHA1 = HashAlgorithm.sha1.ecmaId;
- public static final int HASH_SHA256 = HashAlgorithm.sha256.ecmaId;
- public static final int HASH_SHA384 = HashAlgorithm.sha384.ecmaId;
- public static final int HASH_SHA512 = HashAlgorithm.sha512.ecmaId;
-
- public static final int PROVIDER_RC4 = CipherProvider.rc4.ecmaId;
- public static final int PROVIDER_AES = CipherProvider.aes.ecmaId;
-
- public static final int MODE_ECB = ChainingMode.ecb.ecmaId;
- public static final int MODE_CBC = ChainingMode.cbc.ecmaId;
- public static final int MODE_CFB = ChainingMode.cfb.ecmaId;
-
private int flags;
private int sizeExtra;
private CipherAlgorithm cipherAlgorithm;
@@ -125,8 +107,6 @@ public abstract class EncryptionHeader i
* Sets the keySize (in bits). Before calling this method, make sure
* to set the cipherAlgorithm, as the amount of keyBits gets validated against
* the list of allowed keyBits of the corresponding cipherAlgorithm
- *
- * @param keyBits
*/
public void setKeySize(int keyBits) {
this.keyBits = keyBits;
@@ -170,6 +150,7 @@ public abstract class EncryptionHeader i
this.cspName = cspName;
}
+ @Override
public abstract EncryptionHeader copy();
@Override
Modified: poi/trunk/poi/src/main/java/org/apache/poi/poifs/crypt/package-info.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/poifs/crypt/package-info.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/poifs/crypt/package-info.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/poifs/crypt/package-info.java Fri May 21 21:22:40 2021
@@ -18,7 +18,7 @@
/**
* Implementation of the ECMA-376 and MS-propritary document encryptions<p>
*
- * The implementation is split into the following packages:<p>
+ * The implementation is split into the following packages:
*
* <ul>
* <li>This package contains common functions for both current implemented cipher modes.</li>
Modified: poi/trunk/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryEntry.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryEntry.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryEntry.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryEntry.java Fri May 21 21:22:40 2021
@@ -32,9 +32,7 @@ import org.apache.poi.hpsf.ClassID;
* managed by a Filesystem instance.
*/
-public interface DirectoryEntry
- extends Entry, Iterable<Entry>
-{
+public interface DirectoryEntry extends Entry, Iterable<Entry> {
/**
* get an iterator of the Entry instances contained directly in
@@ -47,7 +45,7 @@ public interface DirectoryEntry
* implementations of Entry.
*/
- public Iterator<Entry> getEntries();
+ Iterator<Entry> getEntries();
/**
* get the names of all the Entries contained directly in this
@@ -58,7 +56,7 @@ public interface DirectoryEntry
* getEntry(String), which may be empty (if this
* DirectoryEntry is empty)
*/
- public Set<String> getEntryNames();
+ Set<String> getEntryNames();
/**
* is this DirectoryEntry empty?
@@ -66,7 +64,7 @@ public interface DirectoryEntry
* @return true if this instance contains no Entry instances
*/
- public boolean isEmpty();
+ boolean isEmpty();
/**
* find out how many Entry instances are contained directly within
@@ -76,13 +74,13 @@ public interface DirectoryEntry
* Entry instances
*/
- public int getEntryCount();
+ int getEntryCount();
/**
* Checks if entry with specified name present
*/
- public boolean hasEntry( final String name );
+ boolean hasEntry( final String name );
/**
* get a specified Entry by name
@@ -96,8 +94,7 @@ public interface DirectoryEntry
* name exists in this DirectoryEntry
*/
- public Entry getEntry(final String name)
- throws FileNotFoundException;
+ Entry getEntry(final String name) throws FileNotFoundException;
/**
* create a new DocumentEntry
@@ -107,12 +104,9 @@ public interface DirectoryEntry
* DocumentEntry
*
* @return the new DocumentEntry
- *
- * @exception IOException
*/
- public DocumentEntry createDocument(final String name,
- final InputStream stream)
+ DocumentEntry createDocument(final String name, final InputStream stream)
throws IOException;
/**
@@ -123,12 +117,9 @@ public interface DirectoryEntry
* @param writer the writer of the new DocumentEntry
*
* @return the new DocumentEntry
- *
- * @exception IOException
*/
- public DocumentEntry createDocument(final String name, final int size,
- final POIFSWriterListener writer)
+ DocumentEntry createDocument(final String name, final int size, final POIFSWriterListener writer)
throws IOException;
/**
@@ -137,26 +128,21 @@ public interface DirectoryEntry
* @param name the name of the new DirectoryEntry
*
* @return the new DirectoryEntry
- *
- * @exception IOException
*/
-
- public DirectoryEntry createDirectory(final String name)
- throws IOException;
+ DirectoryEntry createDirectory(final String name) throws IOException;
/**
* Gets the storage clsid of the directory entry
*
* @return storage Class ID
*/
- public ClassID getStorageClsid();
+ ClassID getStorageClsid();
/**
* Sets the storage clsid for the directory entry
*
* @param clsidStorage storage Class ID
*/
- public void setStorageClsid(ClassID clsidStorage);
-
-} // end public interface DirectoryEntry
+ void setStorageClsid(ClassID clsidStorage);
+}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryNode.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryNode.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryNode.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/poifs/filesystem/DirectoryNode.java Fri May 21 21:22:40 2021
@@ -250,20 +250,22 @@ public class DirectoryNode
* implementations of Entry.
*/
+ @Override
public Iterator<Entry> getEntries()
{
return _entries.iterator();
}
-
+
/**
* get the names of all the Entries contained directly in this
* instance (in other words, names of children only; no grandchildren
* etc).
*
* @return the names of all the entries that may be retrieved with
- * getEntry(String), which may be empty (if this
+ * getEntry(String), which may be empty (if this
* DirectoryEntry is empty)
*/
+ @Override
public Set<String> getEntryNames()
{
return _byname.keySet();
@@ -275,6 +277,7 @@ public class DirectoryNode
* @return true if this instance contains no Entry instances
*/
+ @Override
public boolean isEmpty()
{
return _entries.isEmpty();
@@ -288,11 +291,13 @@ public class DirectoryNode
* Entry instances
*/
+ @Override
public int getEntryCount()
{
return _entries.size();
}
+ @Override
public boolean hasEntry( String name )
{
return name != null && _byname.containsKey( name );
@@ -310,6 +315,7 @@ public class DirectoryNode
* name exists in this DirectoryEntry
*/
+ @Override
public Entry getEntry(final String name) throws FileNotFoundException {
Entry rval = null;
@@ -345,6 +351,7 @@ public class DirectoryNode
* @exception IOException if the document can't be created
*/
+ @Override
public DocumentEntry createDocument(final String name,
final InputStream stream)
throws IOException
@@ -364,6 +371,7 @@ public class DirectoryNode
* @exception IOException if the document can't be created
*/
+ @Override
public DocumentEntry createDocument(final String name, final int size,
final POIFSWriterListener writer)
throws IOException
@@ -381,6 +389,7 @@ public class DirectoryNode
* @exception IOException if the directory can't be created
*/
+ @Override
public DirectoryEntry createDirectory(final String name)
throws IOException
{
@@ -396,7 +405,7 @@ public class DirectoryNode
}
/**
- * Set the contents of a document, creating if needed,
+ * Set the contents of a document, creating if needed,
* otherwise updating. Returns the created / updated DocumentEntry
*
* @param name the name of the new or existing DocumentEntry
@@ -420,12 +429,13 @@ public class DirectoryNode
return existing;
}
}
-
+
/**
* Gets the storage clsid of the directory entry
*
* @return storage Class ID
*/
+ @Override
public ClassID getStorageClsid()
{
return getProperty().getStorageClsid();
@@ -436,6 +446,7 @@ public class DirectoryNode
*
* @param clsidStorage storage Class ID
*/
+ @Override
public void setStorageClsid(ClassID clsidStorage)
{
getProperty().setStorageClsid(clsidStorage);
@@ -485,6 +496,7 @@ public class DirectoryNode
* @return an array of Object; may not be null, but may be empty
*/
+ @Override
public Object [] getViewableArray()
{
return new Object[ 0 ];
@@ -497,6 +509,7 @@ public class DirectoryNode
* @return an Iterator; may not be null, but may have an empty
* back end store
*/
+ @Override
public Iterator<Object> getViewableIterator() {
List<Object> components = new ArrayList<>();
@@ -513,6 +526,7 @@ public class DirectoryNode
* a viewer should call getViewableIterator
*/
+ @Override
public boolean preferArray()
{
return false;
@@ -525,6 +539,7 @@ public class DirectoryNode
* @return short description
*/
+ @Override
public String getShortDescription()
{
return getName();
@@ -533,6 +548,7 @@ public class DirectoryNode
/**
* Returns an Iterator over all the entries
*/
+ @Override
public Iterator<Entry> iterator() {
return getEntries();
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/poifs/filesystem/FilteringDirectoryNode.java Fri May 21 21:22:40 2021
@@ -45,13 +45,13 @@ public class FilteringDirectoryNode impl
/**
* The names of our entries to exclude
*/
- private Set<String> excludes;
+ private final Set<String> excludes;
/**
* Excludes of our child directories
*/
- private Map<String,List<String>> childExcludes;
+ private final Map<String,List<String>> childExcludes;
- private DirectoryEntry directory;
+ private final DirectoryEntry directory;
/**
* Creates a filter round the specified directory, which
@@ -88,28 +88,34 @@ public class FilteringDirectoryNode impl
}
}
+ @Override
public DirectoryEntry createDirectory(String name) throws IOException {
return directory.createDirectory(name);
}
+ @Override
public DocumentEntry createDocument(String name, InputStream stream)
throws IOException {
return directory.createDocument(name, stream);
}
+ @Override
public DocumentEntry createDocument(String name, int size,
POIFSWriterListener writer) throws IOException {
return directory.createDocument(name, size, writer);
}
+ @Override
public Iterator<Entry> getEntries() {
return new FilteringIterator();
}
+ @Override
public Iterator<Entry> iterator() {
return getEntries();
}
+ @Override
public int getEntryCount() {
int size = directory.getEntryCount();
for (String excl : excludes) {
@@ -120,6 +126,7 @@ public class FilteringDirectoryNode impl
return size;
}
+ @Override
public Set<String> getEntryNames() {
Set<String> names = new HashSet<>();
for (String name : directory.getEntryNames()) {
@@ -130,10 +137,12 @@ public class FilteringDirectoryNode impl
return names;
}
+ @Override
public boolean isEmpty() {
return (getEntryCount() == 0);
}
+ @Override
public boolean hasEntry(String name) {
if (excludes.contains(name)) {
return false;
@@ -141,6 +150,7 @@ public class FilteringDirectoryNode impl
return directory.hasEntry(name);
}
+ @Override
public Entry getEntry(String name) throws FileNotFoundException {
if (excludes.contains(name)) {
throw new FileNotFoundException(name);
@@ -158,40 +168,48 @@ public class FilteringDirectoryNode impl
return entry;
}
+ @Override
public ClassID getStorageClsid() {
return directory.getStorageClsid();
}
+ @Override
public void setStorageClsid(ClassID clsidStorage) {
directory.setStorageClsid(clsidStorage);
}
+ @Override
public boolean delete() {
return directory.delete();
}
+ @Override
public boolean renameTo(String newName) {
return directory.renameTo(newName);
}
+ @Override
public String getName() {
return directory.getName();
}
+ @Override
public DirectoryEntry getParent() {
return directory.getParent();
}
+ @Override
public boolean isDirectoryEntry() {
return true;
}
+ @Override
public boolean isDocumentEntry() {
return false;
}
private class FilteringIterator implements Iterator<Entry> {
- private Iterator<Entry> parent;
+ private final Iterator<Entry> parent;
private Entry next;
private FilteringIterator() {
@@ -209,10 +227,12 @@ public class FilteringDirectoryNode impl
}
}
+ @Override
public boolean hasNext() {
return (next != null);
}
+ @Override
public Entry next() {
if (!hasNext()) {
throw new NoSuchElementException();
@@ -223,6 +243,7 @@ public class FilteringDirectoryNode impl
return e;
}
+ @Override
public void remove() {
throw new UnsupportedOperationException("Remove not supported");
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/sl/usermodel/Sheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/sl/usermodel/Sheet.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/sl/usermodel/Sheet.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/sl/usermodel/Sheet.java Fri May 21 21:22:40 2021
@@ -35,15 +35,13 @@ public interface Sheet<
* check this setting in the sheet XML
*/
boolean getFollowMasterGraphics();
-
+
MasterSheet<S,P> getMasterSheet();
Background<S,P> getBackground();
-
+
/**
* Convenience method to draw a sheet to a graphics context
- *
- * @param graphics
*/
void draw(Graphics2D graphics);
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/format/SimpleFraction.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/format/SimpleFraction.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/format/SimpleFraction.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/format/SimpleFraction.java Fri May 21 21:22:40 2021
@@ -59,14 +59,13 @@ public class SimpleFraction {
* <li><a href="http://mathworld.wolfram.com/ContinuedFraction.html">
* Continued Fraction</a> equations (11) and (22)-(26)</li>
* </ul>
- * </p>
*
* Based on org.apache.commons.math.fraction.Fraction from Apache Commons-Math.
* YK: The only reason of having this class is to avoid dependency on the Commons-Math jar.
*
* @param value the double value to convert to a fraction.
* @param epsilon maximum error allowed. The resulting fraction is within
- * <code>epsilon</code> of <code>value</code>, in absolute terms.
+ * {@code epsilon} of {@code value}, in absolute terms.
* @param maxDenominator maximum denominator value allowed.
* @param maxIterations maximum number of convergents
* @throws RuntimeException if the continued fraction failed to
@@ -79,7 +78,7 @@ public class SimpleFraction {
double r0 = value;
long a0 = (long)Math.floor(r0);
if (a0 > overflow) {
- throw new IllegalArgumentException("Overflow trying to convert "+value+" to fraction ("+a0+"/"+1l+")");
+ throw new IllegalArgumentException("Overflow trying to convert "+value+" to fraction ("+a0+"/"+ 1L +")");
}
// check for (almost) integer arguments, which should not go
@@ -141,7 +140,7 @@ public class SimpleFraction {
/**
* Create a fraction given a numerator and denominator.
- * @param numerator
+ * @param numerator the numerator
* @param denominator maxDenominator The maximum allowed value for denominator
*/
public SimpleFraction(int numerator, int denominator)
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/BaseFormulaEvaluator.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/BaseFormulaEvaluator.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/BaseFormulaEvaluator.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/BaseFormulaEvaluator.java Fri May 21 21:22:40 2021
@@ -29,7 +29,7 @@ import org.apache.poi.ss.usermodel.Sheet
import org.apache.poi.ss.usermodel.Workbook;
/**
- * Common functionality across file formats for evaluating formula cells.<p>
+ * Common functionality across file formats for evaluating formula cells.
*/
public abstract class BaseFormulaEvaluator implements FormulaEvaluator, WorkbookEvaluatorProvider {
protected final WorkbookEvaluator _bookEvaluator;
@@ -91,8 +91,8 @@ public abstract class BaseFormulaEvaluat
* evaluateInCell() when the call should not modify the contents of the
* original cell.
*
- * @param cell may be <code>null</code> signifying that the cell is not present (or blank)
- * @return <code>null</code> if the supplied cell is <code>null</code> or blank
+ * @param cell may be {@code null} signifying that the cell is not present (or blank)
+ * @return {@code null} if the supplied cell is {@code null} or blank
*/
@Override
public CellValue evaluate(Cell cell) {
@@ -281,13 +281,11 @@ public abstract class BaseFormulaEvaluat
}
}
- /** {@inheritDoc} */
@Override
public void setIgnoreMissingWorkbooks(boolean ignore){
_bookEvaluator.setIgnoreMissingWorkbooks(ignore);
}
- /** {@inheritDoc} */
@Override
public void setDebugEvaluationOutputForNextEval(boolean value){
_bookEvaluator.setDebugEvaluationOutputForNextEval(value);
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/CacheAreaEval.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/CacheAreaEval.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/CacheAreaEval.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/CacheAreaEval.java Fri May 21 21:22:40 2021
@@ -31,47 +31,50 @@ import org.apache.poi.ss.util.CellRefere
*/
public final class CacheAreaEval extends AreaEvalBase {
-
+
/* Value Containter */
private final ValueEval[] _values;
-
+
public CacheAreaEval(AreaI ptg, ValueEval[] values) {
super(ptg);
_values = values;
}
-
+
public CacheAreaEval(int firstRow, int firstColumn, int lastRow, int lastColumn, ValueEval[] values) {
super(firstRow, firstColumn, lastRow, lastColumn);
_values = values;
}
-
+
+ @Override
public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) {
return getRelativeValue(-1, relativeRowIndex, relativeColumnIndex);
}
-
+
+ @Override
public ValueEval getRelativeValue(int sheetIndex, int relativeRowIndex, int relativeColumnIndex) {
int oneDimensionalIndex = relativeRowIndex * getWidth() + relativeColumnIndex;
return _values[oneDimensionalIndex];
}
+ @Override
public AreaEval offset(int relFirstRowIx, int relLastRowIx,
int relFirstColIx, int relLastColIx) {
-
+
AreaI area = new OffsetArea(getFirstRow(), getFirstColumn(),
relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
-
+
int height = area.getLastRow() - area.getFirstRow() + 1;
int width = area.getLastColumn() - area.getFirstColumn() + 1;
ValueEval[] newVals = new ValueEval[height * width];
-
+
int startRow = area.getFirstRow() - getFirstRow();
int startCol = area.getFirstColumn() - getFirstColumn();
-
+
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
ValueEval temp;
-
+
/* CacheAreaEval is only temporary value representation, does not equal sheet selection
* so any attempts going beyond the selection results in BlankEval
*/
@@ -81,13 +84,14 @@ public final class CacheAreaEval extends
else {
temp = _values[(startRow + j) * getWidth() + (startCol + i)];
}
- newVals[j * width + i] = temp;
+ newVals[j * width + i] = temp;
}
}
return new CacheAreaEval(area, newVals);
}
+ @Override
public TwoDEval getRow(int rowIndex) {
if (rowIndex >= getHeight()) {
throw new IllegalArgumentException("Invalid rowIndex " + rowIndex
@@ -95,13 +99,14 @@ public final class CacheAreaEval extends
}
int absRowIndex = getFirstRow() + rowIndex;
ValueEval[] values = new ValueEval[getWidth()];
-
+
for (int i = 0; i < values.length; i++) {
values[i] = getRelativeValue(rowIndex, i);
}
return new CacheAreaEval(absRowIndex, getFirstColumn() , absRowIndex, getLastColumn(), values);
}
+ @Override
public TwoDEval getColumn(int columnIndex) {
if (columnIndex >= getWidth()) {
throw new IllegalArgumentException("Invalid columnIndex " + columnIndex
@@ -109,14 +114,14 @@ public final class CacheAreaEval extends
}
int absColIndex = getFirstColumn() + columnIndex;
ValueEval[] values = new ValueEval[getHeight()];
-
+
for (int i = 0; i < values.length; i++) {
values[i] = getRelativeValue(i, columnIndex);
}
-
+
return new CacheAreaEval(getFirstRow(), absColIndex, getLastRow(), absColIndex, values);
}
-
+
public String toString() {
CellReference crA = new CellReference(getFirstRow(), getFirstColumn());
CellReference crB = new CellReference(getLastRow(), getLastColumn());
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/ConditionalFormattingEvaluator.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/ConditionalFormattingEvaluator.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/ConditionalFormattingEvaluator.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/ConditionalFormattingEvaluator.java Fri May 21 21:22:40 2021
@@ -38,17 +38,15 @@ import org.apache.poi.ss.util.CellRefere
/**
* Evaluates Conditional Formatting constraints.<p>
*
- * For performance reasons, this class keeps a cache of all previously evaluated rules and cells.
+ * For performance reasons, this class keeps a cache of all previously evaluated rules and cells.
* Be sure to call {@link #clearAllCachedFormats()} if any conditional formats are modified, added, or deleted,
* and {@link #clearAllCachedValues()} whenever cell values change.
- * <p>
- *
*/
public class ConditionalFormattingEvaluator {
private final WorkbookEvaluator workbookEvaluator;
private final Workbook workbook;
-
+
/**
* All the underlying structures, for both HSSF and XSSF, repeatedly go to the raw bytes/XML for the
* different pieces used in the ConditionalFormatting* structures. That's highly inefficient,
@@ -56,12 +54,12 @@ public class ConditionalFormattingEvalua
* <p>
* Instead we need a cached version that is discarded when definitions change.
* <p>
- * Sheets don't implement equals, and since its an interface,
+ * Sheets don't implement equals, and since its an interface,
* there's no guarantee instances won't be recreated on the fly by some implementation.
* So we use sheet name.
*/
private final Map<String, List<EvaluationConditionalFormatRule>> formats = new HashMap<>();
-
+
/**
* Evaluating rules for cells in their region(s) is expensive, so we want to cache them,
* and empty/reevaluate the cache when values change.
@@ -76,21 +74,21 @@ public class ConditionalFormattingEvalua
this.workbook = wb;
this.workbookEvaluator = provider._getWorkbookEvaluator();
}
-
+
protected WorkbookEvaluator getWorkbookEvaluator() {
return workbookEvaluator;
}
-
+
/**
- * Call this whenever rules are added, reordered, or removed, or a rule formula is changed
+ * Call this whenever rules are added, reordered, or removed, or a rule formula is changed
* (not the formula inputs but the formula expression itself)
*/
public void clearAllCachedFormats() {
formats.clear();
}
-
+
/**
- * Call this whenever cell values change in the workbook, so condional formats are re-evaluated
+ * Call this whenever cell values change in the workbook, so condional formats are re-evaluated
* for all cells.
* <p>
* TODO: eventually this should work like {@link EvaluationCache#notifyUpdateCell(int, int, EvaluationCell)}
@@ -102,7 +100,7 @@ public class ConditionalFormattingEvalua
/**
* lazy load by sheet since reading can be expensive
- *
+ *
* @param sheet The sheet to look at
* @return unmodifiable list of rules
*/
@@ -131,43 +129,43 @@ public class ConditionalFormattingEvalua
}
return Collections.unmodifiableList(rules);
}
-
+
/**
- * This checks all applicable {@link ConditionalFormattingRule}s for the cell's sheet,
+ * This checks all applicable {@link ConditionalFormattingRule}s for the cell's sheet,
* in defined "priority" order, returning the matches if any. This is a property currently
- * not exposed from <code>CTCfRule</code> in <code>XSSFConditionalFormattingRule</code>.
+ * not exposed from {@code CTCfRule} in {@code XSSFConditionalFormattingRule}.
* <p>
* Most cells will have zero or one applied rule, but it is possible to define multiple rules
* that apply at the same time to the same cell, thus the List result.
* <p>
- * Note that to properly apply conditional rules, care must be taken to offset the base
+ * Note that to properly apply conditional rules, care must be taken to offset the base
* formula by the relative position of the current cell, or the wrong value is checked.
* This is handled by {@link WorkbookEvaluator#evaluate(String, CellReference, CellRangeAddressBase)}.
* <p>
* If the cell exists and is a formula cell, its cached value may be used for rule evaluation, so
- * make sure it is up to date. If values have changed, it is best to call
+ * make sure it is up to date. If values have changed, it is best to call
* {@link FormulaEvaluator#evaluateFormulaCell(Cell)} or {@link FormulaEvaluator#evaluateAll()} first,
- * or the wrong conditional results may be returned.
- *
+ * or the wrong conditional results may be returned.
+ *
* @param cellRef NOTE: if no sheet name is specified, this uses the workbook active sheet
* @return Unmodifiable List of {@link EvaluationConditionalFormatRule}s that apply to the current cell value,
- * in priority order, as evaluated by Excel (smallest priority # for XSSF, definition order for HSSF),
+ * in priority order, as evaluated by Excel (smallest priority # for XSSF, definition order for HSSF),
* or null if none apply
*/
public List<EvaluationConditionalFormatRule> getConditionalFormattingForCell(final CellReference cellRef) {
List<EvaluationConditionalFormatRule> rules = values.get(cellRef);
-
+
if (rules == null) {
// compute and cache them
rules = new ArrayList<>();
-
+
final Sheet sheet;
if (cellRef.getSheetName() != null) {
sheet = workbook.getSheet(cellRef.getSheetName());
} else {
sheet = workbook.getSheetAt(workbook.getActiveSheetIndex());
}
-
+
/*
* Per Excel help:
* https://support.office.com/en-us/article/Manage-conditional-formatting-rule-precedence-e09711a3-48df-4bcb-b82c-9d8b8b22463d#__toc269129417
@@ -176,7 +174,7 @@ public class ConditionalFormattingEvalua
*/
boolean stopIfTrue = false;
for (EvaluationConditionalFormatRule rule : getRules(sheet)) {
-
+
if (stopIfTrue) {
continue; // a previous rule matched and wants no more evaluations
}
@@ -189,40 +187,40 @@ public class ConditionalFormattingEvalua
Collections.sort(rules);
values.put(cellRef, rules);
}
-
+
return Collections.unmodifiableList(rules);
}
-
+
/**
- * This checks all applicable {@link ConditionalFormattingRule}s for the cell's sheet,
+ * This checks all applicable {@link ConditionalFormattingRule}s for the cell's sheet,
* in defined "priority" order, returning the matches if any. This is a property currently
- * not exposed from <code>CTCfRule</code> in <code>XSSFConditionalFormattingRule</code>.
+ * not exposed from {@code CTCfRule} in {@code XSSFConditionalFormattingRule}.
* <p>
* Most cells will have zero or one applied rule, but it is possible to define multiple rules
* that apply at the same time to the same cell, thus the List result.
* <p>
- * Note that to properly apply conditional rules, care must be taken to offset the base
+ * Note that to properly apply conditional rules, care must be taken to offset the base
* formula by the relative position of the current cell, or the wrong value is checked.
* This is handled by {@link WorkbookEvaluator#evaluate(String, CellReference, CellRangeAddressBase)}.
* <p>
* If the cell exists and is a formula cell, its cached value may be used for rule evaluation, so
- * make sure it is up to date. If values have changed, it is best to call
+ * make sure it is up to date. If values have changed, it is best to call
* {@link FormulaEvaluator#evaluateFormulaCell(Cell)} or {@link FormulaEvaluator#evaluateAll()} first,
- * or the wrong conditional results may be returned.
- *
+ * or the wrong conditional results may be returned.
+ *
* @param cell The cell to look for
* @return Unmodifiable List of {@link EvaluationConditionalFormatRule}s that apply to the current cell value,
- * in priority order, as evaluated by Excel (smallest priority # for XSSF, definition order for HSSF),
+ * in priority order, as evaluated by Excel (smallest priority # for XSSF, definition order for HSSF),
* or null if none apply
*/
public List<EvaluationConditionalFormatRule> getConditionalFormattingForCell(Cell cell) {
return getConditionalFormattingForCell(getRef(cell));
}
-
+
public static CellReference getRef(Cell cell) {
return new CellReference(cell.getSheet().getSheetName(), cell.getRowIndex(), cell.getColumnIndex(), false, false);
}
-
+
/**
* Retrieve all formatting rules for the sheet with the given name.
*
@@ -232,7 +230,7 @@ public class ConditionalFormattingEvalua
public List<EvaluationConditionalFormatRule> getFormatRulesForSheet(String sheetName) {
return getFormatRulesForSheet(workbook.getSheet(sheetName));
}
-
+
/**
* Retrieve all formatting rules for the given sheet.
*
@@ -242,7 +240,7 @@ public class ConditionalFormattingEvalua
public List<EvaluationConditionalFormatRule> getFormatRulesForSheet(Sheet sheet) {
return getRules(sheet);
}
-
+
/**
* Conditional formatting rules can apply only to cells in the sheet to which they are attached.
* The POI data model does not have a back-reference to the owning sheet, so it must be passed in separately.
@@ -262,7 +260,7 @@ public class ConditionalFormattingEvalua
}
return Collections.emptyList();
}
-
+
/**
* Retrieve all cells where the given formatting rule evaluates to true.
*
@@ -272,7 +270,7 @@ public class ConditionalFormattingEvalua
public List<Cell> getMatchingCells(EvaluationConditionalFormatRule rule) {
final List<Cell> cells = new ArrayList<>();
final Sheet sheet = rule.getSheet();
-
+
for (CellRangeAddress region : rule.getRegions()) {
for (int r = region.getFirstRow(); r <= region.getLastRow(); r++) {
final Row row = sheet.getRow(r);
@@ -284,7 +282,7 @@ public class ConditionalFormattingEvalua
if (cell == null) {
continue;
}
-
+
List<EvaluationConditionalFormatRule> cellRules = getConditionalFormattingForCell(cell);
if (cellRules.contains(rule)) {
cells.add(cell);
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationConditionalFormatRule.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationConditionalFormatRule.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationConditionalFormatRule.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationConditionalFormatRule.java Fri May 21 21:22:40 2021
@@ -29,6 +29,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.function.Function;
import org.apache.poi.ss.formula.eval.BlankEval;
import org.apache.poi.ss.formula.eval.BoolEval;
@@ -102,12 +103,7 @@ public class EvaluationConditionalFormat
private final DecimalFormat decimalTextFormat;
/**
- *
- * @param workbookEvaluator
- * @param sheet
- * @param formatting
* @param formattingIndex for priority, zero based
- * @param rule
* @param ruleIndex for priority, zero based, if this is an HSSF rule. Unused for XSSF rules
* @param regions could be read from formatting, but every call creates new objects in a new array.
* this allows calling it once per formatting instance, and re-using the array.
@@ -241,7 +237,6 @@ public class EvaluationConditionalFormat
/**
* Defined as equal sheet name and formatting and rule indexes
- * @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
@@ -263,7 +258,6 @@ public class EvaluationConditionalFormat
* <p>
* HSSF priority is based on definition/persistence order.
*
- * @param o
* @return comparison based on sheet name, formatting index, and rule priority
*/
@Override
@@ -294,7 +288,6 @@ public class EvaluationConditionalFormat
}
/**
- * @param ref
* @return true if this rule evaluates to true for the given cell
*/
/* package */ boolean matches(CellReference ref) {
@@ -448,74 +441,15 @@ public class EvaluationConditionalFormat
return false;
}
- return getMeaningfulValues(region, false, new ValueFunction() {
- @Override
- public Set<ValueAndFormat> evaluate(List<ValueAndFormat> allValues) {
- final ConditionFilterData conf = rule.getFilterConfiguration();
-
- if (! conf.getBottom()) {
- allValues.sort(Collections.reverseOrder());
- } else {
- Collections.sort(allValues);
- }
-
- int limit = Math.toIntExact(conf.getRank());
- if (conf.getPercent()) {
- limit = allValues.size() * limit / 100;
- }
- if (allValues.size() <= limit) {
- return new HashSet<>(allValues);
- }
-
- return new HashSet<>(allValues.subList(0, limit));
- }
- }).contains(cv);
+ return getMeaningfulValues(region, false, this::evaluateTop10).contains(cv);
case UNIQUE_VALUES:
// Per Excel help, "duplicate" means matching value AND format
// https://support.office.com/en-us/article/Filter-for-unique-values-or-remove-duplicate-values-ccf664b0-81d6-449b-bbe1-8daaec1e83c2
- return getMeaningfulValues(region, true, new ValueFunction() {
- @Override
- public Set<ValueAndFormat> evaluate(List<ValueAndFormat> allValues) {
- Collections.sort(allValues);
-
- final Set<ValueAndFormat> unique = new HashSet<>();
-
- for (int i = 0; i < allValues.size(); i++) {
- final ValueAndFormat v = allValues.get(i);
- // skip this if the current value matches the next one, or is the last one and matches the previous one
- if ( (i < allValues.size()-1 && v.equals(allValues.get(i+1)) ) || ( i > 0 && i == allValues.size()-1 && v.equals(allValues.get(i-1)) ) ) {
- // current value matches next value, skip both
- i++;
- continue;
- }
- unique.add(v);
- }
-
- return unique;
- }
- }).contains(cv);
+ return getMeaningfulValues(region, true, this::evaluateUniqueValues).contains(cv);
case DUPLICATE_VALUES:
// Per Excel help, "duplicate" means matching value AND format
// https://support.office.com/en-us/article/Filter-for-unique-values-or-remove-duplicate-values-ccf664b0-81d6-449b-bbe1-8daaec1e83c2
- return getMeaningfulValues(region, true, new ValueFunction() {
- @Override
- public Set<ValueAndFormat> evaluate(List<ValueAndFormat> allValues) {
- Collections.sort(allValues);
-
- final Set<ValueAndFormat> dup = new HashSet<>();
-
- for (int i = 0; i < allValues.size(); i++) {
- final ValueAndFormat v = allValues.get(i);
- // skip this if the current value matches the next one, or is the last one and matches the previous one
- if ( (i < allValues.size()-1 && v.equals(allValues.get(i+1)) ) || ( i > 0 && i == allValues.size()-1 && v.equals(allValues.get(i-1)) ) ) {
- // current value matches next value, add one
- dup.add(v);
- i++;
- }
- }
- return dup;
- }
- }).contains(cv);
+ return getMeaningfulValues(region, true, this::evaluateDuplicateValues).contains(cv);
case ABOVE_AVERAGE:
// from testing, Excel only operates on numbers and dates (which are stored as numbers) in the range.
// numbers stored as text are ignored, but numbers formatted as text are treated as numbers.
@@ -523,33 +457,15 @@ public class EvaluationConditionalFormat
final ConditionFilterData conf = rule.getFilterConfiguration();
// actually ordered, so iteration order is predictable
- List<ValueAndFormat> values = new ArrayList<>(getMeaningfulValues(region, false, new ValueFunction() {
- @Override
- public Set<ValueAndFormat> evaluate(List<ValueAndFormat> allValues) {
- double total = 0;
- ValueEval[] pop = new ValueEval[allValues.size()];
- for (int i = 0; i < allValues.size(); i++) {
- ValueAndFormat v = allValues.get(i);
- total += v.value.doubleValue();
- pop[i] = new NumberEval(v.value.doubleValue());
- }
-
- final Set<ValueAndFormat> avgSet = new LinkedHashSet<>(1);
- avgSet.add(new ValueAndFormat(Double.valueOf(allValues.size() == 0 ? 0 : total / allValues.size()), null, decimalTextFormat));
-
- final double stdDev = allValues.size() <= 1 ? 0 : ((NumberEval) AggregateFunction.STDEV.evaluate(pop, 0, 0)).getNumberValue();
- avgSet.add(new ValueAndFormat(Double.valueOf(stdDev), null, decimalTextFormat));
- return avgSet;
- }
- }));
+ List<ValueAndFormat> values = new ArrayList<>(getMeaningfulValues(region, false, this::evaluateAboveAverage));
Double val = cv.isNumber() ? cv.getValue() : null;
if (val == null) {
return false;
}
- double avg = values.get(0).value.doubleValue();
- double stdDev = values.get(1).value.doubleValue();
+ double avg = values.get(0).value;
+ double stdDev = values.get(1).value;
/*
* use StdDev, aboveAverage, equalAverage to find:
@@ -557,7 +473,7 @@ public class EvaluationConditionalFormat
* operator type
*/
- Double comp = Double.valueOf(conf.getStdDev() > 0 ? (avg + (conf.getAboveAverage() ? 1 : -1) * stdDev * conf.getStdDev()) : avg) ;
+ Double comp = conf.getStdDev() > 0 ? (avg + (conf.getAboveAverage() ? 1 : -1) * stdDev * conf.getStdDev()) : avg;
final OperatorEnum op;
if (conf.getAboveAverage()) {
@@ -576,10 +492,10 @@ public class EvaluationConditionalFormat
return op.isValid(val, comp, null);
case CONTAINS_TEXT:
// implemented both by a cfRule "text" attribute and a formula. Use the text.
- return text == null ? false : cv.toString().toLowerCase(LocaleUtil.getUserLocale()).contains(lowerText);
+ return text != null && cv.toString().toLowerCase(LocaleUtil.getUserLocale()).contains(lowerText);
case NOT_CONTAINS_TEXT:
// implemented both by a cfRule "text" attribute and a formula. Use the text.
- return text == null ? true : ! cv.toString().toLowerCase(LocaleUtil.getUserLocale()).contains(lowerText);
+ return text == null || !cv.toString().toLowerCase(LocaleUtil.getUserLocale()).contains(lowerText);
case BEGINS_WITH:
// implemented both by a cfRule "text" attribute and a formula. Use the text.
return cv.toString().toLowerCase(LocaleUtil.getUserLocale()).startsWith(lowerText);
@@ -616,14 +532,88 @@ public class EvaluationConditionalFormat
}
}
+ private Set<ValueAndFormat> evaluateTop10(List<ValueAndFormat> allValues) {
+ final ConditionFilterData conf = rule.getFilterConfiguration();
+
+ if (! conf.getBottom()) {
+ allValues.sort(Collections.reverseOrder());
+ } else {
+ Collections.sort(allValues);
+ }
+
+ int limit = Math.toIntExact(conf.getRank());
+ if (conf.getPercent()) {
+ limit = allValues.size() * limit / 100;
+ }
+ if (allValues.size() <= limit) {
+ return new HashSet<>(allValues);
+ }
+
+ return new HashSet<>(allValues.subList(0, limit));
+ }
+
+ private Set<ValueAndFormat> evaluateUniqueValues(List<ValueAndFormat> allValues) {
+ Collections.sort(allValues);
+
+ final Set<ValueAndFormat> unique = new HashSet<>();
+
+ for (int i = 0; i < allValues.size(); i++) {
+ final ValueAndFormat v = allValues.get(i);
+ // skip this if the current value matches the next one, or is the last one and matches the previous one
+ if ( (i < allValues.size()-1 && v.equals(allValues.get(i+1)) ) || ( i > 0 && i == allValues.size()-1 && v.equals(allValues.get(i-1)) ) ) {
+ // current value matches next value, skip both
+ i++;
+ continue;
+ }
+ unique.add(v);
+ }
+
+ return unique;
+ }
+
+ public Set<ValueAndFormat> evaluateDuplicateValues(List<ValueAndFormat> allValues) {
+ Collections.sort(allValues);
+
+ final Set<ValueAndFormat> dup = new HashSet<>();
+
+ for (int i = 0; i < allValues.size(); i++) {
+ final ValueAndFormat v = allValues.get(i);
+ // skip this if the current value matches the next one, or is the last one and matches the previous one
+ if ( (i < allValues.size()-1 && v.equals(allValues.get(i+1)) ) || ( i > 0 && i == allValues.size()-1 && v.equals(allValues.get(i-1)) ) ) {
+ // current value matches next value, add one
+ dup.add(v);
+ i++;
+ }
+ }
+ return dup;
+ }
+
+ private Set<ValueAndFormat> evaluateAboveAverage(List<ValueAndFormat> allValues) {
+ double total = 0;
+ ValueEval[] pop = new ValueEval[allValues.size()];
+ for (int i = 0; i < allValues.size(); i++) {
+ ValueAndFormat v = allValues.get(i);
+ total += v.value;
+ pop[i] = new NumberEval(v.value);
+ }
+
+ final Set<ValueAndFormat> avgSet = new LinkedHashSet<>(1);
+ avgSet.add(new ValueAndFormat(allValues.size() == 0 ? 0 : total / allValues.size(), null, decimalTextFormat));
+
+ final double stdDev = allValues.size() <= 1 ? 0 : ((NumberEval) AggregateFunction.STDEV.evaluate(pop, 0, 0)).getNumberValue();
+ avgSet.add(new ValueAndFormat(stdDev, null, decimalTextFormat));
+ return avgSet;
+ }
+
/**
* from testing, Excel only operates on numbers and dates (which are stored as numbers) in the range.
* numbers stored as text are ignored, but numbers formatted as text are treated as numbers.
*
- * @param region
+ * @param func instances evaluate the values for a region and return the positive matches for the function type.
+ *
* @return the meaningful values in the range of cells specified
*/
- private Set<ValueAndFormat> getMeaningfulValues(CellRangeAddress region, boolean withText, ValueFunction func) {
+ private Set<ValueAndFormat> getMeaningfulValues(CellRangeAddress region, boolean withText, Function<List<ValueAndFormat>,Set<ValueAndFormat>> func) {
Set<ValueAndFormat> values = meaningfulRegionValues.get(region);
if (values != null) {
return values;
@@ -645,7 +635,7 @@ public class EvaluationConditionalFormat
}
}
- values = func.evaluate(allValues);
+ values = func.apply(allValues);
meaningfulRegionValues.put(region, values);
return values;
@@ -660,7 +650,7 @@ public class EvaluationConditionalFormat
}
switch (type) {
case NUMERIC:
- return new ValueAndFormat(Double.valueOf(cell.getNumericCellValue()), format, decimalTextFormat);
+ return new ValueAndFormat(cell.getNumericCellValue(), format, decimalTextFormat);
case STRING:
case BOOLEAN:
return new ValueAndFormat(cell.getStringCellValue(), format);
@@ -670,192 +660,6 @@ public class EvaluationConditionalFormat
}
return new ValueAndFormat("", "");
}
- /**
- * instances evaluate the values for a region and return the positive matches for the function type.
- * TODO: when we get to use Java 8, this is obviously a Lambda Function.
- */
- protected interface ValueFunction {
-
- /**
- *
- * @param values
- * @return the desired values for the rules implemented by the current instance
- */
- Set<ValueAndFormat> evaluate(List<ValueAndFormat> values);
- }
-
- /**
- * Not calling it OperatorType to avoid confusion for now with other classes.
- * Definition order matches OOXML type ID indexes.
- * Note that this has NO_COMPARISON as the first item, unlike the similar
- * DataValidation operator enum. Thanks, Microsoft.
- */
- public static enum OperatorEnum {
- NO_COMPARISON {
- /** always false/invalid */
- @Override
- public <C extends Comparable<C>> boolean isValid(C cellValue, C v1, C v2) {
- return false;
- }
- },
- BETWEEN {
- @Override
- public <C extends Comparable<C>> boolean isValid(C cellValue, C v1, C v2) {
- if (v1 == null) {
- if (cellValue instanceof Number) {
- // use zero for null
- double n1 = 0;
- double n2 = v2 == null ? 0 : ((Number) v2).doubleValue();
- return Double.compare( ((Number) cellValue).doubleValue(), n1) >= 0 && Double.compare(((Number) cellValue).doubleValue(), n2) <= 0;
- } else if (cellValue instanceof String) {
- String n1 = "";
- String n2 = v2 == null ? "" : (String) v2;
- return ((String) cellValue).compareToIgnoreCase(n1) >= 0 && ((String) cellValue).compareToIgnoreCase(n2) <= 0;
- } else if (cellValue instanceof Boolean) return false;
- return false; // just in case - not a typical possibility
- }
- return cellValue.compareTo(v1) >= 0 && cellValue.compareTo(v2) <= 0;
- }
- },
- NOT_BETWEEN {
- @Override
- public <C extends Comparable<C>> boolean isValid(C cellValue, C v1, C v2) {
- if (v1 == null) {
- if (cellValue instanceof Number) {
- // use zero for null
- double n1 = 0;
- double n2 = v2 == null ? 0 : ((Number) v2).doubleValue();
- return Double.compare( ((Number) cellValue).doubleValue(), n1) < 0 || Double.compare(((Number) cellValue).doubleValue(), n2) > 0;
- } else if (cellValue instanceof String) {
- String n1 = "";
- String n2 = v2 == null ? "" : (String) v2;
- return ((String) cellValue).compareToIgnoreCase(n1) < 0 || ((String) cellValue).compareToIgnoreCase(n2) > 0;
- } else if (cellValue instanceof Boolean) return true;
- return false; // just in case - not a typical possibility
- }
- return cellValue.compareTo(v1) < 0 || cellValue.compareTo(v2) > 0;
- }
-
- public boolean isValidForIncompatibleTypes() {
- return true;
- }
- },
- EQUAL {
- @Override
- public <C extends Comparable<C>> boolean isValid(C cellValue, C v1, C v2) {
- if (v1 == null) {
- if (cellValue instanceof Number) {
- // use zero for null
- return Double.compare( ((Number) cellValue).doubleValue(), 0) == 0;
- } else if (cellValue instanceof String) {
- return false; // even an empty string is not equal the empty cell, only another empty cell is, handled higher up
- } else if (cellValue instanceof Boolean) return false;
- return false; // just in case - not a typical possibility
- }
- // need to avoid instanceof, to work around a 1.6 compiler bug
- if (cellValue.getClass() == String.class) {
- return cellValue.toString().compareToIgnoreCase(v1.toString()) == 0;
- }
- return cellValue.compareTo(v1) == 0;
- }
- },
- NOT_EQUAL {
- @Override
- public <C extends Comparable<C>> boolean isValid(C cellValue, C v1, C v2) {
- if (v1 == null) {
- return true; // non-null not equal null, returns true
- }
- // need to avoid instanceof, to work around a 1.6 compiler bug
- if (cellValue.getClass() == String.class) {
- return cellValue.toString().compareToIgnoreCase(v1.toString()) == 0;
- }
- return cellValue.compareTo(v1) != 0;
- }
-
- public boolean isValidForIncompatibleTypes() {
- return true;
- }
- },
- GREATER_THAN {
- @Override
- public <C extends Comparable<C>> boolean isValid(C cellValue, C v1, C v2) {
- if (v1 == null) {
- if (cellValue instanceof Number) {
- // use zero for null
- return Double.compare( ((Number) cellValue).doubleValue(), 0) > 0;
- } else if (cellValue instanceof String) {
- return true; // non-null string greater than empty cell
- } else if (cellValue instanceof Boolean) return true;
- return false; // just in case - not a typical possibility
- }
- return cellValue.compareTo(v1) > 0;
- }
- },
- LESS_THAN {
- @Override
- public <C extends Comparable<C>> boolean isValid(C cellValue, C v1, C v2) {
- if (v1 == null) {
- if (cellValue instanceof Number) {
- // use zero for null
- return Double.compare( ((Number) cellValue).doubleValue(), 0) < 0;
- } else if (cellValue instanceof String) {
- return false; // non-null string greater than empty cell
- } else if (cellValue instanceof Boolean) return false;
- return false; // just in case - not a typical possibility
- }
- return cellValue.compareTo(v1) < 0;
- }
- },
- GREATER_OR_EQUAL {
- @Override
- public <C extends Comparable<C>> boolean isValid(C cellValue, C v1, C v2) {
- if (v1 == null) {
- if (cellValue instanceof Number) {
- // use zero for null
- return Double.compare( ((Number) cellValue).doubleValue(), 0) >= 0;
- } else if (cellValue instanceof String) {
- return true; // non-null string greater than empty cell
- } else if (cellValue instanceof Boolean) return true;
- return false; // just in case - not a typical possibility
- }
- return cellValue.compareTo(v1) >= 0;
- }
- },
- LESS_OR_EQUAL {
- @Override
- public <C extends Comparable<C>> boolean isValid(C cellValue, C v1, C v2) {
- if (v1 == null) {
- if (cellValue instanceof Number) {
- // use zero for null
- return Double.compare( ((Number) cellValue).doubleValue(), 0) <= 0;
- } else if (cellValue instanceof String) {
- return false; // non-null string not less than empty cell
- } else if (cellValue instanceof Boolean) return false; // for completeness
- return false; // just in case - not a typical possibility
- }
- return cellValue.compareTo(v1) <= 0;
- }
- },
- ;
-
- /**
- * Evaluates comparison using operator instance rules
- * @param cellValue won't be null, assumption is previous checks handled that
- * @param v1 if null, per Excel behavior various results depending on the type of cellValue and the specific enum instance
- * @param v2 null if not needed. If null when needed, various results, per Excel behavior
- * @return true if the comparison is valid
- */
- public abstract <C extends Comparable<C>> boolean isValid(C cellValue, C v1, C v2);
-
- /**
- * Called when the cell and comparison values are of different data types
- * Needed for negation operators, which should return true.
- * @return true if this comparison is true when the types to compare are different
- */
- public boolean isValidForIncompatibleTypes() {
- return false;
- }
- }
/**
* Note: this class has a natural ordering that is inconsistent with equals.
@@ -914,7 +718,6 @@ public class EvaluationConditionalFormat
/**
* Note: this class has a natural ordering that is inconsistent with equals.
- * @param o
* @return value comparison
*/
@Override
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationSheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationSheet.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationSheet.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/EvaluationSheet.java Fri May 21 21:22:40 2021
@@ -26,7 +26,7 @@ import org.apache.poi.util.Internal;
public interface EvaluationSheet {
/**
- * @return <code>null</code> if there is no cell at the specified coordinates
+ * @return {@code null} if there is no cell at the specified coordinates
*/
EvaluationCell getCell(int rowIndex, int columnIndex);
@@ -37,19 +37,18 @@ public interface EvaluationSheet {
* @see EvaluationWorkbook#clearAllCachedResultValues()
* @since POI 3.15 beta 3
*/
- public void clearAllCachedResultValues();
+ void clearAllCachedResultValues();
/**
* @return last row index referenced on this sheet, for evaluation optimization
* @since POI 4.0.0
*/
- public int getLastRowNum();
+ int getLastRowNum();
/**
* Used by SUBTOTAL and similar functions that have options to ignore hidden rows
- * @param rowIndex
* @return true if the row is hidden, false if not
* @since POI 4.1.0
*/
- public boolean isRowHidden(int rowIndex);
+ boolean isRowHidden(int rowIndex);
}
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaType.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaType.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaType.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/FormulaType.java Fri May 21 21:22:40 2021
@@ -21,59 +21,58 @@ import org.apache.poi.util.Internal;
/**
* Enumeration of various formula types.
- *
+ *
* See Sections 3 and 4.8 of https://www.openoffice.org/sc/excelfileformat.pdf
*/
@Internal
public enum FormulaType {
/** Regular cell formula */
CELL(true),
-
+
/**
* A Shared Formula ("{=SUM(A1:E1*{1,2,3,4,5}}")
- *
+ *
* Similar to an array formula, but stored in a SHAREDFMLA instead of ARRAY record as a file size optimization.
* See Section 4.8 of https://www.openoffice.org/sc/excelfileformat.pdf
*/
SHARED(true),
-
+
/**
* An Array formula ("{=SUM(A1:E1*{1,2,3,4,5}}")
* https://support.office.com/en-us/article/Guidelines-and-examples-of-array-formulas-7D94A64E-3FF3-4686-9372-ECFD5CAA57C7
*/
ARRAY(false),
-
+
/** Conditional formatting */
CONDFORMAT(true),
-
+
/** Named range */
NAMEDRANGE(false),
-
+
/**
* This constant is currently very specific. The exact differences from general data
* validation formulas or conditional format formulas is not known yet
*/
DATAVALIDATION_LIST(false);
-
+
/** formula is expected to return a single value vs. multiple values */
private final boolean isSingleValue ;
/**
* @since POI 3.15 beta 3.
*/
- private FormulaType(boolean singleValue) {
+ FormulaType(boolean singleValue) {
this.isSingleValue = singleValue;
}
-
+
/**
* @return true if this formula type only returns single values, false if it can return multiple values (arrays, ranges, etc.)
*/
public boolean isSingleValue() {
return isSingleValue;
}
-
+
/**
- * Used to transition from <code>int</code>s (possibly stored in the Excel file) to <code>FormulaType</code>s.
- * @param code
+ * Used to transition from {@code int}s (possibly stored in the Excel file) to {@code FormulaType}s.
* @return FormulaType
* @throws IllegalArgumentException if code is out of range
* @since POI 3.15 beta 3.
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/LazyAreaEval.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/LazyAreaEval.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/LazyAreaEval.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/LazyAreaEval.java Fri May 21 21:22:40 2021
@@ -41,23 +41,27 @@ final class LazyAreaEval extends AreaEva
_evaluator = evaluator;
}
- public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) {
+ @Override
+ public ValueEval getRelativeValue(int relativeRowIndex, int relativeColumnIndex) {
return getRelativeValue(getFirstSheetIndex(), relativeRowIndex, relativeColumnIndex);
}
- public ValueEval getRelativeValue(int sheetIndex, int relativeRowIndex, int relativeColumnIndex) {
+ @Override
+ public ValueEval getRelativeValue(int sheetIndex, int relativeRowIndex, int relativeColumnIndex) {
int rowIx = (relativeRowIndex + getFirstRow() ) ;
int colIx = (relativeColumnIndex + getFirstColumn() ) ;
return _evaluator.getEvalForCell(sheetIndex, rowIx, colIx);
}
+ @Override
public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
AreaI area = new OffsetArea(getFirstRow(), getFirstColumn(),
relFirstRowIx, relLastRowIx, relFirstColIx, relLastColIx);
return new LazyAreaEval(area, _evaluator);
}
- public LazyAreaEval getRow(int rowIndex) {
+ @Override
+ public LazyAreaEval getRow(int rowIndex) {
if (rowIndex >= getHeight()) {
throw new IllegalArgumentException("Invalid rowIndex " + rowIndex
+ ". Allowable range is (0.." + getHeight() + ").");
@@ -65,6 +69,7 @@ final class LazyAreaEval extends AreaEva
int absRowIx = getFirstRow() + rowIndex;
return new LazyAreaEval(absRowIx, getFirstColumn(), absRowIx, getLastColumn(), _evaluator);
}
+ @Override
public LazyAreaEval getColumn(int columnIndex) {
if (columnIndex >= getWidth()) {
throw new IllegalArgumentException("Invalid columnIndex " + columnIndex
@@ -89,17 +94,18 @@ final class LazyAreaEval extends AreaEva
/**
* @return whether cell at rowIndex and columnIndex is a subtotal
*/
- public boolean isSubTotal(int rowIndex, int columnIndex){
+ @Override
+ public boolean isSubTotal(int rowIndex, int columnIndex){
// delegate the query to the sheet evaluator which has access to internal ptgs
SheetRefEvaluator _sre = _evaluator.getSheetEvaluator(_evaluator.getFirstSheetIndex());
return _sre.isSubTotal(getFirstRow() + rowIndex, getFirstColumn() + columnIndex);
}
-
+
/**
* @return whether the row at rowIndex is hidden
- * @see org.apache.poi.ss.formula.eval.AreaEvalBase#isRowHidden(int)
*/
- public boolean isRowHidden(int rowIndex) {
+ @Override
+ public boolean isRowHidden(int rowIndex) {
// delegate the query to the sheet evaluator which has access to internal ptgs
SheetRefEvaluator _sre = _evaluator.getSheetEvaluator(_evaluator.getFirstSheetIndex());
return _sre.isRowHidden(getFirstRow() + rowIndex);
Added: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/OperatorEnum.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/OperatorEnum.java?rev=1890089&view=auto
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/OperatorEnum.java (added)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/OperatorEnum.java Fri May 21 21:22:40 2021
@@ -0,0 +1,198 @@
+/* ====================================================================
+ 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;
+
+import org.apache.poi.util.Internal;
+
+/**
+ * Not calling it OperatorType to avoid confusion for now with other classes.
+ * Definition order matches OOXML type ID indexes.
+ * Note that this has NO_COMPARISON as the first item, unlike the similar
+ * DataValidation operator enum. Thanks, Microsoft.
+ */
+@Internal
+enum OperatorEnum {
+ // always false/invalid
+ NO_COMPARISON(OperatorEnum::noComp, false),
+ BETWEEN(OperatorEnum::between, false),
+ NOT_BETWEEN(OperatorEnum::notBetween, true),
+ EQUAL(OperatorEnum::equal, false),
+ NOT_EQUAL(OperatorEnum::notEqual, true),
+ GREATER_THAN(OperatorEnum::greaterThan, false),
+ LESS_THAN(OperatorEnum::lessThan, false),
+ GREATER_OR_EQUAL(OperatorEnum::greaterOrEqual, false),
+ LESS_OR_EQUAL(OperatorEnum::lessOrEqual, false) ;
+
+ private interface CompareOp {
+ <C extends Comparable<C>> boolean isValid(C cellValue, C v1, C v2);
+ }
+
+ private final CompareOp compareOp;
+ private final boolean validForIncompatibleTypes;
+
+ OperatorEnum(CompareOp compareOp, boolean validForIncompatibleTypes) {
+ this.compareOp = compareOp;
+ this.validForIncompatibleTypes = validForIncompatibleTypes;
+ }
+
+ /**
+ * Evaluates comparison using operator instance rules
+ * @param cellValue won't be null, assumption is previous checks handled that
+ * @param v1 if null, per Excel behavior various results depending on the type of cellValue and the specific enum instance
+ * @param v2 null if not needed. If null when needed, various results, per Excel behavior
+ * @return true if the comparison is valid
+ */
+ <C extends Comparable<C>> boolean isValid(C cellValue, C v1, C v2) {
+ return compareOp.isValid(cellValue, v1, v2);
+ }
+
+ /**
+ * Called when the cell and comparison values are of different data types
+ * Needed for negation operators, which should return true.
+ * @return true if this comparison is true when the types to compare are different
+ */
+ boolean isValidForIncompatibleTypes() {
+ return validForIncompatibleTypes;
+ }
+
+ private static <C extends Comparable<C>> boolean noComp(C cellValue, C v1, C v2) {
+ return false;
+ }
+
+ private static <C extends Comparable<C>> boolean between(C cellValue, C v1, C v2) {
+ if (v1 == null) {
+ if (cellValue instanceof Number) {
+ // use zero for null
+ double n1 = 0;
+ double n2 = v2 == null ? 0 : ((Number) v2).doubleValue();
+ return Double.compare( ((Number) cellValue).doubleValue(), n1) >= 0 && Double.compare(((Number) cellValue).doubleValue(), n2) <= 0;
+ } else if (cellValue instanceof String) {
+ String n1 = "";
+ String n2 = v2 == null ? "" : (String) v2;
+ return ((String) cellValue).compareToIgnoreCase(n1) >= 0 && ((String) cellValue).compareToIgnoreCase(n2) <= 0;
+ } else if (cellValue instanceof Boolean) return false;
+ return false; // just in case - not a typical possibility
+ }
+ return cellValue.compareTo(v1) >= 0 && cellValue.compareTo(v2) <= 0;
+ }
+
+ private static <C extends Comparable<C>> boolean notBetween(C cellValue, C v1, C v2) {
+ if (v1 == null) {
+ if (cellValue instanceof Number) {
+ // use zero for null
+ double n1 = 0;
+ double n2 = v2 == null ? 0 : ((Number) v2).doubleValue();
+ return Double.compare( ((Number) cellValue).doubleValue(), n1) < 0 || Double.compare(((Number) cellValue).doubleValue(), n2) > 0;
+ } else if (cellValue instanceof String) {
+ String n1 = "";
+ String n2 = v2 == null ? "" : (String) v2;
+ return ((String) cellValue).compareToIgnoreCase(n1) < 0 || ((String) cellValue).compareToIgnoreCase(n2) > 0;
+ } else {
+ // just in case - not a typical possibility
+ return cellValue instanceof Boolean;
+ }
+ }
+ return cellValue.compareTo(v1) < 0 || cellValue.compareTo(v2) > 0;
+ }
+
+ private static <C extends Comparable<C>> boolean equal(C cellValue, C v1, C v2) {
+ if (v1 == null) {
+ if (cellValue instanceof Number) {
+ // use zero for null
+ return Double.compare( ((Number) cellValue).doubleValue(), 0) == 0;
+ } else if (cellValue instanceof String) {
+ return false; // even an empty string is not equal the empty cell, only another empty cell is, handled higher up
+ } else if (cellValue instanceof Boolean) return false;
+ return false; // just in case - not a typical possibility
+ }
+ // need to avoid instanceof, to work around a 1.6 compiler bug
+ if (cellValue.getClass() == String.class) {
+ return cellValue.toString().compareToIgnoreCase(v1.toString()) == 0;
+ }
+ return cellValue.compareTo(v1) == 0;
+ }
+
+ private static <C extends Comparable<C>> boolean notEqual(C cellValue, C v1, C v2) {
+ if (v1 == null) {
+ return true; // non-null not equal null, returns true
+ }
+ // need to avoid instanceof, to work around a 1.6 compiler bug
+ if (cellValue.getClass() == String.class) {
+ return cellValue.toString().compareToIgnoreCase(v1.toString()) == 0;
+ }
+ return cellValue.compareTo(v1) != 0;
+ }
+
+ private static <C extends Comparable<C>> boolean greaterThan(C cellValue, C v1, C v2) {
+ if (v1 == null) {
+ if (cellValue instanceof Number) {
+ // use zero for null
+ return Double.compare( ((Number) cellValue).doubleValue(), 0) > 0;
+ } else if (cellValue instanceof String) {
+ return true; // non-null string greater than empty cell
+ } else {
+ // just in case - not a typical possibility
+ return cellValue instanceof Boolean;
+ }
+ }
+ return cellValue.compareTo(v1) > 0;
+ }
+
+ private static <C extends Comparable<C>> boolean lessThan(C cellValue, C v1, C v2) {
+ if (v1 == null) {
+ if (cellValue instanceof Number) {
+ // use zero for null
+ return Double.compare( ((Number) cellValue).doubleValue(), 0) < 0;
+ } else if (cellValue instanceof String) {
+ return false; // non-null string greater than empty cell
+ } else if (cellValue instanceof Boolean) return false;
+ return false; // just in case - not a typical possibility
+ }
+ return cellValue.compareTo(v1) < 0;
+ }
+
+ private static <C extends Comparable<C>> boolean greaterOrEqual(C cellValue, C v1, C v2) {
+ if (v1 == null) {
+ if (cellValue instanceof Number) {
+ // use zero for null
+ return Double.compare( ((Number) cellValue).doubleValue(), 0) >= 0;
+ } else if (cellValue instanceof String) {
+ return true; // non-null string greater than empty cell
+ } else {
+ // just in case - not a typical possibility
+ return cellValue instanceof Boolean;
+ }
+ }
+ return cellValue.compareTo(v1) >= 0;
+ }
+
+ private static <C extends Comparable<C>> boolean lessOrEqual(C cellValue, C v1, C v2) {
+ if (v1 == null) {
+ if (cellValue instanceof Number) {
+ // use zero for null
+ return Double.compare( ((Number) cellValue).doubleValue(), 0) <= 0;
+ } else if (cellValue instanceof String) {
+ return false; // non-null string not less than empty cell
+ } else if (cellValue instanceof Boolean) return false; // for completeness
+ return false; // just in case - not a typical possibility
+ }
+ return cellValue.compareTo(v1) <= 0;
+ }
+
+}
Propchange: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/OperatorEnum.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/SharedFormula.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/SharedFormula.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/SharedFormula.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/SharedFormula.java Fri May 21 21:22:40 2021
@@ -38,8 +38,6 @@ public class SharedFormula {
* were it not shared.
*
* @param ptgs parsed tokens of the shared formula
- * @param formulaRow
- * @param formulaColumn
*/
public Ptg[] convertSharedFormulas(Ptg[] ptgs, int formulaRow, int formulaColumn) {
@@ -72,9 +70,8 @@ public class SharedFormula {
} else if (ptg instanceof OperandPtg) {
// Any subclass of OperandPtg is mutable, so it's safest to not share these instances.
ptg = ((OperandPtg) ptg).copy();
- } else {
- // all other Ptgs are immutable and can be shared
}
+ // all other Ptgs are immutable and can be shared
newPtgStack[k] = ptg;
}
return newPtgStack;
Modified: poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/TwoDEval.java
URL: http://svn.apache.org/viewvc/poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/TwoDEval.java?rev=1890089&r1=1890088&r2=1890089&view=diff
==============================================================================
--- poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/TwoDEval.java (original)
+++ poi/trunk/poi/src/main/java/org/apache/poi/ss/formula/TwoDEval.java Fri May 21 21:22:40 2021
@@ -38,25 +38,27 @@ public interface TwoDEval extends ValueE
int getHeight();
/**
- * @return <code>true</code> if the area has just a single row, this also includes
+ * @return {@code true} if the area has just a single row, this also includes
* the trivial case when the area has just a single cell.
*/
- boolean isRow();
+ default boolean isRow() {
+ return false;
+ }
/**
- * @return <code>true</code> if the area has just a single column, this also includes
+ * @return {@code true} if the area has just a single column, this also includes
* the trivial case when the area has just a single cell.
*/
boolean isColumn();
/**
* @param rowIndex relative row index (zero based)
- * @return a single row {@link TwoDEval}
+ * @return a single row TwoDEval
*/
TwoDEval getRow(int rowIndex);
/**
* @param columnIndex relative column index (zero based)
- * @return a single column {@link TwoDEval}
+ * @return a single column TwoDEval
*/
TwoDEval getColumn(int columnIndex);
@@ -65,10 +67,8 @@ public interface TwoDEval extends ValueE
* @return true if the cell at row and col is a subtotal
*/
boolean isSubTotal(int rowIndex, int columnIndex);
-
+
/**
- *
- * @param rowIndex
* @return true if the row is hidden
* @see Subtotal
*/
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org