
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