Browse Source

more tests and tweaks to custom formatting

git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/branches/jdk8@1271 f203690c-595d-4dc9-a70b-905162fa7fd2
tags/jackcess-3.0.0
James Ahlborn 5 years ago
parent
commit
b2bb4fcdba

+ 92
- 75
src/main/java/com/healthmarketscience/jackcess/impl/expr/FormatUtil.java View File

@@ -18,9 +18,7 @@ package com.healthmarketscience.jackcess.impl.expr;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
@@ -892,7 +890,7 @@ public class FormatUtil
pendingLiteral.setLength(0);
}

private static NumberFormat createCustomNumberFormat(
private static BDFormat createCustomNumberFormat(
String[] fmtStrs, NumberFormatter.NotationType[] expTypes,
boolean[] hasFmts, int fmtIdx, Args args) {

@@ -911,26 +909,29 @@ public class FormatUtil
sb.deleteCharAt(++i);
}
}
} else {
// this was a single, literal single quote
sb.append(SINGLE_QUOTE_CHAR);
}
fmtStr = sb.toString();
}
return new LiteralNumberFormat(fmtStr);
return new LiteralBDFormat(fmtStr);
}

NumberFormatter.NotationType expType = expTypes[fmtIdx];
NumberFormat nf = args._ctx.createDecimalFormat(fmtStr);
DecimalFormat df = args._ctx.createDecimalFormat(fmtStr);

DecimalFormat df = (DecimalFormat)nf;
if(df.getMaximumFractionDigits() > 0) {
// if the decimal is included in the format, access always shows it
df.setDecimalSeparatorAlwaysShown(true);
}

if(expType != null) {
nf = new NumberFormatter.ScientificFormat(nf, expType);
return new BaseBDFormat(
new NumberFormatter.ScientificFormat(df, expType));
}

return nf;
return new DecimalBDFormat(df);
}

