diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java index b5d1e18fc3..df0eb7c43a 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java @@ -732,8 +732,44 @@ public class ADMLuceneTest extends TestCase ftsQueryWithCount(searcher, "TEXT:(brown *(5) dog)", 1); ftsQueryWithCount(searcher, "TEXT:(brown *(6) dog)", 1); + //ftsQueryWithCount(searcher, "brown..dog", 1); // is this allowed?? + ftsQueryWithCount(searcher, "cm:content:brown..dog", 1); + QName qname = QName.createQName(TEST_NAMESPACE, "float\\-ista"); ftsQueryWithCount(searcher, qname+":3.40", 1); + ftsQueryWithCount(searcher, qname+":3..4", 1); + ftsQueryWithCount(searcher, qname+":3..3.39", 0); + ftsQueryWithCount(searcher, qname+":3..3.40", 1); + ftsQueryWithCount(searcher, qname+":3.41..3.9", 0); + ftsQueryWithCount(searcher, qname+":3.40..3.9", 1); + + ftsQueryWithCount(searcher, qname+":[3 TO 4]", 1); + ftsQueryWithCount(searcher, qname+":[3 TO 3.39]", 0); + ftsQueryWithCount(searcher, qname+":[3 TO 3.4]", 1); + ftsQueryWithCount(searcher, qname+":[3.41 TO 4]", 0); + ftsQueryWithCount(searcher, qname+":[3.4 TO 4]", 1); + ftsQueryWithCount(searcher, qname+":[3 TO 3.4>", 0); + ftsQueryWithCount(searcher, qname+":<3.4 TO 4]", 0); + ftsQueryWithCount(searcher, qname+":<3.4 TO 3.4>", 0); + + ftsQueryWithCount(searcher, qname+":(3.40)", 1); + ftsQueryWithCount(searcher, qname+":(3..4)", 1); + ftsQueryWithCount(searcher, qname+":(3..3.39)", 0); + ftsQueryWithCount(searcher, qname+":(3..3.40)", 1); + ftsQueryWithCount(searcher, qname+":(3.41..3.9)", 0); + ftsQueryWithCount(searcher, qname+":(3.40..3.9)", 1); + + ftsQueryWithCount(searcher, qname+":([3 TO 4])", 1); + ftsQueryWithCount(searcher, qname+":([3 TO 3.39])", 0); + ftsQueryWithCount(searcher, qname+":([3 TO 3.4])", 1); + ftsQueryWithCount(searcher, qname+":([3.41 TO 4])", 0); + ftsQueryWithCount(searcher, qname+":([3.4 TO 4])", 1); + ftsQueryWithCount(searcher, qname+":([3 TO 3.4>)", 0); + ftsQueryWithCount(searcher, qname+":(<3.4 TO 4])", 0); + ftsQueryWithCount(searcher, qname+":(<3.4 TO 3.4>)", 0); + + + } public void ftsQueryWithCount(ADMLuceneSearcherImpl searcher, String query, int count) diff --git a/source/java/org/alfresco/repo/search/impl/parsers/FTSQueryParser.java b/source/java/org/alfresco/repo/search/impl/parsers/FTSQueryParser.java index 35c400ffa5..cd13752899 100644 --- a/source/java/org/alfresco/repo/search/impl/parsers/FTSQueryParser.java +++ b/source/java/org/alfresco/repo/search/impl/parsers/FTSQueryParser.java @@ -44,6 +44,7 @@ import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSExactTerm; import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSExpandTerm; import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSPhrase; import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSProximity; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSRange; import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSTerm; import org.alfresco.repo.search.impl.querymodel.impl.functions.PropertyAccessor; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; @@ -57,7 +58,8 @@ import org.apache.lucene.search.function.FieldScoreQuery; public class FTSQueryParser { - public Constraint buildFTS(String ftsExpression, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, Selector selector, ArrayList columns, Connective defaultConnective, Connective defaultFieldConnective) + public Constraint buildFTS(String ftsExpression, QueryModelFactory factory, FunctionEvaluationContext functionEvaluationContext, Selector selector, ArrayList columns, + Connective defaultConnective, Connective defaultFieldConnective) { // TODO: Decode sql escape for '' should do in CMIS layer FTSParser parser = null; @@ -295,7 +297,23 @@ public class FTSQueryParser functionArguments.put(larg.getName(), larg); return factory.createFunctionalConstraint(function, functionArguments); case FTSParser.RANGE: - throw new FTSQueryException("Unsupported FTS option " + testNode.getText()); + functionName = FTSRange.NAME; + function = factory.getFunction(functionName); + functionArguments = new LinkedHashMap(); + larg = factory.createLiteralArgument(FTSRange.ARG_FROM_INC, DataTypeDefinition.BOOLEAN, testNode.getChild(0).getType() == FTSParser.INCLUSIVE); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSRange.ARG_FROM, DataTypeDefinition.TEXT, getText(testNode.getChild(1))); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSRange.ARG_TO, DataTypeDefinition.TEXT, getText(testNode.getChild(2))); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSRange.ARG_TO_INC, DataTypeDefinition.BOOLEAN, testNode.getChild(3).getType() == FTSParser.INCLUSIVE); + functionArguments.put(larg.getName(), larg); + if (testNode.getChildCount() > 4) + { + parg = buildFieldReference(FTSExpandTerm.ARG_PROPERTY, (CommonTree) testNode.getChild(4), factory, functionEvaluationContext, selector, columns); + functionArguments.put(parg.getName(), parg); + } + return factory.createFunctionalConstraint(function, functionArguments); case FTSParser.FIELD_GROUP: CommonTree fieldReferenceNode = (CommonTree) testNode.getChild(0); CommonTree fieldExperssion = (CommonTree) testNode.getChild(1); @@ -504,7 +522,20 @@ public class FTSQueryParser functionArguments.put(parg.getName(), parg); return factory.createFunctionalConstraint(function, functionArguments); case FTSParser.FG_RANGE: - throw new FTSQueryException("Unsupported FTS option " + testNode.getText()); + functionName = FTSRange.NAME; + function = factory.getFunction(functionName); + functionArguments = new LinkedHashMap(); + larg = factory.createLiteralArgument(FTSRange.ARG_FROM_INC, DataTypeDefinition.BOOLEAN, testNode.getChild(0).getType() == FTSParser.INCLUSIVE); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSRange.ARG_FROM, DataTypeDefinition.TEXT, getText(testNode.getChild(1))); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSRange.ARG_TO, DataTypeDefinition.TEXT, getText(testNode.getChild(2))); + functionArguments.put(larg.getName(), larg); + larg = factory.createLiteralArgument(FTSRange.ARG_TO_INC, DataTypeDefinition.BOOLEAN, testNode.getChild(3).getType() == FTSParser.INCLUSIVE); + functionArguments.put(larg.getName(), larg); + parg = buildFieldReference(FTSExpandTerm.ARG_PROPERTY, fieldReferenceNode, factory, functionEvaluationContext, selector, columns); + functionArguments.put(parg.getName(), parg); + return factory.createFunctionalConstraint(function, functionArguments); default: throw new FTSQueryException("Unsupported FTS option " + testNode.getText()); } diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSProximity.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSProximity.java index 58583d55e5..b658a0ed88 100644 --- a/source/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSProximity.java +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSProximity.java @@ -70,8 +70,7 @@ public class FTSProximity extends BaseFunction } public Serializable getValue(Map args, FunctionEvaluationContext context) { - // TODO Auto-generated method stub - return null; + throw new UnsupportedOperationException(); } } diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSRange.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSRange.java new file mode 100644 index 0000000000..e1f46b0389 --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/functions/FTSRange.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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 General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.search.impl.querymodel.impl.functions; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.ArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.Multiplicity; +import org.alfresco.repo.search.impl.querymodel.impl.BaseArgumentDefinition; +import org.alfresco.repo.search.impl.querymodel.impl.BaseFunction; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; + +public class FTSRange extends BaseFunction +{ + public final static String NAME = "FTSRange"; + + public final static String ARG_FROM_INC = "FromInc"; + + public final static String ARG_FROM = "From"; + + public final static String ARG_TO = "To"; + + public final static String ARG_TO_INC = "ToInc"; + + public final static String ARG_PROPERTY = "Property"; + + public static LinkedHashMap args; + + static + { + args = new LinkedHashMap(); + args.put(ARG_FROM_INC, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_FROM_INC, DataTypeDefinition.BOOLEAN, true)); + args.put(ARG_FROM, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_FROM, DataTypeDefinition.TEXT, true)); + args.put(ARG_TO, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_TO, DataTypeDefinition.TEXT, true)); + args.put(ARG_TO_INC, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_TO_INC, DataTypeDefinition.BOOLEAN, true)); + args.put(ARG_PROPERTY, new BaseArgumentDefinition(Multiplicity.SINGLE_VALUED, ARG_PROPERTY, DataTypeDefinition.ANY, false)); + } + + /** + * @param name + * @param returnType + * @param argumentDefinitions + */ + public FTSRange() + { + super(NAME, DataTypeDefinition.BOOLEAN, args); + } + + + public Serializable getValue(Map args, FunctionEvaluationContext context) + { + throw new UnsupportedOperationException(); + } + +} diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryModelFactory.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryModelFactory.java index 26fc8183d4..2c5daccfbb 100644 --- a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryModelFactory.java +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryModelFactory.java @@ -74,6 +74,7 @@ import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneFTSE import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneFTSExpandTerm; import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneFTSPhrase; import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneFTSProximity; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneFTSRange; import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneFTSTerm; import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneGreaterThan; import org.alfresco.repo.search.impl.querymodel.impl.lucene.functions.LuceneGreaterThanOrEquals; @@ -121,6 +122,7 @@ public class LuceneQueryModelFactory implements QueryModelFactory functions.put(FTSPhrase.NAME, new LuceneFTSPhrase()); functions.put(LuceneFTSExpandTerm.NAME, new LuceneFTSExpandTerm()); functions.put(LuceneFTSProximity.NAME, new LuceneFTSProximity()); + functions.put(LuceneFTSRange.NAME, new LuceneFTSRange()); } diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSProximity.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSProximity.java index d367d52f35..9618580995 100644 --- a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSProximity.java +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSProximity.java @@ -78,7 +78,7 @@ public class LuceneFTSProximity extends FTSProximity implements LuceneQueryBuild if (propArg != null) { String prop = propArg.getPropertyName(); - query = lqp.getSpanQuery(prop, first, last, slop, true); + query = lqp.getSpanQuery(functionContext.getLuceneFieldName(prop), first, last, slop, true); } else { diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSRange.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSRange.java new file mode 100644 index 0000000000..3229077400 --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSRange.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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 General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.search.impl.querymodel.impl.lucene.functions; + +import java.util.Map; +import java.util.Set; + +import org.alfresco.repo.search.impl.lucene.LuceneQueryParser; +import org.alfresco.repo.search.impl.querymodel.Argument; +import org.alfresco.repo.search.impl.querymodel.FunctionEvaluationContext; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.impl.functions.FTSRange; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent; +import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderContext; +import org.apache.lucene.queryParser.ParseException; +import org.apache.lucene.search.Query; + +public class LuceneFTSRange extends FTSRange implements LuceneQueryBuilderComponent +{ + /** + * + */ + public LuceneFTSRange() + { + super(); + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderComponent#addComponent(org.apache.lucene.search.BooleanQuery, + * org.apache.lucene.search.BooleanQuery, org.alfresco.service.cmr.dictionary.DictionaryService, + * java.lang.String) + */ + public Query addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) + throws ParseException + { + LuceneQueryParser lqp = luceneContext.getLuceneQueryParser(); + Argument argument = functionArgs.get(ARG_FROM_INC); + Boolean fromInc = (Boolean) argument.getValue(functionContext); + argument = functionArgs.get(ARG_FROM); + String from = (String) argument.getValue(functionContext); + argument = functionArgs.get(ARG_TO); + String to = (String) argument.getValue(functionContext); + argument = functionArgs.get(ARG_TO_INC); + Boolean toInc = (Boolean) argument.getValue(functionContext); + + PropertyArgument propArg = (PropertyArgument) functionArgs.get(ARG_PROPERTY); + Query query; + if (propArg != null) + { + String prop = propArg.getPropertyName(); + query = lqp.getRangeQuery(functionContext.getLuceneFieldName(prop), from, to, fromInc, toInc); + } + else + { + query = lqp.getRangeQuery("TEXT", from, to, fromInc, toInc); + } + return query; + } +}