You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by jo...@apache.org on 2008/09/13 07:43:42 UTC

svn commit: r694881 - in /poi/trunk/src: java/org/apache/poi/hssf/usermodel/ testcases/org/apache/poi/hssf/record/formula/eval/ testcases/org/apache/poi/hssf/record/formula/functions/

Author: josh
Date: Fri Sep 12 22:43:41 2008
New Revision: 694881

URL: http://svn.apache.org/viewvc?rev=694881&view=rev
Log:
Added toString methods formatAsString to CellValue. Changed deprecation on CellValue.getRichTextStringValue

Modified:
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java
    poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulasFromSpreadsheet.java
    poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndexFunctionFromSpreadsheet.java
    poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLookupFunctionsFromSpreadsheet.java

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java?rev=694881&r1=694880&r2=694881&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java Fri Sep 12 22:43:41 2008
@@ -179,7 +179,7 @@
             case HSSFCell.CELL_TYPE_NUMERIC:
                 return new CellValue(cell.getNumericCellValue());
             case HSSFCell.CELL_TYPE_STRING:
-                return new CellValue(cell.getRichStringCellValue());
+                return new CellValue(cell.getRichStringCellValue().getString());
         }
         throw new IllegalStateException("Bad cell type (" + cell.getCellType() + ")");
     }
@@ -270,7 +270,7 @@
                 cell.setCellValue(cv.getNumberValue());
                 break;
             case HSSFCell.CELL_TYPE_STRING:
-                cell.setCellValue(cv.getRichTextStringValue());
+                cell.setCellValue(new HSSFRichTextString(cv.getStringValue()));
                 break;
             case HSSFCell.CELL_TYPE_BLANK:
                 // never happens - blanks eventually get translated to zero
@@ -325,7 +325,7 @@
         }
         if (eval instanceof StringEval) {
             StringEval ne = (StringEval) eval;
-            return new CellValue(new HSSFRichTextString(ne.getStringValue()));
+            return new CellValue(ne.getStringValue());
         }
         if (eval instanceof ErrorEval) {
             return CellValue.getError(((ErrorEval)eval).getErrorCode());
@@ -423,7 +423,7 @@
             throw new IllegalStateException("evaluation stack not empty");
         }
         value = dereferenceValue(value, srcRowNum, srcColNum);
-        if (value instanceof BlankEval) {
+        if (value == BlankEval.INSTANCE) {
             // Note Excel behaviour here. A blank final final value is converted to zero.
             return NumberEval.ZERO;
             // Formulas _never_ evaluate to blank.  If a formula appears to have evaluated to
@@ -597,15 +597,15 @@
         private final int _cellType;
         private final double _numberValue;
         private final boolean _booleanValue;
-        private final HSSFRichTextString _richTextStringValue;
+        private final String _textValue;
         private final int _errorCode;
 
         private CellValue(int cellType, double numberValue, boolean booleanValue, 
-                HSSFRichTextString textValue, int errorCode) {
+                String textValue, int errorCode) {
             _cellType = cellType;
             _numberValue = numberValue;
             _booleanValue = booleanValue;
-            _richTextStringValue = textValue;
+            _textValue = textValue;
             _errorCode = errorCode;
         }
         
@@ -616,7 +616,7 @@
         /* package*/ static CellValue valueOf(boolean booleanValue) {
             return booleanValue ? TRUE : FALSE;
         }
-        /* package*/ CellValue(HSSFRichTextString stringValue) {
+        /* package*/ CellValue(String stringValue) {
             this(HSSFCell.CELL_TYPE_STRING, 0.0, false, stringValue, 0);
         }
         /* package*/ static CellValue getError(int errorCode) {
@@ -637,12 +637,10 @@
             return _numberValue;
         }
         /**
-         * @return Returns the stringValue. This method is deprecated, use
-         * getRichTextStringValue instead
-         * @deprecated
+         * @return Returns the stringValue.
          */
         public String getStringValue() {
-            return _richTextStringValue.getString();
+            return _textValue;
         }
         /**
          * @return Returns the cellType.
@@ -658,9 +656,31 @@
         }
         /**
          * @return Returns the richTextStringValue.
+         * @deprecated (Sep 2008) Text formatting is lost during formula evaluation.  Use {@link #getStringValue()}  
          */
         public HSSFRichTextString getRichTextStringValue() {
-            return _richTextStringValue;
+            return new HSSFRichTextString(_textValue);
+        }
+        public String toString() {
+            StringBuffer sb = new StringBuffer(64);
+            sb.append(getClass().getName()).append(" [");
+            sb.append(formatAsString());
+            sb.append("]");
+            return sb.toString();
+        }
+
+        public String formatAsString() {
+            switch (_cellType) {
+                case HSSFCell.CELL_TYPE_NUMERIC:
+                    return String.valueOf(_numberValue);
+                case HSSFCell.CELL_TYPE_STRING:
+                    return '"' + _textValue + '"';
+                case HSSFCell.CELL_TYPE_BOOLEAN:
+                    return _booleanValue ? "TRUE" : "FALSE";
+                case HSSFCell.CELL_TYPE_ERROR:
+                    return ErrorEval.getText(_errorCode);
+            }
+            return "<error unexpected cell type " + _cellType + ">";
         }
     }
 

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulasFromSpreadsheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulasFromSpreadsheet.java?rev=694881&r1=694880&r2=694881&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulasFromSpreadsheet.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/eval/TestFormulasFromSpreadsheet.java Fri Sep 12 22:43:41 2008
@@ -132,7 +132,7 @@
 				break;
 			case HSSFCell.CELL_TYPE_STRING:
 				assertEquals(msg, HSSFCell.CELL_TYPE_STRING, actual.getCellType());
-				assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getRichTextStringValue().getString());
+				assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());
 				break;
 		}
 	}
