You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by jo...@apache.org on 2009/06/04 05:38:53 UTC

svn commit: r781645 - in /poi/trunk/src: documentation/content/xdocs/ java/org/apache/poi/hssf/extractor/ java/org/apache/poi/hssf/record/ java/org/apache/poi/hssf/record/aggregates/ java/org/apache/poi/hssf/usermodel/ java/org/apache/poi/ss/usermodel/...

Author: josh
Date: Thu Jun  4 03:38:52 2009
New Revision: 781645

URL: http://svn.apache.org/viewvc?rev=781645&view=rev
Log:
Bugzilla 47244 - Fixed HSSFSheet to handle missing header / footer records

Added:
    poi/trunk/src/testcases/org/apache/poi/hssf/data/noHeaderFooter47244.xls   (with props)
Modified:
    poi/trunk/src/documentation/content/xdocs/status.xml
    poi/trunk/src/java/org/apache/poi/hssf/extractor/ExcelExtractor.java
    poi/trunk/src/java/org/apache/poi/hssf/record/FooterRecord.java
    poi/trunk/src/java/org/apache/poi/hssf/record/HeaderFooterBase.java
    poi/trunk/src/java/org/apache/poi/hssf/record/HeaderRecord.java
    poi/trunk/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFFooter.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFHeader.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HeaderFooter.java
    poi/trunk/src/java/org/apache/poi/ss/usermodel/Sheet.java
    poi/trunk/src/testcases/org/apache/poi/hssf/record/aggregates/TestPageSettingsBlock.java
    poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
    poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHeaderFooter.java

Modified: poi/trunk/src/documentation/content/xdocs/status.xml
URL: http://svn.apache.org/viewvc/poi/trunk/src/documentation/content/xdocs/status.xml?rev=781645&r1=781644&r2=781645&view=diff
==============================================================================
--- poi/trunk/src/documentation/content/xdocs/status.xml (original)
+++ poi/trunk/src/documentation/content/xdocs/status.xml Thu Jun  4 03:38:52 2009
@@ -35,6 +35,7 @@
         <release version="3.5-beta7" date="2009-??-??">
         </release>
         <release version="3.5-beta6" date="2009-06-11">
+           <action dev="POI-DEVELOPERS" type="fix">47244 - Fixed HSSFSheet to handle missing header / footer records</action>
            <action dev="POI-DEVELOPERS" type="fix">47312 - Fixed formula parser to properly reject cell references with a '0' row component</action>
            <action dev="POI-DEVELOPERS" type="fix">47199 - Fixed PageSettingsBlock/Sheet to tolerate margin records after other non-PSB records</action>
            <action dev="POI-DEVELOPERS" type="fix">47069 - Fixed HSSFSheet#getFirstRowNum and HSSFSheet#getLastRowNum to return correct values after removal of all rows</action>

Modified: poi/trunk/src/java/org/apache/poi/hssf/extractor/ExcelExtractor.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/extractor/ExcelExtractor.java?rev=781645&r1=781644&r2=781645&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/extractor/ExcelExtractor.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/extractor/ExcelExtractor.java Thu Jun  4 03:38:52 2009
@@ -293,10 +293,8 @@
 			}
 			
 			// Header text, if there is any
-			if(_includeHeadersFooters && sheet.getHeader() != null) {
-				text.append(
-						_extractHeaderFooter(sheet.getHeader())
-				);
+			if(_includeHeadersFooters) {
+				text.append(_extractHeaderFooter(sheet.getHeader()));
 			}
 			
 			int firstRow = sheet.getFirstRowNum();
@@ -382,11 +380,9 @@
 				text.append("\n");
 			}
 			
-			// Finally Feader text, if there is any
-			if(_includeHeadersFooters && sheet.getFooter() != null) {
-				text.append(
-						_extractHeaderFooter(sheet.getFooter())
-				);
+			// Finally Footer text, if there is any
+			if(_includeHeadersFooters) {
+				text.append(_extractHeaderFooter(sheet.getFooter()));
 			}
 		}
 		

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/FooterRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/FooterRecord.java?rev=781645&r1=781644&r2=781645&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/FooterRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/FooterRecord.java Thu Jun  4 03:38:52 2009
@@ -27,48 +27,30 @@
  *
  */
 public final class FooterRecord extends HeaderFooterBase {
-    public final static short sid = 0x0015;
+	public final static short sid = 0x0015;
 
-    public FooterRecord(String text) {
-    	super(text);
-    }
+	public FooterRecord(String text) {
+		super(text);
+	}
 
-    public FooterRecord(RecordInputStream in) {
+	public FooterRecord(RecordInputStream in) {
 		super(in);
 	}
 
-     /**
-     * set the footer string
-     *
-     * @param footer string to display
-     */
-    public void setFooter(String footer) {
-        setText(footer);
-    }
-
-    /**
-     * get the footer string
-     *
-     * @return footer string to display
-     */
-    public String getFooter() {
-        return getText();
-    }
-
-    public String toString() {
-        StringBuffer buffer = new StringBuffer();
-
-        buffer.append("[FOOTER]\n");
-        buffer.append("    .footer = ").append(getText()).append("\n");
-        buffer.append("[/FOOTER]\n");
-        return buffer.toString();
-    }
-
-    public short getSid() {
-        return sid;
-    }
-
-    public Object clone() {
-        return new FooterRecord(getText());
-    }
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+
+		buffer.append("[FOOTER]\n");
+		buffer.append("    .footer = ").append(getText()).append("\n");
+		buffer.append("[/FOOTER]\n");
+		return buffer.toString();
+	}
+
+	public short getSid() {
+		return sid;
+	}
+
+	public Object clone() {
+		return new FooterRecord(getText());
+	}
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/HeaderFooterBase.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/HeaderFooterBase.java?rev=781645&r1=781644&r2=781645&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/HeaderFooterBase.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/HeaderFooterBase.java Thu Jun  4 03:38:52 2009
@@ -25,7 +25,7 @@
  *
  * @author Josh Micich
  */
-abstract class HeaderFooterBase extends StandardRecord {
+public abstract class HeaderFooterBase extends StandardRecord {
 	private boolean field_2_hasMultibyte;
 	private String field_3_text;
 
@@ -44,7 +44,8 @@
 				field_3_text = in.readCompressedUnicode(field_1_footer_len);
 			}
 		} else {
-			// Note - this is unusual: when the text is empty string, the whole record is empty (just the 4 byte BIFF header)
+			// Note - this is unusual for BIFF records in general, but normal for header / footer records:
+			// when the text is empty string, the whole record is empty (just the 4 byte BIFF header)
 			field_3_text = "";
 		}
 	}
