Merged HEAD-BUG-FIX (4.3/Cloud) to HEAD (4.3/Cloud)

70680: Merged WAT1 (4.3/Cloud) to HEAD-BUG-FIX (4.3/Cloud)
      69081: ACE-1265: Fixed the selected Date/Size range filtering
      	- Added insertion index for the facet label, to help the Date/Size sorting labels in the UI.
      	- A minor optimization in SolrFacetHelper.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@70911 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Draper
2014-05-19 12:49:26 +00:00
parent c22799ddfa
commit ad28258976
3 changed files with 176 additions and 84 deletions

View File

@@ -31,17 +31,20 @@ public class ScriptFacetResult implements Serializable
private final String facetValue; private final String facetValue;
private final String facetLabel; private final String facetLabel;
private final int facetLabelIndex;
private final int hits; private final int hits;
/** /**
* @param facetValue the facet value. e.g. the content creator's userID * @param facetValue the facet value. e.g. the content creator's userID
* @param facetLabel the display name of the {@code facetValue}. e.g. jdoe => John Doe * @param facetLabel the display name of the {@code facetValue}. e.g. jdoe => John Doe
* @param facetLabelIndex the label index to be used for sorting (Optional).The default value is -1
* @param hits the number of hits * @param hits the number of hits
*/ */
public ScriptFacetResult(String facetValue, String facetLabel, int hits) public ScriptFacetResult(String facetValue, String facetLabel, int facetLabelIndex, int hits)
{ {
this.facetValue = facetValue; this.facetValue = facetValue;
this.facetLabel = facetLabel; this.facetLabel = facetLabel;
this.facetLabelIndex = facetLabelIndex;
this.hits = hits; this.hits = hits;
} }
@@ -61,6 +64,14 @@ public class ScriptFacetResult implements Serializable
return this.facetLabel; return this.facetLabel;
} }
/**
* @return the facetLabelIndex
*/
public int getFacetLabelIndex()
{
return this.facetLabelIndex;
}
/** /**
* @return the hits * @return the hits
*/ */

View File

@@ -34,6 +34,7 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.management.subsystems.SwitchableApplicationContextFactory; import org.alfresco.repo.management.subsystems.SwitchableApplicationContextFactory;
import org.alfresco.repo.model.Repository; import org.alfresco.repo.model.Repository;
import org.alfresco.repo.search.impl.solr.facet.SolrFacetHelper; import org.alfresco.repo.search.impl.solr.facet.SolrFacetHelper;
import org.alfresco.repo.search.impl.solr.facet.SolrFacetHelper.FacetLabel;
import org.alfresco.repo.search.impl.solr.facet.SolrFacetHelper.FacetLabelDisplayHandler; import org.alfresco.repo.search.impl.solr.facet.SolrFacetHelper.FacetLabelDisplayHandler;
import org.alfresco.service.ServiceRegistry; import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentReader;
@@ -928,9 +929,9 @@ public class Search extends BaseScopableProcessorExtension implements Initializi
{ {
String facetValue = f.getFirst(); String facetValue = f.getFirst();
FacetLabelDisplayHandler handler = solrFacetHelper.getDisplayHandler(ff.getField()); FacetLabelDisplayHandler handler = solrFacetHelper.getDisplayHandler(ff.getField());
String label = (handler == null) ? facetValue : handler.getDisplayLabel(facetValue).getSecond(); String label = (handler == null) ? facetValue : handler.getDisplayLabel(facetValue).getLabel();
facets.add(new ScriptFacetResult(facetValue, label, f.getSecond())); facets.add(new ScriptFacetResult(facetValue, label, -1, f.getSecond()));
} }
} }
// store facet results per field // store facet results per field
@@ -938,7 +939,6 @@ public class Search extends BaseScopableProcessorExtension implements Initializi
} }
Set<Entry<String, Integer>> facetQueries = results.getFacetQueries().entrySet(); Set<Entry<String, Integer>> facetQueries = results.getFacetQueries().entrySet();
Map<String, List<ScriptFacetResult>> facetQueryMeta = new HashMap<>(facetQueries.size());
for(Entry<String, Integer> entry : facetQueries) for(Entry<String, Integer> entry : facetQueries)
{ {
// ignore zero hit facet queries // ignore zero hit facet queries
@@ -951,23 +951,22 @@ public class Search extends BaseScopableProcessorExtension implements Initializi
String qName = key.substring(7, key.lastIndexOf(':')); String qName = key.substring(7, key.lastIndexOf(':'));
// Retrieve the previous facet queries // Retrieve the previous facet queries
List<ScriptFacetResult> fqs = facetQueryMeta.get(qName); List<ScriptFacetResult> fqs = facetMeta.get(qName);
if (fqs == null) if (fqs == null)
{ {
fqs = new ArrayList<>(); fqs = new ArrayList<>();
} }
FacetLabelDisplayHandler handler = solrFacetHelper.getDisplayHandler(qName); FacetLabelDisplayHandler handler = solrFacetHelper.getDisplayHandler(qName);
Pair<String, String> valueLabelPair = (handler == null) ? new Pair<String, String>(qName, FacetLabel facetLabel = (handler == null) ? new FacetLabel(qName, key.substring(qName.length(),
key.substring(qName.length(), key.length())) : handler.getDisplayLabel(key); key.length()), -1) : handler.getDisplayLabel(key);
fqs.add(new ScriptFacetResult(valueLabelPair.getFirst(), valueLabelPair.getSecond(), entry.getValue())); fqs.add(new ScriptFacetResult(facetLabel.getValue(), facetLabel.getLabel(), facetLabel.getLabelIndex(), entry.getValue()));
// store facet query results per field // store facet query results per field
facetQueryMeta.put(qName, fqs); facetMeta.put(qName, fqs);
} }
} }
meta.put("facets", facetMeta); meta.put("facets", facetMeta);
meta.put("facetQueries", facetQueryMeta);
} }
catch (Throwable err) catch (Throwable err)
{ {

View File

@@ -20,6 +20,7 @@ package org.alfresco.repo.search.impl.solr.facet;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -72,6 +73,18 @@ public class SolrFacetHelper
private static final String SIZE_BUCKETS_CACHE_KEY = "sizeBucketsCacheKey"; private static final String SIZE_BUCKETS_CACHE_KEY = "sizeBucketsCacheKey";
/** Content size buckets */
private static final List<String> CONTENT_SIZE_BUCKETS = new ArrayList<>(6);
static
{
CONTENT_SIZE_BUCKETS.add("0 TO " + TINY);
CONTENT_SIZE_BUCKETS.add(TINY + " TO " + SMALL);
CONTENT_SIZE_BUCKETS.add(SMALL + " TO " + MEDIUM);
CONTENT_SIZE_BUCKETS.add(MEDIUM + " TO " + LARGE);
CONTENT_SIZE_BUCKETS.add(LARGE + " TO " + HUGE);
CONTENT_SIZE_BUCKETS.add(HUGE + " TO MAX");
}
/** Facet value and facet query display label handlers */ /** Facet value and facet query display label handlers */
private Map<String, FacetLabelDisplayHandler> displayHandlers; private Map<String, FacetLabelDisplayHandler> displayHandlers;
@@ -90,15 +103,14 @@ public class SolrFacetHelper
UserNameDisplayHandler userNameDisplayHandler = new UserNameDisplayHandler(serviceRegistry); UserNameDisplayHandler userNameDisplayHandler = new UserNameDisplayHandler(serviceRegistry);
MimetypeDisplayHandler mimetypeDisplayHandler = new MimetypeDisplayHandler(serviceRegistry); MimetypeDisplayHandler mimetypeDisplayHandler = new MimetypeDisplayHandler(serviceRegistry);
DateBucketsDisplayHandler createdDateBucketsDisplayHandler = new DateBucketsDisplayHandler("cm:created"); DateBucketsDisplayHandler dateBucketsDisplayHandler = new DateBucketsDisplayHandler();
DateBucketsDisplayHandler modifiedDateBucketsDisplayHandler = new DateBucketsDisplayHandler("cm:modified"); ContentSizeBucketsDisplayHandler contentSizeBucketsDisplayHandler = new ContentSizeBucketsDisplayHandler();
ContentSizeBucketsDisplayHandler contentSizeBucketsDisplayHandler = new ContentSizeBucketsDisplayHandler("cm:content.size");
this.displayHandlers.put("@{http://www.alfresco.org/model/content/1.0}creator.__", userNameDisplayHandler); this.displayHandlers.put("@{http://www.alfresco.org/model/content/1.0}creator.__", userNameDisplayHandler);
this.displayHandlers.put("@{http://www.alfresco.org/model/content/1.0}modifier.__", userNameDisplayHandler); this.displayHandlers.put("@{http://www.alfresco.org/model/content/1.0}modifier.__", userNameDisplayHandler);
this.displayHandlers.put("@{http://www.alfresco.org/model/content/1.0}content.mimetype", mimetypeDisplayHandler); this.displayHandlers.put("@{http://www.alfresco.org/model/content/1.0}content.mimetype", mimetypeDisplayHandler);
this.displayHandlers.put("@{http://www.alfresco.org/model/content/1.0}created", createdDateBucketsDisplayHandler); this.displayHandlers.put("@{http://www.alfresco.org/model/content/1.0}created", dateBucketsDisplayHandler);
this.displayHandlers.put("@{http://www.alfresco.org/model/content/1.0}modified", modifiedDateBucketsDisplayHandler); this.displayHandlers.put("@{http://www.alfresco.org/model/content/1.0}modified", dateBucketsDisplayHandler);
this.displayHandlers.put("@{http://www.alfresco.org/model/content/1.0}content.size", contentSizeBucketsDisplayHandler); this.displayHandlers.put("@{http://www.alfresco.org/model/content/1.0}content.size", contentSizeBucketsDisplayHandler);
} }
@@ -134,7 +146,7 @@ public class SolrFacetHelper
} }
// Content size facet query // Content size facet query
for (String bucket : makeContentSizeBuckets()) for (String bucket : CONTENT_SIZE_BUCKETS)
{ {
facetQueries.add(CONTENT_SIZE_FACET_QUERY_PREFIX + '[' + bucket + ']'); facetQueries.add(CONTENT_SIZE_FACET_QUERY_PREFIX + '[' + bucket + ']');
} }
@@ -188,64 +200,45 @@ public class SolrFacetHelper
* *
* @return Map of {@literal <date range, display label key>} * @return Map of {@literal <date range, display label key>}
*/ */
private static Map<String, String> makeDateBucketsDisplayLabel(LocalDate date) private static Map<String, Pair<String, Integer>> makeDateBucketsDisplayLabel(LocalDate date)
{ {
List<String> dateBuckets = makeDateBuckets(date); List<String> dateBuckets = makeDateBuckets(date);
Map<String, String> bucketDisplayName = new HashMap<>(5); Map<String, Pair<String, Integer>> bucketDisplayName = new LinkedHashMap<>(5);
if (dateBuckets.size() != 5) if (dateBuckets.size() != 5)
{ {
throw new AlfrescoRuntimeException("Date buckets size does not match the bucket display label size!"); throw new AlfrescoRuntimeException("Date buckets size does not match the bucket display label size!");
} }
bucketDisplayName.put(dateBuckets.get(0), "faceted-search.date.one-day.label"); bucketDisplayName.put(dateBuckets.get(0), new Pair<String, Integer>("faceted-search.date.one-day.label", 0));
bucketDisplayName.put(dateBuckets.get(1), "faceted-search.date.one-week.label"); bucketDisplayName.put(dateBuckets.get(1), new Pair<String, Integer>("faceted-search.date.one-week.label", 1));
bucketDisplayName.put(dateBuckets.get(2), "faceted-search.date.one-month.label"); bucketDisplayName.put(dateBuckets.get(2), new Pair<String, Integer>("faceted-search.date.one-month.label", 2));
bucketDisplayName.put(dateBuckets.get(3), "faceted-search.date.six-months.label"); bucketDisplayName.put(dateBuckets.get(3), new Pair<String, Integer>("faceted-search.date.six-months.label", 3));
bucketDisplayName.put(dateBuckets.get(4), "faceted-search.date.one-year.label"); bucketDisplayName.put(dateBuckets.get(4), new Pair<String, Integer>("faceted-search.date.one-year.label", 4));
return bucketDisplayName; return bucketDisplayName;
} }
/**
* Creates Content size buckets
*
* @return list of size ranges. e.g. "0 TO 1024"
*/
private static List<String> makeContentSizeBuckets()
{
List<String> sizeBuckets = new ArrayList<>(6);
sizeBuckets.add("0 TO " + TINY);
sizeBuckets.add(TINY + " TO " + SMALL);
sizeBuckets.add(SMALL + " TO " + MEDIUM);
sizeBuckets.add(MEDIUM + " TO " + LARGE);
sizeBuckets.add(LARGE + " TO " + HUGE);
sizeBuckets.add(HUGE + " TO MAX");
return sizeBuckets;
}
/** /**
* Creates display name for the Content size buckets. * Creates display name for the Content size buckets.
* *
* @return Map of {@literal <size range, display label key>} * @return Map of {@literal <size range, display label key>}
*/ */
private static Map<String, String> makeContentSizeBucketsDisplayLabel() private static Map<String, Pair<String, Integer>> makeContentSizeBucketsDisplayLabel()
{ {
List<String> sizeBuckets = makeContentSizeBuckets(); Map<String, Pair<String, Integer>> bucketDisplayName = new HashMap<>(6);
Map<String, String> bucketDisplayName = new HashMap<>(6);
if (sizeBuckets.size() != 6) if (CONTENT_SIZE_BUCKETS.size() != 6)
{ {
throw new AlfrescoRuntimeException("Content size buckets size does not match the bucket display label size!"); throw new AlfrescoRuntimeException("Content size buckets size does not match the bucket display label size!");
} }
bucketDisplayName.put(sizeBuckets.get(0), "faceted-search.size.0-10KB.label"); bucketDisplayName.put(CONTENT_SIZE_BUCKETS.get(0), new Pair<String, Integer>("faceted-search.size.0-10KB.label", 0));
bucketDisplayName.put(sizeBuckets.get(1), "faceted-search.size.10-100KB.label"); bucketDisplayName.put(CONTENT_SIZE_BUCKETS.get(1), new Pair<String, Integer>("faceted-search.size.10-100KB.label", 1));
bucketDisplayName.put(sizeBuckets.get(2), "faceted-search.size.100KB-1MB.label"); bucketDisplayName.put(CONTENT_SIZE_BUCKETS.get(2), new Pair<String, Integer>("faceted-search.size.100KB-1MB.label", 2));
bucketDisplayName.put(sizeBuckets.get(3), "faceted-search.size.1-16MB.label"); bucketDisplayName.put(CONTENT_SIZE_BUCKETS.get(3), new Pair<String, Integer>("faceted-search.size.1-16MB.label", 3));
bucketDisplayName.put(sizeBuckets.get(4), "faceted-search.size.16-128MB.label"); bucketDisplayName.put(CONTENT_SIZE_BUCKETS.get(4), new Pair<String, Integer>("faceted-search.size.16-128MB.label", 4));
bucketDisplayName.put(sizeBuckets.get(5), "faceted-search.size.over128.label"); bucketDisplayName.put(CONTENT_SIZE_BUCKETS.get(5), new Pair<String, Integer>("faceted-search.size.over128.label", 5));
return bucketDisplayName; return bucketDisplayName;
} }
@@ -350,10 +343,10 @@ public class SolrFacetHelper
* *
* @author Jamal Kaabi-Mofrad * @author Jamal Kaabi-Mofrad
*/ */
private static class FacetQueryResultDateBuckets implements Buckets<LocalDate, Map<String, String>> private static class FacetQueryResultDateBuckets implements Buckets<LocalDate, Map<String, Pair<String, Integer>>>
{ {
@Override @Override
public Map<String, String> compute(LocalDate localDate) throws Exception public Map<String, Pair<String, Integer>> compute(LocalDate localDate) throws Exception
{ {
return makeDateBucketsDisplayLabel(localDate); return makeDateBucketsDisplayLabel(localDate);
} }
@@ -365,10 +358,10 @@ public class SolrFacetHelper
* *
* @author Jamal Kaabi-Mofrad * @author Jamal Kaabi-Mofrad
*/ */
private static class FacetQueryResultContentSizeBuckets implements Buckets<String, Map<String, String>> private static class FacetQueryResultContentSizeBuckets implements Buckets<String, Map<String, Pair<String, Integer>>>
{ {
@Override @Override
public Map<String, String> compute(String arg) throws Exception public Map<String, Pair<String, Integer>> compute(String arg) throws Exception
{ {
return makeContentSizeBucketsDisplayLabel(); return makeContentSizeBucketsDisplayLabel();
} }
@@ -381,7 +374,108 @@ public class SolrFacetHelper
*/ */
public static interface FacetLabelDisplayHandler public static interface FacetLabelDisplayHandler
{ {
Pair<String, String> getDisplayLabel(String value); FacetLabel getDisplayLabel(String value);
}
/**
* A class to encapsulate the result of the facet label display handler
*
* @author Jamal Kaabi-Mofrad
*/
public static class FacetLabel
{
private final String value;
private final String label;
private final int labelIndex;
/**
* @param value
* @param label
* @param labelIndex
*/
public FacetLabel(String value, String label, int labelIndex)
{
this.value = value;
this.label = label;
this.labelIndex = labelIndex;
}
/**
* Gets the original facet value or a new modified value
*
* @return the original facet value or a new modified value
*/
public String getValue()
{
return this.value;
}
/**
* Gets the facet display label
*
* @return the label
*/
public String getLabel()
{
return this.label;
}
/**
* Gets the label index to be used for sorting. The index only relevant
* to to Date and Size facets.
*
* @return the index or -1, if it isn't relevant to the facet label
*/
public int getLabelIndex()
{
return this.labelIndex;
}
/*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((this.label == null) ? 0 : this.label.hashCode());
result = prime * result + this.labelIndex;
result = prime * result + ((this.value == null) ? 0 : this.value.hashCode());
return result;
}
/*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof FacetLabel))
return false;
FacetLabel other = (FacetLabel) obj;
if (this.label == null)
{
if (other.label != null)
return false;
}
else if (!this.label.equals(other.label))
return false;
if (this.labelIndex != other.labelIndex)
return false;
if (this.value == null)
{
if (other.value != null)
return false;
}
else if (!this.value.equals(other.value))
return false;
return true;
}
} }
/** /**
@@ -401,7 +495,7 @@ public class SolrFacetHelper
} }
@Override @Override
public Pair<String, String> getDisplayLabel(String value) public FacetLabel getDisplayLabel(String value)
{ {
String name = null; String name = null;
@@ -412,7 +506,7 @@ public class SolrFacetHelper
final String lastName = (String) nodeService.getProperty(personRef, ContentModel.PROP_LASTNAME); final String lastName = (String) nodeService.getProperty(personRef, ContentModel.PROP_LASTNAME);
name = (firstName != null ? firstName + " " : "") + (lastName != null ? lastName : ""); name = (firstName != null ? firstName + " " : "") + (lastName != null ? lastName : "");
} }
return new Pair<String, String>(value, name == null ? value : name.trim()); return new FacetLabel(value, name == null ? value : name.trim(), -1);
} }
} }
@@ -431,11 +525,11 @@ public class SolrFacetHelper
} }
@Override @Override
public Pair<String, String> getDisplayLabel(String value) public FacetLabel getDisplayLabel(String value)
{ {
Map<String, String> mimetypes = mimetypeService.getDisplaysByMimetype(); Map<String, String> mimetypes = mimetypeService.getDisplaysByMimetype();
String displayName = mimetypes.get(value); String displayName = mimetypes.get(value);
return new Pair<String, String>(value, displayName == null ? value : displayName.trim()); return new FacetLabel(value, displayName == null ? value : displayName.trim(), -1);
} }
} }
@@ -446,19 +540,13 @@ public class SolrFacetHelper
*/ */
public static class DateBucketsDisplayHandler implements FacetLabelDisplayHandler public static class DateBucketsDisplayHandler implements FacetLabelDisplayHandler
{ {
private final BucketsCache<LocalDate, Map<String, String>> cache = new BucketsCache<>( private final BucketsCache<LocalDate, Map<String, Pair<String, Integer>>> cache = new BucketsCache<>(
new FacetQueryResultDateBuckets()); new FacetQueryResultDateBuckets());
private final String fq;
public DateBucketsDisplayHandler(String fq)
{
this.fq = fq;
}
@Override @Override
public Pair<String, String> getDisplayLabel(String value) public FacetLabel getDisplayLabel(String value)
{ {
Map<String, String> dateBuckets = null; Map<String, Pair<String, Integer>> dateBuckets = null;
String dateRange = value.substring(value.indexOf('[') + 1, value.length() - 1); String dateRange = value.substring(value.indexOf('[') + 1, value.length() - 1);
String[] lowerUpperDates = dateRange.split("\\sTO\\s"); String[] lowerUpperDates = dateRange.split("\\sTO\\s");
@@ -473,9 +561,9 @@ public class SolrFacetHelper
"Error occurred while trying to get the date buckets from the cache. Calculating the dates without the cache.", e); "Error occurred while trying to get the date buckets from the cache. Calculating the dates without the cache.", e);
dateBuckets = makeDateBucketsDisplayLabel(date); dateBuckets = makeDateBucketsDisplayLabel(date);
} }
String newValue = fq + ":\"" + lowerUpperDates[0] + "\"..\"" + lowerUpperDates[1] + '"'; String newValue = lowerUpperDates[0] + "\"..\"" + lowerUpperDates[1];
String label = dateBuckets.get(dateRange); Pair<String, Integer> labelIndexPair = dateBuckets.get(dateRange);
return new Pair<String, String>(newValue, label); return new FacetLabel(newValue, labelIndexPair.getFirst(), labelIndexPair.getSecond());
} }
} }
@@ -486,22 +574,16 @@ public class SolrFacetHelper
*/ */
public static class ContentSizeBucketsDisplayHandler implements FacetLabelDisplayHandler public static class ContentSizeBucketsDisplayHandler implements FacetLabelDisplayHandler
{ {
private final BucketsCache<String, Map<String, String>> cache = new BucketsCache<>( private final BucketsCache<String, Map<String, Pair<String, Integer>>> cache = new BucketsCache<>(
new FacetQueryResultContentSizeBuckets()); new FacetQueryResultContentSizeBuckets());
private final String fq;
public ContentSizeBucketsDisplayHandler(String fq)
{
this.fq = fq;
}
@Override @Override
public Pair<String, String> getDisplayLabel(String value) public FacetLabel getDisplayLabel(String value)
{ {
String sizeRange = value.substring(value.indexOf('[') + 1, value.length() - 1); String sizeRange = value.substring(value.indexOf('[') + 1, value.length() - 1);
String[] lowerUppperSize = sizeRange.split("\\sTO\\s"); String[] lowerUppperSize = sizeRange.split("\\sTO\\s");
Map<String, String> sizeBuckets; Map<String, Pair<String, Integer>> sizeBuckets;
try try
{ {
sizeBuckets = cache.getRangeBuckets(SIZE_BUCKETS_CACHE_KEY); sizeBuckets = cache.getRangeBuckets(SIZE_BUCKETS_CACHE_KEY);
@@ -513,9 +595,9 @@ public class SolrFacetHelper
sizeBuckets = makeContentSizeBucketsDisplayLabel(); sizeBuckets = makeContentSizeBucketsDisplayLabel();
} }
String newValue = fq + ":\"" + lowerUppperSize[0] + "\"..\"" + lowerUppperSize[1] + '"'; String newValue = lowerUppperSize[0] + "\"..\"" + lowerUppperSize[1];
String label = sizeBuckets.get(sizeRange); Pair<String, Integer> labelIndexPair = sizeBuckets.get(sizeRange);
return new Pair<String, String>(newValue, label); return new FacetLabel(newValue, labelIndexPair.getFirst(), labelIndexPair.getSecond());
} }
} }
} }