@@ -142,7 +142,7 @@
 		if (workbook == null) {
 			workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
 			sheet = workbook.getSheetAt( 0 );
-		  }
+		}
 		_functionFailureCount = 0;
 		_functionSuccessCount = 0;
 		_evaluationFailureCount = 0;
@@ -177,7 +177,7 @@
 	 * Typically pass <code>null</code> to test all functions
 	 */
 	private void processFunctionGroup(int startRowIndex, String testFocusFunctionName) {
- 
+
 		HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
 
 		int rowIndex = startRowIndex;
@@ -248,7 +248,7 @@
 				result = Result.SOME_EVALUATIONS_FAILED;
 			}
 		}
- 		return result;
+		return result;
 	}
 
 	/**

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndexFunctionFromSpreadsheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndexFunctionFromSpreadsheet.java?rev=694881&r1=694880&r2=694881&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndexFunctionFromSpreadsheet.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestIndexFunctionFromSpreadsheet.java Fri Sep 12 22:43:41 2008
@@ -59,7 +59,7 @@
 
 	}
 
- 	// Note - multiple failures are aggregated before ending.
+	// Note - multiple failures are aggregated before ending.
 	// If one or more functions fail, a single AssertionFailedError is thrown at the end
 	private int _evaluationFailureCount;
 	private int _evaluationSuccessCount;
@@ -95,7 +95,7 @@
 				assertEquals(expected.getNumericCellValue(), actual.getNumberValue(), 0.0);
 				break;
 			case HSSFCell.CELL_TYPE_STRING:
-				assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getRichTextStringValue().getString());
+				assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());
 				break;
 		}
 	}
@@ -103,7 +103,7 @@
 
 	private static AssertionFailedError wrongTypeError(String msgPrefix, HSSFCell expectedCell, CellValue actualValue) {
 		return new AssertionFailedError(msgPrefix + " Result type mismatch. Evaluated result was "
-				+ formatValue(actualValue)
+				+ actualValue.formatAsString()
 				+ " but the expected result was "
 				+ formatValue(expectedCell)
 				);
@@ -121,7 +121,7 @@
 		if(actual.getCellType() != HSSFCell.CELL_TYPE_ERROR) {
 			throw new AssertionFailedError(msgPrefix + " Expected cell error ("
 					+ ErrorEval.getText(expectedErrorCode) + ") but actual value was "
-					+ formatValue(actual));
+					+ actual.formatAsString());
 		}
 		if(expectedErrorCode != actual.getErrorValue()) {
 			throw new AssertionFailedError(msgPrefix + " Expected cell error code ("
@@ -142,15 +142,6 @@
 		}
 		throw new RuntimeException("Unexpected cell type of expected value (" + expecedCell.getCellType() + ")");
 	}
-	private static String formatValue(CellValue actual) {
-		switch (actual.getCellType()) {
-			case HSSFCell.CELL_TYPE_BLANK: return "<blank>";
-			case HSSFCell.CELL_TYPE_BOOLEAN: return String.valueOf(actual.getBooleanValue());
-			case HSSFCell.CELL_TYPE_NUMERIC: return String.valueOf(actual.getNumberValue());
-			case HSSFCell.CELL_TYPE_STRING: return actual.getRichTextStringValue().getString();
-		}
-		throw new RuntimeException("Unexpected cell type of evaluated value (" + actual.getCellType() + ")");
-	}
 
 
 	protected void setUp() {
@@ -166,13 +157,13 @@
 		// confirm results
 		String successMsg = "There were "
 				+ _evaluationSuccessCount + " function(s) without error";
- 		if(_evaluationFailureCount > 0) {
+		if(_evaluationFailureCount > 0) {
 			String msg = _evaluationFailureCount + " evaluation(s) failed.  " + successMsg;
 			throw new AssertionFailedError(msg);
 		}
- 		if(false) { // normally no output for successful tests
- 			System.out.println(getClass().getName() + ": " + successMsg);
- 		}
+		if(false) { // normally no output for successful tests
+			System.out.println(getClass().getName() + ": " + successMsg);
+		}
 	}
 
 	private void processTestSheet(HSSFWorkbook workbook, String sheetName) {

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLookupFunctionsFromSpreadsheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLookupFunctionsFromSpreadsheet.java?rev=694881&r1=694880&r2=694881&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLookupFunctionsFromSpreadsheet.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/record/formula/functions/TestLookupFunctionsFromSpreadsheet.java Fri Sep 12 22:43:41 2008
@@ -37,33 +37,33 @@
  * Tests lookup functions (VLOOKUP, HLOOKUP, LOOKUP, MATCH) as loaded from a test data spreadsheet.<p/>
  * These tests have been separated from the common function and operator tests because the lookup
  * functions have more complex test cases and test data setup.
- * 
+ *
  * Tests for bug fixes and specific/tricky behaviour can be found in the corresponding test class
  * (<tt>TestXxxx</tt>) of the target (<tt>Xxxx</tt>) implementor, where execution can be observed
  *  more easily.
- * 
+ *
  * @author Josh Micich
  */
 public final class TestLookupFunctionsFromSpreadsheet extends TestCase {
-	
+
 	private static final class Result {
 		public static final int SOME_EVALUATIONS_FAILED = -1;
 		public static final int ALL_EVALUATIONS_SUCCEEDED = +1;
 		public static final int NO_EVALUATIONS_FOUND = 0;
 	}
 
-	/** 
+	/**
 	 * This class defines constants for navigating around the test data spreadsheet used for these tests.
 	 */
 	private static final class SS {
-		
+
 		/** Name of the test spreadsheet (found in the standard test data folder) */
 		public final static String FILENAME = "LookupFunctionsTestCaseData.xls";
-		
+
 		/** Name of the first sheet in the spreadsheet (contains comments) */
 		public final static String README_SHEET_NAME = "Read Me";
-		
-		
+
+
 		/** Row (zero-based) in each sheet where the evaluation cases start.   */
 		public static final int START_TEST_CASES_ROW_INDEX = 4; // Row '5'
 		/**  Index of the column that contains the function names */
@@ -71,15 +71,15 @@
 		public static final int COLUMN_INDEX_EVALUATION = 1; // Column 'B'
 		public static final int COLUMN_INDEX_EXPECTED_RESULT = 2; // Column 'C'
 		public static final int COLUMN_ROW_COMMENT = 3; // Column 'D'
-	
+
 		/** Used to indicate when there are no more test cases on the current sheet   */
 		public static final String TEST_CASES_END_MARKER = "<end>";
 		/** Used to indicate that the test on the current row should be ignored */
 		public static final String SKIP_CURRENT_TEST_CASE_MARKER = "<skip>";
-	
+
 	}
 
- 	// Note - multiple failures are aggregated before ending.  
+	// Note - multiple failures are aggregated before ending.
 	// If one or more functions fail, a single AssertionFailedError is thrown at the end
 	private int _sheetFailureCount;
 	private int _sheetSuccessCount;
@@ -105,19 +105,19 @@
 		if(actual.getCellType() != expected.getCellType()) {
 			throw wrongTypeError(msg, expected, actual);
 		}
-		
-		
+
+
 		switch (expected.getCellType()) {
 			case HSSFCell.CELL_TYPE_BOOLEAN:
 				assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());
 				break;
 			case HSSFCell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
-				throw new AssertionFailedError("Cannot expect formula as result of formula evaluation: " + msg);
+				throw new IllegalStateException("Cannot expect formula as result of formula evaluation: " + msg);
 			case HSSFCell.CELL_TYPE_NUMERIC:
 				assertEquals(expected.getNumericCellValue(), actual.getNumberValue(), 0.0);
 				break;
 			case HSSFCell.CELL_TYPE_STRING:
-				assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getRichTextStringValue().getString());
+				assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());
 				break;
 		}
 	}
