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