mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged HEAD-BUG-FIX (5.0/Cloud) to HEAD (5.0/Cloud)
80628: Merged WAT1 (5.0/Cloud) to HEAD-BUG-FIX (5.0/Cloud) 76618: Initial commit of Java service changes for facet reordering. Part of ACE-1582. Facet persistence has not been changed, but a property has been added to the folder which contains the facet nodes. This property 'facetOrder' holds a sequence of strings which are the ordered facet IDs. Facets are now returned from the SolrFacetService in a sorted order, where this explicit 'facetOrder' is the primary source for sort order. The sorting algorithm falls back to using indexes if no order is available. It then falls back to using alphabetic sorting if no index is available. These last two scenarios are likely to be corner cases. Still to do: some enhancements to the Java service, webscripts as REST API endpoints. the REST API will provide for reordering of existing facets. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@82922 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -151,10 +151,24 @@
|
|||||||
</property>
|
</property>
|
||||||
</properties>
|
</properties>
|
||||||
</type>
|
</type>
|
||||||
|
|
||||||
<!-- Facets Root Folder -->
|
<!-- Facets Root Folder -->
|
||||||
<type name="srft:facets">
|
<type name="srft:facets">
|
||||||
<title>Facets</title>
|
<title>Facets</title>
|
||||||
<parent>cm:folder</parent>
|
<parent>cm:folder</parent>
|
||||||
|
<properties>
|
||||||
|
<property name="srft:facetOrder">
|
||||||
|
<title>Ordered sequence of Facet IDs</title>
|
||||||
|
<type>d:text</type>
|
||||||
|
<mandatory>false</mandatory>
|
||||||
|
<multiple>true</multiple>
|
||||||
|
<index enabled="false">
|
||||||
|
<atomic>false</atomic>
|
||||||
|
<stored>false</stored>
|
||||||
|
<tokenised>false</tokenised>
|
||||||
|
</index>
|
||||||
|
</property>
|
||||||
|
</properties>
|
||||||
</type>
|
</type>
|
||||||
</types>
|
</types>
|
||||||
|
|
||||||
|
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.search.impl.solr.facet;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
|
||||||
|
/** These exceptions are thrown by the {@link SolrFacetService}. */
|
||||||
|
public class Exceptions extends AlfrescoRuntimeException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
// Constructors for the basic SolrFacet Exception itself.
|
||||||
|
public Exceptions() { this("", null); }
|
||||||
|
public Exceptions(String message) { this(message, null); }
|
||||||
|
public Exceptions(Throwable cause) { this("", null); }
|
||||||
|
public Exceptions(String message, Throwable cause) { super(message, cause); }
|
||||||
|
|
||||||
|
/** This exception is used to signal a bad parameter. */
|
||||||
|
public static class IllegalArgument extends Exceptions
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public IllegalArgument() { super(); }
|
||||||
|
public IllegalArgument(String message) { super(message); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MissingFacetId extends IllegalArgument
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public MissingFacetId() { super(); }
|
||||||
|
public MissingFacetId(String message) { super(message); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DuplicateFacetId extends IllegalArgument
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final String facetId;
|
||||||
|
|
||||||
|
public DuplicateFacetId(String facetId)
|
||||||
|
{
|
||||||
|
this("", facetId);
|
||||||
|
}
|
||||||
|
public DuplicateFacetId(String message, String facetId)
|
||||||
|
{
|
||||||
|
super(message);
|
||||||
|
this.facetId = facetId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFacetId() { return this.facetId; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class UnrecognisedFacetId extends IllegalArgument
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private final String facetId;
|
||||||
|
|
||||||
|
public UnrecognisedFacetId(String facetId)
|
||||||
|
{
|
||||||
|
this("", facetId);
|
||||||
|
}
|
||||||
|
public UnrecognisedFacetId(String message, String facetId)
|
||||||
|
{
|
||||||
|
super(message);
|
||||||
|
this.facetId = facetId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFacetId() { return this.facetId; }
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.search.impl.solr.facet;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
|
|
||||||
|
/** This comparator defines the default sort order for facets. */
|
||||||
|
public class SolrFacetComparator implements Comparator<SolrFacetProperties>
|
||||||
|
{
|
||||||
|
/** A sequence of facet IDs which defines their order, as used in REST API & UI. */
|
||||||
|
private final List<String> sortedIDs;
|
||||||
|
|
||||||
|
public SolrFacetComparator(List<String> sortedIDs)
|
||||||
|
{
|
||||||
|
this.sortedIDs = new ArrayList<>();
|
||||||
|
if (sortedIDs != null) { this.sortedIDs.addAll(sortedIDs); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public int compare(SolrFacetProperties facet1, SolrFacetProperties facet2)
|
||||||
|
{
|
||||||
|
Pair<Integer, Integer> facetIndicesInSortedList = find(facet1, facet2);
|
||||||
|
|
||||||
|
if (bothSorted(facetIndicesInSortedList))
|
||||||
|
{
|
||||||
|
// Sorting is by position in the sortedIDs list.
|
||||||
|
return facetIndicesInSortedList.getFirst() - facetIndicesInSortedList.getSecond();
|
||||||
|
}
|
||||||
|
else if (neitherSorted(facetIndicesInSortedList))
|
||||||
|
{
|
||||||
|
// Sorting is by the index value defined in the facet itself.
|
||||||
|
final int indexDifference = facet1.getIndex() - facet2.getIndex();
|
||||||
|
|
||||||
|
if (indexDifference == 0)
|
||||||
|
{
|
||||||
|
// This could happen if an end user defines/overrides indexes to be equal.
|
||||||
|
// We'll sort based on facet ID if it does happen.
|
||||||
|
return facet1.getFilterID().compareTo(facet2.getFilterID());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return indexDifference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// One is in the sortedIDs list and one is not.
|
||||||
|
// All we want in this case is predictability. The order should be the same.
|
||||||
|
// We'll (arbitrarily) have facets without an explicit position go at the end.
|
||||||
|
return facetIndicesInSortedList.getSecond() == -1 ? -1 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the positional indices of the provided {@link SolrFacetProperties} in the {@link #sortedIDs}. */
|
||||||
|
private Pair<Integer, Integer> find(SolrFacetProperties facet1, SolrFacetProperties facet2)
|
||||||
|
{
|
||||||
|
return new Pair<>(sortedIDs.indexOf(facet1.getFilterID()),
|
||||||
|
sortedIDs.indexOf(facet2.getFilterID()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Are both of the provided positional indexes in the {@link #sortedIDs}? */
|
||||||
|
private boolean bothSorted(Pair<Integer, Integer> indices)
|
||||||
|
{ return indices.getFirst() != -1 && indices.getSecond() != -1; }
|
||||||
|
|
||||||
|
/** Are neither of the provided positional indexes in the {@link #sortedIDs}? */
|
||||||
|
private boolean neitherSorted(Pair<Integer, Integer> indices)
|
||||||
|
{ return indices.getFirst() == -1 && indices.getSecond() == -1; }
|
||||||
|
}
|
@@ -63,4 +63,9 @@ public interface SolrFacetModel
|
|||||||
public static final QName PROP_IS_DEFAULT = QName.createQName(SOLR_FACET_MODEL_URL, "isDefault");
|
public static final QName PROP_IS_DEFAULT = QName.createQName(SOLR_FACET_MODEL_URL, "isDefault");
|
||||||
|
|
||||||
public static final QName PROP_EXTRA_INFORMATION = QName.createQName(SOLR_FACET_CUSTOM_PROPERTY_URL, "extraInformation");
|
public static final QName PROP_EXTRA_INFORMATION = QName.createQName(SOLR_FACET_CUSTOM_PROPERTY_URL, "extraInformation");
|
||||||
|
|
||||||
|
/** The type of the facet container folder. */
|
||||||
|
public static final QName TYPE_FACETS = QName.createQName(SOLR_FACET_MODEL_URL, "facets");
|
||||||
|
|
||||||
|
public static final QName PROP_FACET_ORDER = QName.createQName(SOLR_FACET_MODEL_URL, "facetOrder");
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,10 @@ package org.alfresco.repo.search.impl.solr.facet;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.repo.search.impl.solr.facet.Exceptions.DuplicateFacetId;
|
||||||
|
import org.alfresco.repo.search.impl.solr.facet.Exceptions.IllegalArgument;
|
||||||
|
import org.alfresco.repo.search.impl.solr.facet.Exceptions.MissingFacetId;
|
||||||
|
import org.alfresco.repo.search.impl.solr.facet.Exceptions.UnrecognisedFacetId;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,7 +41,7 @@ public interface SolrFacetService
|
|||||||
* @return List of {@code SolrFacetProperties} or an empty list if none exists
|
* @return List of {@code SolrFacetProperties} or an empty list if none exists
|
||||||
*/
|
*/
|
||||||
public List<SolrFacetProperties> getFacets();
|
public List<SolrFacetProperties> getFacets();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the facet by filter Id.
|
* Gets the facet by filter Id.
|
||||||
*
|
*
|
||||||
@@ -87,4 +91,15 @@ public interface SolrFacetService
|
|||||||
public void deleteFacet(String filterID);
|
public void deleteFacet(String filterID);
|
||||||
|
|
||||||
public int getNextIndex();
|
public int getNextIndex();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reorders existing facets to the provided order.
|
||||||
|
*
|
||||||
|
* @param filterIds an ordered sequence of filter IDs.
|
||||||
|
* @throws NullPointerException if filterIds is {@code null}.
|
||||||
|
* @throws MissingFacetId if the list is empty.
|
||||||
|
* @throws UnrecognisedFacetId if any of the provided filter IDs are not recognised.
|
||||||
|
* @throws DuplicateFacetId if there is a duplicate filter ID in the list.
|
||||||
|
*/
|
||||||
|
public void reorderFacets(List<String> filterIds);
|
||||||
}
|
}
|
||||||
|
@@ -31,9 +31,10 @@ import java.util.Map;
|
|||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.NavigableMap;
|
import java.util.NavigableMap;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.SortedSet;
|
||||||
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.ConcurrentSkipListMap;
|
import java.util.concurrent.ConcurrentSkipListMap;
|
||||||
|
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.cache.SimpleCache;
|
import org.alfresco.repo.cache.SimpleCache;
|
||||||
import org.alfresco.repo.node.NodeServicePolicies;
|
import org.alfresco.repo.node.NodeServicePolicies;
|
||||||
@@ -44,6 +45,10 @@ import org.alfresco.repo.node.NodeServicePolicies.OnUpdateNodePolicy;
|
|||||||
import org.alfresco.repo.policy.BehaviourFilter;
|
import org.alfresco.repo.policy.BehaviourFilter;
|
||||||
import org.alfresco.repo.policy.JavaBehaviour;
|
import org.alfresco.repo.policy.JavaBehaviour;
|
||||||
import org.alfresco.repo.policy.PolicyComponent;
|
import org.alfresco.repo.policy.PolicyComponent;
|
||||||
|
import org.alfresco.repo.search.impl.solr.facet.Exceptions.DuplicateFacetId;
|
||||||
|
import org.alfresco.repo.search.impl.solr.facet.Exceptions.IllegalArgument;
|
||||||
|
import org.alfresco.repo.search.impl.solr.facet.Exceptions.MissingFacetId;
|
||||||
|
import org.alfresco.repo.search.impl.solr.facet.Exceptions.UnrecognisedFacetId;
|
||||||
import org.alfresco.repo.search.impl.solr.facet.SolrFacetProperties.CustomProperties;
|
import org.alfresco.repo.search.impl.solr.facet.SolrFacetProperties.CustomProperties;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||||
@@ -210,7 +215,22 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
@Override
|
@Override
|
||||||
public List<SolrFacetProperties> getFacets()
|
public List<SolrFacetProperties> getFacets()
|
||||||
{
|
{
|
||||||
return new ArrayList<>(facetsMap.values());
|
// Sort the facets into display order
|
||||||
|
final SolrFacetComparator comparator = new SolrFacetComparator(getFacetOrder());
|
||||||
|
|
||||||
|
SortedSet<SolrFacetProperties> result = new TreeSet<>(comparator);
|
||||||
|
result.addAll(facetsMap.values());
|
||||||
|
|
||||||
|
return new ArrayList<>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getFacetOrder()
|
||||||
|
{
|
||||||
|
final NodeRef facetContainer = getFacetsRoot();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final List<String> facetOrder = (List<String>) nodeService.getProperty(facetContainer, SolrFacetModel.PROP_FACET_ORDER);
|
||||||
|
return facetOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -435,6 +455,8 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
{
|
{
|
||||||
logger.debug("Deleted [" + filterID + "] facet.");
|
logger.debug("Deleted [" + filterID + "] facet.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Remove the matching filterID from the property list on the container.
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<QName, Serializable> createNodeProperties(SolrFacetProperties facetProperties)
|
private Map<QName, Serializable> createNodeProperties(SolrFacetProperties facetProperties)
|
||||||
@@ -544,7 +566,8 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
mergedMap.putAll(persistedProperties);
|
mergedMap.putAll(persistedProperties);
|
||||||
|
|
||||||
// Sort the merged maps
|
// Sort the merged maps
|
||||||
Map<String, SolrFacetProperties> sortedMap = CollectionUtils.sortMapByValue(mergedMap, getIndextComparator());
|
Comparator<Entry<String, SolrFacetProperties>> entryComparator = CollectionUtils.toEntryComparator(new SolrFacetComparator(getFacetOrder()));
|
||||||
|
Map<String, SolrFacetProperties> sortedMap = CollectionUtils.sortMapByValue(mergedMap, entryComparator);
|
||||||
LinkedList<SolrFacetProperties> orderedFacets = new LinkedList<>(sortedMap.values());
|
LinkedList<SolrFacetProperties> orderedFacets = new LinkedList<>(sortedMap.values());
|
||||||
|
|
||||||
// Get the last index, as the map is sorted by the FP's index value
|
// Get the last index, as the map is sorted by the FP's index value
|
||||||
@@ -641,24 +664,6 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
this.facetNodeRefCache.remove(filterID);
|
this.facetNodeRefCache.remove(filterID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Note: this comparator imposes orderings that are inconsistent with equals
|
|
||||||
* method of the {@link SolrFacetProperties}."
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private Comparator<Entry<String, SolrFacetProperties>> getIndextComparator()
|
|
||||||
{
|
|
||||||
return new Comparator<Entry<String, SolrFacetProperties>>()
|
|
||||||
{
|
|
||||||
public int compare(Entry<String, SolrFacetProperties> facet1,
|
|
||||||
Entry<String, SolrFacetProperties> facet2)
|
|
||||||
{
|
|
||||||
return Integer.compare(facet1.getValue().getIndex(), facet2.getValue().getIndex());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getNextIndex()
|
public int getNextIndex()
|
||||||
{
|
{
|
||||||
@@ -737,4 +742,47 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public void reorderFacets(List<String> facetIds)
|
||||||
|
{
|
||||||
|
// We need to validate the provided facet IDs
|
||||||
|
if (facetIds == null) { throw new NullPointerException("Illegal null facetIds"); }
|
||||||
|
else if (facetIds.isEmpty()) { throw new MissingFacetId("Illegal empty facetIds"); }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
final List<SolrFacetProperties> existingFacets = getFacets();
|
||||||
|
|
||||||
|
final Map<String, SolrFacetProperties> sortedFacets = new LinkedHashMap<>(); // maintains insertion order
|
||||||
|
for (String facetId : facetIds)
|
||||||
|
{
|
||||||
|
SolrFacetProperties facet = getFacet(facetId);
|
||||||
|
|
||||||
|
if (facet == null)
|
||||||
|
{
|
||||||
|
throw new UnrecognisedFacetId("Cannot reorder facets as ID not recognised:", facetId);
|
||||||
|
}
|
||||||
|
else if (sortedFacets.containsKey(facetId))
|
||||||
|
{
|
||||||
|
throw new DuplicateFacetId("Cannot reorder facets as sequence contains duplicate entry for ID:", facetId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sortedFacets.put(facetId, facet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (existingFacets.size() != sortedFacets.size())
|
||||||
|
{
|
||||||
|
throw new IllegalArgument("Cannot reorder facets. Expected " + existingFacets.size() +
|
||||||
|
" IDs but only received " + sortedFacets.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can now safely apply the updates to the facet ID sequence.
|
||||||
|
//
|
||||||
|
// Put them in an ArrayList to ensure the collection is Serializable.
|
||||||
|
// The alternative is changing the service API to look like <T extends Serializable & List<String>>
|
||||||
|
// which is a bit verbose for an API.
|
||||||
|
ArrayList<String> serializableProp = new ArrayList<>(facetIds);
|
||||||
|
nodeService.setProperty(getFacetsRoot(), SolrFacetModel.PROP_FACET_ORDER, serializableProp);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -96,5 +96,6 @@ public class AllUnitTestsSuite extends TestSuite
|
|||||||
suite.addTest(new JUnit4TestAdapter(org.alfresco.util.test.junitrules.TemporaryMockOverrideTest.class));
|
suite.addTest(new JUnit4TestAdapter(org.alfresco.util.test.junitrules.TemporaryMockOverrideTest.class));
|
||||||
suite.addTest(new JUnit4TestAdapter(org.alfresco.repo.search.impl.solr.SolrQueryHTTPClientTest.class));
|
suite.addTest(new JUnit4TestAdapter(org.alfresco.repo.search.impl.solr.SolrQueryHTTPClientTest.class));
|
||||||
suite.addTest(new JUnit4TestAdapter(org.alfresco.repo.search.impl.solr.SolrStatsResultTest.class));
|
suite.addTest(new JUnit4TestAdapter(org.alfresco.repo.search.impl.solr.SolrStatsResultTest.class));
|
||||||
|
suite.addTest(new JUnit4TestAdapter(org.alfresco.repo.search.impl.solr.facet.SolrFacetComparatorTest.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.repo.search.impl.solr.facet;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.util.collections.CollectionUtils;
|
||||||
|
import org.alfresco.util.collections.Function;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**Some Unit tests for {@link SolrFacetComparator}. */
|
||||||
|
public class SolrFacetComparatorTest
|
||||||
|
{
|
||||||
|
@Test public void simpleSortOfSortedFacets() throws Exception
|
||||||
|
{
|
||||||
|
List<String> expectedIds = Arrays.asList(new String[] { "a", "b", "c"});
|
||||||
|
|
||||||
|
SolrFacetProperties.Builder builder = new SolrFacetProperties.Builder();
|
||||||
|
|
||||||
|
List<SolrFacetProperties> facets = Arrays.asList(new SolrFacetProperties[]
|
||||||
|
{
|
||||||
|
builder.filterID("c").index(1).build(),
|
||||||
|
builder.filterID("b").index(2).build(),
|
||||||
|
builder.filterID("a").index(3).build(),
|
||||||
|
});
|
||||||
|
Collections.sort(facets, new SolrFacetComparator(expectedIds));
|
||||||
|
|
||||||
|
assertEquals(expectedIds, toFacetIds(facets));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> toFacetIds(List<SolrFacetProperties> facets)
|
||||||
|
{
|
||||||
|
return CollectionUtils.transform(facets, new Function<SolrFacetProperties, String>()
|
||||||
|
{
|
||||||
|
@Override public String apply(SolrFacetProperties value)
|
||||||
|
{
|
||||||
|
return value.getFilterID();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2014 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.repo.search.impl.solr.facet;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.repo.search.impl.solr.facet.Exceptions.DuplicateFacetId;
|
||||||
|
import org.alfresco.repo.search.impl.solr.facet.Exceptions.MissingFacetId;
|
||||||
|
import org.alfresco.repo.search.impl.solr.facet.Exceptions.UnrecognisedFacetId;
|
||||||
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
|
import org.alfresco.util.collections.CollectionUtils;
|
||||||
|
import org.alfresco.util.collections.Function;
|
||||||
|
import org.alfresco.util.test.junitrules.ApplicationContextInit;
|
||||||
|
import org.alfresco.util.test.junitrules.RunAsFullyAuthenticatedRule;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests for {@link SolrFacetServiceImpl}.
|
||||||
|
*/
|
||||||
|
public class SolrFacetServiceImplTest
|
||||||
|
{
|
||||||
|
// Rule to initialise the default Alfresco spring configuration
|
||||||
|
@ClassRule public static ApplicationContextInit APP_CONTEXT_INIT = new ApplicationContextInit();
|
||||||
|
|
||||||
|
@Rule public RunAsFullyAuthenticatedRule runAsRule = new RunAsFullyAuthenticatedRule(AuthenticationUtil.getAdminUserName());
|
||||||
|
|
||||||
|
// Various services
|
||||||
|
private static SolrFacetService SOLR_FACET_SERVICE;
|
||||||
|
private static RetryingTransactionHelper TRANSACTION_HELPER;
|
||||||
|
|
||||||
|
@BeforeClass public static void initStaticData() throws Exception
|
||||||
|
{
|
||||||
|
SOLR_FACET_SERVICE = APP_CONTEXT_INIT.getApplicationContext().getBean("solrFacetService", SolrFacetService.class);
|
||||||
|
TRANSACTION_HELPER = APP_CONTEXT_INIT.getApplicationContext().getBean("retryingTransactionHelper", RetryingTransactionHelper.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Ensure non-admin, non-search-admin user cannot access SolrFacetService
|
||||||
|
|
||||||
|
@Test public void getFacetsAndReorderThem() throws Exception
|
||||||
|
{
|
||||||
|
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
@Override public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
final List<String> facetIds = getExistingFacetIds();
|
||||||
|
final List<String> reorderedFacetIds = new ArrayList<>(facetIds);
|
||||||
|
Collections.reverse(reorderedFacetIds);
|
||||||
|
|
||||||
|
SOLR_FACET_SERVICE.reorderFacets(reorderedFacetIds);
|
||||||
|
|
||||||
|
final List<String> newfacetIds = getExistingFacetIds();
|
||||||
|
|
||||||
|
assertEquals(reorderedFacetIds, newfacetIds);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=NullPointerException.class)
|
||||||
|
public void reorderNullFacetIdsShouldFail() throws Exception
|
||||||
|
{
|
||||||
|
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
@Override public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
SOLR_FACET_SERVICE.reorderFacets(null);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=MissingFacetId.class)
|
||||||
|
public void reorderEmptyFacetIdsShouldFail() throws Exception
|
||||||
|
{
|
||||||
|
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
@Override public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
SOLR_FACET_SERVICE.reorderFacets(Collections.<String>emptyList());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=DuplicateFacetId.class)
|
||||||
|
public void reorderDuplicateFacetIdsShouldFail() throws Exception
|
||||||
|
{
|
||||||
|
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
@Override public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
final List<String> facetIds = getExistingFacetIds();
|
||||||
|
facetIds.add(facetIds.get(0));
|
||||||
|
|
||||||
|
SOLR_FACET_SERVICE.reorderFacets(facetIds);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=UnrecognisedFacetId.class)
|
||||||
|
public void reorderUnrecognisedFacetIdsShouldFail() throws Exception
|
||||||
|
{
|
||||||
|
TRANSACTION_HELPER.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
@Override public Void execute() throws Throwable
|
||||||
|
{
|
||||||
|
final List<String> facetIds = getExistingFacetIds();
|
||||||
|
facetIds.add("unrecognisedID");
|
||||||
|
|
||||||
|
SOLR_FACET_SERVICE.reorderFacets(facetIds);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> getExistingFacetIds()
|
||||||
|
{
|
||||||
|
final List<SolrFacetProperties> facetProps = SOLR_FACET_SERVICE.getFacets();
|
||||||
|
final List<String> facetIds = CollectionUtils.transform(facetProps,
|
||||||
|
new Function<SolrFacetProperties, String>()
|
||||||
|
{
|
||||||
|
@Override public String apply(SolrFacetProperties value)
|
||||||
|
{
|
||||||
|
return value.getFilterID();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return facetIds;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user