001
014
015 package com.liferay.portal.kernel.search.highlight;
016
017 import com.liferay.portal.kernel.search.Document;
018 import com.liferay.portal.kernel.search.Field;
019 import com.liferay.portal.kernel.util.ArrayUtil;
020 import com.liferay.portal.kernel.util.StringBundler;
021 import com.liferay.portal.kernel.util.StringPool;
022 import com.liferay.portal.kernel.util.StringUtil;
023 import com.liferay.portal.kernel.util.Validator;
024
025 import java.util.Set;
026 import java.util.StringTokenizer;
027 import java.util.regex.Matcher;
028 import java.util.regex.Pattern;
029
030
033 public class HighlightUtil {
034
035 public static final String HIGHLIGHT_TAG_CLOSE = "</liferay-hl>";
036
037 public static final String HIGHLIGHT_TAG_OPEN = "<liferay-hl>";
038
039 public static final String[] HIGHLIGHTS =
040 {"<span class=\"highlight\">", "</span>"};
041
042 public static void addSnippet(
043 Document document, Set<String> queryTerms, String snippet,
044 String snippetFieldName) {
045
046 if (!snippet.equals(StringPool.BLANK)) {
047 Matcher matcher = _pattern.matcher(snippet);
048
049 while (matcher.find()) {
050 queryTerms.add(matcher.group(1));
051 }
052
053 snippet = StringUtil.replace(
054 snippet, HIGHLIGHT_TAG_OPEN, StringPool.BLANK);
055 snippet = StringUtil.replace(
056 snippet, HIGHLIGHT_TAG_CLOSE, StringPool.BLANK);
057 }
058
059 document.addText(
060 Field.SNIPPET.concat(StringPool.UNDERLINE).concat(snippetFieldName),
061 snippet);
062 }
063
064 public static String highlight(String s, String[] queryTerms) {
065 return highlight(s, queryTerms, HIGHLIGHTS[0], HIGHLIGHTS[1]);
066 }
067
068 public static String highlight(
069 String s, String[] queryTerms, String highlight1, String highlight2) {
070
071 if (Validator.isNull(s) || ArrayUtil.isEmpty(queryTerms)) {
072 return s;
073 }
074
075 if (queryTerms.length == 0) {
076 return StringPool.BLANK;
077 }
078
079 StringBundler sb = new StringBundler(2 * queryTerms.length - 1);
080
081 for (int i = 0; i < queryTerms.length; i++) {
082 sb.append(Pattern.quote(queryTerms[i].trim()));
083
084 if ((i + 1) < queryTerms.length) {
085 sb.append(StringPool.PIPE);
086 }
087 }
088
089 int flags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE;
090
091 Pattern pattern = Pattern.compile(sb.toString(), flags);
092
093 return _highlight(s, pattern, highlight1, highlight2);
094 }
095
096 private static String _highlight(
097 String s, Pattern pattern, String highlight1, String highlight2) {
098
099 StringTokenizer st = new StringTokenizer(s);
100
101 if (st.countTokens() == 0) {
102 return StringPool.BLANK;
103 }
104
105 StringBundler sb = new StringBundler(2 * st.countTokens() - 1);
106
107 while (st.hasMoreTokens()) {
108 String token = st.nextToken();
109
110 Matcher matcher = pattern.matcher(token);
111
112 if (matcher.find()) {
113 StringBuffer hightlighted = new StringBuffer();
114
115 while (true) {
116 matcher.appendReplacement(
117 hightlighted,
118 highlight1 + matcher.group() + highlight2);
119
120 if (!matcher.find()) {
121 break;
122 }
123 }
124
125 matcher.appendTail(hightlighted);
126
127 sb.append(hightlighted);
128 }
129 else {
130 sb.append(token);
131 }
132
133 if (st.hasMoreTokens()) {
134 sb.append(StringPool.SPACE);
135 }
136 }
137
138 return sb.toString();
139 }
140
141 private static final Pattern _pattern = Pattern.compile(
142 HIGHLIGHT_TAG_OPEN + "(.*?)" + HIGHLIGHT_TAG_CLOSE);
143
144 }