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)
80669: Merged WAT1 (5.0/Cloud) to HEAD-BUG-FIX (5.0/Cloud) 78166: ACE-1582: Enhancements to the facet service to persist only the modified value(s) rather than the whole facet's properties. Also fixed facets cache and facets reordering NPE. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@82966 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -119,16 +119,6 @@
|
|||||||
<tokenised>false</tokenised>
|
<tokenised>false</tokenised>
|
||||||
</index>
|
</index>
|
||||||
</property>
|
</property>
|
||||||
<property name="srft:index">
|
|
||||||
<title>Index</title>
|
|
||||||
<type>d:int</type>
|
|
||||||
<mandatory>true</mandatory>
|
|
||||||
<index enabled="false">
|
|
||||||
<atomic>false</atomic>
|
|
||||||
<stored>false</stored>
|
|
||||||
<tokenised>false</tokenised>
|
|
||||||
</index>
|
|
||||||
</property>
|
|
||||||
<property name="srft:isEnabled">
|
<property name="srft:isEnabled">
|
||||||
<title>Is enabled</title>
|
<title>Is enabled</title>
|
||||||
<type>d:boolean</type>
|
<type>d:boolean</type>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# Alfresco default facets
|
# Alfresco default facets
|
||||||
# Note: If you have changed the filter’s default value(s) via Share, then any subsequent changes of the default values won’t be applied to the filter on server startup.
|
# Note: If you have changed the filter's<> default value(s) via Share, then any subsequent changes of those default values won't be applied to the filter on server startup.
|
||||||
#
|
#
|
||||||
|
|
||||||
# Field-Facet-Qname => cm:content.mimetype
|
# Field-Facet-Qname => cm:content.mimetype
|
||||||
@@ -11,9 +11,8 @@ default.cm\:content.mimetype.maxFilters=5
|
|||||||
default.cm\:content.mimetype.hitThreshold=1
|
default.cm\:content.mimetype.hitThreshold=1
|
||||||
default.cm\:content.mimetype.minFilterValueLength=4
|
default.cm\:content.mimetype.minFilterValueLength=4
|
||||||
default.cm\:content.mimetype.sortBy=DESCENDING
|
default.cm\:content.mimetype.sortBy=DESCENDING
|
||||||
default.cm\:content.mimetype.scope=SCOPED_SITES
|
default.cm\:content.mimetype.scope=ALL
|
||||||
default.cm\:content.mimetype.scopedSites=
|
default.cm\:content.mimetype.scopedSites=
|
||||||
default.cm\:content.mimetype.index=0
|
|
||||||
default.cm\:content.mimetype.isEnabled=true
|
default.cm\:content.mimetype.isEnabled=true
|
||||||
|
|
||||||
# Field-Facet-Qname => cm:description.__
|
# Field-Facet-Qname => cm:description.__
|
||||||
@@ -24,10 +23,9 @@ default.cm\:description.__.maxFilters=5
|
|||||||
default.cm\:description.__.hitThreshold=1
|
default.cm\:description.__.hitThreshold=1
|
||||||
default.cm\:description.__.minFilterValueLength=4
|
default.cm\:description.__.minFilterValueLength=4
|
||||||
default.cm\:description.__.sortBy=DESCENDING
|
default.cm\:description.__.sortBy=DESCENDING
|
||||||
default.cm\:description.__.scope=SCOPED_SITES
|
default.cm\:description.__.scope=ALL
|
||||||
default.cm\:description.__.scopedSites=
|
default.cm\:description.__.scopedSites=
|
||||||
default.cm\:description.__.index=1
|
default.cm\:description.__.isEnabled=false
|
||||||
default.cm\:description.__.isEnabled=true
|
|
||||||
|
|
||||||
# Field-Facet-Qname => cm:creator.__.u
|
# Field-Facet-Qname => cm:creator.__.u
|
||||||
default.cm\:creator.__.u.filterID=filter_creator
|
default.cm\:creator.__.u.filterID=filter_creator
|
||||||
@@ -37,9 +35,8 @@ default.cm\:creator.__.u.maxFilters=5
|
|||||||
default.cm\:creator.__.u.hitThreshold=1
|
default.cm\:creator.__.u.hitThreshold=1
|
||||||
default.cm\:creator.__.u.minFilterValueLength=4
|
default.cm\:creator.__.u.minFilterValueLength=4
|
||||||
default.cm\:creator.__.u.sortBy=ALPHABETICALLY
|
default.cm\:creator.__.u.sortBy=ALPHABETICALLY
|
||||||
default.cm\:creator.__.u.scope=SCOPED_SITES
|
default.cm\:creator.__.u.scope=ALL
|
||||||
default.cm\:creator.__.u.scopedSites=
|
default.cm\:creator.__.u.scopedSites=
|
||||||
default.cm\:creator.__.u.index=2
|
|
||||||
default.cm\:creator.__.u.isEnabled=true
|
default.cm\:creator.__.u.isEnabled=true
|
||||||
|
|
||||||
# Field-Facet-Qname => cm:modifier.__.u
|
# Field-Facet-Qname => cm:modifier.__.u
|
||||||
@@ -50,9 +47,8 @@ default.cm\:modifier.__.u.maxFilters=5
|
|||||||
default.cm\:modifier.__.u.hitThreshold=1
|
default.cm\:modifier.__.u.hitThreshold=1
|
||||||
default.cm\:modifier.__.u.minFilterValueLength=4
|
default.cm\:modifier.__.u.minFilterValueLength=4
|
||||||
default.cm\:modifier.__.u.sortBy=ALPHABETICALLY
|
default.cm\:modifier.__.u.sortBy=ALPHABETICALLY
|
||||||
default.cm\:modifier.__.u.scope=SCOPED_SITES
|
default.cm\:modifier.__.u.scope=ALL
|
||||||
default.cm\:modifier.__.u.scopedSites=
|
default.cm\:modifier.__.u.scopedSites=
|
||||||
default.cm\:modifier.__.u.index=3
|
|
||||||
default.cm\:modifier.__.u.isEnabled=true
|
default.cm\:modifier.__.u.isEnabled=true
|
||||||
|
|
||||||
# Field-Facet-Qname => cm:created
|
# Field-Facet-Qname => cm:created
|
||||||
@@ -63,9 +59,8 @@ default.cm\:created.maxFilters=5
|
|||||||
default.cm\:created.hitThreshold=1
|
default.cm\:created.hitThreshold=1
|
||||||
default.cm\:created.minFilterValueLength=4
|
default.cm\:created.minFilterValueLength=4
|
||||||
default.cm\:created.sortBy=ALPHABETICALLY
|
default.cm\:created.sortBy=ALPHABETICALLY
|
||||||
default.cm\:created.scope=SCOPED_SITES
|
default.cm\:created.scope=ALL
|
||||||
default.cm\:created.scopedSites=
|
default.cm\:created.scopedSites=
|
||||||
default.cm\:created.index=4
|
|
||||||
default.cm\:created.isEnabled=true
|
default.cm\:created.isEnabled=true
|
||||||
default.cm\:created.EXTRA-PROP.blockIncludeFacetRequest=true
|
default.cm\:created.EXTRA-PROP.blockIncludeFacetRequest=true
|
||||||
|
|
||||||
@@ -77,9 +72,8 @@ default.cm\:modified.maxFilters=5
|
|||||||
default.cm\:modified.hitThreshold=1
|
default.cm\:modified.hitThreshold=1
|
||||||
default.cm\:modified.minFilterValueLength=4
|
default.cm\:modified.minFilterValueLength=4
|
||||||
default.cm\:modified.sortBy=ALPHABETICALLY
|
default.cm\:modified.sortBy=ALPHABETICALLY
|
||||||
default.cm\:modified.scope=SCOPED_SITES
|
default.cm\:modified.scope=ALL
|
||||||
default.cm\:modified.scopedSites=
|
default.cm\:modified.scopedSites=
|
||||||
default.cm\:modified.index=5
|
|
||||||
default.cm\:modified.isEnabled=true
|
default.cm\:modified.isEnabled=true
|
||||||
default.cm\:modified.EXTRA-PROP.blockIncludeFacetRequest=true
|
default.cm\:modified.EXTRA-PROP.blockIncludeFacetRequest=true
|
||||||
|
|
||||||
@@ -91,8 +85,7 @@ default.cm\:content.size.maxFilters=5
|
|||||||
default.cm\:content.size.hitThreshold=1
|
default.cm\:content.size.hitThreshold=1
|
||||||
default.cm\:content.size.minFilterValueLength=4
|
default.cm\:content.size.minFilterValueLength=4
|
||||||
default.cm\:content.size.sortBy=ALPHABETICALLY
|
default.cm\:content.size.sortBy=ALPHABETICALLY
|
||||||
default.cm\:content.size.scope=SCOPED_SITES
|
default.cm\:content.size.scope=ALL
|
||||||
default.cm\:content.size.scopedSites=
|
default.cm\:content.size.scopedSites=
|
||||||
default.cm\:content.size.index=6
|
|
||||||
default.cm\:content.size.isEnabled=true
|
default.cm\:content.size.isEnabled=true
|
||||||
default.cm\:content.size.EXTRA-PROP.blockIncludeFacetRequest=true
|
default.cm\:content.size.EXTRA-PROP.blockIncludeFacetRequest=true
|
||||||
|
@@ -38,6 +38,11 @@ public class SolrFacetComparator implements Comparator<SolrFacetProperties>
|
|||||||
|
|
||||||
@Override public int compare(SolrFacetProperties facet1, SolrFacetProperties facet2)
|
@Override public int compare(SolrFacetProperties facet1, SolrFacetProperties facet2)
|
||||||
{
|
{
|
||||||
|
if (sortedIDs.isEmpty())
|
||||||
|
{
|
||||||
|
return facet1.getFilterID().compareTo(facet2.getFilterID());
|
||||||
|
}
|
||||||
|
|
||||||
Pair<Integer, Integer> facetIndicesInSortedList = find(facet1, facet2);
|
Pair<Integer, Integer> facetIndicesInSortedList = find(facet1, facet2);
|
||||||
|
|
||||||
if (bothSorted(facetIndicesInSortedList))
|
if (bothSorted(facetIndicesInSortedList))
|
||||||
@@ -47,19 +52,7 @@ public class SolrFacetComparator implements Comparator<SolrFacetProperties>
|
|||||||
}
|
}
|
||||||
else if (neitherSorted(facetIndicesInSortedList))
|
else if (neitherSorted(facetIndicesInSortedList))
|
||||||
{
|
{
|
||||||
// Sorting is by the index value defined in the facet itself.
|
return facet1.getFilterID().compareTo(facet2.getFilterID());
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
|
@@ -39,6 +39,7 @@ import org.apache.commons.logging.Log;
|
|||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.context.ApplicationEvent;
|
import org.springframework.context.ApplicationEvent;
|
||||||
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
||||||
|
import org.springframework.extensions.surf.util.ParameterCheck;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class picks up all the loaded properties passed to it and uses a naming
|
* This class picks up all the loaded properties passed to it and uses a naming
|
||||||
@@ -58,7 +59,6 @@ import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
|||||||
* <li>custom.cm\:content.mimetype.sortBy=DESCENDING</li>
|
* <li>custom.cm\:content.mimetype.sortBy=DESCENDING</li>
|
||||||
* <li>custom.cm\:content.mimetype.scope=SCOPED_SITES</li>
|
* <li>custom.cm\:content.mimetype.scope=SCOPED_SITES</li>
|
||||||
* <li>custom.cm\:content.mimetype.scopedSites=site1,site2,site3</li>
|
* <li>custom.cm\:content.mimetype.scopedSites=site1,site2,site3</li>
|
||||||
* <li>custom.cm\:content.mimetype.index=0</li>
|
|
||||||
* <li>custom.cm\:content.mimetype.isEnabled=true</li>
|
* <li>custom.cm\:content.mimetype.isEnabled=true</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* Also, if there is a need to add additional properties, the following needs to be
|
* Also, if there is a need to add additional properties, the following needs to be
|
||||||
@@ -91,8 +91,8 @@ public class SolrFacetConfig extends AbstractLifecycleBean
|
|||||||
|
|
||||||
public SolrFacetConfig(Properties rawProperties, String inheritanceOrder)
|
public SolrFacetConfig(Properties rawProperties, String inheritanceOrder)
|
||||||
{
|
{
|
||||||
PropertyCheck.mandatory(this, "rawProperties", rawProperties);
|
ParameterCheck.mandatory("rawProperties", rawProperties);
|
||||||
PropertyCheck.mandatory(this, "inheritanceOrder", inheritanceOrder);
|
ParameterCheck.mandatory("inheritanceOrder", inheritanceOrder);
|
||||||
|
|
||||||
this.rawProperties = rawProperties;
|
this.rawProperties = rawProperties;
|
||||||
|
|
||||||
@@ -223,12 +223,7 @@ public class SolrFacetConfig extends AbstractLifecycleBean
|
|||||||
String sortBy = propValues.get(ValueName.PROP_SORTBY.getPropValueName(field));
|
String sortBy = propValues.get(ValueName.PROP_SORTBY.getPropValueName(field));
|
||||||
String scope = propValues.get(ValueName.PROP_SCOPE.getPropValueName(field));
|
String scope = propValues.get(ValueName.PROP_SCOPE.getPropValueName(field));
|
||||||
Set<String> scopedSites = getScopedSites(propValues.get(ValueName.PROP_SCOPED_SITES.getPropValueName(field)));
|
Set<String> scopedSites = getScopedSites(propValues.get(ValueName.PROP_SCOPED_SITES.getPropValueName(field)));
|
||||||
int index = getIntegerValue(propValues.get(ValueName.PROP_INDEX.getPropValueName(field)));
|
Boolean isEnabled = Boolean.valueOf(propValues.get(ValueName.PROP_IS_ENABLED.getPropValueName(field)));
|
||||||
if(index < 0)
|
|
||||||
{
|
|
||||||
throw new SolrFacetConfigException("Index must be greater than or equal to 0");
|
|
||||||
}
|
|
||||||
boolean isEnabled = Boolean.valueOf(propValues.get(ValueName.PROP_IS_ENABLED.getPropValueName(field)));
|
|
||||||
Set<CustomProperties> customProps = getCustomProps(facetFields.get(field), field, propValues);
|
Set<CustomProperties> customProps = getCustomProps(facetFields.get(field), field, propValues);
|
||||||
|
|
||||||
// Construct the FacetProperty object
|
// Construct the FacetProperty object
|
||||||
@@ -242,14 +237,13 @@ public class SolrFacetConfig extends AbstractLifecycleBean
|
|||||||
.minFilterValueLength(minFilterValueLength)
|
.minFilterValueLength(minFilterValueLength)
|
||||||
.sortBy(sortBy)
|
.sortBy(sortBy)
|
||||||
.scope(scope)
|
.scope(scope)
|
||||||
.index(index)
|
|
||||||
.isEnabled(isEnabled)
|
.isEnabled(isEnabled)
|
||||||
.isDefault(true)
|
.isDefault(true)
|
||||||
.scopedSites(scopedSites)
|
.scopedSites(scopedSites)
|
||||||
.customProperties(customProps).build();
|
.customProperties(customProps).build();
|
||||||
|
|
||||||
facetProperties.put(filterID, fp);
|
facetProperties.put(filterID, fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
return facetProperties;
|
return facetProperties;
|
||||||
@@ -273,7 +267,7 @@ public class SolrFacetConfig extends AbstractLifecycleBean
|
|||||||
|
|
||||||
private static void getPropertyAndPropOderControl(Properties properties, Set<String> propNames, Set<String> propOrderControl)
|
private static void getPropertyAndPropOderControl(Properties properties, Set<String> propNames, Set<String> propOrderControl)
|
||||||
{
|
{
|
||||||
|
|
||||||
for (Object propKeyObj : properties.keySet())
|
for (Object propKeyObj : properties.keySet())
|
||||||
{
|
{
|
||||||
String propKey = (String) propKeyObj;
|
String propKey = (String) propKeyObj;
|
||||||
@@ -327,14 +321,14 @@ public class SolrFacetConfig extends AbstractLifecycleBean
|
|||||||
}
|
}
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Set<CustomProperties> getCustomProps(Set<String> additionalProps, String field, Map<String, String> propValues)
|
private static Set<CustomProperties> getCustomProps(Set<String> additionalProps, String field, Map<String, String> propValues)
|
||||||
{
|
{
|
||||||
if (additionalProps == null)
|
if (additionalProps == null)
|
||||||
{
|
{
|
||||||
return Collections.emptySet();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<CustomProperties> customProps = new HashSet<>();
|
Set<CustomProperties> customProps = new HashSet<>();
|
||||||
for (String extraInfo : additionalProps)
|
for (String extraInfo : additionalProps)
|
||||||
{
|
{
|
||||||
@@ -385,7 +379,7 @@ public class SolrFacetConfig extends AbstractLifecycleBean
|
|||||||
{
|
{
|
||||||
PROP_FILTER_ID("filterID"), PROP_DISPLAY_NAME("displayName"), PROP_MAX_FILTERS("maxFilters"), PROP_HIT_THRESHOLD("hitThreshold"),
|
PROP_FILTER_ID("filterID"), PROP_DISPLAY_NAME("displayName"), PROP_MAX_FILTERS("maxFilters"), PROP_HIT_THRESHOLD("hitThreshold"),
|
||||||
PROP_MIN_FILTER_VALUE_LENGTH("minFilterValueLength"), PROP_SORTBY("sortBy"), PROP_SCOPE("scope"), PROP_SCOPED_SITES("scopedSites"),
|
PROP_MIN_FILTER_VALUE_LENGTH("minFilterValueLength"), PROP_SORTBY("sortBy"), PROP_SCOPE("scope"), PROP_SCOPED_SITES("scopedSites"),
|
||||||
PROP_INDEX("index"), PROP_IS_ENABLED("isEnabled"), PROP_DISPLAY_CONTROL("displayControl");
|
PROP_IS_ENABLED("isEnabled"), PROP_DISPLAY_CONTROL("displayControl");
|
||||||
|
|
||||||
private ValueName(String propValueName)
|
private ValueName(String propValueName)
|
||||||
{
|
{
|
||||||
|
@@ -56,16 +56,14 @@ public interface SolrFacetModel
|
|||||||
|
|
||||||
public static final QName PROP_SCOPED_SITES = QName.createQName(SOLR_FACET_MODEL_URL, "scopedSites");
|
public static final QName PROP_SCOPED_SITES = QName.createQName(SOLR_FACET_MODEL_URL, "scopedSites");
|
||||||
|
|
||||||
public static final QName PROP_INDEX = QName.createQName(SOLR_FACET_MODEL_URL, "index");
|
|
||||||
|
|
||||||
public static final QName PROP_IS_ENABLED = QName.createQName(SOLR_FACET_MODEL_URL, "isEnabled");
|
public static final QName PROP_IS_ENABLED = QName.createQName(SOLR_FACET_MODEL_URL, "isEnabled");
|
||||||
|
|
||||||
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. */
|
/** The type of the facet container folder. */
|
||||||
public static final QName TYPE_FACETS = QName.createQName(SOLR_FACET_MODEL_URL, "facets");
|
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");
|
public static final QName PROP_FACET_ORDER = QName.createQName(SOLR_FACET_MODEL_URL, "facetOrder");
|
||||||
}
|
}
|
||||||
|
@@ -46,8 +46,7 @@ public class SolrFacetProperties implements Serializable
|
|||||||
private final String sortBy;
|
private final String sortBy;
|
||||||
private final String scope;
|
private final String scope;
|
||||||
private final Set<String> scopedSites;
|
private final Set<String> scopedSites;
|
||||||
private final int index;
|
private final Boolean isEnabled;
|
||||||
private final boolean isEnabled;
|
|
||||||
private final boolean isDefault; // is loaded from properties files?
|
private final boolean isDefault; // is loaded from properties files?
|
||||||
private final Set<CustomProperties> customProperties;
|
private final Set<CustomProperties> customProperties;
|
||||||
|
|
||||||
@@ -67,7 +66,6 @@ public class SolrFacetProperties implements Serializable
|
|||||||
this.minFilterValueLength = builder.minFilterValueLength;
|
this.minFilterValueLength = builder.minFilterValueLength;
|
||||||
this.sortBy = builder.sortBy;
|
this.sortBy = builder.sortBy;
|
||||||
this.scope = builder.scope;
|
this.scope = builder.scope;
|
||||||
this.index = builder.index;
|
|
||||||
this.isEnabled = builder.isEnabled;
|
this.isEnabled = builder.isEnabled;
|
||||||
this.isDefault = builder.isDefault;
|
this.isDefault = builder.isDefault;
|
||||||
this.scopedSites = Collections.unmodifiableSet(new HashSet<String>(builder.scopedSites));
|
this.scopedSites = Collections.unmodifiableSet(new HashSet<String>(builder.scopedSites));
|
||||||
@@ -157,17 +155,9 @@ public class SolrFacetProperties implements Serializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the index
|
* @return null if the value is not set
|
||||||
*/
|
*/
|
||||||
public int getIndex()
|
public Boolean isEnabled()
|
||||||
{
|
|
||||||
return this.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the isEnabled
|
|
||||||
*/
|
|
||||||
public boolean isEnabled()
|
|
||||||
{
|
{
|
||||||
return this.isEnabled;
|
return this.isEnabled;
|
||||||
}
|
}
|
||||||
@@ -191,7 +181,6 @@ public class SolrFacetProperties implements Serializable
|
|||||||
{
|
{
|
||||||
return Collections.unmodifiableSet(new HashSet<CustomProperties>(this.customProperties));
|
return Collections.unmodifiableSet(new HashSet<CustomProperties>(this.customProperties));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @see java.lang.Object#hashCode()
|
* @see java.lang.Object#hashCode()
|
||||||
@@ -251,7 +240,7 @@ public class SolrFacetProperties implements Serializable
|
|||||||
.append(this.maxFilters).append(", hitThreshold=").append(this.hitThreshold)
|
.append(this.maxFilters).append(", hitThreshold=").append(this.hitThreshold)
|
||||||
.append(", minFilterValueLength=").append(this.minFilterValueLength).append(", sortBy=")
|
.append(", minFilterValueLength=").append(this.minFilterValueLength).append(", sortBy=")
|
||||||
.append(this.sortBy).append(", scope=").append(this.scope).append(", scopedSites=")
|
.append(this.sortBy).append(", scope=").append(this.scope).append(", scopedSites=")
|
||||||
.append(this.scopedSites).append(", index=").append(this.index).append(", isEnabled=").append(this.isEnabled)
|
.append(this.scopedSites).append(", isEnabled=").append(this.isEnabled)
|
||||||
.append(", isDefault=").append(this.isDefault).append(", customProperties=").append(this.customProperties)
|
.append(", isDefault=").append(this.isDefault).append(", customProperties=").append(this.customProperties)
|
||||||
.append("]");
|
.append("]");
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
@@ -263,14 +252,13 @@ public class SolrFacetProperties implements Serializable
|
|||||||
private QName facetQName;
|
private QName facetQName;
|
||||||
private String displayName;
|
private String displayName;
|
||||||
private String displayControl;
|
private String displayControl;
|
||||||
private int maxFilters;
|
private int maxFilters = -1;
|
||||||
private int hitThreshold;
|
private int hitThreshold = -1;;
|
||||||
private int minFilterValueLength;
|
private int minFilterValueLength = -1;
|
||||||
private String sortBy;
|
private String sortBy;
|
||||||
private String scope;
|
private String scope;
|
||||||
private Set<String> scopedSites = Collections.emptySet();
|
private Set<String> scopedSites = Collections.emptySet();
|
||||||
private int index;
|
private Boolean isEnabled;
|
||||||
private boolean isEnabled;
|
|
||||||
private boolean isDefault;
|
private boolean isDefault;
|
||||||
private Set<CustomProperties> customProperties = Collections.emptySet();
|
private Set<CustomProperties> customProperties = Collections.emptySet();
|
||||||
|
|
||||||
@@ -295,7 +283,6 @@ public class SolrFacetProperties implements Serializable
|
|||||||
this.sortBy = that.sortBy;
|
this.sortBy = that.sortBy;
|
||||||
this.scope = that.scope;
|
this.scope = that.scope;
|
||||||
this.scopedSites = that.scopedSites;
|
this.scopedSites = that.scopedSites;
|
||||||
this.index = that.index;
|
|
||||||
this.isEnabled = that.isEnabled;
|
this.isEnabled = that.isEnabled;
|
||||||
this.isDefault = that.isDefault;
|
this.isDefault = that.isDefault;
|
||||||
this.customProperties = that.customProperties;
|
this.customProperties = that.customProperties;
|
||||||
@@ -364,13 +351,7 @@ public class SolrFacetProperties implements Serializable
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder index(int index)
|
public Builder isEnabled(Boolean isEnabled)
|
||||||
{
|
|
||||||
this.index = index;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder isEnabled(boolean isEnabled)
|
|
||||||
{
|
{
|
||||||
this.isEnabled = isEnabled;
|
this.isEnabled = isEnabled;
|
||||||
return this;
|
return this;
|
||||||
@@ -396,7 +377,7 @@ public class SolrFacetProperties implements Serializable
|
|||||||
return new SolrFacetProperties(this);
|
return new SolrFacetProperties(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CustomProperties implements Serializable
|
public static class CustomProperties implements Serializable
|
||||||
{
|
{
|
||||||
private static final long serialVersionUID = 2250062300454166258L;
|
private static final long serialVersionUID = 2250062300454166258L;
|
||||||
|
@@ -20,17 +20,13 @@
|
|||||||
package org.alfresco.repo.search.impl.solr.facet;
|
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Solr Facet service configuration API.
|
* Solr Facet service configuration API.
|
||||||
*
|
*
|
||||||
* @author Jamal Kaabi-Mofrad
|
* @author Jamal Kaabi-Mofrad
|
||||||
|
* @since 5.0
|
||||||
*/
|
*/
|
||||||
public interface SolrFacetService
|
public interface SolrFacetService
|
||||||
{
|
{
|
||||||
@@ -41,7 +37,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.
|
||||||
*
|
*
|
||||||
@@ -90,8 +86,6 @@ public interface SolrFacetService
|
|||||||
*/
|
*/
|
||||||
public void deleteFacet(String filterID);
|
public void deleteFacet(String filterID);
|
||||||
|
|
||||||
public int getNextIndex();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reorders existing facets to the provided order.
|
* Reorders existing facets to the provided order.
|
||||||
*
|
*
|
||||||
|
@@ -21,27 +21,26 @@ package org.alfresco.repo.search.impl.solr.facet;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.NavigableMap;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.ConcurrentSkipListMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
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;
|
||||||
import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy;
|
import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy;
|
||||||
import org.alfresco.repo.node.NodeServicePolicies.BeforeUpdateNodePolicy;
|
|
||||||
import org.alfresco.repo.node.NodeServicePolicies.OnCreateNodePolicy;
|
import org.alfresco.repo.node.NodeServicePolicies.OnCreateNodePolicy;
|
||||||
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;
|
||||||
@@ -71,13 +70,14 @@ import org.springframework.context.ApplicationEvent;
|
|||||||
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
import org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Solr Facet Service Implementation.
|
||||||
|
*
|
||||||
* @author Jamal Kaabi-Mofrad
|
* @author Jamal Kaabi-Mofrad
|
||||||
|
* @since 5.0
|
||||||
*/
|
*/
|
||||||
public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrFacetService,
|
public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrFacetService,
|
||||||
NodeServicePolicies.OnCreateNodePolicy,
|
NodeServicePolicies.OnCreateNodePolicy,
|
||||||
NodeServicePolicies.OnUpdateNodePolicy,
|
NodeServicePolicies.BeforeDeleteNodePolicy
|
||||||
NodeServicePolicies.BeforeDeleteNodePolicy,
|
|
||||||
NodeServicePolicies.BeforeUpdateNodePolicy
|
|
||||||
{
|
{
|
||||||
private static final Log logger = LogFactory.getLog(SolrFacetServiceImpl.class);
|
private static final Log logger = LogFactory.getLog(SolrFacetServiceImpl.class);
|
||||||
/**
|
/**
|
||||||
@@ -102,8 +102,7 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
private SimpleCache<String, Object> singletonCache; // eg. for facetsHomeNodeRef
|
private SimpleCache<String, Object> singletonCache; // eg. for facetsHomeNodeRef
|
||||||
private final String KEY_FACETS_HOME_NODEREF = "key.facetshome.noderef";
|
private final String KEY_FACETS_HOME_NODEREF = "key.facetshome.noderef";
|
||||||
private SimpleCache<String, NodeRef> facetNodeRefCache; // for filterID to nodeRef lookup
|
private SimpleCache<String, NodeRef> facetNodeRefCache; // for filterID to nodeRef lookup
|
||||||
private NavigableMap<Integer, SolrFacetProperties> facetsMap = new ConcurrentSkipListMap<>(); // TODO
|
private ConcurrentMap<String, SolrFacetProperties> defaultFacetsMap = new ConcurrentHashMap<String, SolrFacetProperties>(10);
|
||||||
private int maxAllowedFilters = 100;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param authorityService the authorityService to set
|
* @param authorityService the authorityService to set
|
||||||
@@ -193,14 +192,6 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
this.facetNodeRefCache = facetNodeRefCache;
|
this.facetNodeRefCache = facetNodeRefCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param maxAllowedFilters the maxAllowedFilters to set
|
|
||||||
*/
|
|
||||||
public void setMaxAllowedFilters(int maxAllowedFilters)
|
|
||||||
{
|
|
||||||
this.maxAllowedFilters = maxAllowedFilters;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSearchAdmin(String userName)
|
public boolean isSearchAdmin(String userName)
|
||||||
{
|
{
|
||||||
@@ -217,17 +208,24 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
{
|
{
|
||||||
// Sort the facets into display order
|
// Sort the facets into display order
|
||||||
final SolrFacetComparator comparator = new SolrFacetComparator(getFacetOrder());
|
final SolrFacetComparator comparator = new SolrFacetComparator(getFacetOrder());
|
||||||
|
|
||||||
SortedSet<SolrFacetProperties> result = new TreeSet<>(comparator);
|
SortedSet<SolrFacetProperties> result = new TreeSet<>(comparator);
|
||||||
result.addAll(facetsMap.values());
|
List<ChildAssociationRef> children = nodeService.getChildAssocs(getFacetsRoot());
|
||||||
|
|
||||||
|
for (ChildAssociationRef ref : children)
|
||||||
|
{
|
||||||
|
result.add(getFacetProperties(ref.getChildRef()));
|
||||||
|
}
|
||||||
|
// add the default filters
|
||||||
|
result.addAll(defaultFacetsMap.values());
|
||||||
|
|
||||||
return new ArrayList<>(result);
|
return new ArrayList<>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getFacetOrder()
|
public List<String> getFacetOrder()
|
||||||
{
|
{
|
||||||
final NodeRef facetContainer = getFacetsRoot();
|
final NodeRef facetContainer = getFacetsRoot();
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final List<String> facetOrder = (List<String>) nodeService.getProperty(facetContainer, SolrFacetModel.PROP_FACET_ORDER);
|
final List<String> facetOrder = (List<String>) nodeService.getProperty(facetContainer, SolrFacetModel.PROP_FACET_ORDER);
|
||||||
return facetOrder;
|
return facetOrder;
|
||||||
@@ -242,12 +240,7 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
* the nodeService.
|
* the nodeService.
|
||||||
*/
|
*/
|
||||||
NodeRef nodeRef = getFacetNodeRef(filterID);
|
NodeRef nodeRef = getFacetNodeRef(filterID);
|
||||||
return (nodeRef == null) ? getDefaultLoadedFacet(filterID) : getFacetProperties(nodeRef);
|
return (nodeRef == null) ? defaultFacetsMap.get(filterID) : getFacetProperties(nodeRef);
|
||||||
}
|
|
||||||
|
|
||||||
private SolrFacetProperties getDefaultLoadedFacet(String filterID)
|
|
||||||
{
|
|
||||||
return facetConfig.getDefaultFacets().get(filterID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -297,26 +290,40 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
}
|
}
|
||||||
|
|
||||||
String filterID = (String) properties.get(ContentModel.PROP_NAME);
|
String filterID = (String) properties.get(ContentModel.PROP_NAME);
|
||||||
QName fieldQName = (QName) properties.get(SolrFacetModel.PROP_FIELD_TYPE);
|
|
||||||
String displayName = (String) properties.get(SolrFacetModel.PROP_FIELD_LABEL);
|
|
||||||
String displayControl = (String) properties.get(SolrFacetModel.PROP_DISPLAY_CONTROL);
|
|
||||||
int maxFilters = (Integer) properties.get(SolrFacetModel.PROP_MAX_FILTERS);
|
|
||||||
int hitThreshold = (Integer) properties.get(SolrFacetModel.PROP_HIT_THRESHOLD);
|
|
||||||
int minFilterValueLength = (Integer) properties.get(SolrFacetModel.PROP_MIN_FILTER_VALUE_LENGTH);
|
|
||||||
String sortBy = (String) properties.get(SolrFacetModel.PROP_SORT_BY);
|
|
||||||
String scope = (String) properties.get(SolrFacetModel.PROP_SCOPE);
|
|
||||||
int index = (Integer) properties.get(SolrFacetModel.PROP_INDEX);
|
|
||||||
boolean isEnabled = (Boolean) properties.get(SolrFacetModel.PROP_IS_ENABLED);
|
|
||||||
boolean isDefault = (Boolean) properties.get(SolrFacetModel.PROP_IS_DEFAULT);
|
boolean isDefault = (Boolean) properties.get(SolrFacetModel.PROP_IS_DEFAULT);
|
||||||
|
|
||||||
|
SolrFacetProperties defaultFacet = defaultFacetsMap.get(filterID);
|
||||||
|
if(defaultFacet == null)
|
||||||
|
{
|
||||||
|
defaultFacet = new SolrFacetProperties.Builder().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
QName fieldQName = getDefaultIfNull(defaultFacet.getFacetQName(), (QName) properties.get(SolrFacetModel.PROP_FIELD_TYPE));
|
||||||
|
String displayName = getDefaultIfNull(defaultFacet.getDisplayName(), (String) properties.get(SolrFacetModel.PROP_FIELD_LABEL));
|
||||||
|
String displayControl = getDefaultIfNull(defaultFacet.getDisplayControl(), (String) properties.get(SolrFacetModel.PROP_DISPLAY_CONTROL));
|
||||||
|
int maxFilters = getDefaultIfNull(defaultFacet.getMaxFilters(), (Integer) properties.get(SolrFacetModel.PROP_MAX_FILTERS));
|
||||||
|
int hitThreshold = getDefaultIfNull(defaultFacet.getHitThreshold(), (Integer) properties.get(SolrFacetModel.PROP_HIT_THRESHOLD));
|
||||||
|
int minFilterValueLength = getDefaultIfNull(defaultFacet.getMinFilterValueLength(), (Integer) properties.get(SolrFacetModel.PROP_MIN_FILTER_VALUE_LENGTH));
|
||||||
|
String sortBy = getDefaultIfNull(defaultFacet.getSortBy(), (String) properties.get(SolrFacetModel.PROP_SORT_BY));
|
||||||
|
String scope = getDefaultIfNull(defaultFacet.getScope(), (String) properties.get(SolrFacetModel.PROP_SCOPE));
|
||||||
|
Boolean isEnabled = getDefaultIfNull(defaultFacet.isEnabled(), (Boolean) properties.get(SolrFacetModel.PROP_IS_ENABLED));
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
List<String> scSites = (List<String>) properties.get(SolrFacetModel.PROP_SCOPED_SITES);
|
List<String> scSites = (List<String>) properties.get(SolrFacetModel.PROP_SCOPED_SITES);
|
||||||
Set<String> scopedSites = (scSites == null) ? null : new HashSet<>(scSites);
|
Set<String> scopedSites = getDefaultIfNull(defaultFacet.getScopedSites(), (scSites == null) ? null : new HashSet<>(scSites));
|
||||||
|
|
||||||
|
Set<CustomProperties> extraProps = null;
|
||||||
Map<QName, Serializable> customProperties = getFacetCustomProperties(properties);
|
Map<QName, Serializable> customProperties = getFacetCustomProperties(properties);
|
||||||
Set<CustomProperties> extraProps = new HashSet<>(customProperties.size());
|
if (customProperties.isEmpty())
|
||||||
for(Entry<QName, Serializable> cp : customProperties.entrySet())
|
|
||||||
{
|
{
|
||||||
extraProps.add(new CustomProperties(cp.getKey(), (String) properties.get(ContentModel.PROP_TITLE), null, cp.getValue()));
|
extraProps = defaultFacet.getCustomProperties();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
extraProps = new HashSet<>(customProperties.size());
|
||||||
|
for (Entry<QName, Serializable> cp : customProperties.entrySet())
|
||||||
|
{
|
||||||
|
extraProps.add(new CustomProperties(cp.getKey(), (String) properties.get(ContentModel.PROP_TITLE), null, cp.getValue()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Construct the FacetProperty object
|
// Construct the FacetProperty object
|
||||||
SolrFacetProperties fp = new SolrFacetProperties.Builder()
|
SolrFacetProperties fp = new SolrFacetProperties.Builder()
|
||||||
@@ -329,7 +336,6 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
.minFilterValueLength(minFilterValueLength)
|
.minFilterValueLength(minFilterValueLength)
|
||||||
.sortBy(sortBy)
|
.sortBy(sortBy)
|
||||||
.scope(scope)
|
.scope(scope)
|
||||||
.index(index)
|
|
||||||
.isEnabled(isEnabled)
|
.isEnabled(isEnabled)
|
||||||
.isDefault(isDefault)
|
.isDefault(isDefault)
|
||||||
.scopedSites(scopedSites)
|
.scopedSites(scopedSites)
|
||||||
@@ -338,6 +344,11 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <T> T getDefaultIfNull(T defaultValue, T newValue)
|
||||||
|
{
|
||||||
|
return (newValue == null) ? defaultValue : newValue;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NodeRef createFacetNode(SolrFacetProperties facetProperties)
|
public NodeRef createFacetNode(SolrFacetProperties facetProperties)
|
||||||
{
|
{
|
||||||
@@ -346,12 +357,11 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
|
|
||||||
private NodeRef createFacetNodeImpl(final SolrFacetProperties facetProperties, boolean checkDefaultFP)
|
private NodeRef createFacetNodeImpl(final SolrFacetProperties facetProperties, boolean checkDefaultFP)
|
||||||
{
|
{
|
||||||
|
|
||||||
final String filterID = facetProperties.getFilterID();
|
final String filterID = facetProperties.getFilterID();
|
||||||
NodeRef facetNodeRef = getFacetNodeRef(filterID);
|
NodeRef facetNodeRef = getFacetNodeRef(filterID);
|
||||||
// We need to check the bootstrapped Facet properties (i.e loaded from properties file(s)) as well,
|
// We need to check the bootstrapped Facet properties (i.e loaded from properties file(s)) as well,
|
||||||
// in order to not allow the user to create a new facet with the same filterID as the bootstrapped FP.
|
// in order to not allow the user to create a new facet with the same filterID as the bootstrapped FP.
|
||||||
if (facetNodeRef != null || (checkDefaultFP && getDefaultLoadedFacet(filterID) != null))
|
if (facetNodeRef != null || (checkDefaultFP && defaultFacetsMap.get(filterID) != null))
|
||||||
{
|
{
|
||||||
throw new SolrFacetConfigException("Unable to create facet because the filterID [" + filterID + "] is already in use.");
|
throw new SolrFacetConfigException("Unable to create facet because the filterID [" + filterID + "] is already in use.");
|
||||||
}
|
}
|
||||||
@@ -406,7 +416,7 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
NodeRef facetNodeRef = getFacetNodeRef(filterID);
|
NodeRef facetNodeRef = getFacetNodeRef(filterID);
|
||||||
if (facetNodeRef == null)
|
if (facetNodeRef == null)
|
||||||
{
|
{
|
||||||
SolrFacetProperties fp = getDefaultLoadedFacet(filterID);
|
SolrFacetProperties fp = defaultFacetsMap.get(filterID);
|
||||||
if (fp != null)
|
if (fp != null)
|
||||||
{
|
{
|
||||||
// As we don't create nodes for the bootstrapped FP on server
|
// As we don't create nodes for the bootstrapped FP on server
|
||||||
@@ -436,6 +446,51 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SolrFacetProperties makeValidFacetPropObj(SolrFacetProperties newFP)
|
||||||
|
{
|
||||||
|
|
||||||
|
SolrFacetProperties bootstraptedFP = defaultFacetsMap.get(newFP.getFilterID());
|
||||||
|
// null means there is no default facet
|
||||||
|
if(bootstraptedFP == null)
|
||||||
|
{
|
||||||
|
return new SolrFacetProperties.Builder(newFP).isDefault(false).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
QName fieldQName = getValue(bootstraptedFP.getFacetQName(), newFP.getFacetQName(), null);
|
||||||
|
String displayName = getValue(bootstraptedFP.getDisplayName(), newFP.getDisplayName(), null);
|
||||||
|
String displayControl = getValue(bootstraptedFP.getDisplayControl(), newFP.getDisplayControl(), null);
|
||||||
|
int maxFilters = getValue(bootstraptedFP.getMaxFilters(), newFP.getMaxFilters(), -1);
|
||||||
|
int hitThreshold = getValue(bootstraptedFP.getHitThreshold(), newFP.getHitThreshold(), -1);
|
||||||
|
int minFilterValueLength = getValue(bootstraptedFP.getMinFilterValueLength(), newFP.getMinFilterValueLength(), -1);
|
||||||
|
String sortBy = getValue(bootstraptedFP.getSortBy(), newFP.getSortBy(), null);
|
||||||
|
String scope = getValue(bootstraptedFP.getScope(), newFP.getScope(), null);
|
||||||
|
Boolean isEnabled = getValue(bootstraptedFP.isEnabled(), newFP.isEnabled(), null);
|
||||||
|
Set<String> scopedSites = getValue(bootstraptedFP.getScopedSites(), newFP.getScopedSites(), null);
|
||||||
|
Set<CustomProperties> extraProps = getValue(bootstraptedFP.getCustomProperties(), newFP.getCustomProperties(), null);
|
||||||
|
// Construct the FacetProperty object
|
||||||
|
SolrFacetProperties fp = new SolrFacetProperties.Builder()
|
||||||
|
.filterID(newFP.getFilterID())
|
||||||
|
.facetQName(fieldQName)
|
||||||
|
.displayName(displayName)
|
||||||
|
.displayControl(displayControl)
|
||||||
|
.maxFilters(maxFilters)
|
||||||
|
.hitThreshold(hitThreshold)
|
||||||
|
.minFilterValueLength(minFilterValueLength)
|
||||||
|
.sortBy(sortBy)
|
||||||
|
.scope(scope)
|
||||||
|
.isEnabled(isEnabled)
|
||||||
|
.isDefault(true)
|
||||||
|
.scopedSites(scopedSites)
|
||||||
|
.customProperties(extraProps).build();
|
||||||
|
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T> T getValue(T originalValue, T newValue, T defaultValueIfEquals)
|
||||||
|
{
|
||||||
|
return (originalValue.equals(newValue) ? defaultValueIfEquals : newValue);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteFacet(String filterID)
|
public void deleteFacet(String filterID)
|
||||||
{
|
{
|
||||||
@@ -445,7 +500,7 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
throw new SolrFacetConfigException("The [" + filterID + "] facet cannot be found.");
|
throw new SolrFacetConfigException("The [" + filterID + "] facet cannot be found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
SolrFacetProperties defaultFP = getDefaultLoadedFacet(filterID);
|
SolrFacetProperties defaultFP = defaultFacetsMap.get(filterID);
|
||||||
if (defaultFP != null)
|
if (defaultFP != null)
|
||||||
{
|
{
|
||||||
throw new SolrFacetConfigException("The default [" + filterID + "] facet cannot be deleted. It can only be disabled.");
|
throw new SolrFacetConfigException("The default [" + filterID + "] facet cannot be deleted. It can only be disabled.");
|
||||||
@@ -464,33 +519,51 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
throw new SolrFacetConfigException("Filter Id cannot be null.");
|
throw new SolrFacetConfigException("Filter Id cannot be null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// construct a valid facet property object
|
||||||
|
facetProperties = makeValidFacetPropObj(facetProperties);
|
||||||
Set<CustomProperties> customProperties = facetProperties.getCustomProperties();
|
Set<CustomProperties> customProperties = facetProperties.getCustomProperties();
|
||||||
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(14 + customProperties.size());
|
Map<QName, Serializable> properties = new HashMap<QName, Serializable>(13 + customProperties.size());
|
||||||
|
|
||||||
properties.put(ContentModel.PROP_NAME, facetProperties.getFilterID());
|
properties.put(ContentModel.PROP_NAME, facetProperties.getFilterID());
|
||||||
properties.put(SolrFacetModel.PROP_FIELD_TYPE, facetProperties.getFacetQName());
|
properties.put(SolrFacetModel.PROP_IS_DEFAULT, facetProperties.isDefault());
|
||||||
properties.put(SolrFacetModel.PROP_FIELD_LABEL, facetProperties.getDisplayName());
|
|
||||||
properties.put(SolrFacetModel.PROP_DISPLAY_CONTROL, facetProperties.getDisplayControl());
|
|
||||||
properties.put(SolrFacetModel.PROP_MAX_FILTERS, facetProperties.getMaxFilters());
|
|
||||||
properties.put(SolrFacetModel.PROP_HIT_THRESHOLD, facetProperties.getHitThreshold());
|
|
||||||
properties.put(SolrFacetModel.PROP_MIN_FILTER_VALUE_LENGTH, facetProperties.getMinFilterValueLength());
|
|
||||||
properties.put(SolrFacetModel.PROP_SCOPE, facetProperties.getScope());
|
|
||||||
properties.put(SolrFacetModel.PROP_SORT_BY, facetProperties.getSortBy());
|
|
||||||
properties.put(SolrFacetModel.PROP_SCOPED_SITES, (Serializable) facetProperties.getScopedSites());
|
|
||||||
properties.put(SolrFacetModel.PROP_INDEX, facetProperties.getIndex());
|
|
||||||
properties.put(SolrFacetModel.PROP_IS_ENABLED, facetProperties.isEnabled());
|
|
||||||
|
|
||||||
SolrFacetProperties fp = getDefaultLoadedFacet(facetProperties.getFilterID());
|
addNodeProperty(properties, SolrFacetModel.PROP_FIELD_TYPE, facetProperties.getFacetQName());
|
||||||
properties.put(SolrFacetModel.PROP_IS_DEFAULT, (fp == null) ? false : fp.isDefault());
|
addNodeProperty(properties, SolrFacetModel.PROP_FIELD_LABEL, facetProperties.getDisplayName());
|
||||||
|
addNodeProperty(properties, SolrFacetModel.PROP_DISPLAY_CONTROL, facetProperties.getDisplayControl());
|
||||||
|
addNodeProperty(properties, SolrFacetModel.PROP_MAX_FILTERS, facetProperties.getMaxFilters());
|
||||||
|
addNodeProperty(properties, SolrFacetModel.PROP_HIT_THRESHOLD, facetProperties.getHitThreshold());
|
||||||
|
addNodeProperty(properties, SolrFacetModel.PROP_MIN_FILTER_VALUE_LENGTH, facetProperties.getMinFilterValueLength());
|
||||||
|
addNodeProperty(properties, SolrFacetModel.PROP_SCOPE, facetProperties.getScope());
|
||||||
|
addNodeProperty(properties, SolrFacetModel.PROP_SORT_BY, facetProperties.getSortBy());
|
||||||
|
addNodeProperty(properties, SolrFacetModel.PROP_SCOPED_SITES, (Serializable) facetProperties.getScopedSites());
|
||||||
|
addNodeProperty(properties, SolrFacetModel.PROP_IS_ENABLED, facetProperties.isEnabled());
|
||||||
|
|
||||||
for (CustomProperties cp : customProperties)
|
for (CustomProperties cp : customProperties)
|
||||||
{
|
{
|
||||||
properties.put(cp.getName(), cp.getValue());
|
addNodeProperty(properties, cp.getName(), cp.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addNodeProperty(Map<QName, Serializable> properties, QName qname, Serializable propValue)
|
||||||
|
{
|
||||||
|
if (propValue == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (propValue instanceof Integer && ((Integer) propValue) < 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (propValue instanceof Collection<?> && ((Collection<?>) propValue).isEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
properties.put(qname, propValue);
|
||||||
|
}
|
||||||
|
|
||||||
public NodeRef getFacetsRoot()
|
public NodeRef getFacetsRoot()
|
||||||
{
|
{
|
||||||
NodeRef facetHomeRef = (NodeRef) singletonCache.get(KEY_FACETS_HOME_NODEREF);
|
NodeRef facetHomeRef = (NodeRef) singletonCache.get(KEY_FACETS_HOME_NODEREF);
|
||||||
@@ -535,18 +608,6 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
SolrFacetModel.TYPE_FACET_FIELD,
|
SolrFacetModel.TYPE_FACET_FIELD,
|
||||||
new JavaBehaviour(this, "onCreateNode"));
|
new JavaBehaviour(this, "onCreateNode"));
|
||||||
|
|
||||||
// Filter before update
|
|
||||||
this.policyComponent.bindClassBehaviour(
|
|
||||||
BeforeUpdateNodePolicy.QNAME,
|
|
||||||
SolrFacetModel.TYPE_FACET_FIELD,
|
|
||||||
new JavaBehaviour(this, "beforeUpdateNode"));
|
|
||||||
|
|
||||||
// Filter update
|
|
||||||
this.policyComponent.bindClassBehaviour(
|
|
||||||
OnUpdateNodePolicy.QNAME,
|
|
||||||
SolrFacetModel.TYPE_FACET_FIELD,
|
|
||||||
new JavaBehaviour(this, "onUpdateNode"));
|
|
||||||
|
|
||||||
// Filter before deletion
|
// Filter before deletion
|
||||||
this.policyComponent.bindClassBehaviour(
|
this.policyComponent.bindClassBehaviour(
|
||||||
BeforeDeleteNodePolicy.QNAME,
|
BeforeDeleteNodePolicy.QNAME,
|
||||||
@@ -556,6 +617,7 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
Map<String, SolrFacetProperties> mergedMap = new HashMap<>(100);
|
Map<String, SolrFacetProperties> mergedMap = new HashMap<>(100);
|
||||||
// Loaded facets
|
// Loaded facets
|
||||||
Map<String, SolrFacetProperties> defaultFP = facetConfig.getDefaultFacets();
|
Map<String, SolrFacetProperties> defaultFP = facetConfig.getDefaultFacets();
|
||||||
|
defaultFacetsMap.putAll(defaultFP); // add the default facets to a ConcurrentHashMap for performance reasons
|
||||||
mergedMap.putAll(defaultFP);
|
mergedMap.putAll(defaultFP);
|
||||||
|
|
||||||
// Persisted facets
|
// Persisted facets
|
||||||
@@ -563,51 +625,43 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
// The persisted facets will override the default facets
|
// The persisted facets will override the default facets
|
||||||
mergedMap.putAll(persistedProperties);
|
mergedMap.putAll(persistedProperties);
|
||||||
|
|
||||||
|
List<String> facetOrder = getFacetOrder();
|
||||||
// Sort the merged maps
|
// Sort the merged maps
|
||||||
Comparator<Entry<String, SolrFacetProperties>> entryComparator = CollectionUtils.toEntryComparator(new SolrFacetComparator(getFacetOrder()));
|
Comparator<Entry<String, SolrFacetProperties>> entryComparator = CollectionUtils.toEntryComparator(new SolrFacetComparator(facetOrder));
|
||||||
Map<String, SolrFacetProperties> sortedMap = CollectionUtils.sortMapByValue(mergedMap, entryComparator);
|
Map<String, SolrFacetProperties> sortedMap = CollectionUtils.sortMapByValue(mergedMap, entryComparator);
|
||||||
LinkedList<SolrFacetProperties> orderedFacets = new LinkedList<>(sortedMap.values());
|
|
||||||
|
|
||||||
// Get the last index, as the map is sorted by the FP's index value
|
|
||||||
int maxIndex = orderedFacets.getLast().getIndex();
|
|
||||||
int previousIndex = -1;
|
|
||||||
SolrFacetProperties previousFP = null;
|
|
||||||
for (SolrFacetProperties facet : orderedFacets)
|
|
||||||
{
|
|
||||||
String filterID = facet.getFilterID();
|
|
||||||
int index = facet.getIndex();
|
|
||||||
if (index == previousIndex)
|
|
||||||
{
|
|
||||||
// we can be sure that previousFP is never null, as we don't
|
|
||||||
// allow the index to be -1;
|
|
||||||
if (defaultFP.get(previousFP.getFilterID()) != null && persistedProperties.get(filterID) != null)
|
|
||||||
{
|
|
||||||
SolrFacetProperties updatedPreviousFacet = new SolrFacetProperties.Builder(previousFP).index(++maxIndex).build();
|
|
||||||
mergedMap.put(previousFP.getFilterID(), updatedPreviousFacet);
|
|
||||||
mergedMap.put(filterID, facet);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SolrFacetProperties updatedCurrentFacet = new SolrFacetProperties.Builder(facet).index(++maxIndex).build();
|
|
||||||
mergedMap.put(updatedCurrentFacet.getFilterID(), updatedCurrentFacet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mergedMap.put(filterID, facet);
|
|
||||||
}
|
|
||||||
previousIndex = index;
|
|
||||||
previousFP = facet;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (SolrFacetProperties fp : mergedMap.values())
|
|
||||||
{
|
|
||||||
facetsMap.put(fp.getIndex(), fp);
|
|
||||||
}
|
|
||||||
if (logger.isDebugEnabled() && persistedProperties.size() > 0)
|
if (logger.isDebugEnabled() && persistedProperties.size() > 0)
|
||||||
{
|
{
|
||||||
logger.debug("The facets [" + persistedProperties + "] have overridden their matched default facets.");
|
logger.debug("The facets [" + persistedProperties + "] have overridden their matched default facets.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Set<String> newFacetOrder = (facetOrder == null) ? new LinkedHashSet<String>(sortedMap.size()) : new LinkedHashSet<String>(facetOrder);
|
||||||
|
|
||||||
|
for (SolrFacetProperties fp : sortedMap.values())
|
||||||
|
{
|
||||||
|
newFacetOrder.add(fp.getFilterID());
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthenticationUtil.runAs(new RunAsWork<Void>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Void doWork() throws Exception
|
||||||
|
{
|
||||||
|
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
||||||
|
{
|
||||||
|
public Void execute() throws Exception
|
||||||
|
{
|
||||||
|
reorderFacets(new ArrayList<String>(newFacetOrder));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
}, AuthenticationUtil.getSystemUserName());
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("The facets order [" + newFacetOrder + "] have been persisted.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, SolrFacetProperties> getPersistedFacetProperties()
|
private Map<String, SolrFacetProperties> getPersistedFacetProperties()
|
||||||
@@ -629,38 +683,29 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
// nothing to do
|
// nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void beforeUpdateNode(NodeRef nodeRef)
|
|
||||||
{
|
|
||||||
// Remove the facet, in order to not end up with duplicate facets but different index
|
|
||||||
SolrFacetProperties fp = getFacetProperties(nodeRef);
|
|
||||||
this.facetsMap.remove(fp.getIndex());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onUpdateNode(NodeRef nodeRef)
|
|
||||||
{
|
|
||||||
SolrFacetProperties fp = getFacetProperties(nodeRef);
|
|
||||||
this.facetsMap.put(fp.getIndex(), fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateNode(ChildAssociationRef childAssocRef)
|
public void onCreateNode(ChildAssociationRef childAssocRef)
|
||||||
{
|
{
|
||||||
SolrFacetProperties fp = getFacetProperties(childAssocRef.getChildRef());
|
SolrFacetProperties fp = getFacetProperties(childAssocRef.getChildRef());
|
||||||
this.facetsMap.put(fp.getIndex(), fp);
|
|
||||||
this.facetNodeRefCache.put(fp.getFilterID(), childAssocRef.getChildRef());
|
this.facetNodeRefCache.put(fp.getFilterID(), childAssocRef.getChildRef());
|
||||||
|
|
||||||
// We must also add the new filterID to the facetOrder property.
|
// We must also add the new filterID to the facetOrder property.
|
||||||
final NodeRef facetsRoot = getFacetsRoot();
|
final NodeRef facetsRoot = getFacetsRoot();
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
ArrayList<String> facetOrder = (ArrayList<String>) nodeService.getProperty(facetsRoot, SolrFacetModel.PROP_FACET_ORDER);
|
ArrayList<String> facetOrder = (ArrayList<String>) nodeService.getProperty(facetsRoot, SolrFacetModel.PROP_FACET_ORDER);
|
||||||
// FIXME This could be null.
|
if (facetOrder == null)
|
||||||
|
{
|
||||||
|
List<SolrFacetProperties> facets = getFacets();
|
||||||
|
facetOrder = new ArrayList<String>(facets.size());
|
||||||
|
for (SolrFacetProperties facet : facets)
|
||||||
|
{
|
||||||
|
facetOrder.add(facet.getFilterID());
|
||||||
|
}
|
||||||
|
}
|
||||||
// We'll put it at the end (arbitrarily).
|
// We'll put it at the end (arbitrarily).
|
||||||
facetOrder.add(fp.getFilterID());
|
facetOrder.add(fp.getFilterID());
|
||||||
|
|
||||||
nodeService.setProperty(facetsRoot, SolrFacetModel.PROP_FACET_ORDER, facetOrder);
|
nodeService.setProperty(facetsRoot, SolrFacetModel.PROP_FACET_ORDER, facetOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -668,43 +713,20 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
public void beforeDeleteNode(NodeRef nodeRef)
|
public void beforeDeleteNode(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
String filterID = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
String filterID = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||||
int index = (Integer) nodeService.getProperty(nodeRef, SolrFacetModel.PROP_INDEX);
|
|
||||||
|
|
||||||
this.facetsMap.remove(index);
|
|
||||||
this.facetNodeRefCache.remove(filterID);
|
this.facetNodeRefCache.remove(filterID);
|
||||||
|
|
||||||
// We must also remove the filterID from the facetOrder property.
|
// We must also remove the filterID from the facetOrder property.
|
||||||
final NodeRef facetsRoot = getFacetsRoot();
|
final NodeRef facetsRoot = getFacetsRoot();
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
ArrayList<String> facetOrder = (ArrayList<String>) nodeService.getProperty(facetsRoot, SolrFacetModel.PROP_FACET_ORDER);
|
ArrayList<String> facetOrder = (ArrayList<String>) nodeService.getProperty(facetsRoot, SolrFacetModel.PROP_FACET_ORDER);
|
||||||
|
|
||||||
if (facetOrder.remove(filterID))
|
if (facetOrder.remove(filterID))
|
||||||
{
|
{
|
||||||
nodeService.setProperty(facetsRoot, SolrFacetModel.PROP_FACET_ORDER, facetOrder);
|
nodeService.setProperty(facetsRoot, SolrFacetModel.PROP_FACET_ORDER, facetOrder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getNextIndex()
|
|
||||||
{
|
|
||||||
synchronized (facetsMap)
|
|
||||||
{
|
|
||||||
if (facetsMap.size() >= maxAllowedFilters)
|
|
||||||
{
|
|
||||||
throw new SolrFacetConfigException("You have reached the maximum number of allowed filters. Please delete an existing filter in order to make a new one!");
|
|
||||||
}
|
|
||||||
int max = facetsMap.lastKey();
|
|
||||||
if (max >= Integer.MAX_VALUE)
|
|
||||||
{
|
|
||||||
reorder();
|
|
||||||
max = facetsMap.lastKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
return max + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a map containing the facet's custom properties
|
* Gets a map containing the facet's custom properties
|
||||||
*
|
*
|
||||||
@@ -724,46 +746,6 @@ public class SolrFacetServiceImpl extends AbstractLifecycleBean implements SolrF
|
|||||||
return customProperties;
|
return customProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This will reorder the facetsMap, hence, the invoker needs to use an
|
|
||||||
* appropriate locking mechanism
|
|
||||||
*/
|
|
||||||
private void reorder()
|
|
||||||
{
|
|
||||||
boolean order = false;
|
|
||||||
int previous = 0;
|
|
||||||
for (int i : facetsMap.keySet())
|
|
||||||
{
|
|
||||||
if (i != previous)
|
|
||||||
{
|
|
||||||
order = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
previous++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (order)
|
|
||||||
{
|
|
||||||
Map<Integer, SolrFacetProperties> tempMap = new LinkedHashMap<>();
|
|
||||||
int index = 0;
|
|
||||||
for (SolrFacetProperties fp : facetsMap.values())
|
|
||||||
{
|
|
||||||
if (fp.getIndex() != index)
|
|
||||||
{
|
|
||||||
fp = new SolrFacetProperties.Builder(fp).index(index).build();
|
|
||||||
}
|
|
||||||
tempMap.put(index, fp);
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
facetsMap.clear();
|
|
||||||
|
|
||||||
for (SolrFacetProperties fp : tempMap.values())
|
|
||||||
{
|
|
||||||
updateFacet(fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void reorderFacets(List<String> facetIds)
|
@Override public void reorderFacets(List<String> facetIds)
|
||||||
{
|
{
|
||||||
// We need to validate the provided facet IDs
|
// We need to validate the provided facet IDs
|
||||||
|
@@ -416,4 +416,9 @@ public class Repository01TestSuite extends TestSuite
|
|||||||
suite.addTestSuite(org.alfresco.repo.dictionary.DictionaryModelTypeTest.class);
|
suite.addTestSuite(org.alfresco.repo.dictionary.DictionaryModelTypeTest.class);
|
||||||
suite.addTestSuite(org.alfresco.repo.tagging.UpdateTagScopesActionExecuterTest.class);
|
suite.addTestSuite(org.alfresco.repo.tagging.UpdateTagScopesActionExecuterTest.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tests66(TestSuite suite)
|
||||||
|
{
|
||||||
|
suite.addTest(org.alfresco.repo.search.impl.solr.facet.SolrFacetTestSuite.suite());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.search;
|
package org.alfresco.repo.search;
|
||||||
|
|
||||||
import junit.framework.JUnit4TestAdapter;
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
@@ -31,7 +30,6 @@ import org.alfresco.repo.search.impl.lucene.index.IndexInfoTest;
|
|||||||
import org.alfresco.repo.search.impl.parsers.CMISTest;
|
import org.alfresco.repo.search.impl.parsers.CMISTest;
|
||||||
import org.alfresco.repo.search.impl.parsers.CMIS_FTSTest;
|
import org.alfresco.repo.search.impl.parsers.CMIS_FTSTest;
|
||||||
import org.alfresco.repo.search.impl.parsers.FTSTest;
|
import org.alfresco.repo.search.impl.parsers.FTSTest;
|
||||||
import org.alfresco.repo.search.impl.solr.facet.SolrFacetHelperTest;
|
|
||||||
import org.alfresco.util.NumericEncodingTest;
|
import org.alfresco.util.NumericEncodingTest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,11 +61,7 @@ public class SearchTestSuite extends TestSuite
|
|||||||
suite.addTestSuite(CMIS_FTSTest.class);
|
suite.addTestSuite(CMIS_FTSTest.class);
|
||||||
suite.addTestSuite(CMISTest.class);
|
suite.addTestSuite(CMISTest.class);
|
||||||
suite.addTestSuite(FTSTest.class);
|
suite.addTestSuite(FTSTest.class);
|
||||||
suite.addTest(new JUnit4TestAdapter(SolrFacetHelperTest.class));
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -34,15 +34,16 @@ public class SolrFacetComparatorTest
|
|||||||
{
|
{
|
||||||
@Test public void simpleSortOfSortedFacets() throws Exception
|
@Test public void simpleSortOfSortedFacets() throws Exception
|
||||||
{
|
{
|
||||||
List<String> expectedIds = Arrays.asList(new String[] { "a", "b", "c"});
|
List<String> expectedIds = Arrays.asList(new String[] { "a", "b", "c", "d"});
|
||||||
|
|
||||||
SolrFacetProperties.Builder builder = new SolrFacetProperties.Builder();
|
SolrFacetProperties.Builder builder = new SolrFacetProperties.Builder();
|
||||||
|
|
||||||
List<SolrFacetProperties> facets = Arrays.asList(new SolrFacetProperties[]
|
List<SolrFacetProperties> facets = Arrays.asList(new SolrFacetProperties[]
|
||||||
{
|
{
|
||||||
builder.filterID("c").index(1).build(),
|
builder.filterID("a").build(),
|
||||||
builder.filterID("b").index(2).build(),
|
builder.filterID("d").build(),
|
||||||
builder.filterID("a").index(3).build(),
|
builder.filterID("b").build(),
|
||||||
|
builder.filterID("c").build(),
|
||||||
});
|
});
|
||||||
Collections.sort(facets, new SolrFacetComparator(expectedIds));
|
Collections.sort(facets, new SolrFacetComparator(expectedIds));
|
||||||
|
|
||||||
|
@@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
* 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.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.util.ApplicationContextHelper;
|
||||||
|
import org.junit.*;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationEvent;
|
||||||
|
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class contains tests for the class {@link SolrFacetConfig}
|
||||||
|
*
|
||||||
|
* @author Jamal Kaabi-Mofrad
|
||||||
|
* @since 5.0
|
||||||
|
*/
|
||||||
|
public class SolrFacetConfigTest
|
||||||
|
{
|
||||||
|
private static ClassPathXmlApplicationContext context;
|
||||||
|
private static Properties rawProperties;
|
||||||
|
private static SolrFacetConfig facetConfig;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUp() throws Exception
|
||||||
|
{
|
||||||
|
context = new ClassPathXmlApplicationContext(new String[] { "classpath:facets/test-facet-property-context.xml" },
|
||||||
|
ApplicationContextHelper.getApplicationContext());
|
||||||
|
|
||||||
|
rawProperties = context.getBean("solrFacetRawPropertiesTest", Properties.class);
|
||||||
|
facetConfig = context.getBean("solrFacetConfigsTest", SolrFacetConfig.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void tearDown() throws Exception
|
||||||
|
{
|
||||||
|
context.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBasic() throws Exception
|
||||||
|
{
|
||||||
|
SolrFacetConfig config = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
config = new SolrFacetConfig(null, "");
|
||||||
|
fail("Null properties should have been detected");
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e)
|
||||||
|
{
|
||||||
|
// Expected
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
config = new SolrFacetConfig(rawProperties, null);
|
||||||
|
fail("Null properties should have been detected");
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e)
|
||||||
|
{
|
||||||
|
// Expected
|
||||||
|
}
|
||||||
|
config = new SolrFacetConfig(rawProperties, "default,custom");
|
||||||
|
config.setNamespaceService(context.getBean("namespaceService", NamespaceService.class));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
config.getDefaultFacets();
|
||||||
|
fail("Initialization should be done.");
|
||||||
|
}
|
||||||
|
catch (IllegalStateException e)
|
||||||
|
{
|
||||||
|
// Expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDefault() throws Exception
|
||||||
|
{
|
||||||
|
Map<String, SolrFacetProperties> defaultProps = facetConfig.getDefaultFacets();
|
||||||
|
assertNotNull(defaultProps);
|
||||||
|
assertEquals("Incorrect number of properties", 4, defaultProps.size());
|
||||||
|
|
||||||
|
// loaded from /facets/facets-config-sample.properties
|
||||||
|
SolrFacetProperties contentSizeFP = defaultProps.get("test_filter_content_size");
|
||||||
|
assertEquals("Incorrect QNAME", "{http://www.alfresco.org/model/content/1.0}content.size", contentSizeFP.getFacetQName().toString());
|
||||||
|
assertEquals("faceted-search.facet-menu.facet.size", contentSizeFP.getDisplayName());
|
||||||
|
assertEquals("alfresco/search/FacetFilters", contentSizeFP.getDisplayControl());
|
||||||
|
assertEquals(5, contentSizeFP.getMaxFilters());
|
||||||
|
assertEquals(1, contentSizeFP.getHitThreshold());
|
||||||
|
assertEquals(4, contentSizeFP.getMinFilterValueLength());
|
||||||
|
assertEquals("ALPHABETICALLY", contentSizeFP.getSortBy());
|
||||||
|
assertEquals("ALL", contentSizeFP.getScope());
|
||||||
|
assertEquals(0, contentSizeFP.getScopedSites().size());
|
||||||
|
assertEquals(true, contentSizeFP.isEnabled());
|
||||||
|
assertEquals(1, contentSizeFP.getCustomProperties().size());
|
||||||
|
String customValue = (String) contentSizeFP.getCustomProperties().iterator().next().getValue();
|
||||||
|
assertTrue(Boolean.valueOf(customValue));
|
||||||
|
|
||||||
|
// loaded from /facets/extension/facets-config-custom-sample.properties
|
||||||
|
SolrFacetProperties descFP = defaultProps.get("test_filter_description");
|
||||||
|
assertEquals("Incorrect QNAME", "{http://www.alfresco.org/model/content/1.0}description", descFP.getFacetQName().toString());
|
||||||
|
assertEquals("faceted-search.facet-menu.facet.description", descFP.getDisplayName());
|
||||||
|
assertEquals("alfresco/search/FacetFilters", descFP.getDisplayControl());
|
||||||
|
assertEquals(3, descFP.getMaxFilters());
|
||||||
|
assertEquals(1, descFP.getHitThreshold());
|
||||||
|
assertEquals(2, descFP.getMinFilterValueLength());
|
||||||
|
assertEquals("DESCENDING", descFP.getSortBy());
|
||||||
|
assertEquals("SCOPED_SITES", descFP.getScope());
|
||||||
|
assertEquals(0, descFP.getScopedSites().size());
|
||||||
|
assertEquals(true, descFP.isEnabled());
|
||||||
|
|
||||||
|
// See if the overrides worked
|
||||||
|
SolrFacetProperties creatorFP = defaultProps.get("test_filter_creator");
|
||||||
|
assertEquals("Incorrect QNAME", "{http://www.alfresco.org/model/content/1.0}creator.__.u", creatorFP.getFacetQName().toString());
|
||||||
|
|
||||||
|
String msg = "The value has not been overridden with the value from the custom properties";
|
||||||
|
assertEquals(msg, 10, creatorFP.getMaxFilters());
|
||||||
|
assertEquals(msg, 5, creatorFP.getHitThreshold());
|
||||||
|
assertEquals(msg, 14, creatorFP.getMinFilterValueLength());
|
||||||
|
assertEquals(msg, 1, creatorFP.getScopedSites().size());
|
||||||
|
assertEquals("site1", creatorFP.getScopedSites().iterator().next());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOverrideOrder() throws Exception
|
||||||
|
{
|
||||||
|
ApplicationEvent applicationEvent = new ApplicationEvent(this)
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Override order: default,custom
|
||||||
|
*/
|
||||||
|
SolrFacetConfig config = new SolrFacetConfig(rawProperties, "default,custom");
|
||||||
|
config.setNamespaceService(context.getBean("namespaceService", NamespaceService.class));
|
||||||
|
config.onBootstrap(applicationEvent);
|
||||||
|
|
||||||
|
SolrFacetProperties creatorFP = config.getDefaultFacets().get("test_filter_creator");
|
||||||
|
assertEquals("Incorrect QNAME", "{http://www.alfresco.org/model/content/1.0}creator.__.u", creatorFP.getFacetQName().toString());
|
||||||
|
assertEquals(10, creatorFP.getMaxFilters());
|
||||||
|
assertEquals(5, creatorFP.getHitThreshold());
|
||||||
|
assertEquals(14, creatorFP.getMinFilterValueLength());
|
||||||
|
assertEquals(1, creatorFP.getScopedSites().size());
|
||||||
|
assertEquals("site1", creatorFP.getScopedSites().iterator().next());
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Override order: custom,default
|
||||||
|
*/
|
||||||
|
config = new SolrFacetConfig(rawProperties, "custom,default");
|
||||||
|
config.setNamespaceService(context.getBean("namespaceService", NamespaceService.class));
|
||||||
|
config.onBootstrap(applicationEvent);
|
||||||
|
|
||||||
|
creatorFP = config.getDefaultFacets().get("test_filter_creator");
|
||||||
|
assertEquals("Incorrect QNAME", "{http://www.alfresco.org/model/content/1.0}creator.__.u", creatorFP.getFacetQName().toString());
|
||||||
|
assertEquals(5, creatorFP.getMaxFilters());
|
||||||
|
assertEquals(1, creatorFP.getHitThreshold());
|
||||||
|
assertEquals(4, creatorFP.getMinFilterValueLength());
|
||||||
|
assertEquals(0, creatorFP.getScopedSites().size());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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 junit.framework.JUnit4TestAdapter;
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Jamal Kaabi-Mofrad
|
||||||
|
*/
|
||||||
|
public class SolrFacetTestSuite extends TestSuite
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the test suite
|
||||||
|
*
|
||||||
|
* @return the test suite
|
||||||
|
*/
|
||||||
|
public static Test suite()
|
||||||
|
{
|
||||||
|
TestSuite suite = new TestSuite();
|
||||||
|
suite.addTest(new JUnit4TestAdapter(SolrFacetHelperTest.class));
|
||||||
|
suite.addTest(new JUnit4TestAdapter(SolrFacetServiceImplTest.class));
|
||||||
|
suite.addTest(new JUnit4TestAdapter(SolrFacetConfigTest.class));
|
||||||
|
|
||||||
|
return suite;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,26 @@
|
|||||||
|
# Overrides test_filter_creator in the /facets/facets-config-sample.properties
|
||||||
|
custom.cm\:creator.__.u.filterID=test_filter_creator
|
||||||
|
custom.cm\:creator.__.u.displayName=faceted-search.facet-menu.facet.creator
|
||||||
|
custom.cm\:creator.__.u.displayControl=alfresco/search/FacetFilters
|
||||||
|
custom.cm\:creator.__.u.maxFilters=10
|
||||||
|
custom.cm\:creator.__.u.hitThreshold=5
|
||||||
|
custom.cm\:creator.__.u.minFilterValueLength=14
|
||||||
|
custom.cm\:creator.__.u.sortBy=ALPHABETICALLY
|
||||||
|
custom.cm\:creator.__.u.scope=ALL
|
||||||
|
custom.cm\:creator.__.u.scopedSites=site1
|
||||||
|
custom.cm\:creator.__.u.index=0
|
||||||
|
custom.cm\:creator.__.u.isEnabled=true
|
||||||
|
|
||||||
|
# Add a new Filter
|
||||||
|
# Field-Facet-Qname => cm:description.__
|
||||||
|
custom.cm\:description.filterID=test_filter_description
|
||||||
|
custom.cm\:description.displayName=faceted-search.facet-menu.facet.description
|
||||||
|
custom.cm\:description.displayControl=alfresco/search/FacetFilters
|
||||||
|
custom.cm\:description.maxFilters=3
|
||||||
|
custom.cm\:description.hitThreshold=1
|
||||||
|
custom.cm\:description.minFilterValueLength=2
|
||||||
|
custom.cm\:description.sortBy=DESCENDING
|
||||||
|
custom.cm\:description.scope=SCOPED_SITES
|
||||||
|
custom.cm\:description.scopedSites=
|
||||||
|
custom.cm\:description.index=4
|
||||||
|
custom.cm\:description.isEnabled=true
|
36
source/test-resources/facets/facets-config-sample.properties
Normal file
36
source/test-resources/facets/facets-config-sample.properties
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# Field-Facet-Qname => cm:creator.__.u
|
||||||
|
default.cm\:creator.__.u.filterID=test_filter_creator
|
||||||
|
default.cm\:creator.__.u.displayName=faceted-search.facet-menu.facet.creator
|
||||||
|
default.cm\:creator.__.u.displayControl=alfresco/search/FacetFilters
|
||||||
|
default.cm\:creator.__.u.maxFilters=5
|
||||||
|
default.cm\:creator.__.u.hitThreshold=1
|
||||||
|
default.cm\:creator.__.u.minFilterValueLength=4
|
||||||
|
default.cm\:creator.__.u.sortBy=ALPHABETICALLY
|
||||||
|
default.cm\:creator.__.u.scope=ALL
|
||||||
|
default.cm\:creator.__.u.scopedSites=
|
||||||
|
default.cm\:creator.__.u.isEnabled=true
|
||||||
|
|
||||||
|
# Field-Facet-Qname => cm:modifier.__.u
|
||||||
|
default.cm\:modifier.__.u.filterID=test_filter_modifier
|
||||||
|
default.cm\:modifier.__.u.displayName=faceted-search.facet-menu.facet.modifier
|
||||||
|
default.cm\:modifier.__.u.displayControl=alfresco/search/FacetFilters
|
||||||
|
default.cm\:modifier.__.u.maxFilters=5
|
||||||
|
default.cm\:modifier.__.u.hitThreshold=1
|
||||||
|
default.cm\:modifier.__.u.minFilterValueLength=4
|
||||||
|
default.cm\:modifier.__.u.sortBy=ALPHABETICALLY
|
||||||
|
default.cm\:modifier.__.u.scope=SCOPED_SITES
|
||||||
|
default.cm\:modifier.__.u.scopedSites=
|
||||||
|
default.cm\:modifier.__.u.isEnabled=true
|
||||||
|
|
||||||
|
# Field-Facet-Qname => cm:content.size
|
||||||
|
default.cm\:content.size.filterID=test_filter_content_size
|
||||||
|
default.cm\:content.size.displayName=faceted-search.facet-menu.facet.size
|
||||||
|
default.cm\:content.size.displayControl=alfresco/search/FacetFilters
|
||||||
|
default.cm\:content.size.maxFilters=5
|
||||||
|
default.cm\:content.size.hitThreshold=1
|
||||||
|
default.cm\:content.size.minFilterValueLength=4
|
||||||
|
default.cm\:content.size.sortBy=ALPHABETICALLY
|
||||||
|
default.cm\:content.size.scope=ALL
|
||||||
|
default.cm\:content.size.scopedSites=
|
||||||
|
default.cm\:content.size.isEnabled=true
|
||||||
|
default.cm\:content.size.EXTRA-PROP.blockIncludeFacetRequest=true
|
21
source/test-resources/facets/test-facet-property-context.xml
Normal file
21
source/test-resources/facets/test-facet-property-context.xml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||||
|
|
||||||
|
<beans>
|
||||||
|
|
||||||
|
<bean id="solrFacetRawPropertiesTest" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
|
||||||
|
<property name="locations">
|
||||||
|
<list>
|
||||||
|
<value>classpath*:facets/facets-config-sample.properties</value>
|
||||||
|
<value>classpath*:facets/extension/facets-config-custom-sample.properties</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
<bean id="solrFacetConfigsTest" class="org.alfresco.repo.search.impl.solr.facet.SolrFacetConfig">
|
||||||
|
<constructor-arg index="0" ref="solrFacetRawPropertiesTest" />
|
||||||
|
<constructor-arg index="1">
|
||||||
|
<value>default,custom</value>
|
||||||
|
</constructor-arg>
|
||||||
|
<property name="namespaceService" ref="namespaceService" />
|
||||||
|
</bean>
|
||||||
|
</beans>
|
Reference in New Issue
Block a user