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, boolean quoted) 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(this, splitExtensionField.cur, queryText)); } return super.getFieldQuery(field, queryText, quoted); } }