diff --git a/src/java/org/apache/poi/hssf/record/ExternalNameRecord.java b/src/java/org/apache/poi/hssf/record/ExternalNameRecord.java index 771603c85..fe2085948 100755 --- a/src/java/org/apache/poi/hssf/record/ExternalNameRecord.java +++ b/src/java/org/apache/poi/hssf/record/ExternalNameRecord.java @@ -17,7 +17,6 @@ package org.apache.poi.hssf.record; -import java.util.List; import java.util.Stack; import org.apache.poi.hssf.record.formula.Ptg; @@ -27,153 +26,160 @@ import org.apache.poi.util.StringUtil; /** * EXTERNALNAME
* - * @author josh micich + * @author Josh Micich */ public final class ExternalNameRecord extends Record { - public final static short sid = 0x23; // as per BIFF8. (some old versions used 0x223) + public final static short sid = 0x23; // as per BIFF8. (some old versions used 0x223) + + private static final int OPT_BUILTIN_NAME = 0x0001; + private static final int OPT_AUTOMATIC_LINK = 0x0002; + private static final int OPT_PICTURE_LINK = 0x0004; + private static final int OPT_STD_DOCUMENT_NAME = 0x0008; + private static final int OPT_OLE_LINK = 0x0010; +// private static final int OPT_CLIP_FORMAT_MASK = 0x7FE0; + private static final int OPT_ICONIFIED_PICTURE_LINK= 0x8000; - private static final int OPT_BUILTIN_NAME = 0x0001; - private static final int OPT_AUTOMATIC_LINK = 0x0002; - private static final int OPT_PICTURE_LINK = 0x0004; - private static final int OPT_STD_DOCUMENT_NAME = 0x0008; - private static final int OPT_OLE_LINK = 0x0010; -// private static final int OPT_CLIP_FORMAT_MASK = 0x7FE0; - private static final int OPT_ICONIFIED_PICTURE_LINK = 0x8000; + private short field_1_option_flag; + private short field_2_index; + private short field_3_not_used; + private String field_4_name; + private Ptg[] field_5_name_definition; // TODO - junits for name definition field - - private short field_1_option_flag; - private short field_2_index; - private short field_3_not_used; - private String field_4_name; - private Stack field_5_name_definition; - - - public ExternalNameRecord(RecordInputStream in) { - super(in); - } + public ExternalNameRecord(RecordInputStream in) { + super(in); + } /** * Convenience Function to determine if the name is a built-in name */ public boolean isBuiltInName() { - return (field_1_option_flag & OPT_BUILTIN_NAME) != 0; + return (field_1_option_flag & OPT_BUILTIN_NAME) != 0; + } + /** + * For OLE and DDE, links can be either 'automatic' or 'manual' + */ + public boolean isAutomaticLink() { + return (field_1_option_flag & OPT_AUTOMATIC_LINK) != 0; + } + /** + * only for OLE and DDE + */ + public boolean isPicureLink() { + return (field_1_option_flag & OPT_PICTURE_LINK) != 0; + } + /** + * DDE links only. Iftrue
, this denotes the 'StdDocumentName'
+ */
+ public boolean isStdDocumentNameIdentifier() {
+ return (field_1_option_flag & OPT_STD_DOCUMENT_NAME) != 0;
+ }
+ public boolean isOLELink() {
+ return (field_1_option_flag & OPT_OLE_LINK) != 0;
+ }
+ public boolean isIconifiedPictureLink() {
+ return (field_1_option_flag & OPT_ICONIFIED_PICTURE_LINK) != 0;
+ }
+ /**
+ * @return the standard String representation of this name
+ */
+ public String getText() {
+ return field_4_name;
}
- /**
- * For OLE and DDE, links can be either 'automatic' or 'manual'
- */
- public boolean isAutomaticLink() {
- return (field_1_option_flag & OPT_AUTOMATIC_LINK) != 0;
- }
- /**
- * only for OLE and DDE
- */
- public boolean isPicureLink() {
- return (field_1_option_flag & OPT_PICTURE_LINK) != 0;
- }
- /**
- * DDE links only. If true
, this denotes the 'StdDocumentName'
- */
- public boolean isStdDocumentNameIdentifier() {
- return (field_1_option_flag & OPT_STD_DOCUMENT_NAME) != 0;
- }
- public boolean isOLELink() {
- return (field_1_option_flag & OPT_OLE_LINK) != 0;
- }
- public boolean isIconifiedPictureLink() {
- return (field_1_option_flag & OPT_ICONIFIED_PICTURE_LINK) != 0;
- }
- /**
- * @return the standard String representation of this name
- */
- public String getText() {
- return field_4_name;
- }
- /**
- * called by constructor, should throw runtime exception in the event of a
- * record passed with a differing ID.
- *
- * @param id alleged id for this record
- */
- protected void validateSid(short id) {
- if (id != sid) {
- throw new RecordFormatException("NOT A valid ExternalName RECORD");
- }
- }
+ /**
+ * called by constructor, should throw runtime exception in the event of a
+ * record passed with a differing ID.
+ *
+ * @param id alleged id for this record
+ */
+ protected void validateSid(short id) {
+ if (id != sid) {
+ throw new RecordFormatException("NOT A valid ExternalName RECORD");
+ }
+ }
- private int getDataSize(){
- return 2 + 2 + field_4_name.length() + 2 + getNameDefinitionSize();
- }
+ private int getDataSize(){
+ return 3 * 2 // 3 short fields
+ + 2 + field_4_name.length() // nameLen and name
+ + 2 + getNameDefinitionSize(); // nameDefLen and nameDef
+ }
- /**
- * called by the class that is responsible for writing this sucker.
- * Subclasses should implement this so that their data is passed back in a
- * byte array.
- *
- * @param offset to begin writing at
- * @param data byte array containing instance data
- * @return number of bytes written
- */
- public int serialize( int offset, byte[] data ) {
- // TODO - junit tests
- int dataSize = getDataSize();
+ /**
+ * called by the class that is responsible for writing this sucker.
+ * Subclasses should implement this so that their data is passed back in a
+ * byte array.
+ *
+ * @param offset to begin writing at
+ * @param data byte array containing instance data
+ * @return number of bytes written
+ */
+ public int serialize( int offset, byte[] data ) {
+ int dataSize = getDataSize();
- LittleEndian.putShort( data, 0 + offset, sid );
+ LittleEndian.putShort( data, 0 + offset, sid );
LittleEndian.putShort( data, 2 + offset, (short) dataSize );
- LittleEndian.putShort( data, 4 + offset, field_1_option_flag );
- LittleEndian.putShort( data, 6 + offset, field_2_index );
- LittleEndian.putShort( data, 8 + offset, field_3_not_used );
- short nameLen = (short) field_4_name.length();
+ LittleEndian.putShort( data, 4 + offset, field_1_option_flag );
+ LittleEndian.putShort( data, 6 + offset, field_2_index );
+ LittleEndian.putShort( data, 8 + offset, field_3_not_used );
+ short nameLen = (short) field_4_name.length();
LittleEndian.putShort( data, 10 + offset, nameLen );
- StringUtil.putCompressedUnicode( field_4_name, data, 10 + offset );
- short defLen = (short) getNameDefinitionSize();
- LittleEndian.putShort( data, 12 + nameLen + offset, defLen );
- Ptg.serializePtgStack(field_5_name_definition, data, 12 + nameLen + offset );
+ StringUtil.putCompressedUnicode( field_4_name, data, 12 + offset );
+ short defLen = (short) getNameDefinitionSize();
+ LittleEndian.putShort( data, 12 + nameLen + offset, defLen );
+ Ptg.serializePtgStack(toStack(field_5_name_definition), data, 14 + nameLen + offset );
return dataSize + 4;
- }
+ }
- private int getNameDefinitionSize() {
- int result = 0;
- List list = field_5_name_definition;
-
- for (int k = 0; k < list.size(); k++)
- {
- Ptg ptg = ( Ptg ) list.get(k);
-
- result += ptg.getSize();
- }
- return result;
- }
+ private int getNameDefinitionSize() {
+ int result = 0;
+ for (int i = 0; i < field_5_name_definition.length; i++) {
+ result += field_5_name_definition[i].getSize();
+ }
+ return result;
+ }
- public int getRecordSize(){
- return 6 + 2 + field_4_name.length() + 2 + getNameDefinitionSize();
- }
+ public int getRecordSize(){
+ return 4 + getDataSize();
+ }
- protected void fillFields(RecordInputStream in) {
- field_1_option_flag = in.readShort();
- field_2_index = in.readShort();
- field_3_not_used = in.readShort();
- short nameLength = in.readShort();
- field_4_name = in.readCompressedUnicode(nameLength);
- short formulaLen = in.readShort();
- field_5_name_definition = Ptg.createParsedExpressionTokens(formulaLen, in);
- }
+ protected void fillFields(RecordInputStream in) {
+ field_1_option_flag = in.readShort();
+ field_2_index = in.readShort();
+ field_3_not_used = in.readShort();
+ short nameLength = in.readShort();
+ field_4_name = in.readCompressedUnicode(nameLength);
+ short formulaLen = in.readShort();
+ field_5_name_definition = toPtgArray(Ptg.createParsedExpressionTokens(formulaLen, in));
+ }
- public short getSid() {
- return sid;
- }
+ private static Ptg[] toPtgArray(Stack s) {
+ Ptg[] result = new Ptg[s.size()];
+ s.toArray(result);
+ return result;
+ }
+ private static Stack toStack(Ptg[] ptgs) {
+ Stack result = new Stack();
+ for (int i = 0; i < ptgs.length; i++) {
+ result.push(ptgs[i]);
+ }
+ return result;
+ }
+
+ public short getSid() {
+ return sid;
+ }
- public String toString() {
- StringBuffer sb = new StringBuffer();
- sb.append(getClass().getName()).append(" [EXTERNALNAME ");
- sb.append(" ").append(field_4_name);
- sb.append(" ix=").append(field_2_index);
- sb.append("]");
- return sb.toString();
- }
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(getClass().getName()).append(" [EXTERNALNAME ");
+ sb.append(" ").append(field_4_name);
+ sb.append(" ix=").append(field_2_index);
+ sb.append("]");
+ return sb.toString();
+ }
}
diff --git a/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java b/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java
index b1acfeafa..9da8f45eb 100755
--- a/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java
+++ b/src/testcases/org/apache/poi/hssf/record/AllRecordTests.java
@@ -14,7 +14,6 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
package org.apache.poi.hssf.record;
@@ -28,10 +27,10 @@ import junit.framework.TestSuite;
*
* @author Josh Micich
*/
-public class AllRecordTests {
+public final class AllRecordTests {
public static Test suite() {
- TestSuite result = new TestSuite("Tests for org.apache.poi.hssf.record");
+ TestSuite result = new TestSuite(AllRecordTests.class.getName());
result.addTest(AllFormulaTests.suite());
@@ -56,6 +55,7 @@ public class AllRecordTests {
result.addTestSuite(TestEmbeddedObjectRefSubRecord.class);
result.addTestSuite(TestEndSubRecord.class);
result.addTestSuite(TestEscherAggregate.class);
+ result.addTestSuite(TestExternalNameRecord.class);
result.addTestSuite(TestFontBasisRecord.class);
result.addTestSuite(TestFontIndexRecord.class);
result.addTestSuite(TestFormulaRecord.class);
diff --git a/src/testcases/org/apache/poi/hssf/record/TestExternalNameRecord.java b/src/testcases/org/apache/poi/hssf/record/TestExternalNameRecord.java
new file mode 100644
index 000000000..a90221f5e
--- /dev/null
+++ b/src/testcases/org/apache/poi/hssf/record/TestExternalNameRecord.java
@@ -0,0 +1,55 @@
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.record;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+/**
+ *
+ * @author Josh Micich
+ */
+public final class TestExternalNameRecord extends TestCase {
+
+ private static final byte[] dataFDS = {
+ 0, 0, 0, 0, 0, 0, 3, 0, 70, 68, 83, 0, 0,
+ };
+ private static ExternalNameRecord createSimpleENR() {
+ return new ExternalNameRecord(new TestcaseRecordInputStream((short)0x0023, dataFDS));
+ }
+ public void testBasicDeserializeReserialize() {
+
+ ExternalNameRecord enr = createSimpleENR();
+ assertEquals( "FDS", enr.getText());
+
+ try {
+ TestcaseRecordInputStream.confirmRecordEncoding(0x0023, dataFDS, enr.serialize());
+ } catch (ArrayIndexOutOfBoundsException e) {
+ if(e.getMessage().equals("15")) {
+ throw new AssertionFailedError("Identified bug 44691");
+ }
+ }
+ }
+
+ public void testBasicSize() {
+ ExternalNameRecord enr = createSimpleENR();
+ if(enr.getRecordSize() == 13) {
+ throw new AssertionFailedError("Identified bug 44691");
+ }
+ assertEquals(17, enr.getRecordSize());
+ }
+}