001/*
002 * (C) Copyright 2006-2007 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 * $Id$
018 */
019
020package org.nuxeo.ecm.platform.content.template.service;
021
022import java.util.HashMap;
023import java.util.Map;
024import java.util.Set;
025
026import org.apache.commons.logging.Log;
027import org.apache.commons.logging.LogFactory;
028import org.nuxeo.ecm.core.api.CoreSession;
029import org.nuxeo.ecm.core.api.DocumentModel;
030import org.nuxeo.ecm.core.repository.RepositoryInitializationHandler;
031import org.nuxeo.ecm.platform.content.template.listener.RepositoryInitializationListener;
032import org.nuxeo.runtime.model.ComponentContext;
033import org.nuxeo.runtime.model.ComponentInstance;
034import org.nuxeo.runtime.model.DefaultComponent;
035
036public class ContentTemplateServiceImpl extends DefaultComponent implements ContentTemplateService {
037
038    public static final String NAME = "org.nuxeo.ecm.platform.content.template.service.TemplateService";
039
040    public static final String FACTORY_DECLARATION_EP = "factory";
041
042    public static final String FACTORY_BINDING_EP = "factoryBinding";
043
044    public static final String POST_CONTENT_CREATION_HANDLERS_EP = "postContentCreationHandlers";
045
046    private static final Log log = LogFactory.getLog(ContentTemplateServiceImpl.class);
047
048    private final Map<String, ContentFactoryDescriptor> factories = new HashMap<String, ContentFactoryDescriptor>();
049
050    private final Map<String, FactoryBindingDescriptor> factoryBindings = new HashMap<String, FactoryBindingDescriptor>();
051
052    private final Map<String, ContentFactory> factoryInstancesByType = new HashMap<String, ContentFactory>();
053
054    private final Map<String, ContentFactory> factoryInstancesByFacet = new HashMap<String, ContentFactory>();
055
056    private PostContentCreationHandlerRegistry postContentCreationHandlers;
057
058    private RepositoryInitializationHandler initializationHandler;
059
060    @Override
061    public void activate(ComponentContext context) {
062        // register our Repo init listener
063        initializationHandler = new RepositoryInitializationListener();
064        initializationHandler.install();
065
066        postContentCreationHandlers = new PostContentCreationHandlerRegistry();
067    }
068
069    @Override
070    public void deactivate(ComponentContext context) {
071        if (initializationHandler != null) {
072            initializationHandler.uninstall();
073        }
074    }
075
076    @Override
077    public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
078
079        if (extensionPoint.equals(FACTORY_DECLARATION_EP)) {
080            // store factories
081            ContentFactoryDescriptor descriptor = (ContentFactoryDescriptor) contribution;
082            factories.put(descriptor.getName(), descriptor);
083        } else if (extensionPoint.equals(FACTORY_BINDING_EP)) {
084            // store factories binding to types
085            FactoryBindingDescriptor descriptor = (FactoryBindingDescriptor) contribution;
086            if (factories.containsKey(descriptor.getFactoryName())) {
087                String targetType = descriptor.getTargetType();
088                String targetFacet = descriptor.getTargetFacet();
089
090                // merge binding
091                if (descriptor.getAppend()) {
092                    descriptor = mergeFactoryBindingDescriptor(descriptor);
093                }
094
095                // store binding
096                if (null != targetType) {
097                    factoryBindings.put(targetType, descriptor);
098                } else {
099                    factoryBindings.put(targetFacet, descriptor);
100                }
101
102                // create factory instance : one instance per binding
103                ContentFactoryDescriptor factoryDescriptor = factories.get(descriptor.getFactoryName());
104                try {
105                    ContentFactory factory = factoryDescriptor.getClassName().newInstance();
106                    Boolean factoryOK = factory.initFactory(descriptor.getOptions(), descriptor.getRootAcl(),
107                            descriptor.getTemplate());
108                    if (!factoryOK) {
109                        log.error("Error while initializing instance of factory " + factoryDescriptor.getName());
110                        return;
111                    }
112
113                    // store initialized instance
114                    if (null != targetType) {
115                        factoryInstancesByType.put(targetType, factory);
116                    } else {
117                        factoryInstancesByFacet.put(targetFacet, factory);
118                    }
119
120                } catch (InstantiationException e) {
121                    log.error("Error while creating instance of factory " + factoryDescriptor.getName() + " :"
122                            + e.getMessage());
123                } catch (IllegalAccessException e) {
124                    log.error("Error while creating instance of factory " + factoryDescriptor.getName() + " :"
125                            + e.getMessage());
126                }
127            } else {
128                log.error("Factory Binding" + descriptor.getName() + " can not be registered since Factory "
129                        + descriptor.getFactoryName() + " is not registered");
130            }
131        } else if (POST_CONTENT_CREATION_HANDLERS_EP.equals(extensionPoint)) {
132            PostContentCreationHandlerDescriptor descriptor = (PostContentCreationHandlerDescriptor) contribution;
133            postContentCreationHandlers.addContribution(descriptor);
134        }
135    }
136
137    private FactoryBindingDescriptor mergeFactoryBindingDescriptor(FactoryBindingDescriptor newOne) {
138        FactoryBindingDescriptor old = null;
139        if (null != newOne.getTargetType()) {
140            old = factoryBindings.get(newOne.getTargetType());
141        } else {
142            old = factoryBindings.get(newOne.getTargetFacet());
143        }
144
145        if (old != null) {
146            log.info("FactoryBinding " + old.getName() + " is merging with " + newOne.getName());
147            old.getOptions().putAll(newOne.getOptions());
148            old.getRootAcl().addAll(newOne.getRootAcl());
149            old.getTemplate().addAll(newOne.getTemplate());
150
151            return old;
152        }
153
154        return newOne;
155    }
156
157    public ContentFactory getFactoryForType(String documentType) {
158        return factoryInstancesByType.get(documentType);
159    }
160
161    public ContentFactory getFactoryForFacet(String facet) {
162        return factoryInstancesByFacet.get(facet);
163    }
164
165    public void executeFactoryForType(DocumentModel createdDocument) {
166        ContentFactory factory = getFactoryForType(createdDocument.getType());
167        if (factory != null) {
168            factory.createContentStructure(createdDocument);
169        }
170        Set<String> facets = createdDocument.getFacets();
171        for (String facet : facets) {
172            factory = getFactoryForFacet(facet);
173            if (factory != null) {
174                factory.createContentStructure(createdDocument);
175            }
176        }
177    }
178
179    @Override
180    public void executePostContentCreationHandlers(CoreSession session) {
181        for (PostContentCreationHandler handler : postContentCreationHandlers.getOrderedHandlers()) {
182            handler.execute(session);
183        }
184    }
185
186    // for testing
187    public Map<String, ContentFactoryDescriptor> getFactories() {
188        return factories;
189    }
190
191    public Map<String, FactoryBindingDescriptor> getFactoryBindings() {
192        return factoryBindings;
193    }
194
195    public Map<String, ContentFactory> getFactoryInstancesByType() {
196        return factoryInstancesByType;
197    }
198
199    public Map<String, ContentFactory> getFactoryInstancesByFacet() {
200        return factoryInstancesByFacet;
201    }
202
203}