private static Fmt parseCustomTextFormat(ExprBuf buf, Args args) {
@@ -1289,7 +1290,7 @@ public class FormatUtil
public Set<Map.Entry<Long,String>> entrySet() {
return new AbstractSet<Map.Entry<Long,String>>() {
@Override
public int size() {
public int size() {
return 2;
}
@Override
@@ -1420,40 +1421,66 @@ public class FormatUtil
protected abstract Value formatZero(BigDecimal bd, Args args);
}

private static final class CustomGeneralFmt extends BaseCustomNumberFmt
{
private final Value _posVal;
private final Value _negVal;
private final Value _zeroVal;
private final Value _nullVal;

private CustomGeneralFmt(Value posVal, Value negVal,
Value zeroVal, Value nullVal) {
_posVal = posVal;
_negVal = negVal;
_zeroVal = zeroVal;
_nullVal = nullVal;
}

@Override
protected Value formatNull(Args args) {
return _nullVal;
}
@Override
protected Value formatPos(BigDecimal bd, Args args) {
return _posVal;
}
@Override
protected Value formatNeg(BigDecimal bd, Args args) {
return _negVal;
}
@Override
protected Value formatZero(BigDecimal bd, Args args) {
return _zeroVal;
}
}

private static final class CustomNumberFmt extends BaseCustomNumberFmt
{
private final NumberFormat _posFmt;
private final NumberFormat _negFmt;
private final NumberFormat _zeroFmt;
private final NumberFormat _nullFmt;
private final BDFormat _posFmt;
private final BDFormat _negFmt;
private final BDFormat _zeroFmt;
private final BDFormat _nullFmt;

private CustomNumberFmt(NumberFormat posFmt, NumberFormat negFmt,
NumberFormat zeroFmt, NumberFormat nullFmt) {
private CustomNumberFmt(BDFormat posFmt, BDFormat negFmt,
BDFormat zeroFmt, BDFormat nullFmt) {
_posFmt = posFmt;
_negFmt = negFmt;
_zeroFmt = zeroFmt;
_nullFmt = nullFmt;
}

private Value formatMaybeZero(BigDecimal bd, NumberFormat fmt) {
private Value formatMaybeZero(BigDecimal bd, BDFormat fmt) {
// in theory we want to use the given format. however, if, due to
// rounding, we end up with a number equivalent to zero, then we fall
// back to the zero format. if we are using scientific notation,
// however, then don't worry about this
if(!(fmt instanceof NumberFormatter.ScientificFormat)) {
int maxDecDigits = fmt.getMaximumFractionDigits();
int mult = ((DecimalFormat)fmt).getMultiplier();
while(mult > 1) {
++maxDecDigits;
mult /= 10;
}
if(maxDecDigits < bd.scale()) {
int maxDecDigits = fmt.getMaxDecimalDigits();
if(maxDecDigits < bd.scale()) {
bd = bd.setScale(maxDecDigits, NumberFormatter.ROUND_MODE);
}
}
if(BigDecimal.ZERO.compareTo(bd) == 0) {
// fall back to zero format
fmt = _zeroFmt;
if(BigDecimal.ZERO.compareTo(bd) == 0) {
// fall back to zero format
fmt = _zeroFmt;
}
}

return ValueSupport.toValue(fmt.format(bd));
@@ -1477,72 +1504,62 @@ public class FormatUtil
}
}

private static final class CustomGeneralFmt extends BaseCustomNumberFmt
private static abstract class BDFormat
{
private final Value _posVal;
private final Value _negVal;
private final Value _zeroVal;
private final Value _nullVal;

private CustomGeneralFmt(Value posVal, Value negVal,
Value zeroVal, Value nullVal) {
_posVal = posVal;
_negVal = negVal;
_zeroVal = zeroVal;
_nullVal = nullVal;
public int getMaxDecimalDigits() {
return Integer.MAX_VALUE;
}

@Override
protected Value formatNull(Args args) {
return _nullVal;
}
@Override
protected Value formatPos(BigDecimal bd, Args args) {
return _posVal;
}
@Override
protected Value formatNeg(BigDecimal bd, Args args) {
return _negVal;
}
@Override
protected Value formatZero(BigDecimal bd, Args args) {
return _zeroVal;
}
public abstract String format(BigDecimal bd);
}

private static final class LiteralNumberFormat extends NumberFormat
private static final class LiteralBDFormat extends BDFormat
{
private static final long serialVersionUID = 0L;

private final String _str;

private LiteralNumberFormat(String str) {
private LiteralBDFormat(String str) {
_str = str;
}

@Override
public StringBuffer format(Object number, StringBuffer toAppendTo,
FieldPosition pos)
{
return toAppendTo.append(_str);
public String format(BigDecimal bd) {
return _str;
}
}

@Override
public StringBuffer format(double number, StringBuffer toAppendTo,
FieldPosition pos) {
throw new UnsupportedOperationException();
private static class BaseBDFormat extends BDFormat
{
private final NumberFormat _nf;

private BaseBDFormat(NumberFormat nf) {
_nf = nf;
}

@Override
public Number parse(String source, ParsePosition parsePosition) {
throw new UnsupportedOperationException();
public String format(BigDecimal bd) {
return _nf.format(bd);
}
}

private static final class DecimalBDFormat extends BaseBDFormat
{
private final int _maxDecDigits;

private DecimalBDFormat(DecimalFormat df) {
super(df);

int maxDecDigits = df.getMaximumFractionDigits();
int mult = df.getMultiplier();
while(mult > 1) {
++maxDecDigits;
mult /= 10;
}
_maxDecDigits = maxDecDigits;
}

@Override
public StringBuffer format(long number, StringBuffer toAppendTo,
FieldPosition pos) {
throw new UnsupportedOperationException();
public int getMaxDecimalDigits() {
return _maxDecDigits;
}
}

}

+ 10
- 1
src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java View File

@@ -333,6 +333,7 @@ public class DefaultFunctionsTest extends TestCase
public void testCustomFormat() throws Exception
{
assertEval("07:00 a", "=Format(#01/10/2003 7:00:00 AM#, 'hh:nn a/p')");
assertEval("07:00 p", "=Format(#01/10/2003 7:00:00 PM#, 'hh:nn a/p')");
assertEval("07:00 a 6 2", "=Format(#01/10/2003 7:00:00 AM#, 'hh:nn a/p w ww')");
assertEval("07:00 a 4 1", "=Format(#01/10/2003 7:00:00 AM#, 'hh:nn a/p w ww', 3, 3)");
assertEval("1313", "=Format(#01/10/2003 7:13:00 AM#, 'nnnn; foo bar')");
@@ -349,6 +350,8 @@ public class DefaultFunctionsTest extends TestCase
"=Format('3.9', 'dddd, yy mmm mm/d, hh:nn:ss AMPM')");
assertEval("9:36:00 PM",
"=Format('3.9', 'ttttt')");
assertEval("9:36:00 PM",
"=Format(3.9, 'ttttt')");
assertEval("foo",
"=Format('foo', 'dddd, yy mmm mm d, hh:nn:ss AMPM')");

@@ -359,11 +362,12 @@ public class DefaultFunctionsTest extends TestCase
"n", "'0'",
"", "Null");

assertEvalFormat("';\"y\";!\\n;*~\\z[Blue];'",
assertEvalFormat("'\\p;\"y\";!\\n;*~\\z[Blue];'",
"foo", "'foo'",
"", "''",
"y", "True",
"n", "'0'",
"p", "'10'",
"z", "Null");

assertEvalFormat("'\"p\"#.00#\"blah\"'",
@@ -475,6 +479,11 @@ public class DefaultFunctionsTest extends TestCase
// "", "0"
);

assertEvalFormat("\"#;n'g;'\"",
"5", "5",
"n'g", "-5",
"'", "0");

assertEvalFormat("'$0.0#'",
"$213.0", "213");


Loading…
Cancel
Save