1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.cms.taglibs.util;
35
36 import info.magnolia.cms.core.Content;
37 import info.magnolia.cms.core.ItemType;
38 import info.magnolia.cms.core.NodeData;
39
40 import java.io.IOException;
41 import java.util.ArrayList;
42 import java.util.Collection;
43 import java.util.Iterator;
44 import java.util.regex.Pattern;
45
46 import javax.jcr.PropertyType;
47 import javax.servlet.jsp.JspException;
48 import javax.servlet.jsp.JspWriter;
49 import javax.servlet.jsp.tagext.TagSupport;
50
51 import org.apache.commons.lang.ArrayUtils;
52 import org.apache.commons.lang.StringUtils;
53 import org.apache.commons.lang.exception.NestableRuntimeException;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 public class SearchResultSnippetTag extends TagSupport {
71 private static final Pattern HTML_STRIP = Pattern.compile("<.*?>", Pattern.DOTALL);
72
73 private static final Logger log = LoggerFactory.getLogger(SearchResultSnippetTag.class);
74
75
76
77
78 private Content page;
79
80
81
82
83 private String query;
84
85
86
87
88 private int chars = 100;
89
90
91
92
93 private int maxSnippets = 3;
94
95
96
97
98
99 public void setQuery(String query) {
100 this.query = query;
101 }
102
103
104
105
106
107 public void setChars(int chars) {
108 this.chars = chars;
109 }
110
111
112
113
114
115 public void setMaxSnippets(int maxSnippets) {
116 this.maxSnippets = maxSnippets;
117 }
118
119
120
121
122
123 public void setPage(Content page) {
124 this.page = page;
125 }
126
127
128
129
130 public int doStartTag() throws JspException {
131
132 JspWriter out = this.pageContext.getOut();
133 try {
134 Iterator iterator = getSnippets().iterator();
135 while (iterator.hasNext()) {
136 out.println(iterator.next());
137 }
138 }
139 catch (IOException e) {
140
141 throw new NestableRuntimeException(e);
142 }
143 return EVAL_PAGE;
144 }
145
146
147
148
149
150
151
152
153
154
155 public Collection getSnippets() {
156
157 log.debug("collecting snippets");
158
159 Collection snippets = new ArrayList();
160 String[] searchTerms = StringUtils.split(this.query);
161
162 Collection paragraphCollections = this.page.getChildren(ItemType.CONTENTNODE);
163
164 Iterator iterator = paragraphCollections.iterator();
165 outer : while (iterator.hasNext()) {
166 Content paragraphCollection = (Content) iterator.next();
167
168 Collection paragraphs = paragraphCollection.getChildren();
169
170 Iterator parIterator = paragraphs.iterator();
171 while (parIterator.hasNext()) {
172 Content paragraph = (Content) parIterator.next();
173
174 log.debug("Iterating on paragraph {}", paragraph);
175
176 Collection properties = paragraph.getNodeDataCollection();
177
178 Iterator dataIterator = properties.iterator();
179 while (dataIterator.hasNext()) {
180 NodeData property = (NodeData) dataIterator.next();
181 if (property.getType() != PropertyType.BINARY) {
182
183 String resultString = property.getString();
184
185 log.debug("Iterating on property {}", property.getName());
186 log.debug("Property value is {}", resultString);
187
188
189
190 if (resultString.length() < 20) {
191 continue;
192 }
193
194 for (int j = 0; j < searchTerms.length; j++) {
195 String searchTerm = StringUtils.lowerCase(searchTerms[j]);
196
197
198 if (!ArrayUtils.contains(SimpleSearchTag.KEYWORDS, searchTerm) && searchTerm.length() > 2) {
199
200 log.debug("Looking for search term [{}] in [{}]", searchTerm, resultString);
201
202
203
204 if (!StringUtils.contains(resultString.toLowerCase(), searchTerm)) {
205 continue;
206 }
207
208
209 resultString = stripHtmlTags(resultString);
210
211
212 int pos = resultString.toLowerCase().indexOf(searchTerm);
213 if (pos > -1) {
214
215 int posEnd = pos + searchTerm.length();
216 int from = (pos - chars / 2);
217 if (from < 0) {
218 from = 0;
219 }
220
221 int to = from + chars;
222 if (to > resultString.length()) {
223 to = resultString.length();
224 }
225
226 StringBuffer snippet = new StringBuffer();
227
228 snippet.append(StringUtils.substring(resultString, from, pos));
229 snippet.append("<strong>");
230 snippet.append(StringUtils.substring(resultString, pos, posEnd));
231 snippet.append("</strong>");
232 snippet.append(StringUtils.substring(resultString, posEnd, to));
233
234 if (from > 0) {
235 snippet.insert(0, "... ");
236 }
237 if (to < resultString.length()) {
238 snippet.append("... ");
239 }
240
241 log.debug("Search term found, adding snippet {}", snippet);
242
243 snippets.add(snippet);
244 if (snippets.size() >= this.maxSnippets) {
245
246 log.debug("Maximum number of snippets ({}) reached, exiting",
247 Integer.toString(this.maxSnippets));
248
249 break outer;
250 }
251 }
252 }
253 }
254 }
255 }
256 }
257 }
258
259 return snippets;
260 }
261
262
263
264
265
266 protected String stripHtmlTags(String input) {
267 return HTML_STRIP.matcher(input).replaceAll("");
268 }
269
270
271
272
273 public void release() {
274 this.query = null;
275 this.page = null;
276 this.chars = 100;
277 this.maxSnippets = 3;
278 super.release();
279 }
280
281 }