Package org.apache.jackrabbit.core.query.lucene.join

Source Code of org.apache.jackrabbit.core.query.lucene.join.OperandEvaluator

/*
* 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.core.query.lucene.join;

import static java.util.Locale.ENGLISH;
import static javax.jcr.PropertyType.NAME;

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<String, Value> variables;

    /**
     * Creates an operand evaluator for the given value factory and set of
     * bind variables.
     *
     * @param factory value factory
     * @param variables bind variables
     */
    public OperandEvaluator(
            ValueFactory factory, Map<String, Value> variables) {
        this.factory = factory;
        this.variables = variables;
    }

    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
     */
    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;
            Node node = row.getNode(nn.getSelectorName());
            return new Value[] { factory.createValue(node.getName(), 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);
        }
    }

    /**
     * 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 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(ENGLISH);
            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(ENGLISH);
            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 {
        String name = row.getNode(operand.getSelectorName()).getName();
        int colon = name.indexOf(':');
        if (colon != -1) {
            name = name.substring(colon + 1);
        }
        return new Value[] { factory.createValue(name, 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() };
        }
    }

    /**
     * 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 <code>null</code> if the property does not exist
     * @throws RepositoryException if the property can't be accessed
     */
    private Property getProperty(PropertyValue operand, Row row)
            throws RepositoryException {
        Node node = row.getNode(operand.getSelectorName());
        if (node != null) {
            try {
                return node.getProperty(operand.getPropertyName());
            } catch (PathNotFoundException e) {
                return null;
            }
        } else {
            return null;
        }
    }

}
TOP

Related Classes of org.apache.jackrabbit.core.query.lucene.join.OperandEvaluator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.