1313import org .opensearch .common .inject .Singleton ;
1414import org .opensearch .index .query .QueryBuilder ;
1515import org .opensearch .protobufs .QueryContainer ;
16-
17- import java .util .HashMap ;
18- import java .util .Iterator ;
19- import java .util .Map ;
20- import java .util .ServiceLoader ;
16+ import org .opensearch .transport .grpc .proto .request .search .query .QueryBuilderProtoConverterSpiRegistry ;
2117
2218/**
2319 * Registry for QueryBuilderProtoConverter implementations.
24- * This class discovers and manages all available converters.
20+ * This class wraps the SPI registry and adds built-in converters for the transport-grpc module .
2521 */
2622@ Singleton
2723public class QueryBuilderProtoConverterRegistry {
2824
2925 private static final Logger logger = LogManager .getLogger (QueryBuilderProtoConverterRegistry .class );
30- private final Map < QueryContainer . QueryContainerCase , QueryBuilderProtoConverter > converterMap = new HashMap <>() ;
26+ private final QueryBuilderProtoConverterSpiRegistry delegate ;
3127
3228 /**
3329 * Creates a new registry and loads all available converters.
3430 */
3531 @ Inject
3632 public QueryBuilderProtoConverterRegistry () {
37- // Load built-in converters
38- registerBuiltInConverters ();
33+ // Create the SPI registry which loads external converters
34+ this . delegate = new QueryBuilderProtoConverterSpiRegistry ();
3935
40- // Discover converters from other plugins using Java's ServiceLoader
41- loadExternalConverters ();
36+ // Register built-in converters for this module
37+ registerBuiltInConverters ();
4238 }
4339
4440 /**
@@ -47,96 +43,31 @@ public QueryBuilderProtoConverterRegistry() {
4743 */
4844 protected void registerBuiltInConverters () {
4945 // Add built-in converters
50- registerConverter (new MatchAllQueryBuilderProtoConverter ());
51- registerConverter (new MatchNoneQueryBuilderProtoConverter ());
52- registerConverter (new TermQueryBuilderProtoConverter ());
53- registerConverter (new TermsQueryBuilderProtoConverter ());
54-
55- logger .info ("Registered {} built-in query converters" , converterMap .size ());
56- }
57-
58- /**
59- * Loads external converters using Java's ServiceLoader mechanism.
60- * Protected for testing purposes.
61- */
62- protected void loadExternalConverters () {
63- ServiceLoader <QueryBuilderProtoConverter > serviceLoader = ServiceLoader .load (QueryBuilderProtoConverter .class );
64- Iterator <QueryBuilderProtoConverter > iterator = serviceLoader .iterator ();
46+ delegate .registerConverter (new MatchAllQueryBuilderProtoConverter ());
47+ delegate .registerConverter (new MatchNoneQueryBuilderProtoConverter ());
48+ delegate .registerConverter (new TermQueryBuilderProtoConverter ());
49+ delegate .registerConverter (new TermsQueryBuilderProtoConverter ());
6550
66- int count = 0 ;
67- int failedCount = 0 ;
68- while (iterator .hasNext ()) {
69- try {
70- QueryBuilderProtoConverter converter = iterator .next ();
71- registerConverter (converter );
72- count ++;
73- logger .info ("Loaded external query converter for {}: {}" , converter .getHandledQueryCase (), converter .getClass ().getName ());
74- } catch (Exception e ) {
75- failedCount ++;
76- logger .error ("Failed to load external query converter" , e );
77- }
78- }
79-
80- logger .info ("Loaded {} external query converters ({} failed)" , count , failedCount );
51+ logger .info ("Registered {} built-in query converters" , delegate .size ());
8152 }
8253
8354 /**
8455 * Converts a protobuf query container to an OpenSearch QueryBuilder.
8556 *
8657 * @param queryContainer The protobuf query container
8758 * @return The corresponding OpenSearch QueryBuilder
88- * @throws IllegalArgumentException if no converter can handle the query
59+ * @throws IllegalArgumentException if the query cannot be converted
8960 */
9061 public QueryBuilder fromProto (QueryContainer queryContainer ) {
91- if (queryContainer == null ) {
92- throw new IllegalArgumentException ("Query container cannot be null" );
93- }
94-
95- // Use direct map lookup for better performance
96- QueryContainer .QueryContainerCase queryCase = queryContainer .getQueryContainerCase ();
97- QueryBuilderProtoConverter converter = converterMap .get (queryCase );
98-
99- if (converter != null ) {
100- logger .debug ("Using converter for {}: {}" , queryCase , converter .getClass ().getName ());
101- return converter .fromProto (queryContainer );
102- }
103-
104- throw new IllegalArgumentException ("Unsupported query type in container: " + queryContainer + " (case: " + queryCase + ")" );
62+ return delegate .fromProto (queryContainer );
10563 }
10664
10765 /**
10866 * Registers a new converter.
10967 *
11068 * @param converter The converter to register
111- * @throws IllegalArgumentException if the converter is null or its handled query case is invalid
11269 */
11370 public void registerConverter (QueryBuilderProtoConverter converter ) {
114- if (converter == null ) {
115- throw new IllegalArgumentException ("Converter cannot be null" );
116- }
117-
118- QueryContainer .QueryContainerCase queryCase = converter .getHandledQueryCase ();
119-
120- if (queryCase == null ) {
121- throw new IllegalArgumentException ("Handled query case cannot be null for converter: " + converter .getClass ().getName ());
122- }
123-
124- if (queryCase == QueryContainer .QueryContainerCase .QUERYCONTAINER_NOT_SET ) {
125- throw new IllegalArgumentException (
126- "Cannot register converter for QUERYCONTAINER_NOT_SET case: " + converter .getClass ().getName ()
127- );
128- }
129-
130- QueryBuilderProtoConverter existingConverter = converterMap .put (queryCase , converter );
131- if (existingConverter != null ) {
132- logger .warn (
133- "Replacing existing converter for query type {}: {} -> {}" ,
134- queryCase ,
135- existingConverter .getClass ().getName (),
136- converter .getClass ().getName ()
137- );
138- }
139-
140- logger .debug ("Registered query converter for {}: {}" , queryCase , converter .getClass ().getName ());
71+ delegate .registerConverter (converter );
14172 }
14273}
0 commit comments