package fi.otavanopisto.pyramus.dao.base; import java.util.List; import java.util.Set; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceException; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; 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.DAOFactory; import fi.otavanopisto.pyramus.dao.PyramusEntityDAO; import fi.otavanopisto.pyramus.domainmodel.base.BillingDetails; import fi.otavanopisto.pyramus.domainmodel.base.ContactInfo; import fi.otavanopisto.pyramus.domainmodel.base.School; import fi.otavanopisto.pyramus.domainmodel.base.SchoolField; import fi.otavanopisto.pyramus.domainmodel.base.SchoolVariable; import fi.otavanopisto.pyramus.domainmodel.base.SchoolVariableKey; import fi.otavanopisto.pyramus.domainmodel.base.SchoolVariable_; import fi.otavanopisto.pyramus.domainmodel.base.Tag; import fi.otavanopisto.pyramus.persistence.search.SearchResult; @Stateless public class SchoolDAO extends PyramusEntityDAO<School> { /** * Creates a new school. * * @param code * The school code * @param name * The school name * @param schoolField * @param billingDetails * * @return The created school */ public School create(String code, String name, SchoolField schoolField, BillingDetails billingDetails) { ContactInfo contactInfo = new ContactInfo(); School school = new School(); school.setCode(code); school.setName(name); school.setField(schoolField); school.setContactInfo(contactInfo); school.setBillingDetails(billingDetails); return persist(school); } /** * Returns a list of all schools having a school variable with the given key and value. * * @param key * The school variable key * @param value * The school variable value * * @return A list of all schools having a school variable with the given key and value */ public List<School> listByVariable(String key, String value) { SchoolVariableKeyDAO schoolVariableKeyDAO = DAOFactory.getInstance().getSchoolVariableKeyDAO(); SchoolVariableKey schoolVariableKey = schoolVariableKeyDAO.findVariableKey(key); EntityManager entityManager = getEntityManager(); CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<School> criteria = criteriaBuilder.createQuery(School.class); Root<SchoolVariable> root = criteria.from(SchoolVariable.class); criteria.select(root.get(SchoolVariable_.school)); criteria.where( criteriaBuilder.and( criteriaBuilder.equal(root.get(SchoolVariable_.key), schoolVariableKey), criteriaBuilder.equal(root.get(SchoolVariable_.value), value) )); return entityManager.createQuery(criteria).getResultList(); } @SuppressWarnings("unchecked") public SearchResult<School> searchSchoolsBasic(int resultsPerPage, int page, String text) { int firstResult = page * resultsPerPage; StringBuilder queryBuilder = new StringBuilder(); if (!StringUtils.isBlank(text)) { queryBuilder.append("+("); addTokenizedSearchCriteria(queryBuilder, "code", text, false); addTokenizedSearchCriteria(queryBuilder, "name", text, false); addTokenizedSearchCriteria(queryBuilder, "tags.text", text, false); queryBuilder.append(")"); } EntityManager entityManager = getEntityManager(); FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager); try { String queryString = queryBuilder.toString(); Query luceneQuery; QueryParser parser = new QueryParser("", new StandardAnalyzer()); if (StringUtils.isBlank(queryString)) { luceneQuery = new MatchAllDocsQuery(); } else { luceneQuery = parser.parse(queryString); } FullTextQuery query = (FullTextQuery) fullTextEntityManager.createFullTextQuery(luceneQuery, School.class) .setSort(new Sort(new SortField[] { SortField.FIELD_SCORE, new SortField("nameSortable", SortField.Type.STRING) })).setFirstResult(firstResult) .setMaxResults(resultsPerPage); query.enableFullTextFilter("ArchivedSchool").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); } } /** * Returns a list of schools matching the given search terms. * * @param resultsPerPage * The amount of schools per page * @param page * The search results page * @param code * The school code * @param name * The school name * @param tags * The schools tags * @param filterArchived * <code>true</code> if archived schools should be omitted, otherwise <code>false</code> * * @return A list of schools matching the given search terms */ @SuppressWarnings("unchecked") public SearchResult<School> searchSchools(int resultsPerPage, int page, String code, String name, String tags, boolean filterArchived) { int firstResult = page * resultsPerPage; StringBuilder queryBuilder = new StringBuilder(); if (!StringUtils.isBlank(code)) { addTokenizedSearchCriteria(queryBuilder, "code", code, false); } if (!StringUtils.isBlank(name)) { addTokenizedSearchCriteria(queryBuilder, "name", name, false); } if (!StringUtils.isBlank(tags)) { addTokenizedSearchCriteria(queryBuilder, "tags.text", tags, false); } EntityManager entityManager = getEntityManager(); FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager); try { String queryString = queryBuilder.toString(); Query luceneQuery; QueryParser parser = new QueryParser("", new StandardAnalyzer()); if (StringUtils.isBlank(queryString)) { luceneQuery = new MatchAllDocsQuery(); } else { luceneQuery = parser.parse(queryString); } FullTextQuery query = (FullTextQuery) fullTextEntityManager.createFullTextQuery(luceneQuery, School.class) .setSort(new Sort(new SortField[] { SortField.FIELD_SCORE, new SortField("nameSortable", SortField.Type.STRING) })).setFirstResult(firstResult) .setMaxResults(resultsPerPage); if (filterArchived) { query.enableFullTextFilter("ArchivedSchool").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); } } /** * Updates the given school with the given data. * * @param school * The school to be updated * @param code * The school code * @param name * The school name * @param schoolField * @return */ public School update(School school, String code, String name, SchoolField schoolField) { EntityManager entityManager = getEntityManager(); school.setCode(code); school.setName(name); school.setField(schoolField); entityManager.persist(school); return school; } public School updateTags(School school, Set<Tag> tags) { EntityManager entityManager = getEntityManager(); school.setTags(tags); entityManager.persist(school); return school; } public School updateBillingDetails(School school, BillingDetails billingDetails) { school.setBillingDetails(billingDetails); return persist(school); } public School addTag(School school, Tag tag) { school.addTag(tag); return persist(school); } public School removeTag(School school, Tag tag) { school.removeTag(tag); return persist(school); } }