com.day.cq.search.eval.NodenamePredicateEvaluator 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 java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.query.Row;
import com.day.cq.search.impl.util.GlobPatternUtil;
import org.apache.felix.scr.annotations.Component;
import org.apache.jackrabbit.util.ISO9075;
import org.apache.jackrabbit.util.Text;
import com.day.cq.search.Predicate;
import com.day.cq.search.facets.Facet;
import com.day.cq.search.facets.FacetExtractor;
import com.day.cq.search.facets.buckets.SimpleBucket;
import com.day.cq.search.facets.extractors.FacetImpl;
/**
* Matches on JCR node names.
*
*
* Supports facet extraction. Will provide buckets for each unique node name (filename).
*
*
Name:
* nodename
*
* Properties:
*
* - nodename
* - node name pattern that allows wildcards:
*
= any or no char, ?
= any char,
* [abc]
= only chars in brackets
*
*
* @since 5.2
*/
@Component(metatype = false, factory="com.day.cq.search.eval.PredicateEvaluator/nodename")
public class NodenamePredicateEvaluator extends AbstractPredicateEvaluator {
public static final String NODENAME = "nodename";
@Override
public String getXPathExpression(Predicate p, EvaluationContext context) {
if (!p.hasNonEmptyValue(NODENAME)) {
return null;
}
String name = p.get(NODENAME);
if (containsWildcard(name)) {
if (containsWildcardsNotSupportedWithJcrLike(name)) {
// must resort to filtering
return null;
} else {
return XPath.JCR_LIKE + "(fn:name(), '" + convertWildcardsForJcrLike(name) + "')";
}
}
return "fn:name() = '" + ISO9075.encode(name) + "'";
}
@Override
public boolean includes(Predicate p, Row row, EvaluationContext context) {
if (!p.hasNonEmptyValue(NODENAME)) {
return true;
}
String path = context.getPath(row);
if (path != null) {
return Pattern.matches(GlobPatternUtil.convertWildcardToRegex(p.get(NODENAME)), Text.getName(path));
}
return false;
}
@Override
public Comparator getOrderByComparator(Predicate predicate, final EvaluationContext context) {
return new Comparator() {
public int compare(Row r1, Row r2) {
final String path1 = context.getPath(r1);
if (path1 == null) return 0;
final String path2 = context.getPath(r2);
if (path2 == null) return 0;
return Text.getName(path1).compareTo(Text.getName(path2));
}
};
}
@Deprecated
protected boolean containsWildcard(Predicate p) {
return containsWildcard(p.get(NODENAME));
}
protected boolean containsWildcard(String name) {
for (int i = 0; i < name.length(); i++) {
if ("*?[]".indexOf(name.charAt(i)) != -1) {
return true;
}
}
// not found, return -1
return false;
}
protected boolean containsWildcardsNotSupportedWithJcrLike(String name) {
// character sets [] are only supported via glob patterns
return name.indexOf('[') >= 0 || name.indexOf(']') >= 0;
}
private String convertWildcardsForJcrLike(String term) {
// glob pattern *? => jcr:like %_
return term.replace('*', XPath.JCR_LIKE_ANY_WILDCARD)
.replace('?', XPath.JCR_LIKE_SINGLE_WILDCARD);
}
@Override
public boolean canXpath(Predicate p, EvaluationContext context) {
if (p.hasNonEmptyValue(NODENAME)) {
String name = p.get(NODENAME);
if (containsWildcard(name) && containsWildcardsNotSupportedWithJcrLike(name)) {
return false;
} else {
return true;
}
}
return true;
}
@Override
public boolean canFilter(Predicate predicate, EvaluationContext context) {
return true;
}
@Override
public FacetExtractor getFacetExtractor(Predicate predicate, EvaluationContext context) {
return new NodenameFacetExtractor(predicate.clone());
}
private static class NodenameFacetExtractor implements FacetExtractor {
private Map nameBuckets = new HashMap();
private Predicate predicateTemplate;
public NodenameFacetExtractor(Predicate predicateTemplate) {
this.predicateTemplate = predicateTemplate;
}
public void handleNode(Node node) throws RepositoryException {
String name = node.getName();
SimpleBucket bucket = nameBuckets.get(name);
if (bucket == null) {
Predicate p = predicateTemplate.clone();
p.set(NODENAME, name);
bucket = new SimpleBucket(p, name);
nameBuckets.put(name, bucket);
}
bucket.increment();
}
public Facet getFacet() {
return new FacetImpl(nameBuckets.values());
}
public boolean equals(Object obj) {
return obj instanceof NodenameFacetExtractor;
}
public int hashCode() {
return 1; // all NodenameFacetExtractors are considered equal
}
}
}