package fi.arcusys.koku.common.service.impl; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.ejb.EJB; import javax.ejb.Stateless; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import fi.arcusys.koku.common.service.MessageFolderDAO; import fi.arcusys.koku.common.service.MessageRefDAO; import fi.arcusys.koku.common.service.datamodel.Folder; import fi.arcusys.koku.common.service.datamodel.FolderType; import fi.arcusys.koku.common.service.datamodel.Message; import fi.arcusys.koku.common.service.datamodel.MessageRef; import fi.arcusys.koku.common.service.datamodel.User; import fi.arcusys.koku.common.service.dto.Criteria; import fi.arcusys.koku.common.service.dto.MessageQuery; import fi.arcusys.koku.common.service.dto.OrderBy; /** * DAO implementation for CRUD operations with 'Folder' Entity * * @author Dmitry Kudinov (dmitry.kudinov@arcusys.fi) * May 18, 2011 */ @Stateless public class MessageFolderDAOImpl extends AbstractEntityDAOImpl<Folder> implements MessageFolderDAO { private static final Logger logger = LoggerFactory.getLogger(MessageFolderDAOImpl.class); @EJB private MessageRefDAO messageRefDao; public MessageFolderDAOImpl() { super(Folder.class); } /** * @param user * @param folderType * @return */ public Folder getFolderByUserAndType(final User user, final FolderType folderType) { return getSingleResultOrNull("findFolderByUserAndType", getCommonQueryParams(user, folderType)); } /** * @param user * @param folderType * @param message * @return */ public MessageRef storeMessage(final User user, final FolderType folderType, final Message message) { Folder folder = getFolderByUserAndType(user, folderType); if (folder == null) { folder = createNewFolderByUserAndType(user, folderType); } final MessageRef msgRef = new MessageRef(); msgRef.setFolder(folder); msgRef.setMessage(message); return messageRefDao.create(msgRef); } /** * @param user * @param folderType * @return */ @Override public List<MessageRef> getMessagesByUserAndFolderType(final User user, final FolderType folderType) { return getMessagesByUserWithRoleAndFolderType(user, Collections.<String>emptyList(), folderType, null, FIRST_RESULT_NUMBER, FIRST_RESULT_NUMBER + MAX_RESULTS_COUNT - 1); } /** * @param user * @param folderType * @return */ @Override public List<MessageRef> getMessagesByUserWithRoleAndFolderType(final User user, final List<String> roleUids, final FolderType folderType, final MessageQuery query, final int startNum, final int maxNum) { final Map<String, Object> params = getCommonQueryParams(user, roleUids, folderType); if (query == null || query.getCriteria() == null && query.getOrderBy() == null) { if (isEmpty(roleUids)) { return getResultList("findMessagesByUserAndFolderType", params, startNum, maxNum); } else { return getResultList("findMessagesByUserWithRoleAndFolderType", params, startNum, maxNum); } } else { /* * SELECT mr FROM MessageRef mr * WHERE mr.folder.folderType = :folderType AND mr.folder.user = :user * AND ((mr.message.subject LIKE '%test%' AND mr.message.subject LIKE '%sending%') OR * (mr.message.content LIKE '%test%' AND mr.message.content LIKE '%sending%') * ) * ORDER BY * */ final Criteria criteria = query.getCriteria(); final List<OrderBy> orderBys = query.getOrderBy(); final StringBuilder queryString = new StringBuilder("SELECT DISTINCT mr FROM MessageRef mr, IN(mr.message.receipients) to_ "); // build "where" string, put params final StringBuilder whereString = getWhereStringByCriteria(criteria, folderType, params, !isEmpty(roleUids)); // build "order by" string, put params final StringBuilder orderByString = new StringBuilder(); if (orderBys != null && !orderBys.isEmpty()) { orderByString.append(" ORDER BY "); for (final OrderBy orderBy : orderBys) { orderByString.append(getFieldNameForQuery(orderBy.getField(), folderType)).append(" ").append(orderBy.getType().name()).append(", "); } orderByString.setLength(orderByString.length() - 2); } queryString.append(whereString); queryString.append(orderByString); if (logger.isDebugEnabled()) { logger.debug("Execute search query: " + queryString); } return executeQuery(queryString.toString(), params, startNum, maxNum); } } private StringBuilder getWhereStringByCriteria(final Criteria criteria, final FolderType folderType, final Map<String, Object> params, final boolean withRoles) { final StringBuilder whereString = new StringBuilder("WHERE mr.folder.folderType = :folderType AND ").append( " (mr.folder.user = :user"); if (withRoles) { whereString.append(" OR mr.message.fromRoleUid in (:userRoles)"); } whereString.append(") "); if (criteria != null && criteria.getFields() != null && criteria.getKeywords() != null && !criteria.getFields().isEmpty() && !criteria.getKeywords().isEmpty()) { // escape JPQL symbols final List<String> keywords = new ArrayList<String>(); for (final String keyword : criteria.getKeywords()) { keywords.add(keyword.trim().replaceAll("'", "''")); } whereString.append(" AND ("); for (final MessageQuery.Fields field : criteria.getFields()) { whereString.append(" ("); for (int i = 0; i < keywords.size(); i++) { whereString.append(getFieldNameForQuery(field, folderType)).append(" LIKE :").append("keyword").append(i).append(" AND "); } // remove last 'AND ' in keywords concatenation whereString.setLength(whereString.length() - 4); whereString.append(") OR "); } // remove last 'OR ' in keywords concatenation whereString.setLength(whereString.length() - 3); whereString.append(")"); for (int i = 0; i < keywords.size(); i++) { params.put("keyword" + i, getPrefixAndSuffixLike(keywords.get(i))); } } return whereString; } private String getFieldNameForQuery(final MessageQuery.Fields field, final FolderType folderType) { final String fieldName; if (field == MessageQuery.Fields.Subject) { fieldName = "mr.message.subject"; } else if (field == MessageQuery.Fields.Content) { fieldName = "mr.message.text"; } else if (field == MessageQuery.Fields.CreatedDate) { fieldName = "mr.createdDate"; } else if (field == MessageQuery.Fields.Sender) { fieldName = "mr.message.fromUser.employeePortalName"; } else if (field == MessageQuery.Fields.Receiver) { fieldName = "to_.citizenPortalName"; } else { throw new IllegalArgumentException("Unsupported field: " + field); } return fieldName; } /** * @param user * @param folderType * @return */ public Folder createNewFolderByUserAndType(final User user, final FolderType folderType) { final Folder newFolder = new Folder(); newFolder.setFolderType(folderType); newFolder.setUser(user); return create(newFolder); } /** * @param userId * @param folderType * @return */ @Override public Long getTotalMessagesCountByUserAndRoles(final User user, final List<String> roleUids, final FolderType folderType) { final boolean withRoles = !isEmpty(roleUids); if (withRoles) { return getSingleResult("getTotalMessagesCountWithRole", getCommonQueryParams(user, roleUids, folderType)); } else { return getSingleResult("getTotalMessagesCount", getCommonQueryParams(user, roleUids, folderType)); } } @Override public Long getTotalMessagesCountByUserAndRoles(final User user, final List<String> roleUids, final FolderType folderType, final Criteria criteria) { final Map<String, Object> params = getCommonQueryParams(user, roleUids, folderType); final StringBuilder queryString = new StringBuilder("SELECT COUNT(DISTINCT mr) FROM MessageRef mr, IN (mr.message.receipients) to_ "); queryString.append(getWhereStringByCriteria(criteria, folderType, params, !isEmpty(roleUids))); return executeQueryWithSingleResult(queryString.toString(), params); } /** * @param userId * @param folderType * @return */ @Override public Long getUnreadMessagesCountByUserAndRoles(final User user, final List<String> roleUids, FolderType folderType) { final Map<String, Object> params = getCommonQueryParams(user, roleUids, folderType); params.put("isRead", Boolean.FALSE); final boolean withRoles = !isEmpty(roleUids); if (withRoles) { return getSingleResult("getMessagesCountByReadStatusWithRole", params); } else { return getSingleResult("getMessagesCountByReadStatus", params); } } private Map<String, Object> getCommonQueryParams(final User user, final FolderType folderType) { final Map<String, Object> params = new HashMap<String,Object>(); params.put("user", user); params.put("folderType", folderType); return params; } private Map<String, Object> getCommonQueryParams(final User user, final List<String> userRoles, final FolderType folderType) { final Map<String, Object> params = new HashMap<String,Object>(); params.put("user", user); params.put("folderType", folderType); if (!isEmpty(userRoles)) { params.put("userRoles", userRoles); } return params; } private boolean isEmpty(final List<String> userRoles) { return userRoles == null || userRoles.isEmpty(); } }