lucene-java-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sim...@apache.org
Subject svn commit: r887533 - in /lucene/java/trunk/contrib: ./ misc/src/java/org/apache/lucene/queryParser/ext/ misc/src/test/org/apache/lucene/queryParser/ext/
Date Sat, 05 Dec 2009 12:30:02 GMT
Author: simonw
Date: Sat Dec  5 12:29:59 2009
New Revision: 887533

URL: http://svn.apache.org/viewvc?rev=887533&view=rev
Log:
LUCENE-2039: Added extensible query parser which enables arbitrary parser extensions based
on field naming scheme

Added:
    lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/
    lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ExtendableQueryParser.java
  (with props)
    lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ExtensionQuery.java
  (with props)
    lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/Extensions.java
  (with props)
    lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ParserExtension.java
  (with props)
    lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/package.html
  (with props)
    lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/
    lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/ExtensionStub.java
  (with props)
    lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/TestExtendableQueryParser.java
  (with props)
    lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/TestExtensions.java
  (with props)
Modified:
    lucene/java/trunk/contrib/CHANGES.txt

Modified: lucene/java/trunk/contrib/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/CHANGES.txt?rev=887533&r1=887532&r2=887533&view=diff
==============================================================================
--- lucene/java/trunk/contrib/CHANGES.txt (original)
+++ lucene/java/trunk/contrib/CHANGES.txt Sat Dec  5 12:29:59 2009
@@ -16,6 +16,11 @@
    reader.  (Eirik Bjørsnøs via Mike McCandless)
 
 New features
+ 
+ * LUCENE-2039: Add a extensible query parser to contrib/misc.
+   ExtendableQueryParser enables arbitrary parser extensions based on a
+   customizable field naming scheme.
+   (Simon Willnauer)
 
  * LUCENE-2108: Spellchecker now safely supports concurrent modifications to
    the spell-index. Threads can safely obtain term suggestions while the spell-

Added: lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ExtendableQueryParser.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ExtendableQueryParser.java?rev=887533&view=auto
==============================================================================
--- lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ExtendableQueryParser.java
(added)
+++ lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ExtendableQueryParser.java
Sat Dec  5 12:29:59 2009
@@ -0,0 +1,142 @@
+package org.apache.lucene.queryParser.ext;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.queryParser.ext.Extensions.Pair;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.util.Version;
+
+/**
+ * The {@link ExtendableQueryParser} enables arbitrary query parser extension
+ * based on a customizable field naming scheme. The lucene query syntax allows
+ * implicit and explicit field definitions as query prefix followed by a colon
+ * (':') character. The {@link ExtendableQueryParser} allows to encode extension
+ * keys into the field symbol associated with a registered instance of
+ * {@link ParserExtension}. A customizable separation character separates the
+ * extension key from the actual field symbol. The {@link ExtendableQueryParser}
+ * splits (@see {@link Extensions#splitExtensionField(String, String)}) the
+ * extension key from the field symbol and tries to resolve the associated
+ * {@link ParserExtension}. If the parser can't resolve the key or the field
+ * token does not contain a separation character, {@link ExtendableQueryParser}
+ * yields the same behavior as its super class {@link QueryParser}. Otherwise,
+ * if the key is associated with a {@link ParserExtension} instance, the parser
+ * builds an instance of {@link ExtensionQuery} to be processed by
+ * {@link ParserExtension#parse(ExtensionQuery)}.If a extension field does not
+ * contain a field part the default field for the query will be used.
+ * <p>
+ * To guarantee that an extension field is processed with its associated
+ * extension, the extension query part must escape any special characters like
+ * '*' or '['. If the extension query contains any whitespace characters, the
+ * extension query part must be enclosed in quotes.
+ * Example ('_' used as separation character):
+ * <pre>
+ *   title_customExt:"Apache Lucene\?" OR content_customExt:prefix\*
+ * </pre>
+ * 
+ * Search on the default field:
+ * <pre>
+ *   _customExt:"Apache Lucene\?" OR _customExt:prefix\*
+ * </pre>
+ * </p>
+ * <p>
+ * The {@link ExtendableQueryParser} itself does not implement the logic how
+ * field and extension key are separated or ordered. All logic regarding the
+ * extension key and field symbol parsing is located in {@link Extensions}.
+ * Customized extension schemes should be implemented by sub-classing
+ * {@link Extensions}.
+ * </p>
+ * <p>
+ * For details about the default encoding scheme see {@link Extensions}.
+ * </p>
+ * 
+ * @see Extensions
+ * @see ParserExtension
+ * @see ExtensionQuery
+ */
+public class ExtendableQueryParser extends QueryParser {
+
+  private final String defaultField;
+  private final Extensions extensions;
+
+  /**
+   * Default empty extensions instance
+   */
+  private static final Extensions DEFAULT_EXTENSION = new Extensions();
+
+  /**
+   * Creates a new {@link ExtendableQueryParser} instance
+   * 
+   * @param matchVersion
+   *          the lucene version to use.
+   * @param f
+   *          the default query field
+   * @param a
+   *          the analyzer used to find terms in a query string
+   */
+  public ExtendableQueryParser(final Version matchVersion, final String f,
+      final Analyzer a) {
+    this(matchVersion, f, a, DEFAULT_EXTENSION);
+
+  }
+
+  /**
+   * Creates a new {@link ExtendableQueryParser} instance
+   * 
+   * @param matchVersion
+   *          the lucene version to use.
+   * @param f
+   *          the default query field
+   * @param a
+   *          the analyzer used to find terms in a query string
+   * @param ext
+   *          the query parser extensions
+   */
+  public ExtendableQueryParser(final Version matchVersion, final String f,
+      final Analyzer a, final Extensions ext) {
+    super(matchVersion, f, a);
+    this.defaultField = f;
+    this.extensions = ext;
+  }
+
+  /**
+   * Returns the extension field delimiter character.
+   * 
+   * @return the extension field delimiter character.
+   */
+  public char getExtensionFieldDelimiter() {
+    return extensions.getExtensionFieldDelimiter();
+  }
+
+  @Override
+  protected Query getFieldQuery(final String field, final String queryText)
+      throws ParseException {
+    final Pair<String,String> splitExtensionField = this.extensions
+        .splitExtensionField(defaultField, field);
+    final ParserExtension extension = this.extensions
+        .getExtension(splitExtensionField.cud);
+    if (extension != null) {
+      return extension.parse(new ExtensionQuery(splitExtensionField.cur,
+          queryText));
+    }
+    return super.getFieldQuery(field, queryText);
+  }
+
+}

