diff --git a/ccm-cms/pom.xml b/ccm-cms/pom.xml index 53e255c42..d0223b31b 100644 --- a/ccm-cms/pom.xml +++ b/ccm-cms/pom.xml @@ -65,6 +65,12 @@ provided + + org.hibernate + hibernate-search-orm + provided + + junit junit diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemSearchManager.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemSearchManager.java new file mode 100644 index 000000000..fb17ee755 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemSearchManager.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2016 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.contentsection; + +import org.apache.lucene.search.Query; +import org.hibernate.search.query.dsl.QueryBuilder; +import org.libreccm.search.SearchManager; + +import java.util.List; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; + +/** + * Provides search queries (using Hibernate Search and Lucene) for ContentItems. + * For details about the different search methods ({@code match}, {@code fuzzy} + * and {@code wildcard} please refer to chapter 5 of the + * Hibernate + * Search documentation. + * + * @author Jens Pelzetter + */ +@RequestScoped +public class ContentItemSearchManager { + + /** + * The fields in which the search engine looks for the provided term. + */ + private static final String[] FIELDS = {"id", + "uuid", + "displayName", + "title", + "description"}; + + @Inject + private SearchManager searchManager; + + /** + * Create and execute a {@code match} query. + * + * @param term The term(s) to search for. + * + * @return A list containing all results matching the query. + */ + @SuppressWarnings("unchecked") + public List searchItemMatch(final String term) { + final QueryBuilder queryBuilder = searchManager.createQueryBuilder( + ContentItem.class); + + final Query luceneQuery = queryBuilder + .keyword() + .onFields(FIELDS) + .matching(term) + .createQuery(); + + return (List) searchManager.executeQuery(luceneQuery); + } + + /** + * Create and execute a {@code fuzzy} query. + * + * @param term The term(s) to search for. + * + * @return A list containing all results matching the query. + */ + @SuppressWarnings("unchecked") + public List searchItemFuzzy(final String term) { + final QueryBuilder queryBuilder = searchManager.createQueryBuilder( + ContentItem.class); + + final Query luceneQuery = queryBuilder + .keyword() + .fuzzy() + .onFields(FIELDS) + .matching(term) + .createQuery(); + + return (List) searchManager.executeQuery(luceneQuery); + } + + /** + * Create and execute a {@code wildcard} query. + * + * @param term The term(s) to search for. + * + * @return A list containing all results matching the query. + */ + @SuppressWarnings("unchecked") + public List searchItemWildcard(final String term) { + final QueryBuilder queryBuilder = searchManager.createQueryBuilder( + ContentItem.class); + + final Query luceneQuery = queryBuilder + .keyword() + .wildcard() + .onFields(FIELDS) + .matching(term) + .createQuery(); + + return (List) searchManager.executeQuery(luceneQuery); + } + +} diff --git a/ccm-core/src/main/java/org/libreccm/search/SearchManager.java b/ccm-core/src/main/java/org/libreccm/search/SearchManager.java index 57703bafc..083f8af2a 100644 --- a/ccm-core/src/main/java/org/libreccm/search/SearchManager.java +++ b/ccm-core/src/main/java/org/libreccm/search/SearchManager.java @@ -38,44 +38,71 @@ import javax.persistence.EntityManager; import javax.transaction.Transactional; /** + * Provides an interface to Hibernate search. The methods here can be used to + * reduce the boilerplate code for writing Hibernate Search queries. * * @author Jens Pelzetter */ @ApplicationScoped public class SearchManager { - + @Inject private EntityManager entityManager; - + private FullTextEntityManager fullTextEntityManager; - - public SearchManager() { - - } - + + /** + * Initialises the class by creating a {@link FullTextEntityManager}. + */ @PostConstruct private void init() { fullTextEntityManager = Search.getFullTextEntityManager(entityManager); } - + + /** + * Rebuild the complete index. This methods requires {@code admin} + * privileges. + * + * @return A {@link Future} object for controlling/monitoring the index + * process. + */ @AuthorizationRequired @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN) public Future rebuildIndex() { final MassIndexer indexer = fullTextEntityManager.createIndexer(); return indexer.start(); } - + + /** + * Creates a {@link QueryBuilder} for the provided entity class. + * + * @param entityClass The entity class. + * + * @return A {@link QueryBuilder} which can be used to create a Hibernate + * Search/Lucene query for entities of the provided class. + */ public QueryBuilder createQueryBuilder(final Class entityClass) { - final SearchFactory searchFactory = fullTextEntityManager.getSearchFactory(); + final SearchFactory searchFactory = fullTextEntityManager + .getSearchFactory(); return searchFactory.buildQueryBuilder().forEntity(entityClass).get(); } - + + /** + * Executes a Hibernate Search/Lucene query. This method contains uses the + * {@link #fullTextEntityManager} to wrap the Lucene query into an + * Hibernate/JPA query. To avoid lazy loading issues this method is + * transactional. + * + * @param query The query to execute. + * + * @return A result list containing all entities matching the query. + */ @Transactional(Transactional.TxType.REQUIRED) public List executeQuery(final Query query) { final javax.persistence.Query jpaQuery = fullTextEntityManager .createFullTextQuery(query); - + return jpaQuery.getResultList(); } - + }