package fi.otavanopisto.pyramus.dao.students; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Set; import javax.ejb.Stateless; import javax.enterprise.event.Event; import javax.inject.Inject; import javax.persistence.EntityManager; import javax.persistence.PersistenceException; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Join; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import org.apache.commons.lang.StringUtils; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.Sort; import org.apache.lucene.search.SortField; import org.hibernate.search.jpa.FullTextEntityManager; import org.hibernate.search.jpa.FullTextQuery; import org.hibernate.search.jpa.Search; import fi.otavanopisto.pyramus.dao.PyramusEntityDAO; import fi.otavanopisto.pyramus.domainmodel.base.Tag; import fi.otavanopisto.pyramus.domainmodel.students.Student; import fi.otavanopisto.pyramus.domainmodel.students.StudentGroup; import fi.otavanopisto.pyramus.domainmodel.students.StudentGroupStudent; import fi.otavanopisto.pyramus.domainmodel.students.StudentGroupStudent_; import fi.otavanopisto.pyramus.domainmodel.students.StudentGroupUser; import fi.otavanopisto.pyramus.domainmodel.students.StudentGroupUser_; import fi.otavanopisto.pyramus.domainmodel.students.StudentGroup_; import fi.otavanopisto.pyramus.domainmodel.users.StaffMember; import fi.otavanopisto.pyramus.domainmodel.users.User; import fi.otavanopisto.pyramus.events.StudentGroupCreatedEvent; import fi.otavanopisto.pyramus.events.StudentGroupUpdatedEvent; import fi.otavanopisto.pyramus.persistence.search.SearchResult; @Stateless public class StudentGroupDAO extends PyramusEntityDAO<StudentGroup> { @Inject private Event<StudentGroupCreatedEvent> studentGroupCreatedEvent; @Inject private Event<StudentGroupUpdatedEvent> studentGroupUpdatedEvent; // @Inject // private Event<StudentGroupArchivedEvent> studentGroupRemovedEvent; public StudentGroup create(String name, String description, Date beginDate, User creatingUser, Boolean guidanceGroup) { EntityManager entityManager = getEntityManager(); Date now = new Date(System.currentTimeMillis()); StudentGroup studentGroup = new StudentGroup(); studentGroup.setName(name); studentGroup.setDescription(description); studentGroup.setBeginDate(beginDate); studentGroup.setCreator(creatingUser); studentGroup.setCreated(now); studentGroup.setLastModifier(creatingUser); studentGroup.setLastModified(now); studentGroup.setGuidanceGroup(guidanceGroup); entityManager.persist(studentGroup); studentGroupCreatedEvent.fire(new StudentGroupCreatedEvent(studentGroup.getId())); return studentGroup; } public StudentGroup setStudentGroupTags(StudentGroup studentGroup, Set<Tag> tags) { EntityManager entityManager = getEntityManager(); studentGroup.setTags(tags); entityManager.persist(studentGroup); // TODO: atm tag setting is done in conjunction with update so this would result in double messaging so it's disabled atm // studentGroupUpdatedEvent.fire(new StudentGroupUpdatedEvent(studentGroup.getId())); return studentGroup; } public StudentGroup update(StudentGroup studentGroup, String name, String description, Date beginDate, User updatingUser) { EntityManager entityManager = getEntityManager(); studentGroup.setName(name); studentGroup.setDescription(description); studentGroup.setBeginDate(beginDate); studentGroup.setLastModified(new Date(System.currentTimeMillis())); studentGroup.setLastModifier(updatingUser); entityManager.persist(studentGroup); studentGroupUpdatedEvent.fire(new StudentGroupUpdatedEvent(studentGroup.getId())); return studentGroup; } public List<StudentGroup> listByStudent(Student student) { return listByStudent(student, null, null, null); } public List<StudentGroup> listByStudent(Student student, Integer firstResult, Integer maxResults, Boolean archived) { EntityManager entityManager = getEntityManager(); CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<StudentGroup> criteria = criteriaBuilder.createQuery(StudentGroup.class); Root<StudentGroupStudent> root = criteria.from(StudentGroupStudent.class); Join<StudentGroupStudent, StudentGroup> studentGroup = root.join(StudentGroupStudent_.studentGroup); List<Predicate> predicates = new ArrayList<Predicate>(); predicates.add(criteriaBuilder.equal(root.get(StudentGroupStudent_.student), student)); if (archived != null) predicates.add(criteriaBuilder.equal(studentGroup.get(StudentGroup_.archived), archived)); criteria.select(root.get(StudentGroupStudent_.studentGroup)); criteria.where(criteriaBuilder.and(predicates.toArray(new Predicate[0]))); TypedQuery<StudentGroup> query = entityManager.createQuery(criteria); if (firstResult != null) { query.setFirstResult(firstResult); } if (maxResults != null) { query.setMaxResults(maxResults); } return query.getResultList(); } @SuppressWarnings("unchecked") public SearchResult<StudentGroup> searchStudentGroups(int resultsPerPage, int page, String name, String tags, String description, User user, Date timeframeStart, Date timeframeEnd, boolean filterArchived) { int firstResult = page * resultsPerPage; String timeframeS = null; if (timeframeStart != null) timeframeS = getSearchFormattedDate(timeframeStart); String timeframeE = null; if (timeframeEnd != null) timeframeE = getSearchFormattedDate(timeframeEnd); StringBuilder queryBuilder = new StringBuilder(); if (!StringUtils.isBlank(name)) { addTokenizedSearchCriteria(queryBuilder, "name", name, true); } if (!StringUtils.isBlank(tags)) { addTokenizedSearchCriteria(queryBuilder, "tags.text", tags, true); } if (!StringUtils.isBlank(description)) { addTokenizedSearchCriteria(queryBuilder, "description", description, true); } if (user != null) { addTokenizedSearchCriteria(queryBuilder, "users.staffMember.id", user.getId().toString(), true); } if (timeframeS != null && timeframeE != null) { /** * (beginDate between timeframeStart - timeframeEnd or endDate between timeframeStart - * timeframeEnd) or (startDate less than timeframeStart and endDate more than * timeframeEnd) **/ queryBuilder.append(" +(").append("(").append("beginDate:[").append(timeframeS).append(" TO ").append( timeframeE).append("]").append(")").append(")"); } else if (timeframeS != null) { /** beginDate > timeframeStart **/ queryBuilder.append(" +(").append("beginDate:[").append(timeframeS).append(" TO ").append( getSearchDateInfinityHigh()).append("]").append(")"); } else if (timeframeE != null) { /** beginDate < timeframeEnd **/ queryBuilder.append(" +(").append("beginDate:[").append(getSearchDateInfinityLow()).append(" TO ").append( timeframeE).append("]").append(")"); } EntityManager entityManager = getEntityManager(); FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager); try { QueryParser parser = new QueryParser("", new StandardAnalyzer()); String queryString = queryBuilder.toString(); Query luceneQuery; if (StringUtils.isBlank(queryString)) { luceneQuery = new MatchAllDocsQuery(); } else { luceneQuery = parser.parse(queryString); } FullTextQuery query = (FullTextQuery) fullTextEntityManager.createFullTextQuery(luceneQuery, StudentGroup.class) .setSort(new Sort(new SortField[]{SortField.FIELD_SCORE, new SortField("nameSortable", SortField.Type.STRING)})) .setFirstResult(firstResult) .setMaxResults(resultsPerPage); if (filterArchived) query.enableFullTextFilter("ArchivedStudentGroup").setParameter("archived", Boolean.FALSE); int hits = query.getResultSize(); int pages = hits / resultsPerPage; if (hits % resultsPerPage > 0) pages++; int lastResult = Math.min(firstResult + resultsPerPage, hits) - 1; return new SearchResult<>(page, pages, hits, firstResult, lastResult, query.getResultList()); } catch (ParseException e) { throw new PersistenceException(e); } } @SuppressWarnings("unchecked") public SearchResult<StudentGroup> searchStudentGroupsBasic(int resultsPerPage, int page, String text) { int firstResult = page * resultsPerPage; StringBuilder queryBuilder = new StringBuilder(); if (!StringUtils.isBlank(text)) { queryBuilder.append("+("); addTokenizedSearchCriteria(queryBuilder, "name", text, false); addTokenizedSearchCriteria(queryBuilder, "tags.text", text, false); addTokenizedSearchCriteria(queryBuilder, "description", text, false); queryBuilder.append(")"); } EntityManager entityManager = getEntityManager(); FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager); try { QueryParser parser = new QueryParser("", new StandardAnalyzer()); String queryString = queryBuilder.toString(); Query luceneQuery; if (StringUtils.isBlank(queryString)) { luceneQuery = new MatchAllDocsQuery(); } else { luceneQuery = parser.parse(queryString); } FullTextQuery query = (FullTextQuery) fullTextEntityManager.createFullTextQuery(luceneQuery, StudentGroup.class) .setSort(new Sort(new SortField[] { SortField.FIELD_SCORE, new SortField("nameSortable", SortField.Type.STRING)})) .setFirstResult(firstResult) .setMaxResults(resultsPerPage); query.enableFullTextFilter("ArchivedStudentGroup").setParameter("archived", Boolean.FALSE); int hits = query.getResultSize(); int pages = hits / resultsPerPage; if (hits % resultsPerPage > 0) { pages++; } int lastResult = Math.min(firstResult + resultsPerPage, hits) - 1; return new SearchResult<>(page, pages, hits, firstResult, lastResult, query.getResultList()); } catch (ParseException e) { throw new PersistenceException(e); } } public StudentGroup updateGuidanceGroup(StudentGroup studentGroup, Boolean guidanceGroup) { studentGroup.setGuidanceGroup(guidanceGroup); return persist(studentGroup); } public List<StudentGroup> listByStaffMember(StaffMember staffMember, Integer firstResult, Integer maxResults, Boolean archived) { EntityManager entityManager = getEntityManager(); CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<StudentGroup> criteria = criteriaBuilder.createQuery(StudentGroup.class); Root<StudentGroupUser> root = criteria.from(StudentGroupUser.class); Join<StudentGroupUser, StudentGroup> studentGroup = root.join(StudentGroupUser_.studentGroup); List<Predicate> predicates = new ArrayList<Predicate>(); predicates.add(criteriaBuilder.equal(root.get(StudentGroupUser_.staffMember), staffMember)); if (archived != null) predicates.add(criteriaBuilder.equal(studentGroup.get(StudentGroup_.archived), archived)); criteria.select(root.get(StudentGroupUser_.studentGroup)); criteria.where(criteriaBuilder.and(predicates.toArray(new Predicate[0]))); TypedQuery<StudentGroup> query = entityManager.createQuery(criteria); if (firstResult != null) { query.setFirstResult(firstResult); } if (maxResults != null) { query.setMaxResults(maxResults); } return query.getResultList(); } }