001/*
002 * (C) Copyright 2016 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Antoine Taillefer <ataillefer@nuxeo.com>
018 */
019package org.nuxeo.drive.elasticsearch;
020
021import org.apache.commons.lang.StringUtils;
022import org.apache.commons.logging.Log;
023import org.apache.commons.logging.LogFactory;
024import org.nuxeo.drive.adapter.FolderItem;
025import org.nuxeo.drive.adapter.impl.DefaultSyncRootFolderItem;
026import org.nuxeo.drive.adapter.impl.ScrollDocumentModelList;
027import org.nuxeo.ecm.core.api.CoreSession;
028import org.nuxeo.ecm.core.api.DocumentModel;
029import org.nuxeo.elasticsearch.api.ElasticSearchService;
030import org.nuxeo.elasticsearch.api.EsScrollResult;
031import org.nuxeo.elasticsearch.query.NxQueryBuilder;
032import org.nuxeo.runtime.api.Framework;
033
034/**
035 * Elasticsearch implementation of a {@link DefaultSyncRootFolderItem}.
036 *
037 * @since 8.3
038 */
039public class ESSyncRootFolderItem extends DefaultSyncRootFolderItem {
040
041    private static final long serialVersionUID = 1020938498677864484L;
042
043    private static final Log log = LogFactory.getLog(ESSyncRootFolderItem.class);
044
045    public ESSyncRootFolderItem(String factoryName, FolderItem parentItem, DocumentModel doc) {
046        super(factoryName, parentItem, doc);
047    }
048
049    public ESSyncRootFolderItem(String factoryName, FolderItem parentItem, DocumentModel doc,
050            boolean relaxSyncRootConstraint) {
051        super(factoryName, parentItem, doc, relaxSyncRootConstraint);
052    }
053
054    public ESSyncRootFolderItem(String factoryName, FolderItem parentItem, DocumentModel doc,
055            boolean relaxSyncRootConstraint, boolean getLockInfo) {
056        super(factoryName, parentItem, doc, relaxSyncRootConstraint, getLockInfo);
057    }
058
059    protected ESSyncRootFolderItem() {
060        // Needed for JSON deserialization
061    }
062
063    @Override
064    protected ScrollDocumentModelList getScrollBatch(String scrollId, int batchSize, CoreSession session, long keepAlive) {
065
066        ElasticSearchService ess = Framework.getService(ElasticSearchService.class);
067
068        StringBuilder sb = new StringBuilder(String.format("SELECT * FROM Document WHERE ecm:ancestorId = '%s'", docId));
069        sb.append(" AND ecm:currentLifeCycleState != 'deleted'");
070        sb.append(" AND ecm:mixinType != 'HiddenInNavigation'");
071        sb.append(" AND ecm:isCheckedInVersion = 0");
072        // Let's order by path to make it easier for Drive as it isn't that expensive with Elasticsearch
073        sb.append(" ORDER BY ecm:path");
074        String query = sb.toString();
075        NxQueryBuilder queryBuilder = new NxQueryBuilder(session).nxql(query).limit(batchSize);
076
077        EsScrollResult res;
078        if (StringUtils.isEmpty(scrollId)) {
079            if (log.isDebugEnabled()) {
080                log.debug(String.format(
081                        "Executing Elasticsearch initial search request to scroll through the descendants of %s with batchSize = %d and keepAlive = %d: %s",
082                        docPath, batchSize, keepAlive, query));
083            }
084            res = ess.scroll(queryBuilder, keepAlive);
085        } else {
086            if (log.isDebugEnabled()) {
087                log.debug(String.format(
088                        "Scrolling through the descendants of %s with scrollId = %s, batchSize = %s and keepAlive = %s",
089                        docPath, scrollId, batchSize, keepAlive));
090            }
091            res = ess.scroll(new EsScrollResult(queryBuilder, scrollId, keepAlive));
092        }
093        return new ScrollDocumentModelList(res.getScrollId(), res.getDocuments());
094    }
095
096}