AbstractLuceneExpression.java
| Index Score | ||
|---|---|---|
![]() |
![]() |
org.apache.slide.index.lucene.expressions |
![]() |
![]() |
Jakarta Slide |
View: Reasons, Metrics, Source Code
These are the metrics that contribute to the Enerjy Score for this file, ranked by impact. So the metrics listed at the top influence the score to a greater extent that the metrics listed at the bottom.
/*
* $Header$
* $Revision: 510360 $
* $Date: 2007-02-21 21:55:26 -0500 (Wed, 21 Feb 2007) $
*
* ====================================================================
*
* Copyright 1999-2004 The Apache Software Foundation
*
* Licensed 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.slide.index.lucene.expressions;
import org.apache.slide.index.lucene.LuceneOrderBy;
import org.apache.slide.index.lucene.LuceneBasicResultSetImpl;
import java.io.IOException;
import java.io.StringReader;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.RangeQuery;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.slide.search.CompareHint;
import org.apache.slide.common.SlideException;
import org.apache.slide.common.SlideTokenWrapper;
import org.apache.slide.content.NodeProperty;
import org.apache.slide.content.NodeRevisionDescriptor;
import org.apache.slide.index.lucene.Index;
import org.apache.slide.index.lucene.LuceneExpressionFactory;
import org.apache.slide.search.BadQueryException;
import org.apache.slide.search.InvalidQueryException;
import org.apache.slide.search.InvalidScopeException;
import org.apache.slide.search.QueryScope;
import org.apache.slide.search.RequestedResource;
import org.apache.slide.search.SearchException;
import org.apache.slide.search.basic.BasicResultSetImpl;
import org.apache.slide.search.basic.ComparableResourceImpl;
import org.apache.slide.search.basic.IBasicExpression;
import org.apache.slide.search.basic.IBasicExpressionFactory;
import org.apache.slide.search.basic.IBasicQuery;
import org.apache.slide.search.basic.IBasicResultSet;
import org.apache.slide.search.basic.OrderBy;
import org.apache.slide.security.AccessDeniedException;
import org.apache.slide.store.BindingStore;
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.SubjectNode;
import org.apache.slide.util.Configuration;
import org.apache.slide.util.logger.Logger;
import org.apache.slide.content.NodeRevisionNumber;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
/**
*
*/
public abstract class AbstractLuceneExpression implements IBasicExpression {
static final String LOG_CHANNEL = "org.apache.slide.index.lucene.expressions";
protected LuceneExpressionFactory factory;
protected Index index;
private IBasicResultSet resultSet = null;
private Query query;
private SAXBuilder saxBuilder = new SAXBuilder();
public AbstractLuceneExpression(Index index) {
this.index = index;
}
protected final void setQuery(Query query) {
this.query = query;
}
protected final Query getQuery() {
return this.query;
}
public IBasicExpressionFactory getFactory() {
return factory;
}
public void setFactory(IBasicExpressionFactory factory) {
this.factory = (LuceneExpressionFactory) factory;
}
public IBasicResultSet execute() throws SearchException {
return this.execute(null, -1);
}
public IBasicResultSet execute(OrderBy orderBy) throws SearchException {
return this.execute(orderBy, -1);
}
public IBasicResultSet execute(OrderBy orderBy, int limit)
throws SearchException {
if (this.resultSet != null) {
return this.resultSet;
}
Query luceneQuery = this.getQuery();
IBasicQuery q = factory.getQuery();
String scope = q.getSearchToken().getSlideContext().getSlidePath(
q.getScope().getHref());
if (scope.endsWith("/") && scope.length() > 1) {
scope = scope.substring(0, scope.length() - 1);
}
// add a scope restriction, this allows negated queries too
BooleanQuery booleanQuery = new BooleanQuery();
if (luceneQuery != null)
booleanQuery.add(luceneQuery, BooleanClause.Occur.MUST);
if (Configuration.useGlobalBinding()) {
booleanQuery.add(new TermQuery(
new Term(Index.SCOPE_FIELD_NAME, "/")), BooleanClause.Occur.MUST);
booleanQuery
.add(
new RangeQuery(
new Term(Index.DEPTH_FIELD_NAME, index
.getConfiguration()
.intToIndexString(getDepth(scope))),
new Term(
Index.DEPTH_FIELD_NAME,
index
.getConfiguration()
.intToIndexString(
getDepth(scope)
+ q
.getScope()
.getDepth())),
true), BooleanClause.Occur.MUST);
} else {
booleanQuery.add(new TermQuery(new Term(Index.SCOPE_FIELD_NAME,
scope)), BooleanClause.Occur.MUST);
int queryScopeHrefDepth = getDepth(scope);
// add depth restriction
switch (q.getScope().getDepth()) {
case QueryScope.DEPTH_INFINITY:
break;
case QueryScope.DEPTH_0:
booleanQuery.add(new TermQuery(new Term(Index.DEPTH_FIELD_NAME,
index.getConfiguration().intToIndexString(
getDepth(scope)))), BooleanClause.Occur.MUST);
break;
case QueryScope.DEPTH_1:
default:
booleanQuery.add(new RangeQuery(new Term(
Index.DEPTH_FIELD_NAME, index.getConfiguration()
.intToIndexString(getDepth(scope))), new Term(
Index.DEPTH_FIELD_NAME, index.getConfiguration()
.intToIndexString(
getDepth(scope)
+ q.getScope().getDepth())),
true), BooleanClause.Occur.MUST);
}
}
luceneQuery = booleanQuery;
Sort sorter = null;
if (orderBy != null && orderBy instanceof LuceneOrderBy) {
sorter = ((LuceneOrderBy) orderBy).getSorter();
if (index.getLogger().isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
index.getLogger().log(
" Gotten a sorter! from LuceneOrderBy " + sorter,
LOG_CHANNEL, Logger.DEBUG);
}
}
IndexSearcher searcher = null;
try {
if (index.getLogger().isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
index.getLogger().log(
"start query execution: " + luceneQuery.toString(),
LOG_CHANNEL, Logger.DEBUG);
}
long start = System.currentTimeMillis();
searcher = this.index.getSearcher();
Hits hits = null;
if (sorter != null) {
hits = searcher.search(luceneQuery, sorter);
if (index.getLogger().isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
index.getLogger().log(" Query uses sorter! " + sorter,
LOG_CHANNEL, Logger.DEBUG);
}
} else
hits = searcher.search(luceneQuery);
if (index.getLogger().isEnabled(LOG_CHANNEL, Logger.DEBUG)) {
index.getLogger().log(
"finished: " + hits.length() + " hits ("
+ (System.currentTimeMillis() - start) + "ms)",
LOG_CHANNEL, Logger.DEBUG);
}
IBasicResultSet result = new LuceneBasicResultSetImpl(false);
int counter = 0;
for (int i = 0, l = hits.length(); (i < l)
&& (limit < 0 || counter < limit); i++) {
Document doc = hits.doc(i);
String uri = doc.get(Index.URI_FIELD_NAME);
String number = doc.get(Index.REVISION_FIELD_NAME);
NodeRevisionNumber nodeNumber = new NodeRevisionNumber(number);
RequestedResource resource = null;
// TODO: This is just a quick hack to enable DASL with binding
// store
// Please replace with something less evel!
// At least the INDEXED_BINDING_URI_IDENTIFIER prefix should be
// added at indexing time
if (Configuration.useGlobalBinding()) {
resource = createResource(
BindingStore.INDEXED_BINDING_URI_IDENTIFIER
.substring(1)
+ uri, nodeNumber);
if (resource != null) {
try {
NodeProperty parentProperty = resource.getProperty(
"parent-set",
NodeProperty.DEFAULT_NAMESPACE);
String parentValue = "<parents>"
+ parentProperty.getValue() + "</parents>";
// Get bindings for resource
org.jdom.Document parentDocument = saxBuilder
.build(new StringReader(
(String) parentValue));
List parents = parentDocument.getRootElement()
.getChildren();
for (Iterator parentIterator = parents.iterator(); parentIterator
.hasNext();) {
Element parent = (Element) parentIterator
.next();
String href = parent.getChild("href",
Namespace.getNamespace("DAV:"))
.getText();
String segment = parent.getChild("segment",
Namespace.getNamespace("DAV:"))
.getText();
if (href.startsWith(scope)) {
RequestedResource binding = (RequestedResource) resource
.clone();
binding.setUri(href + "/" + segment);
result.add(binding);
counter++;
}
}
} catch (SlideException e) {
throw new SearchException(
"Property 'parent-set' must be present when using binding enabled search",
e);
} catch (JDOMException e) {
throw new SearchException(
"Malformed 'parent-set' property value", e);
}
}
} else {
resource = createResource(uri, nodeNumber);
if (resource != null) {
result.add(resource);
counter++;
}
}
}
this.resultSet = result;
return result;
} catch (InvalidScopeException e) {
throw e;
} catch (SearchException e) {
throw e;
} catch (IOException e) {
throw new SearchException(e);
} finally {
if (searcher != null) {
try {
searcher.close();
} catch (IOException e1) {
// ignore
}
}
}
}
private int getDepth(String path) {
StringTokenizer tokenizer = new StringTokenizer(path, "/");
return tokenizer.countTokens();
}
protected Query negateQuery(Query query) {
BooleanQuery booleanQuery = new BooleanQuery();
booleanQuery.add(allQuery(), BooleanClause.Occur.MUST);
booleanQuery.add(query, BooleanClause.Occur.MUST_NOT);
return booleanQuery;
}
protected Query allQuery() {
return new TermQuery(new Term(Index.SCOPE_FIELD_NAME, "/"));
}
protected RequestedResource createResource(String uri,
NodeRevisionNumber nodeNumber) throws SearchException {
ObjectNode node = new SubjectNode(uri); // this will return the root
// folder
RequestedResource resource = null;
IBasicQuery query = factory.getQuery();
SlideTokenWrapper token = new SlideTokenWrapper(query.getSearchToken()
.getSlideToken());
token.setForceLock(false);
try {
// resource = new ComparableResourceImpl(node,
// query.getSearchToken(),
// query.getScope(), factory.getPropertyProvider());
resource = new ComparableResourceImpl(node, query.getSearchToken(),
query.getScope(), factory.getPropertyProvider(), nodeNumber);
} catch (AccessDeniedException e) {
// ignore, just not visible due to permissions
resource = null;
} catch (SlideException e) {
throw new SearchException(e);
}
return resource;
}
protected static Element getFirstElement(Element node) {
List children = node.getChildren();
for (int i = 0; i < children.size(); i++) {
if (children.get(i) instanceof Element) {
return (Element) children.get(i);
}
}
return null;
}
/**
* Returns the first <code>D:prop</code> element.
*
* @param operator
* @return Element
* @throws BadQueryException
* if element not found
*/
public static Element getPropertyElement(Element operator)
throws BadQueryException {
Element prop = operator.getChild("prop",
NodeProperty.NamespaceCache.DEFAULT_NAMESPACE);
if (prop == null)
throw new InvalidQueryException("Missing prop element");
prop = getFirstElement(prop);
if (prop == null)
throw new InvalidQueryException("Empty prop element given");
return prop;
}
/**
* Retruns the first <code>D:literal</code> element.
*
* @param operator
* @return
* @throws BadQueryException
* if element not found
*/
protected Element getLiteralElement(Element operator)
throws BadQueryException {
Element literal = operator.getChild("literal",
NodeProperty.NamespaceCache.DEFAULT_NAMESPACE);
if (literal == null)
throw new InvalidQueryException("Missing literal element");
return literal;
}
protected Element getLiteral2Element(Element operator)
throws BadQueryException {
List children = operator.getChildren("literal",
NodeProperty.NamespaceCache.DEFAULT_NAMESPACE);
if (children.size() > 1) {
return (Element) children.get(1);
} else {
throw new InvalidQueryException("Missing second literal element");
}
}
}
The table below shows all metrics for AbstractLuceneExpression.java.




