Package pl.net.bluesoft.rnd.processtool.dao.impl

Source Code of pl.net.bluesoft.rnd.processtool.dao.impl.ProcessInstanceDAOImpl

package pl.net.bluesoft.rnd.processtool.dao.impl;

import static org.hibernate.criterion.Restrictions.eq;
import static org.hibernate.criterion.Restrictions.in;
import static pl.net.bluesoft.util.lang.DateUtil.addDays;
import static pl.net.bluesoft.util.lang.DateUtil.asCalendar;
import static pl.net.bluesoft.util.lang.DateUtil.truncHours;
import static pl.net.bluesoft.util.lang.FormatUtil.formatShortDate;
import static pl.net.bluesoft.util.lang.FormatUtil.nvl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.aperteworkflow.search.ProcessInstanceSearchAttribute;
import org.aperteworkflow.search.ProcessInstanceSearchData;
import org.aperteworkflow.search.SearchProvider;
import org.aperteworkflow.search.Searchable;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.Session;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Subqueries;

import pl.net.bluesoft.rnd.processtool.dao.ProcessInstanceDAO;
import pl.net.bluesoft.rnd.processtool.hibernate.ResultsPageWrapper;
import pl.net.bluesoft.rnd.processtool.hibernate.SimpleHibernateBean;
import pl.net.bluesoft.rnd.processtool.hibernate.transform.NestedAliasToBeanResultTransformer;
import pl.net.bluesoft.rnd.processtool.model.BpmTask;
import pl.net.bluesoft.rnd.processtool.model.ProcessInstance;
import pl.net.bluesoft.rnd.processtool.model.ProcessInstanceAttachmentAttribute;
import pl.net.bluesoft.rnd.processtool.model.ProcessInstanceAttribute;
import pl.net.bluesoft.rnd.processtool.model.ProcessInstanceFilter;
import pl.net.bluesoft.rnd.processtool.model.ProcessInstanceLog;
import pl.net.bluesoft.rnd.processtool.model.UserData;
import pl.net.bluesoft.rnd.processtool.model.config.ProcessDefinitionConfig;
import pl.net.bluesoft.rnd.processtool.model.config.ProcessDefinitionPermission;
import pl.net.bluesoft.rnd.processtool.model.config.ProcessStateConfiguration;
import pl.net.bluesoft.rnd.processtool.model.config.ProcessStatePermission;
import pl.net.bluesoft.util.lang.Collections;
import pl.net.bluesoft.util.lang.Transformer;


/**
* @author tlipski@bluesoft.net.pl 
* @author kkolodziej@bluesoft.net.pl
*/
public class ProcessInstanceDAOImpl extends SimpleHibernateBean<ProcessInstance> implements ProcessInstanceDAO {
    private SearchProvider searchProvider;

    public ProcessInstanceDAOImpl(Session session, SearchProvider searchProvider) {
    super(session);
        this.searchProvider = searchProvider;
  }

