Author: rhauch
Date: 2009-10-15 15:54:48 -0400 (Thu, 15 Oct 2009)
New Revision: 1291
Added:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/Queryable.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/parse/QueryParsers.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/parse/QueryParsersTest.java
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/QueryEngine.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/package-info.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/parse/SqlQueryParser.java
trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathQueryParser.java
trunk/dna-search/src/main/java/org/jboss/dna/search/LuceneQueryEngine.java
Log:
DNA-467 Add search/query support to the graph API
Broke out the language parsing from the QueryEngine and into a new QueryParsers. The
QueryEngine should do everything in terms of a QueryCommand, since it's possible for
the query engines to be layered, and parsing languages is completely orthogonal to
execution.
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/QueryEngine.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/QueryEngine.java 2009-10-15
19:53:51 UTC (rev 1290)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/QueryEngine.java 2009-10-15
19:54:48 UTC (rev 1291)
@@ -23,18 +23,11 @@
*/
package org.jboss.dna.graph.query;
-import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.common.text.ParsingException;
import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.ExecutionContext;
-import org.jboss.dna.graph.GraphI18n;
import org.jboss.dna.graph.query.QueryResults.Statistics;
import org.jboss.dna.graph.query.model.Column;
import org.jboss.dna.graph.query.model.Constraint;
@@ -44,8 +37,6 @@
import org.jboss.dna.graph.query.model.Visitors;
import org.jboss.dna.graph.query.optimize.Optimizer;
import org.jboss.dna.graph.query.optimize.RuleBasedOptimizer;
-import org.jboss.dna.graph.query.parse.InvalidQueryException;
-import org.jboss.dna.graph.query.parse.QueryParser;
import org.jboss.dna.graph.query.plan.CanonicalPlanner;
import org.jboss.dna.graph.query.plan.PlanHints;
import org.jboss.dna.graph.query.plan.PlanNode;
@@ -61,19 +52,30 @@
* A query engine that is able to execute formal queries expressed in the Graph API's
{@link QueryCommand Abstract Query Model}.
*/
@ThreadSafe
-public class QueryEngine {
+public class QueryEngine implements Queryable {
private final Planner planner;
private final Optimizer optimizer;
private final Processor processor;
private final Schemata schemata;
- private final ConcurrentMap<String, QueryParser> parsers = new
ConcurrentHashMap<String, QueryParser>();
+ /**
+ * Create a new query engine given the {@link Planner planner}, {@link Optimizer
optimizer}, {@link Processor processor}, and
+ * {@link Schemata schemata}.
+ *
+ * @param planner the planner that should be used to generate canonical query plans
for the queries; may be null if the
+ * {@link CanonicalPlanner} should be used
+ * @param optimizer the optimizer that should be used to optimize the canonical query
plan; may be null if the
+ * {@link RuleBasedOptimizer} should be used
+ * @param processor the processor implementation that should be used to process the
planned query and return the results
+ * @param schemata the schemata implementation, or null if an empty schema should be
used (resulting in errors when named
+ * tables are queried)
+ * @throws IllegalArgumentException if the processor reference is null
+ */
public QueryEngine( Planner planner,
Optimizer optimizer,
Processor processor,
- Schemata schemata,
- QueryParser... parsers ) {
+ Schemata schemata ) {
CheckArg.isNotNull(processor, "processor");
this.planner = planner != null ? planner : new CanonicalPlanner();
this.optimizer = optimizer != null ? optimizer : new RuleBasedOptimizer();
@@ -85,93 +87,24 @@
return null;
}
};
- for (QueryParser parser : parsers) {
- if (parser != null) addLanguage(parser);
- }
}
/**
- * Add a language to this engine by supplying its parser.
+ * {@inheritDoc}
*
- * @param languageParser the query parser for the language
- * @throws IllegalArgumentException if the language parser is null
+ * @see
org.jboss.dna.graph.query.Queryable#execute(org.jboss.dna.graph.ExecutionContext,
+ * org.jboss.dna.graph.query.model.QueryCommand)
*/
- public void addLanguage( QueryParser languageParser ) {
- CheckArg.isNotNull(languageParser, "languageParser");
- this.parsers.put(languageParser.getLanguage().toLowerCase(), languageParser);
- }
-
- /**
- * Remove from this engine the language with the given name.
- *
- * @param language the name of the language, which is to match the {@link
QueryParser#getLanguage() language} of the parser
- * @return the parser for the language, or null if the engine had no support for the
named language
- * @throws IllegalArgumentException if the language is null
- */
- public QueryParser removeLanguage( String language ) {
- CheckArg.isNotNull(language, "language");
- return this.parsers.remove(language.toLowerCase());
- }
-
- /**
- * Get the set of languages that this engine is capable of parsing.
- *
- * @return the unmodifiable copy of the set of languages; never null but possibly
empty
- */
- public Set<String> getLanguages() {
- Set<String> result = new HashSet<String>();
- for (QueryParser parser : parsers.values()) {
- result.add(parser.getLanguage());
- }
- return Collections.unmodifiableSet(result);
- }
-
- /**
- * Execute the supplied query by planning, optimizing, and then processing it.
- *
- * @param context the context in which the query should be executed
- * @param language the language in which the query is expressed; must be one of the
supported {@link #getLanguages()
- * languages}
- * @param query the query that is to be executed
- * @return the query results; never null
- * @throws IllegalArgumentException if the language, context or query references are
null, or if the language is not know
- * @throws ParsingException if there is an error parsing the supplied query
- * @throws InvalidQueryException if the supplied query can be parsed but is invalid
- */
public QueryResults execute( ExecutionContext context,
- String language,
- String query ) {
- CheckArg.isNotNull(language, "language");
- CheckArg.isNotNull(context, "context");
- CheckArg.isNotNull(query, "query");
- QueryParser parser = parsers.get(language.toLowerCase());
- if (parser == null) {
- throw new
IllegalArgumentException(GraphI18n.unknownQueryLanguage.text(language));
- }
- return execute(context, parser.parseQuery(query, context));
- }
-
- /**
- * Execute the supplied query by planning, optimizing, and then processing it.
- *
- * @param context the context in which the query should be executed
- * @param query the query that is to be executed
- * @return the query results; never null
- * @throws IllegalArgumentException if the context or query references are null
- */
- public QueryResults execute( ExecutionContext context,
QueryCommand query ) {
return execute(context, query, new PlanHints());
}
/**
- * Execute the supplied query by planning, optimizing, and then processing it.
+ * {@inheritDoc}
*
- * @param context the context in which the query should be executed
- * @param query the query that is to be executed
- * @param hints the hints for the execution; may be null if there are no hints
- * @return the query results; never null
- * @throws IllegalArgumentException if the context or query references are null
+ * @see
org.jboss.dna.graph.query.Queryable#execute(org.jboss.dna.graph.ExecutionContext,
+ * org.jboss.dna.graph.query.model.QueryCommand,
org.jboss.dna.graph.query.plan.PlanHints)
*/
public QueryResults execute( ExecutionContext context,
QueryCommand query,
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/Queryable.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/Queryable.java
(rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/Queryable.java 2009-10-15
19:54:48 UTC (rev 1291)
@@ -0,0 +1,58 @@
+/*
+ * 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;
+
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.query.model.QueryCommand;
+import org.jboss.dna.graph.query.plan.PlanHints;
+
+/**
+ * An interface defining the ability to submit a query and obtain results.
+ */
+public interface Queryable {
+
+ /**
+ * Execute the supplied query by planning, optimizing, and then processing it.
+ *
+ * @param context the context in which the query should be executed
+ * @param query the query that is to be executed
+ * @return the query results; never null
+ * @throws IllegalArgumentException if the context or query references are null
+ */
+ QueryResults execute( ExecutionContext context,
+ QueryCommand query );
+
+ /**
+ * Execute the supplied query by planning, optimizing, and then processing it.
+ *
+ * @param context the context in which the query should be executed
+ * @param query the query that is to be executed
+ * @param hints the hints for the execution; may be null if there are no hints
+ * @return the query results; never null
+ * @throws IllegalArgumentException if the context or query references are null
+ */
+ QueryResults execute( ExecutionContext context,
+ QueryCommand query,
+ PlanHints hints );
+}
Property changes on:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/Queryable.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/package-info.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/package-info.java 2009-10-15
19:53:51 UTC (rev 1290)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/package-info.java 2009-10-15
19:54:48 UTC (rev 1291)
@@ -41,6 +41,7 @@
* model using the {@link QueryBuilder}, which provides a fluent API that makes it easy
to create a query
* with Java code. The second (and more common) approach is to use a {@link
org.jboss.dna.graph.query.parse.QueryParser}
* that parses a query represented in a specific language (like SQL or XPath) and then
creates the query's equivalent abstract query model.
+ * There's even a {@link org.jboss.dna.graph.query.parse.QueryParsers} class that can
manage the parsers for multiple languages.
* </p>
* <p>
* The abstract query model classes are immutable, making them very easily shared or
reused if that is advantageous.
Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/parse/QueryParsers.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/parse/QueryParsers.java
(rev 0)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/parse/QueryParsers.java 2009-10-15
19:54:48 UTC (rev 1291)
@@ -0,0 +1,215 @@
+/*
+ * 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.parse;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.text.ParsingException;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.GraphI18n;
+import org.jboss.dna.graph.query.model.QueryCommand;
+
+/**
+ * A thread-safe collection of {@link QueryParser} implementations that can be used to
parse queries by language.
+ */
+@ThreadSafe
+public class QueryParsers {
+
+ private final ConcurrentMap<String, QueryParser> parsers = new
ConcurrentHashMap<String, QueryParser>();
+
+ /**
+ * Create a new collection of the supplied {@link QueryParser} objects.
+ *
+ * @param parsers the parsers
+ */
+ public QueryParsers( QueryParser... parsers ) {
+ if (parsers != null) {
+ for (QueryParser parser : parsers) {
+ if (parser != null) addLanguage(parser);
+ }
+ }
+ }
+
+ /**
+ * Create a new collection of the supplied {@link QueryParser} objects.
+ *
+ * @param parsers the parsers
+ */
+ public QueryParsers( Iterable<QueryParser> parsers ) {
+ if (parsers != null) addLanguages(parsers);
+ }
+
+ /**
+ * Add a language to this engine by supplying its parser.
+ *
+ * @param languageParser the query parser for the language
+ * @throws IllegalArgumentException if the language parser is null
+ */
+ public void addLanguage( QueryParser languageParser ) {
+ CheckArg.isNotNull(languageParser, "languageParser");
+ this.parsers.put(languageParser.getLanguage().toLowerCase(), languageParser);
+ }
+
+ /**
+ * Add one or more languages to this engine by supplying the corresponding parsers.
+ *
+ * @param firstLanguage the query parser for the first language
+ * @param additionalLanguages the query parsers for the additional languages
+ * @throws IllegalArgumentException if the language parser is null
+ */
+ public void addLanguages( QueryParser firstLanguage,
+ QueryParser... additionalLanguages ) {
+ addLanguage(firstLanguage);
+ for (QueryParser language : additionalLanguages) {
+ addLanguage(language);
+ }
+ }
+
+ /**
+ * Add one or more languages to this engine by supplying the corresponding parsers.
+ *
+ * @param languages the query parsers for the languages that are to be added
+ * @throws IllegalArgumentException if the iterable reference is null
+ */
+ public void addLanguages( Iterable<QueryParser> languages ) {
+ CheckArg.isNotNull(languages, "languages");
+ for (QueryParser language : languages) {
+ addLanguage(language);
+ }
+ }
+
+ /**
+ * Remove from this engine the language with the given name.
+ *
+ * @param language the name of the language, which is to match the {@link
QueryParser#getLanguage() language} of the parser
+ * @return the parser for the language, or null if the engine had no support for the
named language
+ * @throws IllegalArgumentException if the language is null
+ */
+ public QueryParser removeLanguage( String language ) {
+ CheckArg.isNotNull(language, "language");
+ return this.parsers.remove(language.toLowerCase());
+ }
+
+ /**
+ * Remove from this engine the language with the given name.
+ *
+ * @param firstLanguage the name of the first language to remove, which must match
the {@link QueryParser#getLanguage()
+ * language} of the parser
+ * @param additionalLanguages the names of the additional languages to remove, which
must match the
+ * {@link QueryParser#getLanguage() language} of the parser
+ * @return the parser for the language, or null if the engine had no support for the
named language
+ * @throws IllegalArgumentException if the language is null
+ */
+ public Collection<QueryParser> removeLanguages( String firstLanguage,
+ String... additionalLanguages ) {
+ Collection<QueryParser> removed = new HashSet<QueryParser>();
+ QueryParser parser = removeLanguage(firstLanguage);
+ if (parser != null) removed.add(parser);
+ for (String language : additionalLanguages) {
+ parser = removeLanguage(language);
+ if (parser != null) removed.add(parser);
+ }
+ return removed;
+ }
+
+ /**
+ * Get the set of languages that this engine is capable of parsing.
+ *
+ * @return the unmodifiable copy of the set of languages; never null but possibly
empty
+ */
+ public Set<String> getLanguages() {
+ Set<String> result = new HashSet<String>();
+ for (QueryParser parser : parsers.values()) {
+ result.add(parser.getLanguage());
+ }
+ return Collections.unmodifiableSet(result);
+ }
+
+ /**
+ * Execute the supplied query by planning, optimizing, and then processing it.
+ *
+ * @param context the context in which the query should be executed
+ * @param language the language in which the query is expressed; must be one of the
supported {@link #getLanguages()
+ * languages}
+ * @param query the query that is to be executed
+ * @return the parsed query command; never null
+ * @throws IllegalArgumentException if the language, context or query references are
null, or if the language is not known
+ * @throws ParsingException if there is an error parsing the supplied query
+ * @throws InvalidQueryException if the supplied query can be parsed but is invalid
+ */
+ public QueryCommand parse( ExecutionContext context,
+ String language,
+ String query ) {
+ CheckArg.isNotNull(language, "language");
+ CheckArg.isNotNull(context, "context");
+ CheckArg.isNotNull(query, "query");
+ QueryParser parser = parsers.get(language.toLowerCase());
+ if (parser == null) {
+ throw new
IllegalArgumentException(GraphI18n.unknownQueryLanguage.text(language));
+ }
+ return parser.parseQuery(query, context);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ // There won't be too many instances of QueryParsers, so have them all return
the same hash code
+ return 1;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof QueryParsers) {
+ QueryParsers that = (QueryParsers)obj;
+ return this.getLanguages().equals(that.getLanguages());
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "Query parsers: " + parsers.keySet();
+ }
+}
Property changes on:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/parse/QueryParsers.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
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:53:51 UTC (rev 1290)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/query/parse/SqlQueryParser.java 2009-10-15
19:54:48 UTC (rev 1291)
@@ -118,6 +118,31 @@
/**
* {@inheritDoc}
*
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return LANGUAGE;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof QueryParser) {
+ QueryParser that = (QueryParser)obj;
+ return this.getLanguage().equals(that.getLanguage());
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see org.jboss.dna.graph.query.parse.QueryParser#parseQuery(String,
ExecutionContext)
*/
public QueryCommand parseQuery( String query,
Added:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/parse/QueryParsersTest.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/parse/QueryParsersTest.java
(rev 0)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/parse/QueryParsersTest.java 2009-10-15
19:54:48 UTC (rev 1291)
@@ -0,0 +1,181 @@
+/*
+ * 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.parse;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.query.model.QueryCommand;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class QueryParsersTest {
+
+ private QueryParsers parsers;
+ private QueryParser parser1;
+ private QueryParser parser2;
+ private QueryParser parser3;
+
+ @Before
+ public void beforeEach() {
+ parsers = new QueryParsers();
+ parser1 = new MockParser("language 1");
+ parser2 = new MockParser("language 2");
+ parser3 = new MockParser("language 3");
+ }
+
+ @Test
+ public void shouldAllowNullArrayInConstructor() {
+ parsers = new QueryParsers((QueryParser[])null);
+ assertThat(parsers.getLanguages().isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldAllowNullIterableInConstructor() {
+ parsers = new QueryParsers((Iterable<QueryParser>)null);
+ assertThat(parsers.getLanguages().isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldAllowOneQueryParserReferenceInConstructor() {
+ parsers = new QueryParsers(parser1);
+ assertThat(parsers.getLanguages().size(), is(1));
+ assertThat(parsers.getLanguages().contains(parser1.getLanguage()), is(true));
+ }
+
+ @Test
+ public void shouldAllowTwoQueryParserReferencesInConstructor() {
+ parsers = new QueryParsers(parser1, parser2);
+ assertThat(parsers.getLanguages().size(), is(2));
+ assertThat(parsers.getLanguages().contains(parser1.getLanguage()), is(true));
+ assertThat(parsers.getLanguages().contains(parser2.getLanguage()), is(true));
+ }
+
+ @Test
+ public void shouldAllowThreeQueryParserReferencesInConstructor() {
+ parsers = new QueryParsers(parser1, parser2, parser3);
+ assertThat(parsers.getLanguages().size(), is(3));
+ assertThat(parsers.getLanguages().contains(parser1.getLanguage()), is(true));
+ assertThat(parsers.getLanguages().contains(parser2.getLanguage()), is(true));
+ assertThat(parsers.getLanguages().contains(parser3.getLanguage()), is(true));
+ }
+
+ @Test
+ public void shouldOverwriteQueryParsersWithSameLanguageInConstructor() {
+ parser2 = new MockParser(parser1.getLanguage());
+ parsers = new QueryParsers(parser1, parser2, parser3);
+ assertThat(parsers.getLanguages().size(), is(2));
+ assertThat(parsers.getLanguages().contains(parser2.getLanguage()), is(true));
+ assertThat(parsers.getLanguages().contains(parser3.getLanguage()), is(true));
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowNullQueryParserReferenceInAddLanguagesMethod() {
+ parsers.addLanguages((QueryParser)null);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldAllowNullIterableInAddLanguagesMethod() {
+ parsers.addLanguages((Iterable<QueryParser>)null);
+ }
+
+ @Test
+ public void shouldAddOneQueryParserReference() {
+ parsers.addLanguage(parser1);
+ assertThat(parsers.getLanguages().size(), is(1));
+ assertThat(parsers.getLanguages().contains(parser1.getLanguage()), is(true));
+ }
+
+ @Test
+ public void shouldAddTwoQueryParserReferences() {
+ parsers.addLanguages(parser1, parser2);
+ assertThat(parsers.getLanguages().size(), is(2));
+ assertThat(parsers.getLanguages().contains(parser1.getLanguage()), is(true));
+ assertThat(parsers.getLanguages().contains(parser2.getLanguage()), is(true));
+ }
+
+ @Test
+ public void shouldAddThreeQueryParserReferences() {
+ parsers.addLanguages(parser1, parser2, parser3);
+ assertThat(parsers.getLanguages().size(), is(3));
+ assertThat(parsers.getLanguages().contains(parser1.getLanguage()), is(true));
+ assertThat(parsers.getLanguages().contains(parser2.getLanguage()), is(true));
+ assertThat(parsers.getLanguages().contains(parser3.getLanguage()), is(true));
+ }
+
+ @Test
+ public void shouldOverwriteQueryParsersWithSameLanguageWhenAddingQueryParser() {
+ parser2 = new MockParser(parser1.getLanguage());
+ parsers.addLanguages(parser1, parser2, parser3);
+ assertThat(parsers.getLanguages().size(), is(2));
+ assertThat(parsers.getLanguages().contains(parser2.getLanguage()), is(true));
+ assertThat(parsers.getLanguages().contains(parser3.getLanguage()), is(true));
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToParseUnknownLanguage() {
+ parsers.parse(new ExecutionContext(), "unknown language", "This is
a bogus query");
+ }
+
+ protected static class MockParser implements QueryParser {
+ private final String language;
+
+ protected MockParser( String language ) {
+ this.language = language;
+ assert this.language != null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.query.parse.QueryParser#getLanguage()
+ */
+ public String getLanguage() {
+ return language;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.query.parse.QueryParser#parseQuery(java.lang.String,
org.jboss.dna.graph.ExecutionContext)
+ */
+ public QueryCommand parseQuery( String query,
+ ExecutionContext context ) throws
InvalidQueryException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "Mock parser for " + language;
+ }
+ }
+}
Property changes on:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/query/parse/QueryParsersTest.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
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-10-15
19:53:51 UTC (rev 1290)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/xpath/XPathQueryParser.java 2009-10-15
19:54:48 UTC (rev 1291)
@@ -51,6 +51,31 @@
/**
* {@inheritDoc}
*
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return LANGUAGE;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof QueryParser) {
+ QueryParser that = (QueryParser)obj;
+ return this.getLanguage().equals(that.getLanguage());
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see org.jboss.dna.graph.query.parse.QueryParser#parseQuery(java.lang.String,
org.jboss.dna.graph.ExecutionContext)
*/
public QueryCommand parseQuery( String query,
Modified: trunk/dna-search/src/main/java/org/jboss/dna/search/LuceneQueryEngine.java
===================================================================
--- trunk/dna-search/src/main/java/org/jboss/dna/search/LuceneQueryEngine.java 2009-10-15
19:53:51 UTC (rev 1290)
+++ trunk/dna-search/src/main/java/org/jboss/dna/search/LuceneQueryEngine.java 2009-10-15
19:54:48 UTC (rev 1291)
@@ -25,10 +25,7 @@
import java.io.IOException;
import java.util.LinkedList;
-import java.util.Set;
import org.apache.lucene.queryParser.ParseException;
-import org.jboss.dna.common.text.ParsingException;
-import org.jboss.dna.common.util.CheckArg;
import org.jboss.dna.graph.query.QueryContext;
import org.jboss.dna.graph.query.QueryEngine;
import org.jboss.dna.graph.query.QueryResults;
@@ -37,8 +34,6 @@
import org.jboss.dna.graph.query.optimize.Optimizer;
import org.jboss.dna.graph.query.optimize.OptimizerRule;
import org.jboss.dna.graph.query.optimize.RuleBasedOptimizer;
-import org.jboss.dna.graph.query.parse.InvalidQueryException;
-import org.jboss.dna.graph.query.parse.QueryParser;
import org.jboss.dna.graph.query.plan.CanonicalPlanner;
import org.jboss.dna.graph.query.plan.PlanHints;
import org.jboss.dna.graph.query.plan.PlanNode;
@@ -58,66 +53,10 @@
engine = new QueryEngine(new CanonicalPlanner(), new LuceneOptimizer(), new
LuceneProcessor(), schemata);
}
- public LuceneQueryEngine( Schemata schemata,
- QueryParser... languages ) {
- engine = new QueryEngine(new CanonicalPlanner(), new LuceneOptimizer(), new
LuceneProcessor(), schemata, languages);
- }
-
/**
- * Add a language to this engine by supplying its parser.
- *
- * @param languageParser the query parser for the language
- * @throws IllegalArgumentException if the language parser is null
- */
- public void addLanguage( QueryParser languageParser ) {
- this.engine.addLanguage(languageParser);
- }
-
- /**
- * Remove from this engine the language with the given name.
- *
- * @param language the name of the language, which is to match the {@link
QueryParser#getLanguage() language} of the parser
- * @return the parser for the language, or null if the engine had no support for the
named language
- * @throws IllegalArgumentException if the language is null
- */
- public QueryParser removeLanguage( String language ) {
- return this.engine.removeLanguage(language);
- }
-
- /**
- * Get the set of languages that this engine is capable of parsing.
- *
- * @return the unmodifiable copy of the set of languages; never null but possibly
empty
- */
- public Set<String> getLanguages() {
- return this.engine.getLanguages();
- }
-
- /**
* Execute the supplied query by planning, optimizing, and then processing it.
*
- * @param indexes the context in which the query should be executed
- * @param language the language in which the query is expressed; must be one of the
supported {@link #getLanguages()
- * languages}
* @param query the query that is to be executed
- * @return the query results; never null
- * @throws IllegalArgumentException if the language, context or query references are
null, or if the language is not know
- * @throws ParsingException if there is an error parsing the supplied query
- * @throws InvalidQueryException if the supplied query can be parsed but is invalid
- */
- public QueryResults execute( IndexContext indexes,
- String language,
- String query ) {
- CheckArg.isNotNull(language, "language");
- CheckArg.isNotNull(indexes, "indexes");
- CheckArg.isNotNull(query, "query");
- return engine.execute(indexes.context(), language, query);
- }
-
- /**
- * Execute the supplied query by planning, optimizing, and then processing it.
- *
- * @param query the query that is to be executed
* @param indexes the indexes that should be used to execute the query; never null
* @return the query results; never null
* @throws IllegalArgumentException if the context or query references are null