package is.idega.idegaweb.egov.bpm.cases.search.impl; import is.idega.idegaweb.egov.bpm.cases.actionhandlers.CaseHandlerAssignmentHandler; import is.idega.idegaweb.egov.cases.util.CasesConstants; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import org.jbpm.graph.def.ProcessDefinition; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import com.idega.block.process.business.CasesRetrievalManager; import com.idega.idegaweb.egov.bpm.data.dao.CasesBPMDAO; import com.idega.jbpm.bean.BPMProcessVariable; import com.idega.jbpm.bean.VariableInstanceInfo; import com.idega.jbpm.data.VariableInstanceQuerier; import com.idega.user.data.User; import com.idega.util.ArrayUtil; import com.idega.util.CoreConstants; import com.idega.util.ListUtil; import com.idega.util.StringUtil; import com.idega.util.expression.ELUtil; @Service @Scope(BeanDefinition.SCOPE_PROTOTYPE) public class ProcessesFilter extends DefaultCasesListSearchFilter { @Autowired private VariableInstanceQuerier variablesQuerier; @Autowired private CasesBPMDAO casesDAO; private String procDefName; @Override public List<Integer> getSearchResults(List<Integer> casesIds) { String processDefinitionId = getProcessId(); List<Integer> casesByProcessDefinition = null; if (CasesConstants.GENERAL_CASES_TYPE.equals(processDefinitionId)) { // Getting ONLY none "BPM" cases try { casesByProcessDefinition = getCasesBusiness().getFilteredProcesslessCasesIds(casesIds, CasesRetrievalManager.CASE_LIST_TYPE_USER.equals(getCaseListType())); } catch (Exception e) { getLogger().log(Level.WARNING, "Error getting non BPM cases", e); } } else { // Getting "BPM" cases casesByProcessDefinition = getCasesByProcessDefinition(processDefinitionId, getProcessVariables()); } if (ListUtil.isEmpty(casesByProcessDefinition)) { getLogger().warning("No cases found by process definition (ID: " + processDefinitionId + ", name: " + getProcessDefinitionName() + ") and variables (" + getProcessVariables() + ")"); } else { getLogger().info("Found " + casesByProcessDefinition.size() + " case(s) by process definition (ID: " + processDefinitionId + ", name: " + getProcessDefinitionName() + ") and variables (" + getProcessVariables() + "): " + (casesByProcessDefinition.size() >= 1000 ? casesByProcessDefinition.subList(0, 999) + " ..." : casesByProcessDefinition)); } return casesByProcessDefinition; } @Override protected String getInfo() { return "Looking for cases by process definition. ID: " + getProcessId() + ", name: " + getProcessDefinitionName() + " and BPM variables: " + getProcessVariables(); } private String getProcessDefinitionName() { return procDefName; } private List<Integer> getCasesByProcessDefinition(String processDefinitionId, List<BPMProcessVariable> vars) { if (StringUtil.isEmpty(processDefinitionId)) return null; ProcessDefinition processDefinition = null; try { Long procDefId = Long.valueOf(processDefinitionId); processDefinition = getBpmFactory().getProcessManager(procDefId).getProcessDefinition(procDefId).getProcessDefinition(); } catch (Exception e) { getLogger().log(Level.WARNING, "Error getting process definition by ID: " + processDefinitionId, e); } String procDefName = processDefinition == null ? null : processDefinition.getName(); if (StringUtil.isEmpty(procDefName)) return null; this.procDefName = procDefName; getLogger().info(getInfo()); List<BPMProcessVariable> variables = new ArrayList<BPMProcessVariable>(vars); Object tmp = null; BPMProcessVariable handlerVariable = null; List<BPMProcessVariable> varsToRemove = new ArrayList<BPMProcessVariable>(); Map<String, List<Serializable>> multValues = new HashMap<String, List<Serializable>>(); for (BPMProcessVariable variable: variables) { String name = variable.getName(); // Checking if variable is holding handler ID if (CaseHandlerAssignmentHandler.handlerUserIdVarName.equals(name) || CaseHandlerAssignmentHandler.performerUserIdVarName.equals(name)) { handlerVariable = variable; } else if ((tmp = variable.getRealValue()) instanceof Collection) { // Checking if value is multi-type Collection<?> newMultipleValues = (Collection<?>) tmp; List<Serializable> existingMultipleValues = multValues.get(name); if (existingMultipleValues == null) { existingMultipleValues = new ArrayList<Serializable>(); multValues.put(name, existingMultipleValues); } for (Object value: newMultipleValues) { if (value instanceof Serializable && !existingMultipleValues.contains(value)) { existingMultipleValues.add((Serializable) value); varsToRemove.add(variable); } } } } List<Integer> casesIdsByMultipleValues = null; if (!multValues.isEmpty()) { casesIdsByMultipleValues = getConvertedFromNumbers(getCasesIdsByMultipleVariableValues(procDefName, multValues)); if (ListUtil.isEmpty(casesIdsByMultipleValues)) return null; getLogger().info("Found cases by multiple variables: " + multValues + " and process definition: " + procDefName + ": " + casesIdsByMultipleValues); } if (handlerVariable != null) { List<Integer> casesIdsByHandlers = getCaseIdsByHandlers(handlerVariable.getName(), handlerVariable.getValue(), procDefName); if (ListUtil.isEmpty(casesIdsByHandlers)) return null; getLogger().info("Found cases by handler: " + handlerVariable + " and process definition: " + procDefName + ": " + casesIdsByHandlers); if (casesIdsByMultipleValues == null) { // Just handler variable was specified casesIdsByMultipleValues = new ArrayList<Integer>(casesIdsByHandlers); } else { // Keeping condition AND casesIdsByMultipleValues = getNarrowedResults(casesIdsByMultipleValues, casesIdsByHandlers); if (ListUtil.isEmpty(casesIdsByMultipleValues)) return null; } variables.remove(handlerVariable); } if (!ListUtil.isEmpty(varsToRemove)) variables.removeAll(varsToRemove); List<Integer> casesIds = null; try { List<Integer> casesIdsByOtherVars = getConvertedFromNumbers(getCasesBPMDAO().getCaseIdsByProcessDefinitionNameAndVariables(procDefName, variables)); casesIds = ListUtil.isEmpty(casesIdsByMultipleValues) ? casesIdsByOtherVars : getNarrowedResults(casesIdsByMultipleValues, casesIdsByOtherVars); } catch(Exception e) { getLogger().log(Level.SEVERE, "Exception while resolving cases ids by process definition id and process name. Process definition id = "+ processDefinitionId + ", variables: " + variables, e); } return casesIds; } private List<Long> getCasesIdsByMultipleVariableValues(String processDefinitionName, Map<String, List<Serializable>> multipleValues) { List<String> procDefNames = Arrays.asList(processDefinitionName); List<Long> procInstIds = new ArrayList<Long>(); for (String variableName: multipleValues.keySet()) { Collection<VariableInstanceInfo> vars = getVariablesQuerier().getProcessVariablesByNameAndValue(variableName, multipleValues.get(variableName), procDefNames); procInstIds = getProcInstIdsFromVars(vars, procInstIds); } return getCasesBPMDAO().getCaseIdsByProcessInstanceIds(procInstIds); } private List<Long> getProcInstIdsFromVars(Collection<VariableInstanceInfo> vars, List<Long> ids) { if (ListUtil.isEmpty(vars)) return null; ids = ids == null ? new ArrayList<Long>() : ids; for (VariableInstanceInfo var: vars) { Long procInstId = var.getProcessInstanceId(); if (procInstId == null) continue; if (!ids.contains(procInstId)) ids.add(procInstId); } return ids; } private List<Integer> getCaseIdsByHandlers(String varName, String handlers, String procDefName) { if (StringUtil.isEmpty(handlers)) return null; String[] ids = handlers.split(CoreConstants.SEMICOLON); if (ArrayUtil.isEmpty(ids)) return null; List<Integer> usersIds = new ArrayList<Integer>(); for (String id: ids) { Integer handlerId = null; try { handlerId = Integer.valueOf(id); } catch (NumberFormatException e) { Collection<User> users = getUserBusiness().getUsersByNameOrEmailOrPhone(id); if (!ListUtil.isEmpty(users)) { for (User user: users) { usersIds.add(Integer.valueOf(user.getId())); } } handlerId = null; } if (handlerId != null) usersIds.add(handlerId); } return getCasesDAO().getCasesIdsByHandlersAndProcessDefinition(usersIds, procDefName); } @Override protected String getFilterKey() { return new StringBuilder().append(getProcessId()).append(getProcessVariables()).toString(); } @Override protected boolean isFilterKeyDefined() { String processDefinitionId = getProcessId(); if (StringUtil.isEmpty(processDefinitionId)) { getLogger().info("Process is not defined, not filtering by it!"); return false; } return true; } VariableInstanceQuerier getVariablesQuerier() { if (variablesQuerier == null) ELUtil.getInstance().autowire(this); return variablesQuerier; } CasesBPMDAO getCasesDAO() { if (casesDAO == null) ELUtil.getInstance().autowire(this); return casesDAO; } }