[dna-commits] DNA SVN: r1505 - in trunk: dna-graph/src/main/java/org/jboss/dna/graph/query/parse and 14 other directories.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Thu Dec 31 11:07:26 EST 2009


Author: rhauch
Date: 2009-12-31 11:07:24 -0500 (Thu, 31 Dec 2009)
New Revision: 1505

Added:
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java
   trunk/dna-jcr/src/test/resources/cars.cnd
   trunk/dna-jcr/src/test/resources/io/
   trunk/dna-jcr/src/test/resources/io/cars-system-view.xml
   trunk/docs/examples/gettingstarted/repositories/src/test/resources/log4j.properties
Modified:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/optimize/ReplaceViews.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/parse/SqlQueryParser.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/plan/CanonicalPlanner.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/plan/PlanUtil.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/process/SelectComponent.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/validate/Validator.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/search/SearchEngineIndexer.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/optimize/RuleBasedOptimizerTest.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/plan/CanonicalPlannerTest.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/NodeTypeSchemata.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryQueryManager.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathQueryParser.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslator.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/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchProcessor.java
   trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchSession.java
Log:
DNA-468 Further fixes and refinements for search and query support through the JCR API. We still have issues with certain XPath queries, and not all the XPath-related TCK tests are passing, but those will be addressed shortly.

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/optimize/ReplaceViews.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/optimize/ReplaceViews.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/optimize/ReplaceViews.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -102,6 +102,7 @@
 
                 // Resolve the node to find the definition in the schemata ...
                 SelectorName tableName = sourceNode.getProperty(Property.SOURCE_NAME, SelectorName.class);
+                SelectorName tableAlias = sourceNode.getProperty(Property.SOURCE_ALIAS, SelectorName.class);
                 Table table = schemata.getTable(tableName);
                 if (table instanceof View) {
                     View view = (View)table;
@@ -120,6 +121,11 @@
                     // tables/views used by the view ...
                     PlanUtil.ColumnMapping viewMappings = PlanUtil.createMappingFor(view, viewPlan);
                     PlanUtil.replaceViewReferences(context, viewPlan, viewMappings);
+                    if (tableAlias != null) {
+                        // We also need to replace references to the alias for the view ...
+                        PlanUtil.ColumnMapping aliasMappings = PlanUtil.createMappingForAliased(tableAlias, view, viewPlan);
+                        PlanUtil.replaceViewReferences(context, viewPlan, aliasMappings);
+                    }
 
                     if (viewPlan.is(Type.PROJECT)) {
                         // The PROJECT from the plan may actually not be needed if there is another PROJECT above it ...

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/parse/SqlQueryParser.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/parse/SqlQueryParser.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/parse/SqlQueryParser.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -493,6 +493,11 @@
                     throw new ParsingException(pos, msg);
                 }
             }
+        } else {
+            // We expected SELECT ...
+            Position pos = tokens.nextPosition();
+            String msg = GraphI18n.unexpectedToken.text(tokens.consume(), pos.getLine(), pos.getColumn());
+            throw new ParsingException(pos, msg);
         }
         return command;
     }
@@ -804,7 +809,7 @@
             return new FullTextSearchParser().parse(expression);
         } catch (ParsingException e) {
             // Convert the position in the exception into a position in the query.
-        	Position queryPos = startOfExpression.add(e.getPosition());
+            Position queryPos = startOfExpression.add(e.getPosition());
             throw new ParsingException(queryPos, e.getMessage());
         }
     }