  public long saveProcessInstance(ProcessInstance processInstance) {
    UserData creator = processInstance.getCreator();
    if (creator != null) {
      if (creator.getId() != null) {
        processInstance.setCreator((UserData) session.get(UserData.class, creator.getId()));
      } else {
        List users = session.createCriteria(UserData.class)
            .add(eq("login", creator.getLogin())).list();
        if (users.isEmpty()) {
          session.saveOrUpdate(creator);
        } else {
          processInstance.setCreator((UserData) users.get(0));
        }
      }
    }
        if (processInstance.getToDelete() != null) {
            for (Object o : processInstance.getToDelete()) {
                session.delete(o);
            }
        }
        Set<ProcessInstanceAttribute> procAttrib = processInstance.getProcessAttributes();
        for (ProcessInstanceAttribute attrib:procAttrib){
          if (attrib instanceof ProcessInstanceAttachmentAttribute && attrib.getId()!=null){
            session.evict(session.get(attrib.getClass(), attrib.getId()));
          }
        }
    session.saveOrUpdate(processInstance);
        session.flush();
        long time = System.currentTimeMillis();
        //update search indexes
        ProcessInstanceSearchData searchData = new ProcessInstanceSearchData(processInstance.getId());
        //put some default search attributes
        if (creator != null) {
            searchData.addSearchAttribute(new ProcessInstanceSearchAttribute("creator_login", creator.getLogin()));
            searchData.addSearchAttribute(new ProcessInstanceSearchAttribute("creator_email", creator.getEmail()));
            searchData.addSearchAttribute(new ProcessInstanceSearchAttribute("creator_realname", creator.getRealName()));
        }
        searchData.addSearchAttributes(new String[][]{
                {"instance_key", processInstance.getExternalKey()},
                {"definition_name", processInstance.getDefinitionName()},
                {"instance_description", processInstance.getDescription()},
                {"instance_internal_id", processInstance.getInternalId()},
                {"instance_keyword", processInstance.getKeyword()},
                {"instance_state", processInstance.getState()},//TODO remember about multiple states (when BpmTask is merged)
                {"instance_create_date", formatShortDate(processInstance.getCreateDate())},
        });
        ProcessDefinitionConfig def = processInstance.getDefinition();
        searchData.addSearchAttributes(new String[][]{
                {"definition_key", def.getBpmDefinitionKey()},
                {"definition_description", def.getDescription()},
                {"definition_comment", def.getComment()},
                {"definition_processname", def.getProcessName()},
        });
        for (ProcessDefinitionPermission perm : def.getPermissions()) {
            if ("SEARCH".equals(perm.getPrivilegeName())) {
                String roleName = perm.getRoleName();
                if (roleName.equals(".*"))
                    roleName = "__AWF__ROLE_ALL";
                roleName = roleName.replace(' ', '_');
                searchData.addSearchAttribute("__AWF__ROLE", roleName, true);
            }
        }
        //lookup process state configuration

        for (BpmTask t : nvl(processInstance.getActiveTasks(), new BpmTask[0])) {
            ProcessStateConfiguration psc
                    = new ProcessDefinitionDAOImpl(session).getProcessStateConfiguration(t);
            if (psc != null) {
                searchData.addSearchAttributes(new String[][]{
                                {"state_commentary", psc.getCommentary()},
                                {"state_description", psc.getDescription()},
                                {"state_name", psc.getName()},
                        });
                for (ProcessStatePermission perm : psc.getPermissions()) {
                    if ("SEARCH".equals(perm.getPrivilegeName())) {
                        String roleName = perm.getRoleName();
                        if (roleName.equals(".*"))
                            roleName = "__AWF__ROLE_ALL";
                        roleName = roleName.replace(' ', '_');
                        searchData.addSearchAttribute("__AWF__ROLE", roleName, true);
                    }
                }
            }
        }
        for (ProcessInstanceAttribute attr : processInstance.getProcessAttributes()) {
            if (attr instanceof Searchable) {
                Collection<ProcessInstanceSearchAttribute> attributes = ((Searchable) attr).getAttributes();
                for (ProcessInstanceSearchAttribute pisa : attributes) {
                    if (pisa.getName().startsWith("__AWF__")) { //no cheating please!
                        String newName = pisa.getName().replace("__AWF__", "");
                        logger.severe("Renaming process provided attribute " + pisa.getName() + " to " + newName +
                                " as it may clash with internal search attributes. PLEASE CORRECT PROCESS DEFINITION.");
                        pisa.setName(newName);
                    }
                }
                searchData.addSearchAttributes(attributes);
            }
        }
        for (String assignee : processInstance.getAssignees()) {
            searchData.addSearchAttribute("__AWF__assignee", assignee, true);
            logger.info("__AWF__assignee: "+ assignee);
        }
        for (String queue : processInstance.getTaskQueues()) {
            searchData.addSearchAttribute("__AWF__queue", queue, true);
            logger.info("__AWF__queue: "+ queue);
        }
        searchData.addSearchAttribute("__AWF__running", String.valueOf(processInstance.getRunning()), true);

        logger.finest("Prepare data for Lucene index update for" + processInstance + " took "
                + (System.currentTimeMillis()-time) + " ms");
        time = System.currentTimeMillis();
        searchProvider.updateIndex(searchData);
        logger.finest("Lucene index update for " + processInstance + " (" + searchData.getSearchAttributes().size()
                + "attributes)  took " + (System.currentTimeMillis()-time) + " ms");
       
    return processInstance.getId();
  }

  public ProcessInstance getProcessInstance(long id) {
    return (ProcessInstance) session.get(ProcessInstance.class, id);
  }

    @Override
    public List<ProcessInstance> getProcessInstances(Collection<Long> ids) {
        if (ids.isEmpty())
            return new ArrayList();
        return getSession().createCriteria(ProcessInstance.class)
                .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                .add(Restrictions.in("id", ids)).list();
    }

