001/*
002 *  Copyright 2022 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.odf.schedulable;
017
018import java.io.IOException;
019import java.util.List;
020import java.util.Objects;
021import java.util.stream.Collectors;
022
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.avalon.framework.service.ServiceManager;
025import org.apache.commons.lang3.StringUtils;
026import org.apache.commons.lang3.exception.ExceptionUtils;
027import org.quartz.JobDataMap;
028import org.quartz.JobExecutionContext;
029
030import org.ametys.cms.contenttype.ContentType;
031import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
032import org.ametys.cms.schedule.AbstractSendingMailSchedulable;
033import org.ametys.core.schedule.progression.ContainerProgressionTracker;
034import org.ametys.core.ui.mail.StandardMailBodyHelper;
035import org.ametys.odf.init.OdfRefTableDataExtensionPoint;
036import org.ametys.odf.init.OdfRefTableDataHelper;
037import org.ametys.odf.init.OdfRefTableDataHelper.OdfRefTableDataResult;
038import org.ametys.plugins.contentio.csv.SynchronizeModeEnumerator.ImportMode;
039import org.ametys.plugins.core.schedule.Scheduler;
040import org.ametys.runtime.i18n.I18nizableText;
041
042/**
043 * Import reference table data described by {@link OdfRefTableDataExtensionPoint}.
044 */
045public class OdfRefTableDataSynchronizationSchedulable extends AbstractSendingMailSchedulable
046{
047    private static final String __CONTEXT_KEY_SYNC_REPORT = OdfRefTableDataSynchronizationSchedulable.class.getName() + "$syncReport";
048    private static final String __IMPORT_MODE = "importMode";
049    
050    private OdfRefTableDataHelper _odfRefTableDataHelper;
051    private ContentTypeExtensionPoint _contentTypeEP;
052    
053    @Override
054    public void service(ServiceManager manager) throws ServiceException
055    {
056        super.service(manager);
057        _odfRefTableDataHelper = (OdfRefTableDataHelper) manager.lookup(OdfRefTableDataHelper.ROLE);
058        _contentTypeEP = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE);
059    }
060    
061    @Override
062    protected void _doExecute(JobExecutionContext context, ContainerProgressionTracker progressionTracker) throws Exception
063    {
064        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
065        ImportMode importMode = ImportMode.valueOf((String) jobDataMap.get(Scheduler.PARAM_VALUES_PREFIX + __IMPORT_MODE));
066        
067        OdfRefTableDataResult result = _odfRefTableDataHelper.processRefTableData(importMode);
068        context.put(__CONTEXT_KEY_SYNC_REPORT, result);
069    }
070
071    @Override
072    protected boolean _isMailBodyInHTML(JobExecutionContext context) throws Exception
073    {
074        return true;
075    }
076
077    @Override
078    protected I18nizableText _getSuccessMailSubject(JobExecutionContext context) throws Exception
079    {
080        String subjectKey = "PLUGINS_ODF_TABLEREF_SYNC_MAIL_SUCCESS_SUBJECT";
081        OdfRefTableDataResult result = (OdfRefTableDataResult) context.get(__CONTEXT_KEY_SYNC_REPORT);
082        if (!result.getPartial().isEmpty() || !result.getFail().isEmpty())
083        {
084            subjectKey += "_WITH_ERRORS";
085        }
086        return new I18nizableText("plugin.odf", subjectKey);
087    }
088
089    @Override
090    protected String _getSuccessMailBody(JobExecutionContext context, String language) throws Exception
091    {
092        try
093        {
094            OdfRefTableDataResult result = (OdfRefTableDataResult) context.get(__CONTEXT_KEY_SYNC_REPORT);
095            
096            StringBuilder sb = new StringBuilder();
097            
098            // Duration
099            sb.append(_i18nUtils.translate(new I18nizableText("plugin.odf", "PLUGINS_ODF_TABLEREF_SYNC_MAIL_SUCCESS_BODY_RESUME_DURATION", List.of(result.duration())), language));
100            
101            // Imported count
102            sb.append(_i18nUtils.translate(new I18nizableText("plugin.odf", "PLUGINS_ODF_TABLEREF_SYNC_MAIL_SUCCESS_BODY_RESUME_COUNT", List.of(result.getImported().toString())), language));
103            
104            // Success
105            if (!result.getSuccess().isEmpty())
106            {
107                sb.append(_i18nUtils.translate(new I18nizableText("plugin.odf", "PLUGINS_ODF_TABLEREF_SYNC_MAIL_SUCCESS_BODY_RESUME_SUCCESS", List.of(String.valueOf(result.getSuccess().size()))), language));
108            }
109            
110            // Partial
111            if (!result.getPartial().isEmpty())
112            {
113                List<String> partialCTypes = result.getPartial();
114                List<String> partialCTypeLabels = partialCTypes.stream()
115                    .map(id -> _contentTypeEP.getExtension(id))
116                    .filter(Objects::nonNull)
117                    .map(ContentType::getLabel)
118                    .map(label -> _i18nUtils.translate(label, language))
119                    .collect(Collectors.toList());
120                
121                sb.append(_i18nUtils.translate(new I18nizableText("plugin.odf", "PLUGINS_ODF_TABLEREF_SYNC_MAIL_SUCCESS_BODY_RESUME_PARTIAL", List.of(String.valueOf(partialCTypes.size()), StringUtils.join(partialCTypeLabels, ", "))), language));
122            }
123            
124            // Fail
125            if (!result.getFail().isEmpty())
126            {
127                List<String> failCTypes = result.getFail();
128                List<String> failCTypesLabels = failCTypes.stream()
129                    .map(id -> _contentTypeEP.getExtension(id))
130                    .filter(Objects::nonNull)
131                    .map(ContentType::getLabel)
132                    .map(label -> _i18nUtils.translate(label, language))
133                    .collect(Collectors.toList());
134                
135                sb.append(_i18nUtils.translate(new I18nizableText("plugin.odf", "PLUGINS_ODF_TABLEREF_SYNC_MAIL_SUCCESS_BODY_RESUME_FAIL", List.of(String.valueOf(failCTypes.size()), StringUtils.join(failCTypesLabels, ", "))), language));
136            }
137            
138            String details = sb.toString();
139            
140            return StandardMailBodyHelper.newHTMLBody()
141                    .withTitle(new I18nizableText("plugin.odf", "PLUGINS_ODF_TABLEREF_SYNC_MAIL_SUCCESS_SUBJECT"))
142                    .addMessage(new I18nizableText("plugin.odf", "PLUGINS_ODF_TABLEREF_SYNC_MAIL_SUCCESS_BODY_RESUME"))
143                    .addMessage(new I18nizableText("plugin.odf", "PLUGINS_ODF_TABLEREF_SYNC_MAIL_SUCCESS_BODY_RESUME_ASK_DETAILS"))
144                    .withDetails(new I18nizableText("plugin.odf", "PLUGINS_ODF_TABLEREF_SYNC_MAIL_SUCCESS_BODY_REPORT"), details, false)
145                    .withLanguage(language)
146                    .build();
147        }
148        catch (IOException e)
149        {
150            getLogger().error("Failed to build HTML email body for reference table synchronization report", e);
151            return null;
152        }
153    }
154
155    @Override
156    protected I18nizableText _getErrorMailSubject(JobExecutionContext context) throws Exception
157    {
158        return new I18nizableText("plugin.odf", "PLUGINS_ODF_TABLEREF_SYNC_MAIL_ERROR_SUBJECT");
159    }
160
161    @Override
162    protected String _getErrorMailBody(JobExecutionContext context, String language, Throwable throwable) throws Exception
163    {
164        String error = StringUtils.join(ExceptionUtils.getStackFrames(throwable), "<br/>");
165        
166        return StandardMailBodyHelper.newHTMLBody()
167                .withTitle(new I18nizableText("plugin.odf", "PLUGINS_ODF_TABLEREF_SYNC_MAIL_ERROR_SUBJECT"))
168                .addMessage(new I18nizableText("plugin.odf", "PLUGINS_ODF_TABLEREF_SYNC_MAIL_ERROR_BODY"))
169                .withDetails(null, error, false)
170                .withLanguage(language)
171                .build();
172    }
173}