poi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject svn commit: r836332 - in /poi/trunk/src: java/org/apache/poi/hssf/record/formula/ArrayPtg.java java/org/apache/poi/hssf/record/formula/Ptg.java testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java
Date Sun, 15 Nov 2009 06:04:04 GMT
Author: josh
Date: Sun Nov 15 06:04:03 2009
New Revision: 836332

URL: http://svn.apache.org/viewvc?rev=836332&view=rev
Log:
made ArrayPtg immutable

Modified:
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java
    poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ptg.java
    poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java?rev=836332&r1=836331&r2=836332&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/ArrayPtg.java Sun Nov 15 06:04:03
2009
@@ -43,22 +43,23 @@
 	 */
 	public static final int PLAIN_TOKEN_SIZE = 1+RESERVED_FIELD_LEN;
 
-	private static final byte[] DEFAULT_RESERVED_DATA = new byte[RESERVED_FIELD_LEN];
-
-	// TODO - fix up field visibility and subclasses
-	private final byte[] field_1_reserved;
+	// 7 bytes of data (stored as an int, short and byte here)
+	private final int _reserved0Int;
+	private final int _reserved1Short;
+	private final int _reserved2Byte;
 
 	// data from these fields comes after the Ptg data of all tokens in current formula
-	private int  token_1_columns;
-	private short token_2_rows;
-	private Object[] token_3_arrayValues;
-
-	public ArrayPtg(LittleEndianInput 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();
-		}
+	private final int  _nColumns;
+	private final int _nRows;
+	private final Object[] _arrayValues;
+
+	ArrayPtg(int reserved0, int reserved1, int reserved2, int nColumns, int nRows, Object[]
arrayValues) {
+		_reserved0Int = reserved0;
+		_reserved1Short = reserved1;
+		_reserved2Byte = reserved2;
+		_nColumns = nColumns;
+		_nRows = nRows;
+		_arrayValues = arrayValues;
 	}
 	/**
 	 * @param values2d array values arranged in rows
@@ -67,10 +68,10 @@
 		int nColumns = values2d[0].length;
 		int nRows = values2d.length;
 		// convert 2-d to 1-d array (row by row according to getValueIndex())
-		token_1_columns = (short) nColumns;
-		token_2_rows = (short) nRows;
+		_nColumns = (short) nColumns;
+		_nRows = (short) nRows;
 
-		Object[] vv = new Object[token_1_columns * token_2_rows];
+		Object[] vv = new Object[_nColumns * _nRows];
 		for (int r=0; r<nRows; r++) {
 			Object[] rowData = values2d[r];
 			for (int c=0; c<nColumns; c++) {
@@ -78,21 +79,23 @@
 			}
 		}
 
-		token_3_arrayValues = vv;
-		field_1_reserved = DEFAULT_RESERVED_DATA;
+		_arrayValues = vv;
+		_reserved0Int = 0;
+		_reserved1Short = 0;
+		_reserved2Byte = 0;
 	}
 	/**
 	 * @return 2-d array (inner index is rowIx, outer index is colIx)
 	 */
 	public Object[][] getTokenArrayValues() {
-		if (token_3_arrayValues == null) {
+		if (_arrayValues == null) {
 			throw new IllegalStateException("array values not read yet");
 		}
-		Object[][] result = new Object[token_2_rows][token_1_columns];
-		for (int r = 0; r < token_2_rows; r++) {
+		Object[][] result = new Object[_nRows][_nColumns];
+		for (int r = 0; r < _nRows; r++) {
 			Object[] rowData = result[r];
-			for (int c = 0; c < token_1_columns; c++) {
-				rowData[c] = token_3_arrayValues[getValueIndex(c, r)];
+			for (int c = 0; c < _nColumns; c++) {
+				rowData[c] = _arrayValues[getValueIndex(c, r)];
 			}
 		}
 		return result;
@@ -102,33 +105,12 @@
 		return false;
 	}
 
-	/**
-	 * 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(LittleEndianInput in) {
-		int 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 sb = new StringBuffer("[ArrayPtg]\n");
 
 		sb.append("nRows = ").append(getRowCount()).append("\n");
 		sb.append("nCols = ").append(getColumnCount()).append("\n");
-		if (token_3_arrayValues == null) {
+		if (_arrayValues == null) {
 			sb.append("  #values#uninitialised#\n");
 		} else {
 			sb.append("  ").append(toFormulaString());
@@ -141,36 +123,38 @@
 	 * @return the index into the internal 1D array for the specified column and row
 	 */
 	/* package */ int getValueIndex(int colIx, int rowIx) {
-		if(colIx < 0 || colIx >= token_1_columns) {
+		if(colIx < 0 || colIx >= _nColumns) {
 			throw new IllegalArgumentException("Specified colIx (" + colIx
-					+ ") is outside the allowed range (0.." + (token_1_columns-1) + ")");
+					+ ") is outside the allowed range (0.." + (_nColumns-1) + ")");
 		}
-		if(rowIx < 0 || rowIx >= token_2_rows) {
+		if(rowIx < 0 || rowIx >= _nRows) {
 			throw new IllegalArgumentException("Specified rowIx (" + rowIx
-					+ ") is outside the allowed range (0.." + (token_2_rows-1) + ")");
+					+ ") is outside the allowed range (0.." + (_nRows-1) + ")");
 		}
-		return rowIx * token_1_columns + colIx;
+		return rowIx * _nColumns + colIx;
 	}
 
 	public void write(LittleEndianOutput out) {
 		out.writeByte(sid + getPtgClass());
-		out.write(field_1_reserved);
+		out.writeInt(_reserved0Int);
+		out.writeShort(_reserved1Short);
+		out.writeByte(_reserved2Byte);
 	}
 
 	public int writeTokenValueBytes(LittleEndianOutput out) {
 
-		out.writeByte(token_1_columns-1);
-		out.writeShort(token_2_rows-1);
-		ConstantValueParser.encode(out, token_3_arrayValues);
-		return 3 + ConstantValueParser.getEncodedSize(token_3_arrayValues);
+		out.writeByte(_nColumns-1);
+		out.writeShort(_nRows-1);
+		ConstantValueParser.encode(out, _arrayValues);
+		return 3 + ConstantValueParser.getEncodedSize(_arrayValues);
 	}
 
-	public short getRowCount() {
-		return token_2_rows;
+	public int getRowCount() {
+		return _nRows;
 	}
 
-	public short getColumnCount() {
-		return (short)token_1_columns;
+	public int getColumnCount() {
+		return _nColumns;
 	}
 
 	/** This size includes the size of the array Ptg plus the Array Ptg Token value size*/
@@ -178,7 +162,7 @@
 		return PLAIN_TOKEN_SIZE
 			// data written after the all tokens:
 			+ 1 + 2 // column, row
-			+ ConstantValueParser.getEncodedSize(token_3_arrayValues);
+			+ ConstantValueParser.getEncodedSize(_arrayValues);
 	}
 
 	public String toFormulaString() {
@@ -192,7 +176,7 @@
 			  	if (x > 0) {
 					b.append(",");
 				}
-		  		Object o = token_3_arrayValues[getValueIndex(x, y)];
+		  		Object o = _arrayValues[getValueIndex(x, y)];
 		  		b.append(getConstantText(o));
 		  	}
 		  }
@@ -223,4 +207,61 @@
 	public byte getDefaultOperandClass() {
 		return Ptg.CLASS_ARRAY;
 	}
+
+	/**
+	 * Represents the initial plain tArray token (without the constant data that trails the
whole
+	 * formula).  Objects of this class are only temporary and cannot be used as {@link Ptg}s.
+	 * These temporary objects get converted to {@link ArrayPtg} by the
+	 * {@link #finishReading(LittleEndianInput)} method.
+	 */
+	static final class Initial extends Ptg {
+		private final int _reserved0;
+		private final int _reserved1;
+		private final int _reserved2;
+
+		public Initial(LittleEndianInput in) {
+			_reserved0 = in.readInt();
+			_reserved1 = in.readUShort();
+			_reserved2 = in.readUByte();
+		}
+		private static RuntimeException invalid() {
+			throw new IllegalStateException("This object is a partially initialised tArray, and cannot
be used as a Ptg");
+		}
+		public byte getDefaultOperandClass() {
+			throw invalid();
+		}
+		public int getSize() {
+			return PLAIN_TOKEN_SIZE;
+		}
+		public boolean isBaseToken() {
+			return false;
+		}
+		public String toFormulaString() {
+			throw invalid();
+		}
+		public void write(LittleEndianOutput out) {
+			throw invalid();
+		}
+		/**
+		 * 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 ArrayPtg finishReading(LittleEndianInput in) {
+			int 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++;
+
+			int totalCount = nRows * nColumns;
+			Object[] arrayValues = ConstantValueParser.parse(in, totalCount);
+
+			ArrayPtg result = new ArrayPtg(_reserved0, _reserved1, _reserved2, nColumns, nRows, arrayValues);
+			result.setClass(getPtgClass());
+			return result;
+		}
+	}
 }

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ptg.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ptg.java?rev=836332&r1=836331&r2=836332&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ptg.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/formula/Ptg.java Sun Nov 15 06:04:03 2009
@@ -51,28 +51,26 @@
 	public static Ptg[] readTokens(int size, LittleEndianInput in) {
 		List<Ptg> temp = new ArrayList<Ptg>(4 + size / 2);
 		int pos = 0;
-		List<Ptg> arrayPtgs = null;
+		boolean hasArrayPtgs = false;
 		while (pos < size) {
 			Ptg ptg = Ptg.createPtg(in);
-			if (ptg instanceof ArrayPtg) {
-				if (arrayPtgs == null) {
-					arrayPtgs = new ArrayList<Ptg>(5);
-				}
-				arrayPtgs.add(ptg);
-				pos += ArrayPtg.PLAIN_TOKEN_SIZE;
-			} else {
-				pos += ptg.getSize();
+			if (ptg instanceof ArrayPtg.Initial) {
+				hasArrayPtgs = true;
 			}
+			pos += ptg.getSize();
 			temp.add(ptg);
 		}
 		if(pos != size) {
 			throw new RuntimeException("Ptg array size mismatch");
 		}
-		if (arrayPtgs != null) {
-			for (int i=0;i<arrayPtgs.size();i++) {
-				ArrayPtg p = (ArrayPtg)arrayPtgs.get(i);
-				p.readTokenValues(in);
+		if (hasArrayPtgs) {
+			Ptg[] result = toPtgArray(temp);
+			for (int i=0;i<result.length;i++) {
+				if (result[i] instanceof ArrayPtg.Initial) {
+					result[i] = ((ArrayPtg.Initial) result[i]).finishReading(in);
+				}
 			}
+			return result;
 		}
 		return toPtgArray(temp);
 	}
@@ -101,7 +99,7 @@
 		int baseId = id & 0x1F | 0x20;
 
 		switch (baseId) {
-			case ArrayPtg.sid:    return new ArrayPtg(in);    // 0x20, 0x40, 0x60
+			case ArrayPtg.sid:    return new ArrayPtg.Initial(in);//0x20, 0x40, 0x60
 			case FuncPtg.sid:     return FuncPtg.create(in);  // 0x21, 0x41, 0x61
 			case FuncVarPtg.sid:  return FuncVarPtg.create(in);//0x22, 0x42, 0x62
 			case NamePtg.sid:     return new NamePtg(in);     // 0x23, 0x43, 0x63

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java?rev=836332&r1=836331&r2=836332&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/TestArrayPtg.java Sun Nov 15
06:04:03 2009
@@ -49,14 +49,16 @@
 		2, 2, 0, 0, 70, 71, // "FG"
 	};
 
+	private static ArrayPtg create(byte[] initialData, byte[] constantData) {
+		ArrayPtg.Initial ptgInit = new ArrayPtg.Initial(TestcaseRecordInputStream.createLittleEndian(initialData));
+		return ptgInit.finishReading(TestcaseRecordInputStream.createLittleEndian(constantData));
+	}
+
 	/**
-	 * Lots of problems with ArrayPtg's encoding of
+	 * Lots of problems with ArrayPtg's decoding and encoding of the element value data
 	 */
 	public void testReadWriteTokenValueBytes() {
-
-		ArrayPtg ptg = new ArrayPtg(TestcaseRecordInputStream.createLittleEndian(ENCODED_PTG_DATA));
-
-		ptg.readTokenValues(TestcaseRecordInputStream.createLittleEndian(ENCODED_CONSTANT_DATA));
+		ArrayPtg ptg = create(ENCODED_PTG_DATA, ENCODED_CONSTANT_DATA);
 		assertEquals(3, ptg.getColumnCount());
 		assertEquals(2, ptg.getRowCount());
 		Object[][] values = ptg.getTokenArrayValues();
@@ -78,12 +80,12 @@
 		assertTrue(Arrays.equals(ENCODED_CONSTANT_DATA, outBuf));
 	}
 
+
 	/**
 	 * Excel stores array elements column by column.  This test makes sure POI does the same.
 	 */
 	public void testElementOrdering() {
-		ArrayPtg ptg = new ArrayPtg(TestcaseRecordInputStream.createLittleEndian(ENCODED_PTG_DATA));
-		ptg.readTokenValues(TestcaseRecordInputStream.createLittleEndian(ENCODED_CONSTANT_DATA));
+		ArrayPtg ptg = create(ENCODED_PTG_DATA, ENCODED_CONSTANT_DATA);
 		assertEquals(3, ptg.getColumnCount());
 		assertEquals(2, ptg.getRowCount());
 
@@ -113,10 +115,7 @@
 	}
 
 	public void testToFormulaString() {
-		ArrayPtg ptg = new ArrayPtg(TestcaseRecordInputStream.createLittleEndian(ENCODED_PTG_DATA));
-
-		ptg.readTokenValues(TestcaseRecordInputStream.createLittleEndian(ENCODED_CONSTANT_DATA));
-
+		ArrayPtg ptg = create(ENCODED_PTG_DATA, ENCODED_CONSTANT_DATA);
 		String actualFormula;
 		try {
 			actualFormula = ptg.toFormulaString();
@@ -139,9 +138,7 @@
 	}
 
 	private static void confirmOperandClassDecoding(byte operandClass) {
-		byte[] fullData = new byte[ENCODED_PTG_DATA.length + ENCODED_CONSTANT_DATA.length];
-		System.arraycopy(ENCODED_PTG_DATA, 0, fullData, 0, ENCODED_PTG_DATA.length);
-		System.arraycopy(ENCODED_CONSTANT_DATA, 0, fullData, ENCODED_PTG_DATA.length, ENCODED_CONSTANT_DATA.length);
+		byte[] fullData = concat(ENCODED_PTG_DATA, ENCODED_CONSTANT_DATA);
 
 		// Force encoded operand class for tArray
 		fullData[0] = (byte) (ArrayPtg.sid + operandClass);
@@ -153,4 +150,11 @@
 		ArrayPtg aPtg = (ArrayPtg) ptgs[0];
 		assertEquals(operandClass, aPtg.getPtgClass());
 	}
+
+	private static byte[] concat(byte[] a, byte[] b) {
+		byte[] result = new byte[a.length + b.length];
+		System.arraycopy(a, 0, result, 0, a.length);
+		System.arraycopy(b, 0, result, a.length, b.length);
+		return result;
+	}
 }



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


Mime
View raw message