All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.cq.searchcollections.lucene.QueryObjectModelImpl Maven / Gradle / Ivy

/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2012 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 **************************************************************************/
package com.adobe.cq.searchcollections.lucene;

import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_JOIN_TYPE_LEFT_OUTER;
import static javax.jcr.query.qom.QueryObjectModelConstants.JCR_JOIN_TYPE_RIGHT_OUTER;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.Value;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.PropertyDefinition;
import javax.jcr.query.InvalidQueryException;
import javax.jcr.query.QueryResult;
import javax.jcr.query.Row;
import javax.jcr.query.RowIterator;
import javax.jcr.query.qom.Column;
import javax.jcr.query.qom.Constraint;
import javax.jcr.query.qom.Join;
import javax.jcr.query.qom.Ordering;
import javax.jcr.query.qom.PropertyValue;
import javax.jcr.query.qom.QueryObjectModelFactory;
import javax.jcr.query.qom.Selector;
import javax.jcr.query.qom.Source;

import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.jackrabbit.commons.iterator.RowIteratorAdapter;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.store.Directory;

import com.adobe.cq.searchcollections.qom.AbstractQueryObjectModel;
import com.adobe.cq.searchcollections.qom.ConstraintSplitter;
import com.adobe.cq.searchcollections.qom.Constraints;
import com.adobe.cq.searchcollections.qom.JoinMerger;
import com.adobe.cq.searchcollections.qom.OperandEvaluator;
import com.adobe.cq.searchcollections.qom.RowComparator;
import com.adobe.cq.searchcollections.qom.SimpleQueryResult;

/**
 * @deprecated
 */
class QueryObjectModelImpl extends AbstractQueryObjectModel {

    private final Directory directory;

    private final Analyzer analyzer;

    private final Session session;

    private final QueryObjectModelFactory factory;

    public QueryObjectModelImpl(Directory directory, Analyzer analyzer,
            Session session, QueryObjectModelFactory factory, Source source,
            Constraint constraint, Ordering[] orderings, Column[] columns) {
        super(source, constraint, orderings, columns);
        this.directory = directory;
        this.analyzer = analyzer;
        this.session = session;
        this.factory = factory;
    }

    public QueryResult execute() throws InvalidQueryException,
            RepositoryException {
        Map variables = new HashMap();
        for (String name : getBindVariableNames()) {
            variables.put(name, getBindValue(name));
        }
        OperandEvaluator evaluator = new OperandEvaluator(
                session.getValueFactory(), variables);

        Source source = getSource();
        if (source instanceof Selector) {
            Selector selector = (Selector) source;
            LuceneQueryFactory lqf = new LuceneQueryFactory(directory,
                    analyzer, session, variables);
            return executeSelector(selector, lqf, evaluator);
        } else if (source instanceof Join) {
            Join join = (Join) source;
            if (join.getJoinType() == JCR_JOIN_TYPE_RIGHT_OUTER) {
                // Swap the join sources to normalize all outer joins to left
                join = factory.join(join.getRight(), join.getLeft(),
                        JCR_JOIN_TYPE_LEFT_OUTER, join.getJoinCondition());
            }
            return executeJoin(join, evaluator);
        } else {
            throw new UnsupportedRepositoryOperationException(
                    "Unknown source type: " + source);
        }
    }

    protected QueryResult executeSelector(Selector selector,
            LuceneQueryFactory lqf, OperandEvaluator evaluator)
            throws RepositoryException {
        Map selectorMap = getSelectorNames(selector);
        String[] selectorNames = selectorMap.keySet().toArray(
                new String[selectorMap.size()]);

        Map columnMap = getColumnMap(selectorMap);
        String[] columnNames = columnMap.keySet().toArray(
                new String[columnMap.size()]);

        try {
        	long offset = getOffset();
        	long limit = getLimit();
        	
        	
        	SearchResults results = lqf.execute(columnMap,
                    selector, getConstraint(), getOrderings(), offset, limit);
        	
        	
            RowIterator rows = new RowIteratorAdapter(results.getResults());
            QueryResult result = new SimpleQueryResult(columnNames,
                    selectorNames, rows, results.getTotalNumberOfResults());
            
            return result;
            // return sort(result, evaluator);
        } catch (IOException e) {
            throw new RepositoryException("Failed to access the query index", e);
        }
    }

