0
# Configuration and Registry
1
2
The X-Content library provides comprehensive configuration system for parsers including named object registries, deprecation handling, API versioning, and field filtering support.
3
4
## Capabilities
5
6
### XContentParserConfiguration
7
8
Central configuration interface for customizing parser behavior.
9
10
```java { .api }
11
/**
12
* Configuration interface for XContentParser instances
13
*/
14
public interface XContentParserConfiguration {
15
16
/**
17
* Empty configuration with default settings - creates parsers that don't support named objects,
18
* throw exceptions on deprecated fields, return current REST API version, and do no filtering
19
*/
20
XContentParserConfiguration EMPTY = XContentProvider.provider().empty();
21
22
/**
23
* Control whether to include source in parsing error messages
24
* @param includeSourceOnError whether to include source on errors (defaults to true)
25
* @return new configuration with the specified setting
26
*/
27
XContentParserConfiguration withIncludeSourceOnError(boolean includeSourceOnError);
28
29
/**
30
* Check if source should be included in parsing error messages
31
* @return true if source should be included on errors
32
*/
33
boolean includeSourceOnError();
34
35
/**
36
* Create new configuration with specified registry
37
* @param registry named XContent registry
38
* @return new configuration with the registry
39
*/
40
XContentParserConfiguration withRegistry(NamedXContentRegistry registry);
41
42
/**
43
* Get the named XContent registry
44
* @return NamedXContentRegistry instance
45
*/
46
NamedXContentRegistry registry();
47
48
/**
49
* Create new configuration with specified deprecation handler
50
* @param handler deprecation handler
51
* @return new configuration with the handler
52
*/
53
XContentParserConfiguration withDeprecationHandler(DeprecationHandler handler);
54
55
/**
56
* Get the deprecation handler
57
* @return DeprecationHandler instance
58
*/
59
DeprecationHandler deprecationHandler();
60
61
/**
62
* Create new configuration with specified REST API version
63
* @param version REST API version
64
* @return new configuration with the version
65
*/
66
XContentParserConfiguration withRestApiVersion(RestApiVersion version);
67
68
/**
69
* Get the REST API version
70
* @return RestApiVersion instance
71
*/
72
RestApiVersion restApiVersion();
73
74
/**
75
* Create new configuration with filtering settings (legacy method)
76
* @param includeStrings field patterns to include
77
* @param excludeStrings field patterns to exclude
78
* @param filtersMatchFieldNamesWithDots whether filters should match field names containing dots
79
* @return new configuration with filtering
80
*/
81
XContentParserConfiguration withFiltering(Set<String> includeStrings, Set<String> excludeStrings,
82
boolean filtersMatchFieldNamesWithDots);
83
84
/**
85
* Create new configuration with advanced filtering settings
86
* @param prefixPath path to be prepended to each sub-path before applying include/exclude rules (null for root)
87
* @param includeStrings field patterns to include (only these paths will be included if specified)
88
* @param excludeStrings field patterns to exclude (these paths will be excluded if specified)
89
* @param filtersMatchFieldNamesWithDots whether filters should match field names containing dots as part of field name
90
* @return new configuration with filtering
91
*/
92
XContentParserConfiguration withFiltering(String prefixPath, Set<String> includeStrings,
93
Set<String> excludeStrings, boolean filtersMatchFieldNamesWithDots);
94
}
95
```
96
97
**Usage Examples:**
98
99
```java
100
import org.elasticsearch.xcontent.*;
101
102
// Use default configuration
103
XContentParserConfiguration defaultConfig = XContentParserConfiguration.EMPTY;
104
105
// Create custom registry
106
NamedXContentRegistry.Entry queryEntry = new NamedXContentRegistry.Entry(
107
Query.class, new ParseField("match"), MatchQuery::fromXContent);
108
NamedXContentRegistry customRegistry = new NamedXContentRegistry(List.of(queryEntry));
109
110
// Configure parser with custom settings
111
XContentParserConfiguration config = XContentParserConfiguration.EMPTY
112
.withRegistry(customRegistry)
113
.withDeprecationHandler(DeprecationHandler.IGNORE_DEPRECATIONS)
114
.withRestApiVersion(RestApiVersion.current());
115
116
// Create parser with configuration
117
XContentParser parser = XContentType.JSON.xContent()
118
.createParser(config, jsonContent);
119
120
// Configuration with filtering (legacy method)
121
XContentParserConfiguration filterConfig = XContentParserConfiguration.EMPTY
122
.withFiltering(Set.of("name", "age"), Set.of("internal.*"), false);
123
124
// Configuration with advanced filtering
125
XContentParserConfiguration advancedFilterConfig = XContentParserConfiguration.EMPTY
126
.withFiltering("user", Set.of("name", "age"), Set.of("internal.*"), true);
127
128
// Configuration with source error handling
129
XContentParserConfiguration errorConfig = XContentParserConfiguration.EMPTY
130
.withIncludeSourceOnError(false);
131
```
132
133
### NamedXContentRegistry
134
135
Registry system for named objects like queries, aggregations, and other pluggable components.
136
137
```java { .api }
138
/**
139
* Registry for named XContent parsers enabling pluggable object parsing
140
*/
141
public class NamedXContentRegistry {
142
143
/**
144
* Registry entry associating category, name, and parser
145
*/
146
public static class Entry {
147
/**
148
* Create a registry entry
149
* @param categoryClass class representing the category (e.g., Query.class)
150
* @param name parse field for the object name
151
* @param parser context parser for the object
152
*/
153
public <T> Entry(Class<T> categoryClass, ParseField name, ContextParser<Object, T> parser);
154
155
/**
156
* Get the category class
157
* @return category class
158
*/
159
public Class<?> getCategoryClass();
160
161
/**
162
* Get the name parse field
163
* @return ParseField with names
164
*/
165
public ParseField getName();
166
167
/**
168
* Get the parser
169
* @return ContextParser instance
170
*/
171
public ContextParser<Object, ?> getParser();
172
}
173
174
/**
175
* Empty registry with no entries
176
*/
177
public static final NamedXContentRegistry EMPTY = new NamedXContentRegistry(Collections.emptyList());
178
179
/**
180
* Create registry with list of entries
181
* @param entries list of registry entries
182
*/
183
public NamedXContentRegistry(List<Entry> entries);
184
185
/**
186
* Parse a named object from content
187
* @param categoryClass category class for the object
188
* @param name object name to parse
189
* @param parser content parser
190
* @param context parsing context
191
* @return parsed object of the specified type
192
*/
193
public <T, C> T parseNamedObject(Class<T> categoryClass, String name,
194
XContentParser parser, C context) throws IOException;
195
196
/**
197
* Get all entries for a specific category
198
* @param categoryClass category class
199
* @return list of entries for the category
200
*/
201
public List<Entry> getRegistry(Class<?> categoryClass);
202
}
203
```
204
205
**Usage Examples:**
206
207
```java
208
// Define parseable objects
209
public abstract class Query {
210
public abstract String getName();
211
}
212
213
public class MatchQuery extends Query {
214
private final String field;
215
private final String value;
216
217
public MatchQuery(String field, String value) {
218
this.field = field;
219
this.value = value;
220
}
221
222
public String getName() { return "match"; }
223
224
public static MatchQuery fromXContent(XContentParser parser) throws IOException {
225
// Parse match query from XContent
226
String field = null;
227
String value = null;
228
229
while (parser.nextToken() != XContentParser.Token.END_OBJECT) {
230
if (parser.currentToken() == XContentParser.Token.FIELD_NAME) {
231
field = parser.currentName();
232
parser.nextToken();
233
value = parser.text();
234
}
235
}
236
return new MatchQuery(field, value);
237
}
238
}
239
240
// Create registry entries
241
List<NamedXContentRegistry.Entry> entries = Arrays.asList(
242
new NamedXContentRegistry.Entry(Query.class, new ParseField("match"),
243
(parser, context) -> MatchQuery.fromXContent(parser)),
244
new NamedXContentRegistry.Entry(Query.class, new ParseField("term"),
245
(parser, context) -> TermQuery.fromXContent(parser))
246
);
247
248
NamedXContentRegistry registry = new NamedXContentRegistry(entries);
249
250
// Parse named objects
251
String queryJson = """
252
{
253
"match": {
254
"title": "elasticsearch"
255
}
256
}
257
""";
258
259
XContentParser parser = XContentType.JSON.xContent()
260
.createParser(XContentParserConfiguration.EMPTY.withRegistry(registry), queryJson);
261
262
parser.nextToken(); // START_OBJECT
263
parser.nextToken(); // FIELD_NAME ("match")
264
String queryType = parser.currentName();
265
parser.nextToken(); // START_OBJECT (query content)
266
267
Query query = registry.parseNamedObject(Query.class, queryType, parser, null);
268
```
269
270
### DeprecationHandler
271
272
Interface for handling deprecated field usage and API warnings.
273
274
```java { .api }
275
/**
276
* Interface for handling deprecated content warnings
277
*/
278
public interface DeprecationHandler {
279
280
/**
281
* Handler that throws UnsupportedOperationException on any deprecation
282
*/
283
DeprecationHandler THROW_UNSUPPORTED_OPERATION = new DeprecationHandler() {
284
@Override
285
public void logRenamedField(String parserName, Supplier<XContentLocation> location,
286
String oldName, String currentName) {
287
throw new UnsupportedOperationException("Deprecated field [" + oldName + "] used");
288
}
289
290
@Override
291
public void logReplacedField(String parserName, Supplier<XContentLocation> location,
292
String oldName, String replacedName) {
293
throw new UnsupportedOperationException("Deprecated field [" + oldName + "] used");
294
}
295
296
@Override
297
public void logRemovedField(String parserName, Supplier<XContentLocation> location,
298
String removedName) {
299
throw new UnsupportedOperationException("Deprecated field [" + removedName + "] used");
300
}
301
};
302
303
/**
304
* Handler that ignores all deprecation warnings
305
*/
306
DeprecationHandler IGNORE_DEPRECATIONS = new DeprecationHandler() {
307
@Override
308
public void logRenamedField(String parserName, Supplier<XContentLocation> location,
309
String oldName, String currentName) {
310
// Ignore
311
}
312
313
@Override
314
public void logReplacedField(String parserName, Supplier<XContentLocation> location,
315
String oldName, String replacedName) {
316
// Ignore
317
}
318
319
@Override
320
public void logRemovedField(String parserName, Supplier<XContentLocation> location,
321
String removedName) {
322
// Ignore
323
}
324
};
325
326
/**
327
* Log usage of a renamed field
328
* @param parserName name of the parser detecting the deprecation
329
* @param location supplier for the location in content
330
* @param oldName deprecated field name that was used
331
* @param currentName current preferred field name
332
*/
333
void logRenamedField(String parserName, Supplier<XContentLocation> location,
334
String oldName, String currentName);
335
336
/**
337
* Log usage of a replaced field
338
* @param parserName name of the parser detecting the deprecation
339
* @param location supplier for the location in content
340
* @param oldName deprecated field name that was used
341
* @param replacedName name of the field that replaced it
342
*/
343
void logReplacedField(String parserName, Supplier<XContentLocation> location,
344
String oldName, String replacedName);
345
346
/**
347
* Log usage of a removed field
348
* @param parserName name of the parser detecting the deprecation
349
* @param location supplier for the location in content
350
* @param removedName name of the removed field
351
*/
352
void logRemovedField(String parserName, Supplier<XContentLocation> location, String removedName);
353
}
354
```
355
356
### ParseField
357
358
Field definition with deprecation support for backward compatibility.
359
360
```java { .api }
361
/**
362
* Represents a field name with support for deprecated alternatives
363
*/
364
public class ParseField {
365
366
/**
367
* Common field definitions used across the codebase
368
*/
369
public static class CommonFields {
370
public static final ParseField TYPE = new ParseField("type");
371
public static final ParseField VALUE = new ParseField("value");
372
public static final ParseField FORMAT = new ParseField("format");
373
// ... other common fields
374
}
375
376
/**
377
* Create a parse field with deprecated alternatives
378
* @param name preferred field name
379
* @param deprecatedNames deprecated field names that should still be accepted
380
*/
381
public ParseField(String name, String... deprecatedNames);
382
383
/**
384
* Get the preferred field name
385
* @return preferred name
386
*/
387
public String getPreferredName();
388
389
/**
390
* Get all valid names including deprecated ones
391
* @return array of all valid names
392
*/
393
public String[] getAllNamesIncludedDeprecated();
394
395
/**
396
* Check if a field name matches this parse field
397
* @param fieldName field name to check
398
* @param handler deprecation handler for warnings
399
* @return true if field name matches
400
*/
401
public boolean match(String fieldName, DeprecationHandler handler);
402
403
/**
404
* Create new parse field with additional deprecated names
405
* @param deprecatedNames additional deprecated names
406
* @return new ParseField with additional deprecations
407
*/
408
public ParseField withDeprecation(String... deprecatedNames);
409
410
/**
411
* Mark all names as deprecated in favor of replacement
412
* @param replacement replacement field name
413
* @return new ParseField with all names deprecated
414
*/
415
public ParseField withAllDeprecated(String replacement);
416
}
417
```
418
419
**Usage Examples:**
420
421
```java
422
// Define fields with deprecation support
423
ParseField nameField = new ParseField("name", "title", "label"); // name preferred, others deprecated
424
ParseField activeField = new ParseField("active", "enabled"); // active preferred, enabled deprecated
425
426
// Use in object parser
427
ObjectParser<User, Void> parser = new ObjectParser<>("user", User::new);
428
parser.declareString(User::setName, nameField);
429
parser.declareBoolean(User::setActive, activeField);
430
431
// Configure deprecation handling
432
XContentParserConfiguration config = XContentParserConfiguration.EMPTY
433
.withDeprecationHandler(DeprecationHandler.IGNORE_DEPRECATIONS);
434
435
// Parse content with deprecated field names
436
String jsonWithDeprecated = """
437
{
438
"title": "John Doe", // Will trigger deprecation warning
439
"enabled": true // Will trigger deprecation warning
440
}
441
""";
442
443
XContentParser contentParser = XContentType.JSON.xContent()
444
.createParser(config, jsonWithDeprecated);
445
User user = parser.parse(contentParser, null);
446
```
447
448
### ObjectPath
449
450
Utility for navigating nested object structures using dot notation.
451
452
```java { .api }
453
/**
454
* Utility class for evaluating object paths using dot notation
455
*/
456
public final class ObjectPath {
457
458
/**
459
* Evaluate a dot-separated path on an object
460
* @param path dot-separated path (e.g., "user.address.street")
461
* @param object root object to navigate
462
* @return value at the specified path, or null if not found
463
*/
464
public static <T> T eval(String path, Object object);
465
466
/**
467
* Evaluate a path array on an object
468
* @param path array of path segments
469
* @param object root object to navigate
470
* @return value at the specified path, or null if not found
471
*/
472
public static <T> T eval(String[] path, Object object);
473
}
474
```
475
476
**Usage Examples:**
477
478
```java
479
// Navigate nested structures
480
Map<String, Object> data = Map.of(
481
"user", Map.of(
482
"name", "John Doe",
483
"address", Map.of(
484
"street", "123 Main St",
485
"city", "New York"
486
)
487
)
488
);
489
490
// Extract nested values
491
String name = ObjectPath.eval("user.name", data); // "John Doe"
492
String street = ObjectPath.eval("user.address.street", data); // "123 Main St"
493
String missing = ObjectPath.eval("user.phone", data); // null
494
495
// Using path arrays
496
String city = ObjectPath.eval(new String[]{"user", "address", "city"}, data); // "New York"
497
```