Skip to content

Commit 2596c10

Browse files
committed
Update CSVEncoder.
1 parent 0b7b07a commit 2596c10

File tree

3 files changed

+67
-92
lines changed

3 files changed

+67
-92
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
subprojects {
1616
group = 'org.httprpc'
17-
version = '5.0.1'
17+
version = '5.1'
1818

1919
repositories {
2020
mavenCentral()

kilo-client/src/main/java/org/httprpc/kilo/io/CSVEncoder.java

Lines changed: 30 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818

1919
import java.io.IOException;
2020
import java.io.Writer;
21-
import java.text.Format;
22-
import java.util.Date;
21+
import java.util.HashMap;
2322
import java.util.List;
2423
import java.util.Map;
2524
import java.util.ResourceBundle;
25+
import java.util.function.Function;
2626

2727
import static org.httprpc.kilo.util.Optionals.*;
2828

@@ -32,9 +32,7 @@
3232
public class CSVEncoder extends Encoder<Iterable<?>> {
3333
private List<String> keys;
3434

35-
private Format numberFormat = null;
36-
private Format booleanFormat = null;
37-
private Format dateFormat = null;
35+
private Map<Class<?>, Function<Object, String>> formatters = new HashMap<>();
3836

3937
private ResourceBundle resourceBundle = null;
4038

@@ -55,63 +53,21 @@ public CSVEncoder(List<String> keys) {
5553
}
5654

5755
/**
58-
* Returns the number format.
56+
* Associates a formatter with a type.
5957
*
60-
* @return
61-
* The number format, or {@code null} if a number format has not been set.
62-
*/
63-
public Format getNumberFormat() {
64-
return numberFormat;
65-
}
66-
67-
/**
68-
* Sets the number format.
69-
*
70-
* @param numberFormat
71-
* The number format, or {@code null} for no number format.
72-
*/
73-
public void setNumberFormat(Format numberFormat) {
74-
this.numberFormat = numberFormat;
75-
}
76-
77-
/**
78-
* Returns the boolean format.
58+
* @param type
59+
* The type to format.
7960
*
80-
* @return
81-
* The boolean format, or {@code null} if a boolean format has not been set.
82-
*/
83-
public Format getBooleanFormat() {
84-
return booleanFormat;
85-
}
86-
87-
/**
88-
* Sets the boolean format.
89-
*
90-
* @param booleanFormat
91-
* The boolean format, or {@code null} for no boolean format.
61+
* @param formatter
62+
* The formatter to apply to instances of the given type.
9263
*/
93-
public void setBooleanFormat(Format booleanFormat) {
94-
this.booleanFormat = booleanFormat;
95-
}
96-
97-
/**
98-
* Returns the date format.
99-
*
100-
* @return
101-
* The date format, or {@code null} if a date format has not been set.
102-
*/
103-
public Format getDateFormat() {
104-
return dateFormat;
105-
}
64+
@SuppressWarnings("unchecked")
65+
public <T> void format(Class<T> type, Function<? super T, String> formatter) {
66+
if (type == null || formatter == null) {
67+
throw new IllegalArgumentException();
68+
}
10669

107-
/**
108-
* Sets the date format.
109-
*
110-
* @param dateFormat
111-
* The date format, or {@code null} for no date format.
112-
*/
113-
public void setDateFormat(Format dateFormat) {
114-
this.dateFormat = dateFormat;
70+
formatters.put(type, (Function<Object, String>)formatter);
11571
}
11672

11773
/**
@@ -189,11 +145,24 @@ private void encode(Iterable<?> rows, Writer writer) throws IOException {
189145
var value = map.get(key);
190146

191147
if (value != null) {
148+
var type = value.getClass();
149+
150+
while (type != null) {
151+
var formatter = formatters.get(type);
152+
153+
if (formatter != null) {
154+
value = formatter.apply(value);
155+
156+
break;
157+
}
158+
159+
type = type.getSuperclass();
160+
}
161+
192162
switch (value) {
193163
case CharSequence text -> encode(text, writer);
194164
case Number number -> encode(number, writer);
195165
case Boolean flag -> encode(flag, writer);
196-
case Date date -> encode(date, writer);
197166
default -> encode(value.toString(), writer);
198167
}
199168
}
@@ -222,26 +191,10 @@ private void encode(CharSequence text, Writer writer) throws IOException {
222191
}
223192

224193
private void encode(Number number, Writer writer) throws IOException {
225-
if (numberFormat != null) {
226-
encode(numberFormat.format(number), writer);
227-
} else {
228-
writer.write(number.toString());
229-
}
194+
writer.write(number.toString());
230195
}
231196

232197
private void encode(Boolean flag, Writer writer) throws IOException {
233-
if (booleanFormat != null) {
234-
encode(booleanFormat.format(flag), writer);
235-
} else {
236-
writer.write(flag.toString());
237-
}
238-
}
239-
240-
private void encode(Date date, Writer writer) throws IOException {
241-
if (dateFormat != null) {
242-
encode(dateFormat.format(date), writer);
243-
} else {
244-
writer.write(String.valueOf(date.getTime()));
245-
}
198+
writer.write(flag.toString());
246199
}
247200
}

kilo-client/src/test/java/org/httprpc/kilo/io/CSVEncoderTest.java

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
import java.text.Format;
2424
import java.text.NumberFormat;
2525
import java.text.ParsePosition;
26+
import java.time.LocalDateTime;
27+
import java.time.format.DateTimeFormatter;
28+
import java.time.format.FormatStyle;
2629
import java.util.Date;
2730
import java.util.ResourceBundle;
2831

@@ -61,8 +64,7 @@ public void testMaps() throws IOException {
6164
entry("a", "A,B,\"C\" "),
6265
entry("b", 1),
6366
entry("c", 2.0),
64-
entry("d", true),
65-
entry("e", new Date(0))
67+
entry("d", true)
6668
),
6769
mapOf(
6870
entry("a", " D\r\nÉ\r\nF\r\n"),
@@ -80,7 +82,7 @@ public void testMaps() throws IOException {
8082
csvEncoder.write(rows, writer);
8183

8284
var expected = "\"a\",\"b\",\"c\",\"D\",\"É\"\r\n"
83-
+ "\"A,B,\"\"C\"\" \",1,2.0,true,0\r\n"
85+
+ "\"A,B,\"\"C\"\" \",1,2.0,true,\r\n"
8486
+ "\" D\r\nÉ\r\nF\r\n\",2,4.0,,\r\n";
8587

8688
assertEquals(expected, writer.toString());
@@ -108,21 +110,35 @@ public void testBeans() throws IOException {
108110

109111
@Test
110112
public void testFormats() throws IOException {
113+
var number = 1000.0;
114+
var integer = 1000;
115+
var flag = true;
116+
var date = new Date();
117+
var localDateTime = LocalDateTime.now();
118+
111119
var rows = listOf(
112120
mapOf(
113-
entry("a", 1),
114-
entry("b", true),
115-
entry("c", new Date(0))
121+
entry("a", number),
122+
entry("b", integer),
123+
entry("c", flag),
124+
entry("d", date),
125+
entry("e", localDateTime)
116126
)
117127
);
118128

119-
var csvEncoder = new CSVEncoder(listOf("a", "b", "c"));
129+
var csvEncoder = new CSVEncoder(listOf("a", "b", "c", "d", "e"));
120130

121131
var numberFormat = NumberFormat.getNumberInstance();
122132

123133
numberFormat.setMinimumFractionDigits(2);
124134

125-
csvEncoder.setNumberFormat(numberFormat);
135+
csvEncoder.format(Number.class, numberFormat::format);
136+
137+
var integerFormat = NumberFormat.getNumberInstance();
138+
139+
integerFormat.setGroupingUsed(false);
140+
141+
csvEncoder.format(Integer.class, integerFormat::format);
126142

127143
var booleanFormat = new Format() {
128144
@Override
@@ -136,20 +152,26 @@ public Object parseObject(String source, ParsePosition pos) {
136152
}
137153
};
138154

139-
csvEncoder.setBooleanFormat(booleanFormat);
155+
csvEncoder.format(Boolean.class, booleanFormat::format);
140156

141157
var dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
142158

143-
csvEncoder.setDateFormat(dateFormat);
159+
csvEncoder.format(Date.class, dateFormat::format);
160+
161+
var dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT, FormatStyle.SHORT);
162+
163+
csvEncoder.format(LocalDateTime.class, dateTimeFormatter::format);
144164

145165
var writer = new StringWriter();
146166

147167
csvEncoder.write(rows, writer);
148168

149-
var expected = "\"a\",\"b\",\"c\"\r\n"
150-
+ "\"" + numberFormat.format(1) + "\","
151-
+ "\"" + booleanFormat.format(true) + "\","
152-
+ "\"" + dateFormat.format(new Date(0)) + "\"\r\n";
169+
var expected = "\"a\",\"b\",\"c\",\"d\",\"e\"\r\n"
170+
+ "\"" + numberFormat.format(number) + "\","
171+
+ "\"" + integerFormat.format(integer) + "\","
172+
+ "\"" + booleanFormat.format(flag) + "\","
173+
+ "\"" + dateFormat.format(date) + "\","
174+
+ "\"" + dateTimeFormatter.format(localDateTime) + "\"\r\n";
153175

154176
assertEquals(expected, writer.toString());
155177
}

0 commit comments

Comments
 (0)