Package com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier

Source Code of com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.WorkflowNotifierManager

/*
*
* Copyright 2013 Entando S.r.l. (http://www.entando.com) All rights reserved.
*
* This file is part of Entando software.
* Entando is a free software;
* You can redistribute it and/or modify it
* under the terms of the GNU General Public License (GPL) as published by the Free Software Foundation; version 2.
*
* See the file License for the specific language governing permissions  
* and limitations under the License
*
*
*
* Copyright 2013 Entando S.r.l. (http://www.entando.com) All rights reserved.
*
*/
package com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

import com.agiletec.aps.system.ApsSystemUtils;
import com.agiletec.aps.system.SystemConstants;
import com.agiletec.aps.system.common.AbstractService;
import com.agiletec.aps.system.common.entity.model.attribute.ITextAttribute;
import com.agiletec.aps.system.exception.ApsSystemException;
import com.agiletec.aps.system.services.authorization.IApsAuthority;
import com.agiletec.aps.system.services.authorization.IAuthorizationManager;
import com.agiletec.aps.system.services.authorization.authorizator.IApsAuthorityManager;
import com.agiletec.aps.system.services.baseconfig.ConfigInterface;
import com.agiletec.aps.system.services.role.IRoleManager;
import com.agiletec.aps.system.services.role.Permission;
import com.agiletec.aps.system.services.role.Role;
import com.agiletec.aps.system.services.user.IAuthenticationProviderManager;
import com.agiletec.aps.system.services.user.IUserManager;
import com.agiletec.aps.util.DateConverter;
import com.agiletec.plugins.jacms.aps.system.services.content.IContentManager;
import com.agiletec.plugins.jacms.aps.system.services.content.model.Content;
import com.agiletec.plugins.jpcontentworkflow.aps.system.JpcontentworkflowSystemConstants;
import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model.ContentStatusChangedEventInfo;
import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.model.NotifierConfig;
import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.parse.WorkflowNotifierDOM;
import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.scheduler.MailSenderTask;
import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.scheduler.Scheduler;
import com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.scheduler.Task;
import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.IContentWorkflowManager;
import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Step;
import com.agiletec.plugins.jpcontentworkflow.aps.system.services.workflow.model.Workflow;
import com.agiletec.plugins.jpmail.aps.services.mail.IMailManager;

import org.entando.entando.aps.system.services.userprofile.IUserProfileManager;
import org.entando.entando.aps.system.services.userprofile.model.IUserProfile;

@Aspect
public class WorkflowNotifierManager extends AbstractService implements IWorkflowNotifierManager {
 
  @Override
  public void init() throws Exception {
    this.loadConfigs();
    this.openScheduler();
    ApsSystemUtils.getLogger().debug(this.getName() + ": inizializzato " +
        "servizio notificatore cambiamento stato contenuti");
  }
 
  @Override
  public void release() {
    this.closeScheduler();
  }
 
  @Override
  public void destroy() {
    this.release();
    super.destroy();
  }

  protected void loadConfigs() throws ApsSystemException {
    try {
      ConfigInterface configManager = this.getConfigManager();
      String xml = configManager.getConfigItem(JpcontentworkflowSystemConstants.WORKFLOW_NOTIFIER_CONFIG_ITEM);
      if (xml == null) {
        throw new ApsSystemException("Configuration item not present: " + JpcontentworkflowSystemConstants.WORKFLOW_NOTIFIER_CONFIG_ITEM);
      }
      WorkflowNotifierDOM configDOM = new WorkflowNotifierDOM();
      this.setNotifierConfig(configDOM.extractConfig(xml));
    } catch (Throwable t) {
      ApsSystemUtils.logThrowable(t, this, "loadConfigs");
      throw new ApsSystemException("Errore in fase di inizializzazione", t);
    }
  }

  @Before("execution(* com.agiletec.plugins.jacms.aps.system.services.content.IContentManager.saveContent(..)) && args(content,..)")
  public void listenContentSaving(Object content) {
    try {
      boolean notify = true;
      Content currentContent = (Content) content;
      String contentId = currentContent.getId();
      if (null != contentId) {
        Content previousContent = this.getContentManager().loadContent(contentId, false);
        if (previousContent.getStatus().equals(currentContent.getStatus())) {
          notify = false;
        }
      }
      if (notify) {
        this.saveContentStatusChanged(currentContent);
      }
    } catch (Throwable t) {
      ApsSystemUtils.logThrowable(t, this, "traceContent", "Error notifying content status change");
    }
  }

  @Override
  public NotifierConfig getNotifierConfig() {
    return _notifierConfig.clone();
  }
  protected NotifierConfig getWorkflowNotifierConfig() {
    return _notifierConfig;
  }
  protected void setNotifierConfig(NotifierConfig notifierConfig) {
    this._notifierConfig = notifierConfig;
  }

  @Override
  public void saveNotifierConfig(NotifierConfig notifierConfig) throws ApsSystemException {
    try {
      WorkflowNotifierDOM configDOM = new WorkflowNotifierDOM();
      String xml = configDOM.createConfigXml(notifierConfig);
      this.getConfigManager().updateConfigItem(JpcontentworkflowSystemConstants.WORKFLOW_NOTIFIER_CONFIG_ITEM, xml);
      this.setNotifierConfig(notifierConfig);
      this.closeScheduler();
      this.openScheduler();
    } catch (Throwable t) {
      ApsSystemUtils.logThrowable(t, this, "saveNotifierConfig");
      throw new ApsSystemException("Errore in fase di salvataggio configurazione notificatore", t);
    }
  }

  protected void saveContentStatusChanged(Content content) {
    if (this.getWorkflowNotifierConfig().isActive()) {
      try {
        ContentStatusChangedEventInfo statusChangedInfo = new ContentStatusChangedEventInfo();
        statusChangedInfo.setContentId(content.getId());
        statusChangedInfo.setContentTypeCode(content.getTypeCode());
        statusChangedInfo.setContentDescr(content.getDescr());
        statusChangedInfo.setMainGroup(content.getMainGroup());
        statusChangedInfo.setDate(new Date());
        statusChangedInfo.setStatus(content.getStatus());
        this.getNotifierDAO().saveContentEvent(statusChangedInfo);
      } catch (Throwable t) {
        ApsSystemUtils.logThrowable(t, this, "saveContentStatusChanged",
            "Error saving content status changed event" + content.getId());
      }
    }
  }

  /**
   * Apre lo scheduler istanziando il task relativo
   * alla spedizione degli sms con i rilevamenti meteo.
   */
  protected void openScheduler() {
    this.closeScheduler();
    NotifierConfig notifierConfig = this.getWorkflowNotifierConfig();
    if (notifierConfig.isActive()) {
      long milliSecondsDelay = notifierConfig.getHoursDelay() * 3600000l; // x minuti secondi millisecondi
      Date startTime = notifierConfig.getStartScheduler();

      startTime = this.calculateStartTime(startTime, milliSecondsDelay);
      Task task = new MailSenderTask(this);
      this._mailSenderScheduler = new Scheduler(task, startTime, milliSecondsDelay);
    }
  }

  private Date calculateStartTime(Date startTime, long delay) {
    Date current = new Date();
    long waitTime = current.getTime() - startTime.getTime();
    if (waitTime > 0) {
      startTime = new Date((current.getTime() + delay) - (waitTime % delay));
    }
    return startTime;
  }

  protected void closeScheduler() {
    if (this._mailSenderScheduler != null) this._mailSenderScheduler.cancel();
    this._mailSenderScheduler = null;
  }

  @Override
  public void sendMails() throws ApsSystemException {
    try {
      Map<String, List<ContentStatusChangedEventInfo>> statusChangedInfos = this.getNotifierDAO().getEventsToNotify();
      ApsSystemUtils.getLogger().trace("Found " + statusChangedInfos.size() + " events to notify");
      if (statusChangedInfos.size()>0) {
        Map<String, List<ContentStatusChangedEventInfo>> contentsForUsers = this.prepareContentsForUsers(statusChangedInfos);
        Iterator<String> iter = contentsForUsers.keySet().iterator();
        while (iter.hasNext()) {
          String username = iter.next();
          List<ContentStatusChangedEventInfo> contentInfos = contentsForUsers.get(username);
          this.sendMail(username, contentInfos);
        }
        List<ContentStatusChangedEventInfo> notifiedContents = new ArrayList<ContentStatusChangedEventInfo>();
        for (List<ContentStatusChangedEventInfo> contentsForType : statusChangedInfos.values()) {
          notifiedContents.addAll(contentsForType);
        }
        ApsSystemUtils.getLogger().trace("Notified " + notifiedContents.size() + " events");
        this.getNotifierDAO().signNotifiedEvents(notifiedContents);
      }
    } catch (Throwable t) {
      ApsSystemUtils.logThrowable(t, this, "sendMails");
      throw new ApsSystemException("Errore in fase di invio mail di notifica", t);
    }
  }

  protected void sendMail(String username, List<ContentStatusChangedEventInfo> contentInfos) {
    try {
      NotifierConfig notifierConfig = this.getWorkflowNotifierConfig();
      String mailAddress = this.getMailAddress(username);
      if (null == mailAddress) {
        return;
      }
      String[] mailAddresses = {mailAddress};
      Map<String, String> params = this.prepareParams(username);
      String subject = this.replaceParams(notifierConfig.getSubject(), params);
      String text = this.prepareMailText(params, contentInfos);
      String senderCode = notifierConfig.getSenderCode();
      String contentType = (notifierConfig.isHtml()) ? IMailManager.CONTENTTYPE_TEXT_HTML : IMailManager.CONTENTTYPE_TEXT_PLAIN;
      this.getMailManager().sendMail(text, subject, mailAddresses, null, null, senderCode, contentType);
    } catch(Throwable t) {
      ApsSystemUtils.logThrowable(t, this, "sendMail", "Error sending mail to user " + username);
    }
  }
 
  protected String getMailAddress(String username) throws Throwable {
    String email = null;
    IUserProfileManager profileManager = (IUserProfileManager) super.getBeanFactory().getBean(SystemConstants.USER_PROFILE_MANAGER);
    IUserProfile profile = profileManager.getProfile(username);
    if (null != profile) {
      ITextAttribute mailAttribute = (ITextAttribute) profile.getAttributeByRole(SystemConstants.USER_PROFILE_ATTRIBUTE_ROLE_MAIL);
      if (null != mailAttribute && mailAttribute.getText().trim().length() > 0) {
        email = mailAttribute.getText();
      }
    }
    return email;
  }
 
  protected Map<String, String> prepareParams(String username) {
    Map<String, String> params = new HashMap<String, String>();
    params.put("user", username);
    return params;
  }
 
  protected void addContentParams(Map<String, String> params, ContentStatusChangedEventInfo contentInfo) {
    params.put("type", contentInfo.getContentTypeCode());
    params.put("contentId", contentInfo.getContentId());
    params.put("descr", contentInfo.getContentDescr());
    params.put("group", contentInfo.getMainGroup());
    params.put("status", contentInfo.getStatus());
    params.put("data", DateConverter.getFormattedDate(contentInfo.getDate(), "dd MMMM yyyy"));
  }

  protected String prepareMailText(Map<String, String> params, List<ContentStatusChangedEventInfo> contentInfos) {
    NotifierConfig notifierConfig = this.getWorkflowNotifierConfig();
    String header = this.replaceParams(notifierConfig.getHeader(), params);
    String footer = this.replaceParams(notifierConfig.getFooter(), params);
    String body = notifierConfig.getTemplate();
    StringBuilder text = new StringBuilder(header);
    for (ContentStatusChangedEventInfo contentInfo : contentInfos) {
      this.addContentParams(params, contentInfo);
      text.append(this.replaceParams(body, params));
    }
    text.append(footer);
    return text.toString();
  }

  /**
   * @param defaultText Il testo di partenza, contenente le stringhe da rimpiazzare secondo la sintassi {chiaveStringa}.
   * @param params La mappa dei parametri da rimpiazzare (solo il nome, esluse le { })<br />
   * ATTENZIONE: le chiavi non devono contenere caratteri speciali per le regular expressions.<br />
   * In tal caso vanno utilizzati i caratteri di escape.
   * @return Il testo con tutte le occorrenze delle parole chiave sostituite.
   */
  protected String replaceParams(String defaultText, Map<String, String> params) {
    String body = defaultText;
    Iterator<Entry<String, String>> it = params.entrySet().iterator();
    while (it.hasNext()) {
      Entry<String, String> pairs = it.next();
      String field = "\\{" + pairs.getKey() + "\\}";
      body = body.replaceAll(field, pairs.getValue());
    }
    return body;
  }
 
  protected Map<String, List<ContentStatusChangedEventInfo>> prepareContentsForUsers (
      Map<String, List<ContentStatusChangedEventInfo>> statusChangedInfos) throws ApsSystemException {
    Map<String, List<ContentStatusChangedEventInfo>> contentsForUsers = new HashMap<String, List<ContentStatusChangedEventInfo>>();
    List<String> editors = new ArrayList<String>();
    List<String> supervisors = new ArrayList<String>();
    this.findContentOperators(editors, supervisors);
    if (null != statusChangedInfos) {
      Iterator<String> iter = statusChangedInfos.keySet().iterator();
      while (iter.hasNext()) {
        String typeCode = iter.next();
        List<ContentStatusChangedEventInfo> infosForContentType = statusChangedInfos.get(typeCode);
        this.prepareUsersForContentType(contentsForUsers, typeCode, infosForContentType, editors, supervisors);
      }
    }
    return contentsForUsers;
  }
 
