com.liferay.document.library.repository.cmis.search.BaseCmisSearchQueryBuilder.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.document.library.repository.cmis.search.BaseCmisSearchQueryBuilder.java

Source

/**
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 */

package com.liferay.document.library.repository.cmis.search;

import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.RepositoryEntry;
import com.liferay.portal.kernel.model.User;
import com.liferay.portal.kernel.search.BooleanClause;
import com.liferay.portal.kernel.search.BooleanClauseOccur;
import com.liferay.portal.kernel.search.BooleanQuery;
import com.liferay.portal.kernel.search.Field;
import com.liferay.portal.kernel.search.Query;
import com.liferay.portal.kernel.search.QueryConfig;
import com.liferay.portal.kernel.search.QueryTerm;
import com.liferay.portal.kernel.search.SearchContext;
import com.liferay.portal.kernel.search.SearchException;
import com.liferay.portal.kernel.search.Sort;
import com.liferay.portal.kernel.search.TermQuery;
import com.liferay.portal.kernel.search.TermRangeQuery;
import com.liferay.portal.kernel.search.WildcardQuery;
import com.liferay.portal.kernel.search.generic.MatchQuery;
import com.liferay.portal.kernel.service.RepositoryEntryLocalService;
import com.liferay.portal.kernel.service.RepositoryEntryLocalServiceUtil;
import com.liferay.portal.kernel.service.UserLocalService;
import com.liferay.portal.kernel.service.UserLocalServiceUtil;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.Validator;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * @author Mika Koivisto
 */
public class BaseCmisSearchQueryBuilder implements CMISSearchQueryBuilder {

    public BaseCmisSearchQueryBuilder() {
        this(RepositoryEntryLocalServiceUtil.getService(), UserLocalServiceUtil.getService());
    }

    @Override
    public String buildQuery(SearchContext searchContext, Query query) throws SearchException {

        StringBundler sb = new StringBundler();

        sb.append("SELECT cmis:objectId");

        QueryConfig queryConfig = searchContext.getQueryConfig();

        if (queryConfig.isScoreEnabled()) {
            sb.append(", SCORE() AS HITS");
        }

        sb.append(" FROM cmis:document");

        CMISDisjunction cmisDisjunction = new CMISDisjunction();

        if (_log.isDebugEnabled()) {
            _log.debug("Repository query support " + queryConfig.getAttribute("capabilityQuery"));
        }

        if (!isSupportsOnlyFullText(queryConfig)) {
            traversePropertiesQuery(cmisDisjunction, query, queryConfig);
        }

        if (isSupportsFullText(queryConfig)) {
            CMISContainsExpression cmisContainsExpression = new CMISContainsExpression();

            traverseContentQuery(cmisContainsExpression, query, queryConfig);

            if (!cmisContainsExpression.isEmpty()) {
                cmisDisjunction.add(cmisContainsExpression);
            }
        }

        if (!cmisDisjunction.isEmpty()) {
            sb.append(" WHERE ");
            sb.append(cmisDisjunction.toQueryFragment());
        }

        Sort[] sorts = searchContext.getSorts();

        if (queryConfig.isScoreEnabled() || ArrayUtil.isNotEmpty(sorts)) {
            sb.append(" ORDER BY ");
        }

        if (ArrayUtil.isNotEmpty(sorts)) {
            int i = 0;

            for (Sort sort : sorts) {
                String fieldName = sort.getFieldName();

                if (!isSupportedField(fieldName)) {
                    continue;
                }

                if (i > 0) {
                    sb.append(", ");
                }

                sb.append(getCmisField(fieldName));

                if (sort.isReverse()) {
                    sb.append(" DESC");
                } else {
                    sb.append(" ASC");
                }

                i++;
            }
        } else if (queryConfig.isScoreEnabled()) {
            sb.append("HITS DESC");
        }

        if (_log.isDebugEnabled()) {
            _log.debug("CMIS query " + sb);
        }

        return sb.toString();
    }