Propchange: lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ExtendableQueryParser.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ExtendableQueryParser.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ExtensionQuery.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ExtensionQuery.java?rev=887533&view=auto
==============================================================================
--- lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ExtensionQuery.java
(added)
+++ lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ExtensionQuery.java
Sat Dec  5 12:29:59 2009
@@ -0,0 +1,63 @@
+package org.apache.lucene.queryParser.ext;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * {@link ExtensionQuery} holds all query components extracted from the original
+ * query string like the query field and the extension query string.
+ * 
+ * @see Extensions
+ * @see ExtendableQueryParser
+ * @see ParserExtension
+ */
+public class ExtensionQuery {
+
+  private final String field;
+  private final String rawQueryString;
+
+  /**
+   * Creates a new {@link ExtensionQuery}
+   * 
+   * @param field
+   *          the query field
+   * @param rawQueryString
+   *          the raw extension query string
+   */
+  public ExtensionQuery(String field, String rawQueryString) {
+    this.field = field;
+    this.rawQueryString = rawQueryString;
+  }
+
+  /**
+   * Returns the query field
+   * 
+   * @return the query field
+   */
+  public String getField() {
+    return field;
+  }
+
+  /**
+   * Returns the raw extension query string
+   * 
+   * @return the raw extension query string
+   */
+  public String getRawQueryString() {
+    return rawQueryString;
+  }
+}

