/*
 * Version 2.1
 * CeCILL Copyright (c) 2006-2009, AtolCD, ADULLACT-projet
 * Initiated by AtolCD S.A. & ADULLACT-projet S.A.
 * Developped by AtolCD S.A. & ADULLACT-projet S.A.
 * 
 * contact@atolcd.com
 * contact@adullact-projet.coop
 * 
 * Ce logiciel est un programme informatique servant à faire circuler des 
 * documents au travers d'un circuit de validation, où chaque acteur vise 
 * le dossier, jusqu'à l'étape finale de signature.
 * 
 * Ce logiciel est régi par la licence CeCILL soumise au droit français et
 * respectant les principes de diffusion des logiciels libres. Vous pouvez
 * utiliser, modifier et/ou redistribuer ce programme sous les conditions
 * de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA 
 * sur le site "http://www.cecill.info".
 * 
 * En contrepartie de l'accessibilité au code source et des droits de copie,
 * de modification et de redistribution accordés par cette licence, il n'est
 * offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,
 * seule une responsabilité restreinte pèse sur l'auteur du programme,  le
 * titulaire des droits patrimoniaux et les concédants successifs.
 * 
 * A cet égard  l'attention de l'utilisateur est attirée sur les risques
 * associés au chargement,  à l'utilisation,  à la modification et/ou au
 * développement et à la reproduction du logiciel par l'utilisateur étant 
 * donné sa spécificité de logiciel libre, qui peut le rendre complexe à 
 * manipuler et qui le réserve donc à des développeurs et des professionnels
 * avertis possédant  des  connaissances  informatiques approfondies.  Les
 * utilisateurs sont donc invités à charger  et  tester  l'adéquation  du
 * logiciel à leurs besoins dans des conditions permettant d'assurer la
 * sécurité de leurs systèmes et ou de leurs données et, plus généralement, 
 * à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. 
 * 
 * Le fait que vous puissiez accéder à cet en-tête signifie que vous avez 
 * pris connaissance de la licence CeCILL, et que vous en avez accepté les
 * termes.
 */
package com.atolcd.parapheur.repo;

import java.util.ArrayList;
import java.util.List;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.tenant.Tenant;
import org.alfresco.repo.tenant.TenantAdminService;
import org.alfresco.repo.tenant.TenantService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.util.Assert;

/**
 *
 * @author svast
 * @author Vivien Barousse
 */
public class S2lowHeliosQuartzJob implements Job {

    /**
     * Used for logging
     */
    private static Log logger = LogFactory.getLog(S2lowHeliosQuartzJob.class);

    /**
     * iParapheur S2lowService
     */
    private S2lowService s2lowService;

    /**
     * Alfresco tenant service
     *
     * This service is used to convert global names to tenant-specific names.
     */
    private TenantService tenantService;

    /**
     * Alfresco tenants admin service.
     *
     * This service is used to retrieve the tenants list, in order to execute
     * the timer for each enabled tenant.
     */
    private TenantAdminService tenantAdminService;

    /**
     * The main method. Runs at intervals defined in module-context.xml.
     *
     * In order to run the timer once for each enabled tenant, we have to run
     * the timer multiple times, once as each tenant admin.
     *
     * @see org.quartz.Job#execute(org.quartz.JobExecutionContext)
     */
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        initialize(context);

        // Lists all users who should run the timer
        List<String> tenantsAdmins = new ArrayList<String>();

        // Global admin, for the default tenant
        tenantsAdmins.add("admin");

        for (Tenant tenant : tenantAdminService.getAllTenants()) {
            // We don't need to run the timer for disabled tenants.
            if (tenant.isEnabled()) {
                String tenantAdmin = tenantService.getDomainUser("admin", tenant.getTenantDomain());
                tenantsAdmins.add(tenantAdmin);
            }
        }

        // Now do the job, as many times as we need, once as each tenant admin
        for (String admin : tenantsAdmins) {
            logger.debug("Call getS2lowHeliosListePES_Retour as " + admin);
            AuthenticationUtil.runAs(new RunAsWork<Object>() {

                /**
                 * Do the actual work.
                 *
                 * This method is invoked as tenant admin.
                 *
                 * We don't need any return value, but implementing RunAsWork
                 * forces to have one. This methods always returns null.
                 * 
                 * @return null
                 */
                public Object doWork() {
                    try {
                        s2lowService.getS2lowHeliosListePES_Retour();
                    } catch (Exception e) {
                        logger.error("Can't retrieve PES_retour [" +
                                tenantService.getUserDomain(AuthenticationUtil.getRunAsUser()) +
                                "]." + e.getMessage());
                    }
                    return null;
                }

            }, admin);
        }
    }

    /**
     * Finds necessary services :
     * <ul>
     *     <li>s2lowService</li>
     *     <li>tenantService</li>
     *     <li>tenantAdminService</li>
     * </ul>
     * 
     * If one of the above services is missing, an IllegalArgumentException is thrown
     * 
     * @param context The JobExecutionContext, used for getting the necessary beans from the config file
     * @throws IllegalArgumentException if a required service is missing
     */
    private void initialize(JobExecutionContext context) {
        logger.debug("initialize");
        JobDataMap jobData = context.getJobDetail().getJobDataMap();

        // Retrieve services from context
        s2lowService = (S2lowService) jobData.get("s2lowService");
        tenantService = (TenantService) jobData.get("tenantService");
        tenantAdminService = (TenantAdminService) jobData.get("tenantAdminService");

        // Verify that all services are present
        Assert.notNull(s2lowService, "s2lowService is required");
        Assert.notNull(tenantService, "tenantService is required");
        Assert.notNull(tenantAdminService, "tenantAdminService is required");
    }

}