    @Override
    public ProcessInstance refreshProcessInstance(ProcessInstance processInstance) {
        return (ProcessInstance) getSession().merge(processInstance);
    }

    @Override
    public ProcessInstance getProcessInstanceByInternalId(String internalIds) {
       long start = System.currentTimeMillis();
     
      ProcessInstance pi = (ProcessInstance) getSession().createCriteria(ProcessInstance.class)
                .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                .add(eq("internalId", internalIds))
                .uniqueResult();
       long duration = System.currentTimeMillis() - start;
      logger.severe("getProcessInstanceByInternalId: " +  duration);
     
        
         return pi;
    }

  @Override
  public ProcessInstance getProcessInstanceByExternalId(String externalId) {
    List list = session.createCriteria(ProcessInstance.class)
            .add(eq("externalKey", externalId))
                        .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                        .list();
    if (list.isEmpty())
      return null;
    else
      return (ProcessInstance) list.get(0);
  }

  @Override
  public List<ProcessInstance> findProcessInstancesByKeyword(String keyword, String processType) {
    return session.createCriteria(ProcessInstance.class)
            .add(eq("keyword", keyword))
//            .add(eq("definition.bpmDefinitionKey", processType))
            .addOrder(Order.desc("id"))
                .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
            .list();

  }
 
 
  @Override
  public Map<String, ProcessInstance> getProcessInstanceByInternalIdMap(Collection<String> internalId) {
        if (internalId.isEmpty()) {
             return new HashMap<String, ProcessInstance>();
         }
         List<ProcessInstance> list = getSession().createCriteria(ProcessInstance.class)
                 .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                 .add(in("internalId", internalId))
                 .list();
         return Collections.transform(list, new Transformer<ProcessInstance, String>() {
             @Override
             public String transform(ProcessInstance obj) {
                 return obj.getInternalId();
             }
         });
  }

  public List<ProcessInstance> getProcessInstancesByIds(List<Long> ids) {
    return getProcessInstances(ids);
  }
 

  public void deleteProcessInstance(ProcessInstance instance) {
    long start = System.currentTimeMillis();
    session.delete(instance);
    long duration = System.currentTimeMillis() - start;
    logger.severe("deleteProcessInstanceByInternalId: " +  duration);
  }
 
 

