package is.idega.idegaweb.egov.bpm.cases.search.impl; import is.idega.idegaweb.egov.bpm.cases.search.CasesListSearchCriteriaBean; import is.idega.idegaweb.egov.bpm.cases.search.CasesListSearchFilter; import is.idega.idegaweb.egov.cases.business.CasesBusiness; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import com.idega.block.process.data.Case; import com.idega.block.process.presentation.beans.CasesSearchCriteriaBean; import com.idega.core.business.DefaultSpringBean; import com.idega.idegaweb.egov.bpm.data.dao.CasesBPMDAO; import com.idega.jbpm.bean.BPMProcessVariable; import com.idega.jbpm.exe.BPMFactory; import com.idega.jbpm.identity.RolesManager; import com.idega.user.business.UserBusiness; import com.idega.util.ArrayUtil; import com.idega.util.CoreConstants; import com.idega.util.CoreUtil; import com.idega.util.IWTimestamp; import com.idega.util.ListUtil; import com.idega.util.expression.ELUtil; public abstract class DefaultCasesListSearchFilter extends DefaultSpringBean implements CasesListSearchFilter { public static final String SEARCH_FILTER_CACHE_NAME = "casesSearchFilterCacheName"; public static final Long SEARCH_FILTER_CACHE_TTL = Long.valueOf(1800); @Autowired private CasesBPMDAO casesBPMDAO; @Autowired private RolesManager rolesManager; @Autowired private BPMFactory bpmFactory; private CasesSearchCriteriaBean criterias; private long start; private long end; private boolean measure; public DefaultCasesListSearchFilter() { super(); } public DefaultCasesListSearchFilter(CasesSearchCriteriaBean criterias) { this(); this.criterias = criterias; } protected abstract String getFilterKey(); protected abstract List<Integer> getSearchResults(List<Integer> casesIds); protected abstract String getInfo(); protected abstract boolean isFilterKeyDefined(); private Map<String, List<Integer>> getCache() { return getCache(SEARCH_FILTER_CACHE_NAME, SEARCH_FILTER_CACHE_TTL); } protected CasesSearchCriteriaBean getCriterias() { return criterias; } private String getSearchKey() { if (criterias == null) { return null; } String filterKey = getFilterKey(); filterKey = filterKey == null ? CoreConstants.MINUS : filterKey; return filterKey.concat(CoreConstants.UNDER).concat(this.toString()); } private List<Integer> beforeFiltering() { String searchKey = getSearchKey(); if (searchKey == null) { return null; } Map<String, List<Integer>> cache = getCache(); if (cache == null) { return null; } List<Integer> cachedIds = cache.get(searchKey); return cachedIds; } protected void afterFiltering(String info, List<Integer> ids) { try { if (ids == null) { return; } String searchKey = getSearchKey(); if (searchKey == null) { return; } Map<String, List<Integer>> cache = getCache(); if (cache == null) { return; } cache.put(searchKey, ids); } finally { endFiltering(info); } } @Override public List<Integer> doFilter(List<Integer> casesIds) { List<Integer> cachedIds = beforeFiltering(); if (!ListUtil.isEmpty(cachedIds)) { return getNarrowedResults(casesIds, cachedIds); } if (ListUtil.isEmpty(casesIds)) { return casesIds; } if (!isFilterKeyDefined()) { return casesIds; } startFiltering(); List<Integer> filtered = getSearchResults(casesIds); if (ListUtil.isEmpty(filtered)) { return getNarrowedResults(casesIds, filtered); } else { afterFiltering(getInfo(), filtered); } filtered = getNarrowedResults(casesIds, filtered); return filtered; } private void endFiltering(String info) { if (!measure) { return; } end = System.currentTimeMillis(); getLogger().info("Query (" + info + ") executed in: " + (end - start) + " ms"); } private void startFiltering() { measure = CoreUtil.isSQLMeasurementOn(); if (measure) { start = System.currentTimeMillis(); } } protected CasesBPMDAO getCasesBPMDAO() { if (casesBPMDAO == null) ELUtil.getInstance().autowire(this); return casesBPMDAO; } public void setCasesBPMDAO(CasesBPMDAO casesBPMDAO) { this.casesBPMDAO = casesBPMDAO; } protected RolesManager getRolesManager() { if (rolesManager == null) ELUtil.getInstance().autowire(this); return rolesManager; } public void setRolesManager(RolesManager rolesManager) { this.rolesManager = rolesManager; } protected BPMFactory getBpmFactory() { if (bpmFactory == null) ELUtil.getInstance().autowire(this); return bpmFactory; } public void setBpmFactory(BPMFactory bpmFactory) { this.bpmFactory = bpmFactory; } public static List<Integer> getConvertedFromNumbers(List<? extends Number> values) { if (ListUtil.isEmpty(values)) { return null; } List<Integer> convertedValues = new ArrayList<Integer>(); for (Object o: values) { if (o instanceof Number) { convertedValues.add(((Number) o).intValue()); } else { getLogger(DefaultCasesListSearchFilter.class).warning("Object is not type of Number: " + o); } } return convertedValues; } public static List<Integer> getNarrowedResults(List<? extends Number> casesIds, List<? extends Number> filterResults) { if (ListUtil.isEmpty(casesIds)) { getLogger(DefaultCasesListSearchFilter.class).info("There are no start data, emptying IDs"); return null; } if (ListUtil.isEmpty(filterResults)) { getLogger(DefaultCasesListSearchFilter.class).info("No results found, emptying IDs"); return null; } List<Integer> tmp = getConvertedFromNumbers(casesIds); Integer id = null; List<Integer> filtered = new ArrayList<Integer>(); for (Object o: filterResults) { if (o instanceof Number) { id = ((Number) o).intValue(); if (tmp.contains(id)) { filtered.add(id); } } else { getLogger(DefaultCasesListSearchFilter.class).warning("ID is not type of Number: " + o); } } return filtered; } protected List<Integer> getUniqueIds(Collection<Integer> casesIDs) { if (ListUtil.isEmpty(casesIDs)) { return null; } List<Integer> ids = new ArrayList<Integer>(casesIDs.size()); for (Object id: casesIDs) { Integer realId = null; if (id instanceof Number) { realId = ((Number) id).intValue(); } else if (id != null) { try { realId = Integer.valueOf(id.toString()); } catch(Exception e) { e.printStackTrace(); } } if (realId != null && !ids.contains(realId)) { ids.add(realId); } } return ids; } protected List<Integer> getCasesIds(Collection<Case> cases) { if (ListUtil.isEmpty(cases)) { return null; } Integer id = null; List<Integer> ids = new ArrayList<Integer>(cases.size()); for (Case theCase: cases) { try { id = Integer.valueOf(theCase.getId()); } catch(NumberFormatException e) { e.printStackTrace(); } if (id != null && !ids.contains(id)) { ids.add(id); } } return ids; } protected CasesBusiness getCasesBusiness() { return getServiceInstance(CasesBusiness.class); } protected UserBusiness getUserBusiness() { return getServiceInstance(UserBusiness.class); } @Override public void setCriterias(CasesSearchCriteriaBean criterias) { this.criterias = criterias; } @Override public String toString() { return this.getClass().getCanonicalName(); } /** Getters from {@link CasesSearchCriteriaBean} **/ protected String getCaseNumber() { return criterias == null ? null : criterias.getCaseNumber(); } protected String getDescription() { return criterias == null ? null : criterias.getDescription(); } protected String getName() { return criterias == null ? null : criterias.getName(); } protected String getPersonalId() { return criterias == null ? null : criterias.getPersonalId(); } protected String[] getStatuses() { if (criterias == null || ArrayUtil.isEmpty(criterias.getStatuses())) return null; Map<String, Boolean> statuses = new HashMap<String, Boolean>(); for (String status: criterias.getStatuses()) { String[] statusKeys = status.split(CoreConstants.COMMA); if (ArrayUtil.isEmpty(statusKeys)) continue; for (String statusKey: statusKeys) statuses.put(statusKey, Boolean.TRUE); } return ArrayUtil.convertListToArray(statuses.keySet()); } protected IWTimestamp getDateFrom() { return criterias == null ? null : criterias.getDateFrom(); } protected IWTimestamp getDateTo() { return criterias == null ? null : criterias.getDateTo(); } protected String getDateRange() { return criterias == null ? null : criterias.getDateRange(); } protected String getContact() { return criterias == null ? null : criterias.getContact(); } protected String getCaseListType() { return criterias instanceof CasesListSearchCriteriaBean ? ((CasesListSearchCriteriaBean) criterias).getCaseListType() : null; } protected String getProcessId() { return criterias instanceof CasesListSearchCriteriaBean ? ((CasesListSearchCriteriaBean) criterias).getProcessId() : null; } protected List<BPMProcessVariable> getProcessVariables() { return criterias instanceof CasesListSearchCriteriaBean ? ((CasesListSearchCriteriaBean) criterias).getProcessVariables() : null; } }