@@ -62,16 +63,9 @@
 		field_3_text = text;
 
 		// Check it'll fit into the space in the record
-		if (field_2_hasMultibyte) {
-			if (field_3_text.length() > 127) {
-				throw new IllegalArgumentException(
-						"Footer string too long (limit is 127 for unicode strings)");
-			}
-		} else {
-			if (field_3_text.length() > 255) {
-				throw new IllegalArgumentException(
-						"Footer string too long (limit is 255 for non-unicode strings)");
-			}
+		if (getDataSize() > RecordInputStream.MAX_RECORD_DATA_SIZE) {
+			throw new IllegalArgumentException("Header/Footer string too long (limit is "
+					+ RecordInputStream.MAX_RECORD_DATA_SIZE + " bytes)");
 		}
 	}
 

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/HeaderRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/HeaderRecord.java?rev=781645&r1=781644&r2=781645&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/HeaderRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/HeaderRecord.java Thu Jun  4 03:38:52 2009
@@ -17,7 +17,6 @@
 
 package org.apache.poi.hssf.record;
 
-
 /**
  * Title:        Header Record<P>
  * Description:  Specifies a header for a sheet<P>
@@ -27,49 +26,30 @@
  * @author Jason Height (jheight at chariot dot net dot au)
  */
 public final class HeaderRecord extends HeaderFooterBase {
-    public final static short sid = 0x0014;
+	public final static short sid = 0x0014;
 
-    public HeaderRecord(String text) {
-    	super(text);
-    }
-
-    public HeaderRecord(RecordInputStream in) {
-    	super(in);
-    }
-
-    /**
-     * set the header string
-     *
-     * @param header string to display
-     */
-    public void setHeader(String header) {
-    	setText(header);
-    }
-
-    /**
-     * get the header string
-     *
-     * @return header string to display
-     */
-    public String getHeader() {
-        return getText();
-    }
-
-    public String toString() {
-        StringBuffer buffer = new StringBuffer();
-
-        buffer.append("[HEADER]\n");
-        buffer.append("    .header = ").append(getText()).append("\n");
-        buffer.append("[/HEADER]\n");
-        return buffer.toString();
-    }
-
-
-    public short getSid() {
-        return sid;
-    }
-
-    public Object clone() {
-      return new HeaderRecord(getText());
-    }
+	public HeaderRecord(String text) {
+		super(text);
+	}
+
+	public HeaderRecord(RecordInputStream in) {
+		super(in);
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+
+		buffer.append("[HEADER]\n");
+		buffer.append("    .header = ").append(getText()).append("\n");
+		buffer.append("[/HEADER]\n");
+		return buffer.toString();
+	}
+
+	public short getSid() {
+		return sid;
+	}
+
+	public Object clone() {
+		return new HeaderRecord(getText());
+	}
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java?rev=781645&r1=781644&r2=781645&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/aggregates/PageSettingsBlock.java Thu Jun  4 03:38:52 2009
@@ -239,10 +239,21 @@
 
 
 	public void visitContainedRecords(RecordVisitor rv) {
+		// Replicates record order from Excel 2007, though this is not critical
+
 		visitIfPresent(_rowBreaksRecord, rv);
 		visitIfPresent(_columnBreaksRecord, rv);
-		visitIfPresent(_header, rv);
-		visitIfPresent(_footer, rv);
+		// Write out empty header / footer records if these are missing 
+		if (_header == null) {
+			rv.visitRecord(new HeaderRecord(""));
+		} else {
+			rv.visitRecord(_header);
+		}
+		if (_footer == null) {
+			rv.visitRecord(new FooterRecord(""));
+		} else {
+			rv.visitRecord(_footer);
+		}
 		visitIfPresent(_hCenter, rv);
 		visitIfPresent(_vCenter, rv);
 		visitIfPresent(_leftMargin, rv);

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFFooter.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFFooter.java?rev=781645&r1=781644&r2=781645&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFFooter.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFFooter.java Thu Jun  4 03:38:52 2009
@@ -15,10 +15,10 @@
    limitations under the License.
 ==================================================================== */
 
-
 package org.apache.poi.hssf.usermodel;
 
 import org.apache.poi.hssf.record.FooterRecord;
+import org.apache.poi.hssf.record.aggregates.PageSettingsBlock;
 import org.apache.poi.ss.usermodel.Footer;
 
 /**
@@ -33,59 +33,29 @@
  * <P>
  * @author Shawn Laubach (slaubach at apache dot org)
  */
-public class HSSFFooter extends HeaderFooter implements Footer {
-    private FooterRecord footerRecord;
+public final class HSSFFooter extends HeaderFooter implements Footer {
+	private final PageSettingsBlock _psb;
 
-    /**
-     * Constructor.  Creates a new footer interface from a footer record
-     * @param footerRecord Footer record to create the footer with
-     */
-    protected HSSFFooter(FooterRecord footerRecord) {
-    	super(footerRecord.getFooter());
-    	this.footerRecord = footerRecord;
-    }
-
-    /**
-     * Sets the left string.
-     * @param newLeft The string to set as the left side.
-     */
-    public void setLeft(String newLeft) {
-	left = newLeft;
-	createFooterString();
-    }
-
-    /**
-     * Sets the center string.
-     * @param newCenter The string to set as the center.
-     */
-    public void setCenter(String newCenter) {
-	center = newCenter;
-	createFooterString();
-    }
-
-    /**
-     * Sets the right string.
-     * @param newRight The string to set as the right side.
-     */
-    public void setRight(String newRight) {
-	right = newRight;
-	createFooterString();
-    }
-    
-    protected String getRawFooter() {
-    	return footerRecord.getFooter();
-    }
-
-
-    /**
-     * Creates the complete footer string based on the left, center, and middle
-     * strings.
-     */
-    private void createFooterString() {
-	footerRecord.setFooter(
-			       "&C" + (center == null ? "" : center) +
-			       "&L" + (left == null ? "" : left) +
-			       "&R" + (right == null ? "" : right));
-    }
+	protected HSSFFooter(PageSettingsBlock psb) {
+		_psb = psb;
+	}
+
+	protected String getRawText() {
+		FooterRecord hf = _psb.getFooter();
+		if (hf == null) {
+			return "";
+		}
+		return hf.getText();
+	}
+
+	@Override
+	protected void setHeaderFooterText(String text) {
+		FooterRecord hfr = _psb.getFooter();
+		if (hfr == null) {
+			hfr = new FooterRecord(text);
+			_psb.setFooter(hfr);
+		} else {
+			hfr.setText(text);
+		}
+	}
 }
-

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFHeader.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFHeader.java?rev=781645&r1=781644&r2=781645&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFHeader.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFHeader.java Thu Jun  4 03:38:52 2009
@@ -18,6 +18,7 @@
 package org.apache.poi.hssf.usermodel;
 
 import org.apache.poi.hssf.record.HeaderRecord;
+import org.apache.poi.hssf.record.aggregates.PageSettingsBlock;
 import org.apache.poi.ss.usermodel.Header;
 
 /**
@@ -33,66 +34,30 @@
  *
  * @author Shawn Laubach (slaubach at apache dot org)
  */
-public class HSSFHeader extends HeaderFooter implements Header {
-	private HeaderRecord headerRecord;
+public final class HSSFHeader extends HeaderFooter implements Header {
 
-    /**
-     * Constructor.  Creates a new header interface from a header record
-     *
-     * @param headerRecord Header record to create the header with
-     */
-    protected HSSFHeader( HeaderRecord headerRecord ) {
-    	super(headerRecord.getHeader());
-        this.headerRecord = headerRecord;
-    }
-
-    /**
-     * Sets the left string.
-     *
-     * @param newLeft The string to set as the left side.
-     */
-    public void setLeft( String newLeft )
-    {
-        left = newLeft;
-        createHeaderString();
-    }
-
-    /**
-     * Sets the center string.
-     *
-     * @param newCenter The string to set as the center.
-     */
-    public void setCenter( String newCenter )
-    {
-        center = newCenter;
-        createHeaderString();
-    }
-
-    /**
-     * Sets the right string.
-     *
-     * @param newRight The string to set as the right side.
-     */
-    public void setRight( String newRight )
-    {
-        right = newRight;
-        createHeaderString();
-    }
-    
-    protected String getRawHeader() {
-    	return headerRecord.getHeader();
-    }
-
-    /**
-     * Creates the complete header string based on the left, center, and middle
-     * strings.
-     */
-    private void createHeaderString()
-    {
-        headerRecord.setHeader( "&C" + ( center == null ? "" : center ) +
-                "&L" + ( left == null ? "" : left ) +
-                "&R" + ( right == null ? "" : right ) );
-    }
+	private final PageSettingsBlock _psb;
 
+	protected HSSFHeader(PageSettingsBlock psb) {
+		_psb = psb;
+	}
+
+	protected String getRawText() {
+		HeaderRecord hf = _psb.getHeader();
+		if (hf == null) {
+			return "";
+		}
+		return hf.getText();
+	}
+
+	@Override
+	protected void setHeaderFooterText(String text) {
+		HeaderRecord hfr = _psb.getHeader();
+		if (hfr == null) {
+			hfr = new HeaderRecord(text);
+			_psb.setHeader(hfr);
+		} else {
+			hfr.setText(text);
+		}
+	}
 }
-

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java?rev=781645&r1=781644&r2=781645&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java Thu Jun  4 03:38:52 2009
@@ -913,20 +913,12 @@
         return new HSSFPrintSetup(_sheet.getPageSettings().getPrintSetup());
     }
 
-    /**
-     * Gets the user model for the document header.
-     * @return The Document header.
-     */
     public HSSFHeader getHeader() {
-        return new HSSFHeader(_sheet.getPageSettings().getHeader());
+        return new HSSFHeader(_sheet.getPageSettings());
     }
 
-    /**
-     * Gets the user model for the document footer.
-     * @return The Document footer.
-     */
     public HSSFFooter getFooter() {
-        return new HSSFFooter(_sheet.getPageSettings().getFooter());
+        return new HSSFFooter(_sheet.getPageSettings());
     }
 
     /**

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HeaderFooter.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HeaderFooter.java?rev=781645&r1=781644&r2=781645&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HeaderFooter.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HeaderFooter.java Thu Jun  4 03:38:52 2009
@@ -14,318 +14,325 @@
    See the License for the specific language governing permissions and
    limitations under the License.
 ==================================================================== */
+
 package org.apache.poi.hssf.usermodel;
 
-import java.util.ArrayList;
 
 /**
- * Common class for {@link HSSFHeader} and
- *  {@link HSSFFooter}.
+ * Common class for {@link HSSFHeader} and {@link HSSFFooter}.
  */
 public abstract class HeaderFooter implements org.apache.poi.ss.usermodel.HeaderFooter {
-	protected String left;
-	protected String center;
-	protected String right;
+
+	protected HeaderFooter() {
+		//
+	}
 	
-	private boolean stripFields = false;
+	/**
+	 * @return the internal text representation (combining center, left and right parts).
+	 * Possibly empty string if no header or footer is set.  Never <code>null</code>.
+	 */
+	protected abstract String getRawText(); 
 	
-	protected HeaderFooter(String text) {
-		while (text != null && text.length() > 1) {
-		    int pos = text.length();
-		    switch (text.substring(1, 2).charAt(0)) {
-			    case 'L' :
+	private String[] splitParts() {
+		String text = getRawText();
+		// default values
+		String _left = "";
+		String _center = "";
+		String _right = "";
+
+		while (text.length() > 1) {
+			int pos = text.length();
+			switch (text.charAt(1)) {
+			case 'L':
 				if (text.indexOf("&C") >= 0) {
-				    pos = Math.min(pos, text.indexOf("&C"));
-				} 
+					pos = Math.min(pos, text.indexOf("&C"));
+				}
 				if (text.indexOf("&R") >= 0) {
-				    pos = Math.min(pos, text.indexOf("&R"));
-				} 
-				left = text.substring(2, pos);
+					pos = Math.min(pos, text.indexOf("&R"));
+				}
+				_left = text.substring(2, pos);
 				text = text.substring(pos);
 				break;
-		    case 'C' : 
+			case 'C':
 				if (text.indexOf("&L") >= 0) {
-				    pos = Math.min(pos, text.indexOf("&L"));
-				} 
+					pos = Math.min(pos, text.indexOf("&L"));
+				}
 				if (text.indexOf("&R") >= 0) {
-				    pos = Math.min(pos, text.indexOf("&R"));
-				} 
-				center = text.substring(2, pos);
+					pos = Math.min(pos, text.indexOf("&R"));
+				}
+				_center = text.substring(2, pos);
 				text = text.substring(pos);
 				break;
-		    case 'R' : 
+			case 'R':
 				if (text.indexOf("&C") >= 0) {
-				    pos = Math.min(pos, text.indexOf("&C"));
-				} 
+					pos = Math.min(pos, text.indexOf("&C"));
+				}
 				if (text.indexOf("&L") >= 0) {
-				    pos = Math.min(pos, text.indexOf("&L"));
-				} 
-				right = text.substring(2, pos);
+					pos = Math.min(pos, text.indexOf("&L"));
+				}
+				_right = text.substring(2, pos);
 				text = text.substring(pos);
 				break;
-		    default: 
-		    	text = null;
-		    }
+			default:
+				throw new IllegalStateException("bad text '" + getRawText() + "'.");
+			}
 		}
+		return new String[] { _left, _center, _right, };
+	}
+
+	/**
+	 * @return the left side of the header or footer.
+	 */
+	public final String getLeft() {
+		return splitParts()[0];
+	}
+
+	/**
+	 * @param newLeft The string to set as the left side.
+	 */
+	public final void setLeft(String newLeft) {
+		updatePart(0, newLeft); 
+	}
+
+	/**
+	 * @return the center of the header or footer.
+	 */
+	public final String getCenter() {
+		return splitParts()[1];
+	}
+
+	/**
+	 * @param newCenter The string to set as the center.
+	 */
+	public final void setCenter(String newCenter) {
+		updatePart(1, newCenter); 
+	}
+
+	/**
+	 * @return The right side of the header or footer.
+	 */
+	public final String getRight() {
+		return splitParts()[2];
+	}
+
+	/**
+	 * @param newRight The string to set as the right side.
+	 */
+	public final void setRight(String newRight) {
+		updatePart(2, newRight); 
 	}
 	