    public Collection<ProcessInstanceLog> getUserHistory(UserData user, Date startDate, Date endDate) {
     
       long start = System.currentTimeMillis();
        Criteria criteria = session.createCriteria(ProcessInstanceLog.class)
                .addOrder(Order.desc("entryDate"));
       
          

        if (user != null) {
            criteria.add(Restrictions.or(Restrictions.eq("user", user), Restrictions.eq("userSubstitute", user)));
        }

        if (startDate != null) {
            criteria.add(Restrictions.ge("entryDate", asCalendar(truncHours(startDate))));
        }
        if (endDate != null) {
            criteria.add(Restrictions.le("entryDate", asCalendar(truncHours(addDays(endDate, 1)))));
        }

        criteria.createAlias("state", "s", CriteriaSpecification.LEFT_JOIN);
        criteria.createAlias("processInstance", "pi");
        criteria.createAlias("pi.definition", "def");
        criteria.createAlias("pi.creator", "crtr");
        criteria.createAlias("ownProcessInstance", "ownPi");
        criteria.createAlias("user", "u");
        criteria.createAlias("userSubstitute", "us", CriteriaSpecification.LEFT_JOIN);
        ProjectionList pl = Projections.projectionList()
                .add(Projections.id(), "id")
                .add(Projections.property("entryDate"), "entryDate")
                .add(Projections.property("eventI18NKey"), "eventI18NKey")
                .add(Projections.property("executionId"), "executionId")
                .add(Projections.property("additionalInfo"), "additionalInfo")
                .add(Projections.property("u.id"), "user.id")
                .add(Projections.property("u.login"), "user.login")
                .add(Projections.property("u.firstName"), "user.firstName")
                .add(Projections.property("u.lastName"), "user.lastName")
                .add(Projections.property("s.id"), "state.id")
                .add(Projections.property("s.name"), "state.name")
                .add(Projections.property("s.description"), "state.description")
                .add(Projections.property("us.id"), "userSubstitute.id")
                .add(Projections.property("us.firstName"), "userSubstitute.firstName")
                .add(Projections.property("us.lastName"), "userSubstitute.lastName")
                .add(Projections.property("pi.id"), "processInstance.id")
                .add(Projections.property("pi.internalId"), "processInstance.internalId")
                .add(Projections.property("pi.externalKey"), "processInstance.externalKey")
                .add(Projections.property("pi.status"), "processInstance.status")
                .add(Projections.property("pi.createDate"), "processInstance.createDate")
                .add(Projections.property("def.id"), "processInstance.definition.id")
                .add(Projections.property("def.description"), "processInstance.definition.description")
                .add(Projections.property("def.comment"), "processInstance.definition.comment")
                .add(Projections.property("crtr.firstName"), "processInstance.creator.firstName")
                .add(Projections.property("crtr.lastName"), "processInstance.creator.lastName")
                .add(Projections.property("ownPi.id"), "ownProcessInstance.id");

        criteria.setProjection(pl);

        criteria.setResultTransformer(new NestedAliasToBeanResultTransformer(ProcessInstanceLog.class));

        long duration = System.currentTimeMillis() - start;
    logger.severe("getUserHistory: " +  duration);
       
        return criteria.list();
    }
   
       
    @Override
    public Collection<ProcessInstance> getUserProcessesAfterDate(UserData userData, Calendar minDate) {
      return getUserProcessesBetweenDates(userData,minDate,null);
    }
   
  
    @Override
    public Collection<ProcessInstance> getUserProcessesBetweenDates(UserData userData, Calendar minDate, Calendar maxDate) {
          
       long start = System.currentTimeMillis();
      Session session = getSession();
            ProjectionList properties = Projections.projectionList();
            properties.add(Projections.property("id"));
            properties.add(Projections.property("internalId"));
           Criteria criteria = session.createCriteria(ProcessInstance.class)
                    .setProjection(Projections.distinct(properties))
                    .createCriteria("processLogs");
                   
                    if(minDate!=null){
                      criteria.add(Restrictions.gt("entryDate", minDate));
                    }
                   
                    if(maxDate!=null){
                      criteria.add(Restrictions.le("entryDate", maxDate));
                    }
          
                   criteria.createAlias("user", "u")
                    .add(Restrictions.eq("u.id", userData.getId()));

           List<Object[]> list = criteria.list();
             Collection<ProcessInstance> collect = Collections.collect(list, new Transformer<Object[], ProcessInstance>() {
                @Override
                public ProcessInstance transform(Object[] row) {
                    ProcessInstance pi = new ProcessInstance();
                    pi.setId((Long) row[0]);
                    pi.setInternalId((String) row[1]);
                    return pi;
                }
            });
           
             long duration = System.currentTimeMillis() - start;
       logger.severe("getUserProcessesBetweenDates: " +  duration);
             return collect;
           
        }
   
   
   

        @Override
        public ResultsPageWrapper<ProcessInstance> getRecentProcesses(UserData userData, Calendar minDate, Integer offset, Integer limit) {
            Session session = getSession();
            List<ProcessInstance> instances = null;
            if (offset != null && limit != null) {
                List<Long> list = session.createCriteria(ProcessInstance.class)
                        .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                        .setProjection(Projections.distinct(Projections.property("id")))
                        .addOrder(Order.desc("id"))
                        .setFirstResult(offset)
                        .setMaxResults(limit)
                        .createCriteria("processLogs")
                        .add(Restrictions.gt("entryDate", minDate))
                        .createAlias("user", "u")
                        .add(Restrictions.eq("u.id", userData.getId()))
                        .list();
                instances = getProcessInstancesByIds(list);
            }

            Number total = (Number) session.createCriteria(ProcessInstance.class)
                    .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
                    .setProjection(Projections.countDistinct("id"))
                    .createCriteria("processLogs")
                    .add(Restrictions.gt("entryDate", minDate))
                    .createAlias("user", "u")
                    .add(Restrictions.eq("u.id", userData.getId())).uniqueResult();
           
            ResultsPageWrapper<ProcessInstance> resultsPageWrapper = new ResultsPageWrapper<ProcessInstance>(instances != null ? instances : new ArrayList<ProcessInstance>(),
                    total == null ? 0 : total.intValue());

            return resultsPageWrapper;
        }

