Begin updating the HSSF CF code to work on the base types, so it can handle both CF and CF12

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1690793 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2015-07-13 18:38:15 +00:00
parent 529c2c7126
commit 65aa10e10f
8 changed files with 104 additions and 39 deletions

View File

@ -21,7 +21,11 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.poi.hssf.model.RecordStream; import org.apache.poi.hssf.model.RecordStream;
import org.apache.poi.hssf.record.CFHeader12Record;
import org.apache.poi.hssf.record.CFHeaderBase;
import org.apache.poi.hssf.record.CFHeaderRecord; import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRule12Record;
import org.apache.poi.hssf.record.CFRuleBase;
import org.apache.poi.hssf.record.CFRuleRecord; import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.Record; import org.apache.poi.hssf.record.Record;
import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.ss.formula.FormulaShifter;
@ -45,12 +49,12 @@ public final class CFRecordsAggregate extends RecordAggregate {
private static final int MAX_97_2003_CONDTIONAL_FORMAT_RULES = 3; private static final int MAX_97_2003_CONDTIONAL_FORMAT_RULES = 3;
private static final POILogger logger = POILogFactory.getLogger(CFRecordsAggregate.class); private static final POILogger logger = POILogFactory.getLogger(CFRecordsAggregate.class);
private final CFHeaderRecord header; private final CFHeaderBase header;
/** List of CFRuleRecord objects */ /** List of CFRuleRecord objects */
private final List<CFRuleRecord> rules; private final List<CFRuleBase> rules;
private CFRecordsAggregate(CFHeaderRecord pHeader, CFRuleRecord[] pRules) { private CFRecordsAggregate(CFHeaderBase pHeader, CFRuleBase[] pRules) {
if(pHeader == null) { if(pHeader == null) {
throw new IllegalArgumentException("header must not be null"); throw new IllegalArgumentException("header must not be null");
} }
@ -67,14 +71,21 @@ public final class CFRecordsAggregate extends RecordAggregate {
throw new RuntimeException("Mismatch number of rules"); throw new RuntimeException("Mismatch number of rules");
} }
header = pHeader; header = pHeader;
rules = new ArrayList<CFRuleRecord>(3); rules = new ArrayList<CFRuleBase>(pRules.length);
for (int i = 0; i < pRules.length; i++) { for (int i = 0; i < pRules.length; i++) {
checkRuleType(pRules[i]);
rules.add(pRules[i]); rules.add(pRules[i]);
} }
} }
public CFRecordsAggregate(CellRangeAddress[] regions, CFRuleRecord[] rules) { public CFRecordsAggregate(CellRangeAddress[] regions, CFRuleBase[] rules) {
this(new CFHeaderRecord(regions, rules.length), rules); this(createHeader(regions, rules), rules);
}
private static CFHeaderBase createHeader(CellRangeAddress[] regions, CFRuleBase[] rules) {
if (rules.length == 0 || rules[0] instanceof CFRuleRecord) {
return new CFHeaderRecord(regions, rules.length);
}
return new CFHeader12Record(regions, rules.length);
} }
/** /**
@ -84,17 +95,19 @@ public final class CFRecordsAggregate extends RecordAggregate {
*/ */
public static CFRecordsAggregate createCFAggregate(RecordStream rs) { public static CFRecordsAggregate createCFAggregate(RecordStream rs) {
Record rec = rs.getNext(); Record rec = rs.getNext();
if (rec.getSid() != CFHeaderRecord.sid) { if (rec.getSid() != CFHeaderRecord.sid &&
rec.getSid() != CFHeader12Record.sid) {
throw new IllegalStateException("next record sid was " + rec.getSid() throw new IllegalStateException("next record sid was " + rec.getSid()
+ " instead of " + CFHeaderRecord.sid + " as expected"); + " instead of " + CFHeaderRecord.sid + " or " +
CFHeader12Record.sid + " as expected");
} }
CFHeaderRecord header = (CFHeaderRecord)rec; CFHeaderBase header = (CFHeaderBase)rec;
int nRules = header.getNumberOfConditionalFormats(); int nRules = header.getNumberOfConditionalFormats();
CFRuleRecord[] rules = new CFRuleRecord[nRules]; CFRuleBase[] rules = new CFRuleBase[nRules];
for (int i = 0; i < rules.length; i++) { for (int i = 0; i < rules.length; i++) {
rules[i] = (CFRuleRecord) rs.getNext(); rules[i] = (CFRuleBase) rs.getNext();
} }
return new CFRecordsAggregate(header, rules); return new CFRecordsAggregate(header, rules);
@ -105,18 +118,17 @@ public final class CFRecordsAggregate extends RecordAggregate {
*/ */
public CFRecordsAggregate cloneCFAggregate() public CFRecordsAggregate cloneCFAggregate()
{ {
CFRuleBase[] newRecs = new CFRuleBase[rules.size()];
CFRuleRecord[] newRecs = new CFRuleRecord[rules.size()];
for (int i = 0; i < newRecs.length; i++) { for (int i = 0; i < newRecs.length; i++) {
newRecs[i] = (CFRuleRecord) getRule(i).clone(); newRecs[i] = (CFRuleRecord) getRule(i).clone();
} }
return new CFRecordsAggregate((CFHeaderRecord) header.clone(), newRecs); return new CFRecordsAggregate((CFHeaderBase)header.clone(), newRecs);
} }
/** /**
* @return the header. Never <code>null</code>. * @return the header. Never <code>null</code>.
*/ */
public CFHeaderRecord getHeader() public CFHeaderBase getHeader()
{ {
return header; return header;
} }
@ -127,18 +139,31 @@ public final class CFRecordsAggregate extends RecordAggregate {
+ ") nRules=" + rules.size()); + ") nRules=" + rules.size());
} }
} }
public CFRuleRecord getRule(int idx) { private void checkRuleType(CFRuleBase r) {
if (header instanceof CFHeaderRecord &&
r instanceof CFRuleRecord) {
return;
}
if (header instanceof CFHeader12Record &&
r instanceof CFRule12Record) {
return;
}
throw new IllegalArgumentException("Header and Rule must both be CF or both be CF12, can't mix");
}
public CFRuleBase getRule(int idx) {
checkRuleIndex(idx); checkRuleIndex(idx);
return rules.get(idx); return rules.get(idx);
} }
public void setRule(int idx, CFRuleRecord r) { public void setRule(int idx, CFRuleBase r) {
if (r == null) { if (r == null) {
throw new IllegalArgumentException("r must not be null"); throw new IllegalArgumentException("r must not be null");
} }
checkRuleIndex(idx); checkRuleIndex(idx);
checkRuleType(r);
rules.set(idx, r); rules.set(idx, r);
} }
public void addRule(CFRuleRecord r) { public void addRule(CFRuleBase r) {
if (r == null) { if (r == null) {
throw new IllegalArgumentException("r must not be null"); throw new IllegalArgumentException("r must not be null");
} }
@ -147,6 +172,7 @@ public final class CFRecordsAggregate extends RecordAggregate {
+ " any more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES + " any more than " + MAX_97_2003_CONDTIONAL_FORMAT_RULES
+ " - this file will cause problems with old Excel versions"); + " - this file will cause problems with old Excel versions");
} }
checkRuleType(r);
rules.add(r); rules.add(r);
header.setNumberOfConditionalFormats(rules.size()); header.setNumberOfConditionalFormats(rules.size());
} }
@ -160,25 +186,29 @@ public final class CFRecordsAggregate extends RecordAggregate {
public String toString() public String toString()
{ {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
String type = "CF";
if (header instanceof CFHeader12Record) {
type = "CF12";
}
buffer.append("[CF]\n"); buffer.append("[").append(type).append("]\n");
if( header != null ) if( header != null )
{ {
buffer.append(header.toString()); buffer.append(header.toString());
} }
for(int i=0; i<rules.size(); i++) for(int i=0; i<rules.size(); i++)
{ {
CFRuleRecord cfRule = rules.get(i); CFRuleBase cfRule = rules.get(i);
buffer.append(cfRule.toString()); buffer.append(cfRule.toString());
} }
buffer.append("[/CF]\n"); buffer.append("[/").append(type).append("]\n");
return buffer.toString(); return buffer.toString();
} }
public void visitContainedRecords(RecordVisitor rv) { public void visitContainedRecords(RecordVisitor rv) {
rv.visitRecord(header); rv.visitRecord(header);
for(int i=0; i<rules.size(); i++) { for(int i=0; i<rules.size(); i++) {
CFRuleRecord rule = rules.get(i); CFRuleBase rule = rules.get(i);
rv.visitRecord(rule); rv.visitRecord(rule);
} }
} }
@ -214,7 +244,7 @@ public final class CFRecordsAggregate extends RecordAggregate {
} }
for(int i=0; i<rules.size(); i++) { for(int i=0; i<rules.size(); i++) {
CFRuleRecord rule = rules.get(i); CFRuleBase rule = rules.get(i);
Ptg[] ptgs; Ptg[] ptgs;
ptgs = rule.getParsedExpression1(); ptgs = rule.getParsedExpression1();
if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) { if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) {
@ -224,6 +254,13 @@ public final class CFRecordsAggregate extends RecordAggregate {
if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) { if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) {
rule.setParsedExpression2(ptgs); rule.setParsedExpression2(ptgs);
} }
if (rule instanceof CFRule12Record) {
CFRule12Record rule12 = (CFRule12Record)rule;
ptgs = rule12.getParsedExpressionScale();
if (ptgs != null && shifter.adjustFormula(ptgs, currentExternSheetIx)) {
rule12.setParsedExpressionScale(ptgs);
}
}
} }
return true; return true;
} }

