001/*
002 * (C) Copyright 2006-20012 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 */
018
019package org.nuxeo.template.listeners;
020
021import static org.nuxeo.ecm.core.api.event.DocumentEventTypes.ABOUT_TO_CREATE;
022import static org.nuxeo.ecm.core.api.event.DocumentEventTypes.BEFORE_DOC_UPDATE;
023
024import java.util.ArrayList;
025import java.util.List;
026
027import org.apache.commons.logging.Log;
028import org.apache.commons.logging.LogFactory;
029import org.nuxeo.common.collections.ScopeType;
030import org.nuxeo.ecm.core.api.Blob;
031import org.nuxeo.ecm.core.api.DocumentModel;
032import org.nuxeo.ecm.core.api.DocumentRef;
033import org.nuxeo.ecm.core.api.IdRef;
034import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
035import org.nuxeo.ecm.core.api.model.Property;
036import org.nuxeo.ecm.core.event.Event;
037import org.nuxeo.ecm.core.event.EventContext;
038import org.nuxeo.ecm.core.event.EventListener;
039import org.nuxeo.ecm.core.event.impl.DocumentEventContext;
040import org.nuxeo.ecm.core.utils.BlobsExtractor;
041import org.nuxeo.runtime.api.Framework;
042import org.nuxeo.template.api.TemplateInput;
043import org.nuxeo.template.api.TemplateProcessorService;
044import org.nuxeo.template.api.adapters.TemplateBasedDocument;
045import org.nuxeo.template.api.adapters.TemplateSourceDocument;
046
047/**
048 * Listener to manage initialization :
049 * <ul>
050 * <li>of the TemplateSourceDocument : init the parameters</li>
051 * <li>of the other DocumentModels if they need to be automatically associated to a template</li>
052 * </ul>
053 *
054 * @author Tiry (tdelprat@nuxeo.com)
055 */
056public class TemplateInitListener implements EventListener {
057
058    private static final Log log = LogFactory.getLog(TemplateInitListener.class);
059
060    public void handleEvent(Event event) {
061
062        EventContext ctx = event.getContext();
063
064        if (ABOUT_TO_CREATE.equals(event.getName()) || BEFORE_DOC_UPDATE.equals(event.getName())) {
065            if (ctx instanceof DocumentEventContext) {
066                DocumentEventContext docCtx = (DocumentEventContext) ctx;
067
068                DocumentModel targetDoc = docCtx.getSourceDocument();
069
070                if (targetDoc.isVersion()) {
071                    return;
072                }
073
074                TemplateSourceDocument templateDoc = targetDoc.getAdapter(TemplateSourceDocument.class);
075                if (templateDoc != null) {
076                    // init types bindings
077                    templateDoc.initTypesBindings();
078
079                    // init template source
080                    List<TemplateInput> params = templateDoc.getParams();
081                    if (params == null || params.size() == 0 || isBlobDirty(targetDoc)) {
082                        templateDoc.initTemplate(false);
083                    }
084                } else {
085                    TemplateBasedDocument tmplBased = targetDoc.getAdapter(TemplateBasedDocument.class);
086                    if (tmplBased == null) {
087                        // if not templateBased see if we must add the facet
088                        // because of the type binding
089                        // or template selection as main file
090                        TemplateProcessorService tps = Framework.getLocalService(TemplateProcessorService.class);
091
092                        String targetTemplateUid = (String) targetDoc.getContextData().getScopedValue(
093                                ScopeType.REQUEST, "templateId");
094                        if ("none".equals(targetTemplateUid)) {
095                            targetTemplateUid = null;
096                        }
097                        List<String> templatesUids = new ArrayList<String>();
098
099                        if (targetTemplateUid != null) {
100                            templatesUids.add(targetTemplateUid);
101                        }
102
103                        List<String> tuids = tps.getTypeMapping().get(targetDoc.getType());
104                        if (tuids != null) {
105                            for (String tuid : tuids) {
106                                // let's be paranoid
107                                if (!templatesUids.contains(tuid)) {
108                                    templatesUids.add(tuid);
109                                }
110                            }
111                        }
112
113                        // do the association
114                        if (templatesUids.size() > 0) {
115                            for (String tuid : templatesUids) {
116                                DocumentRef templateRef = new IdRef(tuid);
117                                // check if source template is visible
118                                if (docCtx.getCoreSession().exists(templateRef)) {
119                                    DocumentModel sourceTemplateDoc = docCtx.getCoreSession().getDocument(templateRef);
120                                    tps.makeTemplateBasedDocument(targetDoc, sourceTemplateDoc, false);
121                                }
122                            }
123                        }
124                    }
125                }
126            }
127        }
128    }
129
130    protected boolean isBlobDirty(DocumentModel targetDoc) {
131        BlobHolder bh = targetDoc.getAdapter(BlobHolder.class);
132        Blob mainBlob = bh.getBlob();
133        if (mainBlob.getDigest() == null) {
134            // Blobs that have not changed should be SQL Blobs and have a digest
135            return true;
136        } else {
137            // newly uploaded Blob should be FileBlob, and anyway Digest can not
138            // have been computed so far
139            return false;
140        }
141    }
142}