com.day.cq.search.eval.JcrBoolPropertyPredicateEvaluator Maven / Gradle / Ivy
/*
* Copyright 1997-2009 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 javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.ValueFormatException;
import javax.jcr.query.Row;
import org.apache.felix.scr.annotations.Component;
import org.apache.jackrabbit.util.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.day.cq.search.Predicate;
/**
* Matches on JCR BOOLEAN properties. Only accepts the values "true" and "false"
* and in case of "false" it will match if the property has the value "false"
* or if it does not exist at all. This can be useful for checking for boolean flags
* that are only set when enabled.
*
*
* The inherited "operation" parameter has no meaning.
*
*
* Supports facet extraction. Will provide buckets for each true/false value, but
* only for existing properties.
*
*
Name:
* boolproperty
*
* Properties:
*
* - boolproperty
* - relative path to property, for example
myFeatureEnabled
or jcr:content/myFeatureEnabled
* - value
* - value to check property for, "true" or "false"
*
*
* @since 5.3
*/
@Component(metatype = false, factory="com.day.cq.search.eval.PredicateEvaluator/boolproperty")
public class JcrBoolPropertyPredicateEvaluator extends
JcrPropertyPredicateEvaluator {
private static final Logger log = LoggerFactory.getLogger(JcrBoolPropertyPredicateEvaluator.class);
public static final String BOOLPROPERTY = "boolproperty";
@Override
public String getXPathExpression(Predicate p, EvaluationContext context) {
if (!p.hasNonEmptyValue(BOOLPROPERTY) || !p.hasNonEmptyValue(VALUE)) {
return null;
}
String property = p.get(BOOLPROPERTY);
String value = p.get(VALUE);
// ensure only true or false as values
if ("false".equals(value)) {
// check both for false value or non-existent at all
return XPath.OPENING_BRACKET + XPath.getEqualsExpression(property, value) + XPath.OR + XPath.getNotExpression(property) + XPath.CLOSING_BRACKET;
} else if ("true".equals(value)) {
return XPath.getEqualsExpression(property, value);
}
return null;
}
@Override
public boolean includes(Predicate p, Row row, EvaluationContext context) {
if (!p.hasNonEmptyValue(BOOLPROPERTY) || !p.hasNonEmptyValue(VALUE)) {
return true;
}
String property = p.get(BOOLPROPERTY);
String value = p.get(VALUE);
Node node = context.getNode(row);
String path = context.getPath(row);
try {
// might be relative property path: "childnode/prop"
String childNode = Text.getRelativeParent(property, 1);
String propName = Text.getName(property);
if (childNode.length() > 0) {
if (node.hasNode(childNode)) {
// node exists => normal behaviour
node = node.getNode(childNode);
} else {
// node does not exist (special case)
// => a constraint such as "childnode/@prop" means:
// given that childnode exists, check if prop exists;
// but if childnode does not exist at all, we cannot check
// and hence never include this in the result at all
// (same behavior as in Xpath, of course)
return false;
}
}
if (node.hasProperty(propName)) {
String propValue = node.getProperty(propName).getString();
if (propValue == null) {
// non-existent property
if ("false".equals(value)) {
return true;
} else {
return false;
}
}
return propValue.equals(value);
} else {
// non-existent property
if ("false".equals(value)) {
return true;
} else {
return false;
}
}
} catch (ValueFormatException e) {
log.warn("Could not evaluate property = '" + property + "', value = '" + value + "', node = '" + path + "'", e);
} catch (RepositoryException e) {
log.error("Could not evaluate property = '" + property + "', value = '" + value + "', node = '" + path + "'", e);
throw new RuntimeException("", e);
}
return true;
}
}