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