001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.repository.cmis.search;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.search.BooleanClause;
022    import com.liferay.portal.kernel.search.BooleanClauseOccur;
023    import com.liferay.portal.kernel.search.BooleanQuery;
024    import com.liferay.portal.kernel.search.Field;
025    import com.liferay.portal.kernel.search.Query;
026    import com.liferay.portal.kernel.search.QueryConfig;
027    import com.liferay.portal.kernel.search.QueryTerm;
028    import com.liferay.portal.kernel.search.SearchContext;
029    import com.liferay.portal.kernel.search.Sort;
030    import com.liferay.portal.kernel.search.TermQuery;
031    import com.liferay.portal.kernel.search.TermRangeQuery;
032    import com.liferay.portal.kernel.search.WildcardQuery;
033    import com.liferay.portal.kernel.util.GetterUtil;
034    import com.liferay.portal.kernel.util.StringBundler;
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.HashSet;
041    import java.util.List;
042    import java.util.Set;
043    
044    import org.apache.chemistry.opencmis.commons.PropertyIds;
045    import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
046    
047    /**
048     * @author Mika Koivisto
049     */
050    public class CMISQueryBuilder {
051    
052            public static String buildQuery(SearchContext searchContext, Query query) {
053                    StringBundler sb = new StringBundler();
054    
055                    sb.append("SELECT ");
056                    sb.append(PropertyIds.OBJECT_ID);
057    
058                    QueryConfig queryConfig = searchContext.getQueryConfig();
059    
060                    if (queryConfig.isScoreEnabled()) {
061                            sb.append(", SCORE() AS HITS");
062                    }
063    
064                    sb.append(" FROM ");
065                    sb.append(BaseTypeId.CMIS_DOCUMENT.value());
066    
067                    CMISConjunction cmisConjunction = new CMISConjunction();
068    
069                    _traverseQuery(cmisConjunction, query);
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() ||
079                            ((sorts != null) && sorts.length > 0)) {
080    
081                            sb.append(" ORDER BY ");
082                    }
083    
084                    if ((sorts != null) && (sorts.length > 0)) {
085                            for (int i = 0; i < sorts.length; i++) {
086                                    Sort sort = sorts[i];
087    
088                                    if (i > 0) {
089                                            sb.append(", ");
090                                    }
091    
092                                    String fieldName = sort.getFieldName();
093    
094                                    if (fieldName.equals(Field.CREATE_DATE)) {
095                                            sb.append(PropertyIds.CREATION_DATE);
096                                    }
097                                    else if (fieldName.equals(Field.MODIFIED_DATE)) {
098                                            sb.append(PropertyIds.LAST_MODIFICATION_DATE);
099                                    }
100                                    else if (fieldName.equals(Field.TITLE)) {
101                                            sb.append(PropertyIds.NAME);
102                                    }
103    
104                                    if (sort.isReverse()) {
105                                            sb.append(" DESC");
106                                    }
107                                    else {
108                                            sb.append(" ASC");
109                                    }
110                            }
111                    }
112                    else if (queryConfig.isScoreEnabled()) {
113                            sb.append("HITS DESC");
114                    }
115    
116                    return sb.toString();
117            }
118    
119            private static CMISCriterion _buildFieldExpression(
120                    String field, String value,
121                    CMISSimpleExpressionOperator cmisSimpleExpressionOperator) {
122    
123                    CMISCriterion cmisCriterion = null;
124    
125                    boolean wildcard =
126                            CMISSimpleExpressionOperator.LIKE == cmisSimpleExpressionOperator;
127    
128                    if (field.equals(Field.CONTENT)) {
129                            value = CMISParameterValueUtil.formatParameterValue(field, value);
130    
131                            cmisCriterion = new CMISContainsExpression(value);
132                    }
133                    else if (field.equals(Field.FOLDER_ID)) {
134                            long folderId = GetterUtil.getLong(value);
135    
136                            try {
137                                    RepositoryEntry repositoryEntry =
138                                            RepositoryEntryLocalServiceUtil.fetchRepositoryEntry(
139                                                    folderId);
140    
141                                    if (repositoryEntry != null) {
142                                            String objectId = repositoryEntry.getMappedId();
143    
144                                            objectId = CMISParameterValueUtil.formatParameterValue(
145                                                    field, objectId, wildcard);
146    
147                                            cmisCriterion = new CMISInFolderExpression(objectId);
148                                    }
149                            }
150                            catch (SystemException se) {
151                                    _log.error(se, se);
152                            }
153                    }
154                    else if (field.equals(Field.TITLE)) {
155                            value = CMISParameterValueUtil.formatParameterValue(
156                                    field, value, wildcard);
157    
158                            cmisCriterion = new CMISSimpleExpression(
159                                    PropertyIds.NAME, value, cmisSimpleExpressionOperator);
160                    }
161                    else if (field.equals(Field.USER_ID)) {
162                            try {
163                                    long userId = GetterUtil.getLong(value);
164    
165                                    User user = UserLocalServiceUtil.getUserById(userId);
166    
167                                    String screenName = CMISParameterValueUtil.formatParameterValue(
168                                            field, user.getScreenName(), wildcard);
169    
170                                    cmisCriterion = new CMISSimpleExpression(
171                                            PropertyIds.CREATED_BY, screenName,
172                                            cmisSimpleExpressionOperator);
173                            }
174                            catch (PortalException pe) {
175                                    if (_log.isWarnEnabled()) {
176                                            _log.warn(pe, pe);
177                                    }
178                            }
179                            catch (SystemException se) {
180                                    _log.error(se, se);
181                            }
182                    }
183                    else if (field.equals(Field.USER_NAME)) {
184                            value = CMISParameterValueUtil.formatParameterValue(
185                                    field, value, wildcard);
186    
187                            cmisCriterion = new CMISSimpleExpression(
188                                    PropertyIds.CREATED_BY, value, cmisSimpleExpressionOperator);
189                    }
190    
191                    return cmisCriterion;
192            }
193    
194            private static void _traverseQuery(CMISJunction criterion, Query query) {
195                    if (query instanceof BooleanQuery) {
196                            BooleanQuery booleanQuery = (BooleanQuery)query;
197    
198                            List<BooleanClause> booleanClauses = booleanQuery.clauses();
199    
200                            CMISConjunction anyCMISConjunction = new CMISConjunction();
201                            CMISConjunction notCMISConjunction = new CMISConjunction();
202                            CMISDisjunction cmisDisjunction = new CMISDisjunction();
203    
204                            for (BooleanClause booleanClause : booleanClauses) {
205                                    CMISJunction cmisJunction = cmisDisjunction;
206    
207                                    BooleanClauseOccur booleanClauseOccur =
208                                            booleanClause.getBooleanClauseOccur();
209    
210                                    if (booleanClauseOccur.equals(BooleanClauseOccur.MUST)) {
211                                            cmisJunction = anyCMISConjunction;
212                                    }
213                                    else if (booleanClauseOccur.equals(
214                                                            BooleanClauseOccur.MUST_NOT)) {
215    
216                                            cmisJunction = notCMISConjunction;
217                                    }
218    
219                                    Query booleanClauseQuery = booleanClause.getQuery();
220    
221                                    _traverseQuery(cmisJunction, booleanClauseQuery);
222                            }
223    
224                            if (!anyCMISConjunction.isEmpty()) {
225                                    criterion.add(anyCMISConjunction);
226                            }
227    
228                            if (!cmisDisjunction.isEmpty()) {
229                                    criterion.add(cmisDisjunction);
230                            }
231    
232                            if (!notCMISConjunction.isEmpty()) {
233                                    criterion.add(new CMISNotExpression(notCMISConjunction));
234                            }
235                    }
236                    else if (query instanceof TermQuery) {
237                            TermQuery termQuery = (TermQuery)query;
238    
239                            QueryTerm queryTerm = termQuery.getQueryTerm();
240    
241                            if (!_supportedFields.contains(queryTerm.getField())) {
242                                    return;
243                            }
244    
245                            CMISCriterion cmisExpression = _buildFieldExpression(
246                                    queryTerm.getField(), queryTerm.getValue(),
247                                    CMISSimpleExpressionOperator.EQ);
248    
249                            if (cmisExpression != null) {
250                                    criterion.add(cmisExpression);
251                            }
252                    }
253                    else if (query instanceof TermRangeQuery) {
254                            TermRangeQuery termRangeQuery = (TermRangeQuery)query;
255    
256                            if (!_supportedFields.contains(termRangeQuery.getField())) {
257                                    return;
258                            }
259    
260                            CMISCriterion cmisCriterion = new CMISBetweenExpression(
261                                    termRangeQuery.getField(), termRangeQuery.getLowerTerm(),
262                                    termRangeQuery.getUpperTerm(), termRangeQuery.includesLower(),
263                                    termRangeQuery.includesUpper());
264    
265                            criterion.add(cmisCriterion);
266                    }
267                    else if (query instanceof WildcardQuery) {
268                            WildcardQuery wildcardQuery = (WildcardQuery)query;
269    
270                            QueryTerm queryTerm = wildcardQuery.getQueryTerm();
271    
272                            if (!_supportedFields.contains(queryTerm.getField())) {
273                                    return;
274                            }
275    
276                            CMISCriterion cmisCriterion = _buildFieldExpression(
277                                    queryTerm.getField(), queryTerm.getValue(),
278                                    CMISSimpleExpressionOperator.LIKE);
279    
280                            if (cmisCriterion != null) {
281                                    criterion.add(cmisCriterion);
282                            }
283                    }
284            }
285    
286            private static Log _log = LogFactoryUtil.getLog(CMISQueryBuilder.class);
287    
288            private static Set<String> _supportedFields;
289    
290            static {
291                    _supportedFields = new HashSet<String>();
292    
293                    _supportedFields.add(Field.CREATE_DATE);
294                    _supportedFields.add(Field.FOLDER_ID);
295                    _supportedFields.add(Field.NAME);
296                    _supportedFields.add(Field.TITLE);
297                    _supportedFields.add(Field.USER_ID);
298                    _supportedFields.add(Field.USER_NAME);
299            }
300    
301    }