All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.day.cq.search.eval.PredicateEvaluator Maven / Gradle / Ivy

/*
 * Copyright 1997-2008 Day Management AG
 * Barfuesserplatz 6, 4001 Basel, Switzerland
 * All Rights Reserved.
 *
 * This software is the confidential and proprietary information of
 * Day Management AG, ("Confidential Information"). You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Day.
 */
package com.day.cq.search.eval;

import java.util.Comparator;

import javax.jcr.query.Row;

import com.day.cq.search.Predicate;
import com.day.cq.search.PredicateConverter;
import com.day.cq.search.Query;
import com.day.cq.search.facets.Facet;
import com.day.cq.search.facets.FacetExtractor;
import com.day.cq.search.facets.extractors.DistinctValuesFacetExtractor;
import com.day.cq.search.result.SearchResult;

import aQute.bnd.annotation.ConsumerType;

/**
 * A PredicateEvaluator handles the evaluation of certain
 * {@link Predicate Predicates}, which are the defining constraints of a
 * {@link Query}. Each evaluator handles a certain type of {@link Predicate
 * Predicates}, which is given by {@link Predicate#getType()}. Generally
 * speaking, it maps a higher-level search constraint, such as "width > 200", to
 * a specific JCR query that fits the actual content model, eg.
 * metadata/@width > 200, or it can manually filter nodes and look
 * at them to check its constraint.
 * 
 * 

* Xpath vs. Filtering: XPath is the query language of choice here, and * the XPath predicate expression must be returned in * {@link #getXPathExpression(Predicate, EvaluationContext)}. If the constraint * of this evaluator cannot be formulated via a JCR XPath predicate expression, * the result can also be filtered using the * {@link #includes(Predicate, Row, EvaluationContext)} method. Please note that * filtering is more likely to negatively impact performance, so xpath is the * preferred way. * *

* Important Note: It is recommended that evaluators implement their * concept via xpath and filtering (ie. two different implementations * of the same constraint), or via filtering only. This is because in the case * of predicate groups that are combined with OR, and at least one of the * predicates is done only via filtering, the whole group must be done via * filtering. Filtering itself cannot add new nodes to the result, so the whole * group must not produce any xpath constraint that would reduce the set * "too much" before filtering. Not complying to this recommendation will make * xpath-only predicates not work inside mixed or groups, but can still work for * other scenarios. * *

* Ordering: To sort the result set, an evaluator can either specify one * or more JCR properties via * {@link #getOrderByProperties(Predicate, EvaluationContext)} or provide a * custom comparator that works on the final result set via * {@link #getOrderByComparator(Predicate, EvaluationContext)}. * *

* Facets: A {@link PredicateEvaluator} also provides a * {@link FacetExtractor} that creates buckets based on the search result, since * facets will conceptually always match to the types of constraints you can put * in a query. The {@link #getFacetExtractor(Predicate, EvaluationContext)} * method returns the extractor that will afterwards run over the result set to * find any facets. * *

* Registration: Implementations of this interface must either be defined * as OSGi components (to be used for any query) or registered explicitly for a * certain query using * {@link Query#registerPredicateEvaluator(String, PredicateEvaluator)}. If the * OSGi component way is chosen, the component must be defined as a component * factory. Names should not start with a "_", as they will be ignored for * queries created from requests (see * {@link PredicateConverter#createPredicates(java.util.Map)}. The name of the * factory must be the fully qualified name of this interface plus "/" and the * type of the predicate this evaluator will be used for. For example for a * {@link PredicateEvaluator} handling the predicate type "fulltext", the SCR * annotation would look like this: * *

 * {@literal @}Component(metatype = false, factory="com.day.cq.search.eval.PredicateEvaluator/fulltext")
 * 
* * @since 5.2 */ @ConsumerType public interface PredicateEvaluator { /** * Returns an XPath predicate expression, which is just a partial * expression that can be placed inside "[" and "]" in a full XPath * statement. Examples are: * *
     * @jcr:title = 'Foobar'
     * 
* * or this longer expression: * *
     * (@count > 10 and @count < 20) or @state = 'foo'
     * 
* *

* As a different constraint, an implementation can also filter the result * of the query, using the * {@link #includes(Predicate, Row, EvaluationContext)} method. Also, it is * recommended to implement the xpath-based constraint again inside * {@linkplain #includes(Predicate, Row, EvaluationContext) includes()} to * support the case where filtering is forced by a parent predicte group. * *

* Note that an implementation must return an empty string or * null if its parameters are empty, ie. if the predicate * should not "take part" in the actual query. This is because we need to * keep track of the potential predicates for the query to get all * {@link Facet Facets}, not only the ones for what is already queried. * *

* If you implement this method, don't forget to implement * {@link #canXpath(Predicate, EvaluationContext)} so that it returns true. * * @param predicate * predicate (for this evaluator type) which is evaluated * @param context * helper class which provides access to various elements of the * query evaluation * @return string containing an XPath predicateEvaluator expression */ String getXPathExpression(Predicate predicate, EvaluationContext context); /** * If the constraint for the given predicate formulated via a JCR XPath * expression, this method can be used to filter the result set row by row * (to get the node behind the row, one can use * {@link EvaluationContext#getNode(Row) context.getNode(row)}. * *

* Please note that this is more likely to negatively impact * performance! * *

* If you implement this method, don't forget to implement * {@link #canFilter(Predicate, EvaluationContext)} so that it returns true. * * @param predicate * predicate (for this evaluator type) which is evaluated * @param row * current row of the result set returned through the xpath query * @param context * helper class which provides access to various elements of the * query evaluation * @return true if this row should be part of the final result * set, false if it should be dropped */ boolean includes(Predicate predicate, Row row, EvaluationContext context); /** * Returns whether this evaluator can return its constraint via xpath, ie. * {@link #getXPathExpression(Predicate, EvaluationContext)}. * *

* Note that the result typically does not depend on either the predicate * or the context (given as parameters) - in most cases this depends * directly on the implementation. * * @param predicate * predicate (for this evaluator type) which is evaluated * @param context * helper class which provides access to various elements of the * query evaluation * @return true if this evaluator can express itself via xpath, * ie. {@link #getXPathExpression(Predicate, EvaluationContext)} * * @since 5.3 */ boolean canXpath(Predicate predicate, EvaluationContext context); /** * Returns whether this evaluator can handle its constraint via filtering, * ie. {@link #includes(Predicate, Row, EvaluationContext)}. * *

* Note that the result typically does not depend on either the predicate * or the context (given as parameters) - in most cases this depends * directly on the implementation. * * @param predicate * predicate (for this evaluator type) which is evaluated * @param context * helper class which provides access to various elements of the * query evaluation * @return true if this evaluator can be express itself via * filtering, ie. * {@link #includes(Predicate, Row, EvaluationContext)} * * @since 5.3 */ boolean canFilter(Predicate predicate, EvaluationContext context); /** * Returns true if the evaluator will actually handle the * predicate in some way in the * {@link #includes(Predicate, Row, EvaluationContext)} method. This is * required to separate evaluators that always return true in * {@link #includes(Predicate, Row, EvaluationContext)}, because they don't * do any filtering, from those that filter the result set and also return * true. * *

* Note that this should return false if the predicate is * "empty", eg. is not providing any required parameters. * * @param predicate * predicate (for this evaluator type) which is evaluated * @param context * helper class which provides access to various elements of the * query evaluation * @return true if this evaluator is filtering the result set * for the given predicate * * @deprecated Since 5.3, use * {@link #canFilter(Predicate, EvaluationContext)} and * {@link #canXpath(Predicate, EvaluationContext)} instead. */ boolean isFiltering(Predicate predicate, EvaluationContext context); /** * Returns a list of JCR property names or relative paths * to properties that should be used when the result should be ordered by * the given predicate. The paths will be used in the order by * part of the Xpath query (in the given order). Can return * null if there is no property to order by. Additional * ordering can happen by returning a custom {@link Comparator} in * {@link #getOrderByComparator(Predicate, EvaluationContext)}. * * @param predicate * predicate (for this evaluator type) which is evaluated * @param context * helper class which provides access to various elements of the * query evaluation * @return one or multiple relative paths to JCR properties or * null */ String[] getOrderByProperties(Predicate predicate, EvaluationContext context); /** * Returns a comparator that will be used to "manually" sort the result * after running the xpath query and after filtering via * {@link #includes(Predicate, Row, EvaluationContext)} happened. This can * be expensive and if possible, * {@link #getOrderByProperties(Predicate, EvaluationContext)} (which is used * for XPath order by) should be used. Result can be null. * * @param predicate * predicate (for this evaluator type) which is evaluated * @param context * helper class which provides access to various elements of the * query evaluation * @return a custom comparator for the given predicate or null */ Comparator getOrderByComparator(Predicate predicate, EvaluationContext context); /** * Returns a {@link FacetExtractor} that is used to create a {@link Facet} * that maps to the given predicate. There are built-in extractor * implementations that can be used (eg. * {@link DistinctValuesFacetExtractor} which automatically creates a Facet * with buckets based on the distinct values of a certain property). * *

* This method will only be called when the API user actually requests the * facets from the search result using {@link SearchResult#getFacets()}. * *

* Important note: this object (the PredicateEvaluator) as an OSGi * component instance will be released before the returned FacetExtractor is * used, ie. before any method is called on it. This lazy usage of the * extractor is needed, because during query execution it cannot be known if * {@link SearchResult#getFacets()} will be called by the client afterwards. * Thus be careful if you return an inner or anonymous class that uses * members of this evaluator which are references to other OSGi components - * at the time of facet extraction, these will be effectively * null. Thus you should retrieve information from the service * while this method is called and store the result in the returned * FacetExtractor object. This also means that you cannot directly use OSGi * references in a FacetExtractor at all (they are not OSGi components). * * @param predicate * predicate (for this evaluator type) which is evaluated * @param context * helper class which provides access to various elements of the * query evaluation * @return a {@link FacetExtractor} that is used to create a {@link Facet} * or null if no extractor shall be provided */ FacetExtractor getFacetExtractor(Predicate predicate, EvaluationContext context); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy