package is.idega.idegaweb.egov.bpm.cases.manager; import is.idega.idegaweb.egov.application.business.ApplicationBusiness; import is.idega.idegaweb.egov.application.data.Application; import is.idega.idegaweb.egov.application.data.ApplicationHome; import is.idega.idegaweb.egov.bpm.business.CasesSubcriberManager; import is.idega.idegaweb.egov.bpm.cases.bundle.ProcessBundleCasesImpl; import is.idega.idegaweb.egov.bpm.cases.presentation.UICasesBPMAssets; import is.idega.idegaweb.egov.bpm.cases.presentation.beans.BPMCasesEngine; import is.idega.idegaweb.egov.bpm.cases.presentation.beans.CasesBPMAssetsState; import is.idega.idegaweb.egov.cases.business.CasesBusiness; import is.idega.idegaweb.egov.cases.data.CaseCategory; import is.idega.idegaweb.egov.cases.data.GeneralCase; import is.idega.idegaweb.egov.cases.util.CasesConstants; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.FinderException; import javax.faces.component.UIComponent; import javax.faces.component.UIViewRoot; import javax.servlet.http.HttpSession; import org.jbpm.JbpmContext; import org.jbpm.JbpmException; import org.jbpm.db.GraphSession; import org.jbpm.graph.def.ProcessDefinition; import org.jbpm.graph.exe.ProcessInstance; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.ApplicationEvent; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.context.support.WebApplicationContextUtils; import com.idega.block.process.business.CaseBusiness; import com.idega.block.process.business.CasesCacheCriteria; import com.idega.block.process.business.CasesRetrievalManager; import com.idega.block.process.business.CasesRetrievalManagerImpl; import com.idega.block.process.business.ProcessConstants; import com.idega.block.process.data.Case; import com.idega.block.process.data.CaseCode; import com.idega.block.process.event.CaseDeletedEvent; import com.idega.block.process.event.CaseModifiedEvent; import com.idega.block.process.presentation.beans.CaseManagerState; import com.idega.block.process.presentation.beans.CasePresentation; import com.idega.block.process.presentation.beans.CasePresentationComparator; import com.idega.block.process.presentation.beans.CasesSearchCriteriaBean; import com.idega.bpm.BPMConstants; import com.idega.business.IBOLookup; import com.idega.business.IBOLookupException; import com.idega.business.IBORuntimeException; import com.idega.core.accesscontrol.business.AccessController; import com.idega.core.builder.data.ICPage; import com.idega.core.builder.data.ICPageHome; import com.idega.data.IDOLookup; import com.idega.data.IDOLookupException; import com.idega.data.SimpleQuerier; import com.idega.idegaweb.IWApplicationContext; import com.idega.idegaweb.IWMainApplication; import com.idega.idegaweb.egov.bpm.data.CaseProcInstBind; import com.idega.idegaweb.egov.bpm.data.CaseTypesProcDefBind; import com.idega.idegaweb.egov.bpm.data.dao.CasesBPMDAO; import com.idega.jbpm.BPMContext; import com.idega.jbpm.JbpmCallback; import com.idega.jbpm.data.ProcessManagerBind; import com.idega.jbpm.events.ProcessInstanceCreatedEvent; import com.idega.jbpm.exe.BPMDocument; import com.idega.jbpm.exe.BPMEmailDocument; import com.idega.jbpm.exe.BPMFactory; import com.idega.jbpm.exe.ProcessInstanceW; import com.idega.jbpm.exe.ProcessManager; import com.idega.jbpm.exe.TaskInstanceW; import com.idega.jbpm.variables.VariablesHandler; import com.idega.presentation.IWContext; import com.idega.presentation.paging.PagedDataCollection; import com.idega.presentation.text.Link; import com.idega.user.business.UserBusiness; import com.idega.user.data.Group; import com.idega.user.data.GroupBMPBean; import com.idega.user.data.User; import com.idega.util.ArrayUtil; import com.idega.util.CoreConstants; import com.idega.util.CoreUtil; import com.idega.util.ListUtil; import com.idega.util.StringHandler; import com.idega.util.StringUtil; import com.idega.util.datastructures.map.MapUtil; import com.idega.util.expression.ELUtil; import com.idega.webface.WFUtil; /** * @author <a href="mailto:civilis@idega.com">Vytautas Čivilis</a> * @version $Revision: 1.13 $ * * Last modified: $Date: 2009/07/14 16:25:04 $ by $Author: valdas $ */ @Scope(BeanDefinition.SCOPE_SINGLETON) @Service(BPMCasesRetrievalManagerImpl.beanIdentifier) @Transactional(readOnly = true) public class BPMCasesRetrievalManagerImpl extends CasesRetrievalManagerImpl implements BPMCasesRetrievalManager { private static final Logger LOGGER = Logger.getLogger(BPMCasesRetrievalManagerImpl.class.getName()); public static final String PARAMETER_PROCESS_INSTANCE_PK = "pr_inst_pk"; @Autowired private CasesBPMDAO casesBPMDAO; @Autowired private BPMContext bpmContext; @Autowired private BPMFactory bpmFactory; @Autowired private VariablesHandler variablesHandler; @Autowired private BPMCasesEngine casesEngine; private ApplicationBusiness applicationBusiness; public static final String beanIdentifier = "casesBPMCaseHandler", caseHandlerType = ProcessConstants.BPM_CASE; @Override public String getBeanIdentifier() { return beanIdentifier; } @Override public String getType() { return caseHandlerType; } @Override public String getProcessIdentifier(Case theCase) { final Long piId = getProcessInstanceId(theCase); if (piId == null) { return null; } return getBpmContext().execute(new JbpmCallback() { @Override public Object doInJbpm(JbpmContext context) throws JbpmException { return context.getProcessInstance(piId).getContextInstance().getVariable(ProcessConstants.CASE_IDENTIFIER); } }); } @Override public Long getProcessInstanceId(Case theCase) { Integer caseId = theCase.getPrimaryKey() instanceof Integer ? (Integer) theCase.getPrimaryKey() : Integer.valueOf((theCase.getPrimaryKey().toString())); CaseProcInstBind cpi = getCasesBPMDAO().getCaseProcInstBindByCaseId(caseId); return cpi == null ? null : cpi.getProcInstId(); } @Override public Long getProcessInstanceIdByCaseId(Object id) { Integer caseId = id instanceof Integer ? (Integer) id : Integer.valueOf(id.toString()); CaseProcInstBind cpi = getCasesBPMDAO().getCaseProcInstBindByCaseId(caseId); return cpi == null ? null : cpi.getProcInstId(); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getConnectedUsers(java.util.Collection) */ @Override public List<User> getConnectedUsers(Collection<ProcessInstanceW> processInstances) { if (ListUtil.isEmpty(processInstances)) { return Collections.emptyList(); } List<User> allUsers = new ArrayList<User>(); for (ProcessInstanceW instance: processInstances) { List<User> users = instance.getUsersConnectedToProcess(); if (ListUtil.isEmpty(users)) { continue; } allUsers.addAll(users); } return allUsers; } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getConnectedUsers(com.idega.block.process.data.Case) */ @Override public List<User> getConnectedUsers(Case theCase) { if (theCase == null) { return Collections.emptyList(); } ProcessInstanceW processInstanceW = getProcessInstancesW(theCase); if (processInstanceW == null) { return Collections.emptyList(); } return getConnectedUsers(Arrays.asList(processInstanceW)); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getBPMEmailDocuments(java.util.Collection, com.idega.user.data.User) */ @Override public List<BPMEmailDocument> getBPMEmailDocuments( Collection<ProcessInstanceW> processInstances, User owner) { if (ListUtil.isEmpty(processInstances) || owner == null) { return Collections.emptyList(); } ArrayList<BPMEmailDocument> emails = new ArrayList<BPMEmailDocument>(); for (ProcessInstanceW instance: processInstances) { List<BPMEmailDocument> entities = instance.getAttachedEmails(owner); if (ListUtil.isEmpty(entities)) { continue; } emails.addAll(entities); } return emails; } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getTaskBPMDocuments(java.util.Collection, com.idega.user.data.User, java.util.Locale) */ @Override public List<BPMDocument> getTaskBPMDocuments( Collection<ProcessInstanceW> processInstances, User owner, Locale locale) { if (ListUtil.isEmpty(processInstances) || owner == null) { return Collections.emptyList(); } if (locale == null) { locale = getCurrentLocale(); } ArrayList<BPMDocument> taskDocuments = new ArrayList<BPMDocument>(); for (ProcessInstanceW instance: processInstances) { List<BPMDocument> entities = instance.getTaskDocumentsForUser(owner, locale); if (ListUtil.isEmpty(entities)) { continue; } taskDocuments.addAll(entities); } return taskDocuments; } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getSubmittedBPMDocuments(java.util.Collection, com.idega.user.data.User, java.util.Locale) */ @Override public List<BPMDocument> getSubmittedBPMDocuments( Collection<ProcessInstanceW> processInstances, User owner, Locale locale) { if (ListUtil.isEmpty(processInstances) || owner == null) { return Collections.emptyList(); } if (locale == null) { locale = getCurrentLocale(); } ArrayList<BPMDocument> submittedDocuments = new ArrayList<BPMDocument>(); for (ProcessInstanceW instance: processInstances) { List<BPMDocument> entities = instance.getSubmittedDocumentsForUser(owner, locale); if (ListUtil.isEmpty(entities)) { continue; } submittedDocuments.addAll(entities); } return submittedDocuments; } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getProcessInstancesW(java.lang.Object) */ @Override public List<ProcessInstanceW> getProcessInstancesW(Object applicationPrimaryKey) { Application application = getApplication(applicationPrimaryKey); if (application == null) { return Collections.emptyList(); } return getProcessInstancesW(application.getUrl()); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getProcessInstancesW(is.idega.idegaweb.egov.application.data.Application) */ @Override public List<ProcessInstanceW> getProcessInstancesW(Application application) { if (application == null) { return Collections.emptyList(); } return getProcessInstancesW(application.getUrl()); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getProcessInstancesW(java.lang.String) */ @Override public List<ProcessInstanceW> getProcessInstancesW(String processDefinitionName) { if (StringUtil.isEmpty(processDefinitionName)) { return Collections.emptyList(); } ProcessManager processManager = getBpmFactory().getProcessManager( processDefinitionName); if (processManager == null) { return Collections.emptyList(); } List<Long> porcessInstancesIds = getProcessInstancesIDs(processDefinitionName); if (ListUtil.isEmpty(porcessInstancesIds)) { return null; } ArrayList<ProcessInstanceW> instancesW = new ArrayList<ProcessInstanceW>(); for (Long porcessInstanceId: porcessInstancesIds) { instancesW.add(processManager.getProcessInstance(porcessInstanceId)); } return instancesW; } @Override public boolean hasManagerAccess(Collection<String> caseIdentifiers) { String[] roles = getManagerRoleNames(caseIdentifiers); if (ArrayUtil.isEmpty(roles)) { return Boolean.FALSE; } AccessController accessController = getApplication().getAccessController(); if (accessController == null) { return Boolean.FALSE; } if (accessController.hasRole(getCurrentUser(), Arrays.asList(roles))) { return Boolean.TRUE; } return Boolean.FALSE; } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getManagerRoleName(java.lang.String) */ @Override public String[] getManagerRoleNames(Collection<String> caseIdentifiers) { if (ListUtil.isEmpty(caseIdentifiers)) { return null; } StringBuilder sb = new StringBuilder("SELECT jvi.stringvalue_ "); sb.append("FROM jbpm_variableinstance jvi, bpm_cases_processinstances bcpi "); sb.append("WHERE jvi.PROCESSINSTANCE_ = bcpi.process_instance_id "); sb.append("AND jvi.NAME_='" + BPMConstants.VAR_MANAGER_ROLE + "' "); sb.append("AND bcpi.case_identifier IN ("); for (Iterator<String> iterator = caseIdentifiers.iterator(); iterator.hasNext();) { sb.append(CoreConstants.QOUTE_SINGLE_MARK) .append(iterator.next()) .append(CoreConstants.QOUTE_SINGLE_MARK); if (iterator.hasNext()) { sb.append(CoreConstants.COMMA).append(CoreConstants.SPACE); } } sb.append(")"); String[] managerRoleNames = null; try { managerRoleNames = SimpleQuerier.executeStringQuery(sb.toString()); } catch (Exception e) { getLogger().log(Level.WARNING, "Unable to get manager role names: ", e); } if (ArrayUtil.isEmpty(managerRoleNames)) { return null; } return managerRoleNames; } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getProcessInstancesW(com.idega.block.process.data.Case) */ @Override public ProcessInstanceW getProcessInstancesW(Case theCase) { Long processInstanceID = getProcessInstanceId(theCase); if (processInstanceID == null) { return null; } ProcessManager processManager = getBpmFactory() .getProcessManagerByProcessInstanceId(processInstanceID); if (processManager == null) { return null; } return processManager.getProcessInstance(processInstanceID); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getProcessInstances(java.lang.String) */ @Override public List<ProcessInstance> getProcessInstances(String processDefinitionName) { return getBpmFactory().getBPMDAO() .getProcessInstances(Arrays.asList(processDefinitionName)); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getProcessInstancesIDs(java.lang.String) */ @Override public List<Long> getProcessInstancesIDs(String processDefinitionName) { return getBpmFactory().getBPMDAO() .getProcessInstanceIdsByProcessDefinitionNames( Arrays.asList(processDefinitionName)); } @Override public Long getProcessDefinitionId(Case theCase) { ProcessDefinition processDefinition = getProcessDefinition(theCase); return processDefinition == null ? null : processDefinition.getId(); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getProcessDefinitions(java.lang.String) */ @Override public List<ProcessDefinition> getProcessDefinitions(String processDefinitionName) { return getBpmFactory().getBPMDAO().getProcessDefinitions(processDefinitionName); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getProcessDefinitionsIDs(java.lang.String) */ @Override public List<Long> getProcessDefinitionsIDs(String processDefinitionName) { return getBpmFactory().getBPMDAO().getProcessDefinitionIdsByName(processDefinitionName); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getProcessDefinitions(is.idega.idegaweb.egov.application.data.Application) */ @Override public List<ProcessDefinition> getProcessDefinitions(Application application) { if (application == null) { return Collections.emptyList(); } return getProcessDefinitions(application.getUrl()); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getProcessDefinitionsIDs(is.idega.idegaweb.egov.application.data.Application) */ @Override public List<Long> getProcessDefinitionsIDs(Application application) { if (application == null) { return Collections.emptyList(); } return getProcessDefinitionsIDs(application.getUrl()); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getProcessDefinitions(java.lang.Object) */ @Override public List<ProcessDefinition> getProcessDefinitions(Object applicationPrimaryKey) { Application application = getApplication(applicationPrimaryKey); if (application == null) { return Collections.emptyList(); } return getProcessDefinitions(application.getUrl()); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getProcessDefinitionsIDs(java.lang.Object) */ @Override public List<Long> getProcessDefinitionsIDs(Object applicationPrimaryKey) { Application application = getApplication(applicationPrimaryKey); if (application == null) { return Collections.emptyList(); } return getProcessDefinitionsIDs(application.getUrl()); } @Override public String getProcessDefinitionName(Case theCase) { ProcessDefinition processDefinition = getProcessDefinition(theCase); return processDefinition == null ? null : processDefinition.getName(); } private ProcessDefinition getProcessDefinition(Case theCase) { final Long piId = getProcessInstanceId(theCase); if (piId == null) return null; return getBpmContext().execute(new JbpmCallback() { @Override public Object doInJbpm(JbpmContext context) throws JbpmException { return context.getProcessInstance(piId).getProcessDefinition(); } }); } @Override public List<Link> getCaseLinks(Case theCase, String casesComponentType) { throw new UnsupportedOperationException("Implement with correct pages if needed"); } @Override public UIComponent getView(IWContext iwc, Integer caseId, String type, String caseManagerType) { if (!caseHandlerType.equals(caseManagerType)) return super.getView(iwc, caseId, type, caseManagerType); CasesBPMAssetsState stateBean = WFUtil.getBeanInstance(CasesBPMAssetsState.beanIdentifier); stateBean.setDisplayPropertyForStyleAttribute(Boolean.FALSE); stateBean.setStandAloneComponent(Boolean.FALSE); CaseManagerState managerState = ELUtil.getInstance().getBean(CaseManagerState.beanIdentifier); managerState.setFullView(!CasesRetrievalManager.CASE_LIST_TYPE_USER.equals(type)); UICasesBPMAssets casesAssets = (UICasesBPMAssets)iwc.getApplication().createComponent(UICasesBPMAssets.COMPONENT_TYPE); UIViewRoot viewRoot = iwc.getViewRoot(); if (viewRoot != null) casesAssets.setId(viewRoot.createUniqueId()); casesAssets.setUsePdfDownloadColumn(stateBean.getUsePDFDownloadColumn() == null ? false : stateBean.getUsePDFDownloadColumn()); casesAssets.setAllowPDFSigning(stateBean.getAllowPDFSigning() == null ? false : stateBean.getAllowPDFSigning()); casesAssets.setHideEmptySection(stateBean.getHideEmptySection() == null ? false : stateBean.getHideEmptySection()); casesAssets.setCommentsPersistenceManagerIdentifier(stateBean.getCommentsPersistenceManagerIdentifier()); casesAssets.setShowAttachmentStatistics(stateBean.getShowAttachmentStatistics() == null ? false : stateBean.getShowAttachmentStatistics()); casesAssets.setShowOnlyCreatorInContacts(stateBean.getShowOnlyCreatorInContacts() == null ? false : stateBean.getShowOnlyCreatorInContacts()); casesAssets.setShowLogExportButton(stateBean.isShowLogExportButton()); casesAssets.setShowComments(stateBean.getShowComments() == null ? Boolean.TRUE : stateBean.getShowComments()); casesAssets.setShowContacts(stateBean.getShowContacts() == null ? Boolean.TRUE : stateBean.getShowContacts()); casesAssets.setSpecialBackPage(stateBean.getSpecialBackPage()); casesAssets.setNameFromExternalEntity(stateBean.isNameFromExternalEntity()); casesAssets.setShowUserProfilePicture(stateBean.getShowUserProfilePicture()); casesAssets.setShowUserCompany(stateBean.getShowUserCompany()); casesAssets.setShowLastLoginDate(stateBean.getShowLastLoginDate()); if (caseId != null) casesAssets.setCaseId(caseId); return casesAssets; } @Override public PagedDataCollection<CasePresentation> getCases(User user, String type, Locale locale, List<String> caseCodes, List<String> caseStatusesToHide, List<String> caseStatusesToShow, int startIndex, int count, boolean onlySubscribedCases, boolean showAllCases) { try { List<Integer> casesIds = getCasePrimaryKeys(user, type, caseCodes, caseStatusesToHide, caseStatusesToShow, onlySubscribedCases, showAllCases, null, null); if (ListUtil.isEmpty(casesIds)) { LOGGER.info("User '" + user + "' doesn't have any cases!"); return new PagedDataCollection<CasePresentation>(new ArrayList<CasePresentation>(), 0); } long start = System.currentTimeMillis(); int totalCount = casesIds.size(); Collection<? extends Case> cases = null; if (startIndex < totalCount) { Collection<Integer> casesToFetch = null; if (startIndex + count < totalCount) { casesToFetch = casesIds.subList(startIndex, (startIndex + count)); } else { casesToFetch = casesIds.subList(startIndex, totalCount); } if (!CasesRetrievalManager.CASE_LIST_TYPE_USER.equals(type)) { cases = getCasesBusiness().getGeneralCaseHome().findAllByIds(casesToFetch); } else { cases = getCaseBusiness().getCasesByIds(casesToFetch); } } else if (startIndex == Integer.MAX_VALUE) { cases = getCaseBusiness().getCasesByIds(casesIds); } else cases = new ArrayList<Case>(); List<CasePresentation> casesPresentation = convertToPresentationBeans(cases, locale); if (!ListUtil.isEmpty(casesPresentation) && IWMainApplication.getDefaultIWMainApplication().getSettings().getBoolean("extra_cases_sorting", Boolean.FALSE)) Collections.sort(casesPresentation, new CasePresentationComparator()); getLogger().info("Cases (total: " + cases.size() + ") converted into beans in " + (System.currentTimeMillis() - start) + " ms"); return new PagedDataCollection<CasePresentation>(casesPresentation, totalCount); } catch (Exception e) { LOGGER.log(Level.WARNING, "Some error occurred while getting cases for user: " + user + " by type: " + type + ", by locale: " + locale + ", by case codes: " + caseCodes + ", by case statuses to hide: " + caseStatusesToHide + ", by case statuses to show: " + caseStatusesToShow + ", start index: " + startIndex + ", count: " + count + ", only subscribed cases: " + onlySubscribedCases, e); } return new PagedDataCollection<CasePresentation>(new ArrayList<CasePresentation>(), 0); } @Override public List<Integer> getCaseIds(User user, String type, List<String> caseCodes, List<String> statusesToHide, List<String> statusesToShow, boolean onlySubscribedCases, boolean showAllCases) throws Exception { return getCaseIds(user, type, caseCodes, statusesToHide, statusesToShow, onlySubscribedCases, showAllCases, null, null, null); } @Override public List<Integer> getCasePrimaryKeys( User user, String type, List<String> caseCodes, List<String> caseStatusesToHide, List<String> caseStatusesToShow, boolean onlySubscribedCases, boolean showAllCases, List<Long> procInstIds, Collection<Long> handlerCategoryIDs) throws Exception { return getCaseIds( user, type, caseCodes, caseStatusesToHide, caseStatusesToShow, onlySubscribedCases, showAllCases, null, procInstIds, handlerCategoryIDs); } private Set<String> getRoles(HttpSession session, AccessController access, User user) { if (user == null) { return null; } if (session == null) { return access.getAllRolesForUser(user); } String activeRole = (String) session.getAttribute(CoreConstants.ACTIVE_ROLE); if (StringUtil.isEmpty(activeRole)) { return access.getAllRolesForUser(user); } return new HashSet<String>(Arrays.asList(activeRole)); } @Override protected List<Integer> getCaseIds( User user, String type, List<String> caseCodes, List<String> caseStatusesToHide, List<String> caseStatusesToShow, boolean onlySubscribedCases, boolean showAllCases, Integer caseId, List<Long> procInstIds, Collection<Long> handlerCategoryIDs) throws Exception { List<Integer> caseIds = null; List<String> statusesToShow = caseStatusesToShow == null ? new ArrayList<String>() : new ArrayList<String>(caseStatusesToShow); List<String> statusesToHide = caseStatusesToHide == null ? new ArrayList<String>() : new ArrayList<String>(caseStatusesToHide); statusesToHide = ListUtil.getFilteredList(statusesToHide); Set<String> roles = null; List<Integer> groups = null; List<String> casecodes = null; /* Checking for administrator or cases super administrator */ IWContext iwc = CoreUtil.getIWContext(); AccessController accessController = IWMainApplication.getDefaultIWMainApplication().getAccessController(); boolean isSuperAdmin = false; if (iwc == null) { isSuperAdmin = user == null ? false : user.equals(accessController.getAdministratorUser()) || accessController.hasRole(user, CasesConstants.ROLE_CASES_SUPER_ADMIN); } else isSuperAdmin = iwc.isSuperAdmin() || iwc.hasRole(CasesConstants.ROLE_CASES_SUPER_ADMIN); try { CasesListParameters params = new CasesListParameters(user, type, isSuperAdmin, statusesToHide, statusesToShow); params = resolveParameters(params, showAllCases); /* Getting roles for given user */ roles = params.getRoles(); if (ListUtil.isEmpty(roles) && user != null) { roles = getRoles(iwc == null ? getSession() : iwc.getSession(), accessController, user); } statusesToShow = showAllCases ? statusesToShow : ListUtil.isEmpty(caseStatusesToShow) ? params.getStatusesToShow() : caseStatusesToShow; statusesToHide = showAllCases ? statusesToHide : ListUtil.isEmpty(caseStatusesToHide) ? params.getStatusesToHide() : caseStatusesToHide; groups = params.getGroups(); casecodes = params.getCodes(); type = StringUtil.isEmpty(type) ? CasesRetrievalManager.CASE_LIST_TYPE_OPEN : type; /* Querying cache */ if (caseId == null) { caseIds = getCachedIds(user, type, caseCodes, statusesToHide, statusesToShow, onlySubscribedCases, roles, groups, casecodes, showAllCases, procInstIds, handlerCategoryIDs); if (caseIds.size() > 5) return caseIds; else { CasesCacheCriteria key = getCacheKey(user, type, caseCodes, statusesToHide, statusesToShow, onlySubscribedCases, roles, groups, casecodes, showAllCases, procInstIds, handlerCategoryIDs); getLogger().warning("Resolved only few cases IDs (" + caseIds + ") from cache by key '" + key + "', it is probably invalid cache entry, will delete it and will query DB"); removeFromCache(key); } } /* Re-subscribing if not subscribed before */ if (onlySubscribedCases && user != null) { try { Map<?, ?> beans = WebApplicationContextUtils.getWebApplicationContext(getApplication().getServletContext()) .getBeansOfType(CasesSubcriberManager.class); if (!MapUtil.isEmpty(beans)) { for (Object bean: beans.values()) { if (bean instanceof CasesSubcriberManager) ((CasesSubcriberManager) bean).doEnsureUserIsSubscribed(user); } } } catch (Exception e) { getLogger().log(Level.WARNING, "Error while ensuring user " + user + " is subscribed to cases", e); } } if (!ListUtil.isEmpty(procInstIds) && procInstIds.size() > 7500) procInstIds = Collections.emptyList(); /* Querying data source */ if (CasesRetrievalManager.CASE_LIST_TYPE_OPEN.equals(type)) { caseIds = isSuperAdmin ? getCasesBPMDAO().getOpenCasesIdsForAdmin(caseCodes, statusesToShow, statusesToHide, caseId, procInstIds, handlerCategoryIDs) : getCasesBPMDAO().getOpenCasesIds(user, caseCodes, statusesToShow, statusesToHide, groups, roles, onlySubscribedCases, caseId, procInstIds, handlerCategoryIDs); } else if (CasesRetrievalManager.CASE_LIST_TYPE_CLOSED.equals(type)) { caseIds = isSuperAdmin ? getCasesBPMDAO().getClosedCasesIdsForAdmin( statusesToShow, statusesToHide, caseId, procInstIds, handlerCategoryIDs) : getCasesBPMDAO().getClosedCasesIds(user, statusesToShow, statusesToHide, groups, roles, onlySubscribedCases, caseId, procInstIds, handlerCategoryIDs); } else if (CasesRetrievalManager.CASE_LIST_TYPE_MY.equals(type)) { caseIds = getCasesBPMDAO().getMyCasesIds(user, statusesToShow, statusesToHide, onlySubscribedCases, caseId, procInstIds, handlerCategoryIDs); } else if (CasesRetrievalManager.CASE_LIST_TYPE_USER.equals(type)) { caseIds = getCasesBPMDAO().getUserCasesIds(user, statusesToShow, statusesToHide, casecodes, roles, onlySubscribedCases, caseId, procInstIds, handlerCategoryIDs); } else if (CasesRetrievalManager.CASE_LIST_TYPE_PUBLIC.equals(type)) { caseIds = getCasesBPMDAO().getPublicCasesIds(statusesToShow, statusesToHide, caseCodes, caseId != null ? Arrays.asList(caseId) : null, procInstIds, handlerCategoryIDs); } else if (CasesRetrievalManager.CASE_LIST_TYPE_HANDLER.equals(type)) { caseIds = getCasesBPMDAO().getHandlerCasesIds(user, caseStatusesToShow, caseStatusesToHide, casecodes, caseId != null ? Arrays.asList(caseId) : null, procInstIds, handlerCategoryIDs); } else { getLogger().warning("Unknown cases list type: '" + type + "'"); } } catch (Exception e) { getLogger().log(Level.WARNING, "Error getting cases", e); throw new RuntimeException(e); } /* Putting to cache */ if (caseId == null) putIdsToCache(caseIds, user, type, caseCodes, statusesToHide, statusesToShow, onlySubscribedCases, roles, groups, casecodes, showAllCases, procInstIds, handlerCategoryIDs); return caseIds; } private CasesListParameters resolveParameters(CasesListParameters params, boolean showAllCases) throws Exception { User user = params.getUser(); String type = params.getType(); boolean isSuperAdmin = params.isSuperAdmin(); List<String> statusesToShow = params.getStatusesToShow(); List<String> statusesToHide = params.getStatusesToHide(); Set<String> roles = params.getRoles(); List<Integer> groups = params.getGroups(); List<String> codes = params.getCodes(); CasesBusiness casesBusiness = getServiceInstance(CasesBusiness.class); UserBusiness userBusiness = getServiceInstance(UserBusiness.class); AccessController accessController = IWMainApplication.getDefaultIWMainApplication().getAccessController(); if (CasesRetrievalManager.CASE_LIST_TYPE_OPEN.equals(type)) { String[] caseStatuses = casesBusiness.getStatusesForOpenCases(); if (!showAllCases) { statusesToShow.addAll(Arrays.asList(caseStatuses)); statusesToShow = ListUtil.getFilteredList(statusesToShow); statusesToHide.addAll(Arrays.asList(casesBusiness.getStatusesForClosedCases())); statusesToHide = ListUtil.getFilteredList(statusesToHide); } if (!isSuperAdmin) { roles = getRoles(getSession(), accessController, user); @SuppressWarnings("unchecked") Collection<GroupBMPBean> groupBeans = userBusiness.getUserGroupsDirectlyRelated(user); if (!ListUtil.isEmpty(groupBeans)) { groups = new ArrayList<Integer>(groupBeans.size()); for (GroupBMPBean group : groupBeans) { groups.add(new Integer(group.getPrimaryKey().toString())); } } } } else if (CasesRetrievalManager.CASE_LIST_TYPE_CLOSED.equals(type)) { String[] caseStatuses = casesBusiness.getStatusesForClosedCases(); if (!showAllCases) { statusesToShow.addAll(Arrays.asList(caseStatuses)); statusesToShow = ListUtil.getFilteredList(statusesToShow); } if (!isSuperAdmin) { if (user != null) { roles = getRoles(getSession(), accessController, user); } @SuppressWarnings("unchecked") Collection<GroupBMPBean> groupBeans = userBusiness.getUserGroupsDirectlyRelated(user); if (!ListUtil.isEmpty(groupBeans)) { groups = new ArrayList<Integer>(groupBeans.size()); for (GroupBMPBean group : groupBeans) { groups.add(new Integer(group.getPrimaryKey().toString())); } } } } else if (CasesRetrievalManager.CASE_LIST_TYPE_MY.equals(type)) { String[] caseStatuses = casesBusiness.getStatusesForMyCases(); if (!showAllCases) { statusesToShow.addAll(Arrays.asList(caseStatuses)); statusesToShow = ListUtil.getFilteredList(statusesToShow); } } else if (CasesRetrievalManager.CASE_LIST_TYPE_USER.equals(type)) { statusesToShow = showAllCases ? statusesToShow : ListUtil.getFilteredList(statusesToShow); CaseCode[] casecodes = getCaseBusiness().getCaseCodesForUserCasesList(); if (user != null) { roles = getRoles(getSession(), accessController, user); } codes = new ArrayList<String>(casecodes.length); for (CaseCode code : casecodes) { codes.add(code.getCode()); } } params.setCodes(codes); params.setGroups(groups); params.setRoles(roles); if (!showAllCases) { params.setStatusesToHide(statusesToHide); params.setStatusesToShow(statusesToShow); } return params; } @Override protected CaseBusiness getCaseBusiness() { try { return IBOLookup.getServiceInstance(IWMainApplication.getDefaultIWApplicationContext(), CasesBusiness.class); } catch (IBOLookupException ile) { throw new IBORuntimeException(ile); } } private CasesBusiness getCasesBusiness() { try { return (CasesBusiness) getCaseBusiness(); } catch (Exception e) { throw new IBORuntimeException(e); } } public CasesBPMDAO getCasesBPMDAO() { return casesBPMDAO; } public void setCasesBPMDAO(CasesBPMDAO casesBPMDAO) { this.casesBPMDAO = casesBPMDAO; } private final HashMap<String, String> uris = new HashMap<String, String>(2); protected synchronized String getPageUri(IWApplicationContext iwac, String pageType) { if (uris != null && uris.containsKey(pageType)) return uris.get(pageType); Collection<ICPage> icpages = getPages(pageType); if (icpages == null || icpages.isEmpty()) { // TODO: create egov bpm page, as not found throw new RuntimeException("No page found by page type: "+pageType); } ICPage icPage = null; if (icPage == null) icPage = icpages.iterator().next(); String uri = icPage.getDefaultPageURI(); if (!uri.startsWith(CoreConstants.PAGES_URI_PREFIX)) uri = CoreConstants.PAGES_URI_PREFIX + uri; String ruri = iwac.getIWMainApplication().getTranslatedURIWithContext(uri); uris.put(pageType, ruri); return ruri; } protected Collection<ICPage> getPages(String pageSubType) { try { ICPageHome home = (ICPageHome) IDOLookup.getHome(ICPage.class); return home.findBySubType(pageSubType, false); } catch (Exception e) { throw new RuntimeException("Exception while resolving pages by subType: "+pageSubType, e); } } public BPMContext getBpmContext() { return bpmContext; } public void setBpmContext(BPMContext bpmContext) { this.bpmContext = bpmContext; } public BPMFactory getBpmFactory() { return bpmFactory; } public void setBpmFactory(BPMFactory bpmFactory) { this.bpmFactory = bpmFactory; } @Override public Map<Long, String> getAllCaseProcessDefinitionsWithName() { List<ProcessDefinition> allProcesses = getAllProcessDefinitions(); if (ListUtil.isEmpty(allProcesses)) { return null; } Map<Long, String> processes = new HashMap<Long, String>(); Locale locale = null; IWContext iwc = CoreUtil.getIWContext(); if (iwc != null) { locale = iwc.getCurrentLocale(); } if (locale == null) { locale = Locale.ENGLISH; } ApplicationHome appHome = null; try { appHome = (ApplicationHome) IDOLookup.getHome(Application.class); } catch (IDOLookupException e) { e.printStackTrace(); } if (appHome == null) { return null; } String localizedName = null; for (ProcessDefinition pd: allProcesses) { localizedName = getProcessDefinitionLocalizedName(pd, locale, appHome); localizedName = StringUtil.isEmpty(localizedName) ? pd.getName() : localizedName; processes.put(Long.valueOf(pd.getId()), localizedName); } return processes; } @Override public List<Long> getAllCaseProcessDefinitions() { List<ProcessDefinition> allProcesses = getAllProcessDefinitions(); if (ListUtil.isEmpty(allProcesses)) { return null; } List<Long> ids = new ArrayList<Long>(); for (ProcessDefinition pd: allProcesses) { ids.add(Long.valueOf(pd.getId())); } return ids; } // TODO: use case type! private List<ProcessDefinition> getAllProcessDefinitions() { final List<CaseTypesProcDefBind> casesProcesses = getCasesBPMDAO().getAllCaseTypes(); if (ListUtil.isEmpty(casesProcesses)) return null; return getBpmContext().execute(new JbpmCallback() { @Override public Object doInJbpm(JbpmContext context) throws JbpmException { ProcessDefinition pd = null; List<ProcessDefinition> caseProcessDefinitions = new ArrayList<ProcessDefinition>(); GraphSession graphSession = context.getGraphSession(); for (CaseTypesProcDefBind caseTypesProcDefBind : casesProcesses) { pd = graphSession.findLatestProcessDefinition(caseTypesProcDefBind.getProcessDefinitionName()); if (pd != null && !caseProcessDefinitions.contains(pd)) { caseProcessDefinitions.add(pd); } } return caseProcessDefinitions; } }); } @Override public String getProcessName(String processName, Locale locale) { ProcessDefinition pd = getBpmFactory().getBPMDAO().findLatestProcessDefinition(processName); if (pd == null) { return null; } try { return getProcessDefinitionLocalizedName(pd, locale, (ApplicationHome) IDOLookup.getHome(Application.class)); } catch (IDOLookupException e) { e.printStackTrace(); } return null; } private String getProcessDefinitionLocalizedName(ProcessDefinition pd, Locale locale, ApplicationHome appHome) { if (pd == null || locale == null || appHome == null) { return null; } Collection<Application> apps = null; try { apps = appHome.findAllByApplicationUrl(pd.getName()); } catch (FinderException e) { e.printStackTrace(); } if (ListUtil.isEmpty(apps)) { Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "Didn't find any application by URL: " + pd.getName() + ", returning standard name!"); return pd.getName(); } ApplicationBusiness applicationBusiness = getServiceInstance(IWMainApplication.getDefaultIWApplicationContext(), ApplicationBusiness.class); if (applicationBusiness == null) { return pd.getName(); } return applicationBusiness.getApplicationName(apps.iterator().next(), locale); } @Override public Long getLatestProcessDefinitionIdByProcessName(String name) { ProcessDefinition pd = getBpmFactory().getBPMDAO().findLatestProcessDefinition(name); return pd == null ? null : pd.getId(); } @Override public PagedDataCollection<CasePresentation> getCasesByIds(List<Integer> ids, Locale locale) { Collection<Case> cases = getCasesBusiness().getCasesByIds(ids); return getCasesByEntities(cases, locale); } @Override public PagedDataCollection<CasePresentation> getCasesByEntities(Collection<Case> cases, Locale locale) { return new PagedDataCollection<CasePresentation>(convertToPresentationBeans(cases, locale), cases.size()); } @SuppressWarnings("unchecked") @Override public PagedDataCollection<CasePresentation> getClosedCases(Collection<Group> groups) { try { Collection<Case> closedCases = getCasesBusiness().getClosedCases(groups); List<CasePresentation> presentationBeans = convertToPresentationBeans(closedCases, CoreUtil.getIWContext().getCurrentLocale()); return new PagedDataCollection<CasePresentation>(presentationBeans); } catch (RemoteException e) { e.printStackTrace(); } return super.getClosedCases(groups); } @SuppressWarnings("unchecked") @Override public PagedDataCollection<CasePresentation> getMyCases(User user) { try { Collection<GeneralCase> closedCases = getCasesBusiness().getMyCases(user); List<CasePresentation> presentationBeans = convertToPresentationBeans(closedCases, CoreUtil.getIWContext().getCurrentLocale()); return new PagedDataCollection<CasePresentation>(presentationBeans); } catch (RemoteException re) { throw new IBORuntimeException(re); } } @Override protected CasePresentation convertToPresentation(Case theCase, CasePresentation bean, Locale locale) { if (bean == null) { bean = new CasePresentation(); } bean = super.convertToPresentation(theCase, bean, locale); bean.setBpm(caseHandlerType.equals(theCase.getCaseManagerType())); String caseIdentifier = theCase.getCaseIdentifier(); if (caseIdentifier == null) { caseIdentifier = getProcessIdentifier(theCase); } if (caseIdentifier == null) { caseIdentifier = theCase.getPrimaryKey().toString(); } bean.setCaseIdentifier(caseIdentifier); if (theCase instanceof GeneralCase) { GeneralCase generalCase = (GeneralCase) theCase; bean.setHandledBy(generalCase.getHandledBy()); bean.setPrivate(generalCase.isPrivate()); CaseCategory caseCategory = generalCase.getCaseCategory(); if (caseCategory != null) { if (ProcessBundleCasesImpl.defaultCaseCategoryName.equals(caseCategory.getName())) { String processName = getProcessDefinitionName(theCase); bean.setProcessName(processName); } bean.setCategoryId(caseCategory.getPrimaryKey().toString()); } try { bean.setCaseStatus(getCasesBusiness().getCaseStatus(theCase.getStatus())); } catch (RemoteException e) { bean.setCaseStatus(theCase.getCaseStatus()); } if (bean.getCaseStatus() != null) { bean.setLocalizedStatus(getLocalizedStatus(theCase, theCase.getCaseStatus(), locale)); } } return bean; } @Override public Long getTaskInstanceIdForTask(Case theCase, String taskName) { Long piId = getProcessInstanceId(theCase); if (piId == null) { return null; } ProcessInstanceW processInstance = getBpmFactory().getProcessManagerByProcessInstanceId(piId).getProcessInstance(piId); if (processInstance == null) { return null; } List<TaskInstanceW> tasks = processInstance.getAllUnfinishedTaskInstances(); if (ListUtil.isEmpty(tasks)) { return null; } for (TaskInstanceW task: tasks) { if (taskName.equals(task.getTaskInstance().getName())) { return task.getTaskInstanceId(); } } return null; } @Override public List<Long> getCasesIdsByProcessDefinitionName(String processDefinitionName) { return getCasesBPMDAO().getCaseIdsByProcessDefinition(processDefinitionName); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getCases(java.util.Collection, java.util.Collection, java.util.Collection, java.util.Collection) */ @Override public List<Case> getCases(Collection<String> processDefinitionNames, Collection<Long> processInstanceIds, Collection<String> caseStatuses, Collection<User> subscribers, Collection<String> caseManagerTypes, Date dateFrom, Date dateTo) { String[] primaryKeys = getCasesPrimaryKeys( processDefinitionNames, null, caseStatuses, subscribers, caseManagerTypes, dateFrom, dateTo); if (ArrayUtil.isEmpty(primaryKeys)) { return Collections.emptyList(); } ArrayList<Integer> ids = new ArrayList<Integer>(primaryKeys.length); for (String id : primaryKeys) { ids.add(Integer.valueOf(id)); } Collection<Case> casesCollection = getCasesBusiness().getCasesByIds(ids); if (ListUtil.isEmpty(casesCollection)) { return Collections.emptyList(); } return new ArrayList<Case>(casesCollection); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getCases(java.util.Collection, java.util.Collection, java.util.Collection) */ @Override public List<Case> getCases(Collection<String> processDefinitionNames, Collection<String> caseStatuses, Collection<User> subscribers) { return getCases(processDefinitionNames, null, caseStatuses, subscribers, null, null, null); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getCases(java.util.Collection, java.util.Collection) */ @Override public List<Case> getCases( Collection<String> processDefinitionNames, Collection<String> caseStatuses) { return getCases(processDefinitionNames, caseStatuses, null); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getCasesPrimaryKeys(java.util.Collection, java.util.Collection, java.util.Collection, java.util.Collection) */ @Override public String[] getCasesPrimaryKeys( Collection<String> processDefinitionNames, Collection<? extends Number> processInstanceIds, Collection<String> caseStatuses, Collection<User> subscribers, Collection<String> caseManagerTypes, Date dateCreatedFrom, Date dateCreatedTo) { List<Long> subscribersIds = null; /* Searching by subscribers */ if (!ListUtil.isEmpty(subscribers)) { subscribersIds = new ArrayList<Long>(subscribers.size()); for (User subscriber : subscribers) { subscribersIds.add(Long.valueOf(subscriber.getPrimaryKey().toString())); } } return getCasesBPMDAO().getCasesPrimaryKeys( processDefinitionNames, processInstanceIds, caseStatuses, null, subscribersIds, null, null, null, caseManagerTypes, null, null, null, null, null, null, null, null, dateCreatedFrom, dateCreatedTo); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getCasesPrimaryKeys(java.util.Collection, java.util.Collection, java.util.Collection) */ @Override public String[] getCasesPrimaryKeys( Collection<String> processDefinitionNames, Collection<String> caseStatuses, Collection<User> subscribers) { return getCasesPrimaryKeys(processDefinitionNames, null, caseStatuses, subscribers, null, null, null); } /* * (non-Javadoc) * @see is.idega.idegaweb.egov.bpm.cases.manager.BPMCasesRetrievalManager#getCasesPrimaryKeys(java.util.Collection, java.util.Collection) */ @Override public String[] getCasesPrimaryKeys( Collection<String> processDefinitionNames, Collection<String> caseStatuses) { return getCasesPrimaryKeys(processDefinitionNames, null, caseStatuses, null, null, null, null); } public VariablesHandler getVariablesHandler() { return variablesHandler; } public void setVariablesHandler(VariablesHandler variablesHandler) { this.variablesHandler = variablesHandler; } @Override public String resolveCaseId(IWContext iwc) { String caseId = super.resolveCaseId(iwc); if (!StringUtil.isEmpty(caseId)) return caseId; String processInstanceId = iwc.getParameter(ProcessManagerBind.processInstanceIdParam); if (StringUtil.isEmpty(processInstanceId)) return null; processInstanceId = StringHandler.replace(processInstanceId, CoreConstants.DOT, CoreConstants.EMPTY); processInstanceId = StringHandler.replace(processInstanceId, CoreConstants.SPACE, CoreConstants.EMPTY); try { Long piId = Long.valueOf(processInstanceId); return getCaseId(piId); } catch(NumberFormatException e) { getLogger().log(Level.WARNING, "Error converting process instance ID '" + processInstanceId + "' to Long"); } return null; } private String getCaseId(Long processInstanceId) { CaseProcInstBind bind = null; try { bind = getCasesBPMDAO().getCaseProcInstBindByProcessInstanceId(processInstanceId); } catch(Exception e) { e.printStackTrace(); } return bind == null ? null : bind.getCaseId().toString(); } @Override public User getCaseOwner(Object entityId) { String caseId = null; if (entityId instanceof Long) { caseId = getCaseId((Long) entityId); } return super.getCaseOwner(caseId == null ? entityId : caseId); } @Override public Collection<CasePresentation> getReLoadedCases(CasesSearchCriteriaBean criterias) { return getCasesEngine().getReLoadedCases(criterias); } public BPMCasesEngine getCasesEngine() { return casesEngine; } public void setCasesEngine(BPMCasesEngine casesEngine) { this.casesEngine = casesEngine; } private User getUser(Integer userId) { if (userId == null || userId < 0) return null; try { UserBusiness userBusiness = getServiceInstance(UserBusiness.class); return userBusiness.getUser(userId); } catch (Exception e) {} return null; } private boolean isCacheUpdateTurnedOn() { return getApplication().getSettings().getBoolean("update_cases_list_cache", Boolean.TRUE); } private void doManageCasesCache(final Case theCase, final boolean ommitClearing) { Thread cacheManager = new Thread(new Runnable() { @Override public void run() { try { if (!isCacheUpdateTurnedOn()) return; if (theCase == null) { getLogger().warning("Case is undefined, unable to manage cache"); return; } String theCaseId = theCase.getId(); Integer caseId = Integer.valueOf(theCaseId); for (CasesCacheCriteria criteria: getCacheKeySet()) { if (criteria == null) continue; if (ommitClearing && containsElement(criteria, caseId)) { // No need to execute SQL query to verify if case ID still belongs to the cache because it is forbidden to remove ID continue; } User user = getUser(criteria.getUserId()); boolean superAdmin = false; try { superAdmin = user == null ? false : IWMainApplication.getDefaultIWMainApplication().getAccessController().getAdministratorUser().equals(user); } catch (Exception e) { getLogger().log(Level.WARNING, "Error while resolving if user " + user + " is administrator"); } List<Integer> ids = null; if (!superAdmin) { try { ids = getCaseIds( user, criteria.getType(), criteria.getCaseCodes(), criteria.getStatusesToHide(), criteria.getStatusesToShow(), criteria.isOnlySubscribedCases(), criteria.isShowAllCases(), caseId, criteria.getProcInstIds(), null ); } catch (Exception e) { String caseInfo = "Case ID " + theCaseId + " (identifier: '" + theCase.getCaseIdentifier() + "', subject: '" + theCase.getSubject() + "', status: " + theCase.getCaseStatus() + ", created: " + theCase.getCreated() + ")"; String message = "Error while verifying if modified case " + caseInfo + " belongs to the cache by key " + criteria.getKey() + " and user " + user; LOGGER.log(Level.WARNING, message, e); clearCache(); return; } } boolean contains = superAdmin ? true : ListUtil.isEmpty(ids) ? false : ids.contains(caseId); if (contains) { addElementToCache(criteria, caseId); } else if (!ommitClearing) { removeElementFromCache(criteria, caseId); } } } catch (Exception e) { String message = "Error updating cases list after case was modified or created: " + theCase; getLogger().log(Level.WARNING, message, e); } } }); cacheManager.start(); } @Override public void onApplicationEvent(final ApplicationEvent event) { if (event instanceof CaseModifiedEvent) { Object source = event.getSource(); if (!(source instanceof Case)) return; if (!isCacheUpdateTurnedOn()) { try { clearCache(); } catch (Exception e) { getLogger().log(Level.WARNING, "Error clearing cases cache", e); } return; } Case theCase = (Case) source; doManageCasesCache(theCase, theCase == null || StringUtil.isEmpty(theCase.getSubject())); } else if (event instanceof ProcessInstanceCreatedEvent) { if (!isCacheUpdateTurnedOn()) { try { clearCache(); } catch (Exception e) { getLogger().log(Level.WARNING, "Error clearing cases cache", e); } return; } ProcessInstanceCreatedEvent procCreatedEvent = (ProcessInstanceCreatedEvent) event; Long piId = procCreatedEvent.getProcessInstanceId(); if (piId == null) return; CaseProcInstBind bind = null; try { bind = getCasesBPMDAO().getCaseProcInstBindByProcessInstanceId(piId); } catch (Exception e) {} if (bind == null) { getLogger().warning("Bind for process instance " + piId + " was not created yet!"); return; } Case theCase = null; try { theCase = getCaseBusiness().getCase(bind.getCaseId()); } catch (Exception e) {} if (theCase == null) { getLogger().warning("Case can not be found by ID " + bind.getCaseId() + " for process instance " + piId); return; } doManageCasesCache(theCase, true); } else if (event instanceof CaseDeletedEvent) { if (!isCacheUpdateTurnedOn()) { try { clearCache(); } catch (Exception e) { getLogger().log(Level.WARNING, "Error clearing cases cache", e); } return; } Object source = event.getSource(); if (!(source instanceof Case)) return; Case theCase = (Case) source; Integer id = Integer.valueOf(theCase.getId()); Collection<CasesCacheCriteria> keys = null; try { keys = getCacheKeySet(); } catch (Exception e) { getLogger().log(Level.WARNING, "Error getting criterias of cases cache", e); } if (!ListUtil.isEmpty(keys)) { for (CasesCacheCriteria key: keys) { try { removeElementFromCache(key, id); } catch (Exception e) { getLogger().log(Level.WARNING, "Error removing element '" + id + "' from cases cache by criteria " + key, e); } } } } } private class CasesListParameters { private User user; private String type; private boolean superAdmin; private List<String> statusesToHide; private List<String> statusesToShow; private Set<String> roles; private List<Integer> groups; private List<String> codes; private CasesListParameters(User user, String type, boolean superAdmin, List<String> statusesToHide, List<String> statusesToShow) { this.user = user; this.type = type; this.superAdmin = superAdmin; this.statusesToHide = statusesToHide; this.statusesToShow = statusesToShow; } public User getUser() { return user; } public String getType() { return type; } public boolean isSuperAdmin() { return superAdmin; } public List<String> getStatusesToHide() { return statusesToHide; } public void setStatusesToHide(List<String> statusesToHide) { this.statusesToHide = statusesToHide; } public List<String> getStatusesToShow() { return statusesToShow; } public void setStatusesToShow(List<String> statusesToShow) { this.statusesToShow = statusesToShow; } public Set<String> getRoles() { return roles; } public void setRoles(Set<String> roles) { this.roles = roles; } public List<Integer> getGroups() { return groups; } public void setGroups(List<Integer> groups) { this.groups = groups; } public List<String> getCodes() { return codes; } public void setCodes(List<String> codes) { this.codes = codes; } } protected Application getApplication(Object applicationID) { try { return getApplicationBusiness().getApplication(applicationID); } catch (RemoteException e) { getLogger().log(Level.WARNING, "Unable to connect to data source: ", e); } catch (FinderException e) { getLogger().log(Level.WARNING, "Unable to find " + Application.class + " by ID: " + applicationID); } return null; } protected ApplicationBusiness getApplicationBusiness() { if (this.applicationBusiness != null) { return this.applicationBusiness; } try { this.applicationBusiness = IBOLookup.getServiceInstance( getApplication().getIWApplicationContext(), ApplicationBusiness.class); } catch (IBOLookupException e) { getLogger().log(Level.WARNING, "Unable to get " + ApplicationBusiness.class + " cause of: ", e); } return this.applicationBusiness; } @Override public List<Case> getCases(Collection<ProcessInstanceW> processInstances) { if (ListUtil.isEmpty(processInstances)) { return Collections.emptyList(); } ArrayList<Long> piids = new ArrayList<Long>(); for (ProcessInstanceW processInstance: processInstances) { piids.add(processInstance.getProcessInstanceId()); } return getCases(null, piids, null, null, null, null, null); } }