package org.rhq.coregui.client.util.effects; import java.util.ArrayList; import java.util.List; public class ColoringUtility { public static String highlight(String data, String filter) { return highlight(data, filter, "yellow"); } public static String highlight(String data, String filter, String color) { String lowerData = data.toLowerCase(); String lowerFilter = filter.toLowerCase(); List<Integer> matchingIndices = new ArrayList<Integer>(); int startFrom = -1; while ((startFrom = lowerData.indexOf(lowerFilter, startFrom + 1)) != -1) { matchingIndices.add(startFrom); } String style = "background-color: " + color; for (int i = matchingIndices.size() - 1; i >= 0; i--) { Integer nextMatchingIndex = matchingIndices.get(i); data = decorate(data, style, nextMatchingIndex, nextMatchingIndex + filter.length()); } return data; } private static String decorate(String data, String style, int startIndex, int endIndex) { if (startIndex == -1 || (startIndex == endIndex)) { return data; // no match or zero-width match } String[] words = data.split("<br/>"); int counter = 0; int wordIndex = 0; int letterIndex = 0; StringBuilder results = new StringBuilder(); while (counter < startIndex) { if (wordIndex == words.length) { break; } if (letterIndex < words[wordIndex].length()) { // more letters left in the current word? results.append(words[wordIndex].charAt(letterIndex)); // append the next char of the current word letterIndex++; // move to the next char in the current word counter++; // only move counter forward when we've added non-BR chars to the results } else { // next word results.append("<br/>"); // put the break point back in between words letterIndex = 0; // point to the first char wordIndex++; // of the next word } } // we're at start index, wrap all words and word fragments in the specified style up to endIndex results.append("<span style=\"" + style + "\">"); // seed action while (counter < endIndex) { if (wordIndex == words.length) { break; } if (letterIndex < words[wordIndex].length()) { // more letters left in the current word? results.append(words[wordIndex].charAt(letterIndex)); // append the next char of the current word letterIndex++; // move to the next char in the current word counter++; // only move counter forward when we've added non-BR chars to the results } else { // next word results.append("</span>"); // close the previous word, we don't highlight breaks results.append("<br/>"); // put the break point back in between words letterIndex = 0; // point to the first char wordIndex++; // of the next word results.append("<span style=\"" + style + "\">"); // prepare for next word } } results.append("</span>"); // end last dangling span // append the rest of the current word fragment, if any if (wordIndex != words.length) { results.append(words[wordIndex].substring(letterIndex)); } // append the rest of the words while (++wordIndex < words.length) { results.append("<br/>"); // put the break point back in between words results.append(words[wordIndex]); } return results.toString(); } }