package nl.gertontenham.magnolia.templating.search; import info.magnolia.cms.util.QueryUtil; import info.magnolia.jcr.util.PropertyUtil; import info.magnolia.jcr.wrapper.I18nNodeWrapper; import info.magnolia.repository.RepositoryConstants; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.RepositoryException; import javax.jcr.query.Query; import java.util.ArrayList; import java.util.List; /** * Created by gtenham on 2015-04-17. */ public class JcrSearchService implements SearchService { private static final Logger log = LoggerFactory.getLogger(JcrSearchService.class); private static final String RETURN_ITEM_TYPE = "mgnl:page"; private List<Node> allResults; private List<SearchEntry> allJcrResults; @Override public SearchResult search(String query, int pageNumber, int maxResultsPerPage) { SearchResult searchResult = new SearchResult(); try { allResults = executeQuery(query, RepositoryConstants.WEBSITE, RETURN_ITEM_TYPE); allJcrResults = getQueryResultItems(allResults); searchResult.setTotalCount(allResults.size()); searchResult.setNumPages(getNumberOfPages( allResults.size(), maxResultsPerPage) ); searchResult.setResults(getPagedResults(allJcrResults, pageNumber, maxResultsPerPage)); } catch (RepositoryException e) { e.printStackTrace(); } return searchResult; } /** * Execute JCR query returning Nodes matching given statement and return node type * * @param statement JCR query string * @param workspace Search in JCR workspace like website * @param returnItemType Return nodes based on primary node type * @return List<Node> * @throws javax.jcr.RepositoryException */ private List<Node> executeQuery(String statement, String workspace, String returnItemType) throws RepositoryException { List<Node> nodeList = new ArrayList<Node>(0); NodeIterator items = QueryUtil.search(workspace, statement, Query.JCR_SQL2, returnItemType); log.debug("Query Executed: {}", statement); while (items.hasNext()) { Node node = items.nextNode(); if (!filterNode(node)) { nodeList.add(new I18nNodeWrapper(node)); } } return nodeList; } /** * Check if node is valid to return as a result. * * @param node * @return True when node needs to be filtered out of the result set */ private Boolean filterNode(Node node) { // Check on noindex robots value Boolean containsNoIndex = StringUtils.containsIgnoreCase(PropertyUtil.getString(node, "robots", "index"), "noindex"); return containsNoIndex; } private int getNumberOfPages(int total, int maxResultsPerPage) { int calcNumPages = total/maxResultsPerPage; if((total % maxResultsPerPage) > 0 ) { calcNumPages++; } return calcNumPages; } private List<SearchEntry> getQueryResultItems(List<Node> nodes) { List<SearchEntry> resultList = new ArrayList<SearchEntry>(0); for (Node node : nodes) { resultList.add(new JcrSearchEntry(node)); } return resultList; } private List<SearchEntry> getPagedResults(List<SearchEntry> results, int pageNumber, int maxResultsPerPage) { List<SearchEntry> nodeListPaged = new ArrayList<SearchEntry>(0); final int total = results.size(); final int startRow = (maxResultsPerPage * (pageNumber - 1)); int newLimit = maxResultsPerPage; if(total > startRow) { if(total < startRow + maxResultsPerPage) { newLimit = total - startRow; } nodeListPaged = results.subList(startRow, startRow + newLimit); } return nodeListPaged; } }