CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-elasticsearch--elasticsearch-x-content

A content processing library for Elasticsearch that provides abstractions for parsing and generating various content formats including JSON, YAML, CBOR, and Smile.

Pending
Overview
Eval results
Files

configuration.mddocs/

Configuration and Registry

The X-Content library provides comprehensive configuration system for parsers including named object registries, deprecation handling, API versioning, and field filtering support.

Capabilities

XContentParserConfiguration

Central configuration interface for customizing parser behavior.

/**
 * Configuration interface for XContentParser instances
 */
public interface XContentParserConfiguration {
    
    /**
     * Empty configuration with default settings - creates parsers that don't support named objects,
     * throw exceptions on deprecated fields, return current REST API version, and do no filtering
     */
    XContentParserConfiguration EMPTY = XContentProvider.provider().empty();
    
    /**
     * Control whether to include source in parsing error messages
     * @param includeSourceOnError whether to include source on errors (defaults to true)
     * @return new configuration with the specified setting
     */
    XContentParserConfiguration withIncludeSourceOnError(boolean includeSourceOnError);
    
    /**
     * Check if source should be included in parsing error messages
     * @return true if source should be included on errors
     */
    boolean includeSourceOnError();
    
    /**
     * Create new configuration with specified registry
     * @param registry named XContent registry
     * @return new configuration with the registry
     */
    XContentParserConfiguration withRegistry(NamedXContentRegistry registry);
    
    /**
     * Get the named XContent registry
     * @return NamedXContentRegistry instance
     */
    NamedXContentRegistry registry();
    
    /**
     * Create new configuration with specified deprecation handler
     * @param handler deprecation handler
     * @return new configuration with the handler
     */
    XContentParserConfiguration withDeprecationHandler(DeprecationHandler handler);
    
    /**
     * Get the deprecation handler
     * @return DeprecationHandler instance
     */
    DeprecationHandler deprecationHandler();
    
    /**
     * Create new configuration with specified REST API version
     * @param version REST API version
     * @return new configuration with the version
     */
    XContentParserConfiguration withRestApiVersion(RestApiVersion version);
    
    /**
     * Get the REST API version
     * @return RestApiVersion instance
     */
    RestApiVersion restApiVersion();
    
    /**
     * Create new configuration with filtering settings (legacy method)
     * @param includeStrings field patterns to include
     * @param excludeStrings field patterns to exclude
     * @param filtersMatchFieldNamesWithDots whether filters should match field names containing dots
     * @return new configuration with filtering
     */
    XContentParserConfiguration withFiltering(Set<String> includeStrings, Set<String> excludeStrings, 
                                             boolean filtersMatchFieldNamesWithDots);
    
    /**
     * Create new configuration with advanced filtering settings
     * @param prefixPath path to be prepended to each sub-path before applying include/exclude rules (null for root)
     * @param includeStrings field patterns to include (only these paths will be included if specified)
     * @param excludeStrings field patterns to exclude (these paths will be excluded if specified)
     * @param filtersMatchFieldNamesWithDots whether filters should match field names containing dots as part of field name
     * @return new configuration with filtering
     */
    XContentParserConfiguration withFiltering(String prefixPath, Set<String> includeStrings, 
                                             Set<String> excludeStrings, boolean filtersMatchFieldNamesWithDots);
}

Usage Examples:

import org.elasticsearch.xcontent.*;

// Use default configuration
XContentParserConfiguration defaultConfig = XContentParserConfiguration.EMPTY;

// Create custom registry
NamedXContentRegistry.Entry queryEntry = new NamedXContentRegistry.Entry(
    Query.class, new ParseField("match"), MatchQuery::fromXContent);
NamedXContentRegistry customRegistry = new NamedXContentRegistry(List.of(queryEntry));

// Configure parser with custom settings
XContentParserConfiguration config = XContentParserConfiguration.EMPTY
    .withRegistry(customRegistry)  
    .withDeprecationHandler(DeprecationHandler.IGNORE_DEPRECATIONS)
    .withRestApiVersion(RestApiVersion.current());

// Create parser with configuration
XContentParser parser = XContentType.JSON.xContent()
    .createParser(config, jsonContent);

// Configuration with filtering (legacy method)
XContentParserConfiguration filterConfig = XContentParserConfiguration.EMPTY
    .withFiltering(Set.of("name", "age"), Set.of("internal.*"), false);

// Configuration with advanced filtering
XContentParserConfiguration advancedFilterConfig = XContentParserConfiguration.EMPTY
    .withFiltering("user", Set.of("name", "age"), Set.of("internal.*"), true);

// Configuration with source error handling
XContentParserConfiguration errorConfig = XContentParserConfiguration.EMPTY
    .withIncludeSourceOnError(false);

NamedXContentRegistry

Registry system for named objects like queries, aggregations, and other pluggable components.

/**
 * Registry for named XContent parsers enabling pluggable object parsing
 */
public class NamedXContentRegistry {
    
    /**
     * Registry entry associating category, name, and parser
     */
    public static class Entry {
        /**
         * Create a registry entry
         * @param categoryClass class representing the category (e.g., Query.class)
         * @param name parse field for the object name
         * @param parser context parser for the object
         */
        public <T> Entry(Class<T> categoryClass, ParseField name, ContextParser<Object, T> parser);
        
        /**
         * Get the category class
         * @return category class
         */
        public Class<?> getCategoryClass();
        
        /**
         * Get the name parse field
         * @return ParseField with names
         */
        public ParseField getName();
        
        /**
         * Get the parser
         * @return ContextParser instance
         */
        public ContextParser<Object, ?> getParser();
    }
    
    /**
     * Empty registry with no entries
     */
    public static final NamedXContentRegistry EMPTY = new NamedXContentRegistry(Collections.emptyList());
    
    /**
     * Create registry with list of entries
     * @param entries list of registry entries
     */
    public NamedXContentRegistry(List<Entry> entries);
    
    /**
     * Parse a named object from content
     * @param categoryClass category class for the object
     * @param name object name to parse
     * @param parser content parser
     * @param context parsing context
     * @return parsed object of the specified type
     */
    public <T, C> T parseNamedObject(Class<T> categoryClass, String name, 
                                    XContentParser parser, C context) throws IOException;
    
    /**
     * Get all entries for a specific category
     * @param categoryClass category class
     * @return list of entries for the category
     */
    public List<Entry> getRegistry(Class<?> categoryClass);
}

Usage Examples:

// Define parseable objects
public abstract class Query {
    public abstract String getName();
}

public class MatchQuery extends Query {
    private final String field;
    private final String value;
    
    public MatchQuery(String field, String value) {
        this.field = field;
        this.value = value;
    }
    
    public String getName() { return "match"; }
    
    public static MatchQuery fromXContent(XContentParser parser) throws IOException {
        // Parse match query from XContent
        String field = null;
        String value = null;
        
        while (parser.nextToken() != XContentParser.Token.END_OBJECT) {
            if (parser.currentToken() == XContentParser.Token.FIELD_NAME) {
                field = parser.currentName();
                parser.nextToken();
                value = parser.text();
            }
        }
        return new MatchQuery(field, value);
    }
}

// Create registry entries
List<NamedXContentRegistry.Entry> entries = Arrays.asList(
    new NamedXContentRegistry.Entry(Query.class, new ParseField("match"), 
                                   (parser, context) -> MatchQuery.fromXContent(parser)),
    new NamedXContentRegistry.Entry(Query.class, new ParseField("term"),
                                   (parser, context) -> TermQuery.fromXContent(parser))
);

NamedXContentRegistry registry = new NamedXContentRegistry(entries);

// Parse named objects
String queryJson = """
{
    "match": {
        "title": "elasticsearch"
    }
}
""";

XContentParser parser = XContentType.JSON.xContent()
    .createParser(XContentParserConfiguration.EMPTY.withRegistry(registry), queryJson);

parser.nextToken(); // START_OBJECT
parser.nextToken(); // FIELD_NAME ("match")
String queryType = parser.currentName();
parser.nextToken(); // START_OBJECT (query content)

Query query = registry.parseNamedObject(Query.class, queryType, parser, null);

DeprecationHandler

Interface for handling deprecated field usage and API warnings.

/**
 * Interface for handling deprecated content warnings
 */
public interface DeprecationHandler {
    
    /**
     * Handler that throws UnsupportedOperationException on any deprecation
     */
    DeprecationHandler THROW_UNSUPPORTED_OPERATION = new DeprecationHandler() {
        @Override
        public void logRenamedField(String parserName, Supplier<XContentLocation> location,
                                   String oldName, String currentName) {
            throw new UnsupportedOperationException("Deprecated field [" + oldName + "] used");
        }
        
        @Override
        public void logReplacedField(String parserName, Supplier<XContentLocation> location,
                                    String oldName, String replacedName) {
            throw new UnsupportedOperationException("Deprecated field [" + oldName + "] used");
        }
        
        @Override
        public void logRemovedField(String parserName, Supplier<XContentLocation> location,
                                   String removedName) {
            throw new UnsupportedOperationException("Deprecated field [" + removedName + "] used"); 
        }
    };
    
    /**
     * Handler that ignores all deprecation warnings
     */
    DeprecationHandler IGNORE_DEPRECATIONS = new DeprecationHandler() {
        @Override
        public void logRenamedField(String parserName, Supplier<XContentLocation> location,
                                   String oldName, String currentName) {
            // Ignore
        }
        
        @Override
        public void logReplacedField(String parserName, Supplier<XContentLocation> location,
                                    String oldName, String replacedName) {
            // Ignore
        }
        
        @Override
        public void logRemovedField(String parserName, Supplier<XContentLocation> location,
                                   String removedName) {
            // Ignore
        }
    };
    