@@ -125,14 +125,14 @@
 
 	private static AssertionFailedError wrongTypeError(String msgPrefix, HSSFCell expectedCell, CellValue actualValue) {
 		return new AssertionFailedError(msgPrefix + " Result type mismatch. Evaluated result was "
-				+ formatValue(actualValue) 
+				+ actualValue.formatAsString()
 				+ " but the expected result was "
 				+ formatValue(expectedCell)
 				);
 	}
 	private static AssertionFailedError unexpectedError(String msgPrefix, HSSFCell expected, int actualErrorCode) {
 		return new AssertionFailedError(msgPrefix + " Error code ("
-				+ ErrorEval.getText(actualErrorCode) 
+				+ ErrorEval.getText(actualErrorCode)
 				+ ") was evaluated, but the expected result was "
 				+ formatValue(expected)
 				);
@@ -141,15 +141,15 @@
 
 	private static void confirmErrorResult(String msgPrefix, int expectedErrorCode, CellValue actual) {
 		if(actual.getCellType() != HSSFCell.CELL_TYPE_ERROR) {
-			throw new AssertionFailedError(msgPrefix + " Expected cell error (" 
+			throw new AssertionFailedError(msgPrefix + " Expected cell error ("
 					+ ErrorEval.getText(expectedErrorCode) + ") but actual value was "
-					+ formatValue(actual));
+					+ actual.formatAsString());
 		}
 		if(expectedErrorCode != actual.getErrorValue()) {
-			throw new AssertionFailedError(msgPrefix + " Expected cell error code (" 
-					+ ErrorEval.getText(expectedErrorCode) 
+			throw new AssertionFailedError(msgPrefix + " Expected cell error code ("
+					+ ErrorEval.getText(expectedErrorCode)
 					+ ") but actual error code was ("
-					+ ErrorEval.getText(actual.getErrorValue()) 
+					+ ErrorEval.getText(actual.getErrorValue())
 					+ ")");
 		}
 	}
@@ -164,49 +164,40 @@
 		}
 		throw new RuntimeException("Unexpected cell type of expected value (" + expecedCell.getCellType() + ")");
 	}