Propchange: lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ExtensionQuery.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ExtensionQuery.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/Extensions.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/Extensions.java?rev=887533&view=auto
==============================================================================
--- lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/Extensions.java
(added)
+++ lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/Extensions.java
Sat Dec  5 12:29:59 2009
@@ -0,0 +1,217 @@
+package org.apache.lucene.queryParser.ext;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.lucene.queryParser.QueryParser;
+
+/**
+ * The {@link Extensions} class represents an extension mapping to associate
+ * {@link ParserExtension} instances with extension keys. An extension key is a
+ * string encoded into a Lucene standard query parser field symbol recognized by
+ * {@link ExtendableQueryParser}. The query parser passes each extension field
+ * token to {@link #splitExtensionField(String, String)} to separate the
+ * extension key from the field identifier.
+ * <p>
+ * In addition to the key to extension mapping this class also defines the field
+ * name overloading scheme. {@link ExtendableQueryParser} uses the given
+ * extension to split the actual field name and extension key by calling
+ * {@link #splitExtensionField(String, String)}. To change the order or the key
+ * / field name encoding scheme users can subclass {@link Extensions} to
+ * implement their own.
+ * 
+ * @see ExtendableQueryParser
+ * @see ParserExtension
+ */
+public class Extensions {
+  private final Map<String,ParserExtension> extensions = new HashMap<String,ParserExtension>();
+  private final char extensionFieldDelimiter;
+  /**
+   * The default extension field delimiter character. This constant is set to
+   * ':'
+   */
+  public static final char DEFAULT_EXTENSION_FIELD_DELIMITER = ':';
+
+  /**
+   * Creates a new {@link Extensions} instance with the
+   * {@link #DEFAULT_EXTENSION_FIELD_DELIMITER} as a delimiter character.
+   */
+  public Extensions() {
+    this(DEFAULT_EXTENSION_FIELD_DELIMITER);
+  }
+
+  /**
+   * Creates a new {@link Extensions} instance
+   * 
+   * @param extensionFieldDelimiter
+   *          the extensions field delimiter character
+   */
+  public Extensions(char extensionFieldDelimiter) {
+    this.extensionFieldDelimiter = extensionFieldDelimiter;
+  }
+
+  /**
+   * Adds a new {@link ParserExtension} instance associated with the given key.
+   * 
+   * @param key
+   *          the parser extension key
+   * @param extension
+   *          the parser extension
+   */
+  public void add(String key, ParserExtension extension) {
+    this.extensions.put(key, extension);
+  }
+
+  /**
+   * Returns the {@link ParserExtension} instance for the given key or
+   * <code>null</code> if no extension can be found for the key.
+   * 
+   * @param key
+   *          the extension key
+   * @return the {@link ParserExtension} instance for the given key or
+   *         <code>null</code> if no extension can be found for the key.
+   */
+  public final ParserExtension getExtension(String key) {
+    return this.extensions.get(key);
+  }
+
+  /**
+   * Returns the extension field delimiter
+   * 
+   * @return the extension field delimiter
+   */
+  public char getExtensionFieldDelimiter() {
+    return extensionFieldDelimiter;
+  }
+
+  /**
+   * Splits a extension field and returns the field / extension part as a
+   * {@link Pair}. This method tries to split on the first occurrence of the
+   * extension field delimiter, if the delimiter is not present in the string
+   * the result will contain a <code>null</code> value for the extension key
and
+   * the given field string as the field value. If the given extension field
+   * string contains no field identifier the result pair will carry the given
+   * default field as the field value.
+   * 
+   * @param defaultField
+   *          the default query field
+   * @param field
+   *          the extension field string
+   * @return a {@link Pair} with the field name as the {@link Pair#cur} and the
+   *         extension key as the {@link Pair#cud}
+   */
+  public Pair<String,String> splitExtensionField(String defaultField,
+      String field) {
+    int indexOf = field.indexOf(this.extensionFieldDelimiter);
+    if (indexOf < 0)
+      return new Pair<String,String>(field, null);
+    final String indexField = indexOf == 0 ? defaultField : field.substring(0,
+        indexOf);
+    final String extensionKey = field.substring(indexOf + 1);
+    return new Pair<String,String>(indexField, extensionKey);
+
+  }
+
+  /**
+   * Escapes an extension field. The default implementation is equivalent to
+   * {@link QueryParser#escape(String)}.
+   * 
+   * @param extfield
+   *          the extension field identifier
+   * @return the extension field identifier with all special chars escaped with
+   *         a backslash character.
+   */
+  public String escapeExtensionField(String extfield) {
+    return QueryParser.escape(extfield);
+  }
+
+  /**
+   * Builds an extension field string from a given extension key and the default
+   * query field. The default field and the key are delimited with the extension
+   * field delimiter character. This method makes no assumption about the order
+   * of the extension key and the field. By default the extension key is
+   * appended to the end of the returned string while the field is added to the
+   * beginning. Special Query characters are escaped in the result.
+   * <p>
+   * Note: {@link Extensions} subclasses must maintain the contract between
+   * {@link #buildExtensionField(String)} and
+   * {@link #splitExtensionField(String, String)} where the latter inverts the
+   * former.
+   * </p>
+   */
+  public String buildExtensionField(String extensionKey) {
+    return buildExtensionField(extensionKey, "");
+  }
+
+  /**
+   * Builds an extension field string from a given extension key and the
+   * extensions field. The field and the key are delimited with the extension
+   * field delimiter character. This method makes no assumption about the order
+   * of the extension key and the field. By default the extension key is
+   * appended to the end of the returned string while the field is added to the
+   * beginning. Special Query characters are escaped in the result.
+   * <p>
+   * Note: {@link Extensions} subclasses must maintain the contract between
+   * {@link #buildExtensionField(String, String)} and
+   * {@link #splitExtensionField(String, String)} where the latter inverts the
+   * former.
+   * </p>
+   * 
+   * @param extensionKey
+   *          the extension key
+   * @param field
+   *          the field to apply the extension on.
+   * @return escaped extension field identifier
+   * @see #buildExtensionField(String) to use the default query field
+   */
+  public String buildExtensionField(String extensionKey, String field) {
+    StringBuilder builder = new StringBuilder(field);
+    builder.append(this.extensionFieldDelimiter);
+    builder.append(extensionKey);
+    return escapeExtensionField(builder.toString());
+  }
+
+  /**
+   * This class represents a generic pair.
+   * 
+   * @param <Cur>
+   *          the pairs first element
+   * @param <Cud>
+   *          the pairs last element of the pair.
+   */
+  public static class Pair<Cur,Cud> {
+
+    public final Cur cur;
+    public final Cud cud;
+
+    /**
+     * Creates a new Pair
+     * 
+     * @param cur
+     *          the pairs first element
+     * @param cud
+     *          the pairs last element
+     */
+    public Pair(Cur cur, Cud cud) {
+      this.cur = cur;
+      this.cud = cud;
+    }
+  }
+
+}

