001/*
002 *  Copyright 2025 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.indexing.solr;
017
018import java.util.Map;
019import java.util.concurrent.Callable;
020
021import org.apache.avalon.framework.service.ServiceManager;
022import org.apache.cocoon.environment.Context;
023import org.apache.cocoon.environment.ObjectModelHelper;
024import org.apache.cocoon.environment.Request;
025import org.apache.cocoon.util.log.SLF4JLoggerAdapter;
026import org.apache.solr.client.solrj.SolrClient;
027import org.slf4j.Logger;
028
029import org.ametys.cms.indexing.IndexingException;
030import org.ametys.core.engine.BackgroundEngineHelper;
031import org.ametys.core.engine.BackgroundEnvironment;
032import org.ametys.plugins.repository.AmetysObject;
033import org.ametys.plugins.repository.AmetysObjectResolver;
034import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector;
035
036/**
037 * Abstract implementation of {@link Callable} for {@link AmetysObject}
038 * @param <T> {@link AmetysObject} type indexing by the callable
039 */
040public abstract class AbstractIndexerCallable<T extends AmetysObject> implements Callable<Void>
041{
042    /** The ametys object identifier */
043    protected String _ametysObjectId;
044    /** The workspace name */
045    protected String _workspaceName;
046    /** The Solr client */
047    protected SolrClient _solrClient;
048    /** The logger */
049    protected Logger _logger;
050    
051    /* Components */
052    private ServiceManager _manager;
053    private Context _cocoonContext;
054    private AmetysObjectResolver _resolver;
055    
056    /**
057     * Constructor.
058     * @param ametysObject The Ametys object, we only keep the identifier
059     * @param workspaceName The workspace name
060     * @param solrClient The Solr client
061     * @param manager The service manager
062     * @param cocoonContext The Cocoon context
063     * @param resolver The Ametys object resolver
064     * @param logger The logger
065     */
066    public AbstractIndexerCallable(T ametysObject, String workspaceName, SolrClient solrClient, ServiceManager manager, Context cocoonContext, AmetysObjectResolver resolver, Logger logger)
067    {
068        this._ametysObjectId = ametysObject.getId();
069        this._workspaceName = workspaceName;
070        this._solrClient = solrClient;
071        this._manager = manager;
072        this._cocoonContext = cocoonContext;
073        this._resolver = resolver;
074        this._logger = logger;
075    }
076    
077    public Void call() throws Exception
078    {
079        Map<String, Object> environmentInformation = BackgroundEngineHelper.createAndEnterEngineEnvironment(_manager, _cocoonContext, new SLF4JLoggerAdapter(_logger));
080        BackgroundEnvironment bgEnv = (BackgroundEnvironment) environmentInformation.get("environment");
081        Request request = ObjectModelHelper.getRequest(bgEnv.getObjectModel());
082        String currentWsp = RequestAttributeWorkspaceSelector.getForcedWorkspace(request);
083
084        try
085        {
086            RequestAttributeWorkspaceSelector.setForcedWorkspace(request, _workspaceName);
087            
088            T ametysObject = _resolver.resolveById(_ametysObjectId);
089            if (_logger.isInfoEnabled())
090            {
091                String message = String.format("Indexing %s: %s in workspace '%s'", getObjectLabel(), ametysObject, _workspaceName);
092                _logger.info(message);
093            }
094            process(ametysObject);
095        }
096        catch (Exception e)
097        {
098            String message = String.format("Error indexing %s '%s' in the solr server on workspace '%s'", getObjectLabel(), _ametysObjectId, _workspaceName);
099            throw new IndexingException(message, e);
100        }
101        finally
102        {
103            RequestAttributeWorkspaceSelector.setForcedWorkspace(request, currentWsp);
104            BackgroundEngineHelper.leaveEngineEnvironment(environmentInformation);
105        }
106        
107        return null;
108    }
109    
110    /**
111     * Process the {@link AmetysObject} in the callable.
112     * @param ametysObject The Ametys object
113     * @throws Exception if an error occurs
114     */
115    protected abstract void process(T ametysObject) throws Exception;
116    
117    /**
118     * Get the object label for logs.
119     * @return the object label
120     */
121    protected abstract String getObjectLabel();
122}