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/05/19 18:29:53 UTC

svn commit: r776377 [2/6] - in /poi/trunk/src/java/org/apache/poi: ddf/ hssf/model/ hssf/record/ hssf/record/aggregates/ hssf/record/cont/ hssf/record/formula/ hssf/record/formula/eval/ hssf/usermodel/ hssf/util/ poifs/dev/ ss/ ss/formula/ ss/formula/e...

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/cont/ContinuableRecordOutput.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/cont/ContinuableRecordOutput.java?rev=776377&r1=776376&r2=776377&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/cont/ContinuableRecordOutput.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/cont/ContinuableRecordOutput.java Tue May 19 16:29:51 2009
@@ -1,257 +1,257 @@
-/* ====================================================================
-   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.cont;
-
-import org.apache.poi.hssf.record.ContinueRecord;
-import org.apache.poi.util.DelayableLittleEndianOutput;
-import org.apache.poi.util.LittleEndianOutput;
-import org.apache.poi.util.StringUtil;
-
-/**
- * An augmented {@link LittleEndianOutput} used for serialization of {@link ContinuableRecord}s.
- * This class keeps track of how much remaining space is available in the current BIFF record and
- * can start new {@link ContinueRecord}s as required. 
- * 
- * @author Josh Micich
- */
-public final class ContinuableRecordOutput implements LittleEndianOutput {
-	
-	private final LittleEndianOutput _out;
-	private UnknownLengthRecordOutput _ulrOutput;
-	private int _totalPreviousRecordsSize;
-
-	ContinuableRecordOutput(LittleEndianOutput out, int sid) {
-		_ulrOutput = new UnknownLengthRecordOutput(out, sid);
-		_out = out;
-		_totalPreviousRecordsSize = 0;
-	}
-	
-	public static ContinuableRecordOutput createForCountingOnly() {
-		return new ContinuableRecordOutput(NOPOutput, -777); // fake sid
-	}
-
-	/**
-	 * @return total number of bytes written so far (including all BIFF headers) 
-	 */
-	public int getTotalSize() {
-		return _totalPreviousRecordsSize + _ulrOutput.getTotalSize();
-	}
-	/**
-	 * Terminates the last record (also updates its 'ushort size' field)
-	 */
-	void terminate() {
-		_ulrOutput.terminate();
-	}
-	/**
-	 * @return number of remaining bytes of space in current record
-	 */
-	public int getAvailableSpace() {
-		return _ulrOutput.getAvailableSpace();
-	}
-	
-	/**
-	 * Terminates the current record and starts a new {@link ContinueRecord} (regardless
-	 * of how much space is still available in the current record).
-	 */
-	public void writeContinue() {
-		_ulrOutput.terminate();
-		_totalPreviousRecordsSize += _ulrOutput.getTotalSize();
-		_ulrOutput = new UnknownLengthRecordOutput(_out, ContinueRecord.sid);
-	}
-	public void writeContinueIfRequired(int requiredContinuousSize) {
-		if (_ulrOutput.getAvailableSpace() < requiredContinuousSize) {
-			writeContinue();
-		}
-	}
-
-	/**
-	 * Writes the 'optionFlags' byte and encoded character data of a unicode string.  This includes:
-	 * <ul>
-	 * <li>byte optionFlags</li>
-	 * <li>encoded character data (in "ISO-8859-1" or "UTF-16LE" encoding)</li>
-	 * </ul>
-	 * 
-	 * Notes:
-	 * <ul>
-	 * <li>The value of the 'is16bitEncoded' flag is determined by the actual character data 
-	 * of <tt>text</tt></li>
-	 * <li>The string options flag is never separated (by a {@link ContinueRecord}) from the
-	 * first chunk of character data it refers to.</li>
-	 * <li>The 'ushort length' field is assumed to have been explicitly written earlier.  Hence, 
-	 * there may be an intervening {@link ContinueRecord}</li>
-	 * </ul>
-	 */
-	public void writeStringData(String text) {
-		boolean is16bitEncoded = StringUtil.hasMultibyte(text);
-		// calculate total size of the header and first encoded char
-		int keepTogetherSize = 1 + 1; // ushort len, at least one character byte
-		int optionFlags = 0x00;
-		if (is16bitEncoded) {
-			optionFlags |= 0x01;
-			keepTogetherSize += 1; // one extra byte for first char
-		}
-		writeContinueIfRequired(keepTogetherSize);
-		writeByte(optionFlags);
-		writeCharacterData(text, is16bitEncoded);
-	}
-	/**
-	 * Writes a unicode string complete with header and character data.  This includes:
-	 * <ul>
-	 * <li>ushort length</li>
-	 * <li>byte optionFlags</li>
-	 * <li>ushort numberOfRichTextRuns (optional)</li>
-	 * <li>ushort extendedDataSize (optional)</li>
-	 * <li>encoded character data (in "ISO-8859-1" or "UTF-16LE" encoding)</li>
-	 * </ul>
-	 * 
-	 * The following bits of the 'optionFlags' byte will be set as appropriate:
-	 * <table border='1'>
-	 * <tr><th>Mask</th><th>Description</th></tr>
-	 * <tr><td>0x01</td><td>is16bitEncoded</td></tr>
-	 * <tr><td>0x04</td><td>hasExtendedData</td></tr>
-	 * <tr><td>0x08</td><td>isRichText</td></tr>
-	 * </table>
-	 * Notes:
-	 * <ul> 
-	 * <li>The value of the 'is16bitEncoded' flag is determined by the actual character data 
-	 * of <tt>text</tt></li>
-	 * <li>The string header fields are never separated (by a {@link ContinueRecord}) from the
-	 * first chunk of character data (i.e. the first character is always encoded in the same
-	 * record as the string header).</li>
-	 * </ul>
-	 */
-	public void writeString(String text, int numberOfRichTextRuns, int extendedDataSize) {
-		boolean is16bitEncoded = StringUtil.hasMultibyte(text);
-		// calculate total size of the header and first encoded char
-		int keepTogetherSize = 2 + 1 + 1; // ushort len, byte optionFlags, at least one character byte
-		int optionFlags = 0x00;
-		if (is16bitEncoded) {
-			optionFlags |= 0x01;
-			keepTogetherSize += 1; // one extra byte for first char
-		}
-		if (numberOfRichTextRuns > 0) {
-			optionFlags |= 0x08;
-			keepTogetherSize += 2;
-		}
-		if (extendedDataSize > 0) {
-			optionFlags |= 0x04;
-			keepTogetherSize += 4;
-		}
-		writeContinueIfRequired(keepTogetherSize);
-		writeShort(text.length());
-		writeByte(optionFlags);
-		if (numberOfRichTextRuns > 0) {
-			writeShort(numberOfRichTextRuns);
-		}
-		if (extendedDataSize > 0) {
-			writeInt(extendedDataSize);
-		}
-		writeCharacterData(text, is16bitEncoded);
-	}
-
-
-	private void writeCharacterData(String text, boolean is16bitEncoded) {
-		int nChars = text.length();
-		int i=0;
-		if (is16bitEncoded) {
-			while(true) {
-				int nWritableChars = Math.min(nChars-i, _ulrOutput.getAvailableSpace() / 2);
-				for ( ; nWritableChars > 0; nWritableChars--) {
-					_ulrOutput.writeShort(text.charAt(i++));
-				}
-				if (i >= nChars) {
-					break;
-				}
-				writeContinue();
-				writeByte(0x01); 
-			}
-		} else {
-			while(true) {
-				int nWritableChars = Math.min(nChars-i, _ulrOutput.getAvailableSpace() / 1);
-				for ( ; nWritableChars > 0; nWritableChars--) {
-					_ulrOutput.writeByte(text.charAt(i++));
-				}
-				if (i >= nChars) {
-					break;
-				}
-				writeContinue();
-				writeByte(0x00); 
-			}
-		}
-	}
-
-	public void write(byte[] b) {
-		writeContinueIfRequired(b.length);
-		_ulrOutput.write(b);
-	}
-	public void write(byte[] b, int offset, int len) {
-		writeContinueIfRequired(len);
-		_ulrOutput.write(b, offset, len);
-	}
-	public void writeByte(int v) {
-		writeContinueIfRequired(1);
-		_ulrOutput.writeByte(v);
-	}
-	public void writeDouble(double v) {
-		writeContinueIfRequired(8);
-		_ulrOutput.writeDouble(v);
-	}
-	public void writeInt(int v) {
-		writeContinueIfRequired(4);
-		_ulrOutput.writeInt(v);
-	}
-	public void writeLong(long v) {
-		writeContinueIfRequired(8);
-		_ulrOutput.writeLong(v);
-	}
-	public void writeShort(int v) {
-		writeContinueIfRequired(2);
-		_ulrOutput.writeShort(v);
-	}
-	
-	/**
-	 * Allows optimised usage of {@link ContinuableRecordOutput} for sizing purposes only.
-	 */
-    private static final LittleEndianOutput NOPOutput = new DelayableLittleEndianOutput() {
-
-		public LittleEndianOutput createDelayedOutput(int size) {
-			return this;
-		}
-		public void write(byte[] b) {
-			// does nothing
-		}
-		public void write(byte[] b, int offset, int len) {
-			// does nothing
-		}
-		public void writeByte(int v) {
-			// does nothing
-		}
-		public void writeDouble(double v) {
-			// does nothing
-		}
-		public void writeInt(int v) {
-			// does nothing
-		}
-		public void writeLong(long v) {
-			// does nothing
-		}
-		public void writeShort(int v) {
-			// does nothing
-		}
-    };
-}
+/* ====================================================================
+   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.cont;
+
+import org.apache.poi.hssf.record.ContinueRecord;
+import org.apache.poi.util.DelayableLittleEndianOutput;
+import org.apache.poi.util.LittleEndianOutput;
+import org.apache.poi.util.StringUtil;
+
+/**
+ * An augmented {@link LittleEndianOutput} used for serialization of {@link ContinuableRecord}s.
+ * This class keeps track of how much remaining space is available in the current BIFF record and
+ * can start new {@link ContinueRecord}s as required.
+ *
+ * @author Josh Micich
+ */
+public final class ContinuableRecordOutput implements LittleEndianOutput {
+
+	private final LittleEndianOutput _out;
+	private UnknownLengthRecordOutput _ulrOutput;
+	private int _totalPreviousRecordsSize;
+
+	ContinuableRecordOutput(LittleEndianOutput out, int sid) {
+		_ulrOutput = new UnknownLengthRecordOutput(out, sid);
+		_out = out;
+		_totalPreviousRecordsSize = 0;
+	}
+
+	public static ContinuableRecordOutput createForCountingOnly() {
+		return new ContinuableRecordOutput(NOPOutput, -777); // fake sid
+	}
+
+	/**
+	 * @return total number of bytes written so far (including all BIFF headers)
+	 */
+	public int getTotalSize() {
+		return _totalPreviousRecordsSize + _ulrOutput.getTotalSize();
+	}
+	/**
+	 * Terminates the last record (also updates its 'ushort size' field)
+	 */
+	void terminate() {
+		_ulrOutput.terminate();
+	}
+	/**
+	 * @return number of remaining bytes of space in current record
+	 */
+	public int getAvailableSpace() {
+		return _ulrOutput.getAvailableSpace();
+	}
+
+	/**
+	 * Terminates the current record and starts a new {@link ContinueRecord} (regardless
+	 * of how much space is still available in the current record).
+	 */
+	public void writeContinue() {
+		_ulrOutput.terminate();
+		_totalPreviousRecordsSize += _ulrOutput.getTotalSize();
+		_ulrOutput = new UnknownLengthRecordOutput(_out, ContinueRecord.sid);
+	}
+	public void writeContinueIfRequired(int requiredContinuousSize) {
+		if (_ulrOutput.getAvailableSpace() < requiredContinuousSize) {
+			writeContinue();
+		}
+	}
+
+	/**
+	 * Writes the 'optionFlags' byte and encoded character data of a unicode string.  This includes:
+	 * <ul>
+	 * <li>byte optionFlags</li>
+	 * <li>encoded character data (in "ISO-8859-1" or "UTF-16LE" encoding)</li>
+	 * </ul>
+	 *
+	 * Notes:
+	 * <ul>
+	 * <li>The value of the 'is16bitEncoded' flag is determined by the actual character data
+	 * of <tt>text</tt></li>
+	 * <li>The string options flag is never separated (by a {@link ContinueRecord}) from the
+	 * first chunk of character data it refers to.</li>
+	 * <li>The 'ushort length' field is assumed to have been explicitly written earlier.  Hence,
+	 * there may be an intervening {@link ContinueRecord}</li>
+	 * </ul>
+	 */
+	public void writeStringData(String text) {
+		boolean is16bitEncoded = StringUtil.hasMultibyte(text);
+		// calculate total size of the header and first encoded char
+		int keepTogetherSize = 1 + 1; // ushort len, at least one character byte
+		int optionFlags = 0x00;
+		if (is16bitEncoded) {
+			optionFlags |= 0x01;
+			keepTogetherSize += 1; // one extra byte for first char
+		}
+		writeContinueIfRequired(keepTogetherSize);
+		writeByte(optionFlags);
+		writeCharacterData(text, is16bitEncoded);
+	}
+	/**
+	 * Writes a unicode string complete with header and character data.  This includes:
+	 * <ul>
+	 * <li>ushort length</li>
+	 * <li>byte optionFlags</li>
+	 * <li>ushort numberOfRichTextRuns (optional)</li>
+	 * <li>ushort extendedDataSize (optional)</li>
+	 * <li>encoded character data (in "ISO-8859-1" or "UTF-16LE" encoding)</li>
+	 * </ul>
+	 *
+	 * The following bits of the 'optionFlags' byte will be set as appropriate:
+	 * <table border='1'>
+	 * <tr><th>Mask</th><th>Description</th></tr>
+	 * <tr><td>0x01</td><td>is16bitEncoded</td></tr>
+	 * <tr><td>0x04</td><td>hasExtendedData</td></tr>
+	 * <tr><td>0x08</td><td>isRichText</td></tr>
+	 * </table>
+	 * Notes:
+	 * <ul>
+	 * <li>The value of the 'is16bitEncoded' flag is determined by the actual character data
+	 * of <tt>text</tt></li>
+	 * <li>The string header fields are never separated (by a {@link ContinueRecord}) from the
+	 * first chunk of character data (i.e. the first character is always encoded in the same
+	 * record as the string header).</li>
+	 * </ul>
+	 */
+	public void writeString(String text, int numberOfRichTextRuns, int extendedDataSize) {
+		boolean is16bitEncoded = StringUtil.hasMultibyte(text);
+		// calculate total size of the header and first encoded char
+		int keepTogetherSize = 2 + 1 + 1; // ushort len, byte optionFlags, at least one character byte
+		int optionFlags = 0x00;
+		if (is16bitEncoded) {
+			optionFlags |= 0x01;
+			keepTogetherSize += 1; // one extra byte for first char
+		}
+		if (numberOfRichTextRuns > 0) {
+			optionFlags |= 0x08;
+			keepTogetherSize += 2;
+		}
+		if (extendedDataSize > 0) {
+			optionFlags |= 0x04;
+			keepTogetherSize += 4;
+		}
+		writeContinueIfRequired(keepTogetherSize);
+		writeShort(text.length());
+		writeByte(optionFlags);
+		if (numberOfRichTextRuns > 0) {
+			writeShort(numberOfRichTextRuns);
+		}
+		if (extendedDataSize > 0) {
+			writeInt(extendedDataSize);
+		}
+		writeCharacterData(text, is16bitEncoded);
+	}
+
+
+	private void writeCharacterData(String text, boolean is16bitEncoded) {
+		int nChars = text.length();
+		int i=0;
+		if (is16bitEncoded) {
+			while(true) {
+				int nWritableChars = Math.min(nChars-i, _ulrOutput.getAvailableSpace() / 2);
+				for ( ; nWritableChars > 0; nWritableChars--) {
+					_ulrOutput.writeShort(text.charAt(i++));
+				}
+				if (i >= nChars) {
+					break;
+				}
+				writeContinue();
+				writeByte(0x01);
+			}
+		} else {
+			while(true) {
+				int nWritableChars = Math.min(nChars-i, _ulrOutput.getAvailableSpace() / 1);
+				for ( ; nWritableChars > 0; nWritableChars--) {
+					_ulrOutput.writeByte(text.charAt(i++));
+				}
+				if (i >= nChars) {
+					break;
+				}
+				writeContinue();
+				writeByte(0x00);
+			}
+		}
+	}
+
+	public void write(byte[] b) {
+		writeContinueIfRequired(b.length);
+		_ulrOutput.write(b);
+	}
+	public void write(byte[] b, int offset, int len) {
+		writeContinueIfRequired(len);
+		_ulrOutput.write(b, offset, len);
+	}
+	public void writeByte(int v) {
+		writeContinueIfRequired(1);
+		_ulrOutput.writeByte(v);
+	}
+	public void writeDouble(double v) {
+		writeContinueIfRequired(8);
+		_ulrOutput.writeDouble(v);
+	}
+	public void writeInt(int v) {
+		writeContinueIfRequired(4);
+		_ulrOutput.writeInt(v);
+	}
+	public void writeLong(long v) {
+		writeContinueIfRequired(8);
+		_ulrOutput.writeLong(v);
+	}
+	public void writeShort(int v) {
+		writeContinueIfRequired(2);
+		_ulrOutput.writeShort(v);
+	}
+
+	/**
+	 * Allows optimised usage of {@link ContinuableRecordOutput} for sizing purposes only.
+	 */
+	private static final LittleEndianOutput NOPOutput = new DelayableLittleEndianOutput() {
+
+		public LittleEndianOutput createDelayedOutput(int size) {
+			return this;
+		}
+		public void write(byte[] b) {
+			// does nothing
+		}
+		public void write(byte[] b, int offset, int len) {
+			// does nothing
+		}
+		public void writeByte(int v) {
+			// does nothing
+		}
+		public void writeDouble(double v) {
+			// does nothing
+		}
+		public void writeInt(int v) {
+			// does nothing
+		}
+		public void writeLong(long v) {
+			// does nothing
+		}
+		public void writeShort(int v) {
+			// does nothing
+		}
+	};
+}

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/cont/UnknownLengthRecordOutput.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/cont/UnknownLengthRecordOutput.java?rev=776377&r1=776376&r2=776377&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/cont/UnknownLengthRecordOutput.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/cont/UnknownLengthRecordOutput.java Tue May 19 16:29:51 2009
@@ -1,114 +1,114 @@
-/* ====================================================================
-   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.cont;
-
-import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.util.DelayableLittleEndianOutput;
-import org.apache.poi.util.LittleEndianByteArrayOutputStream;
-import org.apache.poi.util.LittleEndianOutput;
-/**
- * Allows the writing of BIFF records when the 'ushort size' header field is not known in advance.
- * When the client is finished writing data, it calls {@link #terminate()}, at which point this 
- * class updates the 'ushort size' with its final value. 
- * 
- * @author Josh Micich
- */
-final class UnknownLengthRecordOutput implements LittleEndianOutput {
-	private static final int MAX_DATA_SIZE = RecordInputStream.MAX_RECORD_DATA_SIZE;
-
-	private final LittleEndianOutput _originalOut;
-	/** for writing the 'ushort size'  field once its value is known */
-	private final LittleEndianOutput _dataSizeOutput;
-	private final byte[] _byteBuffer;
-	private LittleEndianOutput _out;
-	private int _size;
-	
-	public UnknownLengthRecordOutput(LittleEndianOutput out, int sid) {
-		_originalOut = out;
-		out.writeShort(sid);
-		if (out instanceof DelayableLittleEndianOutput) {
-			// optimisation
-			DelayableLittleEndianOutput dleo = (DelayableLittleEndianOutput) out;
-			_dataSizeOutput = dleo.createDelayedOutput(2);
-			_byteBuffer = null;
-			_out = out;
-		} else {
-			// otherwise temporarily write all subsequent data to a buffer
-			_dataSizeOutput = out;
-			_byteBuffer = new byte[RecordInputStream.MAX_RECORD_DATA_SIZE];
-			_out = new LittleEndianByteArrayOutputStream(_byteBuffer, 0);
-		}
-	}
-	/**
-	 * includes 4 byte header
-	 */
-	public int getTotalSize() {
-		return 4 + _size;
-	}
-	public int getAvailableSpace() {
-		if (_out == null) {
-			throw new IllegalStateException("Record already terminated");
-		}
-		return MAX_DATA_SIZE - _size;
-	}
-	/**
-	 * Finishes writing the current record and updates 'ushort size' field.<br/>
-	 * After this method is called, only {@link #getTotalSize()} may be called.
-	 */
-	public void terminate() {
-		if (_out == null) {
-			throw new IllegalStateException("Record already terminated");
-		}
-		_dataSizeOutput.writeShort(_size);
-		if (_byteBuffer != null) {
-			_originalOut.write(_byteBuffer, 0, _size);
-			_out = null;
-			return;
-		}
-		_out = null;
-	}
-	
-	public void write(byte[] b) {
-		_out.write(b);
-		_size += b.length;
-	}
-	public void write(byte[] b, int offset, int len) {
-		_out.write(b, offset, len);
-		_size += len;
-	}
-	public void writeByte(int v) {
-		_out.writeByte(v);
-		_size += 1;
-	}
-	public void writeDouble(double v) {
-		_out.writeDouble(v);
-		_size += 8;
-	}
-	public void writeInt(int v) {
-		_out.writeInt(v);
-		_size += 4;
-	}
-	public void writeLong(long v) {
-		_out.writeLong(v);
-		_size += 8;
-	}
-	public void writeShort(int v) {
-		_out.writeShort(v);
-		_size += 2;
-	}
-}
+/* ====================================================================
+   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.cont;
+
+import org.apache.poi.hssf.record.RecordInputStream;
+import org.apache.poi.util.DelayableLittleEndianOutput;
+import org.apache.poi.util.LittleEndianByteArrayOutputStream;
+import org.apache.poi.util.LittleEndianOutput;
+/**
+ * Allows the writing of BIFF records when the 'ushort size' header field is not known in advance.
+ * When the client is finished writing data, it calls {@link #terminate()}, at which point this
+ * class updates the 'ushort size' with its final value.
+ *
+ * @author Josh Micich
+ */
+final class UnknownLengthRecordOutput implements LittleEndianOutput {
+	private static final int MAX_DATA_SIZE = RecordInputStream.MAX_RECORD_DATA_SIZE;
+
+	private final LittleEndianOutput _originalOut;
+	/** for writing the 'ushort size'  field once its value is known */
+	private final LittleEndianOutput _dataSizeOutput;
+	private final byte[] _byteBuffer;
+	private LittleEndianOutput _out;
+	private int _size;
+
+	public UnknownLengthRecordOutput(LittleEndianOutput out, int sid) {
+		_originalOut = out;
+		out.writeShort(sid);
+		if (out instanceof DelayableLittleEndianOutput) {
+			// optimisation
+			DelayableLittleEndianOutput dleo = (DelayableLittleEndianOutput) out;
+			_dataSizeOutput = dleo.createDelayedOutput(2);
+			_byteBuffer = null;
+			_out = out;
+		} else {
+			// otherwise temporarily write all subsequent data to a buffer
+			_dataSizeOutput = out;
+			_byteBuffer = new byte[RecordInputStream.MAX_RECORD_DATA_SIZE];
+			_out = new LittleEndianByteArrayOutputStream(_byteBuffer, 0);
+		}
+	}
+	/**
+	 * includes 4 byte header
+	 */
+	public int getTotalSize() {
+		return 4 + _size;
+	}
+	public int getAvailableSpace() {
+		if (_out == null) {
+			throw new IllegalStateException("Record already terminated");
+		}
+		return MAX_DATA_SIZE - _size;
+	}
+	/**
+	 * Finishes writing the current record and updates 'ushort size' field.<br/>
+	 * After this method is called, only {@link #getTotalSize()} may be called.
+	 */
+	public void terminate() {
+		if (_out == null) {
+			throw new IllegalStateException("Record already terminated");
+		}
+		_dataSizeOutput.writeShort(_size);
+		if (_byteBuffer != null) {
+			_originalOut.write(_byteBuffer, 0, _size);
+			_out = null;
+			return;
+		}
+		_out = null;
+	}
+
+	public void write(byte[] b) {
+		_out.write(b);
+		_size += b.length;
+	}
+	public void write(byte[] b, int offset, int len) {
+		_out.write(b, offset, len);
+		_size += len;
+	}
+	public void writeByte(int v) {
+		_out.writeByte(v);
+		_size += 1;
+	}
+	public void writeDouble(double v) {
+		_out.writeDouble(v);
+		_size += 8;
+	}
+	public void writeInt(int v) {
+		_out.writeInt(v);
+		_size += 4;
+	}
+	public void writeLong(long v) {
+		_out.writeLong(v);
+		_size += 8;
+	}
+	public void writeShort(int v) {
+		_out.writeShort(v);
+		_size += 2;
+	}
+}

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/Area2DPtgBase.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/Area2DPtgBase.java?rev=776377&r1=776376&r2=776377&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/Area2DPtgBase.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/Area2DPtgBase.java Tue May 19 16:29:51 2009
@@ -1,64 +1,64 @@
-/* ====================================================================
-   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.formula;
-
-import org.apache.poi.ss.util.AreaReference;
-import org.apache.poi.util.LittleEndianInput;
-import org.apache.poi.util.LittleEndianOutput;
-
-/**
- * Common superclass of 2-D area refs
- */
-public abstract class Area2DPtgBase extends AreaPtgBase {
-	private final static int SIZE = 9;
-
-	protected Area2DPtgBase(int firstRow, int lastRow, int firstColumn, int lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
-		super(firstRow, lastRow, firstColumn, lastColumn, firstRowRelative, lastRowRelative, firstColRelative, lastColRelative);
-	}
-	protected Area2DPtgBase(AreaReference ar) {
-		super(ar);
-	}
-
-	protected Area2DPtgBase(LittleEndianInput in)  {
-		readCoordinates(in);
-	}
-
-	protected abstract byte getSid();
-
-	public final void write(LittleEndianOutput out) {
-		out.writeByte(getSid() + getPtgClass());
-		writeCoordinates(out);
-	}
-
-	public final int getSize() {
-		return SIZE;
-	}
-
-	public final String toFormulaString() {
-		return formatReferenceAsString();
-	}
-
-	public final String toString() {
-		StringBuffer sb = new StringBuffer();
-		sb.append(getClass().getName());
-		sb.append(" [");
-		sb.append(formatReferenceAsString());
-		sb.append("]");
-		return sb.toString();
-	}
-}
+/* ====================================================================
+   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.formula;
+
+import org.apache.poi.ss.util.AreaReference;
+import org.apache.poi.util.LittleEndianInput;
+import org.apache.poi.util.LittleEndianOutput;
+
+/**
+ * Common superclass of 2-D area refs
+ */
+public abstract class Area2DPtgBase extends AreaPtgBase {
+	private final static int SIZE = 9;
+
+	protected Area2DPtgBase(int firstRow, int lastRow, int firstColumn, int lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
+		super(firstRow, lastRow, firstColumn, lastColumn, firstRowRelative, lastRowRelative, firstColRelative, lastColRelative);
+	}
+	protected Area2DPtgBase(AreaReference ar) {
+		super(ar);
+	}
+
+	protected Area2DPtgBase(LittleEndianInput in)  {
+		readCoordinates(in);
+	}
+
+	protected abstract byte getSid();
+
+	public final void write(LittleEndianOutput out) {
+		out.writeByte(getSid() + getPtgClass());
+		writeCoordinates(out);
+	}
+
+	public final int getSize() {
+		return SIZE;
+	}
+
+	public final String toFormulaString() {
+		return formatReferenceAsString();
+	}
+
+	public final String toString() {
+		StringBuffer sb = new StringBuffer();
+		sb.append(getClass().getName());
+		sb.append(" [");
+		sb.append(formatReferenceAsString());
+		sb.append("]");
+		return sb.toString();
+	}
+}

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefPtg.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefPtg.java?rev=776377&r1=776376&r2=776377&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefPtg.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/RefPtg.java Tue May 19 16:29:51 2009
@@ -1,54 +1,54 @@
-/* ====================================================================
-   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.formula;
-
-import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.util.LittleEndianInput;
-
-/**
- * ReferencePtg - handles references (such as A1, A2, IA4)
- * @author  Andrew C. Oliver (acoliver@apache.org)
- * @author Jason Height (jheight at chariot dot net dot au)
- */
-public final class RefPtg extends Ref2DPtgBase {
-	public final static byte sid = 0x24;
-
-	/**
-	 * Takes in a String representation of a cell reference and fills out the
-	 * numeric fields.
-	 */
-	public RefPtg(String cellref) {
-		super(new CellReference(cellref));
-	}
-
-	public RefPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
-		super(row, column, isRowRelative, isColumnRelative);
-	}
-
-	public RefPtg(LittleEndianInput in)  {
-		super(in);
-	}
-
-	public RefPtg(CellReference cr) {
-		super(cr);
-	}
-
-	protected byte getSid() {
-		return sid;
-	}
-}
+/* ====================================================================
+   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.formula;
+
+import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.util.LittleEndianInput;
+
+/**
+ * ReferencePtg - handles references (such as A1, A2, IA4)
+ * @author  Andrew C. Oliver (acoliver@apache.org)
+ * @author Jason Height (jheight at chariot dot net dot au)
+ */
+public final class RefPtg extends Ref2DPtgBase {
+	public final static byte sid = 0x24;
+
+	/**
+	 * Takes in a String representation of a cell reference and fills out the
+	 * numeric fields.
+	 */
+	public RefPtg(String cellref) {
+		super(new CellReference(cellref));
+	}
+
+	public RefPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
+		super(row, column, isRowRelative, isColumnRelative);
+	}
+
+	public RefPtg(LittleEndianInput in)  {
+		super(in);
+	}
+
+	public RefPtg(CellReference cr) {
+		super(cr);
+	}
+
+	protected byte getSid() {
+		return sid;
+	}
+}

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/ScalarConstantPtg.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ScalarConstantPtg.java?rev=776377&r1=776376&r2=776377&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/ScalarConstantPtg.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/ScalarConstantPtg.java Tue May 19 16:29:51 2009
@@ -1,40 +1,40 @@
-/* ====================================================================
-   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.formula;
-
-
-/**
- * @author Josh Micich
- */
-abstract class ScalarConstantPtg extends Ptg {
-	public boolean isBaseToken() {
-		return true;
-	}
-
-	public final byte getDefaultOperandClass() {
-		return Ptg.CLASS_VALUE;
-	}
-
-	public final String toString() {
-		StringBuffer sb = new StringBuffer(64);
-		sb.append(getClass().getName()).append(" [");
-		sb.append(toFormulaString());
-		sb.append("]");
-		return sb.toString();
-	}
-}
+/* ====================================================================
+   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.formula;
+
+
+/**
+ * @author Josh Micich
+ */
+abstract class ScalarConstantPtg extends Ptg {
+	public boolean isBaseToken() {
+		return true;
+	}
+
+	public final byte getDefaultOperandClass() {
+		return Ptg.CLASS_VALUE;
+	}
+
+	public final String toString() {
+		StringBuffer sb = new StringBuffer(64);
+		sb.append(getClass().getName()).append(" [");
+		sb.append(toFormulaString());
+		sb.append("]");
+		return sb.toString();
+	}
+}

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/RefEvalBase.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/RefEvalBase.java?rev=776377&r1=776376&r2=776377&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/RefEvalBase.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/eval/RefEvalBase.java Tue May 19 16:29:51 2009
@@ -1,40 +1,40 @@
-/* ====================================================================
-   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.formula.eval;
-
-/**
- * Common base class for implementors of {@link RefEval}
- *
- * @author Josh Micich
- */
-public abstract class RefEvalBase implements RefEval {
-
-	private final int _rowIndex;
-	private final int _columnIndex;
-
-	protected RefEvalBase(int rowIndex, int columnIndex) {
-		_rowIndex = rowIndex;
-		_columnIndex = columnIndex;
-	}
-	public final int getRow() {
-		return _rowIndex;
-	}
-	public final int getColumn() {
-		return _columnIndex;
-	}
-}
+/* ====================================================================
+   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.formula.eval;
+
+/**
+ * Common base class for implementors of {@link RefEval}
+ *
+ * @author Josh Micich
+ */
+public abstract class RefEvalBase implements RefEval {
+
+	private final int _rowIndex;
+	private final int _columnIndex;
+
+	protected RefEvalBase(int rowIndex, int columnIndex) {
+		_rowIndex = rowIndex;
+		_columnIndex = columnIndex;
+	}
+	public final int getRow() {
+		return _rowIndex;
+	}
+	public final int getColumn() {
+		return _columnIndex;
+	}
+}

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java?rev=776377&r1=776376&r2=776377&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java Tue May 19 16:29:51 2009
@@ -1,162 +1,162 @@
-/* ====================================================================
-   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.usermodel;
-
-import org.apache.poi.hssf.model.HSSFFormulaParser;
-import org.apache.poi.hssf.model.Workbook;
-import org.apache.poi.hssf.record.NameRecord;
-import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
-import org.apache.poi.hssf.record.formula.NamePtg;
-import org.apache.poi.hssf.record.formula.NameXPtg;
-import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.ss.formula.*;
-import org.apache.poi.ss.SpreadsheetVersion;
-
-/**
- * Internal POI use only
- * 
- * @author Josh Micich
- */
-public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, EvaluationWorkbook, FormulaParsingWorkbook {
-
-    private final HSSFWorkbook _uBook;
-    private final Workbook _iBook;
-
-    public static HSSFEvaluationWorkbook create(HSSFWorkbook book) {
-        if (book == null) {
-            return null;
-        }
-        return new HSSFEvaluationWorkbook(book);
-    }
-
-    private HSSFEvaluationWorkbook(HSSFWorkbook book) {
-        _uBook = book;
-        _iBook = book.getWorkbook();
-    }
-
-    public int getExternalSheetIndex(String sheetName) {
-        int sheetIndex = _uBook.getSheetIndex(sheetName);
-        return _iBook.checkExternSheet(sheetIndex);
-    }
-    public int getExternalSheetIndex(String workbookName, String sheetName) {
-        return _iBook.getExternalSheetIndex(workbookName, sheetName);
-    }
-
-    public NameXPtg getNameXPtg(String name) {
-        return _iBook.getNameXPtg(name);
-    }
-
-    /**
-     * Lookup a named range by its name.
-     *
-     * @param name the name to search
-     * @param sheetIndex  the 0-based index of the sheet this formula belongs to.
-     * The sheet index is required to resolve sheet-level names. <code>-1</code> means workbook-global names
-      */
-    public EvaluationName getName(String name, int sheetIndex) {
-        for(int i=0; i < _iBook.getNumNames(); i++) {
-            NameRecord nr = _iBook.getNameRecord(i);
-            if (nr.getSheetNumber() == sheetIndex+1 && name.equalsIgnoreCase(nr.getNameText())) {
-                return new Name(nr, i);
-            }
-        }
-        return sheetIndex == -1 ? null : getName(name, -1);
-    }
-
-    public int getSheetIndex(EvaluationSheet evalSheet) {
-        HSSFSheet sheet = ((HSSFEvaluationSheet)evalSheet).getHSSFSheet();
-        return _uBook.getSheetIndex(sheet);
-    }
-    public int getSheetIndex(String sheetName) {
-        return _uBook.getSheetIndex(sheetName);
-    }
-
-    public String getSheetName(int sheetIndex) {
-        return _uBook.getSheetName(sheetIndex);
-    }
-
-    public EvaluationSheet getSheet(int sheetIndex) {
-        return new HSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex));
-    }
-    public int convertFromExternSheetIndex(int externSheetIndex) {
-        return _iBook.getSheetIndexFromExternSheetIndex(externSheetIndex);
-    }
-
-    public ExternalSheet getExternalSheet(int externSheetIndex) {
-        return _iBook.getExternalSheet(externSheetIndex);
-    }
-
-    public String resolveNameXText(NameXPtg n) {
-        return _iBook.resolveNameXText(n.getSheetRefIndex(), n.getNameIndex());
-    }
-
-    public String getSheetNameByExternSheet(int externSheetIndex) {
-        return _iBook.findSheetNameFromExternSheet(externSheetIndex);
-    }
-    public String getNameText(NamePtg namePtg) {
-        return _iBook.getNameRecord(namePtg.getIndex()).getNameText();
-    }
-    public EvaluationName getName(NamePtg namePtg) {
-        int ix = namePtg.getIndex();
-        return new Name(_iBook.getNameRecord(ix), ix);
-    }
-    public Ptg[] getFormulaTokens(EvaluationCell evalCell) {
-        HSSFCell cell = ((HSSFEvaluationCell)evalCell).getHSSFCell();
-        if (false) {
-            // re-parsing the formula text also works, but is a waste of time
-            // It is useful from time to time to run all unit tests with this code
-            // to make sure that all formulas POI can evaluate can also be parsed.
-            return HSSFFormulaParser.parse(cell.getCellFormula(), _uBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet()));
-        }
-        FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord();
-        return fra.getFormulaTokens();
-    }
-
-    private static final class Name implements EvaluationName {
-
-        private final NameRecord _nameRecord;
-        private final int _index;
-
-        public Name(NameRecord nameRecord, int index) {
-            _nameRecord = nameRecord;
-            _index = index;
-        }
-        public Ptg[] getNameDefinition() {
-            return _nameRecord.getNameDefinition();
-        }
-        public String getNameText() {
-            return _nameRecord.getNameText();
-        }
-        public boolean hasFormula() {
-            return _nameRecord.hasFormula();
-        }
-        public boolean isFunctionName() {
-            return _nameRecord.isFunctionName();
-        }
-        public boolean isRange() {
-            return _nameRecord.hasFormula(); // TODO - is this right?
-        }
-        public NamePtg createPtg() {
-            return new NamePtg(_index);
-        }
-    }
-
-    public SpreadsheetVersion getSpreadsheetVersion(){
-        return SpreadsheetVersion.EXCEL97;    
-    }
-}
+/* ====================================================================
+   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.usermodel;
+
+import org.apache.poi.hssf.model.HSSFFormulaParser;
+import org.apache.poi.hssf.model.Workbook;
+import org.apache.poi.hssf.record.NameRecord;
+import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
+import org.apache.poi.hssf.record.formula.NamePtg;
+import org.apache.poi.hssf.record.formula.NameXPtg;
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.ss.formula.*;
+import org.apache.poi.ss.SpreadsheetVersion;
+
+/**
+ * Internal POI use only
+ *
+ * @author Josh Micich
+ */
+public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, EvaluationWorkbook, FormulaParsingWorkbook {
+
+    private final HSSFWorkbook _uBook;
+    private final Workbook _iBook;
+
+    public static HSSFEvaluationWorkbook create(HSSFWorkbook book) {
+        if (book == null) {
+            return null;
+        }
+        return new HSSFEvaluationWorkbook(book);
+    }
+
+    private HSSFEvaluationWorkbook(HSSFWorkbook book) {
+        _uBook = book;
+        _iBook = book.getWorkbook();
+    }
+
+    public int getExternalSheetIndex(String sheetName) {
+        int sheetIndex = _uBook.getSheetIndex(sheetName);
+        return _iBook.checkExternSheet(sheetIndex);
+    }
+    public int getExternalSheetIndex(String workbookName, String sheetName) {
+        return _iBook.getExternalSheetIndex(workbookName, sheetName);
+    }
+
+    public NameXPtg getNameXPtg(String name) {
+        return _iBook.getNameXPtg(name);
+    }
+
+    /**
+     * Lookup a named range by its name.
+     *
+     * @param name the name to search
+     * @param sheetIndex  the 0-based index of the sheet this formula belongs to.
+     * The sheet index is required to resolve sheet-level names. <code>-1</code> means workbook-global names
+      */
+    public EvaluationName getName(String name, int sheetIndex) {
+        for(int i=0; i < _iBook.getNumNames(); i++) {
+            NameRecord nr = _iBook.getNameRecord(i);
+            if (nr.getSheetNumber() == sheetIndex+1 && name.equalsIgnoreCase(nr.getNameText())) {
+                return new Name(nr, i);
+            }
+        }
+        return sheetIndex == -1 ? null : getName(name, -1);
+    }
+
+    public int getSheetIndex(EvaluationSheet evalSheet) {
+        HSSFSheet sheet = ((HSSFEvaluationSheet)evalSheet).getHSSFSheet();
+        return _uBook.getSheetIndex(sheet);
+    }
+    public int getSheetIndex(String sheetName) {
+        return _uBook.getSheetIndex(sheetName);
+    }
+
+    public String getSheetName(int sheetIndex) {
+        return _uBook.getSheetName(sheetIndex);
+    }
+
+    public EvaluationSheet getSheet(int sheetIndex) {
+        return new HSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex));
+    }
+    public int convertFromExternSheetIndex(int externSheetIndex) {
+        return _iBook.getSheetIndexFromExternSheetIndex(externSheetIndex);
+    }
+
+    public ExternalSheet getExternalSheet(int externSheetIndex) {
+        return _iBook.getExternalSheet(externSheetIndex);
+    }
+
+    public String resolveNameXText(NameXPtg n) {
+        return _iBook.resolveNameXText(n.getSheetRefIndex(), n.getNameIndex());
+    }
+
+    public String getSheetNameByExternSheet(int externSheetIndex) {
+        return _iBook.findSheetNameFromExternSheet(externSheetIndex);
+    }
+    public String getNameText(NamePtg namePtg) {
+        return _iBook.getNameRecord(namePtg.getIndex()).getNameText();
+    }
+    public EvaluationName getName(NamePtg namePtg) {
+        int ix = namePtg.getIndex();
+        return new Name(_iBook.getNameRecord(ix), ix);
+    }
+    public Ptg[] getFormulaTokens(EvaluationCell evalCell) {
+        HSSFCell cell = ((HSSFEvaluationCell)evalCell).getHSSFCell();
+        if (false) {
+            // re-parsing the formula text also works, but is a waste of time
+            // It is useful from time to time to run all unit tests with this code
+            // to make sure that all formulas POI can evaluate can also be parsed.
+            return HSSFFormulaParser.parse(cell.getCellFormula(), _uBook, FormulaType.CELL, _uBook.getSheetIndex(cell.getSheet()));
+        }
+        FormulaRecordAggregate fra = (FormulaRecordAggregate) cell.getCellValueRecord();
+        return fra.getFormulaTokens();
+    }
+
+    private static final class Name implements EvaluationName {
+
+        private final NameRecord _nameRecord;
+        private final int _index;
+
+        public Name(NameRecord nameRecord, int index) {
+            _nameRecord = nameRecord;
+            _index = index;
+        }
+        public Ptg[] getNameDefinition() {
+            return _nameRecord.getNameDefinition();
+        }
+        public String getNameText() {
+            return _nameRecord.getNameText();
+        }
+        public boolean hasFormula() {
+            return _nameRecord.hasFormula();
+        }
+        public boolean isFunctionName() {
+            return _nameRecord.isFunctionName();
+        }
+        public boolean isRange() {
+            return _nameRecord.hasFormula(); // TODO - is this right?
+        }
+        public NamePtg createPtg() {
+            return new NamePtg(_index);
+        }
+    }
+
+    public SpreadsheetVersion getSpreadsheetVersion(){
+        return SpreadsheetVersion.EXCEL97;
+    }
+}

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java?rev=776377&r1=776376&r2=776377&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java Tue May 19 16:29:51 2009
@@ -1,315 +1,316 @@
-/* ====================================================================
-   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.usermodel;
-
-import java.util.Iterator;
-
-import org.apache.poi.hssf.record.formula.eval.BoolEval;
-import org.apache.poi.hssf.record.formula.eval.ErrorEval;
-import org.apache.poi.hssf.record.formula.eval.NumberEval;
-import org.apache.poi.hssf.record.formula.eval.StringEval;
-import org.apache.poi.hssf.record.formula.eval.ValueEval;
-import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment;
-import org.apache.poi.ss.formula.IStabilityClassifier;
-import org.apache.poi.ss.formula.WorkbookEvaluator;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellValue;
-import org.apache.poi.ss.usermodel.FormulaEvaluator;
-
-/**
- * Evaluates formula cells.<p/>
- *
- * For performance reasons, this class keeps a cache of all previously calculated intermediate
- * cell values.  Be sure to call {@link #clearAllCachedResultValues()} if any workbook cells are changed between
- * calls to evaluate~ methods on this class.
- *
- * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
- * @author Josh Micich
- */
-public class HSSFFormulaEvaluator implements FormulaEvaluator  {
-
-	private WorkbookEvaluator _bookEvaluator;
-
-	/**
-	 * @deprecated (Sep 2008) HSSFSheet parameter is ignored
-	 */
-	public HSSFFormulaEvaluator(HSSFSheet sheet, HSSFWorkbook workbook) {
-		this(workbook);
-		if (false) {
-			sheet.toString(); // suppress unused parameter compiler warning
-		}
-	}
-	public HSSFFormulaEvaluator(HSSFWorkbook workbook) {
-		this(workbook, null);
-	}
-	/**
-	 * @param stabilityClassifier used to optimise caching performance. Pass <code>null</code>
-	 * for the (conservative) assumption that any cell may have its definition changed after 
-	 * evaluation begins.
-	 */
-	public HSSFFormulaEvaluator(HSSFWorkbook workbook, IStabilityClassifier stabilityClassifier) {
-		_bookEvaluator = new WorkbookEvaluator(HSSFEvaluationWorkbook.create(workbook), stabilityClassifier);
-	}
-
-	/**
-	 * Coordinates several formula evaluators together so that formulas that involve external
-	 * references can be evaluated.
-	 * @param workbookNames the simple file names used to identify the workbooks in formulas
-	 * with external links (for example "MyData.xls" as used in a formula "[MyData.xls]Sheet1!A1")
-	 * @param evaluators all evaluators for the full set of workbooks required by the formulas.
-	 */
-	public static void setupEnvironment(String[] workbookNames, HSSFFormulaEvaluator[] evaluators) {
-		WorkbookEvaluator[] wbEvals = new WorkbookEvaluator[evaluators.length];
-		for (int i = 0; i < wbEvals.length; i++) {
-			wbEvals[i] = evaluators[i]._bookEvaluator;
-		}
-		CollaboratingWorkbooksEnvironment.setup(workbookNames, wbEvals);
-	}
-
-	/**
-	 * Does nothing
-	 * @deprecated (Aug 2008) - not needed, since the current row can be derived from the cell
-	 */
-	public void setCurrentRow(HSSFRow row) {
-		// do nothing
-		if (false) {
-			row.getClass(); // suppress unused parameter compiler warning
-		}
-	}
-
-	/**
-	 * Should be called whenever there are major changes (e.g. moving sheets) to input cells
-	 * in the evaluated workbook.  If performance is not critical, a single call to this method
-	 * may be used instead of many specific calls to the notify~ methods.
-	 *
-	 * Failure to call this method after changing cell values will cause incorrect behaviour
-	 * of the evaluate~ methods of this class
-	 */
-	public void clearAllCachedResultValues() {
-		_bookEvaluator.clearAllCachedResultValues();
-	}
-	/**
-	 * Should be called to tell the cell value cache that the specified (value or formula) cell
-	 * has changed.
-	 * Failure to call this method after changing cell values will cause incorrect behaviour
-	 * of the evaluate~ methods of this class
-	 */
-	public void notifyUpdateCell(HSSFCell cell) {
-		_bookEvaluator.notifyUpdateCell(new HSSFEvaluationCell(cell));
-	}
-	/**
-	 * Should be called to tell the cell value cache that the specified cell has just been
-	 * deleted.
-	 * Failure to call this method after changing cell values will cause incorrect behaviour
-	 * of the evaluate~ methods of this class
-	 */
-	public void notifyDeleteCell(HSSFCell cell) {
-		_bookEvaluator.notifyDeleteCell(new HSSFEvaluationCell(cell));
-	}
-	public void notifyDeleteCell(Cell cell) {
-		_bookEvaluator.notifyDeleteCell(new HSSFEvaluationCell((HSSFCell)cell));
-	}
-
-	/**
-	 * Should be called to tell the cell value cache that the specified (value or formula) cell
-	 * has changed.
-	 * Failure to call this method after changing cell values will cause incorrect behaviour
-	 * of the evaluate~ methods of this class
-	 */
-	public void notifySetFormula(Cell cell) {
-		_bookEvaluator.notifyUpdateCell(new HSSFEvaluationCell((HSSFCell)cell));
-	}
-
-	/**
-	 * If cell contains a formula, the formula is evaluated and returned,
-	 * else the CellValue simply copies the appropriate cell value from
-	 * the cell and also its cell type. This method should be preferred over
-	 * evaluateInCell() when the call should not modify the contents of the
-	 * original cell.
-	 *
-	 * @param cell may be <code>null</code> signifying that the cell is not present (or blank)
-	 * @return <code>null</code> if the supplied cell is <code>null</code> or blank
-	 */
-	public CellValue evaluate(Cell cell) {
-		if (cell == null) {
-			return null;
-		}
-
-		switch (cell.getCellType()) {
-			case HSSFCell.CELL_TYPE_BOOLEAN:
-				return CellValue.valueOf(cell.getBooleanCellValue());
-			case HSSFCell.CELL_TYPE_ERROR:
-				return CellValue.getError(cell.getErrorCellValue());
-			case HSSFCell.CELL_TYPE_FORMULA:
-				return evaluateFormulaCellValue(cell);
-			case HSSFCell.CELL_TYPE_NUMERIC:
-				return new CellValue(cell.getNumericCellValue());
-			case HSSFCell.CELL_TYPE_STRING:
-				return new CellValue(cell.getRichStringCellValue().getString());
-			case HSSFCell.CELL_TYPE_BLANK:
-				return null;
-		}
-		throw new IllegalStateException("Bad cell type (" + cell.getCellType() + ")");
-	}
-
-
-	/**
-	 * If cell contains formula, it evaluates the formula, and saves the result of the formula. The
-	 * cell remains as a formula cell. If the cell does not contain formula, this method returns -1
-	 * and leaves the cell unchanged.
-	 *
-	 * Note that the type of the <em>formula result</em> is returned, so you know what kind of
-	 * cached formula result is also stored with  the formula.
-	 * <pre>
-	 * int evaluatedCellType = evaluator.evaluateFormulaCell(cell);
-	 * </pre>
-	 * Be aware that your cell will hold both the formula, and the result. If you want the cell
-	 * replaced with the result of the formula, use {@link #evaluateInCell(org.apache.poi.ss.usermodel.Cell)}
-	 * @param cell The cell to evaluate
-	 * @return -1 for non-formula cells, or the type of the <em>formula result</em>
-	 */
-	public int evaluateFormulaCell(Cell cell) {
-		if (cell == null || cell.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
-			return -1;
-		}
-		CellValue cv = evaluateFormulaCellValue(cell);
-		// cell remains a formula cell, but the cached value is changed
-		setCellValue(cell, cv);
-		return cv.getCellType();
-	}
-
-	/**
-	 * If cell contains formula, it evaluates the formula, and
-	 *  puts the formula result back into the cell, in place
-	 *  of the old formula.
-	 * Else if cell does not contain formula, this method leaves
-	 *  the cell unchanged.
-	 * Note that the same instance of HSSFCell is returned to
-	 * allow chained calls like:
-	 * <pre>
-	 * int evaluatedCellType = evaluator.evaluateInCell(cell).getCellType();
-	 * </pre>
-	 * Be aware that your cell value will be changed to hold the
-	 *  result of the formula. If you simply want the formula
-	 *  value computed for you, use {@link #evaluateFormulaCell(Cell)}}
-	 */
-	public HSSFCell evaluateInCell(Cell cell) {
-		if (cell == null) {
-			return null;
-		}
-		HSSFCell result = (HSSFCell) cell;
-		if (cell.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
-			CellValue cv = evaluateFormulaCellValue(cell);
-			setCellValue(cell, cv);
-			setCellType(cell, cv); // cell will no longer be a formula cell
-		}
-		return result;
-	}
-	private static void setCellType(Cell cell, CellValue cv) {
-		int cellType = cv.getCellType();
-		switch (cellType) {
-			case HSSFCell.CELL_TYPE_BOOLEAN:
-			case HSSFCell.CELL_TYPE_ERROR:
-			case HSSFCell.CELL_TYPE_NUMERIC:
-			case HSSFCell.CELL_TYPE_STRING:
-				cell.setCellType(cellType);
-				return;
-			case HSSFCell.CELL_TYPE_BLANK:
-				// never happens - blanks eventually get translated to zero
-			case HSSFCell.CELL_TYPE_FORMULA:
-				// this will never happen, we have already evaluated the formula
-		}
-		throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
-	}
-
-	private static void setCellValue(Cell cell, CellValue cv) {
-		int cellType = cv.getCellType();
-		switch (cellType) {
-			case HSSFCell.CELL_TYPE_BOOLEAN:
-				cell.setCellValue(cv.getBooleanValue());
-				break;
-			case HSSFCell.CELL_TYPE_ERROR:
-				cell.setCellErrorValue(cv.getErrorValue());
-				break;
-			case HSSFCell.CELL_TYPE_NUMERIC:
-				cell.setCellValue(cv.getNumberValue());
-				break;
-			case HSSFCell.CELL_TYPE_STRING:
-				cell.setCellValue(new HSSFRichTextString(cv.getStringValue()));
-				break;
-			case HSSFCell.CELL_TYPE_BLANK:
-				// never happens - blanks eventually get translated to zero
-			case HSSFCell.CELL_TYPE_FORMULA:
-				// this will never happen, we have already evaluated the formula
-			default:
-				throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
-		}
-	}
-
-	/**
-	 * Loops over all cells in all sheets of the supplied
-	 *  workbook.
-	 * For cells that contain formulas, their formulas are
-	 *  evaluated, and the results are saved. These cells
-	 *  remain as formula cells.
-	 * For cells that do not contain formulas, no changes
-	 *  are made.
-	 * This is a helpful wrapper around looping over all
-	 *  cells, and calling evaluateFormulaCell on each one.
-	 */
-	public static void evaluateAllFormulaCells(HSSFWorkbook wb) {
-		HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
-		for(int i=0; i<wb.getNumberOfSheets(); i++) {
-			HSSFSheet sheet = wb.getSheetAt(i);
-
-			for (Iterator rit = sheet.rowIterator(); rit.hasNext();) {
-				HSSFRow r = (HSSFRow)rit.next();
-
-				for (Iterator cit = r.cellIterator(); cit.hasNext();) {
-					HSSFCell c = (HSSFCell)cit.next();
-					if (c.getCellType() == HSSFCell.CELL_TYPE_FORMULA)
-						evaluator.evaluateFormulaCell(c);
-				}
-			}
-		}
-	}
-
-	/**
-	 * Returns a CellValue wrapper around the supplied ValueEval instance.
-	 * @param eval
-	 */
-	private CellValue evaluateFormulaCellValue(Cell cell) {
-		ValueEval eval = _bookEvaluator.evaluate(new HSSFEvaluationCell((HSSFCell)cell));
-		if (eval instanceof NumberEval) {
-			NumberEval ne = (NumberEval) eval;
-			return new CellValue(ne.getNumberValue());
-		}
-		if (eval instanceof BoolEval) {
-			BoolEval be = (BoolEval) eval;
-			return CellValue.valueOf(be.getBooleanValue());
-		}
-		if (eval instanceof StringEval) {
-			StringEval ne = (StringEval) eval;
-			return new CellValue(ne.getStringValue());
-		}
-		if (eval instanceof ErrorEval) {
-			return CellValue.getError(((ErrorEval)eval).getErrorCode());
-		}
-		throw new RuntimeException("Unexpected eval class (" + eval.getClass().getName() + ")");
-	}
-}
+/* ====================================================================
+   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.usermodel;
+
+import java.util.Iterator;
+
+import org.apache.poi.hssf.record.formula.eval.BoolEval;
+import org.apache.poi.hssf.record.formula.eval.ErrorEval;
+import org.apache.poi.hssf.record.formula.eval.NumberEval;
+import org.apache.poi.hssf.record.formula.eval.StringEval;
+import org.apache.poi.hssf.record.formula.eval.ValueEval;
+import org.apache.poi.ss.formula.CollaboratingWorkbooksEnvironment;
+import org.apache.poi.ss.formula.IStabilityClassifier;
+import org.apache.poi.ss.formula.WorkbookEvaluator;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellValue;
+import org.apache.poi.ss.usermodel.FormulaEvaluator;
+import org.apache.poi.ss.usermodel.Row;
+
+/**
+ * Evaluates formula cells.<p/>
+ *
+ * For performance reasons, this class keeps a cache of all previously calculated intermediate
+ * cell values.  Be sure to call {@link #clearAllCachedResultValues()} if any workbook cells are changed between
+ * calls to evaluate~ methods on this class.
+ *
+ * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
+ * @author Josh Micich
+ */
+public class HSSFFormulaEvaluator implements FormulaEvaluator  {
+
+	private WorkbookEvaluator _bookEvaluator;
+
+	/**
+	 * @deprecated (Sep 2008) HSSFSheet parameter is ignored
+	 */
+	public HSSFFormulaEvaluator(HSSFSheet sheet, HSSFWorkbook workbook) {
+		this(workbook);
+		if (false) {
+			sheet.toString(); // suppress unused parameter compiler warning
+		}
+	}
+	public HSSFFormulaEvaluator(HSSFWorkbook workbook) {
+		this(workbook, null);
+	}
+	/**
+	 * @param stabilityClassifier used to optimise caching performance. Pass <code>null</code>
+	 * for the (conservative) assumption that any cell may have its definition changed after
+	 * evaluation begins.
+	 */
+	public HSSFFormulaEvaluator(HSSFWorkbook workbook, IStabilityClassifier stabilityClassifier) {
+		_bookEvaluator = new WorkbookEvaluator(HSSFEvaluationWorkbook.create(workbook), stabilityClassifier);
+	}
+
+	/**
+	 * Coordinates several formula evaluators together so that formulas that involve external
+	 * references can be evaluated.
+	 * @param workbookNames the simple file names used to identify the workbooks in formulas
+	 * with external links (for example "MyData.xls" as used in a formula "[MyData.xls]Sheet1!A1")
+	 * @param evaluators all evaluators for the full set of workbooks required by the formulas.
+	 */
+	public static void setupEnvironment(String[] workbookNames, HSSFFormulaEvaluator[] evaluators) {
+		WorkbookEvaluator[] wbEvals = new WorkbookEvaluator[evaluators.length];
+		for (int i = 0; i < wbEvals.length; i++) {
+			wbEvals[i] = evaluators[i]._bookEvaluator;
+		}
+		CollaboratingWorkbooksEnvironment.setup(workbookNames, wbEvals);
+	}
+
+	/**
+	 * Does nothing
+	 * @deprecated (Aug 2008) - not needed, since the current row can be derived from the cell
+	 */
+	public void setCurrentRow(HSSFRow row) {
+		// do nothing
+		if (false) {
+			row.getClass(); // suppress unused parameter compiler warning
+		}
+	}
+
+	/**
+	 * Should be called whenever there are major changes (e.g. moving sheets) to input cells
+	 * in the evaluated workbook.  If performance is not critical, a single call to this method
+	 * may be used instead of many specific calls to the notify~ methods.
+	 *
+	 * Failure to call this method after changing cell values will cause incorrect behaviour
+	 * of the evaluate~ methods of this class
+	 */
+	public void clearAllCachedResultValues() {
+		_bookEvaluator.clearAllCachedResultValues();
+	}
+	/**
+	 * Should be called to tell the cell value cache that the specified (value or formula) cell
+	 * has changed.
+	 * Failure to call this method after changing cell values will cause incorrect behaviour
+	 * of the evaluate~ methods of this class
+	 */
+	public void notifyUpdateCell(HSSFCell cell) {
+		_bookEvaluator.notifyUpdateCell(new HSSFEvaluationCell(cell));
+	}
+	/**
+	 * Should be called to tell the cell value cache that the specified cell has just been
+	 * deleted.
+	 * Failure to call this method after changing cell values will cause incorrect behaviour
+	 * of the evaluate~ methods of this class
+	 */
+	public void notifyDeleteCell(HSSFCell cell) {
+		_bookEvaluator.notifyDeleteCell(new HSSFEvaluationCell(cell));
+	}
+	public void notifyDeleteCell(Cell cell) {
+		_bookEvaluator.notifyDeleteCell(new HSSFEvaluationCell((HSSFCell)cell));
+	}
+
+	/**
+	 * Should be called to tell the cell value cache that the specified (value or formula) cell
+	 * has changed.
+	 * Failure to call this method after changing cell values will cause incorrect behaviour
+	 * of the evaluate~ methods of this class
+	 */
+	public void notifySetFormula(Cell cell) {
+		_bookEvaluator.notifyUpdateCell(new HSSFEvaluationCell((HSSFCell)cell));
+	}
+
+	/**
+	 * If cell contains a formula, the formula is evaluated and returned,
+	 * else the CellValue simply copies the appropriate cell value from
+	 * the cell and also its cell type. This method should be preferred over
+	 * evaluateInCell() when the call should not modify the contents of the
+	 * original cell.
+	 *
+	 * @param cell may be <code>null</code> signifying that the cell is not present (or blank)
+	 * @return <code>null</code> if the supplied cell is <code>null</code> or blank
+	 */
+	public CellValue evaluate(Cell cell) {
+		if (cell == null) {
+			return null;
+		}
+
+		switch (cell.getCellType()) {
+			case HSSFCell.CELL_TYPE_BOOLEAN:
+				return CellValue.valueOf(cell.getBooleanCellValue());
+			case HSSFCell.CELL_TYPE_ERROR:
+				return CellValue.getError(cell.getErrorCellValue());
+			case HSSFCell.CELL_TYPE_FORMULA:
+				return evaluateFormulaCellValue(cell);
+			case HSSFCell.CELL_TYPE_NUMERIC:
+				return new CellValue(cell.getNumericCellValue());
+			case HSSFCell.CELL_TYPE_STRING:
+				return new CellValue(cell.getRichStringCellValue().getString());
+			case HSSFCell.CELL_TYPE_BLANK:
+				return null;
+		}
+		throw new IllegalStateException("Bad cell type (" + cell.getCellType() + ")");
+	}
+
+
+	/**
+	 * If cell contains formula, it evaluates the formula, and saves the result of the formula. The
+	 * cell remains as a formula cell. If the cell does not contain formula, this method returns -1
+	 * and leaves the cell unchanged.
+	 *
+	 * Note that the type of the <em>formula result</em> is returned, so you know what kind of
+	 * cached formula result is also stored with  the formula.
+	 * <pre>
+	 * int evaluatedCellType = evaluator.evaluateFormulaCell(cell);
+	 * </pre>
+	 * Be aware that your cell will hold both the formula, and the result. If you want the cell
+	 * replaced with the result of the formula, use {@link #evaluateInCell(org.apache.poi.ss.usermodel.Cell)}
+	 * @param cell The cell to evaluate
+	 * @return -1 for non-formula cells, or the type of the <em>formula result</em>
+	 */
+	public int evaluateFormulaCell(Cell cell) {
+		if (cell == null || cell.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
+			return -1;
+		}
+		CellValue cv = evaluateFormulaCellValue(cell);
+		// cell remains a formula cell, but the cached value is changed
+		setCellValue(cell, cv);
+		return cv.getCellType();
+	}
+
+	/**
+	 * If cell contains formula, it evaluates the formula, and
+	 *  puts the formula result back into the cell, in place
+	 *  of the old formula.
+	 * Else if cell does not contain formula, this method leaves
+	 *  the cell unchanged.
+	 * Note that the same instance of HSSFCell is returned to
+	 * allow chained calls like:
+	 * <pre>
+	 * int evaluatedCellType = evaluator.evaluateInCell(cell).getCellType();
+	 * </pre>
+	 * Be aware that your cell value will be changed to hold the
+	 *  result of the formula. If you simply want the formula
+	 *  value computed for you, use {@link #evaluateFormulaCell(Cell)}}
+	 */
+	public HSSFCell evaluateInCell(Cell cell) {
+		if (cell == null) {
+			return null;
+		}
+		HSSFCell result = (HSSFCell) cell;
+		if (cell.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
+			CellValue cv = evaluateFormulaCellValue(cell);
+			setCellValue(cell, cv);
+			setCellType(cell, cv); // cell will no longer be a formula cell
+		}
+		return result;
+	}
+	private static void setCellType(Cell cell, CellValue cv) {
+		int cellType = cv.getCellType();
+		switch (cellType) {
+			case HSSFCell.CELL_TYPE_BOOLEAN:
+			case HSSFCell.CELL_TYPE_ERROR:
+			case HSSFCell.CELL_TYPE_NUMERIC:
+			case HSSFCell.CELL_TYPE_STRING:
+				cell.setCellType(cellType);
+				return;
+			case HSSFCell.CELL_TYPE_BLANK:
+				// never happens - blanks eventually get translated to zero
+			case HSSFCell.CELL_TYPE_FORMULA:
+				// this will never happen, we have already evaluated the formula
+		}
+		throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
+	}
+
+	private static void setCellValue(Cell cell, CellValue cv) {
+		int cellType = cv.getCellType();
+		switch (cellType) {
+			case HSSFCell.CELL_TYPE_BOOLEAN:
+				cell.setCellValue(cv.getBooleanValue());
+				break;
+			case HSSFCell.CELL_TYPE_ERROR:
+				cell.setCellErrorValue(cv.getErrorValue());
+				break;
+			case HSSFCell.CELL_TYPE_NUMERIC:
+				cell.setCellValue(cv.getNumberValue());
+				break;
+			case HSSFCell.CELL_TYPE_STRING:
+				cell.setCellValue(new HSSFRichTextString(cv.getStringValue()));
+				break;
+			case HSSFCell.CELL_TYPE_BLANK:
+				// never happens - blanks eventually get translated to zero
+			case HSSFCell.CELL_TYPE_FORMULA:
+				// this will never happen, we have already evaluated the formula
+			default:
+				throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
+		}
+	}
+
+	/**
+	 * Loops over all cells in all sheets of the supplied
+	 *  workbook.
+	 * For cells that contain formulas, their formulas are
+	 *  evaluated, and the results are saved. These cells
+	 *  remain as formula cells.
+	 * For cells that do not contain formulas, no changes
+	 *  are made.
+	 * This is a helpful wrapper around looping over all
+	 *  cells, and calling evaluateFormulaCell on each one.
+	 */
+	public static void evaluateAllFormulaCells(HSSFWorkbook wb) {
+		HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
+		for(int i=0; i<wb.getNumberOfSheets(); i++) {
+			HSSFSheet sheet = wb.getSheetAt(i);
+
+			for (Iterator<Row> rit = sheet.rowIterator(); rit.hasNext();) {
+				Row r = rit.next();
+
+				for (Iterator<Cell> cit = r.cellIterator(); cit.hasNext();) {
+					Cell c = cit.next();
+					if (c.getCellType() == HSSFCell.CELL_TYPE_FORMULA)
+						evaluator.evaluateFormulaCell(c);
+				}
+			}
+		}
+	}
+
+	/**
+	 * Returns a CellValue wrapper around the supplied ValueEval instance.
+	 * @param eval
+	 */
+	private CellValue evaluateFormulaCellValue(Cell cell) {
+		ValueEval eval = _bookEvaluator.evaluate(new HSSFEvaluationCell((HSSFCell)cell));
+		if (eval instanceof NumberEval) {
+			NumberEval ne = (NumberEval) eval;
+			return new CellValue(ne.getNumberValue());
+		}
+		if (eval instanceof BoolEval) {
+			BoolEval be = (BoolEval) eval;
+			return CellValue.valueOf(be.getBooleanValue());
+		}
+		if (eval instanceof StringEval) {
+			StringEval ne = (StringEval) eval;
+			return new CellValue(ne.getStringValue());
+		}
+		if (eval instanceof ErrorEval) {
+			return CellValue.getError(((ErrorEval)eval).getErrorCode());
+		}
+		throw new RuntimeException("Unexpected eval class (" + eval.getClass().getName() + ")");
+	}
+}



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