Propchange: lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/Extensions.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/Extensions.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ParserExtension.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ParserExtension.java?rev=887533&view=auto
==============================================================================
--- lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ParserExtension.java
(added)
+++ lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ParserExtension.java
Sat Dec  5 12:29:59 2009
@@ -0,0 +1,53 @@
+package org.apache.lucene.queryParser.ext;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.Query;
+
+/**
+ * This class represents an extension base class to the Lucene standard
+ * {@link QueryParser}. The {@link QueryParser} is generated by the JavaCC
+ * parser generator. Changing or adding functionality or syntax in the standard
+ * query parser requires changes to the JavaCC source file. To enable extending
+ * the standard query parser without changing the JavaCC sources and re-generate
+ * the parser the {@link ParserExtension} can be customized and plugged into an
+ * instance of {@link ExtendableQueryParser}, a direct subclass of
+ * {@link QueryParser}.
+ * 
+ * @see Extensions
+ * @see ExtendableQueryParser
+ */
+public abstract class ParserExtension {
+
+  /**
+   * Processes the given {@link ExtensionQuery} and returns a corresponding
+   * {@link Query} instance. Subclasses must either return a {@link Query}
+   * instance or raise a {@link ParseException}. This method must not return
+   * <code>null</code>.
+   * 
+   * @param query
+   *          the extension query
+   * @return a new query instance
+   * @throws ParseException
+   *           if the query can not be parsed.
+   */
+  public abstract Query parse(final ExtensionQuery query) throws ParseException;
+
+}

Propchange: lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ParserExtension.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/ParserExtension.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/package.html
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/package.html?rev=887533&view=auto
==============================================================================
--- lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/package.html
(added)
+++ lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/package.html
Sat Dec  5 12:29:59 2009
@@ -0,0 +1,22 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<html><head></head>
+<body>
+Extendable QueryParser provides a simple and flexible extension mechanism by overloading
query field names.
+</body>
+</html>

