/* * Copyright (C) 2003-2009 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. */ package org.exoplatform.services.jcr.impl.core.query; import org.exoplatform.services.jcr.config.WorkspaceEntry; import org.exoplatform.services.jcr.core.WorkspaceContainerFacade; import org.exoplatform.services.jcr.impl.core.NodeImpl; import org.exoplatform.services.jcr.impl.core.query.lucene.LuceneQueryBuilder; import org.exoplatform.services.jcr.impl.core.query.lucene.NodeIndexer; import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer; import org.exoplatform.services.jcr.storage.WorkspaceDataContainer; import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection; import java.io.ByteArrayInputStream; import java.util.ArrayList; import java.util.Calendar; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.jcr.Node; import javax.jcr.NodeIterator; import javax.jcr.Property; import javax.jcr.PropertyType; import javax.jcr.RepositoryException; import javax.jcr.Value; import javax.jcr.ValueFactory; import javax.jcr.query.InvalidQueryException; import javax.jcr.query.Query; import javax.jcr.query.QueryManager; import javax.jcr.query.QueryResult; import javax.jcr.query.Row; import javax.jcr.query.RowIterator; /** * Created by The eXo Platform SAS. * * <br>Date: * * @author <a href="karpenko.sergiy@gmail.com">Karpenko Sergiy</a> * @version $Id: TestQueryUsecases.java 111 2008-11-11 11:11:11Z serg $ */ public class TestQueryUsecases extends BaseQueryTest { /** * Get all nodes from repository. * * @throws Exception */ public void testSimpleGetAll() throws Exception { root.addNode("simplenode", "nt:unstructured"); Node doc1 = root.addNode("document1", "nt:file"); NodeImpl cont = (NodeImpl)doc1.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:encoding", "UTF-8"); cont.setProperty("jcr:data", new ByteArrayInputStream("".getBytes())); Node doc2 = root.addNode("document2", "nt:file"); cont = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:encoding", "UTF-8"); cont.setProperty("jcr:data", new ByteArrayInputStream("".getBytes())); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM nt:base ", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertTrue(3 < sqlsize); //make XPath query Query xq = qman.createQuery("//element(*,nt:base)", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertTrue(3 < xpathsize); assertEquals(sqlsize, xpathsize); // Check if we have the same amount of nodes in the database WorkspaceContainerFacade wsc = repository.getWorkspaceContainer(workspace.getName()); WorkspaceDataContainer container = (WorkspaceDataContainer)wsc.getComponent(WorkspaceDataContainer.class); if (container instanceof Reindexable) { assertEquals(sqlsize, ((Reindexable)container).getNodesCount().longValue()); } } /** * Get all files. * * @throws Exception */ public void testGetNodesByNodeType() throws Exception { root.addNode("simplenode", "nt:unstructured"); Node doc1 = root.addNode("document1", "nt:file"); NodeImpl cont = (NodeImpl)doc1.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:encoding", "UTF-8"); cont.setProperty("jcr:data", new ByteArrayInputStream("".getBytes())); Node doc2 = root.addNode("document2", "nt:file"); cont = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:encoding", "UTF-8"); cont.setProperty("jcr:data", new ByteArrayInputStream("".getBytes())); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM nt:file ", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(2, sqlsize); checkResult(res, new Node[]{doc1, doc2}); //make XPath query Query xq = qman.createQuery("//element(*,nt:file)", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(2, xpathsize); checkResult(xres, new Node[]{doc1, doc2}); } public void testGetNodesByMixinType() throws Exception { Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "First document"); Node doc2 = root.addNode("document1", "nt:file"); doc2.addMixin("mix:lockable"); NodeImpl cont = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:encoding", "UTF-8"); cont.setProperty("jcr:data", new ByteArrayInputStream("".getBytes())); Node doc3 = root.addNode("document2", "nt:file"); doc3.addMixin("mix:title"); doc3.setProperty("jcr:title", "Second document"); cont = (NodeImpl)doc3.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:encoding", "UTF-8"); cont.setProperty("jcr:data", new ByteArrayInputStream("".getBytes())); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM mix:title ", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(2, sqlsize); checkResult(res, new Node[]{doc1, doc3}); //make XPath query Query xq = qman.createQuery("//element(*,mix:title)", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(2, xpathsize); checkResult(xres, new Node[]{doc1, doc3}); } /** * Get Collumns. * * @throws Exception */ public void testGetColumns() throws Exception { root.addNode("simplenode", "nt:unstructured"); Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "Star wars"); doc1.setProperty("jcr:description", "Dart rules!!"); Node node2 = root.addNode("document2", "nt:file"); node2.addMixin("mix:title"); node2.setProperty("jcr:title", "Prison break"); node2.setProperty("jcr:description", "Run, Forest, run ))"); NodeImpl cont = (NodeImpl)node2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:data", "text"); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT jcr:title, jcr:description FROM mix:title ", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(2, sqlsize); checkResult(res, new Node[]{doc1, node2}); String[] expectedColumns = new String[]{"jcr:title", "jcr:description"}; String[][] expectedRows = new String[][]{{"Star wars", "Dart rules!!"}, {"Prison break", "Run, Forest, run ))"}}; checkColumns(res, expectedColumns, expectedRows, true); //make XPath query Query xq = qman.createQuery("//element(*,mix:title)/(@jcr:title | @jcr:description)", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(2, xpathsize); checkResult(xres, new Node[]{doc1, node2}); checkColumns(res, expectedColumns, expectedRows, true); } /** * Find all mix:title nodes with title 'Prison break'. * * @throws Exception */ public void testPropertyComparison() throws Exception { root.addNode("simplenode", "nt:unstructured"); Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "War and peace"); doc1.setProperty("jcr:description", "roman"); doc1.setProperty("jcr:pagecount", 1000); Node doc2 = root.addNode("document2", "nt:file"); doc2.addMixin("mix:title"); doc2.setProperty("jcr:title", "Cinderella"); doc2.setProperty("jcr:description", "fairytale"); doc2.setProperty("jcr:pagecount", 100); NodeImpl cont = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:data", "text"); Node doc3 = root.addNode("document3", "nt:unstructured"); doc3.addMixin("mix:title"); doc3.setProperty("jcr:title", "Puss in Boots"); doc3.setProperty("jcr:description", "fairytale"); doc3.setProperty("jcr:pagecount", 60); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT jcr:title FROM mix:title WHERE jcr:pagecount < 90", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(1, sqlsize); checkResult(res, new Node[]{doc3}); //make XPath query Query xq = qman.createQuery("//element(*,mix:title)[@jcr:pagecount < 90]/@jcr:title", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(1, xpathsize); checkResult(xres, new Node[]{doc3}); } public void testAndedConstraints() throws Exception { root.addNode("simplenode", "nt:unstructured"); Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "War and peace"); doc1.setProperty("jcr:description", "roman"); doc1.setProperty("jcr:pagecount", 1000); Node doc2 = root.addNode("document2", "nt:file"); doc2.addMixin("mix:title"); doc2.setProperty("jcr:title", "Cinderella"); doc2.setProperty("jcr:description", "fairytale"); doc2.setProperty("jcr:pagecount", 100); NodeImpl cont = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:data", "text"); Node doc3 = root.addNode("document3", "nt:unstructured"); doc3.addMixin("mix:title"); doc3.setProperty("jcr:title", "Puss in Boots"); doc3.setProperty("jcr:description", "fairytale"); doc3.setProperty("jcr:pagecount", 60); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM mix:title WHERE jcr:description = 'fairytale' AND jcr:pagecount > 90", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(1, sqlsize); checkResult(res, new Node[]{doc2}); //make XPath query Query xq = qman.createQuery("//element(*,mix:title)[@jcr:description='fairytale' and @jcr:pagecount > 90]", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(1, xpathsize); checkResult(xres, new Node[]{doc2}); } public void testORedConstraints() throws Exception { root.addNode("simplenode", "nt:unstructured"); Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "War and peace"); doc1.setProperty("jcr:description", "roman"); doc1.setProperty("jcr:pagecount", 1000); Node doc2 = root.addNode("document2", "nt:file"); doc2.addMixin("mix:title"); doc2.setProperty("jcr:title", "Cinderella"); doc2.setProperty("jcr:description", "fairytale"); doc2.setProperty("jcr:pagecount", 100); NodeImpl cont = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:data", "text"); Node doc3 = root.addNode("document3", "nt:unstructured"); doc3.addMixin("mix:title"); doc3.setProperty("jcr:title", "Puss in Boots"); doc3.setProperty("jcr:description", "fairytale"); doc3.setProperty("jcr:pagecount", 60); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM mix:title WHERE jcr:title = 'Cinderella' OR jcr:description = 'roman'", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(2, sqlsize); checkResult(res, new Node[]{doc1, doc2}); //make XPath query Query xq = qman.createQuery("//element(*,mix:title)[@jcr:title='Cinderella' or @jcr:description = 'roman']", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(2, xpathsize); checkResult(xres, new Node[]{doc1, doc2}); } /** * Find all mix:title nodes which title begins from 'P' symbol. * * @throws Exception */ public void testLIKEConstraint() throws Exception { root.addNode("simplenode", "nt:unstructured"); Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "Star wars"); doc1.setProperty("jcr:description", "Dart rules!!"); Node doc2 = root.addNode("document2", "nt:file"); doc2.addMixin("mix:title"); doc2.setProperty("jcr:title", "Prison break"); doc2.setProperty("jcr:description", "Run, Forest, run ))"); NodeImpl cont = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:data", "text"); Node doc3 = root.addNode("document3", "nt:unstructured"); doc3.addMixin("mix:title"); doc3.setProperty("jcr:title", "Panopticum"); doc3.setProperty("jcr:description", "It's imagine film )"); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM mix:title WHERE jcr:title LIKE 'P%'", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(2, sqlsize); checkResult(res, new Node[]{doc2, doc3}); //make XPath query Query xq = qman.createQuery("//element(*,mix:title)[jcr:like(@jcr:title, 'P%')]", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(2, xpathsize); checkResult(xres, new Node[]{doc2, doc3}); } public void testUPPERConstraint() throws Exception { root.addNode("simplenode", "nt:unstructured"); Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "CaseSensitive"); Node doc2 = root.addNode("document2", "nt:unstructured"); doc2.addMixin("mix:title"); doc2.setProperty("jcr:title", "casesensitive"); Node doc3 = root.addNode("document3", "nt:unstructured"); doc3.addMixin("mix:title"); doc3.setProperty("jcr:title", "caseSENSITIVE"); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM mix:title WHERE UPPER(jcr:title) = 'CASESENSITIVE'", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(3, sqlsize); checkResult(res, new Node[]{doc1, doc2, doc3}); q = qman.createQuery("SELECT * FROM mix:title WHERE LOWER(jcr:title) = 'casesensitive'", Query.SQL); res = q.execute(); sqlsize = res.getNodes().getSize(); assertEquals(3, sqlsize); checkResult(res, new Node[]{doc1, doc2, doc3}); //make XPath query Query xq = qman.createQuery("//element(*,mix:title)[fn:upper-case(@jcr:title)='CASESENSITIVE']", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(3, xpathsize); checkResult(xres, new Node[]{doc1, doc2, doc3}); xq = qman.createQuery("//element(*,mix:title)[fn:lower-case(@jcr:title)='casesensitive']", Query.XPATH); xres = xq.execute(); xpathsize = xres.getNodes().getSize(); assertEquals(3, xpathsize); checkResult(xres, new Node[]{doc1, doc2, doc3}); } /** * Find all mix:title nodes which title begins from 'P' symbol. * * @throws Exception */ public void testLikeWithEscapeSymbol() throws Exception { root.addNode("simplenode", "nt:unstructured"); Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "Porison break");//setProperty("jcr:title", "Star wars"); doc1.setProperty("jcr:description", "Dart rules!!"); Node doc2 = root.addNode("document2", "nt:file"); doc2.addMixin("mix:title"); doc2.setProperty("jcr:title", "P%rison break"); doc2.setProperty("jcr:description", "Run, Forest, run ))"); NodeImpl cont = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:data", "text"); Node doc3 = root.addNode("document3", "nt:unstructured"); doc3.addMixin("mix:title"); doc3.setProperty("jcr:title", "Panopticum"); doc3.setProperty("jcr:description", "It's imagine film )"); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM mix:title WHERE jcr:title LIKE 'P#%ri%' ESCAPE '#'", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(1, sqlsize); checkResult(res, new Node[]{doc2}); //make XPath query Query xq = qman.createQuery("//element(*,mix:title)[jcr:like(@jcr:title, 'P\\%ri%')]", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(1, xpathsize); checkResult(xres, new Node[]{doc2}); } /** * Find all mix:title nodes which title not begins from 'P' symbol. * * @throws Exception */ public void testNotConstraint() throws Exception { root.addNode("simplenode", "nt:unstructured"); Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "Star wars"); doc1.setProperty("jcr:description", "Dart rules!!"); Node doc2 = root.addNode("document2", "nt:file"); doc2.addMixin("mix:title"); doc2.setProperty("jcr:title", "Prison break"); doc2.setProperty("jcr:description", "Run, Forest, run ))"); NodeImpl cont = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:data", "text"); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM mix:title WHERE NOT jcr:title LIKE 'P%'", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(1, sqlsize); checkResult(res, new Node[]{doc1}); //make XPath query Query xq = qman.createQuery("//element(*,mix:title)[not(jcr:like(@jcr:title, 'P%'))]", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(1, xpathsize); checkResult(xres, new Node[]{doc1}); } /** * Find all documents do not contains description. * * @throws Exception */ public void testPropertyNotExist() throws Exception { Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "Star wars"); doc1.setProperty("jcr:description", "Dart rules!!"); Node doc2 = root.addNode("document2", "nt:file"); doc2.addMixin("mix:title"); doc2.setProperty("jcr:title", "Prison break"); doc2.setProperty("jcr:description", "Run, Forest, run ))"); NodeImpl cont = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:data", "text"); Node doc3 = root.addNode("document1", "nt:unstructured"); doc3.addMixin("mix:title"); doc3.setProperty("jcr:title", "Titanic"); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM mix:title WHERE jcr:description IS NULL", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(1, sqlsize); checkResult(res, new Node[]{doc3}); //make XPath query Query xq = qman.createQuery("//element(*,mix:title)[not(@jcr:description)]", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(1, xpathsize); checkResult(xres, new Node[]{doc3}); } /** * Find all documents contains description. * * @throws Exception */ public void testPropertyExist() throws Exception { Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "Star wars"); doc1.setProperty("jcr:description", "Dart rules!!"); Node doc2 = root.addNode("document2", "nt:file"); doc2.addMixin("mix:title"); doc2.setProperty("jcr:title", "Prison break"); doc2.setProperty("jcr:description", "Run, Forest, run ))"); NodeImpl cont = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:data", "text"); Node doc3 = root.addNode("document3", "nt:unstructured"); doc3.addMixin("mix:title"); doc3.setProperty("jcr:title", "Titanic"); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM mix:title WHERE jcr:description IS NOT NULL", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(2, sqlsize); checkResult(res, new Node[]{doc1, doc2}); //make XPath query Query xq = qman.createQuery("//element(*,mix:title)[@jcr:description]", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(2, xpathsize); checkResult(xres, new Node[]{doc1, doc2}); } /** * Find all documents contains description. * * @throws Exception */ public void testFulltextAllNodes() throws Exception { Node doc1 = root.addNode("document1", "nt:file"); NodeImpl cont1 = (NodeImpl)doc1.addNode("jcr:content", "nt:resource"); cont1.setProperty("jcr:mimeType", "text/plain"); cont1.setProperty("jcr:lastModified", Calendar.getInstance()); cont1.setProperty("jcr:data", "The quick brown fox jump over the lazy dog"); session.save(); Node doc2 = root.addNode("document2", "nt:file"); NodeImpl cont2 = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont2.setProperty("jcr:mimeType", "text/plain"); cont2.setProperty("jcr:lastModified", Calendar.getInstance()); cont2.setProperty("jcr:data", "Dogs do not like cats."); Node doc3 = root.addNode("document3", "nt:file"); NodeImpl cont3 = (NodeImpl)doc3.addNode("jcr:content", "nt:resource"); cont3.setProperty("jcr:mimeType", "text/plain"); cont3.setProperty("jcr:lastModified", Calendar.getInstance()); cont3.setProperty("jcr:data", "Cats jumping high."); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM nt:resource WHERE CONTAINS(*,'do')", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(1, sqlsize); checkResult(res, new Node[]{cont2}); //make XPath query Query xq = qman.createQuery("//element(*,nt:resource)[jcr:contains(.,'cats')]", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(2, xpathsize); checkResult(xres, new Node[]{cont2, cont3}); } public void testFulltextAllNodes2() throws Exception { Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "Star wars"); doc1.setProperty("jcr:description", "Dart rules!!"); Node doc2 = root.addNode("document2", "nt:file"); doc2.addMixin("mix:title"); doc2.setProperty("jcr:title", "Prison break."); doc2.setProperty("jcr:description", "Run, Forest, run ))"); NodeImpl cont = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:data", "text"); Node doc3 = root.addNode("document3", "nt:unstructured"); doc3.addMixin("mix:title"); doc3.setProperty("jcr:title", "Titanic"); doc3.setProperty("jcr:description", "The aisberg break ship."); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM mix:title WHERE CONTAINS(*,'break')", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(2, sqlsize); checkResult(res, new Node[]{doc2, doc3}); //make XPath query Query xq = qman.createQuery("//element(*,mix:title)[jcr:contains(.,'break')]", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(2, xpathsize); checkResult(xres, new Node[]{doc2, doc3}); } public void testFulltextByProperty() throws Exception { root.addNode("simplenode", "nt:unstructured"); Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "Star wars"); doc1.setProperty("jcr:description", "Quick brown fox jumps over the lazy dog."); Node doc2 = root.addNode("document2", "nt:file"); doc2.addMixin("mix:title"); doc2.setProperty("jcr:title", "Prison break"); doc2.setProperty("jcr:description", "Brown fox live in forest."); NodeImpl cont = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:data", "text"); Node doc3 = root.addNode("document3", "nt:unstructured"); doc3.addMixin("mix:title"); doc3.setProperty("jcr:title", "Star wars"); doc3.setProperty("jcr:description", "fox is a nice animal."); Node doc4 = root.addNode("document4", "nt:unstructured"); doc4.setProperty("jcr:title", "Star wars"); doc4.setProperty("jcr:description", "There is forest word too."); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM mix:title WHERE CONTAINS(jcr:description, 'forest')", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(1, sqlsize); checkResult(res, new Node[]{doc2}); // Check order //make XPath query Query xq = qman.createQuery("//element(*,mix:title)[jcr:contains(@jcr:description, 'forest')]", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(1, xpathsize); checkResult(xres, new Node[]{doc2}); } public void testExactPath() throws Exception { Node r1 = root.addNode("root1"); Node r2 = r1.addNode("root2"); Node node1 = r2.addNode("node1", "nt:unstructured"); r2.addNode("node1", "nt:unstructured"); r2.addNode("node2", "nt:unstructured"); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM nt:unstructured WHERE jcr:path = '/root1/root2/node1[1]'", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(1, sqlsize); checkResult(res, new Node[]{node1}); //make XPath query Query xq = qman.createQuery("/jcr:root/root1[1]/root2[1]/element(node1,nt:unstructured)[1]", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(1, xpathsize); checkResult(xres, new Node[]{node1}); } public void testFindAllSameName() throws Exception { Node r1 = root.addNode("root1"); Node r2 = r1.addNode("root2"); Node node1 = r2.addNode("node1", "nt:unstructured"); Node node1_2 = r2.addNode("node1", "nt:unstructured"); r2.addNode("node2", "nt:unstructured"); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM nt:unstructured WHERE jcr:path LIKE '/root1/root2/node1[%]'", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(2, sqlsize); checkResult(res, new Node[]{node1, node1_2}); //make XPath query Query xq = qman.createQuery("/jcr:root/root1[1]/root2[1]/element(node1,nt:unstructured)", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(2, xpathsize); checkResult(xres, new Node[]{node1, node1_2}); } public void testChildNodes() throws Exception { Node r1 = root.addNode("root1", "nt:folder"); Node r2 = r1.addNode("root2", "nt:folder"); Node subdir1 = r2.addNode("subdir1", "nt:folder"); subdir1.addNode("node1", "nt:folder"); Node node2 = r2.addNode("node2", "nt:folder"); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery( "SELECT * FROM nt:folder WHERE jcr:path LIKE '/root1/root2/%' AND NOT jcr:path LIKE '/root1/root2/%/%'", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(2, sqlsize); checkResult(res, new Node[]{subdir1, node2}); //make XPath query Query xq = qman.createQuery("/jcr:root/root1[1]/root2[1]/element(*,nt:folder)", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(2, xpathsize); checkResult(xres, new Node[]{subdir1, node2}); } public void testDescendantNodes() throws Exception { Node r1 = root.addNode("root1", "nt:folder"); Node r2 = r1.addNode("root2", "nt:folder"); Node subdir1 = r2.addNode("subdir1", "nt:folder"); Node node1 = subdir1.addNode("node1", "nt:folder"); Node node2 = r2.addNode("node2", "nt:folder"); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM nt:folder WHERE jcr:path LIKE '/root1/root2/%'", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(3, sqlsize); checkResult(res, new Node[]{subdir1, node1, node2}); //make XPath query Query xq = qman.createQuery("/jcr:root/root1[1]/root2[1]//element(*,nt:folder)", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(3, xpathsize); checkResult(xres, new Node[]{subdir1, node1, node2}); } /*** * Descendant or self is unsupported. * * @throws Exception */ public void testDescendantOrSelf() throws Exception { // make SQL query QueryManager qman = this.workspace.getQueryManager(); try { Query q = qman.createQuery( "SELECT * FROM nt:folder WHERE jcr:path = '/root1/root2' OR jcr:path LIKE '/root1/root2/%'", Query.SQL); q.execute(); fail("Secendant or self query is unsupported."); } catch (InvalidQueryException e) { // thats ok descendant or self is unsupported } } public void testGetAllColumns() throws Exception { root.addNode("simplenode", "nt:unstructured"); Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "Star wars"); doc1.setProperty("jcr:description", "Dart rules!!"); Node doc2 = root.addNode("document2", "nt:file"); doc2.addMixin("mix:title"); doc2.setProperty("jcr:title", "Prison break"); doc2.setProperty("jcr:description", "Run, Forest, run ))"); NodeImpl cont = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:data", "text"); Node doc3 = root.addNode("document3", "nt:unstructured"); doc3.addMixin("mix:title"); doc3.setProperty("jcr:title", "Panopticum"); doc3.setProperty("jcr:description", "It's imagine film )"); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM mix:title", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(3, sqlsize); checkResult(res, new Node[]{doc1, doc2, doc3}); String[] expectedColumns = new String[]{"jcr:title", "jcr:description", "jcr:pagecount", "jcr:path"}; String[][] expectedRows = new String[][]{{"Star wars", "Dart rules!!", null, "/document1"}, {"Prison break", "Run, Forest, run ))", null, "/document2"}, {"Panopticum", "It's imagine film )", null, "/document3"}}; checkColumns(res, expectedColumns, expectedRows, true); //make XPath query Query xq = qman.createQuery("//element(*,mix:title)", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(3, xpathsize); checkResult(xres, new Node[]{doc1, doc2, doc3}); } public void testOrderByScore() throws Exception { root.addNode("simplenode", "nt:unstructured"); Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "Star wars"); doc1.setProperty("jcr:description", "Quick brown fox jumps over the lazy dog."); Node doc2 = root.addNode("document2", "nt:file"); doc2.addMixin("mix:title"); doc2.setProperty("jcr:title", "Prison break"); doc2.setProperty("jcr:description", "Brown fox live in forest."); NodeImpl cont = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont.setProperty("jcr:mimeType", "text/plain"); cont.setProperty("jcr:lastModified", Calendar.getInstance()); cont.setProperty("jcr:data", "text"); Node doc3 = root.addNode("document3", "nt:unstructured"); doc3.addMixin("mix:title"); doc3.setProperty("jcr:title", "Star wars"); doc3.setProperty("jcr:description", "fox is a nice animal."); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery( "SELECT * FROM mix:title WHERE CONTAINS(*, 'brown OR fox OR jumps') ORDER BY jcr:score() ASC", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(3, sqlsize); checkOrder(res, new Node[]{doc3, doc2, doc1}); //make XPath query Query xq = qman.createQuery("//element(*,mix:title)[jcr:contains(., 'brown OR fox OR jumps')] order by jcr:score()", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(3, xpathsize); checkOrder(res, new Node[]{doc3, doc2, doc1}); } public void testOrderByLongDesc() throws Exception { root.addNode("simplenode", "nt:unstructured"); Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "Star wars"); doc1.setProperty("jcr:description", "Quick brown fox jumps over the lazy dog."); doc1.setProperty("jcr:pagecount", 4); Node doc2 = root.addNode("document2", "nt:unstructured"); doc2.addMixin("mix:title"); doc2.setProperty("jcr:title", "Prison break"); doc2.setProperty("jcr:description", "Brown fox live in forest."); doc2.setProperty("jcr:pagecount", 7); Node doc3 = root.addNode("document3", "nt:unstructured"); doc3.addMixin("mix:title"); doc3.setProperty("jcr:title", "Star wars"); doc3.setProperty("jcr:description", "fox is a nice animal."); doc3.setProperty("jcr:pagecount", 1); session.save(); QueryManager qman = this.workspace.getQueryManager(); //make XPath query Query xq = qman.createQuery("//element(*,mix:title) order by @jcr:pagecount descending", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(3, xpathsize); checkResult(xres, new Node[]{doc1, doc2, doc3}); checkOrder(xres, new Node[]{doc2, doc1, doc3}); } public void testOrderByProperty() throws Exception { root.addNode("simplenode", "nt:unstructured"); Node doc1 = root.addNode("document1", "nt:unstructured"); doc1.addMixin("mix:title"); doc1.setProperty("jcr:title", "Star wars"); doc1.setProperty("jcr:description", "Quick brown fox jumps over the lazy dog."); doc1.setProperty("jcr:pagecount", 4); Node doc2 = root.addNode("document2", "nt:unstructured"); doc2.addMixin("mix:title"); doc2.setProperty("jcr:title", "Prison break"); doc2.setProperty("jcr:description", "Brown fox live in forest."); doc2.setProperty("jcr:pagecount", 7); Node doc3 = root.addNode("document3", "nt:unstructured"); doc3.addMixin("mix:title"); doc3.setProperty("jcr:title", "Star wars"); doc3.setProperty("jcr:description", "fox is a nice animal."); doc3.setProperty("jcr:pagecount", 1); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM mix:title ORDER BY jcr:pagecount ASC", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(3, sqlsize); checkResult(res, new Node[]{doc1, doc2, doc3}); checkOrder(res, new Node[]{doc3, doc1, doc2}); //make XPath query Query xq = qman.createQuery("//element(*,mix:title) order by @jcr:pagecount ascending", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(3, xpathsize); checkResult(xres, new Node[]{doc1, doc2, doc3}); checkOrder(xres, new Node[]{doc3, doc1, doc2}); } public void testSearchByName() throws Exception { Node doc1 = root.addNode("document1", "nt:file"); NodeImpl cont1 = (NodeImpl)doc1.addNode("jcr:content", "nt:resource"); cont1.setProperty("jcr:mimeType", "text/plain"); cont1.setProperty("jcr:lastModified", Calendar.getInstance()); cont1.setProperty("jcr:data", "The quick brown fox jump over the lazy dog"); session.save(); Node doc2 = root.addNode("document2", "nt:file"); NodeImpl cont2 = (NodeImpl)doc2.addNode("jcr:content", "nt:resource"); cont2.setProperty("jcr:mimeType", "text/plain"); cont2.setProperty("jcr:lastModified", Calendar.getInstance()); cont2.setProperty("jcr:data", "Dogs do not like cats."); Node doc3 = root.addNode("document1", "nt:file"); NodeImpl cont3 = (NodeImpl)doc3.addNode("jcr:content", "nt:resource"); cont3.setProperty("jcr:mimeType", "text/plain"); cont3.setProperty("jcr:lastModified", Calendar.getInstance()); cont3.setProperty("jcr:data", "Cats jumping high."); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM nt:file WHERE fn:name() = 'document1'", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(2, sqlsize); checkResult(res, new Node[]{doc1, doc3}); //make XPath query Query xq = qman.createQuery("//element(*,nt:file)[fn:name() = 'document1']", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(2, xpathsize); checkResult(xres, new Node[]{doc1, doc3}); } public void testMultivalueProperty() throws Exception { Node doc1 = root.addNode("node1", "nt:unstructured"); doc1.setProperty("multiprop", new String[]{"one", "two"}); Node doc2 = root.addNode("node2", "nt:unstructured"); doc2.setProperty("multiprop", new String[]{"one", "two", "three"}); Node doc3 = root.addNode("node3", "nt:unstructured"); doc3.setProperty("multiprop", new String[]{"one", "five"}); session.save(); // make SQL query QueryManager qman = this.workspace.getQueryManager(); Query q = qman.createQuery("SELECT * FROM nt:unstructured WHERE multiprop = 'one' AND multiprop = 'two'", Query.SQL); QueryResult res = q.execute(); long sqlsize = res.getNodes().getSize(); assertEquals(2, sqlsize); checkResult(res, new Node[]{doc1, doc2}); //make XPath query Query xq = qman.createQuery("//element(*,nt:unstructured)[@multiprop = 'one' and @multiprop = 'two']", Query.XPATH); QueryResult xres = xq.execute(); long xpathsize = xres.getNodes().getSize(); assertEquals(2, xpathsize); checkResult(xres, new Node[]{doc1, doc2}); } /** * Checks if the result set contains exactly the <code>nodes</code>. * * @param result the query result. * @param nodes the expected nodes in the result set. */ protected void checkResult(QueryResult result, Node[] nodes) throws RepositoryException { // collect paths String[][] vals = new String[(int)result.getNodes().getSize()][result.getColumnNames().length]; RowIterator rit = result.getRows(); int j = 0; while (rit.hasNext()) { Row r = rit.nextRow(); Value[] v = r.getValues(); for (int i = 0; i < v.length; i++) { vals[j][i] = (v[i] != null) ? v[i].getString() : "null"; } j++; } Set<String> expectedPaths = new HashSet<String>(); for (int i = 0; i < nodes.length; i++) { expectedPaths.add(nodes[i].getPath()); } Set<String> resultPaths = new HashSet<String>(); for (NodeIterator it = result.getNodes(); it.hasNext();) { resultPaths.add(it.nextNode().getPath()); } comparePaths(expectedPaths, resultPaths, false); } private void checkOrder(QueryResult res, Node[] expectedNodes) throws RepositoryException { NodeIterator ni = res.getNodes(); List<String> list = new ArrayList<String>(); while (ni.hasNext()) { list.add(ni.nextNode().getPath()); } ni = res.getNodes(); for (int i = 0; i < expectedNodes.length; i++) { Node expNode = expectedNodes[i]; if (!ni.hasNext()) { fail("Result do not contain node " + expNode.getName()); } assertEquals("Node not found or not in expected order " + expNode.getPath(), expNode.getPath(), ni.nextNode() .getPath()); } assertFalse("Node has more than expected nodes.", ni.hasNext()); } private void comparePaths(Set<String> expectedPaths, Set<String> resultPaths, boolean canContainMore) { // check if all expected are in result for (Iterator<String> it = expectedPaths.iterator(); it.hasNext();) { String path = it.next(); assertTrue(path + " is not part of the result set", resultPaths.contains(path)); } if (!canContainMore) { // check result does not contain more than expected for (Iterator<String> it = resultPaths.iterator(); it.hasNext();) { String path = it.next(); assertTrue(path + " is not expected to be part of the result set. " + " Total size:" + resultPaths.size(), expectedPaths.contains(path)); } } } private void checkColumns(QueryResult res, String[] columns, String[][] values, boolean hasMoreColumns) throws RepositoryException { // check column list String[] rcol = res.getColumnNames(); if (!hasMoreColumns) { assertEquals("Columns count not equal to expected set", rcol.length, columns.length); } else { assertTrue(rcol.length >= columns.length); } for (String colname : columns) { boolean finded = false; for (String rescolname : rcol) { if (colname.equals(rescolname)) { finded = true; } } assertTrue("Column name not founded : " + colname, finded); } //check values RowIterator rit = res.getRows(); for (String[] row : values) { if (!rit.hasNext()) { fail("Expected row not exist."); } Row resrow = rit.nextRow(); for (int j = 0; j < columns.length; j++) { Value val = resrow.getValue(columns[j]); assertEquals(row[j], (val != null) ? val.getString() : null); } } assertFalse("There is more rows than expected", rit.hasNext()); } /** * Represents usecase searching by {@link PropertyType.PATH} property. Reveals bug, when * {@link NodeIndexer} addValues() method adds string representation of node path without * index and {@link LuceneQueryBuilder} getStringValues() method return terms with them. */ public void testJCR_1910() throws Exception { Node rootNode = session.getRootNode(); Node aNode = rootNode.addNode("totmr_a", "exo:JCR_1910"); Node bNode = rootNode.addNode("totmr_b", "exo:JCR_1910"); ValueFactory valueFactory = rootNode.getSession().getValueFactory(); Value value = valueFactory.createValue(aNode.getPath(), PropertyType.PATH); bNode.setProperty("ref", value); Property ref = bNode.getProperty("ref"); assertEquals(PropertyType.PATH, ref.getType()); rootNode.getSession().save(); QueryManager mgr = rootNode.getSession().getWorkspace().getQueryManager(); Query query = mgr.createQuery("SELECT * FROM nt:base WHERE ref='" + aNode.getPath() + "'", Query.SQL); QueryResult result = query.execute(); NodeIterator i = result.getNodes(); assertTrue(i.hasNext()); Node found = i.nextNode(); assertSame(bNode, found); assertFalse(i.hasNext()); } }