summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Stadler <centic@apache.org>2014-10-30 05:53:06 +0000
committerDominik Stadler <centic@apache.org>2014-10-30 05:53:06 +0000
commitc3753981dd89fe172cd4daee76f431500902d69f (patch)
tree4166e077c2f09166a5d8101e7831d17468ba7ac4
parent3b341743de8159d7c1aa0251ba3684125e1f513e (diff)
downloadpoi-c3753981dd89fe172cd4daee76f431500902d69f.tar.gz
poi-c3753981dd89fe172cd4daee76f431500902d69f.zip
Apply patch for bug 57151: Document CellRangeAddress and add some validation to prevent invalid row/column combinations.
Cover class CellRangeAddress fully in unit tests. git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1635389 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/java/org/apache/poi/ss/util/CellRangeAddress.java16
-rw-r--r--src/java/org/apache/poi/util/LittleEndianOutputStream.java21
-rw-r--r--src/testcases/org/apache/poi/ss/util/TestCellRangeAddress.java217
3 files changed, 193 insertions, 61 deletions
diff --git a/src/java/org/apache/poi/ss/util/CellRangeAddress.java b/src/java/org/apache/poi/ss/util/CellRangeAddress.java
index b69476ea24..1f40cf693d 100644
--- a/src/java/org/apache/poi/ss/util/CellRangeAddress.java
+++ b/src/java/org/apache/poi/ss/util/CellRangeAddress.java
@@ -17,9 +17,9 @@
package org.apache.poi.ss.util;
-import org.apache.poi.ss.formula.SheetNameFormatter;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.record.SelectionRecord;
+import org.apache.poi.ss.formula.SheetNameFormatter;
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
import org.apache.poi.util.LittleEndianOutput;
@@ -38,14 +38,26 @@ public class CellRangeAddress extends CellRangeAddressBase {
*/
public static final int ENCODED_SIZE = 8;
+ /**
+ * Creates new cell range. Indexes are zero-based.
+ *
+ * @param firstRow Index of first row
+ * @param lastRow Index of last row (inclusive), must be equal to or larger than {@code firstRow}
+ * @param firstCol Index of first column
+ * @param lastCol Index of last column (inclusive), must be equal to or larger than {@code firstCol}
+ */
public CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) {
super(firstRow, lastRow, firstCol, lastCol);
+
+ if (lastRow < firstRow || lastCol < firstCol)
+ throw new IllegalArgumentException("lastRow < firstRow || lastCol < firstCol");
}
/**
* @deprecated use {@link #serialize(LittleEndianOutput)}
*/
- public int serialize(int offset, byte[] data) {
+ @Deprecated
+ public int serialize(int offset, byte[] data) {
serialize(new LittleEndianByteArrayOutputStream(data, offset, ENCODED_SIZE));
return ENCODED_SIZE;
}
diff --git a/src/java/org/apache/poi/util/LittleEndianOutputStream.java b/src/java/org/apache/poi/util/LittleEndianOutputStream.java
index c8bb9d4b78..3e0daa310d 100644
--- a/src/java/org/apache/poi/util/LittleEndianOutputStream.java
+++ b/src/java/org/apache/poi/util/LittleEndianOutputStream.java
@@ -30,7 +30,8 @@ public final class LittleEndianOutputStream extends FilterOutputStream implement
super(out);
}
- public void writeByte(int v) {
+ @Override
+ public void writeByte(int v) {
try {
out.write(v);
} catch (IOException e) {
@@ -38,11 +39,13 @@ public final class LittleEndianOutputStream extends FilterOutputStream implement
}
}
- public void writeDouble(double v) {
+ @Override
+ public void writeDouble(double v) {
writeLong(Double.doubleToLongBits(v));
}
- public void writeInt(int v) {
+ @Override
+ public void writeInt(int v) {
int b3 = (v >>> 24) & 0xFF;
int b2 = (v >>> 16) & 0xFF;
int b1 = (v >>> 8) & 0xFF;
@@ -57,12 +60,14 @@ public final class LittleEndianOutputStream extends FilterOutputStream implement
}
}
- public void writeLong(long v) {
+ @Override
+ public void writeLong(long v) {
writeInt((int)(v >> 0));
writeInt((int)(v >> 32));
}
- public void writeShort(int v) {
+ @Override
+ public void writeShort(int v) {
int b1 = (v >>> 8) & 0xFF;
int b0 = (v >>> 0) & 0xFF;
try {
@@ -72,7 +77,8 @@ public final class LittleEndianOutputStream extends FilterOutputStream implement
throw new RuntimeException(e);
}
}
- public void write(byte[] b) {
+ @Override
+ public void write(byte[] b) {
// suppress IOException for interface method
try {
super.write(b);
@@ -80,7 +86,8 @@ public final class LittleEndianOutputStream extends FilterOutputStream implement
throw new RuntimeException(e);
}
}
- public void write(byte[] b, int off, int len) {
+ @Override
+ public void write(byte[] b, int off, int len) {
// suppress IOException for interface method
try {
super.write(b, off, len);
diff --git a/src/testcases/org/apache/poi/ss/util/TestCellRangeAddress.java b/src/testcases/org/apache/poi/ss/util/TestCellRangeAddress.java
index a2dff595c5..c5a163394c 100644
--- a/src/testcases/org/apache/poi/ss/util/TestCellRangeAddress.java
+++ b/src/testcases/org/apache/poi/ss/util/TestCellRangeAddress.java
@@ -18,63 +18,176 @@ limitations under the License.
package org.apache.poi.ss.util;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import junit.framework.TestCase;
import org.apache.poi.hssf.record.TestcaseRecordInputStream;
-import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.LittleEndianOutputStream;
-import junit.framework.TestCase;
-
public final class TestCellRangeAddress extends TestCase {
- byte[] data = new byte[] {
- (byte)0x02,(byte)0x00,
- (byte)0x04,(byte)0x00,
- (byte)0x00,(byte)0x00,
- (byte)0x03,(byte)0x00,
- };
-
- public void testLoad() {
- CellRangeAddress ref = new CellRangeAddress(
- TestcaseRecordInputStream.create(0x000, data)
- );
- assertEquals(2, ref.getFirstRow());
- assertEquals(4, ref.getLastRow());
- assertEquals(0, ref.getFirstColumn());
- assertEquals(3, ref.getLastColumn());
-
- assertEquals( 8, CellRangeAddress.ENCODED_SIZE );
- }
-
- public void testStore()
- {
- CellRangeAddress ref = new CellRangeAddress(0,0,0,0);
-
- byte[] recordBytes;
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- LittleEndianOutputStream out = new LittleEndianOutputStream(baos);
-
- // With nothing set
- ref.serialize(out);
- recordBytes = baos.toByteArray();
- assertEquals(recordBytes.length, data.length);
- for (int i = 0; i < data.length; i++) {
- assertEquals("At offset " + i, 0, recordBytes[i]);
+ byte[] data = new byte[] { (byte) 0x02, (byte) 0x00, (byte) 0x04,
+ (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, };
+
+ public void testLoad() {
+ CellRangeAddress ref = new CellRangeAddress(
+ TestcaseRecordInputStream.create(0x000, data));
+ assertEquals(2, ref.getFirstRow());
+ assertEquals(4, ref.getLastRow());
+ assertEquals(0, ref.getFirstColumn());
+ assertEquals(3, ref.getLastColumn());
+
+ assertEquals(8, CellRangeAddress.ENCODED_SIZE);
+ }
+
+ public void testLoadInvalid() {
+ try {
+ assertNotNull(new CellRangeAddress(
+ TestcaseRecordInputStream.create(0x000, new byte[] { (byte)0x02 })));
+ } catch (RuntimeException e) {
+ assertTrue("Had: " + e, e.getMessage().contains("Ran out of data"));
+ }
+ }
+
+ public void testStore() throws IOException {
+ CellRangeAddress ref = new CellRangeAddress(0, 0, 0, 0);
+
+ byte[] recordBytes;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ LittleEndianOutputStream out = new LittleEndianOutputStream(baos);
+ try {
+ // With nothing set
+ ref.serialize(out);
+ recordBytes = baos.toByteArray();
+ assertEquals(recordBytes.length, data.length);
+ for (int i = 0; i < data.length; i++) {
+ assertEquals("At offset " + i, 0, recordBytes[i]);
+ }
+
+ // Now set the flags
+ ref.setFirstRow((short) 2);
+ ref.setLastRow((short) 4);
+ ref.setFirstColumn((short) 0);
+ ref.setLastColumn((short) 3);
+
+ // Re-test
+ baos.reset();
+ ref.serialize(out);
+ recordBytes = baos.toByteArray();
+
+ assertEquals(recordBytes.length, data.length);
+ for (int i = 0; i < data.length; i++) {
+ assertEquals("At offset " + i, data[i], recordBytes[i]);
+ }
+ } finally {
+ out.close();
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public void testStoreDeprecated() throws IOException {
+ CellRangeAddress ref = new CellRangeAddress(0, 0, 0, 0);
+
+ byte[] recordBytes = new byte[CellRangeAddress.ENCODED_SIZE];
+ // With nothing set
+ ref.serialize(0, recordBytes);
+ assertEquals(recordBytes.length, data.length);
+ for (int i = 0; i < data.length; i++) {
+ assertEquals("At offset " + i, 0, recordBytes[i]);
+ }
+
+ // Now set the flags
+ ref.setFirstRow((short) 2);
+ ref.setLastRow((short) 4);
+ ref.setFirstColumn((short) 0);
+ ref.setLastColumn((short) 3);
+
+ // Re-test
+ ref.serialize(0, recordBytes);
+
+ assertEquals(recordBytes.length, data.length);
+ for (int i = 0; i < data.length; i++) {
+ assertEquals("At offset " + i, data[i], recordBytes[i]);
+ }
+ }
+
+ public void testCreateIllegal() throws IOException {
+ // for some combinations we expected exceptions
+ try {
+ assertNotNull(new CellRangeAddress(1, 0, 0, 0));
+ fail("Expect to catch an exception");
+ } catch (IllegalArgumentException e) {
+ // expected here
+ }
+ try {
+ assertNotNull(new CellRangeAddress(0, 0, 1, 0));
+ fail("Expect to catch an exception");
+ } catch (IllegalArgumentException e) {
+ // expected here
+ }
+ }
+
+ public void testCopy() throws IOException {
+ CellRangeAddress ref = new CellRangeAddress(1, 2, 3, 4);
+ CellRangeAddress copy = ref.copy();
+ assertEquals(ref.toString(), copy.toString());
+ }
+
+ public void testGetEncodedSize() throws IOException {
+ assertEquals(2*CellRangeAddress.ENCODED_SIZE, CellRangeAddress.getEncodedSize(2));
}
-
- // Now set the flags
- ref.setFirstRow((short)2);
- ref.setLastRow((short)4);
- ref.setFirstColumn((short)0);
- ref.setLastColumn((short)3);
-
- // Re-test
- baos.reset();
- ref.serialize(out);
- recordBytes = baos.toByteArray();
-
- assertEquals(recordBytes.length, data.length);
- for (int i = 0; i < data.length; i++) {
- assertEquals("At offset " + i, data[i], recordBytes[i]);
+
+ public void testFormatAsString() throws IOException {
+ CellRangeAddress ref = new CellRangeAddress(1, 2, 3, 4);
+
+ assertEquals("D2:E3", ref.formatAsString());
+ assertEquals("D2:E3", CellRangeAddress.valueOf(ref.formatAsString()).formatAsString());
+
+ assertEquals("sheet1!$D$2:$E$3", ref.formatAsString("sheet1", true));
+ assertEquals("sheet1!$D$2:$E$3", CellRangeAddress.valueOf(ref.formatAsString()).formatAsString("sheet1", true));
+ assertEquals("sheet1!$D$2:$E$3", CellRangeAddress.valueOf(ref.formatAsString("sheet1", true)).formatAsString("sheet1", true));
+
+ assertEquals("sheet1!D2:E3", ref.formatAsString("sheet1", false));
+ assertEquals("sheet1!D2:E3", CellRangeAddress.valueOf(ref.formatAsString()).formatAsString("sheet1", false));
+ assertEquals("sheet1!D2:E3", CellRangeAddress.valueOf(ref.formatAsString("sheet1", false)).formatAsString("sheet1", false));
+
+ assertEquals("D2:E3", ref.formatAsString(null, false));
+ assertEquals("D2:E3", CellRangeAddress.valueOf(ref.formatAsString()).formatAsString(null, false));
+ assertEquals("D2:E3", CellRangeAddress.valueOf(ref.formatAsString(null, false)).formatAsString(null, false));
+
+ assertEquals("$D$2:$E$3", ref.formatAsString(null, true));
+ assertEquals("$D$2:$E$3", CellRangeAddress.valueOf(ref.formatAsString()).formatAsString(null, true));
+ assertEquals("$D$2:$E$3", CellRangeAddress.valueOf(ref.formatAsString(null, true)).formatAsString(null, true));
+
+ ref = new CellRangeAddress(-1, -1, 3, 4);
+ assertEquals("D:E", ref.formatAsString());
+ assertEquals("sheet1!$D:$E", CellRangeAddress.valueOf(ref.formatAsString()).formatAsString("sheet1", true));
+ assertEquals("sheet1!$D:$E", CellRangeAddress.valueOf(ref.formatAsString("sheet1", true)).formatAsString("sheet1", true));
+ assertEquals("$D:$E", CellRangeAddress.valueOf(ref.formatAsString()).formatAsString(null, true));
+ assertEquals("$D:$E", CellRangeAddress.valueOf(ref.formatAsString(null, true)).formatAsString(null, true));
+ assertEquals("sheet1!D:E", CellRangeAddress.valueOf(ref.formatAsString()).formatAsString("sheet1", false));
+ assertEquals("sheet1!D:E", CellRangeAddress.valueOf(ref.formatAsString("sheet1", false)).formatAsString("sheet1", false));
+
+ ref = new CellRangeAddress(1, 2, -1, -1);
+ assertEquals("2:3", ref.formatAsString());
+ assertEquals("sheet1!$2:$3", CellRangeAddress.valueOf(ref.formatAsString()).formatAsString("sheet1", true));
+ assertEquals("sheet1!$2:$3", CellRangeAddress.valueOf(ref.formatAsString("sheet1", true)).formatAsString("sheet1", true));
+ assertEquals("$2:$3", CellRangeAddress.valueOf(ref.formatAsString()).formatAsString(null, true));
+ assertEquals("$2:$3", CellRangeAddress.valueOf(ref.formatAsString(null, true)).formatAsString(null, true));
+ assertEquals("sheet1!2:3", CellRangeAddress.valueOf(ref.formatAsString()).formatAsString("sheet1", false));
+ assertEquals("sheet1!2:3", CellRangeAddress.valueOf(ref.formatAsString("sheet1", false)).formatAsString("sheet1", false));
+
+ ref = new CellRangeAddress(1, 1, 2, 2);
+ assertEquals("C2", ref.formatAsString());
+ assertEquals("sheet1!$C$2", CellRangeAddress.valueOf(ref.formatAsString()).formatAsString("sheet1", true));
+ assertEquals("sheet1!$C$2", CellRangeAddress.valueOf(ref.formatAsString("sheet1", true)).formatAsString("sheet1", true));
+ assertEquals("$C$2", CellRangeAddress.valueOf(ref.formatAsString()).formatAsString(null, true));
+ assertEquals("$C$2", CellRangeAddress.valueOf(ref.formatAsString(null, true)).formatAsString(null, true));
+ assertEquals("sheet1!C2", CellRangeAddress.valueOf(ref.formatAsString()).formatAsString("sheet1", false));
+ assertEquals("sheet1!C2", CellRangeAddress.valueOf(ref.formatAsString("sheet1", false)).formatAsString("sheet1", false));
+
+ // is this a valid address?
+ ref = new CellRangeAddress(-1, -1, -1, -1);
+ assertEquals(":", ref.formatAsString());
}
- }
}