Propchange: lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/package.html
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/contrib/misc/src/java/org/apache/lucene/queryParser/ext/package.html
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/ExtensionStub.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/ExtensionStub.java?rev=887533&view=auto
==============================================================================
--- lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/ExtensionStub.java
(added)
+++ lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/ExtensionStub.java
Sat Dec  5 12:29:59 2009
@@ -0,0 +1,33 @@
+package org.apache.lucene.queryParser.ext;
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class ExtensionStub extends ParserExtension {
+
+  @Override
+  public Query parse(ExtensionQuery components) throws ParseException {
+    return new TermQuery(new Term(components.getField(), components
+        .getRawQueryString()));
+  }
+
+}
\ No newline at end of file

Propchange: lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/ExtensionStub.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/ExtensionStub.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/TestExtendableQueryParser.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/TestExtendableQueryParser.java?rev=887533&view=auto
==============================================================================
--- lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/TestExtendableQueryParser.java
(added)
+++ lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/TestExtendableQueryParser.java
Sat Dec  5 12:29:59 2009
@@ -0,0 +1,137 @@
+package org.apache.lucene.queryParser.ext;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.SimpleAnalyzer;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.queryParser.TestQueryParser;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.util.Version;
+
+/**
+ * Testcase for the class {@link ExtendableQueryParser}
+ */
+public class TestExtendableQueryParser extends TestQueryParser {
+  private static char[] DELIMITERS = new char[] {
+      Extensions.DEFAULT_EXTENSION_FIELD_DELIMITER, '-', '|' };
+
+  public TestExtendableQueryParser(String name) {
+    super(name);
+  }
+
+  @Override
+  public QueryParser getParser(Analyzer a) throws Exception {
+    return getParser(a, null);
+  }
+
+  public QueryParser getParser(Analyzer a, Extensions extensions)
+      throws Exception {
+    if (a == null)
+      a = new SimpleAnalyzer();
+    QueryParser qp = extensions == null ? new ExtendableQueryParser(
+        Version.LUCENE_CURRENT, "field", a) : new ExtendableQueryParser(
+        Version.LUCENE_CURRENT, "field", a, extensions);
+    qp.setDefaultOperator(QueryParser.OR_OPERATOR);
+    return qp;
+  }
+
+  public void testUnescapedExtDelimiter() throws Exception {
+    Extensions ext = newExtensions(':');
+    ext.add("testExt", new ExtensionStub());
+    ExtendableQueryParser parser = (ExtendableQueryParser) getParser(null, ext);
+    try {
+      parser.parse("aField:testExt:\"foo \\& bar\"");
+      fail("extension field delimiter is not escaped");
+    } catch (ParseException e) {
+    }
+  }
+
+  public void testExtFieldUnqoted() throws Exception {
+    for (int i = 0; i < DELIMITERS.length; i++) {
+      Extensions ext = newExtensions(DELIMITERS[i]);
+      ext.add("testExt", new ExtensionStub());
+      ExtendableQueryParser parser = (ExtendableQueryParser) getParser(null,
+          ext);
+      String field = ext.buildExtensionField("testExt", "aField");
+      Query query = parser.parse(String.format("%s:foo bar", field));
+      assertTrue("expected instance of BooleanQuery but was "
+          + query.getClass(), query instanceof BooleanQuery);
+      BooleanQuery bquery = (BooleanQuery) query;
+      BooleanClause[] clauses = bquery.getClauses();
+      assertEquals(2, clauses.length);
+      BooleanClause booleanClause = clauses[0];
+      query = booleanClause.getQuery();
+      assertTrue("expected instance of TermQuery but was " + query.getClass(),
+          query instanceof TermQuery);
+      TermQuery tquery = (TermQuery) query;
+      assertEquals("aField", tquery.getTerm()
+          .field());
+      assertEquals("foo", tquery.getTerm().text());
+
+      booleanClause = clauses[1];
+      query = booleanClause.getQuery();
+      assertTrue("expected instance of TermQuery but was " + query.getClass(),
+          query instanceof TermQuery);
+      tquery = (TermQuery) query;
+      assertEquals("field", tquery.getTerm().field());
+      assertEquals("bar", tquery.getTerm().text());
+    }
+  }
+
+  public void testExtDefaultField() throws Exception {
+    for (int i = 0; i < DELIMITERS.length; i++) {
+      Extensions ext = newExtensions(DELIMITERS[i]);
+      ext.add("testExt", new ExtensionStub());
+      ExtendableQueryParser parser = (ExtendableQueryParser) getParser(null,
+          ext);
+      String field = ext.buildExtensionField("testExt");
+      Query parse = parser.parse(String.format("%s:\"foo \\& bar\"", field));
+      assertTrue("expected instance of TermQuery but was " + parse.getClass(),
+          parse instanceof TermQuery);
+      TermQuery tquery = (TermQuery) parse;
+      assertEquals("field", tquery.getTerm().field());
+      assertEquals("foo & bar", tquery.getTerm().text());
+    }
+  }
+
+  public Extensions newExtensions(char delimiter) {
+    return new Extensions(delimiter);
+  }
+
+  public void testExtField() throws Exception {
+    for (int i = 0; i < DELIMITERS.length; i++) {
+      Extensions ext = newExtensions(DELIMITERS[i]);
+      ext.add("testExt", new ExtensionStub());
+      ExtendableQueryParser parser = (ExtendableQueryParser) getParser(null,
+          ext);
+      String field = ext.buildExtensionField("testExt", "afield");
+      Query parse = parser.parse(String.format("%s:\"foo \\& bar\"", field));
+      assertTrue("expected instance of TermQuery but was " + parse.getClass(),
+          parse instanceof TermQuery);
+      TermQuery tquery = (TermQuery) parse;
+      assertEquals("afield", tquery.getTerm().field());
+      assertEquals("foo & bar", tquery.getTerm().text());
+    }
+  }
+
+}

