001/*
002 * (C) Copyright 2006-2011 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 <troger@nuxeo.com>
018 */
019
020package org.nuxeo.ecm.platform.picture.listener;
021
022import static org.nuxeo.ecm.core.api.event.DocumentEventTypes.ABOUT_TO_CREATE;
023import static org.nuxeo.ecm.platform.picture.api.ImagingDocumentConstants.CTX_FORCE_VIEWS_GENERATION;
024import static org.nuxeo.ecm.platform.picture.api.ImagingDocumentConstants.PICTUREBOOK_TYPE_NAME;
025import static org.nuxeo.ecm.platform.picture.api.ImagingDocumentConstants.PICTURE_FACET;
026
027import java.io.IOException;
028import java.net.URL;
029import java.util.ArrayList;
030import java.util.List;
031import java.util.Map;
032
033import org.apache.commons.logging.Log;
034import org.apache.commons.logging.LogFactory;
035import org.nuxeo.common.utils.FileUtils;
036import org.nuxeo.common.utils.Path;
037import org.nuxeo.ecm.core.api.Blob;
038import org.nuxeo.ecm.core.api.Blobs;
039import org.nuxeo.ecm.core.api.CoreSession;
040import org.nuxeo.ecm.core.api.DocumentModel;
041import org.nuxeo.ecm.core.api.PathRef;
042import org.nuxeo.ecm.core.api.model.Property;
043import org.nuxeo.ecm.core.event.Event;
044import org.nuxeo.ecm.core.event.EventContext;
045import org.nuxeo.ecm.core.event.EventListener;
046import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
047import org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeRegistry;
048import org.nuxeo.ecm.platform.picture.api.ImageInfo;
049import org.nuxeo.ecm.platform.picture.api.ImagingService;
050import org.nuxeo.ecm.platform.picture.api.adapters.AbstractPictureAdapter;
051import org.nuxeo.ecm.platform.picture.api.adapters.PictureResourceAdapter;
052import org.nuxeo.runtime.api.Framework;
053
054/**
055 * Listener updating pre-filling the views of a Picture if the main Blob has changed.
056 *
057 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a>
058 * @since 5.5
059 */
060public class PictureChangedListener implements EventListener {
061
062    public static final String EMPTY_PICTURE_PATH = "nuxeo.war/img/empty_picture.png";
063
064    private static final Log log = LogFactory.getLog(PictureChangedListener.class);
065
066    private static ImageInfo emptyPictureImageInfo;
067
068    @Override
069    public void handleEvent(Event event) {
070        EventContext ctx = event.getContext();
071        if (!(ctx instanceof DocumentEventContext)) {
072            return;
073        }
074        DocumentEventContext docCtx = (DocumentEventContext) ctx;
075        DocumentModel doc = docCtx.getSourceDocument();
076        if (doc.hasFacet(PICTURE_FACET) && !doc.isProxy()) {
077            Property fileProp = doc.getProperty("file:content");
078            Property viewsProp = doc.getProperty(AbstractPictureAdapter.VIEWS_PROPERTY);
079
080            boolean forceGeneration = Boolean.TRUE.equals(doc.getContextData(CTX_FORCE_VIEWS_GENERATION));
081            boolean noPictureViews = !viewsProp.isDirty() || viewsProp.size() == 0;
082            boolean fileChanged = ABOUT_TO_CREATE.equals(event.getName()) || fileProp.isDirty();
083            if (forceGeneration || (noPictureViews  && fileChanged)) {
084                preFillPictureViews(docCtx.getCoreSession(), doc);
085            } else {
086                docCtx.setProperty(PictureViewsGenerationListener.DISABLE_PICTURE_VIEWS_GENERATION_LISTENER, true);
087            }
088        }
089    }
090
091    protected void preFillPictureViews(CoreSession session, DocumentModel doc) {
092        try {
093            URL fileUrl = Thread.currentThread().getContextClassLoader().getResource(getEmptyPicturePath());
094            if (fileUrl == null) {
095                return;
096            }
097
098            Blob blob = Blobs.createBlob(FileUtils.getFileFromURL(fileUrl));
099            MimetypeRegistry mimetypeRegistry = Framework.getLocalService(MimetypeRegistry.class);
100            String mimeType = mimetypeRegistry.getMimetypeFromFilenameAndBlobWithDefault(blob.getFilename(), blob,
101                    null);
102            blob.setMimeType(mimeType);
103
104            DocumentModel parentDoc = getParentDocument(session, doc);
105
106            List<Map<String, Object>> pictureConversions = null;
107            if (parentDoc != null && PICTUREBOOK_TYPE_NAME.equals(parentDoc.getType())) {
108                // use PictureBook Properties
109                pictureConversions = (ArrayList<Map<String, Object>>) parentDoc.getPropertyValue(
110                        "picturebook:picturetemplates");
111                if (pictureConversions.isEmpty()) {
112                    pictureConversions = null;
113                }
114            }
115
116            if (emptyPictureImageInfo == null) {
117                ImagingService imagingService = Framework.getLocalService(ImagingService.class);
118                emptyPictureImageInfo = imagingService.getImageInfo(blob);
119            }
120
121            PictureResourceAdapter adapter = doc.getAdapter(PictureResourceAdapter.class);
122            adapter.preFillPictureViews(blob, pictureConversions, emptyPictureImageInfo);
123        } catch (IOException e) {
124            log.error("Error while pre-filling picture views: " + e.getMessage(), e);
125        }
126    }
127
128    protected String getEmptyPicturePath() {
129        return EMPTY_PICTURE_PATH;
130    }
131
132    protected DocumentModel getParentDocument(CoreSession session, DocumentModel doc) {
133        DocumentModel parent;
134        if (session.exists(doc.getRef())) {
135            parent = session.getParentDocument(doc.getRef());
136        } else {
137            Path parentPath = doc.getPath().removeLastSegments(1);
138            parent = session.getDocument(new PathRef(parentPath.toString()));
139        }
140        return parent;
141    }
142
143}