com.day.cq.search.facets.extractors.DistinctValuesFacetExtractor 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.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;
}
}