diff --git a/config/alfresco/subsystems/Search/solr/solr-search-context.xml b/config/alfresco/subsystems/Search/solr/solr-search-context.xml
index 5287f76f3b..cb2e4dfd2a 100644
--- a/config/alfresco/subsystems/Search/solr/solr-search-context.xml
+++ b/config/alfresco/subsystems/Search/solr/solr-search-context.xml
@@ -36,6 +36,8 @@
+
+
diff --git a/config/alfresco/subsystems/Search/solr4/solr-search-context.xml b/config/alfresco/subsystems/Search/solr4/solr-search-context.xml
index cb63cd2bb8..64cea67b03 100644
--- a/config/alfresco/subsystems/Search/solr4/solr-search-context.xml
+++ b/config/alfresco/subsystems/Search/solr4/solr-search-context.xml
@@ -36,6 +36,8 @@
+
+
diff --git a/config/alfresco/subsystems/Search/solr6/solr-search-context.xml b/config/alfresco/subsystems/Search/solr6/solr-search-context.xml
index 5103cfe755..cb06e6dd40 100644
--- a/config/alfresco/subsystems/Search/solr6/solr-search-context.xml
+++ b/config/alfresco/subsystems/Search/solr6/solr-search-context.xml
@@ -36,6 +36,8 @@
+
+
diff --git a/source/java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClient.java b/source/java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClient.java
index dfb7e81e1e..24b596e6c4 100644
--- a/source/java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClient.java
+++ b/source/java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClient.java
@@ -25,19 +25,25 @@
*/
package org.alfresco.repo.search.impl.solr;
+import static org.alfresco.util.SearchDateConversion.parseDateInterval;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.opencmis.dictionary.CMISStrictDictionaryService;
import org.alfresco.repo.admin.RepositoryState;
+import org.alfresco.repo.dictionary.NamespaceDAO;
import org.alfresco.repo.domain.node.NodeDAO;
import org.alfresco.repo.index.shard.Floc;
import org.alfresco.repo.index.shard.ShardInstance;
import org.alfresco.repo.index.shard.ShardRegistry;
+import org.alfresco.repo.search.impl.QueryParserUtils;
import org.alfresco.repo.search.impl.lucene.JSONResult;
import org.alfresco.repo.search.impl.lucene.LuceneQueryParserException;
import org.alfresco.repo.search.impl.lucene.SolrJSONResultSet;
import org.alfresco.repo.search.impl.lucene.SolrJsonProcessor;
import org.alfresco.repo.search.impl.lucene.SolrStatsResult;
import org.alfresco.repo.tenant.TenantService;
+import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
@@ -105,6 +111,8 @@ public class SolrQueryHTTPClient implements BeanFactoryAware, InitializingBean
{
static Log s_logger = LogFactory.getLog(SolrQueryHTTPClient.class);
+ private DictionaryService dictionaryService;
+
private NodeService nodeService;
private PermissionService permissionService;
@@ -141,6 +149,8 @@ public class SolrQueryHTTPClient implements BeanFactoryAware, InitializingBean
private int defaultShardedFacetLimit = 20;
+ private NamespaceDAO namespaceDAO;
+
public SolrQueryHTTPClient()
{
}
@@ -153,7 +163,8 @@ public class SolrQueryHTTPClient implements BeanFactoryAware, InitializingBean
PropertyCheck.mandatory(this, "LanguageMappings", languageMappings);
PropertyCheck.mandatory(this, "StoreMappings", storeMappings);
PropertyCheck.mandatory(this, "RepositoryState", repositoryState);
-
+ PropertyCheck.mandatory(this, "namespaceDAO", namespaceDAO);
+ PropertyCheck.mandatory(this, "dictionaryService", dictionaryService);
}
public void setAlternativeDictionary(String alternativeDictionary)
@@ -192,6 +203,16 @@ public class SolrQueryHTTPClient implements BeanFactoryAware, InitializingBean
this.tenantService = tenantService;
}
+ public void setDictionaryService(DictionaryService dictionaryService)
+ {
+ this.dictionaryService = dictionaryService;
+ }
+
+ public void setNamespaceDAO(NamespaceDAO namespaceDAO)
+ {
+ this.namespaceDAO = namespaceDAO;
+ }
+
public void setShardRegistry(ShardRegistry shardRegistry)
{
this.shardRegistry = shardRegistry;
@@ -810,6 +831,15 @@ public class SolrQueryHTTPClient implements BeanFactoryAware, InitializingBean
{
url.append("&facet.interval=");
String intervalField = interval.getField();
+ boolean isDate = false;
+
+ PropertyDefinition propertyDef = QueryParserUtils.matchPropertyDefinition(searchParameters.getNamespace(),
+ namespaceDAO, dictionaryService, interval.getField());
+ if (propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME)
+ || propertyDef.getDataType().getName().equals(DataTypeDefinition.DATE))
+ {
+ isDate = true;
+ }
if (interval.getLabel() != null && !interval.getLabel().isEmpty())
{
@@ -822,7 +852,8 @@ public class SolrQueryHTTPClient implements BeanFactoryAware, InitializingBean
{
for (IntervalSet aSet:interval.getSets())
{
- url.append("&").append(encoder.encode("f."+intervalField+".facet.interval.set", "UTF-8")).append("=").append(encoder.encode(aSet.toParam(), "UTF-8"));
+ IntervalSet validated = parseDateInterval(aSet,isDate);
+ url.append("&").append(encoder.encode("f."+intervalField+".facet.interval.set", "UTF-8")).append("=").append(encoder.encode(validated.toParam(), "UTF-8"));
}
}
}
diff --git a/source/test-java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClientTest.java b/source/test-java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClientTest.java
index f88f45dba2..73c26843ac 100644
--- a/source/test-java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClientTest.java
+++ b/source/test-java/org/alfresco/repo/search/impl/solr/SolrQueryHTTPClientTest.java
@@ -25,22 +25,45 @@
*/
package org.alfresco.repo.search.impl.solr;
+import static org.alfresco.service.namespace.NamespaceService.CONTENT_MODEL_PREFIX;
import static org.junit.Assert.*;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.notNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.alfresco.model.ContentModel;
+import org.alfresco.repo.admin.RepositoryState;
+import org.alfresco.repo.dictionary.NamespaceDAO;
+import org.alfresco.repo.forms.processor.node.MockClassAttributeDefinition;
+import org.alfresco.repo.tenant.TenantService;
+import org.alfresco.service.ServiceRegistry;
+import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
+import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.FieldHighlightParameters;
import org.alfresco.service.cmr.search.GeneralHighlightParameters;
+import org.alfresco.service.cmr.search.Interval;
+import org.alfresco.service.cmr.search.IntervalParameters;
+import org.alfresco.service.cmr.search.IntervalSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchParameters.SortDefinition;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.search.StatsParameters;
+import org.alfresco.service.namespace.NamespacePrefixResolver;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.util.PropertyCheck;
import org.apache.commons.codec.net.URLCodec;
import org.json.JSONArray;
import org.json.JSONException;
@@ -57,28 +80,53 @@ import org.junit.Test;
*/
public class SolrQueryHTTPClientTest
{
-
- static Map languageMappings;
-
+ static SolrQueryHTTPClient client = new SolrQueryHTTPClient();
+ static URLCodec encoder = new URLCodec();
+
@BeforeClass
public static void setUpBeforeClass() throws Exception
{
- languageMappings = new HashMap();
+ Map languageMappings = new HashMap();
languageMappings.put("solr-alfresco", "alfresco");
languageMappings.put("solr-fts-alfresco", "afts");
languageMappings.put("solr-cmis", "cmis");
- }
- @Before
- public void setUp() throws Exception
- {
+ NamespaceDAO namespaceDAO = mock(NamespaceDAO.class);
+ DictionaryService dictionaryService = mock(DictionaryService.class);
+
+ when(namespaceDAO.getPrefixes()).thenReturn(Arrays.asList(CONTENT_MODEL_PREFIX, "exif"));
+ when(namespaceDAO.getNamespaceURI(anyString())).thenReturn(NamespaceService.CONTENT_MODEL_1_0_URI);
+
+ when(dictionaryService.getProperty(notNull(QName.class))).thenAnswer(invocation ->
+ {
+ Object[] args = invocation.getArguments();
+ QName qName = (QName)args[0];
+ if (qName.getLocalName().contains("created"))
+ {
+ return MockClassAttributeDefinition.mockPropertyDefinition(qName, DataTypeDefinition.DATE);
+ }
+ else
+ {
+ return MockClassAttributeDefinition.mockPropertyDefinition(qName, DataTypeDefinition.ANY);
+ }
+
+ });
+
+ client.setLanguageMappings(languageMappings);
+ client.setDictionaryService(dictionaryService);
+ client.setNamespaceDAO(namespaceDAO);
+
+ //required for init() but not used.
+ client.setNodeService(mock(NodeService.class));
+ client.setTenantService(mock(TenantService.class));
+ client.setStoreMappings(Collections.emptyList());
+ client.setRepositoryState(mock(RepositoryState.class));
+ client.init();
}
@Test
public void testBuildStatsUrl() throws UnsupportedEncodingException
{
- SolrQueryHTTPClient client = new SolrQueryHTTPClient();
- client.setLanguageMappings(languageMappings);
StatsParameters params = getParameters();
String url = client.buildStatsUrl(params, "http://localhost:8080/solr/alfresco/select", Locale.CANADA_FRENCH, null);
assertNotNull(url);
@@ -91,7 +139,7 @@ public class SolrQueryHTTPClientTest
@Test
public void testBuildStatsBody() throws JSONException
{
- SolrQueryHTTPClient client = new SolrQueryHTTPClient();
+
StatsParameters params = getParameters();
JSONObject body = client.buildStatsBody(params, "myTenant", Locale.US);
assertNotNull(body);
@@ -108,7 +156,6 @@ public class SolrQueryHTTPClientTest
StringBuilder luceneQuery = new StringBuilder();
luceneQuery.append(" +TYPE:\"" + ContentModel.TYPE_CONTENT + "\"");
-
String filterQuery = "ANCESTOR:\"workspace://SpacesStore/a1c1a0a1-9d68-4912-b853-b3b277f31288\"";
StatsParameters params = new StatsParameters(SearchService.LANGUAGE_SOLR_FTS_ALFRESCO, luceneQuery.toString(), filterQuery, false);
params.addSort(new SortDefinition(SortDefinition.SortType.FIELD, "contentsize", false));
@@ -122,9 +169,6 @@ public class SolrQueryHTTPClientTest
@Test
public void testBuildHighlightQuery() throws UnsupportedEncodingException
{
- SolrQueryHTTPClient client = new SolrQueryHTTPClient();
- client.setLanguageMappings(languageMappings);
- URLCodec encoder = new URLCodec();
SearchParameters params = new SearchParameters();
params.setSearchTerm("bob");
StringBuilder urlBuilder = new StringBuilder();
@@ -191,7 +235,47 @@ public class SolrQueryHTTPClientTest
assertTrue(url.contains("&f.title.hl.simple.pre="+encoder.encode("*", "UTF-8")));
assertTrue(url.contains("&f.title.hl.simple.post="+encoder.encode("¿", "UTF-8")));
+ }
+ @Test
+ public void testBuildFacetIntervalQuery() throws UnsupportedEncodingException
+ {
+ SearchParameters params = new SearchParameters();
+ params.setSearchTerm("bob");
+
+ IntervalSet intervalSet = new IntervalSet("8", "12", null, null, null);
+ params.setInterval(new IntervalParameters(Arrays.asList(intervalSet), null));
+ StringBuilder urlBuilder = new StringBuilder();
+ client.buildFacetIntervalParameters(params, encoder, urlBuilder);
+ String url = urlBuilder.toString();
+ assertNotNull(url);
+ assertTrue(url.contains("&facet=true"));
+ assertTrue(url.contains(encoder.encode("{!afts}[8,12]", "UTF-8")));
+
+ intervalSet = new IntervalSet("1", "10", "numbers", false, true);
+ params.setInterval(new IntervalParameters(Arrays.asList(intervalSet), null));
+ urlBuilder = new StringBuilder();
+ client.buildFacetIntervalParameters(params, encoder, urlBuilder);
+ url = urlBuilder.toString();
+ assertNotNull(url);
+ assertTrue(url.contains("&facet=true"));
+ assertTrue(url.contains(encoder.encode("{!afts key=numbers}(1,10]", "UTF-8")));
+
+ List intervalList = Arrays.asList(new Interval("cm:price", "Price", null), new Interval("cm:created", "Created", Arrays.asList(new IntervalSet("2015", "2016-12", "special", false, true))));
+ params.setInterval(new IntervalParameters(Arrays.asList(intervalSet), intervalList));
+ urlBuilder = new StringBuilder();
+ client.buildFacetIntervalParameters(params, encoder, urlBuilder);
+ url = urlBuilder.toString();
+ assertNotNull(url);
+ assertTrue(url.contains("&facet=true"));
+ assertTrue(url.contains(encoder.encode("{!afts key=numbers}(1,10]", "UTF-8")));
+
+ assertTrue(url.contains(encoder.encode("{!key=Price}cm:price", "UTF-8")));
+ assertTrue(url.contains(encoder.encode("{!key=Created}cm:created", "UTF-8")));
+ assertTrue(url.contains("f.Created.facet.interval.set"));
+ assertTrue(url.contains(encoder.encode("{!afts key=numbers}", "UTF-8")));
+ assertTrue(url.contains(encoder.encode("(2015-12-31T22:59:59.999Z", "UTF-8")));
+ assertTrue(url.contains(encoder.encode("2016-12-31T22:59:59.999Z]", "UTF-8")));
}
}