]> source.dussan.org Git - poi.git/commitdiff
42564 - fixed ArrayPtg to use ConstantValueParser. Fixed a few other ArrayPtg encodi...
authorJosh Micich <josh@apache.org>
Tue, 6 May 2008 02:02:41 +0000 (02:02 +0000)
committerJosh Micich <josh@apache.org>
Tue, 6 May 2008 02:02:41 +0000 (02:02 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@653668 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/changes.xml
src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/hssf/record/constant/ConstantValueParser.java
src/java/org/apache/poi/hssf/record/constant/ErrorConstant.java
src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java
src/java/org/apache/poi/hssf/record/formula/ArrayPtgA.java
src/java/org/apache/poi/hssf/record/formula/ArrayPtgV.java
src/testcases/org/apache/poi/hssf/record/formula/AllFormulaTests.java
src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java [new file with mode: 0644]
src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java

index a653d3c002356ac37847ebe731c41762ad19378c..5d842b02a332d5ee870da7ae08b96cc9ede6ab67 100644 (file)
@@ -37,6 +37,7 @@
 
                <!-- Don't forget to update status.xml too! -->
         <release version="3.1-beta2" date="2008-05-??">
+           <action dev="POI-DEVELOPERS" type="fix">42564 - fixed ArrayPtg to use ConstantValueParser.  Fixed a few other ArrayPtg encoding issues.</action>
            <action dev="POI-DEVELOPERS" type="fix">Follow-on from 28754 - StringPtg.toFormulaString() should escape double quotes</action>
            <action dev="POI-DEVELOPERS" type="fix">44929 - Improved error handling in HSSFWorkbook when attempting to read a BIFF5 file</action>
            <action dev="POI-DEVELOPERS" type="fix">44675 - Parameter operand classes (function metadata) required to encode SUM() etc properly. Added parse validation for number of parameters</action>
index f2b9fb8e12c0fc70cbb4aa2548b266ebe98bce82..97269693e58fc9700ddc749cea5fd48647fc756d 100644 (file)
@@ -34,6 +34,7 @@
        <!-- Don't forget to update changes.xml too! -->
     <changes>
         <release version="3.1-beta2" date="2008-05-??">
+           <action dev="POI-DEVELOPERS" type="fix">42564 - fixed ArrayPtg to use ConstantValueParser.  Fixed a few other ArrayPtg encoding issues.</action>
            <action dev="POI-DEVELOPERS" type="fix">Follow-on from 28754 - StringPtg.toFormulaString() should escape double quotes</action>
            <action dev="POI-DEVELOPERS" type="fix">44929 - Improved error handling in HSSFWorkbook when attempting to read a BIFF5 file</action>
            <action dev="POI-DEVELOPERS" type="fix">44675 - Parameter operand classes (function metadata) required to encode SUM() etc properly. Added parse validation for number of parameters</action>
index 7d44b008f8878981007787eadc5818974d1ce633..12f26bfdee5fdbd44df17eaca84923114eef2729 100755 (executable)
@@ -24,9 +24,8 @@ import org.apache.poi.util.LittleEndian;
 
 /**
  * To support Constant Values (2.5.7) as required by the CRN record.
- * This class should probably also be used for two dimensional arrays which are encoded by 
+ * This class is also used for two dimensional arrays which are encoded by 
  * EXTERNALNAME (5.39) records and Array tokens.<p/>
- * TODO - code in ArrayPtg should be merged with this code.  It currently supports only 2 of the constant types
  * 
  * @author Josh Micich
  */
index 2fc79a948f4d4d89ada4a46ccb5df6cb85fdafca..3421dd4a8e55fbafd8add2db92a763045c081902 100644 (file)
@@ -47,18 +47,31 @@ public class ErrorConstant {
        public int getErrorCode() {
                return _errorCode;
        }
+       public String getText() {
+               if(HSSFErrorConstants.isValidCode(_errorCode)) {
+                       return HSSFErrorConstants.getText(_errorCode);
+               }
+               return "unknown error code (" + _errorCode + ")";
+       }
 
        public static ErrorConstant valueOf(int errorCode) {
                switch (errorCode) {
-               case HSSFErrorConstants.ERROR_NULL:  return NULL;
-               case HSSFErrorConstants.ERROR_DIV_0: return DIV_0;
-               case HSSFErrorConstants.ERROR_VALUE: return VALUE;
-               case HSSFErrorConstants.ERROR_REF:   return REF;
-               case HSSFErrorConstants.ERROR_NAME:  return NAME;
-               case HSSFErrorConstants.ERROR_NUM:   return NUM;
-               case HSSFErrorConstants.ERROR_NA:    return NA;
+                       case HSSFErrorConstants.ERROR_NULL:  return NULL;
+                       case HSSFErrorConstants.ERROR_DIV_0: return DIV_0;
+                       case HSSFErrorConstants.ERROR_VALUE: return VALUE;
+                       case HSSFErrorConstants.ERROR_REF:   return REF;
+                       case HSSFErrorConstants.ERROR_NAME:  return NAME;
+                       case HSSFErrorConstants.ERROR_NUM:   return NUM;
+                       case HSSFErrorConstants.ERROR_NA:       return NA;
                }
                System.err.println("Warning - unexpected error code (" + errorCode + ")");
                return new ErrorConstant(errorCode);
        }
+       public String toString() {
+               StringBuffer sb = new StringBuffer(64);
+               sb.append(getClass().getName()).append(" [");
+               sb.append(getText());
+               sb.append("]");
+               return sb.toString();
+       }
 }
index 01942be55cf869881c61b51ef3b2e1242d35b2c6..251009b2870af8d6d1b69bcdf7d47457daa1d769 100644 (file)
 
 package org.apache.poi.hssf.record.formula;
 
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.BitField;
-import org.apache.poi.util.BitFieldFactory;
-import org.apache.poi.util.StringUtil;
-
-import org.apache.poi.hssf.util.CellReference;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.record.RecordFormatException;
 import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.hssf.record.SSTRecord;
 import org.apache.poi.hssf.record.UnicodeString;
+import org.apache.poi.hssf.record.constant.ConstantValueParser;
+import org.apache.poi.hssf.record.constant.ErrorConstant;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.util.LittleEndian;
 
 /**
  * ArrayPtg - handles arrays
  * 
- * The ArrayPtg is a little wierd, the size of the Ptg when parsing initially only
+ * The ArrayPtg is a little weird, the size of the Ptg when parsing initially only
  * includes the Ptg sid and the reserved bytes. The next Ptg in the expression then follows.
  * It is only after the "size" of all the Ptgs is met, that the ArrayPtg data is actually
  * held after this. So Ptg.createParsedExpression keeps track of the number of 
@@ -40,209 +35,160 @@ import org.apache.poi.hssf.record.UnicodeString;
  *  
  * @author Jason Height (jheight at chariot dot net dot au)
  */
-
-public class ArrayPtg extends Ptg
-{
-    public final static byte sid  = 0x20;
-    protected byte field_1_reserved;
-    protected byte field_2_reserved;
-    protected byte field_3_reserved;
-    protected byte field_4_reserved;
-    protected byte field_5_reserved;
-    protected byte field_6_reserved;
-    protected byte field_7_reserved;
-    
-    
-    protected short  token_1_columns;
-    protected short token_2_rows;
-    protected Object[][] token_3_arrayValues;
-
-    protected ArrayPtg() {
-      //Required for clone methods
-    }
-
-    public ArrayPtg(RecordInputStream in)
-    {
-       field_1_reserved = in.readByte();
-       field_2_reserved = in.readByte();
-       field_3_reserved = in.readByte();
-       field_4_reserved = in.readByte();
-       field_5_reserved = in.readByte();
-       field_6_reserved = in.readByte();
-       field_7_reserved = in.readByte();
-    }
-    
-    /** 
-     * Read in the actual token (array) values. This occurs 
-     * AFTER the last Ptg in the expression.
-     * See page 304-305 of Excel97-2007BinaryFileFormat(xls)Specification.pdf
-     */
-    public void readTokenValues(RecordInputStream in) {        
-        token_1_columns = (short)(0x00ff & in.readByte());
-        token_2_rows = in.readShort();
-        
-        //The token_1_columns and token_2_rows do not follow the documentation.
-        //The number of physical rows and columns is actually +1 of these values.
-        //Which is not explicitly documented.
-        token_1_columns++;
-        token_2_rows++;        
-        
-        token_3_arrayValues = new Object[token_1_columns][token_2_rows];
-        
-        for (int x=0;x<token_1_columns;x++) {
-                       for (int y=0;y<token_2_rows;y++) {
-                               byte grbit = in.readByte();
-                               if (grbit == 0x01) {
-                                       token_3_arrayValues[x][y] = new Double(in.readDouble());
-                               } else if (grbit == 0x02) {
-                                       //Ignore the doco, it is actually a unicode string with all the
-                                       //trimmings ie 16 bit size, option byte etc
-                                       token_3_arrayValues[x][y] = in.readUnicodeString();
-                               } else throw new RecordFormatException("Unknown grbit '"+grbit+"' at " + x + "," + y + " with " + in.remaining() + " bytes left");
+public class ArrayPtg extends Ptg {
+       public static final byte sid  = 0x20;
+
+       private static final int RESERVED_FIELD_LEN = 7;
+       // TODO - fix up field visibility and subclasses
+       protected byte[] field_1_reserved;
+       // data from these fields comes after the Ptg data of all tokens in current formula
+       protected short  token_1_columns;
+       protected short token_2_rows;
+       protected Object[] token_3_arrayValues;
+
+       protected ArrayPtg() {
+         //Required for clone methods
+       }
+
+       public ArrayPtg(RecordInputStream in)
+       {
+               field_1_reserved = new byte[RESERVED_FIELD_LEN];
+               // TODO - add readFully method to RecordInputStream
+               for(int i=0; i< RESERVED_FIELD_LEN; i++) {
+                       field_1_reserved[i] = in.readByte();
+               }
+       }
+       
+       /** 
+        * Read in the actual token (array) values. This occurs 
+        * AFTER the last Ptg in the expression.
+        * See page 304-305 of Excel97-2007BinaryFileFormat(xls)Specification.pdf
+        */
+       public void readTokenValues(RecordInputStream in) {
+               short nColumns = in.readUByte();
+               short nRows = in.readShort();
+               //The token_1_columns and token_2_rows do not follow the documentation.
+               //The number of physical rows and columns is actually +1 of these values.
+               //Which is not explicitly documented.
+               nColumns++;
+               nRows++;
+               
+               token_1_columns = nColumns;
+               token_2_rows = nRows;
+               
+               int totalCount = nRows * nColumns;
+               token_3_arrayValues = ConstantValueParser.parse(in, totalCount);
+       }
+
+       public String toString()
+       {
+               StringBuffer buffer = new StringBuffer("[ArrayPtg]\n");
+
+               buffer.append("columns = ").append(getColumnCount()).append("\n");
+               buffer.append("rows = ").append(getRowCount()).append("\n");
+               for (int x=0;x<getColumnCount();x++) {
+                       for (int y=0;y<getRowCount();y++) {
+                               Object o = token_3_arrayValues[getValueIndex(x, y)];
+                               buffer.append("[").append(x).append("][").append(y).append("] = ").append(o).append("\n"); 
+                       }
+               }
+               return buffer.toString();
+       }
+
+       /* package */ int getValueIndex(int colIx, int rowIx) {
+               if(colIx < 0 || colIx >= token_1_columns) {
+                       throw new IllegalArgumentException("Specified colIx (" + colIx 
+                                       + ") is outside the allowed range (0.." + (token_1_columns-1) + ")");
+               }
+               if(rowIx < 0 || rowIx >= token_2_rows) {
+                       throw new IllegalArgumentException("Specified rowIx (" + rowIx 
+                                       + ") is outside the allowed range (0.." + (token_2_rows-1) + ")");
+               }
+               return rowIx * token_1_columns + colIx;
+       }
+
+       public void writeBytes(byte[] data, int offset) {
+               
+               LittleEndian.putByte(data, offset + 0, sid + ptgClass);
+               System.arraycopy(field_1_reserved, 0, data, offset+1, RESERVED_FIELD_LEN);
+       }
+
+       public int writeTokenValueBytes(byte[] data, int offset) {
+
+               LittleEndian.putByte(data,  offset + 0, token_1_columns-1);
+               LittleEndian.putShort(data, offset + 1, (short)(token_2_rows-1));
+               ConstantValueParser.encode(data, offset + 3, token_3_arrayValues);
+               return 3 + ConstantValueParser.getEncodedSize(token_3_arrayValues);
+       }
+
+       public short getRowCount() {
+               return token_2_rows;
+       }
+
+       public short getColumnCount() {
+               return token_1_columns;
+       }
+
+       /** This size includes the size of the array Ptg plus the Array Ptg Token value size*/
+       public int getSize()
+       {
+               int size = 1+7+1+2;
+               size += ConstantValueParser.getEncodedSize(token_3_arrayValues);
+               return size;
+       }
+
+       public String toFormulaString(HSSFWorkbook book)
+       {
+               StringBuffer b = new StringBuffer();
+               b.append("{");
+               for (int x=0;x<getColumnCount();x++) {
+                       if (x > 0) {
+                               b.append(";");
                        }
-        }
-    }
-
-    public String toString()
-    {
-        StringBuffer buffer = new StringBuffer("[ArrayPtg]\n");
-
-        buffer.append("columns = ").append(getColumnCount()).append("\n");
-        buffer.append("rows = ").append(getRowCount()).append("\n");
-        for (int x=0;x<getColumnCount();x++) {
-               for (int y=0;y<getRowCount();y++) {
-                       Object o = token_3_arrayValues[x][y];
-                               buffer.append("[").append(x).append("][").append(y).append("] = ").append(o).append("\n"); 
-               }
-        }
-        return buffer.toString();
-    }
-
-    public void writeBytes(byte [] array, int offset)
-    {
-        array[offset++] = (byte) (sid + ptgClass);
-        array[offset++] = field_1_reserved;
-        array[offset++] = field_2_reserved;
-        array[offset++] = field_3_reserved;
-        array[offset++] = field_4_reserved;
-        array[offset++] = field_5_reserved;
-        array[offset++] = field_6_reserved;
-        array[offset++] = field_7_reserved;
-        
-    }
-    public int writeTokenValueBytes(byte [] array, int offset) {
-       int pos = 0;
-       array[pos + offset] = (byte)(token_1_columns-1);
-        pos++;
-        LittleEndian.putShort(array, pos+offset, (short)(token_2_rows-1));
-        pos += 2;
-        for (int x=0;x<getColumnCount();x++) {
-               for (int y=0;y<getRowCount();y++) {
-                       Object o = token_3_arrayValues[x][y];
-                       if (o instanceof Double) {
-                               array[pos+offset] = 0x01;
-                               pos++;
-                               LittleEndian.putDouble(array, pos+offset, ((Double)o).doubleValue());
-                               pos+=8;
-                       } else if (o instanceof UnicodeString) {
-                               array[pos+offset] = 0x02;
-                               pos++;                          
-                               UnicodeString s = (UnicodeString)o;
-                               //JMH TBD Handle string continuation. Id do it now but its 4am.
-                       UnicodeString.UnicodeRecordStats stats = new UnicodeString.UnicodeRecordStats();
-                       s.serialize(stats, pos + offset, array);
-                       pos += stats.recordSize; 
-                       } else throw new RuntimeException("Coding error");
-               }
-        }
-        return pos;
-    }
-
-    public void setRowCount(short row)
-    {
-        token_2_rows = row;
-    }
-
-    public short getRowCount()
-    {
-        return token_2_rows;
-    }
-
-    public void setColumnCount(short col)
-    {
-        token_1_columns = (byte)col;
-    }
-
-    public short getColumnCount()
-    {
-        return token_1_columns;
-    }
-
-    /** This size includes the size of the array Ptg plus the Array Ptg Token value size*/
-    public int getSize()
-    {
-       int size = 1+7+1+2;
-        for (int x=0;x<getColumnCount();x++) {
-               for (int y=0;y<getRowCount();y++) {
-                       Object o = token_3_arrayValues[x][y];
-                       if (o instanceof UnicodeString) {
-                               size++;
-                       UnicodeString.UnicodeRecordStats rs = new UnicodeString.UnicodeRecordStats();
-                    ((UnicodeString)o).getRecordSize(rs);                              
-                               size += rs.recordSize;
-                       } else if (o instanceof Double) {
-                               size += 9;
-                       }
-               }
-        }
-        return size;
-    }
-
-    public String toFormulaString(HSSFWorkbook book)
-    {
-       StringBuffer b = new StringBuffer();
-       b.append("{");
-        for (int x=0;x<getColumnCount();x++) {
-               for (int y=0;y<getRowCount();y++) {
-                       Object o = token_3_arrayValues[x][y];
-                       if (o instanceof String) {
-                               b.append((String)o);
-                       } else if (o instanceof Double) {
-                               b.append(((Double)o).doubleValue());
-                       }
-                       if (y != getRowCount())
-                               b.append(",");
-               }
-               if (x != getColumnCount())
-                       b.append(";");
-          }
-        b.append("}");
-        return b.toString();
-    }
-    
-    public byte getDefaultOperandClass() {
-        return Ptg.CLASS_ARRAY;
-    }
-    
-    public Object clone() {
-      ArrayPtg ptg = new ArrayPtg();
-      ptg.field_1_reserved = field_1_reserved;
-      ptg.field_2_reserved = field_2_reserved;
-      ptg.field_3_reserved = field_3_reserved;
-      ptg.field_4_reserved = field_4_reserved;
-      ptg.field_5_reserved = field_5_reserved;
-      ptg.field_6_reserved = field_6_reserved;
-      ptg.field_7_reserved = field_7_reserved;
-      
-      ptg.token_1_columns = token_1_columns;
-      ptg.token_2_rows = token_2_rows;
-      ptg.token_3_arrayValues = new Object[getColumnCount()][getRowCount()];
-      for (int x=0;x<getColumnCount();x++) {
-       for (int y=0;y<getRowCount();y++) {
-               ptg.token_3_arrayValues[x][y] = token_3_arrayValues[x][y];
-       }
-      }      
-      ptg.setClass(ptgClass);
-      return ptg;
-    }
+                       for (int y=0;y<getRowCount();y++) {
+                               if (y > 0) {
+                                       b.append(",");
+                               }
+                               Object o = token_3_arrayValues[getValueIndex(x, y)];
+                               b.append(getConstantText(o));
+                       }
+                 }
+               b.append("}");
+               return b.toString();
+       }
+       
+       private static String getConstantText(Object o) {
+
+               if (o == null) {
+                       return ""; // TODO - how is 'empty value' represented in formulas?
+               }
+               if (o instanceof UnicodeString) {
+                       return "\"" + ((UnicodeString)o).getString() + "\"";
+               }
+               if (o instanceof Double) {
+                       return ((Double)o).toString();
+               }
+               if (o instanceof Boolean) {
+                       ((Boolean)o).toString();
+               }
+               if (o instanceof ErrorConstant) {
+                       return ((ErrorConstant)o).getText();
+               }
+               throw new IllegalArgumentException("Unexpected constant class (" + o.getClass().getName() + ")");
+       }
+       
+       public byte getDefaultOperandClass() {
+               return Ptg.CLASS_ARRAY;
+       }
+       
+       public Object clone() {
+         ArrayPtg ptg = new ArrayPtg();
+         ptg.field_1_reserved = (byte[]) field_1_reserved.clone();
+         
+         ptg.token_1_columns = token_1_columns;
+         ptg.token_2_rows = token_2_rows;
+         ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone();
+         ptg.setClass(ptgClass);
+         return ptg;
+       }
 }
index 616f737b84793b7fd80a2ca769df1697c964404d..5be866e963f048a3cf69893d3b96db5e548612fb 100644 (file)
 
 package org.apache.poi.hssf.record.formula;
 
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.BitField;
-import org.apache.poi.util.BitFieldFactory;
-import org.apache.poi.util.StringUtil;
-
-import org.apache.poi.hssf.util.CellReference;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.record.RecordFormatException;
 import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.hssf.record.SSTRecord;
-import org.apache.poi.hssf.record.UnicodeString;
 
 /**
  * ArrayPtgA - handles arrays
  *  
  * @author Jason Height (jheight at chariot dot net dot au)
  */
-
-public class ArrayPtgA extends ArrayPtg
-{
+public final class ArrayPtgA extends ArrayPtg {
     public final static byte sid  = 0x60;
 
-    protected ArrayPtgA() {
-       super();
+    private ArrayPtgA() {
       //Required for clone methods
     }
 
-    public ArrayPtgA(RecordInputStream in)
-    {
+    public ArrayPtgA(RecordInputStream in) {
        super(in);
     }
         
     public Object clone() {
       ArrayPtgA ptg = new ArrayPtgA();
-      ptg.field_1_reserved = field_1_reserved;
-      ptg.field_2_reserved = field_2_reserved;
-      ptg.field_3_reserved = field_3_reserved;
-      ptg.field_4_reserved = field_4_reserved;
-      ptg.field_5_reserved = field_5_reserved;
-      ptg.field_6_reserved = field_6_reserved;
-      ptg.field_7_reserved = field_7_reserved;
+      ptg.field_1_reserved = (byte[]) field_1_reserved.clone();
       
       ptg.token_1_columns = token_1_columns;
       ptg.token_2_rows = token_2_rows;
-      ptg.token_3_arrayValues = new Object[getColumnCount()][getRowCount()];
-      for (int x=0;x<getColumnCount();x++) {
-       for (int y=0;y<getRowCount();y++) {
-               ptg.token_3_arrayValues[x][y] = token_3_arrayValues[x][y];
-       }
-      }      
+      ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone();
       ptg.setClass(ptgClass);
       return ptg;
     }
index 94aa32383f42d3feedae5cb068fa0ab29a848bb8..ba955654aae9e11f061474ae80815cfaceaffb54 100644 (file)
 
 package org.apache.poi.hssf.record.formula;
 
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.BitField;
-import org.apache.poi.util.BitFieldFactory;
-import org.apache.poi.util.StringUtil;
-
-import org.apache.poi.hssf.util.CellReference;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.hssf.record.RecordFormatException;
 import org.apache.poi.hssf.record.RecordInputStream;
-import org.apache.poi.hssf.record.SSTRecord;
-import org.apache.poi.hssf.record.UnicodeString;
 
 /**
  * ArrayPtg - handles arrays
  * 
- * The ArrayPtg is a little wierd, the size of the Ptg when parsing initially only
+ * The ArrayPtg is a little weird, the size of the Ptg when parsing initially only
  * includes the Ptg sid and the reserved bytes. The next Ptg in the expression then follows.
  * It is only after the "size" of all the Ptgs is met, that the ArrayPtg data is actually
  * held after this. So Ptg.createParsedExpression keeps track of the number of 
@@ -40,38 +30,24 @@ import org.apache.poi.hssf.record.UnicodeString;
  *  
  * @author Jason Height (jheight at chariot dot net dot au)
  */
-
-public class ArrayPtgV extends ArrayPtg
-{
+public final class ArrayPtgV extends ArrayPtg {
     public final static byte sid  = 0x40;
 
-    protected ArrayPtgV() {
+    private ArrayPtgV() {
       //Required for clone methods
     }
 
-    public ArrayPtgV(RecordInputStream in)
-    {
+    public ArrayPtgV(RecordInputStream in) {
        super(in);
     }
     
     public Object clone() {
       ArrayPtgV ptg = new ArrayPtgV();
-      ptg.field_1_reserved = field_1_reserved;
-      ptg.field_2_reserved = field_2_reserved;
-      ptg.field_3_reserved = field_3_reserved;
-      ptg.field_4_reserved = field_4_reserved;
-      ptg.field_5_reserved = field_5_reserved;
-      ptg.field_6_reserved = field_6_reserved;
-      ptg.field_7_reserved = field_7_reserved;
+      ptg.field_1_reserved = (byte[]) field_1_reserved.clone();
       
       ptg.token_1_columns = token_1_columns;
       ptg.token_2_rows = token_2_rows;
-      ptg.token_3_arrayValues = new Object[getColumnCount()][getRowCount()];
-      for (int x=0;x<getColumnCount();x++) {
-       for (int y=0;y<getRowCount();y++) {
-               ptg.token_3_arrayValues[x][y] = token_3_arrayValues[x][y];
-       }
-      }      
+      ptg.token_3_arrayValues = (Object[]) token_3_arrayValues.clone();
       ptg.setClass(ptgClass);
       return ptg;
     }
index 80f6616fa6b982dd4dff6144574298814ea658e6..a685fd2cb690254059e8a3448b73a3d90ee9abaf 100644 (file)
@@ -40,6 +40,7 @@ public final class AllFormulaTests {
                result.addTestSuite(TestArea3DPtg.class);
                result.addTestSuite(TestAreaErrPtg.class);
                result.addTestSuite(TestAreaPtg.class);
+               result.addTestSuite(TestArrayPtg.class);
                result.addTestSuite(TestErrPtg.class);
                result.addTestSuite(TestExternalFunctionFormulas.class);
                result.addTestSuite(TestFuncPtg.class);
diff --git a/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java b/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java
new file mode 100644 (file)
index 0000000..16f80bb
--- /dev/null
@@ -0,0 +1,95 @@
+/* ====================================================================
+   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 java.util.Arrays;
+
+import org.apache.poi.hssf.record.TestcaseRecordInputStream;
+import org.apache.poi.hssf.record.UnicodeString;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+/**
+ * Tests for <tt>ArrayPtg</tt>
+ * 
+ * @author Josh Micich
+ */
+public final class TestArrayPtg extends TestCase {
+
+       private static final byte[] ENCODED_PTG_DATA = {
+               0x40, 0x00,
+               0x08, 0x00,
+               0, 0, 0, 0, 0, 0, 0, 0, 
+       };
+       private static final byte[] ENCODED_CONSTANT_DATA = {
+               2,    // 3 columns
+               1, 0, // 2 rows
+               4, 1, 0, 0, 0, 0, 0, 0, 0, // TRUE
+               2, 4, 0, 0, 65, 66, 67, 68, // "ABCD"
+               2, 1, 0, 0, 69, // "E"
+               1, 0, 0, 0, 0, 0, 0, 0, 0, // 0
+               4, 0, 0, 0, 0, 0, 0, 0, 0, // FALSE
+               2, 2, 0, 0, 70, 71, // "FG"
+       };
+
+       /**
+        * Lots of problems with ArrayPtg's encoding of 
+        */
+       public void testReadWriteTokenValueBytes() {
+               
+               ArrayPtg ptg = new ArrayPtgV(new TestcaseRecordInputStream(ArrayPtgV.sid, ENCODED_PTG_DATA));
+               
+               ptg.readTokenValues(new TestcaseRecordInputStream(0, ENCODED_CONSTANT_DATA));
+               assertEquals(3, ptg.getColumnCount());
+               assertEquals(2, ptg.getRowCount());
+               Object[] values = ptg.token_3_arrayValues;
+               assertEquals(6, values.length);
+               
+               
+               assertEquals(Boolean.TRUE, values[0]);
+               assertEquals(new UnicodeString("ABCD"), values[1]);
+               assertEquals(new Double(0), values[3]);
+               assertEquals(Boolean.FALSE, values[4]);
+               assertEquals(new UnicodeString("FG"), values[5]);
+               
+               byte[] outBuf = new byte[ENCODED_CONSTANT_DATA.length];
+               ptg.writeTokenValueBytes(outBuf, 0);
+               
+               if(outBuf[0] == 4) {
+                       throw new AssertionFailedError("Identified bug 42564b");
+               }
+               assertTrue(Arrays.equals(ENCODED_CONSTANT_DATA, outBuf));
+       }
+
+       /**
+        * make sure constant elements are stored row by row 
+        */
+       public void testElementOrdering() {
+               ArrayPtg ptg = new ArrayPtgV(new TestcaseRecordInputStream(ArrayPtgV.sid, ENCODED_PTG_DATA));
+               ptg.readTokenValues(new TestcaseRecordInputStream(0, ENCODED_CONSTANT_DATA));
+               assertEquals(3, ptg.getColumnCount());
+               assertEquals(2, ptg.getRowCount());
+               
+               assertEquals(0, ptg.getValueIndex(0, 0));
+               assertEquals(1, ptg.getValueIndex(1, 0));
+               assertEquals(2, ptg.getValueIndex(2, 0));
+               assertEquals(3, ptg.getValueIndex(0, 1));
+               assertEquals(4, ptg.getValueIndex(1, 1));
+               assertEquals(5, ptg.getValueIndex(2, 1));
+       }
+}
index e0a2bde24a7f37b79e6a85c78593bf8c6ebca034..b87510c24e01dc5caf03d107ff1fb180068c4f2c 100644 (file)
@@ -732,7 +732,7 @@ public final class TestBugs extends TestCase {
      *  with the NameRecord, once you get past the BOFRecord
      *  issue.
      */
-    public void DISABLEDtest42564Alt() {
+    public void test42564Alt() {
         HSSFWorkbook wb = openSample("42564-2.xls");
         writeOutAndReadBack(wb);
     }