7
7
8
8
import org .elasticsearch .action .ActionRequestValidationException ;
9
9
import org .elasticsearch .action .fieldcaps .FieldCapabilities ;
10
+ import org .elasticsearch .common .Nullable ;
10
11
import org .elasticsearch .common .ParseField ;
11
12
import org .elasticsearch .common .Strings ;
12
13
import org .elasticsearch .common .io .stream .StreamInput ;
15
16
import org .elasticsearch .common .rounding .DateTimeUnit ;
16
17
import org .elasticsearch .common .rounding .Rounding ;
17
18
import org .elasticsearch .common .unit .TimeValue ;
18
- import org .elasticsearch .common .xcontent .ObjectParser ;
19
- import org .elasticsearch .common .xcontent .ToXContentFragment ;
19
+ import org .elasticsearch .common .xcontent .ConstructingObjectParser ;
20
+ import org .elasticsearch .common .xcontent .ToXContentObject ;
20
21
import org .elasticsearch .common .xcontent .XContentBuilder ;
21
22
import org .elasticsearch .common .xcontent .XContentParser ;
22
23
import org .elasticsearch .search .aggregations .bucket .composite .CompositeValuesSourceBuilder ;
33
34
import java .util .Map ;
34
35
import java .util .Objects ;
35
36
37
+ import static org .elasticsearch .common .xcontent .ConstructingObjectParser .constructorArg ;
38
+ import static org .elasticsearch .common .xcontent .ConstructingObjectParser .optionalConstructorArg ;
39
+ import static org .elasticsearch .common .xcontent .ObjectParser .ValueType ;
40
+
36
41
/**
37
42
* The configuration object for the histograms in the rollup config
38
43
*
47
52
* ]
48
53
* }
49
54
*/
50
- public class DateHistoGroupConfig implements Writeable , ToXContentFragment {
51
- private static final String NAME = "date_histo_group_config" ;
52
- public static final ObjectParser <DateHistoGroupConfig .Builder , Void > PARSER
53
- = new ObjectParser <>(NAME , DateHistoGroupConfig .Builder ::new );
54
-
55
- private static final ParseField INTERVAL = new ParseField ("interval" );
56
- private static final ParseField DELAY = new ParseField ("delay" );
57
- private static final ParseField FIELD = new ParseField ("field" );
58
- public static final ParseField TIME_ZONE = new ParseField ("time_zone" );
55
+ public class DateHistogramGroupConfig implements Writeable , ToXContentObject {
56
+
57
+ private static final String NAME = "date_histogram" ;
58
+ private static final String INTERVAL = "interval" ;
59
+ private static final String FIELD = "field" ;
60
+ public static final String TIME_ZONE = "time_zone" ;
61
+ private static final String DELAY = "delay" ;
62
+ private static final String DEFAULT_TIMEZONE = "UTC" ;
63
+ private static final ConstructingObjectParser <DateHistogramGroupConfig , Void > PARSER ;
64
+ static {
65
+ PARSER = new ConstructingObjectParser <>(NAME , a ->
66
+ new DateHistogramGroupConfig ((String ) a [0 ], (DateHistogramInterval ) a [1 ], (DateHistogramInterval ) a [2 ], (String ) a [3 ]));
67
+ PARSER .declareString (constructorArg (), new ParseField (FIELD ));
68
+ PARSER .declareField (constructorArg (), p -> new DateHistogramInterval (p .text ()), new ParseField (INTERVAL ), ValueType .STRING );
69
+ PARSER .declareField (optionalConstructorArg (), p -> new DateHistogramInterval (p .text ()), new ParseField (DELAY ), ValueType .STRING );
70
+ PARSER .declareString (optionalConstructorArg (), new ParseField (TIME_ZONE ));
71
+ }
59
72
60
- private final DateHistogramInterval interval ;
61
73
private final String field ;
62
- private final DateTimeZone timeZone ;
74
+ private final DateHistogramInterval interval ;
63
75
private final DateHistogramInterval delay ;
76
+ private final String timeZone ;
64
77
65
- static {
66
- PARSER .declareField (DateHistoGroupConfig .Builder ::setInterval ,
67
- p -> new DateHistogramInterval (p .text ()), INTERVAL , ObjectParser .ValueType .STRING );
68
- PARSER .declareString (DateHistoGroupConfig .Builder ::setField , FIELD );
69
- PARSER .declareField (DateHistoGroupConfig .Builder ::setDelay ,
70
- p -> new DateHistogramInterval (p .text ()), DELAY , ObjectParser .ValueType .LONG );
71
- PARSER .declareField (DateHistoGroupConfig .Builder ::setTimeZone , p -> {
72
- if (p .currentToken () == XContentParser .Token .VALUE_STRING ) {
73
- return DateTimeZone .forID (p .text ());
74
- } else {
75
- return DateTimeZone .forOffsetHours (p .intValue ());
76
- }
77
- }, TIME_ZONE , ObjectParser .ValueType .LONG );
78
+ /**
79
+ * Create a new {@link DateHistogramGroupConfig} using the given field and interval parameters.
80
+ */
81
+ public DateHistogramGroupConfig (final String field , final DateHistogramInterval interval ) {
82
+ this (field , interval , null , null );
78
83
}
79
84
80
- private DateHistoGroupConfig (DateHistogramInterval interval ,
81
- String field ,
82
- DateHistogramInterval delay ,
83
- DateTimeZone timeZone ) {
85
+ /**
86
+ * Create a new {@link DateHistogramGroupConfig} using the given configuration parameters.
87
+ * <p>
88
+ * The {@code field} and {@code interval} are required to compute the date histogram for the rolled up documents.
89
+ * The {@code delay} is optional and can be set to {@code null}. It defines how long to wait before rolling up new documents.
90
+ * The {@code timeZone} is optional and can be set to {@code null}. When configured, the time zone value is resolved using
91
+ * ({@link DateTimeZone#forID(String)} and must match a time zone identifier provided by the Joda Time library.
92
+ * </p>
93
+ * @param field the name of the date field to use for the date histogram (required)
94
+ * @param interval the interval to use for the date histogram (required)
95
+ * @param delay the time delay (optional)
96
+ * @param timeZone the id of time zone to use to calculate the date histogram (optional). When {@code null}, the UTC timezone is used.
97
+ */
98
+ public DateHistogramGroupConfig (final String field ,
99
+ final DateHistogramInterval interval ,
100
+ final @ Nullable DateHistogramInterval delay ,
101
+ final @ Nullable String timeZone ) {
102
+ if (field == null || field .isEmpty ()) {
103
+ throw new IllegalArgumentException ("Field must be a non-null, non-empty string" );
104
+ }
105
+ if (interval == null ) {
106
+ throw new IllegalArgumentException ("Interval must be non-null" );
107
+ }
108
+
84
109
this .interval = interval ;
85
110
this .field = field ;
86
111
this .delay = delay ;
87
- this .timeZone = Objects .requireNonNull (timeZone );
112
+ this .timeZone = (timeZone != null && timeZone .isEmpty () == false ) ? timeZone : DEFAULT_TIMEZONE ;
113
+
114
+ // validate interval
115
+ createRounding (this .interval .toString (), this .timeZone );
116
+ if (delay != null ) {
117
+ // and delay
118
+ TimeValue .parseTimeValue (this .delay .toString (), DELAY );
119
+ }
88
120
}
89
121
90
- DateHistoGroupConfig ( StreamInput in ) throws IOException {
122
+ DateHistogramGroupConfig ( final StreamInput in ) throws IOException {
91
123
interval = new DateHistogramInterval (in );
92
124
field = in .readString ();
93
125
delay = in .readOptionalWriteable (DateHistogramInterval ::new );
94
- timeZone = in .readTimeZone ();
126
+ timeZone = in .readString ();
95
127
}
96
128
97
129
@ Override
98
- public void writeTo (StreamOutput out ) throws IOException {
130
+ public void writeTo (final StreamOutput out ) throws IOException {
99
131
interval .writeTo (out );
100
132
out .writeString (field );
101
133
out .writeOptionalWriteable (delay );
102
- out .writeTimeZone (timeZone );
134
+ out .writeString (timeZone );
103
135
}
104
136
105
137
@ Override
106
- public XContentBuilder toXContent (XContentBuilder builder , Params params ) throws IOException {
107
- builder .field (INTERVAL .getPreferredName (), interval .toString ());
108
- builder .field (FIELD .getPreferredName (), field );
109
- if (delay != null ) {
110
- builder .field (DELAY .getPreferredName (), delay .toString ());
138
+ public XContentBuilder toXContent (final XContentBuilder builder , final Params params ) throws IOException {
139
+ builder .startObject ();
140
+ {
141
+ builder .field (INTERVAL , interval .toString ());
142
+ builder .field (FIELD , field );
143
+ if (delay != null ) {
144
+ builder .field (DELAY , delay .toString ());
145
+ }
146
+ builder .field (TIME_ZONE , timeZone );
111
147
}
112
- builder .field (TIME_ZONE .getPreferredName (), timeZone .toString ());
113
-
114
- return builder ;
148
+ return builder .endObject ();
115
149
}
116
150
117
151
/**
@@ -138,17 +172,17 @@ public DateHistogramInterval getDelay() {
138
172
/**
139
173
* Get the timezone to apply
140
174
*/
141
- public DateTimeZone getTimeZone () {
175
+ public String getTimeZone () {
142
176
return timeZone ;
143
177
}
144
178
145
179
/**
146
180
* Create the rounding for this date histogram
147
181
*/
148
182
public Rounding createRounding () {
149
- return createRounding (interval .toString (), timeZone , "" );
183
+ return createRounding (interval .toString (), timeZone );
150
184
}
151
- ;
185
+
152
186
/**
153
187
* This returns a set of aggregation builders which represent the configured
154
188
* set of date histograms. Used by the rollup indexer to iterate over historical data
@@ -158,7 +192,7 @@ public List<CompositeValuesSourceBuilder<?>> toBuilders() {
158
192
new DateHistogramValuesSourceBuilder (RollupField .formatIndexerAggName (field , DateHistogramAggregationBuilder .NAME ));
159
193
vsBuilder .dateHistogramInterval (interval );
160
194
vsBuilder .field (field );
161
- vsBuilder .timeZone (timeZone );
195
+ vsBuilder .timeZone (toDateTimeZone ( timeZone ) );
162
196
return Collections .singletonList (vsBuilder );
163
197
}
164
198
@@ -168,11 +202,11 @@ public List<CompositeValuesSourceBuilder<?>> toBuilders() {
168
202
public Map <String , Object > toAggCap () {
169
203
Map <String , Object > map = new HashMap <>(3 );
170
204
map .put ("agg" , DateHistogramAggregationBuilder .NAME );
171
- map .put (INTERVAL . getPreferredName () , interval .toString ());
205
+ map .put (INTERVAL , interval .toString ());
172
206
if (delay != null ) {
173
- map .put (DELAY . getPreferredName () , delay .toString ());
207
+ map .put (DELAY , delay .toString ());
174
208
}
175
- map .put (TIME_ZONE . getPreferredName () , timeZone . toString () );
209
+ map .put (TIME_ZONE , timeZone );
176
210
177
211
return map ;
178
212
}
@@ -204,21 +238,18 @@ public void validateMappings(Map<String, Map<String, FieldCapabilities>> fieldCa
204
238
}
205
239
206
240
@ Override
207
- public boolean equals (Object other ) {
241
+ public boolean equals (final Object other ) {
208
242
if (this == other ) {
209
243
return true ;
210
244
}
211
-
212
245
if (other == null || getClass () != other .getClass ()) {
213
246
return false ;
214
247
}
215
-
216
- DateHistoGroupConfig that = (DateHistoGroupConfig ) other ;
217
-
218
- return Objects .equals (this .interval , that .interval )
219
- && Objects .equals (this .field , that .field )
220
- && Objects .equals (this .delay , that .delay )
221
- && Objects .equals (this .timeZone , that .timeZone );
248
+ final DateHistogramGroupConfig that = (DateHistogramGroupConfig ) other ;
249
+ return Objects .equals (interval , that .interval )
250
+ && Objects .equals (field , that .field )
251
+ && Objects .equals (delay , that .delay )
252
+ && Objects .equals (timeZone , that .timeZone );
222
253
}
223
254
224
255
@ Override
@@ -231,77 +262,28 @@ public String toString() {
231
262
return Strings .toString (this , true , true );
232
263
}
233
264
234
- private static Rounding createRounding (String expr , DateTimeZone timeZone , String settingName ) {
265
+ public static DateHistogramGroupConfig fromXContent (final XContentParser parser ) throws IOException {
266
+ return PARSER .parse (parser , null );
267
+ }
268
+
269
+ private static Rounding createRounding (final String expr , final String timeZone ) {
235
270
DateTimeUnit timeUnit = DateHistogramAggregationBuilder .DATE_FIELD_UNITS .get (expr );
236
271
final Rounding .Builder rounding ;
237
272
if (timeUnit != null ) {
238
273
rounding = new Rounding .Builder (timeUnit );
239
274
} else {
240
- rounding = new Rounding .Builder (TimeValue .parseTimeValue (expr , settingName ));
275
+ rounding = new Rounding .Builder (TimeValue .parseTimeValue (expr , "createRounding" ));
241
276
}
242
- rounding .timeZone (timeZone );
277
+ rounding .timeZone (toDateTimeZone ( timeZone ) );
243
278
return rounding .build ();
244
279
}
245
280
246
- public static class Builder {
247
- private DateHistogramInterval interval ;
248
- private String field ;
249
- private DateHistogramInterval delay ;
250
- private DateTimeZone timeZone ;
251
-
252
- public DateHistogramInterval getInterval () {
253
- return interval ;
254
- }
255
-
256
- public DateHistoGroupConfig .Builder setInterval (DateHistogramInterval interval ) {
257
- this .interval = interval ;
258
- return this ;
259
- }
260
-
261
- public String getField () {
262
- return field ;
263
- }
264
-
265
- public DateHistoGroupConfig .Builder setField (String field ) {
266
- this .field = field ;
267
- return this ;
268
- }
269
-
270
- public DateTimeZone getTimeZone () {
271
- return timeZone ;
272
- }
273
-
274
- public DateHistoGroupConfig .Builder setTimeZone (DateTimeZone timeZone ) {
275
- this .timeZone = timeZone ;
276
- return this ;
277
- }
278
-
279
- public DateHistogramInterval getDelay () {
280
- return delay ;
281
- }
282
-
283
- public DateHistoGroupConfig .Builder setDelay (DateHistogramInterval delay ) {
284
- this .delay = delay ;
285
- return this ;
286
- }
287
-
288
- public DateHistoGroupConfig build () {
289
- if (field == null || field .isEmpty ()) {
290
- throw new IllegalArgumentException ("Parameter [" + FIELD .getPreferredName () + "] is mandatory." );
291
- }
292
- if (timeZone == null ) {
293
- timeZone = DateTimeZone .UTC ;
294
- }
295
- if (interval == null ) {
296
- throw new IllegalArgumentException ("Parameter [" + INTERVAL .getPreferredName () + "] is mandatory." );
297
- }
298
- // validate interval
299
- createRounding (interval .toString (), timeZone , INTERVAL .getPreferredName ());
300
- if (delay != null ) {
301
- // and delay
302
- TimeValue .parseTimeValue (delay .toString (), INTERVAL .getPreferredName ());
303
- }
304
- return new DateHistoGroupConfig (interval , field , delay , timeZone );
281
+ private static DateTimeZone toDateTimeZone (final String timezone ) {
282
+ try {
283
+ return DateTimeZone .forOffsetHours (Integer .parseInt (timezone ));
284
+ } catch (NumberFormatException e ) {
285
+ return DateTimeZone .forID (timezone );
305
286
}
306
287
}
288
+
307
289
}
0 commit comments