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);