Follows up on HSEARCH-3065, which introduces changes in the DSL that make this possible.
The contributor/collector pattern is currently used in two ways: in the (engine) query building code when manipulating (internal) query DSL classes implementing these "contributor" interfaces, and in the query DSL classes when manipulating prediate/sort builders which also implement these "contributor" interfaces. There is no need to use the same interfaces in those two places, and in the end we're tying together pieces of code which could be independent. It's messy.
The contributor/collector pattern is powerful, but complex and introduces a high level of abstraction that makes the code allow more than it should. In particular, there is no compile-time constraint on how many predicates a SearchPredicateContributor contributes exactly, but in practice we sometimes want to only allow one predicate per contributor. Since builders generally do not need to contribute more than one element, we could simply make them return only one, and only use contributors in the DSL to handle cases where we need to contribute multiple elements (with multiple builders).
I believe we could have a builder SPI that doesn't involve contributors in any way, and could be simpler, by using different generics hacks. I'll try and submit a PR.