Commit 34aab44f authored by Oscar Scholten's avatar Oscar Scholten

CMS-9632: add mechanism to return the parent of the items in the resultset

parent 3afa4a24
/*
* Copyright 2012-2013 Hippo B.V. (http://www.onehippo.com)
* Copyright 2012-2015 Hippo B.V. (http://www.onehippo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -19,6 +19,8 @@ public interface Query {
public Query EMPTY = new EmptyQuery();
Query returnParentNode();
Query offsetBy(int offset);
Query limitTo(int limit);
......@@ -28,6 +30,11 @@ public interface Query {
final class EmptyQuery implements Query, OrderClause {
@Override
public Query returnParentNode() {
return this;
}
@Override
public Query offsetBy(final int offset) {
return this;
......@@ -53,4 +60,3 @@ final class EmptyQuery implements Query, OrderClause {
return this;
}
}
/*
* Copyright 2012-2013 Hippo B.V. (http://www.onehippo.com)
* Copyright 2012-2015 Hippo B.V. (http://www.onehippo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -20,6 +20,8 @@ package org.onehippo.cms7.services.search.query.reflect;
*/
public interface QueryNode {
boolean getReturnParentNode();
int getLimit();
int getOffset();
......
/*
* Copyright 2012-2013 Hippo B.V. (http://www.onehippo.com)
* Copyright 2012-2015 Hippo B.V. (http://www.onehippo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -24,29 +24,37 @@ public class QueryImpl implements Query, QueryNode {
private final QueryImpl parent;
private final boolean returnParentNode;
private final int offset;
private final int limit;
QueryImpl(QueryImpl parent) {
this.parent = parent;
this.returnParentNode = false;
this.offset = -1;
this.limit = -1;
}
QueryImpl(QueryImpl parent, int offset, int limit) {
QueryImpl(QueryImpl parent, boolean returnParentNode, int offset, int limit) {
this.parent = parent;
this.returnParentNode = returnParentNode;
this.offset = offset;
this.limit = limit;
}
@Override
public QueryImpl returnParentNode() {
return new QueryImpl(this, true, this.offset, this.limit);
}
@Override
public QueryImpl offsetBy(final int offset) {
return new QueryImpl(this, offset, this.limit);
return new QueryImpl(this, this.returnParentNode, offset, this.limit);
}
@Override
public QueryImpl limitTo(final int limit) {
return new QueryImpl(this, this.offset, limit);
return new QueryImpl(this, this.returnParentNode, this.offset, limit);
}
@Override
......@@ -70,6 +78,11 @@ public class QueryImpl implements Query, QueryNode {
return parent;
}
@Override
public final boolean getReturnParentNode() {
return returnParentNode;
}
@Override
public final int getLimit() {
return limit;
......
/*
* Copyright 2012-2013 Hippo B.V. (http://www.onehippo.com)
* Copyright 2012-2015 Hippo B.V. (http://www.onehippo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -37,6 +37,7 @@ public interface HippoSearchNodeType {
String RESOLUTION = "hipposearch:resolution";
// query
String RETURNPARENTNODE = "hipposearch:returnparentnode";
String LIMIT = "hipposearch:limit";
String OFFSET = "hipposearch:offset";
String NODETYPE = "hipposearch:nodetype";
......
/*
* Copyright 2012-2013 Hippo B.V. (http://www.onehippo.com)
* Copyright 2012-2015 Hippo B.V. (http://www.onehippo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -31,6 +31,7 @@ public class JcrQueryBuilder {
static final int DEFAULT_LIMIT = 1000;
private boolean returnParentNode = false;
private int limit = DEFAULT_LIMIT;
private int offset = 0;
......@@ -152,6 +153,10 @@ public class JcrQueryBuilder {
}
}
if (this.returnParentNode) {
query.append("/..");
}
if (orderByList.size() > 0) {
query.append(" order by ");
boolean first = true;
......@@ -197,6 +202,14 @@ public class JcrQueryBuilder {
this.selected.add(property);
}
public boolean getReturnParentNode() {
return returnParentNode;
}
public void setReturnParentNode() {
this.returnParentNode = true;
}
public int getOffset() {
return offset;
}
......
/*
* Copyright 2012-2013 Hippo B.V. (http://www.onehippo.com)
* Copyright 2012-2015 Hippo B.V. (http://www.onehippo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -50,6 +50,9 @@ public class JcrQueryVisitor implements QueryVisitor {
@Override
public void visit(final QueryNode query) {
if (query.getReturnParentNode()) {
builder.setReturnParentNode();
}
if (query.getLimit() != -1) {
builder.setLimit(query.getLimit());
}
......
/*
* Copyright 2012-2013 Hippo B.V. (http://www.onehippo.com)
* Copyright 2012-2015 Hippo B.V. (http://www.onehippo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -56,6 +56,7 @@ class JcrPersistingQueryVisitor implements QueryVisitor {
@Override
public void visit(final QueryNode query) {
node.setReturnParentNode(query.getReturnParentNode());
node.setLimit(query.getLimit());
node.setOffset(query.getOffset());
}
......
/*
* Copyright 2012-2013 Hippo B.V. (http://www.onehippo.com)
* Copyright 2012-2015 Hippo B.V. (http://www.onehippo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -74,6 +74,25 @@ public class JcrQueryNode extends JcrConstraintNode {
}
}
public boolean getReturnParentNode() {
try {
if (node.hasProperty(HippoSearchNodeType.RETURNPARENTNODE)) {
return node.getProperty(HippoSearchNodeType.RETURNPARENTNODE).getBoolean();
}
} catch (RepositoryException re) {
log.warn("Unable to read returnparentnode", re);
}
return false;
}
public void setReturnParentNode(boolean value) {
try {
node.setProperty(HippoSearchNodeType.RETURNPARENTNODE, value);
} catch (RepositoryException re) {
log.warn("Unable to store returnparentnode", re);
}
}
public int getLimit() {
try {
if (node.hasProperty(HippoSearchNodeType.LIMIT)) {
......
/*
* Copyright 2012-2013 Hippo B.V. (http://www.onehippo.com)
* Copyright 2012-2015 Hippo B.V. (http://www.onehippo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -111,6 +111,10 @@ public class JcrQueryReader {
}
}
if (node.getReturnParentNode()) {
query = query.returnParentNode();
}
query = query.limitTo(node.getLimit()).offsetBy(node.getOffset());
return query;
......
......@@ -15,6 +15,7 @@
- hipposearch:resolution (string) < 'year', 'month', 'day', 'hour', 'exact'
[hipposearch:query] > hipposearch:compoundconstraint
- hipposearch:returnparentnode (boolean)
- hipposearch:limit (long)
- hipposearch:offset (long)
- hipposearch:nodetype (string)
......@@ -22,4 +23,3 @@
- hipposearch:excludes (string) multiple
- hipposearch:orderBy (string) multiple
- hipposearch:ascDesc (string) multiple < 'ascending', 'descending'
/*
* Copyright 2015 Hippo B.V. (http://www.onehippo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onehippo.cms7.services.search.jcr;
import javax.jcr.Session;
import org.onehippo.cms7.services.search.commons.query.QueryImpl;
import org.onehippo.cms7.services.search.jcr.query.JcrQueryBuilder;
import org.onehippo.cms7.services.search.jcr.query.JcrQueryVisitor;
public class TestUtils {
public static String getQueryAsString(final QueryImpl query, final Session session) {
final JcrQueryBuilder builder = new JcrQueryBuilder(session);
JcrQueryVisitor visitor = new JcrQueryVisitor(builder, session);
query.accept(visitor);
return builder.getQueryString();
}
}
......@@ -15,10 +15,10 @@
*/
package org.onehippo.cms7.services.search.jcr.query;
import org.junit.Test;
import org.onehippo.cms7.services.search.commons.query.InitialQueryImpl;
import org.onehippo.cms7.services.search.commons.query.QueryImpl;
import org.onehippo.cms7.services.search.jcr.TestUtils;
import org.onehippo.cms7.services.search.query.QueryBuilder;
import org.onehippo.cms7.services.search.query.QueryUtils;
import org.onehippo.repository.testutils.RepositoryTestCase;
......@@ -30,24 +30,24 @@ public class TestJcrQueryBuilder extends RepositoryTestCase {
public final static String COMMON_SCOPE = "(@hippo:paths='cafebabe-cafe-babe-cafe-babecafebabe')";
public final static String COMMON_ORDERBY = " order by @jcr:score descending";
public void testEmptyQuery() throws Exception {
InitialQueryImpl query = new InitialQueryImpl();
String queryAsString = TestUtils.getQueryAsString(query, session);
assertEquals("//*" + COMMON_ORDERBY, queryAsString);
}
@Test
public void testNoFilter() throws Exception {
InitialQueryImpl initialQuery = new InitialQueryImpl();
QueryImpl query = initialQuery.from("/");
String queryAsString = getQueryAsString(query);
String queryAsString = TestUtils.getQueryAsString(query, session);
assertEquals("//*[" + COMMON_SCOPE + "]" + COMMON_ORDERBY, queryAsString);
}
private String getQueryAsString(final QueryImpl query) {
final JcrQueryBuilder builder = new JcrQueryBuilder(session);
JcrQueryVisitor visitor = new JcrQueryVisitor(builder, session);
query.accept(visitor);
return builder.getQueryString();
}
@Test
public void testSimpleFilter() throws Exception {
QueryImpl query = new QueryBuilder() {
......@@ -57,7 +57,7 @@ public class TestJcrQueryBuilder extends RepositoryTestCase {
}
}.build();
String queryAsString = getQueryAsString(query);
String queryAsString = TestUtils.getQueryAsString(query, session);
assertEquals("//*[" + COMMON_SCOPE + " and (@a = 'a' and (@b = 'b'))]" + COMMON_ORDERBY, queryAsString);
}
......@@ -78,7 +78,7 @@ public class TestJcrQueryBuilder extends RepositoryTestCase {
}
}.build();
String queryAsString = getQueryAsString(query);
String queryAsString = TestUtils.getQueryAsString(query, session);
//*[(@hippo:paths='cafebabe-cafe-babe-cafe-babecafebabe') and ((jcr:contains(.,'contains') or jcr:contains(.,'contains*')) and (@a = 'a') and (@b = 'b') and (@c = 'c'))] order by @jcr:score descending
assertEquals("//*[" + COMMON_SCOPE + " and ((jcr:contains(.,'contains') or jcr:contains(.,'contains*')) and (@a = 'a') and (@b = 'b') and (@c = 'c'))]" + COMMON_ORDERBY, queryAsString);
}
......@@ -100,7 +100,7 @@ public class TestJcrQueryBuilder extends RepositoryTestCase {
}
}.build();
String queryAsString = getQueryAsString(query);
String queryAsString = TestUtils.getQueryAsString(query, session);
assertEquals("//*[" + COMMON_SCOPE + " and ((jcr:contains(.,'contains') or jcr:contains(.,'contains*')) or (@a = 'a') or (@b = 'b') or (@c = 'c'))]" + COMMON_ORDERBY, queryAsString);
}
......@@ -113,7 +113,7 @@ public class TestJcrQueryBuilder extends RepositoryTestCase {
}
}.build();
String queryAsString = getQueryAsString(query);
String queryAsString = TestUtils.getQueryAsString(query, session);
assertEquals("//*[" + COMMON_SCOPE + "] order by @a ascending", queryAsString);
}
......@@ -126,7 +126,7 @@ public class TestJcrQueryBuilder extends RepositoryTestCase {
}
}.build();
String queryAsString = getQueryAsString(query);
String queryAsString = TestUtils.getQueryAsString(query, session);
assertEquals("//*[" + COMMON_SCOPE + "] order by @a descending", queryAsString);
}
......@@ -139,9 +139,10 @@ public class TestJcrQueryBuilder extends RepositoryTestCase {
}
}.build();
String queryAsString = getQueryAsString(query);
String queryAsString = TestUtils.getQueryAsString(query, session);
assertEquals("//*[" + COMMON_SCOPE + " and (@a = '')]" + COMMON_ORDERBY, queryAsString);
}
@Test
public void test_empty_value_for_TextContraint_via_QueryUtils() throws Exception {
QueryImpl query = new QueryBuilder() {
......@@ -151,7 +152,7 @@ public class TestJcrQueryBuilder extends RepositoryTestCase {
}
}.build();
String queryAsString = getQueryAsString(query);
String queryAsString = TestUtils.getQueryAsString(query, session);
assertEquals("//*[" + COMMON_SCOPE + " and (@a = '')]" + COMMON_ORDERBY, queryAsString);
}
......@@ -164,8 +165,26 @@ public class TestJcrQueryBuilder extends RepositoryTestCase {
}
}.build();
String queryAsString = getQueryAsString(query);
String queryAsString = TestUtils.getQueryAsString(query, session);
assertEquals("//*[" + COMMON_SCOPE + " and (@a = '''' and (@b = ''''))]" + COMMON_ORDERBY, queryAsString);
}
@Test
public void test_adding_return_parent_node_to_empty_query() {
InitialQueryImpl initialQuery = new InitialQueryImpl();
QueryImpl query = initialQuery.returnParentNode();
String queryAsString = TestUtils.getQueryAsString(query, session);
assertEquals("//*/.." + COMMON_ORDERBY, queryAsString);
}
@Test
public void test_adding_subnode_to_query_with_constrains() {
InitialQueryImpl initialQuery = new InitialQueryImpl();
QueryImpl query = initialQuery.from("/").returnParentNode();
String queryAsString = TestUtils.getQueryAsString(query, session);
assertEquals("//*[" + COMMON_SCOPE + "]/.." + COMMON_ORDERBY, queryAsString);
}
}
\ No newline at end of file
}
/*
* Copyright 2012-2013 Hippo B.V. (http://www.onehippo.com)
* Copyright 2012-2015 Hippo B.V. (http://www.onehippo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -23,8 +23,10 @@ import javax.jcr.RepositoryException;
import org.junit.Before;
import org.junit.Test;
import org.onehippo.cms7.services.search.commons.query.QueryImpl;
import org.onehippo.cms7.services.search.document.SearchDocument;
import org.onehippo.cms7.services.search.jcr.HippoSearchNodeType;
import org.onehippo.cms7.services.search.jcr.TestUtils;
import org.onehippo.cms7.services.search.query.InitialQuery;
import org.onehippo.cms7.services.search.query.Query;
import org.onehippo.cms7.services.search.query.constraint.DateConstraint;
......@@ -112,16 +114,23 @@ public class TestHippoJcrSearchService extends RepositoryTestCase {
testPersistRetrieveQuery(initialQuery.where(integer("count").from(5).andTo(10)));
testPersistRetrieveQuery(initialQuery.where(date("publication").from(new Date(), DateConstraint.Resolution.HOUR)));
testPersistRetrieveQuery(initialQuery.where(date("publication").from(new Date(), DateConstraint.Resolution.EXACT)));
testPersistRetrieveQuery(initialQuery.returnParentNode());
}
private void testPersistRetrieveQuery(Query searchQuery) throws Exception {
Node node = createQueryNode();
try {
QueryImpl searchQueryImpl = (QueryImpl) searchQuery;
QueryNode queryNode = searchService.asQueryNode(searchQuery);
searchService.persist(node.getIdentifier(), queryNode);
QueryNode retrieved = searchService.retrieve(node.getIdentifier());
QueryImpl retrievedImpl = (QueryImpl) retrieved;
assertEquals(queryNode.toString(), retrieved.toString());
assertEquals(
TestUtils.getQueryAsString(searchQueryImpl, session),
TestUtils.getQueryAsString(retrievedImpl, session));
} finally {
node.remove();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment