embulk-filter-typecast 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e8a2482d0bd6fc6109bb8763f9a1f9db6b0733db
4
- data.tar.gz: b80c4d01e823e3a4b59594002277fc78e1ee0ef9
3
+ metadata.gz: 0ced2804053187863055f59aa064418cd0b8d7aa
4
+ data.tar.gz: 447a4328482d178a479b404bfb7af62c61a2c1f3
5
5
  SHA512:
6
- metadata.gz: 7473b57b158d8936e14015358dcd21d3bfe852f0b7c33de10da4ad38aa4553b3ddf39e5b41c9ed11df32713c42a33506aba22820b2236590ab124035a1056783
7
- data.tar.gz: 354bf8ab52c2ee5ba124af046abea9e311213c4ebaa03991f432504cc87094a0e1d4815c3c94434ee843de836f6e2146331540fd23b286071c000011bb64c55a
6
+ metadata.gz: 2833a31678457b155864532d95de1af40594ffa7d5ffee4d489bcc4d993b444dacd18adbbcac444b2ad6b2fe85b2fbb837fa559abbdadd13010a98009894ec1d
7
+ data.tar.gz: f668410813b7109c96a6277b6ecd0b576334f74261f2c5ce5d941ddc0b6b6e2b4e84d4daeedde49b3a86abc140cc99481fa7a5a0e0b330a9494efccd0cd5eaaf
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # 0.1.3 (2016-05-19)
2
+
3
+ Enhancements:
4
+
5
+ * Support JSONPath array wildcard
6
+
1
7
  # 0.1.2 (2016-04-28)
2
8
 
3
9
  Enhancements:
data/README.md CHANGED
@@ -19,6 +19,18 @@ A filter plugin for Embulk to cast column type.
19
19
 
20
20
  See [example.csv](./example/example.csv) and [example.yml](./example/example.yml).
21
21
 
