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 start = searchContext.getStart();
084 int end = searchContext.getEnd();
085
086 if (isFilterSearch(searchContext) && (permissionChecker != null)) {
087 searchContext.setStart(0);
088 searchContext.setEnd(end + INDEX_FILTER_SEARCH_LIMIT);
089 }
090
091 Hits hits = SearchEngineUtil.search(searchContext, fullQuery);
092
093 searchContext.setStart(start);
094 searchContext.setEnd(end);
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 searchQuery.addExactTerm(Field.ASSET_CATEGORY_NAMES, keywords);
161 searchQuery.addExactTerm(Field.ASSET_TAG_NAMES, keywords);
162 searchQuery.addTerms(Field.KEYWORDS, keywords);
163 }
164
165 for (String entryClassName : searchContext.getEntryClassNames()) {
166 Indexer indexer = IndexerRegistryUtil.getIndexer(entryClassName);
167
168 if (indexer == null) {
169 continue;
170 }
171
172 if (Validator.isNotNull(keywords)) {
173 addSearchExpandoKeywords(
174 searchQuery, searchContext, keywords, entryClassName);
175 }
176
177 indexer.postProcessSearchQuery(searchQuery, searchContext);
178
179 for (IndexerPostProcessor indexerPostProcessor :
180 indexer.getIndexerPostProcessors()) {
181
182 indexerPostProcessor.postProcessSearchQuery(
183 searchQuery, searchContext);
184 }
185 }
186
187 Map<String, Facet> facets = searchContext.getFacets();
188
189 for (Facet facet : facets.values()) {
190 BooleanClause facetClause = facet.getFacetClause();
191
192 if (facetClause != null) {
193 contextQuery.add(
194 facetClause.getQuery(),
195 facetClause.getBooleanClauseOccur());
196 }
197 }
198
199 BooleanQuery fullQuery = BooleanQueryFactoryUtil.create(searchContext);
200
201 fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
202
203 if (searchQuery.hasClauses()) {
204 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
205 }
206
207 BooleanClause[] booleanClauses = searchContext.getBooleanClauses();
208
209 if (booleanClauses != null) {
210 for (BooleanClause booleanClause : booleanClauses) {
211 fullQuery.add(
212 booleanClause.getQuery(),
213 booleanClause.getBooleanClauseOccur());
214 }
215 }
216
217 for (String entryClassName : searchContext.getEntryClassNames()) {
218 Indexer indexer = IndexerRegistryUtil.getIndexer(entryClassName);
219
220 if (indexer == null) {
221 continue;
222 }
223
224 for (IndexerPostProcessor indexerPostProcessor :
225 indexer.getIndexerPostProcessors()) {
226
227 indexerPostProcessor.postProcessFullQuery(
228 fullQuery, searchContext);
229 }
230 }
231
232 return fullQuery;
233 }
234
235 @Override
236 protected void doDelete(Object obj) throws Exception {
237 throw new UnsupportedOperationException();
238 }
239
240 @Override
241 protected Document doGetDocument(Object obj) throws Exception {
242 throw new UnsupportedOperationException();
243 }
244
245 @Override
246 protected Summary doGetSummary(
247 Document document, Locale locale, String snippet,
248 PortletURL portletURL)
249 throws Exception {
250
251 throw new UnsupportedOperationException();
252 }
253
254 @Override
255 protected void doReindex(Object obj) throws Exception {
256 throw new UnsupportedOperationException();
257 }
258
259 @Override
260 protected void doReindex(String className, long classPK) throws Exception {
261 throw new UnsupportedOperationException();
262 }
263
264 @Override
265 protected void doReindex(String[] ids) throws Exception {
266 throw new UnsupportedOperationException();
267 }
268
269 @Override
270 protected String getPortletId(SearchContext searchContext) {
271 return null;
272 }
273
274 protected boolean isFilterSearch(SearchContext searchContext) {
275 if (searchContext.getEntryClassNames() == null) {
276 return super.isFilterSearch();
277 }
278
279 for (String entryClassName : searchContext.getEntryClassNames()) {
280 Indexer indexer = IndexerRegistryUtil.getIndexer(entryClassName);
281
282 if (indexer == null) {
283 continue;
284 }
285
286 if (indexer.isFilterSearch()) {
287 return true;
288 }
289 }
290
291 return super.isFilterSearch();
292 }
293
294 }