001/*
002 * (C) Copyright 2016-2018 Nuxeo (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.lang3.StringUtils;
022import org.apache.logging.log4j.LogManager;
023import org.apache.logging.log4j.Logger;
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 Logger log = LogManager.getLogger(ESSyncRootFolderItem.class);
042
043    public ESSyncRootFolderItem(String factoryName, FolderItem parentItem, DocumentModel doc) {
044        super(factoryName, parentItem, doc);
045    }
046
047    public ESSyncRootFolderItem(String factoryName, FolderItem parentItem, DocumentModel doc,
048            boolean relaxSyncRootConstraint) {
049        super(factoryName, parentItem, doc, relaxSyncRootConstraint);
050    }
051
052    public ESSyncRootFolderItem(String factoryName, FolderItem parentItem, DocumentModel doc,
053            boolean relaxSyncRootConstraint, boolean getLockInfo) {
054        super(factoryName, parentItem, doc, relaxSyncRootConstraint, getLockInfo);
055    }
056
057    protected ESSyncRootFolderItem() {
058        // Needed for JSON deserialization
059    }
060
061    @Override
062    protected ScrollDocumentModelList getScrollBatch(String scrollId, int batchSize, CoreSession session,
063            long keepAlive) {
064
065        ElasticSearchService ess = Framework.getService(ElasticSearchService.class);
066
067        StringBuilder sb = new StringBuilder(
068                String.format("SELECT * FROM Document WHERE ecm:ancestorId = '%s'", docId));
069        sb.append(" AND ecm:isTrashed = 0");
070        sb.append(" AND ecm:mixinType != 'HiddenInNavigation'");
071        sb.append(" AND ecm:isVersion = 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            log.debug(
080                    "Executing Elasticsearch initial search request to scroll through the descendants of {} with batchSize = {} and keepAlive = {}: {}",
081                    docPath, batchSize, keepAlive, query);
082            res = ess.scroll(queryBuilder, keepAlive);
083        } else {
084            log.debug("Scrolling through the descendants of {} with scrollId = {}, batchSize = {} and keepAlive = {}",
085                    docPath, scrollId, batchSize, keepAlive);
086            res = ess.scroll(new EsScrollResult(queryBuilder, scrollId, keepAlive));
087        }
088        return new ScrollDocumentModelList(res.getScrollId(), res.getDocuments());
089    }
090
091}