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