19
19
20
20
package org .elasticsearch .index .mapper ;
21
21
22
+ import org .elasticsearch .ElasticsearchParseException ;
22
23
import org .elasticsearch .Version ;
23
24
import org .elasticsearch .common .Explicit ;
24
25
import org .elasticsearch .common .Strings ;
34
35
import java .util .Arrays ;
35
36
import java .util .Collection ;
36
37
import java .util .Collections ;
38
+ import java .util .Comparator ;
39
+ import java .util .HashMap ;
37
40
import java .util .Iterator ;
38
41
import java .util .LinkedHashMap ;
39
42
import java .util .List ;
40
43
import java .util .Locale ;
41
44
import java .util .Map ;
45
+ import java .util .stream .Collectors ;
42
46
43
47
import static org .elasticsearch .common .xcontent .support .XContentMapValues .nodeBooleanValue ;
44
48
import static org .elasticsearch .index .mapper .TypeParsers .parseDateTimeFormatter ;
@@ -62,6 +66,7 @@ public static class Builder extends ObjectMapper.Builder {
62
66
protected Explicit <DateFormatter []> dynamicDateTimeFormatters = new Explicit <>(Defaults .DYNAMIC_DATE_TIME_FORMATTERS , false );
63
67
protected Explicit <Boolean > dateDetection = new Explicit <>(Defaults .DATE_DETECTION , false );
64
68
protected Explicit <Boolean > numericDetection = new Explicit <>(Defaults .NUMERIC_DETECTION , false );
69
+ protected final Map <String , RuntimeFieldType > runtimeFieldTypes = new HashMap <>();
65
70
66
71
public Builder (String name , Version indexCreatedVersion ) {
67
72
super (name , indexCreatedVersion );
@@ -83,6 +88,11 @@ public RootObjectMapper.Builder add(Mapper.Builder builder) {
83
88
return this ;
84
89
}
85
90
91
+ public RootObjectMapper .Builder addRuntime (RuntimeFieldType runtimeFieldType ) {
92
+ this .runtimeFieldTypes .put (runtimeFieldType .name (), runtimeFieldType );
93
+ return this ;
94
+ }
95
+
86
96
@ Override
87
97
public RootObjectMapper build (ContentPath contentPath ) {
88
98
return (RootObjectMapper ) super .build (contentPath );
@@ -92,7 +102,7 @@ public RootObjectMapper build(ContentPath contentPath) {
92
102
protected ObjectMapper createMapper (String name , String fullPath , Explicit <Boolean > enabled , Nested nested , Dynamic dynamic ,
93
103
Map <String , Mapper > mappers , Version indexCreatedVersion ) {
94
104
assert !nested .isNested ();
95
- return new RootObjectMapper (name , enabled , dynamic , mappers ,
105
+ return new RootObjectMapper (name , enabled , dynamic , mappers , runtimeFieldTypes ,
96
106
dynamicDateTimeFormatters ,
97
107
dynamicTemplates ,
98
108
dateDetection , numericDetection , indexCreatedVersion );
@@ -127,7 +137,7 @@ private static void fixRedundantIncludes(ObjectMapper objectMapper, boolean pare
127
137
}
128
138
}
129
139
130
- public static class TypeParser extends ObjectMapper .TypeParser {
140
+ static final class TypeParser extends ObjectMapper .TypeParser {
131
141
132
142
@ Override
133
143
public Mapper .Builder parse (String name , Map <String , Object > node , ParserContext parserContext ) throws MapperParsingException {
@@ -145,8 +155,8 @@ public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext
145
155
return builder ;
146
156
}
147
157
148
- protected boolean processField ( RootObjectMapper . Builder builder , String fieldName , Object fieldNode ,
149
- ParserContext parserContext ) {
158
+ @ SuppressWarnings ( "unchecked" )
159
+ private boolean processField ( RootObjectMapper . Builder builder , String fieldName , Object fieldNode , ParserContext parserContext ) {
150
160
if (fieldName .equals ("date_formats" ) || fieldName .equals ("dynamic_date_formats" )) {
151
161
if (fieldNode instanceof List ) {
152
162
List <DateFormatter > formatters = new ArrayList <>();
@@ -200,6 +210,13 @@ protected boolean processField(RootObjectMapper.Builder builder, String fieldNam
200
210
} else if (fieldName .equals ("numeric_detection" )) {
201
211
builder .numericDetection = new Explicit <>(nodeBooleanValue (fieldNode , "numeric_detection" ), true );
202
212
return true ;
213
+ } else if (fieldName .equals ("runtime" )) {
214
+ if (fieldNode instanceof Map ) {
215
+ RuntimeFieldType .parseRuntimeFields ((Map <String , Object >) fieldNode , parserContext , builder ::addRuntime );
216
+ return true ;
217
+ } else {
218
+ throw new ElasticsearchParseException ("runtime must be a map type" );
219
+ }
203
220
}
204
221
return false ;
205
222
}
@@ -209,11 +226,14 @@ protected boolean processField(RootObjectMapper.Builder builder, String fieldNam
209
226
private Explicit <Boolean > dateDetection ;
210
227
private Explicit <Boolean > numericDetection ;
211
228
private Explicit <DynamicTemplate []> dynamicTemplates ;
229
+ private final Map <String , RuntimeFieldType > runtimeFieldTypes ;
212
230
213
231
RootObjectMapper (String name , Explicit <Boolean > enabled , Dynamic dynamic , Map <String , Mapper > mappers ,
232
+ Map <String , RuntimeFieldType > runtimeFieldTypes ,
214
233
Explicit <DateFormatter []> dynamicDateTimeFormatters , Explicit <DynamicTemplate []> dynamicTemplates ,
215
234
Explicit <Boolean > dateDetection , Explicit <Boolean > numericDetection , Version indexCreatedVersion ) {
216
235
super (name , name , enabled , Nested .NO , dynamic , mappers , indexCreatedVersion );
236
+ this .runtimeFieldTypes = runtimeFieldTypes ;
217
237
this .dynamicTemplates = dynamicTemplates ;
218
238
this .dynamicDateTimeFormatters = dynamicDateTimeFormatters ;
219
239
this .dateDetection = dateDetection ;
@@ -233,23 +253,26 @@ public ObjectMapper mappingUpdate(Mapper mapper) {
233
253
return update ;
234
254
}
235
255
236
- public boolean dateDetection () {
256
+ boolean dateDetection () {
237
257
return this .dateDetection .value ();
238
258
}
239
259
240
- public boolean numericDetection () {
260
+ boolean numericDetection () {
241
261
return this .numericDetection .value ();
242
262
}
243
263
244
- public DateFormatter [] dynamicDateTimeFormatters () {
264
+ DateFormatter [] dynamicDateTimeFormatters () {
245
265
return dynamicDateTimeFormatters .value ();
246
266
}
247
267
248
- public DynamicTemplate [] dynamicTemplates () {
268
+ DynamicTemplate [] dynamicTemplates () {
249
269
return dynamicTemplates .value ();
250
270
}
251
271
252
- @ SuppressWarnings ("rawtypes" )
272
+ Collection <RuntimeFieldType > runtimeFieldTypes () {
273
+ return runtimeFieldTypes .values ();
274
+ }
275
+
253
276
public Mapper .Builder findTemplateBuilder (ParseContext context , String name , XContentFieldType matchType ) {
254
277
return findTemplateBuilder (context , name , matchType , null );
255
278
}
@@ -265,7 +288,6 @@ public Mapper.Builder findTemplateBuilder(ParseContext context, String name, Dat
265
288
* @param dateFormat a dateformatter to use if the type is a date, null if not a date or is using the default format
266
289
* @return a mapper builder, or null if there is no template for such a field
267
290
*/
268
- @ SuppressWarnings ("rawtypes" )
269
291
private Mapper .Builder findTemplateBuilder (ParseContext context , String name , XContentFieldType matchType , DateFormatter dateFormat ) {
270
292
DynamicTemplate dynamicTemplate = findTemplate (context .path (), name , matchType );
271
293
if (dynamicTemplate == null ) {
@@ -328,6 +350,8 @@ protected void doMerge(ObjectMapper mergeWith, MergeReason reason) {
328
350
this .dynamicTemplates = mergeWithObject .dynamicTemplates ;
329
351
}
330
352
}
353
+
354
+ this .runtimeFieldTypes .putAll (mergeWithObject .runtimeFieldTypes );
331
355
}
332
356
333
357
@ Override
@@ -358,6 +382,16 @@ protected void doXContent(XContentBuilder builder, ToXContent.Params params) thr
358
382
if (numericDetection .explicit () || includeDefaults ) {
359
383
builder .field ("numeric_detection" , numericDetection .value ());
360
384
}
385
+
386
+ if (runtimeFieldTypes .size () > 0 ) {
387
+ builder .startObject ("runtime" );
388
+ List <RuntimeFieldType > sortedRuntimeFieldTypes = runtimeFieldTypes .values ().stream ().sorted (
389
+ Comparator .comparing (RuntimeFieldType ::name )).collect (Collectors .toList ());
390
+ for (RuntimeFieldType fieldType : sortedRuntimeFieldTypes ) {
391
+ fieldType .toXContent (builder , params );
392
+ }
393
+ builder .endObject ();
394
+ }
361
395
}
362
396
363
397
private static void validateDynamicTemplate (Mapper .TypeParser .ParserContext parserContext ,
0 commit comments