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.repository.search;
016    
017    import com.liferay.portal.kernel.repository.search.RepositorySearchQueryBuilder;
018    import com.liferay.portal.kernel.repository.search.RepositorySearchQueryTermBuilder;
019    import com.liferay.portal.kernel.search.BooleanClause;
020    import com.liferay.portal.kernel.search.BooleanClauseOccur;
021    import com.liferay.portal.kernel.search.BooleanQuery;
022    import com.liferay.portal.kernel.search.Field;
023    import com.liferay.portal.kernel.search.Query;
024    import com.liferay.portal.kernel.search.QueryTerm;
025    import com.liferay.portal.kernel.search.SearchContext;
026    import com.liferay.portal.kernel.search.SearchException;
027    import com.liferay.portal.kernel.search.TermQuery;
028    import com.liferay.portal.kernel.search.TermRangeQuery;
029    import com.liferay.portal.kernel.search.WildcardQuery;
030    import com.liferay.portal.kernel.search.generic.BooleanQueryImpl;
031    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
032    import com.liferay.portal.kernel.util.ArrayUtil;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
035    import com.liferay.portlet.documentlibrary.service.DLAppServiceUtil;
036    import com.liferay.registry.Registry;
037    import com.liferay.registry.RegistryUtil;
038    import com.liferay.registry.ServiceTracker;
039    
040    /**
041     * @author Mika Koivisto
042     */
043    @DoPrivileged
044    public class RepositorySearchQueryBuilderImpl
045            implements RepositorySearchQueryBuilder {
046    
047            public RepositorySearchQueryBuilderImpl() {
048                    Registry registry = RegistryUtil.getRegistry();
049    
050                    _serviceTracker = registry.trackServices(
051                            RepositorySearchQueryTermBuilder.class);
052    
053                    _serviceTracker.open();
054            }
055    
056            @Override
057            public BooleanQuery getFullQuery(SearchContext searchContext)
058                    throws SearchException {
059    
060                    try {
061                            BooleanQuery contextQuery = new BooleanQueryImpl();
062    
063                            addContext(contextQuery, searchContext);
064    
065                            BooleanQuery searchQuery = new BooleanQueryImpl();
066    
067                            addSearchKeywords(searchQuery, searchContext);
068    
069                            BooleanQuery fullQuery = new BooleanQueryImpl();
070    
071                            if (contextQuery.hasClauses()) {
072                                    fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
073                            }
074    
075                            if (searchQuery.hasClauses()) {
076                                    fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
077                            }
078    
079                            BooleanClause<Query>[] booleanClauses =
080                                    searchContext.getBooleanClauses();
081    
082                            if (booleanClauses != null) {
083                                    for (BooleanClause<Query> booleanClause : booleanClauses) {
084                                            fullQuery.add(
085                                                    booleanClause.getClause(),
086                                                    booleanClause.getBooleanClauseOccur());
087                                    }
088                            }
089    
090                            fullQuery.setQueryConfig(searchContext.getQueryConfig());
091    
092                            return fullQuery;
093                    }
094                    catch (Exception e) {
095                            throw new SearchException(e);
096                    }
097            }
098    
099            protected void addContext(
100                            BooleanQuery contextQuery, SearchContext searchContext)
101                    throws Exception {
102    
103                    long[] folderIds = searchContext.getFolderIds();
104    
105                    if (ArrayUtil.isEmpty(folderIds)) {
106                            return;
107                    }
108    
109                    if (folderIds[0] == DLFolderConstants.DEFAULT_PARENT_FOLDER_ID) {
110                            return;
111                    }
112    
113                    BooleanQuery folderIdsQuery = new BooleanQueryImpl();
114    
115                    for (long folderId : folderIds) {
116                            try {
117                                    DLAppServiceUtil.getFolder(folderId);
118                            }
119                            catch (Exception e) {
120                                    continue;
121                            }
122    
123                            folderIdsQuery.addTerm(Field.FOLDER_ID, folderId);
124                    }
125    
126                    contextQuery.add(folderIdsQuery, BooleanClauseOccur.MUST);
127            }
128    
129            protected void addSearchKeywords(
130                            BooleanQuery searchQuery, SearchContext searchContext)
131                    throws Exception {
132    
133                    String keywords = searchContext.getKeywords();
134    
135                    if (Validator.isNull(keywords)) {
136                            return;
137                    }
138    
139                    RepositorySearchQueryTermBuilder repositorySearchQueryTermBuilder =
140                            _serviceTracker.getService();
141    
142                    BooleanQuery titleQuery = new BooleanQueryImpl();
143    
144                    repositorySearchQueryTermBuilder.addTerm(
145                            titleQuery, searchContext, Field.TITLE, keywords);
146    
147                    if (titleQuery.hasClauses() && !contains(searchQuery, titleQuery)) {
148                            searchQuery.add(titleQuery, BooleanClauseOccur.SHOULD);
149                    }
150    
151                    BooleanQuery userNameQuery = new BooleanQueryImpl();
152    
153                    repositorySearchQueryTermBuilder.addTerm(
154                            userNameQuery, searchContext, Field.USER_NAME, keywords);
155    
156                    if (userNameQuery.hasClauses() &&
157                            !contains(searchQuery, userNameQuery)) {
158    
159                            searchQuery.add(userNameQuery, BooleanClauseOccur.SHOULD);
160                    }
161    
162                    BooleanQuery contentQuery = new BooleanQueryImpl();
163    
164                    repositorySearchQueryTermBuilder.addTerm(
165                            contentQuery, searchContext, Field.CONTENT, keywords);
166    
167                    if (contentQuery.hasClauses() && !contains(searchQuery, contentQuery)) {
168                            searchQuery.add(contentQuery, BooleanClauseOccur.SHOULD);
169                    }
170            }
171    
172            protected boolean contains(Query query1, Query query2) {
173                    if (query1 instanceof BooleanQuery) {
174                            BooleanQuery booleanQuery = (BooleanQuery)query1;
175    
176                            for (com.liferay.portal.kernel.search.BooleanClause<Query>
177                                            booleanClause : booleanQuery.clauses()) {
178    
179                                    if (contains(booleanClause.getClause(), query2)) {
180                                            return true;
181                                    }
182                            }
183    
184                            return false;
185                    }
186                    else if (query2 instanceof BooleanQuery) {
187                            BooleanQuery booleanQuery = (BooleanQuery)query2;
188    
189                            for (com.liferay.portal.kernel.search.BooleanClause<Query>
190                                            booleanClause : booleanQuery.clauses()) {
191    
192                                    if (contains(query1, booleanClause.getClause())) {
193                                            return true;
194                                    }
195                            }
196    
197                            return false;
198                    }
199                    else if ((query1 instanceof TermQuery) &&
200                                     (query2 instanceof TermQuery)) {
201    
202                            TermQuery termQuery1 = (TermQuery)query1;
203    
204                            QueryTerm queryTerm1 = termQuery1.getQueryTerm();
205    
206                            String field1 = queryTerm1.getField();
207                            String value1 = queryTerm1.getValue();
208    
209                            TermQuery termQuery2 = (TermQuery)query2;
210    
211                            QueryTerm queryTerm2 = termQuery2.getQueryTerm();
212    
213                            String field2 = queryTerm2.getField();
214                            String value2 = queryTerm2.getValue();
215    
216                            if (field1.equals(field2) && value1.equals(value2)) {
217                                    return true;
218                            }
219                    }
220                    else if ((query1 instanceof TermRangeQuery) &&
221                                     (query2 instanceof TermRangeQuery)) {
222    
223                            TermRangeQuery termRangeQuery1 = (TermRangeQuery)query1;
224    
225                            boolean includesLower1 = termRangeQuery1.includesLower();
226                            boolean includesUpper1 = termRangeQuery1.includesUpper();
227                            String lowerTerm1 = termRangeQuery1.getLowerTerm();
228                            String upperTerm1 = termRangeQuery1.getUpperTerm();
229    
230                            TermRangeQuery termRangeQuery2 = (TermRangeQuery)query2;
231    
232                            boolean includesLower2 = termRangeQuery2.includesLower();
233                            boolean includesUpper2 = termRangeQuery2.includesUpper();
234                            String lowerTerm2 = termRangeQuery2.getLowerTerm();
235                            String upperTerm2 = termRangeQuery2.getUpperTerm();
236    
237                            if ((includesLower1 == includesLower2) &&
238                                    (includesUpper1 == includesUpper2) &&
239                                    lowerTerm1.equals(lowerTerm2) &&
240                                    upperTerm1.equals(upperTerm2)) {
241    
242                                    return true;
243                            }
244                    }
245                    else if ((query1 instanceof WildcardQuery) &&
246                                     (query2 instanceof WildcardQuery)) {
247    
248                            WildcardQuery wildcardQuery1 = (WildcardQuery)query1;
249    
250                            QueryTerm queryTerm1 = wildcardQuery1.getQueryTerm();
251    
252                            String field1 = queryTerm1.getField();
253                            String value1 = queryTerm1.getValue();
254    
255                            WildcardQuery wildcardQuery2 = (WildcardQuery)query2;
256    
257                            QueryTerm queryTerm2 = wildcardQuery2.getQueryTerm();
258    
259                            String field2 = queryTerm2.getField();
260                            String value2 = queryTerm2.getValue();
261    
262                            if (field1.equals(field2) && value1.equals(value2)) {
263                                    return true;
264                            }
265                    }
266    
267                    return false;
268            }
269    
270            private final ServiceTracker
271                    <RepositorySearchQueryTermBuilder, RepositorySearchQueryTermBuilder>
272                            _serviceTracker;
273    
274    }