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