Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NXP-30360: allow to use sort infos when using a quick filter #4826

Merged
merged 2 commits into from Jun 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -175,12 +175,11 @@ public List<Map<String, Serializable>> getCurrentPage() {
}

protected void buildQuery() {
List<SortInfo> sort = null;
List<SortInfo> sort = new ArrayList<>();
List<QuickFilter> quickFilters = getQuickFilters();
String quickFiltersClause = "";

if (quickFilters != null && !quickFilters.isEmpty()) {
sort = new ArrayList<>();
for (QuickFilter quickFilter : quickFilters) {
String clause = quickFilter.getClause();
if (!quickFiltersClause.isEmpty() && clause != null) {
Expand All @@ -190,15 +189,14 @@ protected void buildQuery() {
}
sort.addAll(quickFilter.getSortInfos());
}
} else if (sortInfos != null) {
sort = sortInfos;
}

SortInfo[] sortArray = null;
if (sort != null) {
sortArray = sort.toArray(new SortInfo[] {});
if (sortInfos != null) {
sort.addAll(sortInfos);
}

SortInfo[] sortArray = sort.toArray(SortInfo[]::new);

String newQuery;
PageProviderDefinition def = getDefinition();
WhereClauseDefinition whereClause = def.getWhereClause();
Expand All @@ -207,8 +205,8 @@ protected void buildQuery() {
String originalPattern = def.getPattern();
String pattern = quickFiltersClause.isEmpty() ? originalPattern
: StringUtils.containsIgnoreCase(originalPattern, " WHERE ")
? NXQLQueryBuilder.appendClause(originalPattern, quickFiltersClause)
: originalPattern + " WHERE " + quickFiltersClause;
? NXQLQueryBuilder.appendClause(originalPattern, quickFiltersClause)
: originalPattern + " WHERE " + quickFiltersClause;

newQuery = NXQLQueryBuilder.getQuery(pattern, getParameters(), def.getQuotePatternParameters(),
def.getEscapePatternParameters(), getSearchDocumentModel(), sortArray);
Expand Down Expand Up @@ -239,10 +237,9 @@ public PageSelections<Map<String, Serializable>> getCurrentSelectPage() {
}

/**
* Fetch a page that can be selected. It loads the last page if we're targeting a page beyond the last one or
* the first page if there are no results to show and we're targeting anything other than the first page.
*
* Fix for NXP-8564.
* Fetch a page that can be selected. It loads the last page if we're targeting a page beyond the last one or the
* first page if there are no results to show and we're targeting anything other than the first page. Fix for
* NXP-8564.
*/
protected void rewindSelectablePage() {
long pageSize = getPageSize();
Expand All @@ -251,19 +248,20 @@ protected void rewindSelectablePage() {
if (resultsCount == 0) {
// fetch first page directly
if (log.isDebugEnabled()) {
log.debug(String.format(
"Current page %s is not the first one but " + "shows no result and there are "
+ "no results => rewind to first page",
Long.valueOf(getCurrentPageIndex())));
log.debug(
String.format(
"Current page %s is not the first one but " + "shows no result and there are "
+ "no results => rewind to first page",
Long.valueOf(getCurrentPageIndex())));
}
firstPage();
} else {
// fetch last page
if (log.isDebugEnabled()) {
log.debug(String.format(
"Current page %s is not the first one but " + "shows no result and there are "
+ "%s results => fetch last page",
Long.valueOf(getCurrentPageIndex()), Long.valueOf(resultsCount)));
"Current page %s is not the first one but " + "shows no result and there are "
+ "%s results => fetch last page",
Long.valueOf(getCurrentPageIndex()), Long.valueOf(resultsCount)));
}
lastPage();
}
Expand Down
Expand Up @@ -199,12 +199,11 @@ public List<DocumentModel> getCurrentPage() {
}

protected void buildQuery(CoreSession coreSession) {
List<SortInfo> sort = null;
List<SortInfo> sort = new ArrayList<>();
List<QuickFilter> quickFilters = getQuickFilters();
String quickFiltersClause = "";

if (quickFilters != null && !quickFilters.isEmpty()) {
sort = new ArrayList<>();
for (QuickFilter quickFilter : quickFilters) {
String clause = quickFilter.getClause();
if (clause != null) {
Expand All @@ -216,15 +215,14 @@ protected void buildQuery(CoreSession coreSession) {
}
sort.addAll(quickFilter.getSortInfos());
}
} else if (sortInfos != null) {
sort = sortInfos;
}

SortInfo[] sortArray = null;
if (sort != null) {
sortArray = sort.toArray(new SortInfo[] {});
if (sortInfos != null) {
sort.addAll(sortInfos);
}

SortInfo[] sortArray = sort.toArray(SortInfo[]::new);

String newQuery;
PageProviderDefinition def = getDefinition();
WhereClauseDefinition whereClause = def.getWhereClause();
Expand Down Expand Up @@ -293,8 +291,7 @@ public long getMaxResults() {
if (maxResultsStr != null) {
if (DEFAULT_NAVIGATION_RESULTS_KEY.equals(maxResultsStr)) {
ConfigurationService cs = Framework.getService(ConfigurationService.class);
maxResultsStr = cs.getString(DEFAULT_NAVIGATION_RESULTS_PROPERTY,
DEFAULT_NAVIGATION_RESULTS_VALUE);
maxResultsStr = cs.getString(DEFAULT_NAVIGATION_RESULTS_PROPERTY, DEFAULT_NAVIGATION_RESULTS_VALUE);
} else if (PAGE_SIZE_RESULTS_KEY.equals(maxResultsStr)) {
maxResultsStr = Long.valueOf(getPageSize()).toString();
}
Expand Down Expand Up @@ -367,7 +364,7 @@ protected void rewindSelectablePage() {
String.format(
"Current page %s is not the first one but " + "shows no result and there are "
+ "no results => rewind to first page",
Long.valueOf(getCurrentPageIndex())));
Long.valueOf(getCurrentPageIndex())));
}
firstPage();
} else {
Expand Down
Expand Up @@ -20,10 +20,12 @@

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;

Expand All @@ -32,6 +34,7 @@
import org.junit.runner.RunWith;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.SortInfo;
import org.nuxeo.ecm.core.test.CoreFeature;
import org.nuxeo.ecm.core.test.annotations.Granularity;
import org.nuxeo.ecm.core.test.annotations.RepositoryConfig;
Expand All @@ -43,11 +46,10 @@
import org.nuxeo.runtime.test.runner.Deploy;
import org.nuxeo.runtime.test.runner.Features;
import org.nuxeo.runtime.test.runner.FeaturesRunner;
import org.nuxeo.runtime.test.runner.TransactionalFeature;

/**
* @since 9.3
*
* see NXP-23092
* @since 9.3 see NXP-23092
*/
@RunWith(FeaturesRunner.class)
@Features(CoreFeature.class)
Expand All @@ -61,6 +63,9 @@ public class TestPageProviderCurrentPage {

protected static final int SECOND_PAGE_NUM_DOCS = 25;

@Inject
protected TransactionalFeature transactionalFeature;

@Inject
protected PageProviderService pps;

Expand All @@ -71,7 +76,7 @@ public class TestPageProviderCurrentPage {
public void createTestDocuments() {
PageProviderDefinition ppd = pps.getPageProviderDefinition(DUMMY_FETCH_DOCUMENTS);
long num_docs = ppd.getMaxPageSize() + SECOND_PAGE_NUM_DOCS;
for (int i=0; i < num_docs;i++) {
for (int i = 0; i < num_docs; i++) {
DocumentModel doc = session.createDocumentModel("File");
doc.setPathInfo("/", "File " + i);
doc.setPropertyValue("dc:source", "dummy");
Expand All @@ -86,20 +91,20 @@ public void testPageProviderCurrentPage() {
HashMap<String, Serializable> props = new HashMap<>();
props.put(CoreQueryDocumentPageProvider.CORE_SESSION_PROPERTY, (Serializable) session);
PageProvider<?> pp = pps.getPageProvider(DUMMY_FETCH_DOCUMENTS, ppd, null, null, ppd.getMaxPageSize(), 0L,
props);
props);
// check that both pages are different
assertEquals(0, pp.getCurrentPageIndex());
assertEquals(pp.getMaxPageSize(), pp.getCurrentPageSize());
assertEquals(2, pp.getNumberOfPages());
List<?> page = pp.getCurrentPage();
String prevId = ((DocumentModel)page.get(0)).getId();
String prevId = ((DocumentModel) page.get(0)).getId();
pp.setCurrentPage(1);
assertEquals(1, pp.getCurrentPageIndex());
assertEquals(SECOND_PAGE_NUM_DOCS, pp.getCurrentPageSize());
assertEquals(2, pp.getNumberOfPages());
page = pp.getCurrentPage();
assertNotEquals(prevId, ((DocumentModel)page.get(0)).getId());
prevId = ((DocumentModel)page.get(0)).getId();
assertNotEquals(prevId, ((DocumentModel) page.get(0)).getId());
prevId = ((DocumentModel) page.get(0)).getId();
// since we only have two pages, requesting a third one should return an empty page
pp.setCurrentPage(2);
assertEquals(2, pp.getCurrentPageIndex());
Expand All @@ -108,7 +113,7 @@ public void testPageProviderCurrentPage() {
// however, fetching the current selected page should return the last one instead
PageSelections<?> selections = pp.getCurrentSelectPage();
assertEquals(SECOND_PAGE_NUM_DOCS, selections.getSize());
assertEquals(prevId, ((DocumentModel)selections.getEntries().get(0).getData()).getId());
assertEquals(prevId, ((DocumentModel) selections.getEntries().get(0).getData()).getId());
}

@Test
Expand All @@ -122,13 +127,111 @@ public void testPageProviderCurrentPageWithoutPageSize() {
assertEquals(pp.getMaxPageSize(), pp.getCurrentPageSize());
assertEquals(1, pp.getNumberOfPages());
List<?> page = pp.getCurrentPage();
String prevId = ((DocumentModel)page.get(0)).getId();
String prevId = ((DocumentModel) page.get(0)).getId();
pp.setCurrentPage(1);
assertEquals(0, pp.getCurrentPageIndex());
assertEquals(pp.getMaxPageSize(), pp.getCurrentPageSize());
assertEquals(1, pp.getNumberOfPages());
page = pp.getCurrentPage();
assertEquals(prevId, ((DocumentModel)page.get(0)).getId());
assertEquals(prevId, ((DocumentModel) page.get(0)).getId());
}

// NXP-30360
@Deploy("org.nuxeo.ecm.platform.query.api.test:test-pageprovider-quick-filter-contrib.xml")
@Test
@SuppressWarnings("unchecked")
public void testPageProviderSortAndQuickFilter() {
DocumentModel rootFolder = session.createDocumentModel("/", "rootFolder", "Folder");
rootFolder = session.createDocument(rootFolder);
DocumentModel folder = session.createDocumentModel("/rootFolder", "folder", "Folder");
folder.setPropertyValue("dc:title", "Folder");
session.createDocument(folder);
DocumentModel file1 = session.createDocumentModel("/rootFolder", "file1", "File");
file1.setPropertyValue("dc:title", "File 1");
session.createDocument(file1);
DocumentModel file2 = session.createDocumentModel("/rootFolder", "file2", "File");
file2.setPropertyValue("dc:title", "File 2");
session.createDocument(file2);
transactionalFeature.nextTransaction();

var props = Map.of(CoreQueryDocumentPageProvider.CORE_SESSION_PROPERTY, (Serializable) session);
// default sort infos, no quick filter
PageProvider<?> pp = pps.getPageProvider("test_quick_filter", null, 0L, 0L, props, rootFolder.getId());
assertNotNull(pp);
List<DocumentModel> docs = (List<DocumentModel>) pp.getCurrentPage();
assertEquals(3, docs.size());
assertEquals("File 1", docs.get(0).getTitle());
assertEquals("File 2", docs.get(1).getTitle());
assertEquals("Folder", docs.get(2).getTitle());

// custom sort infos, no quick filter
var sortInfos = List.of(new SortInfo("dc:title", false));
pp = pps.getPageProvider("test_quick_filter", sortInfos, 0L, 0L, props, rootFolder.getId());
assertNotNull(pp);
docs = (List<DocumentModel>) pp.getCurrentPage();
assertEquals(3, docs.size());
assertEquals("Folder", docs.get(0).getTitle());
assertEquals("File 2", docs.get(1).getTitle());
assertEquals("File 1", docs.get(2).getTitle());

// custom sort infos, quick filter
var ppd = pps.getPageProviderDefinition("test_quick_filter");
pp = pps.getPageProvider("test_quick_filter", sortInfos, 0L, 0L, props, null, ppd.getQuickFilters(),
rootFolder.getId());
assertNotNull(pp);
docs = (List<DocumentModel>) pp.getCurrentPage();
assertEquals(2, docs.size());
assertEquals("File 2", docs.get(0).getTitle());
assertEquals("File 1", docs.get(1).getTitle());
}

// NXP-30360
@Deploy("org.nuxeo.ecm.platform.query.api.test:test-pageprovider-quick-filter-contrib.xml")
@Test
@SuppressWarnings("unchecked")
public void testPageProviderSortAndQuickFilterWithQueryAndFetch() {
DocumentModel rootFolder = session.createDocumentModel("/", "rootFolder", "Folder");
rootFolder = session.createDocument(rootFolder);
DocumentModel folder = session.createDocumentModel("/rootFolder", "folder", "Folder");
folder.setPropertyValue("dc:title", "Folder");
session.createDocument(folder);
DocumentModel file1 = session.createDocumentModel("/rootFolder", "file1", "File");
file1.setPropertyValue("dc:title", "File 1");
session.createDocument(file1);
DocumentModel file2 = session.createDocumentModel("/rootFolder", "file2", "File");
file2.setPropertyValue("dc:title", "File 2");
session.createDocument(file2);
transactionalFeature.nextTransaction();

var props = Map.of(CoreQueryDocumentPageProvider.CORE_SESSION_PROPERTY, (Serializable) session);
// default sort infos, no quick filter
PageProvider<?> pp = pps.getPageProvider("test_quick_filter_fetch", null, 0L, 0L, props, rootFolder.getId());
assertNotNull(pp);
List<Map<String, Serializable>> res = (List<Map<String, Serializable>>) pp.getCurrentPage();
assertEquals(3, res.size());
assertEquals("File 1", res.get(0).get("dc:title"));
assertEquals("File 2", res.get(1).get("dc:title"));
assertEquals("Folder", res.get(2).get("dc:title"));

// custom sort infos, no quick filter
var sortInfos = List.of(new SortInfo("dc:title", false));
pp = pps.getPageProvider("test_quick_filter_fetch", sortInfos, 0L, 0L, props, rootFolder.getId());
assertNotNull(pp);
res = (List<Map<String, Serializable>>) pp.getCurrentPage();
assertEquals(3, res.size());
assertEquals("Folder", res.get(0).get("dc:title"));
assertEquals("File 2", res.get(1).get("dc:title"));
assertEquals("File 1", res.get(2).get("dc:title"));

// custom sort infos, quick filter
var ppd = pps.getPageProviderDefinition("test_quick_filter_fetch");
pp = pps.getPageProvider("test_quick_filter_fetch", sortInfos, 0L, 0L, props, null, ppd.getQuickFilters(),
rootFolder.getId());
assertNotNull(pp);
res = (List<Map<String, Serializable>>) pp.getCurrentPage();
assertEquals(2, res.size());
assertEquals("File 2", res.get(0).get("dc:title"));
assertEquals("File 1", res.get(1).get("dc:title"));
}

}
@@ -0,0 +1,37 @@
<?xml version="1.0"?>

<component name="org.nuxeo.ecm.platform.query.api.PageProviderservice.quick.filter.testContrib">

<extension target="org.nuxeo.ecm.platform.query.api.PageProviderService"
point="providers">

<coreQueryPageProvider name="test_quick_filter">
<pattern>
SELECT * FROM Document WHERE ecm:parentId = ?
</pattern>
<sort column="dc:title" ascending="true" />
<quickFilters>
<quickFilter name="noFolder">
<clause>ecm:mixinType != 'Folderish'</clause>
</quickFilter>
</quickFilters>
<pageSize>20</pageSize>
</coreQueryPageProvider>

<genericPageProvider name="test_quick_filter_fetch"
class="org.nuxeo.ecm.platform.query.nxql.CoreQueryAndFetchPageProvider">
<pattern>
SELECT dc:title FROM Document WHERE ecm:parentId = ?
</pattern>
<sort column="dc:title" ascending="true" />
<quickFilters>
<quickFilter name="noFolder">
<clause>ecm:mixinType != 'Folderish'</clause>
</quickFilter>
</quickFilters>
<pageSize>20</pageSize>
</genericPageProvider>

</extension>

</component>