    protected BaseCmisSearchQueryBuilder(RepositoryEntryLocalService repositoryEntryLocalService,
            UserLocalService userLocalService) {

        _repositoryEntryLocalService = repositoryEntryLocalService;
        _userLocalService = userLocalService;
    }

    protected CMISCriterion buildFieldExpression(String field, String value,
            CMISSimpleExpressionOperator cmisSimpleExpressionOperator, QueryConfig queryConfig)
            throws SearchException {

        CMISCriterion cmisCriterion = null;

        boolean wildcard = false;

        if (CMISSimpleExpressionOperator.LIKE == cmisSimpleExpressionOperator) {
            wildcard = true;
        }

        if (field.equals(Field.FOLDER_ID)) {
            long folderId = GetterUtil.getLong(value);

            try {
                RepositoryEntry repositoryEntry = _repositoryEntryLocalService.fetchRepositoryEntry(folderId);

                if (repositoryEntry != null) {
                    String objectId = repositoryEntry.getMappedId();

                    objectId = CMISParameterValueUtil.formatParameterValue(field, objectId, wildcard, queryConfig);

                    if (queryConfig.isSearchSubfolders()) {
                        cmisCriterion = new CMISInTreeExpression(objectId);
                    } else {
                        cmisCriterion = new CMISInFolderExpression(objectId);
                    }
                }
            } catch (SystemException se) {
                throw new SearchException("Unable to determine folder {folderId=" + folderId + "}", se);
            }
        } else if (field.equals(Field.USER_ID)) {
            try {
                long userId = GetterUtil.getLong(value);

                User user = _userLocalService.getUserById(userId);

                String screenName = CMISParameterValueUtil.formatParameterValue(field, user.getScreenName(),
                        wildcard, queryConfig);

                cmisCriterion = new CMISSimpleExpression(getCmisField(field), screenName,
                        cmisSimpleExpressionOperator);
            } catch (Exception e) {
                if (e instanceof SearchException) {
                    throw (SearchException) e;
                }

                throw new SearchException("Unable to determine user {" + field + "=" + value + "}", e);
            }
        } else {
            value = CMISParameterValueUtil.formatParameterValue(field, value, wildcard, queryConfig);

            cmisCriterion = new CMISSimpleExpression(getCmisField(field), value, cmisSimpleExpressionOperator);
        }

        return cmisCriterion;
    }

    protected String getCmisField(String field) {
        return _cmisFields.get(field);
    }

    protected boolean isSupportedField(String field) {
        return _supportedFields.contains(field);
    }

    protected boolean isSupportsFullText(QueryConfig queryConfig) {
        String capabilityQuery = (String) queryConfig.getAttribute("capabilityQuery");

        if (Validator.isNull(capabilityQuery)) {
            return false;
        }

        if (capabilityQuery.equals("bothcombined") || capabilityQuery.equals("fulltextonly")) {

            return true;
        }

        return false;
    }

    protected boolean isSupportsOnlyFullText(QueryConfig queryConfig) {
        String capabilityQuery = (String) queryConfig.getAttribute("capabilityQuery");

        if (Validator.isNull(capabilityQuery)) {
            return false;
        }

        if (capabilityQuery.equals("fulltextonly")) {
            return true;
        }

        return false;
    }

    protected void traverseContentQuery(CMISJunction cmisJunction, Query query, QueryConfig queryConfig)
            throws SearchException {

        if (query instanceof BooleanQuery) {
            BooleanQuery booleanQuery = (BooleanQuery) query;

            List<BooleanClause<Query>> booleanClauses = booleanQuery.clauses();

            CMISFullTextConjunction anyCMISConjunction = new CMISFullTextConjunction();
            CMISDisjunction cmisDisjunction = new CMISDisjunction();
            CMISFullTextConjunction notCMISConjunction = new CMISFullTextConjunction();

            for (BooleanClause<Query> booleanClause : booleanClauses) {
                CMISJunction currentCMISJunction = cmisDisjunction;

                BooleanClauseOccur booleanClauseOccur = booleanClause.getBooleanClauseOccur();

                if (booleanClauseOccur.equals(BooleanClauseOccur.MUST)) {
                    currentCMISJunction = anyCMISConjunction;
                } else if (booleanClauseOccur.equals(BooleanClauseOccur.MUST_NOT)) {

                    currentCMISJunction = notCMISConjunction;
                }

                Query booleanClauseQuery = booleanClause.getClause();

                traverseContentQuery(currentCMISJunction, booleanClauseQuery, queryConfig);
            }

            if (!anyCMISConjunction.isEmpty()) {
                cmisJunction.add(anyCMISConjunction);
            }

            if (!cmisDisjunction.isEmpty()) {
                cmisJunction.add(cmisDisjunction);
            }

            if (!notCMISConjunction.isEmpty()) {
                CMISContainsNotExpression cmisContainsNotExpression = new CMISContainsNotExpression(
                        notCMISConjunction);

                cmisJunction.add(cmisContainsNotExpression);
            }
        } else if (query instanceof TermQuery) {
            TermQuery termQuery = (TermQuery) query;

            QueryTerm queryTerm = termQuery.getQueryTerm();

            if (!_isContentFieldQueryTerm(queryTerm)) {
                return;
            }

            String field = queryTerm.getField();
            String value = queryTerm.getValue();

            value = CMISParameterValueUtil.formatParameterValue(field, value, false, queryConfig);

            CMISContainsValueExpression cmisContainsValueExpression = new CMISContainsValueExpression(value);

            cmisJunction.add(cmisContainsValueExpression);
        } else if (query instanceof WildcardQuery) {
            WildcardQuery wildcardQuery = (WildcardQuery) query;

            QueryTerm queryTerm = wildcardQuery.getQueryTerm();

            if (!_isContentFieldQueryTerm(queryTerm)) {
                return;
            }

            String value = queryTerm.getValue();

            String[] terms = value.split(_STAR_PATTERN);

            CMISConjunction cmisConjunction = new CMISConjunction();

            for (String term : terms) {
                if (Validator.isNotNull(term)) {
                    CMISContainsValueExpression containsValueExpression = new CMISContainsValueExpression(term);

                    cmisConjunction.add(containsValueExpression);
                }
            }

            cmisJunction.add(cmisConjunction);
        } else if (query instanceof TermRangeQuery) {
            return;
        }
    }

