001/*
002 * (C) Copyright 2010-2020 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 *     Nuxeo - initial API and implementation
018 */
019
020package org.nuxeo.ecm.platform.video.listener;
021
022import static org.nuxeo.ecm.core.api.event.DocumentEventTypes.BEFORE_DOC_UPDATE;
023import static org.nuxeo.ecm.core.api.event.DocumentEventTypes.DOCUMENT_CREATED;
024import static org.nuxeo.ecm.platform.video.VideoConstants.CTX_FORCE_INFORMATIONS_GENERATION;
025import static org.nuxeo.ecm.platform.video.VideoConstants.TRANSCODED_VIDEOS_PROPERTY;
026import static org.nuxeo.ecm.platform.video.VideoConstants.VIDEO_FACET;
027
028import java.io.IOException;
029
030import org.apache.logging.log4j.LogManager;
031import org.apache.logging.log4j.Logger;
032import org.nuxeo.ecm.core.api.DocumentModel;
033import org.nuxeo.ecm.core.api.NuxeoException;
034import org.nuxeo.ecm.core.event.Event;
035import org.nuxeo.ecm.core.event.EventContext;
036import org.nuxeo.ecm.core.event.EventListener;
037import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
038import org.nuxeo.ecm.core.work.api.WorkManager;
039import org.nuxeo.ecm.platform.video.VideoHelper;
040import org.nuxeo.ecm.platform.video.service.VideoInfoWork;
041import org.nuxeo.runtime.api.Framework;
042
043/**
044 * Light synchronous listener that schedules an asynchronous work to process the video info of a document.
045 * <p>
046 * This {@link VideoInfoWork} will in turn schedule two asynchronous works to process the video storyboard and
047 * conversions.
048 *
049 * @since 5.5
050 */
051public class VideoChangedListener implements EventListener {
052
053    private static final Logger log = LogManager.getLogger(VideoChangedListener.class);
054
055    /** @since 11.1 **/
056    public static final String DISABLE_VIDEO_CONVERSIONS_GENERATION_LISTENER = "disableVideoConversionsGenerationListener";
057
058    @Override
059    public void handleEvent(Event event) {
060        EventContext ctx = event.getContext();
061        if (!(ctx instanceof DocumentEventContext)) {
062            return;
063        }
064
065        DocumentEventContext docCtx = (DocumentEventContext) ctx;
066        DocumentModel doc = docCtx.getSourceDocument();
067        if (Boolean.TRUE.equals(ctx.getProperty(DISABLE_VIDEO_CONVERSIONS_GENERATION_LISTENER))) {
068            log.trace("Video conversions are disabled for document {}", doc::getId);
069            return;
070        }
071
072        String eventName = event.getName();
073        if (shouldProcess(doc, eventName)) {
074            if (BEFORE_DOC_UPDATE.equals(eventName)) {
075                try {
076                    resetProperties(doc);
077                } catch (IOException e) {
078                    throw new NuxeoException(
079                            String.format("Error while resetting video properties of document %s.", doc), e);
080                }
081            }
082            scheduleAsyncProcessing(doc);
083        }
084    }
085
086    protected boolean shouldProcess(DocumentModel doc, String eventName) {
087        return doc.hasFacet(VIDEO_FACET) && !doc.isProxy()
088                && (Boolean.TRUE.equals(doc.getContextData(CTX_FORCE_INFORMATIONS_GENERATION))
089                        || DOCUMENT_CREATED.equals(eventName) || doc.getProperty("file:content").isDirty());
090    }
091
092    protected void resetProperties(DocumentModel doc) throws IOException {
093        log.debug("Resetting video info, storyboard, previews and conversions of document {}", doc);
094        VideoHelper.updateVideoInfo(doc, null);
095        VideoHelper.updateStoryboard(doc, null);
096        VideoHelper.updatePreviews(doc, null);
097        doc.setPropertyValue(TRANSCODED_VIDEOS_PROPERTY, null);
098    }
099
100    protected void scheduleAsyncProcessing(DocumentModel doc) {
101        WorkManager workManager = Framework.getService(WorkManager.class);
102        VideoInfoWork work = new VideoInfoWork(doc.getRepositoryName(), doc.getId());
103        log.debug("Scheduling work: video info of document {}.", doc);
104        workManager.schedule(work, true);
105    }
106
107}