001/*
002 * (C) Copyright 2010-2013 Nuxeo SA (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 *     Olivier Grisel
016 */
017package org.nuxeo.ecm.platform.suggestbox.service;
018
019import java.util.ArrayList;
020import java.util.List;
021
022import org.apache.commons.logging.Log;
023import org.apache.commons.logging.LogFactory;
024import org.nuxeo.ecm.platform.suggestbox.service.descriptors.SuggesterDescriptor;
025import org.nuxeo.ecm.platform.suggestbox.service.descriptors.SuggesterGroupDescriptor;
026import org.nuxeo.ecm.platform.suggestbox.service.descriptors.SuggesterGroupItemDescriptor;
027import org.nuxeo.ecm.platform.suggestbox.service.registries.SuggesterGroupRegistry;
028import org.nuxeo.ecm.platform.suggestbox.service.registries.SuggesterRegistry;
029import org.nuxeo.runtime.model.ComponentContext;
030import org.nuxeo.runtime.model.ComponentInstance;
031import org.nuxeo.runtime.model.DefaultComponent;
032
033/**
034 * The Class SuggestionServiceImpl.
035 */
036public class SuggestionServiceImpl extends DefaultComponent implements SuggestionService {
037
038    private static final Log log = LogFactory.getLog(SuggestionServiceImpl.class);
039
040    protected SuggesterGroupRegistry suggesterGroups;
041
042    protected SuggesterRegistry suggesters;
043
044    @Override
045    public List<Suggestion> suggest(String userInput, SuggestionContext context) throws SuggestionException {
046        List<Suggestion> suggestions = new ArrayList<Suggestion>();
047        SuggesterGroupDescriptor suggesterGroup = suggesterGroups.getSuggesterGroupDescriptor(context.suggesterGroup);
048        if (suggesterGroup == null) {
049            log.warn("No registered SuggesterGroup with id: " + context.suggesterGroup);
050            return suggestions;
051        }
052
053        for (SuggesterGroupItemDescriptor suggesterGroupItem : suggesterGroup.getSuggesters()) {
054            String suggesterId = suggesterGroupItem.getName();
055            SuggesterDescriptor suggesterDescritor = suggesters.getSuggesterDescriptor(suggesterId);
056            if (suggesterDescritor == null) {
057                log.warn("No suggester registered with id: " + suggesterId);
058                continue;
059            }
060            if (!suggesterDescritor.isEnabled()) {
061                continue;
062            }
063            Suggester suggester = suggesterDescritor.getSuggester();
064            if (suggester == null) {
065                log.warn("Suggester with id '" + suggesterId + "' has a configuration that prevents instanciation"
066                        + " (no className in aggregate descriptor)");
067                continue;
068            }
069            suggestions.addAll(suggester.suggest(userInput, context));
070        }
071        return suggestions;
072    }
073
074    @Override
075    public List<Suggestion> suggest(String input, SuggestionContext context, String suggesterName)
076            throws SuggestionException {
077        SuggesterDescriptor suggesterDescriptor = suggesters.getSuggesterDescriptor(suggesterName);
078        if (suggesterDescriptor == null) {
079            throw new SuggestionException(String.format("No suggester registered under the name '%s'.", suggesterName));
080        }
081        if (!suggesterDescriptor.isEnabled()) {
082            throw new SuggestionException(String.format("Suggester registered under the name '%s' is disabled.",
083                    suggesterName));
084        }
085        Suggester suggester = suggesterDescriptor.getSuggester();
086        if (suggester == null) {
087            String message = "Suggester with id '" + suggesterName
088                    + "' has a configuration that prevents instanciation" + " (no className in aggregate descriptor)";
089            throw new SuggestionException(message);
090        }
091        return suggester.suggest(input, context);
092    }
093
094    // Nuxeo Runtime Component API
095
096    @Override
097    public void activate(ComponentContext context) {
098        super.activate(context);
099        suggesters = new SuggesterRegistry();
100        suggesterGroups = new SuggesterGroupRegistry();
101    }
102
103    @Override
104    public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
105        if (contribution instanceof SuggesterDescriptor) {
106            SuggesterDescriptor suggesterDescriptor = (SuggesterDescriptor) contribution;
107            log.info(String.format("Registering suggester '%s'", suggesterDescriptor.getName()));
108            try {
109                suggesterDescriptor.setRuntimeContext(contributor.getRuntimeContext());
110            } catch (ComponentInitializationException e) {
111                throw new RuntimeException(e);
112            }
113            suggesters.addContribution(suggesterDescriptor);
114        } else if (contribution instanceof SuggesterGroupDescriptor) {
115            SuggesterGroupDescriptor suggesterGroupDescriptor = (SuggesterGroupDescriptor) contribution;
116            log.info(String.format("Registering suggester group '%s'", suggesterGroupDescriptor.getName()));
117            suggesterGroups.addContribution(suggesterGroupDescriptor);
118        } else {
119            log.error(String.format("Unknown contribution to the SuggestionService "
120                    + "styling service, extension point '%s': '%s", extensionPoint, contribution));
121        }
122    }
123
124    @Override
125    public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
126        if (contribution instanceof SuggesterDescriptor) {
127            SuggesterDescriptor suggesterDescriptor = (SuggesterDescriptor) contribution;
128            log.info(String.format("Unregistering suggester '%s'", suggesterDescriptor.getName()));
129            suggesters.removeContribution(suggesterDescriptor);
130        } else if (contribution instanceof SuggesterGroupDescriptor) {
131            SuggesterGroupDescriptor suggesterGroupDescriptor = (SuggesterGroupDescriptor) contribution;
132            log.info(String.format("Unregistering suggester group '%s'", suggesterGroupDescriptor.getName()));
133            suggesterGroups.removeContribution(suggesterGroupDescriptor);
134        } else {
135            log.error(String.format("Unknown contribution to the SuggestionService "
136                    + "styling service, extension point '%s': '%s", extensionPoint, contribution));
137        }
138    }
139
140    /**
141     * Gets the suggester groups registry. Only for test purpose.
142     *
143     * @return the suggester groups
144     */
145    public SuggesterGroupRegistry getSuggesterGroups() {
146        return suggesterGroups;
147    }
148
149}