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