001
014
015 package com.liferay.portal.kernel.repository.cmis.search;
016
017 import com.liferay.portal.kernel.exception.SystemException;
018 import com.liferay.portal.kernel.search.BooleanClause;
019 import com.liferay.portal.kernel.search.BooleanClauseOccur;
020 import com.liferay.portal.kernel.search.BooleanQuery;
021 import com.liferay.portal.kernel.search.Field;
022 import com.liferay.portal.kernel.search.Query;
023 import com.liferay.portal.kernel.search.QueryConfig;
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.Sort;
028 import com.liferay.portal.kernel.search.TermQuery;
029 import com.liferay.portal.kernel.search.TermRangeQuery;
030 import com.liferay.portal.kernel.search.WildcardQuery;
031 import com.liferay.portal.kernel.util.ArrayUtil;
032 import com.liferay.portal.kernel.util.GetterUtil;
033 import com.liferay.portal.kernel.util.StringBundler;
034 import com.liferay.portal.kernel.util.Validator;
035 import com.liferay.portal.model.RepositoryEntry;
036 import com.liferay.portal.model.User;
037 import com.liferay.portal.service.RepositoryEntryLocalServiceUtil;
038 import com.liferay.portal.service.UserLocalServiceUtil;
039
040 import java.util.HashMap;
041 import java.util.HashSet;
042 import java.util.List;
043 import java.util.Map;
044 import java.util.Set;
045
046
049 public class BaseCmisSearchQueryBuilder implements CMISSearchQueryBuilder {
050
051 @Override
052 public String buildQuery(SearchContext searchContext, Query query)
053 throws SearchException {
054
055 StringBundler sb = new StringBundler();
056
057 sb.append("SELECT cmis:objectId");
058
059 QueryConfig queryConfig = searchContext.getQueryConfig();
060
061 if (queryConfig.isScoreEnabled()) {
062 sb.append(", SCORE() AS HITS");
063 }
064
065 sb.append(" FROM cmis:document");
066
067 CMISConjunction cmisConjunction = new CMISConjunction();
068
069 traverseQuery(cmisConjunction, query, queryConfig);
070
071 if (!cmisConjunction.isEmpty()) {
072 sb.append(" WHERE ");
073 sb.append(cmisConjunction.toQueryFragment());
074 }
075
076 Sort[] sorts = searchContext.getSorts();
077
078 if (queryConfig.isScoreEnabled() || ArrayUtil.isNotEmpty(sorts)) {
079 sb.append(" ORDER BY ");
080 }
081
082 if (ArrayUtil.isNotEmpty(sorts)) {
083 int i = 0;
084
085 for (Sort sort : sorts) {
086 String fieldName = sort.getFieldName();
087
088 if (!isSupportedField(fieldName)) {
089 continue;
090 }
091
092 if (i > 0) {
093 sb.append(", ");
094 }
095
096 sb.append(getCmisField(fieldName));
097
098 if (sort.isReverse()) {
099 sb.append(" DESC");
100 }
101 else {
102 sb.append(" ASC");
103 }
104
105 i++;
106 }
107 }
108 else if (queryConfig.isScoreEnabled()) {
109 sb.append("HITS DESC");
110 }
111
112 return sb.toString();
113 }
114
115 protected CMISCriterion buildFieldExpression(
116 String field, String value,
117 CMISSimpleExpressionOperator cmisSimpleExpressionOperator,
118 QueryConfig queryConfig)
119 throws SearchException {
120
121 CMISCriterion cmisCriterion = null;
122
123 boolean wildcard =
124 CMISSimpleExpressionOperator.LIKE == cmisSimpleExpressionOperator;
125
126 if (field.equals(Field.CONTENT)) {
127 value = CMISParameterValueUtil.formatParameterValue(
128 field, value, false, queryConfig);
129
130 cmisCriterion = new CMISContainsExpression(value);
131 }
132 else if (field.equals(Field.FOLDER_ID)) {
133 long folderId = GetterUtil.getLong(value);
134
135 try {
136 RepositoryEntry repositoryEntry =
137 RepositoryEntryLocalServiceUtil.fetchRepositoryEntry(
138 folderId);
139
140 if (repositoryEntry != null) {
141 String objectId = repositoryEntry.getMappedId();
142
143 objectId = CMISParameterValueUtil.formatParameterValue(
144 field, objectId, wildcard, queryConfig);
145
146 cmisCriterion = new CMISInFolderExpression(objectId);
147 }
148 }
149 catch (SystemException se) {
150 throw new SearchException(
151 "Unable to determine folder {folderId=" + folderId + "}",
152 se);
153 }
154 }
155 else if (field.equals(Field.USER_ID)) {
156 try {
157 long userId = GetterUtil.getLong(value);
158
159 User user = UserLocalServiceUtil.getUserById(userId);
160
161 String screenName = CMISParameterValueUtil.formatParameterValue(
162 field, user.getScreenName(), wildcard, queryConfig);
163
164 cmisCriterion = new CMISSimpleExpression(
165 getCmisField(field), screenName,
166 cmisSimpleExpressionOperator);
167 }
168 catch (Exception e) {
169 if (e instanceof SearchException) {
170 throw (SearchException)e;
171 }
172
173 throw new SearchException(
174 "Unable to determine user {" + field + "=" + value + "}",
175 e);
176 }
177 }
178 else {
179 value = CMISParameterValueUtil.formatParameterValue(
180 field, value, wildcard, queryConfig);
181
182 cmisCriterion = new CMISSimpleExpression(
183 getCmisField(field), value, cmisSimpleExpressionOperator);
184 }
185
186 return cmisCriterion;
187 }
188
189 protected String getCmisField(String field) {
190 return _cmisFields.get(field);
191 }
192
193 protected boolean isSupportedField(String field) {
194 return _supportedFields.contains(field);
195 }
196
197 protected boolean isSupportsFullText(QueryConfig queryConfig) {
198 String capabilityQuery = (String)queryConfig.getAttribute(
199 "capabilityQuery");
200
201 if (Validator.isNull(capabilityQuery)) {
202 return false;
203 }
204
205 if (capabilityQuery.equals("bothcombined") ||
206 capabilityQuery.equals("fulltextonly")) {
207
208 return true;
209 }
210
211 return false;
212 }
213
214 protected boolean isSupportsOnlyFullText(QueryConfig queryConfig) {
215 String capabilityQuery = (String)queryConfig.getAttribute(
216 "capabilityQuery");
217
218 if (Validator.isNull(capabilityQuery)) {
219 return false;
220 }
221
222 if (capabilityQuery.equals("fulltextonly")) {
223 return true;
224 }
225
226 return false;
227 }
228
229 protected void traverseQuery(
230 CMISJunction criterion, Query query, QueryConfig queryConfig)
231 throws SearchException {
232
233 if (query instanceof BooleanQuery) {
234 BooleanQuery booleanQuery = (BooleanQuery)query;
235
236 List<BooleanClause> booleanClauses = booleanQuery.clauses();
237
238 CMISConjunction anyCMISConjunction = new CMISConjunction();
239 CMISConjunction notCMISConjunction = new CMISConjunction();
240 CMISDisjunction cmisDisjunction = new CMISDisjunction();
241
242 for (BooleanClause booleanClause : booleanClauses) {
243 CMISJunction cmisJunction = cmisDisjunction;
244
245 BooleanClauseOccur booleanClauseOccur =
246 booleanClause.getBooleanClauseOccur();
247
248 if (booleanClauseOccur.equals(BooleanClauseOccur.MUST)) {
249 cmisJunction = anyCMISConjunction;
250 }
251 else if (booleanClauseOccur.equals(
252 BooleanClauseOccur.MUST_NOT)) {
253
254 cmisJunction = notCMISConjunction;
255 }
256
257 Query booleanClauseQuery = booleanClause.getQuery();
258
259 traverseQuery(cmisJunction, booleanClauseQuery, queryConfig);
260 }
261
262 if (!anyCMISConjunction.isEmpty()) {
263 criterion.add(anyCMISConjunction);
264 }
265
266 if (!cmisDisjunction.isEmpty()) {
267 criterion.add(cmisDisjunction);
268 }
269
270 if (!notCMISConjunction.isEmpty()) {
271 criterion.add(new CMISNotExpression(notCMISConjunction));
272 }
273 }
274 else if (query instanceof TermQuery) {
275 TermQuery termQuery = (TermQuery)query;
276
277 QueryTerm queryTerm = termQuery.getQueryTerm();
278
279 if (!isSupportedField(queryTerm.getField())) {
280 return;
281 }
282
283 CMISCriterion cmisExpression = buildFieldExpression(
284 queryTerm.getField(), queryTerm.getValue(),
285 CMISSimpleExpressionOperator.EQ, queryConfig);
286
287 if (cmisExpression != null) {
288 boolean add = true;
289
290 if ((cmisExpression instanceof CMISContainsExpression) &&
291 !isSupportsFullText(queryConfig)) {
292
293 add = false;
294 }
295 else if (!((cmisExpression instanceof CMISContainsExpression) ||
296 (cmisExpression instanceof CMISInFolderExpression) ||
297 (cmisExpression instanceof CMISInTreeExpression)) &&
298 isSupportsOnlyFullText(queryConfig)) {
299
300 add = false;
301 }
302
303 if (add) {
304 criterion.add(cmisExpression);
305 }
306 }
307 }
308 else if (query instanceof TermRangeQuery) {
309 TermRangeQuery termRangeQuery = (TermRangeQuery)query;
310
311 if (!isSupportedField(termRangeQuery.getField())) {
312 return;
313 }
314
315 String fieldName = termRangeQuery.getField();
316
317 String cmisField = getCmisField(fieldName);
318 String cmisLowerTerm = CMISParameterValueUtil.formatParameterValue(
319 fieldName, termRangeQuery.getLowerTerm(), false, queryConfig);
320 String cmisUpperTerm = CMISParameterValueUtil.formatParameterValue(
321 fieldName, termRangeQuery.getUpperTerm(), false, queryConfig);
322
323 CMISCriterion cmisCriterion = new CMISBetweenExpression(
324 cmisField, cmisLowerTerm, cmisUpperTerm,
325 termRangeQuery.includesLower(), termRangeQuery.includesUpper());
326
327 criterion.add(cmisCriterion);
328 }
329 else if (query instanceof WildcardQuery) {
330 WildcardQuery wildcardQuery = (WildcardQuery)query;
331
332 QueryTerm queryTerm = wildcardQuery.getQueryTerm();
333
334 if (!isSupportedField(queryTerm.getField())) {
335 return;
336 }
337
338 CMISCriterion cmisCriterion = buildFieldExpression(
339 queryTerm.getField(), queryTerm.getValue(),
340 CMISSimpleExpressionOperator.LIKE, queryConfig);
341
342 if (cmisCriterion != null) {
343 boolean add = true;
344
345 if ((cmisCriterion instanceof CMISContainsExpression) &&
346 !isSupportsFullText(queryConfig)) {
347
348 add = false;
349 }
350 else if (!((cmisCriterion instanceof CMISContainsExpression) ||
351 (cmisCriterion instanceof CMISInFolderExpression) ||
352 (cmisCriterion instanceof CMISInTreeExpression)) &&
353 isSupportsOnlyFullText(queryConfig)) {
354
355 add = false;
356 }
357
358 if (add) {
359 criterion.add(cmisCriterion);
360 }
361 }
362 }
363 }
364
365 private static Map<String, String> _cmisFields;
366 private static Set<String> _supportedFields;
367
368 static {
369 _cmisFields = new HashMap<String, String>();
370
371 _cmisFields.put(Field.CREATE_DATE, "cmis:creationDate");
372 _cmisFields.put(Field.MODIFIED_DATE, "cmis:lastModificationDate");
373 _cmisFields.put(Field.NAME, "cmis:name");
374 _cmisFields.put(Field.TITLE, "cmis:name");
375 _cmisFields.put(Field.USER_ID, "cmis:createdBy");
376 _cmisFields.put(Field.USER_NAME, "cmis:createdBy");
377
378 _supportedFields = new HashSet<String>();
379
380 _supportedFields.add(Field.CONTENT);
381 _supportedFields.add(Field.CREATE_DATE);
382 _supportedFields.add(Field.FOLDER_ID);
383 _supportedFields.add(Field.MODIFIED_DATE);
384 _supportedFields.add(Field.NAME);
385 _supportedFields.add(Field.TITLE);
386 _supportedFields.add(Field.USER_ID);
387 _supportedFields.add(Field.USER_NAME);
388 }
389
390 }