-    /**
-     * Get the left side of the header or footer.
-     * @return The string representing the left side.
-     */
-    public String getLeft() {
-    	if(stripFields)
-    		return stripFields(left);
-		return left;
-	}
-    public abstract void setLeft( String newLeft );
-
-    /**
-     * Get the center of the header or footer.
-     * @return The string representing the center.
-     */
-    public String getCenter() {
-    	if(stripFields)
-    		return stripFields(center);
-    	return center;
-    }
-    public abstract void setCenter( String newCenter );
-
-    /**
-     * Get the right side of the header or footer.
-     * @return The string representing the right side.
-     */
-    public String getRight() {
-    	if(stripFields)
-    		return stripFields(right);
-    	return right;
-    }
-    public abstract void setRight( String newRight );
-
-
-    /**
-     * Returns the string that represents the change in font size.
-     *
-     * @param size the new font size
-     * @return The special string to represent a new font size
-     */
-    public static String fontSize( short size )
-    {
-        return "&" + size;
-    }
-
-    /**
-     * Returns the string that represents the change in font.
-     *
-     * @param font  the new font
-     * @param style the fonts style, one of regular, italic, bold, italic bold or bold italic
-     * @return The special string to represent a new font size
-     */
-    public static String font( String font, String style )
-    {
-        return "&\"" + font + "," + style + "\"";
-    }
-
-    /**
-     * Returns the string representing the current page number
-     *
-     * @return The special string for page number
-     */
-    public static String page() {
-    	return PAGE_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the number of pages.
-     *
-     * @return The special string for the number of pages
-     */
-    public static String numPages() {
-    	return NUM_PAGES_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the current date
-     *
-     * @return The special string for the date
-     */
-    public static String date() {
-    	return DATE_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the current time
-     *
-     * @return The special string for the time
-     */
-    public static String time() {
-    	return TIME_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the current file name
-     *
-     * @return The special string for the file name
-     */
-    public static String file() {
-    	return FILE_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the current tab (sheet) name
-     *
-     * @return The special string for tab name
-     */
-    public static String tab() {
-    	return SHEET_NAME_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the start bold
-     *
-     * @return The special string for start bold
-     */
-    public static String startBold() {
-    	return BOLD_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the end bold
-     *
-     * @return The special string for end bold
-     */
-    public static String endBold() {
-    	return BOLD_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the start underline
-     *
-     * @return The special string for start underline
-     */
-    public static String startUnderline() {
-    	return UNDERLINE_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the end underline
-     *
-     * @return The special string for end underline
-     */
-    public static String endUnderline() {
-    	return UNDERLINE_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the start double underline
-     *
-     * @return The special string for start double underline
-     */
-    public static String startDoubleUnderline() {
-    	return DOUBLE_UNDERLINE_FIELD.sequence;
-    }
-
-    /**
-     * Returns the string representing the end double underline
-     *
-     * @return The special string for end double underline
-     */
-    public static String endDoubleUnderline() {
-    	return DOUBLE_UNDERLINE_FIELD.sequence;
-    }
-    
-    
-    /**
-     * Removes any fields (eg macros, page markers etc)
-     *  from the string.
-     * Normally used to make some text suitable for showing
-     *  to humans, and the resultant text should not normally
-     *  be saved back into the document!
-     */
-    public static String stripFields(String text) {
-    	int pos;
-    	
-    	// Check we really got something to work on
-    	if(text == null || text.length() == 0) {
-    		return text;
-    	}
-    	
-    	// Firstly, do the easy ones which are static
-    	for(int i=0; i<Field.ALL_FIELDS.size(); i++) {
-    		String seq = ((Field)Field.ALL_FIELDS.get(i)).sequence;
-    		while((pos = text.indexOf(seq)) > -1) {
-    			text = text.substring(0, pos) +
-    				text.substring(pos+seq.length());
-    		}
-    	}
-    	
-    	// Now do the tricky, dynamic ones
-    	// These are things like font sizes and font names
-    	text = text.replaceAll("\\&\\d+", "");
-    	text = text.replaceAll("\\&\".*?,.*?\"", "");
-    	
-    	// All done
-    	return text;
-    }
-    
-	
+	private void updatePart(int partIndex, String newValue) {
+		String[] parts = splitParts();
+		parts[partIndex] = newValue == null ? "" : newValue;
+		updateHeaderFooterText(parts);
+	}
+	/**
+	 * Creates the complete footer string based on the left, center, and middle
+	 * strings.
+	 */
+	private void updateHeaderFooterText(String[] parts) {
+		String _left = parts[0];
+		String _center = parts[1];
+		String _right = parts[2];
+		
+		if (_center.length() < 1 && _left.length() < 1 && _right.length() < 1) {
+			setHeaderFooterText("");
+			return;
+		}
+		StringBuilder sb = new StringBuilder(64);
+		sb.append("&C");
+		sb.append(_center);
+		sb.append("&L");
+		sb.append(_left);
+		sb.append("&R");
+		sb.append(_right);
+		String text = sb.toString();
+		setHeaderFooterText(text);
+	}
+
+	/**
+	 * @param text the new header footer text (contains mark-up tags). Possibly
+	 *            empty string never <code>null</code>
+	 */
+	protected abstract void setHeaderFooterText(String text);
+
+	/**
+	 * @param size
+	 *            the new font size
+	 * @return The mark-up tag representing a new font size
+	 */
+	public static String fontSize(short size) {
+		return "&" + size;
+	}
+
+	/**
+	 * @param font
+	 *            the new font
+	 * @param style
+	 *            the fonts style, one of regular, italic, bold, italic bold or
+	 *            bold italic
+	 * @return The mark-up tag representing a new font size
+	 */
+	public static String font(String font, String style) {
+		return "&\"" + font + "," + style + "\"";
+	}
+
+	/**
+	 * @return The mark-up tag representing the current page number
+	 */
+	public static String page() {
+		return MarkupTag.PAGE_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag representing the number of pages
+	 */
+	public static String numPages() {
+		return MarkupTag.NUM_PAGES_FIELD.getRepresentation();
+	}
+
 	/**
-	 * Are fields currently being stripped from
-	 *  the text that this {@link HeaderFooter} returns?
-	 *  Default is false, but can be changed
-	 */
-	public boolean areFieldsStripped() {
-		return stripFields;
-	}
-	/**
-	 * Should fields (eg macros) be stripped from
-	 *  the text that this class returns?
-	 * Default is not to strip.
-	 * @param stripFields
-	 */
-	public void setAreFieldsStripped(boolean stripFields) {
-		this.stripFields = stripFields;
-	}
-
-    
-    public static final Field SHEET_NAME_FIELD = new Field("&A");
-    public static final Field DATE_FIELD = new Field("&D");
-    public static final Field FILE_FIELD = new Field("&F");
-    public static final Field FULL_FILE_FIELD = new Field("&Z");
-    public static final Field PAGE_FIELD = new Field("&P");
-    public static final Field TIME_FIELD = new Field("&T");
-    public static final Field NUM_PAGES_FIELD = new Field("&N");
-    
-    public static final Field PICTURE_FIELD = new Field("&G");
-    
-    public static final PairField BOLD_FIELD = new PairField("&B");
-    public static final PairField ITALIC_FIELD = new PairField("&I");
-    public static final PairField STRIKETHROUGH_FIELD = new PairField("&S");
-    public static final PairField SUBSCRIPT_FIELD = new PairField("&Y");
-    public static final PairField SUPERSCRIPT_FIELD = new PairField("&X");
-    public static final PairField UNDERLINE_FIELD = new PairField("&U");
-    public static final PairField DOUBLE_UNDERLINE_FIELD = new PairField("&E");
-    
-    /**
-     * Represents a special field in a header or footer,
-     *  eg the page number
-     */
-    public static class Field {
-    	private static ArrayList ALL_FIELDS = new ArrayList();
-    	/** The character sequence that marks this field */
-    	public final String sequence;
-    	private Field(String sequence) {
-    		this.sequence = sequence;
-    		ALL_FIELDS.add(this);
-    	}
-    }
-    /**
-     * A special field that normally comes in a pair, eg
-     *  turn on underline / turn off underline
-     */
-    public static class PairField extends Field {
-    	private PairField(String sequence) {
-    		super(sequence);
-    	}
-    }
+	 * @return The mark-up tag representing the current date date
+	 */
+	public static String date() {
+		return MarkupTag.DATE_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag representing current time
+	 */
+	public static String time() {
+		return MarkupTag.TIME_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag representing the current file name
+	 */
+	public static String file() {
+		return MarkupTag.FILE_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag representing the current tab (sheet) name
+	 */
+	public static String tab() {
+		return MarkupTag.SHEET_NAME_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag for start bold
+	 */
+	public static String startBold() {
+		return MarkupTag.BOLD_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag for end bold
+	 */
+	public static String endBold() {
+		return MarkupTag.BOLD_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag for start underline
+	 */
+	public static String startUnderline() {
+		return MarkupTag.UNDERLINE_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag for end underline
+	 */
+	public static String endUnderline() {
+		return MarkupTag.UNDERLINE_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag for start double underline
+	 */
+	public static String startDoubleUnderline() {
+		return MarkupTag.DOUBLE_UNDERLINE_FIELD.getRepresentation();
+	}
+
+	/**
+	 * @return The mark-up tag for end double underline
+	 */
+	public static String endDoubleUnderline() {
+		return MarkupTag.DOUBLE_UNDERLINE_FIELD.getRepresentation();
+	}
+
+	/**
+	 * Removes any fields (eg macros, page markers etc) from the string.
+	 * Normally used to make some text suitable for showing to humans, and the
+	 * resultant text should not normally be saved back into the document!
+	 */
+	public static String stripFields(String pText) {
+		int pos;
+
+		// Check we really got something to work on
+		if (pText == null || pText.length() == 0) {
+			return pText;
+		}
+
+		String text = pText;
+
+		// Firstly, do the easy ones which are static
+		for (MarkupTag mt : MarkupTag.values()) {
+			String seq = mt.getRepresentation();
+			while ((pos = text.indexOf(seq)) > -1) {
+				text = text.substring(0, pos) + text.substring(pos + seq.length());
+			}
+		}
+
+		// Now do the tricky, dynamic ones
+		// These are things like font sizes and font names
+		text = text.replaceAll("\\&\\d+", "");
+		text = text.replaceAll("\\&\".*?,.*?\"", "");
+
+		// All done
+		return text;
+	}
+
+	private enum MarkupTag {
+		SHEET_NAME_FIELD ("&A", false),
+		DATE_FIELD       ("&D", false),
+		FILE_FIELD       ("&F", false),
+		FULL_FILE_FIELD  ("&Z", false),
+		PAGE_FIELD       ("&P", false),
+		TIME_FIELD       ("&T", false),
+		NUM_PAGES_FIELD  ("&N", false),
+
+		PICTURE_FIELD    ("&G", false),
+
+		BOLD_FIELD             ("&B", true),
+		ITALIC_FIELD           ("&I", true),
+		STRIKETHROUGH_FIELD    ("&S", true),
+		SUBSCRIPT_FIELD        ("&Y", true),
+		SUPERSCRIPT_FIELD      ("&X", true),
+		UNDERLINE_FIELD        ("&U", true),
+		DOUBLE_UNDERLINE_FIELD ("&E", true),
+		;
+		
+		private final String _representation;
+		private final boolean _occursInPairs;
+		private MarkupTag(String sequence, boolean occursInPairs) {
+			_representation = sequence;
+			_occursInPairs = occursInPairs;
+		}
+		/**
+		 * @return The character sequence that marks this field
+		 */
+		public String getRepresentation() {
+			return _representation;
+		}
+
+		/**
+		 * @return true if this markup tag normally comes in a pair, eg turn on
+		 *         underline / turn off underline
+		 */
+		public boolean occursPairs() {
+			return _occursInPairs;
+		}
+	}
 }

Modified: poi/trunk/src/java/org/apache/poi/ss/usermodel/Sheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ss/usermodel/Sheet.java?rev=781645&r1=781644&r2=781645&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ss/usermodel/Sheet.java (original)
+++ poi/trunk/src/java/org/apache/poi/ss/usermodel/Sheet.java Thu Jun  4 03:38:52 2009
@@ -182,7 +182,7 @@
      * @param height default row height
      */
     void setDefaultRowHeightInPoints(float height);
-    
+
     /**
      * Returns the CellStyle that applies to the given
      *  (0 based) column, or null if no style has been
@@ -275,7 +275,7 @@
     /**
      * Set whether the window should show 0 (zero) in cells containing zero value.
      * When false, cells with zero value appear blank instead of showing the number zero.
-     * 
+     *
      * @param value whether to display or hide all zero values on the worksheet
      */
     void setDisplayZeros(boolean value);
@@ -407,18 +407,19 @@
 
     /**
      * Gets the user model for the default document header.
-     * <p>
+     * <p/>
      * Note that XSSF offers more kinds of document headers than HSSF does
      * </p>
-     * @return the document header.
+     * @return the document header. Never <code>null</code>
      */
     Header getHeader();
 
     /**
      * Gets the user model for the default document footer.
+     * <p/>
      * Note that XSSF offers more kinds of document footers than HSSF does.
      *
-     * @return the document footer.
+     * @return the document footer. Never <code>null</code>
      */
     Footer getFooter();
 
@@ -473,7 +474,7 @@
     void setZoom(int numerator, int denominator);
 
     /**
-     * The top row in the visible view when the sheet is 
+     * The top row in the visible view when the sheet is
      * first viewed after opening it in a viewer
      *
      * @return short indicating the rownum (0 based) of the top row
@@ -481,7 +482,7 @@
     short getTopRow();
 
     /**
-     * The left col in the visible view when the sheet is 
+     * The left col in the visible view when the sheet is
      * first viewed after opening it in a viewer
      *
      * @return short indicating the rownum (0 based) of the top row
@@ -489,7 +490,7 @@
     short getLeftCol();
 
     /**
-     * Sets desktop window pane display area, when the 
+     * Sets desktop window pane display area, when the
      * file is first opened in a viewer.
      *
      * @param toprow the top row to show in desktop window pane

Added: poi/trunk/src/testcases/org/apache/poi/hssf/data/noHeaderFooter47244.xls
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/data/noHeaderFooter47244.xls?rev=781645&view=auto
==============================================================================
Binary file - no diff available.

Propchange: poi/trunk/src/testcases/org/apache/poi/hssf/data/noHeaderFooter47244.xls
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/record/aggregates/TestPageSettingsBlock.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/aggregates/TestPageSettingsBlock.java?rev=781645&r1=781644&r2=781645&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/aggregates/TestPageSettingsBlock.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/aggregates/TestPageSettingsBlock.java Thu Jun  4 03:38:52 2009
@@ -30,12 +30,14 @@
 import org.apache.poi.hssf.record.DimensionsRecord;
 import org.apache.poi.hssf.record.EOFRecord;
 import org.apache.poi.hssf.record.FooterRecord;
+import org.apache.poi.hssf.record.HCenterRecord;
 import org.apache.poi.hssf.record.HeaderRecord;
 import org.apache.poi.hssf.record.IndexRecord;
 import org.apache.poi.hssf.record.NumberRecord;
 import org.apache.poi.hssf.record.Record;
 import org.apache.poi.hssf.record.RecordFormatException;
 import org.apache.poi.hssf.record.UnknownRecord;
+import org.apache.poi.hssf.record.VCenterRecord;
 import org.apache.poi.hssf.record.WindowTwoRecord;
 import org.apache.poi.hssf.usermodel.HSSFPrintSetup;
 import org.apache.poi.hssf.usermodel.HSSFSheet;
@@ -236,4 +238,39 @@
 	private static UnknownRecord ur(int sid, String hexData) {
 		return new UnknownRecord(sid, HexRead.readFromString(hexData));
 	}
+	
+	/**
+	 * Excel tolerates missing header / footer records, but adds them (empty) in when re-saving.
+	 * This is not critical functionality but it has been decided to keep POI consistent with
+	 * Excel in this regard.
+	 */
+	public void testMissingHeaderFooter() {
+		// initialise PSB with some records, but not the header / footer
+		Record[] recs = {
+				new HCenterRecord(),
+				new VCenterRecord(),
+		};
+		RecordStream rs = new RecordStream(Arrays.asList(recs), 0);
+		PageSettingsBlock psb = new PageSettingsBlock(rs);
+
+		// serialize the PSB to see what records come out
+		RecordCollector rc = new RecordCollector();
+		psb.visitContainedRecords(rc);
+		Record[] outRecs = rc.getRecords();
+		
+		if (outRecs.length == 2) {
+			throw new AssertionFailedError("PageSettingsBlock didn't add missing header/footer records");
+		}
+		assertEquals(4, outRecs.length);
+		assertEquals(HeaderRecord.class, outRecs[0].getClass());
+		assertEquals(FooterRecord.class, outRecs[1].getClass());
+		assertEquals(HCenterRecord.class, outRecs[2].getClass());
+		assertEquals(VCenterRecord.class, outRecs[3].getClass());
+		
+		// make sure the added header / footer records are empty 
+		HeaderRecord hr = (HeaderRecord) outRecs[0];
+		assertEquals("", hr.getText());
+		FooterRecord fr = (FooterRecord) outRecs[1];
+		assertEquals("", fr.getText());
+	}
 }

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java?rev=781645&r1=781644&r2=781645&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java Thu Jun  4 03:38:52 2009
@@ -17,16 +17,20 @@
 
 package org.apache.poi.hssf.usermodel;
 
-import java.io.*;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 
 import junit.framework.AssertionFailedError;
-import junit.framework.TestCase;
 
+import org.apache.poi.hssf.HSSFITestDataProvider;
 import org.apache.poi.hssf.HSSFTestDataSamples;
 import org.apache.poi.hssf.OldExcelFormatException;
-import org.apache.poi.hssf.HSSFITestDataProvider;
 import org.apache.poi.hssf.model.Workbook;
 import org.apache.poi.hssf.record.CellValueRecordInterface;
 import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord;
@@ -34,11 +38,7 @@
 import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
 import org.apache.poi.hssf.record.formula.DeletedArea3DPtg;
 import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.RichTextString;
-import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.BaseTestBugzillaIssues;
-import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.util.TempFile;
 
 /**
@@ -1247,16 +1247,18 @@
     }
 
     /**
-     * header / footer text too long
+     * The resolution for bug 45777 assumed that the maximum text length in a header / footer
+     * record was 256 bytes.  This assumption appears to be wrong.  Since the fix for bug 47244,
+     * POI now supports header / footer text lengths beyond 256 bytes.  
      */
     public void test45777() {
         HSSFWorkbook wb = new HSSFWorkbook();
         HSSFSheet s = wb.createSheet();
 
-        String s248 = "";
-        for(int i=0; i<248; i++) {
-            s248 += "x";
-        }
+        char[] cc248 = new char[248];
+        Arrays.fill(cc248, 'x');
+        String s248 = new String(cc248);
+
         String s249 = s248 + "1";
         String s250 = s248 + "12";
         String s251 = s248 + "123";
@@ -1268,42 +1270,45 @@
 
         // Try on headers
         s.getHeader().setCenter(s248);
-        assertEquals(254, s.getHeader().getRawHeader().length());
+        assertEquals(254, s.getHeader().getRawText().length());
         writeOutAndReadBack(wb);
 
-        s.getHeader().setCenter(s249);
-        assertEquals(255, s.getHeader().getRawHeader().length());
+        s.getHeader().setCenter(s251);
+        assertEquals(257, s.getHeader().getRawText().length());
         writeOutAndReadBack(wb);
 
         try {
-            s.getHeader().setCenter(s250); // 256
-            fail();
-        } catch(IllegalArgumentException e) {}
+            s.getHeader().setCenter(s250); // 256 bytes required
+        } catch(IllegalArgumentException e) {
+            throw new AssertionFailedError("Identified bug 47244b - header can be more than 256 bytes");
+        }
 
         try {
-            s.getHeader().setCenter(s251); // 257
-            fail();
-        } catch(IllegalArgumentException e) {}
-
+            s.getHeader().setCenter(s251); // 257 bytes required
+        } catch(IllegalArgumentException e) {
+            throw new AssertionFailedError("Identified bug 47244b - header can be more than 256 bytes");
+        }
 
         // Now try on footers
         s.getFooter().setCenter(s248);
-        assertEquals(254, s.getFooter().getRawFooter().length());
+        assertEquals(254, s.getFooter().getRawText().length());
         writeOutAndReadBack(wb);
 
-        s.getFooter().setCenter(s249);
-        assertEquals(255, s.getFooter().getRawFooter().length());
+        s.getFooter().setCenter(s251);
+        assertEquals(257, s.getFooter().getRawText().length());
         writeOutAndReadBack(wb);
 
         try {
-            s.getFooter().setCenter(s250); // 256
-            fail();
-        } catch(IllegalArgumentException e) {}
+            s.getFooter().setCenter(s250); // 256 bytes required
+        } catch(IllegalArgumentException e) {
+            throw new AssertionFailedError("Identified bug 47244b - footer can be more than 256 bytes");
+        }
 
         try {
-            s.getFooter().setCenter(s251); // 257
-            fail();
-        } catch(IllegalArgumentException e) {}
+            s.getFooter().setCenter(s251); // 257 bytes required
+        } catch(IllegalArgumentException e) {
+            throw new AssertionFailedError("Identified bug 47244b - footer can be more than 256 bytes");
+        }
     }
 
     /**
@@ -1469,24 +1474,24 @@
      * java.io.IOException: block[ 0 ] already removed
      * (is an excel 95 file though)
      */
-    public void test46904() throws IOException {
-    	try {
-    		HSSFWorkbook wb = openSample("46904.xls");
-    		fail();
-    	} catch(OldExcelFormatException e) {
-    		assertTrue(e.getMessage().startsWith(
-    				"The supplied spreadsheet seems to be Excel"
-    		));
-    	}
+    public void test46904() {
+        try {
+            openSample("46904.xls");
+            fail();
+        } catch(OldExcelFormatException e) {
+            assertTrue(e.getMessage().startsWith(
+                    "The supplied spreadsheet seems to be Excel"
+            ));
+        }
     }
     
     /**
      * java.lang.NegativeArraySizeException reading long
      *  non-unicode data for a name record
      */
-    public void test47034() throws IOException {
-		HSSFWorkbook wb = openSample("47034.xls");
-		assertEquals(893, wb.getNumberOfNames());
-		assertEquals("Matthew\\Matthew11_1\\Matthew2331_1\\Matthew2351_1\\Matthew2361_1___lab", wb.getNameName(300));
+    public void test47034() {
+        HSSFWorkbook wb = openSample("47034.xls");
+        assertEquals(893, wb.getNumberOfNames());
+        assertEquals("Matthew\\Matthew11_1\\Matthew2331_1\\Matthew2351_1\\Matthew2361_1___lab", wb.getNameName(300));
     }
 }

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHeaderFooter.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHeaderFooter.java?rev=781645&r1=781644&r2=781645&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHeaderFooter.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHeaderFooter.java Thu Jun  4 03:38:52 2009
@@ -17,43 +17,43 @@
 
 package org.apache.poi.hssf.usermodel;
 
+import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 
 import org.apache.poi.hssf.HSSFTestDataSamples;
 
 /**
- * Tests row shifting capabilities.
- *
+ * Tests for {@link HSSFHeader} / {@link HSSFFooter}
  *
  * @author Shawn Laubach (slaubach at apache dot com)
  */
 public final class TestHSSFHeaderFooter extends TestCase {
 
 	/**
-	 * Tests that get header retreives the proper values.
+	 * Tests that get header retrieves the proper values.
 	 *
 	 * @author Shawn Laubach (slaubach at apache dot org)
 	 */
 	public void testRetrieveCorrectHeader() {
-		// Read initial file in
+
 		HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("EmbeddedChartHeaderTest.xls");
 		HSSFSheet s = wb.getSheetAt( 0 );
-    	HSSFHeader head = s.getHeader();
-    
-    	assertEquals("Top Left", head.getLeft());
-    	assertEquals("Top Center", head.getCenter());
-    	assertEquals("Top Right", head.getRight());
+		HSSFHeader head = s.getHeader();
+
+		assertEquals("Top Left", head.getLeft());
+		assertEquals("Top Center", head.getCenter());
+		assertEquals("Top Right", head.getRight());
 	}
-	
+
 	public void testSpecialChars() {
 		assertEquals("&U", HSSFHeader.startUnderline());
 		assertEquals("&U", HSSFHeader.endUnderline());
 		assertEquals("&P", HSSFHeader.page());
-		
+
 		assertEquals("&22", HSSFFooter.fontSize((short)22));
 		assertEquals("&\"Arial,bold\"", HSSFFooter.font("Arial", "bold"));
 	}
-	
+
 	public void testStripFields() {
 		String simple = "I am a test header";
 		String withPage = "I am a&P test header";
@@ -61,54 +61,51 @@
 		String withFont = "I&22 am a&\"Arial,bold\" test header";
 		String withOtherAnds = "I am a&P test header&&";
 		String withOtherAnds2 = "I am a&P test header&a&b";
-		
+
 		assertEquals(simple, HSSFHeader.stripFields(simple));
 		assertEquals(simple, HSSFHeader.stripFields(withPage));
 		assertEquals(simple, HSSFHeader.stripFields(withLots));
 		assertEquals(simple, HSSFHeader.stripFields(withFont));
 		assertEquals(simple + "&&", HSSFHeader.stripFields(withOtherAnds));
 		assertEquals(simple + "&a&b", HSSFHeader.stripFields(withOtherAnds2));
-		
+
 		// Now test the default strip flag
 		HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("EmbeddedChartHeaderTest.xls");
 		HSSFSheet s = wb.getSheetAt( 0 );
-    	HSSFHeader head = s.getHeader();
-    
-    	assertEquals("Top Left", head.getLeft());
-    	assertEquals("Top Center", head.getCenter());
-    	assertEquals("Top Right", head.getRight());
-    	
-    	head.setLeft("Top &P&F&D Left");
-    	assertEquals("Top &P&F&D Left", head.getLeft());
-    	assertFalse(head.areFieldsStripped());
-    	
-    	head.setAreFieldsStripped(true);
-    	assertEquals("Top  Left", head.getLeft());
-    	assertTrue(head.areFieldsStripped());
-    	
-    	// Now even more complex
-    	head.setCenter("HEADER TEXT &P&N&D&T&Z&F&F&A&G&X END");
-    	assertEquals("HEADER TEXT  END", head.getCenter());
+		HSSFHeader head = s.getHeader();
+
+		assertEquals("Top Left", head.getLeft());
+		assertEquals("Top Center", head.getCenter());
+		assertEquals("Top Right", head.getRight());
+
+		head.setLeft("Top &P&F&D Left");
+		assertEquals("Top &P&F&D Left", head.getLeft());
+
+		assertEquals("Top  Left", HeaderFooter.stripFields(head.getLeft()));
+
+		// Now even more complex
+		head.setCenter("HEADER TEXT &P&N&D&T&Z&F&F&A&G&X END");
+		assertEquals("HEADER TEXT  END",  HeaderFooter.stripFields(head.getCenter()));
 	}
 
 	/**
-	 * Tests that get header retreives the proper values.
+	 * Tests that get header retrieves the proper values.
 	 *
 	 * @author Shawn Laubach (slaubach at apache dot org)
 	 */
 	public void testRetrieveCorrectFooter() {
-		// Read initial file in
+
 		HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("EmbeddedChartHeaderTest.xls");
-		HSSFSheet s = wb.getSheetAt( 0 );
-    	HSSFFooter foot = s.getFooter();
-    
-    	assertEquals("Bottom Left", foot.getLeft());
-    	assertEquals("Bottom Center", foot.getCenter());
-    	assertEquals("Bottom Right", foot.getRight());
+		HSSFSheet s = wb.getSheetAt(0);
+		HSSFFooter foot = s.getFooter();
+
+		assertEquals("Bottom Left", foot.getLeft());
+		assertEquals("Bottom Center", foot.getCenter());
+		assertEquals("Bottom Right", foot.getRight());
 	}
-	
+
 	/**
-	 * Testcase for Bug 17039 HSSFHeader  doesnot support DBCS 
+	 * Testcase for Bug 17039 HSSFHeader  does not support DBCS
 	 */
 	public void testHeaderHas16bitCharacter() {
 		HSSFWorkbook b = new HSSFWorkbook();
@@ -117,17 +114,17 @@
 		h.setLeft("\u0391");
 		h.setCenter("\u0392");
 		h.setRight("\u0393");
-		
+
 		HSSFWorkbook b2 = HSSFTestDataSamples.writeOutAndReadBack(b);
 		HSSFHeader h2 = b2.getSheet("Test").getHeader();
-		
+
 		assertEquals(h2.getLeft(),"\u0391");
 		assertEquals(h2.getCenter(),"\u0392");
 		assertEquals(h2.getRight(),"\u0393");
 	}
-	
+
 	/**
-	 * Testcase for Bug 17039 HSSFFooter doesnot support DBCS 
+	 * Testcase for Bug 17039 HSSFFooter does not support DBCS
 	 */
 	 public void testFooterHas16bitCharacter() {
 		HSSFWorkbook b = new HSSFWorkbook();
@@ -136,10 +133,10 @@
 		f.setLeft("\u0391");
 		f.setCenter("\u0392");
 		f.setRight("\u0393");
-		
+
 		HSSFWorkbook b2 = HSSFTestDataSamples.writeOutAndReadBack(b);
 		HSSFFooter f2 = b2.getSheet("Test").getFooter();
-		
+
 		assertEquals(f2.getLeft(),"\u0391");
 		assertEquals(f2.getCenter(),"\u0392");
 		assertEquals(f2.getRight(),"\u0393");
@@ -152,11 +149,38 @@
 		assertEquals("Header Left " ,h.getLeft(),"\u090f\u0915");
 		assertEquals("Header Center " ,h.getCenter(),"\u0939\u094b\u0917\u093e");
 		assertEquals("Header Right " ,h.getRight(),"\u091c\u093e");
-		
+
 		HSSFFooter f = s.getFooter();
 		assertEquals("Footer Left " ,f.getLeft(),"\u091c\u093e");
 		assertEquals("Footer Center " ,f.getCenter(),"\u091c\u093e");
 		assertEquals("Footer Right " ,f.getRight(),"\u091c\u093e");
 	}
-}
 
+	/**
+	 * Excel tolerates files with missing HEADER/FOOTER records.  POI should do the same.
+	 */
+	public void testMissingHeaderFooterRecord_bug47244() {
+		// noHeaderFooter47244.xls was created by a slightly modified POI
+		// which omitted the HEADER/FOOTER records
+		HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("noHeaderFooter47244.xls");
+		HSSFSheet sheet = wb.getSheetAt(0);
+		HSSFFooter footer;
+		try {
+			footer = sheet.getFooter();
+		} catch (NullPointerException e) {
+			throw new AssertionFailedError("Identified bug 47244a");
+		}
+		assertEquals("", footer.getRawText());
+		HSSFHeader header = sheet.getHeader();
+		assertEquals("", header.getRawText());
+
+		// make sure header / footer is properly linked to underlying data 
+		HSSFHeader header2 = sheet.getHeader();
+		header.setCenter("foo");
+		assertEquals("foo", header2.getCenter());
+
+		HSSFFooter footer2 = sheet.getFooter();
+		footer.setCenter("bar");
+		assertEquals("bar", footer2.getCenter());
+	}
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org