diff --git a/config/alfresco/bootstrap/categories.xml b/config/alfresco/bootstrap/categories.xml
index 760fe4f589..8ec179e3c2 100644
--- a/config/alfresco/bootstrap/categories.xml
+++ b/config/alfresco/bootstrap/categories.xml
@@ -1100,9 +1100,21 @@
+
+
+
+
+ GROUP_EVERYONE
+ Contributor
+
+
+ Tags
+
+
+
diff --git a/config/alfresco/bootstrap/tagRootCategory.xml b/config/alfresco/bootstrap/tagRootCategory.xml
new file mode 100644
index 0000000000..3ba85bb325
--- /dev/null
+++ b/config/alfresco/bootstrap/tagRootCategory.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ GROUP_EVERYONE
+ Collaborator
+
+
+ Tags
+ tag:tag-root
+
+
diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties
index 550ef83307..d97c213656 100644
--- a/config/alfresco/messages/patch-service.properties
+++ b/config/alfresco/messages/patch-service.properties
@@ -189,3 +189,5 @@ patch.avmFormPropertyIdentifier.result=Reindexed wca:webform to make wca:formnam
patch.formsFolder.description=Adds 'Forms' folder to Data Dictionary
+patch.tagRootCategory.description=Adds 'Tags' as new top-level category root
+
diff --git a/config/alfresco/model/contentModel.xml b/config/alfresco/model/contentModel.xml
index c322d5e38e..135c036bb9 100644
--- a/config/alfresco/model/contentModel.xml
+++ b/config/alfresco/model/contentModel.xml
@@ -682,6 +682,24 @@
+
+ Taggable
+ cm:classifiable
+
+
+ Tags
+ d:category
+ false
+ true
+
+ true
+ true
+ false
+
+
+
+
+
Attachable
diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml
index 0478aa2924..666dcd82c4 100644
--- a/config/alfresco/patch/patch-services-context.xml
+++ b/config/alfresco/patch/patch-services-context.xml
@@ -1145,4 +1145,25 @@
+
+ patch.tagRootCategory
+ patch.tagRootCategory.description
+ 0
+ 113
+ 114
+
+
+
+
+
+ /cm:categoryRoot/cm:taggable
+
+
+
+ /cm:categoryRoot
+ alfresco/bootstrap/tagRootCategory.xml
+
+
+
+
diff --git a/source/java/org/alfresco/repo/jscript/Classification.java b/source/java/org/alfresco/repo/jscript/Classification.java
index 3d1d629c4f..d561503bfb 100644
--- a/source/java/org/alfresco/repo/jscript/Classification.java
+++ b/source/java/org/alfresco/repo/jscript/Classification.java
@@ -25,12 +25,15 @@
package org.alfresco.repo.jscript;
import java.util.Collection;
+import java.util.List;
import org.alfresco.service.ServiceRegistry;
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.cmr.search.CategoryService;
import org.alfresco.service.namespace.QName;
+import org.alfresco.util.Pair;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
@@ -124,6 +127,26 @@ public final class Classification extends BaseScopableProcessorExtension
return Context.getCurrentContext().newArray(getScope(), cats);
}
+ /**
+ * Get the category usage count.
+ *
+ * @param aspect
+ * @param maxCount
+ * @return
+ */
+ public Scriptable getCategoryUsage(String aspect, int maxCount)
+ {
+ List> topCats = services.getCategoryService().getTopCategories(storeRef, createQName(aspect), maxCount);
+ Object[] tags = new Object[topCats.size()];
+ int i = 0;
+ for (Pair topCat : topCats)
+ {
+ tags[i++] = new Tag(new CategoryNode(topCat.getFirst(), this.services, getScope()), topCat.getSecond());
+ }
+
+ return Context.getCurrentContext().newArray(getScope(), tags);
+ }
+
private Object[] buildCategoryNodes(Collection cars)
{
Object[] categoryNodes = new Object[cars.size()];
@@ -148,4 +171,33 @@ public final class Classification extends BaseScopableProcessorExtension
}
return qname;
}
+
+ /**
+ * Tag class returned from getCategoryUsage().
+ *
+ * @param CategoryNode
+ * @param frequency
+ * @return
+ */
+ public final class Tag
+ {
+ private CategoryNode categoryNode;
+ private int frequency = 0;
+
+ public Tag(CategoryNode categoryNode, int frequency)
+ {
+ this.categoryNode = categoryNode;
+ this.frequency = frequency;
+ }
+
+ public CategoryNode getCategory()
+ {
+ return categoryNode;
+ }
+
+ public int getFrequency()
+ {
+ return frequency;
+ }
+ }
}