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