        @Override
        final public ResultsPageWrapper<ProcessInstance> getProcessInstanceByInternalIdMapWithFilter(final Collection<String> internalIds,
                                                                                                     final ProcessInstanceFilter filter, Integer offset, Integer limit) {
            if (internalIds.isEmpty()) {
                return new ResultsPageWrapper<ProcessInstance>();
            }
            Session session = getSession();

            DetachedCriteria detachedCriteriaForIds = buildhibernateQuery(internalIds, session, filter, offset, limit);

            Criteria criteria = detachedCriteriaForIds.getExecutableCriteria(session);
            criteria.setFetchMode("definition",FetchMode.SELECT);
            criteria.setFetchMode("creator",FetchMode.SELECT);
            criteria.setFetchMode("parent",FetchMode.SELECT);

            List<ProcessInstance> result = (List<ProcessInstance>)criteria.list();
            int resultsCount = result.size();

            List<ProcessInstance> list;
            /* If limit is zero or null, return results */
            if(limit == null || limit <= 0)
            {
                list = new ArrayList<ProcessInstance>(result);
            }
            else
            {
                criteria.setFirstResult(offset);
                criteria.setMaxResults(limit);
                criteria.addOrder(Order.desc("createDate"));
                criteria.setProjection(Projections.id());//null).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
                List ids = criteria.list();

                if (ids != null && !ids.isEmpty()) {
                    DetachedCriteria detachedCriteriaForData = DetachedCriteria.forClass(ProcessInstance.class, "data");
                    detachedCriteriaForData.addOrder(Order.desc("createDate"));
                    detachedCriteriaForData.add(Property.forName("id").in(ids));
                    detachedCriteriaForData.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
                   
                    Criteria criteria2 = detachedCriteriaForData.getExecutableCriteria(session);
                    criteria2.setFetchMode("definition",FetchMode.SELECT);
                criteria2.setFetchMode("creator",FetchMode.SELECT);
                criteria2.setFetchMode("parent",FetchMode.SELECT);
                    list = criteria2.list();
                }
                else {
                    list = new ArrayList<ProcessInstance>(0);
                }
            }

            return new ResultsPageWrapper<ProcessInstance>(list, resultsCount);
        }

        private DetachedCriteria buildhibernateQuery(Collection<String> internalIds, Session session, ProcessInstanceFilter filter, Integer offset, Integer limit) {
            DetachedCriteria criteria = DetachedCriteria.forClass(ProcessInstance.class, "ids");

            criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
            //criteria.setProjection(Projections.distinct(Projections.property("id")));

            criteria = criteria.add(Restrictions.in("internalId", internalIds));

            if (filter.getCreatedAfter() != null) {
                criteria = criteria.add(Restrictions.gt("createDate", filter.getCreatedAfter()));
            }

            if (filter.getCreatedBefore() != null) {
                criteria = criteria.add(Restrictions.lt("createDate", filter.getCreatedBefore()));
            }

            if (filter.getCreators() != null && !filter.getCreators().isEmpty()) {
                criteria = criteria.add(Restrictions.in("creator", filter.getCreators()));
            }

            if (filter.getUpdatedAfter() != null) {
                criteria = criteria
                        .createCriteria("processLogs")
                        .add(Restrictions.gt("entryDate", filter.getUpdatedAfterCalendar()));
            }

            if (filter.getNotUpdatedAfter() != null) {
                DetachedCriteria entryDateCriteria = DetachedCriteria.forClass(ProcessInstanceLog.class).add(Restrictions.gt("entryDate", filter.getNotUpdatedAfterCalendar()));
                criteria = criteria
                        .createCriteria("processLogs")
                        .add(Restrictions.not(Subqueries.exists(entryDateCriteria)));
            }

            return criteria;
        }


    @Override
    public Collection<ProcessInstance> searchProcesses(String filter, int offset, int limit,
                                                       boolean onlyRunning, String[] userRoles,
                                                       String assignee, String... queues) {
     
       long start = System.currentTimeMillis();
        List<Long> processIds = searchProvider.searchProcesses(filter, offset, limit, onlyRunning, userRoles, assignee, queues);
        List<ProcessInstance> processInstancesByIds = getProcessInstancesByIds(processIds);
        java.util.Collections.sort(processInstancesByIds, new Comparator<ProcessInstance>() {
            @Override
            public int compare(ProcessInstance o1, ProcessInstance o2) {
                return o2.getId().compareTo(o1.getId());
            }
        });
       
        long duration = System.currentTimeMillis() - start;
    logger.severe("searchProcesses: " +  duration);
        return processInstancesByIds;
    }
}
TOP

Related Classes of pl.net.bluesoft.rnd.processtool.dao.impl.ProcessInstanceDAOImpl

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.