/* * ModeShape (http://www.modeshape.org) * * Licensed 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. */ package org.modeshape.jcr.index.lucene.query; import static org.modeshape.jcr.value.ValueComparators.NAME_COMPARATOR; import java.util.Objects; import java.util.function.BiFunction; import java.util.function.BiPredicate; import java.util.function.Function; import javax.jcr.query.qom.Comparison; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.search.Query; import org.apache.lucene.search.Weight; import org.modeshape.jcr.value.Name; import org.modeshape.jcr.value.ValueFactories; import org.modeshape.jcr.value.ValueFactory; /** * A Lucene {@link Query} implementation that is used to apply a {@link Comparison} constraint against the name of nodes. This * query implementation works by using the weight and {@link Weight#scorer(LeafReaderContext)} scorer} of the wrapped * query to score (and return) only those documents that correspond to nodes with Names that satisfy the constraint. */ public class CompareNameQuery extends CompareQuery<Name> { private final ValueFactory<Name> nameValueFactory; /** * Construct a {@link Query} implementation that scores nodes according to the supplied comparator. * * @param field the name of the document field containing the local name value; may not be null * @param constraintValue the constraint path; may not be null * @param nameFactory the value factory used during scoring; may not be null * @param evaluator the {@link BiFunction} implementation that returns whether the node path satisfies the * constraint; may not be null * @param caseOperation the operation that should be performed on the indexed values before the constraint value is being * evaluated; may be null which indicates that no case conversion should be done */ protected CompareNameQuery(final String field, Name constraintValue, ValueFactory<Name> nameFactory, BiPredicate<Name, Name> evaluator, Function<String, String> caseOperation) { super(field, constraintValue, evaluator, caseOperation); this.nameValueFactory = nameFactory; } @Override protected Name convertValue(String casedValue) { return nameValueFactory.create(casedValue); } @Override public Query clone() { return new CompareNameQuery(field(), constraintValue, nameValueFactory, evaluator, caseOperation); } /** * Construct a {@link Query} implementation that scores documents such that the node represented by the document has a name * that is greater than the supplied constraint name. * * @param constraintValue the constraint value; may not be null * @param fieldName the name of the document field containing the name value; may not be null * @param factories the value factories that can be used during the scoring; may not be null * @param caseOperation the operation that should be performed on the indexed values before the constraint value is being * evaluated; may be null which indicates that no case conversion should be done * @return the query; never null */ public static Query createQueryForNodesWithNameEqualTo( Name constraintValue, String fieldName, ValueFactories factories, Function<String, String> caseOperation) { return new CompareNameQuery(fieldName, constraintValue, factories.getNameFactory(), Objects::equals, caseOperation); } /** * Construct a {@link Query} implementation that scores documents such that the node represented by the document has a name * that is greater than the supplied constraint name. * * @param constraintValue the constraint value; may not be null * @param localNameField the name of the document field containing the local name value; may not be null * @param factories the value factories that can be used during the scoring; may not be null * @param caseOperation the operation that should be performed on the indexed values before the constraint value is being * evaluated; may be null which indicates that no case conversion should be done * @return the query; never null */ public static CompareNameQuery createQueryForNodesWithNameGreaterThan( Name constraintValue, String localNameField, ValueFactories factories, Function<String, String> caseOperation ) { return new CompareNameQuery(localNameField, constraintValue, factories.getNameFactory(), (name1, name2) -> NAME_COMPARATOR.compare(name1, name2) > 0, caseOperation); } /** * Construct a {@link Query} implementation that scores documents such that the node represented by the document has a name * that is greater than or equal to the supplied constraint name. * * @param constraintValue the constraint value; may not be null * @param localNameField the name of the document field containing the local name value; may not be null * @param factories the value factories that can be used during the scoring; may not be null * @param caseOperation the operation that should be performed on the indexed values before the constraint value is being * evaluated; may be null which indicates that no case conversion should be done * @return the query; never null */ public static CompareNameQuery createQueryForNodesWithNameGreaterThanOrEqualTo( Name constraintValue, String localNameField, ValueFactories factories, Function<String, String> caseOperation ) { return new CompareNameQuery(localNameField, constraintValue, factories.getNameFactory(), (name1, name2) -> NAME_COMPARATOR.compare(name1, name2) >= 0, caseOperation); } /** * Construct a {@link Query} implementation that scores documents such that the node represented by the document has a name * that is less than the supplied constraint name. * * @param constraintValue the constraint value; may not be null * @param localNameField the name of the document field containing the local name value; may not be null * @param factories the value factories that can be used during the scoring; may not be null * @param caseOperation the operation that should be performed on the indexed values before the constraint value is being * evaluated; may be null which indicates that no case conversion should be done * @return the query; never null */ public static CompareNameQuery createQueryForNodesWithNameLessThan( Name constraintValue, String localNameField, ValueFactories factories, Function<String, String> caseOperation ) { return new CompareNameQuery(localNameField, constraintValue, factories.getNameFactory(), (name1, name2) -> NAME_COMPARATOR.compare(name1, name2) < 0, caseOperation); } /** * Construct a {@link Query} implementation that scores documents such that the node represented by the document has a name * that is less than or equal to the supplied constraint name. * * @param constraintValue the constraint value; may not be null * @param localNameField the name of the document field containing the local name value; may not be null * @param factories the value factories that can be used during the scoring; may not be null * @param caseOperation the operation that should be performed on the indexed values before the constraint value is being * evaluated; may be null which indicates that no case conversion should be done * @return the query; never null */ public static CompareNameQuery createQueryForNodesWithNameLessThanOrEqualTo(Name constraintValue, String localNameField, ValueFactories factories, Function<String, String> caseOperation) { return new CompareNameQuery(localNameField, constraintValue, factories.getNameFactory(), (name1, name2) -> NAME_COMPARATOR.compare(name1, name2) <= 0, caseOperation); } }