From 839f421e5fdbc4ba34a3306677eb2a3d0970fea3 Mon Sep 17 00:00:00 2001 From: Andrew Hind Date: Wed, 7 Jul 2010 12:31:10 +0000 Subject: [PATCH] Split out the lucene query parser from the core repository. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@20978 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../alfresco/cmis/mapping/DirectProperty.java | 2 +- .../impl/lucene/ADMLuceneSearcherImpl.java | 2 +- .../search/impl/lucene/LuceneFunction.java | 45 - .../search/impl/lucene/LuceneQueryParser.java | 3768 ----------------- .../impl/lucene/LuceneXPathHandler.java | 515 --- .../impl/lucene/index/CachingIndexReader.java | 50 - .../AbsoluteStructuredFieldPosition.java | 108 - .../AbstractStructuredFieldPosition.java | 126 - .../query/AnyStructuredFieldPosition.java | 93 - .../lucene/query/CachingTermPositions.java | 197 - .../query/CaseInsensitiveFieldQuery.java | 56 - .../query/CaseInsensitiveFieldRangeQuery.java | 78 - .../lucene/query/CaseInsensitiveTermEnum.java | 80 - .../query/CaseInsensitiveTermRangeEnum.java | 123 - .../impl/lucene/query/ContainerScorer.java | 555 --- .../search/impl/lucene/query/DeltaReader.java | 240 -- ...cendantAndSelfStructuredFieldPosition.java | 45 - .../search/impl/lucene/query/LeafScorer.java | 1089 ----- .../search/impl/lucene/query/PathQuery.java | 386 -- .../search/impl/lucene/query/PathScorer.java | 208 - .../RelativeStructuredFieldPosition.java | 96 - .../SelfAxisStructuredFieldPosition.java | 54 - .../lucene/query/StructuredFieldPosition.java | 116 - .../lucene/query/StructuredFieldTerm.java | 57 - .../AlfrescoFunctionEvaluationContext.java | 2 +- .../lucene/LuceneQueryBuilderContext.java | 2 +- .../util/SearchLanguageConversion.java | 323 -- .../util/SearchLanguageConversionTest.java | 122 - 28 files changed, 4 insertions(+), 8534 deletions(-) delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/LuceneFunction.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryParser.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/LuceneXPathHandler.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/index/CachingIndexReader.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/AbsoluteStructuredFieldPosition.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/AbstractStructuredFieldPosition.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/AnyStructuredFieldPosition.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/CachingTermPositions.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveFieldQuery.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveFieldRangeQuery.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveTermEnum.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveTermRangeEnum.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/ContainerScorer.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/DeltaReader.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/DescendantAndSelfStructuredFieldPosition.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/LeafScorer.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/PathQuery.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/PathScorer.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/RelativeStructuredFieldPosition.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/SelfAxisStructuredFieldPosition.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/StructuredFieldPosition.java delete mode 100644 source/java/org/alfresco/repo/search/impl/lucene/query/StructuredFieldTerm.java delete mode 100644 source/java/org/alfresco/util/SearchLanguageConversion.java delete mode 100644 source/java/org/alfresco/util/SearchLanguageConversionTest.java diff --git a/source/java/org/alfresco/cmis/mapping/DirectProperty.java b/source/java/org/alfresco/cmis/mapping/DirectProperty.java index 51746c0653..0285911f73 100644 --- a/source/java/org/alfresco/cmis/mapping/DirectProperty.java +++ b/source/java/org/alfresco/cmis/mapping/DirectProperty.java @@ -80,7 +80,7 @@ public class DirectProperty extends AbstractSimpleProperty // find best field match HashSet allowableLocales = new HashSet(); - MLAnalysisMode analysisMode = lqp.getConfig().getDefaultMLSearchAnalysisMode(); + MLAnalysisMode analysisMode = lqp.getDefaultSearchMLAnalysisMode(); for (Locale l : MLAnalysisMode.getLocales(analysisMode, sortLocale, false)) { allowableLocales.add(l.toString()); diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java index c921269233..e919dca8d6 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java @@ -286,7 +286,7 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS ClosingIndexSearcher searcher = getSearcher(indexer); Query query = LuceneQueryParser.parse(parameterisedQueryString, searchParameters.getDefaultFieldName(), new LuceneAnalyser(getDictionaryService(), searchParameters.getMlAnalaysisMode() == null ? getLuceneConfig().getDefaultMLSearchAnalysisMode() : searchParameters.getMlAnalaysisMode()), - namespacePrefixResolver, getDictionaryService(), tenantService, defaultOperator, searchParameters, getLuceneConfig(), searcher.getIndexReader()); + namespacePrefixResolver, getDictionaryService(), tenantService, defaultOperator, searchParameters, getLuceneConfig().getDefaultMLSearchAnalysisMode(), searcher.getIndexReader()); if (s_logger.isDebugEnabled()) { s_logger.debug("Query is " + query.toString()); diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneFunction.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneFunction.java deleted file mode 100644 index ec2d58fe2a..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneFunction.java +++ /dev/null @@ -1,45 +0,0 @@ - -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene; - -/** - * Functions that can be applied to lucene fields - * - * Currently upper and lower that perform a case insensitive match for untokenised fields. - * (If the field is tokenised the match should already be case insensitive.) - * - * @author andyh - * - */ -public enum LuceneFunction -{ - /** - * Match as if the field was converted to upper case. - */ - UPPER, - /** - * Match as if the field was converted to lower case. - */ - LOWER, - /** - * A normal lucene field match. - */ - FIELD; -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryParser.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryParser.java deleted file mode 100644 index 5989f6cc02..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryParser.java +++ /dev/null @@ -1,3768 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene; - -import java.io.IOException; -import java.io.StringReader; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Set; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.model.ContentModel; -import org.alfresco.repo.dictionary.IndexTokenisationMode; -import org.alfresco.repo.search.MLAnalysisMode; -import org.alfresco.repo.search.SearcherException; -import org.alfresco.repo.search.impl.lucene.analysis.DateTimeAnalyser; -import org.alfresco.repo.search.impl.lucene.analysis.MLTokenDuplicator; -import org.alfresco.repo.search.impl.lucene.query.CaseInsensitiveFieldQuery; -import org.alfresco.repo.search.impl.lucene.query.CaseInsensitiveFieldRangeQuery; -import org.alfresco.repo.search.impl.lucene.query.PathQuery; -import org.alfresco.repo.tenant.TenantService; -import org.alfresco.service.cmr.dictionary.AspectDefinition; -import org.alfresco.service.cmr.dictionary.ClassDefinition; -import org.alfresco.service.cmr.dictionary.DataTypeDefinition; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.dictionary.PropertyDefinition; -import org.alfresco.service.cmr.dictionary.TypeDefinition; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.search.SearchParameters; -import org.alfresco.service.namespace.NamespacePrefixResolver; -import org.alfresco.service.namespace.QName; -import org.alfresco.util.CachingDateFormat; -import org.alfresco.util.SearchLanguageConversion; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.lucene.analysis.Analyzer; -import org.apache.lucene.analysis.Token; -import org.apache.lucene.analysis.TokenStream; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.queryParser.CharStream; -import org.apache.lucene.queryParser.ParseException; -import org.apache.lucene.queryParser.QueryParser; -import org.apache.lucene.queryParser.QueryParserTokenManager; -import org.apache.lucene.search.BooleanClause; -import org.apache.lucene.search.BooleanQuery; -import org.apache.lucene.search.ConstantScoreRangeQuery; -import org.apache.lucene.search.MatchAllDocsQuery; -import org.apache.lucene.search.MultiPhraseQuery; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.TermQuery; -import org.apache.lucene.search.WildcardTermEnum; -import org.apache.lucene.search.BooleanClause.Occur; -import org.apache.lucene.search.regex.RegexQuery; -import org.apache.lucene.search.spans.SpanNearQuery; -import org.apache.lucene.search.spans.SpanQuery; -import org.apache.lucene.search.spans.SpanTermQuery; -import org.saxpath.SAXPathException; -import org.springframework.extensions.surf.util.I18NUtil; - -import com.werken.saxpath.XPathReader; - -/** - * Extensions to the standard lucene query parser. - *

- * Covers: - *

    - *
  • special fields; - *
  • range expansion; - *
  • adds wild card support for phrases; - *
  • exposes more helper methods to build lucene queries and request tokneisation bahviour. - *
