poi-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From u..@apache.org
Subject svn commit: r634936 [4/8] - in /poi/branches/ooxml: ./ legal/ src/contrib/src/org/apache/poi/hssf/contrib/view/ src/documentation/content/xdocs/ src/documentation/content/xdocs/getinvolved/ src/documentation/content/xdocs/hslf/ src/java/org/apache/poi/...
Date Sat, 08 Mar 2008 11:49:17 GMT
Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/util/AreaReference.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/util/AreaReference.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/util/AreaReference.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/util/AreaReference.java Sat Mar  8 03:49:00 2008
@@ -21,28 +21,63 @@
 import java.util.ArrayList;
 import java.util.StringTokenizer;
 
-public class AreaReference {
+public final class AreaReference {
 
-
-private CellReference [] cells;
-private int dim;
+    /** The character (!) that separates sheet names from cell references */ 
+    private static final char SHEET_NAME_DELIMITER = '!';
+    /** The character (:) that separates the two cell references in a multi-cell area reference */
+    private static final char CELL_DELIMITER = ':';
+    /** The character (') used to quote sheet names when they contain special characters */
+    private static final char SPECIAL_NAME_DELIMITER = '\'';
+    
+    private final CellReference _firstCell;
+    private final CellReference _lastCell;
+    private final boolean _isSingleCell;
 
     /**
-     * Create an area ref from a string representation.
-     * The area reference must be contiguous
+     * Create an area ref from a string representation.  Sheet names containing special characters should be
+     * delimited and escaped as per normal syntax rules for formulas.<br/> 
+     * The area reference must be contiguous (i.e. represent a single rectangle, not a union of rectangles)
      */
     public AreaReference(String reference) {
         if(! isContiguous(reference)) {
-            throw new IllegalArgumentException("References passed to the AreaReference must be contiguous, use generateContiguous(ref) if you have non-contiguous references");
+            throw new IllegalArgumentException(
+                    "References passed to the AreaReference must be contiguous, " +
+                    "use generateContiguous(ref) if you have non-contiguous references");
         }
 
-        String[] refs = seperateAreaRefs(reference);
-        dim = refs.length;
-        cells = new CellReference[dim];
-        for (int i=0;i<dim;i++) {
-            cells[i]=new CellReference(refs[i]);
+        String[] parts = separateAreaRefs(reference);
+        
+        // Special handling for whole-column references
+        if(parts.length == 2 && parts[0].length() == 1 &&
+        		parts[1].length() == 1 && 
+        		parts[0].charAt(0) >= 'A' && parts[0].charAt(0) <= 'Z' &&
+        		parts[1].charAt(0) >= 'A' && parts[1].charAt(0) <= 'Z') {
+        	// Represented internally as x$1 to x$65536
+        	//  which is the maximum range of rows
+        	parts[0] = parts[0] + "$1";
+        	parts[1] = parts[1] + "$65536";
+        }
+        
+        _firstCell = new CellReference(parts[0]);
+        
+        if(parts.length == 2) {
+            _lastCell = new CellReference(parts[1]);
+            _isSingleCell = false;
+        } else {
+            _lastCell = _firstCell;
+            _isSingleCell = true;
         }
     }
+    
+    /**
+     * Creates an area ref from a pair of Cell References.
+     */
+    public AreaReference(CellReference topLeft, CellReference botRight) {
+    	_firstCell = topLeft;
+    	_lastCell = botRight;
+    	_isSingleCell = false;
+    }
 
     /**
      * Is the reference for a contiguous (i.e.
@@ -57,6 +92,24 @@
         }
         return false;
     }
+    
+    /**
+     * Is the reference for a whole-column reference,
+     *  such as C:C or D:G ?
+     */
+    public static boolean isWholeColumnReference(CellReference topLeft, CellReference botRight) {
+    	// These are represented as something like
+    	//   C$1:C$65535 or D$1:F$0
+    	// i.e. absolute from 1st row to 0th one
+    	if(topLeft.getRow() == 0 && topLeft.isRowAbsolute() &&
+    		botRight.getRow() == 65535 && botRight.isRowAbsolute()) {
+    		return true;
+    	}
+    	return false;
+    }
+    public boolean isWholeColumnReference() {
+    	return isWholeColumnReference(_firstCell, _lastCell);
+    }
 
     /**
      * Takes a non-contiguous area reference, and
@@ -73,75 +126,171 @@
         return (AreaReference[])refs.toArray(new AreaReference[refs.size()]);
     }
 
-    //not sure if we need to be flexible here!
-    /** return the dimensions of this area
-     **/
-    public int getDim() {
-        return dim;
-    }
-    /** 
-     * Return the cell references that define this area
-     * (i.e. the two corners) 
+    /**
+     * @return <code>false</code> if this area reference involves more than one cell
+     */
+    public boolean isSingleCell() {
+        return _isSingleCell;
+    }
+    
+    /**
+     * @return the first cell reference which defines this area. Usually this cell is in the upper
+     * left corner of the area (but this is not a requirement).
      */
-    public CellReference[] getCells() {
-        return cells;
+   public CellReference getFirstCell() {
+        return _firstCell;
+    }
+    
+    /**
+     * Note - if this area reference refers to a single cell, the return value of this method will
+     * be identical to that of <tt>getFirstCell()</tt>
+     * @return the second cell reference which defines this area.  For multi-cell areas, this is 
+     * cell diagonally opposite the 'first cell'.  Usually this cell is in the lower right corner 
+     * of the area (but this is not a requirement).
+     */
+    public CellReference getLastCell() {
+        return _lastCell;
     }
     /**
      * Returns a reference to every cell covered by this area
      */
     public CellReference[] getAllReferencedCells() {
     	// Special case for single cell reference
-    	if(cells.length == 1) {
-    		return cells;
+    	if(_isSingleCell) {
+    		return  new CellReference[] { _firstCell, };
     	}
+ 
     	// Interpolate between the two
-    	int minRow = Math.min(cells[0].getRow(), cells[1].getRow());
-    	int maxRow = Math.max(cells[0].getRow(), cells[1].getRow());
-    	int minCol = Math.min(cells[0].getCol(), cells[1].getCol());
-    	int maxCol = Math.max(cells[0].getCol(), cells[1].getCol());
+        int minRow = Math.min(_firstCell.getRow(), _lastCell.getRow());
+    	int maxRow = Math.max(_firstCell.getRow(), _lastCell.getRow());
+    	int minCol = Math.min(_firstCell.getCol(), _lastCell.getCol());
+    	int maxCol = Math.max(_firstCell.getCol(), _lastCell.getCol());
+        String sheetName = _firstCell.getSheetName();
     	
     	ArrayList refs = new ArrayList();
     	for(int row=minRow; row<=maxRow; row++) {
     		for(int col=minCol; col<=maxCol; col++) {
-    			CellReference ref = new CellReference(row, col, cells[0].isRowAbsolute(), cells[0].isColAbsolute());
-    			ref.setSheetName(cells[0].getSheetName());
+    			CellReference ref = new CellReference(sheetName, row, col, _firstCell.isRowAbsolute(), _firstCell.isColAbsolute());
     			refs.add(ref);
     		}
     	}
     	return (CellReference[])refs.toArray(new CellReference[refs.size()]);
     }
 
-    public String toString() {
-        StringBuffer retval = new StringBuffer();
-        for (int i=0;i<dim;i++){
-            retval.append(':');
-            retval.append(cells[i].toString());
+    /**
+     *  Example return values:
+     *    <table border="0" cellpadding="1" cellspacing="0" summary="Example return values">
+     *      <tr><th align='left'>Result</th><th align='left'>Comment</th></tr>
+     *      <tr><td>A1:A1</td><td>Single cell area reference without sheet</td></tr>
+     *      <tr><td>A1:$C$1</td><td>Multi-cell area reference without sheet</td></tr>
+     *      <tr><td>Sheet1!A$1:B4</td><td>Standard sheet name</td></tr>
+     *      <tr><td>'O''Brien''s Sales'!B5:C6'&nbsp;</td><td>Sheet name with special characters</td></tr>
+     *    </table>
+     * @return the text representation of this area reference as it would appear in a formula.
+     */
+    public String formatAsString() {
+    	// Special handling for whole-column references
+    	if(isWholeColumnReference()) {
+    		return
+    			CellReference.convertNumToColString(_firstCell.getCol())
+    			+ ":" +
+    			CellReference.convertNumToColString(_lastCell.getCol());
+    	}
+    	
+        StringBuffer sb = new StringBuffer(32);
+        sb.append(_firstCell.formatAsString());
+        if(!_isSingleCell) {
+            sb.append(CELL_DELIMITER);
+            if(_lastCell.getSheetName() == null) {
+                sb.append(_lastCell.formatAsString());
+            } else {
+                // don't want to include the sheet name twice
+                _lastCell.appendCellReference(sb);
+            }
         }
-        retval.deleteCharAt(0);
-        return retval.toString();
+        return sb.toString();
+    }
+    public String toString() {
+        StringBuffer sb = new StringBuffer(64);
+        sb.append(getClass().getName()).append(" [");
+        sb.append(formatAsString());
+        sb.append("]");
+        return sb.toString();
     }
 
     /**
-     * seperates Area refs in two parts and returns them as seperate elements in a
-     * String array
+     * Separates Area refs in two parts and returns them as separate elements in a String array,
+     * each qualified with the sheet name (if present)
+     * 
+     * @return array with one or two elements. never <code>null</code>
      */
-    private String[] seperateAreaRefs(String reference) {
-        String[] retval = null;
-
-        int length = reference.length();
-
-        int loc = reference.indexOf(':',0);
-        if(loc == -1){
-           retval = new String[1];
-           retval[0] = reference;
+    private static String[] separateAreaRefs(String reference) {
+        // TODO - refactor cell reference parsing logic to one place.
+        // Current known incarnations: 
+        //   FormulaParser.GetName()
+        //   CellReference.separateRefParts() 
+        //   AreaReference.separateAreaRefs() (here)
+        //   SheetNameFormatter.format() (inverse)
+        
+        
+        int len = reference.length();
+        int delimiterPos = -1;
+        boolean insideDelimitedName = false;
+        for(int i=0; i<len; i++) {
+            switch(reference.charAt(i)) {
+                case CELL_DELIMITER:
+                    if(!insideDelimitedName) {
+                        if(delimiterPos >=0) {
+                            throw new IllegalArgumentException("More than one cell delimiter '" 
+                                    + CELL_DELIMITER + "' appears in area reference '" + reference + "'");
+                        }
+                        delimiterPos = i;
+                    }
+                default:
+                    continue;
+                case SPECIAL_NAME_DELIMITER:
+                    // fall through
+            }
+            if(!insideDelimitedName) {
+                insideDelimitedName = true;
+                continue;
+            }
+            
+            if(i >= len-1) {
+                // reference ends with the delimited name. 
+                // Assume names like: "Sheet1!'A1'" are never legal.
+                throw new IllegalArgumentException("Area reference '" + reference 
+                        + "' ends with special name delimiter '"  + SPECIAL_NAME_DELIMITER + "'");
+            }
+            if(reference.charAt(i+1) == SPECIAL_NAME_DELIMITER) {
+                // two consecutive quotes is the escape sequence for a single one
+                i++; // skip this and keep parsing the special name
+            } else {
+                // this is the end of the delimited name
+                insideDelimitedName = false;
+            }
+        }
+        if(delimiterPos < 0) {
+            return new String[] { reference, };
         }
-        else{
-           retval = new String[2];
-           int sheetStart = reference.indexOf("!");
 
-           retval[0] = reference.substring(0, sheetStart+1) + reference.substring(sheetStart + 1,loc);
-           retval[1] = reference.substring(0, sheetStart+1) + reference.substring(loc+1);
+        String partA = reference.substring(0, delimiterPos);
+        String partB = reference.substring(delimiterPos+1);
+        if(partB.indexOf(SHEET_NAME_DELIMITER) >=0) {
+            // TODO - are references like "Sheet1!A1:Sheet1:B2" ever valid?  
+            // FormulaParser has code to handle that.
+            
+            throw new RuntimeException("Unexpected " + SHEET_NAME_DELIMITER 
+                    + " in second cell reference of '" + reference + "'");
+        }
+        
+        int plingPos = partA.lastIndexOf(SHEET_NAME_DELIMITER);
+        if(plingPos < 0) {
+            return new String [] { partA, partB, };
         }
-        return retval;
+        
+        String sheetName = partA.substring(0, plingPos + 1); // +1 to include delimiter
+        
+        return new String [] { partA, sheetName + partB, };
     }
 }

Modified: poi/branches/ooxml/src/java/org/apache/poi/hssf/util/CellReference.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/hssf/util/CellReference.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/hssf/util/CellReference.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/hssf/util/CellReference.java Sat Mar  8 03:49:00 2008
@@ -15,75 +15,99 @@
    limitations under the License.
 ==================================================================== */
 
-
 package org.apache.poi.hssf.util;
 
+import org.apache.poi.hssf.record.formula.SheetNameFormatter;
+
 /**
  *
  * @author  Avik Sengupta
  * @author  Dennis Doubleday (patch to seperateRowColumns())
  */
-public class CellReference {
+public final class CellReference {
+    /** The character ($) that signifies a row or column value is absolute instead of relative */ 
+    private static final char ABSOLUTE_REFERENCE_MARKER = '$';
+    /** The character (!) that separates sheet names from cell references */ 
+    private static final char SHEET_NAME_DELIMITER = '!';
+    /** The character (') used to quote sheet names when they contain special characters */
+    private static final char SPECIAL_NAME_DELIMITER = '\'';
+    
 
-    /** Creates new CellReference */
-    private int row;
-    private int col;
-    private String sheetName;
-    private boolean rowAbs;
-    private boolean colAbs;
+    private final int _rowIndex;
+    private final int _colIndex;
+    private final String _sheetName;
+    private final boolean _isRowAbs;
+    private final boolean _isColAbs;
 
+    /**
+     * Create an cell ref from a string representation.  Sheet names containing special characters should be
+     * delimited and escaped as per normal syntax rules for formulas.
+     */
     public CellReference(String cellRef) {
         String[] parts = separateRefParts(cellRef);
-        sheetName = parts[0];
-        String ref = parts[1]; 
-        if ((ref == null)||("".equals(ref)))
-        	throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
-        if (ref.charAt(0) == '$') {
-            colAbs=true;
-            ref=ref.substring(1);
-        }
-        col = convertColStringToNum(ref);
-        ref=parts[2];
-        if ((ref == null)||("".equals(ref)))
-        	throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
-        if (ref.charAt(0) == '$') {
-            rowAbs=true;
-            ref=ref.substring(1);
+        _sheetName = parts[0];
+        String colRef = parts[1]; 
+        if (colRef.length() < 1) {
+            throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
         }
-        row = Integer.parseInt(ref)-1;
-    }
-
-    public CellReference(int pRow, int pCol) {
-        this(pRow,pCol,false,false);
+        _isColAbs = colRef.charAt(0) == '$';
+        if (_isColAbs) {
+            colRef=colRef.substring(1);
+        }
+        _colIndex = convertColStringToNum(colRef);
+        
+        String rowRef=parts[2];
+        if (rowRef.length() < 1) {
+            throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
+        }
+        _isRowAbs = rowRef.charAt(0) == '$';
+        if (_isRowAbs) {
+            rowRef=rowRef.substring(1);
+        }
+        _rowIndex = Integer.parseInt(rowRef)-1; // -1 to convert 1-based to zero-based
     }
 
     public CellReference(int pRow, int pCol, boolean pAbsRow, boolean pAbsCol) {
-        row=pRow;col=pCol;
-        rowAbs = pAbsRow;
-        colAbs=pAbsCol;
-
+        this(null, pRow, pCol, pAbsRow, pAbsCol);
     }
-
-    public int getRow(){return row;}
-    public short getCol(){return (short) col;}
-    public boolean isRowAbsolute(){return rowAbs;}
-    public boolean isColAbsolute(){return colAbs;}
-    public String getSheetName(){return sheetName;}
-    
-    protected void setSheetName(String sheetName) {
-    	this.sheetName = sheetName;
+    public CellReference(String pSheetName, int pRow, int pCol, boolean pAbsRow, boolean pAbsCol) {
+        // TODO - "-1" is a special value being temporarily used for whole row and whole column area references.
+        // so these checks are currently N.Q.R.
+        if(pRow < -1) {
+            throw new IllegalArgumentException("row index may not be negative");
+        }
+        if(pCol < -1) {
+            throw new IllegalArgumentException("column index may not be negative");
+        }
+        _sheetName = pSheetName;
+        _rowIndex=pRow;
+        _colIndex=pCol;
+        _isRowAbs = pAbsRow;
+        _isColAbs=pAbsCol;
     }
 
+    public int getRow(){return _rowIndex;}
+    public short getCol(){return (short) _colIndex;}
+    public boolean isRowAbsolute(){return _isRowAbs;}
+    public boolean isColAbsolute(){return _isColAbs;}
+    /**
+      * @return possibly <code>null</code> if this is a 2D reference.  Special characters are not
+      * escaped or delimited
+      */
+    public String getSheetName(){
+        return _sheetName;
+    }
+    
     /**
      * takes in a column reference portion of a CellRef and converts it from
      * ALPHA-26 number format to 0-based base 10.
      */
     private int convertColStringToNum(String ref) {
-        int len = ref.length();
+        int lastIx = ref.length()-1;
         int retval=0;
         int pos = 0;
 
-        for (int k = ref.length()-1; k > -1; k--) {
+        for (int k = lastIx; k > -1; k--) {
             char thechar = ref.charAt(k);
             if ( pos == 0) {
                 retval += (Character.getNumericValue(thechar)-9);
@@ -97,42 +121,86 @@
 
 
     /**
-     * Seperates the row from the columns and returns an array.  Element in
-     * position one is the substring containing the columns still in ALPHA-26
-     * number format.
-     */
-    private String[] separateRefParts(String reference) {
-
-        // Look for end of sheet name. This will either set
-        // start to 0 (if no sheet name present) or the
-        // index after the sheet reference ends.
-        String retval[] = new String[3];
-
-        int start = reference.indexOf("!");
-        if (start != -1) retval[0] = reference.substring(0, start);
-        start += 1;
+     * Separates the row from the columns and returns an array of three Strings.  The first element
+     * is the sheet name. Only the first element may be null.  The second element in is the column 
+     * name still in ALPHA-26 number format.  The third element is the row.
+     */
+    private static String[] separateRefParts(String reference) {
+        
+        int plingPos = reference.lastIndexOf(SHEET_NAME_DELIMITER);
+        String sheetName = parseSheetName(reference, plingPos);
+        int start = plingPos+1;
 
         int length = reference.length();
 
 
-        char[] chars = reference.toCharArray();
         int loc = start;
-        if (chars[loc]=='$') loc++;
-        for (; loc < chars.length; loc++) {
-            if (Character.isDigit(chars[loc]) || chars[loc] == '$') {
+        // skip initial dollars 
+        if (reference.charAt(loc)==ABSOLUTE_REFERENCE_MARKER) {
+            loc++;
+        }
+        // step over column name chars until first digit (or dollars) for row number.
+        for (; loc < length; loc++) {
+            char ch = reference.charAt(loc);
+            if (Character.isDigit(ch) || ch == ABSOLUTE_REFERENCE_MARKER) {
                 break;
             }
         }
+        return new String[] {
+           sheetName,
+           reference.substring(start,loc),
+           reference.substring(loc),
+        };
+    }
 
-        retval[1] = reference.substring(start,loc);
-        retval[2] = reference.substring(loc);
-        return retval;
+    private static String parseSheetName(String reference, int indexOfSheetNameDelimiter) {
+        if(indexOfSheetNameDelimiter < 0) {
+            return null;
+        }
+        
+        boolean isQuoted = reference.charAt(0) == SPECIAL_NAME_DELIMITER;
+        if(!isQuoted) {
+            return reference.substring(0, indexOfSheetNameDelimiter);
+        }
+        int lastQuotePos = indexOfSheetNameDelimiter-1;
+        if(reference.charAt(lastQuotePos) != SPECIAL_NAME_DELIMITER) {
+            throw new RuntimeException("Mismatched quotes: (" + reference + ")");
+        }
+
+        // TODO - refactor cell reference parsing logic to one place.
+        // Current known incarnations: 
+        //   FormulaParser.GetName()
+        //   CellReference.parseSheetName() (here)
+        //   AreaReference.separateAreaRefs() 
+        //   SheetNameFormatter.format() (inverse)
+        
+        StringBuffer sb = new StringBuffer(indexOfSheetNameDelimiter);
+        
+        for(int i=1; i<lastQuotePos; i++) { // Note boundaries - skip outer quotes
+            char ch = reference.charAt(i);
+            if(ch != SPECIAL_NAME_DELIMITER) {
+                sb.append(ch);
+                continue;
+            }
+            if(i < lastQuotePos) {
+                if(reference.charAt(i+1) == SPECIAL_NAME_DELIMITER) {
+                    // two consecutive quotes is the escape sequence for a single one
+                    i++; // skip this and keep parsing the special name
+                    sb.append(ch);
+                    continue;
+                }
+            }
+            throw new RuntimeException("Bad sheet name quote escaping: (" + reference + ")");
+        }
+        return sb.toString();
     }
 
     /**
-     * takes in a 0-based base-10 column and returns a ALPHA-26 representation
+     * Takes in a 0-based base-10 column and returns a ALPHA-26
+     *  representation.
+     * eg column #3 -> D
      */
-    private static String convertNumToColString(int col) {
+    protected static String convertNumToColString(int col) {
         String retval = null;
         int mod = col % 26;
         int div = col / 26;
@@ -148,14 +216,46 @@
         return retval;
     }
 
-
+    /**
+     *  Example return values:
+     *    <table border="0" cellpadding="1" cellspacing="0" summary="Example return values">
+     *      <tr><th align='left'>Result</th><th align='left'>Comment</th></tr>
+     *      <tr><td>A1</td><td>Cell reference without sheet</td></tr>
+     *      <tr><td>Sheet1!A1</td><td>Standard sheet name</td></tr>
+     *      <tr><td>'O''Brien''s Sales'!A1'&nbsp;</td><td>Sheet name with special characters</td></tr>
+     *    </table>
+     * @return the text representation of this cell reference as it would appear in a formula.
+     */
+    public String formatAsString() {
+        StringBuffer sb = new StringBuffer(32);
+        if(_sheetName != null) {
+            SheetNameFormatter.appendFormat(sb, _sheetName);
+            sb.append(SHEET_NAME_DELIMITER);
+        }
+        appendCellReference(sb);
+        return sb.toString();
+    }
+    
     public String toString() {
-        StringBuffer retval = new StringBuffer();
-        retval.append( (colAbs)?"$":"");
-        retval.append( convertNumToColString(col));
-        retval.append((rowAbs)?"$":"");
-        retval.append(row+1);
+        StringBuffer sb = new StringBuffer(64);
+        sb.append(getClass().getName()).append(" [");
+        sb.append(formatAsString());
+        sb.append("]");
+        return sb.toString();
+    }
 
-    return retval.toString();
+    /**
+     * Appends cell reference with '$' markers for absolute values as required.
+     * Sheet name is not included.
+     */
+    /* package */ void appendCellReference(StringBuffer sb) {
+        if(_isColAbs) {
+            sb.append(ABSOLUTE_REFERENCE_MARKER);
+        }
+        sb.append( convertNumToColString(_colIndex));
+        if(_isRowAbs) {
+            sb.append(ABSOLUTE_REFERENCE_MARKER);
+        }
+        sb.append(_rowIndex+1);
     }
 }

Modified: poi/branches/ooxml/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java Sat Mar  8 03:49:00 2008
@@ -19,6 +19,7 @@
 
 package org.apache.poi.poifs.filesystem;
 
+import java.io.ByteArrayInputStream;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -30,6 +31,8 @@
 import java.util.Iterator;
 import java.util.List;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.poi.poifs.dev.POIFSViewable;
 import org.apache.poi.poifs.property.DirectoryProperty;
 import org.apache.poi.poifs.property.Property;
@@ -58,6 +61,33 @@
 public class POIFSFileSystem
     implements POIFSViewable
 {
+    private static final Log _logger = LogFactory.getLog(POIFSFileSystem.class);
+    
+    
+    private static final class CloseIgnoringInputStream extends InputStream {
+
+        private final InputStream _is;
+        public CloseIgnoringInputStream(InputStream is) {
+            _is = is;
+        }
+        public int read() throws IOException {
+            return _is.read();
+        }
+        public int read(byte[] b, int off, int len) throws IOException {
+            return _is.read(b, off, len);
+        }
+        public void close() {
+            // do nothing
+        }
+    }
+    
+    /**
+     * Convenience method for clients that want to avoid the auto-close behaviour of the constructor.
+     */
+    public static InputStream createNonClosingInputStream(InputStream is) {
+        return new CloseIgnoringInputStream(is);
+    }
+    
     private PropertyTable _property_table;
     private List          _documents;
     private DirectoryNode _root;
@@ -74,23 +104,52 @@
     }
 
     /**
-     * Create a POIFSFileSystem from an InputStream
+     * Create a POIFSFileSystem from an <tt>InputStream</tt>.  Normally the stream is read until
+     * EOF.  The stream is always closed.<p/>
+     * 
+     * Some streams are usable after reaching EOF (typically those that return <code>true</code> 
+     * for <tt>markSupported()</tt>).  In the unlikely case that the caller has such a stream 
+     * <i>and</i> needs to use it after this constructor completes, a work around is to wrap the
+     * stream in order to trap the <tt>close()</tt> call.  A convenience method (
+     * <tt>createNonClosingInputStream()</tt>) has been provided for this purpose:
+     * <pre>
+     * InputStream wrappedStream = POIFSFileSystem.createNonClosingInputStream(is);
+     * HSSFWorkbook wb = new HSSFWorkbook(wrappedStream);
+     * is.reset(); 
+     * doSomethingElse(is); 
+     * </pre>
+     * Note also the special case of <tt>ByteArrayInputStream</tt> for which the <tt>close()</tt>
+     * method does nothing. 
+     * <pre>
+     * ByteArrayInputStream bais = ...
+     * HSSFWorkbook wb = new HSSFWorkbook(bais); // calls bais.close() !
+     * bais.reset(); // no problem
+     * doSomethingElse(bais);
+     * </pre>
      *
      * @param stream the InputStream from which to read the data
      *
      * @exception IOException on errors reading, or on invalid data
      */
 
-    public POIFSFileSystem(final InputStream stream)
+    public POIFSFileSystem(InputStream stream)
         throws IOException
     {
         this();
+        boolean success = false;
 
         // read the header block from the stream
-        HeaderBlockReader header_block_reader = new HeaderBlockReader(stream);
-
+        HeaderBlockReader header_block_reader;
         // read the rest of the stream into blocks
-        RawDataBlockList  data_blocks         = new RawDataBlockList(stream);
+        RawDataBlockList data_blocks;
+        try {
+            header_block_reader = new HeaderBlockReader(stream);
+            data_blocks = new RawDataBlockList(stream);
+            success = true;
+        } finally {
+            closeInputStream(stream, success);
+        }
+        
 
         // set up the block allocation table (necessary for the
         // data_blocks to be manageable
@@ -112,7 +171,32 @@
                     .getSBATStart()), data_blocks, properties.getRoot()
                         .getChildren(), null);
     }
-    
+    /**
+     * @param stream the stream to be closed
+     * @param success <code>false</code> if an exception is currently being thrown in the calling method
+     */
+    private void closeInputStream(InputStream stream, boolean success) {
+        
+        if(stream.markSupported() && !(stream instanceof ByteArrayInputStream)) {
+            String msg = "POIFS is closing the supplied input stream of type (" 
+                    + stream.getClass().getName() + ") which supports mark/reset.  "
+                    + "This will be a problem for the caller if the stream will still be used.  "
+                    + "If that is the case the caller should wrap the input stream to avoid this close logic.  "
+                    + "This warning is only temporary and will not be present in future versions of POI.";
+            _logger.warn(msg);
+        }
+        try {
+            stream.close();
+        } catch (IOException e) {
+            if(success) {
+                throw new RuntimeException(e);
+            }
+            // else not success? Try block did not complete normally 
+            // just print stack trace and leave original ex to be thrown
+            e.printStackTrace();
+        }
+    }
+
     /**
      * Checks that the supplied InputStream (which MUST
      *  support mark and reset, or be a PushbackInputStream) 
@@ -123,23 +207,23 @@
      * @param inp An InputStream which supports either mark/reset, or is a PushbackInputStream 
      */
     public static boolean hasPOIFSHeader(InputStream inp) throws IOException {
-    	// We want to peek at the first 8 bytes 
-    	inp.mark(8);
+        // We want to peek at the first 8 bytes 
+        inp.mark(8);
 
-    	byte[] header = new byte[8];
-    	IOUtils.readFully(inp, header);
+        byte[] header = new byte[8];
+        IOUtils.readFully(inp, header);
         LongField signature = new LongField(HeaderBlockConstants._signature_offset, header);
 
         // Wind back those 8 bytes
         if(inp instanceof PushbackInputStream) {
-        	PushbackInputStream pin = (PushbackInputStream)inp;
-        	pin.unread(header);
+            PushbackInputStream pin = (PushbackInputStream)inp;
+            pin.unread(header);
         } else {
-        	inp.reset();
+            inp.reset();
         }
-    	
-    	// Did it match the signature?
-    	return (signature.get() == HeaderBlockConstants._signature);
+        
+        // Did it match the signature?
+        return (signature.get() == HeaderBlockConstants._signature);
     }
 
     /**

Modified: poi/branches/ooxml/src/java/org/apache/poi/poifs/storage/RawDataBlock.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/poifs/storage/RawDataBlock.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/poifs/storage/RawDataBlock.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/poifs/storage/RawDataBlock.java Sat Mar  8 03:49:00 2008
@@ -21,6 +21,8 @@
 
 import org.apache.poi.poifs.common.POIFSConstants;
 import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.POILogFactory;
+import org.apache.poi.util.POILogger;
 
 import java.io.*;
 
@@ -35,6 +37,7 @@
 {
     private byte[]  _data;
     private boolean _eof;
+    private static POILogger log = POILogFactory.getLogger(RawDataBlock.class);
 
     /**
      * Constructor RawDataBlock
@@ -75,9 +78,12 @@
             String type = " byte" + ((count == 1) ? ("")
                                                   : ("s"));
 
-            throw new IOException("Unable to read entire block; " + count
-                                  + type + " read before EOF; expected "
-                                  + blockSize + " bytes");
+            log.log(POILogger.ERROR,
+            		"Unable to read entire block; " + count
+                     + type + " read before EOF; expected "
+                     + blockSize + " bytes. Your document"
+                     + " has probably been truncated!"
+            );
         }
         else {
             _eof = false;

Modified: poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndian.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndian.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndian.java (original)
+++ poi/branches/ooxml/src/java/org/apache/poi/util/LittleEndian.java Sat Mar  8 03:49:00 2008
@@ -245,6 +245,16 @@
         putNumber(data, offset, value, SHORT_SIZE);
     }
 
+    /**
+     * executes:<p/>
+     * <code>
+     * data[offset] = (byte)value;
+     * </code></p>
+     * Added for consistency with other put~() methods
+     */
+    public static void putByte(byte[] data, int offset, int value) {
+        putNumber(data, offset, value, LittleEndianConsts.BYTE_SIZE);
+    }
 
     /**
      *  put a array of shorts into a byte array

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/AddEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/AddEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/AddEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/AddEval.java Sat Mar  8 03:49:00 2008
@@ -43,8 +43,6 @@
     private static final ValueEvalToNumericXlator NUM_XLATOR = 
         new ValueEvalToNumericXlator((short)
                 ( ValueEvalToNumericXlator.BOOL_IS_PARSED 
-                | ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
-                | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
                 | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
                 | ValueEvalToNumericXlator.STRING_IS_PARSED
                 | ValueEvalToNumericXlator.REF_STRING_IS_PARSED
@@ -59,33 +57,31 @@
     }
     
     
-    public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
-        Eval retval = null;
+    public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
+    	if(args.length != 2) {
+    		return ErrorEval.VALUE_INVALID;
+    	}
+    	
         double d = 0;
-        switch (operands.length) {
-        default: // will rarely happen. currently the parser itself fails.
-            retval = ErrorEval.UNKNOWN_ERROR;
-            break;
-        case 2:
-            for (int i = 0, iSize = 2; retval==null && i < iSize; i++) {
-                ValueEval ve = singleOperandEvaluate(operands[i], srcRow, srcCol);
-                if (ve instanceof NumericValueEval) {
-                    d += ((NumericValueEval) ve).getNumberValue();
-                }
-                else if (ve instanceof BlankEval) {
-                    // do nothing
-                }
-                else {
-                    retval = ErrorEval.VALUE_INVALID;
-                }
-            } // end for inside case
-        } // end switch
-        
-        if (retval == null) {
-            retval = Double.isNaN(d) ? (ValueEval) ErrorEval.VALUE_INVALID : new NumberEval(d);
+        for (int i = 0; i < 2; i++) {
+            ValueEval ve = singleOperandEvaluate(args[i], srcRow, srcCol);
+            if(ve instanceof ErrorEval) {
+				return ve;
+            }
+            if (ve instanceof NumericValueEval) {
+                d += ((NumericValueEval) ve).getNumberValue();
+            }
+            else if (ve instanceof BlankEval) {
+                // do nothing
+            }
+            else {
+                return ErrorEval.VALUE_INVALID;
+            }
         }
-
-        return retval;
+        if(Double.isNaN(d) || Double.isInfinite(d)) {
+        	return ErrorEval.NUM_ERROR;
+        }
+        return new NumberEval(d);
     }
 
     public int getNumberOfOperands() {

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Area2DEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Area2DEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Area2DEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Area2DEval.java Sat Mar  8 03:49:00 2008
@@ -14,10 +14,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-/*
- * Created on May 8, 2005
- *
- */
+
 package org.apache.poi.hssf.record.formula.eval;
 
 import org.apache.poi.hssf.record.formula.AreaPtg;
@@ -27,48 +24,60 @@
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
  *   
  */
-public class Area2DEval implements AreaEval {
-
-    private AreaPtg delegate;
+public final class Area2DEval implements AreaEval {
+// TODO -refactor with Area3DEval
+    private final AreaPtg _delegate;
 
-    private ValueEval[] values;
+    private final ValueEval[] _values;
 
     public Area2DEval(Ptg ptg, ValueEval[] values) {
-        this.delegate = (AreaPtg) ptg;
-        this.values = values;
+        if(ptg == null) {
+            throw new IllegalArgumentException("ptg must not be null");
+        }
+        if(values == null) {
+            throw new IllegalArgumentException("values must not be null");
+        }
+        for(int i=values.length-1; i>=0; i--) {
+            if(values[i] == null) {
+                throw new IllegalArgumentException("value array elements must not be null");
+            }
+        }
+        // TODO - check size of array vs size of AreaPtg
+        _delegate = (AreaPtg) ptg;
+        _values = values;
     }
 
-    public short getFirstColumn() {
-        return delegate.getFirstColumn();
+    public int getFirstColumn() {
+        return _delegate.getFirstColumn();
     }
 
     public int getFirstRow() {
-        return delegate.getFirstRow();
+        return _delegate.getFirstRow();
     }
 
-    public short getLastColumn() {
-        return delegate.getLastColumn();
+    public int getLastColumn() {
+        return _delegate.getLastColumn();
     }
 
     public int getLastRow() {
-        return delegate.getLastRow();
+        return _delegate.getLastRow();
     }
 
     public ValueEval[] getValues() {
-        return values;
+        return _values;
     }
     
-    public ValueEval getValueAt(int row, short col) {
+    public ValueEval getValueAt(int row, int col) {
         ValueEval retval;
         int index = ((row-getFirstRow())*(getLastColumn()-getFirstColumn()+1))+(col-getFirstColumn());
-        if (index <0 || index >= values.length)
+        if (index <0 || index >= _values.length)
             retval = ErrorEval.VALUE_INVALID;
         else 
-            retval = values[index];
+            retval = _values[index];
         return retval;
     }
     
-    public boolean contains(int row, short col) {
+    public boolean contains(int row, int col) {
         return (getFirstRow() <= row) && (getLastRow() >= row) 
             && (getFirstColumn() <= col) && (getLastColumn() >= col);
     }
@@ -82,10 +91,10 @@
     }
     
     public boolean isColumn() {
-        return delegate.getFirstColumn() == delegate.getLastColumn();
+        return _delegate.getFirstColumn() == _delegate.getLastColumn();
     }
 
     public boolean isRow() {
-        return delegate.getFirstRow() == delegate.getLastRow();
+        return _delegate.getFirstRow() == _delegate.getLastRow();
     }
 }

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Area3DEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Area3DEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Area3DEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Area3DEval.java Sat Mar  8 03:49:00 2008
@@ -14,10 +14,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-/*
- * Created on May 8, 2005
- *
- */
+
 package org.apache.poi.hssf.record.formula.eval;
 
 import org.apache.poi.hssf.record.formula.Area3DPtg;
@@ -27,48 +24,60 @@
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
  *  
  */
-public class Area3DEval implements AreaEval {
+public final class Area3DEval implements AreaEval {
+	// TODO -refactor with Area3DEval
+    private final Area3DPtg _delegate;
 
-    private Area3DPtg delegate;
-
-    private ValueEval[] values;
+    private final ValueEval[] _values;
 
     public Area3DEval(Ptg ptg, ValueEval[] values) {
-        this.values = values;
-        this.delegate = (Area3DPtg) ptg;
+        if(ptg == null) {
+            throw new IllegalArgumentException("ptg must not be null");
+        }
+        if(values == null) {
+            throw new IllegalArgumentException("values must not be null");
+        }
+        for(int i=values.length-1; i>=0; i--) {
+            if(values[i] == null) {
+                throw new IllegalArgumentException("value array elements must not be null");
+            }
+        }
+        // TODO - check size of array vs size of AreaPtg
+        _values = values;
+        _delegate = (Area3DPtg) ptg;
     }
 
-    public short getFirstColumn() {
-        return delegate.getFirstColumn();
+    public int getFirstColumn() {
+        return _delegate.getFirstColumn();
     }
 
     public int getFirstRow() {
-        return delegate.getFirstRow();
+        return _delegate.getFirstRow();
     }
 
-    public short getLastColumn() {
-        return delegate.getLastColumn();
+    public int getLastColumn() {
+        return (short) _delegate.getLastColumn();
     }
 
     public int getLastRow() {
-        return delegate.getLastRow();
+        return _delegate.getLastRow();
     }
 
     public ValueEval[] getValues() {
-        return values;
+        return _values;
     }
     
-    public ValueEval getValueAt(int row, short col) {
+    public ValueEval getValueAt(int row, int col) {
         ValueEval retval;
         int index = (row-getFirstRow())*(col-getFirstColumn());
-        if (index <0 || index >= values.length)
+        if (index <0 || index >= _values.length)
             retval = ErrorEval.VALUE_INVALID;
         else 
-            retval = values[index];
+            retval = _values[index];
         return retval;
     }
     
-    public boolean contains(int row, short col) {
+    public boolean contains(int row, int col) {
         return (getFirstRow() <= row) && (getLastRow() >= row) 
             && (getFirstColumn() <= col) && (getLastColumn() >= col);
     }
@@ -83,11 +92,14 @@
     
     
     public boolean isColumn() {
-        return delegate.getFirstColumn() == delegate.getLastColumn();
+        return _delegate.getFirstColumn() == _delegate.getLastColumn();
     }
 
     public boolean isRow() {
-        return delegate.getFirstRow() == delegate.getLastRow();
+        return _delegate.getFirstRow() == _delegate.getLastRow();
     }
 
+    public int getExternSheetIndex() {
+        return _delegate.getExternSheetIndex();
+    }
 }

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/AreaEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/AreaEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/AreaEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/AreaEval.java Sat Mar  8 03:49:00 2008
@@ -42,13 +42,13 @@
      * returns the 0-based index of the first col in
      * this area.
      */
-    public short getFirstColumn();
+    public int getFirstColumn();
 
     /**
      * returns the 0-based index of the last col in
      * this area.
      */
-    public short getLastColumn();
+    public int getLastColumn();
     
     /**
      * returns true if the Area's start and end row indexes
@@ -80,7 +80,7 @@
      * @param row
      * @param col
      */
-    public ValueEval getValueAt(int row, short col);
+    public ValueEval getValueAt(int row, int col);
     
     /**
      * returns true if the cell at row and col specified 
@@ -89,7 +89,7 @@
      * @param row
      * @param col
      */
-    public boolean contains(int row, short col);
+    public boolean contains(int row, int col);
     
     /**
      * returns true if the specified col is in range

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/BoolEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/BoolEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/BoolEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/BoolEval.java Sat Mar  8 03:49:00 2008
@@ -34,6 +34,16 @@
     public static final BoolEval FALSE = new BoolEval(false);
     
     public static final BoolEval TRUE = new BoolEval(true);
+    
+    /**
+     * Convenience method for the following:<br/>
+     * <code>(b ? BoolEval.TRUE : BoolEval.FALSE)</code>
+     * @return a <tt>BoolEval</tt> instance representing <tt>b</tt>.
+     */
+    public static final BoolEval valueOf(boolean b) {
+        // TODO - find / replace all occurrences
+        return b ? TRUE : FALSE;
+    }
 
     public BoolEval(Ptg ptg) {
         this.value = ((BoolPtg) ptg).getValue();
@@ -48,10 +58,17 @@
     }
 
     public double getNumberValue() {
-        return value ? (short) 1 : (short) 0;
+        return value ? 1 : 0;
     }
 
     public String getStringValue() {
         return value ? "TRUE" : "FALSE";
+    }
+    public String toString() {
+        StringBuffer sb = new StringBuffer(64);
+        sb.append(getClass().getName()).append(" [");
+        sb.append(getStringValue());
+        sb.append("]");
+        return sb.toString();
     }
 }

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/ConcatEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/ConcatEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/ConcatEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/ConcatEval.java Sat Mar  8 03:49:00 2008
@@ -14,10 +14,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-/*
- * Created on May 8, 2005
- *
- */
+
 package org.apache.poi.hssf.record.formula.eval;
 
 import org.apache.poi.hssf.record.formula.ConcatPtg;
@@ -27,7 +24,7 @@
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
  *  
  */
-public class ConcatEval extends StringOperationEval {
+public final class ConcatEval extends StringOperationEval {
 
     private ConcatPtg delegate;
 
@@ -35,36 +32,27 @@
         this.delegate = (ConcatPtg) ptg;
     }
 
-    public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
-        Eval retval = null;
-        StringBuffer sb = null;
-        
-        switch (operands.length) {
-        default: // paranoid check :)
-            retval = ErrorEval.UNKNOWN_ERROR;
-            break;
-        case 2:
-            sb = new StringBuffer();
-            for (int i = 0, iSize = 2; retval == null && i < iSize; i++) { 
-                
-                ValueEval ve = singleOperandEvaluate(operands[i], srcRow, srcCol);
-                if (ve instanceof StringValueEval) {
-                    StringValueEval sve = (StringValueEval) ve;
-                    sb.append(sve.getStringValue());
-                }
-                else if (ve instanceof BlankEval) {
-                    // do nothing
-                }
-                else { // must be an error eval
-                    retval = ve;
-                }
+    public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
+    	if(args.length != 2) {
+    		return ErrorEval.VALUE_INVALID;
+    	}
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < 2; i++) { 
+            
+            ValueEval ve = singleOperandEvaluate(args[i], srcRow, srcCol);
+            if (ve instanceof StringValueEval) {
+                StringValueEval sve = (StringValueEval) ve;
+                sb.append(sve.getStringValue());
+            }
+            else if (ve instanceof BlankEval) {
+                // do nothing
+            }
+            else { // must be an error eval
+                return ve;
             }
         }
         
-        if (retval == null) {
-            retval = new StringEval(sb.toString());
-        }
-        return retval;
+        return new StringEval(sb.toString());
     }
 
     public int getNumberOfOperands() {

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/DivideEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/DivideEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/DivideEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/DivideEval.java Sat Mar  8 03:49:00 2008
@@ -14,10 +14,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-/*
- * Created on May 8, 2005
- *
- */
+
 package org.apache.poi.hssf.record.formula.eval;
 
 import org.apache.poi.hssf.record.formula.Ptg;
@@ -27,15 +24,13 @@
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
  *  
  */
-public class DivideEval extends NumericOperationEval {
+public final class DivideEval extends NumericOperationEval {
 
     private DividePtg delegate;
 
     private static final ValueEvalToNumericXlator NUM_XLATOR = 
         new ValueEvalToNumericXlator((short)
                 ( ValueEvalToNumericXlator.BOOL_IS_PARSED 
-                | ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
-                | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
                 | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
                 | ValueEvalToNumericXlator.STRING_IS_PARSED
                 | ValueEvalToNumericXlator.REF_STRING_IS_PARSED
@@ -49,18 +44,28 @@
         return NUM_XLATOR;
     }
 
-    public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
+    public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
+    	if(args.length != 2) {
+    		return ErrorEval.VALUE_INVALID;
+    	}
         Eval retval = null;
         double d0 = 0;
         double d1 = 0;
-        switch (operands.length) {
-        default: // will rarely happen. currently the parser itself fails.
-            retval = ErrorEval.UNKNOWN_ERROR;
-            break;
-        case 2:
-            ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
+        ValueEval ve = singleOperandEvaluate(args[0], srcRow, srcCol);
+        if (ve instanceof NumericValueEval) {
+            d0 = ((NumericValueEval) ve).getNumberValue();
+        }
+        else if (ve instanceof BlankEval) {
+            // do nothing
+        }
+        else {
+            retval = ErrorEval.VALUE_INVALID;
+        }
+        
+        if (retval == null) { // no error yet
+            ve = singleOperandEvaluate(args[1], srcRow, srcCol);
             if (ve instanceof NumericValueEval) {
-                d0 = ((NumericValueEval) ve).getNumberValue();
+                d1 = ((NumericValueEval) ve).getNumberValue();
             }
             else if (ve instanceof BlankEval) {
                 // do nothing
@@ -68,20 +73,7 @@
             else {
                 retval = ErrorEval.VALUE_INVALID;
             }
-            
-            if (retval == null) { // no error yet
-                ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
-                if (ve instanceof NumericValueEval) {
-                    d1 = ((NumericValueEval) ve).getNumberValue();
-                }
-                else if (ve instanceof BlankEval) {
-                    // do nothing
-                }
-                else {
-                    retval = ErrorEval.VALUE_INVALID;
-                }
-            }
-        } // end switch
+        }
 
         if (retval == null) {
             retval = (d1 == 0) 

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/ErrorEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/ErrorEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/ErrorEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/ErrorEval.java Sat Mar  8 03:49:00 2008
@@ -14,51 +14,100 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-/*
- * Created on May 8, 2005
- *
- */
+
 package org.apache.poi.hssf.record.formula.eval;
 
+import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
+
 /**
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
- * 
+ *
  */
-public class ErrorEval implements ValueEval {
-
-    private int errorCode;
-
+public final class ErrorEval implements ValueEval {
 
-    public static final ErrorEval NAME_INVALID = new ErrorEval(525);
+    // convenient access to namespace
+    private static final HSSFErrorConstants EC = null;
 
-    public static final ErrorEval VALUE_INVALID = new ErrorEval(519);
-
-    
-    // Non std error codes
-    public static final ErrorEval UNKNOWN_ERROR = new ErrorEval(-20);
-
-    public static final ErrorEval FUNCTION_NOT_IMPLEMENTED = new ErrorEval(-30);
-
-    public static final ErrorEval REF_INVALID = new ErrorEval(-40);
+    /** <b>#NULL!</b>  - Intersection of two cell ranges is empty */
+    public static final ErrorEval NULL_INTERSECTION = new ErrorEval(EC.ERROR_NULL);
+    /** <b>#DIV/0!</b> - Division by zero */
+    public static final ErrorEval DIV_ZERO = new ErrorEval(EC.ERROR_DIV_0);
+    /** <b>#VALUE!</b> - Wrong type of operand */
+    public static final ErrorEval VALUE_INVALID = new ErrorEval(EC.ERROR_VALUE);
+    /** <b>#REF!</b> - Illegal or deleted cell reference */
+    public static final ErrorEval REF_INVALID = new ErrorEval(EC.ERROR_REF);
+    /** <b>#NAME?</b> - Wrong function or range name */
+    public static final ErrorEval NAME_INVALID = new ErrorEval(EC.ERROR_NAME);
+    /** <b>#NUM!</b> - Value range overflow */
+    public static final ErrorEval NUM_ERROR = new ErrorEval(EC.ERROR_NUM);
+    /** <b>#N/A</b> - Argument or function not available */
+    public static final ErrorEval NA = new ErrorEval(EC.ERROR_NA);
+
+
+    // POI internal error codes
+    private static final int CIRCULAR_REF_ERROR_CODE = 0xFFFFFFC4;
+    private static final int FUNCTION_NOT_IMPLEMENTED_CODE = 0xFFFFFFE2;
+
+    public static final ErrorEval FUNCTION_NOT_IMPLEMENTED = new ErrorEval(FUNCTION_NOT_IMPLEMENTED_CODE);
+    // Note - Excel does not seem to represent this condition with an error code
+    public static final ErrorEval CIRCULAR_REF_ERROR = new ErrorEval(CIRCULAR_REF_ERROR_CODE);
+
+
+    /**
+     * Translates an Excel internal error code into the corresponding POI ErrorEval instance
+     * @param errorCode
+     */
+    public static ErrorEval valueOf(int errorCode) {
+        switch(errorCode) {
+            case HSSFErrorConstants.ERROR_NULL:  return NULL_INTERSECTION;
+            case HSSFErrorConstants.ERROR_DIV_0: return DIV_ZERO;
+            case HSSFErrorConstants.ERROR_VALUE: return VALUE_INVALID;
+            case HSSFErrorConstants.ERROR_REF:   return REF_INVALID;
+            case HSSFErrorConstants.ERROR_NAME:  return NAME_INVALID;
+            case HSSFErrorConstants.ERROR_NUM:   return NUM_ERROR;
+            case HSSFErrorConstants.ERROR_NA:    return NA;
+            // non-std errors (conditions modeled as errors by POI)
+            case CIRCULAR_REF_ERROR_CODE:        return CIRCULAR_REF_ERROR;
+            case FUNCTION_NOT_IMPLEMENTED_CODE:  return FUNCTION_NOT_IMPLEMENTED;
+        }
+        throw new RuntimeException("Unexpected error code (" + errorCode + ")");
+    }
 
-    public static final ErrorEval NA = new ErrorEval(-50);
-    
-    public static final ErrorEval CIRCULAR_REF_ERROR = new ErrorEval(-60);
-    
-    public static final ErrorEval DIV_ZERO = new ErrorEval(-70);
-    
-    public static final ErrorEval NUM_ERROR = new ErrorEval(-80);
+    /**
+     * Converts error codes to text.  Handles non-standard error codes OK.  
+     * For debug/test purposes (and for formatting error messages).
+     * @return the String representation of the specified Excel error code.
+     */
+    public static String getText(int errorCode) {
+        if(HSSFErrorConstants.isValidCode(errorCode)) {
+            return HSSFErrorConstants.getText(errorCode);
+        }
+        // It is desirable to make these (arbitrary) strings look clearly different from any other
+        // value expression that might appear in a formula.  In addition these error strings should
+        // look unlike the standard Excel errors.  Hence tilde ('~') was used.
+        switch(errorCode) {
+            case CIRCULAR_REF_ERROR_CODE: return "~CIRCULAR~REF~";
+            case FUNCTION_NOT_IMPLEMENTED_CODE: return "~FUNCTION~NOT~IMPLEMENTED~";
+        }
+        return "~non~std~err(" + errorCode + ")~";
+    }
 
+    private int _errorCode;
+    /**
+     * @param errorCode an 8-bit value
+     */
     private ErrorEval(int errorCode) {
-        this.errorCode = errorCode;
+        _errorCode = errorCode;
     }
 
     public int getErrorCode() {
-        return errorCode;
+        return _errorCode;
     }
-
-    public String getStringValue() {
-        return "Err:" + Integer.toString(errorCode);
+    public String toString() {
+        StringBuffer sb = new StringBuffer(64);
+        sb.append(getClass().getName()).append(" [");
+        sb.append(getText(_errorCode));
+        sb.append("]");
+        return sb.toString();
     }
-
 }

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/FunctionEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/FunctionEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/FunctionEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/FunctionEval.java Sat Mar  8 03:49:00 2008
@@ -20,6 +20,9 @@
  */
 package org.apache.poi.hssf.record.formula.eval;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.apache.poi.hssf.record.formula.functions.*;
 
 /**
@@ -27,12 +30,49 @@
  *  
  */
 public abstract class FunctionEval implements OperationEval {
+    /**
+     * Some function IDs that require special treatment
+     */
+    private static final class FunctionID {
+        /** 78 */
+        public static final int OFFSET = 78;
+        /** 148 */
+        public static final int INDIRECT = 148;
+        /** 255 */
+        public static final int EXTERNAL_FUNC = 255;
+    }
+    // convenient access to namespace
+    private static final FunctionID ID = null;
+    
     protected static Function[] functions = produceFunctions();
 
+    private static Map freeRefFunctionsByIdMap;
+     
+    static {
+        Map m = new HashMap();
+        addMapping(m, ID.OFFSET, new Offset());
+        addMapping(m, ID.INDIRECT, new Indirect());
+        addMapping(m, ID.EXTERNAL_FUNC, new ExternalFunction());
+        freeRefFunctionsByIdMap = m;
+    }
+    private static void addMapping(Map m, int offset, FreeRefFunction frf) {
+        m.put(createFRFKey(offset), frf);
+    }
+    private static Integer createFRFKey(int functionIndex) {
+        return new Integer(functionIndex);
+    }
+    
+    
     public Function getFunction() {
         short fidx = getFunctionIndex();
         return functions[fidx];
     }
+    public boolean isFreeRefFunction() {
+        return freeRefFunctionsByIdMap.containsKey(createFRFKey(getFunctionIndex()));
+    }
+    public FreeRefFunction getFreeRefFunction() {
+        return (FreeRefFunction) freeRefFunctionsByIdMap.get(createFRFKey(getFunctionIndex()));
+    }
 
     public abstract short getFunctionIndex();
 
@@ -115,7 +155,7 @@
         retval[75] = new Areas(); // AREAS
         retval[76] = new Rows(); // ROWS
         retval[77] = new Columns(); // COLUMNS
-        retval[78] = new Offset(); // OFFSET
+        retval[ID.OFFSET] = null; // Offset.evaluate has a different signature
         retval[79] = new Absref(); // ABSREF
         retval[80] = new Relref(); // RELREF
         retval[81] = new Argument(); // ARGUMENT
@@ -185,7 +225,7 @@
         retval[145] = new NotImplementedFunction(); // GETDEF
         retval[146] = new Reftext(); // REFTEXT
         retval[147] = new Textref(); // TEXTREF
-        retval[148] = new Indirect(); // INDIRECT
+        retval[ID.INDIRECT] = null; // Indirect.evaluate has different signature
         retval[149] = new NotImplementedFunction(); // REGISTER
         retval[150] = new Call(); // CALL
         retval[151] = new NotImplementedFunction(); // ADDBAR
@@ -278,7 +318,7 @@
         retval[252] = new Frequency(); // FREQUENCY
         retval[253] = new NotImplementedFunction(); // ADDTOOLBAR
         retval[254] = new NotImplementedFunction(); // DELETETOOLBAR
-        retval[255] = new NotImplementedFunction(); // EXTERNALFLAG
+        retval[ID.EXTERNAL_FUNC] = null; // ExternalFunction is a FreeREfFunction
         retval[256] = new NotImplementedFunction(); // RESETTOOLBAR
         retval[257] = new Evaluate(); // EVALUATE
         retval[258] = new NotImplementedFunction(); // GETTOOLBAR

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/MultiplyEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/MultiplyEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/MultiplyEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/MultiplyEval.java Sat Mar  8 03:49:00 2008
@@ -14,10 +14,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-/*
- * Created on May 8, 2005
- *
- */
+
 package org.apache.poi.hssf.record.formula.eval;
 
 import org.apache.poi.hssf.record.formula.Ptg;
@@ -27,15 +24,13 @@
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
  *  
  */
-public class MultiplyEval extends NumericOperationEval {
+public final class MultiplyEval extends NumericOperationEval {
 
     private MultiplyPtg delegate;
 
     private static final ValueEvalToNumericXlator NUM_XLATOR = 
         new ValueEvalToNumericXlator((short)
                 ( ValueEvalToNumericXlator.BOOL_IS_PARSED 
-                | ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
-                | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
                 | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
                 | ValueEvalToNumericXlator.STRING_IS_PARSED
                 | ValueEvalToNumericXlator.REF_STRING_IS_PARSED
@@ -49,46 +44,39 @@
         return NUM_XLATOR;
     }
 
-    public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
-        Eval retval = null;
+    public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
+    	if(args.length != 2) {
+    		return ErrorEval.VALUE_INVALID;
+    	}
+    	
         double d0 = 0;
         double d1 = 0;
-        switch (operands.length) {
-        default: // will rarely happen. currently the parser itself fails.
-            retval = ErrorEval.UNKNOWN_ERROR;
-            break;
-        case 2:
-            ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
-            if (ve instanceof NumericValueEval) {
-                d0 = ((NumericValueEval) ve).getNumberValue();
-            }
-            else if (ve instanceof BlankEval) {
-                // do nothing
-            }
-            else {
-                retval = ErrorEval.VALUE_INVALID;
-            }
-            
-            if (retval == null) { // no error yet
-                ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
-                if (ve instanceof NumericValueEval) {
-                    d1 = ((NumericValueEval) ve).getNumberValue();
-                }
-                else if (ve instanceof BlankEval) {
-                    // do nothing
-                }
-                else {
-                    retval = ErrorEval.VALUE_INVALID;
-                }
-            }
-        } // end switch
-
-        if (retval == null) {
-            retval = (Double.isNaN(d0) || Double.isNaN(d1)) 
-                    ? (ValueEval) ErrorEval.VALUE_INVALID 
-                    : new NumberEval(d0 * d1);
+        ValueEval ve = singleOperandEvaluate(args[0], srcRow, srcCol);
+        if (ve instanceof NumericValueEval) {
+            d0 = ((NumericValueEval) ve).getNumberValue();
+        }
+        else if (ve instanceof BlankEval) {
+            // do nothing
+        }
+        else {
+            return ErrorEval.VALUE_INVALID;
+        }
+        
+        ve = singleOperandEvaluate(args[1], srcRow, srcCol);
+        if (ve instanceof NumericValueEval) {
+            d1 = ((NumericValueEval) ve).getNumberValue();
+        }
+        else if (ve instanceof BlankEval) {
+        // do nothing
+        }
+        else {
+        	return ErrorEval.VALUE_INVALID;
         }
-        return retval;
+ 
+        if (Double.isNaN(d0) || Double.isNaN(d1)) {
+			return ErrorEval.NUM_ERROR;
+		}
+		return new NumberEval(d0 * d1);
     }
 
     public int getNumberOfOperands() {

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/PowerEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/PowerEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/PowerEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/PowerEval.java Sat Mar  8 03:49:00 2008
@@ -14,10 +14,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-/*
- * Created on May 8, 2005
- *
- */
+
 package org.apache.poi.hssf.record.formula.eval;
 
 import org.apache.poi.hssf.record.formula.Ptg;
@@ -27,15 +24,13 @@
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
  *  
  */
-public class PowerEval extends NumericOperationEval {
+public final class PowerEval extends NumericOperationEval {
 
     private PowerPtg delegate;
 
     private static final ValueEvalToNumericXlator NUM_XLATOR = 
         new ValueEvalToNumericXlator((short)
                 ( ValueEvalToNumericXlator.BOOL_IS_PARSED 
-                | ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
-                | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
                 | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
                 | ValueEvalToNumericXlator.STRING_IS_PARSED
                 | ValueEvalToNumericXlator.REF_STRING_IS_PARSED
@@ -49,48 +44,40 @@
         return NUM_XLATOR;
     }
 
-    public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
-        Eval retval = null;
+    public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
+    	if(args.length != 2) {
+    		return ErrorEval.VALUE_INVALID;
+    	}
         double d0 = 0;
         double d1 = 0;
         
-        switch (operands.length) {
-        default: // will rarely happen. currently the parser itself fails.
-            retval = ErrorEval.UNKNOWN_ERROR;
-            break;
-        case 2:
-            ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
-            if (ve instanceof NumericValueEval) {
-                d0 = ((NumericValueEval) ve).getNumberValue();
-            }
-            else if (ve instanceof BlankEval) {
-                // do nothing
-            }
-            else {
-                retval = ErrorEval.VALUE_INVALID;
-            }
-            
-            if (retval == null) { // no error yet
-                ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
-                if (ve instanceof NumericValueEval) {
-                    d1 = ((NumericValueEval) ve).getNumberValue();
-                }
-                else if (ve instanceof BlankEval) {
-                    // do nothing
-                }
-                else {
-                    retval = ErrorEval.VALUE_INVALID;
-                }
-            }
-        } // end switch
-
-        if (retval == null) {
-            double p = Math.pow(d0, d1);
-            retval = (Double.isNaN(p)) 
-                    ? (ValueEval) ErrorEval.VALUE_INVALID 
-                    : new NumberEval(p);
+        ValueEval ve = singleOperandEvaluate(args[0], srcRow, srcCol);
+        if (ve instanceof NumericValueEval) {
+            d0 = ((NumericValueEval) ve).getNumberValue();
+        }
+        else if (ve instanceof BlankEval) {
+            // do nothing
         }
-        return retval;
+        else {
+            return ErrorEval.VALUE_INVALID;
+        }
+        
+        ve = singleOperandEvaluate(args[1], srcRow, srcCol);
+        if (ve instanceof NumericValueEval) {
+            d1 = ((NumericValueEval) ve).getNumberValue();
+        }
+        else if (ve instanceof BlankEval) {
+        // do nothing
+        }
+        else {
+            return ErrorEval.VALUE_INVALID;
+        }
+
+        double p = Math.pow(d0, d1);
+        if (Double.isNaN(p)) {
+			return ErrorEval.VALUE_INVALID;
+		}
+		return new NumberEval(p);
     }
 
     public int getNumberOfOperands() {

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Ref2DEval.java Sat Mar  8 03:49:00 2008
@@ -14,47 +14,37 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-/*
- * Created on May 9, 2005
- *
- */
+
 package org.apache.poi.hssf.record.formula.eval;
 
-import org.apache.poi.hssf.record.formula.Ptg;
 import org.apache.poi.hssf.record.formula.ReferencePtg;
 
 /**
  * @author adeshmukh
  *  
  */
-public class Ref2DEval implements RefEval {
-
-    private ValueEval value;
+public final class Ref2DEval implements RefEval {
 
-    private ReferencePtg delegate;
+    private final ValueEval value;
+    private final ReferencePtg delegate;
     
-    private boolean evaluated;
-
-    public Ref2DEval(Ptg ptg, ValueEval value, boolean evaluated) {
-        this.value = value;
-        this.delegate = (ReferencePtg) ptg;
-        this.evaluated = evaluated;
+    public Ref2DEval(ReferencePtg ptg, ValueEval ve) {
+        if(ve == null) {
+            throw new IllegalArgumentException("ve must not be null");
+        }
+        if(false && ptg == null) { // TODO - fix dodgy code in MultiOperandNumericFunction
+            throw new IllegalArgumentException("ptg must not be null");
+        }
+        value = ve;
+        delegate = ptg;
     }
-
     public ValueEval getInnerValueEval() {
         return value;
     }
-
-    public short getRow() {
+    public int getRow() {
         return delegate.getRow();
     }
-
-    public short getColumn() {
+    public int getColumn() {
         return delegate.getColumn();
     }
-    
-    public boolean isEvaluated() {
-        return evaluated;
-    }
-
 }

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Ref3DEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Ref3DEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Ref3DEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/Ref3DEval.java Sat Mar  8 03:49:00 2008
@@ -14,47 +14,40 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-/*
- * Created on May 9, 2005
- *
- */
+
 package org.apache.poi.hssf.record.formula.eval;
 
-import org.apache.poi.hssf.record.formula.Ptg;
 import org.apache.poi.hssf.record.formula.Ref3DPtg;
 
 /**
  * @author Amol S. Deshmukh
  *  
  */
-public class Ref3DEval implements RefEval {
-
-    private ValueEval value;
-
-    private Ref3DPtg delegate;
+public final class Ref3DEval implements RefEval {
 
-    private boolean evaluated;
+    private final ValueEval value;
+    private final Ref3DPtg delegate;
 
-    public Ref3DEval(Ptg ptg, ValueEval value, boolean evaluated) {
-        this.value = value;
-        this.delegate = (Ref3DPtg) ptg;
-        this.evaluated = evaluated;
+    public Ref3DEval(Ref3DPtg ptg, ValueEval ve) {
+        if(ve == null) {
+            throw new IllegalArgumentException("ve must not be null");
+        }
+        if(ptg == null) {
+            throw new IllegalArgumentException("ptg must not be null");
+        }
+        value = ve;
+        delegate = ptg;
     }
-
     public ValueEval getInnerValueEval() {
         return value;
     }
-
-    public short getRow() {
+    public int getRow() {
         return delegate.getRow();
     }
-
-    public short getColumn() {
+    public int getColumn() {
         return delegate.getColumn();
     }
-    
-    public boolean isEvaluated() {
-        return evaluated;
+    public int getExternSheetIndex() {
+        return delegate.getExternSheetIndex();
     }
-
 }

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/RefEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/RefEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/RefEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/RefEval.java Sat Mar  8 03:49:00 2008
@@ -14,11 +14,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-/*
- * Created on May 9, 2005
- *
- * 
- */
+
 package org.apache.poi.hssf.record.formula.eval;
 
 /**
@@ -44,26 +40,12 @@
     public ValueEval getInnerValueEval();
 
     /**
-     * returns the column index.
+     * returns the zero based column index.
      */
-    public short getColumn();
+    public int getColumn();
 
     /**
-     * returns the row index.
+     * returns the zero based row index.
      */
-    public short getRow();
-    
-    /**
-     * returns true if this RefEval contains an
-     * evaluated value instead of a direct value.
-     * eg. say cell A1 has the value: ="test"
-     * Then the RefEval representing A1 will return
-     * isEvaluated() equal to false. On the other
-     * hand, say cell A1 has the value: =B1 and
-     * B1 has the value "test", then the RefEval
-     * representing A1 will return isEvaluated()
-     * equal to true.
-     */
-    public boolean isEvaluated();
-
+    public int getRow();
 }

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/StringEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/StringEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/StringEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/StringEval.java Sat Mar  8 03:49:00 2008
@@ -14,10 +14,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-/*
- * Created on May 8, 2005
- *
- */
+
 package org.apache.poi.hssf.record.formula.eval;
 
 import org.apache.poi.hssf.record.formula.Ptg;
@@ -27,21 +24,31 @@
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
  *  
  */
-public class StringEval implements StringValueEval {
+public final class StringEval implements StringValueEval {
 
     public static final StringEval EMPTY_INSTANCE = new StringEval("");
     
-    private String value;
+    private final String value;
 
     public StringEval(Ptg ptg) {
-        this.value = ((StringPtg) ptg).getValue();
+        this(((StringPtg) ptg).getValue());
     }
 
     public StringEval(String value) {
+        if(value == null) {
+            throw new IllegalArgumentException("value must not be null");
+        }
         this.value = value;
     }
 
     public String getStringValue() {
         return value;
+    }
+    public String toString() {
+        StringBuffer sb = new StringBuffer(64);
+        sb.append(getClass().getName()).append(" [");
+        sb.append(value);
+        sb.append("]");
+        return sb.toString();
     }
 }

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/StringValueEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/StringValueEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/StringValueEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/StringValueEval.java Sat Mar  8 03:49:00 2008
@@ -14,10 +14,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-/*
- * Created on May 8, 2005
- *
- */
+
 package org.apache.poi.hssf.record.formula.eval;
 
 /**
@@ -26,5 +23,8 @@
  */
 public interface StringValueEval extends ValueEval {
 
-    public String getStringValue();
+    /**
+     * @return never <code>null</code>, possibly empty string.
+     */
+    String getStringValue();
 }

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/SubtractEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/SubtractEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/SubtractEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/SubtractEval.java Sat Mar  8 03:49:00 2008
@@ -14,10 +14,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-/*
- * Created on May 8, 2005
- *
- */
+
 package org.apache.poi.hssf.record.formula.eval;
 
 import org.apache.poi.hssf.record.formula.Ptg;
@@ -27,15 +24,13 @@
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
  *  
  */
-public class SubtractEval extends NumericOperationEval {
+public final class SubtractEval extends NumericOperationEval {
 
     private SubtractPtg delegate;
 
     private static final ValueEvalToNumericXlator NUM_XLATOR = 
         new ValueEvalToNumericXlator((short)
                 ( ValueEvalToNumericXlator.BOOL_IS_PARSED 
-                | ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
-                | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
                 | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
                 | ValueEvalToNumericXlator.STRING_IS_PARSED
                 | ValueEvalToNumericXlator.REF_STRING_IS_PARSED
@@ -49,18 +44,28 @@
         return NUM_XLATOR;
     }
 
-    public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
+    public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
+    	if(args.length != 2) {
+    		return ErrorEval.VALUE_INVALID;
+    	}
         Eval retval = null;
         double d0 = 0;
         double d1 = 0;
-        switch (operands.length) {
-        default: // will rarely happen. currently the parser itself fails.
-            retval = ErrorEval.UNKNOWN_ERROR;
-            break;
-        case 2:
-            ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
+        ValueEval ve = singleOperandEvaluate(args[0], srcRow, srcCol);
+        if (ve instanceof NumericValueEval) {
+            d0 = ((NumericValueEval) ve).getNumberValue();
+        }
+        else if (ve instanceof BlankEval) {
+            // do nothing
+        }
+        else {
+            retval = ErrorEval.VALUE_INVALID;
+        }
+        
+        if (retval == null) { // no error yet
+            ve = singleOperandEvaluate(args[1], srcRow, srcCol);
             if (ve instanceof NumericValueEval) {
-                d0 = ((NumericValueEval) ve).getNumberValue();
+                d1 = ((NumericValueEval) ve).getNumberValue();
             }
             else if (ve instanceof BlankEval) {
                 // do nothing
@@ -68,21 +73,8 @@
             else {
                 retval = ErrorEval.VALUE_INVALID;
             }
-            
-            if (retval == null) { // no error yet
-                ve = singleOperandEvaluate(operands[1], srcRow, srcCol);
-                if (ve instanceof NumericValueEval) {
-                    d1 = ((NumericValueEval) ve).getNumberValue();
-                }
-                else if (ve instanceof BlankEval) {
-                    // do nothing
-                }
-                else {
-                    retval = ErrorEval.VALUE_INVALID;
-                }
-            }
-        } // end switch
-
+        }
+ 
         if (retval == null) {
             retval = (Double.isNaN(d0) || Double.isNaN(d1)) 
                     ? (ValueEval) ErrorEval.VALUE_INVALID 

Modified: poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java
URL: http://svn.apache.org/viewvc/poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java?rev=634936&r1=634935&r2=634936&view=diff
==============================================================================
--- poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java (original)
+++ poi/branches/ooxml/src/scratchpad/src/org/apache/poi/hssf/record/formula/eval/UnaryMinusEval.java Sat Mar  8 03:49:00 2008
@@ -14,10 +14,7 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
-/*
- * Created on May 8, 2005
- *
- */
+
 package org.apache.poi.hssf.record.formula.eval;
 
 import org.apache.poi.hssf.record.formula.Ptg;
@@ -27,14 +24,12 @@
  * @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
  *  
  */
-public class UnaryMinusEval extends NumericOperationEval {
+public final class UnaryMinusEval extends NumericOperationEval {
 
     private UnaryMinusPtg delegate;
     private static final ValueEvalToNumericXlator NUM_XLATOR = 
         new ValueEvalToNumericXlator((short)
                 ( ValueEvalToNumericXlator.BOOL_IS_PARSED 
-                | ValueEvalToNumericXlator.EVALUATED_REF_BOOL_IS_PARSED
-                | ValueEvalToNumericXlator.EVALUATED_REF_STRING_IS_PARSED
                 | ValueEvalToNumericXlator.REF_BOOL_IS_PARSED
                 | ValueEvalToNumericXlator.STRING_IS_PARSED
                 | ValueEvalToNumericXlator.REF_STRING_IS_PARSED
@@ -49,32 +44,24 @@
         return NUM_XLATOR;
     }
 
-    public Eval evaluate(Eval[] operands, int srcRow, short srcCol) {
-        ValueEval retval = null;
+    public Eval evaluate(Eval[] args, int srcRow, short srcCol) {
+    	if(args.length != 1) {
+    		return ErrorEval.VALUE_INVALID;
+    	}
         double d = 0;
         
-        switch (operands.length) {
-        default:
-            retval = ErrorEval.UNKNOWN_ERROR;
-            break;
-        case 1:
-            ValueEval ve = singleOperandEvaluate(operands[0], srcRow, srcCol);
-            if (ve instanceof NumericValueEval) {
-                d = ((NumericValueEval) ve).getNumberValue();
-            }
-            else if (ve instanceof BlankEval) {
-                // do nothing
-            }
-            else if (ve instanceof ErrorEval) {
-                retval = ve;
-            }
+        ValueEval ve = singleOperandEvaluate(args[0], srcRow, srcCol);
+        if (ve instanceof NumericValueEval) {
+            d = ((NumericValueEval) ve).getNumberValue();
         }
-        
-        if (retval == null) {
-            retval = new NumberEval(-d);
+        else if (ve instanceof BlankEval) {
+            // do nothing
         }
-
-        return retval;
+        else if (ve instanceof ErrorEval) {
+            return ve;
+        }
+        
+        return new NumberEval(-d);
     }
 
     public int getNumberOfOperands() {



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


Mime
View raw message