1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.search;
24  
25  import com.liferay.portal.SystemException;
26  import com.liferay.portal.kernel.dao.search.SearchContainer;
27  import com.liferay.portal.kernel.search.OpenSearch;
28  import com.liferay.portal.kernel.search.SearchException;
29  import com.liferay.portal.kernel.util.GetterUtil;
30  import com.liferay.portal.kernel.util.HttpUtil;
31  import com.liferay.portal.kernel.util.StringUtil;
32  import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
33  import com.liferay.portal.kernel.xml.Document;
34  import com.liferay.portal.kernel.xml.Element;
35  import com.liferay.portal.kernel.xml.SAXReaderUtil;
36  import com.liferay.portal.model.Layout;
37  import com.liferay.portal.service.LayoutLocalServiceUtil;
38  import com.liferay.portal.service.UserLocalServiceUtil;
39  import com.liferay.portal.theme.ThemeDisplay;
40  import com.liferay.portal.util.PortalUtil;
41  import com.liferay.portal.util.WebKeys;
42  import com.liferay.portlet.PortletURLImpl;
43  
44  import java.util.Date;
45  
46  import javax.portlet.PortletMode;
47  import javax.portlet.PortletModeException;
48  import javax.portlet.PortletRequest;
49  import javax.portlet.PortletURL;
50  import javax.portlet.WindowState;
51  import javax.portlet.WindowStateException;
52  
53  import javax.servlet.http.HttpServletRequest;
54  
55  /**
56   * <a href="BaseOpenSearchImpl.java.html"><b><i>View Source</i></b></a>
57   *
58   * @author Charles May
59   * @author Brian Wing Shun Chan
60   *
61   */
62  public abstract class BaseOpenSearchImpl implements OpenSearch {
63  
64      public boolean isEnabled() {
65          return true;
66      }
67  
68      public String search(HttpServletRequest request, String url)
69          throws SearchException {
70  
71          try {
72              long userId = PortalUtil.getUserId(request);
73  
74              if (userId == 0) {
75                  long companyId = PortalUtil.getCompanyId(request);
76  
77                  userId = UserLocalServiceUtil.getDefaultUserId(companyId);
78              }
79  
80              String keywords = GetterUtil.getString(
81                  HttpUtil.getParameter(url, "keywords", false));
82              int startPage = GetterUtil.getInteger(
83                  HttpUtil.getParameter(url, "p", false), 1);
84              int itemsPerPage = GetterUtil.getInteger(
85                  HttpUtil.getParameter(url, "c", false),
86                  SearchContainer.DEFAULT_DELTA);
87              String format = GetterUtil.getString(
88                  HttpUtil.getParameter(url, "format", false));
89  
90              return search(
91                  request, userId, keywords, startPage, itemsPerPage, format);
92          }
93          catch (SearchException se) {
94              throw se;
95          }
96          catch (Exception e) {
97              throw new SearchException(e);
98          }
99      }
100 
101     public String search(
102             HttpServletRequest request, long userId, String keywords,
103             int startPage, int itemsPerPage, String format)
104         throws SearchException {
105 
106         return search(
107             request, 0, userId, keywords, startPage, itemsPerPage, format);
108     }
109 
110     public abstract String search(
111             HttpServletRequest request, long groupId, long userId,
112             String keywords, int startPage, int itemsPerPage, String format)
113         throws SearchException;
114 
115     protected void addSearchResult(
116         Element root, String title, String link, Date updated,
117         String summary, double score, String format) {
118 
119         addSearchResult(
120             root, title, link, updated, summary, new String[0], 0, score,
121             format);
122     }
123 
124     protected void addSearchResult(
125         Element root, String title, String link, Date updated, String summary,
126         String[] tags, double ratings, double score, String format) {
127 
128         if (format.equals("rss")) {
129             addSearchResultRSS(
130                 root, title, link, updated, summary, tags, ratings, score);
131         }
132         else {
133             addSearchResultAtom(
134                 root, title, link, updated, summary, tags, ratings, score);
135         }
136     }
137 
138     protected void addSearchResultAtom(
139         Element root, String title, String link, Date updated, String summary,
140         String[] tags, double ratings, double score) {
141 
142         // entry
143 
144         Element entry = OpenSearchUtil.addElement(
145             root, "entry", OpenSearchUtil.DEFAULT_NAMESPACE);
146 
147         // title
148 
149         OpenSearchUtil.addElement(
150             entry, "title", OpenSearchUtil.DEFAULT_NAMESPACE, title);
151 
152         // link
153 
154         Element entryLink = OpenSearchUtil.addElement(
155             entry, "link", OpenSearchUtil.DEFAULT_NAMESPACE);
156 
157         entryLink.addAttribute("href", link);
158 
159         // id
160 
161         OpenSearchUtil.addElement(
162             entry, "id", OpenSearchUtil.DEFAULT_NAMESPACE,
163             "urn:uuid:" + PortalUUIDUtil.generate());
164 
165         // updated
166 
167         OpenSearchUtil.addElement(
168             entry, "updated", OpenSearchUtil.DEFAULT_NAMESPACE, updated);
169 
170         // summary
171 
172         OpenSearchUtil.addElement(
173             entry, "summary", OpenSearchUtil.DEFAULT_NAMESPACE, summary);
174 
175         // tags
176 
177         OpenSearchUtil.addElement(
178             entry, "tags", OpenSearchUtil.DEFAULT_NAMESPACE,
179             StringUtil.merge(tags));
180 
181         // ratings
182 
183         OpenSearchUtil.addElement(
184             entry, "ratings", OpenSearchUtil.DEFAULT_NAMESPACE, ratings);
185 
186         // relevance:score
187 
188         OpenSearchUtil.addElement(
189             entry, "score", OpenSearchUtil.RELEVANCE_NAMESPACE, score);
190     }
191 
192     protected void addSearchResultRSS(
193         Element root, String title, String link, Date updated, String summary,
194         String[] tags, double ratings, double score) {
195 
196         // item
197 
198         Element item = root.addElement("item");
199 
200         // title
201 
202         OpenSearchUtil.addElement(
203             item, "title", OpenSearchUtil.NO_NAMESPACE, title);
204 
205         // link
206 
207         OpenSearchUtil.addElement(
208             item, "link", OpenSearchUtil.NO_NAMESPACE, link);
209 
210         // summary
211 
212         OpenSearchUtil.addElement(
213             item, "description", OpenSearchUtil.NO_NAMESPACE, summary);
214 
215         // tags
216 
217         OpenSearchUtil.addElement(
218             item, "tags", OpenSearchUtil.NO_NAMESPACE, StringUtil.merge(tags));
219 
220         // ratings
221 
222         OpenSearchUtil.addElement(
223             item, "ratings", OpenSearchUtil.NO_NAMESPACE, ratings);
224 
225         // relevance:score
226 
227         OpenSearchUtil.addElement(
228             item, "score", OpenSearchUtil.RELEVANCE_NAMESPACE, score);
229     }
230 
231     protected Object[] addSearchResults(
232         String keywords, int startPage, int itemsPerPage, int total, int start,
233         String title, String searchPath, String format,
234         ThemeDisplay themeDisplay) {
235 
236         int totalPages = 0;
237 
238         if (total % itemsPerPage == 0) {
239             totalPages = total / itemsPerPage;
240         }
241         else {
242             totalPages = (total / itemsPerPage) + 1;
243         }
244 
245         int previousPage = startPage - 1;
246         int nextPage = startPage + 1;
247 
248         Document doc = SAXReaderUtil.createDocument();
249 
250         if (format.equals("rss")) {
251             return addSearchResultsRSS(
252                 doc, keywords, startPage, itemsPerPage, total, start,
253                 totalPages, previousPage, nextPage, title, searchPath,
254                 themeDisplay);
255         }
256         else {
257             return addSearchResultsAtom(
258                 doc, keywords, startPage, itemsPerPage, total, start,
259                 totalPages, previousPage, nextPage, title, searchPath,
260                 themeDisplay);
261         }
262     }
263 
264     protected Object[] addSearchResultsAtom(
265         Document doc, String keywords, int startPage, int itemsPerPage,
266         int total, int start, int totalPages, int previousPage, int nextPage,
267         String title, String searchPath, ThemeDisplay themeDisplay) {
268 
269         // feed
270 
271         Element root = doc.addElement("feed");
272 
273         root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.DEFAULT_NAMESPACE));
274         root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.OS_NAMESPACE));
275         root.add(
276             OpenSearchUtil.getNamespace(OpenSearchUtil.RELEVANCE_NAMESPACE));
277 
278         // title
279 
280         OpenSearchUtil.addElement(
281             root, "title", OpenSearchUtil.DEFAULT_NAMESPACE, title);
282 
283         // updated
284 
285         OpenSearchUtil.addElement(
286             root, "updated", OpenSearchUtil.DEFAULT_NAMESPACE, new Date());
287 
288         // author
289 
290         Element author = OpenSearchUtil.addElement(
291             root, "author", OpenSearchUtil.DEFAULT_NAMESPACE);
292 
293         // name
294 
295         OpenSearchUtil.addElement(
296             author, "name", OpenSearchUtil.DEFAULT_NAMESPACE,
297             themeDisplay.getUserId());
298 
299         // id
300 
301         OpenSearchUtil.addElement(
302             root, "id", OpenSearchUtil.DEFAULT_NAMESPACE,
303             "urn:uuid:" + PortalUUIDUtil.generate());
304 
305         // opensearch:totalResults
306 
307         OpenSearchUtil.addElement(
308             root, "totalResults", OpenSearchUtil.OS_NAMESPACE, total);
309 
310         // opensearch:startIndex
311 
312         OpenSearchUtil.addElement(
313             root, "startIndex", OpenSearchUtil.OS_NAMESPACE, start + 1);
314 
315         // opensearch:itemsPerPage
316 
317         OpenSearchUtil.addElement(
318             root, "itemsPerPage", OpenSearchUtil.OS_NAMESPACE, itemsPerPage);
319 
320         // opensearch:Query
321 
322         Element query = OpenSearchUtil.addElement(
323             root, "Query", OpenSearchUtil.OS_NAMESPACE);
324 
325         query.addAttribute("role", "request");
326         query.addAttribute("searchTerms", keywords);
327         query.addAttribute("startPage", String.valueOf(startPage));
328 
329         // links
330 
331         String searchURL = themeDisplay.getURLPortal() + searchPath;
332 
333         OpenSearchUtil.addLink(
334             root, searchURL, "self", keywords, startPage, itemsPerPage);
335         OpenSearchUtil.addLink(
336             root, searchURL, "first", keywords, 1, itemsPerPage);
337 
338         if (previousPage > 0) {
339             OpenSearchUtil.addLink(
340                 root, searchURL, "previous", keywords, previousPage,
341                 itemsPerPage);
342         }
343 
344         if (nextPage <= totalPages) {
345             OpenSearchUtil.addLink(
346                 root, searchURL, "next", keywords, nextPage, itemsPerPage);
347         }
348 
349         OpenSearchUtil.addLink(
350             root, searchURL, "last", keywords, totalPages, itemsPerPage);
351 
352         Element link = OpenSearchUtil.addElement(
353             root, "link", OpenSearchUtil.DEFAULT_NAMESPACE);
354 
355         link.addAttribute("rel", "search");
356         link.addAttribute("href", searchPath + "_description.xml");
357         link.addAttribute("type", "application/opensearchdescription+xml");
358 
359         return new Object[] {doc, root};
360     }
361 
362     protected Object[] addSearchResultsRSS(
363         Document doc, String keywords, int startPage, int itemsPerPage,
364         int total, int start, int totalPages, int previousPage, int nextPage,
365         String title, String searchPath, ThemeDisplay themeDisplay) {
366 
367         // rss
368 
369         Element root = doc.addElement("rss");
370 
371         root.addAttribute("version", "2.0");
372         root.add(
373             SAXReaderUtil.createNamespace(
374                 "atom", "http://www.w3.org/2005/Atom"));
375         root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.OS_NAMESPACE));
376         root.add(
377             OpenSearchUtil.getNamespace(OpenSearchUtil.RELEVANCE_NAMESPACE));
378 
379         // channel
380 
381         Element channel = root.addElement("channel");
382 
383         // title
384 
385         OpenSearchUtil.addElement(
386             channel, "title", OpenSearchUtil.NO_NAMESPACE, title);
387 
388         // link
389 
390         OpenSearchUtil.addElement(
391             channel, "link", OpenSearchUtil.NO_NAMESPACE,
392             themeDisplay.getURLPortal() + searchPath);
393 
394         // description
395 
396         OpenSearchUtil.addElement(
397             channel, "description", OpenSearchUtil.NO_NAMESPACE, title);
398 
399         // opensearch:totalResults
400 
401         OpenSearchUtil.addElement(
402             channel, "totalResults", OpenSearchUtil.OS_NAMESPACE, total);
403 
404         // opensearch:startIndex
405 
406         OpenSearchUtil.addElement(
407             channel, "startIndex", OpenSearchUtil.OS_NAMESPACE, start + 1);
408 
409         // opensearch:itemsPerPage
410 
411         OpenSearchUtil.addElement(
412             channel, "itemsPerPage", OpenSearchUtil.OS_NAMESPACE, itemsPerPage);
413 
414         // opensearch:Query
415 
416         Element query = OpenSearchUtil.addElement(
417             channel, "Query", OpenSearchUtil.OS_NAMESPACE);
418 
419         query.addAttribute("role", "request");
420         query.addAttribute("searchTerms", keywords);
421         query.addAttribute("startPage", String.valueOf(startPage));
422 
423         return new Object[] {doc, channel};
424     }
425 
426     protected PortletURL getPortletURL(
427             HttpServletRequest request, String portletId)
428         throws PortletModeException, SystemException, WindowStateException {
429 
430         return getPortletURL(request, portletId, 0);
431     }
432 
433     protected PortletURL getPortletURL(
434             HttpServletRequest request, String portletId, long groupId)
435         throws PortletModeException, SystemException, WindowStateException {
436 
437         long plid = LayoutLocalServiceUtil.getDefaultPlid(
438             groupId, false, portletId);
439 
440         if (plid == 0) {
441             plid = LayoutLocalServiceUtil.getDefaultPlid(
442                 groupId, true, portletId);
443         }
444 
445         if (plid == 0) {
446             Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
447 
448             if (layout != null) {
449                 plid = layout.getPlid();
450             }
451         }
452 
453         PortletURL portletURL = new PortletURLImpl(
454             request, portletId, plid, PortletRequest.RENDER_PHASE);
455 
456         portletURL.setWindowState(WindowState.MAXIMIZED);
457         portletURL.setPortletMode(PortletMode.VIEW);
458 
459         return portletURL;
460     }
461 
462 }