Author: rhauch
Date: 2009-10-15 15:55:26 -0400 (Thu, 15 Oct 2009)
New Revision: 1292
Added:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/model/SetCriteria.java
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/QueryBuilder.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/model/Visitor.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/model/Visitors.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/parse/SqlQueryParser.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/QueryBuilderTest.java
Log:
DNA-467 Add search/query support to the graph API
Added support for 'IN' clauses (called set criteria) in the Abstract Query Model.
Also added similar support to the SQL parser, along with support for 'NOT IN'.
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/QueryBuilder.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/QueryBuilder.java 2009-10-15
19:54:48 UTC (rev 1291)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/QueryBuilder.java 2009-10-15
19:55:26 UTC (rev 1292)
@@ -25,6 +25,8 @@
import java.math.BigDecimal;
import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
@@ -78,8 +80,10 @@
import org.jboss.dna.graph.query.model.SameNodeJoinCondition;
import org.jboss.dna.graph.query.model.Selector;
import org.jboss.dna.graph.query.model.SelectorName;
+import org.jboss.dna.graph.query.model.SetCriteria;
import org.jboss.dna.graph.query.model.SetQuery;
import org.jboss.dna.graph.query.model.Source;
+import org.jboss.dna.graph.query.model.StaticOperand;
import org.jboss.dna.graph.query.model.UpperCase;
import org.jboss.dna.graph.query.model.Visitors;
import org.jboss.dna.graph.query.model.SetQuery.Operation;
@@ -1693,6 +1697,17 @@
this.constraintBuilder = constraintBuilder;
}
+ public ConstraintBuilder isIn( Object firstLiteral,
+ Object... additionalLiterals ) {
+ CheckArg.isNotNull(firstLiteral, "firstLiteral");
+ Collection<StaticOperand> right = new
ArrayList<StaticOperand>();
+ right.add(firstLiteral instanceof Literal ? (Literal)firstLiteral : new
Literal(firstLiteral));
+ for (Object literal : additionalLiterals) {
+ right.add(literal instanceof Literal ? (Literal)literal : new
Literal(literal));
+ }
+ return this.constraintBuilder.setConstraint(new SetCriteria(left, right));
+ }
+
/**
* Define the operator that will be used in the comparison, returning an
interface that can be used to define the
* right-hand-side of the comparison.
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/model/SetCriteria.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/model/SetCriteria.java
(rev 0)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/model/SetCriteria.java 2009-10-15
19:55:26 UTC (rev 1292)
@@ -0,0 +1,96 @@
+/*
+ * 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.graph.query.model;
+
+import java.util.Collection;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.CheckArg;
+
+/**
+ * A constraint that evaluates to true when the defined operation evaluates to true.
+ */
+@Immutable
+public class SetCriteria extends Constraint {
+
+ private final DynamicOperand left;
+ private final Collection<StaticOperand> setOperands;
+
+ public SetCriteria( DynamicOperand left,
+ Collection<StaticOperand> setOperands ) {
+ CheckArg.isNotNull(left, "left");
+ CheckArg.isNotNull(setOperands, "setOperands");
+ this.left = left;
+ this.setOperands = setOperands;
+ }
+
+ /**
+ * @return operand1
+ */
+ public final DynamicOperand getLeftOperand() {
+ return left;
+ }
+
+ /**
+ * @return operand2
+ */
+ public final Collection<StaticOperand> getRightOperands() {
+ return setOperands;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return Visitors.readable(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof SetCriteria) {
+ SetCriteria that = (SetCriteria)obj;
+ if (!this.left.equals(that.left)) return false;
+ if (!this.setOperands.equals(that.setOperands)) return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see
org.jboss.dna.graph.query.model.Visitable#accept(org.jboss.dna.graph.query.model.Visitor)
+ */
+ public void accept( Visitor visitor ) {
+ visitor.visit(this);
+ }
+}
Property changes on:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/model/SetCriteria.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/model/Visitor.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/model/Visitor.java 2009-10-15
19:54:48 UTC (rev 1291)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/model/Visitor.java 2009-10-15
19:55:26 UTC (rev 1292)
@@ -88,6 +88,8 @@
void visit( SameNodeJoinCondition obj );
+ void visit( SetCriteria obj );
+
void visit( SetQuery obj );
void visit( UpperCase obj );
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/model/Visitors.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/model/Visitors.java 2009-10-15
19:54:48 UTC (rev 1291)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/model/Visitors.java 2009-10-15
19:55:26 UTC (rev 1292)
@@ -24,6 +24,7 @@
package org.jboss.dna.graph.query.model;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
import org.jboss.dna.common.util.CheckArg;
@@ -155,12 +156,12 @@
@Override
public void visit( NodeDepth depth ) {
- super.visit(depth);
+ symbols.add(depth.getSelectorName());
}
@Override
public void visit( NodePath path ) {
- super.visit(path);
+ symbols.add(path.getSelectorName());
}
@Override
@@ -462,6 +463,14 @@
/**
* {@inheritDoc}
*
+ * @see
org.jboss.dna.graph.query.model.Visitor#visit(org.jboss.dna.graph.query.model.SetCriteria)
+ */
+ public void visit( SetCriteria obj ) {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see
org.jboss.dna.graph.query.model.Visitor#visit(org.jboss.dna.graph.query.model.SetQuery)
*/
public void visit( SetQuery obj ) {
@@ -853,6 +862,20 @@
/**
* {@inheritDoc}
*
+ * @see
org.jboss.dna.graph.query.model.Visitor#visit(org.jboss.dna.graph.query.model.SetCriteria)
+ */
+ public void visit( SetCriteria setCriteria ) {
+ strategy.visit(setCriteria);
+ enqueue(setCriteria.getLeftOperand());
+ for (StaticOperand right : setCriteria.getRightOperands()) {
+ enqueue(right);
+ }
+ visitNext();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see
org.jboss.dna.graph.query.model.Visitor#visit(org.jboss.dna.graph.query.model.SetQuery)
*/
public void visit( SetQuery setQuery ) {
@@ -1331,6 +1354,25 @@
/**
* {@inheritDoc}
*
+ * @see
org.jboss.dna.graph.query.model.Visitor#visit(org.jboss.dna.graph.query.model.SetCriteria)
+ */
+ public void visit( SetCriteria criteria ) {
+ criteria.getLeftOperand().accept(this);
+ append(" IN (");
+ Iterator<StaticOperand> iter = criteria.getRightOperands().iterator();
+ if (iter.hasNext()) {
+ iter.next().accept(this);
+ while (iter.hasNext()) {
+ append(',');
+ iter.next().accept(this);
+ }
+ }
+ append(')');
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see
org.jboss.dna.graph.query.model.Visitor#visit(org.jboss.dna.graph.query.model.SetQuery)
*/
public void visit( SetQuery query ) {
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-10-15
19:54:48 UTC (rev 1291)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/parse/SqlQueryParser.java 2009-10-15
19:55:26 UTC (rev 1292)
@@ -25,6 +25,7 @@
import static org.jboss.dna.common.text.TokenStream.ANY_VALUE;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -84,6 +85,7 @@
import org.jboss.dna.graph.query.model.SameNodeJoinCondition;
import org.jboss.dna.graph.query.model.Selector;
import org.jboss.dna.graph.query.model.SelectorName;
+import org.jboss.dna.graph.query.model.SetCriteria;
import org.jboss.dna.graph.query.model.SetQuery;
import org.jboss.dna.graph.query.model.Source;
import org.jboss.dna.graph.query.model.StaticOperand;
@@ -414,9 +416,18 @@
String msg = GraphI18n.expectingConstraintCondition.text(name,
pos2.getLine(), pos2.getColumn());
throw new ParsingException(pos, msg);
}
- Operator operator = parseComparisonOperator(tokens);
- StaticOperand right = parseStaticOperand(tokens, context);
- constraint = new Comparison(left, operator, right);
+ if (tokens.matches("IN", "(")) {
+ Collection<StaticOperand> staticOperands =
parseInClause(tokens, context);
+ constraint = new SetCriteria(left, staticOperands);
+ } else if (tokens.matches("NOT", "IN",
"(")) {
+ tokens.consume("NOT");
+ Collection<StaticOperand> staticOperands =
parseInClause(tokens, context);
+ constraint = new Not(new SetCriteria(left, staticOperands));
+ } else {
+ Operator operator = parseComparisonOperator(tokens);
+ StaticOperand right = parseStaticOperand(tokens, context);
+ constraint = new Comparison(left, operator, right);
+ }
}
// else continue ...
}
@@ -435,6 +446,21 @@
return constraint;
}
+ protected Collection<StaticOperand> parseInClause( TokenStream tokens,
+ ExecutionContext context ) {
+ Collection<StaticOperand> result = new ArrayList<StaticOperand>();
+ tokens.consume("IN");
+ tokens.consume("(");
+ if (!tokens.canConsume(")")) {
+ // Not empty, so read the static operands ...
+ do {
+ result.add(parseStaticOperand(tokens, context));
+ } while (tokens.canConsume(','));
+ tokens.consume(")");
+ }
+ return result;
+ }
+
protected Term parseFullTextSearchExpression( String expression,
Position position ) {
try {
Modified: trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/QueryBuilderTest.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/QueryBuilderTest.java 2009-10-15
19:54:48 UTC (rev 1291)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/QueryBuilderTest.java 2009-10-15
19:55:26 UTC (rev 1292)
@@ -1325,4 +1325,17 @@
assertThatSql(query, is("SELECT * FROM table AS nodes " + //
"WHERE LOWER(UPPER(NAME(nodes))) =
'literal'"));
}
+
+ @Test
+ public void shouldBuilderQueryWithSetCriteria() {
+ query = builder.selectStar()
+ .from("table AS nodes")
+ .where()
+ .nodeName("nodes")
+ .isIn("value1", "value2", "value3")
+ .end()
+ .query();
+ assertThatSql(query, is("SELECT * FROM table AS nodes " + //
+ "WHERE NAME(nodes) IN
('value1','value2','value3')"));
+ }
}