- * TODO: Locale loop should not include tokenisation expansion - * - * @author andyh - */ -public class LuceneQueryParser extends QueryParser -{ - private static Log s_logger = LogFactory.getLog(LuceneQueryParser.class); - - private NamespacePrefixResolver namespacePrefixResolver; - - private DictionaryService dictionaryService; - - private TenantService tenantService; - - private SearchParameters searchParameters; - - private LuceneConfig config; - - private IndexReader indexReader; - - private int internalSlop = 0; - - private LuceneAnalyser luceneAnalyser; - - /** - * Parses a query string, returning a {@link org.apache.lucene.search.Query}. - * - * @param query - * the query string to be parsed. - * @param field - * the default field for query terms. - * @param analyzer - * used to find terms in the query text. - * @param namespacePrefixResolver - * @param dictionaryService - * @param tenantService - * @param defaultOperator - * @param searchParameters - * @param config - * @param indexReader - * @return - the query - * @throws ParseException - * if the parsing fails - */ - static public Query parse(String query, String field, Analyzer analyzer, NamespacePrefixResolver namespacePrefixResolver, DictionaryService dictionaryService, - TenantService tenantService, Operator defaultOperator, SearchParameters searchParameters, LuceneConfig config, IndexReader indexReader) throws ParseException - { - if (s_logger.isDebugEnabled()) - { - s_logger.debug("Using Alfresco Lucene Query Parser for query: " + query); - } - LuceneQueryParser parser = new LuceneQueryParser(field, analyzer); - parser.setDefaultOperator(defaultOperator); - parser.setNamespacePrefixResolver(namespacePrefixResolver); - parser.setDictionaryService(dictionaryService); - parser.setTenantService(tenantService); - parser.setSearchParameters(searchParameters); - parser.setLuceneConfig(config); - parser.setIndexReader(indexReader); - parser.setAllowLeadingWildcard(true); - // TODO: Apply locale contstraints at the top level if required for the non ML doc types. - Query result = parser.parse(query); - if (s_logger.isDebugEnabled()) - { - s_logger.debug("Query " + query + " is\n\t" + result.toString()); - } - return result; - } - - /** - * @param config - */ - public void setLuceneConfig(LuceneConfig config) - { - this.config = config; - } - - /** - * @param indexReader - */ - public void setIndexReader(IndexReader indexReader) - { - this.indexReader = indexReader; - } - - /** - * @param searchParameters - */ - public void setSearchParameters(SearchParameters searchParameters) - { - this.searchParameters = searchParameters; - } - - /** - * @param namespacePrefixResolver - */ - public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver) - { - this.namespacePrefixResolver = namespacePrefixResolver; - } - - /** - * @param tenantService - */ - public void setTenantService(TenantService tenantService) - { - this.tenantService = tenantService; - } - - public SearchParameters getSearchParameters() - { - return searchParameters; - } - - public IndexReader getIndexReader() - { - return indexReader; - } - - public LuceneConfig getConfig() - { - return config; - } - - /** - * Lucene default constructor - * - * @param arg0 - * @param arg1 - */ - public LuceneQueryParser(String arg0, Analyzer arg1) - { - super(arg0, arg1); - if (arg1 instanceof LuceneAnalyser) - { - luceneAnalyser = (LuceneAnalyser) arg1; - } - } - - /** - * Lucene default constructor - * - * @param arg0 - */ - public LuceneQueryParser(CharStream arg0) - { - super(arg0); - } - - /** - * Lucene default constructor - * - * @param arg0 - */ - public LuceneQueryParser(QueryParserTokenManager arg0) - { - super(arg0); - } - - protected Query getFieldQuery(String field, String queryText, int slop) throws ParseException - { - try - { - internalSlop = slop; - Query query = getFieldQuery(field, queryText); - return query; - } - finally - { - internalSlop = 0; - } - - } - - /** - * @param field - * @param queryText - * @param analysisMode - * @param slop - * @param luceneFunction - * @return the query - * @throws ParseException - */ - public Query getFieldQuery(String field, String queryText, AnalysisMode analysisMode, int slop, LuceneFunction luceneFunction) throws ParseException - { - try - { - internalSlop = slop; - Query query = getFieldQuery(field, queryText, analysisMode, luceneFunction); - return query; - } - finally - { - internalSlop = 0; - } - - } - - /** - * @param field - * @param sqlLikeClause - * @param analysisMode - * @return the query - * @throws ParseException - */ - public Query getLikeQuery(String field, String sqlLikeClause, AnalysisMode analysisMode) throws ParseException - { - String luceneWildCardExpression = SearchLanguageConversion.convert(SearchLanguageConversion.DEF_SQL_LIKE, SearchLanguageConversion.DEF_LUCENE, sqlLikeClause); - return getWildcardQuery(field, luceneWildCardExpression, AnalysisMode.LIKE); - } - - /** - * @param field - * @param queryText - * @param analysisMode - * @param luceneFunction - * @return the query - * @throws ParseException - */ - public Query getDoesNotMatchFieldQuery(String field, String queryText, AnalysisMode analysisMode, LuceneFunction luceneFunction) throws ParseException - { - BooleanQuery query = new BooleanQuery(); - Query allQuery = new MatchAllDocsQuery(); - Query matchQuery = getFieldQuery(field, queryText, analysisMode, luceneFunction); - if ((matchQuery != null)) - { - query.add(allQuery, Occur.MUST); - query.add(matchQuery, Occur.MUST_NOT); - } - else - { - throw new UnsupportedOperationException(); - } - return query; - } - - public Query getFieldQuery(String field, String queryText) throws ParseException - { - return getFieldQuery(field, queryText, AnalysisMode.DEFAULT, LuceneFunction.FIELD); - } - - /** - * @param field - * @param first - * @param last - * @param slop - * @param inOrder - * @return the query - */ - public Query getSpanQuery(String field, String first, String last, int slop, boolean inOrder) - { - if (field.equals("TEXT")) - { - Set text = searchParameters.getTextAttributes(); - if ((text == null) || (text.size() == 0)) - { - Collection contentAttributes = dictionaryService.getAllProperties(DataTypeDefinition.CONTENT); - BooleanQuery query = new BooleanQuery(); - for (QName qname : contentAttributes) - { - Query part = getSpanQuery("@" + qname.toString(), first, last, slop, inOrder); - query.add(part, Occur.SHOULD); - } - return query; - } - else - { - BooleanQuery query = new BooleanQuery(); - for (String fieldName : text) - { - Query part = getSpanQuery(fieldName, first, last, slop, inOrder); - query.add(part, Occur.SHOULD); - } - return query; - } - } - else if (field.startsWith("@")) - { - SpanQuery firstTerm = new SpanTermQuery(new Term(field, first)); - SpanQuery lastTerm = new SpanTermQuery(new Term(field, last)); - return new SpanNearQuery(new SpanQuery[] { firstTerm, lastTerm }, slop, inOrder); - } - else if (field.equals("ALL")) - { - Set all = searchParameters.getAllAttributes(); - if ((all == null) || (all.size() == 0)) - { - Collection contentAttributes = dictionaryService.getAllProperties(null); - BooleanQuery query = new BooleanQuery(); - for (QName qname : contentAttributes) - { - Query part = getSpanQuery("@" + qname.toString(), first, last, slop, inOrder); - query.add(part, Occur.SHOULD); - } - return query; - } - else - { - BooleanQuery query = new BooleanQuery(); - for (String fieldName : all) - { - Query part = getSpanQuery(fieldName, first, last, slop, inOrder); - query.add(part, Occur.SHOULD); - } - return query; - } - - } - else if (matchDataTypeDefinition(field) != null) - { - Collection contentAttributes = dictionaryService.getAllProperties(matchDataTypeDefinition(field).getName()); - BooleanQuery query = new BooleanQuery(); - for (QName qname : contentAttributes) - { - Query part = getSpanQuery("@" + qname.toString(), first, last, slop, inOrder); - query.add(part, Occur.SHOULD); - } - return query; - } - else - { - SpanQuery firstTerm = new SpanTermQuery(new Term(field, first)); - SpanQuery lastTerm = new SpanTermQuery(new Term(field, last)); - return new SpanNearQuery(new SpanQuery[] { firstTerm, lastTerm }, slop, inOrder); - } - - } - - private DataTypeDefinition matchDataTypeDefinition(String string) - { - QName search = QName.createQName(expandQName(string)); - DataTypeDefinition dataTypeDefinition = dictionaryService.getDataType(QName.createQName(expandQName(string))); - QName match = null; - if(dataTypeDefinition == null) - { - for(QName definition : dictionaryService.getAllDataTypes()) - { - if(definition.getNamespaceURI().equalsIgnoreCase(search.getNamespaceURI())) - { - if(definition.getLocalName().equalsIgnoreCase(search.getLocalName())) - { - if(match == null) - { - match = definition; - } - else - { - throw new LuceneIndexException("Ambiguous data datype "+string); - } - } - } - - } - } - else - { - return dataTypeDefinition; - } - if(match == null) - { - return null; - } - else - { - return dictionaryService.getDataType(match); - } - } - - private PropertyDefinition matchPropertyDefinition(String string) - { - QName search = QName.createQName(expandQName(string)); - PropertyDefinition propertyDefinition = dictionaryService.getProperty(QName.createQName(expandQName(string))); - QName match = null; - if(propertyDefinition == null) - { - for(QName definition : dictionaryService.getAllProperties(null)) - { - if(definition.getNamespaceURI().equalsIgnoreCase(search.getNamespaceURI())) - { - if(definition.getLocalName().equalsIgnoreCase(search.getLocalName())) - { - if(match == null) - { - match = definition; - } - else - { - throw new LuceneIndexException("Ambiguous data datype "+string); - } - } - } - - } - } - else - { - return propertyDefinition; - } - if(match == null) - { - return null; - } - else - { - return dictionaryService.getProperty(match); - } - } - - private AspectDefinition matchAspectDefinition(String string) - { - QName search = QName.createQName(expandQName(string)); - AspectDefinition aspectDefinition = dictionaryService.getAspect(QName.createQName(expandQName(string))); - QName match = null; - if(aspectDefinition == null) - { - for(QName definition : dictionaryService.getAllAspects()) - { - if(definition.getNamespaceURI().equalsIgnoreCase(search.getNamespaceURI())) - { - if(definition.getLocalName().equalsIgnoreCase(search.getLocalName())) - { - if(match == null) - { - match = definition; - } - else - { - throw new LuceneIndexException("Ambiguous data datype "+string); - } - } - } - - } - } - else - { - return aspectDefinition; - } - if(match == null) - { - return null; - } - else - { - return dictionaryService.getAspect(match); - } - } - - private TypeDefinition matchTypeDefinition(String string) - { - QName search = QName.createQName(expandQName(string)); - TypeDefinition typeDefinition = dictionaryService.getType(QName.createQName(expandQName(string))); - QName match = null; - if(typeDefinition == null) - { - for(QName definition : dictionaryService.getAllTypes()) - { - if(definition.getNamespaceURI().equalsIgnoreCase(search.getNamespaceURI())) - { - if(definition.getLocalName().equalsIgnoreCase(search.getLocalName())) - { - if(match == null) - { - match = definition; - } - else - { - throw new LuceneIndexException("Ambiguous data datype "+string); - } - } - } - - } - } - else - { - return typeDefinition; - } - if(match == null) - { - return null; - } - else - { - return dictionaryService.getType(match); - } - } - - private ClassDefinition matchClassDefinition(String string) - { - TypeDefinition match = matchTypeDefinition(string); - if(match != null) - { - return match; - } - else - { - return matchAspectDefinition(string); - } - } - - - - /** - * @param field - * @param queryText - * @param analysisMode - * @param luceneFunction - * @return the query - * @throws ParseException - */ - public Query getFieldQuery(String field, String queryText, AnalysisMode analysisMode, LuceneFunction luceneFunction) throws ParseException - { - try - { - if (field.equals("PATH")) - { - XPathReader reader = new XPathReader(); - LuceneXPathHandler handler = new LuceneXPathHandler(); - handler.setNamespacePrefixResolver(namespacePrefixResolver); - handler.setDictionaryService(dictionaryService); - reader.setXPathHandler(handler); - reader.parse(queryText); - PathQuery pathQuery = handler.getQuery(); - pathQuery.setRepeats(false); - return pathQuery; - } - else if (field.equals("PATH_WITH_REPEATS")) - { - XPathReader reader = new XPathReader(); - LuceneXPathHandler handler = new LuceneXPathHandler(); - handler.setNamespacePrefixResolver(namespacePrefixResolver); - handler.setDictionaryService(dictionaryService); - reader.setXPathHandler(handler); - reader.parse(queryText); - PathQuery pathQuery = handler.getQuery(); - pathQuery.setRepeats(true); - return pathQuery; - } - else if (field.equals("TEXT")) - { - Set text = searchParameters.getTextAttributes(); - if ((text == null) || (text.size() == 0)) - { - Collection contentAttributes = dictionaryService.getAllProperties(DataTypeDefinition.CONTENT); - BooleanQuery query = new BooleanQuery(); - for (QName qname : contentAttributes) - { - // The super implementation will create phrase queries etc if required - Query part = getFieldQuery("@" + qname.toString(), queryText, analysisMode, luceneFunction); - if (part != null) - { - query.add(part, Occur.SHOULD); - } - else - { - query.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - return query; - } - else - { - BooleanQuery query = new BooleanQuery(); - for (String fieldName : text) - { - Query part = getFieldQuery(fieldName, queryText, analysisMode, luceneFunction); - if (part != null) - { - query.add(part, Occur.SHOULD); - } - else - { - query.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - return query; - } - - } - else if (field.equals("ID")) - { - if (tenantService.isTenantUser() && (queryText.contains(StoreRef.URI_FILLER))) - { - // assume NodeRef, since it contains StorRef URI filler - queryText = tenantService.getName(new NodeRef(queryText)).toString(); - } - TermQuery termQuery = new TermQuery(new Term(field, queryText)); - return termQuery; - } - else if (field.equals("ISROOT")) - { - TermQuery termQuery = new TermQuery(new Term(field, queryText)); - return termQuery; - } - else if (field.equals("ISCONTAINER")) - { - TermQuery termQuery = new TermQuery(new Term(field, queryText)); - return termQuery; - } - else if (field.equals("ISNODE")) - { - TermQuery termQuery = new TermQuery(new Term(field, queryText)); - return termQuery; - } - else if (field.equals("TX")) - { - TermQuery termQuery = new TermQuery(new Term(field, queryText)); - return termQuery; - } - else if (field.equals("PARENT")) - { - if (tenantService.isTenantUser() && (queryText.contains(StoreRef.URI_FILLER))) - { - // assume NodeRef, since it contains StoreRef URI filler - queryText = tenantService.getName(new NodeRef(queryText)).toString(); - } - TermQuery termQuery = new TermQuery(new Term(field, queryText)); - return termQuery; - } - else if (field.equals("PRIMARYPARENT")) - { - if (tenantService.isTenantUser() && (queryText.contains(StoreRef.URI_FILLER))) - { - // assume NodeRef, since it contains StoreRef URI filler - queryText = tenantService.getName(new NodeRef(queryText)).toString(); - } - TermQuery termQuery = new TermQuery(new Term(field, queryText)); - return termQuery; - } - else if (field.equals("QNAME")) - { - XPathReader reader = new XPathReader(); - LuceneXPathHandler handler = new LuceneXPathHandler(); - handler.setNamespacePrefixResolver(namespacePrefixResolver); - handler.setDictionaryService(dictionaryService); - reader.setXPathHandler(handler); - reader.parse("//" + queryText); - return handler.getQuery(); - } - else if (field.equals("PRIMARYASSOCTYPEQNAME")) - { - XPathReader reader = new XPathReader(); - LuceneXPathHandler handler = new LuceneXPathHandler(); - handler.setNamespacePrefixResolver(namespacePrefixResolver); - handler.setDictionaryService(dictionaryService); - reader.setXPathHandler(handler); - reader.parse("//" + queryText); - PathQuery query = handler.getQuery(); - query.setPathField("PATH"); - query.setQnameField("PRIMARYASSOCTYPEQNAME"); - return query; - } - else if (field.equals("ASSOCTYPEQNAME")) - { - XPathReader reader = new XPathReader(); - LuceneXPathHandler handler = new LuceneXPathHandler(); - handler.setNamespacePrefixResolver(namespacePrefixResolver); - handler.setDictionaryService(dictionaryService); - reader.setXPathHandler(handler); - reader.parse("//" + queryText); - PathQuery query = handler.getQuery(); - query.setPathField("PATH"); - query.setQnameField("PRIMARYASSOCTYPEQNAME"); - return query; - } - else if (field.equals("CLASS")) - { - ClassDefinition target = matchClassDefinition(queryText); - if (target == null) - { - throw new SearcherException("Invalid type: " + queryText); - } - return getFieldQuery(target.isAspect() ? "ASPECT" : "TYPE", queryText, analysisMode, luceneFunction); - } - else if (field.equals("TYPE")) - { - TypeDefinition target = matchTypeDefinition(queryText); - if (target == null) - { - throw new SearcherException("Invalid type: " + queryText); - } - Collection subclasses = dictionaryService.getSubTypes(target.getName(), true); - BooleanQuery booleanQuery = new BooleanQuery(); - for (QName qname : subclasses) - { - TypeDefinition current = dictionaryService.getType(qname); - if (target.getName().equals(current.getName()) || current.getIncludedInSuperTypeQuery()) - { - TermQuery termQuery = new TermQuery(new Term(field, qname.toString())); - if (termQuery != null) - { - booleanQuery.add(termQuery, Occur.SHOULD); - } - } - } - return booleanQuery; - } - else if (field.equals("EXACTTYPE")) - { - TypeDefinition target = matchTypeDefinition(queryText); - if (target == null) - { - throw new SearcherException("Invalid type: " + queryText); - } - QName targetQName = target.getName(); - TermQuery termQuery = new TermQuery(new Term("TYPE", targetQName.toString())); - return termQuery; - - } - else if (field.equals("ASPECT")) - { - AspectDefinition target = matchAspectDefinition(queryText); - if (target == null) - { - // failed to find the aspect in the dictionary - throw new AlfrescoRuntimeException("Unknown aspect specified in query: " + queryText); - } - - Collection subclasses = dictionaryService.getSubAspects(target.getName(), true); - - BooleanQuery booleanQuery = new BooleanQuery(); - for (QName qname : subclasses) - { - AspectDefinition current = dictionaryService.getAspect(qname); - if (target.getName().equals(current.getName()) || current.getIncludedInSuperTypeQuery()) - { - TermQuery termQuery = new TermQuery(new Term(field, qname.toString())); - if (termQuery != null) - { - booleanQuery.add(termQuery, Occur.SHOULD); - } - } - } - return booleanQuery; - } - else if (field.equals("EXACTASPECT")) - { - AspectDefinition target = matchAspectDefinition(queryText); - if (target == null) - { - // failed to find the aspect in the dictionary - throw new AlfrescoRuntimeException("Unknown aspect specified in query: " + queryText); - } - - QName targetQName = target.getName(); - TermQuery termQuery = new TermQuery(new Term("ASPECT", targetQName.toString())); - - return termQuery; - } - else if (field.startsWith("@")) - { - Query query = attributeQueryBuilder(field, queryText, new FieldQuery(), analysisMode, luceneFunction); - return query; - } - else if (field.equals("ALL")) - { - Set all = searchParameters.getAllAttributes(); - if ((all == null) || (all.size() == 0)) - { - Collection contentAttributes = dictionaryService.getAllProperties(null); - BooleanQuery query = new BooleanQuery(); - for (QName qname : contentAttributes) - { - // The super implementation will create phrase queries etc if required - Query part = getFieldQuery("@" + qname.toString(), queryText, analysisMode, luceneFunction); - if (part != null) - { - query.add(part, Occur.SHOULD); - } - else - { - query.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - return query; - } - else - { - BooleanQuery query = new BooleanQuery(); - for (String fieldName : all) - { - Query part = getFieldQuery(fieldName, queryText, analysisMode, luceneFunction); - if (part != null) - { - query.add(part, Occur.SHOULD); - } - else - { - query.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - return query; - } - - } - else if (field.equals("ISUNSET")) - { - PropertyDefinition pd = matchPropertyDefinition(queryText); - if (pd != null) - { - ClassDefinition containerClass = pd.getContainerClass(); - QName container = containerClass.getName(); - BooleanQuery query = new BooleanQuery(); - String classType = containerClass.isAspect() ? "ASPECT" : "TYPE"; - Query typeQuery = getFieldQuery(classType, container.toString(), analysisMode, luceneFunction); - Query presenceQuery = getWildcardQuery("@" + pd.getName().toString(), "*"); - if ((typeQuery != null) && (presenceQuery != null)) - { - query.add(typeQuery, Occur.MUST); - query.add(presenceQuery, Occur.MUST_NOT); - } - return query; - } - else - { - return getFieldQueryImpl(field, queryText, analysisMode, luceneFunction); - } - - } - else if (field.equals("ISNULL")) - { - PropertyDefinition pd = matchPropertyDefinition(queryText); - if (pd != null) - { - BooleanQuery query = new BooleanQuery(); - Query presenceQuery = getWildcardQuery("@" + pd.getName().toString(), "*"); - if (presenceQuery != null) - { - query.add(new MatchAllDocsQuery(), Occur.MUST); - query.add(presenceQuery, Occur.MUST_NOT); - } - return query; - } - else - { - return getFieldQueryImpl(field, queryText, analysisMode, luceneFunction); - } - - } - else if (field.equals("ISNOTNULL")) - { - PropertyDefinition pd = matchPropertyDefinition(queryText); - if (pd != null) - { - ClassDefinition containerClass = pd.getContainerClass(); - QName container = containerClass.getName(); - BooleanQuery query = new BooleanQuery(); - String classType = containerClass.isAspect() ? "ASPECT" : "TYPE"; - Query typeQuery = getFieldQuery(classType, container.toString(), analysisMode, luceneFunction); - Query presenceQuery = getWildcardQuery("@" + pd.getName().toString(), "*"); - if ((typeQuery != null) && (presenceQuery != null)) - { - // query.add(typeQuery, Occur.MUST); - query.add(presenceQuery, Occur.MUST); - } - return query; - } - else - { - return getFieldQueryImpl(field, queryText, analysisMode, luceneFunction); - } - - } - else if (matchDataTypeDefinition(field) != null) - { - Collection contentAttributes = dictionaryService.getAllProperties(matchDataTypeDefinition(field).getName()); - BooleanQuery query = new BooleanQuery(); - for (QName qname : contentAttributes) - { - // The super implementation will create phrase queries etc if required - Query part = getFieldQuery("@" + qname.toString(), queryText, analysisMode, luceneFunction); - if (part != null) - { - query.add(part, Occur.SHOULD); - } - else - { - query.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - return query; - } - else if (field.equals("FTSSTATUS")) - { - TermQuery termQuery = new TermQuery(new Term(field, queryText)); - return termQuery; - } - else - { - return getFieldQueryImpl(field, queryText, analysisMode, luceneFunction); - } - - } - catch (SAXPathException e) - { - throw new ParseException("Failed to parse XPath...\n" + e.getMessage()); - } - - } - - private Query getFieldQueryImpl(String field, String queryText, AnalysisMode analysisMode, LuceneFunction luceneFunction) throws ParseException - { - // Use the analyzer to get all the tokens, and then build a TermQuery, - // PhraseQuery, or noth - - // TODO: Untokenised columns with functions require special handling - - if (luceneFunction != LuceneFunction.FIELD) - { - throw new UnsupportedOperationException("Field queries are not supported on lucene functions (UPPER, LOWER, etc)"); - } - - boolean requiresMLTokenDuplication = false; - String testText = queryText; - String localeString = null; - if (field.startsWith("@")) - { - if ((queryText.length() > 0) && (queryText.charAt(0) == '\u0000')) - { - int position = queryText.indexOf("\u0000", 1); - testText = queryText.substring(position + 1); - requiresMLTokenDuplication = true; - localeString = queryText.substring(1, position); - } - } - - TokenStream source = getAnalyzer().tokenStream(field, new StringReader(queryText), analysisMode); - - ArrayList list = new ArrayList(); - org.apache.lucene.analysis.Token reusableToken = new org.apache.lucene.analysis.Token(); - org.apache.lucene.analysis.Token nextToken; - int positionCount = 0; - boolean severalTokensAtSamePosition = false; - - while (true) - { - try - { - nextToken = source.next(reusableToken); - } - catch (IOException e) - { - nextToken = null; - } - if (nextToken == null) - break; - list.add((org.apache.lucene.analysis.Token) nextToken.clone()); - if (nextToken.getPositionIncrement() != 0) - positionCount += nextToken.getPositionIncrement(); - else - severalTokensAtSamePosition = true; - } - try - { - source.close(); - } - catch (IOException e) - { - // ignore - } - - // add any alpha numeric wildcards that have been missed - // Fixes most stop word and wild card issues - - for (int index = 0; index < testText.length(); index++) - { - char current = testText.charAt(index); - if ((current == '*') || (current == '?')) - { - StringBuilder pre = new StringBuilder(10); - if (index > 0) - { - for (int i = index - 1; i >= 0; i--) - { - char c = testText.charAt(i); - if (Character.isLetterOrDigit(c)) - { - boolean found = false; - for (int j = 0; j < list.size(); j++) - { - org.apache.lucene.analysis.Token test = list.get(j); - if ((test.startOffset() <= i) && (i <= test.endOffset())) - { - found = true; - break; - } - } - if (found) - { - break; - } - else - { - pre.insert(0, c); - } - } - } - if (pre.length() > 0) - { - // Add new token followed by * not given by the tokeniser - org.apache.lucene.analysis.Token newToken = new org.apache.lucene.analysis.Token(index - pre.length(), index); - newToken.setTermBuffer(pre.toString()); - newToken.setType("ALPHANUM"); - if (requiresMLTokenDuplication) - { - Locale locale = I18NUtil.parseLocale(localeString); - MLAnalysisMode mlAnalysisMode = searchParameters.getMlAnalaysisMode() == null ? config.getDefaultMLSearchAnalysisMode() : searchParameters - .getMlAnalaysisMode(); - MLTokenDuplicator duplicator = new MLTokenDuplicator(locale, mlAnalysisMode); - Iterator it = duplicator.buildIterator(newToken); - if (it != null) - { - int count = 0; - while (it.hasNext()) - { - list.add(it.next()); - count++; - if (count > 1) - { - severalTokensAtSamePosition = true; - } - } - } - } - // content - else - { - list.add(newToken); - } - } - } - - StringBuilder post = new StringBuilder(10); - if (index > 0) - { - for (int i = index + 1; i < testText.length(); i++) - { - char c = testText.charAt(i); - if (Character.isLetterOrDigit(c)) - { - boolean found = false; - for (int j = 0; j < list.size(); j++) - { - org.apache.lucene.analysis.Token test = list.get(j); - if ((test.startOffset() <= i) && (i <= test.endOffset())) - { - found = true; - break; - } - } - if (found) - { - break; - } - else - { - post.append(c); - } - } - } - if (post.length() > 0) - { - // Add new token followed by * not given by the tokeniser - org.apache.lucene.analysis.Token newToken = new org.apache.lucene.analysis.Token(index + 1, index + 1 + post.length()); - newToken.setTermBuffer(post.toString()); - newToken.setType("ALPHANUM"); - if (requiresMLTokenDuplication) - { - Locale locale = I18NUtil.parseLocale(localeString); - MLAnalysisMode mlAnalysisMode = searchParameters.getMlAnalaysisMode() == null ? config.getDefaultMLSearchAnalysisMode() : searchParameters - .getMlAnalaysisMode(); - MLTokenDuplicator duplicator = new MLTokenDuplicator(locale, mlAnalysisMode); - Iterator it = duplicator.buildIterator(newToken); - if (it != null) - { - int count = 0; - while (it.hasNext()) - { - list.add(it.next()); - count++; - if (count > 1) - { - severalTokensAtSamePosition = true; - } - } - } - } - // content - else - { - list.add(newToken); - } - } - } - - } - } - - Collections.sort(list, new Comparator() - { - - public int compare(Token o1, Token o2) - { - int dif = o1.startOffset() - o2.startOffset(); - if (dif != 0) - { - return dif; - } - else - { - return o2.getPositionIncrement() - o1.getPositionIncrement(); - } - } - }); - - // Combined * and ? based strings - should redo the tokeniser - - // Assume we only string together tokens for the same position - - int max = 0; - int current = 0; - for (org.apache.lucene.analysis.Token c : list) - { - if (c.getPositionIncrement() == 0) - { - current++; - } - else - { - if (current > max) - { - max = current; - } - current = 0; - } - } - if (current > max) - { - max = current; - } - - ArrayList fixed = new ArrayList(); - for (int repeat = 0; repeat <= max; repeat++) - { - org.apache.lucene.analysis.Token replace = null; - current = 0; - for (org.apache.lucene.analysis.Token c : list) - { - if (c.getPositionIncrement() == 0) - { - current++; - } - else - { - current = 0; - } - - if (current == repeat) - { - - if (replace == null) - { - StringBuilder prefix = new StringBuilder(); - for (int i = c.startOffset() - 1; i >= 0; i--) - { - char test = testText.charAt(i); - if ((test == '*') || (test == '?')) - { - prefix.insert(0, test); - } - else - { - break; - } - } - String pre = prefix.toString(); - if (requiresMLTokenDuplication) - { - String termText = new String(c.termBuffer(), 0, c.termLength()); - int position = termText.indexOf("}"); - String language = termText.substring(0, position + 1); - String token = termText.substring(position + 1); - replace = new org.apache.lucene.analysis.Token(c.startOffset() - pre.length(), c.endOffset()); - replace.setTermBuffer(language + pre + token); - replace.setType(c.type()); - replace.setPositionIncrement(c.getPositionIncrement()); - } - else - { - String termText = new String(c.termBuffer(), 0, c.termLength()); - replace = new org.apache.lucene.analysis.Token(c.startOffset() - pre.length(), c.endOffset()); - replace.setTermBuffer(pre + termText); - replace.setType(c.type()); - replace.setPositionIncrement(c.getPositionIncrement()); - } - } - else - { - StringBuilder prefix = new StringBuilder(); - StringBuilder postfix = new StringBuilder(); - StringBuilder builder = prefix; - for (int i = c.startOffset() - 1; i >= replace.endOffset(); i--) - { - char test = testText.charAt(i); - if ((test == '*') || (test == '?')) - { - builder.insert(0, test); - } - else - { - builder = postfix; - postfix.setLength(0); - } - } - String pre = prefix.toString(); - String post = postfix.toString(); - - // Does it bridge? - if ((pre.length() > 0) && (replace.endOffset() + pre.length()) == c.startOffset()) - { - String termText = new String(c.termBuffer(), 0, c.termLength()); - if (requiresMLTokenDuplication) - { - int position = termText.indexOf("}"); - @SuppressWarnings("unused") - String language = termText.substring(0, position + 1); - String token = termText.substring(position + 1); - int oldPositionIncrement = replace.getPositionIncrement(); - String replaceTermText = new String(replace.termBuffer(), 0, replace.termLength()); - replace = new org.apache.lucene.analysis.Token(replace.startOffset(), c.endOffset()); - replace.setTermBuffer(replaceTermText + pre + token); - replace.setType(replace.type()); - replace.setPositionIncrement(oldPositionIncrement); - } - else - { - int oldPositionIncrement = replace.getPositionIncrement(); - String replaceTermText = new String(replace.termBuffer(), 0, replace.termLength()); - replace = new org.apache.lucene.analysis.Token(replace.startOffset(), c.endOffset()); - replace.setTermBuffer(replaceTermText + pre + termText); - replace.setType(replace.type()); - replace.setPositionIncrement(oldPositionIncrement); - } - } - else - { - String termText = new String(c.termBuffer(), 0, c.termLength()); - if (requiresMLTokenDuplication) - { - int position = termText.indexOf("}"); - String language = termText.substring(0, position + 1); - String token = termText.substring(position + 1); - String replaceTermText = new String(replace.termBuffer(), 0, replace.termLength()); - org.apache.lucene.analysis.Token last = new org.apache.lucene.analysis.Token(replace.startOffset(), replace.endOffset() + post.length()); - last.setTermBuffer(replaceTermText + post); - last.setType(replace.type()); - last.setPositionIncrement(replace.getPositionIncrement()); - fixed.add(last); - replace = new org.apache.lucene.analysis.Token(c.startOffset() - pre.length(), c.endOffset()); - replace.setTermBuffer(language + pre + token); - replace.setType(c.type()); - replace.setPositionIncrement(c.getPositionIncrement()); - } - else - { - String replaceTermText = new String(replace.termBuffer(), 0, replace.termLength()); - org.apache.lucene.analysis.Token last = new org.apache.lucene.analysis.Token(replace.startOffset(), replace.endOffset() + post.length()); - last.setTermBuffer(replaceTermText + post); - last.setType(replace.type()); - last.setPositionIncrement(replace.getPositionIncrement()); - fixed.add(last); - replace = new org.apache.lucene.analysis.Token(c.startOffset() - pre.length(), c.endOffset()); - replace.setTermBuffer(pre + termText); - replace.setType(c.type()); - replace.setPositionIncrement(c.getPositionIncrement()); - } - } - } - } - } - // finish last - if (replace != null) - { - StringBuilder postfix = new StringBuilder(); - if ((replace.endOffset() >= 0) && (replace.endOffset() < testText.length())) - { - for (int i = replace.endOffset(); i < testText.length(); i++) - { - char test = testText.charAt(i); - if ((test == '*') || (test == '?')) - { - postfix.append(test); - } - else - { - break; - } - } - } - String post = postfix.toString(); - int oldPositionIncrement = replace.getPositionIncrement(); - String replaceTermText = new String(replace.termBuffer(), 0, replace.termLength()); - replace = new org.apache.lucene.analysis.Token(replace.startOffset(), replace.endOffset() + post.length()); - replace.setTermBuffer(replaceTermText + post); - replace.setType(replace.type()); - replace.setPositionIncrement(oldPositionIncrement); - fixed.add(replace); - - } - } - - // Add in any missing words containsing * and ? - - // reorder by start position and increment - - Collections.sort(fixed, new Comparator() - { - - public int compare(Token o1, Token o2) - { - int dif = o1.startOffset() - o2.startOffset(); - if (dif != 0) - { - return dif; - } - else - { - return o2.getPositionIncrement() - o1.getPositionIncrement(); - } - } - }); - - list = fixed; - - if (list.size() == 0) - return null; - else if (list.size() == 1) - { - nextToken = (org.apache.lucene.analysis.Token) list.get(0); - String termText = new String(nextToken.termBuffer(), 0, nextToken.termLength()); - if (termText.contains("*") || termText.contains("?")) - { - return newWildcardQuery(new Term(field, termText)); - } - else - { - return newTermQuery(new Term(field, termText)); - } - } - else - { - if (severalTokensAtSamePosition) - { - if (positionCount == 1) - { - // no phrase query: - BooleanQuery q = newBooleanQuery(true); - for (int i = 0; i < list.size(); i++) - { - Query currentQuery; - nextToken = (org.apache.lucene.analysis.Token) list.get(i); - String termText = new String(nextToken.termBuffer(), 0, nextToken.termLength()); - if (termText.contains("*") || termText.contains("?")) - { - currentQuery = newWildcardQuery(new Term(field, termText)); - } - else - { - currentQuery = newTermQuery(new Term(field, termText)); - } - q.add(currentQuery, BooleanClause.Occur.SHOULD); - } - return q; - } - else - { - // phrase query: - MultiPhraseQuery mpq = newMultiPhraseQuery(); - mpq.setSlop(internalSlop); - ArrayList multiTerms = new ArrayList(); - int position = -1; - for (int i = 0; i < list.size(); i++) - { - nextToken = (org.apache.lucene.analysis.Token) list.get(i); - String termText = new String(nextToken.termBuffer(), 0, nextToken.termLength()); - if (nextToken.getPositionIncrement() > 0 && multiTerms.size() > 0) - { - if (getEnablePositionIncrements()) - { - mpq.add((Term[]) multiTerms.toArray(new Term[0]), position); - } - else - { - mpq.add((Term[]) multiTerms.toArray(new Term[0])); - } - multiTerms.clear(); - } - position += nextToken.getPositionIncrement(); - - Term term = new Term(field, termText); - if ((termText != null) && (termText.contains("*") || termText.contains("?"))) - { - addWildcardTerms(multiTerms, term); - } - else - { - multiTerms.add(term); - } - } - if (getEnablePositionIncrements()) - { - if (multiTerms.size() > 0) - { - mpq.add((Term[]) multiTerms.toArray(new Term[0]), position); - } - else - { - mpq.add(new Term[] { new Term(field, "\u0000") }, position); - } - } - else - { - if (multiTerms.size() > 0) - { - mpq.add((Term[]) multiTerms.toArray(new Term[0])); - } - else - { - mpq.add(new Term[] { new Term(field, "\u0000") }); - } - } - return mpq; - } - } - else - { - MultiPhraseQuery q = new MultiPhraseQuery(); - q.setSlop(internalSlop); - int position = -1; - for (int i = 0; i < list.size(); i++) - { - nextToken = (org.apache.lucene.analysis.Token) list.get(i); - String termText = new String(nextToken.termBuffer(), 0, nextToken.termLength()); - Term term = new Term(field, termText); - if (getEnablePositionIncrements()) - { - position += nextToken.getPositionIncrement(); - if ((termText != null) && (termText.contains("*") || termText.contains("?"))) - { - q.add(getMatchingTerms(field, term), position); - } - else - { - q.add(new Term[] { term }, position); - } - } - else - { - if ((termText != null) && (termText.contains("*") || termText.contains("?"))) - { - q.add(getMatchingTerms(field, term)); - } - else - { - q.add(term); - } - } - } - return q; - } - } - } - - private Term[] getMatchingTerms(String field, Term term) throws ParseException - { - ArrayList terms = new ArrayList(); - addWildcardTerms(terms, term); - if (terms.size() == 0) - { - return new Term[] { new Term(field, "\u0000") }; - } - else - { - return terms.toArray(new Term[0]); - } - - } - - private void addWildcardTerms(ArrayList terms, Term term) throws ParseException - { - try - { - WildcardTermEnum wcte = new WildcardTermEnum(indexReader, term); - - while (!wcte.endEnum()) - { - Term current = wcte.term(); - if ((current.text() != null) && (current.text().length() > 0) && (current.text().charAt(0) == '{')) - { - if ((term != null) && (term.text().length() > 0) && (term.text().charAt(0) == '{')) - { - terms.add(current); - } - // If not, we cod not add so wildcards do not match the locale prefix - } - else - { - terms.add(current); - } - - wcte.next(); - } - } - catch (IOException e) - { - throw new ParseException("IO error generating phares wildcards " + e.getMessage()); - } - } - - /** - * @exception ParseException - * throw in overridden method to disallow - */ - protected Query getRangeQuery(String field, String part1, String part2, boolean inclusive) throws ParseException - { - return getRangeQuery(field, part1, part2, inclusive, inclusive, AnalysisMode.DEFAULT, LuceneFunction.FIELD); - } - - /** - * @param field - * @param part1 - * @param part2 - * @param includeLower - * @param includeUpper - * @param analysisMode - * @param luceneFunction - * @return the query - * @exception ParseException - * throw in overridden method to disallow - */ - public Query getRangeQuery(String field, String part1, String part2, boolean includeLower, boolean includeUpper, AnalysisMode analysisMode, LuceneFunction luceneFunction) - throws ParseException - { - - if (field.startsWith("@")) - { - String fieldName; - PropertyDefinition propertyDef = matchPropertyDefinition(field.substring(1)); - if(propertyDef != null) - { - fieldName = "@" + propertyDef.getName(); - } - else - { - fieldName = expandAttributeFieldNamex(field); - } - - IndexTokenisationMode tokenisationMode = IndexTokenisationMode.TRUE; - if (propertyDef != null) - { - tokenisationMode = propertyDef.getIndexTokenisationMode(); - if (tokenisationMode == null) - { - tokenisationMode = IndexTokenisationMode.TRUE; - } - } - - if (propertyDef != null) - { - if (luceneFunction != LuceneFunction.FIELD) - { - if (propertyDef.getDataType().getName().equals(DataTypeDefinition.TEXT)) - { - BooleanQuery booleanQuery = new BooleanQuery(); - MLAnalysisMode mlAnalysisMode = searchParameters.getMlAnalaysisMode() == null ? config.getDefaultMLSearchAnalysisMode() : searchParameters - .getMlAnalaysisMode(); - List locales = searchParameters.getLocales(); - List expandedLocales = new ArrayList(); - for (Locale locale : (((locales == null) || (locales.size() == 0)) ? Collections.singletonList(I18NUtil.getLocale()) : locales)) - { - expandedLocales.addAll(MLAnalysisMode.getLocales(mlAnalysisMode, locale, false)); - } - for (Locale locale : (((expandedLocales == null) || (expandedLocales.size() == 0)) ? Collections.singletonList(I18NUtil.getLocale()) : expandedLocales)) - { - if (locale.toString().length() == 0) - { - continue; - } - - String textFieldName = fieldName; - - if (tokenisationMode == IndexTokenisationMode.BOTH) - { - textFieldName = textFieldName + "." + locale + ".sort"; - } - - addLocaleSpecificUntokenisedTextRangeFunction(field, part1, part2, includeLower, includeUpper, luceneFunction, booleanQuery, mlAnalysisMode, locale, - textFieldName); - - } - return booleanQuery; - } - else - { - throw new UnsupportedOperationException("Lucene Function"); - } - } - - if (propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT)) - { - throw new UnsupportedOperationException("Range is not supported against ml-text"); - } - else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) - { - throw new UnsupportedOperationException("Range is not supported against content"); - } - else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.TEXT)) - { - BooleanQuery booleanQuery = new BooleanQuery(); - MLAnalysisMode mlAnalysisMode = searchParameters.getMlAnalaysisMode() == null ? config.getDefaultMLSearchAnalysisMode() : searchParameters.getMlAnalaysisMode(); - List locales = searchParameters.getLocales(); - List expandedLocales = new ArrayList(); - for (Locale locale : (((locales == null) || (locales.size() == 0)) ? Collections.singletonList(I18NUtil.getLocale()) : locales)) - { - expandedLocales.addAll(MLAnalysisMode.getLocales(mlAnalysisMode, locale, false)); - } - for (Locale locale : (((expandedLocales == null) || (expandedLocales.size() == 0)) ? Collections.singletonList(I18NUtil.getLocale()) : expandedLocales)) - { - - String textFieldName = fieldName; - - if ((analysisMode == AnalysisMode.IDENTIFIER) || (analysisMode == AnalysisMode.LIKE)) - { - { - // text and ml text need locale - IndexTokenisationMode tm = propertyDef.getIndexTokenisationMode(); - if ((tm != null) && (tm == IndexTokenisationMode.BOTH)) - { - if (locale.toString().length() == 0) - { - textFieldName = textFieldName + ".no_locale"; - } - else - { - textFieldName = textFieldName + "." + locale + ".sort"; - } - - } - - } - } - switch (tokenisationMode) - { - case BOTH: - switch (analysisMode) - { - case DEFAULT: - case TOKENISE: - addLocaleSpecificTokenisedTextRange(part1, part2, includeLower, includeUpper, analysisMode, fieldName, booleanQuery, locale, textFieldName); - break; - case IDENTIFIER: - addLocaleSpecificUntokenisedTextRange(field, part1, part2, includeLower, includeUpper, booleanQuery, mlAnalysisMode, locale, textFieldName); - break; - case WILD: - case LIKE: - case PREFIX: - case FUZZY: - default: - throw new UnsupportedOperationException(); - } - break; - case FALSE: - addLocaleSpecificUntokenisedTextRange(field, part1, part2, includeLower, includeUpper, booleanQuery, mlAnalysisMode, locale, textFieldName); - - break; - case TRUE: - addLocaleSpecificTokenisedTextRange(part1, part2, includeLower, includeUpper, analysisMode, fieldName, booleanQuery, locale, textFieldName); - break; - default: - } - - } - return booleanQuery; - } - else if (propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME)) - { - DataTypeDefinition dataType = propertyDef.getDataType(); - String analyserClassName = dataType.getAnalyserClassName(); - boolean usesDateTimeAnalyser = analyserClassName.equals(DateTimeAnalyser.class.getCanonicalName()); - // Expand query for internal date time format - - if (usesDateTimeAnalyser) - { - Calendar start = Calendar.getInstance(); - Calendar end = Calendar.getInstance(); - try - { - Date date = CachingDateFormat.lenientParse(part1); - start.setTime(date); - } - catch (java.text.ParseException e) - { - SimpleDateFormat oldDf = CachingDateFormat.getDateFormat(); - try - { - Date date = oldDf.parse(part1); - start.setTime(date); - start.set(Calendar.MILLISECOND, 0); - } - catch (java.text.ParseException ee) - { - if (part1.equalsIgnoreCase("min")) - { - start.set(Calendar.YEAR, start.getMinimum(Calendar.YEAR)); - start.set(Calendar.DAY_OF_YEAR, start.getMinimum(Calendar.DAY_OF_YEAR)); - start.set(Calendar.HOUR_OF_DAY, start.getMinimum(Calendar.HOUR_OF_DAY)); - start.set(Calendar.MINUTE, start.getMinimum(Calendar.MINUTE)); - start.set(Calendar.SECOND, start.getMinimum(Calendar.SECOND)); - start.set(Calendar.MILLISECOND, start.getMinimum(Calendar.MILLISECOND)); - } - else if (part1.equalsIgnoreCase("now")) - { - start.setTime(new Date()); - } - else if (part1.equalsIgnoreCase("today")) - { - start.setTime(new Date()); - start.set(Calendar.HOUR_OF_DAY, start.getMinimum(Calendar.HOUR_OF_DAY)); - start.set(Calendar.MINUTE, start.getMinimum(Calendar.MINUTE)); - start.set(Calendar.SECOND, start.getMinimum(Calendar.SECOND)); - start.set(Calendar.MILLISECOND, start.getMinimum(Calendar.MILLISECOND)); - - } - else - { - return new TermQuery(new Term("NO_TOKENS", "__")); - } - } - } - try - { - Date date = CachingDateFormat.lenientParse(part2); - end.setTime(date); - } - catch (java.text.ParseException e) - { - SimpleDateFormat oldDf = CachingDateFormat.getDateFormat(); - try - { - Date date = oldDf.parse(part2); - end.setTime(date); - end.set(Calendar.MILLISECOND, 0); - } - catch (java.text.ParseException ee) - { - if (part2.equalsIgnoreCase("max")) - { - end.set(Calendar.YEAR, end.getMaximum(Calendar.YEAR)); - end.set(Calendar.DAY_OF_YEAR, end.getMaximum(Calendar.DAY_OF_YEAR)); - end.set(Calendar.HOUR_OF_DAY, end.getMaximum(Calendar.HOUR_OF_DAY)); - end.set(Calendar.MINUTE, end.getMaximum(Calendar.MINUTE)); - end.set(Calendar.SECOND, end.getMaximum(Calendar.SECOND)); - end.set(Calendar.MILLISECOND, end.getMaximum(Calendar.MILLISECOND)); - } - else if (part2.equalsIgnoreCase("now")) - { - end.setTime(new Date()); - } - else if (part1.equalsIgnoreCase("today")) - { - end.setTime(new Date()); - end.set(Calendar.HOUR_OF_DAY, end.getMinimum(Calendar.HOUR_OF_DAY)); - end.set(Calendar.MINUTE, end.getMinimum(Calendar.MINUTE)); - end.set(Calendar.SECOND, end.getMinimum(Calendar.SECOND)); - end.set(Calendar.MILLISECOND, end.getMinimum(Calendar.MILLISECOND)); - - } - else - { - return new TermQuery(new Term("NO_TOKENS", "__")); - } - } - } - - // Build a composite query for all the bits - Query rq = buildDateTimeRange(fieldName, start, end, includeLower, includeUpper); - return rq; - } - else - { - // Old Date time - String first = getToken(fieldName, part1, AnalysisMode.DEFAULT); - String last = getToken(fieldName, part2, AnalysisMode.DEFAULT); - return new ConstantScoreRangeQuery(fieldName, first, last, includeLower, includeUpper); - } - } - else - { - // Default property behaviour - String first = getToken(fieldName, part1, AnalysisMode.DEFAULT); - String last = getToken(fieldName, part2, AnalysisMode.DEFAULT); - return new ConstantScoreRangeQuery(fieldName, first, last, includeLower, includeUpper); - } - } - else - { - // No DD def - String first = getToken(fieldName, part1, AnalysisMode.DEFAULT); - String last = getToken(fieldName, part2, AnalysisMode.DEFAULT); - return new ConstantScoreRangeQuery(fieldName, first, last, includeLower, includeUpper); - } - } - else - { - // None property - leave alone - if (getLowercaseExpandedTerms()) - { - part1 = part1.toLowerCase(); - part2 = part2.toLowerCase(); - } - return new ConstantScoreRangeQuery(field, part1, part2, includeLower, includeUpper); - } - } - - private void addLocaleSpecificUntokenisedTextRangeFunction(String expandedFieldName, String lower, String upper, boolean includeLower, boolean includeUpper, - LuceneFunction luceneFunction, BooleanQuery booleanQuery, MLAnalysisMode mlAnalysisMode, Locale locale, String textFieldName) - { - String lowerTermText = lower; - if (locale.toString().length() > 0) - { - lowerTermText = "{" + locale + "}" + lower; - } - String upperTermText = upper; - if (locale.toString().length() > 0) - { - upperTermText = "{" + locale + "}" + upper; - } - Query subQuery = buildRangeFunctionQuery(textFieldName, lowerTermText, upperTermText, includeLower, includeUpper, luceneFunction); - booleanQuery.add(subQuery, Occur.SHOULD); - - if (booleanQuery.getClauses().length == 0) - { - booleanQuery.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - - private Query buildRangeFunctionQuery(String expandedFieldName, String lowerTermText, String upperTermText, boolean includeLower, boolean includeUpper, - LuceneFunction luceneFunction) - { - String testLowerTermText = lowerTermText; - if (testLowerTermText.startsWith("{")) - { - int index = lowerTermText.indexOf("}"); - testLowerTermText = lowerTermText.substring(index + 1); - } - - String testUpperTermText = upperTermText; - if (testUpperTermText.startsWith("{")) - { - int index = upperTermText.indexOf("}"); - testUpperTermText = upperTermText.substring(index + 1); - } - - switch (luceneFunction) - { - case LOWER: - if (testLowerTermText.equals(testLowerTermText.toLowerCase()) && testUpperTermText.equals(testUpperTermText.toLowerCase())) - { - return new CaseInsensitiveFieldRangeQuery(expandedFieldName, lowerTermText, upperTermText, includeLower, includeUpper); - } - else - { - // No match - return new TermQuery(new Term("NO_TOKENS", "__")); - } - case UPPER: - if (testLowerTermText.equals(testLowerTermText.toUpperCase()) && testUpperTermText.equals(testUpperTermText.toUpperCase())) - { - return new CaseInsensitiveFieldRangeQuery(expandedFieldName, lowerTermText, upperTermText, includeLower, includeUpper); - } - else - { - // No match - return new TermQuery(new Term("NO_TOKENS", "__")); - } - default: - throw new UnsupportedOperationException("Unsupported Lucene Function " + luceneFunction); - - } - } - - private void addLocaleSpecificTokenisedTextRange(String part1, String part2, boolean includeLower, boolean includeUpper, AnalysisMode analysisMode, String fieldName, - BooleanQuery booleanQuery, Locale locale, String textFieldName) throws ParseException - { - StringBuilder builder = new StringBuilder(); - builder.append("\u0000").append(locale.toString()).append("\u0000").append(part1); - String first = getToken(fieldName, builder.toString(), analysisMode); - - builder = new StringBuilder(); - builder.append("\u0000").append(locale.toString()).append("\u0000").append(part2); - String last = getToken(fieldName, builder.toString(), analysisMode); - - Query query = new ConstantScoreRangeQuery(textFieldName, first, last, includeLower, includeUpper); - booleanQuery.add(query, Occur.SHOULD); - } - - private void addLocaleSpecificUntokenisedTextRange(String field, String part1, String part2, boolean includeLower, boolean includeUpper, BooleanQuery booleanQuery, - MLAnalysisMode mlAnalysisMode, Locale locale, String textFieldName) - { - String lower = part1; - String upper = part2; - if (locale.toString().length() > 0) - { - lower = "{" + locale + "}" + part1; - upper = "{" + locale + "}" + part2; - } - - Query subQuery = new ConstantScoreRangeQuery(textFieldName, lower, upper, includeLower, includeUpper); - booleanQuery.add(subQuery, Occur.SHOULD); - - if (booleanQuery.getClauses().length == 0) - { - booleanQuery.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - - private Query buildDateTimeRange(String field, Calendar start, Calendar end, boolean includeLower, boolean includeUpper) throws ParseException - { - BooleanQuery query = new BooleanQuery(); - Query part; - if (start.get(Calendar.YEAR) == end.get(Calendar.YEAR)) - { - part = new TermQuery(new Term(field, "YE" + start.get(Calendar.YEAR))); - query.add(part, Occur.MUST); - if (start.get(Calendar.MONTH) == end.get(Calendar.MONTH)) - { - part = new TermQuery(new Term(field, build2SF("MO", start.get(Calendar.MONTH)))); - query.add(part, Occur.MUST); - if (start.get(Calendar.DAY_OF_MONTH) == end.get(Calendar.DAY_OF_MONTH)) - { - part = new TermQuery(new Term(field, build2SF("DA", start.get(Calendar.DAY_OF_MONTH)))); - query.add(part, Occur.MUST); - if (start.get(Calendar.HOUR_OF_DAY) == end.get(Calendar.HOUR_OF_DAY)) - { - part = new TermQuery(new Term(field, build2SF("HO", start.get(Calendar.HOUR_OF_DAY)))); - query.add(part, Occur.MUST); - if (start.get(Calendar.MINUTE) == end.get(Calendar.MINUTE)) - { - part = new TermQuery(new Term(field, build2SF("MI", start.get(Calendar.MINUTE)))); - query.add(part, Occur.MUST); - if (start.get(Calendar.SECOND) == end.get(Calendar.SECOND)) - { - part = new TermQuery(new Term(field, build2SF("SE", start.get(Calendar.SECOND)))); - query.add(part, Occur.MUST); - if (start.get(Calendar.MILLISECOND) == end.get(Calendar.MILLISECOND)) - { - if (includeLower && includeUpper) - { - part = new TermQuery(new Term(field, build3SF("MS", start.get(Calendar.MILLISECOND)))); - query.add(part, Occur.MUST); - } - else - { - return new TermQuery(new Term("NO_TOKENS", "__")); - } - } - else - { - // only ms - part = new ConstantScoreRangeQuery(field, build3SF("MS", start.get(Calendar.MILLISECOND)), build3SF("MS", end.get(Calendar.MILLISECOND)), - includeLower, includeUpper); - query.add(part, Occur.MUST); - } - } - else - { - // s + ms - - BooleanQuery subQuery = new BooleanQuery(); - Query subPart; - - subPart = buildStart(field, start, includeLower, Calendar.SECOND, Calendar.MILLISECOND); - if (subPart != null) - { - subQuery.add(subPart, Occur.SHOULD); - } - - if ((end.get(Calendar.SECOND) - start.get(Calendar.SECOND)) > 1) - { - subPart = new ConstantScoreRangeQuery(field, build2SF("SE", start.get(Calendar.SECOND)), build2SF("SE", end.get(Calendar.SECOND)), false, false); - subQuery.add(subPart, Occur.SHOULD); - } - - subPart = buildEnd(field, end, includeUpper, Calendar.SECOND, Calendar.MILLISECOND); - if (subPart != null) - { - subQuery.add(subPart, Occur.SHOULD); - } - - if (subQuery.clauses().size() > 0) - { - query.add(subQuery, Occur.MUST); - } - - } - } - else - { - // min + s + ms - - BooleanQuery subQuery = new BooleanQuery(); - Query subPart; - - for (int i : new int[] { Calendar.MILLISECOND, Calendar.SECOND }) - { - subPart = buildStart(field, start, includeLower, Calendar.MINUTE, i); - if (subPart != null) - { - subQuery.add(subPart, Occur.SHOULD); - } - } - - if ((end.get(Calendar.MINUTE) - start.get(Calendar.MINUTE)) > 1) - { - subPart = new ConstantScoreRangeQuery(field, build2SF("MI", start.get(Calendar.MINUTE)), build2SF("MI", end.get(Calendar.MINUTE)), false, false); - subQuery.add(subPart, Occur.SHOULD); - } - - for (int i : new int[] { Calendar.SECOND, Calendar.MILLISECOND }) - { - subPart = buildEnd(field, end, includeUpper, Calendar.MINUTE, i); - if (subPart != null) - { - subQuery.add(subPart, Occur.SHOULD); - } - } - - if (subQuery.clauses().size() > 0) - { - query.add(subQuery, Occur.MUST); - } - } - } - else - { - // hr + min + s + ms - - BooleanQuery subQuery = new BooleanQuery(); - Query subPart; - - for (int i : new int[] { Calendar.MILLISECOND, Calendar.SECOND, Calendar.MINUTE }) - { - subPart = buildStart(field, start, includeLower, Calendar.HOUR_OF_DAY, i); - if (subPart != null) - { - subQuery.add(subPart, Occur.SHOULD); - } - } - - if ((end.get(Calendar.HOUR_OF_DAY) - start.get(Calendar.HOUR_OF_DAY)) > 1) - { - subPart = new ConstantScoreRangeQuery(field, build2SF("HO", start.get(Calendar.HOUR_OF_DAY)), build2SF("HO", end.get(Calendar.HOUR_OF_DAY)), false, - false); - subQuery.add(subPart, Occur.SHOULD); - } - - for (int i : new int[] { Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND }) - { - subPart = buildEnd(field, end, includeUpper, Calendar.HOUR_OF_DAY, i); - if (subPart != null) - { - subQuery.add(subPart, Occur.SHOULD); - } - } - - if (subQuery.clauses().size() > 0) - { - query.add(subQuery, Occur.MUST); - } - } - } - else - { - // day + hr + min + s + ms - - BooleanQuery subQuery = new BooleanQuery(); - Query subPart; - - for (int i : new int[] { Calendar.MILLISECOND, Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY }) - { - subPart = buildStart(field, start, includeLower, Calendar.DAY_OF_MONTH, i); - if (subPart != null) - { - subQuery.add(subPart, Occur.SHOULD); - } - } - - if ((end.get(Calendar.DAY_OF_MONTH) - start.get(Calendar.DAY_OF_MONTH)) > 1) - { - subPart = new ConstantScoreRangeQuery(field, build2SF("DA", start.get(Calendar.DAY_OF_MONTH)), build2SF("DA", end.get(Calendar.DAY_OF_MONTH)), false, false); - subQuery.add(subPart, Occur.SHOULD); - } - - for (int i : new int[] { Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND }) - { - subPart = buildEnd(field, end, includeUpper, Calendar.DAY_OF_MONTH, i); - if (subPart != null) - { - subQuery.add(subPart, Occur.SHOULD); - } - } - - if (subQuery.clauses().size() > 0) - { - query.add(subQuery, Occur.MUST); - } - - } - } - else - { - // month + day + hr + min + s + ms - - BooleanQuery subQuery = new BooleanQuery(); - Query subPart; - - for (int i : new int[] { Calendar.MILLISECOND, Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY, Calendar.DAY_OF_MONTH }) - { - subPart = buildStart(field, start, includeLower, Calendar.MONTH, i); - if (subPart != null) - { - subQuery.add(subPart, Occur.SHOULD); - } - } - - if ((end.get(Calendar.MONTH) - start.get(Calendar.MONTH)) > 1) - { - subPart = new ConstantScoreRangeQuery(field, build2SF("MO", start.get(Calendar.MONTH)), build2SF("MO", end.get(Calendar.MONTH)), false, false); - subQuery.add(subPart, Occur.SHOULD); - } - - for (int i : new int[] { Calendar.DAY_OF_MONTH, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND }) - { - subPart = buildEnd(field, end, includeUpper, Calendar.MONTH, i); - if (subPart != null) - { - subQuery.add(subPart, Occur.SHOULD); - } - } - - if (subQuery.clauses().size() > 0) - { - query.add(subQuery, Occur.MUST); - } - } - } - else - { - // year + month + day + hr + min + s + ms - - BooleanQuery subQuery = new BooleanQuery(); - Query subPart; - - for (int i : new int[] { Calendar.MILLISECOND, Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY, Calendar.DAY_OF_MONTH, Calendar.MONTH }) - { - subPart = buildStart(field, start, includeLower, Calendar.YEAR, i); - if (subPart != null) - { - subQuery.add(subPart, Occur.SHOULD); - } - } - - if ((end.get(Calendar.YEAR) - start.get(Calendar.YEAR)) > 1) - { - subPart = new ConstantScoreRangeQuery(field, "YE" + start.get(Calendar.YEAR), "YE" + end.get(Calendar.YEAR), false, false); - subQuery.add(subPart, Occur.SHOULD); - } - - for (int i : new int[] { Calendar.MONTH, Calendar.DAY_OF_MONTH, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND }) - { - subPart = buildEnd(field, end, includeUpper, Calendar.YEAR, i); - if (subPart != null) - { - subQuery.add(subPart, Occur.SHOULD); - } - } - - if (subQuery.clauses().size() > 0) - { - query.add(subQuery, Occur.MUST); - } - } - return query; - } - - private Query buildStart(String field, Calendar cal, boolean inclusive, int startField, int padField) - { - BooleanQuery range = new BooleanQuery(); - // only ms difference - Query part; - - int ms = cal.get(Calendar.MILLISECOND) + (inclusive ? 0 : 1); - - switch (startField) - { - case Calendar.YEAR: - part = new TermQuery(new Term(field, "YE" + cal.get(Calendar.YEAR))); - range.add(part, Occur.MUST); - case Calendar.MONTH: - if ((cal.get(Calendar.MONTH) == 0) - && (cal.get(Calendar.DAY_OF_MONTH) == 1) && (cal.get(Calendar.HOUR_OF_DAY) == 0) && (cal.get(Calendar.MINUTE) == 0) && (cal.get(Calendar.SECOND) == 0) - && (ms == 0)) - { - if (padField == Calendar.DAY_OF_MONTH) - { - break; - } - else - { - return null; - } - } - else if (padField == Calendar.MONTH) - { - if (cal.get(Calendar.MONTH) < cal.getMaximum(Calendar.MONTH)) - { - part = new ConstantScoreRangeQuery(field, build2SF("MO", (cal.get(Calendar.MONTH) + 1)), "MO" + cal.getMaximum(Calendar.MONTH), true, true); - range.add(part, Occur.MUST); - break; - } - else - { - return null; - } - } - else - { - part = new TermQuery(new Term(field, build2SF("MO", cal.get(Calendar.MONTH)))); - range.add(part, Occur.MUST); - } - case Calendar.DAY_OF_MONTH: - if ((cal.get(Calendar.DAY_OF_MONTH) == 1) && (cal.get(Calendar.HOUR_OF_DAY) == 0) && (cal.get(Calendar.MINUTE) == 0) && (cal.get(Calendar.SECOND) == 0) && (ms == 0)) - { - if (padField == Calendar.HOUR_OF_DAY) - { - break; - } - else - { - return null; - } - } - else if (padField == Calendar.DAY_OF_MONTH) - { - if (cal.get(Calendar.DAY_OF_MONTH) < cal.getMaximum(Calendar.DAY_OF_MONTH)) - { - part = new ConstantScoreRangeQuery(field, build2SF("DA", (cal.get(Calendar.DAY_OF_MONTH) + 1)), "DA" + cal.getMaximum(Calendar.DAY_OF_MONTH), true, true); - range.add(part, Occur.MUST); - break; - } - else - { - return null; - } - } - else - { - part = new TermQuery(new Term(field, build2SF("DA", cal.get(Calendar.DAY_OF_MONTH)))); - range.add(part, Occur.MUST); - } - case Calendar.HOUR_OF_DAY: - if ((cal.get(Calendar.HOUR_OF_DAY) == 0) && (cal.get(Calendar.MINUTE) == 0) && (cal.get(Calendar.SECOND) == 0) && (ms == 0)) - { - if (padField == Calendar.MINUTE) - { - break; - } - else - { - return null; - } - } - else if (padField == Calendar.HOUR_OF_DAY) - { - if (cal.get(Calendar.HOUR_OF_DAY) < cal.getMaximum(Calendar.HOUR_OF_DAY)) - { - part = new ConstantScoreRangeQuery(field, build2SF("HO", (cal.get(Calendar.HOUR_OF_DAY) + 1)), "HO" + cal.getMaximum(Calendar.HOUR_OF_DAY), true, true); - range.add(part, Occur.MUST); - break; - } - else - { - return null; - } - } - else - { - part = new TermQuery(new Term(field, build2SF("HO", cal.get(Calendar.HOUR_OF_DAY)))); - range.add(part, Occur.MUST); - } - case Calendar.MINUTE: - if ((cal.get(Calendar.MINUTE) == 0) && (cal.get(Calendar.SECOND) == 0) && (ms == 0)) - { - if (padField == Calendar.SECOND) - { - break; - } - else - { - return null; - } - } - else if (padField == Calendar.MINUTE) - { - if (cal.get(Calendar.MINUTE) < cal.getMaximum(Calendar.MINUTE)) - { - part = new ConstantScoreRangeQuery(field, build2SF("MI", (cal.get(Calendar.MINUTE) + 1)), "MI" + cal.getMaximum(Calendar.MINUTE), true, true); - range.add(part, Occur.MUST); - break; - } - else - { - return null; - } - } - else - { - part = new TermQuery(new Term(field, build2SF("MI", cal.get(Calendar.MINUTE)))); - range.add(part, Occur.MUST); - } - case Calendar.SECOND: - if ((cal.get(Calendar.SECOND) == 0) && (ms == 0)) - { - if (padField == Calendar.MILLISECOND) - { - break; - } - else - { - return null; - } - } - else if (padField == Calendar.SECOND) - { - if (cal.get(Calendar.SECOND) < cal.getMaximum(Calendar.SECOND)) - { - part = new ConstantScoreRangeQuery(field, build2SF("SE", (cal.get(Calendar.SECOND) + 1)), "SE" + cal.getMaximum(Calendar.SECOND), true, true); - range.add(part, Occur.MUST); - break; - } - else - { - return null; - } - - } - else - { - part = new TermQuery(new Term(field, build2SF("SE", cal.get(Calendar.SECOND)))); - range.add(part, Occur.MUST); - } - default: - if ((ms > 0) && (ms <= cal.getMaximum(Calendar.MILLISECOND))) - { - part = new ConstantScoreRangeQuery(field, build3SF("MS", ms), "MS" + cal.getMaximum(Calendar.MILLISECOND), true, true); - range.add(part, Occur.MUST); - } - else - { - return null; - } - } - - if (range.clauses().size() > 0) - { - return range; - } - else - { - return null; - } - } - - private Query buildEnd(String field, Calendar cal, boolean inclusive, int startField, int padField) - { - BooleanQuery range = new BooleanQuery(); - // only ms difference - Query part; - - int ms = cal.get(Calendar.MILLISECOND) - (inclusive ? 0 : 1); - - switch (startField) - { - case Calendar.YEAR: - part = new TermQuery(new Term(field, "YE" + cal.get(Calendar.YEAR))); - range.add(part, Occur.MUST); - case Calendar.MONTH: - if ((cal.get(Calendar.MONTH) == 0) - && (cal.get(Calendar.DAY_OF_MONTH) == 1) && (cal.get(Calendar.HOUR_OF_DAY) == 0) && (cal.get(Calendar.MINUTE) == 0) && (cal.get(Calendar.SECOND) == 0) - && (ms == 0)) - { - if (padField == Calendar.MONTH) - { - return null; - } - } - - if (padField == Calendar.MONTH) - { - if (cal.get(Calendar.MONTH) > cal.getMinimum(Calendar.MONTH)) - { - part = new ConstantScoreRangeQuery(field, build2SF("MO", cal.getMinimum(Calendar.MONTH)), build2SF("MO", (cal.get(Calendar.MONTH) - 1)), true, true); - range.add(part, Occur.MUST); - break; - } - else - { - return null; - } - } - else - { - part = new TermQuery(new Term(field, build2SF("MO", cal.get(Calendar.MONTH)))); - range.add(part, Occur.MUST); - } - case Calendar.DAY_OF_MONTH: - if ((cal.get(Calendar.DAY_OF_MONTH) == 1) && (cal.get(Calendar.HOUR_OF_DAY) == 0) && (cal.get(Calendar.MINUTE) == 0) && (cal.get(Calendar.SECOND) == 0) && (ms == 0)) - { - if (padField == Calendar.DAY_OF_MONTH) - { - return null; - } - } - - if (padField == Calendar.DAY_OF_MONTH) - { - if (cal.get(Calendar.DAY_OF_MONTH) > cal.getMinimum(Calendar.DAY_OF_MONTH)) - { - part = new ConstantScoreRangeQuery(field, build2SF("DA", cal.getMinimum(Calendar.DAY_OF_MONTH)), build2SF("DA", (cal.get(Calendar.DAY_OF_MONTH) - 1)), true, - true); - range.add(part, Occur.MUST); - break; - } - else - { - return null; - } - } - else - { - part = new TermQuery(new Term(field, build2SF("DA", cal.get(Calendar.DAY_OF_MONTH)))); - range.add(part, Occur.MUST); - } - case Calendar.HOUR_OF_DAY: - if ((cal.get(Calendar.HOUR_OF_DAY) == 0) && (cal.get(Calendar.MINUTE) == 0) && (cal.get(Calendar.SECOND) == 0) && (ms == 0)) - { - if (padField == Calendar.HOUR_OF_DAY) - { - return null; - } - } - - if (padField == Calendar.HOUR_OF_DAY) - { - if (cal.get(Calendar.HOUR_OF_DAY) > cal.getMinimum(Calendar.HOUR_OF_DAY)) - { - part = new ConstantScoreRangeQuery(field, build2SF("HO", cal.getMinimum(Calendar.HOUR_OF_DAY)), build2SF("HO", (cal.get(Calendar.HOUR_OF_DAY) - 1)), true, true); - range.add(part, Occur.MUST); - break; - } - else - { - return null; - } - } - else - { - part = new TermQuery(new Term(field, build2SF("HO", cal.get(Calendar.HOUR_OF_DAY)))); - range.add(part, Occur.MUST); - } - case Calendar.MINUTE: - if ((cal.get(Calendar.MINUTE) == 0) && (cal.get(Calendar.SECOND) == 0) && (ms == 0)) - { - if (padField == Calendar.MINUTE) - { - return null; - } - } - - if (padField == Calendar.MINUTE) - { - if (cal.get(Calendar.MINUTE) > cal.getMinimum(Calendar.MINUTE)) - { - part = new ConstantScoreRangeQuery(field, build2SF("MI", cal.getMinimum(Calendar.MINUTE)), build2SF("MI", (cal.get(Calendar.MINUTE) - 1)), true, true); - range.add(part, Occur.MUST); - break; - } - else - { - return null; - } - } - else - { - part = new TermQuery(new Term(field, build2SF("MI", cal.get(Calendar.MINUTE)))); - range.add(part, Occur.MUST); - } - case Calendar.SECOND: - if ((cal.get(Calendar.SECOND) == 0) && (ms == 0)) - { - if (padField == Calendar.SECOND) - { - return null; - } - } - - if (padField == Calendar.SECOND) - { - if (cal.get(Calendar.SECOND) > cal.getMinimum(Calendar.SECOND)) - { - part = new ConstantScoreRangeQuery(field, build2SF("SE", cal.getMinimum(Calendar.SECOND)), build2SF("SE", (cal.get(Calendar.SECOND) - 1)), true, true); - range.add(part, Occur.MUST); - break; - } - else - { - return null; - } - } - else - { - part = new TermQuery(new Term(field, build2SF("SE", cal.get(Calendar.SECOND)))); - range.add(part, Occur.MUST); - } - default: - if ((ms >= cal.getMinimum(Calendar.MILLISECOND)) && (ms < cal.getMaximum(Calendar.MILLISECOND))) - { - part = new ConstantScoreRangeQuery(field, build3SF("MS", cal.getMinimum(Calendar.MILLISECOND)), build3SF("MS", ms), true, true); - range.add(part, Occur.MUST); - } - else - { - return null; - } - } - - if (range.clauses().size() > 0) - { - return range; - } - else - { - return null; - } - } - - private String build2SF(String prefix, int value) - { - if (value < 10) - { - return prefix + "0" + value; - } - else - { - return prefix + value; - } - } - - private String build3SF(String prefix, int value) - { - if (value < 10) - { - return prefix + "00" + value; - } - else if (value < 100) - { - return prefix + "0" + value; - } - else - { - return prefix + value; - } - } - - private String expandAttributeFieldNamex(String field) - { - return "@"+expandQName(field.substring(1)); - } - - private String expandQName(String qnameString) - { - String fieldName = qnameString; - // Check for any prefixes and expand to the full uri - if (qnameString.charAt(0) != '{') - { - int colonPosition = qnameString.indexOf(':'); - if (colonPosition == -1) - { - // use the default namespace - fieldName = "{" + searchParameters.getNamespace() + "}" + qnameString; - } - else - { - String prefix = qnameString.substring(0, colonPosition); - String uri = matchURI(prefix); - if(uri == null) - { - fieldName = "{" + searchParameters.getNamespace() + "}" + qnameString; - } - else - { - fieldName = "{" + uri + "}" + qnameString.substring(colonPosition + 1); - } - - } - } - return fieldName; - } - - private String matchURI(String prefix) - { - HashSet prefixes = new HashSet(namespacePrefixResolver.getPrefixes()); - if(prefixes.contains(prefix)) - { - return namespacePrefixResolver.getNamespaceURI(prefix); - } - String match = null; - for(String candidate : prefixes) - { - if(candidate.equalsIgnoreCase(prefix)) - { - if(match == null) - { - match = candidate; - } - else - { - - throw new LuceneIndexException("Ambiguous namespace prefix "+prefix); - - } - } - } - if(match == null) - { - return null; - } - else - { - return namespacePrefixResolver.getNamespaceURI(match); - } - } - - private String getToken(String field, String value, AnalysisMode analysisMode) throws ParseException - { - TokenStream source = getAnalyzer().tokenStream(field, new StringReader(value), analysisMode); - org.apache.lucene.analysis.Token reusableToken = new org.apache.lucene.analysis.Token(); - org.apache.lucene.analysis.Token nextToken; - String tokenised = null; - - while (true) - { - try - { - nextToken = source.next(reusableToken); - } - catch (IOException e) - { - nextToken = null; - } - if (nextToken == null) - break; - tokenised = new String(nextToken.termBuffer(), 0, nextToken.termLength()); - } - try - { - source.close(); - } - catch (IOException e) - { - - } - - return tokenised; - } - - @Override - public Query getPrefixQuery(String field, String termStr) throws ParseException - { - if (field.startsWith("@")) - { - return attributeQueryBuilder(field, termStr, new PrefixQuery(), AnalysisMode.PREFIX, LuceneFunction.FIELD); - } - else if (field.equals("TEXT")) - { - Set text = searchParameters.getTextAttributes(); - if ((text == null) || (text.size() == 0)) - { - Collection contentAttributes = dictionaryService.getAllProperties(DataTypeDefinition.CONTENT); - BooleanQuery query = new BooleanQuery(); - for (QName qname : contentAttributes) - { - // The super implementation will create phrase queries etc if required - Query part = getPrefixQuery("@" + qname.toString(), termStr); - if (part != null) - { - query.add(part, Occur.SHOULD); - } - else - { - query.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - return query; - } - else - { - BooleanQuery query = new BooleanQuery(); - for (String fieldName : text) - { - Query part = getPrefixQuery(fieldName, termStr); - if (part != null) - { - query.add(part, Occur.SHOULD); - } - else - { - query.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - return query; - } - } - else if (field.equals("ID")) - { - boolean lowercaseExpandedTerms = getLowercaseExpandedTerms(); - try - { - setLowercaseExpandedTerms(false); - return super.getPrefixQuery(field, termStr); - } - finally - { - setLowercaseExpandedTerms(lowercaseExpandedTerms); - } - } - else if (field.equals("PARENT")) - { - boolean lowercaseExpandedTerms = getLowercaseExpandedTerms(); - try - { - setLowercaseExpandedTerms(false); - return super.getPrefixQuery(field, termStr); - } - finally - { - setLowercaseExpandedTerms(lowercaseExpandedTerms); - } - } - else - { - return super.getPrefixQuery(field, termStr); - } - } - - @Override - public Query getWildcardQuery(String field, String termStr) throws ParseException - { - return getWildcardQuery(field, termStr, AnalysisMode.WILD); - } - - private Query getWildcardQuery(String field, String termStr, AnalysisMode analysisMode) throws ParseException - { - if (field.startsWith("@")) - { - return attributeQueryBuilder(field, termStr, new WildcardQuery(), analysisMode, LuceneFunction.FIELD); - } - - else if (field.equals("TEXT")) - { - Set text = searchParameters.getTextAttributes(); - if ((text == null) || (text.size() == 0)) - { - Collection contentAttributes = dictionaryService.getAllProperties(DataTypeDefinition.CONTENT); - BooleanQuery query = new BooleanQuery(); - for (QName qname : contentAttributes) - { - // The super implementation will create phrase queries etc if required - Query part = getWildcardQuery("@" + qname.toString(), termStr); - if (part != null) - { - query.add(part, Occur.SHOULD); - } - else - { - query.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - return query; - } - else - { - BooleanQuery query = new BooleanQuery(); - for (String fieldName : text) - { - Query part = getWildcardQuery(fieldName, termStr); - if (part != null) - { - query.add(part, Occur.SHOULD); - } - else - { - query.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - return query; - } - } - else if (field.equals("ID")) - { - boolean lowercaseExpandedTerms = getLowercaseExpandedTerms(); - try - { - setLowercaseExpandedTerms(false); - return super.getWildcardQuery(field, termStr); - } - finally - { - setLowercaseExpandedTerms(lowercaseExpandedTerms); - } - } - else if (field.equals("PARENT")) - { - boolean lowercaseExpandedTerms = getLowercaseExpandedTerms(); - try - { - setLowercaseExpandedTerms(false); - return super.getWildcardQuery(field, termStr); - } - finally - { - setLowercaseExpandedTerms(lowercaseExpandedTerms); - } - } - else - { - return super.getWildcardQuery(field, termStr); - } - } - - @Override - public Query getFuzzyQuery(String field, String termStr, float minSimilarity) throws ParseException - { - if (field.startsWith("@")) - { - return attributeQueryBuilder(field, termStr, new FuzzyQuery(minSimilarity), AnalysisMode.FUZZY, LuceneFunction.FIELD); - } - - else if (field.equals("TEXT")) - { - Set text = searchParameters.getTextAttributes(); - if ((text == null) || (text.size() == 0)) - { - Collection contentAttributes = dictionaryService.getAllProperties(DataTypeDefinition.CONTENT); - BooleanQuery query = new BooleanQuery(); - for (QName qname : contentAttributes) - { - // The super implementation will create phrase queries etc if required - Query part = getFuzzyQuery("@" + qname.toString(), termStr, minSimilarity); - if (part != null) - { - query.add(part, Occur.SHOULD); - } - else - { - query.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - return query; - } - else - { - BooleanQuery query = new BooleanQuery(); - for (String fieldName : text) - { - Query part = getFuzzyQuery(fieldName, termStr, minSimilarity); - if (part != null) - { - query.add(part, Occur.SHOULD); - } - else - { - query.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - return query; - } - } - else if (field.equals("ID")) - { - boolean lowercaseExpandedTerms = getLowercaseExpandedTerms(); - try - { - setLowercaseExpandedTerms(false); - return super.getFuzzyQuery(field, termStr, minSimilarity); - } - finally - { - setLowercaseExpandedTerms(lowercaseExpandedTerms); - } - } - else if (field.equals("PARENT")) - { - boolean lowercaseExpandedTerms = getLowercaseExpandedTerms(); - try - { - setLowercaseExpandedTerms(false); - return super.getFuzzyQuery(field, termStr, minSimilarity); - } - finally - { - setLowercaseExpandedTerms(lowercaseExpandedTerms); - } - } - else - { - return super.getFuzzyQuery(field, termStr, minSimilarity); - } - } - - /** - * @param dictionaryService - */ - public void setDictionaryService(DictionaryService dictionaryService) - { - this.dictionaryService = dictionaryService; - } - - /** - * @param field - * @param queryText - * @param analysisMode - * @param luceneFunction - * @return the query - * @throws ParseException - */ - public Query getSuperFieldQuery(String field, String queryText, AnalysisMode analysisMode, LuceneFunction luceneFunction) throws ParseException - { - return getFieldQueryImpl(field, queryText, analysisMode, luceneFunction); - } - - /** - * @param field - * @param termStr - * @param minSimilarity - * @return the query - * @throws ParseException - */ - public Query getSuperFuzzyQuery(String field, String termStr, float minSimilarity) throws ParseException - { - return super.getFuzzyQuery(field, termStr, minSimilarity); - } - - /** - * @param field - * @param termStr - * @return the query - * @throws ParseException - */ - public Query getSuperPrefixQuery(String field, String termStr) throws ParseException - { - return super.getPrefixQuery(field, termStr); - } - - /** - * @param field - * @param termStr - * @return the query - * @throws ParseException - */ - public Query getSuperWildcardQuery(String field, String termStr) throws ParseException - { - return super.getWildcardQuery(field, termStr); - } - - /* - * (non-Javadoc) - * @see org.apache.lucene.queryParser.QueryParser#newWildcardQuery(org.apache.lucene.index.Term) - */ - @Override - protected Query newWildcardQuery(Term t) - { - if (t.text().contains("\\")) - { - String regexp = SearchLanguageConversion.convert(SearchLanguageConversion.DEF_LUCENE, SearchLanguageConversion.DEF_REGEX, t.text()); - return new RegexQuery(new Term(t.field(), regexp)); - } - else - { - return super.newWildcardQuery(t); - } - } - - /* - * (non-Javadoc) - * @see org.apache.lucene.queryParser.QueryParser#newPrefixQuery(org.apache.lucene.index.Term) - */ - @Override - protected Query newPrefixQuery(Term prefix) - { - if (prefix.text().contains("\\")) - { - String regexp = SearchLanguageConversion.convert(SearchLanguageConversion.DEF_LUCENE, SearchLanguageConversion.DEF_REGEX, prefix.text()); - return new RegexQuery(new Term(prefix.field(), regexp)); - } - else - { - return super.newPrefixQuery(prefix); - } - - } - - interface SubQuery - { - /** - * @param field - * @param queryText - * @param analysisMode - * @param luceneFunction - * @return the query - * @throws ParseException - */ - Query getQuery(String field, String queryText, AnalysisMode analysisMode, LuceneFunction luceneFunction) throws ParseException; - } - - class FieldQuery implements SubQuery - { - public Query getQuery(String field, String queryText, AnalysisMode analysisMode, LuceneFunction luceneFunction) throws ParseException - { - return getSuperFieldQuery(field, queryText, analysisMode, luceneFunction); - } - } - - class FuzzyQuery implements SubQuery - { - float minSimilarity; - - FuzzyQuery(float minSimilarity) - { - this.minSimilarity = minSimilarity; - } - - public Query getQuery(String field, String termStr, AnalysisMode analysisMode, LuceneFunction luceneFunction) throws ParseException - { - return getSuperFuzzyQuery(field, termStr, minSimilarity); - } - } - - class PrefixQuery implements SubQuery - { - public Query getQuery(String field, String termStr, AnalysisMode analysisMode, LuceneFunction luceneFunction) throws ParseException - { - return getSuperPrefixQuery(field, termStr); - } - } - - class WildcardQuery implements SubQuery - { - public Query getQuery(String field, String termStr, AnalysisMode analysisMode, LuceneFunction luceneFunction) throws ParseException - { - return getSuperWildcardQuery(field, termStr); - } - } - - private Query attributeQueryBuilder(String field, String queryText, SubQuery subQueryBuilder, AnalysisMode analysisMode, LuceneFunction luceneFunction) throws ParseException - { - // TODO: Fix duplicate token generation for mltext, content and text. - // -locale expansion here and in tokeisation -> duplicates - - // Get type info etc - String propertyFieldName = null; - String ending = ""; - if (field.endsWith(".mimetype")) - { - propertyFieldName = field.substring(1, field.length() - 9); - ending = ".mimetype"; - } - else if (field.endsWith(".size")) - { - propertyFieldName = field.substring(1, field.length() - 5); - ending = ".size"; - } - else if (field.endsWith(".locale")) - { - propertyFieldName = field.substring(1, field.length() - 7); - ending = ".locale"; - } - else - { - propertyFieldName = field.substring(1); - } - - String expandedFieldName; - QName propertyQName; - PropertyDefinition propertyDef = matchPropertyDefinition(propertyFieldName); - IndexTokenisationMode tokenisationMode = IndexTokenisationMode.TRUE; - if (propertyDef != null) - { - tokenisationMode = propertyDef.getIndexTokenisationMode(); - if (tokenisationMode == null) - { - tokenisationMode = IndexTokenisationMode.TRUE; - } - expandedFieldName = "@"+propertyDef.getName()+ending; - propertyQName = propertyDef.getName(); - } - else - { - expandedFieldName = expandAttributeFieldNamex(field); - propertyQName = QName.createQName(propertyFieldName); - } - - - if (luceneFunction != LuceneFunction.FIELD) - { - if ((tokenisationMode == IndexTokenisationMode.FALSE) || (tokenisationMode == IndexTokenisationMode.BOTH)) - { - return functionQueryBuilder(expandedFieldName, propertyQName, propertyDef, tokenisationMode, queryText, luceneFunction); - } - } - - // Mime type - if (expandedFieldName.endsWith(".mimetype")) - { - if ((propertyDef != null) && (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))) - { - return subQueryBuilder.getQuery(expandedFieldName, queryText, analysisMode, luceneFunction); - } - - } - else if (expandedFieldName.endsWith(".size")) - { - if ((propertyDef != null) && (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))) - { - return subQueryBuilder.getQuery(expandedFieldName, queryText, analysisMode, luceneFunction); - } - - } - else if (expandedFieldName.endsWith(".locale")) - { - if ((propertyDef != null) && (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))) - { - return subQueryBuilder.getQuery(expandedFieldName, queryText, analysisMode, luceneFunction); - } - - } - - // Already in expanded form - - // ML - - if ((propertyDef != null) && (propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT))) - { - // Build a sub query for each locale and or the results together - the analysis will take care of - // cross language matching for each entry - BooleanQuery booleanQuery = new BooleanQuery(); - MLAnalysisMode mlAnalysisMode = searchParameters.getMlAnalaysisMode() == null ? config.getDefaultMLSearchAnalysisMode() : searchParameters.getMlAnalaysisMode(); - List locales = searchParameters.getLocales(); - List expandedLocales = new ArrayList(); - for (Locale locale : (((locales == null) || (locales.size() == 0)) ? Collections.singletonList(I18NUtil.getLocale()) : locales)) - { - expandedLocales.addAll(MLAnalysisMode.getLocales(mlAnalysisMode, locale, false)); - } - for (Locale locale : (((expandedLocales == null) || (expandedLocales.size() == 0)) ? Collections.singletonList(I18NUtil.getLocale()) : expandedLocales)) - { - String mlFieldName = expandedFieldName; - - if ((tokenisationMode == IndexTokenisationMode.BOTH) && ((analysisMode == AnalysisMode.IDENTIFIER) || (analysisMode == AnalysisMode.LIKE))) - { - { - // text and ml text need locale - IndexTokenisationMode tm = propertyDef.getIndexTokenisationMode(); - if ((tm != null) && (tm == IndexTokenisationMode.BOTH)) - { - if (locale.toString().length() == 0) - { - mlFieldName = mlFieldName + ".no_locale"; - } - else - { - mlFieldName = mlFieldName + "." + locale + ".sort"; - } - } - - } - } - - boolean lowercaseExpandedTerms = getLowercaseExpandedTerms(); - try - { - switch (tokenisationMode) - { - case BOTH: - switch (analysisMode) - { - default: - case DEFAULT: - case TOKENISE: - addLocaleSpecificTokenisedMLOrTextAttribute(queryText, subQueryBuilder, analysisMode, luceneFunction, booleanQuery, locale, expandedFieldName); - break; - case IDENTIFIER: - case FUZZY: - case PREFIX: - case WILD: - case LIKE: - setLowercaseExpandedTerms(false); - addLocaleSpecificUntokenisedMLOrTextAttribute(field, queryText, subQueryBuilder, analysisMode, luceneFunction, booleanQuery, mlAnalysisMode, locale, - mlFieldName); - - break; - } - break; - case FALSE: - setLowercaseExpandedTerms(false); - addLocaleSpecificUntokenisedMLOrTextAttribute(field, queryText, subQueryBuilder, analysisMode, luceneFunction, booleanQuery, mlAnalysisMode, locale, - mlFieldName); - break; - case TRUE: - default: - switch (analysisMode) - { - default: - case DEFAULT: - case TOKENISE: - case IDENTIFIER: - addLocaleSpecificTokenisedMLOrTextAttribute(queryText, subQueryBuilder, analysisMode, luceneFunction, booleanQuery, locale, expandedFieldName); - break; - case FUZZY: - case PREFIX: - case WILD: - case LIKE: - addLocaleSpecificUntokenisedMLOrTextAttribute(field, queryText, subQueryBuilder, analysisMode, luceneFunction, booleanQuery, mlAnalysisMode, locale, - mlFieldName); - break; - } - } - } - finally - { - setLowercaseExpandedTerms(lowercaseExpandedTerms); - } - } - return booleanQuery; - } - // Content - else if ((propertyDef != null) && (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))) - { - // Identifier request are ignored for content - - // Build a sub query for each locale and or the results together - - // - add an explicit condition for the locale - - MLAnalysisMode mlAnalysisMode = searchParameters.getMlAnalaysisMode() == null ? config.getDefaultMLSearchAnalysisMode() : searchParameters.getMlAnalaysisMode(); - - if (mlAnalysisMode.includesAll()) - { - return subQueryBuilder.getQuery(expandedFieldName, queryText, analysisMode, luceneFunction); - } - - List locales = searchParameters.getLocales(); - List expandedLocales = new ArrayList(); - for (Locale locale : (((locales == null) || (locales.size() == 0)) ? Collections.singletonList(I18NUtil.getLocale()) : locales)) - { - expandedLocales.addAll(MLAnalysisMode.getLocales(mlAnalysisMode, locale, true)); - } - - if (expandedLocales.size() > 0) - { - BooleanQuery booleanQuery = new BooleanQuery(); - Query contentQuery = subQueryBuilder.getQuery(expandedFieldName, queryText, analysisMode, luceneFunction); - if (contentQuery != null) - { - booleanQuery.add(contentQuery, Occur.MUST); - BooleanQuery subQuery = new BooleanQuery(); - for (Locale locale : (expandedLocales)) - { - StringBuilder builder = new StringBuilder(); - builder.append(expandedFieldName).append(".locale"); - String localeString = locale.toString(); - if (localeString.indexOf("*") == -1) - { - Query localeQuery = getFieldQuery(builder.toString(), localeString); - if (localeQuery != null) - { - subQuery.add(localeQuery, Occur.SHOULD); - } - else - { - subQuery.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - else - { - Query localeQuery = getWildcardQuery(builder.toString(), localeString); - if (localeQuery != null) - { - subQuery.add(localeQuery, Occur.SHOULD); - } - else - { - subQuery.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - } - booleanQuery.add(subQuery, Occur.MUST); - } - return booleanQuery; - } - else - { - Query query = subQueryBuilder.getQuery(expandedFieldName, queryText, analysisMode, luceneFunction); - if (query != null) - { - return query; - } - else - { - return new TermQuery(new Term("NO_TOKENS", "__")); - } - } - - } - else if ((propertyDef != null) && (propertyDef.getDataType().getName().equals(DataTypeDefinition.TEXT))) - { - if (propertyQName.equals(ContentModel.PROP_USER_USERNAME) || propertyQName.equals(ContentModel.PROP_USERNAME) || propertyQName.equals(ContentModel.PROP_AUTHORITY_NAME)) - { - return subQueryBuilder.getQuery(expandedFieldName, queryText, analysisMode, luceneFunction); - } - - BooleanQuery booleanQuery = new BooleanQuery(); - MLAnalysisMode mlAnalysisMode = searchParameters.getMlAnalaysisMode() == null ? config.getDefaultMLSearchAnalysisMode() : searchParameters.getMlAnalaysisMode(); - List locales = searchParameters.getLocales(); - List expandedLocales = new ArrayList(); - for (Locale locale : (((locales == null) || (locales.size() == 0)) ? Collections.singletonList(I18NUtil.getLocale()) : locales)) - { - expandedLocales.addAll(MLAnalysisMode.getLocales(mlAnalysisMode, locale, false)); - } - for (Locale locale : (((expandedLocales == null) || (expandedLocales.size() == 0)) ? Collections.singletonList(I18NUtil.getLocale()) : expandedLocales)) - { - String textFieldName = expandedFieldName; - - if ((tokenisationMode == IndexTokenisationMode.BOTH) && ((analysisMode == AnalysisMode.IDENTIFIER) || (analysisMode == AnalysisMode.LIKE))) - { - { - // text and ml text need locale - IndexTokenisationMode tm = propertyDef.getIndexTokenisationMode(); - if ((tm != null) && (tm == IndexTokenisationMode.BOTH)) - { - textFieldName = textFieldName + "." + locale + ".sort"; - } - - } - } - - boolean lowercaseExpandedTerms = getLowercaseExpandedTerms(); - try - { - switch (tokenisationMode) - { - case BOTH: - switch (analysisMode) - { - default: - case DEFAULT: - case TOKENISE: - addLocaleSpecificTokenisedMLOrTextAttribute(queryText, subQueryBuilder, analysisMode, luceneFunction, booleanQuery, locale, textFieldName); - break; - case IDENTIFIER: - case FUZZY: - case PREFIX: - case WILD: - case LIKE: - setLowercaseExpandedTerms(false); - addLocaleSpecificUntokenisedMLOrTextAttribute(field, queryText, subQueryBuilder, analysisMode, luceneFunction, booleanQuery, mlAnalysisMode, locale, - textFieldName); - break; - } - break; - case FALSE: - setLowercaseExpandedTerms(false); - addLocaleSpecificUntokenisedMLOrTextAttribute(field, queryText, subQueryBuilder, analysisMode, luceneFunction, booleanQuery, mlAnalysisMode, locale, - textFieldName); - break; - case TRUE: - default: - switch (analysisMode) - { - case DEFAULT: - case TOKENISE: - case IDENTIFIER: - addLocaleSpecificTokenisedMLOrTextAttribute(queryText, subQueryBuilder, analysisMode, luceneFunction, booleanQuery, locale, expandedFieldName); - break; - case FUZZY: - case PREFIX: - case WILD: - case LIKE: - addLocaleSpecificUntokenisedMLOrTextAttribute(field, queryText, subQueryBuilder, analysisMode, luceneFunction, booleanQuery, mlAnalysisMode, locale, - textFieldName); - break; - } - break; - } - } - finally - { - setLowercaseExpandedTerms(lowercaseExpandedTerms); - } - - } - return booleanQuery; - } - else - { - // Date does not support like - if ((propertyDef != null) && (propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME))) - { - if (analysisMode == AnalysisMode.LIKE) - { - throw new UnsupportedOperationException("Wild cards are not supported for the datetime type"); - } - } - - // Sort and id is only special for MLText, text, and content - // Dates are not special in this case - Query query = subQueryBuilder.getQuery(expandedFieldName, queryText, AnalysisMode.DEFAULT, luceneFunction); - if (query != null) - { - return query; - } - else - { - return new TermQuery(new Term("NO_TOKENS", "__")); - } - } - } - - private void addLocaleSpecificUntokenisedMLOrTextAttribute(String sourceField, String queryText, SubQuery subQueryBuilder, AnalysisMode analysisMode, - LuceneFunction luceneFunction, BooleanQuery booleanQuery, MLAnalysisMode mlAnalysisMode, Locale locale, String actualField) throws ParseException - { - - String termText = queryText; - if (locale.toString().length() > 0) - { - termText = "{" + locale + "}" + queryText; - } - Query subQuery = subQueryBuilder.getQuery(actualField, termText, analysisMode, luceneFunction); - booleanQuery.add(subQuery, Occur.SHOULD); - - if (booleanQuery.getClauses().length == 0) - { - booleanQuery.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - - private void addLocaleSpecificTokenisedMLOrTextAttribute(String queryText, SubQuery subQueryBuilder, AnalysisMode analysisMode, LuceneFunction luceneFunction, - BooleanQuery booleanQuery, Locale locale, String actualField) throws ParseException - { - StringBuilder builder = new StringBuilder(queryText.length() + 10); - builder.append("\u0000").append(locale.toString()).append("\u0000").append(queryText); - Query subQuery = subQueryBuilder.getQuery(actualField, builder.toString(), analysisMode, luceneFunction); - if (subQuery != null) - { - booleanQuery.add(subQuery, Occur.SHOULD); - } - else - { - booleanQuery.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - - private Query functionQueryBuilder(String expandedFieldName, QName propertyQName, PropertyDefinition propertyDef, IndexTokenisationMode tokenisationMode, String queryText, - LuceneFunction luceneFunction) throws ParseException - { - - // Mime type - if (expandedFieldName.endsWith(".mimetype")) - { - if ((propertyDef != null) && (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))) - { - throw new UnsupportedOperationException("Lucene Function"); - } - - } - else if (expandedFieldName.endsWith(".size")) - { - if ((propertyDef != null) && (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))) - { - throw new UnsupportedOperationException("Lucene Function"); - } - - } - else if (expandedFieldName.endsWith(".locale")) - { - if ((propertyDef != null) && (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))) - { - throw new UnsupportedOperationException("Lucene Function"); - } - - } - - // Already in expanded form - - // ML - - if ((propertyDef != null) && (propertyDef.getDataType().getName().equals(DataTypeDefinition.MLTEXT))) - { - // Build a sub query for each locale and or the results together - the analysis will take care of - // cross language matching for each entry - BooleanQuery booleanQuery = new BooleanQuery(); - MLAnalysisMode mlAnalysisMode = searchParameters.getMlAnalaysisMode() == null ? config.getDefaultMLSearchAnalysisMode() : searchParameters.getMlAnalaysisMode(); - List locales = searchParameters.getLocales(); - List expandedLocales = new ArrayList(); - for (Locale locale : (((locales == null) || (locales.size() == 0)) ? Collections.singletonList(I18NUtil.getLocale()) : locales)) - { - expandedLocales.addAll(MLAnalysisMode.getLocales(mlAnalysisMode, locale, false)); - } - for (Locale locale : (((expandedLocales == null) || (expandedLocales.size() == 0)) ? Collections.singletonList(I18NUtil.getLocale()) : expandedLocales)) - { - String mlFieldName = expandedFieldName; - - if (tokenisationMode == IndexTokenisationMode.BOTH) - { - mlFieldName = mlFieldName + "." + locale + ".sort"; - } - - addLocaleSpecificUntokenisedMLOrTextFunction(expandedFieldName, queryText, luceneFunction, booleanQuery, mlAnalysisMode, locale, mlFieldName); - - } - return booleanQuery; - } - // Content - else if ((propertyDef != null) && (propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT))) - { - throw new UnsupportedOperationException("Lucene functions not supported for content"); - } - else if ((propertyDef != null) && (propertyDef.getDataType().getName().equals(DataTypeDefinition.TEXT))) - { - if (propertyQName.equals(ContentModel.PROP_USER_USERNAME) || propertyQName.equals(ContentModel.PROP_USERNAME) || propertyQName.equals(ContentModel.PROP_AUTHORITY_NAME)) - { - throw new UnsupportedOperationException("Functions are not supported agaisnt special text fields"); - } - - BooleanQuery booleanQuery = new BooleanQuery(); - MLAnalysisMode mlAnalysisMode = searchParameters.getMlAnalaysisMode() == null ? config.getDefaultMLSearchAnalysisMode() : searchParameters.getMlAnalaysisMode(); - List locales = searchParameters.getLocales(); - List expandedLocales = new ArrayList(); - for (Locale locale : (((locales == null) || (locales.size() == 0)) ? Collections.singletonList(I18NUtil.getLocale()) : locales)) - { - expandedLocales.addAll(MLAnalysisMode.getLocales(mlAnalysisMode, locale, false)); - } - for (Locale locale : (((expandedLocales == null) || (expandedLocales.size() == 0)) ? Collections.singletonList(I18NUtil.getLocale()) : expandedLocales)) - { - String textFieldName = expandedFieldName; - - if (tokenisationMode == IndexTokenisationMode.BOTH) - { - textFieldName = textFieldName + "." + locale + ".sort"; - } - - addLocaleSpecificUntokenisedMLOrTextFunction(expandedFieldName, queryText, luceneFunction, booleanQuery, mlAnalysisMode, locale, textFieldName); - - } - return booleanQuery; - } - else - { - throw new UnsupportedOperationException("Lucene Function"); - } - } - - private void addLocaleSpecificUntokenisedMLOrTextFunction(String expandedFieldName, String queryText, LuceneFunction luceneFunction, BooleanQuery booleanQuery, - MLAnalysisMode mlAnalysisMode, Locale locale, String textFieldName) - { - String termText = queryText; - if (locale.toString().length() > 0) - { - termText = "{" + locale + "}" + queryText; - } - Query subQuery = buildFunctionQuery(textFieldName, termText, luceneFunction); - booleanQuery.add(subQuery, Occur.SHOULD); - - if (booleanQuery.getClauses().length == 0) - { - booleanQuery.add(new TermQuery(new Term("NO_TOKENS", "__")), Occur.SHOULD); - } - } - - private Query buildFunctionQuery(String expandedFieldName, String termText, LuceneFunction luceneFunction) - { - String testText = termText; - if (termText.startsWith("{")) - { - int index = termText.indexOf("}"); - testText = termText.substring(index + 1); - } - switch (luceneFunction) - { - case LOWER: - if (testText.equals(testText.toLowerCase())) - { - return new CaseInsensitiveFieldQuery(new Term(expandedFieldName, termText)); - } - else - { - // No match - return new TermQuery(new Term("NO_TOKENS", "__")); - } - case UPPER: - if (testText.equals(testText.toUpperCase())) - { - return new CaseInsensitiveFieldQuery(new Term(expandedFieldName, termText)); - } - else - { - // No match - return new TermQuery(new Term("NO_TOKENS", "__")); - } - default: - throw new UnsupportedOperationException("Unsupported Lucene Function " + luceneFunction); - - } - } - - public static void main(String[] args) throws ParseException, java.text.ParseException - { - Query query; - - Calendar start = Calendar.getInstance(); - Calendar end = Calendar.getInstance(); - SimpleDateFormat df = CachingDateFormat.getDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", false); - - Date date = df.parse("2007-11-30T22:58:58.998"); - System.out.println(date); - start.setTime(date); - System.out.println(start); - - date = df.parse("2008-01-01T03:00:01.002"); - System.out.println(date); - end.setTime(date); - System.out.println(end); - - // start.set(Calendar.YEAR, start.getMinimum(Calendar.YEAR)); - // start.set(Calendar.DAY_OF_YEAR, start.getMinimum(Calendar.DAY_OF_YEAR)); - // start.set(Calendar.HOUR_OF_DAY, start.getMinimum(Calendar.HOUR_OF_DAY)); - // start.set(Calendar.MINUTE, start.getMinimum(Calendar.MINUTE)); - // start.set(Calendar.SECOND, start.getMinimum(Calendar.SECOND)); - // start.set(Calendar.MILLISECOND, start.getMinimum(Calendar.MILLISECOND)); - LuceneQueryParser lqp = new LuceneQueryParser(null, null); - query = lqp.buildDateTimeRange("TEST", start, end, false, false); - System.out.println("Query is " + query); - } - - @Override - public LuceneAnalyser getAnalyzer() - { - return luceneAnalyser; - } - -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneXPathHandler.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneXPathHandler.java deleted file mode 100644 index 650601f14b..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneXPathHandler.java +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene; - -import java.util.ArrayList; - -import org.alfresco.repo.search.impl.lucene.analysis.PathTokenFilter; -import org.alfresco.repo.search.impl.lucene.query.AbsoluteStructuredFieldPosition; -import org.alfresco.repo.search.impl.lucene.query.DescendantAndSelfStructuredFieldPosition; -import org.alfresco.repo.search.impl.lucene.query.PathQuery; -import org.alfresco.repo.search.impl.lucene.query.RelativeStructuredFieldPosition; -import org.alfresco.repo.search.impl.lucene.query.SelfAxisStructuredFieldPosition; -import org.alfresco.repo.search.impl.lucene.query.StructuredFieldPosition; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.namespace.NamespacePrefixResolver; -import org.saxpath.Axis; -import org.saxpath.Operator; -import org.saxpath.SAXPathException; -import org.saxpath.XPathHandler; -/** - * XPATH handler for lucene - currently only does basic paths - * - * @author andyh - * - */ -public class LuceneXPathHandler implements XPathHandler -{ - private PathQuery query; - - private boolean isAbsolutePath = true; - - int absolutePosition = 0; - - private NamespacePrefixResolver namespacePrefixResolver; - - private DictionaryService dictionaryService; - - /** - * - */ - public LuceneXPathHandler() - { - super(); - } - - /** - * Get the resulting query - * @return - the query - */ - public PathQuery getQuery() - { - return this.query; - } - - public void endAbsoluteLocationPath() throws SAXPathException - { - // No action - } - - public void endAdditiveExpr(int op) throws SAXPathException - { - switch (op) - { - case Operator.NO_OP: - break; - case Operator.ADD: - case Operator.SUBTRACT: - throw new UnsupportedOperationException(); - default: - throw new UnsupportedOperationException("Unknown operation " + op); - } - } - - public void endAllNodeStep() throws SAXPathException - { - // Nothing to do - // Todo: Predicates - } - - public void endAndExpr(boolean create) throws SAXPathException - { - if (create) - { - throw new UnsupportedOperationException(); - } - } - - public void endCommentNodeStep() throws SAXPathException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public void endEqualityExpr(int op) throws SAXPathException - { - switch (op) - { - case Operator.NO_OP: - break; - case Operator.EQUALS: - case Operator.NOT_EQUALS: - throw new UnsupportedOperationException(); - default: - throw new UnsupportedOperationException("Unknown operation " + op); - } - } - - public void endFilterExpr() throws SAXPathException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public void endFunction() throws SAXPathException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public void endMultiplicativeExpr(int op) throws SAXPathException - { - switch (op) - { - case Operator.NO_OP: - break; - case Operator.MULTIPLY: - case Operator.DIV: - case Operator.MOD: - throw new UnsupportedOperationException(); - default: - throw new UnsupportedOperationException("Unknown operation " + op); - } - } - - public void endNameStep() throws SAXPathException - { - // Do nothing at the moment - // Could have repdicates - } - - public void endOrExpr(boolean create) throws SAXPathException - { - if (create) - { - throw new UnsupportedOperationException(); - } - } - - public void endPathExpr() throws SAXPathException - { - // Already built - } - - public void endPredicate() throws SAXPathException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public void endProcessingInstructionNodeStep() throws SAXPathException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public void endRelationalExpr(int op) throws SAXPathException - { - switch (op) - { - case Operator.NO_OP: - break; - case Operator.GREATER_THAN: - case Operator.GREATER_THAN_EQUALS: - case Operator.LESS_THAN: - case Operator.LESS_THAN_EQUALS: - throw new UnsupportedOperationException(); - default: - throw new UnsupportedOperationException("Unknown operation " + op); - } - } - - public void endRelativeLocationPath() throws SAXPathException - { - // No action - } - - public void endTextNodeStep() throws SAXPathException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public void endUnaryExpr(int op) throws SAXPathException - { - switch (op) - { - case Operator.NO_OP: - break; - case Operator.NEGATIVE: - throw new UnsupportedOperationException(); - default: - throw new UnsupportedOperationException("Unknown operation " + op); - } - } - - public void endUnionExpr(boolean create) throws SAXPathException - { - if (create) - { - throw new UnsupportedOperationException(); - } - } - - public void endXPath() throws SAXPathException - { - // Do nothing at the moment - } - - public void literal(String arg0) throws SAXPathException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public void number(double arg0) throws SAXPathException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public void number(int arg0) throws SAXPathException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public void startAbsoluteLocationPath() throws SAXPathException - { - if (!isAbsolutePath) - { - throw new IllegalStateException(); - } - - } - - public void startAdditiveExpr() throws SAXPathException - { - // Do nothing at the moment - } - - public void startAllNodeStep(int axis) throws SAXPathException - { - switch (axis) - { - case Axis.CHILD: - if (isAbsolutePath) - { - // addAbsolute(null, null); - // We can always do relative stuff - addRelative(null, null); - } - else - { - addRelative(null, null); - } - break; - case Axis.DESCENDANT_OR_SELF: - query.appendQuery(getArrayList(new DescendantAndSelfStructuredFieldPosition(), new DescendantAndSelfStructuredFieldPosition())); - break; - case Axis.SELF: - query.appendQuery(getArrayList(new SelfAxisStructuredFieldPosition(), new SelfAxisStructuredFieldPosition())); - break; - default: - throw new UnsupportedOperationException(); - } - } - - private ArrayList getArrayList(StructuredFieldPosition one, StructuredFieldPosition two) - { - ArrayList answer = new ArrayList(2); - answer.add(one); - answer.add(two); - return answer; - } - - public void startAndExpr() throws SAXPathException - { - // Do nothing - } - - public void startCommentNodeStep(int arg0) throws SAXPathException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public void startEqualityExpr() throws SAXPathException - { - // Do nothing - } - - public void startFilterExpr() throws SAXPathException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public void startFunction(String arg0, String arg1) throws SAXPathException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public void startMultiplicativeExpr() throws SAXPathException - { - // Do nothing at the moment - } - - public void startNameStep(int axis, String nameSpace, String localName) throws SAXPathException - { - switch (axis) - { - case Axis.CHILD: - if (isAbsolutePath) - { - // addAbsolute(nameSpace, localName); - // we can always do relative stuff - addRelative(nameSpace, localName); - } - else - { - addRelative(nameSpace, localName); - } - break; - default: - throw new UnsupportedOperationException(); - } - - } - - @SuppressWarnings("unused") - private void addAbsolute(String nameSpace, String localName) - { - ArrayList answer = new ArrayList(2); - // TODO: Resolve name space - absolutePosition++; - if ((nameSpace == null) || (nameSpace.length() == 0)) - { - - if(localName.equals("*")) - { - answer.add(new RelativeStructuredFieldPosition("*")); - } - else if (namespacePrefixResolver.getNamespaceURI("") == null) - { - answer.add(new AbsoluteStructuredFieldPosition(PathTokenFilter.NO_NS_TOKEN_TEXT, absolutePosition)); - } - else - { - answer.add(new AbsoluteStructuredFieldPosition(namespacePrefixResolver.getNamespaceURI(""), absolutePosition)); - } - - } - else - { - answer.add(new AbsoluteStructuredFieldPosition(namespacePrefixResolver.getNamespaceURI(nameSpace), absolutePosition)); - } - - absolutePosition++; - if ((localName == null) || (localName.length() == 0)) - { - answer.add(new AbsoluteStructuredFieldPosition("*", absolutePosition)); - } - else - { - answer.add(new AbsoluteStructuredFieldPosition(localName, absolutePosition)); - } - query.appendQuery(answer); - - } - - private void addRelative(String nameSpace, String localName) - { - ArrayList answer = new ArrayList(2); - if ((nameSpace == null) || (nameSpace.length() == 0)) - { - if(localName.equals("*")) - { - answer.add(new RelativeStructuredFieldPosition("*")); - } - else if (namespacePrefixResolver.getNamespaceURI("") == null) - { - answer.add(new RelativeStructuredFieldPosition(PathTokenFilter.NO_NS_TOKEN_TEXT)); - } - else if (namespacePrefixResolver.getNamespaceURI("").equals("")) - { - answer.add(new RelativeStructuredFieldPosition(PathTokenFilter.NO_NS_TOKEN_TEXT)); - } - else - { - answer.add(new RelativeStructuredFieldPosition(namespacePrefixResolver.getNamespaceURI(""))); - } - } - else - { - answer.add(new RelativeStructuredFieldPosition(namespacePrefixResolver.getNamespaceURI(nameSpace))); - } - - if ((localName == null) || (localName.length() == 0)) - { - answer.add(new RelativeStructuredFieldPosition("*")); - } - else - { - answer.add(new RelativeStructuredFieldPosition(localName)); - } - query.appendQuery(answer); - } - - public void startOrExpr() throws SAXPathException - { - // Do nothing at the moment - } - - public void startPathExpr() throws SAXPathException - { - // Just need one! - } - - public void startPredicate() throws SAXPathException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public void startProcessingInstructionNodeStep(int arg0, String arg1) throws SAXPathException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public void startRelationalExpr() throws SAXPathException - { - // Do nothing at the moment - } - - public void startRelativeLocationPath() throws SAXPathException - { - isAbsolutePath = false; - } - - public void startTextNodeStep(int arg0) throws SAXPathException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public void startUnaryExpr() throws SAXPathException - { - // Do nothing for now - } - - public void startUnionExpr() throws SAXPathException - { - // Do nothing at the moment - } - - public void startXPath() throws SAXPathException - { - query = new PathQuery(dictionaryService); - } - - public void variableReference(String uri, String localName) throws SAXPathException - { - - } - - /** - * Set the service to resolve name space prefixes - * @param namespacePrefixResolver - */ - public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver) - { - this.namespacePrefixResolver = namespacePrefixResolver; - } - - /** - * Set the dictionary service. - * @param dictionaryService - */ - public void setDictionaryService(DictionaryService dictionaryService) - { - this.dictionaryService = dictionaryService; - } - - - - -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/index/CachingIndexReader.java b/source/java/org/alfresco/repo/search/impl/lucene/index/CachingIndexReader.java deleted file mode 100644 index 3df2389078..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/index/CachingIndexReader.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.index; - -import java.io.IOException; - -import org.apache.lucene.index.TermDocs; - -/** - * - * @author andyh - * - */ -public interface CachingIndexReader -{ - public String getId(int n) throws IOException; - - public String getPathLinkId(int n) throws IOException; - - public String[] getIds(int n) throws IOException; - - public String getIsCategory(int n) throws IOException; - - public String getPath(int n) throws IOException; - - public String[] getParents(int n) throws IOException; - - public String[] getLinkAspects(int n) throws IOException; - - public String getType(int n) throws IOException; - - public TermDocs getNodeDocs() throws IOException; - -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/AbsoluteStructuredFieldPosition.java b/source/java/org/alfresco/repo/search/impl/lucene/query/AbsoluteStructuredFieldPosition.java deleted file mode 100644 index a1f1300d2d..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/AbsoluteStructuredFieldPosition.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import java.io.IOException; - -/** - * This class patches a term at a specified location. - * - * @author andyh - */ -public class AbsoluteStructuredFieldPosition extends AbstractStructuredFieldPosition -{ - - int requiredPosition; - - /** - * Search for a term at the specified position. - */ - - public AbsoluteStructuredFieldPosition(String termText, int position) - { - super(termText, true, true); - this.requiredPosition = position; - } - - /* - * (non-Javadoc) - * - * @see org.alfresco.lucene.extensions.StructuredFieldPosition#matches(int, - * org.apache.lucene.index.TermPositions) - */ - public int matches(int start, int end, int offset) throws IOException - { - if (offset >= requiredPosition) - { - return -1; - } - - if (getCachingTermPositions() != null) - { - // Doing "termText" - getCachingTermPositions().reset(); - int count = getCachingTermPositions().freq(); - int realPosition = 0; - int adjustedPosition = 0; - for (int i = 0; i < count; i++) - { - realPosition = getCachingTermPositions().nextPosition(); - adjustedPosition = realPosition - start; - if ((end != -1) && (realPosition > end)) - { - return -1; - } - if (adjustedPosition > requiredPosition) - { - return -1; - } - if (adjustedPosition == requiredPosition) - { - return adjustedPosition; - } - - } - } - else - { - // Doing "*" - if ((offset + 1) == requiredPosition) - { - return offset + 1; - } - } - return -1; - - } - - /* - * (non-Javadoc) - * - * @see org.alfresco.lucene.extensions.StructuredFieldPosition#getPosition() - */ - public int getPosition() - { - return requiredPosition; - } - - public String getDescription() - { - return "Absolute Named child"; - } -} \ No newline at end of file diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/AbstractStructuredFieldPosition.java b/source/java/org/alfresco/repo/search/impl/lucene/query/AbstractStructuredFieldPosition.java deleted file mode 100644 index 6ea7037de5..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/AbstractStructuredFieldPosition.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -public abstract class AbstractStructuredFieldPosition implements StructuredFieldPosition -{ - private String termText; - - private boolean isTerminal; - - private boolean isAbsolute; - - private CachingTermPositions tps; - - public AbstractStructuredFieldPosition(String termText, boolean isTerminal, boolean isAbsolute) - { - super(); - this.termText = termText; - this.isTerminal = isTerminal; - this.isAbsolute = isAbsolute; - } - - public boolean isTerminal() - { - return isTerminal; - } - - protected void setTerminal(boolean isTerminal) - { - this.isTerminal = isTerminal; - } - - public boolean isAbsolute() - { - return isAbsolute; - } - - public boolean isRelative() - { - return !isAbsolute; - } - - public String getTermText() - { - return termText; - } - - public int getPosition() - { - return -1; - } - - public void setCachingTermPositions(CachingTermPositions tps) - { - this.tps = tps; - } - - public CachingTermPositions getCachingTermPositions() - { - return this.tps; - } - - - - public boolean allowsLinkingBySelf() - { - return false; - } - - public boolean allowslinkingByParent() - { - return true; - } - - public boolean linkParent() - { - return true; - } - - public boolean linkSelf() - { - return false; - } - - public String toString() - { - StringBuffer buffer = new StringBuffer(256); - buffer.append(getDescription()); - buffer.append("<"+getTermText()+"> at "+getPosition()); - buffer.append(" Terminal = "+isTerminal()); - buffer.append(" Absolute = "+isAbsolute()); - return buffer.toString(); - } - - public abstract String getDescription(); - - public boolean isDescendant() - { - return false; - } - - public boolean matchesAll() - { - return getCachingTermPositions() == null; - } - - - - -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/AnyStructuredFieldPosition.java b/source/java/org/alfresco/repo/search/impl/lucene/query/AnyStructuredFieldPosition.java deleted file mode 100644 index d4db787fff..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/AnyStructuredFieldPosition.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import java.io.IOException; - -/** - * @author andyh - * - * TODO To change the template for this generated type comment go to Window - - * Preferences - Java - Code Style - Code Templates - */ -public class AnyStructuredFieldPosition extends AbstractStructuredFieldPosition -{ - - /** - * - */ - public AnyStructuredFieldPosition(String termText) - { - super(termText, true, false); - if (termText == null) - { - setTerminal(false); - } - } - - public AnyStructuredFieldPosition() - { - super(null, false, false); - } - - /* - * (non-Javadoc) - * - * @see org.alfresco.lucene.extensions.StructuredFieldPosition#matches(int, - * int, org.apache.lucene.index.TermPositions) - */ - public int matches(int start, int end, int offset) throws IOException - { - // we are doing //name - if (getCachingTermPositions() != null) - { - setTerminal(true); - int realPosition = 0; - int adjustedPosition = 0; - getCachingTermPositions().reset(); - int count = getCachingTermPositions().freq(); - for (int i = 0; i < count; i++) - { - realPosition = getCachingTermPositions().nextPosition(); - adjustedPosition = realPosition - start; - if ((end != -1) && (realPosition > end)) - { - return -1; - } - if (adjustedPosition > offset) - { - return adjustedPosition; - } - } - } - else - { - // we are doing // - setTerminal(false); - return offset; - } - return -1; - } - - public String getDescription() - { - return "Any"; - } - -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/CachingTermPositions.java b/source/java/org/alfresco/repo/search/impl/lucene/query/CachingTermPositions.java deleted file mode 100644 index 664bf320b7..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/CachingTermPositions.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import java.io.IOException; - -import org.apache.lucene.index.Term; -import org.apache.lucene.index.TermEnum; -import org.apache.lucene.index.TermPositions; - -/** - * @author andyh - * - * TODO To change the template for this generated type comment go to Window - - * Preferences - Java - Code Style - Code Templates - */ -public class CachingTermPositions implements TermPositions -{ - int[] results; - - int position = -1; - - int last = -1; - - TermPositions delegate; - - CachingTermPositions(TermPositions delegate) - { - this.delegate = delegate; - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.index.TermPositions#nextPosition() - */ - public int nextPosition() throws IOException - { - if (results == null) - { - results = new int[freq()]; - } - position++; - if (last < position) - { - results[position] = delegate.nextPosition(); - last = position; - } - return results[position]; - - } - - public void reset() - { - position = -1; - } - - private void clear() - { - position = -1; - last = -1; - results = null; - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.index.TermDocs#seek(org.apache.lucene.index.Term) - */ - public void seek(Term term) throws IOException - { - delegate.seek(term); - clear(); - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.index.TermDocs#seek(org.apache.lucene.index.TermEnum) - */ - public void seek(TermEnum termEnum) throws IOException - { - delegate.seek(termEnum); - clear(); - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.index.TermDocs#doc() - */ - public int doc() - { - return delegate.doc(); - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.index.TermDocs#freq() - */ - public int freq() - { - return delegate.freq(); - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.index.TermDocs#next() - */ - public boolean next() throws IOException - { - if (delegate.next()) - { - clear(); - return true; - } - else - { - return false; - } - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.index.TermDocs#read(int[], int[]) - */ - public int read(int[] docs, int[] freqs) throws IOException - { - int answer = delegate.read(docs, freqs); - clear(); - return answer; - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.index.TermDocs#skipTo(int) - */ - public boolean skipTo(int target) throws IOException - { - if (delegate.skipTo(target)) - { - clear(); - return true; - } - else - { - return false; - } - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.index.TermDocs#close() - */ - public void close() throws IOException - { - delegate.close(); - clear(); - } - - public byte[] getPayload(byte[] data, int offset) throws IOException - { - return delegate.getPayload(data, offset); - } - - public int getPayloadLength() - { - return delegate.getPayloadLength(); - } - - public boolean isPayloadAvailable() - { - return delegate.isPayloadAvailable(); - } - -} \ No newline at end of file diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveFieldQuery.java b/source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveFieldQuery.java deleted file mode 100644 index f23e39e831..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveFieldQuery.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import java.io.IOException; - -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.search.FilteredTermEnum; -import org.apache.lucene.search.MultiTermQuery; - -/** - * Perform a case insensitive match against a field - * - * @author andyh - * - */ -public class CaseInsensitiveFieldQuery extends MultiTermQuery -{ - /** - * - */ - private static final long serialVersionUID = -2570803495329346982L; - - /** - * @param term - the term for the match - */ - public CaseInsensitiveFieldQuery(Term term) - { - super(term); - } - - @Override - protected FilteredTermEnum getEnum(IndexReader reader) throws IOException - { - Term term = new Term(getTerm().field(), getTerm().text()); - return new CaseInsensitiveTermEnum(reader, term); - } - -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveFieldRangeQuery.java b/source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveFieldRangeQuery.java deleted file mode 100644 index 833bec3a68..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveFieldRangeQuery.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import java.io.IOException; - -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.search.FilteredTermEnum; -import org.apache.lucene.search.MultiTermQuery; - -/** - * Find terms that match a range ignoring case - * - * @author andyh - */ -public class CaseInsensitiveFieldRangeQuery extends MultiTermQuery -{ - /** - * - */ - private static final long serialVersionUID = -5859977841901861122L; - - String expandedFieldName; - - String lowerTermText; - - String upperTermText; - - boolean includeLower; - - boolean includeUpper; - - /** - * @param expandedFieldName - - * field - * @param lowerTermText - - * upper range value - * @param upperTermText - - * lower range value - * @param includeLower - - * include the lower value - * @param includeUpper - - * include the upper value - */ - public CaseInsensitiveFieldRangeQuery(String expandedFieldName, String lowerTermText, String upperTermText, boolean includeLower, boolean includeUpper) - { - super(new Term(expandedFieldName, "")); - this.expandedFieldName = expandedFieldName; - this.lowerTermText = lowerTermText; - this.upperTermText = upperTermText; - this.includeLower = includeLower; - this.includeUpper = includeUpper; - } - - @Override - protected FilteredTermEnum getEnum(IndexReader reader) throws IOException - { - return new CaseInsensitiveTermRangeEnum(reader, expandedFieldName, lowerTermText, upperTermText, includeLower, includeUpper); - } - -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveTermEnum.java b/source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveTermEnum.java deleted file mode 100644 index df9e2d81e3..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveTermEnum.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import java.io.IOException; - -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.search.FilteredTermEnum; - -/** - * A term enum to find case insensitive matches - used for Upper and Lower - * - * @author andyh - */ -public class CaseInsensitiveTermEnum extends FilteredTermEnum -{ - private String field = ""; - - private boolean endEnum = false; - - private String text; - - /** - * @param reader = - * the index reader - * @param term - - * the term to match - * @throws IOException - */ - public CaseInsensitiveTermEnum(IndexReader reader, Term term) throws IOException - { - super(); - field = term.field(); - text = term.text(); - // position at the start - we could do slightly better - setEnum(reader.terms(new Term(term.field(), ""))); - } - - @Override - public float difference() - { - return 1.0f; - } - - @Override - protected boolean endEnum() - { - return endEnum; - } - - @Override - protected boolean termCompare(Term term) - { - if (field.equals(term.field())) - { - String searchText = term.text(); - return searchText.equalsIgnoreCase(text); - } - endEnum = true; - return false; - } - -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveTermRangeEnum.java b/source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveTermRangeEnum.java deleted file mode 100644 index 342bd4649d..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/CaseInsensitiveTermRangeEnum.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import java.io.IOException; - -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.search.FilteredTermEnum; - -/** - * A term enum that finds terms that lie with in some range ignoring case - * - * @author andyh - */ -public class CaseInsensitiveTermRangeEnum extends FilteredTermEnum -{ - - private boolean endEnum = false; - - String expandedFieldName; - - String lowerTermText; - - String upperTermText; - - boolean includeLower; - - boolean includeUpper; - - /** - * @param reader - * the index reader - * @param expandedFieldName - - * field - * @param lowerTermText - - * upper range value - * @param upperTermText - - * lower range value - * @param includeLower - - * include the lower value - * @param includeUpper - - * include the upper value - * @throws IOException - */ - public CaseInsensitiveTermRangeEnum(IndexReader reader, String expandedFieldName, String lowerTermText, String upperTermText, boolean includeLower, boolean includeUpper) - throws IOException - { - super(); - this.expandedFieldName = expandedFieldName; - this.lowerTermText = lowerTermText.toLowerCase(); - this.upperTermText = upperTermText.toLowerCase(); - this.includeLower = includeLower; - this.includeUpper = includeUpper; - - setEnum(reader.terms(new Term(expandedFieldName, ""))); - } - - @Override - public float difference() - { - return 1.0f; - } - - @Override - protected boolean endEnum() - { - return endEnum; - } - - @Override - protected boolean termCompare(Term term) - { - if (expandedFieldName.equals(term.field())) - { - String searchText = term.text().toLowerCase(); - return checkLower(searchText) && checkUpper(searchText); - } - endEnum = true; - return false; - } - - private boolean checkLower(String searchText) - { - if (includeLower) - { - return (lowerTermText.compareTo(searchText) <= 0); - } - else - { - return (lowerTermText.compareTo(searchText) < 0); - } - } - - private boolean checkUpper(String searchText) - { - if (includeUpper) - { - return (upperTermText.compareTo(searchText) >= 0); - } - else - { - return (upperTermText.compareTo(searchText) > 0); - } - } - -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/ContainerScorer.java b/source/java/org/alfresco/repo/search/impl/lucene/query/ContainerScorer.java deleted file mode 100644 index acb14e075c..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/ContainerScorer.java +++ /dev/null @@ -1,555 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import java.io.IOException; - -import org.apache.lucene.index.TermPositions; -import org.apache.lucene.search.Explanation; -import org.apache.lucene.search.Scorer; -import org.apache.lucene.search.Similarity; -import org.apache.lucene.search.Weight; - -/** - * The scorer for structured field queries. - * - * A document either matches or it does not, there for the frequency is reported - * as 0.0f or 1.0. - * - * - * - * @author andyh - */ -public class ContainerScorer extends Scorer -{ - // Unused - Weight weight; - - // Positions of documents with multiple structure elements - // e.g have mutiple paths, multiple categories or multiples entries in the - // same category - TermPositions root; - - // The Field positions that describe the structure we are trying to match - StructuredFieldPosition[] positions; - - // Unused at the moment - byte[] norms; - - // The minium document found so far - int min = 0; - - // The max document found so far - int max = 0; - - // The next root doc - // -1 and it has gone off the end - int rootDoc = 0; - - // Are there potentially more documents - boolean more = true; - - // The frequency of the terms in the doc (0.0f or 1.0f) - float freq = 0.0f; - - // A term position to find all container entries (there is no better way of finding the set of rquired containers) - private TermPositions containers; - - /** - * The arguments here follow the same pattern as used by the PhraseQuery. - * (It has the same unused arguments) - * - * @param weight - - * curently unsued - * @param tps - - * the term positions for the terms we are trying to find - * @param root - - * the term positions for documents with multiple entries - this - * may be null, or contain no matches - it specifies those things - * that appear under multiple categories etc. - * @param positions - - * the structured field positions - where terms should appear - * @param similarity - - * used in the abstract scorer implementation - * @param norms - - * unused - */ - public ContainerScorer(Weight weight, TermPositions root, StructuredFieldPosition[] positions, TermPositions containers, Similarity similarity, byte[] norms) - { - super(similarity); - this.weight = weight; - this.positions = positions; - this.norms = norms; - this.root = root; - this.containers = containers; - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.search.Scorer#next() - */ - public boolean next() throws IOException - { - // If there is no filtering - if (allContainers()) - { - // containers and roots must be in sync or the index is broken - while (more) - { - if (containers.next() && root.next()) - { - if (check(0, root.nextPosition())) - { - return true; - } - } - else - { - more = false; - return false; - } - } - } - - if (!more) - { - // One of the search terms has no more docuements - return false; - } - - if (max == 0) - { - // We need to initialise - // Just do a next on all terms and check if the first doc matches - doNextOnAll(); - if (found()) - { - return true; - } - // drop through to the normal find sequence - } - - return findNext(); - } - - /** - * Are we looking for all containers? - * If there are no positions we must have a better filter - * - * @return - */ - private boolean allContainers() - { - if (positions.length == 0) - { - return true; - } - for (StructuredFieldPosition sfp : positions) - { - if (sfp.getCachingTermPositions() != null) - { - return false; - } - } - return true; - } - - /** - * @return - * @throws IOException - */ - private boolean findNext() throws IOException - { - // Move to the next document - - while (more) - { - move(); // may set more to false - if (found()) - { - return true; - } - } - - // If we get here we must have no more documents - return false; - } - - /** - * Check if we have found a match - * - * @return - * @throws IOException - */ - - private boolean found() throws IOException - { - // No predicate test if there are no positions - if (positions.length == 0) - { - return true; - } - - // no more documents - no match - if (!more) - { - return false; - } - - // min and max must point to the same document - if (min != max) - { - return false; - } - - if (rootDoc != max) - { - return false; - } - - // We have duplicate entries - suport should be improved but it is not used at the moment - // This shuld work akin to the leaf scorer - // It would compact the index - // The match must be in a known term range - int count = root.freq(); - int start = 0; - int end = -1; - for (int i = 0; i < count; i++) - { - if (i == 0) - { - // First starts at zero - start = 0; - end = root.nextPosition() ; - } - else - { - start = end + 1; - end = root.nextPosition() ; - } - - if (check(start, end)) - { - return true; - } - } - - // We had checks to do and they all failed. - return false; - } - - /* - * We have all documents at the same state. Now we check the positions of - * the terms. - */ - - private boolean check(int start, int end) throws IOException - { - int offset = checkTail(start, end, 0, 0); - // Last match may fail - if (offset == -1) - { - return false; - } - else - { - // Check non // ending patterns end at the end of the available pattern - if (positions[positions.length - 1].isTerminal()) - { - return ((offset+1) == end); - } - else - { - return true; - } - } - } - - /** - * For // type pattern matches we need to test patterns of variable greedyness. - * - * - * @param start - * @param end - * @param currentPosition - * @param currentOffset - * @return - * @throws IOException - */ - private int checkTail(int start, int end, int currentPosition, int currentOffset) throws IOException - { - int offset = currentOffset; - for (int i = currentPosition, l = positions.length; i < l; i++) - { - offset = positions[i].matches(start, end, offset); - if (offset == -1) - { - return -1; - } - if (positions[i].isDescendant()) - { - for (int j = offset; j < end; j++) - { - int newOffset = checkTail(start, end, i + 1, j); - if (newOffset != -1) - { - return newOffset; - } - } - return -1; - } - } - return offset; - } - - /* - * Move to the next position to consider for a match test - */ - - private void move() throws IOException - { - if (min == max) - { - // If we were at a match just do next on all terms - // They all must move on - doNextOnAll(); - } - else - { - // We are in a range - try and skip to the max position on all terms - // Only some need to move on - some may move past the current max and set a new target - skipToMax(); - } - } - - /* - * Go through all the term positions and try and move to next document. Any - * failure measn we have no more. - * - * This can be used at initialisation and when moving away from an existing - * match. - * - * This will set min, max, more and rootDoc - * - */ - private void doNextOnAll() throws IOException - { - // Do the terms - int current; - boolean first = true; - for (int i = 0, l = positions.length; i < l; i++) - { - if (positions[i].getCachingTermPositions() != null) - { - if (positions[i].getCachingTermPositions().next()) - - { - current = positions[i].getCachingTermPositions().doc(); - adjustMinMax(current, first); - first = false; - } - else - { - more = false; - return; - } - } - } - - // Do the root term - it must always exists as the path could well have mutiple entries - // If an entry in the index does not have a root terminal it is broken - if (root.next()) - { - rootDoc = root.doc(); - } - else - { - more = false; - return; - } - if (root.doc() < max) - { - if (root.skipTo(max)) - { - rootDoc = root.doc(); - } - else - { - more = false; - return; - } - } - } - - /* - * Try and skip all those term positions at documents less than the current - * max up to value. This is quite likely to fail and leave us with (min != - * max) but that is OK, we try again. - * - * It is possible that max increases as we process terms, this is OK. We - * just failed to skip to a given value of max and start doing the next. - */ - private void skipToMax() throws IOException - { - // Do the terms - int current; - for (int i = 0, l = positions.length; i < l; i++) - { - if (i == 0) - { - min = max; - } - if (positions[i].getCachingTermPositions() != null) - { - if (positions[i].getCachingTermPositions().doc() < max) - { - if (positions[i].getCachingTermPositions().skipTo(max)) - { - current = positions[i].getCachingTermPositions().doc(); - adjustMinMax(current, false); - } - else - { - more = false; - return; - } - } - } - } - - // Do the root - if (root.doc() < max) - { - if (root.skipTo(max)) - { - rootDoc = root.doc(); - } - else - { - more = false; - return; - } - } - } - - /* - * Adjust the min and max values Convenience boolean to set or adjust the - * minimum. - */ - private void adjustMinMax(int doc, boolean setMin) - { - - if (max < doc) - { - max = doc; - } - - if (setMin) - { - min = doc; - } - else if (min > doc) - { - min = doc; - } - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.search.Scorer#doc() - */ - public int doc() - { - if (allContainers()) - { - return containers.doc(); - } - return max; - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.search.Scorer#score() - */ - public float score() throws IOException - { - return 1.0f; - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.search.Scorer#skipTo(int) - */ - public boolean skipTo(int target) throws IOException - { - if (allContainers()) - { - containers.skipTo(target); - root.skipTo(containers.doc()); // must match - if (check(0, root.nextPosition())) - { - return true; - } - while (more) - { - if (containers.next() && root.next()) - { - if (check(0, root.nextPosition())) - { - return true; - } - } - else - { - more = false; - return false; - } - } - } - - max = target; - return findNext(); - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.search.Scorer#explain(int) - */ - public Explanation explain(int doc) throws IOException - { - // TODO: Work out what a proper explanation would be here? - Explanation tfExplanation = new Explanation(); - - while (next() && doc() < doc) - { - } - - float phraseFreq = (doc() == doc) ? freq : 0.0f; - tfExplanation.setValue(getSimilarity().tf(phraseFreq)); - tfExplanation.setDescription("tf(phraseFreq=" + phraseFreq + ")"); - - return tfExplanation; - } - -} \ No newline at end of file diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/DeltaReader.java b/source/java/org/alfresco/repo/search/impl/lucene/query/DeltaReader.java deleted file mode 100644 index 34b469e512..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/DeltaReader.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import java.io.IOException; -import java.util.Arrays; - -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.MultiReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.index.TermDocs; -import org.apache.lucene.index.TermEnum; -import org.apache.lucene.index.TermPositions; - -public class DeltaReader extends MultiReader -{ - int[][] deletions; - - Boolean hasExclusions = null; - - private IndexReader[] subReaders; - - private int maxDoc = 0; - - private int[] starts; - - public DeltaReader(IndexReader[] readers, int[][] deletions) throws IOException - { - super(readers); - this.deletions = deletions; - initialize(readers); - } - - private void initialize(IndexReader[] subReaders) throws IOException - { - this.subReaders = subReaders; - starts = new int[subReaders.length + 1]; // build starts array - for (int i = 0; i < subReaders.length; i++) - { - starts[i] = maxDoc; - maxDoc += subReaders[i].maxDoc(); // compute maxDocs - } - starts[subReaders.length] = maxDoc; - } - - protected void doCommit() throws IOException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - protected void doDelete(int arg0) throws IOException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - protected void doUndeleteAll() throws IOException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - public boolean hasDeletions() - { - return super.hasDeletions() || hasSearchExclusions(); - } - - private boolean hasSearchExclusions() - { - if (hasExclusions == null) - { - for (int i = 0; i < deletions.length; i++) - { - if (deletions[i].length > 0) - { - hasExclusions = new Boolean(true); - break; - } - } - hasExclusions = new Boolean(false); - } - return hasExclusions.booleanValue(); - } - - public boolean isDeleted(int docNumber) - { - int i = readerIndex(docNumber); - return super.isDeleted(docNumber) || (Arrays.binarySearch(deletions[i], docNumber - starts[i]) != -1); - } - - private int readerIndex(int n) - { // find reader for doc n: - int lo = 0; // search starts array - int hi = subReaders.length - 1; // for first element less - - while (hi >= lo) - { - int mid = (lo + hi) >> 1; - int midValue = starts[mid]; - if (n < midValue) - hi = mid - 1; - else if (n > midValue) - lo = mid + 1; - else - { // found a match - while (mid + 1 < subReaders.length && starts[mid + 1] == midValue) - { - mid++; // scan to last match - } - return mid; - } - } - return hi; - } - - public TermDocs termDocs() throws IOException - { - return new DeletingTermDocs(super.termDocs()); - } - - public TermPositions termPositions() throws IOException - { - // TODO Auto-generated method stub - throw new UnsupportedOperationException(); - } - - private class DeletingTermDocs implements TermDocs - { - TermDocs delegate; - - DeletingTermDocs(TermDocs delegate) - { - super(); - this.delegate = delegate; - } - - public void seek(Term term) throws IOException - { - delegate.seek(term); - } - - public void seek(TermEnum termEnum) throws IOException - { - delegate.seek(termEnum); - } - - public int doc() - { - return delegate.doc(); - } - - public int freq() - { - return delegate.freq(); - } - - public boolean next() throws IOException - { - while (delegate.next()) - { - if (!isDeleted(doc())) - { - return true; - } - } - return false; - } - - public int read(int[] docs, int[] freqs) throws IOException - { - int end; - int deletedCount; - do - { - end = delegate.read(docs, freqs); - if (end == 0) - { - return end; - } - deletedCount = 0; - for (int i = 0; i < end; i++) - { - if (!isDeleted(docs[i])) - { - deletedCount++; - } - } - } - while (end == deletedCount); - // fix up for deleted - int position = 0; - for(int i = 0; i < end; i++) - { - if(!isDeleted(i)) - { - docs[position] = docs[i]; - freqs[position] = freqs[i]; - position++; - } - } - return position; - } - - public boolean skipTo(int docNumber) throws IOException - { - delegate.skipTo(docNumber); - if (!isDeleted(doc())) - { - return true; - } - else - { - return next(); - } - } - - public void close() throws IOException - { - delegate.close(); - } - - } -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/DescendantAndSelfStructuredFieldPosition.java b/source/java/org/alfresco/repo/search/impl/lucene/query/DescendantAndSelfStructuredFieldPosition.java deleted file mode 100644 index a6fc4a10a7..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/DescendantAndSelfStructuredFieldPosition.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -public class DescendantAndSelfStructuredFieldPosition extends AnyStructuredFieldPosition -{ - public DescendantAndSelfStructuredFieldPosition() - { - super(); - } - - public String getDescription() - { - return "Descendant and Self Axis"; - } - - public boolean allowsLinkingBySelf() - { - return true; - } - - public boolean isDescendant() - { - return true; - } - - - -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/LeafScorer.java b/source/java/org/alfresco/repo/search/impl/lucene/query/LeafScorer.java deleted file mode 100644 index 64462075cb..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/LeafScorer.java +++ /dev/null @@ -1,1089 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.search.SearcherException; -import org.alfresco.repo.search.impl.lucene.index.CachingIndexReader; -import org.alfresco.repo.search.impl.lucene.index.IndexInfo; -import org.alfresco.service.cmr.dictionary.AspectDefinition; -import org.alfresco.service.cmr.dictionary.DataTypeDefinition; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.dictionary.PropertyDefinition; -import org.alfresco.service.cmr.dictionary.TypeDefinition; -import org.alfresco.service.namespace.QName; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.lucene.document.Document; -import org.apache.lucene.document.Field; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.index.TermDocs; -import org.apache.lucene.index.TermPositions; -import org.apache.lucene.search.Explanation; -import org.apache.lucene.search.Scorer; -import org.apache.lucene.search.Similarity; -import org.apache.lucene.search.Weight; - -/** - * Leaf scorer to complete path queries - * - * @author andyh - */ -public class LeafScorer extends Scorer -{ - /** - * The logger. - */ - private static Log s_logger = LogFactory.getLog(IndexInfo.class); - - static class Counter - { - int count = 0; - - public String toString() - { - return "count = " + count; - } - } - - private int counter; - - private int countInCounter; - - int min = 0; - - int max = 0; - - boolean more = true; - - Scorer containerScorer; - - StructuredFieldPosition[] sfps; - - float freq = 0.0f; - - HashMap parentIds = new HashMap(); - - HashMap> categories = new HashMap>(); - - HashMap selfIds = null; - - boolean hasSelfScorer; - - IndexReader reader; - - private TermDocs allNodes; - - TermPositions level0; - - HashSet selfLinks = new HashSet(); - - BitSet selfDocs = new BitSet(); - - private TermPositions root; - - private int rootDoc; - - private boolean repeat; - - private DictionaryService dictionaryService; - - private int[] parents; - - private int[] self; - - private int[] cats; - - private boolean matchAllLeaves; - - /** - * Constructor - should use an arg object ... - * - * @param weight - * @param root - * @param level0 - * @param containerScorer - * @param sfps - * @param allNodes - * @param selfIds - * @param reader - * @param similarity - * @param norms - * @param dictionaryService - * @param repeat - * @param tp - */ - public LeafScorer(Weight weight, TermPositions root, TermPositions level0, ContainerScorer containerScorer, StructuredFieldPosition[] sfps, TermDocs allNodes, - HashMap selfIds, IndexReader reader, Similarity similarity, byte[] norms, DictionaryService dictionaryService, boolean repeat, TermPositions tp) - { - super(similarity); - this.root = root; - this.containerScorer = containerScorer; - this.sfps = sfps; - this.allNodes = allNodes; - // this.tp = tp; - if (selfIds == null) - { - this.selfIds = new HashMap(); - hasSelfScorer = false; - } - else - { - this.selfIds = selfIds; - hasSelfScorer = true; - } - this.reader = reader; - this.level0 = level0; - this.dictionaryService = dictionaryService; - this.repeat = repeat; - - matchAllLeaves = allNodes(); - try - { - initialise(); - } - catch (IOException e) - { - throw new SearcherException(e); - } - - } - - private String getPathLinkId(IndexReader reader, int n) throws IOException - { - if (reader instanceof CachingIndexReader) - { - CachingIndexReader cachingIndexReader = (CachingIndexReader) reader; - return cachingIndexReader.getPathLinkId(n); - } - else - { - Document document = reader.document(n); - Field[] fields = document.getFields("ID"); - if (fields != null) - { - Field id = fields[fields.length - 1]; - return (id == null) ? null : id.stringValue(); - } - else - { - return null; - } - } - } - - private String getIsCategory(IndexReader reader, int n) throws IOException - { - if (reader instanceof CachingIndexReader) - { - CachingIndexReader cachingIndexReader = (CachingIndexReader) reader; - return cachingIndexReader.getIsCategory(n); - } - else - { - Document document = reader.document(n); - Field isCategory = document.getField("ISCATEGORY"); - return (isCategory == null) ? null : isCategory.stringValue(); - } - } - - private String getPath(IndexReader reader, int n) throws IOException - { - if (reader instanceof CachingIndexReader) - { - CachingIndexReader cachingIndexReader = (CachingIndexReader) reader; - return cachingIndexReader.getPath(n); - } - else - { - Document document = reader.document(n); - Field path = document.getField("PATH"); - return (path == null) ? null : path.stringValue(); - } - } - - private String getType(IndexReader reader, int n) throws IOException - { - if (reader instanceof CachingIndexReader) - { - CachingIndexReader cachingIndexReader = (CachingIndexReader) reader; - return cachingIndexReader.getType(n); - } - else - { - Document document = reader.document(n); - Field path = document.getField("TYPE"); - return (path == null) ? null : path.stringValue(); - } - } - - private String[] getParents(IndexReader reader, int n) throws IOException - { - if (reader instanceof CachingIndexReader) - { - CachingIndexReader cachingIndexReader = (CachingIndexReader) reader; - return cachingIndexReader.getParents(n); - } - else - { - Document document = reader.document(n); - Field[] fields = document.getFields("PARENT"); - if (fields != null) - { - String[] answer = new String[fields.length]; - int i = 0; - for (Field field : fields) - { - answer[i++] = (field == null) ? null : field.stringValue(); - } - return answer; - } - else - { - return null; - } - } - } - - private String[] getlinkAspects(IndexReader reader, int n) throws IOException - { - if (reader instanceof CachingIndexReader) - { - CachingIndexReader cachingIndexReader = (CachingIndexReader) reader; - return cachingIndexReader.getLinkAspects(n); - } - else - { - Document document = reader.document(n); - Field[] fields = document.getFields("LINKASPECT"); - if (fields != null) - { - String[] answer = new String[fields.length]; - int i = 0; - for (Field field : fields) - { - answer[i++] = (field == null) ? null : field.stringValue(); - } - return answer; - } - else - { - return null; - } - } - } - - private void initialise() throws IOException - { - if (containerScorer != null) - { - parentIds.clear(); - while (containerScorer.next()) - { - int doc = containerScorer.doc(); - - String id = getPathLinkId(reader, doc); - Counter counter = parentIds.get(id); - if (counter == null) - { - counter = new Counter(); - parentIds.put(id, counter); - } - counter.count++; - - if (!hasSelfScorer) - { - counter = selfIds.get(id); - if (counter == null) - { - counter = new Counter(); - selfIds.put(id, counter); - } - counter.count++; - } - - String isCategory = getIsCategory(reader, doc); - if (isCategory != null) - { - String pathString = getPath(reader, doc); - if ((pathString.length() > 0) && (pathString.charAt(0) == '/')) - { - pathString = pathString.substring(1); - } - List list = categories.get(id); - if (list == null) - { - list = new ArrayList(); - categories.put(id, list); - } - list.add(pathString); - } - } - } - else if (level0 != null) - { - parentIds.clear(); - while (level0.next()) - { - int doc = level0.doc(); - String id = getPathLinkId(reader, doc); - if (id != null) - { - Counter counter = parentIds.get(id); - if (counter == null) - { - counter = new Counter(); - parentIds.put(id, counter); - } - counter.count++; - - counter = selfIds.get(id); - if (counter == null) - { - counter = new Counter(); - selfIds.put(id, counter); - } - counter.count++; - } - } - if (parentIds.size() > 1) - { - throw new SearcherException("More than one root node in index: " + parentIds.size()); - } - else if (parentIds.size() == 0) - { - if (s_logger.isWarnEnabled()) - { - s_logger.warn("Index has no root node. Check that the correct index locations are being used."); - } - } - } - - if (matchAllLeaves) - { - int position = 0; - parents = new int[10000]; - ArrayList ordered = new ArrayList(parentIds.size()); - ordered.addAll(parentIds.keySet()); - Collections.sort(ordered); - for (String parent : ordered) - { - Counter counter = parentIds.get(parent); - // tp.seek(new Term("PARENT", parent)); - TermPositions tp = reader.termPositions(new Term("PARENT", parent)); - while (tp.next()) - { - for (int i = 0, l = tp.freq(); i < l; i++) - { - for (int j = 0; j < counter.count; j++) - { - parents[position++] = tp.doc(); - if (position == parents.length) - { - int[] old = parents; - parents = new int[old.length * 2]; - System.arraycopy(old, 0, parents, 0, old.length); - } - } - - } - } - - } - int[] old = parents; - parents = new int[position]; - System.arraycopy(old, 0, parents, 0, position); - Arrays.sort(parents); - - position = 0; - self = new int[10000]; - ordered = new ArrayList(selfIds.size()); - ordered.addAll(selfIds.keySet()); - Collections.sort(ordered); - for (String id : ordered) - { - // tp.seek(new Term("ID", id)); - TermPositions tp = reader.termPositions(new Term("ID", id)); - while (tp.next()) - { - Counter counter = selfIds.get(id); - for (int i = 0; i < counter.count; i++) - { - self[position++] = tp.doc(); - if (position == self.length) - { - old = self; - self = new int[old.length * 2]; - System.arraycopy(old, 0, self, 0, old.length); - } - } - } - - } - old = self; - self = new int[position]; - System.arraycopy(old, 0, self, 0, position); - Arrays.sort(self); - - position = 0; - cats = new int[10000]; - ordered = new ArrayList(categories.size()); - ordered.addAll(categories.keySet()); - Collections.sort(ordered); - for (String catid : ordered) - { - for (QName apsectQName : dictionaryService.getAllAspects()) - { - AspectDefinition aspDef = dictionaryService.getAspect(apsectQName); - if (isCategorised(aspDef)) - { - for (PropertyDefinition propDef : aspDef.getProperties().values()) - { - if (propDef.getDataType().getName().equals(DataTypeDefinition.CATEGORY)) - { - // tp.seek(new Term("@" + propDef.getName().toString(), catid)); - TermPositions tp = reader.termPositions(new Term("@" + propDef.getName().toString(), catid)); - while (tp.next()) - { - for (int i = 0, l = tp.freq(); i < l; i++) - { - cats[position++] = tp.doc(); - if (position == cats.length) - { - old = cats; - cats = new int[old.length * 2]; - System.arraycopy(old, 0, cats, 0, old.length); - } - } - } - - } - } - } - } - - } - old = cats; - cats = new int[position]; - System.arraycopy(old, 0, cats, 0, position); - Arrays.sort(cats); - } - } - - public boolean next() throws IOException - { - - if (repeat && (countInCounter < counter)) - { - countInCounter++; - return true; - } - else - { - countInCounter = 1; - counter = 0; - } - - if (matchAllLeaves) - { - while (more) - { - if (allNodes.next()) - { - if (check()) - { - return true; - } - } - else - { - more = false; - return false; - } - } - } - - if (!more) - { - // One of the search terms has no more docuements - return false; - } - - if (max == 0) - { - // We need to initialise - // Just do a next on all terms and check if the first doc matches - doNextOnAll(); - if (found()) - { - return true; - } - } - - return findNext(); - } - - private boolean allNodes() - { - if (sfps.length == 0) - { - return true; - } - for (StructuredFieldPosition sfp : sfps) - { - if (sfp.getCachingTermPositions() != null) - { - return false; - } - } - return true; - } - - private boolean findNext() throws IOException - { - // Move to the next document - - while (more) - { - move(); // may set more to false - if (found()) - { - return true; - } - } - - // If we get here we must have no more documents - return false; - } - - private void skipToMax() throws IOException - { - // Do the terms - int current; - for (int i = 0, l = sfps.length; i < l; i++) - { - if (i == 0) - { - min = max; - } - if (sfps[i].getCachingTermPositions() != null) - { - if (sfps[i].getCachingTermPositions().doc() < max) - { - if (sfps[i].getCachingTermPositions().skipTo(max)) - { - current = sfps[i].getCachingTermPositions().doc(); - adjustMinMax(current, false); - } - else - { - more = false; - return; - } - } - } - } - - // Do the root - if (root.doc() < max) - { - if (root.skipTo(max)) - { - rootDoc = root.doc(); - } - else - { - more = false; - return; - } - } - } - - private void move() throws IOException - { - if (min == max) - { - // If we were at a match just do next on all terms - doNextOnAll(); - } - else - { - // We are in a range - try and skip to the max position on all terms - skipToMax(); - } - } - - private void doNextOnAll() throws IOException - { - // Do the terms - int current; - boolean first = true; - for (int i = 0, l = sfps.length; i < l; i++) - { - if (sfps[i].getCachingTermPositions() != null) - { - if (sfps[i].getCachingTermPositions().next()) - { - current = sfps[i].getCachingTermPositions().doc(); - adjustMinMax(current, first); - first = false; - } - else - { - more = false; - return; - } - } - } - - // Do the root term - if (root.next()) - { - rootDoc = root.doc(); - } - else - { - more = false; - return; - } - if (root.doc() < max) - { - if (root.skipTo(max)) - { - rootDoc = root.doc(); - } - else - { - more = false; - return; - } - } - } - - private void adjustMinMax(int doc, boolean setMin) - { - - if (max < doc) - { - max = doc; - } - - if (setMin) - { - min = doc; - } - else if (min > doc) - { - min = doc; - } - } - - private boolean found() throws IOException - { - if (sfps.length == 0) - { - return true; - } - - // no more documents - no match - if (!more) - { - return false; - } - - // min and max must point to the same document - if (min != max) - { - return false; - } - - if (rootDoc != max) - { - return false; - } - - return check(); - } - - private boolean check() throws IOException - { - if (matchAllLeaves) - { - this.counter = 0; - int position; - - StructuredFieldPosition last = sfps[sfps.length - 1]; - - if (last.linkSelf()) - { - if ((self != null) && sfps[1].linkSelf() && ((position = Arrays.binarySearch(self, doc())) >= 0)) - { - if (!selfDocs.get(doc())) - { - selfDocs.set(doc()); - while (position > -1 && self[position] == doc()) - { - position--; - } - for (int i = position + 1, l = self.length; ((i < l) && (self[i] == doc())); i++) - { - this.counter++; - } - } - } - } - if (!selfDocs.get(doc()) && last.linkParent()) - { - if ((parents != null) && ((position = Arrays.binarySearch(parents, doc())) >= 0)) - { - while (position > -1 && parents[position] == doc()) - { - position--; - } - for (int i = position + 1, l = parents.length; ((i < l) && (parents[i] == doc())); i++) - { - this.counter++; - } - } - - if ((cats != null) && ((position = Arrays.binarySearch(cats, doc())) >= 0)) - { - while (position > -1 && cats[position] == doc()) - { - position--; - } - for (int i = position + 1, l = cats.length; ((i < l) && (cats[i] == doc())); i++) - { - this.counter++; - } - } - } - return counter > 0; - } - - // String name = reader.document(doc()).getField("QNAME").stringValue(); - // We have duplicate entries - // The match must be in a known term range - int count = root.freq(); - int start = 0; - int end = -1; - for (int i = 0; i < count; i++) - { - if (i == 0) - { - // First starts at zero - start = 0; - end = root.nextPosition(); - } - else - { - start = end + 1; - end = root.nextPosition(); - } - - check(start, end, i); - - } - // We had checks to do and they all failed. - return this.counter > 0; - } - - private void check(int start, int end, int position) throws IOException - { - int offset = 0; - for (int i = 0, l = sfps.length; i < l; i++) - { - offset = sfps[i].matches(start, end, offset); - if (offset == -1) - { - return; - } - } - // Last match may fail - if (offset == -1) - { - return; - } - else - { - if ((sfps[sfps.length - 1].isTerminal()) && (offset != 2)) - { - return; - } - } - - // Document doc = reader.document(doc()); - String[] parentFields = getParents(reader, doc()); - - String[] linkFields = null; - if (categories.size() > 0) - { - linkFields = getlinkAspects(reader, doc()); - } - - String parentID = null; - String linkAspect = null; - if ((parentFields != null) && (parentFields.length > position) && (parentFields[position] != null)) - { - parentID = parentFields[position]; - } - if ((linkFields != null) && (linkFields.length > position) && (linkFields[position] != null)) - { - linkAspect = linkFields[position]; - } - - containersIncludeCurrent(parentID, linkAspect); - - } - - private void containersIncludeCurrent(String parentID, String aspectQName) throws IOException - { - if ((containerScorer != null) || (level0 != null)) - { - if (sfps.length == 0) - { - return; - } - String id = getPathLinkId(reader, doc()); - StructuredFieldPosition last = sfps[sfps.length - 1]; - if ((last.linkSelf() && selfIds.containsKey(id))) - { - Counter counter = selfIds.get(id); - if (counter != null) - { - if (!selfLinks.contains(id)) - { - this.counter += counter.count; - selfLinks.add(id); - return; - } - } - } - if ((parentID != null) && (parentID.length() > 0) && last.linkParent()) - { - if (!selfLinks.contains(id)) - { - if (categories.containsKey(parentID)) - { - String type = getType(reader, doc()); - if (type != null) - { - QName typeRef = QName.createQName(type); - if (isCategory(typeRef)) - { - Counter counter = parentIds.get(parentID); - if (counter != null) - { - this.counter += counter.count; - return; - } - } - } - - if (aspectQName != null) - { - QName classRef = QName.createQName(aspectQName); - AspectDefinition aspDef = dictionaryService.getAspect(classRef); - if (isCategorised(aspDef)) - { - for (PropertyDefinition propDef : aspDef.getProperties().values()) - { - if (propDef.getDataType().getName().equals(DataTypeDefinition.CATEGORY)) - { - // get field and compare to ID - // Check in path as QName - // somewhere - Document document = reader.document(doc()); - Field[] categoryFields = document.getFields("@" + propDef.getName()); - if (categoryFields != null) - { - for (Field categoryField : categoryFields) - { - if ((categoryField != null) && (categoryField.stringValue() != null)) - { - if (categoryField.stringValue().endsWith(parentID)) - { - int count = 0; - List paths = categories.get(parentID); - if (paths != null) - { - for (String path : paths) - { - if (path.indexOf(aspectQName) != -1) - { - count++; - } - } - } - this.counter += count; - return; - } - } - } - } - } - } - } - - } - } - else - { - Counter counter = parentIds.get(parentID); - if (counter != null) - { - this.counter += counter.count; - return; - } - } - - } - } - - return; - } - else - { - return; - } - } - - private boolean isCategory(QName classRef) - { - if (classRef == null) - { - return false; - } - TypeDefinition current = dictionaryService.getType(classRef); - while (current != null) - { - if (current.getName().equals(ContentModel.TYPE_CATEGORY)) - { - return true; - } - else - { - QName parentName = current.getParentName(); - if (parentName == null) - { - break; - } - current = dictionaryService.getType(parentName); - } - } - return false; - } - - private boolean isCategorised(AspectDefinition aspDef) - { - AspectDefinition current = aspDef; - while (current != null) - { - if (current.getName().equals(ContentModel.ASPECT_CLASSIFIABLE)) - { - return true; - } - else - { - QName parentName = current.getParentName(); - if (parentName == null) - { - break; - } - current = dictionaryService.getAspect(parentName); - } - } - return false; - } - - public int doc() - { - if (matchAllLeaves) - { - return allNodes.doc(); - } - return max; - } - - public float score() throws IOException - { - return repeat ? 1.0f : counter; - } - - public boolean skipTo(int target) throws IOException - { - - countInCounter = 1; - counter = 0; - - if (matchAllLeaves) - { - allNodes.skipTo(target); - root.skipTo(allNodes.doc()); // must match - if (check()) - { - return true; - } - while (more) - { - if (allNodes.next()) - { - if (check()) - { - return true; - } - } - else - { - more = false; - return false; - } - } - } - - max = target; - return findNext(); - } - - public Explanation explain(int doc) throws IOException - { - Explanation tfExplanation = new Explanation(); - - while (next() && doc() < doc) - { - } - - float phraseFreq = (doc() == doc) ? freq : 0.0f; - tfExplanation.setValue(getSimilarity().tf(phraseFreq)); - tfExplanation.setDescription("tf(phraseFreq=" + phraseFreq + ")"); - - return tfExplanation; - } - -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/PathQuery.java b/source/java/org/alfresco/repo/search/impl/lucene/query/PathQuery.java deleted file mode 100644 index 2c10e9fd67..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/PathQuery.java +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.search.Explanation; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.Scorer; -import org.apache.lucene.search.Searcher; -import org.apache.lucene.search.Weight; - -/** - * An extension to the Lucene query set. - * - * This query supports structured queries against paths. - * - * The field must have been tokenised using the path tokeniser. - * - * This class manages linking together an ordered chain of absolute and relative - * positional queries. - * - * @author Andy Hind - */ -public class PathQuery extends Query -{ - /** - * - */ - private static final long serialVersionUID = 3832904355660707892L; - - private String pathField = "PATH"; - - private String qNameField = "QNAME"; - - private int unitSize = 2; - - private List pathStructuredFieldPositions = new ArrayList(); - - private List qNameStructuredFieldPositions = new ArrayList(); - - private DictionaryService dictionarySertvice; - - private boolean repeats = false; - - /** - * The base query - * - * @param query - */ - - public PathQuery(DictionaryService dictionarySertvice) - { - super(); - this.dictionarySertvice = dictionarySertvice; - } - - public void setQuery(List path, List qname) - { - qNameStructuredFieldPositions.clear(); - pathStructuredFieldPositions.clear(); - if (qname.size() != unitSize) - { - throw new UnsupportedOperationException(); - } - if (path.size() % unitSize != 0) - { - throw new UnsupportedOperationException(); - } - qNameStructuredFieldPositions.addAll(qname); - pathStructuredFieldPositions.addAll(path); - } - - public void appendQuery(List sfps) - { - if (sfps.size() != unitSize) - { - throw new UnsupportedOperationException(); - } - - StructuredFieldPosition last = null; - StructuredFieldPosition next = sfps.get(0); - - if (qNameStructuredFieldPositions.size() > 0) - { - last = qNameStructuredFieldPositions.get(qNameStructuredFieldPositions.size() - 1); - } - - if ((last != null) && next.linkParent() && !last.allowslinkingByParent()) - { - return; - } - - if ((last != null) && next.linkSelf() && !last.allowsLinkingBySelf()) - { - return; - } - - if (qNameStructuredFieldPositions.size() == unitSize) - { - pathStructuredFieldPositions.addAll(qNameStructuredFieldPositions); - } - qNameStructuredFieldPositions.clear(); - qNameStructuredFieldPositions.addAll(sfps); - } - - public String getPathField() - { - return pathField; - } - - public void setPathField(String pathField) - { - this.pathField = pathField; - } - - public String getQnameField() - { - return qNameField; - } - - public void setQnameField(String qnameField) - { - this.qNameField = qnameField; - } - - public Term getPathRootTerm() - { - return new Term(getPathField(), ";"); - } - - public Term getQNameRootTerm() - { - return new Term(getQnameField(), ";"); - } - - /* - * @see org.apache.lucene.search.Query#createWeight(org.apache.lucene.search.Searcher) - */ - protected Weight createWeight(Searcher searcher) - { - return new StructuredFieldWeight(searcher); - } - - /* - * @see java.lang.Object#toString() - */ - public String toString() - { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(":"); - int i = 0; - for(StructuredFieldPosition sfp : pathStructuredFieldPositions) - { - if(i % 2 == 0) - { - stringBuilder.append('/'); - } - else - { - stringBuilder.append(':'); - } - if(sfp.matchesAll()) - { - stringBuilder.append("*"); - } - else - { - stringBuilder.append(sfp.getTermText()); - } - i++; - } - for(StructuredFieldPosition sfp : qNameStructuredFieldPositions) - { - if(i % 2 == 0) - { - stringBuilder.append('/'); - } - else - { - stringBuilder.append(':'); - } - if(sfp.matchesAll()) - { - stringBuilder.append("*"); - } - else - { - stringBuilder.append(sfp.getTermText()); - } - i++; - } - return stringBuilder.toString(); - } - - /* - * @see org.apache.lucene.search.Query#toString(java.lang.String) - */ - public String toString(String field) - { - return toString(); - } - - private class StructuredFieldWeight implements Weight - { - - /** - * - */ - private static final long serialVersionUID = 3257854259645985328L; - - private Searcher searcher; - - private float value; - - private float idf; - - private float queryNorm; - - private float queryWeight; - - public StructuredFieldWeight(Searcher searcher) - { - this.searcher = searcher; - - } - - /* - * @see org.apache.lucene.search.Weight#explain(org.apache.lucene.index.IndexReader, - * int) - */ - public Explanation explain(IndexReader reader, int doc) throws IOException - { - throw new UnsupportedOperationException(); - } - - /* - * @see org.apache.lucene.search.Weight#getQuery() - */ - public Query getQuery() - { - return PathQuery.this; - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.search.Weight#getValue() - */ - public float getValue() - { - return value; - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.search.Weight#normalize(float) - */ - public void normalize(float queryNorm) - { - this.queryNorm = queryNorm; - queryWeight *= queryNorm; // normalize query weight - value = queryWeight * idf; // idf for document - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.search.Weight#scorer(org.apache.lucene.index.IndexReader) - */ - public Scorer scorer(IndexReader reader) throws IOException - { - return PathScorer.createPathScorer(getSimilarity(searcher), PathQuery.this, reader, this, dictionarySertvice, repeats); - - } - - /* - * (non-Javadoc) - * - * @see org.apache.lucene.search.Weight#sumOfSquaredWeights() - */ - public float sumOfSquaredWeights() throws IOException - { - idf = getSimilarity(searcher).idf(getTerms(), searcher); // compute - // idf - queryWeight = idf * getBoost(); // compute query weight - return queryWeight * queryWeight; // square it - } - - private ArrayList getTerms() - { - ArrayList answer = new ArrayList(pathStructuredFieldPositions.size()); - for (StructuredFieldPosition sfp : pathStructuredFieldPositions) - { - if (sfp.getTermText() != null) - { - Term term = new Term(pathField, sfp.getTermText()); - answer.add(term); - } - } - return answer; - } - } - - public void removeDescendantAndSelf() - { - while ((getLast() != null) && getLast().linkSelf()) - { - removeLast(); - removeLast(); - } - } - - private StructuredFieldPosition getLast() - - { - if (qNameStructuredFieldPositions.size() > 0) - { - return qNameStructuredFieldPositions.get(qNameStructuredFieldPositions.size() - 1); - } - else - { - return null; - } - } - - private void removeLast() - { - qNameStructuredFieldPositions.clear(); - for (int i = 0; i < unitSize; i++) - { - if (pathStructuredFieldPositions.size() > 0) - { - qNameStructuredFieldPositions.add(0, pathStructuredFieldPositions.remove(pathStructuredFieldPositions.size() - 1)); - } - } - } - - public boolean isEmpty() - { - return qNameStructuredFieldPositions.size() == 0; - } - - public List getPathStructuredFieldPositions() - { - return pathStructuredFieldPositions; - } - - - public List getQNameStructuredFieldPositions() - { - return qNameStructuredFieldPositions; - } - - public void setRepeats(boolean repeats) - { - this.repeats = repeats; - } - - - - - -} \ No newline at end of file diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/PathScorer.java b/source/java/org/alfresco/repo/search/impl/lucene/query/PathScorer.java deleted file mode 100644 index 553f4a08aa..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/PathScorer.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; - -import org.alfresco.repo.search.impl.lucene.index.CachingIndexReader; -import org.alfresco.repo.search.impl.lucene.query.LeafScorer.Counter; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.apache.lucene.document.Document; -import org.apache.lucene.document.Field; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.index.TermDocs; -import org.apache.lucene.index.TermPositions; -import org.apache.lucene.search.Explanation; -import org.apache.lucene.search.Scorer; -import org.apache.lucene.search.Similarity; -import org.apache.lucene.search.Weight; - -public class PathScorer extends Scorer -{ - Scorer scorer; - - PathScorer(Similarity similarity, Scorer scorer) - { - super(similarity); - this.scorer = scorer; - } - - - public static PathScorer createPathScorer(Similarity similarity, PathQuery pathQuery, IndexReader reader, Weight weight, DictionaryService dictionarySertvice, boolean repeat) throws IOException - { - Scorer selfScorer = null; - HashMap selfIds = null; - - StructuredFieldPosition last = null; - if(pathQuery.getQNameStructuredFieldPositions().size() > 0) - { - last = pathQuery.getQNameStructuredFieldPositions().get(pathQuery.getQNameStructuredFieldPositions().size() - 1); - } - if ((last != null) && last.linkSelf()) - { - PathQuery selfQuery = new PathQuery(dictionarySertvice); - selfQuery.setQuery(pathQuery.getPathStructuredFieldPositions(), pathQuery.getQNameStructuredFieldPositions()); - selfQuery.removeDescendantAndSelf(); - if (!selfQuery.isEmpty()) - { - selfIds = new HashMap(); - selfScorer = PathScorer.createPathScorer(similarity, selfQuery, reader, weight, dictionarySertvice, repeat); - selfIds.clear(); - while (selfScorer.next()) - { - int doc = selfScorer.doc(); - Document document = reader.document(doc); - Field id = document.getField("ID"); - Counter counter = selfIds.get(id.stringValue()); - if (counter == null) - { - counter = new Counter(); - selfIds.put(id.stringValue(), counter); - } - counter.count++; - } - } - } - - - if ((pathQuery.getPathStructuredFieldPositions().size() + pathQuery.getQNameStructuredFieldPositions().size()) == 0) - { - ArrayList answer = new ArrayList(2); - answer.add(new SelfAxisStructuredFieldPosition()); - answer.add(new SelfAxisStructuredFieldPosition()); - - pathQuery.appendQuery(answer); - } - - - for (StructuredFieldPosition sfp : pathQuery.getPathStructuredFieldPositions()) - { - if (sfp.getTermText() != null) - { - TermPositions p = reader.termPositions(new Term(pathQuery.getPathField(), sfp.getTermText())); - if (p == null) - return null; - CachingTermPositions ctp = new CachingTermPositions(p); - sfp.setCachingTermPositions(ctp); - } - } - - for (StructuredFieldPosition sfp : pathQuery.getQNameStructuredFieldPositions()) - { - if (sfp.getTermText() != null) - { - TermPositions p = reader.termPositions(new Term(pathQuery.getQnameField(), sfp.getTermText())); - if (p == null) - return null; - CachingTermPositions ctp = new CachingTermPositions(p); - sfp.setCachingTermPositions(ctp); - } - } - - TermPositions rootContainerPositions = null; - if (pathQuery.getPathRootTerm() != null) - { - rootContainerPositions = reader.termPositions(pathQuery.getPathRootTerm()); - } - - TermPositions rootLeafPositions = null; - if (pathQuery.getQNameRootTerm() != null) - { - rootLeafPositions = reader.termPositions(pathQuery.getQNameRootTerm()); - } - - - TermPositions tp = reader.termPositions(); - - ContainerScorer cs = null; - - TermPositions level0 = null; - - TermDocs nodeDocs; - if (reader instanceof CachingIndexReader) - { - CachingIndexReader cachingIndexReader = (CachingIndexReader) reader; - nodeDocs = cachingIndexReader.getNodeDocs(); - } - else - { - nodeDocs = reader.termDocs(new Term("ISNODE", "T")); - } - - // StructuredFieldPosition[] test = - // (StructuredFieldPosition[])structuredFieldPositions.toArray(new - // StructuredFieldPosition[]{}); - if (pathQuery.getPathStructuredFieldPositions().size() > 0) - { - TermPositions containerPositions = reader.termPositions(new Term("ISCONTAINER", "T")); - cs = new ContainerScorer(weight, rootContainerPositions, (StructuredFieldPosition[]) pathQuery.getPathStructuredFieldPositions().toArray(new StructuredFieldPosition[] {}), - containerPositions, similarity, reader.norms(pathQuery.getPathField())); - } - else - { - level0 = reader.termPositions(new Term("ISROOT", "T")); - } - - if((cs == null) && - (pathQuery.getQNameStructuredFieldPositions().get(pathQuery.getQNameStructuredFieldPositions().size()-1)).linkSelf()) - { - nodeDocs = reader.termDocs(new Term("ISROOT", "T")); - } - - - LeafScorer ls = new LeafScorer(weight, rootLeafPositions, level0, cs, (StructuredFieldPosition[]) pathQuery.getQNameStructuredFieldPositions().toArray(new StructuredFieldPosition[] {}), nodeDocs, - selfIds, reader, similarity, reader.norms(pathQuery.getQnameField()), dictionarySertvice, repeat, tp); - - return new PathScorer(similarity, ls); - } - - @Override - public boolean next() throws IOException - { - return scorer.next(); - } - - @Override - public int doc() - { - return scorer.doc(); - } - - @Override - public float score() throws IOException - { - return scorer.score(); - } - - @Override - public boolean skipTo(int position) throws IOException - { - return scorer.skipTo(position); - } - - @Override - public Explanation explain(int position) throws IOException - { - return scorer.explain(position); - } - -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/RelativeStructuredFieldPosition.java b/source/java/org/alfresco/repo/search/impl/lucene/query/RelativeStructuredFieldPosition.java deleted file mode 100644 index 9f697785a9..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/RelativeStructuredFieldPosition.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import java.io.IOException; - -/** - * Search for a term relative to the last one found. - * - * @author andyh - */ -public class RelativeStructuredFieldPosition extends AbstractStructuredFieldPosition -{ - - int relativePosition; - - /** - * - */ - public RelativeStructuredFieldPosition(String termText) - { - super(termText.equals("*") ? null : termText, true, false); - relativePosition = 1; - - } - - public RelativeStructuredFieldPosition() - { - super(null, false, false); - relativePosition = 1; - } - - /* - * (non-Javadoc) - * - * @see org.alfresco.lucene.extensions.StructuredFieldPosition#matches(int, - * int, org.apache.lucene.index.TermPositions) - */ - public int matches(int start, int end, int offset) throws IOException - { - - if (getCachingTermPositions() != null) - { - // Doing "termText" - getCachingTermPositions().reset(); - int count = getCachingTermPositions().freq(); - int requiredPosition = offset + relativePosition; - int realPosition = 0; - int adjustedPosition = 0; - for (int i = 0; i < count; i++) - { - realPosition = getCachingTermPositions().nextPosition(); - adjustedPosition = realPosition - start; - if ((end != -1) && (realPosition > end)) - { - return -1; - } - if (adjustedPosition == requiredPosition) - { - return adjustedPosition; - } - if (adjustedPosition > requiredPosition) - { - return -1; - } - } - } - else - { - // Doing "*"; - return offset + 1; - } - return -1; - } - - public String getDescription() - { - return "Relative Named child"; - } -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/SelfAxisStructuredFieldPosition.java b/source/java/org/alfresco/repo/search/impl/lucene/query/SelfAxisStructuredFieldPosition.java deleted file mode 100644 index 54f721c341..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/SelfAxisStructuredFieldPosition.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import java.io.IOException; - -public class SelfAxisStructuredFieldPosition extends AbstractStructuredFieldPosition -{ - - public SelfAxisStructuredFieldPosition() - { - super(null, true, false); - } - - public int matches(int start, int end, int offset) throws IOException - { - return offset; - } - - public String getDescription() - { - return "Self Axis"; - } - - public boolean linkSelf() - { - return true; - } - - public boolean isTerminal() - { - return false; - } - - - - -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/StructuredFieldPosition.java b/source/java/org/alfresco/repo/search/impl/lucene/query/StructuredFieldPosition.java deleted file mode 100644 index 20588e2cbb..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/StructuredFieldPosition.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import java.io.IOException; - -/** - * Elements used to test agains path and Qname - * - * @author andyh - */ -public interface StructuredFieldPosition -{ - - /** - * Does this element match - * - * @param start - - * the start postion of the paths terms - * @param end - - * the end position of the paths terms - * @param offset - - * the current offset in the path - * @return returns the next match position (usually offset + 1) or -1 if it - * does not match. - * @throws IOException - */ - public int matches(int start, int end, int offset) throws IOException; - - /** - * If this position is last in the chain and it is terminal it will ensure - * it is an exact match for the length of the chain found. If false, it will - * effectively allow prefix mathces for the likes of descendant-and-below - * style queries. - * - * @return - */ - public boolean isTerminal(); - - /** - * Is this an absolute element; that is, it knows its exact position. - * - * @return - */ - public boolean isAbsolute(); - - /** - * This element only knows its position relative to the previous element. - * - * @return - */ - public boolean isRelative(); - - /** - * Get the test to search for in the term query. This may be null if it - * should not have a term query - * - * @return - */ - public String getTermText(); - - /** - * If absolute return the position. If relative we could compute the - * position knowing the previous term unless this element is preceded by a - * descendat and below style element - * - * @return - */ - public int getPosition(); - - /** - * A reference to the caching term positions this element uses. This may be - * null which indicates all terms match, in that case there is no action - * against the index - * - * @param tps - */ - public void setCachingTermPositions(CachingTermPositions tps); - - public CachingTermPositions getCachingTermPositions(); - - /** - * Normally paths would require onlt parent chaining. for some it is parent - * and child chaining. - * - * @return - */ - - public boolean linkSelf(); - - public boolean linkParent(); - - public boolean allowslinkingByParent(); - - public boolean allowsLinkingBySelf(); - - public boolean isDescendant(); - - public boolean matchesAll(); -} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/query/StructuredFieldTerm.java b/source/java/org/alfresco/repo/search/impl/lucene/query/StructuredFieldTerm.java deleted file mode 100644 index b07cb661c0..0000000000 --- a/source/java/org/alfresco/repo/search/impl/lucene/query/StructuredFieldTerm.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.repo.search.impl.lucene.query; - -import org.apache.lucene.index.Term; - -/** - * @author andyh - */ -public class StructuredFieldTerm -{ - - private Term term; - - private StructuredFieldPosition sfp; - - /** - * - */ - public StructuredFieldTerm(Term term, StructuredFieldPosition sfp) - { - this.term = term; - this.sfp = sfp; - } - - /** - * @return Returns the sfp. - */ - public StructuredFieldPosition getSfp() - { - return sfp; - } - - /** - * @return Returns the term. - */ - public Term getTerm() - { - return term; - } -} diff --git a/source/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java b/source/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java index c24f4eed43..39934b669e 100644 --- a/source/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java +++ b/source/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java @@ -212,7 +212,7 @@ public class AlfrescoFunctionEvaluationContext implements FunctionEvaluationCont // find best field match HashSet allowableLocales = new HashSet(); - MLAnalysisMode analysisMode = lqp.getConfig().getDefaultMLSearchAnalysisMode(); + MLAnalysisMode analysisMode = lqp.getDefaultSearchMLAnalysisMode(); for (Locale l : MLAnalysisMode.getLocales(analysisMode, sortLocale, false)) { allowableLocales.add(l.toString()); diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderContext.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderContext.java index 1f42f3a9e5..01a059e2ba 100644 --- a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderContext.java +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderContext.java @@ -57,7 +57,7 @@ public class LuceneQueryBuilderContext lqp.setNamespacePrefixResolver(namespacePrefixResolver); lqp.setTenantService(tenantService); lqp.setSearchParameters(searchParameters); - lqp.setLuceneConfig(config); + lqp.setDefaultSearchMLAnalysisMode(config.getDefaultMLSearchAnalysisMode()); lqp.setIndexReader(indexReader); lqp.setAllowLeadingWildcard(true); this.namespacePrefixResolver = namespacePrefixResolver; diff --git a/source/java/org/alfresco/util/SearchLanguageConversion.java b/source/java/org/alfresco/util/SearchLanguageConversion.java deleted file mode 100644 index 860025a808..0000000000 --- a/source/java/org/alfresco/util/SearchLanguageConversion.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.util; - -import org.alfresco.repo.search.impl.lucene.LuceneQueryParser; -import org.apache.lucene.queryParser.QueryParser; - -/** - * Helper class to provide conversions between different search languages - * - * @author Derek Hulley - */ -public class SearchLanguageConversion -{ - /** - * SQL like query language summary: - *
    - *
  • Escape: \
  • - *
  • Single char search: _
  • - *
  • Multiple char search: %
  • - *
  • Reserved: \%_
  • - *
- */ - public static LanguageDefinition DEF_SQL_LIKE = new SimpleLanguageDef('\\', "%", "_", "\\%_[]"); - - /** - * XPath like query language summary: - *
    - *
  • Escape: \
  • - *
  • Single char search: _
  • - *
  • Multiple char search: %
  • - *
  • Reserved: \%_
  • - *
- */ - public static LanguageDefinition DEF_XPATH_LIKE = new SimpleLanguageDef('\\', "%", "_", "\\%_[]"); - - /** - * Regular expression query language summary: - *
    - *
  • Escape: \
  • - *
  • Single char search: .
  • - *
  • Multiple char search: .*
  • - *
  • Reserved: \*.+?^$(){}|
  • - *
- */ - public static LanguageDefinition DEF_REGEX = new SimpleLanguageDef('\\', ".*", ".", "\\*.+?^$(){}|"); - - /** - * Lucene syntax summary: {@link QueryParser#escape(String) Lucene Query Parser} - */ - public static LanguageDefinition DEF_LUCENE = new LuceneLanguageDef(true); - - public static LanguageDefinition DEF_LUCENE_INTERNAL = new LuceneLanguageDef(false); - - /** - * CIFS name patch query language summary: - *
    - *
  • Escape: \ (but not used)
  • - *
  • Single char search: ?
  • - *
  • Multiple char search: *
  • - *
  • Reserved: "*\<>?/:|¬£%&+;
  • - *
- */ - public static LanguageDefinition DEF_CIFS = new SimpleLanguageDef('\\', "*", "?", "\"*\\<>?/:|¬£%&+;"); - - /** - * Escape a string according to the XPath like function syntax. - * - * @param str - * the string to escape - * @return Returns the escaped string - */ - public static String escapeForXPathLike(String str) - { - return escape(DEF_XPATH_LIKE, str); - } - - /** - * Escape a string according to the regex language syntax. - * - * @param str - * the string to escape - * @return Returns the escaped string - */ - public static String escapeForRegex(String str) - { - return escape(DEF_REGEX, str); - } - - /** - * Escape a string according to the Lucene query syntax. - * - * @param str - * the string to escape - * @return Returns the escaped string - */ - public static String escapeForLucene(String str) - { - return escape(DEF_LUCENE, str); - } - - /** - * Generic escaping using the language definition - */ - private static String escape(LanguageDefinition def, String str) - { - StringBuilder sb = new StringBuilder(str.length() * 2); - - char[] chars = str.toCharArray(); - for (int i = 0; i < chars.length; i++) - { - // first check for reserved chars - if (def.isReserved(chars[i])) - { - // escape it - sb.append(def.escapeChar); - } - sb.append(chars[i]); - } - return sb.toString(); - } - - /** - * Convert an xpath like function clause into a regex query. - * - * @param xpathLikeClause - * @return Returns a valid regular expression that is equivalent to the given xpath like clause. - */ - public static String convertXPathLikeToRegex(String xpathLikeClause) - { - return "(?s)" + convert(DEF_XPATH_LIKE, DEF_REGEX, xpathLikeClause); - } - - /** - * Convert an xpath like function clause into a Lucene query. - * - * @param xpathLikeClause - * @return Returns a valid Lucene expression that is equivalent to the given xpath like clause. - */ - public static String convertXPathLikeToLucene(String xpathLikeClause) - { - return convert(DEF_XPATH_LIKE, DEF_LUCENE, xpathLikeClause); - } - - /** - * Convert a sql like function clause into a Lucene query. - * - * @param sqlLikeClause - * @return Returns a valid Lucene expression that is equivalent to the given sql like clause. - */ - public static String convertSQLLikeToLucene(String sqlLikeClause) - { - return convert(DEF_SQL_LIKE, DEF_LUCENE_INTERNAL, sqlLikeClause); - } - - /** - * Convert a sql like function clause into a regex query. - * - * @param sqlLikeClause - * @return Returns a valid regular expression that is equivalent to the given sql like clause. - */ - public static String convertSQLLikeToRegex(String sqlLikeClause) - { - return "(?s)" + convert(DEF_SQL_LIKE, DEF_REGEX, sqlLikeClause); - } - - /** - * Convert a CIFS name path into the equivalent Lucene query. - * - * @param cifsNamePath - * the CIFS named path - * @return Returns a valid Lucene expression that is equivalent to the given CIFS name path - */ - public static String convertCifsToLucene(String cifsNamePath) - { - return convert(DEF_CIFS, DEF_LUCENE, cifsNamePath); - } - - public static String convert(LanguageDefinition from, LanguageDefinition to, String query) - { - char[] chars = query.toCharArray(); - - StringBuilder sb = new StringBuilder(chars.length * 2); - - boolean escaping = false; - - for (int i = 0; i < chars.length; i++) - { - if (escaping) // if we are currently escaping, just escape the current character - { - if(to.isReserved(chars[i])) - { - sb.append(to.escapeChar); // the to format escape char - } - sb.append(chars[i]); // the current char - escaping = false; - } - else if (chars[i] == from.escapeChar) // not escaping and have escape char - { - escaping = true; - } - else if (query.startsWith(from.multiCharWildcard, i)) // not escaping but have multi-char wildcard - { - // translate the wildcard - sb.append(to.multiCharWildcard); - } - else if (query.startsWith(from.singleCharWildcard, i)) // have single-char wildcard - { - // translate the wildcard - sb.append(to.singleCharWildcard); - } - else if (to.isReserved(chars[i])) // reserved character - { - sb.append(to.escapeChar).append(chars[i]); - } - else - // just a normal char in both - { - sb.append(chars[i]); - } - } - return sb.toString(); - } - - /** - * Simple store of special characters for a given query language - */ - public static abstract class LanguageDefinition - { - public final char escapeChar; - - public final String multiCharWildcard; - - public final String singleCharWildcard; - - public LanguageDefinition(char escapeChar, String multiCharWildcard, String singleCharWildcard) - { - this.escapeChar = escapeChar; - this.multiCharWildcard = multiCharWildcard; - this.singleCharWildcard = singleCharWildcard; - } - - public abstract boolean isReserved(char ch); - } - - private static class SimpleLanguageDef extends LanguageDefinition - { - private String reserved; - - public SimpleLanguageDef(char escapeChar, String multiCharWildcard, String singleCharWildcard, String reserved) - { - super(escapeChar, multiCharWildcard, singleCharWildcard); - this.reserved = reserved; - } - - @Override - public boolean isReserved(char ch) - { - return (reserved.indexOf(ch) > -1); - } - } - - private static class LuceneLanguageDef extends LanguageDefinition - { - private String reserved; - - public LuceneLanguageDef(boolean reserve) - { - super('\\', "*", "?"); - if (reserve) - { - init(); - } - else - { - reserved = ""; - } - } - - /** - * Discovers all the reserved chars - */ - private void init() - { - StringBuilder sb = new StringBuilder(20); - for (char ch = 0; ch < 256; ch++) - { - char[] chars = new char[] { ch }; - String unescaped = new String(chars); - // check it - String escaped = LuceneQueryParser.escape(unescaped); - if (!escaped.equals(unescaped)) - { - // it was escaped - sb.append(ch); - } - } - reserved = sb.toString(); - } - - @Override - public boolean isReserved(char ch) - { - return (reserved.indexOf(ch) > -1); - } - } -} diff --git a/source/java/org/alfresco/util/SearchLanguageConversionTest.java b/source/java/org/alfresco/util/SearchLanguageConversionTest.java deleted file mode 100644 index b603a2ab66..0000000000 --- a/source/java/org/alfresco/util/SearchLanguageConversionTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2005-2010 Alfresco Software Limited. - * - * This file is part of Alfresco - * - * Alfresco is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ -package org.alfresco.util; - -import junit.framework.TestCase; - -/** - * @see org.alfresco.util.SearchLanguageConversion - * - * @author Derek Hulley - */ -public class SearchLanguageConversionTest extends TestCase -{ - /** - * A string with a whole lod of badness to stress test with - */ - private static final String BAD_STRING = - "\\ | ! \" £ " + - "$ % ^ & * ( " + - ") _ { } [ ] " + - "@ # ~ ' : ; " + - ", . < > + ? " + - "/ \\\\ \\* \\? \\_"; - - public void testEscapeXPathLike() - { - String good = SearchLanguageConversion.escapeForXPathLike(BAD_STRING); - assertEquals("Escaping for xpath failed", - "\\\\ | ! \" £ " + - "$ \\% ^ & * ( " + - ") \\_ { } \\[ \\] " + - "@ # ~ ' : ; " + - ", . < > + ? " + - "/ \\\\\\\\ \\\\* \\\\? \\\\\\_", - good); - } - - public void testEscapeRegex() - { - String good = SearchLanguageConversion.escapeForRegex(BAD_STRING); - assertEquals("Escaping for regex failed", - "\\\\ \\| ! \" £ " + - "\\$ % \\^ & \\* \\( " + - "\\) _ \\{ \\} [ ] " + - "@ # ~ ' : ; " + - ", \\. < > \\+ \\? " + - "/ \\\\\\\\ \\\\\\* \\\\\\? \\\\_", - good); - } - - public void testEscapeLucene() - { - String good = SearchLanguageConversion.escapeForLucene(BAD_STRING); - assertEquals("Escaping for Lucene failed", - "\\\\ \\| \\! \\\" £ " + - "$ % \\^ \\& \\* \\( " + - "\\) _ \\{ \\} \\[ \\] " + - "@ # \\~ ' \\: ; " + - ", . < > \\+ \\? " + - "/ \\\\\\\\ \\\\\\* \\\\\\? \\\\_", - good); - } - - public void testConvertXPathLikeToRegex() - { - String good = SearchLanguageConversion.convertXPathLikeToRegex(BAD_STRING); - assertEquals("XPath like to regex failed", - "(?s) \\| ! \" £ " + - "\\$ .* \\^ & \\* \\( " + - "\\) . \\{ \\} [ ] " + - "@ # ~ ' : ; " + - ", \\. < > \\+ \\? " + - "/ \\\\ \\* \\? _", - good); - } - - public void testConvertXPathLikeToLucene() - { - String good = SearchLanguageConversion.convertXPathLikeToLucene(BAD_STRING); - assertEquals("XPath like to Lucene failed", - " \\| \\! \\\" £ " + - "$ * \\^ \\& \\* \\( " + - "\\) ? \\{ \\} \\[ \\] " + - "@ # \\~ ' \\: ; " + - ", . < > \\+ \\? " + - "/ \\\\ \\* \\? _", - good); - } - - public void testSqlToLucene() - { - String sqlLike = "AB%_*?\\%\\_"; - String lucene = "AB*?\\*\\?%_"; - String converted = SearchLanguageConversion.convert(SearchLanguageConversion.DEF_SQL_LIKE, SearchLanguageConversion.DEF_LUCENE, sqlLike); - assertEquals(lucene, converted); - } - - public void testLuceneToRegexp() - { - String lucene = "AB*?\\*\\?.*."; - String regexp = "AB.*.\\*\\?\\..*\\."; - String converted = SearchLanguageConversion.convert(SearchLanguageConversion.DEF_LUCENE, SearchLanguageConversion.DEF_REGEX, lucene); - assertEquals(regexp, converted); - } - -}