mirror of https://github.com/apache/poi.git
Introduce a CFHeaderBase common parent #58130
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1690503 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
d7666dba2d
commit
275d551956
|
@ -25,14 +25,14 @@ import org.apache.poi.util.LittleEndianOutput;
|
|||
* Conditional Formatting Header v12 record CFHEADER12 (0x0879),
|
||||
* for conditional formattings introduced in Excel 2007 and newer.
|
||||
*/
|
||||
public final class CFHeader12Record extends CFHeaderRecord {
|
||||
public final class CFHeader12Record extends CFHeaderBase {
|
||||
public static final short sid = 0x0879;
|
||||
|
||||
private FtrHeader futureHeader;
|
||||
|
||||
/** Creates new CFHeaderRecord */
|
||||
public CFHeader12Record() {
|
||||
super();
|
||||
createEmpty();
|
||||
futureHeader = new FtrHeader();
|
||||
futureHeader.setRecordType(sid);
|
||||
}
|
||||
|
@ -41,9 +41,7 @@ public final class CFHeader12Record extends CFHeaderRecord {
|
|||
futureHeader = new FtrHeader();
|
||||
futureHeader.setRecordType(sid);
|
||||
}
|
||||
|
||||
public CFHeader12Record(RecordInputStream in)
|
||||
{
|
||||
public CFHeader12Record(RecordInputStream in) {
|
||||
futureHeader = new FtrHeader(in);
|
||||
read(in);
|
||||
}
|
||||
|
@ -69,7 +67,7 @@ public final class CFHeader12Record extends CFHeaderRecord {
|
|||
public Object clone() {
|
||||
CFHeader12Record result = new CFHeader12Record();
|
||||
result.futureHeader = (FtrHeader)futureHeader.clone();
|
||||
// TODO Clone the rest via the base
|
||||
super.copyTo(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
/* ====================================================================
|
||||
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.hssf.record;
|
||||
|
||||
import org.apache.poi.hssf.record.cf.CellRangeUtil;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Parent of Conditional Formatting Header records,
|
||||
* {@link CFHeaderRecord} and {@link CFHeader12Record}.
|
||||
*/
|
||||
public abstract class CFHeaderBase extends StandardRecord {
|
||||
private int field_1_numcf;
|
||||
private int field_2_need_recalculation_and_id;
|
||||
private CellRangeAddress field_3_enclosing_cell_range;
|
||||
private CellRangeAddressList field_4_cell_ranges;
|
||||
|
||||
/** Creates new CFHeaderBase */
|
||||
protected CFHeaderBase() {
|
||||
}
|
||||
protected CFHeaderBase(CellRangeAddress[] regions, int nRules) {
|
||||
CellRangeAddress[] unmergedRanges = regions;
|
||||
CellRangeAddress[] mergeCellRanges = CellRangeUtil.mergeCellRanges(unmergedRanges);
|
||||
setCellRanges(mergeCellRanges);
|
||||
field_1_numcf = nRules;
|
||||
}
|
||||
|
||||
protected void createEmpty() {
|
||||
field_3_enclosing_cell_range = new CellRangeAddress(0, 0, 0, 0);
|
||||
field_4_cell_ranges = new CellRangeAddressList();
|
||||
}
|
||||
protected void read(RecordInputStream in) {
|
||||
field_1_numcf = in.readShort();
|
||||
field_2_need_recalculation_and_id = in.readShort();
|
||||
field_3_enclosing_cell_range = new CellRangeAddress(in);
|
||||
field_4_cell_ranges = new CellRangeAddressList(in);
|
||||
}
|
||||
|
||||
public int getNumberOfConditionalFormats() {
|
||||
return field_1_numcf;
|
||||
}
|
||||
public void setNumberOfConditionalFormats(int n) {
|
||||
field_1_numcf=n;
|
||||
}
|
||||
|
||||
public boolean getNeedRecalculation() {
|
||||
// Held on the 1st bit
|
||||
return field_2_need_recalculation_and_id % 2 == 1;
|
||||
}
|
||||
public void setNeedRecalculation(boolean b) {
|
||||
// held on the first bit
|
||||
if (b == getNeedRecalculation()) return;
|
||||
if (b) field_2_need_recalculation_and_id++;
|
||||
else field_2_need_recalculation_and_id--;
|
||||
}
|
||||
|
||||
public int getID() {
|
||||
// Remaining 15 bits of field 2
|
||||
return field_2_need_recalculation_and_id>>1;
|
||||
}
|
||||
public void setID(int id) {
|
||||
// Remaining 15 bits of field 2
|
||||
boolean needsRecalc = getNeedRecalculation();
|
||||
field_2_need_recalculation_and_id = (id<<1);
|
||||
if (needsRecalc) field_2_need_recalculation_and_id++;
|
||||
}
|
||||
|
||||
public CellRangeAddress getEnclosingCellRange() {
|
||||
return field_3_enclosing_cell_range;
|
||||
}
|
||||
public void setEnclosingCellRange(CellRangeAddress cr) {
|
||||
field_3_enclosing_cell_range = cr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cell ranges list to a single cell range and
|
||||
* modify the enclosing cell range accordingly.
|
||||
* @param cellRanges - list of CellRange objects
|
||||
*/
|
||||
public void setCellRanges(CellRangeAddress[] cellRanges) {
|
||||
if(cellRanges == null) {
|
||||
throw new IllegalArgumentException("cellRanges must not be null");
|
||||
}
|
||||
CellRangeAddressList cral = new CellRangeAddressList();
|
||||
CellRangeAddress enclosingRange = null;
|
||||
for (int i = 0; i < cellRanges.length; i++) {
|
||||
CellRangeAddress cr = cellRanges[i];
|
||||
enclosingRange = CellRangeUtil.createEnclosingCellRange(cr, enclosingRange);
|
||||
cral.addCellRangeAddress(cr);
|
||||
}
|
||||
field_3_enclosing_cell_range = enclosingRange;
|
||||
field_4_cell_ranges = cral;
|
||||
}
|
||||
|
||||
public CellRangeAddress[] getCellRanges() {
|
||||
return field_4_cell_ranges.getCellRangeAddresses();
|
||||
}
|
||||
|
||||
protected abstract String getRecordName();
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append("[").append(getRecordName()).append("]\n");
|
||||
buffer.append("\t.numCF = ").append(getNumberOfConditionalFormats()).append("\n");
|
||||
buffer.append("\t.needRecalc = ").append(getNeedRecalculation()).append("\n");
|
||||
buffer.append("\t.id = ").append(getID()).append("\n");
|
||||
buffer.append("\t.enclosingCellRange= ").append(getEnclosingCellRange()).append("\n");
|
||||
buffer.append("\t.cfranges=[");
|
||||
for( int i=0; i<field_4_cell_ranges.countRanges(); i++) {
|
||||
buffer.append(i==0?"":",").append(field_4_cell_ranges.getCellRangeAddress(i).toString());
|
||||
}
|
||||
buffer.append("]\n");
|
||||
buffer.append("[/").append(getRecordName()).append("]\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
protected int getDataSize() {
|
||||
return 4 // 2 short fields
|
||||
+ CellRangeAddress.ENCODED_SIZE
|
||||
+ field_4_cell_ranges.getSize();
|
||||
}
|
||||
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
out.writeShort(field_1_numcf);
|
||||
out.writeShort(field_2_need_recalculation_and_id);
|
||||
field_3_enclosing_cell_range.serialize(out);
|
||||
field_4_cell_ranges.serialize(out);
|
||||
}
|
||||
|
||||
protected void copyTo(CFHeaderBase result) {
|
||||
result.field_1_numcf = field_1_numcf;
|
||||
result.field_2_need_recalculation_and_id = field_2_need_recalculation_and_id;
|
||||
result.field_3_enclosing_cell_range = field_3_enclosing_cell_range.copy();
|
||||
result.field_4_cell_ranges = field_4_cell_ranges.copy();
|
||||
}
|
||||
}
|
|
@ -17,139 +17,31 @@
|
|||
|
||||
package org.apache.poi.hssf.record;
|
||||
|
||||
import org.apache.poi.hssf.record.cf.CellRangeUtil;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.ss.util.CellRangeAddressList;
|
||||
import org.apache.poi.util.LittleEndianOutput;
|
||||
|
||||
/**
|
||||
* Conditional Formatting Header record CFHEADER (0x01B0).
|
||||
* Used to describe a {@link CFRuleRecord}.
|
||||
* @see CFHeader12Record
|
||||
* TODO Move most of the logic into a base class
|
||||
*/
|
||||
public class CFHeaderRecord extends StandardRecord {
|
||||
public final class CFHeaderRecord extends CFHeaderBase {
|
||||
public static final short sid = 0x01B0;
|
||||
|
||||
private int field_1_numcf;
|
||||
private int field_2_need_recalculation_and_id;
|
||||
private CellRangeAddress field_3_enclosing_cell_range;
|
||||
private CellRangeAddressList field_4_cell_ranges;
|
||||
|
||||
/** Creates new CFHeaderRecord */
|
||||
public CFHeaderRecord() {
|
||||
field_3_enclosing_cell_range = new CellRangeAddress(0, 0, 0, 0);
|
||||
field_4_cell_ranges = new CellRangeAddressList();
|
||||
createEmpty();
|
||||
}
|
||||
public CFHeaderRecord(CellRangeAddress[] regions, int nRules) {
|
||||
CellRangeAddress[] unmergedRanges = regions;
|
||||
CellRangeAddress[] mergeCellRanges = CellRangeUtil.mergeCellRanges(unmergedRanges);
|
||||
setCellRanges(mergeCellRanges);
|
||||
field_1_numcf = nRules;
|
||||
super(regions, nRules);
|
||||
}
|
||||
|
||||
public CFHeaderRecord(RecordInputStream in) {
|
||||
read(in);
|
||||
}
|
||||
protected void read(RecordInputStream in) {
|
||||
field_1_numcf = in.readShort();
|
||||
field_2_need_recalculation_and_id = in.readShort();
|
||||
field_3_enclosing_cell_range = new CellRangeAddress(in);
|
||||
field_4_cell_ranges = new CellRangeAddressList(in);
|
||||
}
|
||||
|
||||
public int getNumberOfConditionalFormats() {
|
||||
return field_1_numcf;
|
||||
}
|
||||
public void setNumberOfConditionalFormats(int n) {
|
||||
field_1_numcf=n;
|
||||
}
|
||||
|
||||
public boolean getNeedRecalculation() {
|
||||
// Held on the 1st bit
|
||||
return field_2_need_recalculation_and_id % 2 == 1;
|
||||
}
|
||||
public void setNeedRecalculation(boolean b) {
|
||||
// held on the first bit
|
||||
if (b == getNeedRecalculation()) return;
|
||||
if (b) field_2_need_recalculation_and_id++;
|
||||
else field_2_need_recalculation_and_id--;
|
||||
}
|
||||
|
||||
public int getID() {
|
||||
// Remaining 15 bits of field 2
|
||||
return field_2_need_recalculation_and_id>>1;
|
||||
}
|
||||
public void setID(int id) {
|
||||
// Remaining 15 bits of field 2
|
||||
boolean needsRecalc = getNeedRecalculation();
|
||||
field_2_need_recalculation_and_id = (id<<1);
|
||||
if (needsRecalc) field_2_need_recalculation_and_id++;
|
||||
}
|
||||
|
||||
public CellRangeAddress getEnclosingCellRange() {
|
||||
return field_3_enclosing_cell_range;
|
||||
}
|
||||
public void setEnclosingCellRange(CellRangeAddress cr) {
|
||||
field_3_enclosing_cell_range = cr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cell ranges list to a single cell range and
|
||||
* modify the enclosing cell range accordingly.
|
||||
* @param cellRanges - list of CellRange objects
|
||||
*/
|
||||
public void setCellRanges(CellRangeAddress[] cellRanges) {
|
||||
if(cellRanges == null) {
|
||||
throw new IllegalArgumentException("cellRanges must not be null");
|
||||
}
|
||||
CellRangeAddressList cral = new CellRangeAddressList();
|
||||
CellRangeAddress enclosingRange = null;
|
||||
for (int i = 0; i < cellRanges.length; i++) {
|
||||
CellRangeAddress cr = cellRanges[i];
|
||||
enclosingRange = CellRangeUtil.createEnclosingCellRange(cr, enclosingRange);
|
||||
cral.addCellRangeAddress(cr);
|
||||
}
|
||||
field_3_enclosing_cell_range = enclosingRange;
|
||||
field_4_cell_ranges = cral;
|
||||
}
|
||||
|
||||
public CellRangeAddress[] getCellRanges() {
|
||||
return field_4_cell_ranges.getCellRangeAddresses();
|
||||
}
|
||||
|
||||
protected String getRecordName() {
|
||||
return "CFHEADER";
|
||||
}
|
||||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
|
||||
buffer.append("[").append(getRecordName()).append("]\n");
|
||||
buffer.append(" .id = ").append(Integer.toHexString(sid)).append("\n");
|
||||
buffer.append(" .numCF = ").append(getNumberOfConditionalFormats()).append("\n");
|
||||
buffer.append(" .needRecalc = ").append(getNeedRecalculation()).append("\n");
|
||||
buffer.append(" .enclosingCellRange= ").append(getEnclosingCellRange()).append("\n");
|
||||
buffer.append(" .cfranges=[");
|
||||
for( int i=0; i<field_4_cell_ranges.countRanges(); i++) {
|
||||
buffer.append(i==0?"":",").append(field_4_cell_ranges.getCellRangeAddress(i).toString());
|
||||
}
|
||||
buffer.append("]\n");
|
||||
buffer.append("[/").append(getRecordName()).append("]\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
protected int getDataSize() {
|
||||
return 4 // 2 short fields
|
||||
+ CellRangeAddress.ENCODED_SIZE
|
||||
+ field_4_cell_ranges.getSize();
|
||||
}
|
||||
|
||||
public void serialize(LittleEndianOutput out) {
|
||||
out.writeShort(field_1_numcf);
|
||||
out.writeShort(field_2_need_recalculation_and_id);
|
||||
field_3_enclosing_cell_range.serialize(out);
|
||||
field_4_cell_ranges.serialize(out);
|
||||
}
|
||||
|
||||
public short getSid() {
|
||||
return sid;
|
||||
|
@ -157,10 +49,7 @@ public class CFHeaderRecord extends StandardRecord {
|
|||
|
||||
public Object clone() {
|
||||
CFHeaderRecord result = new CFHeaderRecord();
|
||||
result.field_1_numcf = field_1_numcf;
|
||||
result.field_2_need_recalculation_and_id = field_2_need_recalculation_and_id;
|
||||
result.field_3_enclosing_cell_range = field_3_enclosing_cell_range.copy();
|
||||
result.field_4_cell_ranges = field_4_cell_ranges.copy();
|
||||
super.copyTo(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,16 +23,11 @@ import junit.framework.TestCase;
|
|||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
|
||||
/**
|
||||
* Tests the serialization and deserialization of the TestCFHeaderRecord
|
||||
* class works correctly.
|
||||
*
|
||||
* @author Dmitriy Kumshayev
|
||||
* Tests the serialization and deserialization of the {@link CFHeaderRecord}
|
||||
* and {@link CFHeader12Record} classes works correctly.
|
||||
*/
|
||||
public final class TestCFHeaderRecord extends TestCase
|
||||
{
|
||||
|
||||
public void testCreateCFHeaderRecord ()
|
||||
{
|
||||
public final class TestCFHeaderRecord extends TestCase {
|
||||
public void testCreateCFHeaderRecord () {
|
||||
CFHeaderRecord record = new CFHeaderRecord();
|
||||
CellRangeAddress[] ranges = {
|
||||
new CellRangeAddress(0,0xFFFF,5,5),
|
||||
|
@ -50,12 +45,52 @@ public final class TestCFHeaderRecord extends TestCase
|
|||
assertEquals(65535, enclosingCellRange.getLastRow());
|
||||
assertEquals(0, enclosingCellRange.getFirstColumn());
|
||||
assertEquals(6, enclosingCellRange.getLastColumn());
|
||||
|
||||
assertEquals(false, record.getNeedRecalculation());
|
||||
assertEquals(0, record.getID());
|
||||
|
||||
record.setNeedRecalculation(true);
|
||||
assertTrue(record.getNeedRecalculation());
|
||||
assertEquals(true, record.getNeedRecalculation());
|
||||
assertEquals(0, record.getID());
|
||||
|
||||
record.setID(7);
|
||||
record.setNeedRecalculation(false);
|
||||
assertFalse(record.getNeedRecalculation());
|
||||
assertEquals(false, record.getNeedRecalculation());
|
||||
assertEquals(7, record.getID());
|
||||
}
|
||||
|
||||
public void testCreateCFHeader12Record () {
|
||||
CFHeader12Record record = new CFHeader12Record();
|
||||
CellRangeAddress[] ranges = {
|
||||
new CellRangeAddress(0,0xFFFF,5,5),
|
||||
new CellRangeAddress(0,0xFFFF,6,6),
|
||||
new CellRangeAddress(0,1,0,1),
|
||||
new CellRangeAddress(0,1,2,3),
|
||||
new CellRangeAddress(2,3,0,1),
|
||||
new CellRangeAddress(2,3,2,3),
|
||||
};
|
||||
record.setCellRanges(ranges);
|
||||
ranges = record.getCellRanges();
|
||||
assertEquals(6,ranges.length);
|
||||
CellRangeAddress enclosingCellRange = record.getEnclosingCellRange();
|
||||
assertEquals(0, enclosingCellRange.getFirstRow());
|
||||
assertEquals(65535, enclosingCellRange.getLastRow());
|
||||
assertEquals(0, enclosingCellRange.getFirstColumn());
|
||||
assertEquals(6, enclosingCellRange.getLastColumn());
|
||||
|
||||
assertEquals(false, record.getNeedRecalculation());
|
||||
assertEquals(0, record.getID());
|
||||
|
||||
record.setNeedRecalculation(true);
|
||||
assertEquals(true, record.getNeedRecalculation());
|
||||
assertEquals(0, record.getID());
|
||||
|
||||
record.setID(7);
|
||||
record.setNeedRecalculation(false);
|
||||
assertEquals(false, record.getNeedRecalculation());
|
||||
assertEquals(7, record.getID());
|
||||
}
|
||||
|
||||
public void testSerialization() {
|
||||
byte[] recordData =
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue