[dna-commits] DNA SVN: r1508 - in trunk: dna-jcr/src/main/java/org/jboss/dna/jcr/xpath and 6 other directories.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Thu Dec 31 16:36:01 EST 2009


Author: rhauch
Date: 2009-12-31 16:36:01 -0500 (Thu, 31 Dec 2009)
New Revision: 1508

Added:
   trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/query/HasValueQuery.java
Modified:
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryQueryManager.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslator.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslatorTest.java
   trunk/dna-jcr/src/test/resources/tck/repositoryForTckTests.xml
   trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/AbstractLuceneSearchEngine.java
   trunk/extensions/dna-search-lucene/src/test/java/org/jboss/dna/search/lucene/LuceneSearchEngineTest.java
Log:
DNA-468 This commit includes several fixes for the XPath query functionality, some fixes for several tests, and some new unit tests.  At this point there are still some outstanding issues with certain XPath tests, but these are being tracked under DNA-612 and DNA-613.

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java	2009-12-31 18:53:06 UTC (rev 1507)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java	2009-12-31 21:36:01 UTC (rev 1508)
@@ -297,6 +297,10 @@
             this.variables = null;
         }
 
+        protected QueryCommand getCommand() {
+            return query;
+        }
+
         /**
          * {@inheritDoc}
          * 

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryQueryManager.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryQueryManager.java	2009-12-31 18:53:06 UTC (rev 1507)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryQueryManager.java	2009-12-31 21:36:01 UTC (rev 1508)
@@ -26,6 +26,7 @@
 import java.io.File;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import javax.jcr.RepositoryException;
@@ -287,6 +288,8 @@
             };
             this.queryEngine = new QueryEngine(planner, optimizer, processor);
 
+            // Index any existing content ...
+            reindexContent();
         }
 
         protected void process( Changes changes ) {
@@ -321,11 +324,13 @@
          */
         @Override
         public void reindexContent() {
-            // Index the existing content ...
-            Graph graph = Graph.create(sourceName, connectionFactory, context);
+            // Get the workspace names ...
+            Set<String> workspaces = Graph.create(sourceName, connectionFactory, context).getWorkspaces();
+
+            // Index the existing content (this obtains a connection and possibly locks the source) ...
             SearchEngineIndexer indexer = new SearchEngineIndexer(context, searchEngine, connectionFactory);
             try {
-                for (String workspace : graph.getWorkspaces()) {
+                for (String workspace : workspaces) {
                     indexer.index(workspace);
                 }
             } finally {

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslator.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslator.java	2009-12-31 18:53:06 UTC (rev 1507)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslator.java	2009-12-31 21:36:01 UTC (rev 1508)
@@ -30,7 +30,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.property.PropertyType;
 import org.jboss.dna.graph.query.QueryBuilder;
 import org.jboss.dna.graph.query.QueryBuilder.ConstraintBuilder;
@@ -38,7 +37,6 @@
 import org.jboss.dna.graph.query.model.QueryCommand;
 import org.jboss.dna.graph.query.model.TypeSystem;
 import org.jboss.dna.graph.query.parse.InvalidQueryException;
-import org.jboss.dna.jcr.JcrNtLexicon;
 import org.jboss.dna.jcr.xpath.XPath.And;
 import org.jboss.dna.jcr.xpath.XPath.AttributeNameTest;
 import org.jboss.dna.jcr.xpath.XPath.AxisStep;
@@ -153,12 +151,12 @@
                 AxisStep axis = (AxisStep)step;
                 NodeTest nodeTest = axis.getNodeTest();
                 if (nodeTest instanceof NameTest) {
-                    if (appliesToPathConstraint(axis.getPredicates())) {
-                        // Can go into the path constraint ...
+                    NameTest nameTest = (NameTest)nodeTest;
+                    if (!nameTest.isWildcard()) {
                         path.add(step);
-                    } else {
+                    }
+                    if (!appliesToPathConstraint(axis.getPredicates())) {
                         // The constraints are more complicated, so we need to define a new source/table ...
-                        // path.add(step);
                         tableName = translateSource(tableName, path, where);
                         translatePredicates(axis.getPredicates(), tableName, where);
                         path.clear();
@@ -302,19 +300,18 @@
                                       ConstraintBuilder where ) {
         if (path.size() == 0) {
             // This is a query against the root node ...
-            ExecutionContext context = new ExecutionContext();
             String alias = newAlias();
-            builder.from(JcrNtLexicon.BASE.getString(context.getNamespaceRegistry()) + " AS " + alias);
+            builder.from("nt:base AS " + alias);
             where.path(alias).isEqualTo("/");
             return alias;
         }
         String alias = newAlias();
         if (tableName != null) {
             // This is after some element(...) steps, so we need to join ...
-            builder.joinAllNodesAs(alias);
+            builder.join("nt:base AS " + alias);
         } else {
             // This is the only part of the query ...
-            builder.fromAllNodesAs(alias);
+            builder.from("nt:base AS " + alias);
         }
         tableName = alias;
         if (path.size() == 1 && path.get(0).collapse() instanceof NameTest) {
@@ -341,7 +338,7 @@
         NameTest typeName = elementTest.getTypeName();
         if (typeName.isWildcard()) {
             tableName = newAlias();
-            builder.fromAllNodesAs(tableName);
+            builder.from("nt:base AS " + tableName);
         } else {
             if (typeName.getLocalTest() == null) {
                 throw new InvalidQueryException(
@@ -417,7 +414,7 @@
             // This adds the criteria that the child node exists ...
             NameTest childName = (NameTest)predicate;
             String alias = newAlias();
-            builder.joinAllNodesAs(alias).onChildNode(tableName, alias);
+            builder.join("nt:base AS " + alias).onChildNode(tableName, alias);
             if (!childName.isWildcard()) where.nodeName(alias).isEqualTo(nameFrom(childName));
             tableName = alias;
         } else if (predicate instanceof Comparison) {
@@ -535,7 +532,7 @@
                 } else if (param1 instanceof NameTest) {
                     // refers to child node, so we need to add a join ...
                     String alias = newAlias();
-                    builder.joinAllNodesAs(alias).onChildNode(tableName, alias);
+                    builder.join("nt:base AS " + alias).onChildNode(tableName, alias);
                     // Now add the criteria ...
                     where.search(alias, value);
                     tableName = alias;
@@ -583,7 +580,7 @@
                 // Special case where this is similar to '[a/@id]'
                 NameTest childName = (NameTest)firstStep;
                 String alias = newAlias();
-                builder.joinAllNodesAs(alias).onChildNode(tableName, alias);
+                builder.join("nt:base AS " + alias).onChildNode(tableName, alias);
                 if (!childName.isWildcard()) {
                     where.nodeName(alias).isEqualTo(nameFrom(childName));
                 }
@@ -592,12 +589,12 @@
             if (firstStep instanceof DescendantOrSelf) {
                 // Special case where this is similar to '[a/@id]'
                 String alias = newAlias();
-                builder.joinAllNodesAs(alias).onDescendant(tableName, alias);
+                builder.join("nt:base AS " + alias).onDescendant(tableName, alias);
                 return translatePredicate(new PathExpression(true, steps.subList(1, steps.size())), alias, where);
             }
             // Add the join ...
             String alias = newAlias();
-            builder.joinAllNodesAs(alias).onDescendant(tableName, alias);
+            builder.join("nt:base AS " + alias).onDescendant(tableName, alias);
             // Now add the criteria ...
             translatePathExpressionConstraint(pathExpr, where, alias);
         } else {

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java	2009-12-31 18:53:06 UTC (rev 1507)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java	2009-12-31 21:36:01 UTC (rev 1508)
@@ -44,6 +44,7 @@
 import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
 import org.jboss.dna.graph.property.Name;
 import org.jboss.dna.graph.property.Path.Segment;
+import org.jboss.dna.jcr.JcrQueryManager.JcrQuery;
 import org.jboss.dna.jcr.JcrRepository.Option;
 import org.jboss.dna.jcr.JcrRepository.QueryLanguage;
 import org.junit.After;
@@ -79,6 +80,7 @@
     private static JcrEngine engine;
     private static JcrRepository repository;
     private Session session;
+    private boolean print;
 
     @BeforeClass
     public static void beforeAll() throws Exception {
@@ -110,6 +112,13 @@
                 stream.close();
             }
 
+            // Create a branch that contains some same-name-siblings ...
+            Node other = session.getRootNode().addNode("Other", "nt:unstructured");
+            other.addNode("NodeA", "nt:unstructured");
+            other.addNode("NodeA", "nt:unstructured");
+            other.addNode("NodeA", "nt:unstructured");
+            session.save();
+
             // Prime creating a first XPath query and SQL query ...
             session.getWorkspace().getQueryManager().createQuery("//element(*,nt:unstructured)", Query.XPATH);
             session.getWorkspace().getQueryManager().createQuery("SELECT * FROM [nt:base]", JcrRepository.QueryLanguage.SQL);
@@ -131,6 +140,7 @@
 
     @Before
     public void beforeEach() throws Exception {
+        print = false;
         // Obtain a session using the anonymous login capability, which we granted READ privilege
         session = repository.login();
     }
@@ -162,6 +172,21 @@
         return result;
     }
 
+    protected void assertResults( Query query,
+                                  QueryResult result,
+                                  long numberOfResults ) throws RepositoryException {
+        assertThat(query, is(notNullValue()));
+        assertThat(result, is(notNullValue()));
+        if (print) {
+            System.out.println();
+            System.out.println(query.getLanguage() + ": " + query.getStatement());
+            System.out.println(" --> : " + ((JcrQuery)query).getCommand());
+            System.out.println(result);
+        }
+        assertThat(result.getNodes().getSize(), is(numberOfResults));
+        assertThat(result.getRows().getSize(), is(numberOfResults));
+    }
+
     protected void assertResultsHaveColumns( QueryResult result,
                                              String... columnNames ) throws RepositoryException {
         Set<String> expectedNames = new HashSet<String>();
@@ -187,7 +212,7 @@
         assertThat(node.hasNode("Sports"), is(true));
         assertThat(node.hasNode("Utility"), is(true));
         assertThat(node.hasNode("Hybrid"), is(true));
-        System.out.println(node.getNode("Hybrid").getNodes().nextNode().getPath());
+        // System.out.println(node.getNode("Hybrid").getNodes().nextNode().getPath());
         assertThat(node.hasNode("Hybrid/Toyota Prius"), is(true));
         assertThat(node.getPrimaryNodeType().getName(), is("nt:unstructured"));
     }
@@ -207,8 +232,8 @@
         assertThat(query, is(notNullValue()));
         QueryResult result = query.execute();
         assertThat(result, is(notNullValue()));
+        assertResults(query, result, 22);
         assertResultsHaveColumns(result, "jcr:primaryType");
-        // System.out.println(result);
     }
 
     // ----------------------------------------------------------------------------------------------------------------
@@ -219,6 +244,7 @@
     public void shouldBeAbleToCreateXPathQuery() throws RepositoryException {
         Query query = session.getWorkspace().getQueryManager().createQuery("//element(*,nt:unstructured)", Query.XPATH);
         assertThat(query, is(notNullValue()));
+        assertResults(query, query.execute(), 21);
     }
 
     @Test
@@ -226,7 +252,7 @@
         Query query = session.getWorkspace().getQueryManager().createQuery("//element(*,nt:base)", Query.XPATH);
         assertThat(query, is(notNullValue()));
         QueryResult result = query.execute();
-        assertThat(result, is(notNullValue()));
+        assertResults(query, result, 22);
         assertResultsHaveColumns(result, "jcr:primaryType", "jcr:path", "jcr:score");
     }
 
@@ -235,17 +261,39 @@
         Query query = session.getWorkspace().getQueryManager().createQuery("//element(*,nt:unstructured)", Query.XPATH);
         assertThat(query, is(notNullValue()));
         QueryResult result = query.execute();
+        assertResults(query, result, 21);
         assertThat(result, is(notNullValue()));
         assertResultsHaveColumns(result, "jcr:primaryType", "jcr:path", "jcr:score");
     }
 
     @Test
+    public void shouldBeAbleToExecuteXPathQueryToFindSameNameSiblingsByIndex() throws RepositoryException {
+        Query query = session.getWorkspace().getQueryManager().createQuery("/jcr:root/Other/NodeA", Query.XPATH);
+        assertThat(query, is(notNullValue()));
+        QueryResult result = query.execute();
+        print = true;
+        assertResults(query, result, 1);
+        assertThat(result, is(notNullValue()));
+        assertThat(result.getNodes().nextNode().getIndex(), is(1));
+        assertResultsHaveColumns(result, "jcr:primaryType", "jcr:path", "jcr:score");
+
+        query = session.getWorkspace().getQueryManager().createQuery("/jcr:root/Other/NodeA[2]", Query.XPATH);
+        assertThat(query, is(notNullValue()));
+        result = query.execute();
+        print = true;
+        assertResults(query, result, 1);
+        assertThat(result, is(notNullValue()));
+        assertThat(result.getNodes().nextNode().getIndex(), is(2));
+        assertResultsHaveColumns(result, "jcr:primaryType", "jcr:path", "jcr:score");
+    }
+
+    @Test
     public void shouldBeAbleToExecuteXPathQueryToFindAllCarNodes() throws RepositoryException {
         Query query = session.getWorkspace().getQueryManager().createQuery("//element(*,car:Car)", Query.XPATH);
         assertThat(query, is(notNullValue()));
         QueryResult result = query.execute();
         assertThat(result, is(notNullValue()));
-        // System.out.println(result);
+        assertResults(query, result, 12);
         assertResultsHaveColumns(result,
                                  "jcr:primaryType",
                                  "jcr:path",
@@ -268,18 +316,27 @@
         Query query = session.getWorkspace().getQueryManager().createQuery("/jcr:root", Query.XPATH);
         assertThat(query, is(notNullValue()));
         QueryResult result = query.execute();
+        assertResults(query, result, 1);
+        assertResultsHaveColumns(result, "jcr:primaryType", "jcr:path", "jcr:score");
+    }
+
+    @Test
+    public void shouldBeAbleToExecuteXPathQueryToFindChildOfRootNode() throws RepositoryException {
+        Query query = session.getWorkspace().getQueryManager().createQuery("/jcr:root/Cars", Query.XPATH);
+        assertThat(query, is(notNullValue()));
+        QueryResult result = query.execute();
         assertThat(result, is(notNullValue()));
-        // System.out.println(result);
+        assertResults(query, result, 1);
         assertResultsHaveColumns(result, "jcr:primaryType", "jcr:path", "jcr:score");
     }
 
-    // @Test
-    // public void shouldBeAbleToExecuteXPathQueryToFindChildOfRootNode() throws RepositoryException {
-    // Query query = session.getWorkspace().getQueryManager().createQuery("/jcr:root/Cars", Query.XPATH);
-    // assertThat(query, is(notNullValue()));
-    // QueryResult result = query.execute();
-    // assertThat(result, is(notNullValue()));
-    // System.out.println(result);
-    // assertResultsHaveColumns(result, "jcr:primaryType", "jcr:path", "jcr:score");
-    // }
+    @Test
+    public void shouldBeAbleToExecuteXPathQueryToFindChildOfRootNodeWithTypeCriteria() throws RepositoryException {
+        Query query = session.getWorkspace().getQueryManager().createQuery("/jcr:root/Cars[@jcr:primaryType]", Query.XPATH);
+        assertThat(query, is(notNullValue()));
+        QueryResult result = query.execute();
+        assertThat(result, is(notNullValue()));
+        assertResults(query, result, 1);
+        assertResultsHaveColumns(result, "jcr:primaryType", "jcr:path", "jcr:score");
+    }
 }

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java	2009-12-31 18:53:06 UTC (rev 1507)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java	2009-12-31 21:36:01 UTC (rev 1508)
@@ -177,7 +177,7 @@
             addTestSuite(org.apache.jackrabbit.test.api.RepositoryLoginTest.class);
 
             // These might not all be level one tests
-            // addTestSuite(org.apache.jackrabbit.test.api.query.XPathPosIndexTest.class);
+            addTestSuite(org.apache.jackrabbit.test.api.query.XPathPosIndexTest.class);
             // addTestSuite(org.apache.jackrabbit.test.api.query.XPathDocOrderTest.class);
             // addTestSuite(org.apache.jackrabbit.test.api.query.XPathOrderByTest.class);
             addTestSuite(org.apache.jackrabbit.test.api.query.XPathJcrPathTest.class);
@@ -188,7 +188,7 @@
             addTestSuite(org.apache.jackrabbit.test.api.query.GetSupportedQueryLanguagesTest.class);
             addTestSuite(org.apache.jackrabbit.test.api.query.GetPropertyNamesTest.class);
             addTestSuite(org.apache.jackrabbit.test.api.query.PredicatesTest.class);
-            // addTestSuite(org.apache.jackrabbit.test.api.query.SimpleSelectionTest.class);
+            addTestSuite(org.apache.jackrabbit.test.api.query.SimpleSelectionTest.class);
 
             // The tests in this suite are level one
             addTest(org.apache.jackrabbit.test.api.nodetype.TestAll.suite());

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslatorTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslatorTest.java	2009-12-31 18:53:06 UTC (rev 1507)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslatorTest.java	2009-12-31 21:36:01 UTC (rev 1508)
@@ -65,12 +65,12 @@
 
     @Test
     public void shouldTranslateFromXPathOfAnyNode() {
-        assertThat(xpath("//element(*)"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1"));
-        assertThat(xpath("/jcr:root//element(*)"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1"));
-        assertThat(xpath("//*"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1"));
-        assertThat(xpath("/jcr:root//*"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1"));
-        assertThat(xpath("//."), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1"));
-        assertThat(xpath("/jcr:root//."), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1"));
+        assertThat(xpath("//element(*)"), isSql("SELECT * FROM [nt:base] AS nodeSet1"));
+        assertThat(xpath("/jcr:root//element(*)"), isSql("SELECT * FROM [nt:base] AS nodeSet1"));
+        assertThat(xpath("//*"), isSql("SELECT * FROM [nt:base] AS nodeSet1"));
+        assertThat(xpath("/jcr:root//*"), isSql("SELECT * FROM [nt:base] AS nodeSet1"));
+        assertThat(xpath("//."), isSql("SELECT * FROM [nt:base] AS nodeSet1"));
+        assertThat(xpath("/jcr:root//."), isSql("SELECT * FROM [nt:base] AS nodeSet1"));
     }
 
     @Test
@@ -80,69 +80,70 @@
 
     @Test
     public void shouldTranslateFromXPathContainingExplicitPath() {
-        assertThat(xpath("/jcr:root/a"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a'"));
-        assertThat(xpath("/jcr:root/a/b"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
-        assertThat(xpath("/jcr:root/a/b/c"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b/c'"));
-        assertThat(xpath("/jcr:root/a/b/c/d"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b/c/d'"));
+        assertThat(xpath("/jcr:root/a"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a'"));
+        assertThat(xpath("/jcr:root/a/b"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
+        assertThat(xpath("/jcr:root/a/b/c"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b/c'"));
+        assertThat(xpath("/jcr:root/a/b/c/d"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b/c/d'"));
     }
 
     @Test
     public void shouldTranslateFromXPathContainingExplicitPathWithChildNumbers() {
-        assertThat(xpath("/jcr:root/a[2]/b"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a[2]/b'"));
-        assertThat(xpath("/jcr:root/a/b[3]"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b[3]'"));
-        assertThat(xpath("/jcr:root/a[2]/b[3]"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a[2]/b[3]'"));
+        assertThat(xpath("/jcr:root/a[2]/b"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a[2]/b'"));
+        assertThat(xpath("/jcr:root/a/b[3]"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b[3]'"));
+        assertThat(xpath("/jcr:root/a[2]/b[3]"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a[2]/b[3]'"));
     }
 
     @Test
     public void shouldTranslateFromXPathContainingExplicitPathWithWildcardChildNumbers() {
-        assertThat(xpath("/jcr:root/a[*]/b"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
-        assertThat(xpath("/jcr:root/a/b[*]"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
-        assertThat(xpath("/jcr:root/a[*]/b[*]"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
+        assertThat(xpath("/jcr:root/a[*]/b"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
+        assertThat(xpath("/jcr:root/a/b[*]"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
+        assertThat(xpath("/jcr:root/a[*]/b[*]"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b'"));
     }
 
     @Test
     public void shouldTranslateFromXPathContainingPathWithDescendantOrSelf() {
         assertThat(xpath("/jcr:root/a/b//c"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b/c' OR PATH(nodeSet1) LIKE '/a/b/%/c'"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b/c' OR PATH(nodeSet1) LIKE '/a/b/%/c'"));
         assertThat(xpath("/jcr:root/a/b[2]//c"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b[2]/c' OR PATH(nodeSet1) LIKE '/a/b[2]/%/c'"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b[2]/c' OR PATH(nodeSet1) LIKE '/a/b[2]/%/c'"));
         assertThat(xpath("/jcr:root/a/b//c[4]"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b/c[4]' OR PATH(nodeSet1) LIKE '/a/b/%/c[4]'"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b/c[4]' OR PATH(nodeSet1) LIKE '/a/b/%/c[4]'"));
         assertThat(xpath("/jcr:root/a/b[2]//c[4]"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b[2]/c[4]' OR PATH(nodeSet1) LIKE '/a/b[2]/%/c[4]'"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/a/b[2]/c[4]' OR PATH(nodeSet1) LIKE '/a/b[2]/%/c[4]'"));
     }
 
     @Test
     public void shouldTranslateFromXPathContainingPathWithMultipleDescendantOrSelf() {
         assertThat(xpath("/jcr:root/a/b//c//d"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE (((PATH(nodeSet1) = '/a/b/c/d' OR PATH(nodeSet1) LIKE '/a/b/%/c/d') OR PATH(nodeSet1) LIKE '/a/b/c/%/d') OR PATH(nodeSet1) LIKE '/a/b/%/c/%/d')"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE (((PATH(nodeSet1) = '/a/b/c/d' OR PATH(nodeSet1) LIKE '/a/b/%/c/d') OR PATH(nodeSet1) LIKE '/a/b/c/%/d') OR PATH(nodeSet1) LIKE '/a/b/%/c/%/d')"));
     }
 
     @Test
     public void shouldTranslateFromXPathContainingPredicatesUsingRelativePaths() {
         assertThat(xpath("//element(*,my:type)[a/@id]"),
-                   isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) WHERE NAME(nodeSet1) = 'a' AND nodeSet1.id IS NOT NULL"));
+                   isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) WHERE NAME(nodeSet1) = 'a' AND nodeSet1.id IS NOT NULL"));
         assertThat(xpath("//element(*,my:type)[a/b/@id]"),
-                   isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) JOIN __ALLNODES__ as nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) = 'b') AND nodeSet2.id IS NOT NULL"));
+                   isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) JOIN [nt:base] as nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) = 'b') AND nodeSet2.id IS NOT NULL"));
         assertThat(xpath("//element(*,my:type)[a/b/((@id and @name) or not(@address))]"),
-                   isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) JOIN __ALLNODES__ as nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) = 'b') AND ((nodeSet2.id IS NOT NULL and nodeSet2.name IS NOT NULL) OR (NOT(nodeSet2.address IS NOT NULL)))"));
+                   isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) JOIN [nt:base] as nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) = 'b') AND ((nodeSet2.id IS NOT NULL and nodeSet2.name IS NOT NULL) OR (NOT(nodeSet2.address IS NOT NULL)))"));
         assertThat(xpath("//element(*,my:type)[./a/b/((@id and @name) or not(@address))]"),
-                   isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) JOIN __ALLNODES__ as nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) = 'b') AND ((nodeSet2.id IS NOT NULL and nodeSet2.name IS NOT NULL) OR (NOT(nodeSet2.address IS NOT NULL)))"));
+                   isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) JOIN [nt:base] as nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) = 'b') AND ((nodeSet2.id IS NOT NULL and nodeSet2.name IS NOT NULL) OR (NOT(nodeSet2.address IS NOT NULL)))"));
         assertThat(xpath("//element(*,my:type)[a/b/((@id and @name) or not(jcr:contains(@desc,'rock star')))]"),
-                   isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) JOIN __ALLNODES__ as nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) = 'b') AND ((nodeSet2.id IS NOT NULL and nodeSet2.name IS NOT NULL) OR (NOT(CONTAINS(nodeSet2.desc,'rock star'))))"));
+                   isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) JOIN [nt:base] as nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE (NAME(nodeSet1) = 'a' AND NAME(nodeSet2) = 'b') AND ((nodeSet2.id IS NOT NULL and nodeSet2.name IS NOT NULL) OR (NOT(CONTAINS(nodeSet2.desc,'rock star'))))"));
         assertThat(xpath("//element(*,my:type)[*/@id]"),
-                   isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) WHERE nodeSet1.id IS NOT NULL"));
+                   isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) WHERE nodeSet1.id IS NOT NULL"));
         assertThat(xpath("//element(*,my:type)[*/*/@id]"),
-                   isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) JOIN __ALLNODES__ as nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE nodeSet2.id IS NOT NULL"));
+                   isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) JOIN [nt:base] as nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE nodeSet2.id IS NOT NULL"));
         assertThat(xpath("//element(*,my:type)[./*/*/@id]"),
-                   isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) JOIN __ALLNODES__ as nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE nodeSet2.id IS NOT NULL"));
+                   isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON ISCHILDNODE(nodeSet1,[my:type]) JOIN [nt:base] as nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE nodeSet2.id IS NOT NULL"));
         assertThat(xpath("//element(*,my:type)[.//@id]"),
-                   isSql("SELECT * FROM [my:type] JOIN __ALLNODES__ as nodeSet1 ON ISDESCENDANTNODE(nodeSet1,[my:type]) WHERE nodeSet1.id IS NOT NULL"));
+                   isSql("SELECT * FROM [my:type] JOIN [nt:base] as nodeSet1 ON ISDESCENDANTNODE(nodeSet1,[my:type]) WHERE nodeSet1.id IS NOT NULL"));
     }
 
     @Test
     public void shouldTranslateFromXPathContainingPredicatesIdentifyingPropertiesThatMustHaveValues() {
+        assertThat(xpath("/jcr:root/testroot/serializationNode[@jcr:primaryType]"),
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/testroot/serializationNode' AND nodeSet1.[jcr:primaryType] IS NOT NULL"));
         assertThat(xpath("//element(*,my:type)[@id]"), isSql("SELECT * FROM [my:type] WHERE id IS NOT NULL"));
         assertThat(xpath("//element(*,my:type)[@id][@name]"),
                    isSql("SELECT * FROM [my:type] WHERE id IS NOT NULL AND name IS NOT NULL"));
@@ -191,8 +192,8 @@
         assertThat(xpath("//element(*,my:type)/(@id union @name)"), isSql("SELECT id, name FROM [my:type]"));
         assertThat(xpath("//element(*,my:type)/(@id union @name union @x:address)"),
                    isSql("SELECT id, name, [x:address] FROM [my:type]"));
-        assertThat(xpath("//(@id|@name)"), isSql("SELECT nodeSet1.id, nodeSet1.name FROM __ALLNODES__ AS nodeSet1"));
-        assertThat(xpath("//./(@id|@name)"), isSql("SELECT nodeSet1.id, nodeSet1.name FROM __ALLNODES__ AS nodeSet1"));
+        assertThat(xpath("//(@id|@name)"), isSql("SELECT nodeSet1.id, nodeSet1.name FROM [nt:base] AS nodeSet1"));
+        assertThat(xpath("//./(@id|@name)"), isSql("SELECT nodeSet1.id, nodeSet1.name FROM [nt:base] AS nodeSet1"));
     }
 
     @Test
@@ -207,68 +208,64 @@
 
     @Test
     public void shouldTranslateFromXPathOfAnyNodeWithName() {
-        assertThat(xpath("//element(nodeName,*)"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName'"));
+        assertThat(xpath("//element(nodeName,*)"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName'"));
 
-        assertThat(xpath("//element(nodeName,*)"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName'"));
+        assertThat(xpath("//element(nodeName,*)"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName'"));
 
-        assertThat(xpath("//nodeName"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName'"));
+        assertThat(xpath("//nodeName"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName'"));
 
         assertThat(xpath("/jcr:root//element(nodeName,*)"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName'"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName'"));
 
-        assertThat(xpath("/jcr:root//nodeName"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName'"));
+        assertThat(xpath("/jcr:root//nodeName"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName'"));
     }
 
     @Test
     public void shouldTranslateFromXPathOfNodeWithNameUnderRoot() {
         assertThat(xpath("/jcr:root/element(nodeName,*)"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName' AND DEPTH(nodeSet1) = CAST(1 AS LONG)"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName' AND DEPTH(nodeSet1) = CAST(1 AS LONG)"));
 
-        assertThat(xpath("/jcr:root/nodeName"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/nodeName'"));
+        assertThat(xpath("/jcr:root/nodeName"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/nodeName'"));
 
-        assertThat(xpath("nodeName"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/nodeName'"));
+        assertThat(xpath("nodeName"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/nodeName'"));
     }
 
     @Test
     public void shouldTranslateFromXPathOfAnyNodeUsingPredicate() {
         assertThat(xpath("//.[jcr:contains(.,'bar')]"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE CONTAINS(nodeSet1.*,'bar')"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE CONTAINS(nodeSet1.*,'bar')"));
         assertThat(xpath("//.[jcr:contains(a,'bar')]"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__ AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE CONTAINS(nodeSet2.*,'bar')"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE CONTAINS(nodeSet2.*,'bar')"));
         assertThat(xpath("//*[jcr:contains(.,'bar')]"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE CONTAINS(nodeSet1.*,'bar')"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE CONTAINS(nodeSet1.*,'bar')"));
         assertThat(xpath("//*[jcr:contains(a,'bar')]"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__ AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE CONTAINS(nodeSet2.*,'bar')"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE CONTAINS(nodeSet2.*,'bar')"));
         assertThat(xpath("//*[jcr:contains(a/@b,'bar')]"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__ AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE NAME(nodeSet2) = 'a' AND CONTAINS(nodeSet2.b,'bar')"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE NAME(nodeSet2) = 'a' AND CONTAINS(nodeSet2.b,'bar')"));
         assertThat(xpath("//*[jcr:contains(a/*/@b,'bar')]"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__ AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) JOIN __ALLNODES__ AS nodeSet3 ON ISCHILDNODE(nodeSet3,nodeSet2) WHERE NAME(nodeSet2) = 'a' AND CONTAINS(nodeSet3.b,'bar')"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) JOIN [nt:base] AS nodeSet3 ON ISCHILDNODE(nodeSet3,nodeSet2) WHERE NAME(nodeSet2) = 'a' AND CONTAINS(nodeSet3.b,'bar')"));
         assertThat(xpath("/jcr:root//element(*)[jcr:contains(a/@b,'bar')]"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__ AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE NAME(nodeSet2) = 'a' AND CONTAINS(nodeSet2.b,'bar')"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE NAME(nodeSet2) = 'a' AND CONTAINS(nodeSet2.b,'bar')"));
         assertThat(xpath("/jcr:root//element(*)[jcr:contains(a/*/@b,'bar')]"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__ AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) JOIN __ALLNODES__ AS nodeSet3 ON ISCHILDNODE(nodeSet3,nodeSet2) WHERE NAME(nodeSet2) = 'a' AND CONTAINS(nodeSet3.b,'bar')"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) JOIN [nt:base] AS nodeSet3 ON ISCHILDNODE(nodeSet3,nodeSet2) WHERE NAME(nodeSet2) = 'a' AND CONTAINS(nodeSet3.b,'bar')"));
         assertThat(xpath("/jcr:root//*[jcr:contains(a/@b,'bar')]"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__ AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE NAME(nodeSet2) = 'a' AND CONTAINS(nodeSet2.b,'bar')"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) WHERE NAME(nodeSet2) = 'a' AND CONTAINS(nodeSet2.b,'bar')"));
         assertThat(xpath("/jcr:root//*[jcr:contains(a/*/@b,'bar')]"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 JOIN __ALLNODES__ AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) JOIN __ALLNODES__ AS nodeSet3 ON ISCHILDNODE(nodeSet3,nodeSet2) WHERE NAME(nodeSet2) = 'a' AND CONTAINS(nodeSet3.b,'bar')"));
+                   isSql("SELECT * FROM [nt:base] AS nodeSet1 JOIN [nt:base] AS nodeSet2 ON ISCHILDNODE(nodeSet2,nodeSet1) JOIN [nt:base] AS nodeSet3 ON ISCHILDNODE(nodeSet3,nodeSet2) WHERE NAME(nodeSet2) = 'a' AND CONTAINS(nodeSet3.b,'bar')"));
     }
 
-    // @Test
-    // public void shouldParseXPathExpressions() {
-    // assertParsable("/jcr:root/a/b/c");
-    // assertParsable("/jcr:root/a/b/c[*]");
-    // assertParsable("/jcr:root/some[1]/element(nodes, my:type)[1]");
-    // assertParsable("//element(*,my:type)");
-    // assertParsable("//element(*,my:type)[@jcr:title='something' and @globalProperty='something else']");
-    // assertParsable("//element(*,my:type)[@jcr:title | @globalProperty]");
-    // assertParsable("//element(*, my:type) order by @my:title");
-    // assertParsable("//element(*, my:type) [jcr:contains(., 'jcr')] order by jcr:score() descending");
-    // assertParsable("//element(*, employee)[@secretary and @assistant]");
-    // }
+    @Test
+    public void shouldParseXPathExpressions() {
+        xpath("/jcr:root/a/b/c");
+        xpath("/jcr:root/a/b/c[*]");
+        xpath("/jcr:root/some[1]/element(nodes, my:type)[1]");
+        xpath("//element(*,my:type)");
+        xpath("//element(*,my:type)[@jcr:title='something' and @globalProperty='something else']");
+        xpath("//element(*,my:type)[@jcr:title | @globalProperty]");
+        xpath("//element(*, my:type) order by @my:title");
+        xpath("//element(*, my:type) [jcr:contains(., 'jcr')] order by jcr:score() descending");
+        xpath("//element(*, employee)[@secretary and @assistant]");
+    }
 
     // ----------------------------------------------------------------------------------------------------------------
     // utility methods

Modified: trunk/dna-jcr/src/test/resources/tck/repositoryForTckTests.xml
===================================================================
--- trunk/dna-jcr/src/test/resources/tck/repositoryForTckTests.xml	2009-12-31 18:53:06 UTC (rev 1507)
+++ trunk/dna-jcr/src/test/resources/tck/repositoryForTckTests.xml	2009-12-31 21:36:01 UTC (rev 1508)
@@ -49,4 +49,13 @@
        Cannot test \r character here on Windows as TCK XML Parser will replace it with \n and fail the comparison 
       -->
     <nt:unstructured jcr:name="node4" multi-line-property="Line&#009;1&#010;Line 2"/>
+    <!-- 
+        XPathPosIndexTest requires multiple nodes named 'node1'
+    -->
+    <nt:unstructured jcr:name="node1" prop1="&lt;foo&amp;foo&gt;">
+       <nt:unstructured jcr:name="jcr:xmltext" jcr:xmlcharacters="This is the text for node1[2]!" />
+    </nt:unstructured>
+    <nt:unstructured jcr:name="node1" prop1="&lt;foo&amp;foo&gt;">
+       <nt:unstructured jcr:name="jcr:xmltext" jcr:xmlcharacters="This is the text for node1[3]!" />
+    </nt:unstructured>
 </testroot>
\ No newline at end of file

Modified: trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/AbstractLuceneSearchEngine.java
===================================================================
--- trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/AbstractLuceneSearchEngine.java	2009-12-31 18:53:06 UTC (rev 1507)
+++ trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/AbstractLuceneSearchEngine.java	2009-12-31 21:36:01 UTC (rev 1508)
@@ -25,6 +25,7 @@
 
 import java.io.IOException;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -87,7 +88,6 @@
 import org.jboss.dna.graph.query.model.PropertyExistence;
 import org.jboss.dna.graph.query.model.PropertyValue;
 import org.jboss.dna.graph.query.model.SameNode;
-import org.jboss.dna.graph.query.model.SelectorName;
 import org.jboss.dna.graph.query.model.SetCriteria;
 import org.jboss.dna.graph.query.model.StaticOperand;
 import org.jboss.dna.graph.query.model.TypeSystem;
@@ -103,6 +103,8 @@
 import org.jboss.dna.graph.search.SearchEngine;
 import org.jboss.dna.graph.search.SearchEngineProcessor;
 import org.jboss.dna.graph.search.SearchEngineWorkspace;
+import org.jboss.dna.search.lucene.query.HasValueQuery;
+import org.jboss.dna.search.lucene.query.MatchNoneQuery;
 
 /**
  * An abstract {@link SearchEngine} implementation that is set up to use the Lucene library. This provides an abstract
@@ -349,11 +351,22 @@
             Query pushDownQuery = null;
             Constraint postProcessConstraint = null;
             try {
+                QueryFactory queryFactory = null;
                 for (Constraint andedConstraint : request.andedConstraints()) {
                     // Determine if it can be represented as a Lucene query ...
                     assert andedConstraint != null;
-                    Query constraintQuery = queryFactory(session, request.variables()).createQuery(andedConstraint);
+                    if (queryFactory == null) queryFactory = queryFactory(session, request.variables());
+                    Query constraintQuery = queryFactory.createQuery(andedConstraint);
                     if (constraintQuery != null) {
+                        if (constraintQuery instanceof MatchAllDocsQuery) {
+                            // This constraint includes all values, so we can just skip it ...
+                            continue;
+                        }
+                        if (constraintQuery instanceof MatchNoneQuery) {
+                            // This constraint invalidates all of the other AND-ed constraints ...
+                            pushDownQuery = constraintQuery;
+                            break;
+                        }
                         // The AND-ed constraint _can_ be represented as a push-down Lucene query ...
                         if (pushDownQuery == null) {
                             // This must be the first query ...
@@ -398,47 +411,54 @@
             // Get the results from Lucene ...
             List<Object[]> tuples = null;
             final Columns columns = request.resultColumns();
-            try {
-                // Execute the query against the content indexes ...
-                IndexSearcher searcher = session.getContentSearcher();
-                TupleCollector collector = session.createTupleCollector(columns);
-                searcher.search(pushDownQuery, collector);
-                tuples = collector.getTuples();
-            } catch (IOException e) {
-                // There was a problem executing the Lucene query ...
-                request.setError(e);
-                return;
+            if (pushDownQuery instanceof MatchNoneQuery) {
+                // There are no results ...
+                tuples = Collections.emptyList();
+            } else {
+                try {
+                    // Execute the query against the content indexes ...
+                    IndexSearcher searcher = session.getContentSearcher();
+                    TupleCollector collector = session.createTupleCollector(columns);
+                    searcher.search(pushDownQuery, collector);
+                    tuples = collector.getTuples();
+                } catch (IOException e) {
+                    // There was a problem executing the Lucene query ...
+                    request.setError(e);
+                    return;
+                }
             }
 
-            if (postProcessConstraint != null && !tuples.isEmpty()) {
-                // Create a delegate processing component that will return the tuples we've already found ...
-                final List<Object[]> allTuples = tuples;
-                QueryContext queryContext = new QueryContext(request.schemata(), typeSystem, null, new SimpleProblems(),
-                                                             request.variables());
-                ProcessingComponent tuplesProcessor = new ProcessingComponent(queryContext, columns) {
-                    @Override
-                    public List<Object[]> execute() {
-                        return allTuples;
-                    }
-                };
-                // Create a processing component that will apply these constraints to the tuples we already found ...
-                SelectComponent selector = new SelectComponent(tuplesProcessor, postProcessConstraint, request.variables());
-                tuples = selector.execute();
-            }
+            if (!tuples.isEmpty()) {
+                if (postProcessConstraint != null) {
+                    // Create a delegate processing component that will return the tuples we've already found ...
+                    final List<Object[]> allTuples = tuples;
+                    QueryContext queryContext = new QueryContext(request.schemata(), typeSystem, null, new SimpleProblems(),
+                                                                 request.variables());
+                    ProcessingComponent tuplesProcessor = new ProcessingComponent(queryContext, columns) {
+                        @Override
+                        public List<Object[]> execute() {
+                            return allTuples;
+                        }
+                    };
+                    // Create a processing component that will apply these constraints to the tuples we already found ...
+                    SelectComponent selector = new SelectComponent(tuplesProcessor, postProcessConstraint, request.variables());
+                    tuples = selector.execute();
+                }
 
-            // Limit the tuples ...
-            Limit limit = request.limit();
-            if (!limit.isUnlimited()) {
-                int firstIndex = limit.getOffset();
-                int maxRows = Math.min(tuples.size(), limit.getRowLimit());
-                if (firstIndex > 0) {
-                    if (firstIndex > tuples.size()) {
-                        tuples.clear();
+                // Limit the tuples ...
+                Limit limit = request.limit();
+                if (!limit.isUnlimited()) {
+                    int firstIndex = limit.getOffset();
+                    int maxRows = Math.min(tuples.size(), limit.getRowLimit());
+                    if (firstIndex > 0) {
+                        if (firstIndex > tuples.size()) {
+                            tuples.clear();
+                        } else {
+                            tuples = tuples.subList(firstIndex, maxRows);
+                        }
                     } else {
-                        tuples = tuples.subList(firstIndex, maxRows);
+                        tuples = tuples.subList(0, maxRows);
                     }
-                } else {
-                    tuples = tuples.subList(0, maxRows);
                 }
             }
 
@@ -518,7 +538,7 @@
                 }
                 if (constraint instanceof PropertyExistence) {
                     PropertyExistence existence = (PropertyExistence)constraint;
-                    return createQuery(existence.getSelectorName(), existence.getPropertyName());
+                    return createQuery(existence);
                 }
                 if (constraint instanceof Between) {
                     Between between = (Between)constraint;
@@ -680,10 +700,13 @@
                 return valueFactory.create(stringFactory.create(value).toLowerCase());
             }
 
-            public Query createQuery( SelectorName selectorName,
-                                      String propertyName ) {
-                Term term = new Term(fieldNameFor(propertyName));
-                return new TermQuery(term);
+            public Query createQuery( PropertyExistence existence ) {
+                String propertyName = existence.getPropertyName();
+                if ("jcr:primaryType".equals(propertyName)) {
+                    // All nodes have a primary type, so therefore we can match all documents ...
+                    return new MatchAllDocsQuery();
+                }
+                return new HasValueQuery(fieldNameFor(propertyName));
             }
 
             public Query createQuery( String fieldName,

Added: trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/query/HasValueQuery.java
===================================================================
--- trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/query/HasValueQuery.java	                        (rev 0)
+++ trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/query/HasValueQuery.java	2009-12-31 21:36:01 UTC (rev 1508)
@@ -0,0 +1,259 @@
+/*
+ * JBoss DNA (http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of 
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ * 
+ * JBoss DNA 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.search.lucene.query;
+
+import java.io.IOException;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.FieldSelector;
+import org.apache.lucene.document.FieldSelectorResult;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.Weight;
+
+/**
+ * A Lucene {@link Query} implementation that is satisfied if there is at least one value for a document.
+ */
+public class HasValueQuery extends Query {
+
+    private static final long serialVersionUID = 1L;
+
+    protected final String fieldName;
+    protected final FieldSelector fieldSelector;
+
+    /**
+     * Construct a {@link Query} implementation that scores nodes according to the supplied comparator.
+     * 
+     * @param fieldName the name of the document field containing the value; may not be null
+     */
+    public HasValueQuery( final String fieldName ) {
+        this.fieldName = fieldName;
+        this.fieldSelector = new FieldSelector() {
+            private static final long serialVersionUID = 1L;
+
+            public FieldSelectorResult accept( String fieldName ) {
+                return HasValueQuery.this.fieldName.equals(fieldName) ? FieldSelectorResult.LOAD_AND_BREAK : FieldSelectorResult.NO_LOAD;
+            }
+        };
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.apache.lucene.search.Query#clone()
+     */
+    @Override
+    public Object clone() {
+        return new HasValueQuery(fieldName);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.apache.lucene.search.Query#createWeight(org.apache.lucene.search.Searcher)
+     */
+    @Override
+    public Weight createWeight( Searcher searcher ) {
+        return new ExistsWeight(searcher);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.apache.lucene.search.Query#toString(java.lang.String)
+     */
+    @Override
+    public String toString( String field ) {
+        return fieldName + " exists";
+    }
+
+    protected boolean hasValue( IndexReader reader,
+                                int docId ) throws IOException {
+        Document doc = reader.document(docId, fieldSelector);
+        String valueString = doc.get(fieldName);
+        return valueString != null;
+    }
+
+    /**
+     * Calculates query weights and builds query scores for our NOT queries.
+     */
+    protected class ExistsWeight extends Weight {
+        private static final long serialVersionUID = 1L;
+        private final Searcher searcher;
+
+        protected ExistsWeight( Searcher searcher ) {
+            this.searcher = searcher;
+            assert this.searcher != null;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.apache.lucene.search.Weight#getQuery()
+         */
+        @Override
+        public Query getQuery() {
+            return HasValueQuery.this;
+        }
+
+        /**
+         * {@inheritDoc}
+         * <p>
+         * This implementation always returns a weight factor of 1.0.
+         * </p>
+         * 
+         * @see org.apache.lucene.search.Weight#getValue()
+         */
+        @Override
+        public float getValue() {
+            return 1.0f; // weight factor of 1.0
+        }
+
+        /**
+         * {@inheritDoc}
+         * <p>
+         * This implementation always returns a normalization factor of 1.0.
+         * </p>
+         * 
+         * @see org.apache.lucene.search.Weight#sumOfSquaredWeights()
+         */
+        @Override
+        public float sumOfSquaredWeights() {
+            return 1.0f; // normalization factor of 1.0
+        }
+
+        /**
+         * {@inheritDoc}
+         * <p>
+         * This implementation always does nothing, as there is nothing to normalize.
+         * </p>
+         * 
+         * @see org.apache.lucene.search.Weight#normalize(float)
+         */
+        @Override
+        public void normalize( float norm ) {
+            // No need to do anything here
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.apache.lucene.search.Weight#scorer(org.apache.lucene.index.IndexReader, boolean, boolean)
+         */
+        @Override
+        public Scorer scorer( IndexReader reader,
+                              boolean scoreDocsInOrder,
+                              boolean topScorer ) {
+            // Return a custom scorer ...
+            return new ExistsScorer(reader);
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.apache.lucene.search.Weight#explain(org.apache.lucene.index.IndexReader, int)
+         */
+        @Override
+        public Explanation explain( IndexReader reader,
+                                    int doc ) {
+            return new Explanation(getValue(), getQuery().toString());
+        }
+    }
+
+    /**
+     * A scorer for the Path query.
+     */
+    protected class ExistsScorer extends Scorer {
+        private int docId = -1;
+        private final int maxDocId;
+        private final IndexReader reader;
+
+        protected ExistsScorer( IndexReader reader ) {
+            // We don't care which Similarity we have, because we don't use it. So get the default.
+            super(Similarity.getDefault());
+            this.reader = reader;
+            assert this.reader != null;
+            this.maxDocId = this.reader.maxDoc() - 1;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.apache.lucene.search.DocIdSetIterator#docID()
+         */
+        @Override
+        public int docID() {
+            return docId;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.apache.lucene.search.DocIdSetIterator#nextDoc()
+         */
+        @Override
+        public int nextDoc() throws IOException {
+            do {
+                ++docId;
+                if (reader.isDeleted(docId)) {
+                    // We should skip this document ...
+                    continue;
+                }
+                if (hasValue(reader, docId)) return docId;
+            } while (docId < maxDocId);
+            return Scorer.NO_MORE_DOCS;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.apache.lucene.search.DocIdSetIterator#advance(int)
+         */
+        @Override
+        public int advance( int target ) throws IOException {
+            if (target == Scorer.NO_MORE_DOCS) return target;
+            while (true) {
+                int doc = nextDoc();
+                if (doc >= target) return doc;
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         * <p>
+         * This method always returns a score of 1.0 for the current document, since only those documents that satisfy the NOT are
+         * scored by this scorer.
+         * </p>
+         * 
+         * @see org.apache.lucene.search.Scorer#score()
+         */
+        @Override
+        public float score() {
+            return 1.0f;
+        }
+    }
+}


Property changes on: trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/query/HasValueQuery.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/extensions/dna-search-lucene/src/test/java/org/jboss/dna/search/lucene/LuceneSearchEngineTest.java
===================================================================
--- trunk/extensions/dna-search-lucene/src/test/java/org/jboss/dna/search/lucene/LuceneSearchEngineTest.java	2009-12-31 18:53:06 UTC (rev 1507)
+++ trunk/extensions/dna-search-lucene/src/test/java/org/jboss/dna/search/lucene/LuceneSearchEngineTest.java	2009-12-31 21:36:01 UTC (rev 1508)
@@ -373,6 +373,14 @@
     // ----------------------------------------------------------------------------------------------------------------
 
     @Test
+    public void shouldFindAllNodesBySimpleQuery() {
+        indexWorkspace(workspaceName1);
+        String query = "SELECT [jcr:primaryType] FROM __ALLNODES__";
+        QueryResults results = query(workspaceName1, query);
+        assertRowCount(results, 18);
+    }
+
+    @Test
     public void shouldFindNodesBySimpleQuery() {
         indexWorkspace(workspaceName1);
         String query = "SELECT model, maker FROM __ALLNODES__";



More information about the dna-commits mailing list