Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jackrabbit.commons.query.qom;
import java.util.Locale;
import java.util.Map;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Value;
import javax.jcr.ValueFactory;
import javax.jcr.query.Row;
import javax.jcr.query.qom.BindVariableValue;
import javax.jcr.query.qom.FullTextSearchScore;
import javax.jcr.query.qom.Length;
import javax.jcr.query.qom.Literal;
import javax.jcr.query.qom.LowerCase;
import javax.jcr.query.qom.NodeLocalName;
import javax.jcr.query.qom.NodeName;
import javax.jcr.query.qom.Operand;
import javax.jcr.query.qom.PropertyValue;
import javax.jcr.query.qom.StaticOperand;
import javax.jcr.query.qom.UpperCase;
/**
* Evaluator of QOM {@link Operand operands}. This class evaluates operands
* in the context of a {@link ValueFactory value factory}, a set of bind
* variables and possibly a query result row.
*/
public class OperandEvaluator {
/** Value factory */
private final ValueFactory factory;
/** Bind variables */
private final Map variables;
/** The locale to use in upper- and lower-case conversion. */
private final Locale locale;
/**
* Creates an operand evaluator for the given value factory and set of
* bind variables. Upper- and lower-case conversions are performed using
* the given locale.
*
* @param factory value factory
* @param variables bind variables
* @param locale locale to use in upper- and lower-case conversions
*/
public OperandEvaluator(
ValueFactory factory, Map variables, Locale locale) {
this.factory = factory;
this.variables = variables;
this.locale = locale;
}
/**
* Creates an operand evaluator for the given value factory and set of
* bind variables. Upper- and lower-case conversions are performed using
* the {@link Locale#ENGLISH}.
*
* @param factory value factory
* @param variables bind variables
*/
public OperandEvaluator(
ValueFactory factory, Map variables) {
this(factory, variables, Locale.ENGLISH);
}
/**
* Returns the value of the given static operand
* ({@link Literal literal} or {@link BindVariableValue bind variable})
* casted to the given type.
*
* @param operand static operand to be evaluated
* @param type expected value type
* @return evaluated value, casted to the given type
* @throws RepositoryException if a named bind variable is not found,
* if the operand type is unknown, or
* if the type conversion fails
*/
public Value getValue(StaticOperand operand, int type)
throws RepositoryException {
Value value = getValue(operand);
if (type == PropertyType.UNDEFINED || type == value.getType()) {
return value;
} if (type == PropertyType.LONG) {
return factory.createValue(value.getLong());
} if (type == PropertyType.DOUBLE) {
return factory.createValue(value.getDouble());
} if (type == PropertyType.DATE) {
return factory.createValue(value.getDate());
} else {
return factory.createValue(value.getString(), type);
}
}
/**
* Returns the value of the given static operand
* ({@link Literal literal} or {@link BindVariableValue bind variable}).
*
* @param operand static operand to be evaluated
* @return evaluated value
* @throws RepositoryException if a named bind variable is not found,
* or if the operand type is unknown
*/
public Value getValue(StaticOperand operand) throws RepositoryException {
if (operand instanceof Literal) {
Literal literal = (Literal) operand;
return literal.getLiteralValue();
} else if (operand instanceof BindVariableValue) {
BindVariableValue bvv = (BindVariableValue) operand;
Value value = variables.get(bvv.getBindVariableName());
if (value != null) {
return value;
} else {
throw new RepositoryException(
"Unknown bind variable: " + bvv.getBindVariableName());
}
} else {
throw new UnsupportedRepositoryOperationException(
"Unknown static operand type: " + operand);
}
}
/**
* Returns the value of the given operand in the context of the given row.
* This is a convenience method that uses a somewhat lossy best-effort
* mapping to evaluate multi-valued operands to a single value. Use the
* {@link #getValues(Operand, Row)} method for more accurate results.
*
* @param operand operand to be evaluated
* @param row query result row
* @return evaluated value
* @throws RepositoryException if the operand can't be evaluated
*/
public Value getValue(Operand operand, Row row) throws RepositoryException {
Value[] values = getValues(operand, row);
if (values.length == 1) {
return values[0];
} else {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < values.length; i++) {
if (i > 0) {
builder.append(' ');
}
builder.append(values[i].getString());
}
return factory.createValue(builder.toString());
}
}
/**
* Evaluates the given operand in the context of the given row.
*
* @param operand operand to be evaluated
* @param row query result row
* @return values of the operand at the given row
* @throws RepositoryException if the operand can't be evaluated
*/
public Value[] getValues(Operand operand, Row row)
throws RepositoryException {
if (operand instanceof StaticOperand) {
StaticOperand so = (StaticOperand) operand;
return new Value[] { getValue(so) };
} else if (operand instanceof FullTextSearchScore) {
FullTextSearchScore ftss = (FullTextSearchScore) operand;
double score = row.getScore(ftss.getSelectorName());
return new Value[] { factory.createValue(score) };
} else if (operand instanceof NodeName) {
NodeName nn = (NodeName) operand;
String name = row.getNode(nn.getSelectorName()).getName();
// root node
if ("".equals(name)) {
return new Value[] { factory.createValue(name,
PropertyType.STRING) };
}
return new Value[] { factory.createValue(name, PropertyType.NAME) };
} else if (operand instanceof Length) {
return getLengthValues((Length) operand, row);
} else if (operand instanceof LowerCase) {
return getLowerCaseValues((LowerCase) operand, row);
} else if (operand instanceof UpperCase) {
return getUpperCaseValues((UpperCase) operand, row);
} else if (operand instanceof NodeLocalName) {
return getNodeLocalNameValues((NodeLocalName) operand, row);
} else if (operand instanceof PropertyValue) {
return getPropertyValues((PropertyValue) operand, row);
} else {
throw new UnsupportedRepositoryOperationException(
"Unknown operand type: " + operand);
}
}
/**
* Evaluates the given operand in the context of the given node.
*
* @param operand operand to be evaluated
* @param node node
* @return values of the operand at the given node
* @throws RepositoryException if the operand can't be evaluated
*/
public Value[] getValues(Operand operand, Node node)
throws RepositoryException {
if (operand instanceof StaticOperand) {
StaticOperand so = (StaticOperand) operand;
return new Value[] { getValue(so) };
}
if (operand instanceof FullTextSearchScore) {
final double defaultScore = 0.0;
return new Value[] { factory.createValue(defaultScore) };
}
if (operand instanceof NodeName) {
String name = node.getName();
// root node
if ("".equals(name)) {
return new Value[] { factory.createValue(name,
PropertyType.STRING) };
}
return new Value[] { factory.createValue(name, PropertyType.NAME) };
}
if (operand instanceof Length) {
return getLengthValues((Length) operand, node);
}
if (operand instanceof LowerCase) {
return getLowerCaseValues((LowerCase) operand, node);
}
if (operand instanceof UpperCase) {
return getUpperCaseValues((UpperCase) operand, node);
}
if (operand instanceof NodeLocalName) {
return getNodeLocalNameValues((NodeLocalName) operand, node);
}
if (operand instanceof PropertyValue) {
return getPropertyValues((PropertyValue) operand, node);
}
throw new UnsupportedRepositoryOperationException(
"Unknown operand type: " + operand);
}
/**
* Returns the values of the given value length operand at the given row.
*
* @see #getProperty(PropertyValue, Row)
* @param operand value length operand
* @param row row
* @return values of the operand at the given row
* @throws RepositoryException if the operand can't be evaluated
*/
private Value[] getLengthValues(Length operand, Row row)
throws RepositoryException {
Property property = getProperty(operand.getPropertyValue(), row);
if (property == null) {
return new Value[0];
} else if (property.isMultiple()) {
long[] lengths = property.getLengths();
Value[] values = new Value[lengths.length];
for (int i = 0; i < lengths.length; i++) {
values[i] = factory.createValue(lengths[i]);
}
return values;
} else {
long length = property.getLength();
return new Value[] { factory.createValue(length) };
}
}
/**
* Returns the values of the given value length operand for the given node.
*
* @see #getProperty(PropertyValue, Node)
* @param operand value length operand
* @param node node
* @return values of the operand for the given node
* @throws RepositoryException if the operand can't be evaluated
*/
private Value[] getLengthValues(Length operand, Node n)
throws RepositoryException {
Property property = getProperty(operand.getPropertyValue(), n);
if (property == null) {
return new Value[0];
}
if (property.isMultiple()) {
long[] lengths = property.getLengths();
Value[] values = new Value[lengths.length];
for (int i = 0; i < lengths.length; i++) {
values[i] = factory.createValue(lengths[i]);
}
return values;
}
long length = property.getLength();
return new Value[] { factory.createValue(length) };
}
/**
* Returns the values of the given lower case operand at the given row.
*
* @param operand lower case operand
* @param row row
* @return values of the operand at the given row
* @throws RepositoryException if the operand can't be evaluated
*/
private Value[] getLowerCaseValues(LowerCase operand, Row row)
throws RepositoryException {
Value[] values = getValues(operand.getOperand(), row);
for (int i = 0; i < values.length; i++) {
String value = values[i].getString();
String lower = value.toLowerCase(locale);
if (!value.equals(lower)) {
values[i] = factory.createValue(lower);
}
}
return values;
}
/**
* Returns the values of the given lower case operand for the given node.
*
* @param operand lower case operand
* @param node node
* @return values of the operand for the given node
* @throws RepositoryException if the operand can't be evaluated
*/
private Value[] getLowerCaseValues(LowerCase operand, Node node)
throws RepositoryException {
Value[] values = getValues(operand.getOperand(), node);
for (int i = 0; i < values.length; i++) {
String value = values[i].getString();
String lower = value.toLowerCase(locale);
if (!value.equals(lower)) {
values[i] = factory.createValue(lower);
}
}
return values;
}
/**
* Returns the values of the given upper case operand at the given row.
*
* @param operand upper case operand
* @param row row
* @return values of the operand at the given row
* @throws RepositoryException if the operand can't be evaluated
*/
private Value[] getUpperCaseValues(UpperCase operand, Row row)
throws RepositoryException {
Value[] values = getValues(operand.getOperand(), row);
for (int i = 0; i < values.length; i++) {
String value = values[i].getString();
String upper = value.toUpperCase(locale);
if (!value.equals(upper)) {
values[i] = factory.createValue(upper);
}
}
return values;
}
/**
* Returns the values of the given upper case operand for the given node.
*
* @param operand upper case operand
* @param node node
* @return values of the operand for the given node
* @throws RepositoryException if the operand can't be evaluated
*/
private Value[] getUpperCaseValues(UpperCase operand, Node node)
throws RepositoryException {
Value[] values = getValues(operand.getOperand(), node);
for (int i = 0; i < values.length; i++) {
String value = values[i].getString();
String upper = value.toUpperCase(locale);
if (!value.equals(upper)) {
values[i] = factory.createValue(upper);
}
}
return values;
}
/**
* Returns the value of the given local name operand at the given row.
*
* @param operand local name operand
* @param row row
* @return value of the operand at the given row
* @throws RepositoryException if the operand can't be evaluated
*/
private Value[] getNodeLocalNameValues(NodeLocalName operand, Row row)
throws RepositoryException {
return getNodeLocalNameValues(operand,
row.getNode(operand.getSelectorName()));
}
/**
* Returns the value of the given local name operand for the given node.
*
* @param operand
* local name operand
* @param node
* node
* @return value of the operand for the given node
* @throws RepositoryException
*/
private Value[] getNodeLocalNameValues(NodeLocalName operand, Node node)
throws RepositoryException {
String name = node.getName();
// root node has no local name
if ("".equals(name)) {
return new Value[] { factory.createValue("", PropertyType.STRING) };
}
int colon = name.indexOf(':');
if (colon != -1) {
name = name.substring(colon + 1);
}
return new Value[] { factory.createValue(name, PropertyType.NAME) };
}
/**
* Returns the values of the given property value operand at the given row.
*
* @see #getProperty(PropertyValue, Row)
* @param operand property value operand
* @param row row
* @return values of the operand at the given row
* @throws RepositoryException if the operand can't be evaluated
*/
private Value[] getPropertyValues(PropertyValue operand, Row row)
throws RepositoryException {
Property property = getProperty(operand, row);
if (property == null) {
return new Value[0];
} else if (property.isMultiple()) {
return property.getValues();
} else {
return new Value[] { property.getValue() };
}
}
private Value[] getPropertyValues(PropertyValue operand, Node node)
throws RepositoryException {
Property property = getProperty(operand, node);
if (property == null) {
return new Value[0];
} else if (property.isMultiple()) {
return property.getValues();
} else {
return new Value[] { property.getValue() };
}
}
/**
* Returns the identified property from the given row. This method
* is used by both the {@link #getValue(Length, Row)} and the
* {@link #getValue(PropertyValue, Row)} methods to access properties.
*
* @param operand property value operand
* @param row row
* @return the identified property,
* or null if the property does not exist
* @throws RepositoryException if the property can't be accessed
*/
private Property getProperty(PropertyValue operand, Row row)
throws RepositoryException {
return getProperty(operand, row.getNode(operand.getSelectorName()));
}
/**
* Returns the identified property from the given node.
*
* Can return null is the property doesn't exist or it is not
* accessible.
*
* @param operand
* @param node
* @return identified property
* @throws RepositoryException
*/
private Property getProperty(PropertyValue operand, Node node)
throws RepositoryException {
if (node == null) {
return null;
}
try {
return node.getProperty(operand.getPropertyName());
} catch (PathNotFoundException e) {
return null;
}
}
}