Package pl.net.bluesoft.rnd.pt.ext.deadline

Source Code of pl.net.bluesoft.rnd.pt.ext.deadline.DeadlineEngine

package pl.net.bluesoft.rnd.pt.ext.deadline;

import org.apache.commons.lang3.time.DateUtils;
import org.aperteworkflow.util.liferay.LiferayBridge;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Subqueries;
import org.quartz.*;
import pl.net.bluesoft.rnd.processtool.ProcessToolContext;
import pl.net.bluesoft.rnd.processtool.ProcessToolContextCallback;
import pl.net.bluesoft.rnd.processtool.bpm.ProcessToolBpmSession;
import pl.net.bluesoft.rnd.processtool.bpm.exception.ProcessToolException;
import pl.net.bluesoft.rnd.processtool.model.BpmTask;
import pl.net.bluesoft.rnd.processtool.model.ProcessInstance;
import pl.net.bluesoft.rnd.processtool.model.UserData;
import pl.net.bluesoft.rnd.processtool.model.config.ProcessStateConfiguration;
import pl.net.bluesoft.rnd.processtool.model.processdata.ProcessDeadline;
import pl.net.bluesoft.rnd.processtool.plugins.ProcessToolRegistry;
import pl.net.bluesoft.rnd.pt.ext.bpmnotifications.service.BpmNotificationService;
import pl.net.bluesoft.rnd.pt.ext.bpmnotifications.util.EmailSender;
import pl.net.bluesoft.rnd.pt.ext.sched.service.ProcessToolSchedulerService;
import pl.net.bluesoft.rnd.util.i18n.I18NSource;
import pl.net.bluesoft.rnd.util.i18n.I18NSourceFactory;
import pl.net.bluesoft.util.lang.Collections;
import pl.net.bluesoft.util.lang.Predicate;
import pl.net.bluesoft.util.lang.Strings;
import pl.net.bluesoft.util.lang.Transformer;

import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

public class DeadlineEngine {
    private static final Logger logger = Logger.getLogger(DeadlineEngine.class.getName());
    private static final String DEFAULT_PROFILE_NAME = "DefaultDeadLineProfile";

    private ProcessToolRegistry registry;

    private Properties pluginProperties;

    public DeadlineEngine(ProcessToolRegistry registry, Properties pluginProperties) throws SchedulerException {
        this.registry = registry;
        this.pluginProperties = pluginProperties;
    }

    public void init() {
        registry.getExecutorService().submit(new Runnable() {
            @Override
            public void run() {
                registry.withProcessToolContext(new ProcessToolContextCallback() {
                    @Override
                    public void withContext(ProcessToolContext ctx) {
                        ProcessToolContext.Util.setThreadProcessToolContext(ctx);
                        try {
                            ProcessToolBpmSession bpmSession = ctx.getProcessToolSessionFactory().createAutoSession();
                            Session session = ctx.getHibernateSession();
                            List<ProcessInstance> instances = loadProcessesWithDeadlines(session);
                            for (ProcessInstance pi : instances) {
                                if (bpmSession.isProcessRunning(pi.getInternalId(), ctx)) {
                                    Set<ProcessDeadline> deadlines = pi.findAttributesByClass(ProcessDeadline.class);
                                    Collection<BpmTask> tasks = bpmSession.findProcessTasks(pi, ctx);
                                    for (ProcessDeadline pd : deadlines) {
                                        for (BpmTask task : tasks) {
                                            if (task.getTaskName().equals(pd.getTaskName()) && task.getAssignee() != null) {
                                                scheduleDeadline(pi.getInternalId(), pd);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        finally {
                            ProcessToolContext.Util.removeThreadProcessToolContext();
                        }
                    }
                });
            }
        });
    }

    private List<ProcessInstance> loadProcessesWithDeadlines(Session session) {
        DetachedCriteria pdc = DetachedCriteria.forClass(ProcessDeadline.class)
                .add(Restrictions.or(Restrictions.eq("alreadyNotified", Boolean.FALSE), Restrictions.isNull("alreadyNotified")))
                .createAlias("processInstance", "pi")
                .setProjection(Projections.distinct(Projections.property("pi.id")));

        return session.createCriteria(ProcessInstance.class)
                .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                .add(Subqueries.propertyIn("id", pdc)).list();
    }

    public void destroy() {
        ProcessToolSchedulerService service = getSchedulerService();
        service.cancelScheduledJobGroup(HandleDeadlineJob.class.getName());
    }

    private ProcessToolSchedulerService getSchedulerService() {
        return registry.getRegisteredService(ProcessToolSchedulerService.class);
    }

    private void scheduleDeadline(String processInternalId, ProcessDeadline pd) {
        ProcessToolSchedulerService service = getSchedulerService();
        Date currentDate = new Date(), dueDate = pd.getDueDate();
        if (DateUtils.isSameDay(dueDate, currentDate) || currentDate.before(dueDate) || !pd.isAlreadyProcessed()) {
            JobDataMap dataMap = new JobDataMap();
            dataMap.put("processInstanceId", processInternalId);
            dataMap.put("deadlineAttribute", pd);
            dataMap.put("deadlineEngine", this);

            String taskName = pd.getTaskName();
            String identity = "pi:" + processInternalId + ";task:" + taskName;

            JobDetail jobDetail = JobBuilder.newJob(HandleDeadlineJob.class)
                    .withIdentity(identity, HandleDeadlineJob.class.getName())
                    .usingJobData(dataMap)
                    .build();

            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(identity, HandleDeadlineJob.class.getName())
                    .startAt(dueDate)
                    .forJob(jobDetail)
                    .build();

            logger.info("Scheduling deadline job handler at: " + dueDate + " for process instance: " + processInternalId
                    + " and task name: " + taskName);
            service.scheduleJob(jobDetail, trigger);
        }
    }

    public void onProcessStateChange(final BpmTask task, ProcessInstance pi, boolean processInitiated) {
        if (pi == null || pi.getId() == null) {
            logger.info("Event contained no persistent process instance. Omitting.");
            return;
        }
        String internalId = pi.getInternalId();
        logger.info("Processing deadlines for process: " + internalId);
        ProcessToolContext ctx = ProcessToolContext.Util.getThreadProcessToolContext();
        pi = ctx.getProcessInstanceDAO().getProcessInstance(pi.getId());
        if (pi == null) {
            throw new ProcessToolException("Unable to find process instance by internal id: " + internalId);
        }
        Set<ProcessDeadline> deadlines = pi.findAttributesByClass(ProcessDeadline.class);
        if (!deadlines.isEmpty()) {
            logger.info("Found deadline configurations for process: " + pi.getInternalId());
            ProcessToolBpmSession bpmSession = ctx.getProcessToolSessionFactory().createAutoSession();
            List<BpmTask> tasks = processInitiated || task == null ? bpmSession.findProcessTasks(pi, ctx) : new ArrayList<BpmTask>() {{
                add(task);
            }};
            if (!tasks.isEmpty()) {
                Set<String> taskNames = new HashSet<String>();
                Collections.collect(tasks, new Transformer<BpmTask, String>() {
                    @Override
                    public String transform(BpmTask obj) {
                        return obj.getTaskName();
                    }
                }, taskNames);
                logger.info("Found tasks for process: " + pi.getInternalId());
                for (ProcessDeadline da : deadlines) {
                    if (taskNames.contains(da.getTaskName())) {
                        scheduleDeadline(pi.getInternalId(), da);
                    }
                }
            }
            else {
                logger.info("No tasks found for process: " + pi.getInternalId());
            }
        }
        else {
            logger.info("No deadlines found for process: " + pi.getInternalId());
        }
    }

    public void handleDeadlineJob(final String processInstanceId, final ProcessDeadline processDeadline) {
        registry.withProcessToolContext(new ProcessToolContextCallback() {
            @Override
            public void withContext(ProcessToolContext ctx) {
                ProcessToolContext.Util.setThreadProcessToolContext(ctx);
                try {
                    signalDeadline(ctx, processInstanceId, processDeadline);
                }
                catch (Exception e) {
                    logger.log(Level.SEVERE, "Exception while sending deadline notification", e);
                }
                finally {
                    ProcessToolContext.Util.removeThreadProcessToolContext();
                }
            }
        });
    }

    private void signalDeadline(ProcessToolContext ctx, String processInstanceId, ProcessDeadline processDeadline) throws Exception {
       
      ProcessInstance pi = ctx.getProcessInstanceDAO().getProcessInstanceByInternalId(processInstanceId);
        ProcessToolBpmSession bpmSession = ctx.getProcessToolSessionFactory().createAutoSession();
        List<BpmTask> tasks = bpmSession.findProcessTasks(pi, ctx);
        for (BpmTask task : tasks) {
            if (task.getTaskName().equals(processDeadline.getTaskName())) {
                String assigneeLogin = task.getAssignee();
        Map<String, UserData> notifyUsers = prepareUsersForNotification(ctx, assigneeLogin, processDeadline);

                // everything is good, unless it’s not
        I18NSource messageSource = getI18NSource();
                ProcessStateConfiguration st = ctx.getProcessDefinitionDAO().getProcessStateConfiguration(task);
                String taskName = messageSource.getMessage(st.getDescription());

                for (UserData user : notifyUsers.values()) {
                    if (processDeadline.getSkipAssignee() != null && processDeadline.getSkipAssignee() && user.getLogin().equals(assigneeLogin)) {
                        logger.info("Skipping deadline signal for assignee: " + assigneeLogin);
                        continue;
                    }
                    Map dataModel = new HashMap();
                    dataModel.put("process", pi);
                    dataModel.put("taskName", taskName);
                    dataModel.put("processVisibleId", Strings.hasText(pi.getExternalKey()) ? pi.getExternalKey() : pi.getInternalId());
                    dataModel.put("notifiedUser", user);
                    dataModel.put("assignedUser", notifyUsers.get(assigneeLogin));

          logger.info("Signaling deadline for task: " + task.getTaskName() + " owned by: " + assigneeLogin + ", mailed to: " + user.getLogin());
         
          if(processDeadline.getProfileName()==null){
            EmailSender.sendEmail(DEFAULT_PROFILE_NAME, getBpmNotifications(), user.getEmail(), processDeadline.getTemplateName(), dataModel)
          }
          else{
            EmailSender.sendEmail(processDeadline.getProfileName(), getBpmNotifications(), user.getEmail(), processDeadline.getTemplateName(), dataModel);
          }
         
                }
                processDeadline.setAlreadyNotified(true);
                ctx.getHibernateSession().saveOrUpdate(processDeadline);
            }
        }
    }

  private BpmNotificationService getBpmNotifications() {
    return registry.getRegisteredService(BpmNotificationService.class);
  }

  private I18NSource getI18NSource() {
    String defaultLocale = pluginProperties.getProperty("default.locale");
    Locale locale = Strings.hasText(defaultLocale) ? new Locale(defaultLocale) : Locale.getDefault();
    return I18NSourceFactory.createI18NSource(locale);
  }

  private Map<String, UserData> prepareUsersForNotification(ProcessToolContext ctx, String assigneeLogin, ProcessDeadline processDeadline) {
        Map<String, UserData> notifyUsers;
        List<String> userLogins = new ArrayList<String>();
        userLogins.add(assigneeLogin);
        if (Strings.hasText(processDeadline.getNotifyUsersWithLogin())) {
            for (String login : processDeadline.getNotifyUsersWithLogin().split(",")) {
                if (Strings.hasText(login)) {
                    userLogins.add(login);
                }
            }
        }
        notifyUsers = loadUsersAsMap(ctx, userLogins);
        if (!notifyUsers.containsKey(assigneeLogin)) {
            throw new ProcessToolException("Unable to find task assignee with login: " + assigneeLogin);
        }
        if (Strings.hasText(processDeadline.getNotifyUsersWithRole())) {
            for (String role : processDeadline.getNotifyUsersWithRole().split(",")) {
                if (Strings.hasText(role)) {
                    for (UserData userWithRole : LiferayBridge.getUsersByRole(role)) {
                        notifyUsers.put(userWithRole.getLogin(), userWithRole);
                    }
                }
            }
        }
        return notifyUsers;
    }

    private Map<String, UserData> loadUsersAsMap(ProcessToolContext ctx, List<String> userLogins) {
        Map<String, UserData> users = ctx.getUserDataDAO().loadUsersByLogin(userLogins);
        for (String login : userLogins) {
            if (users.get(login) == null) {
                UserData user = LiferayBridge.getLiferayUser(login);
                if (user == null) {
                    logger.warning("Unable to find user by login: " + login);
                }
                else {
                    users.put(login, user);
                }
            }
        }
        return Collections.filterValues(users, new Predicate<UserData>() {
            @Override
            public boolean apply(UserData input) {
                return input != null;
            }
        });
    }
}
TOP

Related Classes of pl.net.bluesoft.rnd.pt.ext.deadline.DeadlineEngine

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.