001/*
002 * (C) Copyright 2013 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 *     Thomas Roger
018 */
019package org.nuxeo.ecm.platform.picture;
020
021import static org.nuxeo.ecm.core.api.CoreSession.ALLOW_VERSION_WRITE;
022
023import java.io.IOException;
024import java.util.List;
025
026import org.nuxeo.ecm.core.api.Blob;
027import org.nuxeo.ecm.core.api.DocumentModel;
028import org.nuxeo.ecm.core.api.DocumentNotFoundException;
029import org.nuxeo.ecm.core.api.IdRef;
030import org.nuxeo.ecm.core.api.model.Property;
031import org.nuxeo.ecm.core.event.Event;
032import org.nuxeo.ecm.core.event.EventService;
033import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
034import org.nuxeo.ecm.core.work.AbstractWork;
035import org.nuxeo.ecm.core.work.api.WorkManager;
036import org.nuxeo.ecm.platform.picture.api.adapters.PictureResourceAdapter;
037import org.nuxeo.runtime.api.Framework;
038
039/**
040 * Work generating the different picture views for a Picture.
041 *
042 * @since 5.7
043 */
044public class PictureViewsGenerationWork extends AbstractWork {
045
046    private static final long serialVersionUID = 1L;
047
048    public static final String CATEGORY_PICTURE_GENERATION = "pictureViewsGeneration";
049
050    public static final String PICTURE_VIEWS_GENERATION_DONE_EVENT = "pictureViewsGenerationDone";
051
052    protected final String xpath;
053
054    public PictureViewsGenerationWork(String repositoryName, String docId, String xpath) {
055        super(repositoryName + ':' + docId + ':' + xpath + ":pictureView");
056        setDocument(repositoryName, docId);
057        this.xpath = xpath;
058    }
059
060    @Override
061    public String getCategory() {
062        return CATEGORY_PICTURE_GENERATION;
063    }
064
065    @Override
066    public String getTitle() {
067        return "Picture views generation";
068    }
069
070    @Override
071    public int getRetryCount() {
072        // we could fail to get the doc due to a concurrent delete, so allow to retry
073        return 2;
074    }
075
076    @Override
077    public void work() {
078        setProgress(Progress.PROGRESS_INDETERMINATE);
079        setStatus("Extracting");
080
081        openSystemSession();
082        if (!session.exists(new IdRef(docId))) {
083            setStatus("Nothing to process");
084            return;
085        }
086
087        DocumentModel workingDocument = session.getDocument(new IdRef(docId));
088        Property fileProp = workingDocument.getProperty(xpath);
089        Blob blob = (Blob) fileProp.getValue();
090        if (blob == null) {
091            // do nothing
092            return;
093        }
094
095        String title = workingDocument.getTitle();
096        setStatus("Generating views");
097        try {
098            PictureResourceAdapter picture = workingDocument.getAdapter(PictureResourceAdapter.class);
099            picture.fillPictureViews(blob, blob.getFilename(), title, null);
100        } catch (DocumentNotFoundException e) {
101            // a parent of the document may have been deleted.
102            setStatus("Nothing to process");
103            return;
104        } catch (IOException e) {
105            throw new RuntimeException(e);
106        }
107
108        if (!session.exists(new IdRef(docId))) {
109            setStatus("Nothing to process");
110            return;
111        }
112        setStatus("Saving");
113        if (workingDocument.isVersion()) {
114            workingDocument.putContextData(ALLOW_VERSION_WRITE, Boolean.TRUE);
115        }
116        workingDocument.putContextData("disableNotificationService", Boolean.TRUE);
117        workingDocument.putContextData("disableAuditLogger", Boolean.TRUE);
118        session.saveDocument(workingDocument);
119
120        firePictureViewsGenerationDoneEvent(workingDocument);
121
122        setStatus("Done");
123    }
124
125    /**
126     * Fire a {@code PICTURE_VIEWS_GENERATION_DONE_EVENT} event when no other PictureViewsGenerationWork is scheduled
127     * for this document.
128     *
129     * @since 5.8
130     */
131    protected void firePictureViewsGenerationDoneEvent(DocumentModel doc) {
132        WorkManager workManager = Framework.getLocalService(WorkManager.class);
133        List<String> workIds = workManager.listWorkIds(CATEGORY_PICTURE_GENERATION, null);
134        int worksCount = 0;
135        for (String workId : workIds) {
136            if (workId.equals(getId())) {
137                if (++worksCount > 1) {
138                    // another work scheduled
139                    return;
140                }
141            }
142        }
143        DocumentEventContext ctx = new DocumentEventContext(session, session.getPrincipal(), doc);
144        Event event = ctx.newEvent(PICTURE_VIEWS_GENERATION_DONE_EVENT);
145        Framework.getLocalService(EventService.class).fireEvent(event);
146    }
147
148}