Browse Source

Add ColumnFormatter utility which can apply Column Format property for display of column values

git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1291 f203690c-595d-4dc9-a70b-905162fa7fd2
tags/jackcess-3.0.1
James Ahlborn 5 years ago
parent
commit
831d8c0b1d

+ 6
- 0
src/changes/changes.xml View File

@@ -4,6 +4,12 @@
<author email="javajedi@users.sf.net">Tim McCune</author>
</properties>
<body>
<release version="3.0.1" date="TBD">
<action dev="jahlborn" type="update">
Add ColumnFormatter utility which can apply Column "Format" property
for display of column values.
</action>
</release>
<release version="3.0.0" date="2019-02-08" description="Update to Java 8">
<action dev="jahlborn" type="update">
Jackcess now requires a Java 8+ runtime. As part of this update, all

+ 1
- 1
src/main/java/com/healthmarketscience/jackcess/expr/package-info.java View File

@@ -215,7 +215,7 @@ limitations under the License.
*
* <table border="1" width="25%" cellpadding="3" cellspacing="0">
* <tr class="TableHeadingColor" align="left"><th>Function</th><th>Supported</th></tr>
* <tr class="TableRowColor"><td>Format[$]</td><td>Partial</td></tr>
* <tr class="TableRowColor"><td>Format[$]</td><td>Y</td></tr>
* <tr class="TableRowColor"><td>InStr</td><td>Y</td></tr>
* <tr class="TableRowColor"><td>InStrRev</td><td>Y</td></tr>
* <tr class="TableRowColor"><td>LCase[$]</td><td>Y</td></tr>

+ 6
- 0
src/main/java/com/healthmarketscience/jackcess/impl/ColEvalContext.java View File

@@ -16,6 +16,8 @@ limitations under the License.

package com.healthmarketscience.jackcess.impl;

import com.healthmarketscience.jackcess.expr.Value;




@@ -40,4 +42,8 @@ public abstract class ColEvalContext extends BaseEvalContext
protected String withErrorContext(String msg) {
return _col.withErrorContext(msg);
}

protected Value toValue(Object val) {
return toValue(val, _col.getType());
}
}

+ 1
- 1
src/main/java/com/healthmarketscience/jackcess/impl/ColValidatorEvalContext.java View File

@@ -65,7 +65,7 @@ public class ColValidatorEvalContext extends ColEvalContext

@Override
public Value getThisColumnValue() {
return toValue(_val, getCol().getType());
return toValue(_val);
}

@Override

+ 4
- 3
src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java View File

@@ -29,6 +29,7 @@ import com.healthmarketscience.jackcess.expr.EvalContext;
import com.healthmarketscience.jackcess.expr.EvalException;
import com.healthmarketscience.jackcess.expr.Function;
import com.healthmarketscience.jackcess.expr.FunctionLookup;
import com.healthmarketscience.jackcess.expr.LocaleContext;
import com.healthmarketscience.jackcess.expr.NumericConfig;
import com.healthmarketscience.jackcess.expr.TemporalConfig;
import com.healthmarketscience.jackcess.expr.Value;
@@ -473,11 +474,11 @@ public class DefaultFunctions
}
});

