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