mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2026-09-16 18:13:17 +00:00
[MNT-25111] Shared Links API with where clause does not work with Search Enterprise (#4296)
This commit is contained in:
@@ -26,16 +26,24 @@
|
||||
package org.alfresco.repo.search;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.search.impl.QueryParameterisationException;
|
||||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.repository.XPathException;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.cmr.search.QueryParameter;
|
||||
import org.alfresco.service.cmr.search.QueryParameterDefinition;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.SearchLanguageConversion;
|
||||
|
||||
/**
|
||||
@@ -73,4 +81,90 @@ public abstract class AbstractSearcherComponent implements SearchService
|
||||
return selectProperties(contextNodeRef, xpath, parameters, namespacePrefixResolver, followAllParentLinks,
|
||||
SearchService.LANGUAGE_XPATH);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"PMD.CognitiveComplexity", "PMD.CyclomaticComplexity", "PMD.NPathComplexity", "PMD.AssignmentInOperand"})
|
||||
protected String parameterise(String unparameterised, Map<QName, QueryParameterDefinition> map, QueryParameter[] queryParameters, NamespacePrefixResolver nspr)
|
||||
throws QueryParameterisationException
|
||||
{
|
||||
|
||||
Map<QName, List<Serializable>> valueMap = new HashMap<>();
|
||||
|
||||
if (queryParameters != null)
|
||||
{
|
||||
for (QueryParameter parameter : queryParameters)
|
||||
{
|
||||
List<Serializable> list = valueMap.get(parameter.getQName());
|
||||
if (list == null)
|
||||
{
|
||||
list = new ArrayList<>();
|
||||
valueMap.put(parameter.getQName(), list);
|
||||
}
|
||||
list.add(parameter.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
Map<QName, ListIterator<Serializable>> iteratorMap = new HashMap<>();
|
||||
|
||||
List<QName> missing = new ArrayList<>(1);
|
||||
StringBuilder buffer = new StringBuilder(unparameterised);
|
||||
int index = 0;
|
||||
while ((index = buffer.indexOf("${", index)) != -1)
|
||||
{
|
||||
int endIndex = buffer.indexOf("}", index);
|
||||
if (endIndex == -1)
|
||||
{
|
||||
throw new QueryParameterisationException("Unclosed query parameter placeholder starting at index " + index);
|
||||
}
|
||||
String qNameString = buffer.substring(index + 2, endIndex);
|
||||
QName key = QName.createQName(qNameString, nspr);
|
||||
QueryParameterDefinition parameterDefinition = map.get(key);
|
||||
if (parameterDefinition == null)
|
||||
{
|
||||
missing.add(key);
|
||||
buffer.replace(index, endIndex + 1, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
ListIterator<Serializable> it = iteratorMap.get(key);
|
||||
if ((it == null) || (!it.hasNext()))
|
||||
{
|
||||
List<Serializable> list = valueMap.get(key);
|
||||
if ((list != null) && (!list.isEmpty()))
|
||||
{
|
||||
it = list.listIterator();
|
||||
}
|
||||
if (it != null)
|
||||
{
|
||||
iteratorMap.put(key, it);
|
||||
}
|
||||
}
|
||||
String value;
|
||||
if (it == null)
|
||||
{
|
||||
if (!parameterDefinition.hasDefaultValue())
|
||||
{
|
||||
throw new QueryParameterisationException("No value provided for query parameter: " + key);
|
||||
}
|
||||
value = parameterDefinition.getDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
value = DefaultTypeConverter.INSTANCE.convert(String.class, it.next());
|
||||
}
|
||||
buffer.replace(index, endIndex + 1, value);
|
||||
}
|
||||
}
|
||||
if (!missing.isEmpty())
|
||||
{
|
||||
StringBuilder error = new StringBuilder();
|
||||
error.append("The query uses the following parameters which are not defined: ");
|
||||
for (QName qName : missing)
|
||||
{
|
||||
error.append(qName).append(", ");
|
||||
}
|
||||
error.delete(error.length() - 2, error.length());
|
||||
throw new QueryParameterisationException(error.toString());
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
+25
-1
@@ -28,6 +28,7 @@ package org.alfresco.repo.search.impl.elasticsearch;
|
||||
import static org.alfresco.repo.search.adaptor.QueryConstants.FIELD_TAG;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -66,16 +67,19 @@ public class ElasticsearchSearchService extends AbstractSearcherComponent
|
||||
private final Map<String, LuceneQueryLanguageSPI> queryLanguages;
|
||||
private NodeService nodeService;
|
||||
private DictionaryService dictionaryService;
|
||||
private NamespacePrefixResolver namespacePrefixResolver;
|
||||
|
||||
public ElasticsearchSearchService(QueryRegisterComponent queryRegister,
|
||||
Map<String, LuceneQueryLanguageSPI> queryLanguages,
|
||||
NodeService nodeService,
|
||||
DictionaryService dictionaryService)
|
||||
DictionaryService dictionaryService,
|
||||
NamespacePrefixResolver namespacePrefixResolver)
|
||||
{
|
||||
this.queryRegister = queryRegister;
|
||||
this.queryLanguages = queryLanguages;
|
||||
this.nodeService = nodeService;
|
||||
this.dictionaryService = dictionaryService;
|
||||
this.namespacePrefixResolver = namespacePrefixResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -115,6 +119,7 @@ public class ElasticsearchSearchService extends AbstractSearcherComponent
|
||||
public ResultSet query(SearchParameters searchParameters)
|
||||
{
|
||||
adjustSearchParameters(searchParameters);
|
||||
parameteriseQuery(searchParameters);
|
||||
LuceneQueryLanguageSPI language = queryLanguages.get(searchParameters.getLanguage().toLowerCase());
|
||||
if (language != null)
|
||||
{
|
||||
@@ -126,6 +131,25 @@ public class ElasticsearchSearchService extends AbstractSearcherComponent
|
||||
}
|
||||
}
|
||||
|
||||
private void parameteriseQuery(SearchParameters searchParameters)
|
||||
{
|
||||
if (searchParameters.getQuery() == null
|
||||
|| searchParameters.getQueryParameterDefinitions() == null
|
||||
|| searchParameters.getQueryParameterDefinitions().isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Map<QName, QueryParameterDefinition> map = new HashMap<>();
|
||||
for (QueryParameterDefinition qpd : searchParameters.getQueryParameterDefinitions())
|
||||
{
|
||||
map.put(qpd.getQName(), qpd);
|
||||
}
|
||||
|
||||
String parameterisedQueryString = parameterise(searchParameters.getQuery(), map, null, namespacePrefixResolver);
|
||||
searchParameters.setQuery(parameterisedQueryString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NodeRef> selectNodes(NodeRef contextNodeRef, String xpath, QueryParameterDefinition[] parameters,
|
||||
NamespacePrefixResolver namespacePrefixResolver, boolean followAllParentLinks)
|
||||
|
||||
+8
-1
@@ -35,6 +35,7 @@ import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
||||
|
||||
/**
|
||||
* Factory for Indexer and Searcher instances for Elasticsearch
|
||||
@@ -44,6 +45,7 @@ public class ElasticsearchSearchServiceFactory extends AbstractIndexerAndSearche
|
||||
private QueryRegisterComponent queryRegister;
|
||||
private NodeService nodeService;
|
||||
private DictionaryService dictionaryService;
|
||||
private NamespacePrefixResolver namespacePrefixResolver;
|
||||
|
||||
/**
|
||||
* Elasticsearch is indexing the repository by polling database or listening queue messages from an external service, so no Indexer is available for the Repository.
|
||||
@@ -57,7 +59,7 @@ public class ElasticsearchSearchServiceFactory extends AbstractIndexerAndSearche
|
||||
@Override
|
||||
public SearchService getSearcher(StoreRef storeRef, boolean searchDelta) throws SearcherException
|
||||
{
|
||||
return new ElasticsearchSearchService(queryRegister, getQueryLanguages(), nodeService, dictionaryService);
|
||||
return new ElasticsearchSearchService(queryRegister, getQueryLanguages(), nodeService, dictionaryService, namespacePrefixResolver);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -80,4 +82,9 @@ public class ElasticsearchSearchServiceFactory extends AbstractIndexerAndSearche
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver)
|
||||
{
|
||||
this.namespacePrefixResolver = namespacePrefixResolver;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,10 +30,10 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.search.AbstractSearcherComponent;
|
||||
import org.alfresco.repo.search.CannedQueryDef;
|
||||
import org.alfresco.repo.search.QueryRegisterComponent;
|
||||
import org.alfresco.repo.search.SearcherException;
|
||||
@@ -61,7 +61,7 @@ import org.alfresco.util.SearchLanguageConversion;
|
||||
/**
|
||||
* @author Andy
|
||||
*/
|
||||
public class SolrSearchService implements SearchService
|
||||
public class SolrSearchService extends AbstractSearcherComponent
|
||||
{
|
||||
private NodeService nodeService;
|
||||
|
||||
@@ -227,86 +227,6 @@ public class SolrSearchService implements SearchService
|
||||
}
|
||||
}
|
||||
|
||||
/* Parameterise the query string - not sure if it is required to escape lucence spacials chars The parameters could be used to build the query - the contents of parameters should alread have been escaped if required. ... mush better to provide the parameters and work out what to do TODO: conditional query escapement - may be we should have a parameter type that is not escaped */
|
||||
private String parameterise(String unparameterised, Map<QName, QueryParameterDefinition> map, QueryParameter[] queryParameters, NamespacePrefixResolver nspr)
|
||||
throws QueryParameterisationException
|
||||
{
|
||||
|
||||
Map<QName, List<Serializable>> valueMap = new HashMap<QName, List<Serializable>>();
|
||||
|
||||
if (queryParameters != null)
|
||||
{
|
||||
for (QueryParameter parameter : queryParameters)
|
||||
{
|
||||
List<Serializable> list = valueMap.get(parameter.getQName());
|
||||
if (list == null)
|
||||
{
|
||||
list = new ArrayList<Serializable>();
|
||||
valueMap.put(parameter.getQName(), list);
|
||||
}
|
||||
list.add(parameter.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
Map<QName, ListIterator<Serializable>> iteratorMap = new HashMap<QName, ListIterator<Serializable>>();
|
||||
|
||||
List<QName> missing = new ArrayList<QName>(1);
|
||||
StringBuilder buffer = new StringBuilder(unparameterised);
|
||||
int index = 0;
|
||||
while ((index = buffer.indexOf("${", index)) != -1)
|
||||
{
|
||||
int endIndex = buffer.indexOf("}", index);
|
||||
String qNameString = buffer.substring(index + 2, endIndex);
|
||||
QName key = QName.createQName(qNameString, nspr);
|
||||
QueryParameterDefinition parameterDefinition = map.get(key);
|
||||
if (parameterDefinition == null)
|
||||
{
|
||||
missing.add(key);
|
||||
buffer.replace(index, endIndex + 1, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
ListIterator<Serializable> it = iteratorMap.get(key);
|
||||
if ((it == null) || (!it.hasNext()))
|
||||
{
|
||||
List<Serializable> list = valueMap.get(key);
|
||||
if ((list != null) && (list.size() > 0))
|
||||
{
|
||||
it = list.listIterator();
|
||||
}
|
||||
if (it != null)
|
||||
{
|
||||
iteratorMap.put(key, it);
|
||||
}
|
||||
}
|
||||
String value;
|
||||
if (it == null)
|
||||
{
|
||||
value = parameterDefinition.getDefault();
|
||||
}
|
||||
else
|
||||
{
|
||||
value = DefaultTypeConverter.INSTANCE.convert(String.class, it.next());
|
||||
}
|
||||
buffer.replace(index, endIndex + 1, value);
|
||||
}
|
||||
}
|
||||
if (missing.size() > 0)
|
||||
{
|
||||
StringBuilder error = new StringBuilder();
|
||||
error.append("The query uses the following parameters which are not defined: ");
|
||||
for (QName qName : missing)
|
||||
{
|
||||
error.append(qName);
|
||||
error.append(", ");
|
||||
}
|
||||
error.delete(error.length() - 1, error.length() - 1);
|
||||
error.delete(error.length() - 1, error.length() - 1);
|
||||
throw new QueryParameterisationException(error.toString());
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
*
|
||||
* @see org.alfresco.service.cmr.search.SearchService#query(org.alfresco.service.cmr.search.SearchParameters) */
|
||||
|
||||
+1
@@ -164,6 +164,7 @@
|
||||
<property name="queryRegister" ref="search.queryRegisterComponent" />
|
||||
<property name="nodeService" ref="nodeService" />
|
||||
<property name="dictionaryService" ref="DictionaryService" />
|
||||
<property name="namespacePrefixResolver" ref="namespaceService" />
|
||||
</bean>
|
||||
|
||||
<bean id="elasticsearchQueryExecutor" abstract="true" class="org.alfresco.repo.search.impl.elasticsearch.query.ElasticsearchQueryExecutor">
|
||||
|
||||
@@ -243,6 +243,7 @@ import org.alfresco.util.testing.category.NonBuildTests;
|
||||
org.alfresco.repo.domain.schema.script.ScriptBundleExecutorImplTest.class,
|
||||
org.alfresco.repo.search.MLAnaysisModeExpansionTest.class,
|
||||
org.alfresco.repo.search.DocumentNavigatorTest.class,
|
||||
org.alfresco.repo.search.AbstractSearcherComponentTest.class,
|
||||
org.alfresco.util.NumericEncodingTest.class,
|
||||
org.alfresco.repo.search.impl.parsers.CMIS_FTSTest.class,
|
||||
org.alfresco.repo.search.impl.parsers.CMISTest.class,
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2026 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.search;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.alfresco.repo.search.impl.QueryParameterisationException;
|
||||
import org.alfresco.service.cmr.repository.InvalidNodeRefException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.repository.XPathException;
|
||||
import org.alfresco.service.cmr.search.QueryParameter;
|
||||
import org.alfresco.service.cmr.search.QueryParameterDefinition;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AbstractSearcherComponentTest
|
||||
{
|
||||
private static final String TEST_URI = "http://www.alfresco.org/test/1.0";
|
||||
private static final String PREFIX = "test";
|
||||
|
||||
private final AbstractSearcherComponent searcher = new StubSearcherComponent();
|
||||
|
||||
@Mock
|
||||
private NamespacePrefixResolver namespacePrefixResolver;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
lenient().when(namespacePrefixResolver.getNamespaceURI(PREFIX)).thenReturn(TEST_URI);
|
||||
}
|
||||
|
||||
private static QName paramQName(String localName)
|
||||
{
|
||||
return QName.createQName(TEST_URI, localName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterise_substitutesSuppliedParameterValue()
|
||||
{
|
||||
Map<QName, QueryParameterDefinition> map = new HashMap<>();
|
||||
map.put(paramQName("param"), mock(QueryParameterDefinition.class));
|
||||
|
||||
QueryParameter parameter = mock(QueryParameter.class);
|
||||
when(parameter.getQName()).thenReturn(paramQName("param"));
|
||||
when(parameter.getValue()).thenReturn("hello");
|
||||
|
||||
String result = searcher.parameterise("value:${test:param}", map, new QueryParameter[]{parameter}, namespacePrefixResolver);
|
||||
|
||||
assertThat(result).isEqualTo("value:hello");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterise_substitutesDefaultValueWhenNoParameterSupplied()
|
||||
{
|
||||
QueryParameterDefinition qpd = mock(QueryParameterDefinition.class);
|
||||
when(qpd.hasDefaultValue()).thenReturn(true);
|
||||
when(qpd.getDefault()).thenReturn("admin");
|
||||
|
||||
Map<QName, QueryParameterDefinition> map = new HashMap<>();
|
||||
map.put(paramQName("param"), qpd);
|
||||
|
||||
String result = searcher.parameterise("user:${test:param}", map, null, namespacePrefixResolver);
|
||||
|
||||
assertThat(result).isEqualTo("user:admin");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterise_iteratesSuppliedValuesInOrderForRepeatedPlaceholder()
|
||||
{
|
||||
Map<QName, QueryParameterDefinition> map = new HashMap<>();
|
||||
map.put(paramQName("param"), mock(QueryParameterDefinition.class));
|
||||
|
||||
QueryParameter first = mock(QueryParameter.class);
|
||||
when(first.getQName()).thenReturn(paramQName("param"));
|
||||
when(first.getValue()).thenReturn("one");
|
||||
QueryParameter second = mock(QueryParameter.class);
|
||||
when(second.getQName()).thenReturn(paramQName("param"));
|
||||
when(second.getValue()).thenReturn("two");
|
||||
|
||||
String result = searcher.parameterise("${test:param}-${test:param}", map, new QueryParameter[]{first, second}, namespacePrefixResolver);
|
||||
|
||||
assertThat(result).isEqualTo("one-two");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterise_returnsQueryUnchangedWhenNoPlaceholders()
|
||||
{
|
||||
String result = searcher.parameterise("TYPE:\"cm:content\"", new HashMap<>(), null, namespacePrefixResolver);
|
||||
|
||||
assertThat(result).isEqualTo("TYPE:\"cm:content\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterise_throwsWhenPlaceholderReferencesUndefinedParameter()
|
||||
{
|
||||
assertThatExceptionOfType(QueryParameterisationException.class)
|
||||
.isThrownBy(() -> searcher.parameterise("value:${test:param}", new HashMap<>(), null, namespacePrefixResolver))
|
||||
.withMessageContaining("not defined");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterise_throwsWhenPlaceholderIsUnclosed()
|
||||
{
|
||||
assertThatExceptionOfType(QueryParameterisationException.class)
|
||||
.isThrownBy(() -> searcher.parameterise("value:${test:param", new HashMap<>(), null, namespacePrefixResolver))
|
||||
.withMessageContaining("Unclosed");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parameterise_throwsWhenParameterHasNoValueAndNoDefault()
|
||||
{
|
||||
QueryParameterDefinition qpd = mock(QueryParameterDefinition.class);
|
||||
when(qpd.hasDefaultValue()).thenReturn(false);
|
||||
|
||||
Map<QName, QueryParameterDefinition> map = new HashMap<>();
|
||||
map.put(paramQName("param"), qpd);
|
||||
|
||||
assertThatExceptionOfType(QueryParameterisationException.class)
|
||||
.isThrownBy(() -> searcher.parameterise("value:${test:param}", map, null, namespacePrefixResolver))
|
||||
.withMessageContaining("No value provided");
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimal concrete subclass so the shared {@code protected} parameterise implementation can be exercised in isolation. The remaining {@link org.alfresco.service.cmr.search.SearchService} operations are not needed here.
|
||||
*/
|
||||
private static final class StubSearcherComponent extends AbstractSearcherComponent
|
||||
{
|
||||
@Override
|
||||
public ResultSet query(StoreRef store, String language, String query, QueryParameterDefinition[] queryParameterDefinitions)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSet query(StoreRef store, QName queryId, QueryParameter[] queryParameters)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSet query(SearchParameters searchParameters)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NodeRef> selectNodes(NodeRef contextNodeRef, String xpath, QueryParameterDefinition[] parameters,
|
||||
NamespacePrefixResolver namespacePrefixResolver, boolean followAllParentLinks, String language)
|
||||
throws InvalidNodeRefException, XPathException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Serializable> selectProperties(NodeRef contextNodeRef, String xpath, QueryParameterDefinition[] parameters,
|
||||
NamespacePrefixResolver namespacePrefixResolver, boolean followAllParentLinks, String language)
|
||||
throws InvalidNodeRefException, XPathException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(NodeRef nodeRef, QName propertyQName, String googleLikePattern) throws InvalidNodeRefException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(NodeRef nodeRef, QName propertyQName, String googleLikePattern, SearchParameters.Operator defaultOperator)
|
||||
throws InvalidNodeRefException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean like(NodeRef nodeRef, QName propertyQName, String sqlLikePattern, boolean includeFTS) throws InvalidNodeRefException
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
+40
-1
@@ -33,6 +33,7 @@ import static org.mockito.Mockito.*;
|
||||
import static org.alfresco.service.cmr.search.SearchService.LANGUAGE_FTS_ALFRESCO;
|
||||
import static org.alfresco.service.cmr.search.SearchService.LANGUAGE_LUCENE;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -49,8 +50,11 @@ import org.alfresco.repo.search.SearcherException;
|
||||
import org.alfresco.repo.search.impl.lucene.LuceneQueryLanguageSPI;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.search.QueryParameterDefinition;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ElasticsearchSearchServiceTest
|
||||
@@ -71,6 +75,9 @@ public class ElasticsearchSearchServiceTest
|
||||
@Mock
|
||||
private DictionaryService dictionaryService;
|
||||
|
||||
@Mock
|
||||
private NamespacePrefixResolver namespacePrefixResolver;
|
||||
|
||||
@Mock
|
||||
private SearchParameters searchParameters;
|
||||
|
||||
@@ -83,9 +90,10 @@ public class ElasticsearchSearchServiceTest
|
||||
Map<String, LuceneQueryLanguageSPI> languages = new HashMap<>();
|
||||
languages.put(LANGUAGE.toLowerCase(Locale.getDefault()), queryLanguage);
|
||||
|
||||
searchService = new ElasticsearchSearchService(queryRegister, languages, nodeService, dictionaryService);
|
||||
searchService = new ElasticsearchSearchService(queryRegister, languages, nodeService, dictionaryService, namespacePrefixResolver);
|
||||
|
||||
when(searchParameters.getLanguage()).thenReturn(LANGUAGE);
|
||||
when(searchParameters.getQueryParameterDefinitions()).thenReturn(new ArrayList<>());
|
||||
when(queryLanguage.executeQuery(any(SearchParameters.class))).thenReturn(resultSet);
|
||||
}
|
||||
|
||||
@@ -152,6 +160,37 @@ public class ElasticsearchSearchServiceTest
|
||||
verify(searchParameters, times(1)).setLanguage(LANGUAGE_FTS_ALFRESCO);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void luceneQueryWithParameterDefinition_shouldSubstitutePlaceholderWithDefaultValue()
|
||||
{
|
||||
String qshareUri = "http://www.alfresco.org/model/qshare/1.0";
|
||||
when(namespacePrefixResolver.getNamespaceURI("qshare")).thenReturn(qshareUri);
|
||||
|
||||
QName sharedBy = QName.createQName(qshareUri, "sharedBy");
|
||||
QueryParameterDefinition qpd = mock(QueryParameterDefinition.class);
|
||||
when(qpd.getQName()).thenReturn(sharedBy);
|
||||
when(qpd.hasDefaultValue()).thenReturn(true);
|
||||
when(qpd.getDefault()).thenReturn("admin");
|
||||
|
||||
when(searchParameters.getQuery()).thenReturn("ASPECT:\"qshare:shared\" +@qshare:sharedBy:\"${qshare:sharedBy}\"");
|
||||
when(searchParameters.getQueryParameterDefinitions()).thenReturn(new ArrayList<>(List.of(qpd)));
|
||||
|
||||
searchService.query(searchParameters);
|
||||
|
||||
verify(searchParameters, times(1)).setQuery("ASPECT:\"qshare:shared\" +@qshare:sharedBy:\"admin\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void luceneQueryWithoutParameterDefinitions_shouldNotSubstitute()
|
||||
{
|
||||
when(searchParameters.getQuery()).thenReturn("ASPECT:\"qshare:shared\"");
|
||||
when(searchParameters.getQueryParameterDefinitions()).thenReturn(new ArrayList<>());
|
||||
|
||||
searchService.query(searchParameters);
|
||||
|
||||
verify(searchParameters, never()).setQuery(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void luceneQuery_whenNotMatchingTagQuery_shouldNotBeModified()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user