private static boolean stringIsNumeric(EvalContext ctx, Value param) {
private static boolean stringIsNumeric(LocaleContext ctx, Value param) {
return (maybeGetAsBigDecimal(ctx, param) != null);
}

static BigDecimal maybeGetAsBigDecimal(EvalContext ctx, Value param) {
static BigDecimal maybeGetAsBigDecimal(LocaleContext ctx, Value param) {
try {
return param.getAsBigDecimal(ctx);
} catch(EvalException ignored) {
@@ -490,7 +491,7 @@ public class DefaultFunctions
return (maybeGetAsDateTimeValue(ctx, param) != null);
}

static Value maybeGetAsDateTimeValue(EvalContext ctx, Value param) {
static Value maybeGetAsDateTimeValue(LocaleContext ctx, Value param) {
try {
// see if we can coerce to date/time
return param.getAsDateTimeValue(ctx);

+ 2
- 1
src/main/java/com/healthmarketscience/jackcess/impl/expr/ExpressionTokenizer.java View File

@@ -38,6 +38,7 @@ import com.healthmarketscience.jackcess.expr.ParseException;
import com.healthmarketscience.jackcess.expr.TemporalConfig;
import com.healthmarketscience.jackcess.expr.Value;
import com.healthmarketscience.jackcess.impl.ColumnImpl;
import org.apache.commons.lang3.StringUtils;


/**
@@ -89,7 +90,7 @@ class ExpressionTokenizer
exprStr = exprStr.trim();
}

if((exprStr == null) || (exprStr.length() == 0)) {
if(StringUtils.isEmpty(exprStr)) {
return null;
}


+ 85
- 36
src/main/java/com/healthmarketscience/jackcess/impl/expr/FormatUtil.java View File

@@ -41,6 +41,7 @@ import com.healthmarketscience.jackcess.expr.EvalException;
import com.healthmarketscience.jackcess.expr.NumericConfig;
import com.healthmarketscience.jackcess.expr.TemporalConfig;
import com.healthmarketscience.jackcess.expr.Value;
import org.apache.commons.lang3.StringUtils;
import static com.healthmarketscience.jackcess.impl.expr.ExpressionTokenizer.ExprBuf;

/**
@@ -114,40 +115,41 @@ public class FormatUtil
private static final Map<String,Fmt> PREDEF_FMTS = new HashMap<String,Fmt>();

static {
PREDEF_FMTS.put("General Date", args -> ValueSupport.toValue(
putPredefFormat("General Date", args -> ValueSupport.toValue(
args.coerceToDateTimeValue().getAsString()));
PREDEF_FMTS.put("Long Date",
putPredefFormat("Long Date",
new PredefDateFmt(TemporalConfig.Type.LONG_DATE));
PREDEF_FMTS.put("Medium Date",
putPredefFormat("Medium Date",
new PredefDateFmt(TemporalConfig.Type.MEDIUM_DATE));
PREDEF_FMTS.put("Short Date",
putPredefFormat("Short Date",
new PredefDateFmt(TemporalConfig.Type.SHORT_DATE));
PREDEF_FMTS.put("Long Time",
putPredefFormat("Long Time",
new PredefDateFmt(TemporalConfig.Type.LONG_TIME));
PREDEF_FMTS.put("Medium Time",
putPredefFormat("Medium Time",
new PredefDateFmt(TemporalConfig.Type.MEDIUM_TIME));
PREDEF_FMTS.put("Short Time",
putPredefFormat("Short Time",
new PredefDateFmt(TemporalConfig.Type.SHORT_TIME));

PREDEF_FMTS.put("General Number", args -> ValueSupport.toValue(
putPredefFormat("General Number", args -> ValueSupport.toValue(
args.coerceToNumberValue().getAsString()));
PREDEF_FMTS.put("Currency",
putPredefFormat("Currency",
new PredefNumberFmt(NumericConfig.Type.CURRENCY));
PREDEF_FMTS.put("Euro", new PredefNumberFmt(NumericConfig.Type.EURO));
PREDEF_FMTS.put("Fixed",
putPredefFormat("Euro", new PredefNumberFmt(NumericConfig.Type.EURO));
putPredefFormat("Fixed",
new PredefNumberFmt(NumericConfig.Type.FIXED));
PREDEF_FMTS.put("Standard",
putPredefFormat("Standard",
new PredefNumberFmt(NumericConfig.Type.STANDARD));
PREDEF_FMTS.put("Percent",
putPredefFormat("Percent",
new PredefNumberFmt(NumericConfig.Type.PERCENT));
PREDEF_FMTS.put("Scientific", new ScientificPredefNumberFmt());
putPredefFormat("Scientific", new ScientificPredefNumberFmt());

PREDEF_FMTS.put("True/False", new PredefBoolFmt("True", "False"));
PREDEF_FMTS.put("Yes/No", new PredefBoolFmt("Yes", "No"));
PREDEF_FMTS.put("On/Off", new PredefBoolFmt("On", "Off"));
putPredefFormat("True/False", new PredefBoolFmt("True", "False"));
putPredefFormat("Yes/No", new PredefBoolFmt("Yes", "No"));
putPredefFormat("On/Off", new PredefBoolFmt("On", "Off"));
}

private static final Fmt NULL_FMT = args -> ValueSupport.EMPTY_STR_VAL;
private static final Fmt DUMMY_FMT = args -> args.getNonNullExpr();

private static final char QUOTE_CHAR = '"';
private static final char ESCAPE_CHAR = '\\';
@@ -282,6 +284,15 @@ public class FormatUtil
_firstWeekType = firstWeekType;
}

public Args setExpr(Value expr) {
_expr = expr;
return this;
}

public Value getNonNullExpr() {
return (_expr.isNull() ? ValueSupport.EMPTY_STR_VAL : _expr);
}

public boolean isNullOrEmptyString() {
return(_expr.isNull() ||
// only a string value could ever be an empty string
@@ -385,37 +396,67 @@ public class FormatUtil
public String getAsString() {
return _expr.getAsString(_ctx);
}

public Value format(Fmt fmt) {
Value origExpr = _expr;
try {
return fmt.format(this);
} catch(EvalException ee) {
// values which cannot be formatted as the target type are just
// returned "as is"
return origExpr;
}
}
}

private FormatUtil() {}

/**
* Utility for leveraging format support outside of expression evaluation.
*/
public static class StandaloneFormatter
{
private final Fmt _fmt;
private final Args _args;

private StandaloneFormatter(Fmt fmt, Args args) {
_fmt = fmt;
_args = args;
}

public Value format(Value expr) {
return _args.setExpr(expr).format(_fmt);
}
}

public static Value format(EvalContext ctx, Value expr, String fmtStr,
int firstDay, int firstWeekType) {
Args args = new Args(ctx, expr, firstDay, firstWeekType);
return args.format(createFormat(args, fmtStr));
}

try {
Args args = new Args(ctx, expr, firstDay, firstWeekType);
public static StandaloneFormatter createStandaloneFormatter(
EvalContext ctx, String fmtStr, int firstDay, int firstWeekType) {
Args args = new Args(ctx, null, firstDay, firstWeekType);
Fmt fmt = createFormat(args, fmtStr);
return new StandaloneFormatter(fmt, args);
}

Fmt predefFmt = PREDEF_FMTS.get(fmtStr);
if(predefFmt != null) {
if(args.isNullOrEmptyString()) {
// predefined formats return empty string for null
return ValueSupport.EMPTY_STR_VAL;
}
return predefFmt.format(args);
}
private static Fmt createFormat(Args args, String fmtStr) {
Fmt predefFmt = PREDEF_FMTS.get(fmtStr);
if(predefFmt != null) {
return predefFmt;
}

// TODO implement caching for custom formats? put into Bindings. use
// special "cache" prefix to know which caches to clear when evalconfig
// is altered (could also cache other Format* functions)
if(StringUtils.isEmpty(fmtStr)) {
return DUMMY_FMT;
}

return parseCustomFormat(fmtStr, args).format(args);
// TODO implement caching for custom formats? put into Bindings. use
// special "cache" prefix to know which caches to clear when evalconfig
// is altered (could also cache other Format* functions)

} catch(EvalException ee) {
// values which cannot be formatted as the target type are just
// returned "as is"
return expr;
}
return parseCustomFormat(fmtStr, args);
}

private static Fmt parseCustomFormat(String fmtStr, Args args) {
@@ -1178,6 +1219,14 @@ public class FormatUtil
}
}

private static void putPredefFormat(String key, Fmt fmt) {
// predefined formats return empty string for null
Fmt wrapFmt = args -> (args.isNullOrEmptyString() ?
ValueSupport.EMPTY_STR_VAL :
fmt.format(args));
PREDEF_FMTS.put(key, wrapFmt);
}

private static final class PredefDateFmt implements Fmt
{
private final TemporalConfig.Type _type;

+ 150
- 0
src/main/java/com/healthmarketscience/jackcess/util/ColumnFormatter.java View File

@@ -0,0 +1,150 @@
/*
Copyright (c) 2019 James Ahlborn

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.
*/

package com.healthmarketscience.jackcess.util;

import java.io.IOException;
import java.util.Map;

import com.healthmarketscience.jackcess.Column;
import com.healthmarketscience.jackcess.PropertyMap;
import com.healthmarketscience.jackcess.expr.EvalConfig;
import com.healthmarketscience.jackcess.expr.EvalException;
import com.healthmarketscience.jackcess.impl.ColEvalContext;
import com.healthmarketscience.jackcess.impl.ColumnImpl;
import com.healthmarketscience.jackcess.impl.expr.FormatUtil;
import org.apache.commons.lang3.StringUtils;

/**
* Utility for applying Column formatting to column values for display. This
* utility loads the "Format" property from the given column and builds an
* appropriate formatter (essentially leveraging the internals of the
* expression execution engine's support for the "Format()" function). Since
* formats leverage the expression evaluation engine, the underlying
* Database's {@link EvalConfig} can be used to alter how this utility formats
* values. Note, formatted values may be suitable for <i>display only</i>
* (i.e. a formatted value may not be accepted as an input value to a Table
* add/update method).
*
* @author James Ahlborn
* @usage _general_class_
*/
public class ColumnFormatter
{
private final ColumnImpl _col;
private final FormatEvalContext _ctx;
private String _fmtStr;
private FormatUtil.StandaloneFormatter _fmt;

public ColumnFormatter(Column col) throws IOException {
_col = (ColumnImpl)col;
_ctx = new FormatEvalContext(_col);
reload();
}

/**
* Returns the currently loaded "Format" property for this formatter, may be
* {@code null}.
*/
public String getFormatString() {
return _fmtStr;
}

/**
* Sets the given format string as the "Format" property for the underlying
* Column and reloads this formatter.
*
* @param fmtStr the new format string. may be {@code null}, in which case
* the "Format" property is removed from the underlying Column
*/
public void setFormatString(String fmtStr) throws IOException {
PropertyMap props = _col.getProperties();
if(!StringUtils.isEmpty(fmtStr)) {
props.put(PropertyMap.FORMAT_PROP, fmtStr);
} else {
props.remove(PropertyMap.FORMAT_PROP);
}
props.save();
reload();
}

/**
* Formats the given value according to the format currently defined for the
* underlying Column.
*
* @param val a valid input value for the DataType of the underlying Column
* (i.e. a value which could be passed to a Table add/update
* method for this Column). may be {@code null}
*
* @return the formatted result, always non-{@code null}
*/
public String format(Object val) {
return _ctx.format(val);
}

/**
* Convenience method for retrieving the appropriate Column value from the
* given row array and formatting it.
*
* @return the formatted result, always non-{@code null}
*/
public String getRowValue(Object[] rowArray) {
return format(_col.getRowValue(rowArray));
}

/**
* Convenience method for retrieving the appropriate Column value from the
* given row map and formatting it.
*
* @return the formatted result, always non-{@code null}
*/
public String getRowValue(Map<String,?> rowMap) {
return format(_col.getRowValue(rowMap));
}

/**
* If the properties for the underlying Column have been modified directly
* (or the EvalConfig for the underlying Database has been modified), this
* method may be called to reload the format for the underlying Column.
*/
public final void reload() throws IOException {
_fmt = null;
_fmtStr = null;

_fmtStr = (String)_col.getProperties().getValue(PropertyMap.FORMAT_PROP);
_fmt = FormatUtil.createStandaloneFormatter(_ctx, _fmtStr, 1, 1);
}

/**
* Utility class to provide an EvalContext for the expression evaluation
* engine format support.
*/
private class FormatEvalContext extends ColEvalContext
{
private FormatEvalContext(ColumnImpl col) {
super(col);
}

public String format(Object val) {
try {
return _fmt.format(toValue(val)).getAsString(this);
} catch(EvalException ee) {
// invalid values for a given format result in returning the value as is
return val.toString();
}
}
}
}

+ 1
- 1
src/main/java/com/healthmarketscience/jackcess/util/ColumnValidator.java View File

@@ -27,7 +27,7 @@ import com.healthmarketscience.jackcess.Column;
*
* @author James Ahlborn
*/
public interface ColumnValidator
public interface ColumnValidator
{
/**
* Validates and/or manipulates the given potential new value for the given

+ 9
- 3
src/test/java/com/healthmarketscience/jackcess/TestUtil.java View File

@@ -117,18 +117,24 @@ public class TestUtil
public static Database create(FileFormat fileFormat, boolean keep)
throws Exception
{
return create(fileFormat, keep, false);
return create(fileFormat, keep, true);
}

public static Database createMem(FileFormat fileFormat) throws Exception {
return create(fileFormat, false, true);
return create(fileFormat);
}

public static Database createFile(FileFormat fileFormat) throws Exception {
return create(fileFormat, false, false);
}

private static Database create(FileFormat fileFormat, boolean keep,
boolean inMem)
throws Exception
{
FileChannel channel = (inMem ? MemFileChannel.newChannel() : null);

FileChannel channel = ((inMem && !keep) ? MemFileChannel.newChannel() :
null);

if (fileFormat == FileFormat.GENERIC_JET4) {
// while we don't support creating GENERIC_JET4 as a jackcess feature,

+ 19
- 19
src/test/java/com/healthmarketscience/jackcess/impl/CodecHandlerTest.java View File

@@ -72,7 +72,7 @@ public class CodecHandlerTest extends TestCase
private static void doTestCodecHandler(boolean simple) throws Exception
{
for(Database.FileFormat ff : SUPPORTED_FILEFORMATS) {
Database db = TestUtil.create(ff);
Database db = TestUtil.createFile(ff);
int pageSize = ((DatabaseImpl)db).getFormat().PAGE_SIZE;
File dbFile = db.getFile();
db.close();
@@ -163,7 +163,7 @@ public class CodecHandlerTest extends TestCase
assertEquals(valuePrefix.length() + 100, value.length());
}

private static void encodeFile(File dbFile, int pageSize, boolean simple)
private static void encodeFile(File dbFile, int pageSize, boolean simple)
throws Exception
{
long dbLen = dbFile.length();
@@ -174,7 +174,7 @@ public class CodecHandlerTest extends TestCase

bb.clear();
fileChannel.read(bb, offset);
int pageNumber = (int)(offset / pageSize);
if(simple) {
simpleEncode(bb.array(), bb.array(), pageNumber, 0, pageSize);
@@ -221,12 +221,12 @@ public class CodecHandlerTest extends TestCase
}
}

private static final class SimpleCodecHandler implements CodecHandler
private static final class SimpleCodecHandler implements CodecHandler
{
private final TempBufferHolder _bufH = TempBufferHolder.newHolder(
TempBufferHolder.Type.HARD, true);
private final PageChannel _channel;
private SimpleCodecHandler(PageChannel channel) {
_channel = channel;
}
@@ -238,37 +238,37 @@ public class CodecHandlerTest extends TestCase
public boolean canDecodeInline() {
return true;
}
public void decodePage(ByteBuffer inPage, ByteBuffer outPage,
int pageNumber)
throws IOException
int pageNumber)
throws IOException
{
byte[] arr = inPage.array();
simpleDecode(arr, arr, pageNumber);
}

public ByteBuffer encodePage(ByteBuffer page, int pageNumber,
int pageOffset)
int pageOffset)
throws IOException
{
ByteBuffer bb = _bufH.getPageBuffer(_channel);
bb.clear();
simpleEncode(page.array(), bb.array(), pageNumber, pageOffset,
simpleEncode(page.array(), bb.array(), pageNumber, pageOffset,
page.limit());
return bb;
}
}

private static final class FullCodecHandler implements CodecHandler
private static final class FullCodecHandler implements CodecHandler
{
private final TempBufferHolder _bufH = TempBufferHolder.newHolder(
TempBufferHolder.Type.HARD, true);
private final PageChannel _channel;
private FullCodecHandler(PageChannel channel) {
_channel = channel;
}
public boolean canEncodePartialPage() {
return false;
}
@@ -276,17 +276,17 @@ public class CodecHandlerTest extends TestCase
public boolean canDecodeInline() {
return true;
}
public void decodePage(ByteBuffer inPage, ByteBuffer outPage,
int pageNumber)
throws IOException
public void decodePage(ByteBuffer inPage, ByteBuffer outPage,
int pageNumber)
throws IOException
{
byte[] arr = inPage.array();
fullDecode(arr, arr, pageNumber);
}

public ByteBuffer encodePage(ByteBuffer page, int pageNumber,
int pageOffset)
public ByteBuffer encodePage(ByteBuffer page, int pageNumber,
int pageOffset)
throws IOException
{
assertEquals(0, pageOffset);

+ 114
- 0
src/test/java/com/healthmarketscience/jackcess/util/ColumnFormatterTest.java View File

@@ -0,0 +1,114 @@
/*
Copyright (c) 2019 James Ahlborn

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.
*/

package com.healthmarketscience.jackcess.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import com.healthmarketscience.jackcess.Column;
import com.healthmarketscience.jackcess.ColumnBuilder;
import com.healthmarketscience.jackcess.CursorBuilder;
import com.healthmarketscience.jackcess.DataType;
import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.Database.FileFormat;
import com.healthmarketscience.jackcess.IndexCursor;
import com.healthmarketscience.jackcess.PropertyMap;
import com.healthmarketscience.jackcess.Row;
import com.healthmarketscience.jackcess.Table;
import com.healthmarketscience.jackcess.TableBuilder;
import junit.framework.TestCase;
import static com.healthmarketscience.jackcess.TestUtil.*;
import static com.healthmarketscience.jackcess.impl.JetFormatTest.*;

/**
*
* @author James Ahlborn
*/
public class ColumnFormatterTest extends TestCase
{

public void testFormat() throws Exception {

for (final FileFormat fileFormat : SUPPORTED_FILEFORMATS) {
Database db = create(fileFormat);
db.setEvaluateExpressions(true);

Table t = new TableBuilder("test")
.addColumn(new ColumnBuilder("id", DataType.LONG).setAutoNumber(true))
.addColumn(new ColumnBuilder("data1", DataType.TEXT)
.putProperty(PropertyMap.FORMAT_PROP,
">@@\\x\\x"))
.addColumn(new ColumnBuilder("data2", DataType.LONG)
.putProperty(PropertyMap.FORMAT_PROP,
"#.#E+0"))
.addColumn(new ColumnBuilder("data3", DataType.MONEY)
.putProperty(PropertyMap.FORMAT_PROP,
"Currency"))
.toTable(db);

ColumnFormatter d1Fmt = new ColumnFormatter(t.getColumn("data1"));
ColumnFormatter d2Fmt = new ColumnFormatter(t.getColumn("data2"));
ColumnFormatter d3Fmt = new ColumnFormatter(t.getColumn("data3"));

t.addRow(Column.AUTO_NUMBER, "foobar", 37, "0.03");
t.addRow(Column.AUTO_NUMBER, "37", 4500, 4500);
t.addRow(Column.AUTO_NUMBER, "foobarbaz", -37, "-37.13");
t.addRow(Column.AUTO_NUMBER, null, null, null);

List<String> found = new ArrayList<>();
for(Row r : t) {
found.add(d1Fmt.getRowValue(r));
found.add(d2Fmt.getRowValue(r));
found.add(d3Fmt.getRowValue(r));
}

assertEquals(Arrays.asList(
"FOxxOBAR", "3.7E+1", "$0.03",
"37xx", "4.5E+3", "$4,500.00",
"FOxxOBARBAZ", "-3.7E+1", "($37.13)",
"", "", ""),
found);

d1Fmt.setFormatString("Scientific");
d2Fmt.setFormatString(null);
d3Fmt.setFormatString("General Date");

assertEquals("Scientific", t.getColumn("data1").getProperties()
.getValue(PropertyMap.FORMAT_PROP));
assertEquals("General Date", t.getColumn("data3").getProperties()
.getValue(PropertyMap.FORMAT_PROP));

found = new ArrayList<>();
for(Row r : t) {
found.add(d1Fmt.getRowValue(r));
found.add(d2Fmt.getRowValue(r));
found.add(d3Fmt.getRowValue(r));
}

assertEquals(Arrays.asList(
"foobar", "37", "12:43:12 AM",
"3.70E+1", "4500", "4/26/1912",
"foobarbaz", "-37", "11/23/1899 3:07:12 AM",
"", "", ""),
found);

db.close();
}
}
}

Loading…
Cancel
Save