I’m working on making Lucene analyzers for patient search configurable. The idea is that an implementer should be able to control the analyzers and filters used by Lucene by changing global properties. This should also make it possible to add custom analyzers, as has been done with the NamePhonetics module.
I have a few questions.
1 – @raff very helpfully pointed the way – the Hibernate Search Programmatic API seems like the way to go for this. We would replace the AnalyzerDefs annotation on BaseOpenmrsObject with some setup code. I am not sure where exactly that setup code should go. Somewhere that runs on each startup? I’m still very unfamiliar with OpenMRS Core’s non-API code.
2 – The Hibernate Search docs show a programmatically defined analyzer being attached to an object using
cfg.getProperties().put("hibernate.search.model_mapping", mapping);
I don’t know of anywhere in the OpenMRS code that uses Hibrernate’s programmatic configuration API – everything I know of is XML. Are the two interchangeable? Do they play nice together? Do we have programmatic access to the Hibernate Configuration?
3 – Suggestions about the Global Properties API we should support? I assume we need to stay backward-compatible with patientSearch.matchMode
(which allows the user to choose between the START analyzer or the ANYWHERE analyzer). I’d like to support users simply providing a list of filters and a single analyzer would be composed from them, which would be inserted in getPersonNameQuery. A user might, for example, provide the global property
patientSearch.searchFilters="ClassicFilter,LowerCaseFilter,ASCIIFoldingFilter,DoubleMetaphoneFilter"
and an analyzer like
.analyzerDef( "name", StandardTokenizerFactory.class )
.filter( ClassicFilterFactory.class )
.filter( LowerCaseFilterFactory.class )
.filter( ASCIIFoldingFilterFactory.class )
.filter( DoubleMetaphone.class )
would be composed. The downsides of this is that it only allows you to define a single analyzer for names, and that there’s no way to provide parameters to filters.
4 – Another possibility is that we simply don’t expose a Global Properties API for this, but rather provide some way to make it configurable from a module. Maybe Analyzers could be created in Spring Components, which the thing that initializes the BaseOpenmrsObject analyzers would know about via Spring magic? Or would it work for modules to simply use the Hibernate Search Programmatic API (or some abstraction thereof) in their Activators?