Groovy find and replace

Calling on all groovy experts

Been attempting to do a find and replace in a hook_post_process script. I’m essentially trying to recreate what boldicize tag does with a few little difference. I’ll explain why I can’t just use boldicize further down in the post.

Collection is an XML collection, where all the xml elements are mapped to metadata classes. In this example I’m using the class ‘T’. I want to be able to search the metadata class for any of the original search terms, and if found, wrap them in HTML strong tags so when the metadata ‘T’ class is rendered on the results page it’s bolded.

Matching should be for any term in the original query, but needs to match on partial words (more on why later), but should only match start of word boundaries.

What I’ve come up with so far is this:

transaction?.response?.resultPacket?.results.each() {
  it.metaData["T"] = it.metaData["T"].replaceAll("(?i)(" + transaction.question.inputParameterMap["query"].replaceAll(" ", "|^") + ")", { full, word -> "<strong>${full}</strong>" } );
}

So it’s all working beautifully except that the rendering isn’t preserving the original capitalisation. It seems by using (?i) it’s changed the capitalisation of the original text. But if I remove (?i) I don’t get a case-insensitive match.

Apparently this is expected when using (?i) and instead I should be setting options on the Matcher or RegEx object itself, however there seems no option to do that in groovy, and when I’ve tried to use a Java-only solution the hook script fails to run - assume Java error.

So why am I not just using boldicize? The original query gets altered on the way in (via another hook script) that adds wildcard after every search term, and significantly alters the search scope to one of several, pre-populated search fields. Boldicize will usually just match on whole words only, I need this to match on partial (as that is what the search does). Additionally, I need to be able to control when a specific metadata field is being boldicized depending on whether or not that field was searched for in the original search.

Another option I’m exploring is modifying the regex pattern used by boldicize. I have done this before but it wasn’t my cup of tea. Will explore it again. Even if I get this to work it seems the results page will have a lot of “if search type = this, boldicize that and that but not that”, etc.

Thanks

Answering my own question:

Have now got it working by altering the regex used by boldicize, this is my solution:

transaction.response.resultPacket.queryHighlightRegex = "(i?)\\b" + transaction.question.inputParameterMap["query"].replaceAll(" ", "|\\\\b");

Downside is that now the logic of when to boldicize and when not to based on the search type (and subsequent search scoping) has to be moved the results design file, which is possible, but I was hoping to keep it in the hook script, slightly less confusing code to maintain that way.

Hi Quimby,

Thanks for your post and providing your solution.

You have raised some interesting points in regards query highlighting. I have raised some of these points to be considered in our product roadmap.