From: <fg...@us...> - 2011-03-05 20:08:12
|
Revision: 3369 http://openutils.svn.sourceforge.net/openutils/?rev=3369&view=rev Author: fgiust Date: 2011-03-05 20:08:02 +0000 (Sat, 05 Mar 2011) Log Message: ----------- Modified Paths: -------------- trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/advanced/impl/AdvancedResultImpl.java trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/advanced/impl/QueryExecutorHelper.java trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/jcr/query/Criteria.java trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/jcr/query/DirectJcrQuery.java trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/jcr/query/xpath/impl/AbstractCriteriaImpl.java trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/BasePathWithSpacesTest.java trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/JcrContainsQuestionMarkTest.java trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/OrderingTest.java trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/PaginationTest.java Modified: trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/advanced/impl/AdvancedResultImpl.java =================================================================== --- trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/advanced/impl/AdvancedResultImpl.java 2011-03-05 18:41:17 UTC (rev 3368) +++ trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/advanced/impl/AdvancedResultImpl.java 2011-03-05 20:08:02 UTC (rev 3369) @@ -69,6 +69,8 @@ */ private Logger log = LoggerFactory.getLogger(AdvancedResultImpl.class); + private final boolean applyLocalPaging; + /** * @param jcrQueryResult * @param itemsPerPage @@ -85,13 +87,34 @@ HierarchyManager hm, Query spellCheckerQuery) { + this(jcrQueryResult, itemsPerPage, pageNumberStartingFromOne, statement, hm, spellCheckerQuery, false); + } + + /** + * @param jcrQueryResult + * @param itemsPerPage + * @param pageNumberStartingFromOne + * @param statement + * @param hm + * @param spellCheckerQuery + * @param applyLocalPaging don't assume the result iterator is already paginated, do it "manually" + */ + public AdvancedResultImpl( + QueryResultImpl jcrQueryResult, + int itemsPerPage, + int pageNumberStartingFromOne, + String statement, + HierarchyManager hm, + Query spellCheckerQuery, + boolean applyLocalPaging) + { this.jcrQueryResult = jcrQueryResult; this.itemsPerPage = itemsPerPage; this.statement = statement; this.hm = hm; this.spellCheckerQuery = spellCheckerQuery; - this.pageNumberStartingFromOne = pageNumberStartingFromOne; + this.applyLocalPaging = applyLocalPaging; } /** @@ -115,7 +138,7 @@ */ public int getTotalSize() { - if (jcrQueryResult.getTotalSize() == -1 && itemsPerPage == 0) + if (jcrQueryResult.getTotalSize() == -1 && (itemsPerPage == 0 || applyLocalPaging)) { try { @@ -155,6 +178,38 @@ throw jqe; } + if (applyLocalPaging && itemsPerPage > 0) + { + final int offset = (Math.max(pageNumberStartingFromOne, 1) - 1) * itemsPerPage; + + // removing preceding records + rows.skip(offset); + + // removing folllowing records and alter getSize() + return new AccessibleResultItemResultIterator(rows, this.hm) + { + + /** + * {@inheritDoc} + */ + @Override + public boolean hasNext() + { + return super.getPosition() - offset < Math.min(super.getSize() - offset, itemsPerPage) + && super.hasNext(); + } + + /** + * {@inheritDoc} + */ + @Override + public long getSize() + { + return Math.min(super.getSize() - offset, itemsPerPage); + } + }; + } + return new AccessibleResultItemResultIterator(rows, this.hm); } Modified: trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/advanced/impl/QueryExecutorHelper.java =================================================================== --- trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/advanced/impl/QueryExecutorHelper.java 2011-03-05 18:41:17 UTC (rev 3368) +++ trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/advanced/impl/QueryExecutorHelper.java 2011-03-05 20:08:02 UTC (rev 3369) @@ -26,6 +26,7 @@ import javax.jcr.query.InvalidQueryException; import javax.jcr.query.Query; +import net.sourceforge.openutils.mgnlcriteria.jcr.query.Criteria; import net.sourceforge.openutils.mgnlcriteria.jcr.query.JCRQueryException; import net.sourceforge.openutils.mgnlcriteria.jcr.query.xpath.utils.XPathTextUtils; @@ -77,7 +78,24 @@ public static AdvancedResultImpl execute(String stmt, String language, HierarchyManager hm, int maxResults, int offset, String spellCheckString) { + return execute(stmt, language, hm, maxResults, offset, spellCheckString, false); + } + /** + * Executes a jcr query. + * @param stmt the statement of the jcr query + * @param language the language of the jcr query + * @param hm the HirarchyManager for obtaining the QueryManager + * @param maxResults maximun number of results to retrieve + * @param offset the index of the first result to retrieve (0, 1, 2, ...) + * @param spellCheckString the input string used for spell checking + * @param forcePagingWithDocumentOrder see {@link Criteria#setForcePagingWithDocumentOrder(boolean)} + * @return the execution result + */ + public static AdvancedResultImpl execute(String stmt, String language, HierarchyManager hm, int maxResults, + int offset, String spellCheckString, boolean forcePagingWithDocumentOrder) + { + Session jcrSession = hm.getWorkspace().getSession(); javax.jcr.query.QueryManager jcrQueryManager; @@ -87,14 +105,17 @@ QueryImpl query = (QueryImpl) jcrQueryManager.createQuery(stmt, language); - if (maxResults > 0) + if (!forcePagingWithDocumentOrder) { - query.setLimit(maxResults); - } + if (maxResults > 0) + { + query.setLimit(maxResults); + } - if (offset > 0) - { - query.setOffset(offset); + if (offset > 0) + { + query.setOffset(offset); + } } int pageNumberStartingFromOne = 1; @@ -123,7 +144,8 @@ pageNumberStartingFromOne, stmt, hm, - spellCheckerQuery); + spellCheckerQuery, + forcePagingWithDocumentOrder); } finally { Modified: trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/jcr/query/Criteria.java =================================================================== --- trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/jcr/query/Criteria.java 2011-03-05 18:41:17 UTC (rev 3368) +++ trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/jcr/query/Criteria.java 2011-03-05 20:08:02 UTC (rev 3369) @@ -161,4 +161,26 @@ * @return the generated xpath expression */ String toXpathExpression(); + + /** + * <p> + * Enable paging while keeping results sorted in document order. + * </p> + * <p> + * Document order is only applied by jackrabbit after the paginated result has been retrieved. + * </p> + * <p> + * This means that if you have 20 nodes and you want to retrieve them in 2 pages containing 10 elements, only the + * order of elements in a single page is kept (but the "first" 10 noted in the first page will not be the nodes you + * are expecting in document order). Setting this flag to true forces the retrieval of the full list of nodes and a + * post-pagination which will mimic the behaviour you get when an "order by" is specified. + * </p> + * <p> + * Warning: this has surely a performance hit, since jackrabbit applied document ordering by retrieving any single + * node (while normally pagination is applied directly on the luce index). + * </p> + * @param force true to force paging while keeping results sorted in document order + * @return this (for method chaining) + */ + Criteria setForcePagingWithDocumentOrder(boolean force); } \ No newline at end of file Modified: trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/jcr/query/DirectJcrQuery.java =================================================================== --- trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/jcr/query/DirectJcrQuery.java 2011-03-05 18:41:17 UTC (rev 3368) +++ trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/jcr/query/DirectJcrQuery.java 2011-03-05 20:08:02 UTC (rev 3369) @@ -108,7 +108,7 @@ public AdvancedResult execute() { - return QueryExecutorHelper.execute(query, language, hm, maxResults, offset, spellCheckString); + return QueryExecutorHelper.execute(query, language, hm, maxResults, offset, spellCheckString, false); } } Modified: trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/jcr/query/xpath/impl/AbstractCriteriaImpl.java =================================================================== --- trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/jcr/query/xpath/impl/AbstractCriteriaImpl.java 2011-03-05 18:41:17 UTC (rev 3368) +++ trunk/openutils-mgnlcriteria/src/main/java/net/sourceforge/openutils/mgnlcriteria/jcr/query/xpath/impl/AbstractCriteriaImpl.java 2011-03-05 20:08:02 UTC (rev 3369) @@ -68,6 +68,8 @@ protected String workspace = ContentRepository.WEBSITE; + protected boolean forcePagingWithDocumentOrder; + protected AbstractCriteriaImpl() { @@ -201,6 +203,15 @@ /** * {@inheritDoc} */ + public Criteria setForcePagingWithDocumentOrder(boolean force) + { + this.forcePagingWithDocumentOrder = force; + return this; + } + + /** + * {@inheritDoc} + */ public String toXpathExpression() { JCRMagnoliaCriteriaQueryTranslator translator = new JCRMagnoliaCriteriaQueryTranslator(this); @@ -227,7 +238,8 @@ MgnlContext.getHierarchyManager(workspace), maxResults, offset, - spellCheckString); + spellCheckString, + forcePagingWithDocumentOrder && this.orderEntries.isEmpty()); } } \ No newline at end of file Modified: trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/BasePathWithSpacesTest.java =================================================================== --- trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/BasePathWithSpacesTest.java 2011-03-05 18:41:17 UTC (rev 3368) +++ trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/BasePathWithSpacesTest.java 2011-03-05 20:08:02 UTC (rev 3369) @@ -29,7 +29,6 @@ import net.sourceforge.openutils.mgnlcriteria.jcr.query.JCRCriteriaFactory; import net.sourceforge.openutils.mgnlcriteria.jcr.query.ResultIterator; import net.sourceforge.openutils.mgnlcriteria.jcr.query.criterion.Criterion; -import net.sourceforge.openutils.mgnlcriteria.jcr.query.criterion.Order; import net.sourceforge.openutils.mgnlcriteria.jcr.query.criterion.Restrictions; import org.testng.Assert; @@ -84,10 +83,11 @@ Criteria criteria = JCRCriteriaFactory.createCriteria().setWorkspace(ContentRepository.WEBSITE); criteria.setBasePath("//*[prop1='A' and prop2='B']/Lorem ipsum dolor sit amet"); criteria.add(Restrictions.eq(Criterion.JCR_PRIMARYTYPE, "mgnl:content")); - criteria.addOrder(Order.desc("@jcr:score")); + // criteria.addOrder(Order.desc("@jcr:score")); AdvancedResult advResult = criteria.execute(); // if not escaped properly it will crash + Assert.assertEquals(advResult.getItems().getSize(), 0); Assert.assertEquals(advResult.getTotalSize(), 0); } Modified: trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/JcrContainsQuestionMarkTest.java =================================================================== --- trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/JcrContainsQuestionMarkTest.java 2011-03-05 18:41:17 UTC (rev 3368) +++ trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/JcrContainsQuestionMarkTest.java 2011-03-05 20:08:02 UTC (rev 3369) @@ -77,7 +77,7 @@ try { String stmt = "//*[((@jcr:primaryType='mgnl:content') and (jcr:contains(@title,'test?')))] order by @jcr:score"; - advResult = QueryExecutorHelper.execute(stmt, Query.XPATH, hm, 10, 0, null); + advResult = QueryExecutorHelper.execute(stmt, Query.XPATH, hm, 10, 0, null, false); } catch (JCRQueryException e) { @@ -99,7 +99,7 @@ HierarchyManager hm = MgnlContext.getHierarchyManager(ContentRepository.WEBSITE); String stmt = "//*[((@jcr:primaryType='mgnl:content') and (jcr:contains(@title,'test\\?')))] order by @jcr:score"; - AdvancedResultImpl advResult = QueryExecutorHelper.execute(stmt, Query.XPATH, hm, -1, 0, null); + AdvancedResultImpl advResult = QueryExecutorHelper.execute(stmt, Query.XPATH, hm, -1, 0, null, false); Assert.assertEquals(advResult.getTotalSize(), 1); Assert.assertEquals(advResult.getItems().next().getTitle(), "hello test? world"); @@ -114,11 +114,11 @@ AdvancedResultImpl advResult; stmt = "//*[((@jcr:primaryType='mgnl:content') and (jcr:contains(@title,'te?st')))] order by @jcr:score"; - advResult = QueryExecutorHelper.execute(stmt, Query.XPATH, hm, -1, 0, null); + advResult = QueryExecutorHelper.execute(stmt, Query.XPATH, hm, -1, 0, null, false); Assert.assertEquals(advResult.getTotalSize(), 0); stmt = "//*[((@jcr:primaryType='mgnl:content') and (jcr:contains(@title,'te\\?st')))] order by @jcr:score"; - advResult = QueryExecutorHelper.execute(stmt, Query.XPATH, hm, -1, 0, null); + advResult = QueryExecutorHelper.execute(stmt, Query.XPATH, hm, -1, 0, null, false); Assert.assertEquals(advResult.getTotalSize(), 1); Assert.assertEquals(advResult.getItems().next().getTitle(), "hello te?st world"); } Modified: trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/OrderingTest.java =================================================================== --- trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/OrderingTest.java 2011-03-05 18:41:17 UTC (rev 3368) +++ trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/OrderingTest.java 2011-03-05 20:08:02 UTC (rev 3369) @@ -108,7 +108,7 @@ AdvancedResult advResult = criteria.execute(); - // Assert.assertEquals(advResult.getTotalSize(), LETTERS_ARRAY.length); + Assert.assertEquals(advResult.getTotalSize(), LETTERS_ARRAY.length); ResultIterator<AdvancedResultItem> resultIterator = advResult.getItems(); Assert.assertEquals(resultIterator.getSize(), LETTERS_ARRAY.length); @@ -133,20 +133,20 @@ criteria.setBasePath("/letters"); criteria.add(Restrictions.eq("@jcr:primaryType", "mgnl:content")); criteria.setPaging(PAGINATION_LENGTH, 1); + criteria.setForcePagingWithDocumentOrder(true); log.debug(criteria.toXpathExpression()); AdvancedResult advResult = criteria.execute(); - // Assert.assertEquals(advResult.getTotalSize(), LETTERS_ARRAY.length); + Assert.assertEquals(advResult.getTotalSize(), LETTERS_ARRAY.length, "Unset total size."); ResultIterator<AdvancedResultItem> resultIterator = advResult.getItems(); - Assert.assertEquals(resultIterator.getSize(), PAGINATION_LENGTH); + Assert.assertEquals(resultIterator.getSize(), PAGINATION_LENGTH, "Wrong iterator size."); int i = 0; for (AdvancedResultItem currentResult : resultIterator) { - // log.warn("found " + currentResult.getTitle()); Assert.assertEquals(currentResult.getTitle(), LETTERS_ARRAY[i], "Position " + i + ": found " @@ -155,5 +155,7 @@ + LETTERS_ARRAY[i]); i++; } + + Assert.assertEquals(i, PAGINATION_LENGTH, "Wrong number of results returned by the iterator."); } } Modified: trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/PaginationTest.java =================================================================== --- trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/PaginationTest.java 2011-03-05 18:41:17 UTC (rev 3368) +++ trunk/openutils-mgnlcriteria/src/test/java/net/sourceforge/openutils/mgnlcriteria/advanced/PaginationTest.java 2011-03-05 20:08:02 UTC (rev 3369) @@ -131,9 +131,9 @@ Assert.assertEquals(advResult.getTotalSize(), 26); ResultIterator<AdvancedResultItem> resultIterator = advResult.getItems(); - Assert.assertEquals(resultIterator.getSize(), 17); Assert.assertEquals(resultIterator.next().getTitle(), "J"); + Assert.assertEquals(resultIterator.getSize(), 17); } /** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |