001
014
015 package com.liferay.portal.kernel.search;
016
017 import com.liferay.portal.kernel.search.facet.Facet;
018 import com.liferay.portal.kernel.util.GetterUtil;
019 import com.liferay.portal.kernel.util.SetUtil;
020 import com.liferay.portal.kernel.util.UnicodeProperties;
021 import com.liferay.portal.kernel.util.Validator;
022 import com.liferay.portal.security.permission.PermissionChecker;
023 import com.liferay.portal.security.permission.PermissionThreadLocal;
024 import com.liferay.portlet.expando.model.ExpandoBridge;
025 import com.liferay.portlet.expando.model.ExpandoColumnConstants;
026 import com.liferay.portlet.expando.util.ExpandoBridgeFactoryUtil;
027 import com.liferay.portlet.expando.util.ExpandoBridgeIndexerUtil;
028
029 import java.util.Locale;
030 import java.util.Map;
031 import java.util.Set;
032
033 import javax.portlet.PortletURL;
034
035
038 public class FacetedSearcher extends BaseIndexer {
039
040 public static Indexer getInstance() {
041 return new FacetedSearcher();
042 }
043
044 public String[] getClassNames() {
045 return null;
046 }
047
048 @Override
049 public IndexerPostProcessor[] getIndexerPostProcessors() {
050 throw new UnsupportedOperationException();
051 }
052
053 public String getPortletId() {
054 return null;
055 }
056
057 @Override
058 public void registerIndexerPostProcessor(
059 IndexerPostProcessor indexerPostProcessor) {
060
061 throw new UnsupportedOperationException();
062 }
063
064 @Override
065 public Hits search(SearchContext searchContext) throws SearchException {
066 try {
067 searchContext.setSearchEngineId(getSearchEngineId());
068
069 BooleanQuery contextQuery = BooleanQueryFactoryUtil.create(
070 searchContext);
071
072 contextQuery.addRequiredTerm(
073 Field.COMPANY_ID, searchContext.getCompanyId());
074
075 BooleanQuery fullQuery = createFullQuery(
076 contextQuery, searchContext);
077
078 fullQuery.setQueryConfig(searchContext.getQueryConfig());
079
080 PermissionChecker permissionChecker =
081 PermissionThreadLocal.getPermissionChecker();
082
083 int end = searchContext.getEnd();
084 int start = searchContext.getStart();
085
086 if (isFilterSearch(searchContext) && (permissionChecker != null)) {
087 searchContext.setEnd(end + INDEX_FILTER_SEARCH_LIMIT);
088 searchContext.setStart(0);
089 }
090
091 Hits hits = SearchEngineUtil.search(searchContext, fullQuery);
092
093 searchContext.setEnd(end);
094 searchContext.setStart(start);
095
096 if (isFilterSearch(searchContext) && (permissionChecker != null)) {
097 hits = filterSearch(hits, permissionChecker, searchContext);
098 }
099
100 return hits;
101 }
102 catch (SearchException se) {
103 throw se;
104 }
105 catch (Exception e) {
106 throw new SearchException(e);
107 }
108 }
109
110 @Override
111 public void unregisterIndexerPostProcessor(
112 IndexerPostProcessor indexerPostProcessor) {
113
114 throw new UnsupportedOperationException();
115 }
116
117 protected void addSearchExpandoKeywords(
118 BooleanQuery searchQuery, SearchContext searchContext,
119 String keywords, String className)
120 throws Exception {
121
122 ExpandoBridge expandoBridge = ExpandoBridgeFactoryUtil.getExpandoBridge(
123 searchContext.getCompanyId(), className);
124
125 Set<String> attributeNames = SetUtil.fromEnumeration(
126 expandoBridge.getAttributeNames());
127
128 for (String attributeName : attributeNames) {
129 UnicodeProperties properties = expandoBridge.getAttributeProperties(
130 attributeName);
131
132 int indexType = GetterUtil.getInteger(
133 properties.getProperty(ExpandoColumnConstants.INDEX_TYPE));
134
135 if (indexType != ExpandoColumnConstants.INDEX_TYPE_NONE) {
136 String fieldName = ExpandoBridgeIndexerUtil.encodeFieldName(
137 attributeName);
138
139 if (searchContext.isAndSearch()) {
140 searchQuery.addRequiredTerm(fieldName, keywords);
141 }
142 else {
143 searchQuery.addTerm(fieldName, keywords);
144 }
145 }
146 }
147 }
148
149 @Override
150 protected BooleanQuery createFullQuery(
151 BooleanQuery contextQuery, SearchContext searchContext)
152 throws Exception {
153
154 BooleanQuery searchQuery = BooleanQueryFactoryUtil.create(
155 searchContext);
156
157 String keywords = searchContext.getKeywords();
158
159 if (Validator.isNotNull(keywords)) {
160 addSearchLocalizedTerm(
161 searchQuery, searchContext, Field.ASSET_CATEGORY_TITLES, false);
162
163 searchQuery.addExactTerm(Field.ASSET_TAG_NAMES, keywords);
164 searchQuery.addTerms(Field.KEYWORDS, keywords);
165 }
166
167 for (String entryClassName : searchContext.getEntryClassNames()) {
168 Indexer indexer = IndexerRegistryUtil.getIndexer(entryClassName);
169
170 if (indexer == null) {
171 continue;
172 }
173
174 String searchEngineId = searchContext.getSearchEngineId();
175
176 if (!searchEngineId.equals(indexer.getSearchEngineId())) {
177 continue;
178 }
179
180 if (Validator.isNotNull(keywords)) {
181 addSearchExpandoKeywords(
182 searchQuery, searchContext, keywords, entryClassName);
183 }
184
185 indexer.postProcessSearchQuery(searchQuery, searchContext);
186
187 for (IndexerPostProcessor indexerPostProcessor :
188 indexer.getIndexerPostProcessors()) {
189
190 indexerPostProcessor.postProcessSearchQuery(
191 searchQuery, searchContext);
192 }
193 }
194
195 Map<String, Facet> facets = searchContext.getFacets();
196
197 for (Facet facet : facets.values()) {
198 BooleanClause facetClause = facet.getFacetClause();
199
200 if (facetClause != null) {
201 contextQuery.add(
202 facetClause.getQuery(),
203 facetClause.getBooleanClauseOccur());
204 }
205 }
206
207 BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(searchContext);
208
209 fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
210
211 if (searchQuery.hasClauses()) {
212 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
213 }
214
215 BooleanClause[] booleanClauses = searchContext.getBooleanClauses();
216
217 if (booleanClauses != null) {
218 for (BooleanClause booleanClause : booleanClauses) {
219 fullQuery.add(
220 booleanClause.getQuery(),
221 booleanClause.getBooleanClauseOccur());
222 }
223 }
224
225 for (String entryClassName : searchContext.getEntryClassNames()) {
226 Indexer indexer = IndexerRegistryUtil.getIndexer(entryClassName);
227
228 if (indexer == null) {
229 continue;
230 }
231
232 String searchEngineId = searchContext.getSearchEngineId();
233
234 if (!searchEngineId.equals(indexer.getSearchEngineId())) {
235 continue;
236 }
237
238 for (IndexerPostProcessor indexerPostProcessor :
239 indexer.getIndexerPostProcessors()) {
240
241 indexerPostProcessor.postProcessFullQuery(
242 fullQuery, searchContext);
243 }
244 }
245
246 return fullQuery;
247 }
248
249 @Override
250 protected void doDelete(Object obj) throws Exception {
251 throw new UnsupportedOperationException();
252 }
253
254 @Override
255 protected Document doGetDocument(Object obj) throws Exception {
256 throw new UnsupportedOperationException();
257 }
258
259 @Override
260 protected Summary doGetSummary(
261 Document document, Locale locale, String snippet,
262 PortletURL portletURL)
263 throws Exception {
264
265 throw new UnsupportedOperationException();
266 }
267
268 @Override
269 protected void doReindex(Object obj) throws Exception {
270 throw new UnsupportedOperationException();
271 }
272
273 @Override
274 protected void doReindex(String className, long classPK) throws Exception {
275 throw new UnsupportedOperationException();
276 }
277
278 @Override
279 protected void doReindex(String[] ids) throws Exception {
280 throw new UnsupportedOperationException();
281 }
282
283 @Override
284 protected String getPortletId(SearchContext searchContext) {
285 return null;
286 }
287
288 protected boolean isFilterSearch(SearchContext searchContext) {
289 if (searchContext.getEntryClassNames() == null) {
290 return super.isFilterSearch();
291 }
292
293 for (String entryClassName : searchContext.getEntryClassNames()) {
294 Indexer indexer = IndexerRegistryUtil.getIndexer(entryClassName);
295
296 if (indexer == null) {
297 continue;
298 }
299
300 if (indexer.isFilterSearch()) {
301 return true;
302 }
303 }
304
305 return super.isFilterSearch();
306 }
307
308 }