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

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Thu Oct 15 15:54:48 EDT 2009


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.
+ */
+ at 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



More information about the dna-commits mailing list