diff --git a/config/alfresco/core-services-context.xml b/config/alfresco/core-services-context.xml
index e1e96ac459..ac3c832015 100644
--- a/config/alfresco/core-services-context.xml
+++ b/config/alfresco/core-services-context.xml
@@ -318,7 +318,7 @@
- org.alfresco.repo.search.IndexerAndSearcher
+ org.alfresco.repo.search.impl.lucene.LuceneIndexerAndSearcher
@@ -502,6 +502,9 @@
+
+
+
diff --git a/config/alfresco/model/contentModel.xml b/config/alfresco/model/contentModel.xml
index 1e1240b49b..b394441108 100644
--- a/config/alfresco/model/contentModel.xml
+++ b/config/alfresco/model/contentModel.xml
@@ -668,7 +668,7 @@
true
true
- true
+ false
diff --git a/config/alfresco/public-services-security-context.xml b/config/alfresco/public-services-security-context.xml
index b4808de92f..dba1cbbc19 100644
--- a/config/alfresco/public-services-security-context.xml
+++ b/config/alfresco/public-services-security-context.xml
@@ -456,6 +456,8 @@
+
+
@@ -468,11 +470,12 @@
org.alfresco.service.cmr.search.CategoryService.getClassifications=AFTER_ACL_NODE.sys:base.ReadProperties
org.alfresco.service.cmr.search.CategoryService.getRootCategories=AFTER_ACL_NODE.sys:base.ReadProperties
org.alfresco.service.cmr.search.CategoryService.getClassificationAspects=ACL_ALLOW
- org.alfresco.service.cmr.search.CategoryService.createClassifiction=ACL_METHOD.ROLE_ADMINISTRATOR
- org.alfresco.service.cmr.search.CategoryService.createRootCategory=ACL_METHOD.ROLE_ADMINISTRATOR
- org.alfresco.service.cmr.search.CategoryService.createCategory=ACL_METHOD.ROLE_ADMINISTRATOR
- org.alfresco.service.cmr.search.CategoryService.deleteClassification=ACL_METHOD.ROLE_ADMINISTRATOR
- org.alfresco.service.cmr.search.CategoryService.deleteCategory=ACL_METHOD.ROLE_ADMINISTRATOR
+ org.alfresco.service.cmr.search.CategoryService.createClassifiction=ACL_ALLOW
+ org.alfresco.service.cmr.search.CategoryService.createRootCategory=ACL_ALLOW
+ org.alfresco.service.cmr.search.CategoryService.createCategory=ACL_ALLOW
+ org.alfresco.service.cmr.search.CategoryService.deleteClassification=ACL_ALLOW
+ org.alfresco.service.cmr.search.CategoryService.deleteCategory=ACL_ALLOW
+ org.alfresco.service.cmr.search.CategoryService.getTopCategories=ACL_ALLOW
diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneCategoryTest.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneCategoryTest.java
index 3f850c7e90..c3328e9594 100644
--- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneCategoryTest.java
+++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneCategoryTest.java
@@ -28,8 +28,11 @@ import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Random;
+import javax.transaction.NotSupportedException;
+import javax.transaction.SystemException;
import javax.transaction.UserTransaction;
import junit.framework.TestCase;
@@ -58,6 +61,7 @@ import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
+import org.alfresco.util.Pair;
import org.springframework.context.ApplicationContext;
/**
@@ -282,7 +286,7 @@ public class ADMLuceneCategoryTest extends TestCase
genCatProp.setMandatory(true);
genCatProp.setMultiValued(true);
genCatProp.setStoredInIndex(true);
- genCatProp.setTokenisedInIndex(true);
+ genCatProp.setTokenisedInIndex(false);
genCatProp.setType("d:" + DataTypeDefinition.CATEGORY.getLocalName());
assetClassCategorisationQName = QName.createQName(TEST_NAMESPACE, "AssetClass");
@@ -294,7 +298,7 @@ public class ADMLuceneCategoryTest extends TestCase
acProp.setMandatory(true);
acProp.setMultiValued(true);
acProp.setStoredInIndex(true);
- acProp.setTokenisedInIndex(true);
+ acProp.setTokenisedInIndex(false);
acProp.setType("d:" + DataTypeDefinition.CATEGORY.getLocalName());
investmentRegionCategorisationQName = QName.createQName(TEST_NAMESPACE, "InvestmentRegion");
@@ -306,7 +310,7 @@ public class ADMLuceneCategoryTest extends TestCase
irProp.setMandatory(true);
irProp.setMultiValued(true);
irProp.setStoredInIndex(true);
- irProp.setTokenisedInIndex(true);
+ irProp.setTokenisedInIndex(false);
irProp.setType("d:" + DataTypeDefinition.CATEGORY.getLocalName());
marketingRegionCategorisationQName = QName.createQName(TEST_NAMESPACE, "MarketingRegion");
@@ -318,7 +322,7 @@ public class ADMLuceneCategoryTest extends TestCase
mrProp.setMandatory(true);
mrProp.setMultiValued(true);
mrProp.setStoredInIndex(true);
- mrProp.setTokenisedInIndex(true);
+ mrProp.setTokenisedInIndex(false);
mrProp.setType("d:" + DataTypeDefinition.CATEGORY.getLocalName());
dictionaryDAO.putModel(model);
@@ -798,6 +802,52 @@ public class ADMLuceneCategoryTest extends TestCase
}
+ public void testCatCount() throws Exception
+ {
+ TransactionService transactionService = serviceRegistry.getTransactionService();
+ UserTransaction tx = transactionService.getUserTransaction();
+ tx.begin();
+
+
+ assertEquals(1, categoryService.getChildren(catACBase , CategoryService.Mode.MEMBERS, CategoryService.Depth.IMMEDIATE).size());
+ assertEquals(2, categoryService.getChildren(catACBase , CategoryService.Mode.SUB_CATEGORIES, CategoryService.Depth.IMMEDIATE).size());
+ assertEquals(3, categoryService.getChildren(catACBase , CategoryService.Mode.ALL, CategoryService.Depth.IMMEDIATE).size());
+ assertEquals(14, categoryService.getChildren(catACBase , CategoryService.Mode.MEMBERS, CategoryService.Depth.ANY).size());
+ assertEquals(3, categoryService.getChildren(catACBase , CategoryService.Mode.SUB_CATEGORIES, CategoryService.Depth.ANY).size());
+ assertEquals(17, categoryService.getChildren(catACBase , CategoryService.Mode.ALL, CategoryService.Depth.ANY).size());
+ assertEquals(2, categoryService.getClassifications(rootNodeRef.getStoreRef()).size());
+ assertEquals(2, categoryService.getCategories(rootNodeRef.getStoreRef(), QName.createQName(TEST_NAMESPACE, "AssetClass"), CategoryService.Depth.IMMEDIATE).size());
+ assertEquals(3, categoryService.getCategories(rootNodeRef.getStoreRef(), QName.createQName(TEST_NAMESPACE, "AssetClass"), CategoryService.Depth.ANY).size());
+ assertEquals(6, categoryService.getClassificationAspects().size());
+ assertEquals(2, categoryService.getRootCategories(rootNodeRef.getStoreRef(), QName.createQName(TEST_NAMESPACE, "AssetClass")).size());
+
+ List> top = categoryService.getTopCategories(rootNodeRef.getStoreRef(), QName.createQName(TEST_NAMESPACE, "AssetClass"), 10);
+ for(Pair current : top)
+ {
+ System.out.println(""+nodeService.getPaths(current.getFirst(), true) + " "+current.getSecond());
+ }
+
+ top = categoryService.getTopCategories(rootNodeRef.getStoreRef(), QName.createQName(TEST_NAMESPACE, "InvestmentRegion"), 10);
+ for(Pair current : top)
+ {
+ System.out.println(""+nodeService.getPaths(current.getFirst(), true) + " "+current.getSecond());
+ }
+
+ top = categoryService.getTopCategories(rootNodeRef.getStoreRef(), QName.createQName(TEST_NAMESPACE, "MarketingRegion"), 10);
+ for(Pair current : top)
+ {
+ System.out.println(""+nodeService.getPaths(current.getFirst(), true) + " "+current.getSecond());
+ }
+
+ top = categoryService.getTopCategories(rootNodeRef.getStoreRef(), QName.createQName(TEST_NAMESPACE, "Region"), 10);
+ for(Pair current : top)
+ {
+ System.out.println(""+nodeService.getPaths(current.getFirst(), true) + " "+current.getSecond());
+ }
+
+ tx.commit();
+ }
+
@SuppressWarnings("unused")
private int getTotalScore(ResultSet results)
{
diff --git a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java
index ec2da9a7e6..8d6ef78f84 100644
--- a/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java
+++ b/source/java/org/alfresco/repo/search/impl/lucene/ADMLuceneSearcherImpl.java
@@ -27,8 +27,10 @@ package org.alfresco.repo.search.impl.lucene;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
@@ -60,11 +62,13 @@ import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO9075;
+import org.alfresco.util.Pair;
import org.alfresco.util.SearchLanguageConversion;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermDocs;
import org.apache.lucene.index.TermEnum;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.Query;
@@ -93,7 +97,7 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
private NamespacePrefixResolver namespacePrefixResolver;
private NodeService nodeService;
-
+
private TenantService tenantService;
private QueryRegisterComponent queryRegister;
@@ -156,13 +160,12 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
{
this.nodeService = nodeService;
}
-
+
public void setTenantService(TenantService tenantService)
{
this.tenantService = tenantService;
}
-
/**
* Set the query register
*
@@ -175,8 +178,8 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
public ResultSet query(StoreRef store, String language, String queryString, Path[] queryOptions, QueryParameterDefinition[] queryParameterDefinitions) throws SearcherException
{
- store = tenantService.getName(store);
-
+ store = tenantService.getName(store);
+
SearchParameters sp = new SearchParameters();
sp.addStore(store);
sp.setLanguage(language);
@@ -206,9 +209,9 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
{
throw new IllegalStateException("Only one store can be searched at present");
}
-
+
ArrayList stores = searchParameters.getStores();
- stores.set(0, tenantService.getName(searchParameters.getStores().get(0)));
+ stores.set(0, tenantService.getName(searchParameters.getStores().get(0)));
String parameterisedQueryString;
if (searchParameters.getQueryParameterDefinitions().size() > 0)
@@ -243,18 +246,9 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
}
ClosingIndexSearcher searcher = getSearcher(indexer);
- Query query = LuceneQueryParser.parse(
- parameterisedQueryString, DEFAULT_FIELD,
- new LuceneAnalyser(
- getDictionaryService(),
- searchParameters.getMlAnalaysisMode() == null ? getLuceneConfig().getDefaultMLSearchAnalysisMode() : searchParameters.getMlAnalaysisMode()),
- namespacePrefixResolver,
- getDictionaryService(),
- tenantService,
- defaultOperator,
- searchParameters,
- getLuceneConfig(),
- searcher.getIndexReader());
+ Query query = LuceneQueryParser.parse(parameterisedQueryString, DEFAULT_FIELD, new LuceneAnalyser(getDictionaryService(),
+ searchParameters.getMlAnalaysisMode() == null ? getLuceneConfig().getDefaultMLSearchAnalysisMode() : searchParameters.getMlAnalaysisMode()),
+ namespacePrefixResolver, getDictionaryService(), tenantService, defaultOperator, searchParameters, getLuceneConfig(), searcher.getIndexReader());
if (s_logger.isDebugEnabled())
{
s_logger.debug("Query is " + query.toString());
@@ -277,24 +271,24 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
{
case FIELD:
String field = sd.getField();
- if(field.startsWith("@"))
+ if (field.startsWith("@"))
{
- field = expandAttributeFieldName(field);
- PropertyDefinition propertyDef = getDictionaryService().getProperty(QName.createQName(field.substring(1)));
+ field = expandAttributeFieldName(field);
+ PropertyDefinition propertyDef = getDictionaryService().getProperty(QName.createQName(field.substring(1)));
- if (propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME))
- {
- DataTypeDefinition dataType = propertyDef.getDataType();
- String analyserClassName = dataType.getAnalyserClassName();
- if(analyserClassName.equals(DateTimeAnalyser.class.getCanonicalName()))
- {
- field = field + ".sort";
- }
- }
+ if (propertyDef.getDataType().getName().equals(DataTypeDefinition.DATETIME))
+ {
+ DataTypeDefinition dataType = propertyDef.getDataType();
+ String analyserClassName = dataType.getAnalyserClassName();
+ if (analyserClassName.equals(DateTimeAnalyser.class.getCanonicalName()))
+ {
+ field = field + ".sort";
+ }
+ }
}
if (fieldHasTerm(searcher.getReader(), field))
- {
+ {
fields[index++] = new SortField(field, !sd.isAscending());
}
else
@@ -319,13 +313,7 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
}
Path[] paths = searchParameters.getAttributePaths().toArray(new Path[0]);
- return new LuceneResultSet(
- hits,
- searcher,
- nodeService,
- tenantService,
- paths,
- searchParameters);
+ return new LuceneResultSet(hits, searcher, nodeService, tenantService, paths, searchParameters);
}
catch (ParseException e)
{
@@ -358,13 +346,7 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
return new EmptyResultSet();
}
Hits hits = searcher.search(query);
- return new LuceneResultSet(
- hits,
- searcher,
- nodeService,
- tenantService,
- searchParameters.getAttributePaths().toArray(new Path[0]),
- searchParameters);
+ return new LuceneResultSet(hits, searcher, nodeService, tenantService, searchParameters.getAttributePaths().toArray(new Path[0]), searchParameters);
}
catch (SAXPathException e)
{
@@ -584,9 +566,9 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
boolean followAllParentLinks, String language) throws InvalidNodeRefException, XPathException
{
NodeSearcher nodeSearcher = new NodeSearcher(nodeService, getDictionaryService(), this);
-
+
contextNodeRef = tenantService.getName(contextNodeRef);
-
+
return nodeSearcher.selectNodes(contextNodeRef, xpath, parameters, namespacePrefixResolver, followAllParentLinks, language);
}
@@ -750,4 +732,91 @@ public class ADMLuceneSearcherImpl extends AbstractLuceneBase implements LuceneS
}
return fieldName;
}
+
+ public List> getTopTerms(String field, int count)
+ {
+ ClosingIndexSearcher searcher = null;
+ try
+ {
+ LinkedList> answer = new LinkedList>();
+ searcher = getSearcher(indexer);
+ IndexReader reader = searcher.getIndexReader();
+ TermEnum terms = reader.terms(new Term(field, ""));
+ while (terms.next())
+ {
+ Term term = terms.term();
+ if(!term.field().equals(field))
+ {
+ break;
+ }
+ int freq = terms.docFreq();
+ Pair pair = new Pair(term.text(), Integer.valueOf(freq));
+ if (answer.size() < count)
+ {
+ if (answer.size() == 0)
+ {
+ answer.add(pair);
+ }
+ else if (answer.get(answer.size() - 1).getSecond().compareTo(pair.getSecond()) >= 0)
+ {
+ answer.add(pair);
+ }
+ else
+ {
+ for (ListIterator> it = answer.listIterator(); it.hasNext(); /**/)
+ {
+ Pair test = it.next();
+ if (test.getSecond().compareTo(pair.getSecond()) < 0)
+ {
+ it.previous();
+ it.add(pair);
+ break;
+ }
+ }
+ }
+ }
+ else if (answer.get(count - 1).getSecond().compareTo(pair.getSecond()) < 0)
+ {
+ for (ListIterator> it = answer.listIterator(); it.hasNext(); /**/)
+ {
+ Pair test = it.next();
+ if (test.getSecond().compareTo(pair.getSecond()) < 0)
+ {
+ it.previous();
+ it.add(pair);
+ break;
+ }
+ }
+ answer.removeLast();
+ }
+ else
+ {
+ // off the end
+ }
+ }
+ terms.close();
+ return answer;
+
+ }
+ catch (IOException e)
+ {
+ throw new SearcherException(e);
+ }
+ finally
+ {
+ if (searcher != null)
+ {
+ try
+ {
+ searcher.close();
+ }
+ catch (IOException e)
+ {
+ throw new SearcherException(e);
+ }
+ }
+ }
+
+ }
+
}
diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneCategoryServiceImpl.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneCategoryServiceImpl.java
index 32c93b990f..b057c19c55 100644
--- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneCategoryServiceImpl.java
+++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneCategoryServiceImpl.java
@@ -31,6 +31,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
@@ -38,7 +39,10 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.search.IndexerAndSearcher;
import org.alfresco.repo.search.IndexerException;
import org.alfresco.repo.tenant.TenantService;
+import org.alfresco.service.cmr.dictionary.AspectDefinition;
+import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
+import org.alfresco.service.cmr.dictionary.PropertyDefinition;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
@@ -47,22 +51,25 @@ import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.CategoryService;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.ResultSetRow;
+import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ISO9075;
+import org.alfresco.util.Pair;
/**
* Category service implementation
*
* @author andyh
- *
*/
public class LuceneCategoryServiceImpl implements CategoryService
{
private NodeService nodeService;
+
+ private NodeService publicNodeService;
private TenantService tenantService;
-
+
private NamespacePrefixResolver namespacePrefixResolver;
private DictionaryService dictionaryService;
@@ -81,6 +88,7 @@ public class LuceneCategoryServiceImpl implements CategoryService
/**
* Set the node service
+ *
* @param nodeService
*/
public void setNodeService(NodeService nodeService)
@@ -88,8 +96,19 @@ public class LuceneCategoryServiceImpl implements CategoryService
this.nodeService = nodeService;
}
+ /**
+ * Set the public node service
+ *
+ * @param nodeService
+ */
+ public void setPublicNodeService(NodeService publicNodeService)
+ {
+ this.publicNodeService = publicNodeService;
+ }
+
/**
* Set the tenant service
+ *
* @param tenantService
*/
public void setTenantService(TenantService tenantService)
@@ -99,6 +118,7 @@ public class LuceneCategoryServiceImpl implements CategoryService
/**
* Set the service to map prefixes to uris
+ *
* @param namespacePrefixResolver
*/
public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver)
@@ -108,6 +128,7 @@ public class LuceneCategoryServiceImpl implements CategoryService
/**
* Set the dictionary service
+ *
* @param dictionaryService
*/
public void setDictionaryService(DictionaryService dictionaryService)
@@ -117,6 +138,7 @@ public class LuceneCategoryServiceImpl implements CategoryService
/**
* Set the indexer and searcher
+ *
* @param indexerAndSearcher
*/
public void setIndexerAndSearcher(IndexerAndSearcher indexerAndSearcher)
@@ -132,13 +154,13 @@ public class LuceneCategoryServiceImpl implements CategoryService
}
categoryRef = tenantService.getName(categoryRef);
-
+
ResultSet resultSet = null;
try
{
StringBuilder luceneQuery = new StringBuilder(64);
- switch(mode)
+ switch (mode)
{
case ALL:
luceneQuery.append("PATH:\"");
@@ -264,15 +286,15 @@ public class LuceneCategoryServiceImpl implements CategoryService
ResultSet resultSet = null;
try
{
- resultSet = indexerAndSearcher.getSearcher(storeRef, false).query(storeRef, "lucene", "PATH:\"/" + getPrefix(qname.getNamespaceURI()) + ISO9075.encode(qname.getLocalName()) + "\"",
- null, null);
+ resultSet = indexerAndSearcher.getSearcher(storeRef, false).query(storeRef, "lucene",
+ "PATH:\"/" + getPrefix(qname.getNamespaceURI()) + ISO9075.encode(qname.getLocalName()) + "\"", null, null);
Set nodeRefs = new HashSet(resultSet.length());
for (ResultSetRow row : resultSet)
{
nodeRefs.add(row.getNodeRef());
}
-
+
return nodeRefs;
}
finally
@@ -305,7 +327,7 @@ public class LuceneCategoryServiceImpl implements CategoryService
public Collection getClassificationAspects()
{
- return dictionaryService.getSubAspects(ContentModel.ASPECT_CLASSIFIABLE, true);
+ return dictionaryService.getSubAspects(ContentModel.ASPECT_CLASSIFIABLE, true);
}
public NodeRef createClassifiction(StoreRef storeRef, QName typeName, String attributeName)
@@ -326,23 +348,23 @@ public class LuceneCategoryServiceImpl implements CategoryService
public NodeRef createCategory(NodeRef parent, String name)
{
- if(!nodeService.exists(parent))
+ if (!nodeService.exists(parent))
{
throw new AlfrescoRuntimeException("Missing category?");
}
String uri = nodeService.getPrimaryParent(parent).getQName().getNamespaceURI();
String validLocalName = QName.createValidLocalName(name);
- NodeRef newCategory = nodeService.createNode(parent, ContentModel.ASSOC_SUBCATEGORIES, QName.createQName(uri, validLocalName), ContentModel.TYPE_CATEGORY).getChildRef();
- nodeService.setProperty(newCategory, ContentModel.PROP_NAME, name);
+ NodeRef newCategory = publicNodeService.createNode(parent, ContentModel.ASSOC_SUBCATEGORIES, QName.createQName(uri, validLocalName), ContentModel.TYPE_CATEGORY).getChildRef();
+ publicNodeService.setProperty(newCategory, ContentModel.PROP_NAME, name);
return newCategory;
}
public NodeRef createRootCategory(StoreRef storeRef, QName aspectName, String name)
{
Set nodeRefs = getClassificationNodes(storeRef, aspectName);
- if(nodeRefs.size() == 0)
+ if (nodeRefs.size() == 0)
{
- throw new AlfrescoRuntimeException("Missing classification: "+aspectName);
+ throw new AlfrescoRuntimeException("Missing classification: " + aspectName);
}
NodeRef parent = nodeRefs.iterator().next();
return createCategory(parent, name);
@@ -350,16 +372,78 @@ public class LuceneCategoryServiceImpl implements CategoryService
public void deleteCategory(NodeRef nodeRef)
{
- nodeService.deleteNode(nodeRef);
+ publicNodeService.deleteNode(nodeRef);
}
public void deleteClassification(StoreRef storeRef, QName aspectName)
{
throw new UnsupportedOperationException();
}
-
-
-
-
+ public List> getTopCategories(StoreRef storeRef, QName aspectName, int count)
+ {
+ if (indexerAndSearcher instanceof LuceneIndexerAndSearcher)
+ {
+ AspectDefinition definition = dictionaryService.getAspect(aspectName);
+ if(definition == null)
+ {
+ throw new IllegalStateException("Unknown aspect");
+ }
+ QName catProperty = null;
+ Map properties = definition.getProperties();
+ for(QName pName : properties.keySet())
+ {
+ if(pName.getNamespaceURI().equals(aspectName.getNamespaceURI()))
+ {
+ if(pName.getLocalName().equalsIgnoreCase(aspectName.getLocalName()))
+ {
+ PropertyDefinition def = properties.get(pName);
+ if(def.getDataType().getName().equals(DataTypeDefinition.CATEGORY))
+ {
+ catProperty = pName;
+ }
+ }
+ }
+ }
+ if(catProperty == null)
+ {
+ throw new IllegalStateException("Aspect does not have category property mirroring the aspect name");
+ }
+
+
+ LuceneIndexerAndSearcher lias = (LuceneIndexerAndSearcher) indexerAndSearcher;
+ String field = "@" + catProperty;
+ SearchService searchService = lias.getSearcher(storeRef, true);
+ if (searchService instanceof LuceneSearcher)
+ {
+ LuceneSearcher luceneSearcher = (LuceneSearcher)searchService;
+ List> topTerms = luceneSearcher.getTopTerms(field, count);
+ List> answer = new ArrayList>();
+ for (Pair term : topTerms)
+ {
+ Pair toAdd;
+ NodeRef nodeRef = new NodeRef(term.getFirst());
+ if (nodeService.exists(nodeRef))
+ {
+ toAdd = new Pair(nodeRef, term.getSecond());
+ }
+ else
+ {
+ toAdd = new Pair(null, term.getSecond());
+ }
+ answer.add(toAdd);
+ }
+ return answer;
+ }
+ else
+ {
+ throw new UnsupportedOperationException("getPolularCategories is only supported for lucene indexes");
+ }
+ }
+ else
+ {
+ throw new UnsupportedOperationException("getPolularCategories is only supported for lucene indexes");
+ }
+ }
+
}
diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexerAndSearcher.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexerAndSearcher.java
index dcd46679f1..156eacba8f 100644
--- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexerAndSearcher.java
+++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneIndexerAndSearcher.java
@@ -24,8 +24,13 @@
*/
package org.alfresco.repo.search.impl.lucene;
+import java.util.List;
+
import org.alfresco.repo.search.IndexerAndSearcher;
import org.alfresco.repo.search.IndexerException;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.StoreRef;
+import org.alfresco.util.Pair;
public interface LuceneIndexerAndSearcher extends IndexerAndSearcher, LuceneConfig
{
@@ -40,4 +45,5 @@ public interface LuceneIndexerAndSearcher extends IndexerAndSearcher, LuceneConf
}
public R doWithAllWriteLocks(WithAllWriteLocksWork lockWork);
+
}
diff --git a/source/java/org/alfresco/repo/search/impl/lucene/LuceneSearcher.java b/source/java/org/alfresco/repo/search/impl/lucene/LuceneSearcher.java
index 406ab6a4ab..c18dfbae8e 100644
--- a/source/java/org/alfresco/repo/search/impl/lucene/LuceneSearcher.java
+++ b/source/java/org/alfresco/repo/search/impl/lucene/LuceneSearcher.java
@@ -24,9 +24,13 @@
*/
package org.alfresco.repo.search.impl.lucene;
+import java.util.List;
+
import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.namespace.NamespacePrefixResolver;
+import org.alfresco.util.Pair;
/**
* Lucene implementation specific entension to the seracher API
@@ -50,4 +54,13 @@ public interface LuceneSearcher extends SearchService
* @param namespacePrefixResolver
*/
public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver);
+
+ /**
+ * Get top terms
+ *
+ * @param field
+ * @param count
+ * @return
+ */
+ public List> getTopTerms(String field, int count);
}
diff --git a/source/java/org/alfresco/service/cmr/search/CategoryService.java b/source/java/org/alfresco/service/cmr/search/CategoryService.java
index 23686266b3..18f74adc55 100644
--- a/source/java/org/alfresco/service/cmr/search/CategoryService.java
+++ b/source/java/org/alfresco/service/cmr/search/CategoryService.java
@@ -25,6 +25,7 @@
package org.alfresco.service.cmr.search;
import java.util.Collection;
+import java.util.List;
import org.alfresco.service.Auditable;
import org.alfresco.service.PublicService;
@@ -32,6 +33,7 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.namespace.QName;
+import org.alfresco.util.Pair;
/**
* Category Service
@@ -163,4 +165,14 @@ public interface CategoryService
*/
@Auditable(key = Auditable.Key.ARG_0, parameters = {"nodeRef"})
public void deleteCategory(NodeRef nodeRef);
+
+ /**
+ * Get the most polular categories
+ *
+ * @param storeRef
+ * @param aspectName
+ * @param count
+ * @return
+ */
+ public List> getTopCategories(StoreRef storeRef, QName aspectName, int count);
}