001    /**
002     * Copyright (c) 2000-present 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.dao.search;
016    
017    import com.liferay.portal.kernel.util.DeterminateKeyGenerator;
018    import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
019    import com.liferay.portal.kernel.util.GetterUtil;
020    import com.liferay.portal.kernel.util.OrderByComparator;
021    import com.liferay.portal.kernel.util.ParamUtil;
022    import com.liferay.portal.kernel.util.PropsKeys;
023    import com.liferay.portal.kernel.util.PropsUtil;
024    import com.liferay.portal.kernel.util.SearchContainerReference;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.kernel.util.StringUtil;
027    import com.liferay.portal.kernel.util.TextFormatter;
028    import com.liferay.portal.kernel.util.Validator;
029    import com.liferay.portal.kernel.util.WebKeys;
030    import com.liferay.portal.util.PortalUtil;
031    
032    import java.util.ArrayList;
033    import java.util.List;
034    import java.util.Map;
035    
036    import javax.portlet.PortletRequest;
037    import javax.portlet.PortletURL;
038    
039    import javax.servlet.http.HttpServletRequest;
040    
041    /**
042     * @author Brian Wing Shun Chan
043     */
044    public class SearchContainer<R> {
045    
046            public static final int DEFAULT_CUR = 1;
047    
048            public static final String DEFAULT_CUR_PARAM = "cur";
049    
050            /**
051             * @deprecated As of 6.2.0, replaced by {@link #DEFAULT_CUR}.
052             */
053            @Deprecated
054            public static final int DEFAULT_CUR_VALUE = DEFAULT_CUR;
055    
056            public static final int DEFAULT_DELTA = GetterUtil.getInteger(
057                    PropsUtil.get(PropsKeys.SEARCH_CONTAINER_PAGE_DEFAULT_DELTA));
058    
059            public static final boolean DEFAULT_DELTA_CONFIGURABLE = true;
060    
061            public static final String DEFAULT_DELTA_PARAM = "delta";
062    
063            public static final String DEFAULT_DEPRECATED_TOTAL_VAR = "deprecatedTotal";
064    
065            /**
066             * @deprecated As of 6.2.0, see LPS-6312
067             */
068            @Deprecated
069            public static final int DEFAULT_MAX_PAGES = 25;
070    
071            public static final String DEFAULT_ORDER_BY_COL_PARAM = "orderByCol";
072    
073            public static final String DEFAULT_ORDER_BY_TYPE_PARAM = "orderByType";
074    
075            public static final String DEFAULT_RESULTS_VAR = "results";
076    
077            public static final String DEFAULT_TOTAL_VAR = "total";
078    
079            public static final String DEFAULT_VAR = "searchContainer";
080    
081            public static final int MAX_DELTA = 200;
082    
083            public SearchContainer() {
084                    _curParam = DEFAULT_CUR_PARAM;
085                    _displayTerms = null;
086                    _portletRequest = null;
087                    _searchTerms = null;
088            }
089    
090            public SearchContainer(
091                    PortletRequest portletRequest, DisplayTerms displayTerms,
092                    DisplayTerms searchTerms, String curParam, int cur, int delta,
093                    PortletURL iteratorURL, List<String> headerNames,
094                    String emptyResultsMessage) {
095    
096                    this (
097                            portletRequest, displayTerms, searchTerms, curParam, cur, delta,
098                            iteratorURL, headerNames, emptyResultsMessage, StringPool.BLANK);
099            }
100    
101            public SearchContainer(
102                    PortletRequest portletRequest, DisplayTerms displayTerms,
103                    DisplayTerms searchTerms, String curParam, int cur, int delta,
104                    PortletURL iteratorURL, List<String> headerNames,
105                    String emptyResultsMessage, String cssClass) {
106    
107                    _portletRequest = portletRequest;
108                    _displayTerms = displayTerms;
109                    _searchTerms = searchTerms;
110    
111                    _curParam = curParam;
112    
113                    boolean resetCur = ParamUtil.getBoolean(portletRequest, "resetCur");
114    
115                    if (resetCur) {
116                            _cur = DEFAULT_CUR;
117                    }
118                    else {
119                            if (cur < 1) {
120                                    _cur = ParamUtil.getInteger(
121                                            portletRequest, _curParam, DEFAULT_CUR);
122    
123                                    if (_cur < 1) {
124                                            _cur = DEFAULT_CUR;
125                                    }
126                            }
127                            else {
128                                    _cur = cur;
129                            }
130                    }
131    
132                    if (!_curParam.equals(DEFAULT_CUR_PARAM)) {
133                            _deltaParam =
134                                    DEFAULT_DELTA_PARAM +
135                                            StringUtil.replace(
136                                                    _curParam, DEFAULT_CUR_PARAM, StringPool.BLANK);
137                    }
138    
139                    setDelta(ParamUtil.getInteger(portletRequest, _deltaParam, delta));
140    
141                    _iteratorURL = iteratorURL;
142    
143                    _iteratorURL.setParameter(_curParam, String.valueOf(_cur));
144                    _iteratorURL.setParameter(_deltaParam, String.valueOf(_delta));
145    
146                    _setParameter(DisplayTerms.KEYWORDS);
147                    _setParameter(DisplayTerms.ADVANCED_SEARCH);
148                    _setParameter(DisplayTerms.AND_OPERATOR);
149    
150                    if (headerNames != null) {
151                            _headerNames = new ArrayList<>(headerNames.size());
152    
153                            _headerNames.addAll(headerNames);
154    
155                            _buildNormalizedHeaderNames(_headerNames);
156                    }
157    
158                    _emptyResultsMessage = emptyResultsMessage;
159    
160                    SearchContainerReference searchContainerReference =
161                            (SearchContainerReference)portletRequest.getAttribute(
162                                    WebKeys.SEARCH_CONTAINER_REFERENCE);
163    
164                    if (searchContainerReference != null) {
165                            searchContainerReference.register(this);
166                    }
167    
168                    if (Validator.isNotNull(cssClass)) {
169                            _cssClass = cssClass;
170                    }
171            }
172    
173            public SearchContainer(
174                    PortletRequest portletRequest, DisplayTerms displayTerms,
175                    DisplayTerms searchTerms, String curParam, int delta,
176                    PortletURL iteratorURL, List<String> headerNames,
177                    String emptyResultsMessage) {
178    
179                    this (
180                            portletRequest, displayTerms, searchTerms, curParam, 0, delta,
181                            iteratorURL, headerNames, emptyResultsMessage);
182            }
183    
184            public SearchContainer(
185                    PortletRequest portletRequest, PortletURL iteratorURL,
186                    List<String> headerNames, String emptyResultsMessage) {
187    
188                    this(
189                            portletRequest, null, null, DEFAULT_CUR_PARAM, DEFAULT_DELTA,
190                            iteratorURL, headerNames, emptyResultsMessage);
191            }
192    
193            public String getClassName() {
194                    return _className;
195            }
196    
197            public String getCssClass() {
198                    return _cssClass;
199            }
200    
201            public int getCur() {
202                    return _cur;
203            }
204    
205            public String getCurParam() {
206                    return _curParam;
207            }
208    
209            /**
210             * @deprecated As of 6.2.0, replaced by {@link #getCur}
211             */
212            @Deprecated
213            public int getCurValue() {
214                    return getCur();
215            }
216    
217            public int getDelta() {
218                    return _delta;
219            }
220    
221            public String getDeltaParam() {
222                    return _deltaParam;
223            }
224    
225            public DisplayTerms getDisplayTerms() {
226                    return _displayTerms;
227            }
228    
229            public String getEmptyResultsMessage() {
230                    return _emptyResultsMessage;
231            }
232    
233            public int getEnd() {
234                    return _end;
235            }
236    
237            public List<String> getHeaderNames() {
238                    return _headerNames;
239            }
240    
241            public String getId(HttpServletRequest request, String namespace) {
242                    if (_uniqueId) {
243                            return _id;
244                    }
245    
246                    if (Validator.isNotNull(_id)) {
247                            _id = PortalUtil.getUniqueElementId(request, namespace, _id);
248                            _uniqueId = true;
249    
250                            return _id;
251                    }
252    
253                    String id = null;
254    
255                    if (Validator.isNotNull(_className)) {
256                            String simpleClassName = _className;
257    
258                            int pos = simpleClassName.lastIndexOf(StringPool.PERIOD);
259    
260                            if (pos != -1) {
261                                    simpleClassName = simpleClassName.substring(pos + 1);
262                            }
263    
264                            String variableCasingSimpleClassName = TextFormatter.format(
265                                    simpleClassName, TextFormatter.I);
266    
267                            id = TextFormatter.formatPlural(variableCasingSimpleClassName);
268    
269                            id = id.concat("SearchContainer");
270    
271                            _id = PortalUtil.getUniqueElementId(request, namespace, id);
272                            _uniqueId = true;
273    
274                            return _id;
275                    }
276    
277                    id = DeterminateKeyGenerator.generate("taglib_search_container");
278    
279                    _id = id.concat("SearchContainer");
280                    _uniqueId = true;
281    
282                    return _id;
283            }
284    
285            public PortletURL getIteratorURL() {
286                    return _iteratorURL;
287            }
288    
289            /**
290             * @deprecated As of 6.2.0, see LPS-6312
291             */
292            @Deprecated
293            public int getMaxPages() {
294                    return _maxPages;
295            }
296    
297            public List<String> getNormalizedHeaderNames() {
298                    return _normalizedHeaderNames;
299            }
300    
301            public Map<String, String> getOrderableHeaders() {
302                    return _orderableHeaders;
303            }
304    
305            public String getOrderByCol() {
306                    return _orderByCol;
307            }
308    
309            public String getOrderByColParam() {
310                    return _orderByColParam;
311            }
312    
313            public OrderByComparator<R> getOrderByComparator() {
314                    return _orderByComparator;
315            }
316    
317            public String getOrderByJS() {
318                    return _orderByJS;
319            }
320    
321            public String getOrderByType() {
322                    return _orderByType;
323            }
324    
325            public String getOrderByTypeParam() {
326                    return _orderByTypeParam;
327            }
328    
329            public PortletRequest getPortletRequest() {
330                    return _portletRequest;
331            }
332    
333            public int getResultEnd() {
334                    return _resultEnd;
335            }
336    
337            public List<ResultRow> getResultRows() {
338                    return _resultRows;
339            }
340    
341            public List<R> getResults() {
342                    return _results;
343            }
344    
345            public RowChecker getRowChecker() {
346                    return _rowChecker;
347            }
348    
349            public DisplayTerms getSearchTerms() {
350                    return _searchTerms;
351            }
352    
353            public int getStart() {
354                    return _start;
355            }
356    
357            public int getTotal() {
358                    return _total;
359            }
360    
361            public String getTotalVar() {
362                    return _totalVar;
363            }
364    
365            public boolean hasResults() {
366                    return !_results.isEmpty();
367            }
368    
369            public boolean isDeltaConfigurable() {
370                    return _deltaConfigurable;
371            }
372    
373            public boolean isHover() {
374                    return _hover;
375            }
376    
377            public boolean isRecalculateCur() {
378                    if ((_total == 0) && (_cur == DEFAULT_CUR)) {
379                            return false;
380                    }
381    
382                    if (((_cur - 1) * _delta) >= _total) {
383                            return true;
384                    }
385    
386                    return false;
387            }
388    
389            public void setClassName(String className) {
390                    _className = className;
391            }
392    
393            public void setCssClass(String cssClass) {
394                    _cssClass = cssClass;
395            }
396    
397            public void setDelta(int delta) {
398                    if (delta <= 0) {
399                            _delta = DEFAULT_DELTA;
400                    }
401                    else if (delta > MAX_DELTA) {
402                            _delta = MAX_DELTA;
403                    }
404                    else {
405                            _delta = delta;
406                    }
407    
408                    _calculateStartAndEnd();
409            }
410    
411            public void setDeltaConfigurable(boolean deltaConfigurable) {
412                    _deltaConfigurable = deltaConfigurable;
413            }
414    
415            public void setDeltaParam(String deltaParam) {
416                    _deltaParam = deltaParam;
417            }
418    
419            public void setEmptyResultsMessage(String emptyResultsMessage) {
420                    _emptyResultsMessage = emptyResultsMessage;
421            }
422    
423            public void setHeaderNames(List<String> headerNames) {
424                    _headerNames = headerNames;
425    
426                    _buildNormalizedHeaderNames(headerNames);
427            }
428    
429            public void setHover(boolean hover) {
430                    _hover = hover;
431            }
432    
433            public void setId(String id) {
434                    _id = id;
435            }
436    
437            public void setIteratorURL(PortletURL iteratorURL) {
438                    _iteratorURL = iteratorURL;
439            }
440    
441            /**
442             * @deprecated As of 6.2.0, see LPS-6312
443             */
444            @Deprecated
445            public void setMaxPages(int maxPages) {
446                    _maxPages = maxPages;
447            }
448    
449            public void setOrderableHeaders(Map<String, String> orderableHeaders) {
450                    _orderableHeaders = orderableHeaders;
451            }
452    
453            public void setOrderByCol(String orderByCol) {
454                    _orderByCol = orderByCol;
455    
456                    _iteratorURL.setParameter(_orderByColParam, _orderByCol);
457            }
458    
459            public void setOrderByColParam(String orderByColParam) {
460                    _orderByColParam = orderByColParam;
461            }
462    
463            public void setOrderByComparator(OrderByComparator<R> orderByComparator) {
464                    _orderByComparator = orderByComparator;
465            }
466    
467            public void setOrderByJS(String orderByJS) {
468                    _orderByJS = orderByJS;
469            }
470    
471            public void setOrderByType(String orderByType) {
472                    _orderByType = orderByType;
473    
474                    _iteratorURL.setParameter(_orderByTypeParam, _orderByType);
475            }
476    
477            public void setOrderByTypeParam(String orderByTypeParam) {
478                    _orderByTypeParam = orderByTypeParam;
479            }
480    
481            public void setResults(List<R> results) {
482                    _results = results;
483            }
484    
485            public void setRowChecker(RowChecker rowChecker) {
486                    _rowChecker = rowChecker;
487            }
488    
489            public void setTotal(int total) {
490                    _total = total;
491    
492                    _calculateCur();
493                    _calculateStartAndEnd();
494            }
495    
496            public void setTotalVar(String totalVar) {
497                    _totalVar = totalVar;
498            }
499    
500            private void _buildNormalizedHeaderNames(List<String> headerNames) {
501                    if (headerNames == null) {
502                            return;
503                    }
504    
505                    _normalizedHeaderNames = new ArrayList<>(headerNames.size());
506    
507                    for (String headerName : headerNames) {
508                            _normalizedHeaderNames.add(
509                                    FriendlyURLNormalizerUtil.normalize(headerName));
510                    }
511            }
512    
513            private void _calculateCur() {
514                    if (_total == 0) {
515                            _cur = DEFAULT_CUR;
516    
517                            return;
518                    }
519    
520                    if (isRecalculateCur()) {
521                            if ((_total % _delta) == 0) {
522                                    _cur = (_total / _delta);
523                            }
524                            else {
525                                    _cur = (_total / _delta) + 1;
526                            }
527                    }
528            }
529    
530            private void _calculateStartAndEnd() {
531                    int[] startAndEnd = SearchPaginationUtil.calculateStartAndEnd(
532                            _cur, _delta);
533    
534                    _start = startAndEnd[0];
535                    _end = startAndEnd[1];
536    
537                    _resultEnd = _end;
538    
539                    if (_resultEnd > _total) {
540                            _resultEnd = _total;
541                    }
542            }
543    
544            private void _setParameter(String name) {
545                    String value = _portletRequest.getParameter(name);
546    
547                    if (value != null) {
548                            _iteratorURL.setParameter(name, value);
549                    }
550            }
551    
552            private String _className;
553            private String _cssClass = StringPool.BLANK;
554            private int _cur;
555            private final String _curParam;
556            private int _delta = DEFAULT_DELTA;
557            private boolean _deltaConfigurable = DEFAULT_DELTA_CONFIGURABLE;
558            private String _deltaParam = DEFAULT_DELTA_PARAM;
559            private final DisplayTerms _displayTerms;
560            private String _emptyResultsMessage;
561            private int _end;
562            private List<String> _headerNames;
563            private boolean _hover = true;
564            private String _id;
565            private PortletURL _iteratorURL;
566    
567            /**
568             * @deprecated As of 6.2.0, see LPS-6312
569             */
570            @Deprecated
571            private int _maxPages = DEFAULT_MAX_PAGES;
572    
573            private List<String> _normalizedHeaderNames;
574            private Map<String, String> _orderableHeaders;
575            private String _orderByCol;
576            private String _orderByColParam = DEFAULT_ORDER_BY_COL_PARAM;
577            private OrderByComparator<R> _orderByComparator;
578            private String _orderByJS;
579            private String _orderByType;
580            private String _orderByTypeParam = DEFAULT_ORDER_BY_TYPE_PARAM;
581            private final PortletRequest _portletRequest;
582            private int _resultEnd;
583            private final List<ResultRow> _resultRows = new ArrayList<>();
584            private List<R> _results = new ArrayList<>();
585            private RowChecker _rowChecker;
586            private final DisplayTerms _searchTerms;
587            private int _start;
588            private int _total;
589            private String _totalVar;
590            private boolean _uniqueId;
591    
592    }