  protected void findContentOperators(List<String> editors, List<String> supervisors) throws ApsSystemException {
    List<Role> rolesWithSupervisor = ((IRoleManager) this.getRoleManager()).getRolesWithPermission(Permission.SUPERVISOR);
    List<String> roleNamesWithSupervisor = this.getRolesNames(rolesWithSupervisor);
    List<Role> rolesWithEditors = ((IRoleManager) this.getRoleManager()).getRolesWithPermission("editContents");
    List<String> roleNamesWithEditor = this.getRolesNames(rolesWithEditors);
    IUserProfileManager profileManager = (IUserProfileManager) super.getBeanFactory().getBean(SystemConstants.USER_PROFILE_MANAGER);
    List<String> usernames = profileManager.searchId(null);
    for (int i = 0; i < usernames.size(); i++) {
      String extractedUsername = usernames.get(i);
      List<IApsAuthority> userRoles = this.getRoleManager().getAuthorizationsByUser(extractedUsername);
      if (null == userRoles) {
        continue;
      }
      for (int j = 0; j < userRoles.size(); j++) {
        IApsAuthority role = userRoles.get(j);
        if (null == role) {
          continue;
        }
        if (roleNamesWithSupervisor.contains(role.getAuthority())) {
          supervisors.add(extractedUsername);
        }
        if (roleNamesWithEditor.contains(role.getAuthority())) {
          editors.add(extractedUsername);
        }
      }
    }
  }
 
  private List<String> getRolesNames(List<Role> roles) {
    List<String> names = new ArrayList<String>();
    if (null == roles) {
      return names;
    }
    for (int i = 0; i < roles.size(); i++) {
      IApsAuthority role = roles.get(i);
      if (null == role) {
        continue;
      }
      names.add(role.getAuthority());
    }
    return names;
  }
 
  protected void prepareUsersForContentType(Map<String, List<ContentStatusChangedEventInfo>> contentsForUsers,
      String typeCode, List<ContentStatusChangedEventInfo> infosForContentType, List<String> editors, List<String> supervisors) throws ApsSystemException {
    Workflow workflow = this.getWorkflowManager().getWorkflow(typeCode);
    String contentTypeRole = workflow.getRole();
    if (contentTypeRole == null || contentTypeRole.length() == 0) {
      editors = this.filterUsersForRole(contentTypeRole, editors);
      supervisors = this.filterUsersForRole(contentTypeRole, supervisors);
    }
    List<String> usersForStep = null;
    String previousStepRole = null;
    for (ContentStatusChangedEventInfo contentInfo : infosForContentType) {
      String currentStep = contentInfo.getStatus();
      Step step = workflow.getStep(currentStep);
      String currentStepRole = step!=null ? step.getRole() : null;
      boolean needsSupervisor = Content.STATUS_READY.equals(currentStep);
      if (previousStepRole==null || !previousStepRole.equals(currentStepRole)) {
        previousStepRole = currentStepRole;
        if (needsSupervisor) {
          usersForStep = supervisors;
        } else {
          usersForStep = this.filterUsersForRole(currentStepRole, editors);
        }
      }
      String mainGroup = contentInfo.getMainGroup();
      List<String> allowedUsers = this.filterUsersForGroup(mainGroup, usersForStep);
      this.addContentForUsers(contentInfo, allowedUsers, contentsForUsers);
    }
  }

  protected List<String> filterUsersForRole(String roleName, List<String> users) throws ApsSystemException {
    List<String> usersForContentType = null;
    try {
      if (users.isEmpty() || roleName == null || roleName.length()==0) {
        usersForContentType = users;
      } else {
        usersForContentType = new ArrayList<String>();
        IApsAuthorityManager roleManager = this.getRoleManager();
        IApsAuthority authority = roleManager.getAuthority(roleName);
        List<String> usernamesWithAuth = this.getRoleManager().getUsernamesByAuthority(authority);
        for (int i = 0; i < users.size(); i++) {
          String username = users.get(i);
          if (null == username) {
            continue;
          }
          for (int j = 0; j < usernamesWithAuth.size(); j++) {
            String userWithAuth = usernamesWithAuth.get(j);
            if (null == userWithAuth) {
              continue;
            }
            if (username.equals(userWithAuth)) {
              usersForContentType.add(username);
            }
          }
        }
      }
    } catch (Throwable t) {
      ApsSystemUtils.logThrowable(t, this, "filterUsersForRole");
      throw new ApsSystemException("Errore nel filtro degli utenti in base al ruolo", t);
    }
    return usersForContentType;
  }
 