22
+ ## JSONPath (like) name
23
+
24
+ For `type: json` column, you can specify [JSONPath](http://goessner.net/articles/JsonPath/) for column's name as:
25
+
26
+ ```
27
+ $.payload.key1
28
+ $.payload.array[0]
29
+ $.payload.array[*]
30
+ ```
31
+
32
+ NOTE: JSONPath syntax is not fully supported
33
+
22
34
  ## ToDo
23
35
 
24
36
  * Write test
data/build.gradle CHANGED
@@ -13,7 +13,7 @@ configurations {
13
13
  provided
14
14
  }
15
15
 
16
- version = "0.1.2"
16
+ version = "0.1.3"
17
17
  sourceCompatibility = 1.7
18
18
  targetCompatibility = 1.7
19
19
 
data/example/empty.yml ADDED
@@ -0,0 +1,24 @@
1
+ in:
2
+ type: file
3
+ path_prefix: example/example.csv
4
+ parser:
5
+ type: csv
6
+ charset: UTF-8
7
+ newline: CRLF
8
+ null_string: 'NULL'
9
+ skip_header_lines: 1
10
+ comment_line_marker: '#'
11
+ columns:
12
+ - {name: timestamp, type: timestamp, format: "%Y-%m-%d %H:%M:%S.%N", timezone: "+09:00"}
13
+ - {name: "null", type: string}
14
+ - {name: long, type: long}
15
+ - {name: string, type: string}
16
+ - {name: double, type: double}
17
+ - {name: json1, type: json}
18
+ - {name: json2, type: json}
19
+ - {name: ignore, type: timestamp, format: "%Y-%m-%d", timezone: "+09:00"}
20
+ - {name: boolean, type: boolean}
21
+ filters:
22
+ - type: typecast
23
+ out:
24
+ type: "null"
data/example/example.csv CHANGED
@@ -1,11 +1,11 @@
1
- timestamp,null,long,string,double,json1,json2,boolean
2
- 2015-07-13 00:00:00.100000,,90,l6lTsvxd,903.4,{"string":"0"},{"long":0},true
3
- 2015-07-13 00:00:00.100000,,91,XoALSEQg,394.5,{"string":"1"},{"long":1},true
4
- 2015-07-13 00:00:00.100000,,92,0hgDRI_m,810.9,{"string":"2"},{"long":2},true
5
- 2015-07-13 00:00:00.100000,,93,KjCRAc-A,477.4,{"string":"3"},{"long":3},true
6
- 2015-07-13 00:00:00.100000,,94,fyQVGlT8,725.3,{"string":"4"},{"long":4},true
7
- 2015-07-13 00:00:00.100000,,95,FpBYRPWK,316.6,{"string":"5"},{"long":5},false
8
- 2015-07-13 00:00:00.100000,,96,9ikvnUqp,369.5,{"string":"6"},{"long":6},false
9
- 2015-07-13 00:00:00.100000,,97,RRNYDAzK,506.5,{"string":"7"},{"long":7},false
10
- 2015-07-13 00:00:00.100000,,90,l6lTsvxd,903.4,{"string":"8"},{"long":8},false
11
- 2015-07-13 00:00:00.100000,,91,XoALSEQg,394.5,{"string":"9"},{"long":9},false
1
+ timestamp,null,long,string,double,json1,json2,array_str,array_int,ignore,boolean
2
+ 2015-07-13 00:00:00.100000,,90,l6lTsvxd,903.4,{"string":"0"},{"long":0},["0"],[0],2015-07-13,true
3
+ 2015-07-13 00:00:00.100000,,91,XoALSEQg,394.5,{"string":"1"},{"long":1},["1"],[1],2015-07-13,true
4
+ 2015-07-13 00:00:00.100000,,92,0hgDRI_m,810.9,{"string":"2"},{"long":2},["2"],[2],2015-07-13,true
5
+ 2015-07-13 00:00:00.100000,,93,KjCRAc-A,477.4,{"string":"3"},{"long":3},["3"],[3],2015-07-13,true
6
+ 2015-07-13 00:00:00.100000,,94,fyQVGlT8,725.3,{"string":"4"},{"long":4},["4"],[4],2015-07-13,true
7
+ 2015-07-13 00:00:00.100000,,95,FpBYRPWK,316.6,{"string":"5"},{"long":5},["5"],[5],2015-07-13,false
8
+ 2015-07-13 00:00:00.100000,,96,9ikvnUqp,369.5,{"string":"6"},{"long":6},["6"],[6],2015-07-13,false
9
+ 2015-07-13 00:00:00.100000,,97,RRNYDAzK,506.5,{"string":"7"},{"long":7},["7"],[7],2015-07-13,false
10
+ 2015-07-13 00:00:00.100000,,90,l6lTsvxd,903.4,{"string":"8"},{"long":8},["8"],[8],2015-07-13,false
11
+ 2015-07-13 00:00:00.100000,,91,XoALSEQg,394.5,{"string":"9"},{"long":9},["9"],[9],2015-07-13,false
data/example/example.yml CHANGED
@@ -16,6 +16,9 @@ in:
16
16
  - {name: double, type: double}
17
17
  - {name: json1, type: json}
18
18
  - {name: json2, type: json}
19
+ - {name: array_str, type: json}
20
+ - {name: array_int, type: json}
21
+ - {name: ignore, type: timestamp, format: "%Y-%m-%d", timezone: "+09:00"}
19
22
  - {name: boolean, type: boolean}
20
23
  filters:
21
24
  - type: typecast
@@ -29,5 +32,7 @@ filters:
29
32
  - {name: boolean, type: string}
30
33
  - {name: "$.json1.string", type: string}
31
34
  - {name: "$.json2.long", type: string}
35
+ - {name: "$.array_str[0]", type: long}
36
+ - {name: "$.array_int[*]", type: string}
32
37
  out:
33
38
  type: "null"
data/settings.gradle ADDED
@@ -0,0 +1 @@
1
+ rootProject.name = 'embulk-filter-typecast'
@@ -1,11 +1,15 @@
1
1
  package org.embulk.filter.typecast;
2
2
 
3
- import org.embulk.filter.typecast.cast.*;
4
-
3
+ import org.embulk.filter.typecast.TypecastFilterPlugin.ColumnConfig;
5
4
  import org.embulk.filter.typecast.TypecastFilterPlugin.PluginTask;
6
5
 
6
+ import org.embulk.filter.typecast.cast.BooleanCast;
7
+ import org.embulk.filter.typecast.cast.DoubleCast;
8
+ import org.embulk.filter.typecast.cast.JsonCast;
9
+ import org.embulk.filter.typecast.cast.LongCast;
10
+ import org.embulk.filter.typecast.cast.StringCast;
11
+ import org.embulk.filter.typecast.cast.TimestampCast;
7
12
  import org.embulk.spi.Column;
8
- import org.embulk.spi.DataException;
9
13
  import org.embulk.spi.Exec;
10
14
  import org.embulk.spi.PageBuilder;
11
15
  import org.embulk.spi.PageReader;
@@ -13,11 +17,19 @@ import org.embulk.spi.Schema;
13
17
  import org.embulk.spi.time.Timestamp;
14
18
  import org.embulk.spi.time.TimestampFormatter;
15
19
  import org.embulk.spi.time.TimestampParser;
16
- import org.embulk.spi.type.*;
20
+ import org.embulk.spi.type.BooleanType;
21
+ import org.embulk.spi.type.DoubleType;
22
+ import org.embulk.spi.type.JsonType;
23
+ import org.embulk.spi.type.LongType;
24
+ import org.embulk.spi.type.StringType;
25
+ import org.embulk.spi.type.TimestampType;
26
+ import org.embulk.spi.type.Type;
27
+ import org.joda.time.DateTimeZone;
17
28
  import org.msgpack.value.Value;
18
29
 
19
30
  import org.slf4j.Logger;
20
31
 
32
+ import java.util.HashMap;
21
33
 
22
34
  class ColumnCaster
23
35
  {
@@ -27,6 +39,8 @@ class ColumnCaster
27
39
  private final Schema outputSchema;
28
40
  private final PageReader pageReader;
29
41
  private final PageBuilder pageBuilder;
42
+ private final HashMap<String, TimestampParser> timestampParserMap = new HashMap<>();
43
+ private final HashMap<String, TimestampFormatter> timestampFormatterMap = new HashMap<>();
30
44
  private final JsonVisitor jsonVisitor;
31
45
 
32
46
  ColumnCaster(TypecastFilterPlugin.PluginTask task, Schema inputSchema, Schema outputSchema,
@@ -37,24 +51,78 @@ class ColumnCaster
37
51
  this.outputSchema = outputSchema;
38
52
  this.pageReader = pageReader;
39
53
  this.pageBuilder = pageBuilder;
54
+
55
+ buildTimestampParserMap();
56
+ buildTimestampFormatterMap();
40
57
  this.jsonVisitor = new JsonVisitor(task, inputSchema, outputSchema);
41
58
  }
42
59
 
43
- public void setFromBoolean(Column outputColumn, boolean value) {
60
+ private void buildTimestampParserMap()
61
+ {
62
+ // columnName => TimestampParser
63
+ for (ColumnConfig columnConfig : task.getColumns()) {
64
+ if (columnConfig.getName().startsWith("$.")) {
65
+ continue; // type: json columns do not support type: timestamp
66
+ }
67
+ Column inputColumn = inputSchema.lookupColumn(columnConfig.getName());
68
+ if (inputColumn.getType() instanceof StringType && columnConfig.getType() instanceof TimestampType) {
69
+ TimestampParser parser = getTimestampParser(columnConfig, task);
70
+ this.timestampParserMap.put(columnConfig.getName(), parser);
71
+ }
72
+ }
73
+ }
74
+
75
+ private void buildTimestampFormatterMap()
76
+ {
77
+ // columnName => TimestampFormatter
78
+ for (ColumnConfig columnConfig : task.getColumns()) {
79
+ if (columnConfig.getName().startsWith("$.")) {
80
+ continue; // type: json columns do not have type: timestamp
81
+ }
82
+ Column inputColumn = inputSchema.lookupColumn(columnConfig.getName());
83
+ if (inputColumn.getType() instanceof TimestampType && columnConfig.getType() instanceof StringType) {
84
+ TimestampFormatter parser = getTimestampFormatter(columnConfig, task);
85
+ this.timestampFormatterMap.put(columnConfig.getName(), parser);
86
+ }
87
+ }
88
+ }
89
+
90
+ private TimestampParser getTimestampParser(ColumnConfig columnConfig, PluginTask task)
91
+ {
92
+ DateTimeZone timezone = columnConfig.getTimeZone().or(task.getDefaultTimeZone());
93
+ String format = columnConfig.getFormat().or(task.getDefaultTimestampFormat());
94
+ return new TimestampParser(task.getJRuby(), format, timezone);
95
+ }
96
+
97
+ private TimestampFormatter getTimestampFormatter(ColumnConfig columnConfig, PluginTask task)
98
+ {
99
+ String format = columnConfig.getFormat().or(task.getDefaultTimestampFormat());
100
+ DateTimeZone timezone = columnConfig.getTimeZone().or(task.getDefaultTimeZone());
101
+ return new TimestampFormatter(task.getJRuby(), format, timezone);
102
+ }
103
+
104
+ public void setFromBoolean(Column outputColumn, boolean value)
105
+ {
44
106
  Type outputType = outputColumn.getType();
45
107
  if (outputType instanceof BooleanType) {
46
108
  pageBuilder.setBoolean(outputColumn, BooleanCast.asBoolean(value));
47
- } else if (outputType instanceof LongType) {
109
+ }
110
+ else if (outputType instanceof LongType) {
48
111
  pageBuilder.setLong(outputColumn, BooleanCast.asLong(value));
49
- } else if (outputType instanceof DoubleType) {
112
+ }
113
+ else if (outputType instanceof DoubleType) {
50
114
  pageBuilder.setDouble(outputColumn, BooleanCast.asDouble(value));
51
- } else if (outputType instanceof StringType) {
115
+ }
116
+ else if (outputType instanceof StringType) {
52
117
  pageBuilder.setString(outputColumn, BooleanCast.asString(value));
53
- } else if (outputType instanceof TimestampType) {
118
+ }
119
+ else if (outputType instanceof TimestampType) {
54
120
  pageBuilder.setTimestamp(outputColumn, BooleanCast.asTimestamp(value));
55
- } else if (outputType instanceof JsonType) {
121
+ }
122
+ else if (outputType instanceof JsonType) {
56
123
  pageBuilder.setJson(outputColumn, BooleanCast.asJson(value));
57
- } else {
124
+ }
125
+ else {
58
126
  assert (false);
59
127
  }
60
128
  }
@@ -64,86 +132,107 @@ class ColumnCaster
64
132
  Type outputType = outputColumn.getType();
65
133
  if (outputType instanceof BooleanType) {
66
134
  pageBuilder.setBoolean(outputColumn, LongCast.asBoolean(value));
67
- } else if (outputType instanceof LongType) {
135
+ }
136
+ else if (outputType instanceof LongType) {
68
137
  pageBuilder.setLong(outputColumn, LongCast.asLong(value));
69
- } else if (outputType instanceof DoubleType) {
138
+ }
139
+ else if (outputType instanceof DoubleType) {
70
140
  pageBuilder.setDouble(outputColumn, LongCast.asDouble(value));
71
- } else if (outputType instanceof StringType) {
141
+ }
142
+ else if (outputType instanceof StringType) {
72
143
  pageBuilder.setString(outputColumn, LongCast.asString(value));
73
- } else if (outputType instanceof TimestampType) {
144
+ }
145
+ else if (outputType instanceof TimestampType) {
74
146
  pageBuilder.setTimestamp(outputColumn, LongCast.asTimestamp(value));
75
- } else if (outputType instanceof JsonType) {
147
+ }
148
+ else if (outputType instanceof JsonType) {
76
149
  pageBuilder.setJson(outputColumn, LongCast.asJson(value));
77
- } else {
78
- assert(false);
150
+ }
151
+ else {
152
+ assert false;
79
153
  }
80
154
  }
81
155
 
82
156
  public void setFromDouble(Column outputColumn, double value)
83
157
  {
84
- try {
85
- Type outputType = outputColumn.getType();
86
- if (outputType instanceof BooleanType) {
87
- pageBuilder.setBoolean(outputColumn, DoubleCast.asBoolean(value));
88
- } else if (outputType instanceof LongType) {
89
- pageBuilder.setLong(outputColumn, DoubleCast.asLong(value));
90
- } else if (outputType instanceof DoubleType) {
91
- pageBuilder.setDouble(outputColumn, DoubleCast.asDouble(value));
92
- } else if (outputType instanceof StringType) {
93
- pageBuilder.setString(outputColumn, DoubleCast.asString(value));
94
- } else if (outputType instanceof TimestampType) {
95
- pageBuilder.setTimestamp(outputColumn, DoubleCast.asTimestamp(value));
96
- } else if (outputType instanceof JsonType) {
97
- pageBuilder.setJson(outputColumn, DoubleCast.asJson(value));
98
- } else {
99
- assert (false);
100
- }
158
+ Type outputType = outputColumn.getType();
159
+ if (outputType instanceof BooleanType) {
160
+ pageBuilder.setBoolean(outputColumn, DoubleCast.asBoolean(value));
101
161
  }
102
- catch (DataException ex) {
103
-
162
+ else if (outputType instanceof LongType) {
163
+ pageBuilder.setLong(outputColumn, DoubleCast.asLong(value));
164
+ }
165
+ else if (outputType instanceof DoubleType) {
166
+ pageBuilder.setDouble(outputColumn, DoubleCast.asDouble(value));
167
+ }
168
+ else if (outputType instanceof StringType) {
169
+ pageBuilder.setString(outputColumn, DoubleCast.asString(value));
170
+ }
171
+ else if (outputType instanceof TimestampType) {
172
+ pageBuilder.setTimestamp(outputColumn, DoubleCast.asTimestamp(value));
173
+ }
174
+ else if (outputType instanceof JsonType) {
175
+ pageBuilder.setJson(outputColumn, DoubleCast.asJson(value));
176
+ }
177
+ else {
178
+ assert false;
104
179
  }
105
180
  }
106
181
 
107
- public void setFromString(Column outputColumn, String value, TimestampParser timestampParser)
182
+ public void setFromString(Column outputColumn, String value)
108
183
  {
109
184
  Type outputType = outputColumn.getType();
110
185
  if (outputType instanceof BooleanType) {
111
186
  pageBuilder.setBoolean(outputColumn, StringCast.asBoolean(value));
112
- } else if (outputType instanceof LongType) {
187
+ }
188
+ else if (outputType instanceof LongType) {
113
189
  pageBuilder.setLong(outputColumn, StringCast.asLong(value));
114
- } else if (outputType instanceof DoubleType) {
190
+ }
191
+ else if (outputType instanceof DoubleType) {
115
192
  pageBuilder.setDouble(outputColumn, StringCast.asDouble(value));
116
- } else if (outputType instanceof StringType) {
193
+ }
194
+ else if (outputType instanceof StringType) {
117
195
  pageBuilder.setString(outputColumn, StringCast.asString(value));
118
- } else if (outputType instanceof TimestampType) {
196
+ }
197
+ else if (outputType instanceof TimestampType) {
198
+ TimestampParser timestampParser = timestampParserMap.get(outputColumn.getName());
119
199
  pageBuilder.setTimestamp(outputColumn, StringCast.asTimestamp(value, timestampParser));
120
- } else if (outputType instanceof JsonType) {
200
+ }
201
+ else if (outputType instanceof JsonType) {
121
202
  Value jsonValue = StringCast.asJson(value);
122
203
  String jsonPath = new StringBuilder("$.").append(outputColumn.getName()).toString();
123
204
  Value castedValue = jsonVisitor.visit(jsonPath, jsonValue);
124
205
  pageBuilder.setJson(outputColumn, castedValue);
125
- } else {
126
- assert(false);
206
+ }
207
+ else {
208
+ assert false;
127
209
  }
128
210
  }
129
211
 
130
- public void setFromTimestamp(Column outputColumn, Timestamp value, TimestampFormatter timestampFormatter)
212
+ public void setFromTimestamp(Column outputColumn, Timestamp value)
131
213
  {
132
214
  Type outputType = outputColumn.getType();
133
215
  if (outputType instanceof BooleanType) {
134
216
  pageBuilder.setBoolean(outputColumn, TimestampCast.asBoolean(value));
135
- } else if (outputType instanceof LongType) {
217
+ }
218
+ else if (outputType instanceof LongType) {
136
219
  pageBuilder.setLong(outputColumn, TimestampCast.asLong(value));
137
- } else if (outputType instanceof DoubleType) {
220
+ }
221
+ else if (outputType instanceof DoubleType) {
138
222
  pageBuilder.setDouble(outputColumn, TimestampCast.asDouble(value));
139
- } else if (outputType instanceof StringType) {
223
+ }
224
+ else if (outputType instanceof StringType) {
225
+ TimestampFormatter timestampFormatter = timestampFormatterMap.get(outputColumn.getName());
140
226
  pageBuilder.setString(outputColumn, TimestampCast.asString(value, timestampFormatter));
141
- } else if (outputType instanceof TimestampType) {
227
+ }
228
+ else if (outputType instanceof TimestampType) {
142
229
  pageBuilder.setTimestamp(outputColumn, TimestampCast.asTimestamp(value));
143
- } else if (outputType instanceof JsonType) {
230
+ }
231
+ else if (outputType instanceof JsonType) {
144
232
  pageBuilder.setJson(outputColumn, TimestampCast.asJson(value));
145
- } else {
146
- assert(false);
233
+ }
234
+ else {
235
+ assert false;
147
236
  }
148
237
  }
149
238
 
@@ -154,18 +243,24 @@ class ColumnCaster
154
243
  Type outputType = outputColumn.getType();
155
244
  if (outputType instanceof BooleanType) {
156
245
  pageBuilder.setBoolean(outputColumn, JsonCast.asBoolean(castedValue));
157
- } else if (outputType instanceof LongType) {
246
+ }
247
+ else if (outputType instanceof LongType) {
158
248
  pageBuilder.setLong(outputColumn, JsonCast.asLong(castedValue));
159
- } else if (outputType instanceof DoubleType) {
249
+ }
250
+ else if (outputType instanceof DoubleType) {
160
251
  pageBuilder.setDouble(outputColumn, JsonCast.asDouble(castedValue));
161
- } else if (outputType instanceof StringType) {
252
+ }
253
+ else if (outputType instanceof StringType) {
162
254
  pageBuilder.setString(outputColumn, JsonCast.asString(castedValue));
163
- } else if (outputType instanceof TimestampType) {
255
+ }
256
+ else if (outputType instanceof TimestampType) {
164
257
  pageBuilder.setTimestamp(outputColumn, JsonCast.asTimestamp(castedValue));
165
- } else if (outputType instanceof JsonType) {
258
+ }
259
+ else if (outputType instanceof JsonType) {
166
260
  pageBuilder.setJson(outputColumn, JsonCast.asJson(castedValue));
167
- } else {
168
- assert(false);
261
+ }
262
+ else {
263
+ assert false;
169
264
  }
170
265
  }
171
266
  }
@@ -1,21 +1,19 @@
1
1
  package org.embulk.filter.typecast;
2
2
 
3
- import org.embulk.spi.*;
4
- import org.embulk.spi.type.StringType;
5
- import org.embulk.spi.type.TimestampType;
6
-
7
- import org.embulk.filter.typecast.TypecastFilterPlugin.ColumnConfig;
8
3
  import org.embulk.filter.typecast.TypecastFilterPlugin.PluginTask;
9
4
 
10
- import org.embulk.spi.time.TimestampFormatter;
11
- import org.embulk.spi.time.TimestampParser;
12
- import org.joda.time.DateTimeZone;
5
+ import org.embulk.spi.Column;
6
+ import org.embulk.spi.ColumnVisitor;
7
+ import org.embulk.spi.DataException;
8
+ import org.embulk.spi.Exec;
9
+ import org.embulk.spi.PageBuilder;
10
+ import org.embulk.spi.PageReader;
11
+ import org.embulk.spi.Schema;
13
12
  import org.slf4j.Logger;
14
13
 
15
14
  import java.util.HashMap;
16
15
 
17
- public class ColumnVisitorImpl
18
- implements ColumnVisitor
16
+ class ColumnVisitorImpl implements ColumnVisitor
19
17
  {
20
18
  private static final Logger logger = Exec.getLogger(TypecastFilterPlugin.class);
21
19
  private final PluginTask task;
@@ -24,8 +22,6 @@ public class ColumnVisitorImpl
24
22
  private final PageReader pageReader;
25
23
  private final PageBuilder pageBuilder;
26
24
  private final HashMap<String, Column> outputColumnMap = new HashMap<>();
27
- private final HashMap<String, TimestampParser> timestampParserMap = new HashMap<>();
28
- private final HashMap<String, TimestampFormatter> timestampFormatterMap = new HashMap<>();
29
25
  private final ColumnCaster columnCaster;
30
26
 
31
27
  ColumnVisitorImpl(PluginTask task, Schema inputSchema, Schema outputSchema,
@@ -40,8 +36,6 @@ public class ColumnVisitorImpl
40
36
  this.columnCaster = new ColumnCaster(task, inputSchema, outputSchema, pageReader, pageBuilder);
41
37
 
42
38
  buildOutputColumnMap();
43
- buildTimestampParserMap();
44
- buildTimestampFormatterMap();
45
39
  }
46
40
 
47
41
  private void buildOutputColumnMap()
@@ -52,66 +46,26 @@ public class ColumnVisitorImpl
52
46
  }
53
47
  }
54
48
 
55
- private void buildTimestampParserMap()
56
- {
57
- // columnName => TimestampParser
58
- for (ColumnConfig columnConfig : task.getColumns()) {
59
- if (columnConfig.getName().startsWith("$.")) {
60
- continue; // type: json columns do not support type: timestamp
61
- }
62
- Column inputColumn = inputSchema.lookupColumn(columnConfig.getName());
63
- if (inputColumn.getType() instanceof StringType && columnConfig.getType() instanceof TimestampType) {
64
- TimestampParser parser = getTimestampParser(columnConfig, task);
65
- this.timestampParserMap.put(columnConfig.getName(), parser);
66
- }
67
- }
68
- }
69
-
70
- private void buildTimestampFormatterMap()
71
- {
72
- // columnName => TimestampFormatter
73
- for (ColumnConfig columnConfig : task.getColumns()) {
74
- if (columnConfig.getName().startsWith("$.")) {
75
- continue; // type: json columns do not have type: timestamp
76
- }
77
- Column inputColumn = inputSchema.lookupColumn(columnConfig.getName());
78
- if (inputColumn.getType() instanceof TimestampType && columnConfig.getType() instanceof StringType) {
79
- TimestampFormatter parser = getTimestampFormatter(columnConfig, task);
80
- this.timestampFormatterMap.put(columnConfig.getName(), parser);
81
- }
82
- }
83
- }
84
-
85
- private TimestampParser getTimestampParser(ColumnConfig columnConfig, PluginTask task)
86
- {
87
- DateTimeZone timezone = columnConfig.getTimeZone().or(task.getDefaultTimeZone());
88
- String format = columnConfig.getFormat().or(task.getDefaultTimestampFormat());
89
- return new TimestampParser(task.getJRuby(), format, timezone);
90
- }
91
-
92
- private TimestampFormatter getTimestampFormatter(ColumnConfig columnConfig, PluginTask task)
93
- {
94
- String format = columnConfig.getFormat().or(task.getDefaultTimestampFormat());
95
- DateTimeZone timezone = columnConfig.getTimeZone().or(task.getDefaultTimeZone());
96
- return new TimestampFormatter(task.getJRuby(), format, timezone);
97
- }
98
-
99
49
  private interface PageBuildable
100
50
  {
101
- public void run() throws DataException;
51
+ void run() throws DataException;
102
52
  }
103
53
 
104
- private void withStopOnInvalidRecord(final PageBuildable op, final Column inputColumn, final Column outputColumn) throws DataException {
54
+ private void withStopOnInvalidRecord(final PageBuildable op, final Column inputColumn, final Column outputColumn)
55
+ throws DataException
56
+ {
105
57
  if (pageReader.isNull(inputColumn)) {
106
58
  pageBuilder.setNull(outputColumn);
107
59
  }
108
60
  else {
109
61
  if (task.getStopOnInvalidRecord()) {
110
62
  op.run();
111
- } else {
63
+ }
64
+ else {
112
65
  try {
113
66
  op.run();
114
- } catch (final DataException ex) {
67
+ }
68
+ catch (final DataException ex) {
115
69
  logger.warn(ex.getMessage());
116
70
  pageBuilder.setNull(outputColumn);
117
71
  }
@@ -124,7 +78,8 @@ public class ColumnVisitorImpl
124
78
  {
125
79
  final Column outputColumn = outputColumnMap.get(inputColumn.getName());
126
80
  PageBuildable op = new PageBuildable() {
127
- public void run() throws DataException {
81
+ public void run() throws DataException
82
+ {
128
83
  columnCaster.setFromBoolean(outputColumn, pageReader.getBoolean(inputColumn));
129
84
  }
130
85
  };
@@ -136,7 +91,8 @@ public class ColumnVisitorImpl
136
91
  {
137
92
  final Column outputColumn = outputColumnMap.get(inputColumn.getName());
138
93
  PageBuildable op = new PageBuildable() {
139
- public void run() throws DataException {
94
+ public void run() throws DataException
95
+ {
140
96
  columnCaster.setFromLong(outputColumn, pageReader.getLong(inputColumn));
141
97
  }
142
98
  };
@@ -148,7 +104,8 @@ public class ColumnVisitorImpl
148
104
  {
149
105
  final Column outputColumn = outputColumnMap.get(inputColumn.getName());
150
106
  PageBuildable op = new PageBuildable() {
151
- public void run() throws DataException {
107
+ public void run() throws DataException
108
+ {
152
109
  columnCaster.setFromDouble(outputColumn, pageReader.getDouble(inputColumn));
153
110
  }
154
111
  };
@@ -159,10 +116,10 @@ public class ColumnVisitorImpl
159
116
  public void stringColumn(final Column inputColumn)
160
117
  {
161
118
  final Column outputColumn = outputColumnMap.get(inputColumn.getName());
162
- final TimestampParser timestampParser = timestampParserMap.get(inputColumn.getName());
163
119
  PageBuildable op = new PageBuildable() {
164
- public void run() throws DataException {
165
- columnCaster.setFromString(outputColumn, pageReader.getString(inputColumn), timestampParser);
120
+ public void run() throws DataException
121
+ {
122
+ columnCaster.setFromString(outputColumn, pageReader.getString(inputColumn));
166
123
  }
167
124
  };
168
125
  withStopOnInvalidRecord(op, inputColumn, outputColumn);
@@ -172,10 +129,10 @@ public class ColumnVisitorImpl
172
129
  public void timestampColumn(final Column inputColumn)
173
130
  {
174
131
  final Column outputColumn = outputColumnMap.get(inputColumn.getName());
175
- final TimestampFormatter timestampFormatter = timestampFormatterMap.get(inputColumn.getName());
176
132
  PageBuildable op = new PageBuildable() {
177
- public void run() throws DataException {
178
- columnCaster.setFromTimestamp(outputColumn, pageReader.getTimestamp(inputColumn), timestampFormatter);
133
+ public void run() throws DataException
134
+ {
135
+ columnCaster.setFromTimestamp(outputColumn, pageReader.getTimestamp(inputColumn));
179
136
  }
180
137
  };
181
138
  withStopOnInvalidRecord(op, inputColumn, outputColumn);
@@ -186,7 +143,8 @@ public class ColumnVisitorImpl
186
143
  {
187
144
  final Column outputColumn = outputColumnMap.get(inputColumn.getName());
188
145
  PageBuildable op = new PageBuildable() {
189
- public void run() throws DataException {
146
+ public void run() throws DataException
147
+ {
190
148
  columnCaster.setFromJson(outputColumn, pageReader.getJson(inputColumn));
191
149
  }
192
150
  };
@@ -1,34 +1,45 @@
1
1
  package org.embulk.filter.typecast;
2
2
 
3
- import org.embulk.filter.typecast.cast.*;
4
-
3
+ import org.embulk.filter.typecast.cast.BooleanCast;
4
+ import org.embulk.filter.typecast.cast.DoubleCast;
5
+ import org.embulk.filter.typecast.cast.LongCast;
6
+ import org.embulk.filter.typecast.cast.StringCast;
5
7
  import org.embulk.spi.DataException;
6
- import org.embulk.spi.type.*;
8
+ import org.embulk.spi.type.BooleanType;
9
+ import org.embulk.spi.type.DoubleType;
10
+ import org.embulk.spi.type.JsonType;
11
+ import org.embulk.spi.type.LongType;
12
+ import org.embulk.spi.type.StringType;
13
+ import org.embulk.spi.type.Type;
7
14
  import org.msgpack.value.BooleanValue;
8
- import org.msgpack.value.IntegerValue;
9
15
  import org.msgpack.value.FloatValue;
16
+ import org.msgpack.value.IntegerValue;
10
17
  import org.msgpack.value.StringValue;
11
18
  import org.msgpack.value.Value;
12
19
  import org.msgpack.value.ValueFactory;
13
20
 
14
21
  class JsonCaster
15
22
  {
16
- public JsonCaster()
17
- {
18
- }
23
+ public JsonCaster() {}
19
24
 
20
- public Value fromBoolean(Type outputType, BooleanValue value) {
25
+ public Value fromBoolean(Type outputType, BooleanValue value)
26
+ {
21
27
  if (outputType instanceof BooleanType) {
22
28
  return value;
23
- } else if (outputType instanceof LongType) {
29
+ }
30
+ else if (outputType instanceof LongType) {
24
31
  return ValueFactory.newInteger(BooleanCast.asLong(value.getBoolean()));
25
- } else if (outputType instanceof DoubleType) {
32
+ }
33
+ else if (outputType instanceof DoubleType) {
26
34
  return ValueFactory.newFloat(BooleanCast.asDouble(value.getBoolean()));
27
- } else if (outputType instanceof StringType) {
35
+ }
36
+ else if (outputType instanceof StringType) {
28
37
  return ValueFactory.newString(BooleanCast.asString(value.getBoolean()));
29
- } else if (outputType instanceof JsonType) {
38
+ }
39
+ else if (outputType instanceof JsonType) {
30
40
  throw new DataException(String.format("cannot cast boolean to json: \"%s\"", value));
31
- } else {
41
+ }
42
+ else {
32
43
  assert (false);
33
44
  return null;
34
45
  }
@@ -38,16 +49,21 @@ class JsonCaster
38
49
  {
39
50
  if (outputType instanceof BooleanType) {
40
51
  return ValueFactory.newBoolean(LongCast.asBoolean(value.asLong()));
41
- } else if (outputType instanceof LongType) {
52
+ }
53
+ else if (outputType instanceof LongType) {
42
54
  return value;
43
- } else if (outputType instanceof DoubleType) {
55
+ }
56
+ else if (outputType instanceof DoubleType) {
44
57
  return ValueFactory.newFloat(LongCast.asDouble(value.asLong()));
45
- } else if (outputType instanceof StringType) {
58
+ }
59
+ else if (outputType instanceof StringType) {
46
60
  return ValueFactory.newString(LongCast.asString(value.asLong()));
47
- } else if (outputType instanceof JsonType) {
61
+ }
62
+ else if (outputType instanceof JsonType) {
48
63
  throw new DataException(String.format("cannot cast long to json:: \"%s\"", value));
49
- } else {
50
- assert(false);
64
+ }
65
+ else {
66
+ assert false;
51
67
  return null;
52
68
  }
53
69
  }
@@ -56,15 +72,20 @@ class JsonCaster
56
72
  {
57
73
  if (outputType instanceof BooleanType) {
58
74
  return ValueFactory.newBoolean(DoubleCast.asBoolean(value.toDouble()));
59
- } else if (outputType instanceof LongType) {
75
+ }
76
+ else if (outputType instanceof LongType) {
60
77
  return ValueFactory.newInteger(DoubleCast.asLong(value.toDouble()));
61
- } else if (outputType instanceof DoubleType) {
78
+ }
79
+ else if (outputType instanceof DoubleType) {
62
80
  return value;
63
- } else if (outputType instanceof StringType) {
81
+ }
82
+ else if (outputType instanceof StringType) {
64
83
  return ValueFactory.newString(DoubleCast.asString(value.toDouble()));
65
- } else if (outputType instanceof JsonType) {
84
+ }
85
+ else if (outputType instanceof JsonType) {
66
86
  throw new DataException(String.format("cannot cast double to json:: \"%s\"", value));
67
- } else {
87
+ }
88
+ else {
68
89
  assert (false);
69
90
  return null;
70
91
  }
@@ -74,16 +95,21 @@ class JsonCaster
74
95
  {
75
96
  if (outputType instanceof BooleanType) {
76
97
  return ValueFactory.newBoolean(StringCast.asBoolean(value.asString()));
77
- } else if (outputType instanceof LongType) {
98
+ }
99
+ else if (outputType instanceof LongType) {
78
100
  return ValueFactory.newInteger(StringCast.asLong(value.asString()));
79
- } else if (outputType instanceof DoubleType) {
101
+ }
102
+ else if (outputType instanceof DoubleType) {
80
103
  return ValueFactory.newFloat(StringCast.asDouble(value.asString()));
81
- } else if (outputType instanceof StringType) {
104
+ }
105
+ else if (outputType instanceof StringType) {
82
106
  return value;
83
- } else if (outputType instanceof JsonType) {
107
+ }
108
+ else if (outputType instanceof JsonType) {
84
109
  return StringCast.asJson(value.asString());
85
- } else {
86
- assert(false);
110
+ }
111
+ else {
112
+ assert false;
87
113
  return null;
88
114
  }
89
115
  }
@@ -1,15 +1,16 @@
1
1
  package org.embulk.filter.typecast;
2
2
 
3
- import org.embulk.spi.*;
3
+ import org.embulk.filter.typecast.TypecastFilterPlugin.ColumnConfig;
4
+ import org.embulk.filter.typecast.TypecastFilterPlugin.PluginTask;
5
+
6
+ import org.embulk.spi.Exec;
7
+ import org.embulk.spi.Schema;
4
8
  import org.embulk.spi.type.Type;
5
9
  import org.msgpack.value.ArrayValue;
6
10
  import org.msgpack.value.MapValue;
7
11
  import org.msgpack.value.Value;
8
12
  import org.msgpack.value.ValueFactory;
9
13
 
10
- import org.embulk.filter.typecast.TypecastFilterPlugin.ColumnConfig;
11
- import org.embulk.filter.typecast.TypecastFilterPlugin.PluginTask;
12
-
13
14
  import org.slf4j.Logger;
14
15
 
15
16
  import java.util.HashMap;
@@ -65,6 +66,7 @@ public class JsonVisitor
65
66
  partialPath.append(".").append(arrayParts[0]);
66
67
  this.shouldVisitSet.add(partialPath.toString());
67
68
  for (int j = 1; j < arrayParts.length; j++) {
69
+ // Supports both [0] and [*]
68
70
  partialPath.append("[").append(arrayParts[j]);
69
71
  this.shouldVisitSet.add(partialPath.toString());
70
72
  }
@@ -93,6 +95,9 @@ public class JsonVisitor
93
95
  Value[] newValue = new Value[size];
94
96
  for (int i = 0; i < size; i++) {
95
97
  String k = new StringBuilder(jsonPath).append("[").append(Integer.toString(i)).append("]").toString();
98
+ if (!shouldVisit(k)) {
99
+ k = new StringBuilder(jsonPath).append("[*]").toString(); // try [*] too
100
+ }
96
101
  Value v = arrayValue.get(i);
97
102
  newValue[i] = visit(k, v);
98
103
  }
@@ -10,11 +10,14 @@ import org.embulk.config.ConfigSource;
10
10
  import org.embulk.config.Task;
11
11
  import org.embulk.config.TaskSource;
12
12
 
13
- import org.embulk.spi.*;
14
- import org.embulk.spi.time.Timestamp;
15
- import org.embulk.spi.time.TimestampFormatter;
16
- import org.embulk.spi.time.TimestampParser;
17
-
13
+ import org.embulk.spi.Column;
14
+ import org.embulk.spi.Exec;
15
+ import org.embulk.spi.FilterPlugin;
16
+ import org.embulk.spi.Page;
17
+ import org.embulk.spi.PageBuilder;
18
+ import org.embulk.spi.PageOutput;
19
+ import org.embulk.spi.PageReader;
20
+ import org.embulk.spi.Schema;
18
21
  import org.embulk.spi.type.TimestampType;
19
22
  import org.embulk.spi.type.Type;
20
23
  import org.joda.time.DateTimeZone;
@@ -59,7 +62,6 @@ public class TypecastFilterPlugin implements FilterPlugin
59
62
  @ConfigDefault("false")
60
63
  Boolean getStopOnInvalidRecord();
61
64
 
62
-
63
65
  @Config("default_timezone")
64
66
  @ConfigDefault("\"UTC\"")
65
67
  public DateTimeZone getDefaultTimeZone();
@@ -91,7 +93,8 @@ public class TypecastFilterPlugin implements FilterPlugin
91
93
  String name = columnConfig.getName();
92
94
  if (name.startsWith("$.")) { // check only top level column name
93
95
  String firstName = name.split("\\.", 3)[1];
94
- inputSchema.lookupColumn(firstName);
96
+ String firstNameWithoutArray = firstName.split("\\[")[0];
97
+ inputSchema.lookupColumn(firstNameWithoutArray);
95
98
  }
96
99
  else {
97
100
  inputSchema.lookupColumn(name);
@@ -137,7 +140,7 @@ public class TypecastFilterPlugin implements FilterPlugin
137
140
 
138
141
  @Override
139
142
  public PageOutput open(final TaskSource taskSource, final Schema inputSchema,
140
- final Schema outputSchema, final PageOutput output)
143
+ final Schema outputSchema, final PageOutput output)
141
144
  {
142
145
  final PluginTask task = taskSource.loadTask(PluginTask.class);
143
146
 
@@ -1,13 +1,16 @@
1
1
  package org.embulk.filter.typecast.cast;
2
2
 
3
- import org.embulk.spi.time.Timestamp;
4
3
  import org.embulk.spi.DataException;
4
+ import org.embulk.spi.time.Timestamp;
5
5
  import org.msgpack.value.Value;
6
6
 
7
- public class BooleanCast {
7
+ public class BooleanCast
8
+ {
9
+ private BooleanCast() {}
10
+
8
11
  private static String buildErrorMessage(String as, boolean value)
9
12
  {
10
- return String.format("cannot cast double to %s: \"%s\"", as, value);
13
+ return String.format("cannot cast boolean to %s: \"%s\"", as, value);
11
14
  }
12
15
 
13
16
  public static boolean asBoolean(boolean value) throws DataException
@@ -1,10 +1,13 @@
1
1
  package org.embulk.filter.typecast.cast;
2
2
 
3
- import org.embulk.spi.time.Timestamp;
4
3
  import org.embulk.spi.DataException;
4
+ import org.embulk.spi.time.Timestamp;
5
5
  import org.msgpack.value.Value;
6
6
 
7
- public class DoubleCast {
7
+ public class DoubleCast
8
+ {
9
+ private DoubleCast() {}
10
+
8
11
  private static String buildErrorMessage(String as, double value)
9
12
  {
10
13
  return String.format("cannot cast double to %s: \"%s\"", as, value);
@@ -17,7 +20,7 @@ public class DoubleCast {
17
20
 
18
21
  public static long asLong(double value) throws DataException
19
22
  {
20
- return (long)value;
23
+ return (long) value;
21
24
  }
22
25
 
23
26
  public static double asDouble(double value) throws DataException
@@ -37,7 +40,7 @@ public class DoubleCast {
37
40
 
38
41
  public static Timestamp asTimestamp(double value) throws DataException
39
42
  {
40
- long epochSecond = (long)value;
43
+ long epochSecond = (long) value;
41
44
  long nanoAdjustMent = (long) ((value - epochSecond) * 1000000000);
42
45
  return Timestamp.ofEpochSecond(epochSecond, nanoAdjustMent);
43
46
  }
@@ -4,10 +4,13 @@ import org.embulk.spi.DataException;
4
4
  import org.embulk.spi.time.Timestamp;
5
5
  import org.msgpack.value.Value;
6
6
 
7
- public class JsonCast {
7
+ public class JsonCast
8
+ {
9
+ private JsonCast() {}
10
+
8
11
  private static String buildErrorMessage(String as, Value value)
9
12
  {
10
- return String.format("cannot cast String to %s: \"%s\"", as, value);
13
+ return String.format("cannot cast Json to %s: \"%s\"", as, value);
11
14
  }
12
15
 
13
16
  public static boolean asBoolean(Value value) throws DataException
@@ -1,10 +1,13 @@
1
1
  package org.embulk.filter.typecast.cast;
2
2
 
3
- import org.embulk.spi.time.Timestamp;
4
3
  import org.embulk.spi.DataException;
4
+ import org.embulk.spi.time.Timestamp;
5
5
  import org.msgpack.value.Value;
6
6
 
7
- public class LongCast {
7
+ public class LongCast
8
+ {
9
+ private LongCast() {}
10
+
8
11
  private static String buildErrorMessage(String as, long value)
9
12
  {
10
13
  return String.format("cannot cast long to %s: \"%s\"", as, value);
@@ -30,7 +33,7 @@ public class LongCast {
30
33
 
31
34
  public static double asDouble(long value) throws DataException
32
35
  {
33
- return (double)value;
36
+ return (double) value;
34
37
  }
35
38
 
36
39
  public static String asString(long value) throws DataException
@@ -2,14 +2,15 @@ package org.embulk.filter.typecast.cast;
2
2
 
3
3
  import com.google.common.collect.ImmutableSet;
4
4
  import org.embulk.spi.DataException;
5
- import org.embulk.spi.json.JsonParser;
6
5
  import org.embulk.spi.json.JsonParseException;
6
+ import org.embulk.spi.json.JsonParser;
7
7
  import org.embulk.spi.time.Timestamp;
8
- import org.embulk.spi.time.TimestampParser;
9
8
  import org.embulk.spi.time.TimestampParseException;
9
+ import org.embulk.spi.time.TimestampParser;
10
10
  import org.msgpack.value.Value;
11
11
 
12
- public class StringCast {
12
+ public class StringCast
13
+ {
13
14
  private static final JsonParser jsonParser = new JsonParser();
14
15
 
15
16
  // copy from csv plugin
@@ -29,6 +30,7 @@ public class StringCast {
29
30
  "off", "Off", "OFF",
30
31
  "0");
31
32
 
33
+ private StringCast() {}
32
34
 
33
35
  private static String buildErrorMessage(String as, String value)
34
36
  {
@@ -5,7 +5,10 @@ import org.embulk.spi.time.Timestamp;
5
5
  import org.embulk.spi.time.TimestampFormatter;
6
6
  import org.msgpack.value.Value;
7
7
 
8
- public class TimestampCast {
8
+ public class TimestampCast
9
+ {
10
+ private TimestampCast() {}
11
+
9
12
  private static String buildErrorMessage(String as, Timestamp value)
10
13
  {
11
14
  return String.format("cannot cast Timestamp to %s: \"%s\"", as, value);
@@ -25,7 +28,7 @@ public class TimestampCast {
25
28
  {
26
29
  long epochSecond = value.getEpochSecond();
27
30
  long nano = value.getNano();
28
- return epochSecond + ((double)nano / 1000000000.0);
31
+ return epochSecond + ((double) nano / 1000000000.0);
29
32
  }
30
33
 
31
34
  public static String asString(Timestamp value, TimestampFormatter formatter) throws DataException
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk-filter-typecast
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Naotoshi Seo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-28 00:00:00.000000000 Z
11
+ date: 2016-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,7 @@ files:
52
52
  - README.md
53
53
  - build.gradle
54
54
  - config/checkstyle/checkstyle.xml
55
+ - example/empty.yml
55
56
  - example/example.csv
56
57
  - example/example.yml
57
58
  - example/example2.yml
@@ -60,6 +61,7 @@ files:
60
61
  - gradlew
61
62
  - gradlew.bat
62
63
  - lib/embulk/filter/typecast.rb
64
+ - settings.gradle
63
65
  - src/main/java/org/embulk/filter/typecast/ColumnCaster.java
64
66
  - src/main/java/org/embulk/filter/typecast/ColumnVisitorImpl.java
65
67
  - src/main/java/org/embulk/filter/typecast/JsonCaster.java
@@ -72,7 +74,7 @@ files:
72
74
  - src/main/java/org/embulk/filter/typecast/cast/StringCast.java
73
75
  - src/main/java/org/embulk/filter/typecast/cast/TimestampCast.java
74
76
  - src/test/java/org/embulk/filter/TestTypecastFilterPlugin.java
75
- - classpath/embulk-filter-typecast-0.1.2.jar
77
+ - classpath/embulk-filter-typecast-0.1.3.jar
76
78
  homepage: https://github.com/sonots/embulk-filter-typecast
77
79
  licenses:
78
80
  - MIT