@@ -1110,7 +1115,7 @@
         }
         // Otherwise the source should be a single named selector
         if (source instanceof Selector) {
-            selectorName = ((Selector)source).getName();
+            selectorName = ((Selector)source).getAliasOrName();
             return new PropertyValue(selectorName, firstWord);
         }
         String msg = GraphI18n.mustBeScopedAtLineAndColumn.text(firstWord, pos.getLine(), pos.getColumn());

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/plan/CanonicalPlanner.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/plan/CanonicalPlanner.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/plan/CanonicalPlanner.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -391,14 +391,16 @@
         if (columns.isEmpty()) {
             columns = new LinkedList<Column>();
             // SELECT *, so find all of the columns that are available from all the sources ...
-            for (Table table : selectors.values()) {
+            for (Map.Entry<SelectorName, Table> entry : selectors.entrySet()) {
+                SelectorName tableName = entry.getKey();
+                Table table = entry.getValue();
                 // Add the selector that is being used ...
-                projectNode.addSelector(table.getName());
+                projectNode.addSelector(tableName);
                 // Compute the columns from this selector ...
                 for (Schemata.Column column : table.getColumns()) {
                     String columnName = column.getName();
                     String propertyName = columnName;
-                    columns.add(new Column(table.getName(), propertyName, columnName));
+                    columns.add(new Column(tableName, propertyName, columnName));
                 }
             }
         } else {

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/plan/PlanUtil.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/plan/PlanUtil.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/plan/PlanUtil.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -827,6 +827,30 @@
         return mapping;
     }
 
+    public static ColumnMapping createMappingForAliased( SelectorName viewAlias,
+                                                         View view,
+                                                         PlanNode viewPlan ) {
+        ColumnMapping mapping = new ColumnMapping(viewAlias);
+
+        // Find the PROJECT node in the view plan ...
+        PlanNode project = viewPlan.findAtOrBelow(Type.PROJECT);
+        assert project != null;
+
+        // Get the Columns from the PROJECT in the plan node ...
+        List<Column> projectedColumns = project.getPropertyAsList(Property.PROJECT_COLUMNS, Column.class);
+
+        // Get the Schemata columns defined by the view ...
+        List<org.jboss.dna.graph.query.validate.Schemata.Column> viewColumns = view.getColumns();
+        assert viewColumns.size() == projectedColumns.size();
+
+        for (int i = 0; i != viewColumns.size(); ++i) {
+            Column projectedColunn = projectedColumns.get(i);
+            String viewColumnName = viewColumns.get(i).getName();
+            mapping.map(viewColumnName, projectedColunn);
+        }
+        return mapping;
+    }
+
     /**
      * Defines how the view columns are mapped (or resolved) into the columns from the source tables.
      */

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/process/SelectComponent.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/process/SelectComponent.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/process/SelectComponent.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -26,6 +26,7 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.regex.Pattern;
@@ -44,6 +45,7 @@
 import org.jboss.dna.graph.query.model.Or;
 import org.jboss.dna.graph.query.model.PropertyExistence;
 import org.jboss.dna.graph.query.model.SameNode;
+import org.jboss.dna.graph.query.model.SetCriteria;
 import org.jboss.dna.graph.query.model.StaticOperand;
 import org.jboss.dna.graph.query.model.TypeSystem;
 import org.jboss.dna.graph.query.model.TypeSystem.TypeFactory;
@@ -234,7 +236,6 @@
      *        in perhaps an non-ideal manner
      * @return the constraint evaluator; never null
      */
-    @SuppressWarnings( "unchecked" )
     protected ConstraintChecker createChecker( final TypeSystem types,
                                                Schemata schemata,
                                                Columns columns,
@@ -396,82 +397,122 @@
             Comparison comparison = (Comparison)constraint;
 
             // Create the correct dynamic operation ...
-            final DynamicOperation dynamicOperation = createDynamicOperation(types, schemata, columns, comparison.getOperand1());
-            final String expectedType = dynamicOperation.getExpectedType();
-
-            // Determine the literal value ...
+            DynamicOperation dynamicOperation = createDynamicOperation(types, schemata, columns, comparison.getOperand1());
+            Operator operator = comparison.getOperator();
             StaticOperand staticOperand = comparison.getOperand2();
-            Object literalValue = null;
-            if (staticOperand instanceof BindVariableName) {
-                BindVariableName bindVariable = (BindVariableName)staticOperand;
-                String variableName = bindVariable.getVariableName();
-                literalValue = variables.get(variableName); // may be null
-            } else {
-                Literal literal = (Literal)staticOperand;
-                literalValue = literal.getValue();
+            return createChecker(types, schemata, columns, dynamicOperation, operator, staticOperand);
+        }
+        if (constraint instanceof SetCriteria) {
+            SetCriteria setCriteria = (SetCriteria)constraint;
+            DynamicOperation dynamicOperation = createDynamicOperation(types, schemata, columns, setCriteria.getLeftOperand());
+            Operator operator = Operator.EQUAL_TO;
+            final List<ConstraintChecker> checkers = new LinkedList<ConstraintChecker>();
+            for (StaticOperand setValue : setCriteria.getRightOperands()) {
+                ConstraintChecker rightChecker = createChecker(types, schemata, columns, dynamicOperation, operator, setValue);
+                assert rightChecker != null;
+                checkers.add(rightChecker);
             }
-            // Create the correct comparator ...
-            final TypeFactory<?> typeFactory = types.getTypeFactory(expectedType);
-            assert typeFactory != null;
-            final Comparator<Object> comparator = (Comparator<Object>)typeFactory.getComparator();
-            assert comparator != null;
-            // Create the correct operation ...
-            final TypeFactory<?> literalFactory = types.getTypeFactory(expectedType);
-            final Object rhs = literalFactory.create(literalValue);
-            switch (comparison.getOperator()) {
-                case EQUAL_TO:
-                    return new ConstraintChecker() {
-                        public boolean satisfiesConstraints( Object[] tuples ) {
-                            return comparator.compare(dynamicOperation.evaluate(tuples), rhs) == 0;
-                        }
-                    };
-                case GREATER_THAN:
-                    return new ConstraintChecker() {
-                        public boolean satisfiesConstraints( Object[] tuples ) {
-                            return comparator.compare(dynamicOperation.evaluate(tuples), rhs) > 0;
-                        }
-                    };
-                case GREATER_THAN_OR_EQUAL_TO:
-                    return new ConstraintChecker() {
-                        public boolean satisfiesConstraints( Object[] tuples ) {
-                            return comparator.compare(dynamicOperation.evaluate(tuples), rhs) >= 0;
-                        }
-                    };
-                case LESS_THAN:
-                    return new ConstraintChecker() {
-                        public boolean satisfiesConstraints( Object[] tuples ) {
-                            return comparator.compare(dynamicOperation.evaluate(tuples), rhs) < 0;
-                        }
-                    };
-                case LESS_THAN_OR_EQUAL_TO:
-                    return new ConstraintChecker() {
-                        public boolean satisfiesConstraints( Object[] tuples ) {
-                            return comparator.compare(dynamicOperation.evaluate(tuples), rhs) <= 0;
-                        }
-                    };
-                case NOT_EQUAL_TO:
-                    return new ConstraintChecker() {
-                        public boolean satisfiesConstraints( Object[] tuples ) {
-                            return comparator.compare(dynamicOperation.evaluate(tuples), rhs) != 0;
-                        }
-                    };
-                case LIKE:
-                    // Convert the LIKE expression to a regular expression
-                    final Pattern pattern = createRegexFromLikeExpression(types.asString(rhs));
-                    return new ConstraintChecker() {
-                        public boolean satisfiesConstraints( Object[] tuples ) {
-                            Object tupleValue = dynamicOperation.evaluate(tuples);
-                            if (tupleValue == null) return false;
-                            String value = types.asString(tupleValue);
-                            return pattern.matcher(value).matches();
-                        }
-                    };
+            if (checkers.isEmpty()) {
+                // Nothing will satisfy these constraints ...
+                return new ConstraintChecker() {
+                    public boolean satisfiesConstraints( Object[] tuple ) {
+                        return false;
+                    }
+                };
             }
+            return new ConstraintChecker() {
+                public boolean satisfiesConstraints( Object[] tuple ) {
+                    for (ConstraintChecker checker : checkers) {
+                        if (checker.satisfiesConstraints(tuple)) return true;
+                    }
+                    return false;
+                }
+            };
         }
         assert false;
         return null;
     }
 
+    @SuppressWarnings( "unchecked" )
+    protected ConstraintChecker createChecker( final TypeSystem types,
+                                               Schemata schemata,
+                                               Columns columns,
+                                               final DynamicOperation dynamicOperation,
+                                               Operator operator,
+                                               StaticOperand staticOperand ) {
+        final String expectedType = dynamicOperation.getExpectedType();
+
+        // Determine the literal value ...
+        Object literalValue = null;
+        if (staticOperand instanceof BindVariableName) {
+            BindVariableName bindVariable = (BindVariableName)staticOperand;
+            String variableName = bindVariable.getVariableName();
+            literalValue = variables.get(variableName); // may be null
+        } else {
+            Literal literal = (Literal)staticOperand;
+            literalValue = literal.getValue();
+        }
+        // Create the correct comparator ...
+        final TypeFactory<?> typeFactory = types.getTypeFactory(expectedType);
+        assert typeFactory != null;
+        final Comparator<Object> comparator = (Comparator<Object>)typeFactory.getComparator();
+        assert comparator != null;
+        // Create the correct operation ...
+        final TypeFactory<?> literalFactory = types.getTypeFactory(expectedType);
+        final Object rhs = literalFactory.create(literalValue);
+        switch (operator) {
+            case EQUAL_TO:
+                return new ConstraintChecker() {
+                    public boolean satisfiesConstraints( Object[] tuples ) {
+                        return comparator.compare(dynamicOperation.evaluate(tuples), rhs) == 0;
+                    }
+                };
+            case GREATER_THAN:
+                return new ConstraintChecker() {
+                    public boolean satisfiesConstraints( Object[] tuples ) {
+                        return comparator.compare(dynamicOperation.evaluate(tuples), rhs) > 0;
+                    }
+                };
+            case GREATER_THAN_OR_EQUAL_TO:
+                return new ConstraintChecker() {
+                    public boolean satisfiesConstraints( Object[] tuples ) {
+                        return comparator.compare(dynamicOperation.evaluate(tuples), rhs) >= 0;
+                    }
+                };
+            case LESS_THAN:
+                return new ConstraintChecker() {
+                    public boolean satisfiesConstraints( Object[] tuples ) {
+                        return comparator.compare(dynamicOperation.evaluate(tuples), rhs) < 0;
+                    }
+                };
+            case LESS_THAN_OR_EQUAL_TO:
+                return new ConstraintChecker() {
+                    public boolean satisfiesConstraints( Object[] tuples ) {
+                        return comparator.compare(dynamicOperation.evaluate(tuples), rhs) <= 0;
+                    }
+                };
+            case NOT_EQUAL_TO:
+                return new ConstraintChecker() {
+                    public boolean satisfiesConstraints( Object[] tuples ) {
+                        return comparator.compare(dynamicOperation.evaluate(tuples), rhs) != 0;
+                    }
+                };
+            case LIKE:
+                // Convert the LIKE expression to a regular expression
+                final Pattern pattern = createRegexFromLikeExpression(types.asString(rhs));
+                return new ConstraintChecker() {
+                    public boolean satisfiesConstraints( Object[] tuples ) {
+                        Object tupleValue = dynamicOperation.evaluate(tuples);
+                        if (tupleValue == null) return false;
+                        String value = types.asString(tupleValue);
+                        return pattern.matcher(value).matches();
+                    }
+                };
+        }
+        assert false;
+        return null;
+    }
+
     protected static Pattern createRegexFromLikeExpression( String likeExpression ) {
         return null;
     }

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/validate/Validator.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/validate/Validator.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/validate/Validator.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -23,6 +23,7 @@
  */
 package org.jboss.dna.graph.query.validate;
 
+import java.util.HashMap;
 import java.util.Map;
 import org.jboss.dna.common.collection.Problems;
 import org.jboss.dna.graph.GraphI18n;
@@ -59,6 +60,7 @@
 
     private final QueryContext context;
     private final Problems problems;
+    private final Map<SelectorName, Table> selectorsByNameOrAlias;
     private final Map<SelectorName, Table> selectorsByName;
 
     /**
@@ -69,7 +71,11 @@
                       Map<SelectorName, Table> selectorsByName ) {
         this.context = context;
         this.problems = this.context.getProblems();
-        this.selectorsByName = selectorsByName;
+        this.selectorsByNameOrAlias = selectorsByName;
+        this.selectorsByName = new HashMap<SelectorName, Table>();
+        for (Table table : selectorsByName.values()) {
+            this.selectorsByName.put(table.getName(), table);
+        }
     }
 
     /**
@@ -301,8 +307,17 @@
         verify(obj.getSelector2Name());
     }
 
+    protected Table tableWithNameOrAlias( SelectorName tableName ) {
+        Table table = selectorsByNameOrAlias.get(tableName);
+        if (table == null) {
+            // Try looking up the table by it's real name (if an alias were used) ...
+            table = selectorsByName.get(tableName);
+        }
+        return table;
+    }
+
     protected Table verify( SelectorName selectorName ) {
-        Table table = selectorsByName.get(selectorName);
+        Table table = tableWithNameOrAlias(selectorName);
         if (table == null) {
             problems.addError(GraphI18n.tableDoesNotExist, selectorName.getName());
         }
@@ -310,7 +325,7 @@
     }
 
     protected Table verifyTable( SelectorName tableName ) {
-        Table table = selectorsByName.get(tableName);
+        Table table = tableWithNameOrAlias(tableName);
         if (table == null) {
             problems.addError(GraphI18n.tableDoesNotExist, tableName.getName());
         }
@@ -319,7 +334,7 @@
 
     protected Schemata.Column verify( SelectorName selectorName,
                                       String propertyName ) {
-        Table table = selectorsByName.get(selectorName);
+        Table table = tableWithNameOrAlias(selectorName);
         if (table == null) {
             problems.addError(GraphI18n.tableDoesNotExist, selectorName.getName());
             return null;

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/search/SearchEngineIndexer.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/search/SearchEngineIndexer.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/search/SearchEngineIndexer.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -35,8 +35,10 @@
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.common.util.Logger;
 import org.jboss.dna.common.util.NamedThreadFactory;
+import org.jboss.dna.graph.DnaLexicon;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.JcrLexicon;
 import org.jboss.dna.graph.Location;
 import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
 import org.jboss.dna.graph.connector.RepositorySourceException;
@@ -286,6 +288,11 @@
         Location topNode = locationIter.next();
         assert topNode.equals(startingLocation);
         Map<Name, Property> properties = readSubgraph.getPropertiesFor(topNode);
+        if (startingLocation.getPath().isRoot()) {
+            // The properties of the root node generally don't include the primary type, but we need to add it here ...
+            Property rootPrimaryType = context.getPropertyFactory().create(JcrLexicon.PRIMARY_TYPE, DnaLexicon.ROOT);
+            properties.put(JcrLexicon.PRIMARY_TYPE, rootPrimaryType);
+        }
         UpdatePropertiesRequest request = new UpdatePropertiesRequest(topNode, workspaceName, properties, true);
         request.setActualLocationOfNode(topNode);
         process(request);

Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/optimize/RuleBasedOptimizerTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/optimize/RuleBasedOptimizerTest.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/optimize/RuleBasedOptimizerTest.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -184,6 +184,79 @@
     }
 
     @Test
+    public void shouldOptimizePlanForSimpleQueryWithSelectStarWithAlias() {
+        node = optimize("SELECT * FROM t1 AS x1");
+        // Create the expected plan ...
+        PlanNode expected = new PlanNode(Type.ACCESS, selector("x1"));
+        PlanNode project = new PlanNode(Type.PROJECT, expected, selector("x1"));
+        project.setProperty(Property.PROJECT_COLUMNS, columns(column("x1", "c11"), column("x1", "c12"), column("x1", "c13")));
+        PlanNode source = new PlanNode(Type.SOURCE, project, selector("x1"));
+        source.setProperty(Property.SOURCE_NAME, selector("t1"));
+        source.setProperty(Property.SOURCE_ALIAS, selector("x1"));
+        source.setProperty(Property.SOURCE_COLUMNS, context.getSchemata().getTable(selector("t1")).getColumns());
+        // Compare the expected and actual plan ...
+        assertThat(node.isSameAs(expected), is(true));
+    }
+
+    @Test
+    public void shouldOptimizePlanForSimpleQueryWithSelectStarFromTableWithAliasAndValueCriteria() {
+        node = optimize("SELECT * FROM t1 AS x1 WHERE c13 < CAST('3' AS LONG)");
+        // Create the expected plan ...
+        PlanNode expected = new PlanNode(Type.ACCESS, selector("x1"));
+        PlanNode project = new PlanNode(Type.PROJECT, expected, selector("x1"));
+        project.setProperty(Property.PROJECT_COLUMNS, columns(column("x1", "c11"), column("x1", "c12"), column("x1", "c13")));
+        PlanNode select = new PlanNode(Type.SELECT, project, selector("x1"));
+        select.setProperty(Property.SELECT_CRITERIA, new Comparison(new PropertyValue(selector("x1"), "c13"), Operator.LESS_THAN,
+                                                                    new Literal(3L)));
+        PlanNode source = new PlanNode(Type.SOURCE, select, selector("x1"));
+        source.setProperty(Property.SOURCE_NAME, selector("t1"));
+        source.setProperty(Property.SOURCE_ALIAS, selector("x1"));
+        source.setProperty(Property.SOURCE_COLUMNS, context.getSchemata().getTable(selector("t1")).getColumns());
+        // Compare the expected and actual plan ...
+        assertThat(node.isSameAs(expected), is(true));
+    }
+
+    @Test
+    public void shouldOptimizePlanForSimpleQueryWithSelectStarFromViewWithNoAliasAndValueCriteria() {
+        node = optimize("SELECT * FROM v1 WHERE c11 = 'value'");
+        // Create the expected plan ...
+        PlanNode expected = new PlanNode(Type.ACCESS, selector("t1"));
+        PlanNode project = new PlanNode(Type.PROJECT, expected, selector("t1"));
+        project.setProperty(Property.PROJECT_COLUMNS, columns(column("t1", "c11"), column("t1", "c12", "c2")));
+        PlanNode select1 = new PlanNode(Type.SELECT, project, selector("t1"));
+        select1.setProperty(Property.SELECT_CRITERIA, new Comparison(new PropertyValue(selector("t1"), "c11"), Operator.EQUAL_TO,
+                                                                     new Literal("value")));
+        PlanNode select2 = new PlanNode(Type.SELECT, select1, selector("t1"));
+        select2.setProperty(Property.SELECT_CRITERIA, new Comparison(new PropertyValue(selector("t1"), "c13"),
+                                                                     Operator.LESS_THAN, new Literal(3L)));
+        PlanNode source = new PlanNode(Type.SOURCE, select2, selector("t1"));
+        source.setProperty(Property.SOURCE_NAME, selector("t1"));
+        source.setProperty(Property.SOURCE_COLUMNS, context.getSchemata().getTable(selector("t1")).getColumns());
+        // Compare the expected and actual plan ...
+        assertThat(node.isSameAs(expected), is(true));
+    }
+
+    @Test
+    public void shouldOptimizePlanForSimpleQueryWithSelectStarFromViewWithAliasAndValueCriteria() {
+        node = optimize("SELECT * FROM v1 AS x1 WHERE c11 = 'value'");
+        // Create the expected plan ...
+        PlanNode expected = new PlanNode(Type.ACCESS, selector("t1"));
+        PlanNode project = new PlanNode(Type.PROJECT, expected, selector("t1"));
+        project.setProperty(Property.PROJECT_COLUMNS, columns(column("t1", "c11"), column("t1", "c12", "c2")));
+        PlanNode select1 = new PlanNode(Type.SELECT, project, selector("t1"));
+        select1.setProperty(Property.SELECT_CRITERIA, new Comparison(new PropertyValue(selector("t1"), "c11"), Operator.EQUAL_TO,
+                                                                     new Literal("value")));
+        PlanNode select2 = new PlanNode(Type.SELECT, select1, selector("t1"));
+        select2.setProperty(Property.SELECT_CRITERIA, new Comparison(new PropertyValue(selector("t1"), "c13"),
+                                                                     Operator.LESS_THAN, new Literal(3L)));
+        PlanNode source = new PlanNode(Type.SOURCE, select2, selector("t1"));
+        source.setProperty(Property.SOURCE_NAME, selector("t1"));
+        source.setProperty(Property.SOURCE_COLUMNS, context.getSchemata().getTable(selector("t1")).getColumns());
+        // Compare the expected and actual plan ...
+        assertThat(node.isSameAs(expected), is(true));
+    }
+
+    @Test
     public void shouldOptimizePlanForSimpleQueryWithPropertyValueCriteria() {
         node = optimize("SELECT c11, c12 FROM t1 WHERE c13 < CAST('3' AS LONG)");
         // Create the expected plan ...

Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/plan/CanonicalPlannerTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/plan/CanonicalPlannerTest.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/plan/CanonicalPlannerTest.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -26,7 +26,9 @@
 import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertThat;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import org.jboss.dna.common.collection.Problems;
 import org.jboss.dna.common.collection.SimpleProblems;
 import org.jboss.dna.graph.ExecutionContext;
@@ -73,6 +75,14 @@
         return new SelectorName(name);
     }
 
+    protected Set<SelectorName> selectors( String... names ) {
+        Set<SelectorName> selectors = new HashSet<SelectorName>();
+        for (String name : names) {
+            selectors.add(selector(name));
+        }
+        return selectors;
+    }
+
     @SuppressWarnings( "unchecked" )
     protected void assertProjectNode( PlanNode node,
                                       String... columnNames ) {
@@ -161,6 +171,41 @@
     }
 
     @Test
+    public void shouldProducePlanWhenSelectingColumnsFromTableWithoutAlias() {
+        schemata = schemataBuilder.addTable("someTable", "column1", "column2", "column3").build();
+        query = builder.select("column1", "column2").from("someTable").where().path("someTable").isEqualTo(1L).end().query();
+        queryContext = new QueryContext(schemata, typeSystem, hints, problems);
+        plan = planner.createPlan(queryContext, query);
+        assertThat(problems.hasErrors(), is(false));
+        assertThat(plan.getType(), is(PlanNode.Type.PROJECT));
+        assertThat(plan.getSelectors(), is(selectors("someTable")));
+    }
+
+    @Test
+    public void shouldProducePlanWhenSelectingColumnsFromTableWithAlias() {
+        schemata = schemataBuilder.addTable("dna:someTable", "column1", "column2", "column3").build();
+        query = builder.select("column1", "column2").from("dna:someTable AS t1").where().path("t1").isEqualTo(1L).end().query();
+        queryContext = new QueryContext(schemata, typeSystem, hints, problems);
+        plan = planner.createPlan(queryContext, query);
+        assertThat(problems.hasErrors(), is(false));
+        System.out.println(plan);
+        assertThat(plan.getType(), is(PlanNode.Type.PROJECT));
+        assertThat(plan.getSelectors(), is(selectors("t1")));
+    }
+
+    @Test
+    public void shouldProducePlanWhenSelectingAllColumnsFromTableWithAlias() {
+        schemata = schemataBuilder.addTable("dna:someTable", "column1", "column2", "column3").build();
+        query = builder.selectStar().from("dna:someTable AS t1").where().path("t1").isEqualTo(1L).end().query();
+        queryContext = new QueryContext(schemata, typeSystem, hints, problems);
+        plan = planner.createPlan(queryContext, query);
+        assertThat(problems.hasErrors(), is(false));
+        System.out.println(plan);
+        assertThat(plan.getType(), is(PlanNode.Type.PROJECT));
+        assertThat(plan.getSelectors(), is(selectors("t1")));
+    }
+
+    @Test
     public void shouldProduceErrorWhenFullTextSearchingTableWithNoSearchableColumns() {
         schemata = schemataBuilder.addTable("someTable", "column1", "column2", "column3").build();
         // Make sure the query without the search criteria does not have an error

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrContentHandler.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -291,7 +291,7 @@
         private String currentPropName;
         private int currentPropType;
 
-        private StringBuffer valueBuffer;
+        private StringBuilder valueBuffer;
         private final Map<String, List<Value>> currentProps;
 
         /**
@@ -303,7 +303,6 @@
             this.parentStack.push(currentNode);
 
             this.currentProps = new HashMap<String, List<Value>>();
-            this.valueBuffer = new StringBuffer();
 
             this.svNameName = JcrSvLexicon.NAME.getString(namespaces());
             this.svTypeName = JcrSvLexicon.TYPE.getString(namespaces());
@@ -320,6 +319,8 @@
                                   String localName,
                                   String name,
                                   Attributes atts ) throws SAXException {
+            // Always create a new string buffer for the content value, because we're starting a new element ...
+            valueBuffer = new StringBuilder();
             if ("node".equals(localName)) {
                 if (currentNodeName != null) {
                     addNodeIfPending();
@@ -346,7 +347,7 @@
                     if (rawUuid != null) {
                         assert rawUuid.size() == 1;
                         uuid = UUID.fromString(rawUuid.get(0).getString());
-                        
+
                         try {
                             // Deal with any existing node ...
                             AbstractJcrNode existingNodeWithUuid = cache().findJcrNode(Location.create(uuid));
@@ -363,20 +364,23 @@
                                         throw new ConstraintViolationException(
                                                                                JcrI18n.cannotRemoveParentNodeOfTarget.text(existingNodeWithUuid.getPath(),
                                                                                                                            uuid,
-                                                                                                                           parentStack.firstElement().getPath()));
+                                                                                                                           parentStack.firstElement()
+                                                                                                                                      .getPath()));
                                     }
                                     existingNodeWithUuid.remove();
                                     break;
                                 case ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW:
                                     throw new ItemExistsException(
                                                                   JcrI18n.itemAlreadyExistsWithUuid.text(uuid,
-                                                                                                         cache().session().workspace().getName(),
+                                                                                                         cache().session()
+                                                                                                                .workspace()
+                                                                                                                .getName(),
                                                                                                          existingNodeWithUuid.getPath()));
                             }
                         } catch (ItemNotFoundException e) {
                             // there wasn't an existing item, so just continue
                         }
-                        
+
                     }
 
                     String typeName = currentProps.get(primaryTypeName).get(0).getString();
@@ -439,7 +443,6 @@
                 } catch (RepositoryException re) {
                     throw new EnclosingSAXException(re);
                 }
-                valueBuffer = new StringBuffer();
             }
         }
 
@@ -453,7 +456,6 @@
                                 int start,
                                 int length ) {
             valueBuffer.append(ch, start, length);
-
         }
     }
 

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrPropertyDefinition.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -31,6 +31,7 @@
 import javax.jcr.Value;
 import javax.jcr.nodetype.PropertyDefinition;
 import net.jcip.annotations.Immutable;
+import org.jboss.dna.graph.DnaIntLexicon;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Location;
 import org.jboss.dna.graph.property.Binary;
@@ -56,6 +57,7 @@
     private final String[] valueConstraints;
     private final boolean multiple;
     private final boolean fullTextSearchable;
+    private final boolean isPrivate;
     private PropertyDefinitionId id;
     private ConstraintChecker checker = null;
 
@@ -77,6 +79,7 @@
         this.valueConstraints = valueConstraints;
         this.multiple = multiple;
         this.fullTextSearchable = fullTextSearchable;
+        this.isPrivate = name.getNamespaceUri().equals(DnaIntLexicon.Namespace.URI);
     }
 
     /**
@@ -128,6 +131,15 @@
         return multiple;
     }
 
+    /**
+     * Return whether this property definition is considered private.
+     * 
+     * @return true if the definition is private, or false otherwise
+     */
+    public boolean isPrivate() {
+        return isPrivate;
+    }
+
     public boolean isFullTextSearchable() {
         return fullTextSearchable;
     }

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 14:14:56 UTC (rev 1504)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrQueryManager.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -114,6 +114,10 @@
         try {
             // Parsing must be done now ...
             QueryCommand command = parser.parseQuery(expression, typeSystem);
+            if (command == null) {
+                // The query is not well-formed and cannot be parsed ...
+                throw new InvalidQueryException(JcrI18n.queryCannotBeParsedUsingLanguage.text(language, expression));
+            }
             PlanHints hints = new PlanHints();
             // If using XPath, we need to add a few hints ...
             if (Query.XPATH.equals(language)) {
@@ -420,6 +424,16 @@
             final List<Object[]> tuples = results.getTuples();
             return new QueryResultRowIterator(session, results.getColumns(), tuples.iterator(), numRows);
         }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see java.lang.Object#toString()
+         */
+        @Override
+        public String toString() {
+            return results.toString();
+        }
     }
 
     /**

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -321,6 +321,22 @@
      */
     protected static final Map<Option, String> DEFAULT_OPTIONS;
 
+    public static final class QueryLanguage {
+        /**
+         * The standard JCR 1.0 XPath query language.
+         */
+        public static final String XPATH = Query.XPATH;
+        /**
+         * The SQL dialect that is based upon an enhanced version of the JCR 2.0 SQL query language.
+         */
+        public static final String SQL = SqlQueryParser.LANGUAGE;
+        /**
+         * The full-text search language defined as part of the abstract query model, in Section 6.7.19 of the JCR 2.0
+         * specification.
+         */
+        public static final String SEARCH = FullTextSearchParser.LANGUAGE;
+    }
+
     static {
         // Initialize the unmodifiable map of default options ...
         EnumMap<Option, String> defaults = new EnumMap<Option, String>(Option.class);
@@ -932,7 +948,7 @@
         if (this.federatedSource != null) {
             this.federatedSource.close();
         }
-        
+
         this.repositoryObservationManager.shutdown();
     }
 
@@ -1192,7 +1208,7 @@
         /**
          * @param repositoryObservable the repository library observable this observer should register with
          */
-        protected RepositoryObservationManager(Observable repositoryObservable) {
+        protected RepositoryObservationManager( Observable repositoryObservable ) {
             this.repositoryObservable = repositoryObservable;
             this.repositoryObservable.register(this);
         }
@@ -1249,7 +1265,7 @@
                 this.observerService.shutdown();
             }
         }
-        
+
         /**
          * {@inheritDoc}
          * 

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -65,6 +65,7 @@
 import org.jboss.dna.graph.property.Path;
 import org.jboss.dna.graph.property.PathFactory;
 import org.jboss.dna.graph.property.ValueFactories;
+import org.jboss.dna.graph.request.InvalidWorkspaceException;
 import org.jboss.dna.graph.session.GraphSession;
 import org.jboss.dna.jcr.JcrContentHandler.EnclosingSAXException;
 import org.jboss.dna.jcr.JcrContentHandler.SaveMode;
@@ -880,6 +881,29 @@
     }
 
     /**
+     * Crawl and index the content in this workspace.
+     * 
+     * @throws IllegalArgumentException if the workspace is null
+     * @throws InvalidWorkspaceException if there is no workspace with the supplied name
+     */
+    public void reindexContent() {
+        repository().queryManager().reindexContent(workspace());
+    }
+
+    /**
+     * Crawl and index the content starting at the supplied path in this workspace, to the designated depth.
+     * 
+     * @param path the path of the content to be indexed
+     * @param depth the depth of the content to be indexed
+     * @throws IllegalArgumentException if the workspace or path are null, or if the depth is less than 1
+     * @throws InvalidWorkspaceException if there is no workspace with the supplied name
+     */
+    public void reindexContent( String path,
+                                int depth ) {
+        repository().queryManager().reindexContent(workspace(), path, depth);
+    }
+
+    /**
      * Get a snapshot of the current session state. This snapshot is immutable and will not reflect any future state changes in
      * the session.
      * 

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/NodeTypeSchemata.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/NodeTypeSchemata.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/NodeTypeSchemata.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -139,8 +139,10 @@
         Set<String> fullTextSearchableNames = new HashSet<String>();
         for (JcrPropertyDefinition defn : propertyDefinitions) {
             if (defn.isResidual()) continue;
+            if (defn.isPrivate()) continue;
             // if (defn.isMultiple()) continue;
             Name name = defn.getInternalName();
+
             String columnName = name.getString(registry);
             if (first) {
                 builder.addTable(tableName, columnName);
@@ -229,12 +231,18 @@
         for (JcrPropertyDefinition defn : defns) {
             if (defn.isResidual()) continue;
             if (defn.isMultiple()) continue;
+            if (defn.isPrivate()) continue;
             Name name = defn.getInternalName();
+
             String columnName = name.getString(registry);
             if (first) first = false;
             else viewDefinition.append(',');
             viewDefinition.append('[').append(columnName).append(']');
         }
+        if (first) {
+            // All the properties were skipped ...
+            return;
+        }
         viewDefinition.append(" FROM ").append(AllNodes.ALL_NODES_NAME);
 
         // The 'nt:base' node type will have every single object in it, so we don't need to add the type criteria ...

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 14:14:56 UTC (rev 1504)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/RepositoryQueryManager.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -43,6 +43,7 @@
 import org.jboss.dna.graph.observe.Changes;
 import org.jboss.dna.graph.observe.Observable;
 import org.jboss.dna.graph.observe.Observer;
+import org.jboss.dna.graph.property.Path;
 import org.jboss.dna.graph.query.QueryContext;
 import org.jboss.dna.graph.query.QueryEngine;
 import org.jboss.dna.graph.query.QueryResults;
@@ -62,8 +63,10 @@
 import org.jboss.dna.graph.query.process.SelectComponent.Analyzer;
 import org.jboss.dna.graph.query.validate.Schemata;
 import org.jboss.dna.graph.request.AccessQueryRequest;
+import org.jboss.dna.graph.request.InvalidWorkspaceException;
 import org.jboss.dna.graph.request.processor.RequestProcessor;
 import org.jboss.dna.graph.search.SearchEngine;
+import org.jboss.dna.graph.search.SearchEngineIndexer;
 import org.jboss.dna.graph.search.SearchEngineProcessor;
 import org.jboss.dna.search.lucene.IndexRules;
 import org.jboss.dna.search.lucene.LuceneConfiguration;
@@ -98,6 +101,42 @@
         return workspace.graph().search(searchExpression, maxRowCount, offset);
     }
 
+    /**
+     * Crawl and index the content in the named workspace.
+     * 
+     * @throws IllegalArgumentException if the workspace is null
+     * @throws InvalidWorkspaceException if there is no workspace with the supplied name
+     */
+    public void reindexContent() {
+        // do nothing by default
+    }
+
+    /**
+     * Crawl and index the content in the named workspace.
+     * 
+     * @param workspace the workspace
+     * @throws IllegalArgumentException if the workspace is null
+     * @throws InvalidWorkspaceException if there is no workspace with the supplied name
+     */
+    public void reindexContent( JcrWorkspace workspace ) {
+        // do nothing by default
+    }
+
+    /**
+     * Crawl and index the content starting at the supplied path in the named workspace, to the designated depth.
+     * 
+     * @param workspace the workspace
+     * @param path the path of the content to be indexed
+     * @param depth the depth of the content to be indexed
+     * @throws IllegalArgumentException if the workspace or path are null, or if the depth is less than 1
+     * @throws InvalidWorkspaceException if there is no workspace with the supplied name
+     */
+    public void reindexContent( JcrWorkspace workspace,
+                                String path,
+                                int depth ) {
+        // do nothing by default
+    }
+
     static class Disabled extends RepositoryQueryManager {
 
         /**
@@ -138,6 +177,7 @@
         private final Observer searchObserver;
         private final ExecutorService service;
         private final QueryEngine queryEngine;
+        private final RepositoryConnectionFactory connectionFactory;
 
         SelfContained( ExecutionContext context,
                        String nameOfSourceToBeSearchable,
@@ -147,6 +187,7 @@
                        boolean updateIndexesSynchronously ) throws RepositoryException {
             this.context = context;
             this.sourceName = nameOfSourceToBeSearchable;
+            this.connectionFactory = connectionFactory;
             // Define the configuration ...
             TextEncoder encoder = new UrlEncoder();
             if (indexDirectory != null) {
@@ -273,6 +314,59 @@
             }
         }
 
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.jcr.RepositoryQueryManager#reindexContent()
+         */
+        @Override
+        public void reindexContent() {
+            // Index the existing content ...
+            Graph graph = Graph.create(sourceName, connectionFactory, context);
+            SearchEngineIndexer indexer = new SearchEngineIndexer(context, searchEngine, connectionFactory);
+            try {
+                for (String workspace : graph.getWorkspaces()) {
+                    indexer.index(workspace);
+                }
+            } finally {
+                indexer.close();
+            }
+
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.jcr.RepositoryQueryManager#reindexContent(org.jboss.dna.jcr.JcrWorkspace)
+         */
+        @Override
+        public void reindexContent( JcrWorkspace workspace ) {
+            SearchEngineIndexer indexer = new SearchEngineIndexer(context, searchEngine, connectionFactory);
+            try {
+                indexer.index(workspace.getName());
+            } finally {
+                indexer.close();
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.jcr.RepositoryQueryManager#reindexContent(org.jboss.dna.jcr.JcrWorkspace, java.lang.String, int)
+         */
+        @Override
+        public void reindexContent( JcrWorkspace workspace,
+                                    String path,
+                                    int depth ) {
+            Path at = workspace.context().getValueFactories().getPathFactory().create(path);
+            SearchEngineIndexer indexer = new SearchEngineIndexer(context, searchEngine, connectionFactory);
+            try {
+                indexer.index(workspace.getName(), at, depth);
+            } finally {
+                indexer.close();
+            }
+        }
+
         protected class GraphQueryContext extends QueryContext {
             private final RequestProcessor processor;
             private final String workspaceName;

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathQueryParser.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathQueryParser.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathQueryParser.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -82,8 +82,6 @@
     public QueryCommand parseQuery( String query,
                                     TypeSystem typeSystem ) throws InvalidQueryException, ParsingException {
         Component xpath = new XPathParser(typeSystem).parseXPath(query);
-        System.out.println(query);
-        System.out.println(" --> " + xpath);
         // Convert the result into a QueryCommand ...
         QueryCommand command = new XPathToQueryTranslator(typeSystem, query).createQuery(xpath);
         return command;

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 14:14:56 UTC (rev 1504)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslator.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -30,6 +30,7 @@
 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;
@@ -37,6 +38,7 @@
 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;
@@ -298,6 +300,14 @@
     protected String translateSource( String tableName,
                                       List<StepExpression> path,
                                       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);
+            where.path(alias).isEqualTo("/");
+            return alias;
+        }
         String alias = newAlias();
         if (tableName != null) {
             // This is after some element(...) steps, so we need to join ...
@@ -310,7 +320,7 @@
         if (path.size() == 1 && path.get(0).collapse() instanceof NameTest) {
             // Node immediately below root ...
             NameTest nodeName = (NameTest)path.get(0).collapse();
-            where.nodeName(alias).isEqualTo(nameFrom(nodeName)).and().depth(alias).isEqualTo(1);
+            where.path(alias).isEqualTo("/" + nameFrom(nodeName));
         } else if (path.size() == 2 && path.get(0) instanceof DescendantOrSelf && path.get(1).collapse() instanceof NameTest) {
             // Node anywhere ...
             NameTest nodeName = (NameTest)path.get(1).collapse();

Added: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java	                        (rev 0)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -0,0 +1,278 @@
+/*
+ * 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.jcr;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertThat;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import javax.jcr.ImportUUIDBehavior;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryResult;
+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.JcrRepository.Option;
+import org.jboss.dna.jcr.JcrRepository.QueryLanguage;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * This is a test suite that operates against a complete JcrRepository instance created and managed using the JcrEngine.
+ * Essentially this is an integration test, but it does test lower-level functionality of the implementation of the JCR interfaces
+ * related to querying. (It is simply more difficult to unit test these implementations because of the difficulty in mocking the
+ * many other components to replicate the same functionality.)
+ * <p>
+ * Also, because queries are read-only, the engine is set up once and used for the entire set of test methods.
+ * </p>
+ */
+public class JcrQueryManagerTest {
+
+    protected static URI resourceUri( String name ) throws URISyntaxException {
+        return resourceUrl(name).toURI();
+    }
+
+    protected static URL resourceUrl( String name ) {
+        return JcrQueryManagerTest.class.getClassLoader().getResource(name);
+    }
+
+    protected static InputStream resourceStream( String name ) {
+        return JcrQueryManagerTest.class.getClassLoader().getResourceAsStream(name);
+    }
+
+    private static JcrConfiguration configuration;
+    private static JcrEngine engine;
+    private static JcrRepository repository;
+    private Session session;
+
+    @BeforeClass
+    public static void beforeAll() throws Exception {
+        configuration = new JcrConfiguration();
+        configuration.repositorySource("car-source")
+                     .usingClass(InMemoryRepositorySource.class)
+                     .setDescription("The automobile content");
+        configuration.repository("cars")
+                     .setSource("car-source")
+                     .registerNamespace("car", "http://www.jboss.org/dna/examples/cars/1.0")
+                     .addNodeTypes(resourceUrl("cars.cnd"))
+                     .setOption(Option.ANONYMOUS_USER_ROLES,
+                                JcrSession.DNA_READ_PERMISSION + "," + JcrSession.DNA_WRITE_PERMISSION);
+        engine = configuration.build();
+        engine.start();
+
+        // Start the repository ...
+        repository = engine.getRepository("cars");
+
+        // Use a session to load the contents ...
+        Session session = repository.login();
+        try {
+            InputStream stream = resourceStream("io/cars-system-view.xml");
+            try {
+                session.getWorkspace().importXML("/", stream, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
+            } catch (Throwable t) {
+                t.printStackTrace();
+            } finally {
+                stream.close();
+            }
+        } finally {
+            session.logout();
+        }
+    }
+
+    @AfterClass
+    public static void afterAll() throws Exception {
+        engine.shutdown();
+        engine.awaitTermination(3, TimeUnit.SECONDS);
+        engine = null;
+        configuration = null;
+    }
+
+    @Before
+    public void beforeEach() throws Exception {
+        // Obtain a session using the anonymous login capability, which we granted READ privilege
+        session = repository.login();
+    }
+
+    @After
+    public void afterEach() throws Exception {
+        if (session != null) {
+            try {
+                session.logout();
+            } finally {
+                session = null;
+            }
+        }
+    }
+
+    protected Name name( String name ) {
+        return engine.getExecutionContext().getValueFactories().getNameFactory().create(name);
+    }
+
+    protected Segment segment( String segment ) {
+        return engine.getExecutionContext().getValueFactories().getPathFactory().createSegment(segment);
+    }
+
+    protected List<Segment> segments( String... segments ) {
+        List<Segment> result = new ArrayList<Segment>();
+        for (String segment : segments) {
+            result.add(segment(segment));
+        }
+        return result;
+    }
+
+    protected void assertResultsHaveColumns( QueryResult result,
+                                             String... columnNames ) throws RepositoryException {
+        Set<String> expectedNames = new HashSet<String>();
+        for (String name : columnNames) {
+            expectedNames.add(name);
+        }
+        Set<String> actualNames = new HashSet<String>();
+        for (String name : result.getColumnNames()) {
+            actualNames.add(name);
+        }
+        assertThat(actualNames, is(expectedNames));
+    }
+
+    @Test
+    public void shouldStartUp() {
+        assertThat(engine.getRepositoryService(), is(notNullValue()));
+    }
+
+    @Test
+    public void shouldHaveLoadedContent() throws RepositoryException {
+        Node node = session.getRootNode().getNode("Cars");
+        assertThat(node, is(notNullValue()));
+        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());
+        assertThat(node.hasNode("Hybrid/Toyota Prius"), is(true));
+        assertThat(node.getPrimaryNodeType().getName(), is("nt:unstructured"));
+    }
+
+    @Test
+    public void shouldReturnQueryManagerFromWorkspace() throws RepositoryException {
+        assertThat(session.getWorkspace().getQueryManager(), is(notNullValue()));
+    }
+
+    // ----------------------------------------------------------------------------------------------------------------
+    // JCR2-SQL Queries
+    // ----------------------------------------------------------------------------------------------------------------
+
+    @Test
+    public void shouldBeAbleToCreateAndExecuteSqlQuery() throws RepositoryException {
+        Query query = session.getWorkspace().getQueryManager().createQuery("SELECT * FROM [nt:base]", QueryLanguage.SQL);
+        assertThat(query, is(notNullValue()));
+        QueryResult result = query.execute();
+        assertThat(result, is(notNullValue()));
+        assertResultsHaveColumns(result, "jcr:primaryType");
+        System.out.println(result);
+    }
+
+    // ----------------------------------------------------------------------------------------------------------------
+    // XPath Queries
+    // ----------------------------------------------------------------------------------------------------------------
+
+    @Test
+    public void shouldBeAbleToCreateXPathQuery() throws RepositoryException {
+        Query query = session.getWorkspace().getQueryManager().createQuery("//element(*,nt:unstructured)", Query.XPATH);
+        assertThat(query, is(notNullValue()));
+    }
+
+    @Test
+    public void shouldBeAbleToExecuteXPathQueryToFindAllNodes() throws RepositoryException {
+        Query query = session.getWorkspace().getQueryManager().createQuery("//element(*,nt:base)", Query.XPATH);
+        assertThat(query, is(notNullValue()));
+        QueryResult result = query.execute();
+        assertThat(result, is(notNullValue()));
+        assertResultsHaveColumns(result, "jcr:primaryType", "jcr:path", "jcr:score");
+    }
+
+    @Test
+    public void shouldBeAbleToExecuteXPathQueryToFindAllUnstructuredNodes() throws RepositoryException {
+        Query query = session.getWorkspace().getQueryManager().createQuery("//element(*,nt:unstructured)", Query.XPATH);
+        assertThat(query, is(notNullValue()));
+        QueryResult result = query.execute();
+        assertThat(result, is(notNullValue()));
+        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);
+        assertResultsHaveColumns(result,
+                                 "jcr:primaryType",
+                                 "jcr:path",
+                                 "jcr:score",
+                                 "car:mpgCity",
+                                 "car:userRating",
+                                 "car:mpgHighway",
+                                 "car:engine",
+                                 "car:model",
+                                 "car:year",
+                                 "car:maker",
+                                 "car:lengthInInches",
+                                 "car:valueRating",
+                                 "car:wheelbaseInInches",
+                                 "car:msrp");
+    }
+
+    @Test
+    public void shouldBeAbleToExecuteXPathQueryToFindRootNode() throws RepositoryException {
+        Query query = session.getWorkspace().getQueryManager().createQuery("/jcr:root", 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 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");
+    // }
+}


Property changes on: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrQueryManagerTest.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

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 14:14:56 UTC (rev 1504)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrTckTest.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -186,7 +186,7 @@
             addTestSuite(org.apache.jackrabbit.test.api.query.GetPersistentQueryPathLevel1Test.class);
             addTestSuite(org.apache.jackrabbit.test.api.query.GetStatementTest.class);
             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.GetPropertyNamesTest.class);
             addTestSuite(org.apache.jackrabbit.test.api.query.PredicatesTest.class);
             // addTestSuite(org.apache.jackrabbit.test.api.query.SimpleSelectionTest.class);
 

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 14:14:56 UTC (rev 1504)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/xpath/XPathToQueryTranslatorTest.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -65,7 +65,6 @@
 
     @Test
     public void shouldTranslateFromXPathOfAnyNode() {
-        assertThat(xpath("/jcr:root"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1"));
         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"));
@@ -75,9 +74,13 @@
     }
 
     @Test
+    public void shouldTranslateFromXPathContainingExplicitRootPath() {
+        assertThat(xpath("/jcr:root"), isSql("SELECT * FROM [nt:base] AS nodeSet1 WHERE PATH(nodeSet1) = '/'"));
+    }
+
+    @Test
     public void shouldTranslateFromXPathContainingExplicitPath() {
-        assertThat(xpath("/jcr:root/a"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE NAME(nodeSet1) = 'a' AND DEPTH(nodeSet1) = CAST(1 AS LONG)"));
+        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'"));
@@ -225,10 +228,9 @@
                    isSql("SELECT * FROM __ALLNODES__ 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 NAME(nodeSet1) = 'nodeName' AND DEPTH(nodeSet1) = CAST(1 AS LONG)"));
+                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/nodeName'"));
 
-        assertThat(xpath("nodeName"),
-                   isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE NAME(nodeSet1) = 'nodeName' AND DEPTH(nodeSet1) = CAST(1 AS LONG)"));
+        assertThat(xpath("nodeName"), isSql("SELECT * FROM __ALLNODES__ AS nodeSet1 WHERE PATH(nodeSet1) = '/nodeName'"));
     }
 
     @Test

Added: trunk/dna-jcr/src/test/resources/cars.cnd
===================================================================
--- trunk/dna-jcr/src/test/resources/cars.cnd	                        (rev 0)
+++ trunk/dna-jcr/src/test/resources/cars.cnd	2009-12-31 16:07:24 UTC (rev 1505)
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+ 
+//------------------------------------------------------------------------------
+// N A M E S P A C E S
+//------------------------------------------------------------------------------
+<jcr='http://www.jcp.org/jcr/1.0'>
+<nt='http://www.jcp.org/jcr/nt/1.0'>
+<mix='http://www.jcp.org/jcr/mix/1.0'>
+<car='http://www.jboss.org/dna/examples/cars/1.0'>
+
+//------------------------------------------------------------------------------
+// N O D E T Y P E S
+//------------------------------------------------------------------------------
+
+[car:Car] > nt:unstructured
+  - car:maker (string)
+  - car:model (string)
+  - car:year (string) < '(19|20)\d{2}'                     // any 4 digit number starting with '19' or '20'
+  - car:msrp (string) < '[$]\d{1,3}[,]?\d{3}([.]\d{2})?'   // of the form "$X,XXX.ZZ", "$XX,XXX.ZZ" or "$XXX,XXX.ZZ" 
+                                                           // where '.ZZ' is optional
+  - car:userRating (long) < '[1,5]'                        // any value from 1 to 5 (inclusive)
+  - car:valueRating (long) < '[1,5]'                       // any value from 1 to 5 (inclusive)
+  - car:mpgCity (long) < '(0,]'                            // any value greater than 0
+  - car:mpgHighway (long) < '(0,]'                         // any value greater than 0
+  - car:lengthInInches (double) < '(0,]'                   // any value greater than 0
+  - car:wheelbaseInInches (double) < '(0,]'                // any value greater than 0
+  - car:engine (string)
+

Added: trunk/dna-jcr/src/test/resources/io/cars-system-view.xml
===================================================================
--- trunk/dna-jcr/src/test/resources/io/cars-system-view.xml	                        (rev 0)
+++ trunk/dna-jcr/src/test/resources/io/cars-system-view.xml	2009-12-31 16:07:24 UTC (rev 1505)
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sv:node xmlns:jcr="http://www.jcp.org/jcr/1.0" 
+         xmlns:nt="http://www.jcp.org/jcr/nt/1.0" 
+         xmlns:sv="http://www.jcp.org/jcr/sv/1.0"
+         xmlns:car="http://www.jboss.org/dna/examples/cars/1.0"
+         sv:name="Cars">
+  <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:unstructured</sv:value></sv:property>
+  <sv:node sv:name="Hybrid">
+    <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:unstructured</sv:value></sv:property>
+    <sv:node sv:name="Toyota Prius">
+      <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>car:Car</sv:value></sv:property>
+      <sv:property sv:name="car:maker" sv:type="String"><sv:value>Toyota</sv:value></sv:property>
+      <sv:property sv:name="car:model" sv:type="String"><sv:value>Prius</sv:value></sv:property>
+      <sv:property sv:name="car:year" sv:type="String"><sv:value>2008</sv:value></sv:property>
+      <sv:property sv:name="car:msrp" sv:type="String"><sv:value>$21,500</sv:value></sv:property>
+      <sv:property sv:name="car:userRating" sv:type="Long"><sv:value>4</sv:value></sv:property>
+      <sv:property sv:name="car:valueRating" sv:type="Long"><sv:value>5</sv:value></sv:property>
+      <sv:property sv:name="car:mpgCity" sv:type="Long"><sv:value>48</sv:value></sv:property>
+      <sv:property sv:name="car:mpgHighway" sv:type="Long"><sv:value>45</sv:value></sv:property>
+    </sv:node>
+    <sv:node sv:name="Toyota Highlander">
+      <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>car:Car</sv:value></sv:property>
+      <sv:property sv:name="car:maker" sv:type="String"><sv:value>Toyota</sv:value></sv:property>
+      <sv:property sv:name="car:model" sv:type="String"><sv:value>Highlander</sv:value></sv:property>
+      <sv:property sv:name="car:year" sv:type="String"><sv:value>2008</sv:value></sv:property>
+      <sv:property sv:name="car:msrp" sv:type="String"><sv:value>$34,200</sv:value></sv:property>
+      <sv:property sv:name="car:userRating" sv:type="Long"><sv:value>4</sv:value></sv:property>
+      <sv:property sv:name="car:valueRating" sv:type="Long"><sv:value>5</sv:value></sv:property>
+      <sv:property sv:name="car:mpgCity" sv:type="Long"><sv:value>27</sv:value></sv:property>
+      <sv:property sv:name="car:mpgHighway" sv:type="Long"><sv:value>25</sv:value></sv:property>
+    </sv:node>
+    <sv:node sv:name="Nissan Altima">
+      <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>car:Car</sv:value></sv:property>
+      <sv:property sv:name="car:maker" sv:type="String"><sv:value>Nissan</sv:value></sv:property>
+      <sv:property sv:name="car:model" sv:type="String"><sv:value>Altima</sv:value></sv:property>
+      <sv:property sv:name="car:year" sv:type="String"><sv:value>2008</sv:value></sv:property>
+      <sv:property sv:name="car:msrp" sv:type="String"><sv:value>$18,260</sv:value></sv:property>
+      <sv:property sv:name="car:mpgCity" sv:type="Long"><sv:value>23</sv:value></sv:property>
+      <sv:property sv:name="car:mpgHighway" sv:type="Long"><sv:value>32</sv:value></sv:property>
+    </sv:node>
+  </sv:node>
+  <sv:node sv:name="Sports">
+    <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:unstructured</sv:value></sv:property>
+    <sv:node sv:name="Aston Martin DB9">
+      <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>car:Car</sv:value></sv:property>
+      <sv:property sv:name="car:maker" sv:type="String"><sv:value>Aston Martin</sv:value></sv:property>
+      <sv:property sv:name="car:model" sv:type="String"><sv:value>DB9</sv:value></sv:property>
+      <sv:property sv:name="car:year" sv:type="String"><sv:value>2008</sv:value></sv:property>
+      <sv:property sv:name="car:msrp" sv:type="String"><sv:value>$171,600</sv:value></sv:property>
+      <sv:property sv:name="car:userRating" sv:type="Long"><sv:value>5</sv:value></sv:property>
+      <sv:property sv:name="car:mpgCity" sv:type="Long"><sv:value>12</sv:value></sv:property>
+      <sv:property sv:name="car:mpgHighway" sv:type="Long"><sv:value>19</sv:value></sv:property>
+      <sv:property sv:name="car:lengthInInches" sv:type="Double"><sv:value>185.5</sv:value></sv:property>
+      <sv:property sv:name="car:wheelbaseInInches" sv:type="Double"><sv:value>108.0</sv:value></sv:property>
+      <sv:property sv:name="car:engine" sv:type="String"><sv:value>5,935 cc 5.9 liters V 12</sv:value></sv:property>
+    </sv:node>
+    <sv:node sv:name="Infiniti G37">
+      <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>car:Car</sv:value></sv:property>
+      <sv:property sv:name="car:maker" sv:type="String"><sv:value>Infiniti</sv:value></sv:property>
+      <sv:property sv:name="car:model" sv:type="String"><sv:value>G37</sv:value></sv:property>
+      <sv:property sv:name="car:year" sv:type="String"><sv:value>2008</sv:value></sv:property>
+      <sv:property sv:name="car:msrp" sv:type="String"><sv:value>$34,900</sv:value></sv:property>
+      <sv:property sv:name="car:userRating" sv:type="Long"><sv:value>3</sv:value></sv:property>
+      <sv:property sv:name="car:valueRating" sv:type="Long"><sv:value>4</sv:value></sv:property>
+      <sv:property sv:name="car:mpgCity" sv:type="Long"><sv:value>18</sv:value></sv:property>
+      <sv:property sv:name="car:mpgHighway" sv:type="Long"><sv:value>24</sv:value></sv:property>
+    </sv:node>
+  </sv:node>
+  <sv:node sv:name="Luxury">
+    <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:unstructured</sv:value></sv:property>
+    <sv:node sv:name="Cadillac DTS">
+      <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>car:Car</sv:value></sv:property>
+      <sv:property sv:name="car:maker" sv:type="String"><sv:value>Cadillac</sv:value></sv:property>
+      <sv:property sv:name="car:model" sv:type="String"><sv:value>DTS</sv:value></sv:property>
+      <sv:property sv:name="car:year" sv:type="String"><sv:value>2008</sv:value></sv:property>
+      <sv:property sv:name="car:userRating" sv:type="Long"><sv:value>1</sv:value></sv:property>
+      <sv:property sv:name="car:engine" sv:type="String"><sv:value>3.6-liter V6</sv:value></sv:property>
+    </sv:node>
+    <sv:node sv:name="Bentley Continental">
+      <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>car:Car</sv:value></sv:property>
+      <sv:property sv:name="car:maker" sv:type="String"><sv:value>Bentley</sv:value></sv:property>
+      <sv:property sv:name="car:model" sv:type="String"><sv:value>Continental</sv:value></sv:property>
+      <sv:property sv:name="car:year" sv:type="String"><sv:value>2008</sv:value></sv:property>
+      <sv:property sv:name="car:msrp" sv:type="String"><sv:value>$170,990</sv:value></sv:property>
+      <sv:property sv:name="car:mpgCity" sv:type="Long"><sv:value>10</sv:value></sv:property>
+      <sv:property sv:name="car:mpgHighway" sv:type="Long"><sv:value>17</sv:value></sv:property>
+    </sv:node>
+    <sv:node sv:name="Lexus IS350">
+      <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>car:Car</sv:value></sv:property>
+      <sv:property sv:name="car:maker" sv:type="String"><sv:value>Lexus</sv:value></sv:property>
+      <sv:property sv:name="car:model" sv:type="String"><sv:value>IS350</sv:value></sv:property>
+      <sv:property sv:name="car:year" sv:type="String"><sv:value>2008</sv:value></sv:property>
+      <sv:property sv:name="car:msrp" sv:type="String"><sv:value>$36,305</sv:value></sv:property>
+      <sv:property sv:name="car:userRating" sv:type="Long"><sv:value>4</sv:value></sv:property>
+      <sv:property sv:name="car:valueRating" sv:type="Long"><sv:value>5</sv:value></sv:property>
+      <sv:property sv:name="car:mpgCity" sv:type="Long"><sv:value>18</sv:value></sv:property>
+      <sv:property sv:name="car:mpgHighway" sv:type="Long"><sv:value>25</sv:value></sv:property>
+    </sv:node>
+  </sv:node>
+  <sv:node sv:name="Utility">
+    <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>nt:unstructured</sv:value></sv:property>
+    <sv:node sv:name="Land Rover LR2">
+      <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>car:Car</sv:value></sv:property>
+      <sv:property sv:name="car:maker" sv:type="String"><sv:value>Land Rover</sv:value></sv:property>
+      <sv:property sv:name="car:model" sv:type="String"><sv:value>LR2</sv:value></sv:property>
+      <sv:property sv:name="car:year" sv:type="String"><sv:value>2008</sv:value></sv:property>
+      <sv:property sv:name="car:msrp" sv:type="String"><sv:value>$33,985</sv:value></sv:property>
+      <sv:property sv:name="car:userRating" sv:type="Long"><sv:value>4</sv:value></sv:property>
+      <sv:property sv:name="car:valueRating" sv:type="Long"><sv:value>5</sv:value></sv:property>
+      <sv:property sv:name="car:mpgCity" sv:type="Long"><sv:value>16</sv:value></sv:property>
+      <sv:property sv:name="car:mpgHighway" sv:type="Long"><sv:value>23</sv:value></sv:property>
+    </sv:node>
+    <sv:node sv:name="Land Rover LR3">
+      <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>car:Car</sv:value></sv:property>
+      <sv:property sv:name="car:maker" sv:type="String"><sv:value>Land Rover</sv:value></sv:property>
+      <sv:property sv:name="car:model" sv:type="String"><sv:value>LR3</sv:value></sv:property>
+      <sv:property sv:name="car:year" sv:type="String"><sv:value>2008</sv:value></sv:property>
+      <sv:property sv:name="car:msrp" sv:type="String"><sv:value>$48,525</sv:value></sv:property>
+      <sv:property sv:name="car:userRating" sv:type="Long"><sv:value>5</sv:value></sv:property>
+      <sv:property sv:name="car:valueRating" sv:type="Long"><sv:value>2</sv:value></sv:property>
+      <sv:property sv:name="car:mpgCity" sv:type="Long"><sv:value>12</sv:value></sv:property>
+      <sv:property sv:name="car:mpgHighway" sv:type="Long"><sv:value>17</sv:value></sv:property>
+    </sv:node>
+    <sv:node sv:name="Hummer H3">
+      <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>car:Car</sv:value></sv:property>
+      <sv:property sv:name="car:maker" sv:type="String"><sv:value>Hummer</sv:value></sv:property>
+      <sv:property sv:name="car:model" sv:type="String"><sv:value>H3</sv:value></sv:property>
+      <sv:property sv:name="car:year" sv:type="String"><sv:value>2008</sv:value></sv:property>
+      <sv:property sv:name="car:msrp" sv:type="String"><sv:value>$30,595</sv:value></sv:property>
+      <sv:property sv:name="car:userRating" sv:type="Long"><sv:value>3</sv:value></sv:property>
+      <sv:property sv:name="car:valueRating" sv:type="Long"><sv:value>4</sv:value></sv:property>
+      <sv:property sv:name="car:mpgCity" sv:type="Long"><sv:value>13</sv:value></sv:property>
+      <sv:property sv:name="car:mpgHighway" sv:type="Long"><sv:value>16</sv:value></sv:property>
+    </sv:node>
+    <sv:node sv:name="Ford F-150">
+      <sv:property sv:name="jcr:primaryType" sv:type="Name"><sv:value>car:Car</sv:value></sv:property>
+      <sv:property sv:name="car:maker" sv:type="String"><sv:value>Ford</sv:value></sv:property>
+      <sv:property sv:name="car:model" sv:type="String"><sv:value>F-150</sv:value></sv:property>
+      <sv:property sv:name="car:year" sv:type="String"><sv:value>2008</sv:value></sv:property>
+      <sv:property sv:name="car:msrp" sv:type="String"><sv:value>$23,910</sv:value></sv:property>
+      <sv:property sv:name="car:userRating" sv:type="Long"><sv:value>5</sv:value></sv:property>
+      <sv:property sv:name="car:valueRating" sv:type="Long"><sv:value>1</sv:value></sv:property>
+      <sv:property sv:name="car:mpgCity" sv:type="Long"><sv:value>14</sv:value></sv:property>
+      <sv:property sv:name="car:mpgHighway" sv:type="Long"><sv:value>20</sv:value></sv:property>
+    </sv:node>
+  </sv:node>
+</sv:node>


Property changes on: trunk/dna-jcr/src/test/resources/io/cars-system-view.xml
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/docs/examples/gettingstarted/repositories/src/test/resources/log4j.properties
===================================================================
--- trunk/docs/examples/gettingstarted/repositories/src/test/resources/log4j.properties	                        (rev 0)
+++ trunk/docs/examples/gettingstarted/repositories/src/test/resources/log4j.properties	2009-12-31 16:07:24 UTC (rev 1505)
@@ -0,0 +1,11 @@
+# Direct log messages to stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %m%n
+
+# Root logger option
+log4j.rootLogger=WARNING, stdout
+
+# Set up the default logging to be INFO level, then override specific units
+log4j.logger.org.jboss.dna=WARNING

Modified: trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchProcessor.java
===================================================================
--- trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchProcessor.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchProcessor.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -45,7 +45,6 @@
 import org.jboss.dna.graph.Location;
 import org.jboss.dna.graph.observe.Observer;
 import org.jboss.dna.graph.property.DateTime;
-import org.jboss.dna.graph.property.NamespaceRegistry;
 import org.jboss.dna.graph.property.Path;
 import org.jboss.dna.graph.property.Property;
 import org.jboss.dna.graph.query.QueryResults.Columns;
@@ -81,9 +80,10 @@
     protected static final TextEncoder NAMESPACE_ENCODER = new SecureHashTextEncoder(Algorithm.SHA_1, 10);
 
     protected static ExecutionContext contextWithEncodedNamespaces( ExecutionContext context ) {
-        NamespaceRegistry encodingRegistry = new EncodingNamespaceRegistry(context.getNamespaceRegistry(), NAMESPACE_ENCODER);
-        ExecutionContext encodingContext = context.with(encodingRegistry);
-        return encodingContext;
+        return context;
+        // NamespaceRegistry encodingRegistry = new EncodingNamespaceRegistry(context.getNamespaceRegistry(), NAMESPACE_ENCODER);
+        // ExecutionContext encodingContext = context.with(encodingRegistry);
+        // return encodingContext;
     }
 
     protected static final Columns FULL_TEXT_RESULT_COLUMNS = new FullTextSearchResultColumns();

Modified: trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchSession.java
===================================================================
--- trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchSession.java	2009-12-31 14:14:56 UTC (rev 1504)
+++ trunk/extensions/dna-search-lucene/src/main/java/org/jboss/dna/search/lucene/LuceneSearchSession.java	2009-12-31 16:07:24 UTC (rev 1505)
@@ -646,8 +646,14 @@
     protected String getIdFor( Path path ) throws IOException {
         // Create a query to find all the nodes below the parent path ...
         IndexSearcher searcher = getPathsSearcher();
-        String stringifiedPath = processor.pathAsString(path);
-        TermQuery query = new TermQuery(new Term(PathIndex.PATH, stringifiedPath));
+        Query query = null;
+        if (path.isRoot()) {
+            // Look for the query
+            query = NumericRangeQuery.newIntRange(PathIndex.DEPTH, 0, 0, true, true);
+        } else {
+            String stringifiedPath = processor.pathAsString(path);
+            query = new TermQuery(new Term(PathIndex.PATH, stringifiedPath));
+        }
 
         // Now execute and collect the UUIDs ...
         TopDocs topDocs = searcher.search(query, 1);



More information about the dna-commits mailing list