    protected void traversePropertiesQuery(CMISJunction cmisJunction, Query query, QueryConfig queryConfig)
            throws SearchException {

        if (query instanceof BooleanQuery) {
            BooleanQuery booleanQuery = (BooleanQuery) query;

            List<BooleanClause<Query>> booleanClauses = booleanQuery.clauses();

            CMISConjunction anyCMISConjunction = new CMISConjunction();
            CMISDisjunction cmisDisjunction = new CMISDisjunction();
            CMISConjunction notCMISConjunction = new CMISConjunction();

            for (BooleanClause<Query> booleanClause : booleanClauses) {
                CMISJunction currentCMISJunction = cmisDisjunction;

                BooleanClauseOccur booleanClauseOccur = booleanClause.getBooleanClauseOccur();

                if (booleanClauseOccur.equals(BooleanClauseOccur.MUST)) {
                    currentCMISJunction = anyCMISConjunction;
                } else if (booleanClauseOccur.equals(BooleanClauseOccur.MUST_NOT)) {

                    currentCMISJunction = notCMISConjunction;
                }

                Query booleanClauseQuery = booleanClause.getClause();

                traversePropertiesQuery(currentCMISJunction, booleanClauseQuery, queryConfig);
            }

            if (!anyCMISConjunction.isEmpty()) {
                cmisJunction.add(anyCMISConjunction);
            }

            if (!cmisDisjunction.isEmpty()) {
                cmisJunction.add(cmisDisjunction);
            }

            if (!notCMISConjunction.isEmpty()) {
                cmisJunction.add(new CMISNotExpression(notCMISConjunction));
            }
        } else if (query instanceof MatchQuery) {
            MatchQuery matchQuery = (MatchQuery) query;

            if (!isSupportedField(matchQuery.getField())) {
                return;
            }

            CMISCriterion cmisCriterion = buildFieldExpression(matchQuery.getField(), matchQuery.getValue(),
                    CMISSimpleExpressionOperator.EQ, queryConfig);

            if (cmisCriterion != null) {
                cmisJunction.add(cmisCriterion);
            }
        } else if (query instanceof TermQuery) {
            TermQuery termQuery = (TermQuery) query;

            QueryTerm queryTerm = termQuery.getQueryTerm();

            if (!isSupportedField(queryTerm.getField())) {
                return;
            }

            CMISCriterion cmisCriterion = buildFieldExpression(queryTerm.getField(), queryTerm.getValue(),
                    CMISSimpleExpressionOperator.EQ, queryConfig);

            if (cmisCriterion != null) {
                cmisJunction.add(cmisCriterion);
            }
        } else if (query instanceof TermRangeQuery) {
            TermRangeQuery termRangeQuery = (TermRangeQuery) query;

            if (!isSupportedField(termRangeQuery.getField())) {
                return;
            }

            String fieldName = termRangeQuery.getField();

            String cmisField = getCmisField(fieldName);
            String cmisLowerTerm = CMISParameterValueUtil.formatParameterValue(fieldName,
                    termRangeQuery.getLowerTerm(), false, queryConfig);
            String cmisUpperTerm = CMISParameterValueUtil.formatParameterValue(fieldName,
                    termRangeQuery.getUpperTerm(), false, queryConfig);

            CMISCriterion cmisCriterion = new CMISBetweenExpression(cmisField, cmisLowerTerm, cmisUpperTerm,
                    termRangeQuery.includesLower(), termRangeQuery.includesUpper());

            cmisJunction.add(cmisCriterion);
        } else if (query instanceof WildcardQuery) {
            WildcardQuery wildcardQuery = (WildcardQuery) query;

            QueryTerm queryTerm = wildcardQuery.getQueryTerm();

            if (!isSupportedField(queryTerm.getField())) {
                return;
            }

            CMISCriterion cmisCriterion = buildFieldExpression(queryTerm.getField(), queryTerm.getValue(),
                    CMISSimpleExpressionOperator.LIKE, queryConfig);

            if (cmisCriterion != null) {
                cmisJunction.add(cmisCriterion);
            }
        }
    }

    private boolean _isContentFieldQueryTerm(QueryTerm queryTerm) {
        String fieldName = queryTerm.getField();

        return fieldName.equals(Field.CONTENT);
    }

    private static final String _STAR_PATTERN = Pattern.quote(StringPool.STAR);

    private static final Log _log = LogFactoryUtil.getLog(BaseCmisSearchQueryBuilder.class);

    private static final Map<String, String> _cmisFields;
    private static final Set<String> _supportedFields;

    static {
        _cmisFields = new HashMap<>();

        _cmisFields.put(Field.CREATE_DATE, "cmis:creationDate");
        _cmisFields.put(Field.MODIFIED_DATE, "cmis:lastModificationDate");
        _cmisFields.put(Field.NAME, "cmis:name");
        _cmisFields.put(Field.TITLE, "cmis:name");
        _cmisFields.put(Field.USER_ID, "cmis:createdBy");
        _cmisFields.put(Field.USER_NAME, "cmis:createdBy");

        _supportedFields = new HashSet<>();

        _supportedFields.add(Field.CREATE_DATE);
        _supportedFields.add(Field.FOLDER_ID);
        _supportedFields.add(Field.MODIFIED_DATE);
        _supportedFields.add(Field.NAME);
        _supportedFields.add(Field.TITLE);
        _supportedFields.add(Field.USER_ID);
        _supportedFields.add(Field.USER_NAME);
    }

    private final RepositoryEntryLocalService _repositoryEntryLocalService;
    private final UserLocalService _userLocalService;

}