    /**
     * Log usage of a renamed field
     * @param parserName name of the parser detecting the deprecation
     * @param location supplier for the location in content
     * @param oldName deprecated field name that was used
     * @param currentName current preferred field name
     */
    void logRenamedField(String parserName, Supplier<XContentLocation> location, 
                        String oldName, String currentName);
    
    /**
     * Log usage of a replaced field
     * @param parserName name of the parser detecting the deprecation
     * @param location supplier for the location in content
     * @param oldName deprecated field name that was used
     * @param replacedName name of the field that replaced it
     */
    void logReplacedField(String parserName, Supplier<XContentLocation> location,
                         String oldName, String replacedName);
    
    /**
     * Log usage of a removed field
     * @param parserName name of the parser detecting the deprecation
     * @param location supplier for the location in content
     * @param removedName name of the removed field
     */
    void logRemovedField(String parserName, Supplier<XContentLocation> location, String removedName);
}

ParseField

Field definition with deprecation support for backward compatibility.

/**
 * Represents a field name with support for deprecated alternatives
 */
public class ParseField {
    
    /**
     * Common field definitions used across the codebase
     */
    public static class CommonFields {
        public static final ParseField TYPE = new ParseField("type");
        public static final ParseField VALUE = new ParseField("value");
        public static final ParseField FORMAT = new ParseField("format");
        // ... other common fields
    }
    
    /**
     * Create a parse field with deprecated alternatives
     * @param name preferred field name
     * @param deprecatedNames deprecated field names that should still be accepted
     */
    public ParseField(String name, String... deprecatedNames);
    
    /**
     * Get the preferred field name
     * @return preferred name
     */
    public String getPreferredName();
    
    /**
     * Get all valid names including deprecated ones
     * @return array of all valid names
     */
    public String[] getAllNamesIncludedDeprecated();
    
    /**
     * Check if a field name matches this parse field
     * @param fieldName field name to check
     * @param handler deprecation handler for warnings
     * @return true if field name matches
     */
    public boolean match(String fieldName, DeprecationHandler handler);
    
    /**
     * Create new parse field with additional deprecated names
     * @param deprecatedNames additional deprecated names
     * @return new ParseField with additional deprecations
     */
    public ParseField withDeprecation(String... deprecatedNames);
    
    /**
     * Mark all names as deprecated in favor of replacement
     * @param replacement replacement field name
     * @return new ParseField with all names deprecated
     */
    public ParseField withAllDeprecated(String replacement);
}

Usage Examples:

// Define fields with deprecation support
ParseField nameField = new ParseField("name", "title", "label");  // name preferred, others deprecated
ParseField activeField = new ParseField("active", "enabled");     // active preferred, enabled deprecated

// Use in object parser
ObjectParser<User, Void> parser = new ObjectParser<>("user", User::new);
parser.declareString(User::setName, nameField);
parser.declareBoolean(User::setActive, activeField);

// Configure deprecation handling
XContentParserConfiguration config = XContentParserConfiguration.EMPTY
    .withDeprecationHandler(DeprecationHandler.IGNORE_DEPRECATIONS);

// Parse content with deprecated field names
String jsonWithDeprecated = """
{
    "title": "John Doe",      // Will trigger deprecation warning
    "enabled": true           // Will trigger deprecation warning  
}
""";

XContentParser contentParser = XContentType.JSON.xContent()
    .createParser(config, jsonWithDeprecated);
User user = parser.parse(contentParser, null);

ObjectPath

Utility for navigating nested object structures using dot notation.

/**
 * Utility class for evaluating object paths using dot notation
 */
public final class ObjectPath {
    
    /**
     * Evaluate a dot-separated path on an object
     * @param path dot-separated path (e.g., "user.address.street")
     * @param object root object to navigate
     * @return value at the specified path, or null if not found
     */
    public static <T> T eval(String path, Object object);
    
    /**
     * Evaluate a path array on an object
     * @param path array of path segments
     * @param object root object to navigate  
     * @return value at the specified path, or null if not found
     */
    public static <T> T eval(String[] path, Object object);
}

Usage Examples:

// Navigate nested structures
Map<String, Object> data = Map.of(
    "user", Map.of(
        "name", "John Doe",
        "address", Map.of(
            "street", "123 Main St",
            "city", "New York"
        )
    )
);

// Extract nested values
String name = ObjectPath.eval("user.name", data);           // "John Doe"
String street = ObjectPath.eval("user.address.street", data); // "123 Main St"
String missing = ObjectPath.eval("user.phone", data);       // null

// Using path arrays
String city = ObjectPath.eval(new String[]{"user", "address", "city"}, data); // "New York"

Install with Tessl CLI

npx tessl i tessl/maven-org-elasticsearch--elasticsearch-x-content

docs

configuration.md

content-generation.md

content-parsing.md

content-types.md

index.md

object-mapping.md

tile.json