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.repository.Content;
032import org.ametys.cms.repository.ContentQueryHelper;
033import org.ametys.cms.repository.ContentTypeExpression;
034import org.ametys.plugins.repository.AmetysObjectIterable;
035import org.ametys.plugins.repository.AmetysObjectResolver;
036import org.ametys.plugins.repository.UnknownAmetysObjectException;
037import org.ametys.plugins.repository.query.expression.Expression;
038import org.ametys.plugins.repository.query.expression.Expression.Operator;
039import org.ametys.runtime.i18n.I18nizableText;
040import org.ametys.runtime.model.Enumerator;
041import org.ametys.runtime.plugin.component.AbstractLogEnabled;
042
043/**
044 * Enumerator of the contents matching a configured query
045 */
046public class ContentQueryEnumerator extends AbstractLogEnabled implements Enumerator<String>, Configurable, Serviceable, Component
047{
048    /** The list of content types to fill enum with */
049    protected List<String> _contentTypes;
050    /** The AmetysObjectResolver instance */
051    protected AmetysObjectResolver _ametysObjectResolver;
052
053    public void service(ServiceManager manager) throws ServiceException
054    {
055        _ametysObjectResolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
056    }
057
058    public void configure(Configuration configuration) throws ConfigurationException
059    {
060        _contentTypes = _configureContentTypes(configuration.getChild("content-types", true));
061    }
062
063    public I18nizableText getEntry(String value) throws Exception
064    {
065        try
066        {
067            Content content = _ametysObjectResolver.resolveById(value);
068            return new I18nizableText(content.getTitle());
069        }
070        catch (UnknownAmetysObjectException e)
071        {
072            // value does not exists anymore?
073            getLogger().debug("The content of id '{}' does not exists anymore", value, e);
074            return null;
075        }
076    }
077
078    public Map<String, I18nizableText> getTypedEntries() throws Exception
079    {
080        Expression expr = new ContentTypeExpression(Operator.EQ, _contentTypes.toArray(new String[0]));
081        
082        AmetysObjectIterable<Content> contents = _ametysObjectResolver.query(ContentQueryHelper.getContentXPathQuery(expr));
083        return contents.stream().collect(Collectors.toMap(Content::getId, c -> new I18nizableText(c.getTitle())));
084    }
085    
086    /**
087     * Configure the content type ids
088     * @param configuration The content types configuration
089     * @return The set of content type ids
090     * @throws ConfigurationException If an error occurs
091     */
092    protected List<String> _configureContentTypes(Configuration configuration) throws ConfigurationException
093    {
094        List<String> cTypes = new ArrayList<>();
095        for (Configuration cType : configuration.getChildren("type"))
096        {
097            cTypes.add(cType.getAttribute("id"));
098        }
099
100        if (cTypes.size() == 0)
101        {
102            throw new ConfigurationException("The 'content-types' element is mandatory", configuration);
103        }
104        
105        return cTypes;
106    }
107}