001/*
002 *  Copyright 2024 Anyware Services
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 */
016package org.ametys.cms.content;
017
018import java.util.ArrayList;
019import java.util.List;
020import java.util.Map;
021import java.util.stream.Collectors;
022
023import org.apache.avalon.framework.component.Component;
024import org.apache.avalon.framework.configuration.Configurable;
025import org.apache.avalon.framework.configuration.Configuration;
026import org.apache.avalon.framework.configuration.ConfigurationException;
027import org.apache.avalon.framework.service.ServiceException;
028import org.apache.avalon.framework.service.ServiceManager;
029import org.apache.avalon.framework.service.Serviceable;
030
031import org.ametys.cms.content.indexing.solr.SolrFieldNames;
032import org.ametys.cms.repository.Content;
033import org.ametys.cms.search.query.ContentTypeQuery;
034import org.ametys.cms.search.query.DocumentTypeQuery;
035import org.ametys.cms.search.solr.SearcherFactory;
036import org.ametys.cms.search.solr.SearcherFactory.Searcher;
037import org.ametys.plugins.repository.AmetysObjectIterable;
038import org.ametys.plugins.repository.AmetysObjectResolver;
039import org.ametys.plugins.repository.UnknownAmetysObjectException;
040import org.ametys.runtime.i18n.I18nizableText;
041import org.ametys.runtime.model.Enumerator;
042import org.ametys.runtime.plugin.component.AbstractLogEnabled;
043
044/**
045 * Enumerator of the contents matching a configured query
046 */
047public class ContentQueryEnumerator extends AbstractLogEnabled implements Enumerator<String>, Configurable, Serviceable, Component
048{
049    /** The list of content types to fill enum with */
050    protected List<String> _contentTypes;
051    /** The AmetysObjectResolver instance */
052    protected AmetysObjectResolver _ametysObjectResolver;
053    /** The searcher factory */
054    protected SearcherFactory _searcherFactory;
055
056    public void service(ServiceManager manager) throws ServiceException
057    {
058        _ametysObjectResolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
059        _searcherFactory = (SearcherFactory) manager.lookup(SearcherFactory.ROLE);
060    }
061
062    public void configure(Configuration configuration) throws ConfigurationException
063    {
064        _contentTypes = _configureContentTypes(configuration.getChild("content-types", true));
065    }
066
067    public I18nizableText getEntry(String value) throws Exception
068    {
069        try
070        {
071            Content content = _ametysObjectResolver.resolveById(value);
072            return new I18nizableText(content.getTitle());
073        }
074        catch (UnknownAmetysObjectException e)
075        {
076            // value does not exists anymore?
077            getLogger().debug("The content of id '{}' does not exists anymore", value, e);
078            return null;
079        }
080    }
081
082    public Map<String, I18nizableText> getEntries() throws Exception
083    {
084        ContentTypeQuery cTypeQuery = new ContentTypeQuery(_contentTypes.toArray(new String[_contentTypes.size()]));
085        
086        Searcher searcher = _searcherFactory.create().withQuery(cTypeQuery)
087                .addFilterQuery(new DocumentTypeQuery(SolrFieldNames.TYPE_CONTENT))
088                .setCheckRights(true);
089
090        AmetysObjectIterable<Content> contents = searcher.search();
091        return contents.stream().collect(Collectors.toMap(Content::getId, c -> new I18nizableText(c.getTitle())));
092    }
093    
094    /**
095     * Configure the content type ids
096     * @param configuration The content types configuration
097     * @return The set of content type ids
098     * @throws ConfigurationException If an error occurs
099     */
100    protected List<String> _configureContentTypes(Configuration configuration) throws ConfigurationException
101    {
102        List<String> cTypes = new ArrayList<>();
103        for (Configuration cType : configuration.getChildren("type"))
104        {
105            cTypes.add(cType.getAttribute("id"));
106        }
107
108        if (cTypes.size() == 0)
109        {
110            throw new ConfigurationException("The 'content-types' element is mandatory", configuration);
111        }
112        
113        return cTypes;
114    }
115}