001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.search;
016    
017    import com.liferay.portal.kernel.dao.search.SearchContainer;
018    import com.liferay.portal.kernel.util.GetterUtil;
019    import com.liferay.portal.kernel.util.HttpUtil;
020    import com.liferay.portal.kernel.util.PropsUtil;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.StringUtil;
023    import com.liferay.portal.kernel.util.WebKeys;
024    import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
025    import com.liferay.portal.kernel.xml.Document;
026    import com.liferay.portal.kernel.xml.Element;
027    import com.liferay.portal.kernel.xml.SAXReaderUtil;
028    import com.liferay.portal.model.Layout;
029    import com.liferay.portal.service.LayoutLocalServiceUtil;
030    import com.liferay.portal.service.UserLocalServiceUtil;
031    import com.liferay.portal.theme.ThemeDisplay;
032    import com.liferay.portal.util.PortalUtil;
033    import com.liferay.portlet.PortletURLFactoryUtil;
034    
035    import java.util.Date;
036    
037    import javax.portlet.PortletMode;
038    import javax.portlet.PortletRequest;
039    import javax.portlet.PortletURL;
040    import javax.portlet.WindowState;
041    
042    import javax.servlet.http.HttpServletRequest;
043    
044    /**
045     * @author Charles May
046     * @author Brian Wing Shun Chan
047     */
048    public abstract class BaseOpenSearchImpl implements OpenSearch {
049    
050            public boolean isEnabled() {
051                    return _enabled;
052            }
053    
054            public abstract String search(
055                            HttpServletRequest request, long groupId, long userId,
056                            String keywords, int startPage, int itemsPerPage, String format)
057                    throws SearchException;
058    
059            public String search(
060                            HttpServletRequest request, long userId, String keywords,
061                            int startPage, int itemsPerPage, String format)
062                    throws SearchException {
063    
064                    return search(
065                            request, 0, userId, keywords, startPage, itemsPerPage, format);
066            }
067    
068            public String search(HttpServletRequest request, String url)
069                    throws SearchException {
070    
071                    try {
072                            long userId = PortalUtil.getUserId(request);
073    
074                            if (userId == 0) {
075                                    long companyId = PortalUtil.getCompanyId(request);
076    
077                                    userId = UserLocalServiceUtil.getDefaultUserId(companyId);
078                            }
079    
080                            String keywords = GetterUtil.getString(
081                                    HttpUtil.getParameter(url, "keywords", false));
082                            int startPage = GetterUtil.getInteger(
083                                    HttpUtil.getParameter(url, "p", false), 1);
084                            int itemsPerPage = GetterUtil.getInteger(
085                                    HttpUtil.getParameter(url, "c", false),
086                                    SearchContainer.DEFAULT_DELTA);
087                            String format = GetterUtil.getString(
088                                    HttpUtil.getParameter(url, "format", false));
089    
090                            return search(
091                                    request, userId, keywords, startPage, itemsPerPage, format);
092                    }
093                    catch (SearchException se) {
094                            throw se;
095                    }
096                    catch (Exception e) {
097                            throw new SearchException(e);
098                    }
099            }
100    
101            protected void addSearchResult(
102                    Element root, long groupId, String entryClassName, long entryClassPK,
103                    String title, String link, Date updated, String summary, double score,
104                    String format) {
105    
106                    addSearchResult(
107                            root, groupId, entryClassName, entryClassPK, title, link, updated,
108                            summary, new String[0], 0, score, format);
109            }
110    
111            protected void addSearchResult(
112                    Element root, long groupId, String entryClassName, long entryClassPK,
113                    String title, String link, Date updated, String summary, String[] tags,
114                    double ratings, double score, String format) {
115    
116                    if (format.equals("rss")) {
117                            addSearchResultRSS(
118                                    root, groupId, entryClassName, entryClassPK, title, link,
119                                    updated, summary, tags, ratings, score);
120                    }
121                    else {
122                            addSearchResultAtom(
123                                    root, groupId, entryClassName, entryClassPK, title, link,
124                                    updated, summary, tags, ratings, score);
125                    }
126            }
127    
128            protected void addSearchResultAtom(
129                    Element root, long groupId, String entryClassName, long entryClassPK,
130                    String title, String link, Date updated, String summary, String[] tags,
131                    double ratings, double score) {
132    
133                    // entry
134    
135                    Element entry = OpenSearchUtil.addElement(
136                            root, "entry", OpenSearchUtil.DEFAULT_NAMESPACE);
137    
138                    // groupId
139    
140                    OpenSearchUtil.addElement(
141                            entry, "groupId", OpenSearchUtil.LIFERAY_NAMESPACE, groupId);
142    
143                    // entryClassName
144    
145                    OpenSearchUtil.addElement(
146                            entry, "entryClassName", OpenSearchUtil.LIFERAY_NAMESPACE,
147                            entryClassName);
148    
149                    // entryClassPK
150    
151                    OpenSearchUtil.addElement(
152                            entry, "entryClassPK", OpenSearchUtil.LIFERAY_NAMESPACE,
153                            entryClassPK);
154    
155                    // title
156    
157                    OpenSearchUtil.addElement(
158                            entry, "title", OpenSearchUtil.DEFAULT_NAMESPACE, title);
159    
160                    // link
161    
162                    Element entryLink = OpenSearchUtil.addElement(
163                            entry, "link", OpenSearchUtil.DEFAULT_NAMESPACE);
164    
165                    entryLink.addAttribute("href", link);
166    
167                    // id
168    
169                    OpenSearchUtil.addElement(
170                            entry, "id", OpenSearchUtil.DEFAULT_NAMESPACE,
171                            "urn:uuid:" + PortalUUIDUtil.generate());
172    
173                    // updated
174    
175                    OpenSearchUtil.addElement(
176                            entry, "updated", OpenSearchUtil.DEFAULT_NAMESPACE, updated);
177    
178                    // summary
179    
180                    OpenSearchUtil.addElement(
181                            entry, "summary", OpenSearchUtil.DEFAULT_NAMESPACE, summary);
182    
183                    // tags
184    
185                    OpenSearchUtil.addElement(
186                            entry, "tags", OpenSearchUtil.DEFAULT_NAMESPACE,
187                            StringUtil.merge(tags));
188    
189                    // ratings
190    
191                    OpenSearchUtil.addElement(
192                            entry, "ratings", OpenSearchUtil.DEFAULT_NAMESPACE, ratings);
193    
194                    // relevance:score
195    
196                    OpenSearchUtil.addElement(
197                            entry, "score", OpenSearchUtil.RELEVANCE_NAMESPACE, score);
198            }
199    
200            protected void addSearchResultRSS(
201                    Element root, long groupId, String entryClassName, long entryClassPK,
202                    String title, String link, Date updated, String summary, String[] tags,
203                    double ratings, double score) {
204    
205                    // item
206    
207                    Element item = root.addElement("item");
208    
209                    // groupId
210    
211                    OpenSearchUtil.addElement(
212                            item, "groupId", OpenSearchUtil.LIFERAY_NAMESPACE, groupId);
213    
214                    // entryClassName
215    
216                    OpenSearchUtil.addElement(
217                            item, "entryClassName", OpenSearchUtil.LIFERAY_NAMESPACE,
218                            entryClassName);
219    
220                    // entryClassPK
221    
222                    OpenSearchUtil.addElement(
223                            item, "entryClassPK", OpenSearchUtil.LIFERAY_NAMESPACE,
224                            entryClassPK);
225    
226                    // title
227    
228                    OpenSearchUtil.addElement(
229                            item, "title", OpenSearchUtil.NO_NAMESPACE, title);
230    
231                    // link
232    
233                    OpenSearchUtil.addElement(
234                            item, "link", OpenSearchUtil.NO_NAMESPACE, link);
235    
236                    // summary
237    
238                    OpenSearchUtil.addElement(
239                            item, "description", OpenSearchUtil.NO_NAMESPACE, summary);
240    
241                    // tags
242    
243                    OpenSearchUtil.addElement(
244                            item, "tags", OpenSearchUtil.NO_NAMESPACE, StringUtil.merge(tags));
245    
246                    // ratings
247    
248                    OpenSearchUtil.addElement(
249                            item, "ratings", OpenSearchUtil.NO_NAMESPACE, ratings);
250    
251                    // relevance:score
252    
253                    OpenSearchUtil.addElement(
254                            item, "score", OpenSearchUtil.RELEVANCE_NAMESPACE, score);
255            }
256    
257            /**
258             * @deprecated
259             */
260            protected Object[] addSearchResults(
261                    String keywords, int startPage, int itemsPerPage, int total, int start,
262                    String title, String searchPath, String format,
263                    ThemeDisplay themeDisplay) {
264    
265                    return addSearchResults(
266                            new String[0], keywords, startPage, itemsPerPage, total, start,
267                            title, searchPath, format, themeDisplay);
268            }
269    
270            protected Object[] addSearchResults(
271                    String[] queryTerms, String keywords, int startPage, int itemsPerPage,
272                    int total, int start, String title, String searchPath, String format,
273                    ThemeDisplay themeDisplay) {
274    
275                    int totalPages = 0;
276    
277                    if (total % itemsPerPage == 0) {
278                            totalPages = total / itemsPerPage;
279                    }
280                    else {
281                            totalPages = (total / itemsPerPage) + 1;
282                    }
283    
284                    int previousPage = startPage - 1;
285                    int nextPage = startPage + 1;
286    
287                    Document doc = SAXReaderUtil.createDocument();
288    
289                    if (format.equals("rss")) {
290                            return addSearchResultsRSS(
291                                    doc, queryTerms, keywords, startPage, itemsPerPage, total,
292                                    start, totalPages, previousPage, nextPage, title, searchPath,
293                                    themeDisplay);
294                    }
295                    else {
296                            return addSearchResultsAtom(
297                                    doc, queryTerms, keywords, startPage, itemsPerPage, total,
298                                    start, totalPages, previousPage, nextPage, title, searchPath,
299                                    themeDisplay);
300                    }
301            }
302    
303            protected Object[] addSearchResultsAtom(
304                    Document doc, String[] queryTerms, String keywords, int startPage,
305                    int itemsPerPage, int total, int start, int totalPages,
306                    int previousPage, int nextPage, String title, String searchPath,
307                    ThemeDisplay themeDisplay) {
308    
309                    // feed
310    
311                    Element root = doc.addElement("feed");
312    
313                    root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.DEFAULT_NAMESPACE));
314                    root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.OS_NAMESPACE));
315                    root.add(
316                            OpenSearchUtil.getNamespace(OpenSearchUtil.RELEVANCE_NAMESPACE));
317    
318                    // title
319    
320                    OpenSearchUtil.addElement(
321                            root, "title", OpenSearchUtil.DEFAULT_NAMESPACE, title);
322    
323                    // updated
324    
325                    OpenSearchUtil.addElement(
326                            root, "updated", OpenSearchUtil.DEFAULT_NAMESPACE, new Date());
327    
328                    // author
329    
330                    Element author = OpenSearchUtil.addElement(
331                            root, "author", OpenSearchUtil.DEFAULT_NAMESPACE);
332    
333                    // name
334    
335                    OpenSearchUtil.addElement(
336                            author, "name", OpenSearchUtil.DEFAULT_NAMESPACE,
337                            themeDisplay.getUserId());
338    
339                    // id
340    
341                    OpenSearchUtil.addElement(
342                            root, "id", OpenSearchUtil.DEFAULT_NAMESPACE,
343                            "urn:uuid:" + PortalUUIDUtil.generate());
344    
345                    // queryTerms
346    
347                    OpenSearchUtil.addElement(
348                            root, "queryTerms", OpenSearchUtil.DEFAULT_NAMESPACE,
349                            StringUtil.merge(queryTerms, StringPool.COMMA_AND_SPACE));
350    
351                    // opensearch:totalResults
352    
353                    OpenSearchUtil.addElement(
354                            root, "totalResults", OpenSearchUtil.OS_NAMESPACE, total);
355    
356                    // opensearch:startIndex
357    
358                    OpenSearchUtil.addElement(
359                            root, "startIndex", OpenSearchUtil.OS_NAMESPACE, start + 1);
360    
361                    // opensearch:itemsPerPage
362    
363                    OpenSearchUtil.addElement(
364                            root, "itemsPerPage", OpenSearchUtil.OS_NAMESPACE, itemsPerPage);
365    
366                    // opensearch:Query
367    
368                    Element query = OpenSearchUtil.addElement(
369                            root, "Query", OpenSearchUtil.OS_NAMESPACE);
370    
371                    query.addAttribute("role", "request");
372                    query.addAttribute("searchTerms", keywords);
373                    query.addAttribute("startPage", String.valueOf(startPage));
374    
375                    // links
376    
377                    String searchURL = themeDisplay.getURLPortal() + searchPath;
378    
379                    OpenSearchUtil.addLink(
380                            root, searchURL, "self", keywords, startPage, itemsPerPage);
381                    OpenSearchUtil.addLink(
382                            root, searchURL, "first", keywords, 1, itemsPerPage);
383    
384                    if (previousPage > 0) {
385                            OpenSearchUtil.addLink(
386                                    root, searchURL, "previous", keywords, previousPage,
387                                    itemsPerPage);
388                    }
389    
390                    if (nextPage <= totalPages) {
391                            OpenSearchUtil.addLink(
392                                    root, searchURL, "next", keywords, nextPage, itemsPerPage);
393                    }
394    
395                    OpenSearchUtil.addLink(
396                            root, searchURL, "last", keywords, totalPages, itemsPerPage);
397    
398                    Element link = OpenSearchUtil.addElement(
399                            root, "link", OpenSearchUtil.DEFAULT_NAMESPACE);
400    
401                    link.addAttribute("rel", "search");
402                    link.addAttribute("href", searchPath + "_description.xml");
403                    link.addAttribute("type", "application/opensearchdescription+xml");
404    
405                    return new Object[] {doc, root};
406            }
407    
408            protected Object[] addSearchResultsRSS(
409                    Document doc, String[] queryTerms, String keywords, int startPage,
410                    int itemsPerPage, int total, int start, int totalPages,
411                    int previousPage, int nextPage, String title, String searchPath,
412                    ThemeDisplay themeDisplay) {
413    
414                    // rss
415    
416                    Element root = doc.addElement("rss");
417    
418                    root.addAttribute("version", "2.0");
419                    root.add(
420                            SAXReaderUtil.createNamespace(
421                                    "atom", "http://www.w3.org/2005/Atom"));
422                    root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.OS_NAMESPACE));
423                    root.add(
424                            OpenSearchUtil.getNamespace(OpenSearchUtil.RELEVANCE_NAMESPACE));
425    
426                    // channel
427    
428                    Element channel = root.addElement("channel");
429    
430                    // title
431    
432                    OpenSearchUtil.addElement(
433                            channel, "title", OpenSearchUtil.NO_NAMESPACE, title);
434    
435                    // link
436    
437                    OpenSearchUtil.addElement(
438                            channel, "link", OpenSearchUtil.NO_NAMESPACE,
439                            themeDisplay.getURLPortal() + searchPath);
440    
441                    // description
442    
443                    OpenSearchUtil.addElement(
444                            channel, "description", OpenSearchUtil.NO_NAMESPACE, title);
445    
446                    // queryTerms
447    
448                    OpenSearchUtil.addElement(
449                            channel, "queryTerms", OpenSearchUtil.NO_NAMESPACE,
450                            StringUtil.merge(queryTerms, StringPool.COMMA_AND_SPACE));
451    
452                    // opensearch:totalResults
453    
454                    OpenSearchUtil.addElement(
455                            channel, "totalResults", OpenSearchUtil.OS_NAMESPACE, total);
456    
457                    // opensearch:startIndex
458    
459                    OpenSearchUtil.addElement(
460                            channel, "startIndex", OpenSearchUtil.OS_NAMESPACE, start + 1);
461    
462                    // opensearch:itemsPerPage
463    
464                    OpenSearchUtil.addElement(
465                            channel, "itemsPerPage", OpenSearchUtil.OS_NAMESPACE, itemsPerPage);
466    
467                    // opensearch:Query
468    
469                    Element query = OpenSearchUtil.addElement(
470                            channel, "Query", OpenSearchUtil.OS_NAMESPACE);
471    
472                    query.addAttribute("role", "request");
473                    query.addAttribute("searchTerms", keywords);
474                    query.addAttribute("startPage", String.valueOf(startPage));
475    
476                    return new Object[] {doc, channel};
477            }
478    
479            protected PortletURL getPortletURL(
480                            HttpServletRequest request, String portletId)
481                    throws Exception {
482    
483                    return getPortletURL(request, portletId, 0);
484            }
485    
486            protected PortletURL getPortletURL(
487                            HttpServletRequest request, String portletId, long groupId)
488                    throws Exception {
489    
490                    long plid = LayoutLocalServiceUtil.getDefaultPlid(
491                            groupId, false, portletId);
492    
493                    if (plid == 0) {
494                            plid = LayoutLocalServiceUtil.getDefaultPlid(
495                                    groupId, true, portletId);
496                    }
497    
498                    if (plid == 0) {
499                            Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
500    
501                            if (layout != null) {
502                                    plid = layout.getPlid();
503                            }
504                    }
505    
506                    PortletURL portletURL = PortletURLFactoryUtil.create(
507                            request, portletId, plid, PortletRequest.RENDER_PHASE);
508    
509                    portletURL.setWindowState(WindowState.MAXIMIZED);
510                    portletURL.setPortletMode(PortletMode.VIEW);
511    
512                    return portletURL;
513            }
514    
515            private boolean _enabled = GetterUtil.getBoolean(
516                    PropsUtil.get(getClass().getName()), true);
517    
518    }