  protected List<String> filterUsersForGroup(String groupName, List<String> usernames) throws ApsSystemException {
    List<String> usersForContentType = null;
    if (usernames.isEmpty() || groupName == null || groupName.length()==0) {
      usersForContentType = usernames;
    } else {
      usersForContentType = new ArrayList<String>();
      IApsAuthorityManager groupManager = (IApsAuthorityManager) super.getBeanFactory().getBean(SystemConstants.GROUP_MANAGER);
      IApsAuthority authority = groupManager.getAuthority(groupName);
      List<String> usersWithAuth = groupManager.getUsernamesByAuthority(authority);
      for (int i = 0; i < usernames.size(); i++) {
        String username = usernames.get(i);
        if (null == username) {
          continue;
        }
        for (int j = 0; j < usersWithAuth.size(); j++) {
          String userWithAuth = usersWithAuth.get(j);
          if (null == userWithAuth) {
            continue;
          }
          if (username.equals(userWithAuth)) {
            usersForContentType.add(username);
          }
        }
      }
    }
    return usersForContentType;
  }
 
  protected void addContentForUsers(ContentStatusChangedEventInfo contentInfo, List<String> allowedUsers,
      Map<String, List<ContentStatusChangedEventInfo>> contentsForUsers) {
    if (null == contentsForUsers || contentsForUsers.isEmpty()) {
      return;
    }
    for (int i = 0; i < allowedUsers.size(); i++) {
      String username = allowedUsers.get(i);
      List<ContentStatusChangedEventInfo> infos = contentsForUsers.get(username);
      if (infos == null) {
        infos = new ArrayList<ContentStatusChangedEventInfo>();
        contentsForUsers.put(username, infos);
      }
      infos.add(contentInfo);
    }
  }

  protected ConfigInterface getConfigManager() {
    return _configManager;
  }
  public void setConfigManager(ConfigInterface configManager) {
    this._configManager = configManager;
  }
 
  protected IUserManager getUserManager() {
    return _userManager;
  }
  public void setUserManager(IUserManager userManager) {
    this._userManager = userManager;
  }
 
  protected IAuthenticationProviderManager getAuthProvider() {
    return _authProvider;
  }
  public void setAuthProvider(IAuthenticationProviderManager authProvider) {
    this._authProvider = authProvider;
  }
 
  protected IAuthorizationManager getAuthorizationManager() {
    return _authorizationManager;
  }
  public void setAuthorizationManager(IAuthorizationManager authorizationManager) {
    this._authorizationManager = authorizationManager;
  }
 
  protected IApsAuthorityManager getRoleManager() {
    return _roleManager;
  }
  public void setRoleManager(IApsAuthorityManager roleManager) {
    this._roleManager = roleManager;
  }
 
  protected IContentWorkflowManager getWorkflowManager() {
    return _workflowManager;
  }
  public void setWorkflowManager(IContentWorkflowManager workflowManager) {
    this._workflowManager = workflowManager;
  }
 
  protected IMailManager getMailManager() {
    return _mailManager;
  }
  public void setMailManager(IMailManager mailManager) {
    this._mailManager = mailManager;
  }
 
  protected IContentManager getContentManager() {
    return _contentManager;
  }
  public void setContentManager(IContentManager contentManager) {
    this._contentManager = contentManager;
  }
 
  protected IWorkflowNotifierDAO getNotifierDAO() {
    return _notifierDAO;
  }
  public void setNotifierDAO(IWorkflowNotifierDAO notifierDAO) {
    this._notifierDAO = notifierDAO;
  }
 
  private NotifierConfig _notifierConfig;
  protected Scheduler _mailSenderScheduler;

  private ConfigInterface _configManager;
  private IUserManager _userManager;
  private IAuthenticationProviderManager _authProvider;
  private IAuthorizationManager _authorizationManager;
  private IApsAuthorityManager _roleManager;
  private IContentWorkflowManager _workflowManager;
  private IMailManager _mailManager;
  private IContentManager _contentManager;
  private IWorkflowNotifierDAO _notifierDAO;

}
TOP

Related Classes of com.agiletec.plugins.jpcontentworkflow.aps.system.services.notifier.WorkflowNotifierManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.