View File

@ -17,7 +17,7 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.record.CFRuleRecord; import org.apache.poi.hssf.record.CFRuleBase;
import org.apache.poi.hssf.record.cf.BorderFormatting; import org.apache.poi.hssf.record.cf.BorderFormatting;
/** /**
@ -26,10 +26,10 @@ import org.apache.poi.hssf.record.cf.BorderFormatting;
*/ */
public final class HSSFBorderFormatting implements org.apache.poi.ss.usermodel.BorderFormatting public final class HSSFBorderFormatting implements org.apache.poi.ss.usermodel.BorderFormatting
{ {
private final CFRuleRecord cfRuleRecord; private final CFRuleBase cfRuleRecord;
private final BorderFormatting borderFormatting; private final BorderFormatting borderFormatting;
protected HSSFBorderFormatting(CFRuleRecord cfRuleRecord) protected HSSFBorderFormatting(CFRuleBase cfRuleRecord)
{ {
this.cfRuleRecord = cfRuleRecord; this.cfRuleRecord = cfRuleRecord;
this.borderFormatting = cfRuleRecord.getBorderFormatting(); this.borderFormatting = cfRuleRecord.getBorderFormatting();

View File

@ -16,7 +16,7 @@
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.record.CFRuleRecord; import org.apache.poi.hssf.record.CFRuleBase;
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate; import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
import org.apache.poi.ss.usermodel.ConditionalFormatting; import org.apache.poi.ss.usermodel.ConditionalFormatting;
import org.apache.poi.ss.usermodel.ConditionalFormattingRule; import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
@ -147,7 +147,7 @@ public final class HSSFConditionalFormatting implements ConditionalFormatting
*/ */
public HSSFConditionalFormattingRule getRule(int idx) public HSSFConditionalFormattingRule getRule(int idx)
{ {
CFRuleRecord ruleRecord = cfAggregate.getRule(idx); CFRuleBase ruleRecord = cfAggregate.getRule(idx);
return new HSSFConditionalFormattingRule(_workbook, ruleRecord); return new HSSFConditionalFormattingRule(_workbook, ruleRecord);
} }

View File

@ -18,6 +18,7 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.model.HSSFFormulaParser; import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.record.CFRuleBase;
import org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator; import org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator;
import org.apache.poi.hssf.record.CFRuleRecord; import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.cf.BorderFormatting; import org.apache.poi.hssf.record.cf.BorderFormatting;
@ -36,10 +37,10 @@ public final class HSSFConditionalFormattingRule implements ConditionalFormattin
{ {
private static final byte CELL_COMPARISON = CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS; private static final byte CELL_COMPARISON = CFRuleRecord.CONDITION_TYPE_CELL_VALUE_IS;
private final CFRuleRecord cfRuleRecord; private final CFRuleBase cfRuleRecord;
private final HSSFWorkbook workbook; private final HSSFWorkbook workbook;
HSSFConditionalFormattingRule(HSSFWorkbook pWorkbook, CFRuleRecord pRuleRecord) { HSSFConditionalFormattingRule(HSSFWorkbook pWorkbook, CFRuleBase pRuleRecord) {
if (pWorkbook == null) { if (pWorkbook == null) {
throw new IllegalArgumentException("pWorkbook must not be null"); throw new IllegalArgumentException("pWorkbook must not be null");
} }
@ -50,7 +51,7 @@ public final class HSSFConditionalFormattingRule implements ConditionalFormattin
cfRuleRecord = pRuleRecord; cfRuleRecord = pRuleRecord;
} }
CFRuleRecord getCfRuleRecord() CFRuleBase getCfRuleRecord()
{ {
return cfRuleRecord; return cfRuleRecord;
} }

View File

@ -17,7 +17,7 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.record.CFRuleRecord; import org.apache.poi.hssf.record.CFRuleBase;
import org.apache.poi.hssf.record.cf.FontFormatting; import org.apache.poi.hssf.record.cf.FontFormatting;
/** /**
* High level representation for Font Formatting component * High level representation for Font Formatting component
@ -25,7 +25,6 @@ import org.apache.poi.hssf.record.cf.FontFormatting;
*/ */
public final class HSSFFontFormatting implements org.apache.poi.ss.usermodel.FontFormatting public final class HSSFFontFormatting implements org.apache.poi.ss.usermodel.FontFormatting
{ {
/** Underline type - None */ /** Underline type - None */
public final static byte U_NONE = FontFormatting.U_NONE; public final static byte U_NONE = FontFormatting.U_NONE;
/** Underline type - Single */ /** Underline type - Single */
@ -39,7 +38,7 @@ public final class HSSFFontFormatting implements org.apache.poi.ss.usermodel.Fon
private final FontFormatting fontFormatting; private final FontFormatting fontFormatting;
protected HSSFFontFormatting(CFRuleRecord cfRuleRecord) protected HSSFFontFormatting(CFRuleBase cfRuleRecord)
{ {
this.fontFormatting = cfRuleRecord.getFontFormatting(); this.fontFormatting = cfRuleRecord.getFontFormatting();
} }

View File

@ -17,7 +17,7 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.record.CFRuleRecord; import org.apache.poi.hssf.record.CFRuleBase;
import org.apache.poi.hssf.record.cf.PatternFormatting; import org.apache.poi.hssf.record.cf.PatternFormatting;
/** /**
@ -25,10 +25,10 @@ import org.apache.poi.hssf.record.cf.PatternFormatting;
*/ */
public class HSSFPatternFormatting implements org.apache.poi.ss.usermodel.PatternFormatting public class HSSFPatternFormatting implements org.apache.poi.ss.usermodel.PatternFormatting
{ {
private final CFRuleRecord cfRuleRecord; private final CFRuleBase cfRuleRecord;
private final PatternFormatting patternFormatting; private final PatternFormatting patternFormatting;
protected HSSFPatternFormatting(CFRuleRecord cfRuleRecord) protected HSSFPatternFormatting(CFRuleBase cfRuleRecord)
{ {
this.cfRuleRecord = cfRuleRecord; this.cfRuleRecord = cfRuleRecord;
this.patternFormatting = cfRuleRecord.getPatternFormatting(); this.patternFormatting = cfRuleRecord.getPatternFormatting();

View File

@ -17,14 +17,15 @@
package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.record.CFRuleBase;
import org.apache.poi.hssf.record.CFRuleRecord; import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate; import org.apache.poi.hssf.record.aggregates.CFRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable; import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.ConditionalFormatting; import org.apache.poi.ss.usermodel.ConditionalFormatting;
import org.apache.poi.ss.usermodel.ConditionalFormattingRule; import org.apache.poi.ss.usermodel.ConditionalFormattingRule;
import org.apache.poi.ss.usermodel.SheetConditionalFormatting; import org.apache.poi.ss.usermodel.SheetConditionalFormatting;
import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.SpreadsheetVersion;
/** /**
* The 'Conditional Formatting' facet of <tt>HSSFSheet</tt> * The 'Conditional Formatting' facet of <tt>HSSFSheet</tt>
@ -146,7 +147,7 @@ public final class HSSFSheetConditionalFormatting implements SheetConditionalFor
throw new IllegalArgumentException("Number of rules must not exceed 3"); throw new IllegalArgumentException("Number of rules must not exceed 3");
} }
CFRuleRecord[] rules = new CFRuleRecord[cfRules.length]; CFRuleBase[] rules = new CFRuleBase[cfRules.length];
for (int i = 0; i != cfRules.length; i++) { for (int i = 0; i != cfRules.length; i++) {
rules[i] = cfRules[i].getCfRuleRecord(); rules[i] = cfRules[i].getCfRuleRecord();
} }

View File

@ -28,6 +28,7 @@ import junit.framework.TestCase;
import org.apache.poi.hssf.model.RecordStream; import org.apache.poi.hssf.model.RecordStream;
import org.apache.poi.hssf.record.CFHeaderBase; import org.apache.poi.hssf.record.CFHeaderBase;
import org.apache.poi.hssf.record.CFHeaderRecord; import org.apache.poi.hssf.record.CFHeaderRecord;
import org.apache.poi.hssf.record.CFRule12Record;
import org.apache.poi.hssf.record.CFRuleBase; import org.apache.poi.hssf.record.CFRuleBase;
import org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator; import org.apache.poi.hssf.record.CFRuleBase.ComparisonOperator;
import org.apache.poi.hssf.record.CFRuleRecord; import org.apache.poi.hssf.record.CFRuleRecord;
@ -128,4 +129,30 @@ public final class TestCFRecordsAggregate extends TestCase {
} }
assertEquals(rules.length, nRules); assertEquals(rules.length, nRules);
} }
public void testCantMixTypes() {
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
CellRangeAddress[] cellRanges = {
new CellRangeAddress(0,1,0,0),
new CellRangeAddress(0,1,2,2),
};
CFRuleBase[] rules = {
CFRuleRecord.create(sheet, "7"),
CFRule12Record.create(sheet, ComparisonOperator.BETWEEN, "2", "5"),
};
try {
new CFRecordsAggregate(cellRanges, rules);
fail("Shouldn't be able to mix between types");
} catch (IllegalArgumentException e) {}
rules = new CFRuleBase[] { CFRuleRecord.create(sheet, "7") };
CFRecordsAggregate agg = new CFRecordsAggregate(cellRanges, rules);
try {
agg.addRule(CFRule12Record.create(sheet, "7"));
fail("Shouldn't be able to mix between types");
} catch (IllegalArgumentException e) {}
}
} }