diff --git a/src/main/java/org/alfresco/opencmis/search/CMISResultSetColumn.java b/src/main/java/org/alfresco/opencmis/search/CMISResultSetColumn.java index f047d33b4c..267bc91717 100644 --- a/src/main/java/org/alfresco/opencmis/search/CMISResultSetColumn.java +++ b/src/main/java/org/alfresco/opencmis/search/CMISResultSetColumn.java @@ -37,7 +37,13 @@ import org.apache.chemistry.opencmis.commons.enums.PropertyType; public class CMISResultSetColumn implements ResultSetColumn { - private String name; + // Constant used at alfresco-data-model > org.alfresco.opencmis.search.CMISQueryParser.buildColumns() + public static final String SCORE_SELECTOR_ID = "SEARCH_SCORE"; + public static final String SCORE_SELECTOR_FUNCTION = "Score"; + + private String name; + + private String functionName; private PropertyDefinitionWrapper propertyDefinition; @@ -45,12 +51,13 @@ public class CMISResultSetColumn implements ResultSetColumn private QName alfrescoPropertyQName; - private QName alfrescoDataTypeQName; - - CMISResultSetColumn(String name, PropertyDefinitionWrapper propertyDefinition, PropertyType dataType, + private QName alfrescoDataTypeQName; + + CMISResultSetColumn(String name, String functionName, PropertyDefinitionWrapper propertyDefinition, PropertyType dataType, QName alfrescoPropertyQName, QName alfrescoDataTypeQName) { - this.name = name; + this.name = name; + this.functionName = functionName; this.propertyDefinition = propertyDefinition; this.dataType = dataType; this.alfrescoPropertyQName = alfrescoPropertyQName; @@ -60,6 +67,11 @@ public class CMISResultSetColumn implements ResultSetColumn public String getName() { return name; + } + + public String getFunctionName() + { + return functionName; } public PropertyDefinitionWrapper getCMISPropertyDefinition() @@ -80,5 +92,6 @@ public class CMISResultSetColumn implements ResultSetColumn public QName getPropertyType() { return alfrescoPropertyQName; - } + } + } diff --git a/src/main/java/org/alfresco/opencmis/search/CMISResultSetMetaData.java b/src/main/java/org/alfresco/opencmis/search/CMISResultSetMetaData.java index 95352a7fa1..bc11740528 100644 --- a/src/main/java/org/alfresco/opencmis/search/CMISResultSetMetaData.java +++ b/src/main/java/org/alfresco/opencmis/search/CMISResultSetMetaData.java @@ -106,7 +106,8 @@ public class CMISResultSetMetaData implements ResultSetMetaData { alfrescoDataTypeQName = cmisDictionaryService.findAlfrescoDataType(type); } - CMISResultSetColumn cmd = new CMISResultSetColumn(column.getAlias(), propertyDefinition, type, + CMISResultSetColumn cmd = new CMISResultSetColumn(column.getAlias(), column.getFunction().getName(), + propertyDefinition, type, alfrescoPropertyQName, alfrescoDataTypeQName); columnMetaData.put(cmd.getName(), cmd); } diff --git a/src/main/java/org/alfresco/opencmis/search/CMISResultSetRow.java b/src/main/java/org/alfresco/opencmis/search/CMISResultSetRow.java index 59c8c7b5aa..70cd427932 100644 --- a/src/main/java/org/alfresco/opencmis/search/CMISResultSetRow.java +++ b/src/main/java/org/alfresco/opencmis/search/CMISResultSetRow.java @@ -25,22 +25,22 @@ */ package org.alfresco.opencmis.search; -import java.io.Serializable; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.alfresco.opencmis.dictionary.CMISDictionaryService; -import org.alfresco.opencmis.dictionary.CMISNodeInfo; -import org.alfresco.repo.search.impl.querymodel.Column; -import org.alfresco.repo.search.impl.querymodel.PropertyArgument; -import org.alfresco.repo.search.impl.querymodel.Query; -import org.alfresco.repo.search.impl.querymodel.impl.functions.PropertyAccessor; -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.cmr.search.ResultSetRow; +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.alfresco.opencmis.dictionary.CMISDictionaryService; +import org.alfresco.opencmis.dictionary.CMISNodeInfo; +import org.alfresco.repo.search.impl.querymodel.Column; +import org.alfresco.repo.search.impl.querymodel.PropertyArgument; +import org.alfresco.repo.search.impl.querymodel.Query; +import org.alfresco.repo.search.impl.querymodel.impl.functions.PropertyAccessor; +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.cmr.search.ResultSetRow; import org.alfresco.service.namespace.QName; /** @@ -58,8 +58,8 @@ public class CMISResultSetRow implements ResultSetRow */ private int index; - private Map scores; - + private Map scores; + private NodeService nodeService; private Map nodeRefs; @@ -118,8 +118,8 @@ public class CMISResultSetRow implements ResultSetRow overall = (overall * (count / (count + 1.0f))) + (score / (count + 1.0f)); } return overall; - } - + } + /* * (non-Javadoc) * @@ -176,7 +176,14 @@ public class CMISResultSetRow implements ResultSetRow context.setScore(getScore()); for (Column column : query.getColumns()) { - if (column.getAlias().equals(columnName)) + + // When an SCORE selector is included, score must be adapted to range 0..1 due to CMIS specification + if (column.getAlias().equals(CMISResultSetColumn.SCORE_SELECTOR_ID) || + column.getFunction().getName().equals(CMISResultSetColumn.SCORE_SELECTOR_FUNCTION)) + { + return getNormalisedScore(); + } + else if (column.getAlias().equals(columnName)) { return column.getFunction().getValue(column.getFunctionArguments(), context); } @@ -220,7 +227,18 @@ public class CMISResultSetRow implements ResultSetRow } } return null; - } + } + + /** + /** + * CMIS Specification states that scoring results must be in a 0..1 range + * This function re-adapt the scores when any scoring field or expression is requested by the query. + * It's a safe approach, as includes negative numbers and also paged requests. + * @return + */ + private float getNormalisedScore() { + return (float) (Math.atan(getScore()) / Math.PI) + 0.5f; + } /* * (non-Javadoc) @@ -287,6 +305,6 @@ public class CMISResultSetRow implements ResultSetRow public Serializable getValue(QName qname) { throw new UnsupportedOperationException(); - } - + } + }