TaskNotifyGru.java
/*
* Copyright (c) 2002-2021, City of Paris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice
* and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* License 1.0
*/
package fr.paris.lutece.plugins.workflow.modules.notifygru.service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import fr.paris.lutece.plugins.grubusiness.business.customer.Customer;
import fr.paris.lutece.plugins.grubusiness.business.demand.Demand;
import fr.paris.lutece.plugins.grubusiness.business.notification.BackofficeNotification;
import fr.paris.lutece.plugins.grubusiness.business.notification.BillingAccountBasedSMSNotification;
import fr.paris.lutece.plugins.grubusiness.business.notification.BroadcastNotification;
import fr.paris.lutece.plugins.grubusiness.business.notification.EmailAddress;
import fr.paris.lutece.plugins.grubusiness.business.notification.EmailNotification;
import fr.paris.lutece.plugins.grubusiness.business.notification.Event;
import fr.paris.lutece.plugins.grubusiness.business.notification.MyDashboardNotification;
import fr.paris.lutece.plugins.grubusiness.business.notification.Notification;
import fr.paris.lutece.plugins.grubusiness.business.notification.NotifyGruResponse;
import fr.paris.lutece.plugins.grubusiness.business.notification.SMSNotification;
import fr.paris.lutece.plugins.librarynotifygru.exception.NotifyGruException;
import fr.paris.lutece.plugins.librarynotifygru.services.NotificationService;
import fr.paris.lutece.plugins.workflow.modules.notifygru.business.EventHistory;
import fr.paris.lutece.plugins.workflow.modules.notifygru.business.NotifyGruHistory;
import fr.paris.lutece.plugins.workflow.modules.notifygru.business.TaskNotifyGruConfig;
import fr.paris.lutece.plugins.workflow.modules.notifygru.service.cache.NotifyGruCacheService;
import fr.paris.lutece.plugins.workflow.modules.notifygru.utils.constants.Constants;
import fr.paris.lutece.plugins.workflow.service.provider.MarkerProviderService;
import fr.paris.lutece.plugins.workflow.service.provider.ProviderManagerUtil;
import fr.paris.lutece.plugins.workflow.utils.WorkflowUtils;
import fr.paris.lutece.plugins.workflowcore.business.resource.ResourceHistory;
import fr.paris.lutece.plugins.workflowcore.service.config.ITaskConfigService;
import fr.paris.lutece.plugins.workflowcore.service.provider.AbstractProviderManager;
import fr.paris.lutece.plugins.workflowcore.service.provider.IMarkerProvider;
import fr.paris.lutece.plugins.workflowcore.service.provider.IProvider;
import fr.paris.lutece.plugins.workflowcore.service.provider.InfoMarker;
import fr.paris.lutece.plugins.workflowcore.service.resource.IResourceHistoryService;
import fr.paris.lutece.plugins.workflowcore.service.task.SimpleTask;
import fr.paris.lutece.portal.business.mailinglist.Recipient;
import fr.paris.lutece.portal.service.i18n.I18nService;
import fr.paris.lutece.portal.service.mailinglist.AdminMailingListService;
import fr.paris.lutece.portal.service.template.AppTemplateService;
import fr.paris.lutece.portal.service.util.AppException;
import fr.paris.lutece.portal.service.util.AppLogService;
import fr.paris.lutece.util.html.HtmlTemplate;
/**
* TaskNotifyGru.
*/
public class TaskNotifyGru extends SimpleTask
{
/** The _task notify gru config service. */
// SERVICES
@Inject
@Named( TaskNotifyGruConfigService.BEAN_SERVICE )
private ITaskConfigService _taskNotifyGruConfigService;
/** The _task notify gru history service. */
@Inject
@Named( NotifyGruHistoryService.BEAN_SERVICE )
private INotifyGruHistoryService _taskNotifyGruHistoryService;
/** Lib-NotifyGru sender service */
@Inject
@Named( Constants.BEAN_NOTIFICATION_SENDER )
private NotificationService _notifyGruSenderService;
@Inject
private IResourceHistoryService _resourceHistoryService;
/**
* {@inheritDoc}
*
* @param nIdResourceHistory
* @param request
* @param locale
*/
@Override
public void processTask( int nIdResourceHistory, HttpServletRequest request, Locale locale )
{
/* Task Config form cache, it can't be null due to getNotifyGruConfigFromCache algorithm */
TaskNotifyGruConfig config = NotifyGruCacheService.getInstance( ).getNotifyGruConfigFromCache( _taskNotifyGruConfigService, this.getId( ) );
String strProviderManagerId = ProviderManagerUtil.fetchProviderManagerId( config.getIdSpringProvider( ) );
String strProviderId = ProviderManagerUtil.fetchProviderId( config.getIdSpringProvider( ) );
AbstractProviderManager providerManager = ProviderManagerUtil.fetchProviderManager( strProviderManagerId );
if ( providerManager == null )
{
AppLogService.error( "Task id " + this.getId( ) + " : Unable to retrieve the provider manager '" + strProviderManagerId + "'" );
return;
}
ResourceHistory resourceHistory = _resourceHistoryService.findByPrimaryKey( nIdResourceHistory );
IProvider provider = providerManager.createProvider( strProviderId, resourceHistory, request );
if ( provider == null )
{
AppLogService.error( "Task id " + this.getId( ) + " : Unable to retrieve the provider '" + config.getIdSpringProvider( ) + "'" );
return;
}
NotifyGruHistory notifyGruHistory = new NotifyGruHistory( );
notifyGruHistory.setIdTask( this.getId( ) );
notifyGruHistory.setIdResourceHistory( nIdResourceHistory );
Map<String, Object> model = markersToModel( findMarkers( resourceHistory, provider, config.getMarkerProviders( ), request ) );
Notification notificationObject = buildNotification( config, provider );
EmailNotification emailNotification = null;
boolean bNotifEmpty = true;
if ( config.isActiveOngletEmail( ) && StringUtils.isNotBlank( provider.provideCustomerEmail( ) ) )
{
emailNotification = buildEmailNotification( config, provider, model );
notificationObject.setEmailNotification( emailNotification );
notifyGruHistory.setEmail( NotificationToHistory.populateEmail( config, emailNotification ) );
bNotifEmpty = false;
}
MyDashboardNotification myDashBoardNotification = null;
if ( config.isActiveOngletGuichet( ) && StringUtils.isNotBlank( provider.provideCustomerConnectionId( ) ) )
{
myDashBoardNotification = buildMyDashboardNotification( config, model );
notificationObject.setMyDashboardNotification( myDashBoardNotification );
notifyGruHistory.setGuichet( NotificationToHistory.populateGuichet( config, myDashBoardNotification ) );
bNotifEmpty = false;
}
SMSNotification smsNotification = null;
if ( config.isActiveOngletSMS( ) && StringUtils.isNotBlank( provider.provideCustomerMobilePhone( ) ) )
{
smsNotification = buildSMSNotification( config, provider, model );
notificationObject.setSmsNotification( smsNotification );
notifyGruHistory.setSMS( NotificationToHistory.populateSMS( config, smsNotification ) );
bNotifEmpty = false;
}
BackofficeNotification backofficeNotification = null;
if ( config.isActiveOngletAgent( ) )
{
backofficeNotification = buildBackofficeNotification( config, model );
notificationObject.setBackofficeNotification( backofficeNotification );
notifyGruHistory.setAgent( NotificationToHistory.populateAgent( config, backofficeNotification ) );
bNotifEmpty = false;
}
BroadcastNotification broadcastNotification = null;
if ( config.isActiveOngletBroadcast( ) )
{
broadcastNotification = buildBroadcastNotification( config, model );
if ( !broadcastNotification.getRecipient( ).isEmpty( ) )
{
notificationObject.addBroadcastEmail( broadcastNotification );
notifyGruHistory.setBroadCast( NotificationToHistory.populateBroadcast( config, broadcastNotification ) );
bNotifEmpty = false;
}
}
// crm status id
notifyGruHistory.setCrmStatusId( config.getCrmStatusId( ) );
if ( !bNotifEmpty )
{
try
{
NotifyGruResponse response = _notifyGruSenderService.send( notificationObject );
if ( response.getErrors( ) != null && !response.getErrors( ).isEmpty( ) )
{
EventHistory event = new EventHistory( );
event.setStatus( NotifyGruResponse.STATUS_ERROR );
event.setCode( response.getErrors( ).get( 0 ).getStatus( ) );
event.setMessage( response.getErrors( ).get( 0 ).getMessage( ) );
notifyGruHistory.setEvent( event );
}
else
if ( response.getWarnings( ) != null && !response.getWarnings( ).isEmpty( ) )
{
EventHistory event = new EventHistory( );
event.setStatus( NotifyGruResponse.STATUS_WARNING );
StringBuilder msg = new StringBuilder( );
for ( Event notificationEvent : response.getWarnings( ) )
{
msg.append( notificationEvent.getType( ) ).append( " " );
msg.append( notificationEvent.getStatus( ) ).append( " " );
msg.append( notificationEvent.getMessage( ) ).append( " | " );
}
event.setMessage( msg.toString( ) );
notifyGruHistory.setEvent( event );
}
_taskNotifyGruHistoryService.create( notifyGruHistory, WorkflowUtils.getPlugin( ) );
}
catch( AppException | NotifyGruException e )
{
AppLogService.error( "Unable to send the notification" );
EventHistory event = new EventHistory( );
event.setStatus( NotifyGruResponse.STATUS_ERROR );
event.setMessage( e.getLocalizedMessage( ) );
notifyGruHistory.setEvent( event );
_taskNotifyGruHistoryService.create( notifyGruHistory, WorkflowUtils.getPlugin( ) );
}
}
}
/**
* Builds an {@link Notification} object
*
* @param config
* the task configuration
* @param provider
* the provider
* @return the {@link Notification} object
*/
private static Notification buildNotification( TaskNotifyGruConfig config, IProvider provider )
{
Notification notification = new Notification( );
Demand demand = new Demand( );
demand.setStatusId( config.getDemandStatus( ) );
demand.setReference( provider.provideDemandReference( ) );
notification.setDate( System.currentTimeMillis( ) );
demand.setId( provider.provideDemandId( ) );
demand.setTypeId( provider.provideDemandTypeId( ) );
demand.setSubtypeId( provider.provideDemandSubtypeId( ) );
demand.setMaxSteps( config.getDemandMaxStepGuichet( ) );
demand.setCurrentStep( config.getDemandUserCurrentStepGuichet( ) );
Customer customer = new Customer( );
customer.setId( provider.provideCustomerId( ) );
customer.setConnectionId( provider.provideCustomerConnectionId( ) );
customer.setEmail( provider.provideCustomerEmail( ) );
demand.setCustomer( customer );
notification.setDemand( demand );
return notification;
}
/**
* Builds an {@link MyDashboardNotification} object
*
* @param config
* the task configuration
* @param model
* the model
* @return the {@link MyDashboardNotification} object
*/
private MyDashboardNotification buildMyDashboardNotification( TaskNotifyGruConfig config, Map<String, Object> model )
{
MyDashboardNotification userDashBoard = new MyDashboardNotification( );
userDashBoard.setStatusId( config.getCrmStatusId( ) );
userDashBoard.setStatusText( replaceMarkers( config.getStatustextGuichet( ), model ) );
userDashBoard.setSenderName( config.getSenderNameGuichet( ) );
userDashBoard.setSubject( replaceMarkers( config.getSubjectGuichet( ), model ) );
userDashBoard.setMessage( replaceMarkers( config.getMessageGuichet( ), model ) );
userDashBoard.setData( StringUtils.EMPTY );
return userDashBoard;
}
/**
* Builds an {@link BackofficeNotification} object
*
* @param config
* the task configuration
* @param model
* the model
* @return the {@link BackofficeNotification} object
*/
private BackofficeNotification buildBackofficeNotification( TaskNotifyGruConfig config, Map<String, Object> model )
{
BackofficeNotification userAgent = new BackofficeNotification( );
userAgent.setStatusText( replaceMarkers( config.getStatustextAgent( ), model ) );
userAgent.setMessage( replaceMarkers( config.getMessageAgent( ), model ) );
return userAgent;
}
/**
* Builds an {@link SMSNotification} object
*
* @param config
* the task configuration
* @param provider
* the provider
* @param model
* the model
* @return the {@link SMSNotification} object
*/
private <T extends SMSNotification> T buildSMSNotification( TaskNotifyGruConfig config, IProvider provider, Map<String, Object> model )
{
if ( !config.isBillingAccountBasedSmsNotification( ) )
{
SMSNotification userSMS = new BillingAccountBasedSMSNotification( );
userSMS.setMessage( replaceMarkers( config.getMessageSMS( ), model ) );
userSMS.setPhoneNumber( provider.provideCustomerMobilePhone( ) );
userSMS.setSenderName( provider.provideSmsSender( ) );
return (T) userSMS;
}
else
{
BillingAccountBasedSMSNotification billingAccountUserSMS = new BillingAccountBasedSMSNotification( );
billingAccountUserSMS.setMessage( replaceMarkers( config.getMessageSMS( ), model ) );
billingAccountUserSMS.setPhoneNumber( provider.provideCustomerMobilePhone( ) );
billingAccountUserSMS.setSenderName( provider.provideSmsSender( ) );
billingAccountUserSMS.setBillingAccount( config.getBillingAccountSMS( ) );
billingAccountUserSMS.setBillingGroup( config.getBillingGroupSMS( ) );
return (T) billingAccountUserSMS;
}
}
/**
* Builds an {@link EmailNotification} object
*
* @param config
* the task configuration
* @param provider
* the provider
* @param model
* the model
* @return the {@link EmailNotification} object
*/
private EmailNotification buildEmailNotification( TaskNotifyGruConfig config, IProvider provider, Map<String, Object> model )
{
EmailNotification userEmailNotification = new EmailNotification( );
userEmailNotification.setSenderName( config.getSenderNameEmail( ) );
userEmailNotification.setSenderEmail( config.getSenderEmail( ) );
userEmailNotification.setRecipient( provider.provideCustomerEmail( ) );
userEmailNotification.setSubject( replaceMarkers( config.getSubjectEmail( ), model ) );
userEmailNotification.setMessage( replaceMarkers( config.getMessageEmail( ), model ) );
userEmailNotification.setCc( replaceSemicolons( config.getRecipientsCcEmail( ) ) );
userEmailNotification.setBcc( replaceSemicolons( config.getRecipientsCciEmail( ) ) );
return userEmailNotification;
}
/**
* Replaces the semicolons in a list of recipients
*
* @param strMessage
* the message
* @return the message with semicolons replaced
*/
private static String replaceSemicolons( String strMessage )
{
if ( StringUtils.isEmpty( strMessage ) )
{
return strMessage;
}
return strMessage.replace( ';', ',' );
}
/**
* Builds an {@link BroadcastNotification} object
*
* @param config
* the task configuration
* @param model
* the model
* @return the {@link BroadcastNotification} object
*/
private BroadcastNotification buildBroadcastNotification( TaskNotifyGruConfig config, Map<String, Object> model )
{
BroadcastNotification broadcastNotification = new BroadcastNotification( );
List<String> listRecipientBroadcast = new ArrayList<>( );
if ( StringUtils.isNotEmpty( config.getEmailBroadcast( ) ) )
{
String strRecipientBroadcast = replaceMarkers( config.getEmailBroadcast( ), model );
if ( StringUtils.isNotEmpty( strRecipientBroadcast ) )
{
listRecipientBroadcast.addAll( Arrays.asList( strRecipientBroadcast.split( Constants.SEMICOLON ) ) );
}
}
if ( config.getIdMailingListBroadcast( ) > 0 )
{
Collection<Recipient> listRecipients = AdminMailingListService.getRecipients( config.getIdMailingListBroadcast( ) );
for ( Recipient recipient : listRecipients )
{
listRecipientBroadcast.add( recipient.getEmail( ) );
}
}
String strRecipientCcBroadcast = StringUtils.EMPTY;
if ( StringUtils.isNotEmpty( config.getRecipientsCcBroadcast( ) ) )
{
strRecipientCcBroadcast = replaceMarkers( config.getRecipientsCcBroadcast( ), model );
}
broadcastNotification.setSenderName( config.getSenderNameBroadcast( ) );
broadcastNotification.setSenderEmail( config.getSenderEmail( ) );
// we split a StringBuilder we can
broadcastNotification.setRecipient( EmailAddress.buildEmailAddresses( listRecipientBroadcast.toArray( new String [ ] { } ) ) );
broadcastNotification.setSubject( replaceMarkers( config.getSubjectBroadcast( ), model ) );
broadcastNotification.setMessage( replaceMarkers( config.getMessageBroadcast( ), model ) );
broadcastNotification.setCc( EmailAddress.buildEmailAddresses( strRecipientCcBroadcast.split( Constants.SEMICOLON ) ) );
broadcastNotification.setBcc( EmailAddress.buildEmailAddresses( config.getRecipientsCciBroadcast( ).split( Constants.SEMICOLON ) ) );
return broadcastNotification;
}
/**
* Finds the NotifyGru markers
*
* @param resourceHistory
* the resource history
* @param provider
* the provider
* @param listMarkerProviderIds
* the list of marker provider ids
* @param request
* the request
* @return the NotifyGru markers
*/
private Collection<InfoMarker> findMarkers( ResourceHistory resourceHistory, IProvider provider, List<String> listMarkerProviderIds,
HttpServletRequest request )
{
Collection<InfoMarker> collectionMarkers = provider.provideMarkerValues( );
for ( String strMarkerProviderId : listMarkerProviderIds )
{
IMarkerProvider markerProvider = MarkerProviderService.getInstance( ).find( strMarkerProviderId );
if ( markerProvider != null )
{
collectionMarkers.addAll( markerProvider.provideMarkerValues( resourceHistory, this, request ) );
}
}
return collectionMarkers;
}
/**
* Replaces the markers in the specified message
*
* @param strMessage
* the message
* @param model
* the model
* @return the message with markers replaced
*/
private static String replaceMarkers( String strMessage, Map<String, Object> model )
{
HtmlTemplate template = AppTemplateService.getTemplateFromStringFtl( strMessage, Locale.FRENCH, model );
return template.getHtml( );
}
/**
* Converts the specified collection of NotifyGru markers into a model
*
* @param collectionNotifyGruMarkers
* the collection to convert
* @return the model
*/
private Map<String, Object> markersToModel( Collection<InfoMarker> collectionNotifyGruMarkers )
{
Map<String, Object> model = new HashMap<>( );
for ( InfoMarker notifyGruMarker : collectionNotifyGruMarkers )
{
model.put( notifyGruMarker.getMarker( ), notifyGruMarker.getValue( ) );
}
return model;
}
/*
* (non-Javadoc)
*
* @see fr.paris.lutece.plugins.workflowcore.service.task.SimpleTask#doRemoveConfig()
*/
@Override
public void doRemoveConfig( )
{
_taskNotifyGruConfigService.remove( this.getId( ) );
_taskNotifyGruHistoryService.removeByTask( this.getId( ), WorkflowUtils.getPlugin( ) );
}
/**
* {@inheritDoc}
*
* @param nIdHistory
*/
@Override
public void doRemoveTaskInformation( int nIdHistory )
{
_taskNotifyGruHistoryService.removeByHistory( nIdHistory, this.getId( ), WorkflowUtils.getPlugin( ) );
}
/**
* {@inheritDoc}
*
* @param locale
* @return
*/
@Override
public String getTitle( Locale locale )
{
return I18nService.getLocalizedString( Constants.TITLE_NOTIFY, locale );
}
}