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