-	private static String formatValue(CellValue actual) {
-		switch (actual.getCellType()) {
-			case HSSFCell.CELL_TYPE_BLANK: return "<blank>";
-			case HSSFCell.CELL_TYPE_BOOLEAN: return String.valueOf(actual.getBooleanValue());
-			case HSSFCell.CELL_TYPE_NUMERIC: return String.valueOf(actual.getNumberValue());
-			case HSSFCell.CELL_TYPE_STRING: return actual.getRichTextStringValue().getString();
-		}
-		throw new RuntimeException("Unexpected cell type of evaluated value (" + actual.getCellType() + ")");
-	}
 
 
-	protected void setUp() throws Exception {
+	protected void setUp() {
 		_sheetFailureCount = 0;
 		_sheetSuccessCount = 0;
 		_evaluationFailureCount = 0;
 		_evaluationSuccessCount = 0;
 	}
-	
+
 	public void testFunctionsFromTestSpreadsheet() {
 		HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
-   	
+
 		confirmReadMeSheet(workbook);
 		int nSheets = workbook.getNumberOfSheets();
 		for(int i=1; i< nSheets; i++) {
 			int sheetResult = processTestSheet(workbook, i, workbook.getSheetName(i));
 			switch(sheetResult) {
-				case Result.ALL_EVALUATIONS_SUCCEEDED: _sheetSuccessCount ++; break; 
-				case Result.SOME_EVALUATIONS_FAILED: _sheetFailureCount ++; break; 
+				case Result.ALL_EVALUATIONS_SUCCEEDED: _sheetSuccessCount ++; break;
+				case Result.SOME_EVALUATIONS_FAILED: _sheetFailureCount ++; break;
 			}
 		}
-		
+
 		// confirm results
-		String successMsg = "There were " 
+		String successMsg = "There were "
 				+ _sheetSuccessCount + " successful sheets(s) and "
 				+ _evaluationSuccessCount + " function(s) without error";
- 		if(_sheetFailureCount > 0) {
+		if(_sheetFailureCount > 0) {
 			String msg = _sheetFailureCount + " sheets(s) failed with "
 			+ _evaluationFailureCount + " evaluation(s).  " + successMsg;
 			throw new AssertionFailedError(msg);
 		}
- 		if(false) { // normally no output for successful tests
- 			System.out.println(getClass().getName() + ": " + successMsg);
- 		}
+		if(false) { // normally no output for successful tests
+			System.out.println(getClass().getName() + ": " + successMsg);
+		}
 	}
 
 	private int processTestSheet(HSSFWorkbook workbook, int sheetIndex, String sheetName) {
@@ -214,7 +205,7 @@
 		HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
 		int maxRows = sheet.getLastRowNum()+1;
 		int result = Result.NO_EVALUATIONS_FOUND; // so far
-		
+
 		String currentGroupComment = null;
 		for(int rowIndex=SS.START_TEST_CASES_ROW_INDEX; rowIndex<maxRows; rowIndex++) {
 			HSSFRow r = sheet.getRow(rowIndex);
@@ -240,7 +231,7 @@
 			CellValue actualValue = evaluator.evaluate(c);
 			HSSFCell expectedValueCell = r.getCell(SS.COLUMN_INDEX_EXPECTED_RESULT);
 			String rowComment = getRowCommentColumnValue(r);
-			
+
 			String msgPrefix = formatTestCaseDetails(sheetName, r.getRowNum(), c, currentGroupComment, rowComment);
 			try {
 				confirmExpectedResult(msgPrefix, expectedValueCell, actualValue);
@@ -257,22 +248,22 @@
 				printShortStackTrace(System.err, e);
 				result = Result.SOME_EVALUATIONS_FAILED;
 			}
-			
+
 		}
-		throw new RuntimeException("Missing end marker '" + SS.TEST_CASES_END_MARKER 
+		throw new RuntimeException("Missing end marker '" + SS.TEST_CASES_END_MARKER
 				+ "' on sheet '" + sheetName + "'");
-		
+
 	}
 
 
 	private static String formatTestCaseDetails(String sheetName, int rowNum, HSSFCell c, String currentGroupComment,
 			String rowComment) {
-		
+
 		StringBuffer sb = new StringBuffer();
 		CellReference cr = new CellReference(sheetName, rowNum, c.getCellNum(), false, false);
 		sb.append(cr.formatAsString());
 		sb.append(" {=").append(c.getCellFormula()).append("}");
-		
+
 		if(currentGroupComment != null) {
 			sb.append(" '");
 			sb.append(currentGroupComment);
@@ -288,13 +279,13 @@
 				sb.append("' ");
 			}
 		}
-		
+
 		return sb.toString();
 	}
 
 	/**
-	 * Asserts that the 'read me' comment page exists, and has this class' name in one of the 
-	 * cells.  This back-link is to make it easy to find this class if a reader encounters the 
+	 * Asserts that the 'read me' comment page exists, and has this class' name in one of the
+	 * cells.  This back-link is to make it easy to find this class if a reader encounters the
 	 * spreadsheet first.
 	 */
 	private void confirmReadMeSheet(HSSFWorkbook workbook) {
@@ -313,7 +304,7 @@
 	 */
 	private static void printShortStackTrace(PrintStream ps, Throwable e) {
 		StackTraceElement[] stes = e.getStackTrace();
-		
+
 		int startIx = 0;
 		// skip any top frames inside junit.framework.Assert
 		while(startIx<stes.length) {
@@ -339,17 +330,17 @@
 		for(int i=startIx; i<endIx; i++) {
 			ps.println("\tat " + stes[i].toString());
 		}
-		
+
 	}
 
 	private static String getRowCommentColumnValue(HSSFRow r) {
 		return getCellTextValue(r, SS.COLUMN_ROW_COMMENT, "row comment");
 	}
-	
+
 	private static String getMarkerColumnValue(HSSFRow r) {
 		return getCellTextValue(r, SS.COLUMN_INDEX_MARKER, "marker");
 	}
-	
+
 	/**
 	 * @return <code>null</code> if cell is missing, empty or blank
 	 */
@@ -367,7 +358,7 @@
 		if(cell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
 			return cell.getRichStringCellValue().getString();
 		}
-		
+
 		throw new RuntimeException("Bad cell type for '" + columnName + "' column: ("
 				+ cell.getCellType() + ") row (" + (r.getRowNum() +1) + ")");
 	}



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