PredicateGroupEvaluator.java 8.86 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  javax.jcr.query.Row
 *  org.apache.felix.scr.annotations.Component
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.search.eval;

import com.day.cq.search.Predicate;
import com.day.cq.search.PredicateGroup;
import com.day.cq.search.eval.AbstractPredicateEvaluator;
import com.day.cq.search.eval.EvaluationContext;
import com.day.cq.search.eval.PredicateEvaluator;
import com.day.cq.search.facets.FacetExtractor;
import java.util.ArrayList;
import java.util.Iterator;
import javax.jcr.query.Row;
import org.apache.felix.scr.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(metatype=0, factory="com.day.cq.search.eval.PredicateEvaluator/group")
public class PredicateGroupEvaluator
extends AbstractPredicateEvaluator {
    private static final Logger log = LoggerFactory.getLogger(PredicateGroupEvaluator.class);
    protected static String FORCED_FILTERING = PredicateGroupEvaluator.class.getName() + "forced-filtering";
    protected static String UNSUPPORTED_FILTER_WARNING_GIVEN = PredicateGroupEvaluator.class.getName() + ".filter-warning";

    protected String getOpeningBracket() {
        return "(";
    }

    protected String getClosingBracket() {
        return ")";
    }

    @Override
    public String getXPathExpression(Predicate p, EvaluationContext context) {
        if (p == null || !(p instanceof PredicateGroup)) {
            return null;
        }
        PredicateGroup group = (PredicateGroup)p;
        if (this.isForcedFiltering(group, context)) {
            return "";
        }
        ArrayList<String> expressions = new ArrayList<String>();
        for (Predicate pred : group) {
            PredicateEvaluator evaluator;
            String ex;
            if (pred.ignored() || (evaluator = context.getPredicateEvaluator(pred.getType())) == null || (ex = evaluator.getXPathExpression(pred, context)) == null || ex.length() <= 0) continue;
            expressions.add(ex);
        }
        StringBuffer xpath = new StringBuffer();
        if (expressions.size() > 0) {
            if (group.isNegated()) {
                xpath.append("not");
            }
            xpath.append(this.getOpeningBracket());
            Iterator exIter = expressions.iterator();
            while (exIter.hasNext()) {
                xpath.append((String)exIter.next());
                if (!exIter.hasNext()) continue;
                if (group.allRequired()) {
                    xpath.append(" and ");
                    continue;
                }
                xpath.append(" or ");
            }
            xpath.append(this.getClosingBracket());
        }
        return xpath.toString();
    }

    @Override
    public boolean includes(Predicate p, Row row, EvaluationContext context) {
        boolean result;
        if (p == null || !(p instanceof PredicateGroup)) {
            return false;
        }
        PredicateGroup group = (PredicateGroup)p;
        boolean bl = result = group.allRequired() ? this.andInclude(group, row, context) : this.orInclude(group, row, context);
        return group.isNegated() ? !result : result;
    }

    private boolean andInclude(PredicateGroup group, Row row, EvaluationContext context) {
        if (group.isEmpty()) {
            return true;
        }
        boolean forcedFiltering = context.get(FORCED_FILTERING) != null;
        for (Predicate p : group) {
            PredicateEvaluator evaluator;
            if (p.ignored() || (evaluator = context.getPredicateEvaluator(p.getType())) == null || !forcedFiltering && evaluator.canXpath(p, context) || evaluator.includes(p, row, context)) continue;
            if (log.isTraceEnabled()) {
                log.trace("AND group: predicate '" + p.getName() + "' (" + p.getType() + ") denied row " + context.getPath(row));
            }
            return false;
        }
        return true;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    private boolean orInclude(PredicateGroup group, Row row, EvaluationContext context) {
        boolean forcedFiltering;
        int predicatesAsked = 0;
        boolean inheritedForcedFiltering = context.get(FORCED_FILTERING) != null;
        boolean bl = forcedFiltering = inheritedForcedFiltering || this.isForcedFiltering(group, context);
        if (!inheritedForcedFiltering && forcedFiltering) {
            context.put(FORCED_FILTERING, true);
        }
        try {
            for (Predicate p : group) {
                PredicateEvaluator evaluator;
                if (p.ignored() || (evaluator = context.getPredicateEvaluator(p.getType())) == null || !forcedFiltering && evaluator.canXpath(p, context)) continue;
                if (evaluator.includes(p, row, context)) {
                    if (forcedFiltering && context.get(UNSUPPORTED_FILTER_WARNING_GIVEN) == null && !evaluator.canFilter(p, context)) {
                        log.warn("Search result might be incorrect - forcing filtering with a PredicateEvaluator that does NOT support filtering: '" + p.getPath() + "' = " + evaluator.getClass().getName());
                        context.put(UNSUPPORTED_FILTER_WARNING_GIVEN, true);
                    }
                    boolean bl2 = true;
                    return bl2;
                }
                ++predicatesAsked;
            }
            if (predicatesAsked == 0) {
                boolean i$ = true;
                return i$;
            }
            if (log.isTraceEnabled()) {
                log.trace("OR group: no predicate in group '" + group.getName() + "' accepted row " + context.getPath(row));
            }
            boolean i$ = false;
            return i$;
        }
        finally {
            if (!inheritedForcedFiltering && forcedFiltering) {
                context.put(FORCED_FILTERING, null);
            }
        }
    }

    protected boolean isForcedFiltering(PredicateGroup group, EvaluationContext context) {
        if (group.allRequired()) {
            return false;
        }
        for (Predicate p : group) {
            PredicateEvaluator evaluator;
            if (p.ignored() || (evaluator = context.getPredicateEvaluator(p.getType())) == null || evaluator.canXpath(p, context)) continue;
            return true;
        }
        return false;
    }

    @Override
    public boolean canXpath(Predicate predicate, EvaluationContext context) {
        if (predicate == null || !(predicate instanceof PredicateGroup)) {
            return false;
        }
        PredicateGroup group = (PredicateGroup)predicate;
        for (Predicate p : group) {
            PredicateEvaluator evaluator;
            if (p.ignored() || (evaluator = context.getPredicateEvaluator(p.getType())) == null || evaluator.canXpath(p, context)) continue;
            return false;
        }
        return true;
    }

    @Override
    public boolean canFilter(Predicate predicate, EvaluationContext context) {
        if (predicate == null || !(predicate instanceof PredicateGroup)) {
            return false;
        }
        PredicateGroup group = (PredicateGroup)predicate;
        for (Predicate p : group) {
            PredicateEvaluator evaluator;
            if (p.ignored() || (evaluator = context.getPredicateEvaluator(p.getType())) == null || evaluator.canFilter(p, context)) continue;
            return false;
        }
        return true;
    }

    public String listFilteringPredicates(PredicateGroup group, EvaluationContext context) {
        StringBuffer result = new StringBuffer();
        boolean groupHasForcedFiltering = this.isForcedFiltering(group, context);
        for (Predicate p : group) {
            PredicateEvaluator evaluator;
            if (p.ignored()) continue;
            if (groupHasForcedFiltering) {
                if (result.length() > 0) {
                    result.append(", ");
                }
                if ((evaluator = context.getPredicateEvaluator(p.getType())) != null && !evaluator.canFilter(p, context)) {
                    result.append("WARN - NO FILTERING SUPPORT: ");
                }
                result.append("{").append(p.toString()).append("}");
                continue;
            }
            if (p instanceof PredicateGroup) {
                if (result.length() > 0) {
                    result.append(", ");
                }
                result.append(this.listFilteringPredicates((PredicateGroup)p, context));
                continue;
            }
            evaluator = context.getPredicateEvaluator(p.getType());
            if (evaluator == null || evaluator.canXpath(p, context)) continue;
            if (result.length() > 0) {
                result.append(", ");
            }
            result.append("{").append(p.toString()).append("}");
        }
        return result.toString();
    }

    @Override
    public FacetExtractor getFacetExtractor(Predicate predicate, EvaluationContext context) {
        return null;
    }
}