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

com.day.cq.search.facets.extractors.DistinctValuesFacetExtractor Maven / Gradle / Ivy

There is a newer version: 6.5.21
Show newest version
/*
 * 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.facets.extractors;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;

import com.day.cq.search.Predicate;
import com.day.cq.search.facets.Facet;
import com.day.cq.search.facets.buckets.SimpleBucket;

/**
 * DistinctBucketsFacetExtractor automatically extracts buckets
 * based on distinct values for given properties (or node paths) in the result.
 * 
 * @since 5.2
 */
public class DistinctValuesFacetExtractor extends PropertyFacetExtractor {
    
    private final String valueFilter;

    /**
     * The compiled expression pattern.
     */
    private final Pattern valuePattern;
    
    private Predicate predicateTemplate;
    
    private String valueParameterName;
    
    private Map bucketMap = new HashMap();

    /**
     * Creates a new facet extractor with the given valueFilter.
     * The values for this facet are based on the property values referenced by
     * propertyRelPath. A predicateTemplate must be
     * given which for each detected bucket will be cloned and filled with the
     * specific value of the bucket; the value will be placed in the parameter
     * of the predicate given by valueParameterName.
     * 
     * @param propertyRelPath
     *            a relative path that points to a property. The relative path
     *            is based on the path of the result nodes.
     * @param valueFilter
     *            a regular expression to only select property values matching the
     *            expression and add each matching group as one value
     *            or null to use the property value(s) as is.
     * @param predicateTemplate
     *            the predicate template, which will be cloned and filled with
     *            the specific value for each bucket
     * @param valueParameterName
     *            name of the parameter in the predicateTemplate to
     *            set with the value for the bucket
     */
    public DistinctValuesFacetExtractor(String propertyRelPath, String valueFilter, Predicate predicateTemplate, String valueParameterName) {
        super(propertyRelPath);
        
        this.predicateTemplate = predicateTemplate;
        this.valueParameterName = valueParameterName;
        
        if (valueFilter == null) {
            // no filtering, use all values
            this.valueFilter = null;
            this.valuePattern = null;

        } else {
            this.valueFilter = valueFilter;
            this.valuePattern = Pattern.compile(this.valueFilter);
        }
    }

    public Facet getFacet() {
        if (bucketMap.size() == 0) {
            return null;
        }
        return new FacetImpl(bucketMap.values());
    }

    protected void handleValue(Value value) throws RepositoryException {
        // use string representation of value as key
        String val = getBucketValue(value.getString());
        if (val == null) {
            return;
        }
        SimpleBucket b = bucketMap.get(val);
        if (b == null) {
            Predicate p = predicateTemplate.clone();
            p.set(valueParameterName, val);
            b = new SimpleBucket(p, val);
            bucketMap.put(val, b);
        }
        b.increment();
    }

    /**
     * This allows subclasses to filter the bucket value. If this method returns
     * null, the bucket will be ignored. This original
     * implementation simply returns the given value.
     */
    protected String getBucketValue(String value) {
        return value;
    }

    /**
     * Filters the values by applying the filter of the definition
     * associated with this facet.
     *
     * @param values the values to filter.
     * @param vf the value factory.
     * @return the filtered values.
     * @throws RepositoryException if an error occurs while reading the values.
     */
    protected List filter(List values, ValueFactory vf) throws RepositoryException {
        if (valuePattern == null) {
            // return all values as-is
            return values;
        } else {
            // only add values that match the given pattern
            // and add all matching groups as separate values
            List filtered = new ArrayList(values.size());
            for (Value value : values) {
                Matcher m = valuePattern.matcher(value.getString());
                if (m.matches()) {
                    for (int g = 1; g <= m.groupCount(); g++) {
                        String s = m.group(g);
                        if (s != null) {
                            filtered.add(vf.createValue(s));
                        }
                    }
                }
            }
            return filtered;
        }
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if ((obj == null) || (obj.getClass() != this.getClass())) {
            return false;
        }
        
        DistinctValuesFacetExtractor other = (DistinctValuesFacetExtractor) obj;
        if (propertyRelPath != other.propertyRelPath && !propertyRelPath.equals(other.propertyRelPath)) {
            return false;
        }
        if (valueFilter != other.valueFilter && !valueFilter.equals(other.valueFilter)) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 31 * hash + (propertyRelPath == null ? 0 : propertyRelPath.hashCode());
        hash = 31 * hash + (valueFilter == null ? 0 : valueFilter.hashCode());
        return hash;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy