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}