// set max clause count for boolean queries
BooleanQuery.setMaxClauseCount(_booleanQueryMaxClauseCount);
if (this.isRebuildingIndex()) {
throw new WGQueryException(phrase, "Lucene search temporary disabled. Rebuilding lucene index ...");
}
if (phrase == null || phrase.trim().equals("")) {
return null;
}
try {
BooleanQuery wholeQuery = new BooleanQuery();
int max = WGACore.DEFAULT_QUERY_MAXRESULTS;
Integer maxResults = (Integer) parameters.get(WGDatabase.QUERYOPTION_MAXRESULTS);
if (maxResults != null) {
max = maxResults;
}
// handle dboption EXCLUDEDOCUMENT
WGContent excludeContent = (WGContent) parameters.get(WGDatabase.QUERYOPTION_EXCLUDEDOCUMENT);
if (excludeContent != null) {
String uniqueKey = buildUniqueIndexKey(excludeContent.getDatabase().getDbReference(), excludeContent.getDocumentKey());
wholeQuery.add(new TermQuery(new Term(INDEXFIELD_UNIQUEKEY, uniqueKey)), BooleanClause.Occur.MUST_NOT);
}
// list of dbs to search in
String searchScope = (String) parameters.get(LuceneManager.QUERYOPTION_SEARCHSCOPE);
List searchDBKeys = new ArrayList();
if (searchScope.equals(LuceneManager.SEARCHSCOPE_DB)) {
searchDBKeys.add(db.getDbReference());
}
if (searchScope.equals(LuceneManager.SEARCHSCOPE_DOMAIN)) {
Iterator dbs = _core.openContentDBs(request, (String)db.getAttribute(WGACore.DBATTRIB_DOMAIN)).iterator();
while (dbs.hasNext()) {
WGDatabase currentDB = (WGDatabase) dbs.next();
searchDBKeys.add(currentDB.getDbReference());
}
}
if (searchScope.equals(LuceneManager.SEARCHSCOPE_WGA)) {
Iterator dbs = _core.openContentDBs(request).iterator();
while (dbs.hasNext()) {
WGDatabase currentDB = (WGDatabase) dbs.next();
searchDBKeys.add(currentDB.getDbReference());
}
}
if (searchScope.equals(LuceneManager.SEARCHSCOPE_DB_LIST)) {
String dbListCSV = (String) parameters.get(QUERYOPTION_SEARCHDBKEYS);
if (dbListCSV == null || dbListCSV.trim().equals("")) {
throw new WGQueryException(phrase, "Search scope is 'dblist' but no db keys given.");
} else {
Iterator dbkeys = WGUtils.deserializeCollection(dbListCSV, ",").iterator();
while (dbkeys.hasNext()) {
String dbkey = (String) dbkeys.next();
searchDBKeys.add(dbkey.trim().toLowerCase());
}
}
}
// Handle language selection;
List<WGLanguage> languagesPriorityList = null;
boolean filterLanguages = false;
if (parameters.containsKey(WGDatabase.QUERYOPTION_LANGUAGES)) {
List<WGLanguage> langs = (List<WGLanguage>) parameters.get(WGDatabase.QUERYOPTION_LANGUAGES);
if (langs.size() > 1) {
BooleanQuery langQuery = new BooleanQuery();
for (WGLanguage lang : langs) {
langQuery.add(new TermQuery(new Term(WGContent.META_LANGUAGE, lang.getName())), BooleanClause.Occur.SHOULD);
}
wholeQuery.add(langQuery, BooleanClause.Occur.MUST);
languagesPriorityList = langs;
filterLanguages = true;
}
else if (langs.size() == 1){
wholeQuery.add(new TermQuery(new Term(WGContent.META_LANGUAGE, langs.get(0).getName())), BooleanClause.Occur.MUST);
languagesPriorityList = Collections.singletonList(langs.get(0));
}
}
else if (parameters.containsKey(WGDatabase.QUERYOPTION_ONLYLANGUAGE)) {
String language = (String)parameters.get(WGDatabase.QUERYOPTION_ONLYLANGUAGE);
wholeQuery.add(new TermQuery(new Term(WGContent.META_LANGUAGE, language)), BooleanClause.Occur.MUST);
languagesPriorityList = Collections.singletonList(db.getLanguage(language));
}
if (languagesPriorityList == null) {
languagesPriorityList = getLanguagesForSearchDBKeys(searchDBKeys);;
}
// Handle visibility selection
if (!parameters.containsKey(WGDatabase.QUERYOPTION_ENHANCE) || parameters.get(WGDatabase.QUERYOPTION_ENHANCE).equals(new Boolean(true))) {
wholeQuery.add(new TermQuery(new Term(WGContent.META_VISIBLE, "true")), BooleanClause.Occur.MUST);
String role = (String)parameters.get(WGDatabase.QUERYOPTION_ROLE);
if (role != null) {
if (!role.equalsIgnoreCase(WGContent.DISPLAYTYPE_NONE)) {
wholeQuery.add(new TermQuery(new Term("HIDDENIN" + role.toUpperCase(), "false")), BooleanClause.Occur.MUST);
}
}
}
if (parameters.containsKey(WGDatabase.QUERYOPTION_ONLYRELEASED)) {
wholeQuery.add(new TermQuery(new Term(WGContent.META_STATUS, WGContent.STATUS_RELEASE)), BooleanClause.Occur.MUST);
}
// build dbQuery (OR combination of all searchDbs indexed by lucene)
BooleanQuery dbQuery = new BooleanQuery();
Iterator itSearchDBKeys = searchDBKeys.iterator();
while (itSearchDBKeys.hasNext()) {
String currentDBKey = (String) itSearchDBKeys.next();
if (_indexedDbs.containsKey(currentDBKey)) {
dbQuery.add(new TermQuery(new Term(INDEXFIELD_DBKEY, currentDBKey)), BooleanClause.Occur.SHOULD);
}
}
wholeQuery.add(dbQuery, BooleanClause.Occur.MUST);
// Add parsed search phrase.
// Search in allcontent for each language using the configured analyzer
// if no analyzer is configured for a language search at least with one
// default analyzer
boolean searchWithDefaultAnalyzer = false;
//if no languages found search at least with DefaultAnalyzer
if (languagesPriorityList.size() <= 0) {
searchWithDefaultAnalyzer = true;
}
//build phrase query
BooleanQuery phraseQuery = new BooleanQuery();
Iterator languageList = languagesPriorityList.iterator();
while (languageList.hasNext()) {
WGLanguage languageItem = (WGLanguage) languageList.next();
Analyzer analyzer = _core.getAnalyzerForLanguageCode(languageItem.getName());
if (analyzer != null) {
QueryParser parser = new IndexingRuleBasedQueryParser(INDEXFIELD_ALLCONTENT, analyzer, _indexedDbs, searchDBKeys, _metaKeywordFields);
Query query = parser.parse(phrase);
BooleanQuery testPhraseAndLangQuery = new BooleanQuery();
testPhraseAndLangQuery.add(query, BooleanClause.Occur.MUST);
testPhraseAndLangQuery.add(new TermQuery(new Term(WGContent.META_LANGUAGE, languageItem.getName())), BooleanClause.Occur.MUST);
phraseQuery.add(testPhraseAndLangQuery, BooleanClause.Occur.SHOULD);
}
else {
searchWithDefaultAnalyzer = true;
}
}
if (searchWithDefaultAnalyzer) {
QueryParser parser = new IndexingRuleBasedQueryParser(INDEXFIELD_ALLCONTENT, _core.getDefaultAnalyzer(), _indexedDbs, searchDBKeys, _metaKeywordFields);
Query query = parser.parse(phrase);
phraseQuery.add(query, BooleanClause.Occur.SHOULD);
}
wholeQuery.add(phraseQuery, BooleanClause.Occur.MUST);
// parse native options
Sort sort = null;
String sortFieldName = "";
String nativeOptionsStr = (String) parameters.get(WGDatabase.QUERYOPTION_NATIVEOPTIONS);
boolean includeVirtualContent = false;
if (nativeOptionsStr != null) {
Iterator nativeOptions = WGUtils.deserializeCollection(nativeOptionsStr, ",", true).iterator();
while (nativeOptions.hasNext()) {
String option = (String) nativeOptions.next();
if (option.startsWith("sort:")) {
sortFieldName = option.substring(5).trim();
boolean reverse = false;
if (sortFieldName.toLowerCase().endsWith("(asc)")) {
sortFieldName = sortFieldName.substring(0, sortFieldName.length() - 5).trim();
}
else if (sortFieldName.toLowerCase().endsWith("(desc)")) {
sortFieldName = sortFieldName.substring(0, sortFieldName.length() - 6).trim();
reverse = true;
}
if (sortFieldName.length() > 0) {
char first = sortFieldName.charAt(0);
if (first >= 'A' && first <= 'Z') {
// meta sort
sortFieldName = sortFieldName.toUpperCase();
} else {
// item sort
sortFieldName = sortFieldName.toLowerCase();
}
}
// sort order currently only german
sort = new Sort(new SortField(SORTITEM_PREFIX + sortFieldName, Locale.GERMANY, reverse));
} else if (option.equalsIgnoreCase(NATIVE_QUERYOPTION_INCLUDEVIRTUALCONTENT)) {
includeVirtualContent = true;
}
}
}
if (!includeVirtualContent) {
wholeQuery.add(new TermQuery(new Term(INDEXFIELD_ISVIRTUALCONTENT, String.valueOf(true))), BooleanClause.Occur.MUST_NOT);
}
TopDocs hits;
//register executed query as output parameter
parameters.put(WGDatabase.QUERYOPTION_RETURNQUERY, wholeQuery.toString());
// simplify query and register as taginfo
parameters.put(TAGINFO_SIMPLIFIEDQUERY, rewrite(wholeQuery));
long timeBefore = System.currentTimeMillis();
if (sort != null) {
try {
hits = search(wholeQuery, max, sort);
} catch (NullPointerException e) {
// lucene bug when sorting for non existing fields with Locale
throw new WGQueryException(wholeQuery.toString(), "Sortfield '" + sortFieldName + "' not indexed.");
}
}
else {
try {
hits = search(wholeQuery, max, null);
} catch (BooleanQuery.TooManyClauses e) {
parameters.put(TAGINFO_UNSPECIFICQUERY, new Boolean(true));
throw new WGQueryException(phrase, "Too many BooleanClauses in query. " +
"Please use a more specific query or increase value of " +
"'booleanQueryMaxClauseCount' via WGAManager. Current value is '" + this.getBooleanQueryMaxClauseCount() + "'.");
}
}
long timeAfter = System.currentTimeMillis();
long executionTime = timeAfter - timeBefore;
LuceneResultSet resultSet;
if (filterLanguages) {
resultSet = new LuceneLanguageChoosingResultSet(hits, _core, request, parameters, wholeQuery, executionTime, languagesPriorityList);
}
else {
resultSet = new LuceneMultiDBResultSet(hits, _core, request, parameters, wholeQuery, executionTime);
}
// put resultset in per thread list
List rsList = (List) _resultsetList.get();
if (rsList == null) {
rsList = new LinkedList();
_resultsetList.set(rsList);
}
rsList.add(resultSet);
return resultSet;
}
catch (org.apache.lucene.queryParser.ParseException e) {
throw new WGQueryException("Unable to parse lucene query", e.getMessage(), e);
}
catch (Exception e) {
_core.getLog().error("Error executing lucene search: " + e.getClass().getName() + " - " + e.getMessage(), e);
throw new WGQueryException(phrase, e.getClass().getName() + ": " + e.getMessage(), e);
}
}