18
18
19
19
import java .time .Instant ;
20
20
import java .time .ZoneId ;
21
+ import java .time .ZoneOffset ;
21
22
import java .time .ZonedDateTime ;
23
+ import java .util .Locale ;
24
+ import java .util .Objects ;
22
25
23
26
import org .apache .kafka .connect .header .Header ;
24
27
import org .apache .kafka .connect .sink .SinkRecord ;
@@ -39,58 +42,67 @@ enum Type {
39
42
CUSTOM
40
43
41
44
}
45
+ class Builder {
46
+ private ZoneId zoneId = ZoneOffset .UTC ;
47
+ private Type type ;
48
+ private String additionalParameters ;
42
49
43
- static TimestampSource forConfiguration (final String configuration , final ZoneId zoneId ) {
44
- final String [] parts = configuration .split (":" , 2 );
45
- final String typeName = parts [0 ];
46
- final String context = parts .length > 1 ? parts [1 ] : null ;
47
- for (final Type t : Type .values ()) {
48
- if (t .name ().equalsIgnoreCase (typeName )) {
49
- return create (t , context , zoneId );
50
- }
50
+ public Builder zoneId (final ZoneId zoneId ) {
51
+ Objects .requireNonNull (zoneId , "zoneId cannot be null" );
52
+ this .zoneId = zoneId ;
53
+ return this ;
51
54
}
52
- throw new IllegalArgumentException (String .format ("Unknown timestamp source: %s" , configuration ));
53
- }
54
55
55
- private static TimestampSource create (Type t , String context , ZoneId zoneId ) {
56
- switch (t ) {
57
- case WALLCLOCK :
58
- if (context != null ) {
59
- throw new IllegalArgumentException ("Wallclock timestamp source does not support context" );
60
- }
61
- return new WallclockTimestampSource (zoneId );
62
- case EVENT :
63
- if (context != null ) {
64
- throw new IllegalArgumentException ("Event timestamp source does not support context" );
65
- }
66
- return new EventTimestampSource (zoneId );
67
- case DATA :
68
- if (context == null ) {
69
- throw new IllegalArgumentException ("Data timestamp source requires context" );
70
- }
71
- return new DataTimestampSource (context , zoneId );
72
- case HEADER :
73
- if (context == null ) {
74
- throw new IllegalArgumentException ("Header timestamp source requires context" );
75
- }
76
- return new HeaderTimestampSource (context , zoneId );
77
- case CUSTOM :
78
- if (context == null ) {
79
- throw new IllegalArgumentException ("Header timestamp source requires context" );
80
- }
81
- final String [] parts = context .split (":" , 2 );
82
- final String className = parts [0 ];
83
- final String params = parts .length > 1 ? parts [1 ] : null ;
84
- try {
85
- final Class <?> clazz = Class .forName (className );
86
- return (TimestampSource ) clazz .getConstructor (String .class , ZoneId .class ).newInstance (params , zoneId );
87
- } catch (final Exception e ) {
88
- throw new IllegalArgumentException ("Failed to create custom timestamp source" , e );
89
- }
90
- default :
91
- throw new IllegalArgumentException (
92
- String .format ("Unsupported timestamp extractor type: %s" , t ));
56
+ public Builder configuration (final String configuration ) {
57
+ final String [] parts = configuration .split (":" , 2 );
58
+ final String typeName = parts [0 ];
59
+ this .type = Type .valueOf (typeName .toUpperCase (Locale .ENGLISH ));
60
+
61
+ this .additionalParameters = parts .length > 1 ? parts [1 ] : null ;
62
+ return this ;
93
63
}
64
+
65
+ public TimestampSource build () {
66
+ switch (type ) {
67
+ case WALLCLOCK :
68
+ if (additionalParameters != null ) {
69
+ throw new IllegalArgumentException ("Wallclock timestamp source does not support additionalParameters" );
70
+ }
71
+ return new WallclockTimestampSource (zoneId );
72
+ case EVENT :
73
+ if (additionalParameters != null ) {
74
+ throw new IllegalArgumentException ("Event timestamp source does not support additionalParameters" );
75
+ }
76
+ return new EventTimestampSource (zoneId );
77
+ case DATA :
78
+ if (additionalParameters == null ) {
79
+ throw new IllegalArgumentException ("Data timestamp source requires additionalParameters" );
80
+ }
81
+ return new DataTimestampSource (additionalParameters , zoneId );
82
+ case HEADER :
83
+ if (additionalParameters == null ) {
84
+ throw new IllegalArgumentException ("Header timestamp source requires additionalParameters" );
85
+ }
86
+ return new HeaderTimestampSource (additionalParameters , zoneId );
87
+ case CUSTOM :
88
+ if (additionalParameters == null ) {
89
+ throw new IllegalArgumentException ("Header timestamp source requires additionalParameters" );
90
+ }
91
+ final String [] parts = additionalParameters .split (":" , 2 );
92
+ final String className = parts [0 ];
93
+ final String params = parts .length > 1 ? parts [1 ] : null ;
94
+ try {
95
+ final Class <?> clazz = Class .forName (className );
96
+ return (TimestampSource ) clazz .getConstructor (String .class , ZoneId .class ).newInstance (params , zoneId );
97
+ } catch (final Exception e ) {
98
+ throw new IllegalArgumentException ("Failed to create custom timestamp source" , e );
99
+ }
100
+ default :
101
+ throw new IllegalArgumentException (
102
+ String .format ("Unsupported timestamp extractor type: %s" , type ));
103
+ }
104
+ }
105
+
94
106
}
95
107
96
108
abstract class AbstractTimestampSource implements TimestampSource {
@@ -148,16 +160,16 @@ public ZonedDateTime time(final SinkRecord record) {
148
160
}
149
161
150
162
final class DataTimestampSource extends AbstractTimestampSource {
151
- private final Path path ;
163
+ private final PathAccess path ;
152
164
153
165
DataTimestampSource (final String pathDefinition , final ZoneId zoneId ) {
154
166
super (zoneId , Type .DATA );
155
- this .path = Path .parse (pathDefinition );
167
+ this .path = PathAccess .parse (pathDefinition );
156
168
}
157
169
158
170
@ Override
159
171
public ZonedDateTime time (final SinkRecord record ) {
160
- Object value = path .extractDataFrom (record );
172
+ final Object value = path .extractDataFrom (record );
161
173
return rawTime (value );
162
174
}
163
175
@@ -173,7 +185,7 @@ final class HeaderTimestampSource extends AbstractTimestampSource {
173
185
174
186
@ Override
175
187
public ZonedDateTime time (final SinkRecord record ) {
176
- Header header = record .headers ().lastWithName (headerName );
188
+ final Header header = record .headers ().lastWithName (headerName );
177
189
return rawTime (header == null ? null : header .value ());
178
190
}
179
191
}
0 commit comments