Propchange: lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/TestExtendableQueryParser.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/TestExtendableQueryParser.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Added: lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/TestExtensions.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/TestExtensions.java?rev=887533&view=auto
==============================================================================
--- lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/TestExtensions.java
(added)
+++ lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/TestExtensions.java
Sat Dec  5 12:29:59 2009
@@ -0,0 +1,78 @@
+package org.apache.lucene.queryParser.ext;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.util.LuceneTestCase;
+
+/**
+ * Testcase for the {@link Extensions} class
+ */
+public class TestExtensions extends LuceneTestCase {
+
+  private Extensions ext;
+
+  protected void setUp() throws Exception {
+    super.setUp();
+    this.ext = new Extensions();
+  }
+
+  public void testBuildExtensionField() {
+    assertEquals("field\\:key", ext.buildExtensionField("key", "field"));
+    assertEquals("\\:key", ext.buildExtensionField("key"));
+
+    ext = new Extensions('.');
+    assertEquals("field.key", ext.buildExtensionField("key", "field"));
+    assertEquals(".key", ext.buildExtensionField("key"));
+  }
+
+  public void testSplitExtensionField() {
+    assertEquals("field\\:key", ext.buildExtensionField("key", "field"));
+    assertEquals("\\:key", ext.buildExtensionField("key"));
+
+    ext = new Extensions('.');
+    assertEquals("field.key", ext.buildExtensionField("key", "field"));
+    assertEquals(".key", ext.buildExtensionField("key"));
+  }
+
+  public void testAddGetExtension() {
+    ParserExtension extension = new ExtensionStub();
+    assertNull(ext.getExtension("foo"));
+    ext.add("foo", extension);
+    assertSame(extension, ext.getExtension("foo"));
+    ext.add("foo", null);
+    assertNull(ext.getExtension("foo"));
+  }
+
+  public void testGetExtDelimiter() {
+    assertEquals(Extensions.DEFAULT_EXTENSION_FIELD_DELIMITER, this.ext
+        .getExtensionFieldDelimiter());
+    ext = new Extensions('?');
+    assertEquals('?', this.ext.getExtensionFieldDelimiter());
+  }
+
+  public void testEscapeExtension() {
+    assertEquals("abc\\:\\?\\{\\}\\[\\]\\\\\\(\\)\\+\\-\\!\\~", ext
+        .escapeExtensionField("abc:?{}[]\\()+-!~"));
+    try {
+      ext.escapeExtensionField(null);
+      fail("should throw NPE - escape string is null");
+    } catch (NullPointerException e) {
+      // 
+    }
+  }
+}

Propchange: lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/TestExtensions.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: lucene/java/trunk/contrib/misc/src/test/org/apache/lucene/queryParser/ext/TestExtensions.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL



Mime
View raw message