001    /**
002     * Copyright (c) 2000-2013 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.LayoutServiceUtil;
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            @Override
051            public boolean isEnabled() {
052                    return _enabled;
053            }
054    
055            @Override
056            public abstract String search(
057                            HttpServletRequest request, long groupId, long userId,
058                            String keywords, int startPage, int itemsPerPage, String format)
059                    throws SearchException;
060    
061            @Override
062            public String search(
063                            HttpServletRequest request, long userId, String keywords,
064                            int startPage, int itemsPerPage, String format)
065                    throws SearchException {
066    
067                    return search(
068                            request, 0, userId, keywords, startPage, itemsPerPage, format);
069            }
070    
071            @Override
072            public String search(HttpServletRequest request, String url)
073                    throws SearchException {
074    
075                    try {
076                            long userId = PortalUtil.getUserId(request);
077    
078                            if (userId == 0) {
079                                    long companyId = PortalUtil.getCompanyId(request);
080    
081                                    userId = UserLocalServiceUtil.getDefaultUserId(companyId);
082                            }
083    
084                            String keywords = GetterUtil.getString(
085                                    HttpUtil.getParameter(url, "keywords", false));
086                            int startPage = GetterUtil.getInteger(
087                                    HttpUtil.getParameter(url, "p", false), 1);
088                            int itemsPerPage = GetterUtil.getInteger(
089                                    HttpUtil.getParameter(url, "c", false),
090                                    SearchContainer.DEFAULT_DELTA);
091                            String format = GetterUtil.getString(
092                                    HttpUtil.getParameter(url, "format", false));
093    
094                            return search(
095                                    request, userId, keywords, startPage, itemsPerPage, format);
096                    }
097                    catch (SearchException se) {
098                            throw se;
099                    }
100                    catch (Exception e) {
101                            throw new SearchException(e);
102                    }
103            }
104    
105            protected void addSearchResult(
106                    Element root, long groupId, long scopeGroupId, String entryClassName,
107                    long entryClassPK, String title, String link, Date updated,
108                    String summary, double score, String format) {
109    
110                    addSearchResult(
111                            root, groupId, scopeGroupId, entryClassName, entryClassPK, title,
112                            link, updated, summary, new String[0], 0, score, format);
113            }
114    
115            protected void addSearchResult(
116                    Element root, long groupId, long scopeGroupId, String entryClassName,
117                    long entryClassPK, String title, String link, Date updated,
118                    String summary, String[] tags, double ratings, double score,
119                    String format) {
120    
121                    if (format.equals("rss")) {
122                            addSearchResultRSS(
123                                    root, groupId, scopeGroupId, entryClassName, entryClassPK,
124                                    title, link, updated, summary, tags, ratings, score);
125                    }
126                    else {
127                            addSearchResultAtom(
128                                    root, groupId, scopeGroupId, entryClassName, entryClassPK,
129                                    title, link, updated, summary, tags, ratings, score);
130                    }
131            }
132    
133            protected void addSearchResultAtom(
134                    Element root, long groupId, long scopeGroupId, String entryClassName,
135                    long entryClassPK, String title, String link, Date updated,
136                    String summary, String[] tags, double ratings, double score) {
137    
138                    // entry
139    
140                    Element entry = OpenSearchUtil.addElement(
141                            root, "entry", OpenSearchUtil.DEFAULT_NAMESPACE);
142    
143                    // groupId
144    
145                    OpenSearchUtil.addElement(
146                            entry, "groupId", OpenSearchUtil.LIFERAY_NAMESPACE, groupId);
147    
148                    // scopeGroupId
149    
150                    OpenSearchUtil.addElement(
151                            entry, "scopeGroupId", OpenSearchUtil.LIFERAY_NAMESPACE,
152                            scopeGroupId);
153    
154                    // entryClassName
155    
156                    OpenSearchUtil.addElement(
157                            entry, "entryClassName", OpenSearchUtil.LIFERAY_NAMESPACE,
158                            entryClassName);
159    
160                    // entryClassPK
161    
162                    OpenSearchUtil.addElement(
163                            entry, "entryClassPK", OpenSearchUtil.LIFERAY_NAMESPACE,
164                            entryClassPK);
165    
166                    // title
167    
168                    OpenSearchUtil.addElement(
169                            entry, "title", OpenSearchUtil.DEFAULT_NAMESPACE, title);
170    
171                    // link
172    
173                    Element entryLink = OpenSearchUtil.addElement(
174                            entry, "link", OpenSearchUtil.DEFAULT_NAMESPACE);
175    
176                    entryLink.addAttribute("href", link);
177    
178                    // id
179    
180                    OpenSearchUtil.addElement(
181                            entry, "id", OpenSearchUtil.DEFAULT_NAMESPACE,
182                            "urn:uuid:" + PortalUUIDUtil.generate());
183    
184                    // updated
185    
186                    OpenSearchUtil.addElement(
187                            entry, "updated", OpenSearchUtil.DEFAULT_NAMESPACE, updated);
188    
189                    // summary
190    
191                    OpenSearchUtil.addElement(
192                            entry, "summary", OpenSearchUtil.DEFAULT_NAMESPACE, summary);
193    
194                    // tags
195    
196                    OpenSearchUtil.addElement(
197                            entry, "tags", OpenSearchUtil.DEFAULT_NAMESPACE,
198                            StringUtil.merge(tags));
199    
200                    // ratings
201    
202                    OpenSearchUtil.addElement(
203                            entry, "ratings", OpenSearchUtil.DEFAULT_NAMESPACE, ratings);
204    
205                    // relevance:score
206    
207                    OpenSearchUtil.addElement(
208                            entry, "score", OpenSearchUtil.RELEVANCE_NAMESPACE, score);
209            }
210    
211            protected void addSearchResultRSS(
212                    Element root, long groupId, long scopeGroupId, String entryClassName,
213                    long entryClassPK, String title, String link, Date updated,
214                    String summary, String[] tags, double ratings, double score) {
215    
216                    // item
217    
218                    Element item = root.addElement("item");
219    
220                    // groupId
221    
222                    OpenSearchUtil.addElement(
223                            item, "groupId", OpenSearchUtil.LIFERAY_NAMESPACE, groupId);
224    
225                    // scopeGroupId
226    
227                    OpenSearchUtil.addElement(
228                            item, "scopeGroupId", OpenSearchUtil.LIFERAY_NAMESPACE,
229                            scopeGroupId);
230    
231                    // entryClassName
232    
233                    OpenSearchUtil.addElement(
234                            item, "entryClassName", OpenSearchUtil.LIFERAY_NAMESPACE,
235                            entryClassName);
236    
237                    // entryClassPK
238    
239                    OpenSearchUtil.addElement(
240                            item, "entryClassPK", OpenSearchUtil.LIFERAY_NAMESPACE,
241                            entryClassPK);
242    
243                    // title
244    
245                    OpenSearchUtil.addElement(
246                            item, "title", OpenSearchUtil.NO_NAMESPACE, title);
247    
248                    // link
249    
250                    OpenSearchUtil.addElement(
251                            item, "link", OpenSearchUtil.NO_NAMESPACE, link);
252    
253                    // summary
254    
255                    OpenSearchUtil.addElement(
256                            item, "description", OpenSearchUtil.NO_NAMESPACE, summary);
257    
258                    // tags
259    
260                    OpenSearchUtil.addElement(
261                            item, "tags", OpenSearchUtil.NO_NAMESPACE, StringUtil.merge(tags));
262    
263                    // ratings
264    
265                    OpenSearchUtil.addElement(
266                            item, "ratings", OpenSearchUtil.NO_NAMESPACE, ratings);
267    
268                    // relevance:score
269    
270                    OpenSearchUtil.addElement(
271                            item, "score", OpenSearchUtil.RELEVANCE_NAMESPACE, score);
272            }
273    
274            /**
275             * @deprecated
276             */
277            protected Object[] addSearchResults(
278                    String keywords, int startPage, int itemsPerPage, int total, int start,
279                    String title, String searchPath, String format,
280                    ThemeDisplay themeDisplay) {
281    
282                    return addSearchResults(
283                            new String[0], keywords, startPage, itemsPerPage, total, start,
284                            title, searchPath, format, themeDisplay);
285            }
286    
287            protected Object[] addSearchResults(
288                    String[] queryTerms, String keywords, int startPage, int itemsPerPage,
289                    int total, int start, String title, String searchPath, String format,
290                    ThemeDisplay themeDisplay) {
291    
292                    int totalPages = 0;
293    
294                    if ((total % itemsPerPage) == 0) {
295                            totalPages = total / itemsPerPage;
296                    }
297                    else {
298                            totalPages = (total / itemsPerPage) + 1;
299                    }
300    
301                    int previousPage = startPage - 1;
302                    int nextPage = startPage + 1;
303    
304                    Document doc = SAXReaderUtil.createDocument();
305    
306                    if (format.equals("rss")) {
307                            return addSearchResultsRSS(
308                                    doc, queryTerms, keywords, startPage, itemsPerPage, total,
309                                    start, totalPages, previousPage, nextPage, title, searchPath,
310                                    themeDisplay);
311                    }
312                    else {
313                            return addSearchResultsAtom(
314                                    doc, queryTerms, keywords, startPage, itemsPerPage, total,
315                                    start, totalPages, previousPage, nextPage, title, searchPath,
316                                    themeDisplay);
317                    }
318            }
319    
320            protected Object[] addSearchResultsAtom(
321                    Document doc, String[] queryTerms, String keywords, int startPage,
322                    int itemsPerPage, int total, int start, int totalPages,
323                    int previousPage, int nextPage, String title, String searchPath,
324                    ThemeDisplay themeDisplay) {
325    
326                    // feed
327    
328                    Element root = doc.addElement("feed");
329    
330                    root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.DEFAULT_NAMESPACE));
331                    root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.OS_NAMESPACE));
332                    root.add(
333                            OpenSearchUtil.getNamespace(OpenSearchUtil.RELEVANCE_NAMESPACE));
334    
335                    // title
336    
337                    OpenSearchUtil.addElement(
338                            root, "title", OpenSearchUtil.DEFAULT_NAMESPACE, title);
339    
340                    // updated
341    
342                    OpenSearchUtil.addElement(
343                            root, "updated", OpenSearchUtil.DEFAULT_NAMESPACE, new Date());
344    
345                    // author
346    
347                    Element author = OpenSearchUtil.addElement(
348                            root, "author", OpenSearchUtil.DEFAULT_NAMESPACE);
349    
350                    // name
351    
352                    OpenSearchUtil.addElement(
353                            author, "name", OpenSearchUtil.DEFAULT_NAMESPACE,
354                            themeDisplay.getUserId());
355    
356                    // id
357    
358                    OpenSearchUtil.addElement(
359                            root, "id", OpenSearchUtil.DEFAULT_NAMESPACE,
360                            "urn:uuid:" + PortalUUIDUtil.generate());
361    
362                    // queryTerms
363    
364                    OpenSearchUtil.addElement(
365                            root, "queryTerms", OpenSearchUtil.DEFAULT_NAMESPACE,
366                            StringUtil.merge(queryTerms, StringPool.COMMA_AND_SPACE));
367    
368                    // opensearch:totalResults
369    
370                    OpenSearchUtil.addElement(
371                            root, "totalResults", OpenSearchUtil.OS_NAMESPACE, total);
372    
373                    // opensearch:startIndex
374    
375                    OpenSearchUtil.addElement(
376                            root, "startIndex", OpenSearchUtil.OS_NAMESPACE, start + 1);
377    
378                    // opensearch:itemsPerPage
379    
380                    OpenSearchUtil.addElement(
381                            root, "itemsPerPage", OpenSearchUtil.OS_NAMESPACE, itemsPerPage);
382    
383                    // opensearch:Query
384    
385                    Element query = OpenSearchUtil.addElement(
386                            root, "Query", OpenSearchUtil.OS_NAMESPACE);
387    
388                    query.addAttribute("role", "request");
389                    query.addAttribute("searchTerms", keywords);
390                    query.addAttribute("startPage", String.valueOf(startPage));
391    
392                    // links
393    
394                    String searchURL = themeDisplay.getURLPortal() + searchPath;
395    
396                    OpenSearchUtil.addLink(
397                            root, searchURL, "self", keywords, startPage, itemsPerPage);
398                    OpenSearchUtil.addLink(
399                            root, searchURL, "first", keywords, 1, itemsPerPage);
400    
401                    if (previousPage > 0) {
402                            OpenSearchUtil.addLink(
403                                    root, searchURL, "previous", keywords, previousPage,
404                                    itemsPerPage);
405                    }
406    
407                    if (nextPage <= totalPages) {
408                            OpenSearchUtil.addLink(
409                                    root, searchURL, "next", keywords, nextPage, itemsPerPage);
410                    }
411    
412                    OpenSearchUtil.addLink(
413                            root, searchURL, "last", keywords, totalPages, itemsPerPage);
414    
415                    Element link = OpenSearchUtil.addElement(
416                            root, "link", OpenSearchUtil.DEFAULT_NAMESPACE);
417    
418                    link.addAttribute("rel", "search");
419                    link.addAttribute("href", searchPath + "_description.xml");
420                    link.addAttribute("type", "application/opensearchdescription+xml");
421    
422                    return new Object[] {doc, root};
423            }
424    
425            protected Object[] addSearchResultsRSS(
426                    Document doc, String[] queryTerms, String keywords, int startPage,
427                    int itemsPerPage, int total, int start, int totalPages,
428                    int previousPage, int nextPage, String title, String searchPath,
429                    ThemeDisplay themeDisplay) {
430    
431                    // rss
432    
433                    Element root = doc.addElement("rss");
434    
435                    root.addAttribute("version", "2.0");
436                    root.add(
437                            SAXReaderUtil.createNamespace(
438                                    "atom", "http://www.w3.org/2005/Atom"));
439                    root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.OS_NAMESPACE));
440                    root.add(
441                            OpenSearchUtil.getNamespace(OpenSearchUtil.RELEVANCE_NAMESPACE));
442    
443                    // channel
444    
445                    Element channel = root.addElement("channel");
446    
447                    // title
448    
449                    OpenSearchUtil.addElement(
450                            channel, "title", OpenSearchUtil.NO_NAMESPACE, title);
451    
452                    // link
453    
454                    OpenSearchUtil.addElement(
455                            channel, "link", OpenSearchUtil.NO_NAMESPACE,
456                            themeDisplay.getURLPortal() + searchPath);
457    
458                    // description
459    
460                    OpenSearchUtil.addElement(
461                            channel, "description", OpenSearchUtil.NO_NAMESPACE, title);
462    
463                    // queryTerms
464    
465                    OpenSearchUtil.addElement(
466                            channel, "queryTerms", OpenSearchUtil.NO_NAMESPACE,
467                            StringUtil.merge(queryTerms, StringPool.COMMA_AND_SPACE));
468    
469                    // opensearch:totalResults
470    
471                    OpenSearchUtil.addElement(
472                            channel, "totalResults", OpenSearchUtil.OS_NAMESPACE, total);
473    
474                    // opensearch:startIndex
475    
476                    OpenSearchUtil.addElement(
477                            channel, "startIndex", OpenSearchUtil.OS_NAMESPACE, start + 1);
478    
479                    // opensearch:itemsPerPage
480    
481                    OpenSearchUtil.addElement(
482                            channel, "itemsPerPage", OpenSearchUtil.OS_NAMESPACE, itemsPerPage);
483    
484                    // opensearch:Query
485    
486                    Element query = OpenSearchUtil.addElement(
487                            channel, "Query", OpenSearchUtil.OS_NAMESPACE);
488    
489                    query.addAttribute("role", "request");
490                    query.addAttribute("searchTerms", keywords);
491                    query.addAttribute("startPage", String.valueOf(startPage));
492    
493                    return new Object[] {doc, channel};
494            }
495    
496            protected PortletURL getPortletURL(
497                            HttpServletRequest request, String portletId)
498                    throws Exception {
499    
500                    return getPortletURL(request, portletId, 0);
501            }
502    
503            protected PortletURL getPortletURL(
504                            HttpServletRequest request, String portletId, long scopeGroupId)
505                    throws Exception {
506    
507                    Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
508    
509                    long layoutGroupId = scopeGroupId;
510    
511                    if (layout != null) {
512                            layoutGroupId = layout.getGroupId();
513                    }
514    
515                    long plid = LayoutServiceUtil.getDefaultPlid(
516                            layoutGroupId, scopeGroupId, false, portletId);
517    
518                    if (plid == 0) {
519                            plid = LayoutServiceUtil.getDefaultPlid(
520                                    layoutGroupId, scopeGroupId, true, portletId);
521                    }
522    
523                    if (plid == 0) {
524                            if (layout != null) {
525                                    plid = layout.getPlid();
526                            }
527                    }
528    
529                    PortletURL portletURL = PortletURLFactoryUtil.create(
530                            request, portletId, plid, PortletRequest.RENDER_PHASE);
531    
532                    portletURL.setWindowState(WindowState.MAXIMIZED);
533                    portletURL.setPortletMode(PortletMode.VIEW);
534    
535                    return portletURL;
536            }
537    
538            private boolean _enabled = GetterUtil.getBoolean(
539                    PropsUtil.get(getClass().getName()), true);
540    
541    }