001/* 002 * (C) Copyright 2017-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 * Guillaume Renard 018 */ 019 020package org.nuxeo.ecm.platform.rendition.operation; 021 022import java.io.IOException; 023 024import org.apache.commons.logging.Log; 025import org.apache.commons.logging.LogFactory; 026import org.nuxeo.ecm.automation.OperationContext; 027import org.nuxeo.ecm.automation.core.Constants; 028import org.nuxeo.ecm.automation.core.annotations.Context; 029import org.nuxeo.ecm.automation.core.annotations.Operation; 030import org.nuxeo.ecm.automation.core.annotations.OperationMethod; 031import org.nuxeo.ecm.automation.core.annotations.Param; 032import org.nuxeo.ecm.automation.core.util.BlobList; 033import org.nuxeo.ecm.collections.api.CollectionManager; 034import org.nuxeo.ecm.collections.core.adapter.Collection; 035import org.nuxeo.ecm.core.api.Blob; 036import org.nuxeo.ecm.core.api.CoreSession; 037import org.nuxeo.ecm.core.api.DocumentModel; 038import org.nuxeo.ecm.core.api.DocumentModelIterator; 039import org.nuxeo.ecm.core.api.DocumentRef; 040import org.nuxeo.ecm.core.api.IdRef; 041import org.nuxeo.ecm.core.api.NuxeoException; 042import org.nuxeo.ecm.core.schema.FacetNames; 043import org.nuxeo.ecm.core.utils.BlobUtils; 044import org.nuxeo.ecm.platform.rendition.Rendition; 045import org.nuxeo.ecm.platform.rendition.service.RenditionService; 046 047/** 048 * Returns a Folderish Document or Collection default rendition. 049 * 050 * @since 9.3 051 */ 052@Operation(id = GetContainerRendition.ID, category = Constants.CAT_BLOB, label = "Gets the folder's children or the collection's members default renditions", description = "Gets the list of blob of the folder's children or the collection's members default renditions. Returns a blob list file containing all the default rendition blobs.") 053public class GetContainerRendition { 054 055 private static final Log log = LogFactory.getLog(GetContainerRendition.class); 056 057 public static final String ID = "Document.GetContainerRendition"; 058 059 @Context 060 protected RenditionService renditionService; 061 062 @Context 063 protected CollectionManager collectionManager; 064 065 @Param(name = "reason", required = false) 066 protected String reason; 067 068 @Param(name = "limit", description = "Limit of members to be returned. Default is 100.", required = false) 069 protected int limit = 100; 070 071 @Param(name = "maxDepth", description = "Depth of the hierarchy to be explored. Default is 1.", required = false) 072 protected int maxDepth = 1; 073 074 @Context 075 protected CoreSession session; 076 077 @Context 078 protected OperationContext ctx; 079 080 protected BlobList getCollectionBlobs(Collection collection, int currentDepth) throws IOException { 081 BlobList blobs = new BlobList(); 082 int added = 0; 083 for (String memberId : collection.getCollectedDocumentIds()) { 084 DocumentRef memberRef = new IdRef(memberId); 085 if (session.exists(memberRef) && !session.isTrashed(memberRef)) { 086 DocumentModel member = session.getDocument(memberRef); 087 Blob blob = getDefaultRendition(member, currentDepth + 1); 088 if (blob != null) { 089 blobs.add(blob); 090 if (limit > -1 && ++added >= limit) { 091 if (log.isDebugEnabled()) { 092 log.debug(String.format( 093 "Limit of %s reached, increase the limit parameter to get more results.", limit)); 094 } 095 break; 096 } 097 } 098 } 099 } 100 return blobs; 101 } 102 103 protected Blob getDefaultRendition(DocumentModel doc, int currentDepth) throws IOException { 104 Blob blob = null; 105 if (collectionManager.isCollection(doc) || doc.hasFacet(FacetNames.FOLDERISH)) { 106 if (currentDepth >= maxDepth) { 107 return null; 108 } 109 blob = processContainer(doc, currentDepth + 1); 110 } else { 111 Rendition rendition = renditionService.getDefaultRendition(doc, reason, null); 112 if (rendition != null) { 113 blob = rendition.getBlob(); 114 if (blob == null) { 115 if (log.isDebugEnabled()) { 116 log.debug(String.format("Default rendition '%s' has an null Blob for document '%s'", 117 rendition.getName(), doc.getPathAsString())); 118 } 119 } 120 } 121 } 122 return blob; 123 } 124 125 protected BlobList getFolderishBlobs(DocumentModel parent, int currentDepth) throws IOException { 126 BlobList blobs = new BlobList(); 127 int added = 0; 128 DocumentModelIterator it = session.getChildrenIterator(parent.getRef()); 129 while (it.hasNext()) { 130 DocumentModel child = it.next(); 131 if (!child.isTrashed()) { 132 Blob blob = getDefaultRendition(child, currentDepth); 133 if (blob != null) { 134 blobs.add(blob); 135 if (limit > -1 && ++added >= limit) { 136 if (log.isDebugEnabled()) { 137 log.debug(String.format( 138 "Limit of %s reached, increase the limit parameter to get more results.", limit)); 139 } 140 break; 141 } 142 } 143 } 144 } 145 return blobs; 146 } 147 148 protected Blob processContainer(DocumentModel doc, int currentDepth) throws IOException { 149 BlobList blobs; 150 if (collectionManager.isCollection(doc)) { 151 blobs = getCollectionBlobs(doc.getAdapter(Collection.class), currentDepth); 152 } else if (doc.hasFacet(FacetNames.FOLDERISH)) { 153 blobs = getFolderishBlobs(doc, currentDepth + 1); 154 } else { 155 throw new NuxeoException("The operation only accepts folderish document or collection"); 156 } 157 return BlobUtils.zip(blobs, doc.getName() + ".zip"); 158 } 159 160 @OperationMethod 161 public Blob run(DocumentModel doc) throws IOException { 162 if (maxDepth <= 0) { 163 throw new NuxeoException("Maximum depth must greater or equal to 1."); 164 } 165 return processContainer(doc, 0); 166 } 167 168}