瀏覽代碼

Bug 58326 - Forbidden APIs patches - first set of changes for locale and timezone settings

also includes fixes for
- name shadowing 
- unused deprecated method "getClipRect" in classes extending Graphics2d
- HexDump - replaced intermediate String.format calls with custom padding
- convert testcases to junit4
- closing resources

also tested with an arbitary timezone (PST) and locale (ru)

supresses forbidden apis check for
- LocaleUtil (the only place where Locale.getDefault() and TimeZone.getDefault() should be called)
- Classes using FontMetrics - without the actual text it's difficult to return something sane

Some usage of UTC and Locale.ROOT might be still wrong, e.g. in MapiMessage we don't access the
extended mapi properties, which might contain the timezone

DataFormatter has now a Observable property which need to be observed when custom formats are used
and the Locale changes

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1701688 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_3_13_FINAL
Andreas Beeker 8 年之前
父節點
當前提交
a3d2eb57ff
共有 100 個文件被更改,包括 3165 次插入2523 次删除
  1. 15
    13
      build.xml
  2. 2
    1
      src/java/org/apache/poi/hssf/eventusermodel/FormatTrackingHSSFListener.java
  3. 2
    2
      src/java/org/apache/poi/hssf/model/InternalWorkbook.java
  4. 1
    2
      src/java/org/apache/poi/hssf/usermodel/DVConstraint.java
  5. 3
    9
      src/java/org/apache/poi/hssf/usermodel/DummyGraphics2d.java
  6. 10
    14
      src/java/org/apache/poi/hssf/usermodel/EscherGraphics.java
  7. 2
    1
      src/java/org/apache/poi/hssf/usermodel/HSSFCell.java
  8. 2
    1
      src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java
  9. 17
    0
      src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java
  10. 3
    9
      src/java/org/apache/poi/ss/format/CellDateFormatter.java
  11. 4
    0
      src/java/org/apache/poi/ss/format/CellFormatPart.java
  12. 1
    1
      src/java/org/apache/poi/ss/format/CellGeneralFormatter.java
  13. 10
    6
      src/java/org/apache/poi/ss/format/CellNumberFormatter.java
  14. 6
    16
      src/java/org/apache/poi/ss/formula/atp/DateParser.java
  15. 4
    11
      src/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java
  16. 5
    8
      src/java/org/apache/poi/ss/formula/atp/YearFracCalculator.java
  17. 8
    8
      src/java/org/apache/poi/ss/formula/function/FunctionDataBuilder.java
  18. 2
    9
      src/java/org/apache/poi/ss/formula/functions/DateFunc.java
  19. 3
    10
      src/java/org/apache/poi/ss/formula/functions/Days360.java
  20. 1
    1
      src/java/org/apache/poi/ss/formula/functions/Dec2Hex.java
  21. 2
    7
      src/java/org/apache/poi/ss/formula/functions/EDate.java
  22. 7
    12
      src/java/org/apache/poi/ss/formula/functions/EOMonth.java
  23. 1
    1
      src/java/org/apache/poi/ss/formula/functions/TextFunction.java
  24. 7
    12
      src/java/org/apache/poi/ss/formula/functions/Today.java
  25. 9
    13
      src/java/org/apache/poi/ss/formula/functions/WeekNum.java
  26. 98
    31
      src/java/org/apache/poi/ss/usermodel/DataFormatter.java
  27. 10
    39
      src/java/org/apache/poi/ss/usermodel/DateUtil.java
  28. 6
    4
      src/java/org/apache/poi/ss/usermodel/ExcelStyleDateFormatter.java
  29. 5
    1
      src/java/org/apache/poi/util/FontMetricsDumper.java
  30. 39
    23
      src/java/org/apache/poi/util/HexDump.java
  31. 136
    0
      src/java/org/apache/poi/util/LocaleUtil.java
  32. 32
    0
      src/java/org/apache/poi/util/SuppressForbidden.java
  33. 6
    8
      src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PackagePropertiesPart.java
  34. 2
    1
      src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java
  35. 2
    2
      src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java
  36. 4
    2
      src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java
  37. 2
    1
      src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java
  38. 2
    1
      src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java
  39. 2
    1
      src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java
  40. 2
    1
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java
  41. 44
    21
      src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java
  42. 70
    77
      src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackageCoreProperties.java
  43. 41
    7
      src/ooxml/testcases/org/apache/poi/ss/format/TestCellFormatPart.java
  44. 4
    3
      src/ooxml/testcases/org/apache/poi/ss/usermodel/BaseTestXCell.java
  45. 7
    2
      src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFCell.java
  46. 139
    229
      src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestFormulaEvaluatorOnXSSF.java
  47. 29
    12
      src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestUnfixedBugs.java
  48. 434
    308
      src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java
  49. 21
    1
      src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java
  50. 25
    0
      src/resources/devtools/forbidden-signatures.txt
  51. 3
    3
      src/scratchpad/src/org/apache/poi/hmef/attribute/TNEFDateAttribute.java
  52. 2
    0
      src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java
  53. 3
    7
      src/scratchpad/src/org/apache/poi/hslf/util/SystemTimeUtils.java
  54. 2
    10
      src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java
  55. 3
    2
      src/scratchpad/src/org/apache/poi/hsmf/datatypes/MessageSubmissionChunk.java
  56. 2
    2
      src/scratchpad/src/org/apache/poi/hsmf/datatypes/PropertyValue.java
  57. 6
    5
      src/scratchpad/src/org/apache/poi/hsmf/dev/HSMFDump.java
  58. 13
    11
      src/scratchpad/src/org/apache/poi/hsmf/extractor/OutlookTextExtactor.java
  59. 6
    3
      src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java
  60. 5
    7
      src/scratchpad/src/org/apache/poi/hwpf/model/PlexOfField.java
  61. 3
    4
      src/scratchpad/src/org/apache/poi/hwpf/usermodel/DateAndTime.java
  62. 36
    9
      src/scratchpad/testcases/org/apache/poi/hslf/record/TestComment2000.java
  63. 28
    9
      src/scratchpad/testcases/org/apache/poi/hslf/record/TestComment2000Atom.java
  64. 19
    4
      src/scratchpad/testcases/org/apache/poi/hslf/util/TestSystemTimeUtils.java
  65. 23
    25
      src/scratchpad/testcases/org/apache/poi/hsmf/AllHSMFTests.java
  66. 56
    30
      src/scratchpad/testcases/org/apache/poi/hsmf/TestFixedSizedProperties.java
  67. 66
    46
      src/scratchpad/testcases/org/apache/poi/hsmf/extractor/TestOutlookTextExtractor.java
  68. 52
    78
      src/scratchpad/testcases/org/apache/poi/hsmf/parsers/TestPOIFSChunkParser.java
  69. 17
    24
      src/testcases/org/apache/poi/hpsf/basic/TestWrite.java
  70. 263
    260
      src/testcases/org/apache/poi/hpsf/basic/TestWriteWellKnown.java
  71. 186
    148
      src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java
  72. 12
    12
      src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
  73. 2
    4
      src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java
  74. 56
    30
      src/testcases/org/apache/poi/hssf/usermodel/TestFormulaEvaluatorBugs.java
  75. 68
    37
      src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java
  76. 41
    11
      src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDataFormatter.java
  77. 102
    110
      src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java
  78. 17
    9
      src/testcases/org/apache/poi/hssf/usermodel/TestReadWriteChart.java
  79. 34
    18
      src/testcases/org/apache/poi/hssf/usermodel/TestText.java
  80. 21
    23
      src/testcases/org/apache/poi/ss/format/CellFormatTestBase.java
  81. 108
    26
      src/testcases/org/apache/poi/ss/format/TestCellFormat.java
  82. 16
    17
      src/testcases/org/apache/poi/ss/formula/atp/TestDateParser.java
  83. 7
    24
      src/testcases/org/apache/poi/ss/formula/atp/TestNetworkdaysFunction.java
  84. 45
    32
      src/testcases/org/apache/poi/ss/formula/atp/TestWorkdayCalculator.java
  85. 97
    76
      src/testcases/org/apache/poi/ss/formula/atp/TestWorkdayFunction.java
  86. 7
    9
      src/testcases/org/apache/poi/ss/formula/atp/TestYearFracCalculator.java
  87. 28
    91
      src/testcases/org/apache/poi/ss/formula/atp/TestYearFracCalculatorFromSpreadsheet.java
  88. 130
    210
      src/testcases/org/apache/poi/ss/formula/eval/TestFormulasFromSpreadsheet.java
  89. 4
    4
      src/testcases/org/apache/poi/ss/formula/functions/TestDays360.java
  90. 24
    14
      src/testcases/org/apache/poi/ss/formula/functions/TestEDate.java
  91. 58
    42
      src/testcases/org/apache/poi/ss/formula/functions/TestEOMonth.java
  92. 54
    38
      src/testcases/org/apache/poi/ss/formula/functions/TestText.java
  93. 9
    7
      src/testcases/org/apache/poi/ss/formula/functions/TestTime.java
  94. 44
    13
      src/testcases/org/apache/poi/ss/usermodel/BaseTestCell.java
  95. 42
    11
      src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetAutosizeColumn.java
  96. 36
    9
      src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java
  97. 18
    15
      src/testcases/org/apache/poi/ss/usermodel/TestDateUtil.java
  98. 1
    1
      src/testcases/org/apache/poi/ss/util/TestDateFormatConverter.java
  99. 1
    1
      src/testcases/org/apache/poi/util/TestHexDump.java
  100. 0
    0
      src/testcases/org/apache/poi/util/TestStringUtil.java

+ 15
- 13
build.xml 查看文件

@@ -1105,6 +1105,7 @@ under the License.
failureproperty="ooxml.test.failed">
<classpath refid="@{classpath}"/>
<syspropertyset refid="junit.properties"/>
<jvmarg value="-Xmx768M"/>
<jvmarg value="-ea"/>
<formatter type="plain"/>
<formatter type="xml"/>
@@ -1126,6 +1127,7 @@ under the License.
<path refid="ooxml.xmlsec.classpath"/>
</classpath>
<syspropertyset refid="junit.properties"/>
<jvmarg value="-Xmx768M"/>
<jvmarg value="-ea"/>
<formatter type="plain"/>
<formatter type="xml"/>
@@ -1715,6 +1717,7 @@ under the License.
<exclude name="resources/ooxml/org/apache/poi/xslf/usermodel/empty.pptx" />
<exclude name="resources/main/org/apache/poi/sl/draw/geom/presetShapeDefinitions.xml" />
<exclude name="examples/src/org/apache/poi/xslf/usermodel/pie-chart-data.txt" />
<exclude name="**/*.iml" />
</fileset>
</rat:report>

@@ -1733,23 +1736,22 @@ under the License.
<taskdef name="forbiddenapis"
classname="de.thetaphi.forbiddenapis.AntTask"
classpath="${forbidden.jar}"/>
<antcall target="-do-forbidden-apis-check">
<param name="dir" value="${main.output.dir}"/>
</antcall>
<antcall target="-do-forbidden-apis-check">
<param name="dir" value="${scratchpad.output.dir}"/>
</antcall>
<antcall target="-do-forbidden-apis-check">
<param name="dir" value="${ooxml.output.dir}"/>
</antcall>
</target>
<target name="-do-forbidden-apis-check">
<forbiddenapis
internalRuntimeForbidden="true"
classpathref="javadoc.classpath"
dir="${dir}">
classpathref="javadoc.classpath"
suppressAnnotation="org.apache.poi.util.SuppressForbidden"
>
<bundledsignatures name="jdk-unsafe-${jdk.version.source}"/>
<bundledsignatures name="jdk-deprecated-${jdk.version.source}"/>
<signaturesFileset file="src/resources/devtools/forbidden-signatures.txt"/>
<fileset dir="${main.output.dir}"/>
<fileset dir="${scratchpad.output.dir}"/>
<fileset dir="${ooxml.output.dir}"/>
<!--
<fileset dir="${main.output.test.dir}"/>
<fileset dir="${scratchpad.output.test.dir}"/>
<fileset dir="${ooxml.output.test.dir}"/>
-->
</forbiddenapis>
</target>


+ 2
- 1
src/java/org/apache/poi/hssf/eventusermodel/FormatTrackingHSSFListener.java 查看文件

@@ -31,6 +31,7 @@ import org.apache.poi.hssf.record.NumberRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;

@@ -52,7 +53,7 @@ public class FormatTrackingHSSFListener implements HSSFListener {
* the {@link Locale#getDefault() default locale} for the formats.
*/
public FormatTrackingHSSFListener(HSSFListener childListener) {
this(childListener, Locale.getDefault());
this(childListener, LocaleUtil.getUserLocale());
}

/**

+ 2
- 2
src/java/org/apache/poi/hssf/model/InternalWorkbook.java 查看文件

@@ -22,7 +22,6 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;

@@ -96,6 +95,7 @@ import org.apache.poi.ss.formula.udf.UDFFinder;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;

@@ -1774,7 +1774,7 @@ public final class InternalWorkbook {
retval.setDefaultCountry(( short ) 1);

// from Russia with love ;)
if ( Locale.getDefault().toString().equals( "ru_RU" ) ) {
if ( LocaleUtil.getUserLocale().toString().equals( "ru_RU" ) ) {
retval.setCurrentCountry(( short ) 7);
}
else {

+ 1
- 2
src/java/org/apache/poi/hssf/usermodel/DVConstraint.java 查看文件

@@ -17,7 +17,6 @@

package org.apache.poi.hssf.usermodel;

import java.text.MessageFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -463,7 +462,7 @@ public class DVConstraint implements DataValidationConstraint {
case ValidationType.FORMULA:
return createCustomFormulaConstraint(toFormulaString(dvRecord.getFormula1(), book).string());
default:
throw new UnsupportedOperationException(MessageFormat.format("validationType={0}", dvRecord.getDataType()));
throw new UnsupportedOperationException("validationType="+dvRecord.getDataType());
}
}


+ 3
- 9
src/java/org/apache/poi/hssf/usermodel/DummyGraphics2d.java 查看文件

@@ -34,13 +34,13 @@ import java.util.Map;
public class DummyGraphics2d
extends Graphics2D
{
BufferedImage img;
private BufferedImage bufimg;
private Graphics2D g2D;
public DummyGraphics2d()
{
img = new BufferedImage(1000, 1000, 2);
g2D = (Graphics2D)img.getGraphics();
bufimg = new BufferedImage(1000, 1000, 2);
g2D = (Graphics2D)bufimg.getGraphics();
}
public void addRenderingHints(Map<?,?> hints)
@@ -710,12 +710,6 @@ public class DummyGraphics2d
return g2D.getClipBounds( r );
}
@SuppressWarnings("deprecation")
public Rectangle getClipRect() {
System.out.println( "getClipRect():" );
return g2D.getClipRect();
}
public Color getColor()
{
System.out.println( "getColor():" );

+ 10
- 14
src/java/org/apache/poi/hssf/usermodel/EscherGraphics.java 查看文件

@@ -20,6 +20,7 @@ package org.apache.poi.hssf.usermodel;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.SuppressForbidden;

import java.awt.*;
import java.awt.image.ImageObserver;
@@ -57,8 +58,7 @@ import java.text.AttributedCharacterIterator;
* <code>HSSFClientAnchor.getAnchorHeightInPoints()</code>.
* </blockquote>
*/
public class EscherGraphics
extends Graphics
public class EscherGraphics extends Graphics
{
private HSSFShapeGroup escherGroup;
private HSSFWorkbook workbook;
@@ -293,18 +293,18 @@ public class EscherGraphics
textbox.setString( s );
}

private HSSFFont matchFont( Font font )
private HSSFFont matchFont( Font matchFont )
{
HSSFColor hssfColor = workbook.getCustomPalette()
.findColor((byte)foreground.getRed(), (byte)foreground.getGreen(), (byte)foreground.getBlue());
if (hssfColor == null)
hssfColor = workbook.getCustomPalette().findSimilarColor((byte)foreground.getRed(), (byte)foreground.getGreen(), (byte)foreground.getBlue());
boolean bold = (font.getStyle() & Font.BOLD) != 0;
boolean italic = (font.getStyle() & Font.ITALIC) != 0;
boolean bold = (matchFont.getStyle() & Font.BOLD) != 0;
boolean italic = (matchFont.getStyle() & Font.ITALIC) != 0;
HSSFFont hssfFont = workbook.findFont(bold ? HSSFFont.BOLDWEIGHT_BOLD : 0,
hssfColor.getIndex(),
(short)(font.getSize() * 20),
font.getName(),
(short)(matchFont.getSize() * 20),
matchFont.getName(),
italic,
false,
(short)0,
@@ -314,8 +314,8 @@ public class EscherGraphics
hssfFont = workbook.createFont();
hssfFont.setBoldweight(bold ? HSSFFont.BOLDWEIGHT_BOLD : 0);
hssfFont.setColor(hssfColor.getIndex());
hssfFont.setFontHeight((short)(font.getSize() * 20));
hssfFont.setFontName(font.getName());
hssfFont.setFontHeight((short)(matchFont.getSize() * 20));
hssfFont.setFontName(matchFont.getName());
hssfFont.setItalic(italic);
hssfFont.setStrikeout(false);
hssfFont.setTypeOffset((short) 0);
@@ -431,11 +431,6 @@ public class EscherGraphics
return null;
}

public Rectangle getClipRect()
{
return getClipBounds();
}

public Color getColor()
{
return foreground;
@@ -447,6 +442,7 @@ public class EscherGraphics
}

@SuppressWarnings("deprecation")
@SuppressForbidden
public FontMetrics getFontMetrics(Font f)
{
return Toolkit.getDefaultToolkit().getFontMetrics(f);

+ 2
- 1
src/java/org/apache/poi/hssf/usermodel/HSSFCell.java 查看文件

@@ -52,6 +52,7 @@ import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.ss.util.NumberToTextConverter;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;

@@ -989,7 +990,7 @@ public class HSSFCell implements Cell {
case CELL_TYPE_NUMERIC:
//TODO apply the dataformat for this cell
if (HSSFDateUtil.isCellDateFormatted(this)) {
DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", LocaleUtil.getUserLocale());
return sdf.format(getDateCellValue());
}
return String.valueOf(getNumericCellValue());

+ 2
- 1
src/java/org/apache/poi/hssf/usermodel/HSSFDataFormatter.java 查看文件

@@ -23,6 +23,7 @@ import java.text.SimpleDateFormat;
import java.util.Locale;

import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.util.LocaleUtil;

/**
* HSSFDataFormatter contains methods for formatting the value stored in an
@@ -76,7 +77,7 @@ public final class HSSFDataFormatter extends DataFormatter {
* Creates a formatter using the {@link Locale#getDefault() default locale}.
*/
public HSSFDataFormatter() {
this(Locale.getDefault());
this(LocaleUtil.getUserLocale());
}

}

+ 17
- 0
src/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java 查看文件

@@ -19,6 +19,7 @@

package org.apache.poi.poifs.filesystem;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

@@ -85,6 +86,22 @@ public class POIFSFileSystem
super(stream);
}

/**
* <p>Creates a POIFSFileSystem from a <tt>File</tt>. This uses less memory than
* creating from an <tt>InputStream</tt>. The File will be opened read-only</p>
*
* <p>Note that with this constructor, you will need to call {@link #close()}
* when you're done to have the underlying file closed, as the file is
* kept open during normal operation to read the data out.</p>
*
* @param file the File from which to read the data
*
* @exception IOException on errors reading, or on invalid data
*/
public POIFSFileSystem(File file) throws IOException {
super(file);
}
/**
* Checks that the supplied InputStream (which MUST
* support mark and reset, or be a PushbackInputStream)

+ 3
- 9
src/java/org/apache/poi/ss/format/CellDateFormatter.java 查看文件

@@ -24,19 +24,14 @@ import java.util.Calendar;
import java.util.Date;
import java.util.Formatter;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;

import org.apache.poi.util.LocaleUtil;

/**
* Formats a date value.
*/
public class CellDateFormatter extends CellFormatter {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
private boolean amPmUpper;
private boolean showM;
private boolean showAmPm;
@@ -50,8 +45,7 @@ public class CellDateFormatter extends CellFormatter {
"mm/d/y");

static {
Calendar c = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT);
c.set(1904, 0, 1, 0, 0, 0);
Calendar c = LocaleUtil.getLocaleCalendar(1904, 0, 1, 0, 0, 0);
EXCEL_EPOCH_DATE = c.getTime();
EXCEL_EPOCH_TIME = c.getTimeInMillis();
}

+ 4
- 0
src/java/org/apache/poi/ss/format/CellFormatPart.java 查看文件

@@ -524,4 +524,8 @@ public class CellFormatPart {
String str = m.group(g);
return (str == null ? "" : str);
}

public String toString() {
return format.format;
}
}

+ 1
- 1
src/java/org/apache/poi/ss/format/CellGeneralFormatter.java 查看文件

@@ -57,7 +57,7 @@ public class CellGeneralFormatter extends CellFormatter {
stripZeros = false;
}

Formatter formatter = new Formatter(toAppendTo);
Formatter formatter = new Formatter(toAppendTo, LOCALE);
try {
formatter.format(LOCALE, fmt, value);
} finally {

+ 10
- 6
src/java/org/apache/poi/ss/format/CellNumberFormatter.java 查看文件

@@ -17,6 +17,7 @@
package org.apache.poi.ss.format;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.FieldPosition;
import java.util.BitSet;
import java.util.Collections;
@@ -30,6 +31,7 @@ import java.util.TreeSet;
import java.util.regex.Matcher;

import org.apache.poi.ss.format.CellFormatPart.PartHandler;
import org.apache.poi.util.LocaleUtil;

/**
* This class implements printing out a value using a number format.
@@ -182,8 +184,8 @@ public class CellNumberFormatter extends CellFormatter {
private char insertSignForExponent;

public String handlePart(Matcher m, String part, CellFormatType type,
StringBuffer desc) {
int pos = desc.length();
StringBuffer descBuf) {
int pos = descBuf.length();
char firstCh = part.charAt(0);
switch (firstCh) {
case 'e':
@@ -203,7 +205,7 @@ public class CellNumberFormatter extends CellFormatter {
case '#':
if (insertSignForExponent != '\0') {
specials.add(new Special(insertSignForExponent, pos));
desc.append(insertSignForExponent);
descBuf.append(insertSignForExponent);
insertSignForExponent = '\0';
pos++;
}
@@ -354,7 +356,8 @@ public class CellNumberFormatter extends CellFormatter {
fmtBuf.append('E');
placeZeros(fmtBuf, exponentSpecials.subList(2,
exponentSpecials.size()));
decimalFmt = new DecimalFormat(fmtBuf.toString());
DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(LocaleUtil.getUserLocale());
decimalFmt = new DecimalFormat(fmtBuf.toString(), dfs);
}

if (exponent != null)
@@ -594,7 +597,7 @@ public class CellNumberFormatter extends CellFormatter {
writeFraction(value, null, fractional, output, mods);
} else {
StringBuffer result = new StringBuffer();
Formatter f = new Formatter(result);
Formatter f = new Formatter(result, LOCALE);
try {
f.format(LOCALE, printfFmt, value);
} finally {
@@ -767,6 +770,7 @@ public class CellNumberFormatter extends CellFormatter {
writeInteger(exponentNum, output, exponentDigitSpecials, mods, false);
}

@SuppressWarnings("unchecked")
private void writeFraction(double value, StringBuffer result,
double fractional, StringBuffer output, Set<StringMod> mods) {

@@ -869,7 +873,7 @@ public class CellNumberFormatter extends CellFormatter {
List<Special> numSpecials, Set<StringMod> mods) {

StringBuffer sb = new StringBuffer();
Formatter formatter = new Formatter(sb);
Formatter formatter = new Formatter(sb, LOCALE);
try {
formatter.format(LOCALE, fmt, num);
} finally {

+ 6
- 16
src/java/org/apache/poi/ss/formula/atp/DateParser.java 查看文件

@@ -18,24 +18,16 @@
package org.apache.poi.ss.formula.atp;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Pattern;

import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.util.LocaleUtil;

/**
* Parser for java dates.
*/
public class DateParser {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");

public DateParser instance = new DateParser();

private DateParser() {
@@ -80,10 +72,10 @@ public class DateParser {
return makeDate(f0, f1, f2);
}
// otherwise the format seems to depend on OS settings (default date format)
if (false) {
// MM/DD/YYYY is probably a good guess, if the in the US
return makeDate(f2, f0, f1);
}
// if (false) {
// // MM/DD/YYYY is probably a good guess, if the in the US
// return makeDate(f2, f0, f1);
// }
// TODO - find a way to choose the correct date format
throw new RuntimeException("Unable to determine date format for text '" + strVal + "'");
}
@@ -95,9 +87,7 @@ public class DateParser {
if (month < 1 || month > 12) {
throw new EvaluationException(ErrorEval.VALUE_INVALID);
}
Calendar cal = new GregorianCalendar(DEFAULT_TIMEZONE, Locale.ROOT);
cal.set(year, month - 1, 1, 0, 0, 0);
cal.set(Calendar.MILLISECOND, 0);
Calendar cal = LocaleUtil.getLocaleCalendar(year, month - 1, 1, 0, 0, 0);
if (day < 1 || day > cal.getActualMaximum(Calendar.DAY_OF_MONTH)) {
throw new EvaluationException(ErrorEval.VALUE_INVALID);
}

+ 4
- 11
src/java/org/apache/poi/ss/formula/atp/WorkdayCalculator.java 查看文件

@@ -19,21 +19,14 @@ package org.apache.poi.ss.formula.atp;

import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;

/**
* A calculator for workdays, considering dates as excel representations.
*/
public class WorkdayCalculator {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");

public static final WorkdayCalculator instance = new WorkdayCalculator();

/**
@@ -69,7 +62,7 @@ public class WorkdayCalculator {
public Date calculateWorkdays(double start, int workdays, double[] holidays) {
Date startDate = DateUtil.getJavaDate(start);
int direction = workdays < 0 ? -1 : 1;
Calendar endDate = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT);
Calendar endDate = LocaleUtil.getLocaleCalendar();
endDate.setTime(startDate);
double excelEndDate = DateUtil.getExcelDate(endDate.getTime());
while (workdays != 0) {
@@ -97,7 +90,7 @@ public class WorkdayCalculator {
int startDay = (int) Math.floor(start < end ? start : end);
int endDay = (int) Math.floor(end > start ? end : start);
for (; startDay <= endDay; startDay++) {
Calendar today = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT);
Calendar today = LocaleUtil.getLocaleCalendar();
today.setTime(DateUtil.getJavaDate(startDay));
if (today.get(Calendar.DAY_OF_WEEK) == dayOfWeek) {
pastDaysOfWeek++;
@@ -133,7 +126,7 @@ public class WorkdayCalculator {
* @return <code>true</code> if date is weekend, <code>false</code> otherwise.
*/
protected boolean isWeekend(double aDate) {
Calendar date = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT);
Calendar date = LocaleUtil.getLocaleCalendar();
date.setTime(DateUtil.getJavaDate(aDate));
return date.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || date.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY;
}

+ 5
- 8
src/java/org/apache/poi/ss/formula/atp/YearFracCalculator.java 查看文件

@@ -18,13 +18,11 @@
package org.apache.poi.ss.formula.atp;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;


/**
@@ -35,8 +33,6 @@ import org.apache.poi.ss.usermodel.DateUtil;
* @author Josh Micich
*/
final class YearFracCalculator {
/** use UTC time-zone to avoid daylight savings issues */
private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("UTC");
private static final int MS_PER_HOUR = 60 * 60 * 1000;
private static final int MS_PER_DAY = 24 * MS_PER_HOUR;
private static final int DAYS_PER_NORMAL_YEAR = 365;
@@ -317,9 +313,10 @@ final class YearFracCalculator {
}

private static SimpleDate createDate(int dayCount) {
GregorianCalendar calendar = new GregorianCalendar(UTC_TIME_ZONE, Locale.ROOT);
DateUtil.setCalendar(calendar, dayCount, 0, false, false);
return new SimpleDate(calendar);
/** use UTC time-zone to avoid daylight savings issues */
Calendar cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
DateUtil.setCalendar(cal, dayCount, 0, false, false);
return new SimpleDate(cal);
}

private static final class SimpleDate {

+ 8
- 8
src/java/org/apache/poi/ss/formula/function/FunctionDataBuilder.java 查看文件

@@ -30,16 +30,16 @@ import java.util.Set;
*/
final class FunctionDataBuilder {
private int _maxFunctionIndex;
private final Map _functionDataByName;
private final Map _functionDataByIndex;
private final Map<String,FunctionMetadata> _functionDataByName;
private final Map<Integer,FunctionMetadata> _functionDataByIndex;
/** stores indexes of all functions with footnotes (i.e. whose definitions might change) */
private final Set _mutatingFunctionIndexes;
private final Set<Integer> _mutatingFunctionIndexes;

public FunctionDataBuilder(int sizeEstimate) {
_maxFunctionIndex = -1;
_functionDataByName = new HashMap(sizeEstimate * 3 / 2);
_functionDataByIndex = new HashMap(sizeEstimate * 3 / 2);
_mutatingFunctionIndexes = new HashSet();
_functionDataByName = new HashMap<String,FunctionMetadata>(sizeEstimate * 3 / 2);
_functionDataByIndex = new HashMap<Integer,FunctionMetadata>(sizeEstimate * 3 / 2);
_mutatingFunctionIndexes = new HashSet<Integer>();
}

public void add(int functionIndex, String functionName, int minParams, int maxParams,
@@ -55,14 +55,14 @@ final class FunctionDataBuilder {
}
// allow function definitions to change only if both previous and the new items have footnotes
FunctionMetadata prevFM;
prevFM = (FunctionMetadata) _functionDataByName.get(functionName);
prevFM = _functionDataByName.get(functionName);
if(prevFM != null) {
if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) {
throw new RuntimeException("Multiple entries for function name '" + functionName + "'");
}
_functionDataByIndex.remove(Integer.valueOf(prevFM.getIndex()));
}
prevFM = (FunctionMetadata) _functionDataByIndex.get(indexKey);
prevFM = _functionDataByIndex.get(indexKey);
if(prevFM != null) {
if(!hasFootnote || !_mutatingFunctionIndexes.contains(indexKey)) {
throw new RuntimeException("Multiple entries for function index (" + functionIndex + ")");

+ 2
- 9
src/java/org/apache/poi/ss/formula/functions/DateFunc.java 查看文件

@@ -27,18 +27,13 @@ import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;


/**
* Implementation for the Excel function DATE
*/
public final class DateFunc extends Fixed3ArgFunction {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");

public static final Function instance = new DateFunc();

private DateFunc() {
@@ -91,9 +86,7 @@ public final class DateFunc extends Fixed3ArgFunction {
}

// Turn this into a Java date
Calendar c = new GregorianCalendar(DEFAULT_TIMEZONE, Locale.ROOT);
c.set(year, month, day, 0, 0, 0);
c.set(Calendar.MILLISECOND, 0);
Calendar c = LocaleUtil.getLocaleCalendar(year, month, day);
// Handle negative days of the week, that pull us across
// the 29th of Feb 1900

+ 3
- 10
src/java/org/apache/poi/ss/formula/functions/Days360.java 查看文件

@@ -17,14 +17,13 @@
package org.apache.poi.ss.formula.functions;

import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.OperandResolver;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;

/**
* <p>Calculates the number of days between two dates based on a 360-day year
@@ -67,12 +66,6 @@ import org.apache.poi.ss.usermodel.DateUtil;
* @see <a href="https://support.microsoft.com/en-us/kb/235575">DAYS360 Function Produces Different Values Depending on the Version of Excel</a>
*/
public class Days360 extends Var2or3ArgFunction {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");

public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
double result;
try {
@@ -112,8 +105,8 @@ public class Days360 extends Var2or3ArgFunction {
}

private static Calendar getDate(double date) {
Calendar processedDate = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT);
processedDate.setTime(DateUtil.getJavaDate(date, false, DEFAULT_TIMEZONE));
Calendar processedDate = LocaleUtil.getLocaleCalendar();
processedDate.setTime(DateUtil.getJavaDate(date, false));
return processedDate;
}


+ 1
- 1
src/java/org/apache/poi/ss/formula/functions/Dec2Hex.java 查看文件

@@ -109,7 +109,7 @@ public final class Dec2Hex extends Var1or2ArgFunction implements FreeRefFunction
String hex;
if (placesNumber != 0) {
hex = String.format("%0"+placesNumber+"X", number1.intValue(), Locale.ROOT);
hex = String.format(Locale.ROOT, "%0"+placesNumber+"X", number1.intValue());
}
else {
hex = Integer.toHexString(number1.intValue());

+ 2
- 7
src/java/org/apache/poi/ss/formula/functions/EDate.java 查看文件

@@ -30,17 +30,12 @@ import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.RefEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;

/**
* Implementation for Excel EDATE () function.
*/
public class EDate implements FreeRefFunction {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");

public static final FreeRefFunction instance = new EDate();

public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
@@ -52,7 +47,7 @@ public class EDate implements FreeRefFunction {
int offsetInMonthAsNumber = (int) getValue(args[1]);

Date startDate = DateUtil.getJavaDate(startDateAsNumber);
Calendar calendar = Calendar.getInstance(DEFAULT_TIMEZONE, Locale.ROOT);
Calendar calendar = LocaleUtil.getLocaleCalendar();
calendar.setTime(startDate);
calendar.add(Calendar.MONTH, offsetInMonthAsNumber);
return new NumberEval(DateUtil.getExcelDate(calendar.getTime()));

+ 7
- 12
src/java/org/apache/poi/ss/formula/functions/EOMonth.java 查看文件

@@ -19,9 +19,6 @@ package org.apache.poi.ss.formula.functions;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.poi.ss.formula.OperationEvaluationContext;
import org.apache.poi.ss.formula.eval.ErrorEval;
@@ -29,6 +26,7 @@ import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
/**
* Implementation for the Excel EOMONTH() function.<p/>
@@ -45,12 +43,6 @@ import org.apache.poi.ss.usermodel.DateUtil;
* zero or negative (in the past).
*/
public class EOMonth implements FreeRefFunction {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
public static final FreeRefFunction instance = new EOMonth();
@Override
@@ -70,10 +62,13 @@ public class EOMonth implements FreeRefFunction {
Date startDate = DateUtil.getJavaDate(startDateAsNumber, false);
Calendar cal = new GregorianCalendar(DEFAULT_TIMEZONE, Locale.ROOT);
Calendar cal = LocaleUtil.getLocaleCalendar();
cal.setTime(startDate);
cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.clear(Calendar.HOUR);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);
cal.add(Calendar.MONTH, months + 1);
cal.set(Calendar.DAY_OF_MONTH, 1);

+ 1
- 1
src/java/org/apache/poi/ss/formula/functions/TextFunction.java 查看文件

@@ -36,7 +36,7 @@ import org.apache.poi.ss.usermodel.DataFormatter;
*/
public abstract class TextFunction implements Function {
protected static final DataFormatter formatter = new DataFormatter();
protected static final String EMPTY_STRING = "";
protected static final String EMPTY_STRING = "";

protected static final String evaluateStringArg(ValueEval eval, int srcRow, int srcCol) throws EvaluationException {
ValueEval ve = OperandResolver.getSingleValue(eval, srcRow, srcCol);

+ 7
- 12
src/java/org/apache/poi/ss/formula/functions/Today.java 查看文件

@@ -18,28 +18,23 @@
package org.apache.poi.ss.formula.functions;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;

/**
* Implementation of Excel TODAY() Function<br/>
*/
public final class Today extends Fixed0ArgFunction {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");

public ValueEval evaluate(int srcRowIndex, int srcColumnIndex) {
Calendar now = new GregorianCalendar(DEFAULT_TIMEZONE, Locale.ROOT);
now.set(now.get(Calendar.YEAR), now.get(Calendar.MONTH), now.get(Calendar.DATE),0,0,0);
now.set(Calendar.MILLISECOND, 0);
Calendar now = LocaleUtil.getLocaleCalendar();
now.clear(Calendar.HOUR);
now.set(Calendar.HOUR_OF_DAY,0);
now.clear(Calendar.MINUTE);
now.clear(Calendar.SECOND);
now.clear(Calendar.MILLISECOND);
return new NumberEval(DateUtil.getExcelDate(now.getTime()));
}
}

+ 9
- 13
src/java/org/apache/poi/ss/formula/functions/WeekNum.java 查看文件

@@ -17,14 +17,16 @@
package org.apache.poi.ss.formula.functions;
import java.util.Calendar;
import org.apache.poi.ss.formula.OperationEvaluationContext;
import org.apache.poi.ss.formula.eval.*;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.OperandResolver;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import org.apache.poi.util.LocaleUtil;
/**
* Implementation for Excel WeekNum() function.<p/>
@@ -42,12 +44,6 @@ import java.util.TimeZone;
* 2 Week begins on Monday. Weekdays are numbered 1 through 7.
*/
public class WeekNum extends Fixed2ArgFunction implements FreeRefFunction {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getTimeZone("UTC");
public static final FreeRefFunction instance = new WeekNum();
public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval serialNumVE, ValueEval returnTypeVE) {
@@ -57,7 +53,7 @@ public class WeekNum extends Fixed2ArgFunction implements FreeRefFunction {
} catch (EvaluationException e) {
return ErrorEval.VALUE_INVALID;
}
Calendar serialNumCalendar = new GregorianCalendar(DEFAULT_TIMEZONE, Locale.ROOT);
Calendar serialNumCalendar = LocaleUtil.getLocaleCalendar();
serialNumCalendar.setTime(DateUtil.getJavaDate(serialNum, false));
int returnType = 0;

+ 98
- 31
src/java/org/apache/poi/ss/usermodel/DataFormatter.java 查看文件

@@ -36,10 +36,13 @@ import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.poi.ss.util.NumberToTextConverter;
import org.apache.poi.util.LocaleUtil;


/**
@@ -100,7 +103,7 @@ import org.apache.poi.ss.util.NumberToTextConverter;
* Excel will output "", <code>DataFormatter</code> will output "0".
* </ul>
*/
public class DataFormatter {
public class DataFormatter implements Observer {
private static final String defaultFractionWholePartFormat = "#";
private static final String defaultFractionFractionPartFormat = "#/##";
/** Pattern to find a number format: "0" or "#" */
@@ -153,18 +156,18 @@ public class DataFormatter {
/**
* The decimal symbols of the locale used for formatting values.
*/
private final DecimalFormatSymbols decimalSymbols;
private DecimalFormatSymbols decimalSymbols;

/**
* The date symbols of the locale used for formatting values.
*/
private final DateFormatSymbols dateSymbols;
private DateFormatSymbols dateSymbols;

/** <em>General</em> format for whole numbers. */
private final Format generalWholeNumFormat;
private Format generalWholeNumFormat;

/** <em>General</em> format for decimal numbers. */
private final Format generalDecimalNumFormat;
private Format generalDecimalNumFormat;

/** A default format to use when a number pattern cannot be parsed. */
private Format defaultNumFormat;
@@ -173,15 +176,37 @@ public class DataFormatter {
* A map to cache formats.
* Map<String,Format> formats
*/
private final Map<String,Format> formats;
private final Map<String,Format> formats = new HashMap<String,Format>();

private boolean emulateCsv = false;

/** stores the locale valid it the last formatting call */
private Locale locale;
/** stores if the locale should change according to {@link LocaleUtil#getUserLocale()} */
private boolean localeIsAdapting = true;
private class LocaleChangeObservable extends Observable {
void checkForLocaleChange() {
checkForLocaleChange(LocaleUtil.getUserLocale());
}
void checkForLocaleChange(Locale newLocale) {
if (!localeIsAdapting) return;
if (newLocale.equals(locale)) return;
super.setChanged();
notifyObservers(newLocale);
}
}
/** the Observable to notify, when the locale has been changed */
private final LocaleChangeObservable localeChangedObervable = new LocaleChangeObservable();
/**
* Creates a formatter using the {@link Locale#getDefault() default locale}.
*/
public DataFormatter() {
this(false);
this.localeIsAdapting = true;
}

/**
@@ -190,8 +215,8 @@ public class DataFormatter {
* @param emulateCsv whether to emulate CSV output.
*/
public DataFormatter(boolean emulateCsv) {
this(Locale.getDefault());
this.emulateCsv = emulateCsv;
this(LocaleUtil.getUserLocale(), emulateCsv);
this.localeIsAdapting = true;
}

/**
@@ -208,29 +233,9 @@ public class DataFormatter {
* Creates a formatter using the given locale.
*/
public DataFormatter(Locale locale) {
dateSymbols = new DateFormatSymbols(locale);
decimalSymbols = new DecimalFormatSymbols(locale);
generalWholeNumFormat = new DecimalFormat("#", decimalSymbols);
generalDecimalNumFormat = new DecimalFormat("#.##########", decimalSymbols);

formats = new HashMap<String,Format>();

// init built-in formats

Format zipFormat = ZipPlusFourFormat.instance;
addFormat("00000\\-0000", zipFormat);
addFormat("00000-0000", zipFormat);

Format phoneFormat = PhoneFormat.instance;
// allow for format string variations
addFormat("[<=9999999]###\\-####;\\(###\\)\\ ###\\-####", phoneFormat);
addFormat("[<=9999999]###-####;(###) ###-####", phoneFormat);
addFormat("###\\-####;\\(###\\)\\ ###\\-####", phoneFormat);
addFormat("###-####;(###) ###-####", phoneFormat);

Format ssnFormat = SSNFormat.instance;
addFormat("000\\-00\\-0000", ssnFormat);
addFormat("000-00-0000", ssnFormat);
localeChangedObervable.addObserver(this);
localeChangedObervable.checkForLocaleChange(locale);
this.localeIsAdapting = false;
}

/**
@@ -260,6 +265,8 @@ public class DataFormatter {
}

private Format getFormat(double cellValue, int formatIndex, String formatStrIn) {
localeChangedObervable.checkForLocaleChange();
// // Might be better to separate out the n p and z formats, falling back to p when n and z are not set.
// // That however would require other code to be re factored.
// String[] formatBits = formatStrIn.split(";");
@@ -329,6 +336,8 @@ public class DataFormatter {
}

private Format createFormat(double cellValue, int formatIndex, String sFormat) {
localeChangedObervable.checkForLocaleChange();
String formatStr = sFormat;
// Remove colour formatting if present
@@ -666,6 +675,8 @@ public class DataFormatter {
return getDefaultFormat(cell.getNumericCellValue());
}
private Format getDefaultFormat(double cellValue) {
localeChangedObervable.checkForLocaleChange();
// for numeric cells try user supplied default
if (defaultNumFormat != null) {
return defaultNumFormat;
@@ -742,6 +753,8 @@ public class DataFormatter {
* @see #formatCellValue(Cell)
*/
public String formatRawCellContents(double value, int formatIndex, String formatString, boolean use1904Windowing) {
localeChangedObervable.checkForLocaleChange();
// Is it a date?
if(DateUtil.isADateFormat(formatIndex,formatString)) {
if(DateUtil.isValidExcelDate(value)) {
@@ -820,6 +833,7 @@ public class DataFormatter {
* @return a string value of the cell
*/
public String formatCellValue(Cell cell, FormulaEvaluator evaluator) {
localeChangedObervable.checkForLocaleChange();
if (cell == null) {
return "";
@@ -927,6 +941,59 @@ public class DataFormatter {
format.setRoundingMode(roundingMode);
}

/**
* If the Locale has been changed via {@link LocaleUtil#setUserLocale(Locale)} the stored
* formats need to be refreshed. All formats which aren't originated from DataFormatter
* itself, i.e. all Formats added via {@link DataFormatter#addFormat(String, Format)} and
* {@link DataFormatter#setDefaultNumberFormat(Format)}, need to be added again.
* To notify callers, the returned {@link Observable} should be used.
* The Object in {@link Observer#update(Observable, Object)} is the new Locale.
*
* @return the listener object, where callers can register themself
*/
public Observable getLocaleChangedObservable() {
return localeChangedObervable;
}

/**
* Update formats when locale has been changed
*
* @param observable usually this is our own Observable instance
* @param localeObj only reacts on Locale objects
*/
public void update(Observable observable, Object localeObj) {
if (!(localeObj instanceof Locale)) return;
Locale newLocale = (Locale)localeObj;
if (!localeIsAdapting || newLocale.equals(locale)) return;
locale = newLocale;
dateSymbols = DateFormatSymbols.getInstance(locale);
decimalSymbols = DecimalFormatSymbols.getInstance(locale);
generalWholeNumFormat = new DecimalFormat("#", decimalSymbols);
generalDecimalNumFormat = new DecimalFormat("#.##########", decimalSymbols);

// init built-in formats

formats.clear();
Format zipFormat = ZipPlusFourFormat.instance;
addFormat("00000\\-0000", zipFormat);
addFormat("00000-0000", zipFormat);

Format phoneFormat = PhoneFormat.instance;
// allow for format string variations
addFormat("[<=9999999]###\\-####;\\(###\\)\\ ###\\-####", phoneFormat);
addFormat("[<=9999999]###-####;(###) ###-####", phoneFormat);
addFormat("###\\-####;\\(###\\)\\ ###\\-####", phoneFormat);
addFormat("###-####;(###) ###-####", phoneFormat);

Format ssnFormat = SSNFormat.instance;
addFormat("000\\-00\\-0000", ssnFormat);
addFormat("000-00-0000", ssnFormat);
}



/**
* Format class for Excel's SSN format. This class mimics Excel's built-in
* SSN formatting.

+ 10
- 39
src/java/org/apache/poi/ss/usermodel/DateUtil.java 查看文件

@@ -20,10 +20,11 @@ package org.apache.poi.ss.usermodel;

import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Pattern;

import org.apache.poi.util.LocaleUtil;

/**
* Contains methods for dealing with Excel dates.
*/
@@ -52,13 +53,6 @@ public class DateUtil {
// elapsed time patterns: [h],[m] and [s]
private static final Pattern date_ptrn4 = Pattern.compile("^\\[([hH]+|[mM]+|[sS]+)\\]");

/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
private static final TimeZone TIMEZONE_UTC = TimeZone.getTimeZone("UTC");


/**
* Given a Date, converts it into a double representing its internal Excel representation,
* which is the number of days since 1/1/1900. Fractional days represent hours, minutes, and seconds.
@@ -78,7 +72,7 @@ public class DateUtil {
* @param use1904windowing Should 1900 or 1904 date windowing be used?
*/
public static double getExcelDate(Date date, boolean use1904windowing) {
Calendar calStart = Calendar.getInstance(getUserTimeZone(), Locale.ROOT);
Calendar calStart = LocaleUtil.getLocaleCalendar();
calStart.setTime(date); // If date includes hours, minutes, and seconds, set them to 0
return internalGetExcelDate(calStart, use1904windowing);
}
@@ -242,6 +236,9 @@ public class DateUtil {
}
calendar.set(startYear,0, wholeDays + dayAdjust, 0, 0, 0);
calendar.set(Calendar.MILLISECOND, millisecondsInDay);
if (calendar.get(Calendar.MILLISECOND) == 0) {
calendar.clear(Calendar.MILLISECOND);
}
if (roundSeconds) {
calendar.add(Calendar.MILLISECOND, 500);
calendar.clear(Calendar.MILLISECOND);
@@ -281,7 +278,7 @@ public class DateUtil {
* @return Java representation of the date in UTC, or null if date is not a valid Excel date
*/
public static Calendar getJavaCalendarUTC(double date, boolean use1904windowing) {
return getJavaCalendar(date, use1904windowing, TIMEZONE_UTC, false);
return getJavaCalendar(date, use1904windowing, LocaleUtil.TIMEZONE_UTC, false);
}


@@ -314,9 +311,9 @@ public class DateUtil {
int millisecondsInDay = (int)((date - wholeDays) * DAY_MILLISECONDS + 0.5);
Calendar calendar;
if (timeZone != null) {
calendar = Calendar.getInstance(timeZone, Locale.ROOT);
calendar = LocaleUtil.getLocaleCalendar(timeZone);
} else {
calendar = Calendar.getInstance(getUserTimeZone(), Locale.ROOT); // using default time-zone
calendar = LocaleUtil.getLocaleCalendar(); // using default time-zone
}
setCalendar(calendar, wholeDays, millisecondsInDay, use1904windowing, roundSeconds);
return calendar;
@@ -334,13 +331,6 @@ public class DateUtil {
private static ThreadLocal<String> lastFormatString = new ThreadLocal<String>();
private static ThreadLocal<Boolean> lastCachedResult = new ThreadLocal<Boolean>();
private static ThreadLocal<TimeZone> userTimeZone = new ThreadLocal<TimeZone>() {
@Override
protected TimeZone initialValue() {
return TIMEZONE_UTC;
}
};

private static boolean isCached(String formatString, int formatIndex) {
String cachedFormatString = lastFormatString.get();
return cachedFormatString != null && formatIndex == lastFormatIndex.get()
@@ -353,23 +343,6 @@ public class DateUtil {
lastCachedResult.set(Boolean.valueOf(cached));
}

/**
* as timezone information is not stored in any format, it can be
* set before any date calculations take place
*
* @param timezone the timezone under which date calculations take place
*/
public static void setUserTimeZone(TimeZone timezone) {
userTimeZone.set(timezone);
}
/**
* @return the time zone which is used for date calculations
*/
public static TimeZone getUserTimeZone() {
return userTimeZone.get();
}
/**
* Given a format ID and its format String, will check to see if the
* format represents a date format or not.
@@ -684,9 +657,7 @@ public class DateUtil {
int month = parseInt(monthStr, "month", 1, 12);
int day = parseInt(dayStr, "day", 1, 31);

Calendar cal = Calendar.getInstance(getUserTimeZone(), Locale.ROOT);
cal.set(year, month-1, day, 0, 0, 0);
cal.set(Calendar.MILLISECOND, 0);
Calendar cal = LocaleUtil.getLocaleCalendar(year, month-1, day);
return cal.getTime();
}
private static int parseInt(String strVal, String fieldName, int rangeMax) throws FormatException {

+ 6
- 4
src/java/org/apache/poi/ss/usermodel/ExcelStyleDateFormatter.java 查看文件

@@ -17,6 +17,9 @@
package org.apache.poi.ss.usermodel;

import java.util.*;

import org.apache.poi.util.LocaleUtil;

import java.math.RoundingMode;
import java.text.*;

@@ -56,16 +59,15 @@ public class ExcelStyleDateFormatter extends SimpleDateFormat {
DataFormatter.setExcelStyleRoundingMode(format2digits, RoundingMode.DOWN);
DataFormatter.setExcelStyleRoundingMode(format3digit);
DataFormatter.setExcelStyleRoundingMode(format4digits);
setTimeZone(LocaleUtil.getUserTimeZone());
}

private double dateToBeFormatted = 0.0;

public ExcelStyleDateFormatter() {
super();
}
// no-arg constructor is private because of undefined super call with locale

public ExcelStyleDateFormatter(String pattern) {
super(processFormatPattern(pattern));
super(processFormatPattern(pattern), LocaleUtil.getUserLocale());
}

public ExcelStyleDateFormatter(String pattern,

+ 5
- 1
src/java/org/apache/poi/util/FontMetricsDumper.java 查看文件

@@ -18,7 +18,10 @@
package org.apache.poi.util;

import java.awt.*;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
@@ -26,6 +29,7 @@ import java.util.Properties;
@SuppressWarnings("deprecation")
public class FontMetricsDumper
{
@SuppressForbidden
public static void main( String[] args ) throws IOException
{


+ 39
- 23
src/java/org/apache/poi/util/HexDump.java 查看文件

@@ -149,14 +149,15 @@ public class HexDump {
chars_read = 16;
}
buffer.append(String.format(Locale.ROOT, "%08X ", display_offset));
buffer.append(xpad(display_offset, 8, ""));
for (int k = 0; k < 16; k++) {
if (k < chars_read) {
buffer.append(String.format(Locale.ROOT, "%02X ", data[ k + j ]));
buffer.append(xpad(data[ k + j ], 2, " "));
} else {
buffer.append(" ");
}
}
buffer.append(' ');
for (int k = 0; k < chars_read; k++) {
buffer.append(toAscii(data[ k + j ]));
}
@@ -232,20 +233,19 @@ public class HexDump {
* will be written to a new line
* @return A String representing the array of bytes
*/
public static String toHex(final byte[] value, final int bytesPerLine)
{
final int digits =
(int) Math.round(Math.log(value.length) / Math.log(10) + 0.5);
final String formatString = (digits == 0 ? ": %d" : "%0"+digits+"d: ");
StringBuffer retVal = new StringBuffer();
retVal.append(String.format(Locale.ROOT, formatString, 0));
int i = -1;
for(int x = 0; x < value.length; x++)
{
if (++i == bytesPerLine)
{
public static String toHex(final byte[] value, final int bytesPerLine) {
if (value.length == 0) {
return ": 0";
}
final int digits = (int) Math.round(Math.log(value.length) / Math.log(10) + 0.5);
StringBuilder retVal = new StringBuilder();
retVal.append(xpad(0, digits, ""));
retVal.append(": ");
for(int x=0, i=-1; x < value.length; x++) {
if (++i == bytesPerLine) {
retVal.append('\n');
retVal.append(String.format(Locale.ROOT, formatString, x));
retVal.append(xpad(x, digits, ""));
retVal.append(": ");
i = 0;
} else if (x>0) {
retVal.append(", ");
@@ -262,7 +262,7 @@ public class HexDump {
* @return The result right padded with 0
*/
public static String toHex(final short value) {
return String.format(Locale.ROOT, "%04X", value);
return xpad(value & 0xFFFF, 4, "");
}

/**
@@ -272,7 +272,7 @@ public class HexDump {
* @return The result right padded with 0
*/
public static String toHex(final byte value) {
return String.format(Locale.ROOT, "%02X", value);
return xpad(value & 0xFF, 2, "");
}

/**
@@ -282,7 +282,7 @@ public class HexDump {
* @return The result right padded with 0
*/
public static String toHex(final int value) {
return String.format(Locale.ROOT, "%08X", value);
return xpad(value & 0xFFFFFFFF, 8, "");
}

/**
@@ -292,7 +292,7 @@ public class HexDump {
* @return The result right padded with 0
*/
public static String toHex(final long value) {
return String.format(Locale.ROOT, "%016X", value);
return xpad(value & 0xFFFFFFFF, 16, "");
}

/**
@@ -336,30 +336,46 @@ public class HexDump {
* @return string of 16 (zero padded) uppercase hex chars and prefixed with '0x'
*/
public static String longToHex(long value) {
return String.format(Locale.ROOT, "0x%016X", value);
return xpad(value, 16, "0x");
}
/**
* @return string of 8 (zero padded) uppercase hex chars and prefixed with '0x'
*/
public static String intToHex(int value) {
return String.format(Locale.ROOT, "0x%08X", value & 0xFFFFFFFF);
return xpad(value & 0xFFFFFFFF, 8, "0x");
}
/**
* @return string of 4 (zero padded) uppercase hex chars and prefixed with '0x'
*/
public static String shortToHex(int value) {
return String.format(Locale.ROOT, "0x%04X", value & 0xFFFF);
return xpad(value & 0xFFFF, 4, "0x");
}
/**
* @return string of 2 (zero padded) uppercase hex chars and prefixed with '0x'
*/
public static String byteToHex(int value) {
return String.format(Locale.ROOT, "0x%02X", value & 0xFF);
return xpad(value & 0xFF, 2, "0x");
}

private static String xpad(long value, int pad, String prefix) {
String sv = Long.toHexString(value).toUpperCase(Locale.ROOT);
int len = sv.length();
if ((pad == 0 || len == pad) && "".equals(prefix)) return sv;
StringBuilder sb = new StringBuilder(prefix);
if (len < pad) {
sb.append("0000000000000000", 0, pad-len);
sb.append(sv);
} else if (len > pad) {
sb.append(sv, len-pad, len);
} else {
sb.append(sv);
}
return sb.toString();
}
public static void main(String[] args) throws Exception {
File file = new File(args[0]);
InputStream in = new BufferedInputStream(new FileInputStream(file));

+ 136
- 0
src/java/org/apache/poi/util/LocaleUtil.java 查看文件

@@ -0,0 +1,136 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.util;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
/**
* This utility class is used to set locale and time zone settings beside
* of the JDK internal {@link java.util.Locale#setDefault(Locale)} and
* {@link java.util.TimeZone#setDefault(TimeZone)} methods, because
* the locale/time zone specific handling of certain office documents -
* maybe for different time zones / locales ... - shouldn't affect
* other java components.
*
* The settings are saved in a {@link java.lang.ThreadLocal},
* so they only apply to the current thread and can't be set globally.
*/
public class LocaleUtil {
/**
* Excel doesn't store TimeZone information in the file, so if in doubt,
* use UTC to perform calculations
*/
public static final TimeZone TIMEZONE_UTC = TimeZone.getTimeZone("UTC");
private static final ThreadLocal<TimeZone> userTimeZone = new ThreadLocal<TimeZone>() {
@Override
@SuppressForbidden
protected TimeZone initialValue() {
return TimeZone.getDefault();
}
};
private static final ThreadLocal<Locale> userLocale = new ThreadLocal<Locale>() {
@Override
@SuppressForbidden
protected Locale initialValue() {
return Locale.getDefault();
}
};
/**
* As time zone information is not stored in any format, it can be
* set before any date calculations take place.
* This setting is specific to the current thread.
*
* @param timezone the timezone under which date calculations take place
*/
public static void setUserTimeZone(TimeZone timezone) {
userTimeZone.set(timezone);
}
/**
* @return the time zone which is used for date calculations, defaults to UTC
*/
public static TimeZone getUserTimeZone() {
return userTimeZone.get();
}
/**
* Sets default user locale.
* This setting is specific to the current thread.
*/
public static void setUserLocale(Locale locale) {
userLocale.set(locale);
}
/**
* @return the default user locale, defaults to {@link Locale#ROOT}
*/
public static Locale getUserLocale() {
return userLocale.get();
}
/**
* @return a calendar for the user locale and time zone
*/
public static Calendar getLocaleCalendar() {
return getLocaleCalendar(getUserTimeZone());
}
/**
* Convenience method - month is 0-based as in java.util.Calendar
*
* @param year
* @param month
* @param day
* @return a calendar for the user locale and time zone, and the given date
*/
public static Calendar getLocaleCalendar(int year, int month, int day) {
return getLocaleCalendar(year, month, day, 0, 0, 0);
}
/**
* Convenience method - month is 0-based as in java.util.Calendar
*
* @param year
* @param month
* @param day
* @param hour
* @param minute
* @param second
* @return a calendar for the user locale and time zone, and the given date
*/
public static Calendar getLocaleCalendar(int year, int month, int day, int hour, int minute, int second) {
Calendar cal = getLocaleCalendar();
cal.set(year, month, day, hour, minute, second);
cal.clear(Calendar.MILLISECOND);
return cal;
}
/**
* @return a calendar for the user locale and time zone
*/
public static Calendar getLocaleCalendar(TimeZone timeZone) {
return Calendar.getInstance(timeZone, getUserLocale());
}
}

+ 32
- 0
src/java/org/apache/poi/util/SuppressForbidden.java 查看文件

@@ -0,0 +1,32 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.util;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*
* Marking class for elements to be ignored by the forbidden apis check
*/
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface SuppressForbidden {
}

+ 6
- 8
src/ooxml/java/org/apache/poi/openxml4j/opc/internal/PackagePropertiesPart.java 查看文件

@@ -22,8 +22,7 @@ import java.io.OutputStream;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;

import java.util.TimeZone;
import java.util.Locale;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
@@ -33,6 +32,7 @@ import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageProperties;
import org.apache.poi.openxml4j.util.Nullable;
import org.apache.poi.util.LocaleUtil;

/**
* Represents the core properties part of a package.
@@ -559,9 +559,8 @@ public final class PackagePropertiesPart extends PackagePart implements
if (s == null || s.equals("")) {
return new Nullable<Date>();
}
SimpleDateFormat df = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss'Z'");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
Date d = df.parse(s, new ParsePosition(0));
if (d == null) {
throw new InvalidFormatException("Date not well formated");
@@ -586,9 +585,8 @@ public final class PackagePropertiesPart extends PackagePart implements
return "";
}
SimpleDateFormat df = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss'Z'");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
return df.format(date);
}


+ 2
- 1
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java 查看文件

@@ -31,6 +31,7 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.TimeZone;
@@ -196,7 +197,7 @@ public class OOXMLSignatureFacet extends SignatureFacet {
/*
* SignatureTime
*/
DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
String nowStr = fmt.format(signatureConfig.getExecutionTime());
LOG.log(POILogger.DEBUG, "now: " + nowStr);

+ 2
- 2
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java 查看文件

@@ -31,6 +31,7 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
@@ -115,8 +116,7 @@ public class XAdESSignatureFacet extends SignatureFacet {
SignedSignaturePropertiesType signedSignatureProperties = signedProperties.addNewSignedSignatureProperties();
// SigningTime
Calendar xmlGregorianCalendar = Calendar.getInstance();
xmlGregorianCalendar.setTimeZone(TimeZone.getTimeZone("Z"));
Calendar xmlGregorianCalendar = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT);
xmlGregorianCalendar.setTime(signatureConfig.getExecutionTime());
xmlGregorianCalendar.clear(Calendar.MILLISECOND);
signedSignatureProperties.setSigningTime(xmlGregorianCalendar);

+ 4
- 2
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java 查看文件

@@ -39,6 +39,8 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.UUID;
import javax.xml.crypto.MarshalException;
@@ -214,7 +216,7 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
CRLIdentifierType crlIdentifier = crlRef.addNewCRLIdentifier();
String issuerName = crl.getIssuerDN().getName().replace(",", ", ");
crlIdentifier.setIssuer(issuerName);
Calendar cal = Calendar.getInstance();
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT);
cal.setTime(crl.getThisUpdate());
crlIdentifier.setIssueTime(cal);
crlIdentifier.setNumber(getCrlNumber(crl));
@@ -238,7 +240,7 @@ public class XAdESXLSignatureFacet extends SignatureFacet {
BasicOCSPResp basicOcspResp = (BasicOCSPResp)ocspResp.getResponseObject();
Calendar cal = Calendar.getInstance();
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT);
cal.setTime(basicOcspResp.getProducedAt());
ocspIdentifier.setProducedAt(cal);

+ 2
- 1
src/ooxml/java/org/apache/poi/xslf/util/PPTX2PNG.java 查看文件

@@ -26,6 +26,7 @@ import java.awt.image.BufferedImage;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.imageio.ImageIO;
@@ -155,7 +156,7 @@ public class PPTX2PNG {
// save the result
if (!"null".equals(format)) {
String outname = file.getName().replaceFirst(".pptx?", "");
outname = String.format("%1$s-%2$04d.%3$s", outname, slideNo, format);
outname = String.format(Locale.ROOT, "%1$s-%2$04d.%3$s", outname, slideNo, format);
File outfile = new File(outdir, outname);
ImageIO.write(img, format, outfile);
}

+ 2
- 1
src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java 查看文件

@@ -25,6 +25,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Vector;

@@ -314,7 +315,7 @@ public class XSSFExportToXml implements Comparator<String>{
}

private String getFormattedDate(XSSFCell cell) {
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT);
return sdf.format(cell.getDateCellValue());
}


+ 2
- 1
src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFCell.java 查看文件

@@ -35,6 +35,7 @@ import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.xssf.usermodel.XSSFHyperlink;
@@ -653,7 +654,7 @@ public class SXSSFCell implements Cell {
return getCellFormula();
case CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(this)) {
DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", LocaleUtil.getUserLocale());
return sdf.format(getDateCellValue());
}
return getNumericCellValue() + "";

+ 2
- 1
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java 查看文件

@@ -21,6 +21,7 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.FormulaParser;
@@ -840,7 +841,7 @@ public final class XSSFCell implements Cell {
return getCellFormula();
case CELL_TYPE_NUMERIC:
if (DateUtil.isCellDateFormatted(this)) {
DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy");
DateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy", Locale.ROOT);
return sdf.format(getDateCellValue());
}
return Double.toString(getNumericCellValue());

+ 44
- 21
src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java 查看文件

@@ -17,37 +17,49 @@

package org.apache.poi;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import junit.framework.TestCase;

import org.apache.poi.POIXMLProperties.CoreProperties;
import org.apache.poi.openxml4j.util.Nullable;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.XWPFTestDataSamples;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
* Test setting extended and custom OOXML properties
*/
public final class TestPOIXMLProperties extends TestCase {
public final class TestPOIXMLProperties {
private XWPFDocument sampleDoc;
private POIXMLProperties _props;
private CoreProperties _coreProperties;

@Before
public void setUp() throws IOException {
XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("documentProperties.docx");
sampleDoc = XWPFTestDataSamples.openSampleDocument("documentProperties.docx");
_props = sampleDoc.getProperties();
_coreProperties = _props.getCoreProperties();
assertNotNull(_props);
}
@After
public void closeResources() throws Exception {
sampleDoc.close();
}

public void testWorkbookExtendedProperties() {
@Test
public void testWorkbookExtendedProperties() throws Exception {
XSSFWorkbook workbook = new XSSFWorkbook();
POIXMLProperties props = workbook.getProperties();
assertNotNull(props);
@@ -71,7 +83,7 @@ public final class TestPOIXMLProperties extends TestCase {

XSSFWorkbook newWorkbook =
XSSFTestDataSamples.writeOutAndReadBack(workbook);
workbook.close();
assertTrue(workbook != newWorkbook);


@@ -88,16 +100,19 @@ public final class TestPOIXMLProperties extends TestCase {

assertEquals(application, newCtProps.getApplication());
assertEquals(appVersion, newCtProps.getAppVersion());
newWorkbook.close();
}


/**
* Test usermodel API for setting custom properties
*/
public void testCustomProperties() {
POIXMLDocument wb = new XSSFWorkbook();
@Test
public void testCustomProperties() throws Exception {
POIXMLDocument wb1 = new XSSFWorkbook();

POIXMLProperties.CustomProperties customProps = wb.getProperties().getCustomProperties();
POIXMLProperties.CustomProperties customProps = wb1.getProperties().getCustomProperties();
customProps.addProperty("test-1", "string val");
customProps.addProperty("test-2", 1974);
customProps.addProperty("test-3", 36.6);
@@ -110,9 +125,10 @@ public final class TestPOIXMLProperties extends TestCase {
}
customProps.addProperty("test-4", true);

wb = XSSFTestDataSamples.writeOutAndReadBack((XSSFWorkbook)wb);
POIXMLDocument wb2 = XSSFTestDataSamples.writeOutAndReadBack((XSSFWorkbook)wb1);
wb1.close();
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties ctProps =
wb.getProperties().getCustomProperties().getUnderlyingProperties();
wb2.getProperties().getCustomProperties().getUnderlyingProperties();
assertEquals(4, ctProps.sizeOfPropertyArray());
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty p;

@@ -131,7 +147,7 @@ public final class TestPOIXMLProperties extends TestCase {
p = ctProps.getPropertyArray(2);
assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid());
assertEquals("test-3", p.getName());
assertEquals(36.6, p.getR8());
assertEquals(36.6, p.getR8(), 0);
assertEquals(4, p.getPid());

p = ctProps.getPropertyArray(3);
@@ -139,9 +155,12 @@ public final class TestPOIXMLProperties extends TestCase {
assertEquals("test-4", p.getName());
assertEquals(true, p.getBool());
assertEquals(5, p.getPid());
wb2.close();
}

public void testDocumentProperties() {
@Test
public void testDocumentProperties() {
String category = _coreProperties.getCategory();
assertEquals("test", category);
String contentStatus = "Draft";
@@ -158,21 +177,25 @@ public final class TestPOIXMLProperties extends TestCase {
assertEquals("Hello World", title);
}

public void testTransitiveSetters() throws IOException {
@Test
public void testTransitiveSetters() throws IOException {
XWPFDocument doc = new XWPFDocument();
CoreProperties cp = doc.getProperties().getCoreProperties();

Date dateCreated = new GregorianCalendar(2010, 6, 15, 10, 0, 0).getTime();

Date dateCreated = LocaleUtil.getLocaleCalendar(2010, 6, 15, 10, 0, 0).getTime();
cp.setCreated(new Nullable<Date>(dateCreated));
assertEquals(dateCreated.toString(), cp.getCreated().toString());

doc = XWPFTestDataSamples.writeOutAndReadBack(doc);
XWPFDocument doc2 = XWPFTestDataSamples.writeOutAndReadBack(doc);
doc.close();
cp = doc.getProperties().getCoreProperties();
Date dt3 = cp.getCreated();
assertEquals(dateCreated.toString(), dt3.toString());
doc2.close();
}

@Test
public void testGetSetRevision() {
String revision = _coreProperties.getRevision();
assertTrue("Revision number is 1", Integer.parseInt(revision) > 1);
@@ -183,7 +206,7 @@ public final class TestPOIXMLProperties extends TestCase {
}
public static boolean dateTimeEqualToUTCString(Date dateTime, String utcString) {
Calendar utcCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.UK);
Calendar utcCalendar = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
utcCalendar.setTimeInMillis(dateTime.getTime());
String dateTimeUtcString = utcCalendar.get(Calendar.YEAR) + "-" +
zeroPad((utcCalendar.get(Calendar.MONTH)+1)) + "-" +

+ 70
- 77
src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestPackageCoreProperties.java 查看文件

@@ -17,111 +17,97 @@

package org.apache.poi.openxml4j.opc;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import junit.framework.TestCase;
import java.util.Locale;

import org.apache.poi.POIDataSamples;
import org.apache.poi.openxml4j.OpenXML4JTestDataSamples;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
import org.apache.poi.openxml4j.util.Nullable;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Test;
import org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty;

public final class TestPackageCoreProperties extends TestCase {
private static final POILogger logger = POILogFactory.getLogger(TestPackageCoreProperties.class);

public final class TestPackageCoreProperties {
/**
* Test package core properties getters.
*/
public void testGetProperties() {
try {
// Open the package
OPCPackage p = OPCPackage.open(OpenXML4JTestDataSamples.openSampleStream("TestPackageCoreProperiesGetters.docx"));
compareProperties(p);
p.revert();
} catch (OpenXML4JException e) {
logger.log(POILogger.DEBUG, e.getMessage());
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
@Test
public void testGetProperties() throws Exception {
// Open the package
@SuppressWarnings("resource")
OPCPackage p = OPCPackage.open(OpenXML4JTestDataSamples.openSampleStream("TestPackageCoreProperiesGetters.docx"));
compareProperties(p);
p.revert();
}

/**
* Test package core properties setters.
*/
public void testSetProperties() throws Exception {
@Test
public void testSetProperties() throws Exception {
String inputPath = OpenXML4JTestDataSamples.getSampleFileName("TestPackageCoreProperiesSetters.docx");

File outputFile = OpenXML4JTestDataSamples.getOutputFile("TestPackageCoreProperiesSettersOUTPUT.docx");

// Open package
OPCPackage p = OPCPackage.open(inputPath, PackageAccess.READ_WRITE);
try {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
Date dateToInsert = df.parse("2007-05-12T08:00:00Z", new ParsePosition(
0));
PackageProperties props = p.getPackageProperties();
props.setCategoryProperty("MyCategory");
props.setContentStatusProperty("MyContentStatus");
props.setContentTypeProperty("MyContentType");
props.setCreatedProperty(new Nullable<Date>(dateToInsert));
props.setCreatorProperty("MyCreator");
props.setDescriptionProperty("MyDescription");
props.setIdentifierProperty("MyIdentifier");
props.setKeywordsProperty("MyKeywords");
props.setLanguageProperty("MyLanguage");
props.setLastModifiedByProperty("Julien Chable");
props.setLastPrintedProperty(new Nullable<Date>(dateToInsert));
props.setModifiedProperty(new Nullable<Date>(dateToInsert));
props.setRevisionProperty("2");
props.setTitleProperty("MyTitle");
props.setSubjectProperty("MySubject");
props.setVersionProperty("2");
// Save the package in the output directory
p.save(outputFile);
// Open the newly created file to check core properties saved values.
OPCPackage p2 = OPCPackage.open(outputFile.getAbsolutePath(), PackageAccess.READ);
try {
compareProperties(p2);
p2.revert();
} finally {
p2.close();
}
outputFile.delete();
} finally {
// use revert to not re-write the input file
p.revert();
}
@SuppressWarnings("resource")
OPCPackage p = OPCPackage.open(inputPath, PackageAccess.READ_WRITE);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
Date dateToInsert = df.parse("2007-05-12T08:00:00Z", new ParsePosition(0));

PackageProperties props = p.getPackageProperties();
props.setCategoryProperty("MyCategory");
props.setContentStatusProperty("MyContentStatus");
props.setContentTypeProperty("MyContentType");
props.setCreatedProperty(new Nullable<Date>(dateToInsert));
props.setCreatorProperty("MyCreator");
props.setDescriptionProperty("MyDescription");
props.setIdentifierProperty("MyIdentifier");
props.setKeywordsProperty("MyKeywords");
props.setLanguageProperty("MyLanguage");
props.setLastModifiedByProperty("Julien Chable");
props.setLastPrintedProperty(new Nullable<Date>(dateToInsert));
props.setModifiedProperty(new Nullable<Date>(dateToInsert));
props.setRevisionProperty("2");
props.setTitleProperty("MyTitle");
props.setSubjectProperty("MySubject");
props.setVersionProperty("2");
// Save the package in the output directory
p.save(outputFile);
p.revert();

// Open the newly created file to check core properties saved values.
@SuppressWarnings("resource")
OPCPackage p2 = OPCPackage.open(outputFile.getAbsolutePath(), PackageAccess.READ);
compareProperties(p2);
p2.revert();
outputFile.delete();
}

private void compareProperties(OPCPackage p) throws InvalidFormatException {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
Date expectedDate = df.parse("2007-05-12T08:00:00Z", new ParsePosition(
0));
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
Date expectedDate = df.parse("2007-05-12T08:00:00Z", new ParsePosition(0));

// Gets the core properties
PackageProperties props = p.getPackageProperties();
assertEquals("MyCategory", props.getCategoryProperty().getValue());
assertEquals("MyContentStatus", props.getContentStatusProperty()
.getValue());
assertEquals("MyContentStatus", props.getContentStatusProperty().getValue());
assertEquals("MyContentType", props.getContentTypeProperty().getValue());
assertEquals(expectedDate, props.getCreatedProperty().getValue());
assertEquals("MyCreator", props.getCreatorProperty().getValue());
@@ -129,8 +115,7 @@ public final class TestPackageCoreProperties extends TestCase {
assertEquals("MyIdentifier", props.getIdentifierProperty().getValue());
assertEquals("MyKeywords", props.getKeywordsProperty().getValue());
assertEquals("MyLanguage", props.getLanguageProperty().getValue());
assertEquals("Julien Chable", props.getLastModifiedByProperty()
.getValue());
assertEquals("Julien Chable", props.getLastModifiedByProperty().getValue());
assertEquals(expectedDate, props.getLastPrintedProperty().getValue());
assertEquals(expectedDate, props.getModifiedProperty().getValue());
assertEquals("2", props.getRevisionProperty().getValue());
@@ -139,9 +124,10 @@ public final class TestPackageCoreProperties extends TestCase {
assertEquals("2", props.getVersionProperty().getValue());
}

public void testCoreProperties_bug51374() throws Exception {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
@Test
public void testCoreProperties_bug51374() throws Exception {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ROOT);
df.setTimeZone(LocaleUtil.TIMEZONE_UTC);
String strDate = "2007-05-12T08:00:00Z";
Date date = df.parse(strDate);

@@ -197,7 +183,8 @@ public final class TestPackageCoreProperties extends TestCase {
pkg.close();
}

public void testGetPropertiesLO() throws Exception {
@Test
public void testGetPropertiesLO() throws Exception {
// Open the package
OPCPackage pkg1 = OPCPackage.open(OpenXML4JTestDataSamples.openSampleStream("51444.xlsx"));
PackageProperties props1 = pkg1.getPackageProperties();
@@ -206,13 +193,16 @@ public final class TestPackageCoreProperties extends TestCase {
ByteArrayOutputStream out = new ByteArrayOutputStream();
pkg1.save(out);
out.close();
pkg1.close();

OPCPackage pkg2 = OPCPackage.open(new ByteArrayInputStream(out.toByteArray()));
PackageProperties props2 = pkg2.getPackageProperties();
props2.setTitleProperty("Bug 51444 fixed");
pkg2.close();
}

public void testEntitiesInCoreProps_56164() throws Exception {
@Test
public void testEntitiesInCoreProps_56164() throws Exception {
InputStream is = OpenXML4JTestDataSamples.openSampleStream("CorePropertiesHasEntities.ooxml");
OPCPackage p = OPCPackage.open(is);
is.close();
@@ -236,9 +226,12 @@ public final class TestPackageCoreProperties extends TestCase {
// Check
assertEquals("Stefan Kopf", props.getCreatorProperty().getValue());
p.close();
}
public void testListOfCustomProperties() throws Exception {
@Test
public void testListOfCustomProperties() throws Exception {
File inp = POIDataSamples.getSpreadSheetInstance().getFile("ExcelWithAttachments.xlsm");
OPCPackage pkg = OPCPackage.open(inp, PackageAccess.READ);
XSSFWorkbook wb = new XSSFWorkbook(pkg);

+ 41
- 7
src/ooxml/testcases/org/apache/poi/ss/format/TestCellFormatPart.java 查看文件

@@ -16,14 +16,36 @@
==================================================================== */
package org.apache.poi.ss.format;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.XSSFITestDataProvider;
import static org.junit.Assert.assertEquals;

import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.xssf.XSSFITestDataProvider;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

/** Test the individual CellFormatPart types. */
public class TestCellFormatPart extends CellFormatTestBase {
private static Locale userLocale;
@BeforeClass
public static void setLocale() {
userLocale = LocaleUtil.getUserLocale();
LocaleUtil.setUserLocale(Locale.ROOT);
}
@AfterClass
public static void unsetLocale() {
LocaleUtil.setUserLocale(userLocale);
}
private static final Pattern NUMBER_EXTRACT_FMT = Pattern.compile(
"([-+]?[0-9]+)(\\.[0-9]+)?.*(?:(e).*?([+-]?[0-9]+))",
Pattern.CASE_INSENSITIVE);
@@ -32,6 +54,7 @@ public class TestCellFormatPart extends CellFormatTestBase {
super(XSSFITestDataProvider.instance);
}

@Test
public void testGeneralFormat() throws Exception {
runFormatTests("GeneralFormatTests.xlsx", new CellValue() {
public Object getValue(Cell cell) {
@@ -54,6 +77,7 @@ public class TestCellFormatPart extends CellFormatTestBase {
});
}

@Test
public void testNumberApproxFormat() throws Exception {
runFormatTests("NumberFormatApproxTests.xlsx", new CellValue() {
public Object getValue(Cell cell) {
@@ -73,14 +97,22 @@ public class TestCellFormatPart extends CellFormatTestBase {
});
}

@Test
public void testDateFormat() throws Exception {
runFormatTests("DateFormatTests.xlsx", new CellValue() {
public Object getValue(Cell cell) {
return cell.getDateCellValue();
}
});
TimeZone tz = LocaleUtil.getUserTimeZone();
LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
try {
runFormatTests("DateFormatTests.xlsx", new CellValue() {
public Object getValue(Cell cell) {
return cell.getDateCellValue();
}
});
} finally {
LocaleUtil.setUserTimeZone(tz);
}
}

@Test
public void testElapsedFormat() throws Exception {
runFormatTests("ElapsedFormatTests.xlsx", new CellValue() {
public Object getValue(Cell cell) {
@@ -89,6 +121,7 @@ public class TestCellFormatPart extends CellFormatTestBase {
});
}

@Test
public void testTextFormat() throws Exception {
runFormatTests("TextFormatTests.xlsx", new CellValue() {
public Object getValue(Cell cell) {
@@ -100,6 +133,7 @@ public class TestCellFormatPart extends CellFormatTestBase {
});
}

@Test
public void testConditions() throws Exception {
runFormatTests("FormatConditionTests.xlsx", new CellValue() {
Object getValue(Cell cell) {

+ 4
- 3
src/ooxml/testcases/org/apache/poi/ss/usermodel/BaseTestXCell.java 查看文件

@@ -17,13 +17,13 @@

package org.apache.poi.ss.usermodel;

import static org.junit.Assert.assertEquals;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.ss.ITestDataProvider;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.xssf.SXSSFITestDataProvider;
import org.apache.poi.xssf.XSSFITestDataProvider;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.junit.Test;

/**
* Class for combined testing of XML-specific functionality of
@@ -37,6 +37,7 @@ public abstract class BaseTestXCell extends BaseTestCell {
super(testDataProvider);
}

@Test
public void testXmlEncoding(){
Workbook wb = _testDataProvider.createWorkbook();
Sheet sh = wb.createSheet();

+ 7
- 2
src/ooxml/testcases/org/apache/poi/xssf/streaming/TestSXSSFCell.java 查看文件

@@ -19,6 +19,8 @@

package org.apache.poi.xssf.streaming;

import static org.junit.Assert.assertEquals;

import java.io.IOException;

import javax.xml.namespace.QName;
@@ -30,6 +32,8 @@ import org.apache.poi.xssf.SXSSFITestDataProvider;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.xmlbeans.XmlCursor;
import org.junit.AfterClass;
import org.junit.Test;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;

/**
@@ -42,11 +46,12 @@ public class TestSXSSFCell extends BaseTestXCell {
super(SXSSFITestDataProvider.instance);
}

@Override
public void tearDown(){
@AfterClass
public static void tearDown(){
SXSSFITestDataProvider.instance.cleanup();
}

@Test
public void testPreserveSpaces() throws IOException {
String[] samplesWithSpaces = {
" POI",

+ 139
- 229
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestFormulaEvaluatorOnXSSF.java 查看文件

@@ -17,14 +17,18 @@

package org.apache.poi.xssf.usermodel;

import java.io.InputStream;
import java.io.PrintStream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;

import junit.framework.Assert;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;

import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.ss.formula.eval.TestFormulasFromSpreadsheet;
import org.apache.poi.ss.formula.functions.TestMathX;
import org.apache.poi.ss.usermodel.Cell;
@@ -32,7 +36,13 @@ import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.util.LocaleUtil;
import org.junit.AfterClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

/**
* Performs much the same role as {@link TestFormulasFromSpreadsheet},
@@ -44,206 +54,127 @@ import org.apache.poi.openxml4j.opc.OPCPackage;
* Excel 2007, and re-save it as FormulaEvalTestData_Copy.xlsx
*
*/
public final class TestFormulaEvaluatorOnXSSF 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;
}
@RunWith(Parameterized.class)
public final class TestFormulaEvaluatorOnXSSF {

private static XSSFWorkbook workbook;
private static Sheet sheet;
private static FormulaEvaluator evaluator;
private static Locale userLocale;
/**
* This class defines constants for navigating around the test data spreadsheet used for these tests.
*/
private static final class SS {
private static interface SS {
/**
* Name of the test spreadsheet (found in the standard test data folder)
*/
public final static String FILENAME = "FormulaEvalTestData_Copy.xlsx";
String FILENAME = "FormulaEvalTestData_Copy.xlsx";
/**
* Row (zero-based) in the test spreadsheet where the operator examples start.
*/
public static final int START_OPERATORS_ROW_INDEX = 22; // Row '23'
int START_OPERATORS_ROW_INDEX = 22; // Row '23'
/**
* Row (zero-based) in the test spreadsheet where the function examples start.
*/
public static final int START_FUNCTIONS_ROW_INDEX = 95; // Row '96'
int START_FUNCTIONS_ROW_INDEX = 95; // Row '96'
/**
* Index of the column that contains the function names
*/
public static final int COLUMN_INDEX_FUNCTION_NAME = 1; // Column 'B'
int COLUMN_INDEX_FUNCTION_NAME = 1; // Column 'B'

/**
* Used to indicate when there are no more functions left
*/
public static final String FUNCTION_NAMES_END_SENTINEL = "<END-OF-FUNCTIONS>";
String FUNCTION_NAMES_END_SENTINEL = "<END-OF-FUNCTIONS>";

/**
* Index of the column where the test values start (for each function)
*/
public static final short COLUMN_INDEX_FIRST_TEST_VALUE = 3; // Column 'D'
short COLUMN_INDEX_FIRST_TEST_VALUE = 3; // Column 'D'

/**
* Each function takes 4 rows in the test spreadsheet
*/
public static final int NUMBER_OF_ROWS_PER_FUNCTION = 4;
int NUMBER_OF_ROWS_PER_FUNCTION = 4;
}

private XSSFWorkbook workbook;
private Sheet sheet;
// Note - multiple failures are aggregated before ending.
// If one or more functions fail, a single AssertionFailedError is thrown at the end
private int _functionFailureCount;
private int _functionSuccessCount;
private int _evaluationFailureCount;
private int _evaluationSuccessCount;
@Parameter(value = 0)
public String targetFunctionName;
@Parameter(value = 1)
public int formulasRowIdx;
@Parameter(value = 2)
public int expectedValuesRowIdx;

private static final Cell getExpectedValueCell(Row row, short columnIndex) {
if (row == null) {
return null;
}
return row.getCell(columnIndex);
}
@AfterClass
public static void closeResource() throws Exception {
LocaleUtil.setUserLocale(userLocale);
workbook.close();
}
@Parameters(name="{0}")
public static Collection<Object[]> data() throws Exception {
// Function "Text" uses custom-formats which are locale specific
// can't set the locale on a per-testrun execution, as some settings have been
// already set, when we would try to change the locale by then
userLocale = LocaleUtil.getUserLocale();
LocaleUtil.setUserLocale(Locale.ROOT);

workbook = new XSSFWorkbook( OPCPackage.open(HSSFTestDataSamples.getSampleFile(SS.FILENAME), PackageAccess.READ) );
sheet = workbook.getSheetAt( 0 );
evaluator = new XSSFFormulaEvaluator(workbook);
List<Object[]> data = new ArrayList<Object[]>();
processFunctionGroup(data, SS.START_OPERATORS_ROW_INDEX, null);
processFunctionGroup(data, SS.START_FUNCTIONS_ROW_INDEX, null);
// example for debugging individual functions/operators:
// processFunctionGroup(data, SS.START_OPERATORS_ROW_INDEX, "ConcatEval");
// processFunctionGroup(data, SS.START_FUNCTIONS_ROW_INDEX, "Text");

private static void confirmExpectedResult(String msg, Cell expected, CellValue actual) {
if (expected == null) {
throw new AssertionFailedError(msg + " - Bad setup data expected value is null");
}
if(actual == null) {
throw new AssertionFailedError(msg + " - actual value was null");
}
switch (expected.getCellType()) {
case Cell.CELL_TYPE_BLANK:
assertEquals(msg, Cell.CELL_TYPE_BLANK, actual.getCellType());
break;
case Cell.CELL_TYPE_BOOLEAN:
assertEquals(msg, Cell.CELL_TYPE_BOOLEAN, actual.getCellType());
assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());
break;
case Cell.CELL_TYPE_ERROR:
assertEquals(msg, Cell.CELL_TYPE_ERROR, actual.getCellType());
if(false) { // TODO: fix ~45 functions which are currently returning incorrect error values
assertEquals(msg, expected.getErrorCellValue(), actual.getErrorValue());
}
break;
case Cell.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);
case Cell.CELL_TYPE_NUMERIC:
assertEquals(msg, Cell.CELL_TYPE_NUMERIC, actual.getCellType());
TestMathX.assertEquals(msg, expected.getNumericCellValue(), actual.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
// double delta = Math.abs(expected.getNumericCellValue()-actual.getNumberValue());
// double pctExpected = Math.abs(0.00001*expected.getNumericCellValue());
// assertTrue(msg, delta <= pctExpected);
break;
case Cell.CELL_TYPE_STRING:
assertEquals(msg, Cell.CELL_TYPE_STRING, actual.getCellType());
assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());
break;
}
}

return data;
}
/**
* @param startRowIndex row index in the spreadsheet where the first function/operator is found
* @param testFocusFunctionName name of a single function/operator to test alone.
* Typically pass <code>null</code> to test all functions
*/
private static void processFunctionGroup(List<Object[]> data, int startRowIndex, String testFocusFunctionName) {
for (int rowIndex = startRowIndex; true; rowIndex += SS.NUMBER_OF_ROWS_PER_FUNCTION) {
Row r = sheet.getRow(rowIndex);
String targetFunctionName = getTargetFunctionName(r);
if(targetFunctionName == null) {
fail("Test spreadsheet cell empty on row ("
+ (rowIndex+1) + "). Expected function name or '"
+ SS.FUNCTION_NAMES_END_SENTINEL + "'");
}
if(targetFunctionName.equals(SS.FUNCTION_NAMES_END_SENTINEL)) {
// found end of functions list
break;
}
if(testFocusFunctionName == null || targetFunctionName.equalsIgnoreCase(testFocusFunctionName)) {
// expected results are on the row below
Row expectedValuesRow = sheet.getRow(rowIndex + 1);
if(expectedValuesRow == null) {
int missingRowNum = rowIndex + 2; //+1 for 1-based, +1 for next row
fail("Missing expected values row for function '"
+ targetFunctionName + " (row " + missingRowNum + ")");
}
data.add(new Object[]{targetFunctionName, rowIndex, rowIndex + 1});
}
}
}

protected void setUp() throws Exception {
if (workbook == null) {
InputStream is = HSSFTestDataSamples.openSampleFileStream(SS.FILENAME);
OPCPackage pkg = OPCPackage.open(is);
workbook = new XSSFWorkbook( pkg );
sheet = workbook.getSheetAt( 0 );
}
_functionFailureCount = 0;
_functionSuccessCount = 0;
_evaluationFailureCount = 0;
_evaluationSuccessCount = 0;
}
/**
* Checks that we can actually open the file
*/
public void testOpen() {
assertNotNull(workbook);
}
/**
* Disabled for now, as many things seem to break
* for XSSF, which is a shame
*/
public void testFunctionsFromTestSpreadsheet() {
processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, null);
processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, null);
// example for debugging individual functions/operators:
// processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, "ConcatEval");
// processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, "AVERAGE");
// confirm results
String successMsg = "There were "
+ _evaluationSuccessCount + " successful evaluation(s) and "
+ _functionSuccessCount + " function(s) without error";
if(_functionFailureCount > 0) {
String msg = _functionFailureCount + " function(s) failed in "
+ _evaluationFailureCount + " evaluation(s). " + successMsg;
throw new AssertionFailedError(msg);
}
if(false) { // normally no output for successful tests
System.out.println(getClass().getName() + ": " + successMsg);
}
}

/**
* @param startRowIndex row index in the spreadsheet where the first function/operator is found
* @param testFocusFunctionName name of a single function/operator to test alone.
* Typically pass <code>null</code> to test all functions
*/
private void processFunctionGroup(int startRowIndex, String testFocusFunctionName) {
FormulaEvaluator evaluator = new XSSFFormulaEvaluator(workbook);

int rowIndex = startRowIndex;
while (true) {
Row r = sheet.getRow(rowIndex);
String targetFunctionName = getTargetFunctionName(r);
if(targetFunctionName == null) {
throw new AssertionFailedError("Test spreadsheet cell empty on row ("
+ (rowIndex+1) + "). Expected function name or '"
+ SS.FUNCTION_NAMES_END_SENTINEL + "'");
}
if(targetFunctionName.equals(SS.FUNCTION_NAMES_END_SENTINEL)) {
// found end of functions list
break;
}
if(testFocusFunctionName == null || targetFunctionName.equalsIgnoreCase(testFocusFunctionName)) {
// expected results are on the row below
Row expectedValuesRow = sheet.getRow(rowIndex + 1);
if(expectedValuesRow == null) {
int missingRowNum = rowIndex + 2; //+1 for 1-based, +1 for next row
throw new AssertionFailedError("Missing expected values row for function '"
+ targetFunctionName + " (row " + missingRowNum + ")");
}
switch(processFunctionRow(evaluator, targetFunctionName, r, expectedValuesRow)) {
case Result.ALL_EVALUATIONS_SUCCEEDED: _functionSuccessCount++; break;
case Result.SOME_EVALUATIONS_FAILED: _functionFailureCount++; break;
default:
throw new RuntimeException("unexpected result");
case Result.NO_EVALUATIONS_FOUND: // do nothing
}
}
rowIndex += SS.NUMBER_OF_ROWS_PER_FUNCTION;
}
}

/**
*
* @return a constant from the local Result class denoting whether there were any evaluation
* cases, and whether they all succeeded.
*/
private int processFunctionRow(FormulaEvaluator evaluator, String targetFunctionName,
Row formulasRow, Row expectedValuesRow) {
int result = Result.NO_EVALUATIONS_FOUND; // so far
@Test
public void processFunctionRow() {
Row formulasRow = sheet.getRow(formulasRowIdx);
Row expectedValuesRow = sheet.getRow(expectedValuesRowIdx);
short endcolnum = formulasRow.getLastCellNum();

// iterate across the row for all the evaluation cases
@@ -256,31 +187,44 @@ public final class TestFormulaEvaluatorOnXSSF extends TestCase {
continue;
}

CellValue actualValue;
try {
actualValue = evaluator.evaluate(c);
} catch (RuntimeException e) {
_evaluationFailureCount ++;
printShortStackTrace(System.err, e);
result = Result.SOME_EVALUATIONS_FAILED;
continue;
}
CellValue actValue = evaluator.evaluate(c);
Cell expValue = (expectedValuesRow == null) ? null : expectedValuesRow.getCell(colnum);

Cell expectedValueCell = getExpectedValueCell(expectedValuesRow, colnum);
try {
confirmExpectedResult("Function '" + targetFunctionName + "': Formula: " + c.getCellFormula() + " @ " + formulasRow.getRowNum() + ":" + colnum,
expectedValueCell, actualValue);
_evaluationSuccessCount ++;
if(result != Result.SOME_EVALUATIONS_FAILED) {
result = Result.ALL_EVALUATIONS_SUCCEEDED;
}
} catch (AssertionFailedError e) {
_evaluationFailureCount ++;
printShortStackTrace(System.err, e);
result = Result.SOME_EVALUATIONS_FAILED;
}
String msg = String.format(Locale.ROOT, "Function '%s': Formula: %s @ %d:%d"
, targetFunctionName, c.getCellFormula(), formulasRow.getRowNum(), colnum);
assertNotNull(msg + " - Bad setup data expected value is null", expValue);
assertNotNull(msg + " - actual value was null", actValue);
switch (expValue.getCellType()) {
case Cell.CELL_TYPE_BLANK:
assertEquals(msg, Cell.CELL_TYPE_BLANK, actValue.getCellType());
break;
case Cell.CELL_TYPE_BOOLEAN:
assertEquals(msg, Cell.CELL_TYPE_BOOLEAN, actValue.getCellType());
assertEquals(msg, expValue.getBooleanCellValue(), actValue.getBooleanValue());
break;
case Cell.CELL_TYPE_ERROR:
assertEquals(msg, Cell.CELL_TYPE_ERROR, actValue.getCellType());
// if(false) { // TODO: fix ~45 functions which are currently returning incorrect error values
// assertEquals(msg, expValue.getErrorCellValue(), actValue.getErrorValue());
// }
break;
case Cell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
fail("Cannot expect formula as result of formula evaluation: " + msg);
case Cell.CELL_TYPE_NUMERIC:
assertEquals(msg, Cell.CELL_TYPE_NUMERIC, actValue.getCellType());
TestMathX.assertEquals(msg, expValue.getNumericCellValue(), actValue.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
// double delta = Math.abs(expValue.getNumericCellValue()-actValue.getNumberValue());
// double pctExpValue = Math.abs(0.00001*expValue.getNumericCellValue());
// assertTrue(msg, delta <= pctExpValue);
break;
case Cell.CELL_TYPE_STRING:
assertEquals(msg, Cell.CELL_TYPE_STRING, actValue.getCellType());
assertEquals(msg, expValue.getRichStringCellValue().getString(), actValue.getStringValue());
break;
}
}
return result;
}

/*
@@ -301,40 +245,6 @@ public final class TestFormulaEvaluatorOnXSSF extends TestCase {
return false;
}


/**
* Useful to keep output concise when expecting many failures to be reported by this test case
*/
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) {
if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
break;
}
startIx++;
}
// skip bottom frames (part of junit framework)
int endIx = startIx+1;
while(endIx < stes.length) {
if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
break;
}
endIx++;
}
if(startIx >= endIx) {
// something went wrong. just print the whole stack trace
e.printStackTrace(ps);
}
endIx -= 4; // skip 4 frames of reflection invocation
ps.println(e.toString());
for(int i=startIx; i<endIx; i++) {
ps.println("\tat " + stes[i].toString());
}
}

/**
* @return <code>null</code> if cell is missing, empty or blank
*/
@@ -355,7 +265,7 @@ public final class TestFormulaEvaluatorOnXSSF extends TestCase {
return cell.getRichStringCellValue().getString();
}
throw new AssertionFailedError("Bad cell type for 'function name' column: ("
+ cell.getCellType() + ") row (" + (r.getRowNum() +1) + ")");
fail("Bad cell type for 'function name' column: ("+cell.getColumnIndex()+") row ("+(r.getRowNum()+1)+")");
return null;
}
}

+ 29
- 12
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestUnfixedBugs.java 查看文件

@@ -17,6 +17,12 @@
package org.apache.poi.xssf.usermodel;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
@@ -25,10 +31,6 @@ import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import junit.framework.TestCase;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.ss.usermodel.Cell;
@@ -42,6 +44,7 @@ import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellUtil;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.xssf.SXSSFITestDataProvider;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
@@ -57,7 +60,8 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
* Bugzilla id's PLEASE MOVE tests from this class to TestBugs once the bugs are
* fixed, so that they are then run automatically.
*/
public final class TestUnfixedBugs extends TestCase {
public final class TestUnfixedBugs {
@Test
public void testBug54084Unicode() throws IOException {
// sample XLSX with the same text-contents as the text-file above
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("54084 - Greek - beyond BMP.xlsx");
@@ -76,8 +80,14 @@ public final class TestUnfixedBugs extends TestCase {
verifyBug54084Unicode(wbWritten);
// finally also write it out via the streaming interface and verify that we still can read it back in
Workbook wbStreamingWritten = SXSSFITestDataProvider.instance.writeOutAndReadBack(new SXSSFWorkbook(wb));
SXSSFWorkbook swb = new SXSSFWorkbook(wb);
Workbook wbStreamingWritten = SXSSFITestDataProvider.instance.writeOutAndReadBack(swb);
verifyBug54084Unicode(wbStreamingWritten);
wbWritten.close();
swb.close();
wbStreamingWritten.close();
wb.close();
}
private void verifyBug54084Unicode(Workbook wb) {
@@ -95,7 +105,8 @@ public final class TestUnfixedBugs extends TestCase {
assertEquals("The data in the text-file should exactly match the data that we read from the workbook", testData, value);
}
public void test54071() {
@Test
public void test54071() throws Exception {
Workbook workbook = XSSFTestDataSamples.openSampleWorkbook("54071.xlsx");
Sheet sheet = workbook.getSheetAt(0);
int rows = sheet.getPhysicalNumberOfRows();
@@ -120,8 +131,11 @@ public final class TestUnfixedBugs extends TestCase {
}
}
}
workbook.close();
}
@Test
public void test54071Simple() {
double value1 = 41224.999988425923;
double value2 = 41224.999988368058;
@@ -143,15 +157,13 @@ public final class TestUnfixedBugs extends TestCase {
// second to be different here!
int startYear = 1900;
int dayAdjust = -1; // Excel thinks 2/29/1900 is a valid date, which it isn't
Calendar calendar1 = new GregorianCalendar(Locale.ROOT);
calendar1.set(startYear,0, wholeDays1 + dayAdjust, 0, 0, 0);
Calendar calendar1 = LocaleUtil.getLocaleCalendar(startYear,0, wholeDays1 + dayAdjust);
calendar1.set(Calendar.MILLISECOND, millisecondsInDay1);
// this is the rounding part:
calendar1.add(Calendar.MILLISECOND, 500);
calendar1.clear(Calendar.MILLISECOND);
Calendar calendar2 = new GregorianCalendar(Locale.ROOT);
calendar2.set(startYear,0, wholeDays2 + dayAdjust, 0, 0, 0);
Calendar calendar2 = LocaleUtil.getLocaleCalendar(startYear,0, wholeDays2 + dayAdjust);
calendar2.set(Calendar.MILLISECOND, millisecondsInDay2);
// this is the rounding part:
calendar2.add(Calendar.MILLISECOND, 500);
@@ -163,7 +175,8 @@ public final class TestUnfixedBugs extends TestCase {
assertEquals(DateUtil.getJavaDate(value1, false), DateUtil.getJavaDate(value2, false));
}
public void test57236() {
@Test
public void test57236() throws Exception {
// Having very small numbers leads to different formatting, Excel uses the scientific notation, but POI leads to "0"
/*
@@ -189,10 +202,12 @@ public final class TestUnfixedBugs extends TestCase {
}
}
}
wb.close();
}
// When this is fixed, the test case should go to BaseTestXCell with
// adjustments to use _testDataProvider to also verify this for XSSF
@Test
public void testBug57294() throws IOException {
Workbook wb = SXSSFITestDataProvider.instance.createWorkbook();
@@ -217,6 +232,8 @@ public final class TestUnfixedBugs extends TestCase {
assertEquals(0, strBack.getIndexOfFormattingRun(0));
assertEquals(2, strBack.getIndexOfFormattingRun(1));
assertEquals(4, strBack.getIndexOfFormattingRun(2));
wbBack.close();
}
@Test

+ 434
- 308
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java
文件差異過大導致無法顯示
查看文件


+ 21
- 1
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFCell.java 查看文件

@@ -17,6 +17,11 @@

package org.apache.poi.xssf.usermodel;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.IOException;

import org.apache.poi.hssf.HSSFITestDataProvider;
@@ -34,6 +39,7 @@ import org.apache.poi.xssf.SXSSFITestDataProvider;
import org.apache.poi.xssf.XSSFITestDataProvider;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.junit.Test;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellType;

@@ -50,6 +56,7 @@ public final class TestXSSFCell extends BaseTestXCell {
* Bug 47026: trouble changing cell type when workbook doesn't contain
* Shared String Table
*/
@Test
public void test47026_1() {
Workbook source = _testDataProvider.openSampleWorkbook("47026.xlsm");
Sheet sheet = source.getSheetAt(0);
@@ -59,6 +66,7 @@ public final class TestXSSFCell extends BaseTestXCell {
cell.setCellValue("456");
}

@Test
public void test47026_2() {
Workbook source = _testDataProvider.openSampleWorkbook("47026.xlsm");
Sheet sheet = source.getSheetAt(0);
@@ -75,6 +83,7 @@ public final class TestXSSFCell extends BaseTestXCell {
* Some programs, for example, Microsoft Excel Driver for .xlsx insert inline string
* instead of using the shared string table. See bug 47206
*/
@Test
public void testInlineString() {
XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.openSampleWorkbook("xlsx-jdbc.xlsx");
XSSFSheet sheet = wb.getSheetAt(0);
@@ -99,6 +108,7 @@ public final class TestXSSFCell extends BaseTestXCell {
/**
* Bug 47278 - xsi:nil attribute for <t> tag caused Excel 2007 to fail to open workbook
*/
@Test
public void test47278() {
XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.createWorkbook();
Sheet sheet = wb.createSheet();
@@ -121,6 +131,7 @@ public final class TestXSSFCell extends BaseTestXCell {
assertEquals(Cell.CELL_TYPE_BLANK, cell_1.getCellType());
}

@Test
public void testFormulaString() throws IOException {
XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.createWorkbook();
try {
@@ -162,6 +173,7 @@ public final class TestXSSFCell extends BaseTestXCell {
/**
* Bug 47889: problems when calling XSSFCell.getStringCellValue() on a workbook created in Gnumeric
*/
@Test
public void test47889() {
XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.openSampleWorkbook("47889.xlsx");
XSSFSheet sh = wb.getSheetAt(0);
@@ -180,13 +192,14 @@ public final class TestXSSFCell extends BaseTestXCell {
//try a numeric cell
cell = sh.getRow(1).getCell(0);
assertEquals(XSSFCell.CELL_TYPE_NUMERIC, cell.getCellType());
assertEquals(1.0, cell.getNumericCellValue());
assertEquals(1.0, cell.getNumericCellValue(), 0);
assertEquals("1.0", cell.toString());
//Gnumeric produces spreadsheets without styles
//make sure we return null for that instead of throwing OutOfBounds
assertEquals(null, cell.getCellStyle());
}

@Test
public void testMissingRAttribute() {
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sheet = wb.createSheet();
@@ -238,6 +251,7 @@ public final class TestXSSFCell extends BaseTestXCell {
assertEquals("F1", a6.getReference());
}

@Test
public void testMissingRAttributeBug54288() {
// workbook with cells missing the R attribute
XSSFWorkbook wb = (XSSFWorkbook)_testDataProvider.openSampleWorkbook("54288.xlsx");
@@ -278,6 +292,7 @@ public final class TestXSSFCell extends BaseTestXCell {
}
}
@Test
public void test56170() throws IOException {
final Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56170.xlsx");
final XSSFSheet sheet = (XSSFSheet) wb.getSheetAt(0);
@@ -326,6 +341,7 @@ public final class TestXSSFCell extends BaseTestXCell {
stream.close();*/
}
@Test
public void test56170Reproduce() throws IOException {
final Workbook wb = new XSSFWorkbook();
try {
@@ -370,6 +386,7 @@ public final class TestXSSFCell extends BaseTestXCell {
}
}

@Test
public void testBug56644ReturnNull() throws IOException {
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56644.xlsx");
try {
@@ -382,6 +399,7 @@ public final class TestXSSFCell extends BaseTestXCell {
}
}

@Test
public void testBug56644ReturnBlank() throws IOException {
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56644.xlsx");
try {
@@ -394,6 +412,7 @@ public final class TestXSSFCell extends BaseTestXCell {
}
}

@Test
public void testBug56644CreateBlank() throws IOException {
Workbook wb = XSSFTestDataSamples.openSampleWorkbook("56644.xlsx");
try {
@@ -406,6 +425,7 @@ public final class TestXSSFCell extends BaseTestXCell {
}
}

@Test
public void testEncodingbeloAscii(){
StringBuffer sb = new StringBuffer();
// test all possible characters

+ 25
- 0
src/resources/devtools/forbidden-signatures.txt 查看文件

@@ -0,0 +1,25 @@
# (C) Copyright Uwe Schindler (Generics Policeman) and others.
# Parts of this work are licensed to the Apache Software Foundation (ASF)
# under one or more contributor license agreements.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This file contains API signatures which are specific to POI.
# The goal is to minimize implicit defaults
@ignoreUnresolvable
@defaultMessage POI forbidden APIs
java.util.Locale#getDefault()
java.util.Locale#setDefault(java.util.Locale)
java.util.TimeZone#getDefault()

+ 3
- 3
src/scratchpad/src/org/apache/poi/hmef/attribute/TNEFDateAttribute.java 查看文件

@@ -21,12 +21,12 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import org.apache.poi.hmef.Attachment;
import org.apache.poi.hmef.HMEFMessage;
import org.apache.poi.hpsf.Util;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;

@@ -53,7 +53,7 @@ public final class TNEFDateAttribute extends TNEFAttribute {
);
} else if(data.length == 14) {
// It's the 7 date fields. We think it's in UTC...
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Calendar c = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
c.set(Calendar.YEAR, LittleEndian.getUShort(data, 0));
c.set(Calendar.MONTH, LittleEndian.getUShort(data, 2) - 1); // Java months are 0 based!
c.set(Calendar.DAY_OF_MONTH, LittleEndian.getUShort(data, 4));
@@ -61,7 +61,7 @@ public final class TNEFDateAttribute extends TNEFAttribute {
c.set(Calendar.MINUTE, LittleEndian.getUShort(data, 8));
c.set(Calendar.SECOND, LittleEndian.getUShort(data, 10));
// The 7th field is day of week, which we don't require
c.set(Calendar.MILLISECOND, 0); // Not set in the file
c.clear(Calendar.MILLISECOND); // Not set in the file
this.data = c.getTime();
} else {
throw new IllegalArgumentException("Invalid date, found " + data.length + " bytes");

+ 2
- 0
src/scratchpad/src/org/apache/poi/hslf/model/PPGraphics2D.java 查看文件

@@ -63,6 +63,7 @@ import org.apache.poi.sl.usermodel.StrokeStyle;
import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.SuppressForbidden;

/**
* Translates Graphics2D calls into PowerPoint.
@@ -1716,6 +1717,7 @@ public final class PPGraphics2D extends Graphics2D implements Cloneable {
* @see java.awt.Graphics#getFontMetrics()
*/
@SuppressWarnings("deprecation")
@SuppressForbidden
public FontMetrics getFontMetrics(Font f) {
return Toolkit.getDefaultToolkit().getFontMetrics(f);
}

+ 3
- 7
src/scratchpad/src/org/apache/poi/hslf/util/SystemTimeUtils.java 查看文件

@@ -19,10 +19,9 @@ package org.apache.poi.hslf.util;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;

import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LocaleUtil;

/**
* A helper class for dealing with SystemTime Structs, as defined at
@@ -33,9 +32,6 @@ import org.apache.poi.util.LittleEndian;
* - that the day of the week (0) starts on Sunday in SYSTEMTIME, and Monday in Calendar
* It is also the case that this does not store the timezone, and no... it is not
* stored as UTC either, but rather the local system time (yuck.)
*
* @author Daniel Noll
* @author Nick Burch
*/
public final class SystemTimeUtils {
/**
@@ -48,7 +44,7 @@ public final class SystemTimeUtils {
* Get the date found in the byte array, as a java Data object
*/
public static Date getDate(byte[] data, int offset) {
Calendar cal = new GregorianCalendar(Locale.ROOT);
Calendar cal = LocaleUtil.getLocaleCalendar();

cal.set(Calendar.YEAR, LittleEndian.getShort(data,offset));
cal.set(Calendar.MONTH, LittleEndian.getShort(data,offset+2)-1);
@@ -75,7 +71,7 @@ public final class SystemTimeUtils {
* into the supplied byte array.
*/
public static void storeDate(Date date, byte[] dest, int offset) {
Calendar cal = new GregorianCalendar();
Calendar cal = LocaleUtil.getLocaleCalendar();
cal.setTime(date);

LittleEndian.putShort(dest, offset + 0, (short) cal.get(Calendar.YEAR));

+ 2
- 10
src/scratchpad/src/org/apache/poi/hsmf/MAPIMessage.java 查看文件

@@ -81,7 +81,7 @@ public class MAPIMessage extends POIDocument {
*/
public MAPIMessage() {
// TODO - make writing possible
super(new POIFSFileSystem());
super(new NPOIFSFileSystem());
}


@@ -91,7 +91,7 @@ public class MAPIMessage extends POIDocument {
* @throws IOException
*/
public MAPIMessage(String filename) throws IOException {
this(new FileInputStream(new File(filename)));
this(new NPOIFSFileSystem(new File(filename)));
}

/**
@@ -102,14 +102,6 @@ public class MAPIMessage extends POIDocument {
public MAPIMessage(InputStream in) throws IOException {
this(new NPOIFSFileSystem(in));
}
/**
* Constructor for reading MSG Files from a POIFS filesystem
* @param fs
* @throws IOException
*/
public MAPIMessage(POIFSFileSystem fs) throws IOException {
this(fs.getRoot());
}
/**
* Constructor for reading MSG Files from a POIFS filesystem
* @param fs

+ 3
- 2
src/scratchpad/src/org/apache/poi/hsmf/datatypes/MessageSubmissionChunk.java 查看文件

@@ -26,6 +26,7 @@ import java.util.regex.Pattern;

import org.apache.poi.hsmf.datatypes.Types.MAPIType;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;

@@ -85,7 +86,7 @@ public class MessageSubmissionChunk extends Chunk {
// Should be yymmddhhmmssZ
Matcher m = datePatern.matcher(dateS);
if(m.matches()) {
date = Calendar.getInstance();
date = LocaleUtil.getLocaleCalendar();

// work around issues with dates like 1989, which appear as "89" here
int year = Integer.parseInt(m.group(1));
@@ -96,7 +97,7 @@ public class MessageSubmissionChunk extends Chunk {
date.set(Calendar.HOUR_OF_DAY, Integer.parseInt(m.group(4)));
date.set(Calendar.MINUTE, Integer.parseInt(m.group(5)));
date.set(Calendar.SECOND, Integer.parseInt(m.group(6)));
date.set(Calendar.MILLISECOND, 0);
date.clear(Calendar.MILLISECOND);
} else {
logger.log(POILogger.WARN, "Warning - unable to make sense of date " + dateS);
}

+ 2
- 2
src/scratchpad/src/org/apache/poi/hsmf/datatypes/PropertyValue.java 查看文件

@@ -19,9 +19,9 @@ package org.apache.poi.hsmf.datatypes;

import java.math.BigInteger;
import java.util.Calendar;
import java.util.TimeZone;

import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LocaleUtil;

/**
* An instance of a {@link MAPIProperty} inside a {@link PropertiesChunk}.
@@ -218,7 +218,7 @@ public class PropertyValue {
long time = LittleEndian.getLong(data);
time = (time / 10 / 1000) - OFFSET;

Calendar timeC = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
Calendar timeC = LocaleUtil.getLocaleCalendar();
timeC.setTimeInMillis(time);

return timeC;

+ 6
- 5
src/scratchpad/src/org/apache/poi/hsmf/dev/HSMFDump.java 查看文件

@@ -17,7 +17,7 @@

package org.apache.poi.hsmf.dev;

import java.io.FileInputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;

@@ -27,14 +27,14 @@ import org.apache.poi.hsmf.datatypes.MAPIProperty;
import org.apache.poi.hsmf.datatypes.PropertiesChunk;
import org.apache.poi.hsmf.datatypes.PropertyValue;
import org.apache.poi.hsmf.parsers.POIFSChunkParser;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;

/**
* Dumps out the chunk details, and where possible contents
*/
public class HSMFDump {
private POIFSFileSystem fs;
public HSMFDump(POIFSFileSystem fs) {
private NPOIFSFileSystem fs;
public HSMFDump(NPOIFSFileSystem fs) {
this.fs = fs;
}
@@ -84,9 +84,10 @@ public class HSMFDump {
public static void main(String[] args) throws Exception {
for(String file : args) {
POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(file));
NPOIFSFileSystem fs = new NPOIFSFileSystem(new File(file), true);
HSMFDump dump = new HSMFDump(fs);
dump.dump();
fs.close();
}
}
}

+ 13
- 11
src/scratchpad/src/org/apache/poi/hsmf/extractor/OutlookTextExtactor.java 查看文件

@@ -21,7 +21,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.poi.POIOLE2TextExtractor;
import org.apache.poi.hsmf.MAPIMessage;
@@ -31,6 +30,7 @@ import org.apache.poi.hsmf.exceptions.ChunkNotFoundException;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.StringUtil.StringsIterator;

/**
@@ -51,9 +51,6 @@ public class OutlookTextExtactor extends POIOLE2TextExtractor {
public OutlookTextExtactor(DirectoryNode poifsDir) throws IOException {
this(new MAPIMessage(poifsDir));
}
public OutlookTextExtactor(POIFSFileSystem fs) throws IOException {
this(new MAPIMessage(fs));
}
public OutlookTextExtactor(NPOIFSFileSystem fs) throws IOException {
this(new MAPIMessage(fs));
}
@@ -63,11 +60,16 @@ public class OutlookTextExtactor extends POIOLE2TextExtractor {
public static void main(String[] args) throws Exception {
for(String filename : args) {
OutlookTextExtactor extractor = new OutlookTextExtactor(
new NPOIFSFileSystem(new File(filename))
);
System.out.println( extractor.getText() );
extractor.close();
NPOIFSFileSystem poifs = null;
OutlookTextExtactor extractor = null;
try {
poifs = new NPOIFSFileSystem(new File(filename));
extractor = new OutlookTextExtactor(poifs);
System.out.println( extractor.getText() );
} finally {
if (extractor != null) extractor.close();
if (poifs != null) poifs.close();
}
}
}

@@ -120,8 +122,8 @@ public class OutlookTextExtactor extends POIOLE2TextExtractor {
// Date - try two ways to find it
try {
// First try via the proper chunk
SimpleDateFormat f = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss Z");
f.setTimeZone(TimeZone.getTimeZone("UTC"));
SimpleDateFormat f = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss Z", Locale.ROOT);
f.setTimeZone(LocaleUtil.getUserTimeZone());
s.append("Date: " + f.format(msg.getMessageDate().getTime()) + "\n");
} catch(ChunkNotFoundException e) {
try {

+ 6
- 3
src/scratchpad/src/org/apache/poi/hsmf/parsers/POIFSChunkParser.java 查看文件

@@ -40,7 +40,7 @@ import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentInputStream;
import org.apache.poi.poifs.filesystem.DocumentNode;
import org.apache.poi.poifs.filesystem.Entry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;

@@ -52,7 +52,7 @@ import org.apache.poi.util.POILogger;
public final class POIFSChunkParser {
private static POILogger logger = POILogFactory.getLogger(POIFSChunkParser.class);

public static ChunkGroup[] parse(POIFSFileSystem fs) throws IOException {
public static ChunkGroup[] parse(NPOIFSFileSystem fs) throws IOException {
return parse(fs.getRoot());
}
public static ChunkGroup[] parse(DirectoryNode node) throws IOException {
@@ -205,12 +205,15 @@ public final class POIFSChunkParser {
if(chunk != null) {
if(entry instanceof DocumentNode) {
DocumentInputStream inp = null;
try {
DocumentInputStream inp = new DocumentInputStream((DocumentNode)entry);
inp = new DocumentInputStream((DocumentNode)entry);
chunk.readValue(inp);
grouping.record(chunk);
} catch(IOException e) {
logger.log(POILogger.ERROR, "Error reading from part " + entry.getName() + " - " + e.toString());
} finally {
if (inp != null) inp.close();
}
} else {
grouping.record(chunk);

+ 5
- 7
src/scratchpad/src/org/apache/poi/hwpf/model/PlexOfField.java 查看文件

@@ -19,7 +19,7 @@

package org.apache.poi.hwpf.model;

import java.text.MessageFormat;
import java.util.Locale;

import org.apache.poi.util.Internal;

@@ -63,11 +63,9 @@ public class PlexOfField
return fld;
}

public String toString()
{
return MessageFormat.format( "[{0}, {1}) - FLD - 0x{2}; 0x{3}",
getFcStart(), getFcEnd(),
Integer.toHexString( 0xff & fld.getBoundaryType() ),
Integer.toHexString( 0xff & fld.getFlt() ) );
public String toString() {
String str = String.format(Locale.ROOT, "[%d, %d) - FLD - 0x%x; 0x%x"
, getFcStart(), getFcEnd(), fld.getBoundaryType(), fld.getFlt());
return str;
}
}

+ 3
- 4
src/scratchpad/src/org/apache/poi/hwpf/usermodel/DateAndTime.java 查看文件

@@ -22,6 +22,7 @@ import java.util.Calendar;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LocaleUtil;

/**
* This class is used to represent a date and time in a Word document.
@@ -39,7 +40,7 @@ public final class DateAndTime
private short _info2;
private static final BitField _months = BitFieldFactory.getInstance(0xf);
private static final BitField _years = BitFieldFactory.getInstance(0x1ff0);
private static final BitField _weekday = BitFieldFactory.getInstance(0xe000);
// private static final BitField _weekday = BitFieldFactory.getInstance(0xe000);

public DateAndTime()
{
@@ -53,8 +54,7 @@ public final class DateAndTime
public Calendar getDate() {
// TODO Discover if the timezone is stored somewhere else or not
Calendar cal = Calendar.getInstance();
cal.set(
Calendar cal = LocaleUtil.getLocaleCalendar(
_years.getValue(_info2)+1900,
_months.getValue(_info2)-1,
_dom.getValue(_info),
@@ -62,7 +62,6 @@ public final class DateAndTime
_minutes.getValue(_info),
0
);
cal.set(Calendar.MILLISECOND, 0);
return cal;
}


+ 36
- 9
src/scratchpad/testcases/org/apache/poi/hslf/record/TestComment2000.java 查看文件

@@ -18,10 +18,19 @@
package org.apache.poi.hslf.record;


import junit.framework.TestCase;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.ByteArrayOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import org.apache.poi.util.LocaleUtil;
import org.junit.BeforeClass;
import org.junit.Test;

/**
* Tests that Comment2000 works properly.
@@ -29,7 +38,7 @@ import java.util.Date;
*
* @author Nick Burch (nick at torchbox dot com)
*/
public final class TestComment2000 extends TestCase {
public final class TestComment2000 {
// From a real file
private byte[] data_a = new byte[] {
0x0F, 00, 0xE0-256, 0x2E, 0x9C-256, 00, 00, 00,
@@ -82,22 +91,35 @@ public final class TestComment2000 extends TestCase {
0x0A, 00, 00, 00
};

private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
private static SimpleDateFormat sdf;
@BeforeClass
public static void initDateFormat() {
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ROOT);
sdf.setTimeZone(LocaleUtil.getUserTimeZone());
}

@Test
public void testRecordType() {
Comment2000 ca = new Comment2000(data_a, 0, data_a.length);
assertEquals(12000l, ca.getRecordType());
}
public void testAuthor() {
@Test
public void testAuthor() {
Comment2000 ca = new Comment2000(data_a, 0, data_a.length);
assertEquals("Dumbledore", ca.getAuthor());
assertEquals("D", ca.getAuthorInitials());
}
public void testText() {
@Test
public void testText() {
Comment2000 ca = new Comment2000(data_a, 0, data_a.length);
assertEquals("Yes, they certainly are, aren't they!", ca.getText());
}
public void testCommentAtom() throws Exception {
@Test
public void testCommentAtom() throws Exception {
Comment2000 ca = new Comment2000(data_a, 0, data_a.length);
Comment2000Atom c2a = ca.getComment2000Atom();

@@ -107,7 +129,9 @@ public final class TestComment2000 extends TestCase {
Date exp_a = sdf.parse("2006-01-24 10:26:15.205");
assertEquals(exp_a, c2a.getDate());
}
public void testCommentAtomB() throws Exception {
@Test
public void testCommentAtomB() throws Exception {
Comment2000 cb = new Comment2000(data_b, 0, data_b.length);
Comment2000Atom c2b = cb.getComment2000Atom();

@@ -118,7 +142,8 @@ public final class TestComment2000 extends TestCase {
assertEquals(exp_b, c2b.getDate());
}

public void testWrite() throws Exception {
@Test
public void testWrite() throws Exception {
Comment2000 ca = new Comment2000(data_a, 0, data_a.length);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ca.writeOut(baos);
@@ -131,7 +156,8 @@ public final class TestComment2000 extends TestCase {
}

// Change a few things
public void testChange() throws Exception {
@Test
public void testChange() throws Exception {
Comment2000 ca = new Comment2000(data_a, 0, data_a.length);
Comment2000 cb = new Comment2000(data_b, 0, data_b.length);
Comment2000 cn = new Comment2000();
@@ -196,6 +222,7 @@ public final class TestComment2000 extends TestCase {
/**
* A Comment2000 records with missing commentTextAtom
*/
@Test
public void testBug44770() {
byte[] data = {
0x0F, 0x00, (byte)0xE0, 0x2E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, (byte)0xBA, 0x0F,

+ 28
- 9
src/scratchpad/testcases/org/apache/poi/hslf/record/TestComment2000Atom.java 查看文件

@@ -18,17 +18,23 @@
package org.apache.poi.hslf.record;


import junit.framework.TestCase;
import static org.junit.Assert.assertEquals;

import java.io.ByteArrayOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import org.apache.poi.util.LocaleUtil;
import org.junit.BeforeClass;
import org.junit.Test;

/**
* Tests that Comment2000Atom works properly.
*
* @author Nick Burch (nick at torchbox dot com)
*/
public final class TestComment2000Atom extends TestCase {
public final class TestComment2000Atom {
// From a real file
private byte[] data_a = new byte[] {
00, 00, 0xE1-256, 0x2E, 0x1C, 00, 00, 00,
@@ -45,14 +51,22 @@ public final class TestComment2000Atom extends TestCase {
0x0E, 00, 00, 00
};

private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
private static SimpleDateFormat sdf;
@BeforeClass
public static void initDateFormat() {
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ROOT);
sdf.setTimeZone(LocaleUtil.getUserTimeZone());
}

@Test
public void testRecordType() {
Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length);
assertEquals(12001l, ca.getRecordType());
}

public void testGetDate() throws Exception {
@Test
public void testGetDate() throws Exception {
Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length);
Comment2000Atom cb = new Comment2000Atom(data_b, 0, data_b.length);

@@ -65,7 +79,8 @@ public final class TestComment2000Atom extends TestCase {
assertEquals(exp_b, cb.getDate());
}

public void testGetNums() {
@Test
public void testGetNums() {
Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length);
Comment2000Atom cb = new Comment2000Atom(data_b, 0, data_b.length);

@@ -75,7 +90,8 @@ public final class TestComment2000Atom extends TestCase {
assertEquals(5, cb.getNumber());
}

public void testGetPos() {
@Test
public void testGetPos() {
Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length);
Comment2000Atom cb = new Comment2000Atom(data_b, 0, data_b.length);

@@ -88,7 +104,8 @@ public final class TestComment2000Atom extends TestCase {
assertEquals(0x0E, cb.getYOffset());
}

public void testWrite() throws Exception {
@Test
public void testWrite() throws Exception {
Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ca.writeOut(baos);
@@ -101,7 +118,8 @@ public final class TestComment2000Atom extends TestCase {
}

// Create A from scratch
public void testCreate() throws Exception {
@Test
public void testCreate() throws Exception {
Comment2000Atom a = new Comment2000Atom();

// Set number, x and y
@@ -125,7 +143,8 @@ public final class TestComment2000Atom extends TestCase {
}

// Try to turn a into b
public void testChange() throws Exception {
@Test
public void testChange() throws Exception {
Comment2000Atom ca = new Comment2000Atom(data_a, 0, data_a.length);

// Change the number

+ 19
- 4
src/scratchpad/testcases/org/apache/poi/hslf/util/TestSystemTimeUtils.java 查看文件

@@ -18,17 +18,22 @@
package org.apache.poi.hslf.util;


import static org.junit.Assert.assertEquals;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import junit.framework.TestCase;
import org.apache.poi.util.LocaleUtil;
import org.junit.BeforeClass;
import org.junit.Test;

/**
* Tests that SystemTimeUtils works properly.
*
* @author Nick Burch (nick at torchbox dot com)
*/
public final class TestSystemTimeUtils extends TestCase {
public final class TestSystemTimeUtils {
// From real files
private byte[] data_a = new byte[] {
0xD6-256, 07, 01, 00,
@@ -43,9 +48,16 @@ public final class TestSystemTimeUtils extends TestCase {
0x0A, 00, 00, 00
};

private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
private static SimpleDateFormat sdf;
@BeforeClass
public static void initDateFormat() {
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ROOT);
sdf.setTimeZone(LocaleUtil.getUserTimeZone());
}

public void testGetDateA() throws Exception {
@Test
public void testGetDateA() throws Exception {
Date date = SystemTimeUtils.getDate(data_a);

// Is 2006-01-24 (2nd day of week) 10:26:15.205
@@ -54,6 +66,7 @@ public final class TestSystemTimeUtils extends TestCase {
assertEquals(exp, date);
}

@Test
public void testGetDateB() throws Exception {
Date date = SystemTimeUtils.getDate(data_b, 8+4);

@@ -63,6 +76,7 @@ public final class TestSystemTimeUtils extends TestCase {
assertEquals(exp, date);
}

@Test
public void testWriteDateA() throws Exception {
byte[] out_a = new byte[data_a.length];
Date date = sdf.parse("2006-01-24 10:26:15.205");
@@ -73,6 +87,7 @@ public final class TestSystemTimeUtils extends TestCase {
}
}

@Test
public void testWriteDateB() throws Exception {
byte[] out_b = new byte[data_b.length];
// Copy over start and end, ignoring the 16 byte date field in the middle

+ 23
- 25
src/scratchpad/testcases/org/apache/poi/hsmf/AllHSMFTests.java 查看文件

@@ -17,30 +17,28 @@

package org.apache.poi.hsmf;

import junit.framework.Test;
import junit.framework.TestSuite;

import org.apache.poi.hsmf.datatypes.*;
import org.apache.poi.hsmf.datatypes.TestChunkData;
import org.apache.poi.hsmf.datatypes.TestSorters;
import org.apache.poi.hsmf.datatypes.TestTypes;
import org.apache.poi.hsmf.extractor.TestOutlookTextExtractor;
import org.apache.poi.hsmf.parsers.*;

public final class AllHSMFTests {
public static Test suite() {
TestSuite suite = new TestSuite(AllHSMFTests.class.getName());

suite.addTestSuite(TestBasics.class);
suite.addTestSuite(TestBlankFileRead.class);
suite.addTestSuite(TestSimpleFileRead.class);
suite.addTestSuite(TestOutlook30FileRead.class);
suite.addTestSuite(TestFileWithAttachmentsRead.class);
suite.addTestSuite(TestChunkData.class);
suite.addTestSuite(TestTypes.class);
suite.addTestSuite(TestSorters.class);
suite.addTestSuite(TestOutlookTextExtractor.class);
suite.addTestSuite(TestPOIFSChunkParser.class);
suite.addTestSuite(TestMessageSubmissionChunkY2KRead.class);
suite.addTestSuite(TestMessageSubmissionChunk.class);

return suite;
}
import org.apache.poi.hsmf.parsers.TestPOIFSChunkParser;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@Suite.SuiteClasses({
TestBasics.class,
TestBlankFileRead.class,
TestSimpleFileRead.class,
TestOutlook30FileRead.class,
TestFileWithAttachmentsRead.class,
TestChunkData.class,
TestTypes.class,
TestSorters.class,
TestOutlookTextExtractor.class,
TestPOIFSChunkParser.class,
TestMessageSubmissionChunkY2KRead.class,
TestMessageSubmissionChunk.class
})
public class AllHSMFTests {
}

+ 56
- 30
src/scratchpad/testcases/org/apache/poi/hsmf/TestFixedSizedProperties.java 查看文件

@@ -17,19 +17,24 @@

package org.apache.poi.hsmf;

import static org.apache.poi.POITestCase.assertContains;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

import org.apache.poi.POIDataSamples;
import org.apache.poi.POITestCase;
import org.apache.poi.hsmf.datatypes.ChunkBasedPropertyValue;
import org.apache.poi.hsmf.datatypes.Chunks;
import org.apache.poi.hsmf.datatypes.MAPIProperty;
@@ -38,41 +43,58 @@ import org.apache.poi.hsmf.datatypes.PropertyValue.LongPropertyValue;
import org.apache.poi.hsmf.datatypes.PropertyValue.TimePropertyValue;
import org.apache.poi.hsmf.dev.HSMFDump;
import org.apache.poi.hsmf.extractor.OutlookTextExtactor;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.util.LocaleUtil;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

/**
* Tests that we can read fixed sized properties, as well as variable
* ones, for example Submission Dates
*/
public final class TestFixedSizedProperties extends POITestCase {
protected static final String messageSucceeds = "53784_succeeds.msg";
protected static final String messageFails = "53784_fails.msg";
private MAPIMessage mapiMessageSucceeds;
private MAPIMessage mapiMessageFails;
private POIFSFileSystem fsMessageSucceeds;
private POIFSFileSystem fsMessageFails;
private SimpleDateFormat messageDateFormat;
public final class TestFixedSizedProperties {
private static final String messageSucceeds = "53784_succeeds.msg";
private static final String messageFails = "53784_fails.msg";
private static MAPIMessage mapiMessageSucceeds;
private static MAPIMessage mapiMessageFails;
private static NPOIFSFileSystem fsMessageSucceeds;
private static NPOIFSFileSystem fsMessageFails;
private static SimpleDateFormat messageDateFormat;
private static TimeZone userTimeZone;

/**
* Initialize this test, load up the messages.
*/
public TestFixedSizedProperties() throws Exception {
@BeforeClass
public static void initMapi() throws Exception {
POIDataSamples samples = POIDataSamples.getHSMFInstance();
this.mapiMessageSucceeds = new MAPIMessage(
samples.openResourceAsStream(messageSucceeds));
this.mapiMessageFails = new MAPIMessage(
samples.openResourceAsStream(messageFails));
this.fsMessageSucceeds = new POIFSFileSystem(new FileInputStream(samples.getFile(messageSucceeds)));
this.fsMessageFails = new POIFSFileSystem(new FileInputStream(samples.getFile(messageFails)));
fsMessageSucceeds = new NPOIFSFileSystem(samples.getFile(messageSucceeds));
fsMessageFails = new NPOIFSFileSystem(samples.getFile(messageFails));

mapiMessageSucceeds = new MAPIMessage(fsMessageSucceeds);
mapiMessageFails = new MAPIMessage(fsMessageFails);
messageDateFormat = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss");
messageDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
messageDateFormat = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss", Locale.ROOT);
messageDateFormat.setTimeZone(LocaleUtil.TIMEZONE_UTC);

userTimeZone = LocaleUtil.getUserTimeZone();
LocaleUtil.setUserTimeZone(LocaleUtil.TIMEZONE_UTC);
}
@AfterClass
public static void closeFS() throws Exception {
LocaleUtil.setUserTimeZone(userTimeZone);
fsMessageSucceeds.close();
fsMessageFails.close();
}
/**
* Check we can find a sensible number of properties on a few
* of our test files
*/
@Test
public void testPropertiesFound() throws Exception {
Map<MAPIProperty,List<PropertyValue>> props;
@@ -86,6 +108,7 @@ public final class TestFixedSizedProperties extends POITestCase {
/**
* Check we find properties of a variety of different types
*/
@Test
public void testPropertyValueTypes() throws Exception {
Chunks mainChunks = mapiMessageSucceeds.getMainChunks();
@@ -116,30 +139,32 @@ public final class TestFixedSizedProperties extends POITestCase {

/**
* Test to see if we can read the Date Chunk with OutlookTextExtractor.
* TODO Work out why the Fri 22nd vs Monday 25th problem is occurring and fix
*/
public void DISABLEDtestReadMessageDateSucceedsWithOutlookTextExtractor() {
@Test
// @Ignore("TODO Work out why the Fri 22nd vs Monday 25th problem is occurring and fix")
public void testReadMessageDateSucceedsWithOutlookTextExtractor() throws Exception {
OutlookTextExtactor ext = new OutlookTextExtactor(mapiMessageSucceeds);
String text = ext.getText();
assertContains(text, "Date: Fri, 22 Jun 2012 21:32:54\n");
assertContains(text, "Date: Fri, 22 Jun 2012 18:32:54 +0000\n");
ext.close();
}

/**
* Test to see if we can read the Date Chunk with OutlookTextExtractor.
* TODO Work out why the Thu 21st vs Monday 25th problem is occurring and fix
*/
public void DISABLEDtestReadMessageDateFailsWithOutlookTextExtractor() {
@Test
// @Ignore("TODO Work out why the Thu 21st vs Monday 25th problem is occurring and fix")
public void testReadMessageDateFailsWithOutlookTextExtractor() throws Exception {
OutlookTextExtactor ext = new OutlookTextExtactor(mapiMessageFails);
String text = ext.getText();
assertContains(text, "Date: Thu, 21 Jun 2012 17:14:04\n");
assertContains(text, "Date: Thu, 21 Jun 2012 14:14:04 +0000\n");
ext.close();
}

/**
* Test to see if we can read the Date Chunk with HSMFDump.
* @throws IOException
*/
@Test
public void testReadMessageDateSucceedsWithHSMFDump() throws IOException {
PrintStream stream = new PrintStream(new ByteArrayOutputStream());
HSMFDump dump = new HSMFDump(fsMessageSucceeds);
@@ -148,8 +173,8 @@ public final class TestFixedSizedProperties extends POITestCase {

/**
* Test to see if we can read the Date Chunk with HSMFDump.
* @throws Exception
*/
@Test
public void testReadMessageDateFailsWithHSMFDump() throws Exception {
PrintStream stream = new PrintStream(new ByteArrayOutputStream());
HSMFDump dump = new HSMFDump(fsMessageFails);
@@ -159,6 +184,7 @@ public final class TestFixedSizedProperties extends POITestCase {
/**
* Will be based on the ClientSubmit time
*/
@Test
public void testClientSubmitTime() throws Exception {
// Check via the message date
Calendar clientSubmitTime = mapiMessageSucceeds.getMessageDate();

+ 66
- 46
src/scratchpad/testcases/org/apache/poi/hsmf/extractor/TestOutlookTextExtractor.java 查看文件

@@ -17,33 +17,47 @@

package org.apache.poi.hsmf.extractor;

import static org.apache.poi.POITestCase.assertContains;
import static org.apache.poi.POITestCase.assertNotContained;
import static org.junit.Assert.assertEquals;

import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.poi.POIDataSamples;
import org.apache.poi.POITestCase;
import org.apache.poi.hsmf.MAPIMessage;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.util.LocaleUtil;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

/**
* Tests to verify that the text extractor works
*/
public final class TestOutlookTextExtractor extends POITestCase {
private POIDataSamples samples;

public TestOutlookTextExtractor() throws IOException {
samples = POIDataSamples.getHSMFInstance();
}
public final class TestOutlookTextExtractor {
private POIDataSamples samples = POIDataSamples.getHSMFInstance();
private static TimeZone userTZ;
@BeforeClass
public static void initTimeZone() {
userTZ = LocaleUtil.getUserTimeZone();
LocaleUtil.setUserTimeZone(LocaleUtil.TIMEZONE_UTC);
}
@AfterClass
public static void resetTimeZone() {
LocaleUtil.setUserTimeZone(userTZ);
}
@Test
public void testQuick() throws Exception {
POIFSFileSystem simple = new POIFSFileSystem(
new FileInputStream(samples.getFile("quick.msg"))
);
MAPIMessage msg = new MAPIMessage(simple);
NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile("quick.msg"), true);
MAPIMessage msg = new MAPIMessage(poifs);
OutlookTextExtactor ext = new OutlookTextExtactor(msg);
String text = ext.getText();
@@ -54,20 +68,21 @@ public final class TestOutlookTextExtractor extends POITestCase {
assertEquals(-1, text.indexOf("BCC:"));
assertEquals(-1, text.indexOf("Attachment:"));
assertContains(text, "Subject: Test the content transformer\n");
Calendar cal = new GregorianCalendar(2007, 5, 14, 9, 42, 55);
SimpleDateFormat f = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss Z");
f.setTimeZone(TimeZone.getTimeZone("UTC"));
Calendar cal = LocaleUtil.getLocaleCalendar(2007, 5, 14, 9, 42, 55);
SimpleDateFormat f = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss Z", Locale.ROOT);
f.setTimeZone(LocaleUtil.getUserTimeZone());
String dateText = f.format(cal.getTime());
assertContains(text, "Date: " + dateText + "\n");
assertContains(text, "The quick brown fox jumps over the lazy dog");

ext.close();
poifs.close();
}
@Test
public void testSimple() throws Exception {
MAPIMessage msg = new MAPIMessage(new POIFSFileSystem(
new FileInputStream(samples.getFile("simple_test_msg.msg"))
));
NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile("simple_test_msg.msg"), true);
MAPIMessage msg = new MAPIMessage(poifs);
OutlookTextExtactor ext = new OutlookTextExtactor(msg);
String text = ext.getText();
@@ -81,25 +96,30 @@ public final class TestOutlookTextExtractor extends POITestCase {
assertContains(text, "This is a test message.");

ext.close();
poifs.close();
}

@Test
public void testConstructors() throws Exception {
OutlookTextExtactor ext = new OutlookTextExtactor(new FileInputStream(
samples.getFile("simple_test_msg.msg")));
FileInputStream fis = new FileInputStream(samples.getFile("simple_test_msg.msg"));
OutlookTextExtactor ext = new OutlookTextExtactor(fis);
String inp = ext.getText();
ext.close();
fis.close();

ext = new OutlookTextExtactor(new POIFSFileSystem(new FileInputStream(
samples.getFile("simple_test_msg.msg"))));
String poifs = ext.getText();
NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile("simple_test_msg.msg"), true);
ext = new OutlookTextExtactor(poifs);
String poifsTxt = ext.getText();
ext.close();
poifs.close();

ext = new OutlookTextExtactor(new MAPIMessage(new FileInputStream(
samples.getFile("simple_test_msg.msg"))));
fis = new FileInputStream(samples.getFile("simple_test_msg.msg"));
ext = new OutlookTextExtactor(new MAPIMessage(fis));
String mapi = ext.getText();
ext.close();
fis.close();

assertEquals(inp, poifs);
assertEquals(inp, poifsTxt);
assertEquals(inp, mapi);
}
@@ -107,6 +127,7 @@ public final class TestOutlookTextExtractor extends POITestCase {
* Test that we correctly handle multiple To+CC+BCC
* recipients in an email we sent.
*/
@Test
public void testSentWithMulipleRecipients() throws Exception {
// To: 'Ashutosh Dandavate' <ashutosh.dandavate@alfresco.com>,
// 'Paul Holmes-Higgin' <paul.hh@alfresco.com>,
@@ -120,9 +141,8 @@ public final class TestOutlookTextExtractor extends POITestCase {
"example_sent_regular.msg", "example_sent_unicode.msg"
};
for(String file : files) {
MAPIMessage msg = new MAPIMessage(new POIFSFileSystem(
new FileInputStream(samples.getFile(file))
));
NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile(file), true);
MAPIMessage msg = new MAPIMessage(poifs);
OutlookTextExtactor ext = new OutlookTextExtactor(msg);
String text = ext.getText();
@@ -139,6 +159,7 @@ public final class TestOutlookTextExtractor extends POITestCase {
assertContains(text, "The quick brown fox jumps over the lazy dog");

ext.close();
poifs.close();
}
}
@@ -146,6 +167,7 @@ public final class TestOutlookTextExtractor extends POITestCase {
* Test that we correctly handle multiple To+CC
* recipients in an email we received.
*/
@Test
public void testReceivedWithMultipleRecipients() throws Exception {
// To: 'Ashutosh Dandavate' <ashutosh.dandavate@alfresco.com>,
// 'Paul Holmes-Higgin' <paul.hh@alfresco.com>,
@@ -159,9 +181,9 @@ public final class TestOutlookTextExtractor extends POITestCase {
"example_received_regular.msg", "example_received_unicode.msg"
};
for(String file : files) {
MAPIMessage msg = new MAPIMessage(new POIFSFileSystem(
new FileInputStream(samples.getFile(file))
));
NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile(file), true);
MAPIMessage msg = new MAPIMessage(poifs);
OutlookTextExtactor ext = new OutlookTextExtactor(msg);
String text = ext.getText();
@@ -177,6 +199,7 @@ public final class TestOutlookTextExtractor extends POITestCase {
assertContains(text, "The quick brown fox jumps over the lazy dog");

ext.close();
poifs.close();
}
}
@@ -184,10 +207,8 @@ public final class TestOutlookTextExtractor extends POITestCase {
* See also {@link org.apache.poi.extractor.TestExtractorFactory#testEmbeded()}
*/
public void testWithAttachments() throws Exception {
POIFSFileSystem simple = new POIFSFileSystem(
new FileInputStream(samples.getFile("attachment_test_msg.msg"))
);
MAPIMessage msg = new MAPIMessage(simple);
NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile("attachment_test_msg.msg"), true);
MAPIMessage msg = new MAPIMessage(poifs);
OutlookTextExtactor ext = new OutlookTextExtactor(msg);
// Check the normal bits
@@ -207,13 +228,12 @@ public final class TestOutlookTextExtractor extends POITestCase {
// TestExtractorFactory

ext.close();
poifs.close();
}
public void testWithAttachedMessage() throws Exception {
POIFSFileSystem simple = new POIFSFileSystem(
new FileInputStream(samples.getFile("58214_with_attachment.msg"))
);
MAPIMessage msg = new MAPIMessage(simple);
NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile("58214_with_attachment.msg"), true);
MAPIMessage msg = new MAPIMessage(poifs);
OutlookTextExtactor ext = new OutlookTextExtactor(msg);
String text = ext.getText();
@@ -226,13 +246,12 @@ public final class TestOutlookTextExtractor extends POITestCase {
assertNotContained(text, "Lorem ipsum dolor sit");
ext.close();
poifs.close();
}
public void testEncodings() throws Exception {
POIFSFileSystem simple = new POIFSFileSystem(
new FileInputStream(samples.getFile("chinese-traditional.msg"))
);
MAPIMessage msg = new MAPIMessage(simple);
NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile("chinese-traditional.msg"), true);
MAPIMessage msg = new MAPIMessage(poifs);
OutlookTextExtactor ext = new OutlookTextExtactor(msg);
String text = ext.getText();
@@ -245,5 +264,6 @@ public final class TestOutlookTextExtractor extends POITestCase {
assertContains(text, "( MSG \u683c\u5f0f\u6e2c\u8a66 )");

ext.close();
poifs.close();
}
}

+ 52
- 78
src/scratchpad/testcases/org/apache/poi/hsmf/parsers/TestPOIFSChunkParser.java 查看文件

@@ -17,13 +17,16 @@

package org.apache.poi.hsmf.parsers;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;

import org.apache.poi.POIDataSamples;
import org.apache.poi.hsmf.MAPIMessage;
import org.apache.poi.hsmf.datatypes.AttachmentChunks;
import org.apache.poi.hsmf.datatypes.ChunkGroup;
@@ -35,25 +38,19 @@ import org.apache.poi.hsmf.datatypes.RecipientChunks.RecipientChunksSorter;
import org.apache.poi.hsmf.datatypes.StringChunk;
import org.apache.poi.hsmf.datatypes.Types;
import org.apache.poi.hsmf.exceptions.ChunkNotFoundException;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.POIDataSamples;

import junit.framework.TestCase;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;

/**
* Tests to verify that the chunk parser works properly
*/
public final class TestPOIFSChunkParser extends TestCase {
private POIDataSamples samples;
public final class TestPOIFSChunkParser {
private POIDataSamples samples = POIDataSamples.getHSMFInstance();

public TestPOIFSChunkParser() throws IOException {
samples = POIDataSamples.getHSMFInstance();
}
public void testFindsCore() throws IOException {
POIFSFileSystem simple = new POIFSFileSystem(
new FileInputStream(samples.getFile("quick.msg"))
);
@Test
public void testFindsCore() throws Exception {
NPOIFSFileSystem simple = new NPOIFSFileSystem(samples.getFile("quick.msg"), true);
// Check a few core things are present
simple.getRoot().getEntry(
@@ -65,29 +62,20 @@ public final class TestPOIFSChunkParser extends TestCase {
// Now load the file
MAPIMessage msg = new MAPIMessage(simple);
try {
assertEquals("Kevin Roast", msg.getDisplayTo());
assertEquals("Kevin Roast", msg.getDisplayFrom());
assertEquals("Test the content transformer", msg.getSubject());
} catch(ChunkNotFoundException e) {
fail();
}
assertEquals("Kevin Roast", msg.getDisplayTo());
assertEquals("Kevin Roast", msg.getDisplayFrom());
assertEquals("Test the content transformer", msg.getSubject());
// Check date too
try {
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Calendar c = msg.getMessageDate();
assertEquals( "2007-06-14 09:42:55", f.format(c.getTime()) );
} catch(ChunkNotFoundException e) {
fail();
}
Calendar calExp = LocaleUtil.getLocaleCalendar(2007,5,14,9,42,55);
Calendar calAct = msg.getMessageDate();
assertEquals( calExp, calAct );

simple.close();
}
public void testFindsRecips() throws IOException, ChunkNotFoundException {
POIFSFileSystem simple = new POIFSFileSystem(
new FileInputStream(samples.getFile("quick.msg"))
);
NPOIFSFileSystem simple = new NPOIFSFileSystem(samples.getFile("quick.msg"), true);
simple.getRoot().getEntry("__recip_version1.0_#00000000");

@@ -121,11 +109,12 @@ public final class TestPOIFSChunkParser extends TestCase {
assertEquals("kevin.roast@alfresco.org", msg.getRecipientDetailsChunks()[0].recipientSMTPChunk.getValue());
assertEquals("/O=HOSTEDSERVICE2/OU=FIRST ADMINISTRATIVE GROUP/CN=RECIPIENTS/CN=Kevin.roast@ben",
msg.getRecipientDetailsChunks()[0].recipientEmailChunk.getValue());
simple.close();
// Now look at another message
msg = new MAPIMessage(new POIFSFileSystem(
new FileInputStream(samples.getFile("simple_test_msg.msg"))
));
simple = new NPOIFSFileSystem(samples.getFile("simple_test_msg.msg"), true);
msg = new MAPIMessage(simple);
assertNotNull(msg.getRecipientDetailsChunks());
assertEquals(1, msg.getRecipientDetailsChunks().length);
@@ -134,12 +123,12 @@ public final class TestPOIFSChunkParser extends TestCase {
assertEquals(null, msg.getRecipientDetailsChunks()[0].recipientNameChunk);
assertEquals("travis@overwrittenstack.com", msg.getRecipientDetailsChunks()[0].recipientEmailChunk.getValue());
assertEquals("travis@overwrittenstack.com", msg.getRecipientEmailAddress());
simple.close();
}
public void testFindsMultipleRecipients() throws IOException, ChunkNotFoundException {
POIFSFileSystem multiple = new POIFSFileSystem(
new FileInputStream(samples.getFile("example_received_unicode.msg"))
);
NPOIFSFileSystem multiple = new NPOIFSFileSystem(samples.getFile("example_received_unicode.msg"), true);
multiple.getRoot().getEntry("__recip_version1.0_#00000000");
multiple.getRoot().getEntry("__recip_version1.0_#00000001");
@@ -225,12 +214,12 @@ public final class TestPOIFSChunkParser extends TestCase {
assertEquals("nickb@alfresco.com", msg.getRecipientEmailAddressList()[3]);
assertEquals("nick.burch@alfresco.com", msg.getRecipientEmailAddressList()[4]);
assertEquals("roy.wetherall@alfresco.com", msg.getRecipientEmailAddressList()[5]);
multiple.close();
}
public void testFindsNameId() throws IOException {
POIFSFileSystem simple = new POIFSFileSystem(
new FileInputStream(samples.getFile("quick.msg"))
);
NPOIFSFileSystem simple = new NPOIFSFileSystem(samples.getFile("quick.msg"), true);
simple.getRoot().getEntry("__nameid_version1.0");

@@ -247,15 +236,13 @@ public final class TestPOIFSChunkParser extends TestCase {
MAPIMessage msg = new MAPIMessage(simple);
assertNotNull(msg.getNameIdChunks());
assertEquals(10, msg.getNameIdChunks().getAll().length);
simple.close();
}
public void testFindsAttachments() throws IOException {
POIFSFileSystem with = new POIFSFileSystem(
new FileInputStream(samples.getFile("attachment_test_msg.msg"))
);
POIFSFileSystem without = new POIFSFileSystem(
new FileInputStream(samples.getFile("quick.msg"))
);
public void testFindsAttachments() throws Exception {
NPOIFSFileSystem with = new NPOIFSFileSystem(samples.getFile("attachment_test_msg.msg"), true);
NPOIFSFileSystem without = new NPOIFSFileSystem(samples.getFile("quick.msg"), true);
AttachmentChunks attachment;
@@ -284,15 +271,8 @@ public final class TestPOIFSChunkParser extends TestCase {
// Check raw details on one without
try {
without.getRoot().getEntry("__attach_version1.0_#00000000");
fail();
} catch(FileNotFoundException e) {}
try {
without.getRoot().getEntry("__attach_version1.0_#00000001");
fail();
} catch(FileNotFoundException e) {}
assertFalse(without.getRoot().hasEntry("__attach_version1.0_#00000000"));
assertFalse(without.getRoot().hasEntry("__attach_version1.0_#00000001"));
// One with, from the top
MAPIMessage msgWith = new MAPIMessage(with);
@@ -309,14 +289,9 @@ public final class TestPOIFSChunkParser extends TestCase {
assertEquals(89, attachment.attachData.getValue().length);
// Plus check core details are there
try {
assertEquals("'nicolas1.23456@free.fr'", msgWith.getDisplayTo());
assertEquals("Nicolas1 23456", msgWith.getDisplayFrom());
assertEquals("test pi\u00e8ce jointe 1", msgWith.getSubject());
} catch(ChunkNotFoundException e) {
fail();
}
assertEquals("'nicolas1.23456@free.fr'", msgWith.getDisplayTo());
assertEquals("Nicolas1 23456", msgWith.getDisplayFrom());
assertEquals("test pi\u00e8ce jointe 1", msgWith.getSubject());
// One without, from the top
MAPIMessage msgWithout = new MAPIMessage(without);
@@ -325,13 +300,12 @@ public final class TestPOIFSChunkParser extends TestCase {
assertEquals(0, msgWithout.getAttachmentFiles().length);
// But has core details
try {
assertEquals("Kevin Roast", msgWithout.getDisplayTo());
assertEquals("Kevin Roast", msgWithout.getDisplayFrom());
assertEquals("Test the content transformer", msgWithout.getSubject());
} catch(ChunkNotFoundException e) {
fail();
}
assertEquals("Kevin Roast", msgWithout.getDisplayTo());
assertEquals("Kevin Roast", msgWithout.getDisplayFrom());
assertEquals("Test the content transformer", msgWithout.getSubject());

without.close();
with.close();
}
/**
@@ -340,13 +314,13 @@ public final class TestPOIFSChunkParser extends TestCase {
* such as "Olk10SideProps_0001"
*/
public void testOlk10SideProps() throws Exception {
POIFSFileSystem poifs = new POIFSFileSystem(
new FileInputStream(samples.getFile("51873.msg"))
);
NPOIFSFileSystem poifs = new NPOIFSFileSystem(samples.getFile("51873.msg"), true);
MAPIMessage msg = new MAPIMessage(poifs);

// Check core details came through
assertEquals("bubba@bubbasmith.com", msg.getDisplayTo());
assertEquals("Test with Olk10SideProps_ Chunk", msg.getSubject());
poifs.close();
}
}

+ 17
- 24
src/testcases/org/apache/poi/hpsf/basic/TestWrite.java 查看文件

@@ -38,6 +38,7 @@ import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.apache.poi.POIDataSamples;
@@ -117,8 +118,8 @@ public class TestWrite
*
* @exception IOException if an I/O exception occurs
*/
@Test
public void withoutAFormatID() throws IOException
@Test(expected=NoFormatIDException.class)
public void withoutAFormatID() throws Exception
{
final File filename = TempFile.createTempFile(POI_FS, ".doc");

@@ -131,8 +132,7 @@ public class TestWrite
ps.addSection(new MutableSection());

/* Write it to a POIFS and the latter to disk: */
try
{
try {
final ByteArrayOutputStream psStream = new ByteArrayOutputStream();
ps.write(psStream);
psStream.close();
@@ -140,15 +140,8 @@ public class TestWrite
poiFs.createDocument(new ByteArrayInputStream(streamData),
SummaryInformation.DEFAULT_STREAM_NAME);
poiFs.writeFilesystem(out);
out.close();
fail("Should have thrown a NoFormatIDException.");
}
catch (Exception ex)
{
assertTrue(ex instanceof NoFormatIDException);
}
finally
{
} finally {
poiFs.close();
out.close();
}
}
@@ -185,6 +178,7 @@ public class TestWrite
poiFs.createDocument(new ByteArrayInputStream(streamData),
SummaryInformation.DEFAULT_STREAM_NAME);
poiFs.writeFilesystem(out);
poiFs.close();
out.close();

/* Read the POIFS: */
@@ -236,6 +230,7 @@ public class TestWrite
poiFs.createDocument(ps.toInputStream(),
SummaryInformation.DEFAULT_STREAM_NAME);
poiFs.writeFilesystem(out);
poiFs.close();
out.close();

/* Read the POIFS: */
@@ -317,6 +312,7 @@ public class TestWrite

poiFs.createDocument(ps.toInputStream(), STREAM_NAME);
poiFs.writeFilesystem(out);
poiFs.close();
out.close();

/* Read the POIFS: */
@@ -755,6 +751,7 @@ public class TestWrite
psf1[i].getName());
poiFs.writeFilesystem(out);
}
poiFs.close();
out.close();


@@ -805,6 +802,7 @@ public class TestWrite
Integer.valueOf(codepage));
poiFs.createDocument(ps1.toInputStream(), "Test");
poiFs.writeFilesystem(out);
poiFs.close();
out.close();

/* Read back: */
@@ -1010,7 +1008,7 @@ public class TestWrite
// or via sun.misc.Cleaner, but this is regarded unsafe
// http://stackoverflow.com/questions/2972986
// http://bugs.java.com/view_bug.do?bug_id=4724038
Assume.assumeFalse(System.getProperty("os.name").toLowerCase().contains("win"));
Assume.assumeFalse(System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("win"));
throw e;
}
}
@@ -1022,7 +1020,7 @@ public class TestWrite
* @throws IOException
* @throws HPSFException
*/
@Test
@Test(expected=IllegalPropertySetDataException.class)
public void dictionaryWithInvalidCodepage() throws IOException, HPSFException
{
final File copy = TempFile.createTempFile("Test-HPSF", "ole2");
@@ -1039,8 +1037,7 @@ public class TestWrite
m.put(Long.valueOf(2), "String 2");
m.put(Long.valueOf(3), "String 3");

try
{
try {
s.setDictionary(m);
s.setFormatID(SectionIDMap.DOCUMENT_SUMMARY_INFORMATION_ID[0]);
int codepage = 12345;
@@ -1048,13 +1045,9 @@ public class TestWrite
Integer.valueOf(codepage));
poiFs.createDocument(ps1.toInputStream(), "Test");
poiFs.writeFilesystem(out);
} finally {
poiFs.close();
out.close();
fail("This testcase did not detect the invalid codepage value.");
}
catch (IllegalPropertySetDataException ex)
{
out.close();
assertTrue(true);
}
}

@@ -1069,7 +1062,7 @@ public class TestWrite
{
final String charSetName = System.getProperty("file.encoding");
final Charset charSet = Charset.forName(charSetName);
return charSet.displayName();
return charSet.displayName(Locale.ROOT);
}



+ 263
- 260
src/testcases/org/apache/poi/hpsf/basic/TestWriteWellKnown.java 查看文件

@@ -17,6 +17,12 @@

package org.apache.poi.hpsf.basic;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
@@ -26,45 +32,47 @@ import java.io.IOException;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import junit.framework.TestCase;

import org.apache.poi.POIDataSamples;
import org.apache.poi.hpsf.*;
import org.apache.poi.hpsf.CustomProperties;
import org.apache.poi.hpsf.CustomProperty;
import org.apache.poi.hpsf.DocumentSummaryInformation;
import org.apache.poi.hpsf.MarkUnsupportedException;
import org.apache.poi.hpsf.MutableProperty;
import org.apache.poi.hpsf.MutableSection;
import org.apache.poi.hpsf.NoPropertySetStreamException;
import org.apache.poi.hpsf.PropertySet;
import org.apache.poi.hpsf.PropertySetFactory;
import org.apache.poi.hpsf.SummaryInformation;
import org.apache.poi.hpsf.UnexpectedPropertySetTypeException;
import org.apache.poi.hpsf.Variant;
import org.apache.poi.hpsf.VariantSupport;
import org.apache.poi.hpsf.WritingNotSupportedException;
import org.apache.poi.hpsf.wellknown.SectionIDMap;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.DocumentInputStream;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.TempFile;
import org.junit.BeforeClass;
import org.junit.Test;

/**
* <p>Tests HPSF's high-level writing functionality for the well-known property
* set "SummaryInformation" and "DocumentSummaryInformation".</p>
*
* @author Rainer Klute
* <a href="mailto:klute@rainer-klute.de">klute@rainer-klute.de</a>
*/
public class TestWriteWellKnown extends TestCase {
public class TestWriteWellKnown {

private static final String POI_FS = "TestWriteWellKnown.doc";


/**
* @see TestCase#setUp()
*/
@Override
public void setUp()
{
@BeforeClass
public static void setUp() {
VariantSupport.setLogUnsupportedTypes(false);
}



/**
* <p>This test method checks whether DocumentSummary information streams
* can be read. This is done by opening all "Test*" files in the 'poifs' directrory
@@ -72,6 +80,7 @@ public class TestWriteWellKnown extends TestCase {
* the document summary information stream in the root directory and calling
* its get... methods.</p>
*/
@Test
public void testReadDocumentSummaryInformation()
throws FileNotFoundException, IOException,
NoPropertySetStreamException, MarkUnsupportedException,
@@ -88,36 +97,18 @@ public class TestWriteWellKnown extends TestCase {
}
});

for (int i = 0; i < docs.length; i++)
{
for (final File doc : docs) {
NPOIFSFileSystem poifs = null;
try {
final File doc = docs[i];
/* Read a test document <em>doc</em> into a POI filesystem. */
final POIFSFileSystem poifs = new POIFSFileSystem(new FileInputStream(doc));
poifs = new NPOIFSFileSystem(doc, true);
final DirectoryEntry dir = poifs.getRoot();
DocumentEntry dsiEntry = null;
try
{
dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
}
catch (FileNotFoundException ex)
{
/*
* A missing document summary information stream is not an error
* and therefore silently ignored here.
*/
}
/*
* If there is a document summry information stream, read it from
* the POI filesystem.
*/
if (dsiEntry != null)
{
final DocumentInputStream dis = new DocumentInputStream(dsiEntry);
final PropertySet ps = new PropertySet(dis);
final DocumentSummaryInformation dsi = new DocumentSummaryInformation(ps);
if (dir.hasEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME)) {
final DocumentSummaryInformation dsi = getDocumentSummaryInformation(poifs);
/* Execute the get... methods. */
dsi.getByteCount();
@@ -139,12 +130,72 @@ public class TestWriteWellKnown extends TestCase {
dsi.getSlideCount();
}
} catch (Exception e) {
throw new IOException("While handling file " + docs[i], e);
throw new IOException("While handling file " + doc, e);
} finally {
if (poifs != null) poifs.close();
}
}
}


static final String P_APPLICATION_NAME = "ApplicationName";
static final String P_AUTHOR = "Author";
static final int P_CHAR_COUNT = 4712;
static final String P_COMMENTS = "Comments";
static final Date P_CREATE_DATE_TIME;
static final long P_EDIT_TIME = 4713 * 1000 * 10;
static final String P_KEYWORDS = "Keywords";
static final String P_LAST_AUTHOR = "LastAuthor";
static final Date P_LAST_PRINTED;
static final Date P_LAST_SAVE_DATE_TIME;
static final int P_PAGE_COUNT = 4714;
static final String P_REV_NUMBER = "RevNumber";
static final int P_SECURITY = 1;
static final String P_SUBJECT = "Subject";
static final String P_TEMPLATE = "Template";
// FIXME (byte array properties not yet implemented): static final byte[] P_THUMBNAIL = new byte[123];
static final String P_TITLE = "Title";
static final int P_WORD_COUNT = 4715;

static final int P_BYTE_COUNT = 4716;
static final String P_CATEGORY = "Category";
static final String P_COMPANY = "Company";
// FIXME (byte array properties not yet implemented): static final byte[] P_DOCPARTS = new byte[123];
// FIXME (byte array properties not yet implemented): static final byte[] P_HEADING_PAIR = new byte[123];
static final int P_HIDDEN_COUNT = 4717;
static final int P_LINE_COUNT = 4718;
static final boolean P_LINKS_DIRTY = true;
static final String P_MANAGER = "Manager";
static final int P_MM_CLIP_COUNT = 4719;
static final int P_NOTE_COUNT = 4720;
static final int P_PAR_COUNT = 4721;
static final String P_PRESENTATION_FORMAT = "PresentationFormat";
static final boolean P_SCALE = false;
static final int P_SLIDE_COUNT = 4722;
static final Date now = new Date();

static final Integer POSITIVE_INTEGER = new Integer(2222);
static final Long POSITIVE_LONG = new Long(3333);
static final Double POSITIVE_DOUBLE = new Double(4444);
static final Integer NEGATIVE_INTEGER = new Integer(2222);
static final Long NEGATIVE_LONG = new Long(3333);
static final Double NEGATIVE_DOUBLE = new Double(4444);

static final Integer MAX_INTEGER = new Integer(Integer.MAX_VALUE);
static final Integer MIN_INTEGER = new Integer(Integer.MIN_VALUE);
static final Long MAX_LONG = new Long(Long.MAX_VALUE);
static final Long MIN_LONG = new Long(Long.MIN_VALUE);
static final Double MAX_DOUBLE = new Double(Double.MAX_VALUE);
static final Double MIN_DOUBLE = new Double(Double.MIN_VALUE);

static {
Calendar cal = LocaleUtil.getLocaleCalendar(2000, 6, 6, 6, 6, 6);
P_CREATE_DATE_TIME = cal.getTime();
cal.set(2001, 7, 7, 7, 7, 7);
P_LAST_PRINTED = cal.getTime();
cal.set(2002, 8, 8, 8, 8, 8);
P_LAST_SAVE_DATE_TIME = cal.getTime();
}
/**
* <p>This test method test the writing of properties in the well-known
* property set streams "SummaryInformation" and
@@ -192,19 +243,35 @@ public class TestWriteWellKnown extends TestCase {
* @throws UnexpectedPropertySetTypeException
* @throws WritingNotSupportedException
*/
public void testWriteWellKnown() throws IOException,
NoPropertySetStreamException, MarkUnsupportedException,
UnexpectedPropertySetTypeException, WritingNotSupportedException
{
@Test
public void testWriteWellKnown() throws Exception {
POIDataSamples _samples = POIDataSamples.getHPSFInstance();
final File dataDir = _samples.getFile("");
final File doc1 = new File(dataDir, POI_FS);

final File doc1 = TempFile.createTempFile("POI_HPSF_Test1.", ".tmp");
final File doc2 = TempFile.createTempFile("POI_HPSF_Test2.", ".tmp");
final File doc3 = TempFile.createTempFile("POI_HPSF_Test3.", ".tmp");

FileInputStream fis = new FileInputStream(_samples.getFile(POI_FS));
FileOutputStream fos = new FileOutputStream(doc1);
IOUtils.copy(fis, fos);
fos.close();
fis.close();
CustomProperties cps1 = write1stFile(doc1, doc2);
CustomProperties cps2 = write2ndFile(doc2, doc3);
write3rdFile(doc3, null);
assertEquals(cps1, cps2);
}
/*
* Write all properties supported by HPSF to the summary information
* (e.g. author, edit date, application name) and to the document
* summary information (e.g. company, manager).
*/
private static CustomProperties write1stFile(File fileIn, File fileOut) throws Exception {
/* Read a test document <em>doc1</em> into a POI filesystem. */
POIFSFileSystem poifs = new POIFSFileSystem(new FileInputStream(doc1));
DirectoryEntry dir = poifs.getRoot();
DocumentEntry siEntry = (DocumentEntry) dir.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
DocumentEntry dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
NPOIFSFileSystem poifs = new NPOIFSFileSystem(fileIn, false);

/*
* Read the summary information stream and the document summary
@@ -216,76 +283,8 @@ public class TestWriteWellKnown extends TestCase {
* explicitly (overwriting the former contents). Then the POI filesystem
* should be saved to a file.
*/
DocumentInputStream dis = new DocumentInputStream(siEntry);
PropertySet ps = new PropertySet(dis);
SummaryInformation si = new SummaryInformation(ps);
dis = new DocumentInputStream(dsiEntry);
ps = new PropertySet(dis);
DocumentSummaryInformation dsi = new DocumentSummaryInformation(ps);

/*
* Write all properties supported by HPSF to the summary information
* (e.g. author, edit date, application name) and to the document
* summary information (e.g. company, manager).
*/
Calendar cal = new GregorianCalendar(Locale.ROOT);
cal.set(2000, 6, 6, 6, 6, 6);
final long time1 = cal.getTimeInMillis();
cal.set(2001, 7, 7, 7, 7, 7);
final long time2 = cal.getTimeInMillis();
cal.set(2002, 8, 8, 8, 8, 8);
final long time3 = cal.getTimeInMillis();

int nr = 4711;
final String P_APPLICATION_NAME = "ApplicationName";
final String P_AUTHOR = "Author";
final int P_CHAR_COUNT = ++nr;
final String P_COMMENTS = "Comments";
final Date P_CREATE_DATE_TIME = new Date(time1);
final long P_EDIT_TIME = ++nr * 1000 * 10;
final String P_KEYWORDS = "Keywords";
final String P_LAST_AUTHOR = "LastAuthor";
final Date P_LAST_PRINTED = new Date(time2);
final Date P_LAST_SAVE_DATE_TIME = new Date(time3);
final int P_PAGE_COUNT = ++nr;
final String P_REV_NUMBER = "RevNumber";
final int P_SECURITY = 1;
final String P_SUBJECT = "Subject";
final String P_TEMPLATE = "Template";
// FIXME (byte array properties not yet implemented): final byte[] P_THUMBNAIL = new byte[123];
final String P_TITLE = "Title";
final int P_WORD_COUNT = ++nr;

final int P_BYTE_COUNT = ++nr;
final String P_CATEGORY = "Category";
final String P_COMPANY = "Company";
// FIXME (byte array properties not yet implemented): final byte[] P_DOCPARTS = new byte[123];
// FIXME (byte array properties not yet implemented): final byte[] P_HEADING_PAIR = new byte[123];
final int P_HIDDEN_COUNT = ++nr;
final int P_LINE_COUNT = ++nr;
final boolean P_LINKS_DIRTY = true;
final String P_MANAGER = "Manager";
final int P_MM_CLIP_COUNT = ++nr;
final int P_NOTE_COUNT = ++nr;
final int P_PAR_COUNT = ++nr;
final String P_PRESENTATION_FORMAT = "PresentationFormat";
final boolean P_SCALE = false;
final int P_SLIDE_COUNT = ++nr;
final Date now = new Date();

final Integer POSITIVE_INTEGER = new Integer(2222);
final Long POSITIVE_LONG = new Long(3333);
final Double POSITIVE_DOUBLE = new Double(4444);
final Integer NEGATIVE_INTEGER = new Integer(2222);
final Long NEGATIVE_LONG = new Long(3333);
final Double NEGATIVE_DOUBLE = new Double(4444);

final Integer MAX_INTEGER = new Integer(Integer.MAX_VALUE);
final Integer MIN_INTEGER = new Integer(Integer.MIN_VALUE);
final Long MAX_LONG = new Long(Long.MAX_VALUE);
final Long MIN_LONG = new Long(Long.MIN_VALUE);
final Double MAX_DOUBLE = new Double(Double.MAX_VALUE);
final Double MIN_DOUBLE = new Double(Double.MIN_VALUE);
SummaryInformation si = getSummaryInformation(poifs);
DocumentSummaryInformation dsi = getDocumentSummaryInformation(poifs);

si.setApplicationName(P_APPLICATION_NAME);
si.setAuthor(P_AUTHOR);
@@ -322,76 +321,71 @@ public class TestWriteWellKnown extends TestCase {
dsi.setScale(P_SCALE);
dsi.setSlideCount(P_SLIDE_COUNT);

CustomProperties customProperties = dsi.getCustomProperties();
if (customProperties == null)
customProperties = new CustomProperties();
customProperties.put("Schl\u00fcssel \u00e4", "Wert \u00e4");
customProperties.put("Schl\u00fcssel \u00e4\u00f6", "Wert \u00e4\u00f6");
customProperties.put("Schl\u00fcssel \u00e4\u00f6\u00fc", "Wert \u00e4\u00f6\u00fc");
customProperties.put("Schl\u00fcssel \u00e4\u00f6\u00fc\u00d6", "Wert \u00e4\u00f6\u00fc\u00d6");
customProperties.put("positive_Integer", POSITIVE_INTEGER);
customProperties.put("positive_Long", POSITIVE_LONG);
customProperties.put("positive_Double", POSITIVE_DOUBLE);
customProperties.put("negative_Integer", NEGATIVE_INTEGER);
customProperties.put("negative_Long", NEGATIVE_LONG);
customProperties.put("negative_Double", NEGATIVE_DOUBLE);
customProperties.put("Boolean", Boolean.TRUE);
customProperties.put("Date", now);
customProperties.put("max_Integer", MAX_INTEGER);
customProperties.put("min_Integer", MIN_INTEGER);
customProperties.put("max_Long", MAX_LONG);
customProperties.put("min_Long", MIN_LONG);
customProperties.put("max_Double", MAX_DOUBLE);
customProperties.put("min_Double", MIN_DOUBLE);
CustomProperties cps = dsi.getCustomProperties();
assertNull(cps);
cps = new CustomProperties();
cps.put("Schl\u00fcssel \u00e4", "Wert \u00e4");
cps.put("Schl\u00fcssel \u00e4\u00f6", "Wert \u00e4\u00f6");
cps.put("Schl\u00fcssel \u00e4\u00f6\u00fc", "Wert \u00e4\u00f6\u00fc");
cps.put("Schl\u00fcssel \u00e4\u00f6\u00fc\u00d6", "Wert \u00e4\u00f6\u00fc\u00d6");
cps.put("positive_Integer", POSITIVE_INTEGER);
cps.put("positive_Long", POSITIVE_LONG);
cps.put("positive_Double", POSITIVE_DOUBLE);
cps.put("negative_Integer", NEGATIVE_INTEGER);
cps.put("negative_Long", NEGATIVE_LONG);
cps.put("negative_Double", NEGATIVE_DOUBLE);
cps.put("Boolean", Boolean.TRUE);
cps.put("Date", now);
cps.put("max_Integer", MAX_INTEGER);
cps.put("min_Integer", MIN_INTEGER);
cps.put("max_Long", MAX_LONG);
cps.put("min_Long", MIN_LONG);
cps.put("max_Double", MAX_DOUBLE);
cps.put("min_Double", MIN_DOUBLE);
// Check the keys went in
assertTrue(customProperties.containsKey("Schl\u00fcssel \u00e4"));
assertTrue(customProperties.containsKey("Boolean"));
assertTrue(cps.containsKey("Schl\u00fcssel \u00e4"));
assertTrue(cps.containsKey("Boolean"));
// Check the values went in
assertEquals("Wert \u00e4", customProperties.get("Schl\u00fcssel \u00e4"));
assertEquals(Boolean.TRUE, customProperties.get("Boolean"));
assertTrue(customProperties.containsValue(Boolean.TRUE));
assertTrue(customProperties.containsValue("Wert \u00e4"));
assertEquals("Wert \u00e4", cps.get("Schl\u00fcssel \u00e4"));
assertEquals(Boolean.TRUE, cps.get("Boolean"));
assertTrue(cps.containsValue(Boolean.TRUE));
assertTrue(cps.containsValue("Wert \u00e4"));
// Check that things that aren't in aren't in
assertFalse(customProperties.containsKey("False Boolean"));
assertFalse(customProperties.containsValue(Boolean.FALSE));
assertFalse(cps.containsKey("False Boolean"));
assertFalse(cps.containsValue(Boolean.FALSE));

// Save as our custom properties
dsi.setCustomProperties(customProperties);
dsi.setCustomProperties(cps);

/* Write the summary information stream and the document summary
* information stream to the POI filesystem. */
si.write(dir, siEntry.getName());
dsi.write(dir, dsiEntry.getName());
si.write(poifs.getRoot(), SummaryInformation.DEFAULT_STREAM_NAME);
dsi.write(poifs.getRoot(), DocumentSummaryInformation.DEFAULT_STREAM_NAME);

/* Write the POI filesystem to a (temporary) file <em>doc2</em>
* and close the latter. */
final File doc2 = TempFile.createTempFile("POI_HPSF_Test.", ".tmp");
doc2.deleteOnExit();
OutputStream out = new FileOutputStream(doc2);
OutputStream out = new FileOutputStream(fileOut);
poifs.writeFilesystem(out);
out.close();

/*
* Open <em>doc2</em> for reading and check summary information and
* document summary information. All properties written before must be
* found in the property streams of <em>doc2</em> and have the correct
* values.
*/
poifs = new POIFSFileSystem(new FileInputStream(doc2));
dir = poifs.getRoot();
siEntry = (DocumentEntry) dir.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);

dis = new DocumentInputStream(siEntry);
ps = new PropertySet(dis);
si = new SummaryInformation(ps);
dis = new DocumentInputStream(dsiEntry);
ps = new PropertySet(dis);
dsi = new DocumentSummaryInformation(ps);
poifs.close();
return cps;
}
/*
* Open <em>doc2</em> for reading and check summary information and
* document summary information. All properties written before must be
* found in the property streams of <em>doc2</em> and have the correct
* values.
*/
private static CustomProperties write2ndFile(File fileIn, File fileOut) throws Exception {
NPOIFSFileSystem poifs = new NPOIFSFileSystem(fileIn, false);
SummaryInformation si = getSummaryInformation(poifs);
DocumentSummaryInformation dsi = getDocumentSummaryInformation(poifs);

assertEquals(P_APPLICATION_NAME, si.getApplicationName());
assertEquals(P_AUTHOR, si.getAuthor());
@@ -429,7 +423,7 @@ public class TestWriteWellKnown extends TestCase {
assertEquals(P_SLIDE_COUNT, dsi.getSlideCount());

final CustomProperties cps = dsi.getCustomProperties();
assertEquals(customProperties, cps);
assertNotNull(cps);
assertNull(cps.get("No value available"));
assertEquals("Wert \u00e4", cps.get("Schl\u00fcssel \u00e4"));
assertEquals("Wert \u00e4\u00f6", cps.get("Schl\u00fcssel \u00e4\u00f6"));
@@ -492,93 +486,108 @@ public class TestWriteWellKnown extends TestCase {
/*
* <li><p>Write the summary information stream and the document summary
* information stream to the POI filesystem. */
si.write(dir, siEntry.getName());
dsi.write(dir, dsiEntry.getName());
si.write(poifs.getRoot(), SummaryInformation.DEFAULT_STREAM_NAME);
dsi.write(poifs.getRoot(), DocumentSummaryInformation.DEFAULT_STREAM_NAME);

/*
* <li><p>Write the POI filesystem to a (temporary) file <em>doc3</em>
* and close the latter. */
final File doc3 = TempFile.createTempFile("POI_HPSF_Test.", ".tmp");
doc3.deleteOnExit();
out = new FileOutputStream(doc3);
FileOutputStream out = new FileOutputStream(fileOut);
poifs.writeFilesystem(out);
out.close();
poifs.close();
return cps;
}
/*
* Open <em>doc3</em> for reading and check summary information
* and document summary information. All properties removed before must not
* be found in the property streams of <em>doc3</em>.
*/
private static CustomProperties write3rdFile(File fileIn, File fileOut) throws Exception {
NPOIFSFileSystem poifs = new NPOIFSFileSystem(fileIn, false);
SummaryInformation si = getSummaryInformation(poifs);
DocumentSummaryInformation dsi = getDocumentSummaryInformation(poifs);

/*
* Open <em>doc3</em> for reading and check summary information
* and document summary information. All properties removed before must not
* be found in the property streams of <em>doc3</em>.
*/
poifs = new POIFSFileSystem(new FileInputStream(doc3));
dir = poifs.getRoot();
siEntry = (DocumentEntry) dir.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);

dis = new DocumentInputStream(siEntry);
ps = new PropertySet(dis);
si = new SummaryInformation(ps);
dis = new DocumentInputStream(dsiEntry);
ps = new PropertySet(dis);
dsi = new DocumentSummaryInformation(ps);

assertEquals(null, si.getApplicationName());
assertEquals(null, si.getAuthor());
assertNull(si.getApplicationName());
assertNull(si.getAuthor());
assertEquals(0, si.getCharCount());
assertTrue(si.wasNull());
assertEquals(null, si.getComments());
assertEquals(null, si.getCreateDateTime());
assertNull(si.getComments());
assertNull(si.getCreateDateTime());
assertEquals(0, si.getEditTime());
assertTrue(si.wasNull());
assertEquals(null, si.getKeywords());
assertEquals(null, si.getLastAuthor());
assertEquals(null, si.getLastPrinted());
assertEquals(null, si.getLastSaveDateTime());
assertNull(si.getKeywords());
assertNull(si.getLastAuthor());
assertNull(si.getLastPrinted());
assertNull(si.getLastSaveDateTime());
assertEquals(0, si.getPageCount());
assertTrue(si.wasNull());
assertEquals(null, si.getRevNumber());
assertNull(si.getRevNumber());
assertEquals(0, si.getSecurity());
assertTrue(si.wasNull());
assertEquals(null, si.getSubject());
assertEquals(null, si.getTemplate());
assertEquals(null, si.getThumbnail());
assertEquals(null, si.getTitle());
assertNull(si.getSubject());
assertNull(si.getTemplate());
assertNull(si.getThumbnail());
assertNull(si.getTitle());
assertEquals(0, si.getWordCount());
assertTrue(si.wasNull());

assertEquals(0, dsi.getByteCount());
assertTrue(dsi.wasNull());
assertEquals(null, dsi.getCategory());
assertEquals(null, dsi.getCustomProperties());
// FIXME (byte array properties not yet implemented): assertEquals(null, dsi.getDocparts());
// FIXME (byte array properties not yet implemented): assertEquals(null, dsi.getHeadingPair());
assertNull(dsi.getCategory());
assertNull(dsi.getCustomProperties());
// FIXME (byte array properties not yet implemented): assertNull(dsi.getDocparts());
// FIXME (byte array properties not yet implemented): assertNull(dsi.getHeadingPair());
assertEquals(0, dsi.getHiddenCount());
assertTrue(dsi.wasNull());
assertEquals(0, dsi.getLineCount());
assertTrue(dsi.wasNull());
assertEquals(false, dsi.getLinksDirty());
assertFalse(dsi.getLinksDirty());
assertTrue(dsi.wasNull());
assertEquals(null, dsi.getManager());
assertNull(dsi.getManager());
assertEquals(0, dsi.getMMClipCount());
assertTrue(dsi.wasNull());
assertEquals(0, dsi.getNoteCount());
assertTrue(dsi.wasNull());
assertEquals(0, dsi.getParCount());
assertTrue(dsi.wasNull());
assertEquals(null, dsi.getPresentationFormat());
assertEquals(false, dsi.getScale());
assertNull(dsi.getPresentationFormat());
assertFalse(dsi.getScale());
assertTrue(dsi.wasNull());
assertEquals(0, dsi.getSlideCount());
assertTrue(dsi.wasNull());
poifs.close();
return dsi.getCustomProperties();
}

private static SummaryInformation getSummaryInformation(NPOIFSFileSystem poifs) throws Exception {
DocumentInputStream dis = poifs.createDocumentInputStream(SummaryInformation.DEFAULT_STREAM_NAME);
PropertySet ps = new PropertySet(dis);
SummaryInformation si = new SummaryInformation(ps);
dis.close();
return si;
}
private static DocumentSummaryInformation getDocumentSummaryInformation(NPOIFSFileSystem poifs) throws Exception {
DocumentInputStream dis = poifs.createDocumentInputStream(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
PropertySet ps = new PropertySet(dis);
DocumentSummaryInformation dsi = new DocumentSummaryInformation(ps);
dis.close();
return dsi;
}


/**
* <p>Tests the simplified custom properties by reading them from the
* available test files.</p>
*
* @throws Throwable if anything goes wrong.
*/
@Test
public void testReadCustomPropertiesFromFiles() throws Throwable
{
final AllDataFilesTester.TestTask task = new AllDataFilesTester.TestTask()
@@ -590,43 +599,35 @@ public class TestWriteWellKnown extends TestCase {
UnexpectedPropertySetTypeException
{
/* Read a test document <em>doc</em> into a POI filesystem. */
final POIFSFileSystem poifs = new POIFSFileSystem(new FileInputStream(file));
final DirectoryEntry dir = poifs.getRoot();
DocumentEntry dsiEntry = null;
try
{
dsiEntry = (DocumentEntry) dir.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
}
catch (FileNotFoundException ex)
{
NPOIFSFileSystem poifs = null;
try {
poifs = new NPOIFSFileSystem(file);
final DirectoryEntry dir = poifs.getRoot();
/*
* A missing document summary information stream is not an error
* and therefore silently ignored here.
* If there is a document summry information stream, read it from
* the POI filesystem, else create a new one.
*/
}

/*
* If there is a document summry information stream, read it from
* the POI filesystem, else create a new one.
*/
DocumentSummaryInformation dsi;
if (dsiEntry != null)
{
final DocumentInputStream dis = new DocumentInputStream(dsiEntry);
final PropertySet ps = new PropertySet(dis);
dsi = new DocumentSummaryInformation(ps);
}
else
dsi = PropertySetFactory.newDocumentSummaryInformation();
final CustomProperties cps = dsi.getCustomProperties();

if (cps == null)
/* The document does not have custom properties. */
return;

for (CustomProperty cp : cps.values()) {
cp.getName();
cp.getValue();
DocumentSummaryInformation dsi;
if (dir.hasEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME)) {
final DocumentInputStream dis = poifs.createDocumentInputStream(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
final PropertySet ps = new PropertySet(dis);
dsi = new DocumentSummaryInformation(ps);
dis.close();
} else {
dsi = PropertySetFactory.newDocumentSummaryInformation();
}
final CustomProperties cps = dsi.getCustomProperties();
if (cps == null)
/* The document does not have custom properties. */
return;
for (CustomProperty cp : cps.values()) {
cp.getName();
cp.getValue();
}
} finally {
if (poifs != null) poifs.close();
}
}
};
@@ -657,6 +658,7 @@ public class TestWriteWellKnown extends TestCase {
/**
* <p>Tests basic custom property features.</p>
*/
@Test
public void testCustomerProperties()
{
final String KEY = "Schl\u00fcssel \u00e4";
@@ -695,6 +697,7 @@ public class TestWriteWellKnown extends TestCase {
* <p>Tests reading custom properties from a section including reading
* custom properties which are not pure.</p>
*/
@Test
public void testGetCustomerProperties()
{
final int ID_1 = 2;
@@ -709,7 +712,7 @@ public class TestWriteWellKnown extends TestCase {

/* A document summary information set stream by default does have custom properties. */
cps = dsi.getCustomProperties();
assertEquals(null, cps);
assertNull(cps);

/* Test an empty custom properties set. */
s = new MutableSection();

+ 186
- 148
src/testcases/org/apache/poi/hssf/extractor/TestExcelExtractor.java 查看文件

@@ -17,10 +17,13 @@

package org.apache.poi.hssf.extractor;

import java.io.IOException;
import java.io.InputStream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import junit.framework.TestCase;
import java.io.File;
import java.io.IOException;
import java.util.Locale;

import org.apache.poi.POIDataSamples;
import org.apache.poi.hssf.HSSFTestDataSamples;
@@ -28,24 +31,22 @@ import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;

/**
*
*/
public final class TestExcelExtractor extends TestCase {

private static ExcelExtractor createExtractor(String sampleFileName) {

InputStream is = HSSFTestDataSamples.openSampleFileStream(sampleFileName);
public final class TestExcelExtractor {

try {
return new ExcelExtractor(new POIFSFileSystem(is));
} catch (IOException e) {
throw new RuntimeException(e);
}
@SuppressWarnings("resource")
private static ExcelExtractor createExtractor(String sampleFileName) throws IOException {
File file = HSSFTestDataSamples.getSampleFile(sampleFileName);
return new ExcelExtractor(new POIFSFileSystem(file));
}


@Test
public void testSimple() throws IOException {
ExcelExtractor extractor = createExtractor("Simple.xls");

@@ -60,7 +61,8 @@ public final class TestExcelExtractor extends TestCase {
}
}

public void testNumericFormula() {
@Test
public void testNumericFormula() throws IOException {

ExcelExtractor extractor = createExtractor("sumifformula.xls");

@@ -87,9 +89,12 @@ public final class TestExcelExtractor extends TestCase {
"Sheet2\nSheet3\n",
extractor.getText()
);
extractor.close();
}

public void testwithContinueRecords() {
@Test
public void testwithContinueRecords() throws IOException {

ExcelExtractor extractor = createExtractor("StringContinueRecords.xls");

@@ -99,9 +104,12 @@ public final class TestExcelExtractor extends TestCase {
// Until we fixed bug #41064, this would've
// failed by now
assertTrue(extractor.getText().length() > 40960);
extractor.close();
}

public void testStringConcat() {
@Test
public void testStringConcat() throws IOException {

ExcelExtractor extractor = createExtractor("SimpleWithFormula.xls");

@@ -112,9 +120,12 @@ public final class TestExcelExtractor extends TestCase {
extractor.setFormulasNotResults(true);

assertEquals("Sheet1\nreplaceme\nreplaceme\nCONCATENATE(A1,A2)\nSheet2\nSheet3\n", extractor.getText());
extractor.close();
}

public void testStringFormula() {
@Test
public void testStringFormula() throws IOException {

ExcelExtractor extractor = createExtractor("StringFormulas.xls");

@@ -125,40 +136,49 @@ public final class TestExcelExtractor extends TestCase {
extractor.setFormulasNotResults(true);

assertEquals("Sheet1\nUPPER(\"xyz\")\nSheet2\nSheet3\n", extractor.getText());
extractor.close();
}


public void testEventExtractor() throws Exception {
@Test
public void testEventExtractor() throws Exception {
// First up, a simple file with string
// based formulas in it
EventBasedExcelExtractor extractor = new EventBasedExcelExtractor(
new POIFSFileSystem(
HSSFTestDataSamples.openSampleFileStream("SimpleWithFormula.xls")
)
);
EventBasedExcelExtractor extractor1 = null;
try {
extractor.setIncludeSheetNames(true);
String text = extractor.getText();
extractor1 = new EventBasedExcelExtractor(
new POIFSFileSystem(
HSSFTestDataSamples.openSampleFileStream("SimpleWithFormula.xls")
)
);
extractor1.setIncludeSheetNames(true);
String text = extractor1.getText();
assertEquals("Sheet1\nreplaceme\nreplaceme\nreplacemereplaceme\nSheet2\nSheet3\n", text);
extractor.setIncludeSheetNames(false);
extractor.setFormulasNotResults(true);
extractor1.setIncludeSheetNames(false);
extractor1.setFormulasNotResults(true);
text = extractor.getText();
text = extractor1.getText();
assertEquals("replaceme\nreplaceme\nCONCATENATE(A1,A2)\n", text);
} finally {
if (extractor1 != null) extractor1.close();
}

// Now, a slightly longer file with numeric formulas
EventBasedExcelExtractor extractor2 = null;
try {
extractor2 = new EventBasedExcelExtractor(
new POIFSFileSystem(
HSSFTestDataSamples.openSampleFileStream("sumifformula.xls")
)
);
extractor2.setIncludeSheetNames(false);
extractor2.setFormulasNotResults(true);
// Now, a slightly longer file with numeric formulas
extractor = new EventBasedExcelExtractor(
new POIFSFileSystem(
HSSFTestDataSamples.openSampleFileStream("sumifformula.xls")
)
);
extractor.setIncludeSheetNames(false);
extractor.setFormulasNotResults(true);
text = extractor.getText();
String text = extractor2.getText();
assertEquals(
"1000\t1\tSUMIF(A1:A5,\">4000\",B1:B5)\n" +
"2000\t2\n" +
@@ -168,11 +188,12 @@ public final class TestExcelExtractor extends TestCase {
text
);
} finally {
extractor.close();
if (extractor2 != null) extractor2.close();
}
}

public void testWithComments() {
@Test
public void testWithComments() throws IOException {
ExcelExtractor extractor = createExtractor("SimpleWithComments.xls");
extractor.setIncludeSheetNames(false);

@@ -192,9 +213,12 @@ public final class TestExcelExtractor extends TestCase {
"3\tthree Comment by Yegor Kozlov: Yegor Kozlov: third cell\n",
extractor.getText()
);
extractor.close();
}

public void testWithBlank() {
@Test
public void testWithBlank() throws IOException {
ExcelExtractor extractor = createExtractor("MissingBits.xls");
String def = extractor.getText();
extractor.setIncludeBlankCells(true);
@@ -213,136 +237,145 @@ public final class TestExcelExtractor extends TestCase {
"Hello\n" +
"11\t\t\t23\n"
));
extractor.close();
}

public void testFormatting() throws Exception {
ExcelExtractor extractor = createExtractor("Formatting.xls");
extractor.setIncludeBlankCells(false);
extractor.setIncludeSheetNames(false);
String text = extractor.getText();
// Note - not all the formats in the file
// actually quite match what they claim to
// be, as some are auto-local builtins...
assertTrue(text.startsWith(
"Dates, all 24th November 2006\n"
));
assertTrue(
text.indexOf(
"yyyy/mm/dd\t2006/11/24\n"
) > -1
);
assertTrue(
text.indexOf(
"yyyy-mm-dd\t2006-11-24\n"
) > -1
);
assertTrue(
text.indexOf(
"dd-mm-yy\t24-11-06\n"
) > -1
);
assertTrue("Had: " + text + ", but should contain 'nn.nn\\t10.52\\n'",
text.indexOf(
"nn.nn\t10.52\n"
) > -1
);
assertTrue(
text.indexOf(
"nn.nnn\t10.520\n"
) > -1
);
assertTrue(
text.indexOf(
"\u00a3nn.nn\t\u00a310.52\n"
) > -1
);
@Test
public void testFormatting() throws Exception {
Locale userLocale = LocaleUtil.getUserLocale();
LocaleUtil.setUserLocale(Locale.ROOT);
try {
ExcelExtractor extractor = createExtractor("Formatting.xls");
extractor.setIncludeBlankCells(false);
extractor.setIncludeSheetNames(false);
String text = extractor.getText();
// Note - not all the formats in the file
// actually quite match what they claim to
// be, as some are auto-local builtins...
assertTrue(text.startsWith(
"Dates, all 24th November 2006\n"
));
assertTrue(
text.indexOf(
"yyyy/mm/dd\t2006/11/24\n"
) > -1
);
assertTrue(
text.indexOf(
"yyyy-mm-dd\t2006-11-24\n"
) > -1
);
assertTrue(
text.indexOf(
"dd-mm-yy\t24-11-06\n"
) > -1
);
assertTrue("Had: " + text + ", but should contain 'nn.nn\\t10.52\\n'",
text.indexOf(
"nn.nn\t10.52\n"
) > -1
);
assertTrue(
text.indexOf(
"nn.nnn\t10.520\n"
) > -1
);
assertTrue(
text.indexOf(
"\u00a3nn.nn\t\u00a310.52\n"
) > -1
);
extractor.close();
} finally {
LocaleUtil.setUserLocale(userLocale);
}
}

/**
* Embeded in a non-excel file
*/
public void testWithEmbeded() throws Exception {
POIFSFileSystem fs = new POIFSFileSystem(
POIDataSamples.getDocumentInstance().openResourceAsStream("word_with_embeded.doc")
);

DirectoryNode objPool = (DirectoryNode) fs.getRoot().getEntry("ObjectPool");
DirectoryNode dirA = (DirectoryNode) objPool.getEntry("_1269427460");
DirectoryNode dirB = (DirectoryNode) objPool.getEntry("_1269427461");
@Test
public void testWithEmbeded() throws Exception {
POIFSFileSystem fs = null;
HSSFWorkbook wbA = null, wbB = null;
ExcelExtractor exA = null, exB = null;

HSSFWorkbook wbA = new HSSFWorkbook(dirA, fs, true);
HSSFWorkbook wbB = new HSSFWorkbook(dirB, fs, true);

ExcelExtractor exA = new ExcelExtractor(wbA);
try {
ExcelExtractor exB = new ExcelExtractor(wbB);
try {
assertEquals("Sheet1\nTest excel file\nThis is the first file\nSheet2\nSheet3\n",
exA.getText());
assertEquals("Sample Excel", exA.getSummaryInformation().getTitle());
assertEquals("Sheet1\nAnother excel file\nThis is the second file\nSheet2\nSheet3\n",
exB.getText());
assertEquals("Sample Excel 2", exB.getSummaryInformation().getTitle());
} finally {
exB.close();
}
fs = new POIFSFileSystem(POIDataSamples.getDocumentInstance().getFile("word_with_embeded.doc"));

DirectoryNode objPool = (DirectoryNode) fs.getRoot().getEntry("ObjectPool");
DirectoryNode dirA = (DirectoryNode) objPool.getEntry("_1269427460");
DirectoryNode dirB = (DirectoryNode) objPool.getEntry("_1269427461");
wbA = new HSSFWorkbook(dirA, fs, true);
exA = new ExcelExtractor(wbA);
wbB = new HSSFWorkbook(dirB, fs, true);
exB = new ExcelExtractor(wbB);

assertEquals("Sheet1\nTest excel file\nThis is the first file\nSheet2\nSheet3\n", exA.getText());
assertEquals("Sample Excel", exA.getSummaryInformation().getTitle());
assertEquals("Sheet1\nAnother excel file\nThis is the second file\nSheet2\nSheet3\n", exB.getText());
assertEquals("Sample Excel 2", exB.getSummaryInformation().getTitle());
} finally {
exA.close();
if (exB != null) exB.close();
if (wbB != null) wbB.close();
if (exA != null) exA.close();
if (wbA != null) wbA.close();
if (fs != null) fs.close();
}
}

/**
* Excel embeded in excel
*/
public void testWithEmbededInOwn() throws Exception {
@Test
public void testWithEmbededInOwn() throws Exception {
POIDataSamples ssSamples = POIDataSamples.getSpreadSheetInstance();
POIFSFileSystem fs = new POIFSFileSystem(
ssSamples.openResourceAsStream("excel_with_embeded.xls")
);
POIFSFileSystem fs = null;
HSSFWorkbook wbA = null, wbB = null;
ExcelExtractor exA = null, exB = null, ex = null;

DirectoryNode dirA = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B5");
DirectoryNode dirB = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B4");
try {
fs = new POIFSFileSystem(ssSamples.getFile("excel_with_embeded.xls"));

HSSFWorkbook wbA = new HSSFWorkbook(dirA, fs, true);
HSSFWorkbook wbB = new HSSFWorkbook(dirB, fs, true);
DirectoryNode dirA = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B5");
DirectoryNode dirB = (DirectoryNode) fs.getRoot().getEntry("MBD0000A3B4");

ExcelExtractor exA = new ExcelExtractor(wbA);
try {
ExcelExtractor exB = new ExcelExtractor(wbB);
try {
assertEquals("Sheet1\nTest excel file\nThis is the first file\nSheet2\nSheet3\n",
exA.getText());
assertEquals("Sample Excel", exA.getSummaryInformation().getTitle());
assertEquals("Sheet1\nAnother excel file\nThis is the second file\nSheet2\nSheet3\n",
exB.getText());
assertEquals("Sample Excel 2", exB.getSummaryInformation().getTitle());
wbA = new HSSFWorkbook(dirA, fs, true);
wbB = new HSSFWorkbook(dirB, fs, true);

exA = new ExcelExtractor(wbA);
exB = new ExcelExtractor(wbB);
assertEquals("Sheet1\nTest excel file\nThis is the first file\nSheet2\nSheet3\n", exA.getText());
assertEquals("Sample Excel", exA.getSummaryInformation().getTitle());
assertEquals("Sheet1\nAnother excel file\nThis is the second file\nSheet2\nSheet3\n", exB.getText());
assertEquals("Sample Excel 2", exB.getSummaryInformation().getTitle());
// And the base file too
ExcelExtractor ex = new ExcelExtractor(fs);
try {
assertEquals("Sheet1\nI have lots of embeded files in me\nSheet2\nSheet3\n",
ex.getText());
assertEquals("Excel With Embeded", ex.getSummaryInformation().getTitle());
} finally {
ex.close();
}
} finally {
exB.close();
}
} finally {
exA.close();
// And the base file too
ex = new ExcelExtractor(fs);
assertEquals("Sheet1\nI have lots of embeded files in me\nSheet2\nSheet3\n", ex.getText());
assertEquals("Excel With Embeded", ex.getSummaryInformation().getTitle());
} finally {
if (ex != null) ex.close();
if (exB != null) exB.close();
if (exA != null) exA.close();
if (wbB != null) wbB.close();
if (wbA != null) wbA.close();
if (fs != null) fs.close();
}
}

/**
* Test that we get text from headers and footers
*/
public void test45538() {
@Test
public void test45538() throws IOException {
String[] files = {
"45538_classic_Footer.xls", "45538_form_Footer.xls",
"45538_classic_Header.xls", "45538_form_Header.xls"
@@ -352,21 +385,26 @@ public final class TestExcelExtractor extends TestCase {
String text = extractor.getText();
assertTrue("Unable to find expected word in text\n" + text, text.indexOf("testdoc") >=0);
assertTrue("Unable to find expected word in text\n" + text, text.indexOf("test phrase") >= 0);
extractor.close();
}
}

public void testPassword() {
@Test
public void testPassword() throws IOException {
Biff8EncryptionKey.setCurrentUserPassword("password");
ExcelExtractor extractor = createExtractor("password.xls");
String text = extractor.getText();
Biff8EncryptionKey.setCurrentUserPassword(null);

assertTrue(text.contains("ZIP"));
extractor.close();
}

public void testNullPointerException() {
@Test
public void testNullPointerException() throws IOException {
ExcelExtractor extractor = createExtractor("ar.org.apsme.www_Form%20Inscripcion%20Curso%20NO%20Socios.xls");
assertNotNull(extractor);
assertNotNull(extractor.getText());
extractor.close();
}
}

+ 12
- 12
src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java 查看文件

@@ -36,9 +36,9 @@ import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.poi.EncryptedDocumentException;
@@ -69,13 +69,13 @@ import org.apache.poi.ss.usermodel.BaseTestBugzillaIssues;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.TempFile;
import org.junit.Ignore;
import org.junit.Test;
@@ -2193,10 +2193,9 @@ public final class TestBugs extends BaseTestBugzillaIssues {

@Test
public void bug48968() throws Exception {
TimeZone tz = DateUtil.getUserTimeZone();
try {
DateUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
TimeZone userTimeZone = LocaleUtil.getUserTimeZone();
LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
try {
HSSFWorkbook wb = openSample("48968.xls");
assertEquals(1, wb.getNumberOfSheets());
@@ -2241,9 +2240,9 @@ public final class TestBugs extends BaseTestBugzillaIssues {
assertEquals(39.0+14.0+1, s.getRow(6).getCell(0).getNumericCellValue(), 0);
assertEquals("SECOND(A1)", s.getRow(7).getCell(0).getCellFormula());
assertEquals(54.0+24.0-60, s.getRow(7).getCell(0).getNumericCellValue(), 0);
} finally {
DateUtil.setUserTimeZone(tz);
}
} finally {
LocaleUtil.setUserTimeZone(userTimeZone);
}
}

@@ -2474,12 +2473,13 @@ public final class TestBugs extends BaseTestBugzillaIssues {
Sheet sheet = wb.getSheet("test-sheet");
int rowCount = sheet.getLastRowNum() + 1;
int newRows = 5;
Calendar cal = LocaleUtil.getLocaleCalendar();
for (int r = rowCount; r < rowCount + newRows; r++) {
Row row = sheet.createRow((short) r);
row.createCell(0).setCellValue(1.03 * (r + 7));
row.createCell(1).setCellValue(new Date());
row.createCell(2).setCellValue(Calendar.getInstance());
row.createCell(3).setCellValue(String.format("row:%d/col:%d", r, 3));
row.createCell(1).setCellValue(cal.getTime());
row.createCell(2).setCellValue(cal);
row.createCell(3).setCellValue(String.format(Locale.ROOT, "row:%d/col:%d", r, 3));
row.createCell(4).setCellValue(true);
row.createCell(5).setCellType(Cell.CELL_TYPE_ERROR);
row.createCell(6).setCellValue("added cells.");

+ 2
- 4
src/testcases/org/apache/poi/hssf/usermodel/TestCellStyle.java 查看文件

@@ -32,12 +32,11 @@ import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.TempFile;

/**
* Class to test cell styling functionality
*
* @author Andrew C. Oliver
*/

public final class TestCellStyle extends TestCase {
@@ -115,8 +114,7 @@ public final class TestCellStyle extends TestCase {
cell = row.createCell(2);
cs.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy"));
cell.setCellStyle(cs);
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
Calendar cal = LocaleUtil.getLocaleCalendar();
cell.setCellValue(cal);

wb.write(out);

+ 56
- 30
src/testcases/org/apache/poi/hssf/usermodel/TestFormulaEvaluatorBugs.java 查看文件

@@ -17,15 +17,14 @@

package org.apache.poi.hssf.usermodel;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Iterator;

import junit.framework.AssertionFailedError;
import junit.framework.TestCase;

import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
@@ -43,15 +42,19 @@ import org.apache.poi.ss.formula.ptg.RefPtg;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.LocaleUtil;
import org.junit.BeforeClass;
import org.junit.Test;

/**
*
*/
public final class TestFormulaEvaluatorBugs extends TestCase {
public final class TestFormulaEvaluatorBugs {
private static boolean OUTPUT_TEST_FILES = false;
private String tmpDirName;
private static String tmpDirName;

protected void setUp() {
@BeforeClass
public static void setUp() {
tmpDirName = System.getProperty("java.io.tmpdir");
OUTPUT_TEST_FILES = Boolean.parseBoolean(
System.getProperty("org.apache.poi.test.output_test_files", "False"));
@@ -66,6 +69,7 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
* WARNING - tedious bug where you actually have to
* open up excel
*/
@Test
public void test44636() throws Exception {
// Open the existing file, tweak one value and
// re-calculate
@@ -80,15 +84,16 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
HSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
assertEquals(4.2 * 25, row.getCell(3).getNumericCellValue(), 0.0001);

FileOutputStream out;
if (OUTPUT_TEST_FILES) {
// Save
File existing = new File(tmpDirName, "44636-existing.xls");
out = new FileOutputStream(existing);
FileOutputStream out = new FileOutputStream(existing);
wb.write(out);
out.close();
System.err.println("Existing file for bug #44636 written to " + existing.toString());
}
wb.close();
// Now, do a new file from scratch
wb = new HSSFWorkbook();
sheet = wb.createSheet();
@@ -106,21 +111,21 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
if (OUTPUT_TEST_FILES) {
// Save
File scratch = new File(tmpDirName, "44636-scratch.xls");
out = new FileOutputStream(scratch);
FileOutputStream out = new FileOutputStream(scratch);
wb.write(out);
out.close();
System.err.println("New file for bug #44636 written to " + scratch.toString());
}
wb.close();
}

/**
* Bug 44297: 32767+32768 is evaluated to -1
* Fix: IntPtg must operate with unsigned short. Reading signed short results in incorrect formula calculation
* if a formula has values in the interval [Short.MAX_VALUE, (Short.MAX_VALUE+1)*2]
*
* @author Yegor Kozlov
*/
public void test44297() {
@Test
public void test44297() throws Exception {

HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("44297.xls");

@@ -175,13 +180,16 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
cell = row.getCell(0);
assertEquals("-1000000-3000000", cell.getCellFormula());
assertEquals(-4000000, eva.evaluate(cell).getNumberValue(), 0);
wb.close();
}

/**
* Bug 44410: SUM(C:C) is valid in excel, and means a sum
* of all the rows in Column C
*/
public void test44410() {
@Test
public void test44410() throws Exception {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("SingleLetterRanges.xls");

HSSFSheet sheet = wb.getSheetAt(0);
@@ -233,12 +241,15 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
HSSFCell cellSUM2D = rowSUM2D.getCell(0);
assertEquals("SUM(C:D)", cellSUM2D.getCellFormula());
assertEquals(66, eva.evaluate(cellSUM2D).getNumberValue(), 0);
wb.close();
}

/**
* Tests that we can evaluate boolean cells properly
*/
public void testEvaluateBooleanInCell_bug44508() {
@Test
public void testEvaluateBooleanInCell_bug44508() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
wb.setSheetName(0, "Sheet1");
@@ -254,9 +265,12 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
fail("Identified bug 44508");
}
assertEquals(true, cell.getBooleanCellValue());
wb.close();
}

public void testClassCast_bug44861() {
@Test
public void testClassCast_bug44861() throws Exception {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("44861.xls");

// Check direct
@@ -276,9 +290,12 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
}
}
}
wb.close();
}

public void testEvaluateInCellWithErrorCode_bug44950() {
@Test
public void testEvaluateInCellWithErrorCode_bug44950() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("Sheet1");
HSSFRow row = sheet.createRow(1);
@@ -289,13 +306,16 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
fe.evaluateInCell(cell);
} catch (NumberFormatException e) {
if (e.getMessage().equals("You cannot get an error value from a non-error cell")) {
throw new AssertionFailedError("Identified bug 44950 b");
fail("Identified bug 44950 b");
}
throw e;
} finally {
wb.close();
}
}

public void testDateWithNegativeParts_bug48528() {
@Test
public void testDateWithNegativeParts_bug48528() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("Sheet1");
HSSFRow row = sheet.createRow(1);
@@ -310,31 +330,33 @@ public final class TestFormulaEvaluatorBugs extends TestCase {

cell.setCellFormula("DATE(2012,2,1)");
fe.notifyUpdateCell(cell);
assertEquals(40940.0, fe.evaluate(cell).getNumberValue());
assertEquals(40940.0, fe.evaluate(cell).getNumberValue(), 0);

cell.setCellFormula("DATE(2012,2,1+4)");
fe.notifyUpdateCell(cell);
assertEquals(40944.0, fe.evaluate(cell).getNumberValue());
assertEquals(40944.0, fe.evaluate(cell).getNumberValue(), 0);

cell.setCellFormula("DATE(2012,2-1,1+4)");
fe.notifyUpdateCell(cell);
assertEquals(40913.0, fe.evaluate(cell).getNumberValue());
assertEquals(40913.0, fe.evaluate(cell).getNumberValue(), 0);

cell.setCellFormula("DATE(2012,2,1-27)");
fe.notifyUpdateCell(cell);
assertEquals(40913.0, fe.evaluate(cell).getNumberValue());
assertEquals(40913.0, fe.evaluate(cell).getNumberValue(), 0);

cell.setCellFormula("DATE(2012,2-2,1+4)");
fe.notifyUpdateCell(cell);
assertEquals(40882.0, fe.evaluate(cell).getNumberValue());
assertEquals(40882.0, fe.evaluate(cell).getNumberValue(), 0);

cell.setCellFormula("DATE(2012,2,1-58)");
fe.notifyUpdateCell(cell);
assertEquals(40882.0, fe.evaluate(cell).getNumberValue());
assertEquals(40882.0, fe.evaluate(cell).getNumberValue(), 0);

cell.setCellFormula("DATE(2012,2-12,1+4)");
fe.notifyUpdateCell(cell);
assertEquals(40579.0, fe.evaluate(cell).getNumberValue());
assertEquals(40579.0, fe.evaluate(cell).getNumberValue(), 0);
wb.close();
}

private static final class EvalListener extends EvaluationListener {
@@ -363,7 +385,8 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
/**
* The HSSFFormula evaluator performance benefits greatly from caching of intermediate cell values
*/
public void testSlowEvaluate45376() {
@Test
public void testSlowEvaluate45376() throws Exception {
/*
* Note - to observe behaviour without caching, disable the call to
* updateValue() from FormulaCellCacheEntry.updateFormulaResult().
@@ -384,7 +407,7 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
"DATE(YEAR(" + prevCell + "),MONTH(" + prevCell + ")+1,1),NA())";
cell.setCellFormula(formula);
}
Calendar cal = new GregorianCalendar(2000, 0, 1, 0, 0, 0);
Calendar cal = LocaleUtil.getLocaleCalendar(2000, 0, 1, 0, 0, 0);
row.createCell(0).setCellValue(cal);

// Choose cell A9 instead of A10, so that the failing test case doesn't take too long to execute.
@@ -397,8 +420,8 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
// Without caching, evaluating cell 'A9' takes 21845 evaluations which consumes
// much time (~3 sec on Core 2 Duo 2.2GHz)
// short-circuit-if optimisation cuts this down to 255 evaluations which is still too high
System.err.println("Cell A9 took " + evalCount + " intermediate evaluations");
throw new AssertionFailedError("Identifed bug 45376 - Formula evaluator should cache values");
// System.err.println("Cell A9 took " + evalCount + " intermediate evaluations");
fail("Identifed bug 45376 - Formula evaluator should cache values");
}
// With caching, the evaluationCount is 8 which is exactly the
// number of formula cells that needed to be evaluated.
@@ -413,9 +436,12 @@ public final class TestFormulaEvaluatorBugs extends TestCase {

// confirm the evaluation result too
assertEquals(ErrorEval.NA, ve);
wb.close();
}

@SuppressWarnings("resource")
@Test
public void test55747_55324() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFFormulaEvaluator ev = wb.getCreationHelper().createFormulaEvaluator();

+ 68
- 37
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFCell.java 查看文件

@@ -17,12 +17,15 @@

package org.apache.poi.hssf.usermodel;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.poi.hssf.HSSFITestDataProvider;
import org.apache.poi.hssf.HSSFTestDataSamples;
@@ -38,15 +41,14 @@ import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;

import junit.framework.AssertionFailedError;

/**
* Tests various functionality having to do with {@link HSSFCell}. For instance support for
* particular datatypes, etc.
* @author Andrew C. Oliver (andy at superlinksoftware dot com)
* @author Dan Sherman (dsherman at isisph.com)
* @author Alex Jacoby (ajacoby at gmail.com)
*/
public final class TestHSSFCell extends BaseTestCell {

@@ -59,27 +61,28 @@ public final class TestHSSFCell extends BaseTestCell {
* is working properly. Conversion of the date is also an issue,
* but there's a separate unit test for that.
*/
public void testDateWindowingRead() {
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.ROOT);
cal.set(2000, 0, 1, 0, 0, 0); // Jan. 1, 2000
cal.clear(Calendar.MILLISECOND);
@Test
public void testDateWindowingRead() throws Exception {
Calendar cal = LocaleUtil.getLocaleCalendar(2000, 0, 1, 0, 0, 0);// Jan. 1, 2000
Date date = cal.getTime();

// first check a file with 1900 Date Windowing
HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("1900DateWindowing.xls");
HSSFSheet sheet = workbook.getSheetAt(0);
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("1900DateWindowing.xls");
HSSFSheet sheet = wb.getSheetAt(0);

assertEquals("Date from file using 1900 Date Windowing",
date.getTime(),
sheet.getRow(0).getCell(0).getDateCellValue().getTime());
wb.close();

// now check a file with 1904 Date Windowing
workbook = HSSFTestDataSamples.openSampleWorkbook("1904DateWindowing.xls");
sheet = workbook.getSheetAt(0);
wb = HSSFTestDataSamples.openSampleWorkbook("1904DateWindowing.xls");
sheet = wb.getSheetAt(0);

assertEquals("Date from file using 1904 Date Windowing",
date.getTime(),
sheet.getRow(0).getCell(0).getDateCellValue().getTime());
wb.close();
}


@@ -90,28 +93,32 @@ public final class TestHSSFCell extends BaseTestCell {
* previous test ({@link #testDateWindowingRead}) fails, the
* results of this test are meaningless.
*/
public void testDateWindowingWrite() {
GregorianCalendar cal = new GregorianCalendar(2000,0,1); // Jan. 1, 2000
@Test
public void testDateWindowingWrite() throws Exception {
Calendar cal = LocaleUtil.getLocaleCalendar(2000,0,1,0,0,0); // Jan. 1, 2000
Date date = cal.getTime();

// first check a file with 1900 Date Windowing
HSSFWorkbook wb;
wb = HSSFTestDataSamples.openSampleWorkbook("1900DateWindowing.xls");
HSSFWorkbook wb1 = HSSFTestDataSamples.openSampleWorkbook("1900DateWindowing.xls");

setCell(wb, 0, 1, date);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
setCell(wb1, 0, 1, date);
HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1);

assertEquals("Date from file using 1900 Date Windowing",
date.getTime(),
readCell(wb, 0, 1).getTime());
readCell(wb2, 0, 1).getTime());
wb1.close();
wb2.close();

// now check a file with 1904 Date Windowing
wb = HSSFTestDataSamples.openSampleWorkbook("1904DateWindowing.xls");
setCell(wb, 0, 1, date);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
wb1 = HSSFTestDataSamples.openSampleWorkbook("1904DateWindowing.xls");
setCell(wb1, 0, 1, date);
wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1);
assertEquals("Date from file using 1900 Date Windowing",
date.getTime(),
readCell(wb, 0, 1).getTime());
readCell(wb2, 0, 1).getTime());
wb1.close();
wb2.close();
}

private static void setCell(HSSFWorkbook workbook, int rowIdx, int colIdx, Date date) {
@@ -135,12 +142,13 @@ public final class TestHSSFCell extends BaseTestCell {
/**
* Tests that the active cell can be correctly read and set
*/
public void testActiveCell() {
@Test
public void testActiveCell() throws Exception {
//read in sample
HSSFWorkbook book = HSSFTestDataSamples.openSampleWorkbook("Simple.xls");
HSSFWorkbook wb1 = HSSFTestDataSamples.openSampleWorkbook("Simple.xls");

//check initial position
HSSFSheet umSheet = book.getSheetAt(0);
HSSFSheet umSheet = wb1.getSheetAt(0);
InternalSheet s = umSheet.getSheet();
assertEquals("Initial active cell should be in col 0",
(short) 0, s.getActiveCellCol());
@@ -156,18 +164,22 @@ public final class TestHSSFCell extends BaseTestCell {
3, s.getActiveCellRow());

//write book to temp file; read and verify that position is serialized
book = HSSFTestDataSamples.writeOutAndReadBack(book);
HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1);
wb1.close();

umSheet = book.getSheetAt(0);
umSheet = wb2.getSheetAt(0);
s = umSheet.getSheet();

assertEquals("After serialize, active cell should be in col 2",
(short) 2, s.getActiveCellCol());
assertEquals("After serialize, active cell should be on row 3",
3, s.getActiveCellRow());
wb2.close();
}

@Test
public void testActiveCellBug56114() throws IOException {
Workbook wb = new HSSFWorkbook();
Sheet sh = wb.createSheet();
@@ -222,7 +234,8 @@ public final class TestHSSFCell extends BaseTestCell {
/**
* Test reading hyperlinks
*/
public void testWithHyperlink() {
@Test
public void testWithHyperlink() throws Exception {

HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("WithHyperlink.xls");

@@ -235,12 +248,15 @@ public final class TestHSSFCell extends BaseTestCell {
assertEquals("http://poi.apache.org/", link.getAddress());
assertEquals(4, link.getFirstRow());
assertEquals(0, link.getFirstColumn());
wb.close();
}

/**
* Test reading hyperlinks
*/
public void testWithTwoHyperlinks() {
@Test
public void testWithTwoHyperlinks() throws Exception {

HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("WithTwoHyperLinks.xls");

@@ -261,13 +277,16 @@ public final class TestHSSFCell extends BaseTestCell {
assertEquals("http://poi.apache.org/hssf/", link2.getAddress());
assertEquals(8, link2.getFirstRow());
assertEquals(1, link2.getFirstColumn());
wb.close();
}

/**
* Test to ensure we can only assign cell styles that belong
* to our workbook, and not those from other workbooks.
*/
public void testCellStyleWorkbookMatch() {
@Test
public void testCellStyleWorkbookMatch() throws Exception {
HSSFWorkbook wbA = new HSSFWorkbook();
HSSFWorkbook wbB = new HSSFWorkbook();

@@ -306,6 +325,9 @@ public final class TestHSSFCell extends BaseTestCell {
} catch (IllegalArgumentException e) {
// expected during successful test
}
wbB.close();
wbA.close();
}

/**
@@ -315,6 +337,7 @@ public final class TestHSSFCell extends BaseTestCell {
* versions (prior to bug 46213 / r717883) crash instead.
* @throws IOException
*/
@Test
public void testCachedTypeChange() throws IOException {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("Sheet1");
@@ -362,22 +385,27 @@ public final class TestHSSFCell extends BaseTestCell {
/**
* HSSF prior to version 3.7 had a bug: it could write a NaN but could not read such a file back.
*/
public void testReadNaN() {
@Test
public void testReadNaN() throws Exception {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("49761.xls");
assertNotNull(wb);
wb.close();
}

public void testHSSFCell() {
@Test
public void testHSSFCell() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFRow row = sheet.createRow(0);
row.createCell(0);
HSSFCell cell = new HSSFCell(wb, sheet, 0, (short)0);
assertNotNull(cell);
assertNotNull(cell);
wb.close();
}

@SuppressWarnings("deprecation")
public void testDeprecatedMethods() {
@Test
public void testDeprecatedMethods() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFRow row = sheet.createRow(0);
@@ -402,8 +430,11 @@ public final class TestHSSFCell extends BaseTestCell {
cell.removeCellComment();
cell.removeCellComment();
wb.close();
}

@Test
public void testCellType() throws IOException {
Workbook wb = _testDataProvider.createWorkbook();
Sheet sheet = wb.createSheet();

+ 41
- 11
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDataFormatter.java 查看文件

@@ -17,18 +17,25 @@

package org.apache.poi.hssf.usermodel;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;

import junit.framework.TestCase;
import org.apache.poi.util.LocaleUtil;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

/**
* Unit tests for HSSFDataFormatter.java
@@ -36,9 +43,25 @@ import junit.framework.TestCase;
* @author James May (james dot may at fmr dot com)
*
*/
public final class TestHSSFDataFormatter extends TestCase {

private final HSSFDataFormatter formatter;
public final class TestHSSFDataFormatter {

private static TimeZone userTimeZone;
@BeforeClass
public static void setTimeZone() {
userTimeZone = LocaleUtil.getUserTimeZone();
LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
LocaleUtil.setUserLocale(Locale.US);
}
@AfterClass
public static void resetTimeZone() {
LocaleUtil.setUserTimeZone(userTimeZone);
LocaleUtil.setUserLocale(Locale.ROOT);
}

private final HSSFDataFormatter formatter;
private final HSSFWorkbook wb;

public TestHSSFDataFormatter() {
@@ -197,6 +220,7 @@ public final class TestHSSFDataFormatter extends TestCase {
/**
* Test getting formatted values from numeric and date cells.
*/
@Test
public void testGetFormattedCellValueHSSFCell() {
// Valid date formats -- cell values should be date formatted & not "555.555"
HSSFRow row = wb.getSheetAt(0).getRow(0);
@@ -216,7 +240,9 @@ public final class TestHSSFDataFormatter extends TestCase {
//assert the correct month form, as in the original Excel format
String monthPtrn = fmt.indexOf("mmmm") != -1 ? "MMMM" : "MMM";
// this line is intended to compute how "July" would look like in the current locale
String jul = new SimpleDateFormat(monthPtrn).format(new GregorianCalendar(2010,6,15).getTime());
SimpleDateFormat sdf = new SimpleDateFormat(monthPtrn, LocaleUtil.getUserLocale());
Calendar calDef = LocaleUtil.getLocaleCalendar(2010, 6, 15, 0, 0, 0);
String jul = sdf.format(calDef.getTime());
// special case for MMMMM = 1st letter of month name
if(fmt.indexOf("mmmmm") > -1) {
jul = jul.substring(0,1);
@@ -228,7 +254,6 @@ public final class TestHSSFDataFormatter extends TestCase {
row = wb.getSheetAt(0).getRow(1);
it = row.cellIterator();
log("==== VALID TIME FORMATS ====");
while (it.hasNext()) {
Cell cell = it.next();
String fmt = cell.getCellStyle().getDataFormatString();
@@ -265,7 +290,7 @@ public final class TestHSSFDataFormatter extends TestCase {
log(formatter.formatCellValue(cell));
// should be equal to "1234567890.12345"
// in some locales the the decimal delimiter is a comma, not a dot
char decimalSeparator = new DecimalFormatSymbols().getDecimalSeparator();
char decimalSeparator = new DecimalFormatSymbols(LocaleUtil.getUserLocale()).getDecimalSeparator();
assertEquals("1234567890" + decimalSeparator + "12345", formatter.formatCellValue(cell));
}

@@ -297,6 +322,7 @@ public final class TestHSSFDataFormatter extends TestCase {
assertEquals(formatter.formatCellValue(null), "");
}

@Test
public void testGetFormattedCellValueHSSFCellHSSFFormulaEvaluator() {
// test formula format
HSSFRow row = wb.getSheetAt(0).getRow(7);
@@ -310,7 +336,7 @@ public final class TestHSSFDataFormatter extends TestCase {
// now with a formula evaluator
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
log(formatter.formatCellValue(cell, evaluator) + "\t\t\t (with evaluator)");
char decimalSeparator = new DecimalFormatSymbols().getDecimalSeparator();
char decimalSeparator = new DecimalFormatSymbols(LocaleUtil.getUserLocale()).getDecimalSeparator();
assertEquals("24" + decimalSeparator + "50%", formatter.formatCellValue(cell,evaluator));
}
@@ -319,10 +345,12 @@ public final class TestHSSFDataFormatter extends TestCase {
* Test using a default number format. The format should be used when a
* format pattern cannot be parsed by DecimalFormat.
*/
@Test
public void testSetDefaultNumberFormat() {
HSSFRow row = wb.getSheetAt(0).getRow(3);
Iterator<Cell> it = row.cellIterator();
Format defaultFormat = new DecimalFormat("Balance $#,#00.00 USD;Balance -$#,#00.00 USD");
DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(LocaleUtil.getUserLocale());
Format defaultFormat = new DecimalFormat("Balance $#,#00.00 USD;Balance -$#,#00.00 USD", dfs);
formatter.setDefaultNumberFormat(defaultFormat);

log("\n==== DEFAULT NUMBER FORMAT ====");
@@ -338,6 +366,7 @@ public final class TestHSSFDataFormatter extends TestCase {
/**
* A format of "@" means use the general format
*/
@Test
public void testGeneralAtFormat() {
HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("47154.xls");
HSSFSheet sheet = workbook.getSheetAt(0);
@@ -356,6 +385,7 @@ public final class TestHSSFDataFormatter extends TestCase {
/**
* Tests various formattings of dates and numbers
*/
@Test
public void testFromFile() {
HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("Formatting.xls");
HSSFSheet sheet = workbook.getSheetAt(0);

+ 102
- 110
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFDateUtil.java 查看文件

@@ -17,41 +17,38 @@

package org.apache.poi.hssf.usermodel;

import static org.junit.Assert.*;
import static java.util.Calendar.AUGUST;
import static java.util.Calendar.FEBRUARY;
import static java.util.Calendar.JANUARY;
import static java.util.Calendar.JULY;
import static java.util.Calendar.MARCH;
import static java.util.Calendar.MAY;
import static java.util.Calendar.OCTOBER;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.InternalWorkbook;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;

/**
* Class TestHSSFDateUtil
*
*
* @author Dan Sherman (dsherman at isisph.com)
* @author Hack Kampbjorn (hak at 2mba.dk)
* @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
* @author Alex Jacoby (ajacoby at gmail.com)
* @version %I%, %G%
*/
public final class TestHSSFDateUtil {

public static final int CALENDAR_JANUARY = 0;
public static final int CALENDAR_FEBRUARY = 1;
public static final int CALENDAR_MARCH = 2;
public static final int CALENDAR_APRIL = 3;
public static final int CALENDAR_JULY = 6;
public static final int CALENDAR_OCTOBER = 9;

/**
* Checks the date conversion functions in the HSSFDateUtil class.
*/
@@ -59,25 +56,24 @@ public final class TestHSSFDateUtil {
public void dateConversion() {

// Iteratating over the hours exposes any rounding issues.
for (int hour = 0; hour < 23; hour++)
{
GregorianCalendar date = new GregorianCalendar(2002, 0, 1,
hour, 1, 1);
double excelDate =
HSSFDateUtil.getExcelDate(date.getTime(), false);

assertEquals("Checking hour = " + hour, date.getTime().getTime(),
Calendar cal = LocaleUtil.getLocaleCalendar(2002,JANUARY,1,0,1,1);
for (int hour = 0; hour < 23; hour++) {
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false);

assertEquals("Checking hour = " + hour, cal.getTime().getTime(),
HSSFDateUtil.getJavaDate(excelDate, false).getTime());

cal.add(Calendar.HOUR_OF_DAY, 1);
}

// check 1900 and 1904 date windowing conversions
double excelDate = 36526.0;
// with 1900 windowing, excelDate is Jan. 1, 2000
// with 1904 windowing, excelDate is Jan. 2, 2004
GregorianCalendar cal = new GregorianCalendar(2000,0,1); // Jan. 1, 2000
cal.set(2000,JANUARY,1,0,0,0); // Jan. 1, 2000
Date dateIf1900 = cal.getTime();
cal.add(GregorianCalendar.YEAR,4); // now Jan. 1, 2004
cal.add(GregorianCalendar.DATE,1); // now Jan. 2, 2004
cal.add(Calendar.YEAR,4); // now Jan. 1, 2004
cal.add(Calendar.DATE,1); // now Jan. 2, 2004
Date dateIf1904 = cal.getTime();
// 1900 windowing
assertEquals("Checking 1900 Date Windowing",
@@ -95,11 +91,9 @@ public final class TestHSSFDateUtil {
*/
@Test
public void excelConversionOnDSTStart() {
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
TimeZone.setDefault(cet);
Calendar cal = new GregorianCalendar(2004, CALENDAR_MARCH, 28);
Calendar cal = LocaleUtil.getLocaleCalendar(2004,MARCH,28,0,0,0);
for (int hour = 0; hour < 24; hour++) {
// Skip 02:00 CET as that is the Daylight change time
// and Java converts it automatically to 03:00 CEST
if (hour == 2) {
@@ -108,6 +102,8 @@ public final class TestHSSFDateUtil {

cal.set(Calendar.HOUR_OF_DAY, hour);
Date javaDate = cal.getTime();

double excelDate = HSSFDateUtil.getExcelDate(javaDate, false);
double difference = excelDate - Math.floor(excelDate);
int differenceInHours = (int) (difference * 24 * 60 + 0.5) / 60;
@@ -126,9 +122,7 @@ public final class TestHSSFDateUtil {
*/
@Test
public void javaConversionOnDSTStart() {
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
TimeZone.setDefault(cet);
Calendar cal = new GregorianCalendar(2004, CALENDAR_MARCH, 28);
Calendar cal = LocaleUtil.getLocaleCalendar(2004,MARCH,28,0,0,0);
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false);
double oneHour = 1.0 / 24;
double oneMinute = oneHour / 60;
@@ -154,9 +148,7 @@ public final class TestHSSFDateUtil {
*/
@Test
public void excelConversionOnDSTEnd() {
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
TimeZone.setDefault(cet);
Calendar cal = new GregorianCalendar(2004, CALENDAR_OCTOBER, 31);
Calendar cal = LocaleUtil.getLocaleCalendar(2004,OCTOBER,31,0,0,0);
for (int hour = 0; hour < 24; hour++) {
cal.set(Calendar.HOUR_OF_DAY, hour);
Date javaDate = cal.getTime();
@@ -178,9 +170,7 @@ public final class TestHSSFDateUtil {
*/
@Test
public void javaConversionOnDSTEnd() {
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
TimeZone.setDefault(cet);
Calendar cal = new GregorianCalendar(2004, CALENDAR_OCTOBER, 31);
Calendar cal = LocaleUtil.getLocaleCalendar(2004,OCTOBER,31,0,0,0);
double excelDate = HSSFDateUtil.getExcelDate(cal.getTime(), false);
double oneHour = 1.0 / 24;
double oneMinute = oneHour / 60;
@@ -198,40 +188,45 @@ public final class TestHSSFDateUtil {
*/
@Test
public void calendarConversion() {
GregorianCalendar date = new GregorianCalendar(2002, 0, 1, 12, 1, 1);
Date expected = date.getTime();

// Iterating over the hours exposes any rounding issues.
for (int hour = -12; hour <= 12; hour++)
{
String id = "GMT" + (hour < 0 ? "" : "+") + hour + ":00";
date.setTimeZone(TimeZone.getTimeZone(id));
date.set(Calendar.HOUR_OF_DAY, 12);
double excelDate = HSSFDateUtil.getExcelDate(date, false);
Date javaDate = HSSFDateUtil.getJavaDate(excelDate);

// Should match despite time-zone
assertEquals("Checking timezone " + id, expected.getTime(), javaDate.getTime());
TimeZone userTZ = LocaleUtil.getUserTimeZone();
LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
try {
Calendar cal = LocaleUtil.getLocaleCalendar(2002,JANUARY,1,12,1,1);
Date expected = cal.getTime();
// Iterating over the hours exposes any rounding issues.
for (int hour = -12; hour <= 12; hour++)
{
String id = "GMT" + (hour < 0 ? "" : "+") + hour + ":00";
cal.setTimeZone(TimeZone.getTimeZone(id));
cal.set(Calendar.HOUR_OF_DAY, 12);
double excelDate = HSSFDateUtil.getExcelDate(cal, false);
Date javaDate = HSSFDateUtil.getJavaDate(excelDate);
// Should match despite time-zone
assertEquals("Checking timezone " + id, expected.getTime(), javaDate.getTime());
}
// Check that the timezone aware getter works correctly
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
TimeZone ldn = TimeZone.getTimeZone("Europe/London");
// 12:45 on 27th April 2012
double excelDate = 41026.53125;
// Same, no change
assertEquals(
HSSFDateUtil.getJavaDate(excelDate, false).getTime(),
HSSFDateUtil.getJavaDate(excelDate, false, cet).getTime()
);
// London vs Copenhagen, should differ by an hour
Date cetDate = HSSFDateUtil.getJavaDate(excelDate, false);
Date ldnDate = HSSFDateUtil.getJavaDate(excelDate, false, ldn);
assertEquals(ldnDate.getTime() - cetDate.getTime(), 60*60*1000);
} finally {
LocaleUtil.setUserTimeZone(userTZ);
}
// Check that the timezone aware getter works correctly
TimeZone cet = TimeZone.getTimeZone("Europe/Copenhagen");
TimeZone ldn = TimeZone.getTimeZone("Europe/London");
TimeZone.setDefault(cet);
// 12:45 on 27th April 2012
double excelDate = 41026.53125;
// Same, no change
assertEquals(
HSSFDateUtil.getJavaDate(excelDate, false).getTime(),
HSSFDateUtil.getJavaDate(excelDate, false, cet).getTime()
);
// London vs Copenhagen, should differ by an hour
Date cetDate = HSSFDateUtil.getJavaDate(excelDate, false);
Date ldnDate = HSSFDateUtil.getJavaDate(excelDate, false, ldn);
assertEquals(ldnDate.getTime() - cetDate.getTime(), 60*60*1000);
}

/**
@@ -405,7 +400,8 @@ public final class TestHSSFDateUtil {

@Test
public void excelDateBorderCases() throws ParseException {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT);
df.setTimeZone(LocaleUtil.getUserTimeZone());
assertEquals(1.0, DateUtil.getExcelDate(df.parse("1900-01-01")), 0.00001);
assertEquals(31.0, DateUtil.getExcelDate(df.parse("1900-01-31")), 0.00001);
@@ -415,38 +411,38 @@ public final class TestHSSFDateUtil {

@Test
public void dateBug_2Excel() {
assertEquals(59.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_FEBRUARY, 28), false), 0.00001);
assertEquals(61.0, HSSFDateUtil.getExcelDate(createDate(1900, CALENDAR_MARCH, 1), false), 0.00001);
assertEquals(59.0, HSSFDateUtil.getExcelDate(createDate(1900, FEBRUARY, 28), false), 0.00001);
assertEquals(61.0, HSSFDateUtil.getExcelDate(createDate(1900, MARCH, 1), false), 0.00001);

assertEquals(37315.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_FEBRUARY, 28), false), 0.00001);
assertEquals(37316.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_MARCH, 1), false), 0.00001);
assertEquals(37257.00, HSSFDateUtil.getExcelDate(createDate(2002, CALENDAR_JANUARY, 1), false), 0.00001);
assertEquals(38074.00, HSSFDateUtil.getExcelDate(createDate(2004, CALENDAR_MARCH, 28), false), 0.00001);
assertEquals(37315.00, HSSFDateUtil.getExcelDate(createDate(2002, FEBRUARY, 28), false), 0.00001);
assertEquals(37316.00, HSSFDateUtil.getExcelDate(createDate(2002, MARCH, 1), false), 0.00001);
assertEquals(37257.00, HSSFDateUtil.getExcelDate(createDate(2002, JANUARY, 1), false), 0.00001);
assertEquals(38074.00, HSSFDateUtil.getExcelDate(createDate(2004, MARCH, 28), false), 0.00001);
}

@Test
public void dateBug_2Java() {
assertEquals(createDate(1900, CALENDAR_FEBRUARY, 28), HSSFDateUtil.getJavaDate(59.0, false));
assertEquals(createDate(1900, CALENDAR_MARCH, 1), HSSFDateUtil.getJavaDate(61.0, false));
assertEquals(createDate(1900, FEBRUARY, 28), HSSFDateUtil.getJavaDate(59.0, false));
assertEquals(createDate(1900, MARCH, 1), HSSFDateUtil.getJavaDate(61.0, false));

assertEquals(createDate(2002, CALENDAR_FEBRUARY, 28), HSSFDateUtil.getJavaDate(37315.00, false));
assertEquals(createDate(2002, CALENDAR_MARCH, 1), HSSFDateUtil.getJavaDate(37316.00, false));
assertEquals(createDate(2002, CALENDAR_JANUARY, 1), HSSFDateUtil.getJavaDate(37257.00, false));
assertEquals(createDate(2004, CALENDAR_MARCH, 28), HSSFDateUtil.getJavaDate(38074.00, false));
assertEquals(createDate(2002, FEBRUARY, 28), HSSFDateUtil.getJavaDate(37315.00, false));
assertEquals(createDate(2002, MARCH, 1), HSSFDateUtil.getJavaDate(37316.00, false));
assertEquals(createDate(2002, JANUARY, 1), HSSFDateUtil.getJavaDate(37257.00, false));
assertEquals(createDate(2004, MARCH, 28), HSSFDateUtil.getJavaDate(38074.00, false));
}

@Test
public void date1904() {
assertEquals(createDate(1904, CALENDAR_JANUARY, 2), HSSFDateUtil.getJavaDate(1.0, true));
assertEquals(createDate(1904, CALENDAR_JANUARY, 1), HSSFDateUtil.getJavaDate(0.0, true));
assertEquals(0.0, HSSFDateUtil.getExcelDate(createDate(1904, CALENDAR_JANUARY, 1), true), 0.00001);
assertEquals(1.0, HSSFDateUtil.getExcelDate(createDate(1904, CALENDAR_JANUARY, 2), true), 0.00001);
assertEquals(createDate(1904, JANUARY, 2), HSSFDateUtil.getJavaDate(1.0, true));
assertEquals(createDate(1904, JANUARY, 1), HSSFDateUtil.getJavaDate(0.0, true));
assertEquals(0.0, HSSFDateUtil.getExcelDate(createDate(1904, JANUARY, 1), true), 0.00001);
assertEquals(1.0, HSSFDateUtil.getExcelDate(createDate(1904, JANUARY, 2), true), 0.00001);

assertEquals(createDate(1998, CALENDAR_JULY, 5), HSSFDateUtil.getJavaDate(35981, false));
assertEquals(createDate(1998, CALENDAR_JULY, 5), HSSFDateUtil.getJavaDate(34519, true));
assertEquals(createDate(1998, JULY, 5), HSSFDateUtil.getJavaDate(35981, false));
assertEquals(createDate(1998, JULY, 5), HSSFDateUtil.getJavaDate(34519, true));

assertEquals(35981.0, HSSFDateUtil.getExcelDate(createDate(1998, CALENDAR_JULY, 5), false), 0.00001);
assertEquals(34519.0, HSSFDateUtil.getExcelDate(createDate(1998, CALENDAR_JULY, 5), true), 0.00001);
assertEquals(35981.0, HSSFDateUtil.getExcelDate(createDate(1998, JULY, 5), false), 0.00001);
assertEquals(34519.0, HSSFDateUtil.getExcelDate(createDate(1998, JULY, 5), true), 0.00001);
}

/**
@@ -462,9 +458,7 @@ public final class TestHSSFDateUtil {
* @param day one based
*/
private static Date createDate(int year, int month, int day, int hour, int minute, int second) {
Calendar c = new GregorianCalendar(Locale.ROOT);
c.set(year, month, day, hour, minute, second);
c.set(Calendar.MILLISECOND, 0);
Calendar c = LocaleUtil.getLocaleCalendar(year, month, day, hour, minute, second);
return c.getTime();
}

@@ -474,26 +468,26 @@ public final class TestHSSFDateUtil {
@Test
public void absoluteDay() {
// 1 Jan 1900 is 1 day after 31 Dec 1899
GregorianCalendar calendar = new GregorianCalendar(1900, 0, 1);
assertEquals("Checking absolute day (1 Jan 1900)", 1, HSSFDateUtil.absoluteDay(calendar, false));
Calendar cal = LocaleUtil.getLocaleCalendar(1900,JANUARY,1,0,0,0);
assertEquals("Checking absolute day (1 Jan 1900)", 1, HSSFDateUtil.absoluteDay(cal, false));
// 1 Jan 1901 is 366 days after 31 Dec 1899
calendar = new GregorianCalendar(1901, 0, 1);
assertEquals("Checking absolute day (1 Jan 1901)", 366, HSSFDateUtil.absoluteDay(calendar, false));
cal.set(1901,JANUARY,1,0,0,0);
assertEquals("Checking absolute day (1 Jan 1901)", 366, HSSFDateUtil.absoluteDay(cal, false));
}

@Test
public void absoluteDayYearTooLow() {
GregorianCalendar calendar = new GregorianCalendar(1899, 0, 1);
Calendar cal = LocaleUtil.getLocaleCalendar(1899,JANUARY,1,0,0,0);
try {
HSSFDateUtil.absoluteDay(calendar, false);
HSSFDateUtil.absoluteDay(cal, false);
fail("Should fail here");
} catch (IllegalArgumentException e) {
// expected here
}

try {
calendar = new GregorianCalendar(1903, 0, 1);
HSSFDateUtil.absoluteDay(calendar, true);
cal.set(1903,JANUARY,1,0,0,0);
HSSFDateUtil.absoluteDay(cal, true);
fail("Should fail here");
} catch (IllegalArgumentException e) {
// expected here
@@ -512,8 +506,8 @@ public final class TestHSSFDateUtil {

@Test
public void parseDate() {
assertEquals(createDate(2008, Calendar.AUGUST, 3), HSSFDateUtil.parseYYYYMMDDDate("2008/08/03"));
assertEquals(createDate(1994, Calendar.MAY, 1), HSSFDateUtil.parseYYYYMMDDDate("1994/05/01"));
assertEquals(createDate(2008, AUGUST, 3), HSSFDateUtil.parseYYYYMMDDDate("2008/08/03"));
assertEquals(createDate(1994, MAY, 1), HSSFDateUtil.parseYYYYMMDDDate("1994/05/01"));
}

/**
@@ -540,10 +534,8 @@ public final class TestHSSFDateUtil {
HSSFSheet sheet = workbook.createSheet();
HSSFCell cell = sheet.createRow(0).createCell(0);

Calendar cal = Calendar.getInstance();

// A pseudo special Excel dates
cal.set(1900, 0, 1);
Calendar cal = LocaleUtil.getLocaleCalendar(1900, JANUARY, 1);

Date valueToTest = cal.getTime();


+ 17
- 9
src/testcases/org/apache/poi/hssf/usermodel/TestReadWriteChart.java 查看文件

@@ -17,42 +17,50 @@

package org.apache.poi.hssf.usermodel;

import java.util.GregorianCalendar;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import junit.framework.TestCase;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.InternalSheet;
import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.EOFRecord;
import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;

/**
* @author Glen Stampoultzis (glens at apache.org)
*/
public final class TestReadWriteChart extends TestCase {
public final class TestReadWriteChart {

/**
* In the presence of a chart we need to make sure BOF/EOF records still exist.
*/
public void testBOFandEOFRecords() {
@Test
public void testBOFandEOFRecords() throws Exception {
HSSFWorkbook workbook = HSSFTestDataSamples.openSampleWorkbook("SimpleChart.xls");
HSSFSheet sheet = workbook.getSheetAt(0);
HSSFRow firstRow = sheet.getRow(0);
HSSFCell firstCell = firstRow.getCell(0);

//System.out.println("first assertion for date");
assertEquals(new GregorianCalendar(2000, 0, 1, 10, 51, 2).getTime(),
HSSFDateUtil
.getJavaDate(firstCell.getNumericCellValue(), false));
Calendar calExp = LocaleUtil.getLocaleCalendar(2000, 0, 1, 10, 51, 2);
Date dateAct = HSSFDateUtil.getJavaDate(firstCell.getNumericCellValue(), false);
assertEquals(calExp.getTime(), dateAct);
HSSFRow row = sheet.createRow(15);
HSSFCell cell = row.createCell(1);

cell.setCellValue(22);
InternalSheet newSheet = workbook.getSheetAt(0).getSheet();
List records = newSheet.getRecords();
List<RecordBase> records = newSheet.getRecords();

assertTrue(records.get(0) instanceof BOFRecord);
assertTrue(records.get(records.size() - 1) instanceof EOFRecord);
workbook.close();
}
}

+ 34
- 18
src/testcases/org/apache/poi/hssf/usermodel/TestText.java 查看文件

@@ -18,21 +18,23 @@
package org.apache.poi.hssf.usermodel;
import static org.junit.Assert.assertArrayEquals;
import junit.framework.TestCase;
import static org.junit.Assert.assertEquals;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.HSSFTestModelHelper;
import org.apache.poi.hssf.model.TextboxShape;
import org.apache.poi.hssf.record.ObjRecord;
import org.apache.poi.hssf.record.TextObjectRecord;
import org.junit.Test;
/**
* @author Evgeniy Berlog
* @date 25.06.12
*/
public class TestText extends TestCase {
public class TestText {
public void testResultEqualsToAbstractShape() {
@Test
public void testResultEqualsToAbstractShape() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
@@ -81,11 +83,14 @@ public class TestText extends TestCase {
assertEquals(expected.length, actual.length);
assertArrayEquals(expected, actual);
wb.close();
}
public void testAddTextToExistingFile() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
@Test
public void testAddTextToExistingFile() throws Exception {
HSSFWorkbook wb1 = new HSSFWorkbook();
HSSFSheet sh = wb1.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor());
textbox.setString(new HSSFRichTextString("just for test"));
@@ -94,8 +99,9 @@ public class TestText extends TestCase {
assertEquals(patriarch.getChildren().size(), 2);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1);
wb1.close();
sh = wb2.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 2);
@@ -103,19 +109,23 @@ public class TestText extends TestCase {
text3.setString(new HSSFRichTextString("text3"));
assertEquals(patriarch.getChildren().size(), 3);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2);
wb2.close();
sh = wb3.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
assertEquals(patriarch.getChildren().size(), 3);
assertEquals(((HSSFTextbox) patriarch.getChildren().get(0)).getString().getString(), "just for test");
assertEquals(((HSSFTextbox) patriarch.getChildren().get(1)).getString().getString(), "just for test2");
assertEquals(((HSSFTextbox) patriarch.getChildren().get(2)).getString().getString(), "text3");
wb3.close();
}
public void testSetGetProperties() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sh = wb.createSheet();
@Test
public void testSetGetProperties() throws Exception {
HSSFWorkbook wb1 = new HSSFWorkbook();
HSSFSheet sh = wb1.createSheet();
HSSFPatriarch patriarch = sh.createDrawingPatriarch();
HSSFTextbox textbox = patriarch.createTextbox(new HSSFClientAnchor());
textbox.setString(new HSSFRichTextString("test"));
@@ -139,8 +149,9 @@ public class TestText extends TestCase {
textbox.setMarginTop(10);
assertEquals(textbox.getMarginTop(), 10);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
HSSFWorkbook wb2 = HSSFTestDataSamples.writeOutAndReadBack(wb1);
wb1.close();
sh = wb2.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
textbox = (HSSFTextbox) patriarch.getChildren().get(0);
assertEquals(textbox.getString().getString(), "test");
@@ -167,8 +178,9 @@ public class TestText extends TestCase {
assertEquals(textbox.getMarginRight(), 91);
assertEquals(textbox.getMarginTop(), 101);
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sh = wb.getSheetAt(0);
HSSFWorkbook wb3 = HSSFTestDataSamples.writeOutAndReadBack(wb2);
wb2.close();
sh = wb3.getSheetAt(0);
patriarch = sh.getDrawingPatriarch();
textbox = (HSSFTextbox) patriarch.getChildren().get(0);
@@ -179,9 +191,12 @@ public class TestText extends TestCase {
assertEquals(textbox.getMarginLeft(), 81);
assertEquals(textbox.getMarginRight(), 91);
assertEquals(textbox.getMarginTop(), 101);
wb3.close();
}
public void testExistingFileWithText(){
@Test
public void testExistingFileWithText() throws Exception {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("drawings.xls");
HSSFSheet sheet = wb.getSheet("text");
HSSFPatriarch drawing = sheet.getDrawingPatriarch();
@@ -194,5 +209,6 @@ public class TestText extends TestCase {
assertEquals(textbox.getMarginLeft(), 3600000);
assertEquals(textbox.getMarginRight(), 0);
assertEquals(textbox.getString().getString(), "teeeeesssstttt");
wb.close();
}
}

+ 21
- 23
src/testcases/org/apache/poi/ss/format/CellFormatTestBase.java 查看文件

@@ -25,10 +25,12 @@ import static java.awt.Color.ORANGE;
import static java.awt.Color.RED;
import static java.awt.Color.WHITE;
import static java.awt.Color.YELLOW;
import static org.junit.Assert.assertEquals;

import java.awt.Color;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
@@ -36,15 +38,14 @@ import java.util.TreeSet;

import javax.swing.JLabel;

import junit.framework.TestCase;

import org.apache.poi.ss.ITestDataProvider;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;

/**
* This class is a base class for spreadsheet-based tests, such as are used for
@@ -57,9 +58,7 @@ import org.apache.poi.util.POILogFactory;
* flag "Categories" is not empty, only tests that have at least one category
* listed in "Categories" are run.
*/
@SuppressWarnings(
{"JUnitTestCaseWithNoTests", "JUnitTestClassNamingConvention"})
public class CellFormatTestBase extends TestCase {
public class CellFormatTestBase {
private static final POILogger logger = POILogFactory.getLogger(CellFormatTestBase.class);

private final ITestDataProvider _testDataProvider;
@@ -86,7 +85,6 @@ public class CellFormatTestBase extends TestCase {
abstract static class CellValue {
abstract Object getValue(Cell cell);

@SuppressWarnings({"UnusedDeclaration"})
Color getColor(Cell cell) {
return TEST_COLOR;
}
@@ -114,20 +112,19 @@ public class CellFormatTestBase extends TestCase {
}

Sheet sheet = workbook.getSheet("Tests");
int end = sheet.getLastRowNum();
// Skip the header row, therefore "+ 1"
for (int r = sheet.getFirstRowNum() + 1; r <= end; r++) {
Row row = sheet.getRow(r);
if (row == null)
continue;
int cellnum = 0;
String expectedText = row.getCell(cellnum).getStringCellValue();
String format = row.getCell(1).getStringCellValue();
Iterator<Row> rowIter = sheet.rowIterator();
// Skip the header row
rowIter.next();
while (rowIter.hasNext()) {
Row row = rowIter.next();
if (row == null) continue;
String expectedText = row.getCell(0).getStringCellValue();
String format = row.getCell(1).getStringCellValue();
Cell value = row.getCell(2);
String testCategoryList = row.getCell(3).getStringCellValue();
boolean byCategory = runByCategory(runCategories, testCategoryList);
if ((expectedText.length() > 0 || format.length() > 0) && byCategory) {
Cell cell = row.getCell(2);
tryFormat(r, expectedText, format, valueGetter, cell);
tryFormat(row.getRowNum(), expectedText, format, valueGetter, value);
}
}
}
@@ -216,16 +213,17 @@ public class CellFormatTestBase extends TestCase {
label.setForeground(testColor);
label.setText("xyzzy");

logger.log(POILogger.INFO, String.format("Row %d: \"%s\" -> \"%s\": expected \"%s\"", row + 1,
String.valueOf(value), desc, expectedText));
logger.log(POILogger.INFO, String.format(LocaleUtil.getUserLocale(),
"Row %d: \"%s\" -> \"%s\": expected \"%s\"",
row + 1, String.valueOf(value), desc, expectedText));
String actualText = tryColor(desc, null, getter, value, expectedText,
testColor);
logger.log(POILogger.INFO, String.format(", actual \"%s\")%n", actualText));
logger.log(POILogger.INFO, String.format(LocaleUtil.getUserLocale(),
", actual \"%s\")%n", actualText));

if (tryAllColors && testColor != TEST_COLOR) {
for (int i = 0; i < COLOR_NAMES.length; i++) {
String cname = COLOR_NAMES[i];
tryColor(desc, cname, getter, value, expectedText, COLORS[i]);
tryColor(desc, COLOR_NAMES[i], getter, value, expectedText, COLORS[i]);
}
}
}

+ 108
- 26
src/testcases/org/apache/poi/ss/format/TestCellFormat.java 查看文件

@@ -16,23 +16,45 @@
==================================================================== */
package org.apache.poi.ss.format;

import static org.junit.Assert.assertEquals;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

import javax.swing.JLabel;

import junit.framework.TestCase;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.LocaleUtil;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class TestCellFormat extends TestCase {
public class TestCellFormat {
private static TimeZone userTimeZone;
@BeforeClass
public static void setTimeZone() {
userTimeZone = LocaleUtil.getUserTimeZone();
LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
LocaleUtil.setUserLocale(Locale.US);
}
@AfterClass
public static void resetTimeZone() {
LocaleUtil.setUserTimeZone(userTimeZone);
LocaleUtil.setUserLocale(Locale.ROOT);
}
private static final String _255_POUND_SIGNS;
static {
@@ -43,6 +65,7 @@ public class TestCellFormat extends TestCase {
_255_POUND_SIGNS = sb.toString();
}
@Test
public void testSome() {
JLabel l = new JLabel();
CellFormat fmt = CellFormat.getInstance(
@@ -50,48 +73,56 @@ public class TestCellFormat extends TestCase {
fmt.apply(l, 1.1);
}
@Test
public void testPositiveFormatHasOnePart() {
CellFormat fmt = CellFormat.getInstance("0.00");
CellFormatResult result = fmt.apply(12.345);
assertEquals("12.35", result.text);
}
@Test
public void testNegativeFormatHasOnePart() {
CellFormat fmt = CellFormat.getInstance("0.00");
CellFormatResult result = fmt.apply(-12.345);
assertEquals("-12.35", result.text);
}
@Test
public void testZeroFormatHasOnePart() {
CellFormat fmt = CellFormat.getInstance("0.00");
CellFormatResult result = fmt.apply(0.0);
assertEquals("0.00", result.text);
}
@Test
public void testPositiveFormatHasPosAndNegParts() {
CellFormat fmt = CellFormat.getInstance("0.00;-0.00");
CellFormatResult result = fmt.apply(12.345);
assertEquals("12.35", result.text);
}
@Test
public void testNegativeFormatHasPosAndNegParts() {
CellFormat fmt = CellFormat.getInstance("0.00;-0.00");
CellFormatResult result = fmt.apply(-12.345);
assertEquals("-12.35", result.text);
}

@Test
public void testNegativeFormatHasPosAndNegParts2() {
CellFormat fmt = CellFormat.getInstance("0.00;(0.00)");
CellFormatResult result = fmt.apply(-12.345);
assertEquals("(12.35)", result.text);
}
@Test
public void testZeroFormatHasPosAndNegParts() {
CellFormat fmt = CellFormat.getInstance("0.00;-0.00");
CellFormatResult result = fmt.apply(0.0);
assertEquals("0.00", result.text);
}

@Test
public void testFormatWithThreeSections() {
CellFormat fmt = CellFormat.getInstance("0.00;-0.00;-");
@@ -101,6 +132,7 @@ public class TestCellFormat extends TestCase {
assertEquals("abc", fmt.apply("abc").text);
}
@Test
public void testFormatWithFourSections() {
CellFormat fmt = CellFormat.getInstance("0.00;-0.00;-; @ ");
@@ -110,7 +142,8 @@ public class TestCellFormat extends TestCase {
assertEquals(" abc ", fmt.apply("abc").text);
}

public void testApplyCellForGeneralFormat() {
@Test
public void testApplyCellForGeneralFormat() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -147,9 +180,11 @@ public class TestCellFormat extends TestCase {
CellFormatResult result4 = cf.apply(cell4);
assertEquals("abc", result4.text);
wb.close();
}
public void testApplyCellForAtFormat() {
@Test
public void testApplyCellForAtFormat() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -186,9 +221,11 @@ public class TestCellFormat extends TestCase {
CellFormatResult result4 = cf.apply(cell4);
assertEquals("abc", result4.text);
wb.close();
}
public void testApplyCellForDateFormat() {
@Test
public void testApplyCellForDateFormat() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -207,9 +244,11 @@ public class TestCellFormat extends TestCase {
CellFormatResult result1 = cf.apply(cell1);
assertEquals(_255_POUND_SIGNS, result1.text);
wb.close();
}
public void testApplyCellForTimeFormat() {
@Test
public void testApplyCellForTimeFormat() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -223,9 +262,11 @@ public class TestCellFormat extends TestCase {
CellFormatResult result = cf.apply(cell);
assertEquals("03:04", result.text);
wb.close();
}
public void testApplyCellForDateFormatAndNegativeFormat() {
@Test
public void testApplyCellForDateFormatAndNegativeFormat() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -244,9 +285,11 @@ public class TestCellFormat extends TestCase {
CellFormatResult result1 = cf.apply(cell1);
assertEquals("(1)", result1.text);
wb.close();
}
public void testApplyJLabelCellForGeneralFormat() {
@Test
public void testApplyJLabelCellForGeneralFormat() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -294,9 +337,11 @@ public class TestCellFormat extends TestCase {
assertEquals("abc", result4.text);
assertEquals("abc", label4.getText());
wb.close();
}
public void testApplyJLabelCellForAtFormat() {
@Test
public void testApplyJLabelCellForAtFormat() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -344,9 +389,11 @@ public class TestCellFormat extends TestCase {
assertEquals("abc", result4.text);
assertEquals("abc", label4.getText());
wb.close();
}

public void testApplyJLabelCellForDateFormat() {
@Test
public void testApplyJLabelCellForDateFormat() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -370,9 +417,11 @@ public class TestCellFormat extends TestCase {
assertEquals(_255_POUND_SIGNS, result1.text);
assertEquals(_255_POUND_SIGNS, label1.getText());
wb.close();
}

public void testApplyJLabelCellForTimeFormat() {
@Test
public void testApplyJLabelCellForTimeFormat() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -389,9 +438,11 @@ public class TestCellFormat extends TestCase {
assertEquals("03:04", result.text);
assertEquals("03:04", label.getText());
wb.close();
}
public void testApplyJLabelCellForDateFormatAndNegativeFormat() {
@Test
public void testApplyJLabelCellForDateFormatAndNegativeFormat() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -415,9 +466,11 @@ public class TestCellFormat extends TestCase {
assertEquals("(1)", result1.text);
assertEquals("(1)", label1.getText());
wb.close();
}

public void testApplyFormatHasOnePartAndPartHasCondition() {
@Test
public void testApplyFormatHasOnePartAndPartHasCondition() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -442,9 +495,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc");
assertEquals("abc", cf.apply(cell).text);
wb.close();
}
public void testApplyFormatHasTwoPartsFirstHasCondition() {
@Test
public void testApplyFormatHasTwoPartsFirstHasCondition() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -475,9 +530,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("TRUE");
assertEquals("TRUE", cf.apply(cell).text);
wb.close();
}
public void testApplyFormatHasTwoPartsBothHaveCondition() {
@Test
public void testApplyFormatHasTwoPartsBothHaveCondition() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -505,9 +562,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc");
assertEquals("abc", cf.apply(cell).text);
wb.close();
}
public void testApplyFormatHasThreePartsFirstHasCondition() {
@Test
public void testApplyFormatHasThreePartsFirstHasCondition() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -537,9 +596,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc");
assertEquals("abc", cf.apply(cell).text);
wb.close();
}
public void testApplyFormatHasThreePartsFirstTwoHaveCondition() {
@Test
public void testApplyFormatHasThreePartsFirstTwoHaveCondition() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -564,9 +625,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc");
assertEquals("abc", cf.apply(cell).text);
wb.close();
}

public void testApplyFormatHasThreePartsFirstIsDateFirstTwoHaveCondition() {
@Test
public void testApplyFormatHasThreePartsFirstIsDateFirstTwoHaveCondition() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -591,9 +654,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc");
assertEquals("abc", cf.apply(cell).text);
wb.close();
}

public void testApplyFormatHasTwoPartsFirstHasConditionSecondIsGeneral() {
@Test
public void testApplyFormatHasTwoPartsFirstHasConditionSecondIsGeneral() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -618,9 +683,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc");
assertEquals("abc", cf.apply(cell).text);
wb.close();
}

public void testApplyFormatHasThreePartsFirstTwoHaveConditionThirdIsGeneral() {
@Test
public void testApplyFormatHasThreePartsFirstTwoHaveConditionThirdIsGeneral() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -645,9 +712,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc");
assertEquals("abc", cf.apply(cell).text);
wb.close();
}
public void testApplyFormatHasFourPartsFirstHasCondition() {
@Test
public void testApplyFormatHasFourPartsFirstHasCondition() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -677,9 +746,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue("abc");
assertEquals("~~abc~~", cf.apply(cell).text);
wb.close();
}
public void testApplyFormatHasFourPartsSecondHasCondition() {
@Test
public void testApplyFormatHasFourPartsSecondHasCondition() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -710,9 +781,11 @@ public class TestCellFormat extends TestCase {
cell.setCellValue(true);
assertEquals("~~TRUE~~", cf.apply(cell).text);
wb.close();
}

public void testApplyFormatHasFourPartsFirstTwoHaveCondition() {
@Test
public void testApplyFormatHasFourPartsFirstTwoHaveCondition() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -739,11 +812,14 @@ public class TestCellFormat extends TestCase {
cell.setCellValue(true);
assertEquals("~~TRUE~~", cf.apply(cell).text);
wb.close();
}
/*
* Test apply(Object value) with a number as parameter
*/
@Test
public void testApplyObjectNumber() {
CellFormat cf1 = CellFormat.getInstance("0.000");
@@ -771,15 +847,17 @@ public class TestCellFormat extends TestCase {
/*
* Test apply(Object value) with a Date as parameter
*/
@Test
public void testApplyObjectDate() throws ParseException {
CellFormat cf1 = CellFormat.getInstance("m/d/yyyy");
Date date1 = new SimpleDateFormat("M/d/y").parse("01/11/2012");
Date date1 = new SimpleDateFormat("M/d/y", Locale.ROOT).parse("01/11/2012");
assertEquals("1/11/2012", cf1.apply(date1).text);
}

public void testApplyCellForDateFormatWithConditions() {
@Test
public void testApplyCellForDateFormatWithConditions() throws Exception {
// Create a workbook, row and cell to test with
Workbook wb = new HSSFWorkbook();
@@ -798,11 +876,13 @@ public class TestCellFormat extends TestCase {
cell.setCellValue(-1);
assertEquals(_255_POUND_SIGNS, cf.apply(cell).text);
wb.close();
}
/*
* Test apply(Object value) with a String as parameter
*/
@Test
public void testApplyObjectString() {
CellFormat cf = CellFormat.getInstance("0.00");
@@ -814,6 +894,7 @@ public class TestCellFormat extends TestCase {
/*
* Test apply(Object value) with a Boolean as parameter
*/
@Test
public void testApplyObjectBoolean() {
CellFormat cf1 = CellFormat.getInstance("0");
@@ -826,6 +907,7 @@ public class TestCellFormat extends TestCase {
}
@Test
public void testSimpleFractionFormat() throws IOException {
CellFormat cf1 = CellFormat.getInstance("# ?/?");
// Create a workbook, row and cell to test with

+ 16
- 17
src/testcases/org/apache/poi/ss/formula/atp/TestDateParser.java 查看文件

@@ -17,21 +17,18 @@

package org.apache.poi.ss.formula.atp;

import static java.util.Calendar.OCTOBER;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.util.Calendar;
import java.util.Date;

import junit.framework.TestCase;

import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;

/**
* @author jfaenomoto@gmail.com
*/
public class TestDateParser extends TestCase {

public class TestDateParser {
@Test
public void testFailWhenNoDate() {
try {
DateParser.parseDate("potato");
@@ -41,6 +38,7 @@ public class TestDateParser extends TestCase {
}
}

@Test
public void testFailWhenLooksLikeDateButItIsnt() {
try {
DateParser.parseDate("potato/cucumber/banana");
@@ -50,6 +48,7 @@ public class TestDateParser extends TestCase {
}
}

@Test
public void testFailWhenIsInvalidDate() {
try {
DateParser.parseDate("13/13/13");
@@ -59,18 +58,18 @@ public class TestDateParser extends TestCase {
}
}

@SuppressWarnings("deprecation")
@Test
public void testShouldParseValidDate() throws EvaluationException {
Calendar aDate = Calendar.getInstance();
aDate.setTime(new Date(84, OCTOBER, 20));
assertEquals(aDate, DateParser.parseDate("1984/10/20"));
Calendar expDate = LocaleUtil.getLocaleCalendar(1984, Calendar.OCTOBER, 20);
Calendar actDate = DateParser.parseDate("1984/10/20");
assertEquals(expDate, actDate);
}

@SuppressWarnings("deprecation")
@Test
public void testShouldIgnoreTimestamp() throws EvaluationException {
Calendar aDate = Calendar.getInstance();
aDate.setTime(new Date(84, OCTOBER, 20));
assertEquals(aDate, DateParser.parseDate("1984/10/20 12:34:56"));
Calendar expDate = LocaleUtil.getLocaleCalendar(1984, Calendar.OCTOBER, 20);
Calendar actDate = DateParser.parseDate("1984/10/20 12:34:56");
assertEquals(expDate, actDate);
}

}

+ 7
- 24
src/testcases/org/apache/poi/ss/formula/atp/TestNetworkdaysFunction.java 查看文件

@@ -17,21 +17,12 @@

package org.apache.poi.ss.formula.atp;

import static java.util.Calendar.DECEMBER;
import static java.util.Calendar.JANUARY;
import static java.util.Calendar.MARCH;
import static java.util.Calendar.NOVEMBER;
import static java.util.Calendar.OCTOBER;
import static org.apache.poi.ss.formula.eval.ErrorEval.NAME_INVALID;
import static org.apache.poi.ss.formula.eval.ErrorEval.VALUE_INVALID;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import junit.framework.TestCase;

import org.apache.poi.ss.formula.OperationEvaluationContext;
import org.apache.poi.ss.formula.TwoDEval;
import org.apache.poi.ss.formula.eval.AreaEval;
@@ -40,23 +31,15 @@ import org.apache.poi.ss.formula.eval.NumericValueEval;
import org.apache.poi.ss.formula.eval.StringEval;
import org.apache.poi.ss.formula.eval.ValueEval;

/**
* @author jfaenomoto@gmail.com
*/
@SuppressWarnings("deprecation") // YK: uses deprecated {@link java.util.Date(int year, int month, int date)}
public class TestNetworkdaysFunction extends TestCase {

private static final SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");

private static final String STARTING_DATE = formatter.format(new Date(108, OCTOBER, 1));

private static final String END_DATE = formatter.format(new Date(109, MARCH, 1));

private static final String FIRST_HOLIDAY = formatter.format(new Date(108, NOVEMBER, 26));
import junit.framework.TestCase;

private static final String SECOND_HOLIDAY = formatter.format(new Date(108, DECEMBER, 4));
public class TestNetworkdaysFunction extends TestCase {

private static final String THIRD_HOLIDAY = formatter.format(new Date(109, JANUARY, 21));
private static final String STARTING_DATE = "2008/10/01";
private static final String END_DATE = "2009/03/01";
private static final String FIRST_HOLIDAY = "2008/11/26";
private static final String SECOND_HOLIDAY = "2008/12/04";
private static final String THIRD_HOLIDAY = "2009/01/21";

private static final OperationEvaluationContext EC = new OperationEvaluationContext(null, null, 1, 1, 1, null);


+ 45
- 32
src/testcases/org/apache/poi/ss/formula/atp/TestWorkdayCalculator.java 查看文件

@@ -17,87 +17,100 @@

package org.apache.poi.ss.formula.atp;

import static java.util.Calendar.DECEMBER;
import static java.util.Calendar.SATURDAY;
import static org.junit.Assert.assertEquals;

import java.util.Calendar;
import java.util.Date;

import junit.framework.TestCase;

import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;

/**
* @author jfaenomoto@gmail.com
*/
@SuppressWarnings("deprecation") // YK: heavily uses deprecated {@link java.util.Date(int year, int month, int date)}
public class TestWorkdayCalculator extends TestCase {
public class TestWorkdayCalculator {

@Test
public void testCalculateWorkdaysShouldReturnJustWeekdaysWhenNoWeekend() {
final double A_MONDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 12));
final double A_FRIDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 16));
final double A_MONDAY = DateUtil.getExcelDate(d(2011, 12, 12));
final double A_FRIDAY = DateUtil.getExcelDate(d(2011, 12, 16));
assertEquals(5, WorkdayCalculator.instance.calculateWorkdays(A_MONDAY, A_FRIDAY, new double[0]));
}

@Test
public void testCalculateWorkdaysShouldReturnAllDaysButNoSaturdays() {
final double A_WEDNESDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 14));
final double A_SATURDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 18));
final double A_WEDNESDAY = DateUtil.getExcelDate(d(2011, 12, 14));
final double A_SATURDAY = DateUtil.getExcelDate(d(2011, 12, 18));
assertEquals(3, WorkdayCalculator.instance.calculateWorkdays(A_WEDNESDAY, A_SATURDAY, new double[0]));
}

@Test
public void testCalculateWorkdaysShouldReturnAllDaysButNoSundays() {
final double A_SUNDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 11));
final double A_THURSDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 15));
final double A_SUNDAY = DateUtil.getExcelDate(d(2011, 12, 11));
final double A_THURSDAY = DateUtil.getExcelDate(d(2011, 12, 15));
assertEquals(4, WorkdayCalculator.instance.calculateWorkdays(A_SUNDAY, A_THURSDAY, new double[0]));
}

@Test
public void testCalculateWorkdaysShouldReturnAllDaysButNoHolidays() {
final double A_MONDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 12));
final double A_FRIDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 16));
final double A_WEDNESDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 14));
final double A_MONDAY = DateUtil.getExcelDate(d(2011, 12, 12));
final double A_FRIDAY = DateUtil.getExcelDate(d(2011, 12, 16));
final double A_WEDNESDAY = DateUtil.getExcelDate(d(2011, 12, 14));
assertEquals(4, WorkdayCalculator.instance.calculateWorkdays(A_MONDAY, A_FRIDAY, new double[]{ A_WEDNESDAY }));
}

@Test
public void testCalculateWorkdaysShouldIgnoreWeekendHolidays() {
final double A_FRIDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 16));
final double A_SATURDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 17));
final double A_SUNDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 18));
final double A_WEDNESDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 21));
final double A_FRIDAY = DateUtil.getExcelDate(d(2011, 12, 16));
final double A_SATURDAY = DateUtil.getExcelDate(d(2011, 12, 17));
final double A_SUNDAY = DateUtil.getExcelDate(d(2011, 12, 18));
final double A_WEDNESDAY = DateUtil.getExcelDate(d(2011, 12, 21));
assertEquals(4, WorkdayCalculator.instance.calculateWorkdays(A_FRIDAY, A_WEDNESDAY, new double[]{ A_SATURDAY, A_SUNDAY }));
}

@Test
public void testCalculateWorkdaysNumberOfDays() {
double start = 41553.0;
int days = 1;
assertEquals(new Date(113, 9, 7), WorkdayCalculator.instance.calculateWorkdays(start, days, new double[0]));
assertEquals(d(2013, 10, 7), WorkdayCalculator.instance.calculateWorkdays(start, days, new double[0]));
}

@Test
public void testPastDaysOfWeekShouldReturn0Past0Saturdays() {
final double A_WEDNESDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 7));
final double A_FRIDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 9));
final double A_WEDNESDAY = DateUtil.getExcelDate(d(2011, 12, 7));
final double A_FRIDAY = DateUtil.getExcelDate(d(2011, 12, 9));
assertEquals(0, WorkdayCalculator.instance.pastDaysOfWeek(A_WEDNESDAY, A_FRIDAY, SATURDAY));
}

@Test
public void testPastDaysOfWeekShouldReturn1Past1Saturdays() {
final double A_WEDNESDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 7));
final double A_SUNDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 11));
final double A_WEDNESDAY = DateUtil.getExcelDate(d(2011, 12, 7));
final double A_SUNDAY = DateUtil.getExcelDate(d(2011, 12, 11));
assertEquals(1, WorkdayCalculator.instance.pastDaysOfWeek(A_WEDNESDAY, A_SUNDAY, SATURDAY));
}

@Test
public void testPastDaysOfWeekShouldReturn2Past2Saturdays() {
final double A_THURSDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 8));
final double A_MONDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 19));
final double A_THURSDAY = DateUtil.getExcelDate(d(2011, 12, 8));
final double A_MONDAY = DateUtil.getExcelDate(d(2011, 12, 19));
assertEquals(2, WorkdayCalculator.instance.pastDaysOfWeek(A_THURSDAY, A_MONDAY, SATURDAY));
}

@Test
public void testPastDaysOfWeekShouldReturn1BeginningFromASaturday() {
final double A_SATURDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 10));
final double A_SUNDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 11));
final double A_SATURDAY = DateUtil.getExcelDate(d(2011, 12, 10));
final double A_SUNDAY = DateUtil.getExcelDate(d(2011, 12, 11));
assertEquals(1, WorkdayCalculator.instance.pastDaysOfWeek(A_SATURDAY, A_SUNDAY, SATURDAY));
}

@Test
public void testPastDaysOfWeekShouldReturn1EndingAtASaturday() {
final double A_THURSDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 8));
final double A_SATURDAY = DateUtil.getExcelDate(new Date(111, DECEMBER, 10));
final double A_THURSDAY = DateUtil.getExcelDate(d(2011, 12, 8));
final double A_SATURDAY = DateUtil.getExcelDate(d(2011, 12, 10));
assertEquals(1, WorkdayCalculator.instance.pastDaysOfWeek(A_THURSDAY, A_SATURDAY, SATURDAY));
}
private static Date d(int year, int month, int day) {
Calendar cal = LocaleUtil.getLocaleCalendar(year, month-1, day, 0, 0, 0);
return cal.getTime();
}
}

+ 97
- 76
src/testcases/org/apache/poi/ss/formula/atp/TestWorkdayFunction.java 查看文件

@@ -18,17 +18,12 @@

package org.apache.poi.ss.formula.atp;

import static java.util.Calendar.APRIL;
import static java.util.Calendar.DECEMBER;
import static java.util.Calendar.JANUARY;
import static java.util.Calendar.MAY;
import static java.util.Calendar.NOVEMBER;
import static java.util.Calendar.OCTOBER;
import static java.util.Calendar.SEPTEMBER;

import static org.apache.poi.ss.formula.eval.ErrorEval.VALUE_INVALID;
import static org.junit.Assert.assertEquals;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@@ -40,114 +35,140 @@ import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.StringEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;

import junit.framework.TestCase;

/**
* @author jfaenomoto@gmail.com
*/
@SuppressWarnings("deprecation") // YK: heavily uses deprecated {@link java.util.Date(int year, int month, int date)}
public class TestWorkdayFunction extends TestCase {

private static final SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");

private static final String STARTING_DATE = formatter.format(new Date(108, OCTOBER, 1));
public class TestWorkdayFunction {

private static final String FIRST_HOLIDAY = formatter.format(new Date(108, NOVEMBER, 26));

private static final String SECOND_HOLIDAY = formatter.format(new Date(108, DECEMBER, 4));

private static final String THIRD_HOLIDAY = formatter.format(new Date(109, JANUARY, 21));

private static final String RETROATIVE_HOLIDAY = formatter.format(new Date(108, SEPTEMBER, 29));
private static final String STARTING_DATE = "2008/10/01";
private static final String FIRST_HOLIDAY = "2008/11/26";
private static final String SECOND_HOLIDAY = "2008/12/04";
private static final String THIRD_HOLIDAY = "2009/01/21";
private static final String RETROATIVE_HOLIDAY = "2008/09/29";

private static final OperationEvaluationContext EC = new OperationEvaluationContext(null, null, 1, 1, 1, null);

@Test
public void testFailWhenNoArguments() {
assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate(new ValueEval[0], null));
ValueEval ve[] = new ValueEval[0];
assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate(ve, null));
}

@Test
public void testFailWhenLessThan2Arguments() {
assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate(new ValueEval[1], null));
ValueEval ve[] = new ValueEval[1];
assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate(ve, null));
}

@Test
public void testFailWhenMoreThan3Arguments() {
assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate(new ValueEval[4], null));
ValueEval ve[] = new ValueEval[4];
assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate(ve, null));
}

@Test
public void testFailWhenArgumentsAreNotDatesNorNumbers() {
assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate(
new ValueEval[]{ new StringEval("Potato"), new StringEval("Cucumber") }, EC));
ValueEval ve[] = { new StringEval("Potato"), new StringEval("Cucumber") };
assertEquals(VALUE_INVALID, WorkdayFunction.instance.evaluate(ve, EC));
}

@Test
public void testReturnWorkdays() {
assertEquals(new Date(109, APRIL, 30), DateUtil.getJavaDate(((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{
new StringEval(STARTING_DATE), new NumberEval(151) }, EC)).getNumberValue()));
Calendar expCal = LocaleUtil.getLocaleCalendar(2009, 3, 30);
Date expDate = expCal.getTime();
ValueEval ve[] = { new StringEval(STARTING_DATE), new NumberEval(151) };
Date actDate = DateUtil.getJavaDate(((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue());
assertEquals(expDate, actDate);
}

@Test
public void testReturnWorkdaysSpanningAWeekendSubtractingDays() {
String startDate = "2013/09/30";
int days = -1;
StringEval stringEval = new StringEval(startDate);
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{
stringEval, new NumberEval(days) }, EC)).getNumberValue();
assertEquals(41544.0, numberValue);
Calendar expCal = LocaleUtil.getLocaleCalendar(2013, 8, 27);
Date expDate = expCal.getTime();
ValueEval ve[] = { new StringEval("2013/09/30"), new NumberEval(-1) };
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue();
assertEquals(41544.0, numberValue, 0);
Date date = DateUtil.getJavaDate(numberValue);
assertEquals("Should be 2013/09/27", new Date(113, 8, 27), date);
Date actDate = DateUtil.getJavaDate(numberValue);
assertEquals(expDate, actDate);
}

@Test
public void testReturnWorkdaysSpanningAWeekendAddingDays() {
String startDate = "2013/09/27";
int days = 1;
StringEval stringEval = new StringEval(startDate);
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{
stringEval, new NumberEval(days) }, EC)).getNumberValue();
assertEquals(41547.0, numberValue);
Date date = DateUtil.getJavaDate(numberValue);
assertEquals("Should be 2013/09/30", new Date(113, 8, 30), date);
Calendar expCal = LocaleUtil.getLocaleCalendar(2013, 8, 30);
Date expDate = expCal.getTime();
ValueEval ve[] = { new StringEval("2013/09/27"), new NumberEval(1) };
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue();
assertEquals(41547.0, numberValue, 0);
Date actDate = DateUtil.getJavaDate(numberValue);
assertEquals(expDate, actDate);
}

@Test
public void testReturnWorkdaysWhenStartIsWeekendAddingDays() {
String startDate = "2013/10/06";
int days = 1;
StringEval stringEval = new StringEval(startDate);
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{
stringEval, new NumberEval(days) }, EC)).getNumberValue();
assertEquals(41554.0, numberValue);
Date date = DateUtil.getJavaDate(numberValue);
assertEquals("Should be 2013/10/07", new Date(113, 9, 7), date);
Calendar expCal = LocaleUtil.getLocaleCalendar(2013, 9, 7);
Date expDate = expCal.getTime();
ValueEval ve[] = { new StringEval("2013/10/06"), new NumberEval(1) };
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue();
assertEquals(41554.0, numberValue, 0);
Date actDate = DateUtil.getJavaDate(numberValue);
assertEquals(expDate, actDate);
}

@Test
public void testReturnWorkdaysWhenStartIsWeekendSubtractingDays() {
String startDate = "2013/10/06";
int days = -1;
StringEval stringEval = new StringEval(startDate);
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{
stringEval, new NumberEval(days) }, EC)).getNumberValue();
assertEquals(41551.0, numberValue);
Date date = DateUtil.getJavaDate(numberValue);
assertEquals("Should be 2013/10/04", new Date(113, 9, 4), date);
Calendar expCal = LocaleUtil.getLocaleCalendar(2013, 9, 4);
Date expDate = expCal.getTime();
ValueEval ve[] = { new StringEval("2013/10/06"), new NumberEval(-1) };
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue();
assertEquals(41551.0, numberValue, 0);
Date actDate = DateUtil.getJavaDate(numberValue);
assertEquals(expDate, actDate);
}

@Test
public void testReturnWorkdaysWithDaysTruncated() {
assertEquals(new Date(109, APRIL, 30), DateUtil.getJavaDate(((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{
new StringEval(STARTING_DATE), new NumberEval(151.99999) }, EC)).getNumberValue()));
Calendar expCal = LocaleUtil.getLocaleCalendar(2009, 3, 30);
Date expDate = expCal.getTime();
ValueEval ve[] = { new StringEval(STARTING_DATE), new NumberEval(151.99999) };
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue();
Date actDate = DateUtil.getJavaDate(numberValue);
assertEquals(expDate, actDate);
}

@Test
public void testReturnRetroativeWorkday() {
assertEquals(new Date(108, SEPTEMBER, 23), DateUtil.getJavaDate(((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{
new StringEval(STARTING_DATE), new NumberEval(-5), new StringEval(RETROATIVE_HOLIDAY) }, EC))
.getNumberValue()));
Calendar expCal = LocaleUtil.getLocaleCalendar(2008, 8, 23);
Date expDate = expCal.getTime();
ValueEval ve[] = { new StringEval(STARTING_DATE), new NumberEval(-5), new StringEval(RETROATIVE_HOLIDAY) };
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue();
Date actDate = DateUtil.getJavaDate(numberValue);
assertEquals(expDate, actDate);
}

@Test
public void testReturnNetworkdaysWithManyHolidays() {
assertEquals(new Date(109, MAY, 5), DateUtil.getJavaDate(((NumberEval) WorkdayFunction.instance.evaluate(new ValueEval[]{
new StringEval(STARTING_DATE), new NumberEval(151),
new MockAreaEval(FIRST_HOLIDAY, SECOND_HOLIDAY, THIRD_HOLIDAY) }, EC)).getNumberValue()));
Calendar expCal = LocaleUtil.getLocaleCalendar(2009, 4, 5);
Date expDate = expCal.getTime();
ValueEval ve[] = {
new StringEval(STARTING_DATE), new NumberEval(151),
new MockAreaEval(FIRST_HOLIDAY, SECOND_HOLIDAY, THIRD_HOLIDAY) };
double numberValue = ((NumberEval) WorkdayFunction.instance.evaluate(ve, EC)).getNumberValue();
Date actDate = DateUtil.getJavaDate(numberValue);
assertEquals(expDate, actDate);
}

private class MockAreaEval extends AreaEvalBase {

+ 7
- 9
src/testcases/org/apache/poi/ss/formula/atp/TestYearFracCalculator.java 查看文件

@@ -17,20 +17,21 @@

package org.apache.poi.ss.formula.atp;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import static org.junit.Assert.assertEquals;

import junit.framework.TestCase;
import java.util.Calendar;

import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;

/**
* Specific test cases for YearFracCalculator
*/
public final class TestYearFracCalculator extends TestCase {
public final class TestYearFracCalculator {

@Test
public void testBasis1() {
confirm(md(1999, 1, 1), md(1999, 4, 5), 1, 0.257534247);
confirm(md(1999, 4, 1), md(1999, 4, 5), 1, 0.010958904);
@@ -59,10 +60,7 @@ public final class TestYearFracCalculator extends TestCase {
}

private static double md(int year, int month, int day) {
Calendar c = new GregorianCalendar(Locale.ROOT);
c.set(year, month-1, day, 0, 0, 0);
c.set(Calendar.MILLISECOND, 0);
Calendar c = LocaleUtil.getLocaleCalendar(year, month-1, day);
return DateUtil.getExcelDate(c.getTime());
}
}

+ 28
- 91
src/testcases/org/apache/poi/ss/formula/atp/TestYearFracCalculatorFromSpreadsheet.java 查看文件

@@ -17,31 +17,29 @@

package org.apache.poi.ss.formula.atp;

import java.io.PrintStream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Iterator;

import junit.framework.Assert;
import junit.framework.AssertionFailedError;
import junit.framework.ComparisonFailure;
import junit.framework.TestCase;

import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;

/**
* Tests YearFracCalculator using test-cases listed in a sample spreadsheet
*
* @author Josh Micich
*/
public final class TestYearFracCalculatorFromSpreadsheet extends TestCase {
public final class TestYearFracCalculatorFromSpreadsheet {
private static final class SS {

@@ -52,15 +50,14 @@ public final class TestYearFracCalculatorFromSpreadsheet extends TestCase {
public static final int EXPECTED_RESULT_COLUMN = 13; // "N"
}

public void testAll() {
@Test
public void testAll() throws Exception {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("yearfracExamples.xls");
HSSFSheet sheet = wb.getSheetAt(0);
HSSFFormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator(wb);
int nSuccess = 0;
int nFailures = 0;
int nUnexpectedErrors = 0;
Iterator rowIterator = sheet.rowIterator();
Iterator<Row> rowIterator = sheet.rowIterator();
while(rowIterator.hasNext()) {
HSSFRow row = (HSSFRow) rowIterator.next();
@@ -68,28 +65,16 @@ public final class TestYearFracCalculatorFromSpreadsheet extends TestCase {
if (cell == null || cell.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
continue;
}
try {
processRow(row, cell, formulaEvaluator);
nSuccess++;
} catch (RuntimeException e) {
nUnexpectedErrors ++;
printShortStackTrace(System.err, e);
} catch (AssertionFailedError e) {
nFailures ++;
printShortStackTrace(System.err, e);
}
}
if (nUnexpectedErrors + nFailures > 0) {
String msg = nFailures + " failures(s) and " + nUnexpectedErrors
+ " unexpected errors(s) occurred. See stderr for details";
throw new AssertionFailedError(msg);
}
if (nSuccess < 1) {
throw new RuntimeException("No test sample cases found");
processRow(row, cell, formulaEvaluator);
nSuccess++;
}

assertTrue("No test sample cases found", nSuccess > 0);
wb.close();
}
private static void processRow(HSSFRow row, HSSFCell cell, HSSFFormulaEvaluator formulaEvaluator) {
private void processRow(HSSFRow row, HSSFCell cell, HSSFFormulaEvaluator formulaEvaluator)
throws EvaluationException {
double startDate = makeDate(row, SS.START_YEAR_COLUMN);
double endDate = makeDate(row, SS.END_YEAR_COLUMN);
@@ -98,81 +83,33 @@ public final class TestYearFracCalculatorFromSpreadsheet extends TestCase {
double expectedValue = getDoubleCell(row, SS.EXPECTED_RESULT_COLUMN);
double actualValue;
try {
actualValue = YearFracCalculator.calculate(startDate, endDate, basis);
} catch (EvaluationException e) {
throw new RuntimeException(e);
}
if (expectedValue != actualValue) {
throw new ComparisonFailure("Direct calculate failed - row " + (row.getRowNum()+1),
String.valueOf(expectedValue), String.valueOf(actualValue));
}
double actualValue = YearFracCalculator.calculate(startDate, endDate, basis);

String loc = " - row " + (row.getRowNum()+1);
assertEquals("Direct calculate failed"+loc, expectedValue, actualValue, 0);
actualValue = formulaEvaluator.evaluate(cell).getNumberValue();
if (expectedValue != actualValue) {
throw new ComparisonFailure("Formula evaluate failed - row " + (row.getRowNum()+1),
String.valueOf(expectedValue), String.valueOf(actualValue));
}
assertEquals("Formula evaluate failed"+loc, expectedValue, actualValue, 0);
}

private static double makeDate(HSSFRow row, int yearColumn) {
int year = getIntCell(row, yearColumn + 0);
int month = getIntCell(row, yearColumn + 1);
int day = getIntCell(row, yearColumn + 2);
Calendar c = new GregorianCalendar(year, month-1, day, 0, 0, 0);
c.set(Calendar.MILLISECOND, 0);
Calendar c = LocaleUtil.getLocaleCalendar(year, month-1, day);
return HSSFDateUtil.getExcelDate(c.getTime());
}

private static int getIntCell(HSSFRow row, int colIx) {
double dVal = getDoubleCell(row, colIx);
if (Math.floor(dVal) != dVal) {
throw new RuntimeException("Non integer value (" + dVal
+ ") cell found at column " + (char)('A' + colIx));
}
String msg = "Non integer value (" + dVal + ") cell found at column " + (char)('A' + colIx);
assertEquals(msg, Math.floor(dVal), dVal, 0);
return (int)dVal;
}

private static double getDoubleCell(HSSFRow row, int colIx) {
HSSFCell cell = row.getCell(colIx);
if (cell == null) {
throw new RuntimeException("No cell found at column " + colIx);
}
assertNotNull("No cell found at column " + colIx, cell);
double dVal = cell.getNumericCellValue();
return dVal;
}

/**
* Useful to keep output concise when expecting many failures to be reported by this test case
* TODO - refactor duplicates in other Test~FromSpreadsheet classes
*/
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) {
if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
break;
}
startIx++;
}
// skip bottom frames (part of junit framework)
int endIx = startIx+1;
while(endIx < stes.length) {
if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
break;
}
endIx++;
}
if(startIx >= endIx) {
// something went wrong. just print the whole stack trace
e.printStackTrace(ps);
}
endIx -= 4; // skip 4 frames of reflection invocation
ps.println(e.toString());
for(int i=startIx; i<endIx; i++) {
ps.println("\tat " + stes[i].toString());
}
}
}

+ 130
- 210
src/testcases/org/apache/poi/ss/formula/eval/TestFormulasFromSpreadsheet.java 查看文件

@@ -21,8 +21,9 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;

import org.apache.poi.hssf.HSSFTestDataSamples;
@@ -33,14 +34,15 @@ import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellValue;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.junit.Assert;
import org.junit.Before;
import org.apache.poi.util.LocaleUtil;
import org.junit.AfterClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

import junit.framework.AssertionFailedError;
import junit.framework.TestCase;

/**
* Tests formulas and operators as loaded from a test data spreadsheet.<p/>
@@ -49,248 +51,166 @@ import junit.framework.TestCase;
* exercised as well. 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 Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*/
@RunWith(Parameterized.class)
public final class TestFormulasFromSpreadsheet {
private static final POILogger logger = POILogFactory.getLogger(TestFormulasFromSpreadsheet.class);

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;
}

/**
private static HSSFWorkbook workbook;
private static Sheet sheet;
private static HSSFFormulaEvaluator evaluator;
private static Locale userLocale;
/**
* This class defines constants for navigating around the test data spreadsheet used for these tests.
*/
private static final class SS {
private static interface SS {

/**
* Name of the test spreadsheet (found in the standard test data folder)
*/
public final static String FILENAME = "FormulaEvalTestData.xls";
String FILENAME = "FormulaEvalTestData.xls";
/**
* Row (zero-based) in the test spreadsheet where the operator examples start.
*/
public static final int START_OPERATORS_ROW_INDEX = 22; // Row '23'
int START_OPERATORS_ROW_INDEX = 22; // Row '23'
/**
* Row (zero-based) in the test spreadsheet where the function examples start.
*/
public static final int START_FUNCTIONS_ROW_INDEX = 95; // Row '96'
int START_FUNCTIONS_ROW_INDEX = 95; // Row '96'
/**
* Index of the column that contains the function names
*/
public static final int COLUMN_INDEX_FUNCTION_NAME = 1; // Column 'B'
int COLUMN_INDEX_FUNCTION_NAME = 1; // Column 'B'

/**
* Used to indicate when there are no more functions left
*/
public static final String FUNCTION_NAMES_END_SENTINEL = "<END-OF-FUNCTIONS>";
String FUNCTION_NAMES_END_SENTINEL = "<END-OF-FUNCTIONS>";

/**
* Index of the column where the test values start (for each function)
*/
public static final short COLUMN_INDEX_FIRST_TEST_VALUE = 3; // Column 'D'
short COLUMN_INDEX_FIRST_TEST_VALUE = 3; // Column 'D'

/**
* Each function takes 4 rows in the test spreadsheet
*/
public static final int NUMBER_OF_ROWS_PER_FUNCTION = 4;
}

private HSSFWorkbook workbook;
private Sheet sheet;
// Note - multiple failures are aggregated before ending.
// If one or more functions fail, a single AssertionFailedError is thrown at the end
private int _functionFailureCount;
private int _functionSuccessCount;
private int _evaluationFailureCount;
private int _evaluationSuccessCount;

private static final Cell getExpectedValueCell(Row row, int columnIndex) {
if (row == null) {
return null;
}
return row.getCell(columnIndex);
}


private static void confirmExpectedResult(String msg, Cell expected, CellValue actual) {
assertNotNull(msg + " - Bad setup data expected value is null", expected);
assertNotNull(msg + " - actual value was null", actual);

switch (expected.getCellType()) {
case Cell.CELL_TYPE_BLANK:
assertEquals(msg, Cell.CELL_TYPE_BLANK, actual.getCellType());
break;
case Cell.CELL_TYPE_BOOLEAN:
assertEquals(msg, Cell.CELL_TYPE_BOOLEAN, actual.getCellType());
assertEquals(msg, expected.getBooleanCellValue(), actual.getBooleanValue());
break;
case Cell.CELL_TYPE_ERROR:
assertEquals(msg, Cell.CELL_TYPE_ERROR, actual.getCellType());
assertEquals(msg, ErrorEval.getText(expected.getErrorCellValue()), ErrorEval.getText(actual.getErrorValue()));
break;
case Cell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
fail("Cannot expect formula as result of formula evaluation: " + msg);
case Cell.CELL_TYPE_NUMERIC:
assertEquals(msg, Cell.CELL_TYPE_NUMERIC, actual.getCellType());
TestMathX.assertEquals(msg, expected.getNumericCellValue(), actual.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
break;
case Cell.CELL_TYPE_STRING:
assertEquals(msg, Cell.CELL_TYPE_STRING, actual.getCellType());
assertEquals(msg, expected.getRichStringCellValue().getString(), actual.getStringValue());
break;
}
}

@Before
protected void setUp() {
if (workbook == null) {
workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
sheet = workbook.getSheetAt( 0 );
}
_functionFailureCount = 0;
_functionSuccessCount = 0;
_evaluationFailureCount = 0;
_evaluationSuccessCount = 0;
int NUMBER_OF_ROWS_PER_FUNCTION = 4;
}

@Test
public void testFunctionsFromTestSpreadsheet() {

processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, null);
processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, null);
// example for debugging individual functions/operators:
// processFunctionGroup(SS.START_OPERATORS_ROW_INDEX, "ConcatEval");
// processFunctionGroup(SS.START_FUNCTIONS_ROW_INDEX, "AVERAGE");

// confirm results
String successMsg = "There were "
+ _evaluationSuccessCount + " successful evaluation(s) and "
+ _functionSuccessCount + " function(s) without error";
String msg = _functionFailureCount + " function(s) failed in "
+ _evaluationFailureCount + " evaluation(s). " + successMsg;
assertEquals(msg, _functionFailureCount, 0);
logger.log(POILogger.INFO, getClass().getName() + ": " + successMsg);
}

/**
* @param startRowIndex row index in the spreadsheet where the first function/operator is found
* @param testFocusFunctionName name of a single function/operator to test alone.
* Typically pass <code>null</code> to test all functions
*/
private void processFunctionGroup(int startRowIndex, String testFocusFunctionName) {
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
Collection<String> funcs = FunctionEval.getSupportedFunctionNames();

int rowIndex = startRowIndex;
while (true) {
Row r = sheet.getRow(rowIndex);
String targetFunctionName = getTargetFunctionName(r);
assertNotNull("Test spreadsheet cell empty on row ("
@Parameter(value = 0)
public String targetFunctionName;
@Parameter(value = 1)
public int formulasRowIdx;
@Parameter(value = 2)
public int expectedValuesRowIdx;

@AfterClass
public static void closeResource() throws Exception {
LocaleUtil.setUserLocale(userLocale);
workbook.close();
}

@Parameters(name="{0}")
public static Collection<Object[]> data() throws Exception {
// Function "Text" uses custom-formats which are locale specific
// can't set the locale on a per-testrun execution, as some settings have been
// already set, when we would try to change the locale by then
userLocale = LocaleUtil.getUserLocale();
LocaleUtil.setUserLocale(Locale.ROOT);

workbook = HSSFTestDataSamples.openSampleWorkbook(SS.FILENAME);
sheet = workbook.getSheetAt( 0 );
evaluator = new HSSFFormulaEvaluator(workbook);
List<Object[]> data = new ArrayList<Object[]>();
processFunctionGroup(data, SS.START_OPERATORS_ROW_INDEX, null);
processFunctionGroup(data, SS.START_FUNCTIONS_ROW_INDEX, null);
// example for debugging individual functions/operators:
// processFunctionGroup(data, SS.START_OPERATORS_ROW_INDEX, "ConcatEval");
// processFunctionGroup(data, SS.START_FUNCTIONS_ROW_INDEX, "Text");

return data;
}
/**
* @param startRowIndex row index in the spreadsheet where the first function/operator is found
* @param testFocusFunctionName name of a single function/operator to test alone.
* Typically pass <code>null</code> to test all functions
*/
private static void processFunctionGroup(List<Object[]> data, int startRowIndex, String testFocusFunctionName) {
for (int rowIndex = startRowIndex; true; rowIndex += SS.NUMBER_OF_ROWS_PER_FUNCTION) {
Row r = sheet.getRow(rowIndex);
String targetFunctionName = getTargetFunctionName(r);
assertNotNull("Test spreadsheet cell empty on row ("
+ (rowIndex+1) + "). Expected function name or '"
+ SS.FUNCTION_NAMES_END_SENTINEL + "'", targetFunctionName);
if(targetFunctionName.equals(SS.FUNCTION_NAMES_END_SENTINEL)) {
// found end of functions list
break;
}
if(testFocusFunctionName == null || targetFunctionName.equalsIgnoreCase(testFocusFunctionName)) {

// expected results are on the row below
Row expectedValuesRow = sheet.getRow(rowIndex + 1);
if(targetFunctionName.equals(SS.FUNCTION_NAMES_END_SENTINEL)) {
// found end of functions list
break;
}
if(testFocusFunctionName == null || targetFunctionName.equalsIgnoreCase(testFocusFunctionName)) {

// expected results are on the row below
Row expectedValuesRow = sheet.getRow(rowIndex + 1);
int missingRowNum = rowIndex + 2; //+1 for 1-based, +1 for next row
assertNotNull("Missing expected values row for function '"
+ targetFunctionName + " (row " + missingRowNum + ")", expectedValuesRow);
switch(processFunctionRow(evaluator, targetFunctionName, r, expectedValuesRow)) {
case Result.ALL_EVALUATIONS_SUCCEEDED: _functionSuccessCount++; break;
case Result.SOME_EVALUATIONS_FAILED: _functionFailureCount++; break;
default:
throw new RuntimeException("unexpected result");
case Result.NO_EVALUATIONS_FOUND: // do nothing
String uname = targetFunctionName.toUpperCase(Locale.ROOT);
if(startRowIndex >= SS.START_FUNCTIONS_ROW_INDEX &&
funcs.contains(uname)) {
logger.log(POILogger.WARN, uname + ": function is supported but missing test data");
}
break;
}
}
rowIndex += SS.NUMBER_OF_ROWS_PER_FUNCTION;
}
}

/**
*
* @return a constant from the local Result class denoting whether there were any evaluation
* cases, and whether they all succeeded.
*/
private int processFunctionRow(HSSFFormulaEvaluator evaluator, String targetFunctionName,
Row formulasRow, Row expectedValuesRow) {

int result = Result.NO_EVALUATIONS_FOUND; // so far
short endcolnum = formulasRow.getLastCellNum();

// iterate across the row for all the evaluation cases
for (int colnum=SS.COLUMN_INDEX_FIRST_TEST_VALUE; colnum < endcolnum; colnum++) {
Cell c = formulasRow.getCell(colnum);
if (c == null || c.getCellType() != Cell.CELL_TYPE_FORMULA) {
continue;
}

CellValue actualValue = evaluator.evaluate(c);

Cell expectedValueCell = getExpectedValueCell(expectedValuesRow, colnum);
try {
confirmExpectedResult("Function '" + targetFunctionName + "': Formula: " + c.getCellFormula() + " @ " + formulasRow.getRowNum() + ":" + colnum,
expectedValueCell, actualValue);
_evaluationSuccessCount ++;
if(result != Result.SOME_EVALUATIONS_FAILED) {
result = Result.ALL_EVALUATIONS_SUCCEEDED;
}
} catch (AssertionFailedError e) {
_evaluationFailureCount ++;
printShortStackTrace(System.err, e);
result = Result.SOME_EVALUATIONS_FAILED;
}
}
return result;
}

/**
* Useful to keep output concise when expecting many failures to be reported by this test case
*/
private static void printShortStackTrace(PrintStream ps, AssertionFailedError e) {
StackTraceElement[] stes = e.getStackTrace();

int startIx = 0;
// skip any top frames inside junit.framework.Assert
while(startIx<stes.length) {
if(!stes[startIx].getClassName().equals(Assert.class.getName())) {
break;
}
startIx++;
}
// skip bottom frames (part of junit framework)
int endIx = startIx+1;
while(endIx < stes.length) {
if(stes[endIx].getClassName().equals(TestCase.class.getName())) {
break;
}
endIx++;
}
if(startIx >= endIx) {
// something went wrong. just print the whole stack trace
e.printStackTrace(ps);
}
endIx -= 4; // skip 4 frames of reflection invocation
ps.println(e.toString());
for(int i=startIx; i<endIx; i++) {
ps.println("\tat " + stes[i].toString());
}
}

data.add(new Object[]{targetFunctionName, rowIndex, rowIndex + 1});
}
}
}

@Test
public void processFunctionRow() {
Row formulasRow = sheet.getRow(formulasRowIdx);
Row expectedValuesRow = sheet.getRow(expectedValuesRowIdx);

short endcolnum = formulasRow.getLastCellNum();

// iterate across the row for all the evaluation cases
for (int colnum=SS.COLUMN_INDEX_FIRST_TEST_VALUE; colnum < endcolnum; colnum++) {
Cell c = formulasRow.getCell(colnum);
if (c == null || c.getCellType() != Cell.CELL_TYPE_FORMULA) {
continue;
}

CellValue actValue = evaluator.evaluate(c);
Cell expValue = (expectedValuesRow == null) ? null : expectedValuesRow.getCell(colnum);

String msg = String.format(Locale.ROOT, "Function '%s': Formula: %s @ %d:%d"
, targetFunctionName, c.getCellFormula(), formulasRow.getRowNum(), colnum);

assertNotNull(msg + " - Bad setup data expected value is null", expValue);
assertNotNull(msg + " - actual value was null", actValue);

switch (expValue.getCellType()) {
case Cell.CELL_TYPE_BLANK:
assertEquals(msg, Cell.CELL_TYPE_BLANK, actValue.getCellType());
break;
case Cell.CELL_TYPE_BOOLEAN:
assertEquals(msg, Cell.CELL_TYPE_BOOLEAN, actValue.getCellType());
assertEquals(msg, expValue.getBooleanCellValue(), actValue.getBooleanValue());
break;
case Cell.CELL_TYPE_ERROR:
assertEquals(msg, Cell.CELL_TYPE_ERROR, actValue.getCellType());
assertEquals(msg, ErrorEval.getText(expValue.getErrorCellValue()), ErrorEval.getText(actValue.getErrorValue()));
break;
case Cell.CELL_TYPE_FORMULA: // will never be used, since we will call method after formula evaluation
fail("Cannot expect formula as result of formula evaluation: " + msg);
case Cell.CELL_TYPE_NUMERIC:
assertEquals(msg, Cell.CELL_TYPE_NUMERIC, actValue.getCellType());
TestMathX.assertEquals(msg, expValue.getNumericCellValue(), actValue.getNumberValue(), TestMathX.POS_ZERO, TestMathX.DIFF_TOLERANCE_FACTOR);
break;
case Cell.CELL_TYPE_STRING:
assertEquals(msg, Cell.CELL_TYPE_STRING, actValue.getCellType());
assertEquals(msg, expValue.getRichStringCellValue().getString(), actValue.getStringValue());
break;
}
}
}
/**
* @return <code>null</code> if cell is missing, empty or blank
*/

+ 4
- 4
src/testcases/org/apache/poi/ss/formula/functions/TestDays360.java 查看文件

@@ -28,6 +28,7 @@ import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.formula.eval.BoolEval;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;

public final class TestDays360 {
@@ -36,14 +37,13 @@ public final class TestDays360 {
* @param month 1-based
*/
private static Date makeDate(int year, int month, int day) {
Calendar cal = Calendar.getInstance(Locale.ROOT);
cal.set(year, month-1, day, 0, 0, 0);
cal.set(Calendar.MILLISECOND, 0);
Calendar cal = LocaleUtil.getLocaleCalendar(year, month-1, day);
return cal.getTime();
}

private static Date decrementDay(Date d) {
Calendar c = (Calendar)d.clone();
Calendar c = LocaleUtil.getLocaleCalendar();
c.setTime(d);
c.add(Calendar.DAY_OF_MONTH, -1);
return c.getTime();
}

+ 24
- 14
src/testcases/org/apache/poi/ss/formula/functions/TestEDate.java 查看文件

@@ -17,22 +17,24 @@

package org.apache.poi.ss.formula.functions;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.Calendar;
import java.util.Date;

import junit.framework.TestCase;

import org.apache.poi.ss.formula.eval.AreaEval;
import org.apache.poi.ss.formula.eval.BlankEval;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.RefEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.ErrorConstants;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;

public class TestEDate extends TestCase {
public class TestEDate {

@Test
public void testEDateProperValues() {
// verify some border-case combinations of startDate and month-increase
checkValue(1000, 0, 1000d);
@@ -49,71 +51,79 @@ public class TestEDate extends TestCase {
private void checkValue(int startDate, int monthInc, double expectedResult) {
EDate eDate = new EDate();
NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(startDate), new NumberEval(monthInc)}, null);
assertEquals(expectedResult, result.getNumberValue());
assertEquals(expectedResult, result.getNumberValue(), 0);
}
@Test
public void testEDateInvalidValues() {
EDate eDate = new EDate();
ErrorEval result = (ErrorEval) eDate.evaluate(new ValueEval[]{new NumberEval(1000)}, null);
assertEquals(ErrorConstants.ERROR_VALUE, result.getErrorCode());
assertEquals(ErrorConstants.ERROR_VALUE, result.getErrorCode(), 0);
}

@Test
public void testEDateIncrease() {
EDate eDate = new EDate();
Date startDate = new Date();
int offset = 2;
NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(DateUtil.getExcelDate(startDate)), new NumberEval(offset)}, null);
Date resultDate = DateUtil.getJavaDate(result.getNumberValue());
Calendar instance = Calendar.getInstance();
Calendar instance = LocaleUtil.getLocaleCalendar();
instance.setTime(startDate);
instance.add(Calendar.MONTH, offset);
assertEquals(resultDate, instance.getTime());

}

@Test
public void testEDateDecrease() {
EDate eDate = new EDate();
Date startDate = new Date();
int offset = -2;
NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(DateUtil.getExcelDate(startDate)), new NumberEval(offset)}, null);
Date resultDate = DateUtil.getJavaDate(result.getNumberValue());
Calendar instance = Calendar.getInstance();
Calendar instance = LocaleUtil.getLocaleCalendar();
instance.setTime(startDate);
instance.add(Calendar.MONTH, offset);
assertEquals(resultDate, instance.getTime());
}
@Test
public void testBug56688() {
EDate eDate = new EDate();
NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(1000), new RefEvalImplementation(new NumberEval(0))}, null);
assertEquals(1000d, result.getNumberValue());
assertEquals(1000d, result.getNumberValue(), 0);
}

@Test
public void testRefEvalStartDate() {
EDate eDate = new EDate();
NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new RefEvalImplementation(new NumberEval(1000)), new NumberEval(0)}, null);
assertEquals(1000d, result.getNumberValue());
assertEquals(1000d, result.getNumberValue(), 0);
}

@Test
public void testEDateInvalidValueEval() {
ValueEval evaluate = new EDate().evaluate(new ValueEval[]{new ValueEval() {}, new NumberEval(0)}, null);
assertTrue(evaluate instanceof ErrorEval);
assertEquals(ErrorEval.VALUE_INVALID, evaluate);
}

@Test
public void testEDateBlankValueEval() {
NumberEval evaluate = (NumberEval) new EDate().evaluate(new ValueEval[]{BlankEval.instance, new NumberEval(0)}, null);
assertEquals(-1.0d, evaluate.getNumberValue());
assertEquals(-1.0d, evaluate.getNumberValue(), 0);
}

@Test
public void testEDateBlankRefValueEval() {
EDate eDate = new EDate();
NumberEval result = (NumberEval) eDate.evaluate(new ValueEval[]{new RefEvalImplementation(BlankEval.instance), new NumberEval(0)}, null);
assertEquals("0 startDate triggers BAD_DATE currently, thus -1.0!",
-1.0d, result.getNumberValue());
-1.0d, result.getNumberValue(), 0);

result = (NumberEval) eDate.evaluate(new ValueEval[]{new NumberEval(1), new RefEvalImplementation(BlankEval.instance)}, null);
assertEquals("Blank is handled as 0 otherwise",
1.0d, result.getNumberValue());
1.0d, result.getNumberValue(), 0);
}
}

+ 58
- 42
src/testcases/org/apache/poi/ss/formula/functions/TestEOMonth.java 查看文件

@@ -17,12 +17,13 @@
package org.apache.poi.ss.formula.functions;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Calendar;
import java.util.Date;
import junit.framework.TestCase;
import org.apache.poi.ss.formula.OperationEvaluationContext;
import org.apache.poi.ss.formula.eval.BlankEval;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.NumberEval;
@@ -30,8 +31,10 @@ import org.apache.poi.ss.formula.eval.StringEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.ErrorConstants;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;
public class TestEOMonth extends TestCase{
public class TestEOMonth {
private static final double BAD_DATE = -1.0;
@@ -47,6 +50,7 @@ public class TestEOMonth extends TestCase{
private final FreeRefFunction eOMonth = EOMonth.instance;
private final OperationEvaluationContext ec = new OperationEvaluationContext(null, null, 0, 0, 0, null);
@Test
public void testEOMonthProperValues() {
// verify some border-case combinations of startDate and month-increase
checkValue(DATE_1900_01_01, 0, DATE_1900_01_31);
@@ -56,6 +60,7 @@ public class TestEOMonth extends TestCase{
checkValue(DATE_2034_06_09, 1, DATE_2034_07_31);
}
@Test
public void testEOMonthBadDateValues() {
checkValue(0.0, -2, BAD_DATE);
checkValue(0.0, -3, BAD_DATE);
@@ -63,74 +68,85 @@ public class TestEOMonth extends TestCase{
}
private void checkValue(double startDate, int monthInc, double expectedResult) {
NumberEval result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(startDate), new NumberEval(monthInc)}, ec);
assertEquals(expectedResult, result.getNumberValue());
ValueEval ve[] = {new NumberEval(startDate), new NumberEval(monthInc)};
NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec);
assertEquals(expectedResult, result.getNumberValue(), 0);
}
@Test
public void testEOMonthZeroDate() {
NumberEval result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(0), new NumberEval(0)}, ec);
assertEquals("0 startDate is 1900-01-00", DATE_1900_01_31, result.getNumberValue());
assertEquals("0 startDate is 1900-01-00", DATE_1900_01_31, result.getNumberValue(), 0);
result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(0), new NumberEval(1)}, ec);
assertEquals("0 startDate is 1900-01-00", DATE_1900_02_28, result.getNumberValue());
assertEquals("0 startDate is 1900-01-00", DATE_1900_02_28, result.getNumberValue(), 0);
}
@Test
public void testEOMonthInvalidArguments() {
ValueEval result = eOMonth.evaluate(new ValueEval[] {new NumberEval(DATE_1902_09_26)}, ec);
assertTrue(result instanceof ErrorEval);
assertEquals(ErrorConstants.ERROR_VALUE, ((ErrorEval) result).getErrorCode());
assertEquals(ErrorConstants.ERROR_VALUE, ((ErrorEval) result).getErrorCode(), 0);
result = eOMonth.evaluate(new ValueEval[] {new StringEval("a"), new StringEval("b")}, ec);
assertTrue(result instanceof ErrorEval);
assertEquals(ErrorConstants.ERROR_VALUE, ((ErrorEval) result).getErrorCode());
}
public void testEOMonthIncrease() {
checkOffset(new Date(), 2);
}
public void testEOMonthDecrease() {
checkOffset(new Date(), -2);
assertEquals(ErrorConstants.ERROR_VALUE, ((ErrorEval) result).getErrorCode(), 0);
}
private void checkOffset(Date startDate, int offset) {
NumberEval result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(DateUtil.getExcelDate(startDate)), new NumberEval(offset)}, ec);
Date resultDate = DateUtil.getJavaDate(result.getNumberValue());
Calendar instance = Calendar.getInstance();
instance.setTime(startDate);
instance.add(Calendar.MONTH, offset);
instance.add(Calendar.MONTH, 1);
instance.set(Calendar.DAY_OF_MONTH, 1);
instance.add(Calendar.DAY_OF_MONTH, -1);
instance.set(Calendar.HOUR_OF_DAY, 0);
instance.set(Calendar.MINUTE, 0);
instance.set(Calendar.SECOND, 0);
instance.set(Calendar.MILLISECOND, 0);
assertEquals(instance.getTime(), resultDate);
@Test
public void checkOffset() {
for (int offset=-12; offset<=12; offset++) {
Calendar cal = LocaleUtil.getLocaleCalendar();
Date startDate = cal.getTime();
cal.add(Calendar.MONTH, offset);
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
cal.clear(Calendar.HOUR);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);
Date expDate = cal.getTime();
ValueEval ve[] = {
new NumberEval(DateUtil.getExcelDate(startDate)),
new NumberEval(offset)
};
NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec);
Date actDate = DateUtil.getJavaDate(result.getNumberValue());
assertEquals(expDate, actDate);
}
}
@Test
public void testBug56688() {
NumberEval result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(DATE_1902_09_26), new RefEvalImplementation(new NumberEval(0))}, ec);
assertEquals(DATE_1902_09_30, result.getNumberValue());
ValueEval ve[] = {new NumberEval(DATE_1902_09_26), new RefEvalImplementation(new NumberEval(0))};
NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec);
assertEquals(DATE_1902_09_30, result.getNumberValue(), 0);
}
@Test
public void testRefEvalStartDate() {
NumberEval result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new RefEvalImplementation(new NumberEval(DATE_1902_09_26)), new NumberEval(0)}, ec);
assertEquals(DATE_1902_09_30, result.getNumberValue());
ValueEval ve[] = {new RefEvalImplementation(new NumberEval(DATE_1902_09_26)), new NumberEval(0)};
NumberEval result = (NumberEval) eOMonth.evaluate(ve, ec);
assertEquals(DATE_1902_09_30, result.getNumberValue(), 0);
}
@Test
public void testEOMonthBlankValueEval() {
NumberEval evaluate = (NumberEval) eOMonth.evaluate(new ValueEval[] {BlankEval.instance, new NumberEval(0)}, ec);
assertEquals("Blank is handled as 0", DATE_1900_01_31, evaluate.getNumberValue());
assertEquals("Blank is handled as 0", DATE_1900_01_31, evaluate.getNumberValue(), 0);
}
@Test
public void testEOMonthBlankRefValueEval() {
NumberEval result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new RefEvalImplementation(BlankEval.instance), new NumberEval(1)}, ec);
assertEquals("Blank is handled as 0",
DATE_1900_02_28, result.getNumberValue());
ValueEval[] ve1 = {new RefEvalImplementation(BlankEval.instance), new NumberEval(1)};
NumberEval result = (NumberEval) eOMonth.evaluate(ve1, ec);
assertEquals("Blank is handled as 0", DATE_1900_02_28, result.getNumberValue(), 0);
result = (NumberEval) eOMonth.evaluate(new ValueEval[] {new NumberEval(1), new RefEvalImplementation(BlankEval.instance)}, ec);
assertEquals("Blank is handled as 0",
DATE_1900_01_31, result.getNumberValue());
ValueEval[] ve2 = {new NumberEval(1), new RefEvalImplementation(BlankEval.instance)};
result = (NumberEval) eOMonth.evaluate(ve2, ec);
assertEquals("Blank is handled as 0", DATE_1900_01_31, result.getNumberValue(), 0);
}
}

+ 54
- 38
src/testcases/org/apache/poi/ss/formula/functions/TestText.java 查看文件

@@ -17,21 +17,25 @@

package org.apache.poi.ss.formula.functions;

import static org.junit.Assert.assertEquals;

import java.text.DateFormatSymbols;
import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

import junit.framework.TestCase;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.formula.eval.StringEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;

/**
* Test case for TEXT()
*/
public final class TestText extends TestCase {
public final class TestText {
@Test
public void testTextWithStringFirstArg() {
ValueEval strArg = new StringEval("abc");
ValueEval formatArg = new StringEval("abc");
@@ -40,13 +44,14 @@ public final class TestText extends TestCase {
assertEquals(ErrorEval.VALUE_INVALID, result);
}

@Test
public void testTextWithDeciamlFormatSecondArg() {
ValueEval numArg = new NumberEval(321321.321);
ValueEval formatArg = new StringEval("#,###.00000");
ValueEval[] args = { numArg, formatArg };
ValueEval result = TextFunction.TEXT.evaluate(args, -1, (short)-1);
char groupSeparator = new DecimalFormatSymbols(Locale.getDefault()).getGroupingSeparator();
char decimalSeparator = new DecimalFormatSymbols(Locale.getDefault()).getDecimalSeparator();
char groupSeparator = new DecimalFormatSymbols(LocaleUtil.getUserLocale()).getGroupingSeparator();
char decimalSeparator = new DecimalFormatSymbols(LocaleUtil.getUserLocale()).getDecimalSeparator();
ValueEval testResult = new StringEval("321" + groupSeparator + "321" + decimalSeparator + "32100");
assertEquals(testResult.toString(), result.toString());
numArg = new NumberEval(321.321);
@@ -64,6 +69,7 @@ public final class TestText extends TestCase {
assertEquals(testResult.toString(), result.toString());
}

@Test
public void testTextWithFractionFormatSecondArg() {
ValueEval numArg = new NumberEval(321.321);
ValueEval formatArg = new StringEval("# #/#");
@@ -85,37 +91,47 @@ public final class TestText extends TestCase {
assertEquals(testResult.toString(), result.toString());
}

@Test
public void testTextWithDateFormatSecondArg() {
// Test with Java style M=Month
ValueEval numArg = new NumberEval(321.321);
ValueEval formatArg = new StringEval("dd:MM:yyyy hh:mm:ss");
ValueEval[] args = { numArg, formatArg };
ValueEval result = TextFunction.TEXT.evaluate(args, -1, (short)-1);
ValueEval testResult = new StringEval("16:11:1900 07:42:14");
assertEquals(testResult.toString(), result.toString());

// Excel also supports "m before h is month"
formatArg = new StringEval("dd:mm:yyyy hh:mm:ss");
args[1] = formatArg;
result = TextFunction.TEXT.evaluate(args, -1, (short)-1);
testResult = new StringEval("16:11:1900 07:42:14");
assertEquals(testResult.toString(), result.toString());

// this line is intended to compute how "November" would look like in the current locale
String november = new SimpleDateFormat("MMMM").format(new GregorianCalendar(2010,10,15).getTime());

// Again with Java style
formatArg = new StringEval("MMMM dd, yyyy");
args[1] = formatArg;
result = TextFunction.TEXT.evaluate(args, -1, (short)-1);
testResult = new StringEval(november + " 16, 1900");
assertEquals(testResult.toString(), result.toString());

// And Excel style
formatArg = new StringEval("mmmm dd, yyyy");
args[1] = formatArg;
result = TextFunction.TEXT.evaluate(args, -1, (short)-1);
testResult = new StringEval(november + " 16, 1900");
assertEquals(testResult.toString(), result.toString());
TimeZone userTZ = LocaleUtil.getUserTimeZone();
LocaleUtil.setUserTimeZone(TimeZone.getTimeZone("CET"));
try {
// Test with Java style M=Month
ValueEval numArg = new NumberEval(321.321);
ValueEval formatArg = new StringEval("dd:MM:yyyy hh:mm:ss");
ValueEval[] args = { numArg, formatArg };
ValueEval result = TextFunction.TEXT.evaluate(args, -1, (short)-1);
ValueEval testResult = new StringEval("16:11:1900 07:42:14");
assertEquals(testResult.toString(), result.toString());
// Excel also supports "m before h is month"
formatArg = new StringEval("dd:mm:yyyy hh:mm:ss");
args[1] = formatArg;
result = TextFunction.TEXT.evaluate(args, -1, (short)-1);
testResult = new StringEval("16:11:1900 07:42:14");
assertEquals(testResult.toString(), result.toString());
// this line is intended to compute how "November" would look like in the current locale
// update: now the locale will be (if not set otherwise) always Locale.getDefault() (see LocaleUtil)
DateFormatSymbols dfs = DateFormatSymbols.getInstance(LocaleUtil.getUserLocale());
SimpleDateFormat sdf = new SimpleDateFormat("MMMM", dfs);
String november = sdf.format(LocaleUtil.getLocaleCalendar(2015,10,1).getTime());
// Again with Java style
formatArg = new StringEval("MMMM dd, yyyy");
args[1] = formatArg;
result = TextFunction.TEXT.evaluate(args, -1, (short)-1);
testResult = new StringEval(november + " 16, 1900");
assertEquals(testResult.toString(), result.toString());
// And Excel style
formatArg = new StringEval("mmmm dd, yyyy");
args[1] = formatArg;
result = TextFunction.TEXT.evaluate(args, -1, (short)-1);
testResult = new StringEval(november + " 16, 1900");
assertEquals(testResult.toString(), result.toString());
} finally {
LocaleUtil.setUserTimeZone(userTZ);
}
}
}

+ 9
- 7
src/testcases/org/apache/poi/ss/formula/functions/TestTime.java 查看文件

@@ -17,9 +17,9 @@

package org.apache.poi.ss.formula.functions;

import java.util.regex.Pattern;
import static org.junit.Assert.assertEquals;

import junit.framework.TestCase;
import java.util.regex.Pattern;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
@@ -28,13 +28,13 @@ import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.junit.Before;
import org.junit.Test;

/**
* Tests for {@link TimeFunc}
*
* @author @author Steven Butler (sebutler @ gmail dot com)
*/
public final class TestTime extends TestCase {
public final class TestTime {

private static final int SECONDS_PER_MINUTE = 60;
private static final int SECONDS_PER_HOUR = 60 * SECONDS_PER_MINUTE;
@@ -44,7 +44,8 @@ public final class TestTime extends TestCase {
private HSSFWorkbook wb;
private HSSFDataFormatter form;
private HSSFCellStyle style;

@Before
public void setUp() {
wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("new sheet");
@@ -58,11 +59,13 @@ public final class TestTime extends TestCase {
evaluator = new HSSFFormulaEvaluator(wb);
}

@Test
public void testSomeArgumentsMissing() {
confirm("00:00:00", "TIME(, 0, 0)");
confirm("12:00:00", "TIME(12, , )");
}

@Test
public void testValid() {
confirm("00:00:01", 0, 0, 1);
confirm("00:01:00", 0, 1, 0);
@@ -101,7 +104,6 @@ public final class TestTime extends TestCase {
}

private void confirm(String expectedTimeStr, String formulaText) {
// System.out.println("=" + formulaText);
String[] parts = Pattern.compile(":").split(expectedTimeStr);
int expH = Integer.parseInt(parts[0]);
int expM = Integer.parseInt(parts[1]);

+ 44
- 13
src/testcases/org/apache/poi/ss/usermodel/BaseTestCell.java 查看文件

@@ -17,23 +17,31 @@

package org.apache.poi.ss.usermodel;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;

import junit.framework.AssertionFailedError;
import junit.framework.TestCase;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.ITestDataProvider;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.util.LocaleUtil;
import org.junit.Test;

import junit.framework.AssertionFailedError;

/**
* Common superclass for testing implementations of
* {@link org.apache.poi.ss.usermodel.Cell}
*/
public abstract class BaseTestCell extends TestCase {
public abstract class BaseTestCell {

protected final ITestDataProvider _testDataProvider;

@@ -44,6 +52,7 @@ public abstract class BaseTestCell extends TestCase {
_testDataProvider = testDataProvider;
}

@Test
public void testSetValues() {
Workbook book = _testDataProvider.createWorkbook();
Sheet sheet = book.createSheet("test");
@@ -80,7 +89,7 @@ public abstract class BaseTestCell extends TestCase {
assertProhibitedValueAccess(cell, Cell.CELL_TYPE_NUMERIC, Cell.CELL_TYPE_BOOLEAN,
Cell.CELL_TYPE_FORMULA, Cell.CELL_TYPE_ERROR);

Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.ROOT);
Calendar c = LocaleUtil.getLocaleCalendar();
c.setTimeInMillis(123456789);
cell.setCellValue(c.getTime());
assertEquals(c.getTime().getTime(), cell.getDateCellValue().getTime());
@@ -132,6 +141,7 @@ public abstract class BaseTestCell extends TestCase {
/**
* test that Boolean and Error types (BoolErrRecord) are supported properly.
*/
@Test
public void testBoolErr() {

Workbook wb = _testDataProvider.createWorkbook();
@@ -173,6 +183,7 @@ public abstract class BaseTestCell extends TestCase {
/**
* test that Cell Styles being applied to formulas remain intact
*/
@Test
public void testFormulaStyle() {

Workbook wb = _testDataProvider.createWorkbook();
@@ -214,6 +225,7 @@ public abstract class BaseTestCell extends TestCase {
}

/**tests the toString() method of HSSFCell*/
@Test
public void testToString() {
Workbook wb = _testDataProvider.createWorkbook();
Row r = wb.createSheet("Sheet1").createRow(0);
@@ -245,6 +257,7 @@ public abstract class BaseTestCell extends TestCase {
/**
* Test that setting cached formula result keeps the cell type
*/
@Test
public void testSetFormulaValue() {
Workbook wb = _testDataProvider.createWorkbook();
Sheet s = wb.createSheet();
@@ -278,7 +291,7 @@ public abstract class BaseTestCell extends TestCase {
return _testDataProvider.createWorkbook().createSheet("Sheet1").createRow(0).createCell(0);
}

@Test
public void testChangeTypeStringToBool() {
Cell cell = createACell();

@@ -305,6 +318,7 @@ public abstract class BaseTestCell extends TestCase {
assertEquals("FALSE", cell.getRichStringCellValue().getString());
}

@Test
public void testChangeTypeBoolToString() {
Cell cell = createACell();

@@ -321,6 +335,7 @@ public abstract class BaseTestCell extends TestCase {
assertEquals("TRUE", cell.getRichStringCellValue().getString());
}

@Test
public void testChangeTypeErrorToNumber() {
Cell cell = createACell();
cell.setCellErrorValue((byte)ErrorConstants.ERROR_NAME);
@@ -332,6 +347,7 @@ public abstract class BaseTestCell extends TestCase {
assertEquals(2.5, cell.getNumericCellValue(), 0.0);
}

@Test
public void testChangeTypeErrorToBoolean() {
Cell cell = createACell();
cell.setCellErrorValue((byte)ErrorConstants.ERROR_NAME);
@@ -353,6 +369,7 @@ public abstract class BaseTestCell extends TestCase {
* {@link FormulaEvaluator#evaluateInCell(Cell)} with a
* string result type.
*/
@Test
public void testConvertStringFormulaCell() {
Cell cellA1 = createACell();
cellA1.setCellFormula("\"abc\"");
@@ -371,10 +388,12 @@ public abstract class BaseTestCell extends TestCase {
}
assertEquals("abc", cellA1.getStringCellValue());
}
/**
* similar to {@link #testConvertStringFormulaCell()} but checks at a
* lower level that {#link {@link Cell#setCellType(int)} works properly
*/
@Test
public void testSetTypeStringOnFormulaCell() {
Cell cellA1 = createACell();
FormulaEvaluator fe = cellA1.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
@@ -418,6 +437,7 @@ public abstract class BaseTestCell extends TestCase {
/**
* Test for bug in convertCellValueToBoolean to make sure that formula results get converted
*/
@Test
public void testChangeTypeFormulaToBoolean() {
Cell cell = createACell();
cell.setCellFormula("1=1");
@@ -433,6 +453,7 @@ public abstract class BaseTestCell extends TestCase {
* Bug 40296: HSSFCell.setCellFormula throws
* ClassCastException if cell is created using HSSFRow.createCell(short column, int type)
*/
@Test
public void test40296() {
Workbook wb = _testDataProvider.createWorkbook();
Sheet workSheet = wb.createSheet("Sheet1");
@@ -470,6 +491,7 @@ public abstract class BaseTestCell extends TestCase {
assertEquals("SUM(A1:B1)", cell.getCellFormula());
}

@Test
public void testSetStringInFormulaCell_bug44606() {
Workbook wb = _testDataProvider.createWorkbook();
Cell cell = wb.createSheet("Sheet1").createRow(0).createCell(0);
@@ -484,7 +506,8 @@ public abstract class BaseTestCell extends TestCase {
/**
* Make sure that cell.setCellType(Cell.CELL_TYPE_BLANK) preserves the cell style
*/
public void testSetBlank_bug47028() {
@Test
public void testSetBlank_bug47028() {
Workbook wb = _testDataProvider.createWorkbook();
CellStyle style = wb.createCellStyle();
Cell cell = wb.createSheet("Sheet1").createRow(0).createCell(0);
@@ -514,7 +537,8 @@ public abstract class BaseTestCell extends TestCase {
* </li>
* </ul>
*/
public void testNanAndInfinity() {
@Test
public void testNanAndInfinity() {
Workbook wb = _testDataProvider.createWorkbook();
Sheet workSheet = wb.createSheet("Sheet1");
Row row = workSheet.createRow(0);
@@ -550,7 +574,8 @@ public abstract class BaseTestCell extends TestCase {
assertEquals(ErrorConstants.ERROR_DIV_0, cell2.getErrorCellValue());
}

public void testDefaultStyleProperties() {
@Test
public void testDefaultStyleProperties() {
Workbook wb = _testDataProvider.createWorkbook();

Cell cell = wb.createSheet("Sheet1").createRow(0).createCell(0);
@@ -584,7 +609,8 @@ public abstract class BaseTestCell extends TestCase {
assertFalse(style2.getHidden());
}

public void testBug55658SetNumericValue(){
@Test
public void testBug55658SetNumericValue(){
Workbook wb = _testDataProvider.createWorkbook();
Sheet sh = wb.createSheet();
Row row = sh.createRow(0);
@@ -604,7 +630,8 @@ public abstract class BaseTestCell extends TestCase {
assertEquals("24", wb.getSheetAt(0).getRow(0).getCell(1).getStringCellValue());
}

public void testRemoveHyperlink(){
@Test
public void testRemoveHyperlink(){
Workbook wb = _testDataProvider.createWorkbook();
Sheet sh = wb.createSheet("test");
Row row = sh.createRow(0);
@@ -646,7 +673,8 @@ public abstract class BaseTestCell extends TestCase {
* an problem that cell could not return error value form formula cell).
* @throws IOException
*/
public void testGetErrorCellValueFromFormulaCell() throws IOException {
@Test
public void testGetErrorCellValueFromFormulaCell() throws IOException {
Workbook wb = _testDataProvider.createWorkbook();
try {
Sheet sheet = wb.createSheet();
@@ -660,7 +688,8 @@ public abstract class BaseTestCell extends TestCase {
}
}
public void testSetRemoveStyle() throws Exception {
@Test
public void testSetRemoveStyle() throws Exception {
Workbook wb = _testDataProvider.createWorkbook();
Sheet sheet = wb.createSheet();
Row row = sheet.createRow(0);
@@ -699,6 +728,7 @@ public abstract class BaseTestCell extends TestCase {
wb.close();
}

@Test
public void test57008() throws IOException {
Workbook wb = _testDataProvider.createWorkbook();
Sheet sheet = wb.createSheet();
@@ -740,6 +770,7 @@ public abstract class BaseTestCell extends TestCase {
* The maximum length of cell contents (text) is 32,767 characters.
* @throws IOException
*/
@Test
public void testMaxTextLength() throws IOException{
Workbook wb = _testDataProvider.createWorkbook();
Sheet sheet = wb.createSheet();

+ 42
- 11
src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetAutosizeColumn.java 查看文件

@@ -17,15 +17,20 @@

package org.apache.poi.ss.usermodel;

import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.Calendar;
import java.util.Locale;

import org.apache.poi.ss.ITestDataProvider;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.JvmBugs;
import org.apache.poi.util.LocaleUtil;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import java.util.Calendar;

/**
* Common superclass for testing automatic sizing of sheet columns
*
@@ -35,12 +40,25 @@ public abstract class BaseTestSheetAutosizeColumn {

private final ITestDataProvider _testDataProvider;

private static Locale userLocale;
@BeforeClass
public static void initLocale() {
userLocale = LocaleUtil.getUserLocale();
LocaleUtil.setUserLocale(Locale.ROOT);
}
@AfterClass
public static void resetLocale() {
LocaleUtil.setUserLocale(userLocale);
}
protected BaseTestSheetAutosizeColumn(ITestDataProvider testDataProvider) {
_testDataProvider = testDataProvider;
}

@Test
public void numericCells(){
public void numericCells() throws Exception {
Workbook workbook = _testDataProvider.createWorkbook();
fixFonts(workbook);
DataFormat df = workbook.getCreationHelper().createDataFormat();
@@ -77,10 +95,12 @@ public abstract class BaseTestSheetAutosizeColumn {
assertEquals(sheet.getColumnWidth(1), sheet.getColumnWidth(2)); // columns 1, 2 and 3 should have the same width
assertEquals(sheet.getColumnWidth(2), sheet.getColumnWidth(3)); // columns 1, 2 and 3 should have the same width
assertEquals(sheet.getColumnWidth(4), sheet.getColumnWidth(5)); // 10.0000 and '10.0000'
workbook.close();
}

@Test
public void booleanCells(){
public void booleanCells() throws Exception {
Workbook workbook = _testDataProvider.createWorkbook();
fixFonts(workbook);
Sheet sheet = workbook.createSheet();
@@ -106,10 +126,12 @@ public abstract class BaseTestSheetAutosizeColumn {
assertTrue(sheet.getColumnWidth(1) > sheet.getColumnWidth(0)); // 'true' is wider than '0'
assertEquals(sheet.getColumnWidth(1), sheet.getColumnWidth(2)); // columns 1, 2 and 3 should have the same width
assertEquals(sheet.getColumnWidth(2), sheet.getColumnWidth(3)); // columns 1, 2 and 3 should have the same width

workbook.close();
}

@Test
public void dateCells(){
public void dateCells() throws Exception {
Workbook workbook = _testDataProvider.createWorkbook();
fixFonts(workbook);
Sheet sheet = workbook.createSheet();
@@ -124,8 +146,7 @@ public abstract class BaseTestSheetAutosizeColumn {
CellStyle style5 = workbook.createCellStyle(); //rotated text
style5.setDataFormat(df.getFormat("mmm/dd/yyyy"));

Calendar calendar = Calendar.getInstance();
calendar.set(2010, 0, 1); // Jan 1 2010
Calendar calendar = LocaleUtil.getLocaleCalendar(2010, 0, 1); // Jan 1 2010

Row row = sheet.createRow(0);
row.createCell(0).setCellValue(DateUtil.getJavaDate(0)); //default date
@@ -172,10 +193,12 @@ public abstract class BaseTestSheetAutosizeColumn {
assertTrue(sheet.getColumnWidth(5) > sheet.getColumnWidth(3)); // 'mmm/dd/yyyy' is wider than 'mmm'
assertEquals(sheet.getColumnWidth(6), sheet.getColumnWidth(5)); // date formatted as 'mmm/dd/yyyy'
assertEquals(sheet.getColumnWidth(4), sheet.getColumnWidth(7)); // date formula formatted as 'mmm'
workbook.close();
}

@Test
public void stringCells(){
public void stringCells() throws Exception {
Workbook workbook = _testDataProvider.createWorkbook();
fixFonts(workbook);
Sheet sheet = workbook.createSheet();
@@ -205,10 +228,12 @@ public abstract class BaseTestSheetAutosizeColumn {
assertEquals(sheet.getColumnWidth(4), sheet.getColumnWidth(3));
boolean ignoreFontSizeX2 = JvmBugs.hasLineBreakMeasurerBug();
assertTrue(ignoreFontSizeX2 || sheet.getColumnWidth(5) > sheet.getColumnWidth(4)); //larger font results in a wider column width
workbook.close();
}

@Test
public void rotatedText(){
public void rotatedText() throws Exception {
Workbook workbook = _testDataProvider.createWorkbook();
fixFonts(workbook);
Sheet sheet = workbook.createSheet();
@@ -230,10 +255,12 @@ public abstract class BaseTestSheetAutosizeColumn {
int w1 = sheet.getColumnWidth(1);

assertTrue(w0*5 < w1); // rotated text occupies at least five times less horizontal space than normal text
workbook.close();
}

@Test
public void mergedCells(){
public void mergedCells() throws Exception {
Workbook workbook = _testDataProvider.createWorkbook();
fixFonts(workbook);
Sheet sheet = workbook.createSheet();
@@ -251,6 +278,8 @@ public abstract class BaseTestSheetAutosizeColumn {

sheet.autoSizeColumn(0, true);
assertTrue(sheet.getColumnWidth(0) > defaulWidth);
workbook.close();
}

@@ -293,6 +322,8 @@ public abstract class BaseTestSheetAutosizeColumn {
Row r60708 = sheet.createRow(60708);
r60708.createCell(0).setCellValue("Near the end");
sheet.autoSizeColumn(0);
workbook.close();
}
// TODO should we have this stuff in the FormulaEvaluator?

+ 36
- 9
src/testcases/org/apache/poi/ss/usermodel/TestDataFormatter.java 查看文件

@@ -21,16 +21,22 @@

package org.apache.poi.ss.usermodel;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.IOException;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import junit.framework.TestCase;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.TestHSSFDataFormatter;
import org.apache.poi.util.LocaleUtil;
import org.junit.Ignore;
import org.junit.Test;

/**
* Tests of {@link DataFormatter}
@@ -38,13 +44,14 @@ import org.apache.poi.hssf.usermodel.TestHSSFDataFormatter;
* See {@link TestHSSFDataFormatter} too for
* more tests.
*/
public class TestDataFormatter extends TestCase {
public class TestDataFormatter {
private static final double _15_MINUTES = 0.041666667;

/**
* Test that we use the specified locale when deciding
* how to format normal numbers
*/
@Test
public void testLocale() {
DataFormatter dfUS = new DataFormatter(Locale.US);
DataFormatter dfFR = new DataFormatter(Locale.FRENCH);
@@ -61,6 +68,7 @@ public class TestDataFormatter extends TestCase {
* a specific locale, but we should format things as if
* the locale (eg '[$-1010409]') isn't there
*/
@Test
public void testLocaleBasedFormats() {
DataFormatter dfUS = new DataFormatter(Locale.US);

@@ -78,6 +86,7 @@ public class TestDataFormatter extends TestCase {
* Ensure that colours get correctly
* zapped from within the format strings
*/
@Test
public void testColours() {
DataFormatter dfUS = new DataFormatter(Locale.US);
@@ -105,6 +114,7 @@ public class TestDataFormatter extends TestCase {
assertEquals("[ab]12.34[x]", dfUS.formatRawCellContents(12.343, -1, "[ab]##.##[x]"));
}
@Test
public void testColoursAndBrackets() {
DataFormatter dfUS = new DataFormatter(Locale.US);
@@ -149,6 +159,7 @@ public class TestDataFormatter extends TestCase {
* and Excel differ, and workarounds are not
* yet in place for all of these
*/
@Test
public void testNegativeZero() {
DataFormatter dfUS = new DataFormatter(Locale.US);
@@ -193,6 +204,7 @@ public class TestDataFormatter extends TestCase {
* Test that we correctly handle fractions in the
* format string, eg # #/#
*/
@Test
public void testFractions() {
DataFormatter dfUS = new DataFormatter(Locale.US);
@@ -262,6 +274,7 @@ public class TestDataFormatter extends TestCase {
* and *x (fill to the column width with "x"s) are
* correctly ignored by us.
*/
@Test
public void testPaddingSpaces() {
DataFormatter dfUS = new DataFormatter(Locale.US);
assertEquals("12.34", dfUS.formatRawCellContents(12.343, -1, "##.##_ "));
@@ -278,6 +291,7 @@ public class TestDataFormatter extends TestCase {
/**
* DataFormatter is the CSV mode preserves spaces
*/
@Test
public void testPaddingSpacesCSV() {
DataFormatter dfUS = new DataFormatter(Locale.US, true);
assertEquals("12.34 ", dfUS.formatRawCellContents(12.343, -1, "##.##_ "));
@@ -311,12 +325,11 @@ public class TestDataFormatter extends TestCase {
* Test that the special Excel month format MMMMM
* gets turned into the first letter of the month
*/
@Test
public void testMMMMM() {
DataFormatter dfUS = new DataFormatter(Locale.US);
Calendar c = Calendar.getInstance();
c.set(Calendar.MILLISECOND, 0);
c.set(2010, 5, 1, 2, 0, 0);
Calendar c = LocaleUtil.getLocaleCalendar(2010, 5, 1, 2, 0, 0);
assertEquals("2010-J-1 2:00:00", dfUS.formatRawCellContents(
DateUtil.getExcelDate(c, false), -1, "YYYY-MMMMM-D h:mm:ss"
@@ -326,6 +339,7 @@ public class TestDataFormatter extends TestCase {
/**
* Tests that we do AM/PM handling properly
*/
@Test
public void testAMPM() {
DataFormatter dfUS = new DataFormatter(Locale.US);
@@ -343,6 +357,7 @@ public class TestDataFormatter extends TestCase {
* Test that we can handle elapsed time,
* eg formatting 1 day 4 hours as 28 hours
*/
@Test
public void testElapsedTime() {
DataFormatter dfUS = new DataFormatter(Locale.US);

@@ -447,6 +462,7 @@ public class TestDataFormatter extends TestCase {
}
}

@Test
public void testDateWindowing() {
DataFormatter dfUS = new DataFormatter(Locale.US);
@@ -455,6 +471,7 @@ public class TestDataFormatter extends TestCase {
assertEquals("1904-01-01 00:00:00", dfUS.formatRawCellContents(0.0, -1, "yyyy-mm-dd hh:mm:ss", true));
}

@Test
public void testScientificNotation() {
DataFormatter dfUS = new DataFormatter(Locale.US);

@@ -463,6 +480,7 @@ public class TestDataFormatter extends TestCase {
assertEquals("0.00E+00", dfUS.formatRawCellContents(0.0, -1, "0.00E+00"));
}

@Test
public void testInvalidDate() {
DataFormatter df1 = new DataFormatter(Locale.US);
assertEquals("-1.0", df1.formatRawCellContents(-1, -1, "mm/dd/yyyy"));
@@ -472,6 +490,7 @@ public class TestDataFormatter extends TestCase {
df2.formatRawCellContents(-1, -1, "mm/dd/yyyy"));
}

@Test
public void testEscapes() {
DataFormatter dfUS = new DataFormatter(Locale.US);

@@ -485,6 +504,7 @@ public class TestDataFormatter extends TestCase {
assertEquals("1901/01/01", dfUS.formatRawCellContents(367.0, -1, "yyyy\\/mm\\/dd"));
}

@Test
public void testOther() {
DataFormatter dfUS = new DataFormatter(Locale.US, true);

@@ -494,6 +514,7 @@ public class TestDataFormatter extends TestCase {
assertEquals(" $- ", dfUS.formatRawCellContents(0.0, -1, "_-$* #,##0.00_-;-$* #,##0.00_-;_-$* \"-\"??_-;_-@_-"));
}
@Test
public void testErrors() throws IOException {
DataFormatter dfUS = new DataFormatter(Locale.US, true);

@@ -519,6 +540,7 @@ public class TestDataFormatter extends TestCase {
* the start of a format string to format it differently, we
* should at least handle it as it if wasn't there
*/
@Test
public void testDatesWithLocales() {
DataFormatter dfUS = new DataFormatter(Locale.US, true);
@@ -543,7 +565,9 @@ public class TestDataFormatter extends TestCase {
/**
* TODO Fix these so that they work
*/
public void DISABLEDtestCustomFormats() {
@Test
@Ignore
public void testCustomFormats() {
DataFormatter dfUS = new DataFormatter(Locale.US, true);
String fmt;
@@ -560,6 +584,7 @@ public class TestDataFormatter extends TestCase {
/**
* ExcelStyleDateFormatter should work for Milliseconds too
*/
@Test
public void testExcelStyleDateFormatterStringOnMillis() {
// Test directly with the .000 style
DateFormat formatter1 = new ExcelStyleDateFormatter("ss.000");
@@ -589,7 +614,8 @@ public class TestDataFormatter extends TestCase {
assertEquals("01.010", dfUS.formatRawCellContents(0.0000116898, -1, "ss.000"));
}

public void testBug54786() {
@Test
public void testBug54786() {
DataFormatter formatter = new DataFormatter();
String format = "[h]\"\"h\"\" m\"\"m\"\"";
assertTrue(DateUtil.isADateFormat(-1,format));
@@ -613,7 +639,8 @@ public class TestDataFormatter extends TestCase {
}
}
public void testIsADateFormat() {
@Test
public void testIsADateFormat() {
// first check some cases that should not be a date, also call multiple times to ensure the cache is used
assertFalse(DateUtil.isADateFormat(-1, null));
assertFalse(DateUtil.isADateFormat(-1, null));

+ 18
- 15
src/testcases/org/apache/poi/ss/usermodel/TestDateUtil.java 查看文件

@@ -23,6 +23,7 @@ import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import org.apache.poi.util.LocaleUtil;
import org.junit.Test;

public class TestDateUtil {
@@ -30,7 +31,7 @@ public class TestDateUtil {
@Test
public void getJavaDate_InvalidValue() {
double dateValue = -1;
TimeZone tz = TimeZone.getDefault();
TimeZone tz = LocaleUtil.getUserTimeZone();
boolean use1904windowing = false;
boolean roundSeconds = false;

@@ -44,13 +45,11 @@ public class TestDateUtil {
@Test
public void getJavaDate_ValidValue() {
double dateValue = 0;
TimeZone tz = TimeZone.getDefault();
TimeZone tz = LocaleUtil.getUserTimeZone();
boolean use1904windowing = false;
boolean roundSeconds = false;

Calendar calendar = Calendar.getInstance(tz);
calendar.set(1900, 0, 0, 0, 0, 0);
calendar.set(Calendar.MILLISECOND, 0);
Calendar calendar = LocaleUtil.getLocaleCalendar(1900, 0, 0);
Date date = calendar.getTime();

assertEquals(date, DateUtil.getJavaDate(dateValue));
@@ -63,7 +62,7 @@ public class TestDateUtil {
@Test
public void getJavaCalendar_InvalidValue() {
double dateValue = -1;
TimeZone tz = TimeZone.getDefault();
TimeZone tz = LocaleUtil.getUserTimeZone();
boolean use1904windowing = false;
boolean roundSeconds = false;

@@ -76,17 +75,21 @@ public class TestDateUtil {
@Test
public void getJavaCalendar_ValidValue() {
double dateValue = 0;
TimeZone tz = TimeZone.getDefault();
TimeZone tz = LocaleUtil.getUserTimeZone();
boolean use1904windowing = false;
boolean roundSeconds = false;

Calendar calendar = Calendar.getInstance(tz);
calendar.set(1900, 0, 0, 0, 0, 0);
calendar.set(Calendar.MILLISECOND, 0);

assertEquals(calendar, DateUtil.getJavaCalendar(dateValue));
assertEquals(calendar, DateUtil.getJavaCalendar(dateValue, use1904windowing));
assertEquals(calendar, DateUtil.getJavaCalendar(dateValue, use1904windowing, tz));
assertEquals(calendar, DateUtil.getJavaCalendar(dateValue, use1904windowing, tz, roundSeconds));
Calendar expCal = LocaleUtil.getLocaleCalendar(1900, 0, 0);

Calendar actCal[] = {
DateUtil.getJavaCalendar(dateValue),
DateUtil.getJavaCalendar(dateValue, use1904windowing),
DateUtil.getJavaCalendar(dateValue, use1904windowing, tz),
DateUtil.getJavaCalendar(dateValue, use1904windowing, tz, roundSeconds)
};
assertEquals(expCal, actCal[0]);
assertEquals(expCal, actCal[1]);
assertEquals(expCal, actCal[2]);
assertEquals(expCal, actCal[3]);
}
}

+ 1
- 1
src/testcases/org/apache/poi/ss/util/TestDateFormatConverter.java 查看文件

@@ -69,7 +69,7 @@ public final class TestDateFormatConverter extends TestCase {
Row row = sheet.createRow(rowNum++);
row.createCell(0).setCellValue(locale.toString());
row.createCell(1).setCellValue(locale.getDisplayName());
row.createCell(1).setCellValue(locale.getDisplayName(Locale.ROOT));
DateFormat dateFormat;
if( dates ) {

+ 1
- 1
src/testcases/org/apache/poi/util/TestHexDump.java 查看文件

@@ -134,7 +134,7 @@ public final class TestHexDump {
obj[17] = chrs.toString();
format.append("%18$s"+HexDump.EOL);
String str = String.format(format.toString(), obj);
String str = String.format(LocaleUtil.getUserLocale(), format.toString(), obj);
strExp.append(str);
}
byte bytesExp[] = strExp.toString().getBytes(HexDump.UTF8);

+ 0
- 0
src/testcases/org/apache/poi/util/TestStringUtil.java 查看文件


部分文件因文件數量過多而無法顯示

Loading…
取消
儲存