    private QueryResult executeJoin(Join join, OperandEvaluator evaluator)
            throws RepositoryException {
        JoinMerger merger = JoinMerger.getJoinMerger(join,
                getColumnMap(getSelectorNames(join)), evaluator, factory);
        ConstraintSplitter splitter = new ConstraintSplitter(getConstraint(),
                factory, merger.getLeftSelectors(), merger.getRightSelectors());

        Source left = join.getLeft();
        Constraint leftConstraint = splitter.getLeftConstraint();
        QueryResult leftResult = factory.createQuery(left, leftConstraint,
                null, null).execute();
        List leftRows = new ArrayList();
        for (Row row : JcrUtils.getRows(leftResult)) {
            leftRows.add(row);
        }

        RowIterator rightRows;
        Source right = join.getRight();
        List rightConstraints = merger
                .getRightJoinConstraints(leftRows);
        if (rightConstraints.size() < 500) {
            Constraint rightConstraint = Constraints.and(factory,
                    Constraints.or(factory, rightConstraints),
                    splitter.getRightConstraint());
            rightRows = factory.createQuery(right, rightConstraint, null, null)
                    .execute().getRows();
        } else {
            List list = new ArrayList();
            for (int i = 0; i < rightConstraints.size(); i += 500) {
                Constraint rightConstraint = Constraints.and(
                        factory,
                        Constraints.or(
                                factory,
                                rightConstraints.subList(
                                        i,
                                        Math.min(i + 500,
                                                rightConstraints.size()))),
                        splitter.getRightConstraint());
                QueryResult rigthResult = factory.createQuery(right,
                        rightConstraint, null, null).execute();
                for (Row row : JcrUtils.getRows(rigthResult)) {
                    list.add(row);
                }
            }
            rightRows = new RowIteratorAdapter(list);
        }

        QueryResult result = merger.merge(new RowIteratorAdapter(leftRows),
                rightRows);
        return result;
        // return sort(result, evaluator);
    }

    private Map getColumnMap(
            Map selectors) throws RepositoryException {
        Map map = new LinkedHashMap();
        Column[] columns = getColumns();
        if (columns != null && columns.length > 0) {
            for (int i = 0; i < columns.length; i++) {
                String name = columns[i].getColumnName();
                if (name != null) {
                    map.put(name, factory.propertyValue(
                            columns[i].getSelectorName(),
                            columns[i].getPropertyName()));
                } else {
                    String selector = columns[i].getSelectorName();
                    map.putAll(getColumnMap(selector, selectors.get(selector)));
                }
            }
        } else {
            for (Map.Entry selector : selectors.entrySet()) {
                map.putAll(getColumnMap(selector.getKey(), selector.getValue()));
            }
        }
        return map;
    }

    private Map getColumnMap(String selector,
            NodeType type) throws RepositoryException {
        Map map = new LinkedHashMap();
        for (PropertyDefinition definition : type.getPropertyDefinitions()) {
            String name = definition.getName();
            if (!definition.isMultiple() && !"*".equals(name)) {
                // TODO: Add proper quoting
                map.put(selector + "." + name,
                        factory.propertyValue(selector, name));
            }
        }
        return map;
    }

    private Map getSelectorNames(Source source)
            throws RepositoryException {
        if (source instanceof Selector) {
            Selector selector = (Selector) source;
            return Collections.singletonMap(selector.getSelectorName(),
                    getNodeType(selector));
        } else if (source instanceof Join) {
            Join join = (Join) source;
            Map map = new LinkedHashMap();
            map.putAll(getSelectorNames(join.getLeft()));
            map.putAll(getSelectorNames(join.getRight()));
            return map;
        } else {
            throw new UnsupportedRepositoryOperationException(
                    "Unknown source type: " + source);
        }
    }

    private NodeType getNodeType(Selector selector) throws RepositoryException {
        try {
            return session.getWorkspace().getNodeTypeManager()
                    .getNodeType(selector.getNodeTypeName());
        } catch (NoSuchNodeTypeException e) {
            throw new InvalidQueryException(
                    "Selected node type does not exist: " + selector, e);
        }
    }

    /**
     * Sorts the given query results according to the given QOM orderings. If
     * one or more orderings have been specified, this method will iterate
     * through the entire original result set, order the collected rows, and
     * return a new result set based on the sorted collection of rows.
     * 
     * @param result
     *            original query results
     * @param evaluator
     *            operand evaluator
     * @return sorted query results
     * @throws RepositoryException
     *             if the results can not be sorted
     */
    public QueryResult sort(QueryResult result, OperandEvaluator evaluator)
            throws RepositoryException {
        Ordering[] orderings = getOrderings();
        long offset = getOffset();
        long limit = getLimit();
        if ((orderings != null && orderings.length > 0) || offset != 0
                || limit >= 0) {
            List rows = new ArrayList();

            RowIterator iterator = result.getRows();
            while (iterator.hasNext()) {
                rows.add(iterator.nextRow());
            }

            if (orderings != null && orderings.length > 0) {
                Collections.sort(rows, new RowComparator(orderings, evaluator));
            }

            long totalNumberOfResults = rows.size();
            
            if (offset > 0) {
                int size = rows.size();
                rows = rows.subList((int) Math.min(offset, size), size);
            }
            if (limit >= 0) {
                int size = rows.size();
                rows = rows.subList(0, (int) Math.min(limit, size));
            }

            return new SimpleQueryResult(result.getColumnNames(),
                    result.getSelectorNames(), new RowIteratorAdapter(rows), totalNumberOfResults);
        } else {
            return result;
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy