From e46585becff33af867b25db2bbe81b34953e14d4 Mon Sep 17 00:00:00 2001 From: Andrew Hind Date: Thu, 28 May 2009 10:34:51 +0000 Subject: [PATCH] More SearchService refactor. Added CMIS SQL to the search service. Tidy ups. FTS supports default namespace and templates via search parameters API. (MOB-568, MOB-569) git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@14463 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/cmis-api-context.xml | 33 +++- config/alfresco/core-services-context.xml | 22 +-- .../org/alfresco/cmis/CMISDataTypeEnum.java | 88 ++++++++-- .../java/org/alfresco/cmis/CMISResultSet.java | 31 +--- .../alfresco/cmis/CMISResultSetColumn.java | 16 +- .../alfresco/cmis/CMISResultSetMetaData.java | 4 +- .../org/alfresco/cmis/CMISResultSetRow.java | 62 +------- .../alfresco/cmis/CMISResultSetSelector.java | 12 +- .../alfresco/cmis/search/CMISQueryParser.java | 4 + .../cmis/search/CMISQueryServiceImpl.java | 16 +- .../cmis/search/CMISResultSetColumnImpl.java | 32 +++- .../cmis/search/CMISResultSetImpl.java | 76 ++++++++- .../search/CMISResultSetMetaDataImpl.java | 46 +++++- .../cmis/search/CMISResultSetRowImpl.java | 42 ++++- .../search/CMISResultSetSelectorImpl.java | 7 + .../repo/search/SimpleResultSetMetaData.java | 4 +- .../ADMLuceneIndexerAndSearcherFactory.java | 14 +- .../impl/lucene/ADMLuceneSearcherImpl.java | 72 ++++----- .../search/impl/lucene/ADMLuceneTest.java | 72 ++++++++- .../AVMLuceneIndexerAndSearcherFactory.java | 11 +- ...stractLuceneIndexerAndSearcherFactory.java | 14 ++ .../LuceneAlfrescoFtsQueryLanguage.java | 81 ++++++++++ .../LuceneAlfrescoSqlQueryLanguage.java | 99 ++++++++++++ .../LuceneCmisStrictSqlQueryLanguage.java | 99 ++++++++++++ .../impl/lucene/LuceneQueryLanguageSPI.java | 58 +++++++ .../search/impl/lucene/LuceneQueryParser.java | 5 + .../impl/lucene/LuceneResultSetRow.java | 8 - .../AlfrescoFunctionEvaluationContext.java | 44 ++++- .../repo/search/impl/parsers/CMISLexer.java | 2 +- .../repo/search/impl/parsers/CMISParser.java | 32 ++-- .../repo/search/impl/parsers/FTSLexer.java | 2 +- .../repo/search/impl/parsers/FTSParser.java | 32 ++-- .../repo/search/impl/parsers/fts_test.gunit | 2 + .../impl/lucene/LuceneConjunction.java | 2 +- .../impl/lucene/LuceneDisjunction.java | 2 - .../impl/lucene/LucenePropertyArgument.java | 4 +- .../querymodel/impl/lucene/LuceneQuery.java | 1 + .../impl/lucene/LuceneQueryBuilder.java | 15 ++ .../lucene/LuceneQueryBuilderComponent.java | 9 ++ .../lucene/LuceneQueryBuilderContext.java | 14 +- .../impl/lucene/LuceneQueryEngine.java | 1 - .../impl/lucene/LuceneQueryModelFactory.java | 5 +- .../lucene/functions/LuceneFTSFuzzyTerm.java | 5 + .../lucene/functions/LuceneFTSPrefixTerm.java | 5 + .../lucene/functions/LuceneFTSProximity.java | 5 + .../impl/lucene/functions/LuceneFTSRange.java | 5 + .../lucene/functions/LuceneFTSWildTerm.java | 5 + .../search/results/ResultSetSPIWrapper.java | 143 +++++++++++++++++ .../service/cmr/search/ResultSet.java | 96 +---------- .../service/cmr/search/ResultSetMetaData.java | 4 +- .../service/cmr/search/ResultSetSPI.java | 138 ++++++++++++++++ .../service/cmr/search/SearchParameters.java | 150 +++++++++++++----- .../service/cmr/search/SearchService.java | 4 +- 53 files changed, 1365 insertions(+), 390 deletions(-) create mode 100644 source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoFtsQueryLanguage.java create mode 100644 source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoSqlQueryLanguage.java create mode 100644 source/java/org/alfresco/repo/search/impl/lucene/LuceneCmisStrictSqlQueryLanguage.java create mode 100644 source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryLanguageSPI.java create mode 100644 source/java/org/alfresco/repo/search/results/ResultSetSPIWrapper.java create mode 100644 source/java/org/alfresco/service/cmr/search/ResultSetSPI.java diff --git a/config/alfresco/cmis-api-context.xml b/config/alfresco/cmis-api-context.xml index be412bf99d..ba666d9f3b 100644 --- a/config/alfresco/cmis-api-context.xml +++ b/config/alfresco/cmis-api-context.xml @@ -2,7 +2,33 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -56,6 +82,9 @@ + + + @@ -85,5 +114,7 @@ + + \ No newline at end of file diff --git a/config/alfresco/core-services-context.xml b/config/alfresco/core-services-context.xml index 7fa7a866c7..41d28b145d 100644 --- a/config/alfresco/core-services-context.xml +++ b/config/alfresco/core-services-context.xml @@ -510,6 +510,19 @@ + + + + + + + + + + + + + - - - ${lucene.maxAtomicTransformationTime} @@ -621,9 +631,6 @@ - - - ${lucene.maxAtomicTransformationTime} @@ -692,9 +699,6 @@ - - - ${lucene.maxAtomicTransformationTime} diff --git a/source/java/org/alfresco/cmis/CMISDataTypeEnum.java b/source/java/org/alfresco/cmis/CMISDataTypeEnum.java index 5ac924c2d5..afae90cfa0 100644 --- a/source/java/org/alfresco/cmis/CMISDataTypeEnum.java +++ b/source/java/org/alfresco/cmis/CMISDataTypeEnum.java @@ -24,6 +24,9 @@ */ package org.alfresco.cmis; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.namespace.QName; + /** * CMIS Property Types Enum * @@ -31,19 +34,74 @@ package org.alfresco.cmis; */ public enum CMISDataTypeEnum implements EnumLabel { - STRING("string"), - DECIMAL("decimal"), - INTEGER("integer"), - BOOLEAN("boolean"), - DATETIME("datetime"), - URI("uri"), - ID("id"), - XML("xml"), - HTML("html"); - - + STRING("string") + { + public QName getDefaultDataType() + { + return DataTypeDefinition.TEXT; + } + }, + DECIMAL("decimal") + { + public QName getDefaultDataType() + { + return DataTypeDefinition.DOUBLE; + } + }, + INTEGER("integer") + { + public QName getDefaultDataType() + { + return DataTypeDefinition.LONG; + } + }, + BOOLEAN("boolean") + { + public QName getDefaultDataType() + { + return DataTypeDefinition.BOOLEAN; + } + }, + DATETIME("datetime") + { + public QName getDefaultDataType() + { + return DataTypeDefinition.DATETIME; + } + }, + URI("uri") + { + public QName getDefaultDataType() + { + return DataTypeDefinition.TEXT; + } + }, + ID("id") + { + public QName getDefaultDataType() + { + return DataTypeDefinition.TEXT; + } + }, + XML("xml") + { + public QName getDefaultDataType() + { + return DataTypeDefinition.TEXT; + } + }, + HTML("html") + { + public QName getDefaultDataType() + { + return DataTypeDefinition.TEXT; + } + }; + + public abstract QName getDefaultDataType(); + private String label; - + /** * Construct * @@ -54,7 +112,9 @@ public enum CMISDataTypeEnum implements EnumLabel this.label = label; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.alfresco.cmis.EnumLabel#label() */ public String getLabel() @@ -62,5 +122,5 @@ public enum CMISDataTypeEnum implements EnumLabel return label; } - public static EnumFactory FACTORY = new EnumFactory(CMISDataTypeEnum.class, null, true); + public static EnumFactory FACTORY = new EnumFactory(CMISDataTypeEnum.class, null, true); } diff --git a/source/java/org/alfresco/cmis/CMISResultSet.java b/source/java/org/alfresco/cmis/CMISResultSet.java index 832a18ee7f..0f6b74da7f 100644 --- a/source/java/org/alfresco/cmis/CMISResultSet.java +++ b/source/java/org/alfresco/cmis/CMISResultSet.java @@ -24,6 +24,8 @@ */ package org.alfresco.cmis; +import org.alfresco.service.cmr.search.ResultSetSPI; + /** @@ -31,7 +33,7 @@ package org.alfresco.cmis; * * @author andyh */ -public interface CMISResultSet extends Iterable +public interface CMISResultSet extends ResultSetSPI { /** * Get the result set meta-data. @@ -39,13 +41,6 @@ public interface CMISResultSet extends Iterable */ public CMISResultSetMetaData getMetaData(); - /** - * Get the start point for this results set in the overall - * set of rows that match the query - this will be equal to the skip count - * set when executing the query. - * @return the start position - */ - public int getStart(); /** * Get the number of rows in this result set. @@ -60,25 +55,5 @@ public interface CMISResultSet extends Iterable */ public int getLength(); - /** - * Close the result set and release any resources held/ - * The result set is also bound to the transaction and will auto close at - * the end of the transaction. - */ - public void close(); - - /** - * Was this result set curtailed - are there more pages to the result set? - * @return true if there are more results - */ - public boolean hasMore(); - - - /** - * Get the given row - * @param i -the position in this result set - start + i gives the position in the overall result set - * @return the row - */ - public CMISResultSetRow getRow(int i); } diff --git a/source/java/org/alfresco/cmis/CMISResultSetColumn.java b/source/java/org/alfresco/cmis/CMISResultSetColumn.java index 08a679398e..9be3435540 100644 --- a/source/java/org/alfresco/cmis/CMISResultSetColumn.java +++ b/source/java/org/alfresco/cmis/CMISResultSetColumn.java @@ -24,6 +24,8 @@ */ package org.alfresco.cmis; +import org.alfresco.service.cmr.search.ResultSetColumn; + /** * The column meta data for a result set @@ -31,23 +33,17 @@ package org.alfresco.cmis; * @author andyh * */ -public interface CMISResultSetColumn -{ - /** - * The column name - * @return - the column name - */ - public String getName(); - +public interface CMISResultSetColumn extends ResultSetColumn +{ /** * The property definition if there is one for the column * @return - the property definition or null if it does not make sense for the column */ - public CMISPropertyDefinition getPropertyDefinition(); + public CMISPropertyDefinition getCMISPropertyDefinition(); /** * The type of the column * @return - the CMIS type for the column */ - public CMISDataTypeEnum getPropertyType(); + public CMISDataTypeEnum getCMISDataType(); } diff --git a/source/java/org/alfresco/cmis/CMISResultSetMetaData.java b/source/java/org/alfresco/cmis/CMISResultSetMetaData.java index 56b7944644..bc72fcf64c 100644 --- a/source/java/org/alfresco/cmis/CMISResultSetMetaData.java +++ b/source/java/org/alfresco/cmis/CMISResultSetMetaData.java @@ -24,6 +24,8 @@ */ package org.alfresco.cmis; +import org.alfresco.service.cmr.search.ResultSetMetaData; + /** * The meta data associated with a result set @@ -31,7 +33,7 @@ package org.alfresco.cmis; * @author andyh * */ -public interface CMISResultSetMetaData +public interface CMISResultSetMetaData extends ResultSetMetaData { /** * The selector meta-data. diff --git a/source/java/org/alfresco/cmis/CMISResultSetRow.java b/source/java/org/alfresco/cmis/CMISResultSetRow.java index 08e5cbf824..1f57107d61 100644 --- a/source/java/org/alfresco/cmis/CMISResultSetRow.java +++ b/source/java/org/alfresco/cmis/CMISResultSetRow.java @@ -24,10 +24,7 @@ */ package org.alfresco.cmis; -import java.io.Serializable; -import java.util.Map; - -import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.search.ResultSetRow; /** * A row in a CMISResultSet @@ -35,64 +32,11 @@ import org.alfresco.service.cmr.repository.NodeRef; * @author andyh * */ -public interface CMISResultSetRow +public interface CMISResultSetRow extends ResultSetRow { - /** - * Get all the column data. - * @return - a map of serializable column values with the column name as the key - */ - public Map getValues(); - - /** - * Get the data for a single column - * @param columnName - * @return the value - */ - public Serializable getValue(String columnName); - - /** - * Get the overall score. - * - * @return the overall score - */ - public float getScore(); - - /** - * Get the scores. - * @return a map of selector name to score. - */ - public Map getScores(); - - /** - * Get the score related to the named selector. - * @param selectorName - * @return - the score. - */ - public float getScore(String selectorName); - - /** - * Gets the node refs - * @return a map of selector name to node ref - */ - public Map getNodeRefs(); - - /** - * Gets the node ref related to the named selector - * @param selectorName - * @return the node ref - */ - public NodeRef getNodeRef(String selectorName); - - /** - * Get the index of this result set in the result set - * If you want the overall position in paged results you have to add the skipCount fo the result set. - * @return the index of the row. - */ - public int getIndex(); - /** * Get the result set for which this row is a member. * @return - the result set. */ - public CMISResultSet getResultSet(); + public CMISResultSet getCMISResultSet(); } diff --git a/source/java/org/alfresco/cmis/CMISResultSetSelector.java b/source/java/org/alfresco/cmis/CMISResultSetSelector.java index 76f563e618..73451a43c8 100644 --- a/source/java/org/alfresco/cmis/CMISResultSetSelector.java +++ b/source/java/org/alfresco/cmis/CMISResultSetSelector.java @@ -24,6 +24,8 @@ */ package org.alfresco.cmis; +import org.alfresco.service.cmr.search.ResultSetSelector; + /** * The meta-data for a result set selector. @@ -31,14 +33,8 @@ package org.alfresco.cmis; * @author andyh * */ -public interface CMISResultSetSelector -{ - /** - * The name of the selector - * @return - the selector name - */ - public String getName(); - +public interface CMISResultSetSelector extends ResultSetSelector +{ /** * Get the type definition for the selector. * @return - the CMIS type definition. diff --git a/source/java/org/alfresco/cmis/search/CMISQueryParser.java b/source/java/org/alfresco/cmis/search/CMISQueryParser.java index 7541b21d98..26cc43ee94 100644 --- a/source/java/org/alfresco/cmis/search/CMISQueryParser.java +++ b/source/java/org/alfresco/cmis/search/CMISQueryParser.java @@ -1049,6 +1049,10 @@ public class CMISQueryParser qualifer = columnReferenceNode.getChild(1).getText(); } CMISPropertyDefinition propDef = cmisDictionaryService.findProperty(cmisPropertyName, null); + if(propDef == null) + { + throw new CMISQueryException("Unknown column/property " + cmisPropertyName); + } return factory.createPropertyArgument(argumentName, propDef.isQueryable(), propDef.isOrderable(), qualifer, propDef.getPropertyId().getName()); } diff --git a/source/java/org/alfresco/cmis/search/CMISQueryServiceImpl.java b/source/java/org/alfresco/cmis/search/CMISQueryServiceImpl.java index 3c0f406741..58a4b17a57 100644 --- a/source/java/org/alfresco/cmis/search/CMISQueryServiceImpl.java +++ b/source/java/org/alfresco/cmis/search/CMISQueryServiceImpl.java @@ -38,6 +38,7 @@ import org.alfresco.cmis.CMISServices; import org.alfresco.repo.search.impl.querymodel.Query; import org.alfresco.repo.search.impl.querymodel.QueryEngine; import org.alfresco.repo.search.impl.querymodel.QueryEngineResults; +import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.search.ResultSet; @@ -53,6 +54,8 @@ public class CMISQueryServiceImpl implements CMISQueryService private QueryEngine queryEngine; private NodeService nodeService; + + private DictionaryService alfrescoDictionaryService; /** * @param service @@ -90,6 +93,17 @@ public class CMISQueryServiceImpl implements CMISQueryService this.nodeService = nodeService; } + + + /** + * @param alfrescoDictionaryService + * the Alfresco Dictionary Service to set + */ + public void setAlfrescoDictionaryService(DictionaryService alfrescoDictionaryService) + { + this.alfrescoDictionaryService = alfrescoDictionaryService; + } + /* * (non-Javadoc) * @@ -121,7 +135,7 @@ public class CMISQueryServiceImpl implements CMISQueryService wrapped.put(selector, current); } } - CMISResultSet cmis = new CMISResultSetImpl(wrapped, options, nodeService, query, cmisDictionaryService); + CMISResultSet cmis = new CMISResultSetImpl(wrapped, options, nodeService, query, cmisDictionaryService, alfrescoDictionaryService); return cmis; } diff --git a/source/java/org/alfresco/cmis/search/CMISResultSetColumnImpl.java b/source/java/org/alfresco/cmis/search/CMISResultSetColumnImpl.java index 034547530e..188464e9f9 100644 --- a/source/java/org/alfresco/cmis/search/CMISResultSetColumnImpl.java +++ b/source/java/org/alfresco/cmis/search/CMISResultSetColumnImpl.java @@ -25,8 +25,10 @@ package org.alfresco.cmis.search; import org.alfresco.cmis.CMISDataTypeEnum; +import org.alfresco.cmis.CMISDictionaryService; import org.alfresco.cmis.CMISPropertyDefinition; import org.alfresco.cmis.CMISResultSetColumn; +import org.alfresco.service.namespace.QName; /** * @author andyh @@ -39,13 +41,19 @@ public class CMISResultSetColumnImpl implements CMISResultSetColumn private CMISPropertyDefinition propertyDefinition; - private CMISDataTypeEnum propertyType; + private CMISDataTypeEnum dataType; - CMISResultSetColumnImpl(String name, CMISPropertyDefinition propertyDefinition, CMISDataTypeEnum propertyType) + private QName alfrescoPropertyQName; + + private QName alfrescoDataTypeQName; + + CMISResultSetColumnImpl(String name, CMISPropertyDefinition propertyDefinition, CMISDataTypeEnum dataType, QName alfrescoPropertyQName, QName alfrescoDataTypeQName) { this.name = name; this.propertyDefinition = propertyDefinition; - this.propertyType = propertyType; + this.dataType = dataType; + this.alfrescoPropertyQName = alfrescoPropertyQName; + this.alfrescoDataTypeQName = alfrescoDataTypeQName; } @@ -60,7 +68,7 @@ public class CMISResultSetColumnImpl implements CMISResultSetColumn /* (non-Javadoc) * @see org.alfresco.cmis.search.CMISResultSetColumn#getPropertyDefinition() */ - public CMISPropertyDefinition getPropertyDefinition() + public CMISPropertyDefinition getCMISPropertyDefinition() { return propertyDefinition; } @@ -68,9 +76,21 @@ public class CMISResultSetColumnImpl implements CMISResultSetColumn /* (non-Javadoc) * @see org.alfresco.cmis.search.CMISResultSetColumn#getPropertyType() */ - public CMISDataTypeEnum getPropertyType() + public CMISDataTypeEnum getCMISDataType() { - return propertyType; + return dataType; + } + + + public QName getDataType() + { + return alfrescoDataTypeQName; + } + + + public QName getPropertyType() + { + return alfrescoPropertyQName; } } diff --git a/source/java/org/alfresco/cmis/search/CMISResultSetImpl.java b/source/java/org/alfresco/cmis/search/CMISResultSetImpl.java index c71f65c0a1..ccb5e72a47 100644 --- a/source/java/org/alfresco/cmis/search/CMISResultSetImpl.java +++ b/source/java/org/alfresco/cmis/search/CMISResultSetImpl.java @@ -25,9 +25,11 @@ package org.alfresco.cmis.search; import java.io.Serializable; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; @@ -37,10 +39,13 @@ import org.alfresco.cmis.CMISResultSet; import org.alfresco.cmis.CMISResultSetMetaData; import org.alfresco.cmis.CMISResultSetRow; import org.alfresco.repo.search.impl.querymodel.Query; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.search.LimitBy; import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.ResultSetRow; /** * @author andyh @@ -58,15 +63,18 @@ public class CMISResultSetImpl implements CMISResultSet, Serializable Query query; CMISDictionaryService cmisDictionaryService; + + DictionaryService alfrescoDictionaryService; - public CMISResultSetImpl(Map wrapped, CMISQueryOptions options, NodeService nodeService, Query query, CMISDictionaryService cmisDictionaryService) + public CMISResultSetImpl(Map wrapped, CMISQueryOptions options, NodeService nodeService, Query query, CMISDictionaryService cmisDictionaryService, DictionaryService alfrescoDictionaryService) { this.wrapped = wrapped; this.options = options; this.nodeService = nodeService; this.query = query; this.cmisDictionaryService = cmisDictionaryService; + this.alfrescoDictionaryService = alfrescoDictionaryService; } /* @@ -95,7 +103,7 @@ public class CMISResultSetImpl implements CMISResultSet, Serializable */ public CMISResultSetMetaData getMetaData() { - return new CMISResultSetMetaDataImpl(options, query, cmisDictionaryService); + return new CMISResultSetMetaDataImpl(options, query, cmisDictionaryService, alfrescoDictionaryService); } /* @@ -197,4 +205,68 @@ public class CMISResultSetImpl implements CMISResultSet, Serializable return scores; } + public ChildAssociationRef getChildAssocRef(int n) + { + NodeRef nodeRef = getNodeRef(n); + return nodeService.getPrimaryParent(nodeRef); + } + + + + public List getChildAssocRefs() + { + ArrayList cars = new ArrayList(length()); + for (ResultSetRow row : this) + { + cars.add(row.getChildAssocRef()); + } + return cars; + } + + public NodeRef getNodeRef(int n) + { + Map refs = getNodeRefs(n); + if(refs.size() == 1) + { + return refs.values().iterator().next(); + } + else + { + throw new IllegalStateException("Ambiguous selector"); + } + } + + public List getNodeRefs() + { + ArrayList nodeRefs = new ArrayList(length()); + for (ResultSetRow row : this) + { + nodeRefs.add(row.getNodeRef()); + } + return nodeRefs; + } + + public CMISResultSetMetaData getResultSetMetaData() + { + return getMetaData(); + } + + public float getScore(int n) + { + Map scores = getScores(n); + if(scores.size() == 1) + { + return scores.values().iterator().next(); + } + else + { + throw new IllegalStateException("Ambiguous selector"); + } + } + + public int length() + { + return getLength(); + } + } diff --git a/source/java/org/alfresco/cmis/search/CMISResultSetMetaDataImpl.java b/source/java/org/alfresco/cmis/search/CMISResultSetMetaDataImpl.java index 6cc10168da..f71b7aa2b1 100644 --- a/source/java/org/alfresco/cmis/search/CMISResultSetMetaDataImpl.java +++ b/source/java/org/alfresco/cmis/search/CMISResultSetMetaDataImpl.java @@ -40,6 +40,12 @@ import org.alfresco.repo.search.impl.querymodel.PropertyArgument; import org.alfresco.repo.search.impl.querymodel.Query; import org.alfresco.repo.search.impl.querymodel.Selector; import org.alfresco.repo.search.impl.querymodel.impl.functions.PropertyAccessor; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.search.LimitBy; +import org.alfresco.service.cmr.search.PermissionEvaluationMode; +import org.alfresco.service.cmr.search.ResultSetType; +import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.namespace.QName; /** @@ -53,7 +59,7 @@ public class CMISResultSetMetaDataImpl implements CMISResultSetMetaData private Map selectorMetaData; - public CMISResultSetMetaDataImpl(CMISQueryOptions options, Query query, CMISDictionaryService cmisDictionaryService) + public CMISResultSetMetaDataImpl(CMISQueryOptions options, Query query, CMISDictionaryService cmisDictionaryService, DictionaryService alfrescoDictionaryService) { this.options = options; @@ -71,10 +77,22 @@ public class CMISResultSetMetaDataImpl implements CMISResultSetMetaData { CMISPropertyDefinition propertyDefinition = null; CMISDataTypeEnum type = null; + QName alfrescoPropertyQName = null; + QName alfrescoDataTypeQName = null; if (column.getFunction().getName().equals(PropertyAccessor.NAME)) { PropertyArgument arg = (PropertyArgument) column.getFunctionArguments().get(PropertyAccessor.ARG_PROPERTY); String propertyName = arg.getPropertyName(); + alfrescoPropertyQName = QName.createQName(propertyName); + PropertyDefinition alfPropDef = alfrescoDictionaryService.getProperty(alfrescoPropertyQName); + if(alfPropDef == null) + { + alfrescoPropertyQName = null; + } + else + { + alfrescoDataTypeQName = alfPropDef.getDataType().getName(); + } propertyDefinition = cmisDictionaryService.findProperty(propertyName, null); type = propertyDefinition.getDataType(); } @@ -82,7 +100,11 @@ public class CMISResultSetMetaDataImpl implements CMISResultSetMetaData { type = cmisDictionaryService.findDataType(column.getFunction().getReturnType()); } - CMISResultSetColumn cmd = new CMISResultSetColumnImpl(column.getAlias(), propertyDefinition, type); + if(alfrescoDataTypeQName == null) + { + alfrescoDataTypeQName = type.getDefaultDataType(); + } + CMISResultSetColumn cmd = new CMISResultSetColumnImpl(column.getAlias(), propertyDefinition, type, alfrescoPropertyQName, alfrescoDataTypeQName); columnMetaData.put(cmd.getName(), cmd); } } @@ -157,4 +179,24 @@ public class CMISResultSetMetaDataImpl implements CMISResultSetMetaData return selectorMetaData.values().toArray(new CMISResultSetSelector[0]); } + public LimitBy getLimitedBy() + { + throw new UnsupportedOperationException(); + } + + public PermissionEvaluationMode getPermissionEvaluationMode() + { + throw new UnsupportedOperationException(); + } + + public ResultSetType getResultSetType() + { + return ResultSetType.COLUMN_AND_NODE_REF; + } + + public SearchParameters getSearchParameters() + { + throw new UnsupportedOperationException(); + } + } diff --git a/source/java/org/alfresco/cmis/search/CMISResultSetRowImpl.java b/source/java/org/alfresco/cmis/search/CMISResultSetRowImpl.java index 5f5db46eff..347a79f228 100644 --- a/source/java/org/alfresco/cmis/search/CMISResultSetRowImpl.java +++ b/source/java/org/alfresco/cmis/search/CMISResultSetRowImpl.java @@ -30,11 +30,16 @@ import java.util.Map; import org.alfresco.cmis.CMISDictionaryService; import org.alfresco.cmis.CMISResultSet; +import org.alfresco.cmis.CMISResultSetMetaData; import org.alfresco.cmis.CMISResultSetRow; import org.alfresco.repo.search.impl.querymodel.Column; import org.alfresco.repo.search.impl.querymodel.Query; +import org.alfresco.repo.search.results.ResultSetSPIWrapper; +import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.namespace.QName; /** * @author andyh @@ -87,9 +92,9 @@ public class CMISResultSetRowImpl implements CMISResultSetRow * * @see org.alfresco.cmis.search.CMISResultSetRow#getResultSet() */ - public CMISResultSet getResultSet() + public ResultSet getResultSet() { - return resultSet; + return new ResultSetSPIWrapper(resultSet); } /* @@ -186,4 +191,37 @@ public class CMISResultSetRowImpl implements CMISResultSetRow return answer; } + public CMISResultSet getCMISResultSet() + { + return resultSet; + } + + public ChildAssociationRef getChildAssocRef() + { + NodeRef nodeRef = getNodeRef(); + return nodeService.getPrimaryParent(nodeRef); + } + + public NodeRef getNodeRef() + { + if(getCMISResultSet().getMetaData().getColumns().length == 1) + { + return getNodeRef(getCMISResultSet().getMetaData().getColumns()[0].getName()); + } + else + { + throw new UnsupportedOperationException("Ambiguous selector"); + } + } + + public QName getQName() + { + return getChildAssocRef().getQName(); + } + + public Serializable getValue(QName qname) + { + throw new UnsupportedOperationException(); + } + } diff --git a/source/java/org/alfresco/cmis/search/CMISResultSetSelectorImpl.java b/source/java/org/alfresco/cmis/search/CMISResultSetSelectorImpl.java index 191077fbb7..f74e881577 100644 --- a/source/java/org/alfresco/cmis/search/CMISResultSetSelectorImpl.java +++ b/source/java/org/alfresco/cmis/search/CMISResultSetSelectorImpl.java @@ -26,6 +26,7 @@ package org.alfresco.cmis.search; import org.alfresco.cmis.CMISResultSetSelector; import org.alfresco.cmis.CMISTypeDefinition; +import org.alfresco.service.namespace.QName; /** * @author andyh @@ -60,4 +61,10 @@ public class CMISResultSetSelectorImpl implements CMISResultSetSelector return typeDefinition; } + + public QName getType() + { + return typeDefinition.getTypeId().getQName(); + } + } diff --git a/source/java/org/alfresco/repo/search/SimpleResultSetMetaData.java b/source/java/org/alfresco/repo/search/SimpleResultSetMetaData.java index d9897903e8..940539d1ac 100644 --- a/source/java/org/alfresco/repo/search/SimpleResultSetMetaData.java +++ b/source/java/org/alfresco/repo/search/SimpleResultSetMetaData.java @@ -86,7 +86,7 @@ public class SimpleResultSetMetaData implements ResultSetMetaData throw new UnsupportedOperationException(); } - public ResultSetColumn getColumns() + public ResultSetColumn[] getColumns() { throw new UnsupportedOperationException(); } @@ -106,7 +106,7 @@ public class SimpleResultSetMetaData implements ResultSetMetaData throw new UnsupportedOperationException(); } - public ResultSetSelector getSelectors() + public ResultSetSelector[] getSelectors() { throw new UnsupportedOperationException(); } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerAndSearcherFactory.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerAndSearcherFactory.java index 8713ee049b..34d4d4ee22 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerAndSearcherFactory.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneIndexerAndSearcherFactory.java @@ -26,6 +26,7 @@ package org.alfresco.repo.search.impl.lucene; import java.util.List; +import org.alfresco.cmis.CMISQueryService; import org.alfresco.repo.search.SearcherException; import org.alfresco.repo.search.SupportsBackgroundIndexing; import org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexer; @@ -53,8 +54,6 @@ public class ADMLuceneIndexerAndSearcherFactory extends AbstractLuceneIndexerAnd protected FullTextSearchIndexer fullTextSearchIndexer; protected ContentService contentService; - - private QueryEngine queryEngine; /** * Set the dictinary service @@ -98,13 +97,6 @@ public class ADMLuceneIndexerAndSearcherFactory extends AbstractLuceneIndexerAnd this.contentService = contentService; } - - - public void setQueryEngine(QueryEngine queryEngine) - { - this.queryEngine = queryEngine; - } - protected LuceneIndexer createIndexer(StoreRef storeRef, String deltaId) { storeRef = tenantService.getName(storeRef); @@ -131,8 +123,8 @@ public class ADMLuceneIndexerAndSearcherFactory extends AbstractLuceneIndexerAnd searcher.setTenantService(tenantService); searcher.setDictionaryService(dictionaryService); searcher.setQueryRegister(getQueryRegister()); - searcher.setQueryEngine(queryEngine); searcher.setDictionaryService(dictionaryService); + searcher.setQueryLanguages(queryLanguages); return searcher; } @@ -144,8 +136,8 @@ public class ADMLuceneIndexerAndSearcherFactory extends AbstractLuceneIndexerAnd searcher.setTenantService(tenantService); searcher.setDictionaryService(dictionaryService); searcher.setQueryRegister(getQueryRegister()); - searcher.setQueryEngine(queryEngine); searcher.setDictionaryService(dictionaryService); + searcher.setQueryLanguages(queryLanguages); return searcher; } 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 1a50763833..00a950c687 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java @@ -37,6 +37,10 @@ import java.util.Locale; import java.util.Map; import java.util.Set; +import org.alfresco.cmis.CMISQueryOptions; +import org.alfresco.cmis.CMISQueryService; +import org.alfresco.cmis.CMISResultSetMetaData; +import org.alfresco.cmis.CMISResultSetRow; import org.alfresco.i18n.I18NUtil; import org.alfresco.model.ContentModel; import org.alfresco.repo.search.CannedQueryDef; @@ -54,6 +58,7 @@ import org.alfresco.repo.search.impl.querymodel.QueryEngineResults; import org.alfresco.repo.search.impl.querymodel.QueryModelFactory; import org.alfresco.repo.search.impl.querymodel.QueryOptions; import org.alfresco.repo.search.impl.querymodel.QueryOptions.Connective; +import org.alfresco.repo.search.results.ResultSetSPIWrapper; import org.alfresco.repo.search.results.SortedResultSet; import org.alfresco.repo.tenant.TenantService; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; @@ -118,7 +123,7 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS private LuceneIndexer indexer; - private QueryEngine queryEngine; + private Map queryLanguages; /* * Searcher implementation @@ -176,6 +181,26 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS this.namespacePrefixResolver = namespacePrefixResolver; } + public NamespacePrefixResolver getNamespacePrefixResolver() + { + return namespacePrefixResolver; + } + + public NodeService getNodeService() + { + return nodeService; + } + + public TenantService getTenantService() + { + return tenantService; + } + + public QueryRegisterComponent getQueryRegister() + { + return queryRegister; + } + public boolean indexExists() { // return mainIndexExists(); @@ -192,11 +217,6 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS this.tenantService = tenantService; } - public void setQueryEngine(QueryEngine queryEngine) - { - this.queryEngine = queryEngine; - } - /** * Set the query register * @@ -207,6 +227,11 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS this.queryRegister = queryRegister; } + public void setQueryLanguages(Map queryLanguages) + { + this.queryLanguages = queryLanguages; + } + public ResultSet query(StoreRef store, String language, String queryString, QueryParameterDefinition[] queryParameterDefinitions) throws SearcherException { store = tenantService.getName(store); @@ -460,42 +485,17 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS throw new SearcherException("IO exception during search", e); } } - else if (searchParameters.getLanguage().equalsIgnoreCase(SearchService.LANGUAGE_FTS_ALFRESCO)) + else { - String ftsExpression = searchParameters.getQuery(); - FTSQueryParser ftsQueryParser = new FTSQueryParser(); - QueryModelFactory factory = queryEngine.getQueryModelFactory(); - AlfrescoFunctionEvaluationContext context = new AlfrescoFunctionEvaluationContext(namespacePrefixResolver, getDictionaryService()); - - QueryOptions options = new QueryOptions(searchParameters.getQuery(), null); - options.setFetchSize(searchParameters.getBulkFecthSize()); - options.setIncludeInTransactionData(!searchParameters.excludeDataInTheCurrentTransaction()); - options.setDefaultFTSConnective(searchParameters.getDefaultOperator() == SearchParameters.Operator.OR ? Connective.OR : Connective.AND); - options.setDefaultFTSFieldConnective(searchParameters.getDefaultOperator() == SearchParameters.Operator.OR ? Connective.OR : Connective.AND); - if (searchParameters.getLimitBy() == LimitBy.FINAL_SIZE) + LuceneQueryLanguageSPI language = queryLanguages.get(searchParameters.getLanguage().toLowerCase()); + if (language != null) { - options.setMaxItems(searchParameters.getLimit()); + return language.executQuery(searchParameters, this); } else { - options.setMaxItems(-1); + throw new SearcherException("Unknown query language: " + searchParameters.getLanguage()); } - options.setMlAnalaysisMode(searchParameters.getMlAnalaysisMode()); - options.setLocales(searchParameters.getLocales()); - options.setStores(searchParameters.getStores()); - - HashMap templates = new HashMap(); - templates.put("ANDY", "%(cm:content, cm:title)"); - Constraint constraint = ftsQueryParser.buildFTS(ftsExpression, factory, context, null, null, options.getDefaultFTSConnective(), options.getDefaultFTSFieldConnective(), - templates); - org.alfresco.repo.search.impl.querymodel.Query query = factory.createQuery(null, null, constraint, null); - - QueryEngineResults results = queryEngine.executeQuery(query, options, context); - return results.getResults().values().iterator().next(); - } - else - { - throw new SearcherException("Unknown query language: " + searchParameters.getLanguage()); } } 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 cd0e12d601..d45568dcd7 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneTest.java @@ -639,6 +639,56 @@ public class ADMLuceneTest extends TestCase } + public void testAlfrescoSql() throws InterruptedException + { + luceneFTS.pause(); + buildBaseIndex(); + + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + searcher.setNodeService(nodeService); + searcher.setDictionaryService(dictionaryService); + searcher.setTenantService(tenantService); + searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); + searcher.setQueryRegister(queryRegisterComponent); + searcher.setQueryLanguages(((AbstractLuceneIndexerAndSearcherFactory) indexerAndSearcher).queryLanguages); + + alfrescoSqlQueryWithCount(searcher, "SELECT * FROM DOCUMENT", 1); + alfrescoSqlQueryWithCount(searcher, "SELECT * FROM DOCUMENT D JOIN CM_OWNABLE O ON (D.OBJECTID = O.OBJECTID)", 0); + } + + public void alfrescoSqlQueryWithCount(ADMLuceneSearcherImpl searcher, String query, int count) + { + ResultSet results = searcher.query(rootNodeRef.getStoreRef(), SearchService.LANGUAGE_SQL_ALFTRESCO, query, null); + assertEquals(count, results.length()); + results.getResultSetMetaData(); + results.close(); + } + + public void testCmisSql() throws InterruptedException + { + luceneFTS.pause(); + buildBaseIndex(); + + ADMLuceneSearcherImpl searcher = ADMLuceneSearcherImpl.getSearcher(rootNodeRef.getStoreRef(), indexerAndSearcher); + searcher.setNodeService(nodeService); + searcher.setDictionaryService(dictionaryService); + searcher.setTenantService(tenantService); + searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); + searcher.setQueryRegister(queryRegisterComponent); + searcher.setQueryLanguages(((AbstractLuceneIndexerAndSearcherFactory) indexerAndSearcher).queryLanguages); + + sqlQueryWithCount(searcher, "SELECT * FROM DOCUMENT", 1); + sqlQueryWithCount(searcher, "SELECT * FROM DOCUMENT D WHERE CONTAINS(D,'lazy')", 1); + } + + public void sqlQueryWithCount(ADMLuceneSearcherImpl searcher, String query, int count) + { + ResultSet results = searcher.query(rootNodeRef.getStoreRef(), SearchService.LANGUAGE_SQL_CMIS_STRICT, query, null); + assertEquals(count, results.length()); + results.getResultSetMetaData(); + results.close(); + } + public void testFTS() throws InterruptedException { luceneFTS.pause(); @@ -650,7 +700,7 @@ public class ADMLuceneTest extends TestCase searcher.setTenantService(tenantService); searcher.setNamespacePrefixResolver(getNamespacePrefixReolsver("namespace")); searcher.setQueryRegister(queryRegisterComponent); - searcher.setQueryEngine(queryEngine); + searcher.setQueryLanguages(((AbstractLuceneIndexerAndSearcherFactory) indexerAndSearcher).queryLanguages); ftsQueryWithCount(searcher, "\"lazy\"", 1); ftsQueryWithCount(searcher, "lazy and dog", 1); @@ -837,12 +887,30 @@ public class ADMLuceneTest extends TestCase ftsQueryWithCount(searcher, "lazy^20 -lazy^20", 15, null, n14); ftsQueryWithCount(searcher, "cm:content:lazy", 1); + // Simple template ftsQueryWithCount(searcher, "ANDY:lazy", 1); + // default namesapce cm + ftsQueryWithCount(searcher, "content:lazy", 1); + + + ftsQueryWithCount(searcher, "PATH:\"//.\"", 15); + + ftsQueryWithCount(searcher, "+PATH:\"/app:company_home/st:sites/cm:rmtestnew1/cm:documentLibrary//*\"", 0); + ftsQueryWithCount(searcher, "+PATH:\"/app:company_home/st:sites/cm:rmtestnew1/cm:documentLibrary//*\" -TYPE:\"{http://www.alfresco.org/model/content/1.0}thumbnail\"", 15); + ftsQueryWithCount(searcher, "+PATH:\"/app:company_home/st:sites/cm:rmtestnew1/cm:documentLibrary//*\" AND -TYPE:\"{http://www.alfresco.org/model/content/1.0}thumbnail\"", 0); + } public void ftsQueryWithCount(ADMLuceneSearcherImpl searcher, String query, int count) { - ResultSet results = searcher.query(rootNodeRef.getStoreRef(), SearchService.LANGUAGE_FTS_ALFRESCO, query, null); + SearchParameters sp = new SearchParameters(); + sp.setLanguage( SearchService.LANGUAGE_FTS_ALFRESCO); + sp.addStore(rootNodeRef.getStoreRef()); + sp.setQuery(query); + sp.addQueryTemplate("ANDY", "%cm:content"); + sp.setNamespace(NamespaceService.CONTENT_MODEL_1_0_URI); + sp.excludeDataInTheCurrentTransaction(true); + ResultSet results = searcher.query(sp); assertEquals(count, results.length()); results.close(); } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerAndSearcherFactory.java b/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerAndSearcherFactory.java index 8593d53f9b..214ec25f8f 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerAndSearcherFactory.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/AVMLuceneIndexerAndSearcherFactory.java @@ -27,6 +27,7 @@ package org.alfresco.repo.search.impl.lucene; import java.util.ArrayList; import java.util.List; +import org.alfresco.cmis.CMISQueryService; import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.repo.content.ContentStore; import org.alfresco.repo.search.SearcherException; @@ -69,8 +70,6 @@ public class AVMLuceneIndexerAndSearcherFactory extends AbstractLuceneIndexerAnd private FullTextSearchIndexer fullTextSearchIndexer; - private QueryEngine queryEngine; - public AVMLuceneIndexerAndSearcherFactory() { //s_logger.error("Creating AVMLuceneIndexerAndSearcherFactory"); @@ -140,12 +139,6 @@ public class AVMLuceneIndexerAndSearcherFactory extends AbstractLuceneIndexerAnd { this.contentStore = contentStore; } - - - public void setQueryEngine(QueryEngine queryEngine) - { - this.queryEngine = queryEngine; - } @Override protected LuceneIndexer createIndexer(StoreRef storeRef, String deltaId) @@ -185,8 +178,8 @@ public class AVMLuceneIndexerAndSearcherFactory extends AbstractLuceneIndexerAnd searcher.setTenantService(tenantService); searcher.setDictionaryService(dictionaryService); searcher.setQueryRegister(getQueryRegister()); - searcher.setQueryEngine(queryEngine); searcher.setDictionaryService(dictionaryService); + searcher.setQueryLanguages(queryLanguages); return searcher; } diff --git a/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerAndSearcherFactory.java b/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerAndSearcherFactory.java index 1ddd4c25b8..2da803c2d6 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerAndSearcherFactory.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/AbstractLuceneIndexerAndSearcherFactory.java @@ -94,6 +94,8 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI private int queryMaxClauses; private int indexerBatchSize; + + protected Map queryLanguages = new HashMap(); /** * A map of active global transactions . It contains all the indexers a transaction has used, with at most one @@ -1782,6 +1784,18 @@ public abstract class AbstractLuceneIndexerAndSearcherFactory implements LuceneI this.postSortDateTime = postSortDateTime; } + + public void registerQueryLanguage(LuceneQueryLanguageSPI queryLanguage) + { + this.queryLanguages.put(queryLanguage.getName().toLowerCase(), queryLanguage); + } + + protected LuceneQueryLanguageSPI getQueryLanguage(String name) + { + return this.queryLanguages.get(name); + } + + protected abstract List getAllStores(); public R doWithAllWriteLocks(WithAllWriteLocksWork lockWork) diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoFtsQueryLanguage.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoFtsQueryLanguage.java new file mode 100644 index 0000000000..90a87bb205 --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoFtsQueryLanguage.java @@ -0,0 +1,81 @@ +package org.alfresco.repo.search.impl.lucene; + +import java.util.HashMap; +import java.util.List; + +import org.alfresco.repo.search.impl.parsers.AlfrescoFunctionEvaluationContext; +import org.alfresco.repo.search.impl.parsers.FTSQueryParser; +import org.alfresco.repo.search.impl.querymodel.Constraint; +import org.alfresco.repo.search.impl.querymodel.QueryEngine; +import org.alfresco.repo.search.impl.querymodel.QueryEngineResults; +import org.alfresco.repo.search.impl.querymodel.QueryModelFactory; +import org.alfresco.repo.search.impl.querymodel.QueryOptions; +import org.alfresco.repo.search.impl.querymodel.QueryOptions.Connective; +import org.alfresco.service.cmr.search.LimitBy; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchParameters; +import org.alfresco.service.cmr.search.SearchService; + +/** + * Alfresco FTS Query language support + * @author andyh + * + */ +public class LuceneAlfrescoFtsQueryLanguage implements LuceneQueryLanguageSPI +{ + QueryEngine queryEngine; + + /** + * Set the query engine + * @param queryEngine + */ + public void setQueryEngine(QueryEngine queryEngine) + { + this.queryEngine = queryEngine; + } + + public ResultSet executQuery(SearchParameters searchParameters, ADMLuceneSearcherImpl admLuceneSearcher) + { + String ftsExpression = searchParameters.getQuery(); + QueryModelFactory factory = queryEngine.getQueryModelFactory(); + AlfrescoFunctionEvaluationContext context = new AlfrescoFunctionEvaluationContext(admLuceneSearcher.getNamespacePrefixResolver(), admLuceneSearcher.getDictionaryService(), searchParameters.getNamespace()); + + QueryOptions options = new QueryOptions(searchParameters.getQuery(), null); + options.setFetchSize(searchParameters.getBulkFecthSize()); + options.setIncludeInTransactionData(!searchParameters.excludeDataInTheCurrentTransaction()); + options.setDefaultFTSConnective(searchParameters.getDefaultOperator() == SearchParameters.Operator.OR ? Connective.OR : Connective.AND); + options.setDefaultFTSFieldConnective(searchParameters.getDefaultOperator() == SearchParameters.Operator.OR ? Connective.OR : Connective.AND); + if (searchParameters.getLimitBy() == LimitBy.FINAL_SIZE) + { + options.setMaxItems(searchParameters.getLimit()); + } + else + { + options.setMaxItems(-1); + } + options.setMlAnalaysisMode(searchParameters.getMlAnalaysisMode()); + options.setLocales(searchParameters.getLocales()); + options.setStores(searchParameters.getStores()); + + Constraint constraint = FTSQueryParser.buildFTS(ftsExpression, factory, context, null, null, options.getDefaultFTSConnective(), options.getDefaultFTSFieldConnective(), + searchParameters.getQueryTemplates()); + org.alfresco.repo.search.impl.querymodel.Query query = factory.createQuery(null, null, constraint, null); + + QueryEngineResults results = queryEngine.executeQuery(query, options, context); + return results.getResults().values().iterator().next(); + } + + public String getName() + { + return SearchService.LANGUAGE_FTS_ALFRESCO; + } + + public void setFactories(List factories) + { + for (AbstractLuceneIndexerAndSearcherFactory factory : factories) + { + factory.registerQueryLanguage(this); + } + } + +} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoSqlQueryLanguage.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoSqlQueryLanguage.java new file mode 100644 index 0000000000..33afea8a03 --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneAlfrescoSqlQueryLanguage.java @@ -0,0 +1,99 @@ +/* + * 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.lucene; + +import java.util.List; + +import org.alfresco.cmis.CMISQueryOptions; +import org.alfresco.cmis.CMISQueryService; +import org.alfresco.cmis.CMISResultSetMetaData; +import org.alfresco.cmis.CMISResultSetRow; +import org.alfresco.cmis.CMISQueryOptions.CMISQueryMode; +import org.alfresco.repo.search.impl.querymodel.QueryOptions.Connective; +import org.alfresco.repo.search.results.ResultSetSPIWrapper; +import org.alfresco.service.cmr.search.LimitBy; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchParameters; +import org.alfresco.service.cmr.search.SearchService; + +/** + * Support for sql-cmis-strict in the search service + * @author andyh + * + */ +public class LuceneAlfrescoSqlQueryLanguage implements LuceneQueryLanguageSPI +{ + private CMISQueryService cmisQueryService; + + /** + * Set the search service + * + * @param cmisQueryService + */ + public void setCmisQueryService(CMISQueryService cmisQueryService) + { + this.cmisQueryService = cmisQueryService; + } + + public ResultSet executQuery(SearchParameters searchParameters, ADMLuceneSearcherImpl admLuceneSearcher) + { + String sql = searchParameters.getQuery(); + + CMISQueryOptions options = new CMISQueryOptions(sql, searchParameters.getStores().get(0)); + options.setDefaultFTSConnective(searchParameters.getDefaultOperator() == SearchParameters.Operator.OR ? Connective.OR : Connective.AND); + options.setDefaultFTSFieldConnective(searchParameters.getDefaultOperator() == SearchParameters.Operator.OR ? Connective.OR : Connective.AND); + options.setFetchSize(searchParameters.getBulkFecthSize()); + options.setIncludeInTransactionData(!searchParameters.excludeDataInTheCurrentTransaction()); + if (searchParameters.getLimitBy() == LimitBy.FINAL_SIZE) + { + options.setMaxItems(searchParameters.getLimit()); + } + else + { + options.setMaxItems(-1); + } + options.setMlAnalaysisMode(searchParameters.getMlAnalaysisMode()); + options.setLocales(searchParameters.getLocales()); + options.setStores(searchParameters.getStores()); + + options.setQueryMode(CMISQueryMode.CMS_WITH_ALFRESCO_EXTENSIONS); + + return new ResultSetSPIWrapper(cmisQueryService.query(options)); + } + + public String getName() + { + return SearchService.LANGUAGE_SQL_ALFTRESCO; + } + + public void setFactories(List factories) + { + for (AbstractLuceneIndexerAndSearcherFactory factory : factories) + { + factory.registerQueryLanguage(this); + } + } + +} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneCmisStrictSqlQueryLanguage.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneCmisStrictSqlQueryLanguage.java new file mode 100644 index 0000000000..4497eb5d8f --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneCmisStrictSqlQueryLanguage.java @@ -0,0 +1,99 @@ +/* + * 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.lucene; + +import java.util.List; + +import org.alfresco.cmis.CMISQueryOptions; +import org.alfresco.cmis.CMISQueryService; +import org.alfresco.cmis.CMISResultSetMetaData; +import org.alfresco.cmis.CMISResultSetRow; +import org.alfresco.cmis.CMISQueryOptions.CMISQueryMode; +import org.alfresco.repo.search.impl.querymodel.QueryOptions.Connective; +import org.alfresco.repo.search.results.ResultSetSPIWrapper; +import org.alfresco.service.cmr.search.LimitBy; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchParameters; +import org.alfresco.service.cmr.search.SearchService; + +/** + * Support for Alfresco SQL in the search service + * @author andyh + * + */ +public class LuceneCmisStrictSqlQueryLanguage implements LuceneQueryLanguageSPI +{ + private CMISQueryService cmisQueryService; + + /** + * Set the search service + * + * @param cmisQueryService + */ + public void setCmisQueryService(CMISQueryService cmisQueryService) + { + this.cmisQueryService = cmisQueryService; + } + + public ResultSet executQuery(SearchParameters searchParameters, ADMLuceneSearcherImpl admLuceneSearcher) + { + String sql = searchParameters.getQuery(); + + CMISQueryOptions options = new CMISQueryOptions(sql, searchParameters.getStores().get(0)); + options.setDefaultFTSConnective(searchParameters.getDefaultOperator() == SearchParameters.Operator.OR ? Connective.OR : Connective.AND); + options.setDefaultFTSFieldConnective(searchParameters.getDefaultOperator() == SearchParameters.Operator.OR ? Connective.OR : Connective.AND); + options.setFetchSize(searchParameters.getBulkFecthSize()); + options.setIncludeInTransactionData(!searchParameters.excludeDataInTheCurrentTransaction()); + if (searchParameters.getLimitBy() == LimitBy.FINAL_SIZE) + { + options.setMaxItems(searchParameters.getLimit()); + } + else + { + options.setMaxItems(-1); + } + options.setMlAnalaysisMode(searchParameters.getMlAnalaysisMode()); + options.setLocales(searchParameters.getLocales()); + options.setStores(searchParameters.getStores()); + + options.setQueryMode(CMISQueryMode.CMS_STRICT); + + return new ResultSetSPIWrapper(cmisQueryService.query(options)); + } + + public String getName() + { + return SearchService.LANGUAGE_SQL_CMIS_STRICT; + } + + public void setFactories(List factories) + { + for (AbstractLuceneIndexerAndSearcherFactory factory : factories) + { + factory.registerQueryLanguage(this); + } + } + +} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryLanguageSPI.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryLanguageSPI.java new file mode 100644 index 0000000000..2d80ee17a2 --- /dev/null +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryLanguageSPI.java @@ -0,0 +1,58 @@ +/* + * 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.lucene; + +import java.util.List; + +import org.alfresco.repo.search.impl.querymodel.QueryOptions; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.SearchParameters; +import org.apache.lucene.search.Searcher; + +/** + * @author andyh + * + */ +public interface LuceneQueryLanguageSPI +{ + /** + * The unique name for the query language + * @return - the unique name + */ + public String getName(); + + /** + * Execute the query + * @param searchParameters + * @param admLuceneSearcher + * @return - the query results + */ + public ResultSet executQuery(SearchParameters searchParameters, ADMLuceneSearcherImpl admLuceneSearcher); + + /** + * Register + */ + public void setFactories(List factories); +} diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryParser.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryParser.java index 70bd92ee42..aaf7b5b304 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryParser.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneQueryParser.java @@ -771,6 +771,11 @@ public class LuceneQueryParser extends QueryParser } return query; } + else if (field.equals("FTSSTATUS")) + { + TermQuery termQuery = new TermQuery(new Term(field, queryText)); + return termQuery; + } else { return getFieldQueryImpl(field, queryText, analysisMode); diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneResultSetRow.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneResultSetRow.java index 64d9ab489f..b0c157a488 100644 --- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneResultSetRow.java +++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneResultSetRow.java @@ -31,7 +31,6 @@ import org.alfresco.model.ContentModel; import org.alfresco.repo.search.AbstractResultSetRow; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.Path; import org.alfresco.service.namespace.QName; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; @@ -84,13 +83,6 @@ public class LuceneResultSetRow extends AbstractResultSetRow return lrs.getNodeService().getProperties(lrs.getNodeRef(getIndex())); } - public Serializable getValue(Path path) - { - // TODO: implement path base look up against the document or via the - // node service - throw new UnsupportedOperationException(); - } - public QName getQName() { Field field = getDocument().getField("QNAME"); 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 6e33c264fa..eb3ade2f86 100644 --- a/source/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java +++ b/source/java/org/alfresco/repo/search/impl/parsers/AlfrescoFunctionEvaluationContext.java @@ -26,6 +26,7 @@ package org.alfresco.repo.search.impl.parsers; import java.io.Serializable; import java.util.Collection; +import java.util.HashSet; import java.util.Map; import org.alfresco.repo.search.impl.lucene.LuceneQueryParser; @@ -41,14 +42,41 @@ import org.apache.lucene.search.Query; public class AlfrescoFunctionEvaluationContext implements FunctionEvaluationContext { + private static HashSet EXPOSED_FIELDS = new HashSet(); + private NamespacePrefixResolver namespacePrefixResolver; private DictionaryService dictionaryService; + + private String defaultNamespace; - public AlfrescoFunctionEvaluationContext(NamespacePrefixResolver namespacePrefixResolver, DictionaryService dictionaryService) + static + { + EXPOSED_FIELDS.add("PATH"); + EXPOSED_FIELDS.add("TEXT"); + EXPOSED_FIELDS.add("ID"); + EXPOSED_FIELDS.add("ISROOT"); + EXPOSED_FIELDS.add("ISNODE"); + EXPOSED_FIELDS.add("TX"); + EXPOSED_FIELDS.add("PARENT"); + EXPOSED_FIELDS.add("PRIMARYPARENT"); + EXPOSED_FIELDS.add("QNAME"); + EXPOSED_FIELDS.add("CLASS"); + EXPOSED_FIELDS.add("TYPE"); + EXPOSED_FIELDS.add("EXACTTYPE"); + EXPOSED_FIELDS.add("ASPECT"); + EXPOSED_FIELDS.add("EXACTASPECT"); + EXPOSED_FIELDS.add("ALL"); + EXPOSED_FIELDS.add("ISUNSET"); + EXPOSED_FIELDS.add("ISNULL"); + EXPOSED_FIELDS.add("ISNOTNULL"); + } + + public AlfrescoFunctionEvaluationContext(NamespacePrefixResolver namespacePrefixResolver, DictionaryService dictionaryService, String defaultNamespace) { this.namespacePrefixResolver = namespacePrefixResolver; this.dictionaryService = dictionaryService; + this.defaultNamespace = defaultNamespace; } public Query buildLuceneEquality(LuceneQueryParser lqp, String propertyName, Serializable value, PredicateMode mode) throws ParseException @@ -192,8 +220,20 @@ public class AlfrescoFunctionEvaluationContext implements FunctionEvaluationCont } } - return propertyName; + if(EXPOSED_FIELDS.contains(propertyName)) + { + return propertyName; + } + QName qname = QName.createQName(defaultNamespace, propertyName); + if (dictionaryService.getProperty(qname) != null) + { + return "@" + qname.toString(); + } + else + { + throw new FTSQueryException("Unknown property: "+propertyName); + } } diff --git a/source/java/org/alfresco/repo/search/impl/parsers/CMISLexer.java b/source/java/org/alfresco/repo/search/impl/parsers/CMISLexer.java index 40a81ed988..46ec78e0f3 100644 --- a/source/java/org/alfresco/repo/search/impl/parsers/CMISLexer.java +++ b/source/java/org/alfresco/repo/search/impl/parsers/CMISLexer.java @@ -1,4 +1,4 @@ -// $ANTLR !Unknown version! W:\\alfresco\\HEAD\\root\\projects\\Repository\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g 2009-05-20 17:49:31 +// $ANTLR !Unknown version! W:\\alfresco\\HEAD\\root\\projects\\Repository\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g 2009-05-26 10:05:04 package org.alfresco.repo.search.impl.parsers; import org.antlr.runtime.*; diff --git a/source/java/org/alfresco/repo/search/impl/parsers/CMISParser.java b/source/java/org/alfresco/repo/search/impl/parsers/CMISParser.java index a7900a94bd..c8a0acb9dd 100644 --- a/source/java/org/alfresco/repo/search/impl/parsers/CMISParser.java +++ b/source/java/org/alfresco/repo/search/impl/parsers/CMISParser.java @@ -1,4 +1,4 @@ -// $ANTLR !Unknown version! W:\\alfresco\\HEAD\\root\\projects\\Repository\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g 2009-05-20 17:49:30 +// $ANTLR !Unknown version! W:\\alfresco\\HEAD\\root\\projects\\Repository\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\CMIS.g 2009-05-26 10:05:01 package org.alfresco.repo.search.impl.parsers; import org.antlr.runtime.*; @@ -277,7 +277,7 @@ public class CMISParser extends Parser { // AST REWRITE - // elements: whereClause, orderByClause, selectList, fromClause + // elements: whereClause, fromClause, orderByClause, selectList // token labels: // rule labels: retval // token list labels: @@ -717,7 +717,7 @@ public class CMISParser extends Parser { // AST REWRITE - // elements: columnName, valueExpression + // elements: valueExpression, columnName // token labels: // rule labels: retval // token list labels: @@ -1111,7 +1111,7 @@ public class CMISParser extends Parser { // AST REWRITE - // elements: qualifier, columnName + // elements: columnName, qualifier // token labels: // rule labels: retval // token list labels: @@ -1256,7 +1256,7 @@ public class CMISParser extends Parser { // AST REWRITE - // elements: qualifier, multiValuedColumnName + // elements: multiValuedColumnName, qualifier // token labels: // rule labels: retval // token list labels: @@ -1384,7 +1384,7 @@ public class CMISParser extends Parser { // AST REWRITE - // elements: functionArgument, LPAREN, functionName, RPAREN + // elements: LPAREN, RPAREN, functionName, functionArgument // token labels: // rule labels: retval, functionName // token list labels: @@ -1597,7 +1597,7 @@ public class CMISParser extends Parser { // AST REWRITE - // elements: qualifier, columnName + // elements: columnName, qualifier // token labels: // rule labels: retval // token list labels: @@ -2049,7 +2049,7 @@ public class CMISParser extends Parser { // AST REWRITE - // elements: singleTable, joinedTable + // elements: joinedTable, singleTable // token labels: // rule labels: retval // token list labels: @@ -2401,7 +2401,7 @@ public class CMISParser extends Parser { // AST REWRITE - // elements: tableReference, joinSpecification, JOIN, joinType + // elements: tableReference, joinSpecification, joinType, JOIN // token labels: // rule labels: retval // token list labels: @@ -2529,7 +2529,7 @@ public class CMISParser extends Parser { // AST REWRITE - // elements: joinedTable, singleTable + // elements: singleTable, joinedTable // token labels: // rule labels: retval // token list labels: @@ -2788,7 +2788,7 @@ public class CMISParser extends Parser { // AST REWRITE - // elements: ON, lhs, rhs, EQUALS + // elements: EQUALS, ON, rhs, lhs // token labels: // rule labels: retval, rhs, lhs // token list labels: @@ -3638,7 +3638,7 @@ public class CMISParser extends Parser { // AST REWRITE - // elements: literalOrParameterName, compOp, valueExpression + // elements: compOp, literalOrParameterName, valueExpression // token labels: // rule labels: retval // token list labels: @@ -3999,7 +3999,7 @@ public class CMISParser extends Parser { // AST REWRITE - // elements: columnReference, inValueList, NOT + // elements: NOT, columnReference, inValueList // token labels: // rule labels: retval // token list labels: @@ -4244,7 +4244,7 @@ public class CMISParser extends Parser { // AST REWRITE - // elements: columnReference, NOT, characterStringLiteral + // elements: NOT, characterStringLiteral, columnReference // token labels: // rule labels: retval // token list labels: @@ -4881,7 +4881,7 @@ public class CMISParser extends Parser { // AST REWRITE - // elements: inValueList, NOT, ANY, multiValuedColumnReference + // elements: ANY, multiValuedColumnReference, NOT, inValueList // token labels: // rule labels: retval // token list labels: @@ -5448,7 +5448,7 @@ public class CMISParser extends Parser { // AST REWRITE - // elements: sortSpecification, ORDER + // elements: ORDER, sortSpecification // token labels: // rule labels: retval // token list labels: diff --git a/source/java/org/alfresco/repo/search/impl/parsers/FTSLexer.java b/source/java/org/alfresco/repo/search/impl/parsers/FTSLexer.java index 4fee36985a..add96750c7 100644 --- a/source/java/org/alfresco/repo/search/impl/parsers/FTSLexer.java +++ b/source/java/org/alfresco/repo/search/impl/parsers/FTSLexer.java @@ -1,4 +1,4 @@ -// $ANTLR !Unknown version! W:\\alfresco\\HEAD\\root\\projects\\Repository\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g 2009-05-20 17:49:31 +// $ANTLR !Unknown version! W:\\alfresco\\HEAD\\root\\projects\\Repository\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g 2009-05-26 10:05:03 package org.alfresco.repo.search.impl.parsers; import org.antlr.runtime.*; diff --git a/source/java/org/alfresco/repo/search/impl/parsers/FTSParser.java b/source/java/org/alfresco/repo/search/impl/parsers/FTSParser.java index 0a5166f5ca..0e0ec02eab 100644 --- a/source/java/org/alfresco/repo/search/impl/parsers/FTSParser.java +++ b/source/java/org/alfresco/repo/search/impl/parsers/FTSParser.java @@ -1,4 +1,4 @@ -// $ANTLR !Unknown version! W:\\alfresco\\HEAD\\root\\projects\\Repository\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g 2009-05-20 17:49:30 +// $ANTLR !Unknown version! W:\\alfresco\\HEAD\\root\\projects\\Repository\\source\\java\\org\\alfresco\\repo\\search\\impl\\parsers\\FTS.g 2009-05-26 10:05:01 package org.alfresco.repo.search.impl.parsers; import org.antlr.runtime.*; @@ -814,7 +814,7 @@ public class FTSParser extends Parser { // AST REWRITE - // elements: ftsTest, boost + // elements: boost, ftsTest // token labels: // rule labels: retval // token list labels: @@ -955,7 +955,7 @@ public class FTSParser extends Parser { // AST REWRITE - // elements: ftsTest, boost + // elements: boost, ftsTest // token labels: // rule labels: retval // token list labels: @@ -1099,7 +1099,7 @@ public class FTSParser extends Parser { // AST REWRITE - // elements: ftsTest, boost + // elements: boost, ftsTest // token labels: // rule labels: retval // token list labels: @@ -3333,7 +3333,7 @@ public class FTSParser extends Parser { // AST REWRITE - // elements: ftsFieldGroupTest, boost + // elements: boost, ftsFieldGroupTest // token labels: // rule labels: retval // token list labels: @@ -3474,7 +3474,7 @@ public class FTSParser extends Parser { // AST REWRITE - // elements: ftsFieldGroupTest, boost + // elements: boost, ftsFieldGroupTest // token labels: // rule labels: retval // token list labels: @@ -3772,7 +3772,7 @@ public class FTSParser extends Parser { // AST REWRITE - // elements: ftsFieldGroupTerm, fuzzy + // elements: fuzzy, ftsFieldGroupTerm // token labels: // rule labels: retval // token list labels: @@ -3849,7 +3849,7 @@ public class FTSParser extends Parser { // AST REWRITE - // elements: fuzzy, ftsFieldGroupExactTerm + // elements: ftsFieldGroupExactTerm, fuzzy // token labels: // rule labels: retval // token list labels: @@ -3926,7 +3926,7 @@ public class FTSParser extends Parser { // AST REWRITE - // elements: ftsFieldGroupPhrase, slop + // elements: slop, ftsFieldGroupPhrase // token labels: // rule labels: retval // token list labels: @@ -4504,7 +4504,7 @@ public class FTSParser extends Parser { // AST REWRITE - // elements: ftsFieldGroupTerm, ftsFieldGroupTerm, proximityGroup + // elements: ftsFieldGroupTerm, proximityGroup, ftsFieldGroupTerm // token labels: // rule labels: retval // token list labels: @@ -4518,16 +4518,16 @@ public class FTSParser extends Parser { // 408:3: -> ftsFieldGroupTerm ( proximityGroup ftsFieldGroupTerm )+ { adaptor.addChild(root_0, stream_ftsFieldGroupTerm.nextTree()); - if ( !(stream_ftsFieldGroupTerm.hasNext()||stream_proximityGroup.hasNext()) ) { + if ( !(stream_proximityGroup.hasNext()||stream_ftsFieldGroupTerm.hasNext()) ) { throw new RewriteEarlyExitException(); } - while ( stream_ftsFieldGroupTerm.hasNext()||stream_proximityGroup.hasNext() ) { + while ( stream_proximityGroup.hasNext()||stream_ftsFieldGroupTerm.hasNext() ) { adaptor.addChild(root_0, stream_proximityGroup.nextTree()); adaptor.addChild(root_0, stream_ftsFieldGroupTerm.nextTree()); } - stream_ftsFieldGroupTerm.reset(); stream_proximityGroup.reset(); + stream_ftsFieldGroupTerm.reset(); } @@ -4816,7 +4816,7 @@ public class FTSParser extends Parser { // AST REWRITE - // elements: range_right, ftsRangeWord, range_left, ftsRangeWord + // elements: ftsRangeWord, ftsRangeWord, range_right, range_left // token labels: // rule labels: retval // token list labels: @@ -5207,7 +5207,7 @@ public class FTSParser extends Parser { // AST REWRITE - // elements: uri, identifier, prefix + // elements: identifier, prefix, uri // token labels: // rule labels: retval // token list labels: @@ -5367,7 +5367,7 @@ public class FTSParser extends Parser { // AST REWRITE - // elements: identifier, uri, prefix + // elements: uri, identifier, prefix // token labels: // rule labels: retval // token list labels: diff --git a/source/java/org/alfresco/repo/search/impl/parsers/fts_test.gunit b/source/java/org/alfresco/repo/search/impl/parsers/fts_test.gunit index fd6cde4bba..81c0e1ef20 100644 --- a/source/java/org/alfresco/repo/search/impl/parsers/fts_test.gunit +++ b/source/java/org/alfresco/repo/search/impl/parsers/fts_test.gunit @@ -13,6 +13,8 @@ ftsQuery: "test:flag:true AND %test:field" -> "(CONJUNCTION (DISJUNCTION (CONJUNCTION (DEFAULT (TERM true (FIELD_REF flag (PREFIX test)))) (DEFAULT (TEMPLATE (FIELD_REF field (PREFIX test)))))))" "test:flag:true AND %NEST" -> "(CONJUNCTION (DISJUNCTION (CONJUNCTION (DEFAULT (TERM true (FIELD_REF flag (PREFIX test)))) (DEFAULT (TEMPLATE (FIELD_REF NEST))))))" "test:flag:true AND %(NEST,test:field, test_field1, {http://www.alfresco.org/model/content/1.0}name)" -> "(CONJUNCTION (DISJUNCTION (CONJUNCTION (DEFAULT (TERM true (FIELD_REF flag (PREFIX test)))) (DEFAULT (TEMPLATE (FIELD_REF NEST) (FIELD_REF field (PREFIX test)) (FIELD_REF test_field1) (FIELD_REF name (NAME_SPACE {http://www.alfresco.org/model/content/1.0})))))))" +"+PATH:\"/app:company_home/st:sites/cm:rmtestnew1/cm:documentLibrary//*\" +(ASPECT:\"{http://www.alfresco.org/model/recordsmanagement/1.0}record\") -TYPE:\"{http://www.alfresco.org/model/content/1.0}thumbnail\"" -> "OK" + ftsImplicitConjunctionOrDisjunction: "red" -> (CONJUNCTION (DISJUNCTION (CONJUNCTION (DEFAULT (TERM red))))) diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneConjunction.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneConjunction.java index 86684e26bd..7d0fede7ec 100644 --- a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneConjunction.java +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneConjunction.java @@ -36,7 +36,6 @@ import org.apache.lucene.index.Term; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; -import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; @@ -66,6 +65,7 @@ public class LuceneConjunction extends BaseConjunction implements LuceneQueryBui { BooleanQuery query = new BooleanQuery(); boolean must = false; + @SuppressWarnings("unused") boolean should = false; boolean must_not = false; for (Constraint constraint : getConstraints()) diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneDisjunction.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneDisjunction.java index d489e56c31..2fd6238424 100644 --- a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneDisjunction.java +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneDisjunction.java @@ -36,10 +36,8 @@ import org.apache.lucene.index.Term; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; -import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; -import org.apache.lucene.search.BooleanClause.Occur; /** * @author andyh diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LucenePropertyArgument.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LucenePropertyArgument.java index c1b11deb37..28f69a1047 100644 --- a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LucenePropertyArgument.java +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LucenePropertyArgument.java @@ -25,7 +25,6 @@ package org.alfresco.repo.search.impl.querymodel.impl.lucene; import org.alfresco.repo.search.impl.querymodel.impl.BasePropertyArgument; -import org.alfresco.service.namespace.QName; /** * @author andyh @@ -36,6 +35,9 @@ public class LucenePropertyArgument extends BasePropertyArgument /** * @param name + * @param queryable + * @param orderable + * @param selector * @param propertyName */ public LucenePropertyArgument(String name, boolean queryable, boolean orderable, String selector, String propertyName) diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQuery.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQuery.java index ea1d29551f..4adf25fdee 100644 --- a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQuery.java +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQuery.java @@ -76,6 +76,7 @@ public class LuceneQuery extends BaseQuery implements LuceneQueryBuilder BooleanQuery luceneQuery = new BooleanQuery(); boolean must = false; + @SuppressWarnings("unused") boolean should = false; boolean must_not = false; diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilder.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilder.java index 26df64774f..2c2bf33559 100644 --- a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilder.java +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilder.java @@ -36,7 +36,22 @@ import org.apache.lucene.search.Sort; */ public interface LuceneQueryBuilder { + /** + * Build the matching lucene query + * @param selectors + * @param luceneContext + * @param functionContext + * @return - the query + * @throws ParseException + */ public Query buildQuery(Set selectors, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) throws ParseException; + /** + * Build the matching lucene sort + * @param selectors + * @param luceneContext + * @param functionContext + * @return - the sort spec + */ public Sort buildSort(Set selectors, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext); } diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderComponent.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderComponent.java index 01315ebac2..52721a6fa2 100644 --- a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderComponent.java +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryBuilderComponent.java @@ -37,5 +37,14 @@ import org.apache.lucene.search.Query; */ public interface LuceneQueryBuilderComponent { + /** + * Generate the lucene query from the query component + * @param selectors + * @param functionArgs + * @param luceneContext + * @param functionContext + * @return - the lucene query fragment for this component + * @throws ParseException + */ public Query addComponent(Set selectors, Map functionArgs, LuceneQueryBuilderContext luceneContext, FunctionEvaluationContext functionContext) throws ParseException; } 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 c76f7043a2..fb5bc60eec 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 @@ -42,6 +42,16 @@ public class LuceneQueryBuilderContext private NamespacePrefixResolver namespacePrefixResolver; + /** + * Context for building lucene queries + * + * @param dictionaryService + * @param namespacePrefixResolver + * @param tenantService + * @param searchParameters + * @param config + * @param indexReader + */ public LuceneQueryBuilderContext(DictionaryService dictionaryService, NamespacePrefixResolver namespacePrefixResolver, TenantService tenantService, SearchParameters searchParameters, LuceneConfig config, IndexReader indexReader) { @@ -60,7 +70,7 @@ public class LuceneQueryBuilderContext } /** - * @return + * @return - the parser */ public LuceneQueryParser getLuceneQueryParser() { @@ -68,7 +78,7 @@ public class LuceneQueryBuilderContext } /** - * @return + * @return - the namespace prefix resolver */ public NamespacePrefixResolver getNamespacePrefixResolver() { diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryEngine.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryEngine.java index 8e10b57348..af8dbf9f37 100644 --- a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryEngine.java +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/LuceneQueryEngine.java @@ -50,7 +50,6 @@ import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.namespace.NamespaceService; -import org.alfresco.util.Pair; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.search.Hits; import org.apache.lucene.search.Sort; 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 c8eae1760e..72e20e96b9 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 @@ -99,8 +99,11 @@ import org.alfresco.service.namespace.QName; */ public class LuceneQueryModelFactory implements QueryModelFactory { - public HashMap functions = new HashMap(); + private HashMap functions = new HashMap(); + /** + * Default lucene query model factory and functions + */ public LuceneQueryModelFactory() { functions.put(Equals.NAME, new LuceneEquals()); diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSFuzzyTerm.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSFuzzyTerm.java index 7373260939..5ccfd1c249 100644 --- a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSFuzzyTerm.java +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSFuzzyTerm.java @@ -37,6 +37,11 @@ import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderCo import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.search.Query; +/** + * Fuzzy matching + * @author andyh + * + */ public class LuceneFTSFuzzyTerm extends FTSFuzzyTerm implements LuceneQueryBuilderComponent { diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSPrefixTerm.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSPrefixTerm.java index b9bfcbdcc1..1738df5bb1 100644 --- a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSPrefixTerm.java +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSPrefixTerm.java @@ -37,6 +37,11 @@ import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderCo import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.search.Query; +/** + * Perfix term + * @author andyh + * + */ public class LuceneFTSPrefixTerm extends FTSPrefixTerm implements LuceneQueryBuilderComponent { /** 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 9618580995..a7bc61c5ca 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 @@ -37,6 +37,11 @@ import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderCo import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.search.Query; +/** + * Proximity + * @author andyh + * + */ public class LuceneFTSProximity extends FTSProximity implements LuceneQueryBuilderComponent { 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 index 1c314314be..5bfb6ef965 100644 --- 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 @@ -38,6 +38,11 @@ import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderCo import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.search.Query; +/** + * Range + * @author andyh + * + */ public class LuceneFTSRange extends FTSRange implements LuceneQueryBuilderComponent { /** diff --git a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSWildTerm.java b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSWildTerm.java index 8eb9590f1b..8d6c430827 100644 --- a/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSWildTerm.java +++ b/source/java/org/alfresco/repo/search/impl/querymodel/impl/lucene/functions/LuceneFTSWildTerm.java @@ -37,6 +37,11 @@ import org.alfresco.repo.search.impl.querymodel.impl.lucene.LuceneQueryBuilderCo import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.search.Query; +/** + * Wild Card + * @author andyh + * + */ public class LuceneFTSWildTerm extends FTSWildTerm implements LuceneQueryBuilderComponent { diff --git a/source/java/org/alfresco/repo/search/results/ResultSetSPIWrapper.java b/source/java/org/alfresco/repo/search/results/ResultSetSPIWrapper.java new file mode 100644 index 0000000000..c41f79f269 --- /dev/null +++ b/source/java/org/alfresco/repo/search/results/ResultSetSPIWrapper.java @@ -0,0 +1,143 @@ +/* + * 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.results; + +import java.util.Iterator; +import java.util.List; + +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.search.ResultSet; +import org.alfresco.service.cmr.search.ResultSetMetaData; +import org.alfresco.service.cmr.search.ResultSetRow; +import org.alfresco.service.cmr.search.ResultSetSPI; + +/** + * Wrap an SPI result set with the basic interface + * + * @author andyh + * + * @param + * @param + */ +public class ResultSetSPIWrapper implements ResultSet +{ + private ResultSetSPI wrapped; + + /** + * Create a wrapped result set + * @param wrapped + */ + public ResultSetSPIWrapper(ResultSetSPI wrapped) + { + this.wrapped = wrapped; + } + + public void close() + { + wrapped.close(); + } + + public ChildAssociationRef getChildAssocRef(int n) + { + return wrapped.getChildAssocRef(n); + } + + public List getChildAssocRefs() + { + return wrapped.getChildAssocRefs(); + } + + public NodeRef getNodeRef(int n) + { + return wrapped.getNodeRef(n); + } + + public List getNodeRefs() + { + return wrapped.getNodeRefs(); + } + + public ResultSetMetaData getResultSetMetaData() + { + return wrapped.getResultSetMetaData(); + } + + public ResultSetRow getRow(int i) + { + return wrapped.getRow(i); + } + + public float getScore(int n) + { + return wrapped.getScore(n); + } + + public int getStart() + { + return wrapped.getStart(); + } + + public boolean hasMore() + { + return wrapped.hasMore(); + } + + public int length() + { + return wrapped.length(); + } + + public Iterator iterator() + { + return new WrappedIterator(wrapped.iterator()); + } + + private static class WrappedIterator implements Iterator + { + private Iterator wrapped; + + WrappedIterator(Iterator wrapped) + { + this.wrapped = wrapped; + } + + public boolean hasNext() + { + return wrapped.hasNext(); + } + + public ResultSetRow next() + { + return wrapped.next(); + } + + public void remove() + { + wrapped.remove(); + } + + } +} diff --git a/source/java/org/alfresco/service/cmr/search/ResultSet.java b/source/java/org/alfresco/service/cmr/search/ResultSet.java index 6b152fe9f8..39038b8bb2 100644 --- a/source/java/org/alfresco/service/cmr/search/ResultSet.java +++ b/source/java/org/alfresco/service/cmr/search/ResultSet.java @@ -24,10 +24,6 @@ */ package org.alfresco.service.cmr.search; -import java.util.List; - -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; /** * This is the common interface for both row (Alfresco node) and column (CMIS style property or function) based results. @@ -40,97 +36,7 @@ import org.alfresco.service.cmr.repository.NodeRef; * * @author andyh */ -public interface ResultSet extends Iterable // Specific iterator over ResultSetRows +public interface ResultSet extends ResultSetSPI // Specific iterator over ResultSetRows { - /** - * Get the number of rows in this result set. This will be less than or equal to the maximum number of rows - * requested or the full length of the results set if no restriction on length are specified. If a skip count is - * given, the length represents the number of results after the skip count and does not include the items skipped. - * - * @return the number of results. -1 means unknown and can be returned for lazy evaluations of permissions when the - * actual size is not known and evaluated upon request. - */ - public int length(); - /** - * Get the id of the node at the given index (if there is only one selector or no selector) - * - * @param n - * zero-based index - * @return return the the node ref for the row if there is only one selector - * @throws AmbiguousSelectorException - */ - public NodeRef getNodeRef(int n); - - /** - * Get the score for the node at the given position (if there is only one selector or no selector) - * - * @param n - * zero-based index - * @return return the score for the row if there is only one selector - * @throws AmbiguousSelectorException - */ - public float getScore(int n); - - /** - * Close the result set and release any resources held/ The result set is bound to the transaction and will auto - * close at the end of the transaction. - */ - public void close(); - - /** - * Get a row from the result set by row index, starting at 0. - * - * @param i - * zero-based index - * @return return the row - */ - public ResultSetRow getRow(int i); - - /** - * Get a list of all the node refs in the result set (if there is only one selector or no selector) - * - * @return the node refs if there is only one selector or no selector * - * @throws AmbiguousSelectorException - */ - public List getNodeRefs(); - - /** - * Get a list of all the child associations in the results set. (if there is only one selectoror no selector) - * - * @return the child assoc refs if there is only one selector or no selector * - * @throws AmbiguousSelectorException - */ - public List getChildAssocRefs(); - - /** - * Get the child assoc ref for a particular row. (if there is only one selectoror no selector) - * - * @param n - * zero-based index - * @return the child assoc ref for the row if there is only one selector or no selector - */ - public ChildAssociationRef getChildAssocRef(int n); - - /** - * Get the meta data for the results set. - * - * @return the metadata - */ - public ResultSetMetaData getResultSetMetaData(); - - /** - * Get the start point for this results set in the overall set of rows that match the query - this will be equal to - * the skip count set when executing the query, and zero if this is not set. - * - * @return the position of the first result in the overall result set - */ - public int getStart(); - - /** - * Was this result set curtailed - are there more pages to the result set? - * - * @return true if there are more pages in the result set - */ - public boolean hasMore(); } diff --git a/source/java/org/alfresco/service/cmr/search/ResultSetMetaData.java b/source/java/org/alfresco/service/cmr/search/ResultSetMetaData.java index a2ccf3b10c..cd44423250 100644 --- a/source/java/org/alfresco/service/cmr/search/ResultSetMetaData.java +++ b/source/java/org/alfresco/service/cmr/search/ResultSetMetaData.java @@ -68,14 +68,14 @@ public interface ResultSetMetaData * The selector meta-data. * @return - the selector meta-data. */ - public ResultSetSelector getSelectors(); + public ResultSetSelector[] getSelectors(); /** * The column meta-data. * @return - the column meta-data. */ - public ResultSetColumn getColumns(); + public ResultSetColumn[] getColumns(); /** * Get the names of the selectors. diff --git a/source/java/org/alfresco/service/cmr/search/ResultSetSPI.java b/source/java/org/alfresco/service/cmr/search/ResultSetSPI.java new file mode 100644 index 0000000000..01cfdfe473 --- /dev/null +++ b/source/java/org/alfresco/service/cmr/search/ResultSetSPI.java @@ -0,0 +1,138 @@ +/* + * 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.service.cmr.search; + +import java.util.List; + +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; + +/** + * This is the common interface for both row (Alfresco node) and column (CMIS style property or function) based results. + * The meta-data for the results sets contains the detailed info on what columns are available. For row based result + * sets there is no selector - all the nodes returned do not have to have a specific type or aspect. For example, an FTS + * search on properties of type d:content has no type constraint implied or otherwise. Searches against properties have + * an implied type, but as there can be more than one property -> more than one type or aspect implied (eg via OR in FTS + * or lucene) they are ignored An iterable result set from a searcher query. Implementations must implement the + * indexes for row lookup as zero-based. + * + * @author andyh + * @param + * @param + */ +public interface ResultSetSPI extends Iterable // Specific iterator over ResultSetRows +{ + /** + * Get the number of rows in this result set. This will be less than or equal to the maximum number of rows + * requested or the full length of the results set if no restriction on length are specified. If a skip count is + * given, the length represents the number of results after the skip count and does not include the items skipped. + * + * @return the number of results. -1 means unknown and can be returned for lazy evaluations of permissions when the + * actual size is not known and evaluated upon request. + */ + public int length(); + + /** + * Get the id of the node at the given index (if there is only one selector or no selector) + * + * @param n + * zero-based index + * @return return the the node ref for the row if there is only one selector + * @throws AmbiguousSelectorException + */ + public NodeRef getNodeRef(int n); + + /** + * Get the score for the node at the given position (if there is only one selector or no selector) + * + * @param n + * zero-based index + * @return return the score for the row if there is only one selector + * @throws AmbiguousSelectorException + */ + public float getScore(int n); + + /** + * Close the result set and release any resources held/ The result set is bound to the transaction and will auto + * close at the end of the transaction. + */ + public void close(); + + /** + * Get a row from the result set by row index, starting at 0. + * + * @param i + * zero-based index + * @return return the row + */ + public ROW getRow(int i); + + /** + * Get a list of all the node refs in the result set (if there is only one selector or no selector) + * + * @return the node refs if there is only one selector or no selector * + * @throws AmbiguousSelectorException + */ + public List getNodeRefs(); + + /** + * Get a list of all the child associations in the results set. (if there is only one selectoror no selector) + * + * @return the child assoc refs if there is only one selector or no selector * + * @throws AmbiguousSelectorException + */ + public List getChildAssocRefs(); + + /** + * Get the child assoc ref for a particular row. (if there is only one selectoror no selector) + * + * @param n + * zero-based index + * @return the child assoc ref for the row if there is only one selector or no selector + */ + public ChildAssociationRef getChildAssocRef(int n); + + /** + * Get the meta data for the results set. + * + * @return the metadata + */ + public MD getResultSetMetaData(); + + /** + * Get the start point for this results set in the overall set of rows that match the query - this will be equal to + * the skip count set when executing the query, and zero if this is not set. + * + * @return the position of the first result in the overall result set + */ + public int getStart(); + + /** + * Was this result set curtailed - are there more pages to the result set? + * + * @return true if there are more pages in the result set + */ + public boolean hasMore(); +} diff --git a/source/java/org/alfresco/service/cmr/search/SearchParameters.java b/source/java/org/alfresco/service/cmr/search/SearchParameters.java index a8e01d90b2..f61b8f5d90 100644 --- a/source/java/org/alfresco/service/cmr/search/SearchParameters.java +++ b/source/java/org/alfresco/service/cmr/search/SearchParameters.java @@ -33,11 +33,9 @@ import java.util.Locale; import java.util.Map; import java.util.Set; -import org.alfresco.repo.domain.hibernate.BulkLoader; import org.alfresco.repo.search.MLAnalysisMode; -import org.alfresco.repo.search.impl.querymodel.QueryOptions.Connective; -import org.alfresco.service.cmr.repository.Path; import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.namespace.NamespaceService; /** * This class provides parameters to define a search. TODO - paging of results page number and page size - paging @@ -58,12 +56,24 @@ public class SearchParameters /* * Standard sort definitions for sorting in document and score order. */ + /** + * Sort in the order docs were added to the index - oldest docs first + */ public static final SortDefinition SORT_IN_DOCUMENT_ORDER_ASCENDING = new SortDefinition(SortDefinition.SortType.DOCUMENT, null, true); + /** + * Sort in the reverse order docs were added to the index - new/updateed docs first + */ public static final SortDefinition SORT_IN_DOCUMENT_ORDER_DESCENDING = new SortDefinition(SortDefinition.SortType.DOCUMENT, null, false); + /** + * Sort in ascending score + */ public static final SortDefinition SORT_IN_SCORE_ORDER_ASCENDING = new SortDefinition(SortDefinition.SortType.SCORE, null, false); + /** + * Sort in descending score order + */ public static final SortDefinition SORT_IN_SCORE_ORDER_DESCENDING = new SortDefinition(SortDefinition.SortType.SCORE, null, true); /** @@ -72,14 +82,27 @@ public class SearchParameters */ public enum Operator { - OR, AND + /** + * OR + */ + OR, + /** + * AND + */ + AND } /* * Expose as constants */ + /** + * OR + */ public static final Operator OR = Operator.OR; + /** + * AND + */ public static final Operator AND = Operator.AND; /* @@ -125,7 +148,7 @@ public class SearchParameters private Map queryTemplates = new HashMap(); - private String namespace; + private String namespace = NamespaceService.CONTENT_MODEL_1_0_URI; /** * Default constructor @@ -135,6 +158,10 @@ public class SearchParameters super(); } + /** + * Get the search language + * @return - string id of search language + */ public String getLanguage() { return language; @@ -143,7 +170,7 @@ public class SearchParameters /** * Get the query. * - * @return + * @return - the query string */ public String getQuery() { @@ -217,7 +244,7 @@ public class SearchParameters * treated as primary, the second as secondary etc. A helper method to create SortDefinitions. * * @param field - - * this is intially a direct attribute on a node not an attribute on the parent etc TODO: It could be a + * this is initially a direct attribute on a node not an attribute on the parent etc TODO: It could be a * relative path at some time. * @param ascending - * true to sort ascending, false for descending. @@ -241,7 +268,7 @@ public class SearchParameters /** * Is data in the current transaction excluded from the search. * - * @return + * @return - true if data in the current transaction is ignored */ public boolean excludeDataInTheCurrentTransaction() { @@ -251,7 +278,7 @@ public class SearchParameters /** * Get the query parameters that apply to this query. * - * @return + * @return - the parameter */ public ArrayList getQueryParameterDefinitions() { @@ -261,7 +288,7 @@ public class SearchParameters /** * Get the sort definitions that apply to this query. * - * @return + * @return - the sort definitions */ public ArrayList getSortDefinitions() { @@ -271,7 +298,7 @@ public class SearchParameters /** * Get the stores in which this query should find results. * - * @return + * @return - the list of stores */ public ArrayList getStores() { @@ -292,7 +319,7 @@ public class SearchParameters /** * Get the default operator for query elements when they are not explicit in the query. * - * @return + * @return the default operator */ public Operator getDefaultOperator() { @@ -302,7 +329,7 @@ public class SearchParameters /** * Get how the result set should be limited * - * @return + * @return how the result set will be limited */ public LimitBy getLimitBy() { @@ -322,7 +349,7 @@ public class SearchParameters /** * Get when permissions are evaluated. * - * @return + * @return - how permissions are evaluated */ public PermissionEvaluationMode getPermissionEvaluation() { @@ -342,7 +369,7 @@ public class SearchParameters /** * If limiting the result set in some way, get the limiting value used. * - * @return + * @return the limit */ public int getLimit() { @@ -363,7 +390,7 @@ public class SearchParameters * The way in which multilingual fields are treated durig a search. By default, only the specified locale is used * and it must be an exact match. * - * @return + * @return - how locale related text is tokenised */ public MLAnalysisMode getMlAnalaysisMode() { @@ -394,7 +421,7 @@ public class SearchParameters /** * Get the locales used for multi-lingual text searches. * - * @return + * @return - the locales */ public List getLocales() { @@ -402,9 +429,9 @@ public class SearchParameters } /** - * Add a locale to include for multi-lingual text searches. If non are set, the default is to use the user's locale. + * Add a field for TEXT expansion * - * @param locale + * @param attribute - field/attribute in the index */ public void addTextAttribute(String attribute) { @@ -412,9 +439,9 @@ public class SearchParameters } /** - * Get the locales used for multi-lingual text searches. + * Get the text attributes used for text expansion. * - * @return + * @return the text attributes used for text expansion */ public Set getTextAttributes() { @@ -422,9 +449,9 @@ public class SearchParameters } /** - * Add a locale to include for multi-lingual text searches. If non are set, the default is to use the user's locale. + * Add a field for ALL expansion * - * @param locale + * @param attribute - field/attribute in the index */ public void addAllAttribute(String attribute) { @@ -432,9 +459,9 @@ public class SearchParameters } /** - * Get the locales used for multi-lingual text searches. + * Get the text attributes used for ALL expansion. * - * @return + * @return the text attributes used for ALL expansion */ public Set getAllAttributes() { @@ -445,7 +472,6 @@ public class SearchParameters * Bulk fetch results in the cache * * @param bulkFetch - * @return */ public void setBulkFetch(boolean bulkFetch) { @@ -453,9 +479,9 @@ public class SearchParameters } /** - * Do we bulk fect + * Do we bulk fetch * - * @return + * @return - true if we do */ public boolean getBulkFetch() { @@ -463,9 +489,9 @@ public class SearchParameters } /** - * Set the bulk fect size + * Set the bulk fetch size * - * @param bulkFecthSize + * @param bulkFetchSize */ public void setBulkFetchSize(int bulkFetchSize) { @@ -475,7 +501,7 @@ public class SearchParameters /** * Get the bulk fetch size. * - * @return + * @return the fetch size */ public int getBulkFecthSize() { @@ -537,8 +563,8 @@ public class SearchParameters /** * Set the default connective used when OR and AND are not specified for the FTS contains() function. * - * @param defaultFTSConnective - * the defaultFTSConnective to set + * @param defaultFTSOperator + * the defaultFTSOperator to set */ public void setDefaultFTSOperator(Operator defaultFTSOperator) { @@ -558,8 +584,8 @@ public class SearchParameters /** * As setDefaultFTSConnective() but for field groups * - * @param defaultFTSFieldConnective - * the defaultFTSFieldConnective to set + * @param defaultFTSFieldOperator + * the defaultFTSFieldOperator to set */ public void setDefaultFTSFieldConnective(Operator defaultFTSFieldOperator) { @@ -584,6 +610,28 @@ public class SearchParameters this.namespace = namespace; } + + /** + * Get the query templates + * @return - the query templates + */ + public Map getQueryTemplates() + { + return queryTemplates; + } + + /** + * Add/replace a query template + * Not all languages support query templates + * @param name + * @param template + * @return any removed template or null + */ + public String addQueryTemplate(String name, String template) + { + return queryTemplates.put(name, template); + } + /** * A helper class for sort definition. Encapsulated using the lucene sortType, field name and a flag for * ascending/descending. @@ -593,9 +641,25 @@ public class SearchParameters public static class SortDefinition { + /** + * What is used for the sort + * @author andyh + * + */ public enum SortType { - FIELD, DOCUMENT, SCORE + /** + * A Field + */ + FIELD, + /** + * Doc number + */ + DOCUMENT, + /** + * Score + */ + SCORE }; SortType sortType; @@ -611,16 +675,28 @@ public class SearchParameters this.ascending = ascending; } + /** + * Is ascending + * @return true if ascending + */ public boolean isAscending() { return ascending; } + /** + * Field + * @return - the field + */ public String getField() { return field; } + /** + * What is used for the sort + * @return sort type + */ public SortType getSortType() { return sortType; @@ -628,4 +704,6 @@ public class SearchParameters } + + } diff --git a/source/java/org/alfresco/service/cmr/search/SearchService.java b/source/java/org/alfresco/service/cmr/search/SearchService.java index da9ee27c6c..16a1cae49b 100644 --- a/source/java/org/alfresco/service/cmr/search/SearchService.java +++ b/source/java/org/alfresco/service/cmr/search/SearchService.java @@ -58,9 +58,9 @@ public interface SearchService public static final String LANGUAGE_FTS_ALFRESCO = "fts-alfresco"; - //public static final String LANGUAGE_SQL_CMIS_STRICT = "sql-cmis-strict"; + public static final String LANGUAGE_SQL_CMIS_STRICT = "sql-cmis-strict"; - //public static final String LANGUAGE_SQL_ALFTRESCO = "sql-alfresco"; + public static final String LANGUAGE_SQL_ALFTRESCO = "sql-alfresco"; /** * Search against a store. Pulls back all attributes on each node. Does not