package fi.otavanopisto.muikku.plugins.announcer.dao; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.stream.Collectors; import javax.persistence.EntityManager; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.persistence.criteria.Subquery; import org.apache.commons.collections.CollectionUtils; import fi.otavanopisto.muikku.model.users.UserEntity; import fi.otavanopisto.muikku.model.users.UserGroupEntity; import fi.otavanopisto.muikku.model.workspace.WorkspaceEntity; import fi.otavanopisto.muikku.plugins.CorePluginsDAO; import fi.otavanopisto.muikku.plugins.announcer.model.Announcement; import fi.otavanopisto.muikku.plugins.announcer.model.AnnouncementUserGroup; import fi.otavanopisto.muikku.plugins.announcer.model.AnnouncementUserGroup_; import fi.otavanopisto.muikku.plugins.announcer.model.Announcement_; import fi.otavanopisto.muikku.plugins.announcer.workspace.model.AnnouncementWorkspace; import fi.otavanopisto.muikku.plugins.announcer.workspace.model.AnnouncementWorkspace_; public class AnnouncementDAO extends CorePluginsDAO<Announcement> { private static final long serialVersionUID = -8721990589622544635L; public Announcement create(Long publisherUserEntityId, String caption, String content, Date created, Date startDate, Date endDate, Boolean archived, Boolean publiclyVisible) { Announcement announcement = new Announcement(); announcement.setPublisherUserEntityId(publisherUserEntityId); announcement.setCaption(caption); announcement.setContent(content); announcement.setCreated(created); announcement.setStartDate(startDate); announcement.setEndDate(endDate); announcement.setArchived(archived); announcement.setPubliclyVisible(publiclyVisible); return persist(announcement); } public List<Announcement> listAnnouncements(List<UserGroupEntity> userGroupEntities, List<WorkspaceEntity> workspaceEntities, AnnouncementEnvironmentRestriction environment, AnnouncementTimeFrame timeFrame, boolean archived) { return listAnnouncements(userGroupEntities, workspaceEntities, environment, timeFrame, null, archived); } public List<Announcement> listAnnouncements( List<UserGroupEntity> userGroupEntities, List<WorkspaceEntity> workspaceEntities, AnnouncementEnvironmentRestriction environment, AnnouncementTimeFrame timeFrame, UserEntity announcementOwner, boolean archived) { EntityManager entityManager = getEntityManager(); Date currentDate = onlyDateFields(new Date()); CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<Announcement> criteria = criteriaBuilder.createQuery(Announcement.class); Root<Announcement> root = criteria.from(Announcement.class); criteria.select(root).distinct(true); List<Predicate> predicates = new ArrayList<Predicate>(); predicates.add(criteriaBuilder.equal(root.get(Announcement_.archived), archived)); switch (timeFrame) { case ALL: // No restrictions here break; case CURRENTANDUPCOMING: predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(Announcement_.endDate), currentDate)); break; case CURRENTANDEXPIRED: predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(Announcement_.startDate), currentDate)); break; case CURRENT: predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(Announcement_.startDate), currentDate)); predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get(Announcement_.endDate), currentDate)); break; case UPCOMING: predicates.add(criteriaBuilder.greaterThan(root.get(Announcement_.startDate), currentDate)); break; case EXPIRED: predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get(Announcement_.endDate), currentDate)); break; } if (announcementOwner != null) { predicates.add(criteriaBuilder.equal(root.get(Announcement_.publisherUserEntityId), announcementOwner.getId())); } // Predicates for group visibility restrictions (workspace, usergroup or environment) List<Predicate> groupPredicates = new ArrayList<Predicate>(); /** * Environment announcements: * - All announcements which are not tied to a workspace * - Publicly visible and/or group (when requested) */ switch (environment) { case NONE: // No environment announcements added break; case PUBLIC: groupPredicates.add( criteriaBuilder.and( criteriaBuilder.not(criteriaBuilder.in(root).value(subqueryWorkspaceAnnouncements(criteriaBuilder, criteria))), criteriaBuilder.equal(root.get(Announcement_.publiclyVisible), Boolean.TRUE) ) ); break; case PUBLICANDGROUP: groupPredicates.add( criteriaBuilder.not(criteriaBuilder.in(root).value(subqueryWorkspaceAnnouncements(criteriaBuilder, criteria))) ); break; } /** * Workspace announcements: * - All announcements tied to specified workspace(s) */ if (CollectionUtils.isNotEmpty(workspaceEntities)) { List<Long> workspaceEntityIds = workspaceEntities.stream().map((WorkspaceEntity workspaceEntity) -> workspaceEntity.getId()).collect(Collectors.toList()); Subquery<Announcement> subquery = criteria.subquery(Announcement.class); Root<AnnouncementWorkspace> announcementWorkspace = subquery.from(AnnouncementWorkspace.class); subquery.select(announcementWorkspace.get(AnnouncementWorkspace_.announcement)); subquery.where( criteriaBuilder.and( criteriaBuilder.equal(announcementWorkspace.get(AnnouncementWorkspace_.archived), Boolean.FALSE), announcementWorkspace.get(AnnouncementWorkspace_.workspaceEntityId).in(workspaceEntityIds) )); groupPredicates.add(root.in(subquery)); } /** * User group announcements: * - Environment announcements that are tied to user group. */ if (CollectionUtils.isNotEmpty(userGroupEntities)) { List<Long> userGroupEntityIds = userGroupEntities.stream().map((UserGroupEntity userGroupEntity) -> userGroupEntity.getId()).collect(Collectors.toList()); Subquery<Announcement> subquery = criteria.subquery(Announcement.class); Root<AnnouncementUserGroup> announcementUserGroup = subquery.from(AnnouncementUserGroup.class); subquery.select(announcementUserGroup.get(AnnouncementUserGroup_.announcement)); subquery.where( criteriaBuilder.and( criteriaBuilder.equal(announcementUserGroup.get(AnnouncementUserGroup_.archived), Boolean.FALSE), announcementUserGroup.get(AnnouncementUserGroup_.userGroupEntityId).in(userGroupEntityIds) )); groupPredicates.add(root.in(subquery)); } predicates.add(criteriaBuilder.or(groupPredicates.toArray(new Predicate[0]))); criteria.where(criteriaBuilder.and(predicates.toArray(new Predicate[0]))); criteria.orderBy(criteriaBuilder.desc(root.get(Announcement_.startDate))); return entityManager.createQuery(criteria).getResultList(); } public Announcement updateCaption(Announcement announcement, String caption) { announcement.setCaption(caption); return persist(announcement); } public Announcement updateContent(Announcement announcement, String content) { announcement.setContent(content); return persist(announcement); } public Announcement updateStartDate(Announcement announcement, Date startDate) { announcement.setStartDate(startDate); return persist(announcement); } public Announcement updateEndDate(Announcement announcement, Date endDate) { announcement.setEndDate(endDate); return persist(announcement); } public Announcement updatePubliclyVisible(Announcement announcement, Boolean publiclyVisible) { announcement.setPubliclyVisible(publiclyVisible); return persist(announcement); } public Announcement updateArchived(Announcement announcement, Boolean archived) { announcement.setArchived(archived); return persist(announcement); } public void delete(Announcement announcement) { super.delete(announcement); } private Subquery<Announcement> subqueryWorkspaceAnnouncements(CriteriaBuilder criteriaBuilder, CriteriaQuery<Announcement> criteria) { Subquery<Announcement> subquery = criteria.subquery(Announcement.class); Root<AnnouncementWorkspace> announcementWorkspaces = subquery.from(AnnouncementWorkspace.class); subquery.select(announcementWorkspaces.get(AnnouncementWorkspace_.announcement)); subquery.where(criteriaBuilder.equal(announcementWorkspaces.get(AnnouncementWorkspace_.archived), Boolean.FALSE)); return subquery; } private Date onlyDateFields(Date currentDate) { Calendar cal = Calendar.getInstance(); cal.setTime(currentDate); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); currentDate = cal.getTime(); return currentDate; } }